--- ray/src/util/rmatrix.c 2025/04/04 22:47:56 2.90 +++ ray/src/util/rmatrix.c 2025/04/18 23:59:03 2.97 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: rmatrix.c,v 2.90 2025/04/04 22:47:56 greg Exp $"; +static const char RCSid[] = "$Id: rmatrix.c,v 2.97 2025/04/18 23:59:03 greg Exp $"; #endif /* * General matrix operations. @@ -389,7 +389,7 @@ rmx_load_data(RMATRIX *rm, FILE *fp) /* Load matrix from supported file type */ RMATRIX * -rmx_load(const char *inspec, RMPref rmp) +rmx_load(const char *inspec) { FILE *fp; RMATRIX *dnew; @@ -403,21 +403,8 @@ rmx_load(const char *inspec, RMPref rmp) fp = stdin; else if (inspec[0] == '!') fp = popen(inspec+1, "r"); - else { /* check suffix */ - const char *sp = strrchr(inspec, '.'); - if (sp > inspec && !strcasecmp(sp+1, "XML")) { /* BSDF? */ - CMATRIX *cm = rmp==RMPnone ? (CMATRIX *)NULL : - rmp==RMPtrans ? cm_loadBTDF(inspec) : - cm_loadBRDF(inspec, rmp==RMPreflB) ; - if (!cm) - return(NULL); - dnew = rmx_from_cmatrix(cm); - cm_free(cm); - dnew->dtype = DTascii; - return(dnew); /* return here */ - } /* else open it ourselves */ + else fp = fopen(inspec, "r"); - } if (!fp) { fprintf(stderr, "Cannot open for reading: %s\n", inspec); return(NULL); @@ -758,8 +745,10 @@ rmx_transfer_data(RMATRIX *rdst, RMATRIX *rsrc, int do int rmx_transpose(RMATRIX *rm) { - RMATRIX dnew; - int i, j; + uby8 *bmap; + rmx_dtype val[MAXCOMP]; + RMATRIX dold; + int i, j; if (!rm || !rm->mtx | (rm->ncomp > MAXCOMP)) return(0); @@ -772,34 +761,61 @@ rmx_transpose(RMATRIX *rm) return(1); } if (rm->nrows == rm->ncols) { /* square matrix case */ - rmx_dtype val[MAXCOMP]; - for (j = rm->ncols; j--; ) - for (i = rm->nrows; i--; ) { - if (i == j) continue; - memcpy(val, rmx_val(rm,i,j), + for (i = rm->nrows; i--; ) + for (j = rm->ncols; j--; ) { + if (i == j) continue; + memcpy(val, rmx_val(rm,i,j), sizeof(rmx_dtype)*rm->ncomp); - memcpy(rmx_lval(rm,i,j), rmx_val(rm,j,i), + memcpy(rmx_lval(rm,i,j), rmx_val(rm,j,i), sizeof(rmx_dtype)*rm->ncomp); - memcpy(rmx_val(rm,j,i), val, + memcpy(rmx_val(rm,j,i), val, sizeof(rmx_dtype)*rm->ncomp); - } + } return(1); } - memset(&dnew, 0, sizeof(dnew)); - dnew.ncols = rm->nrows; dnew.nrows = rm->ncols; - dnew.ncomp = rm->ncomp; - if (!rmx_prepare(&dnew)) +#define bmbyte(r,c) bmap[((r)*rm->ncols+(c))>>3] +#define bmbit(r,c) (1 << ((r)*rm->ncols+(c) & 7)) +#define bmop(r,c, op) (bmbyte(r,c) op bmbit(r,c)) +#define bmtest(r,c) bmop(r,c,&) +#define bmset(r,c) bmop(r,c,|=) + /* loop completion bitmap */ + bmap = (uby8 *)calloc(((size_t)rm->nrows*rm->ncols+7)>>3, 1); + if (!bmap) return(0); - rmx_addinfo(&dnew, rm->info); - dnew.dtype = rm->dtype; - copycolor(dnew.cexp, rm->cexp); - memcpy(dnew.wlpart, rm->wlpart, sizeof(dnew.wlpart)); - for (j = dnew.ncols; j--; ) - for (i = dnew.nrows; i--; ) - memcpy(rmx_lval(&dnew,i,j), rmx_val(rm,j,i), - sizeof(rmx_dtype)*dnew.ncomp); - /* and reassign result */ - return(rmx_transfer_data(rm, &dnew, 1)); + dold = *rm; + rm->ncols = dold.nrows; rm->nrows = dold.ncols; + for (i = rm->nrows; i--; ) /* try every starting point */ + for (j = rm->ncols; j--; ) { + int i0, j0; + int i1 = i; + size_t j1 = j; + if (bmtest(i, j)) + continue; /* traversed loop earlier */ + memcpy(val, rmx_val(rm,i,j), + sizeof(rmx_dtype)*rm->ncomp); + for ( ; ; ) { /* new transpose loop */ + const rmx_dtype *ds; + i0 = i1; j0 = j1; + ds = rmx_val(&dold, j0, i0); + j1 = (ds - dold.mtx)/dold.ncomp; + i1 = j1 / rm->ncols; + j1 -= (size_t)i1*rm->ncols; + bmset(i1, j1); /* mark as done */ + if ((i1 == i) & (j1 == j)) + break; /* back at start */ + memcpy(rmx_lval(rm,i0,j0), ds, + sizeof(rmx_dtype)*rm->ncomp); + } /* complete the loop */ + memcpy(rmx_lval(rm,i0,j0), val, + sizeof(rmx_dtype)*rm->ncomp); + } + free(bmap); /* all done! */ + return(1); +#undef bmbyte +#undef bmbit +#undef bmop +#undef bmtest +#undef bmset } /* Multiply (concatenate) two matrices and allocate the result */ @@ -1036,13 +1052,17 @@ cm_from_rmatrix(const RMATRIX *rm) case 1: setcolor(cv, dp[0], dp[0], dp[0]); break; - default: { + default: + if (sizeof(COLORV) == sizeof(rmx_dtype)) { + scolor2color(cv, (const COLORV *)dp, + rm->ncomp, rm->wlpart); + } else { COLORV scol[MAXCOMP]; - int k; - for (k = rm->ncomp; k--; ) - scol[k] = dp[k]; + int k = rm->ncomp; + while (k--) scol[k] = dp[k]; scolor2color(cv, scol, rm->ncomp, rm->wlpart); - } break; + } + break; } } }