--- ray/src/util/rmatrix.c 2016/08/18 17:57:57 2.22 +++ ray/src/util/rmatrix.c 2018/04/09 21:30:07 2.26 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: rmatrix.c,v 2.22 2016/08/18 17:57:57 greg Exp $"; +static const char RCSid[] = "$Id: rmatrix.c,v 2.26 2018/04/09 21:30:07 greg Exp $"; #endif /* * General matrix operations. @@ -9,6 +9,7 @@ static const char RCSid[] = "$Id: rmatrix.c,v 2.22 201 #include #include #include +#include #include "rtio.h" #include "platform.h" #include "resolu.h" @@ -145,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 (getbinary(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); } @@ -333,20 +326,12 @@ 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 (putbinary(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); } @@ -520,6 +505,63 @@ rmx_multiply(const RMATRIX *m1, const RMATRIX *m2) 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 */