--- ray/src/util/rmatrix.c 2015/05/04 20:53:21 2.13 +++ ray/src/util/rmatrix.c 2019/08/12 04:46:34 2.32 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: rmatrix.c,v 2.13 2015/05/04 20:53:21 greg Exp $"; +static const char RCSid[] = "$Id: rmatrix.c,v 2.32 2019/08/12 04:46:34 greg Exp $"; #endif /* * General matrix operations. @@ -9,7 +9,11 @@ static const char RCSid[] = "$Id: rmatrix.c,v 2.13 201 #include #include #include +#include +#include "rtio.h" +#include "platform.h" #include "resolu.h" +#include "paths.h" #include "rmatrix.h" static char rmx_mismatch_warn[] = "WARNING: data type mismatch\n"; @@ -46,7 +50,9 @@ rmx_free(RMATRIX *rm) int rmx_newtype(int dtyp1, int dtyp2) { - if ((dtyp1==DTxyze) | (dtyp1==DTrgbe) && dtyp1 != dtyp2) + if ((dtyp1==DTxyze) | (dtyp1==DTrgbe) | + (dtyp2==DTxyze) | (dtyp2==DTrgbe) + && dtyp1 != dtyp2) return(0); if (dtyp1 < dtyp2) return(dtyp1); @@ -75,7 +81,7 @@ static int get_dminfo(char *s, void *p) { RMATRIX *ip = (RMATRIX *)p; - char fmt[64]; + char fmt[MAXFMTLEN]; int i; if (headidval(fmt, s)) @@ -108,9 +114,7 @@ static int rmx_load_ascii(RMATRIX *rm, FILE *fp) { int i, j, k; -#ifdef _WIN32 - _setmode(fileno(fp), _O_TEXT); -#endif + for (i = 0; i < rm->nrows; i++) for (j = 0; j < rm->ncols; j++) for (k = 0; k < rm->ncomp; k++) @@ -131,7 +135,7 @@ rmx_load_float(RMATRIX *rm, FILE *fp) } for (i = 0; i < rm->nrows; i++) for (j = 0; j < rm->ncols; j++) { - if (fread(val, sizeof(val[0]), rm->ncomp, fp) != rm->ncomp) + if (getbinary(val, sizeof(val[0]), rm->ncomp, fp) != rm->ncomp) return(0); for (k = rm->ncomp; k--; ) rmx_lval(rm,i,j,k) = val[k]; @@ -142,20 +146,12 @@ rmx_load_float(RMATRIX *rm, FILE *fp) static int rmx_load_double(RMATRIX *rm, FILE *fp) { - int i, j, k; - double val[100]; + int i, j; - if (rm->ncomp > 100) { - fputs("Unsupported # components in rmx_load_double()\n", stderr); - exit(1); - } for (i = 0; i < rm->nrows; i++) - for (j = 0; j < rm->ncols; j++) { - if (fread(val, sizeof(val[0]), rm->ncomp, fp) != rm->ncomp) + for (j = 0; j < rm->ncols; j++) + if (getbinary(&rmx_lval(rm,i,j,0), sizeof(double), rm->ncomp, fp) != rm->ncomp) return(0); - for (k = rm->ncomp; k--; ) - rmx_lval(rm,i,j,k) = val[k]; - } return(1); } @@ -192,15 +188,11 @@ rmx_load(const char *inspec) if (inspec == NULL) { /* reading from stdin? */ inspec = ""; -#ifdef _WIN32 - _setmode(fileno(stdin), _O_BINARY); -#endif + SET_FILE_BINARY(stdin); } else if (inspec[0] == '!') { if ((fp = popen(inspec+1, "r")) == NULL) return(NULL); -#ifdef _WIN32 - _setmode(fileno(fp), _O_BINARY); -#endif + SET_FILE_BINARY(stdin); } else { const char *sp = inspec; /* check suffix */ while (*sp) @@ -213,6 +205,7 @@ rmx_load(const char *inspec) return(NULL); dnew = rmx_from_cmatrix(cm); cm_free(cm); + dnew->dtype = DTascii; return(dnew); } /* else open it ourselves */ @@ -250,6 +243,7 @@ rmx_load(const char *inspec) dnew->info = dinfo.info; switch (dinfo.dtype) { case DTascii: + SET_FILE_TEXT(stdin); if (!rmx_load_ascii(dnew, fp)) goto loaderr; dnew->dtype = DTascii; /* should leave double? */ @@ -296,14 +290,15 @@ loaderr: /* should report error? */ static int rmx_write_ascii(const RMATRIX *rm, FILE *fp) { + const char *fmt = (rm->dtype == DTfloat) ? " %.7e" : + (rm->dtype == DTrgbe) | (rm->dtype == DTxyze) ? " %.3e" : + " %.15e" ; int i, j, k; -#ifdef _WIN32 - _setmode(fileno(fp), _O_TEXT); -#endif + for (i = 0; i < rm->nrows; i++) { for (j = 0; j < rm->ncols; j++) { for (k = 0; k < rm->ncomp; k++) - fprintf(fp, " %.15e", rmx_lval(rm,i,j,k)); + fprintf(fp, fmt, rmx_lval(rm,i,j,k)); fputc('\t', fp); } fputc('\n', fp); @@ -325,7 +320,7 @@ rmx_write_float(const RMATRIX *rm, FILE *fp) for (j = 0; j < rm->ncols; j++) { for (k = rm->ncomp; k--; ) val[k] = (float)rmx_lval(rm,i,j,k); - if (fwrite(val, sizeof(val[0]), rm->ncomp, fp) != rm->ncomp) + if (putbinary(val, sizeof(val[0]), rm->ncomp, fp) != rm->ncomp) return(0); } return(1); @@ -334,37 +329,29 @@ rmx_write_float(const RMATRIX *rm, FILE *fp) static int rmx_write_double(const RMATRIX *rm, FILE *fp) { - int i, j, k; - double val[100]; + int i, j; - if (rm->ncomp > 100) { - fputs("Unsupported # components in rmx_write_double()\n", stderr); - exit(1); - } for (i = 0; i < rm->nrows; i++) - for (j = 0; j < rm->ncols; j++) { - for (k = rm->ncomp; k--; ) - val[k] = rmx_lval(rm,i,j,k); - if (fwrite(val, sizeof(val[0]), rm->ncomp, fp) != rm->ncomp) + for (j = 0; j < rm->ncols; j++) + if (putbinary(&rmx_lval(rm,i,j,0), sizeof(double), rm->ncomp, fp) != rm->ncomp) return(0); - } return(1); } static int rmx_write_rgbe(const RMATRIX *rm, FILE *fp) { - COLOR *scan = (COLOR *)malloc(sizeof(COLOR)*rm->ncols); + COLR *scan = (COLR *)malloc(sizeof(COLR)*rm->ncols); int i, j; if (scan == NULL) return(0); for (i = 0; i < rm->nrows; i++) { for (j = rm->ncols; j--; ) - setcolor(scan[j], rmx_lval(rm,i,j,0), + setcolr(scan[j], rmx_lval(rm,i,j,0), rmx_lval(rm,i,j,1), rmx_lval(rm,i,j,2) ); - if (fwritescan(scan, rm->ncols, fp) < 0) { + if (fwritecolrs(scan, rm->ncols, fp) < 0) { free(scan); return(0); } @@ -382,6 +369,9 @@ rmx_write(const RMATRIX *rm, int dtype, FILE *fp) if ((rm == NULL) | (fp == NULL)) return(0); +#ifdef getc_unlocked + flockfile(fp); +#endif /* complete header */ if (rm->info) fputs(rm->info, fp); @@ -426,6 +416,9 @@ rmx_write(const RMATRIX *rm, int dtype, FILE *fp) return(0); } ok &= (fflush(fp) == 0); +#ifdef getc_unlocked + funlockfile(fp); +#endif rmx_free(mydm); return(ok); } @@ -473,6 +466,14 @@ rmx_transpose(const RMATRIX *rm) if (rm == NULL) return(0); + if ((rm->nrows == 1) | (rm->ncols == 1)) { + dnew = rmx_copy(rm); + if (dnew == NULL) + return(NULL); + dnew->nrows = rm->ncols; + dnew->ncols = rm->nrows; + return(dnew); + } dnew = rmx_alloc(rm->ncols, rm->nrows, rm->ncomp); if (dnew == NULL) return(NULL); @@ -511,13 +512,69 @@ rmx_multiply(const RMATRIX *m1, const RMATRIX *m2) for (k = mres->ncomp; k--; ) { long double d = 0; for (h = m1->ncols; h--; ) - d += (long double)rmx_lval(m1,i,h,k) * - (long double)rmx_lval(m2,h,j,k); + d += rmx_lval(m1,i,h,k) * rmx_lval(m2,h,j,k); rmx_lval(mres,i,j,k) = (double)d; } return(mres); } +/* Element-wise multiplication (or division) of m2 into m1 */ +int +rmx_elemult(RMATRIX *m1, const RMATRIX *m2, int divide) +{ + int zeroDivides = 0; + int i, j, k; + + if ((m1 == NULL) | (m2 == NULL) || + (m1->ncols != m2->ncols) | (m1->nrows != m2->nrows)) + return(0); + if ((m2->ncomp > 1) & (m2->ncomp != m1->ncomp)) + return(0); + i = rmx_newtype(m1->dtype, m2->dtype); + if (i) + m1->dtype = i; + else + rmx_addinfo(m1, rmx_mismatch_warn); + for (i = m1->nrows; i--; ) + for (j = m1->ncols; j--; ) + if (divide) { + double d; + if (m2->ncomp == 1) { + d = rmx_lval(m2,i,j,0); + if (d == 0) { + ++zeroDivides; + for (k = m1->ncomp; k--; ) + rmx_lval(m1,i,j,k) = 0; + } else { + d = 1./d; + for (k = m1->ncomp; k--; ) + rmx_lval(m1,i,j,k) *= d; + } + } else + for (k = m1->ncomp; k--; ) { + d = rmx_lval(m2,i,j,k); + if (d == 0) { + ++zeroDivides; + rmx_lval(m1,i,j,k) = 0; + } else + rmx_lval(m1,i,j,k) /= d; + } + } else { + if (m2->ncomp == 1) { + const double d = rmx_lval(m2,i,j,0); + for (k = m1->ncomp; k--; ) + rmx_lval(m1,i,j,k) *= d; + } else + for (k = m1->ncomp; k--; ) + rmx_lval(m1,i,j,k) *= rmx_lval(m2,i,j,k); + } + if (zeroDivides) { + fputs("Divide by zero in rmx_elemult()\n", stderr); + errno = ERANGE; + } + return(1); +} + /* Sum second matrix into first, applying scale factor beforehand */ int rmx_sum(RMATRIX *msum, const RMATRIX *madd, const double sf[]) @@ -565,6 +622,8 @@ rmx_scale(RMATRIX *rm, const double sf[]) for (k = rm->ncomp; k--; ) rmx_lval(rm,i,j,k) *= sf[k]; + if (rm->info) + rmx_addinfo(rm, "Applied scalar\n"); return(1); } @@ -580,6 +639,13 @@ rmx_transform(const RMATRIX *msrc, int n, const double dnew = rmx_alloc(msrc->nrows, msrc->ncols, n); if (dnew == NULL) return(NULL); + if (msrc->info) { + char buf[128]; + sprintf(buf, "Applied %dx%d matrix transform\n", + dnew->ncomp, msrc->ncomp); + rmx_addinfo(dnew, msrc->info); + rmx_addinfo(dnew, buf); + } dnew->dtype = msrc->dtype; for (i = dnew->nrows; i--; ) for (j = dnew->ncols; j--; )