--- ray/src/util/rmtxop.c 2019/08/12 01:20:26 2.13 +++ ray/src/util/rmtxop.c 2022/03/23 00:58:35 2.20 @@ -1,11 +1,10 @@ #ifndef lint -static const char RCSid[] = "$Id: rmtxop.c,v 2.13 2019/08/12 01:20:26 greg Exp $"; +static const char RCSid[] = "$Id: rmtxop.c,v 2.20 2022/03/23 00:58:35 greg Exp $"; #endif /* * General component matrix operations. */ -#include #include #include #include "rtio.h" @@ -15,8 +14,6 @@ static const char RCSid[] = "$Id: rmtxop.c,v 2.13 2019 #define MAXCOMP 16 /* #components we support */ -static const char stdin_name[] = ""; - /* unary matrix operation(s) */ typedef struct { double sca[MAXCOMP]; /* scalar coefficients */ @@ -29,6 +26,7 @@ typedef struct { /* matrix input source and requested operation(s) */ typedef struct { const char *inspec; /* input specification */ + RMPref rmp; /* matrix preference */ RUNARYOP preop; /* unary operation(s) */ RMATRIX *mtx; /* original matrix if loaded */ int binop; /* binary op with next (or 0) */ @@ -40,11 +38,10 @@ int verbose = 0; /* verbose reporting? */ static int loadmatrix(ROPMAT *rop) { - if (rop->mtx != NULL) + if (rop->mtx != NULL) /* already loaded? */ return(0); - rop->mtx = rmx_load(rop->inspec == stdin_name ? - (const char *)NULL : rop->inspec); + rop->mtx = rmx_load(rop->inspec, rop->rmp); if (rop->mtx == NULL) { fputs(rop->inspec, stderr); fputs(": cannot load matrix\n", stderr); @@ -140,19 +137,22 @@ binaryop(const char *inspec, RMATRIX *mleft, int op, R if ((mleft == NULL) | (mright == NULL)) return(NULL); - switch (op) { case '.': /* concatenate */ - mres = rmx_multiply(mleft, mright); + if (mleft->ncomp != mright->ncomp) { + fputs(inspec, stderr); + fputs(": # components do not match\n", stderr); + } else if (mleft->ncols != mright->nrows) { + fputs(inspec, stderr); + fputs(": mismatched dimensions\n", + stderr); + } else + mres = rmx_multiply(mleft, mright); rmx_free(mleft); rmx_free(mright); if (mres == NULL) { fputs(inspec, stderr); - if (mleft->ncols != mright->nrows) - fputs(": mismatched dimensions for multiply\n", - stderr); - else - fputs(": concatenation failed\n", stderr); + fputs(": concatenation failed\n", stderr); return(NULL); } if (verbose) { @@ -229,12 +229,17 @@ op_right2left(ROPMAT *mop) int rpos = 0; /* find end of list */ while (mop[rpos].binop) - rpos++; + if (mop[rpos++].binop != '.') { + fputs( + "Right-to-left evaluation only for matrix multiplication!\n", + stderr); + return(NULL); + } mright = loadop(mop+rpos); while (rpos-- > 0) { if (mright == NULL) break; - mright = binaryop(mop[rpos].inspec, + mright = binaryop(mop[rpos+1].inspec, loadop(mop+rpos), mop[rpos].binop, mright); } return(mright); @@ -313,16 +318,15 @@ main(int argc, char *argv[]) int i; /* get options and arguments */ for (i = 1; i < argc; i++) { - if (nmats >= nall) - mop = grow_moparray(mop, nall += 2); if (argv[i][0] && !argv[i][1] && strchr(".+*/", argv[i][0]) != NULL) { - if (mop[nmats].inspec == NULL || mop[nmats].binop) { - fprintf(stderr, "%s: missing matrix argument\n", - argv[0]); + if (!nmats || mop[nmats-1].binop) { + fprintf(stderr, + "%s: missing matrix argument before '%c' operation\n", + argv[0], argv[i][0]); return(1); } - mop[nmats++].binop = argv[i][0]; + mop[nmats-1].binop = argv[i][0]; } else if (argv[i][0] != '-' || !argv[i][1]) { if (argv[i][0] == '-') { if (stdin_used++) { @@ -341,7 +345,7 @@ main(int argc, char *argv[]) int n = argc-1 - i; switch (argv[i][1]) { /* get option */ case 'v': - verbose = !verbose; + verbose++; break; case 'f': switch (argv[i][2]) { @@ -376,19 +380,41 @@ main(int argc, char *argv[]) get_factors(mop[nmats].preop.cmat, n, argv+i+1); break; + case 'r': + if (argv[i][2] == 'f') + mop[nmats].rmp = RMPreflF; + else if (argv[i][2] == 'b') + mop[nmats].rmp = RMPreflB; + else + goto userr; + break; default: fprintf(stderr, "%s: unknown operation '%s'\n", argv[0], argv[i]); goto userr; } } + if (nmats >= nall) + mop = grow_moparray(mop, nall += 2); } if (mop[0].inspec == NULL) /* nothing to do? */ goto userr; + if (mop[nmats-1].binop) { + fprintf(stderr, + "%s: missing matrix argument after '%c' operation\n", + argv[0], mop[nmats-1].binop); + return(1); + } /* favor quicker concatenation */ - mres = prefer_right2left(mop) ? op_right2left(mop) : op_left2right(mop); - if (!mres) + mop[nmats].mtx = prefer_right2left(mop) ? op_right2left(mop) + : op_left2right(mop); + if (mop[nmats].mtx == NULL) return(1); + /* apply trailing unary operations */ + mop[nmats].inspec = "trailing_ops"; + mres = loadop(mop+nmats); + if (mres == NULL) + return(1); /* write result to stdout */ if (outfmt == DTfromHeader) outfmt = mres->dtype; @@ -404,7 +430,7 @@ main(int argc, char *argv[]) return(0); userr: fprintf(stderr, - "Usage: %s [-v][-f[adfc][-t][-s sf .. | -c ce ..] m1 [.+*/] .. > mres\n", + "Usage: %s [-v][-f[adfc][-t][-s sf .. | -c ce ..][-rf|-rb] m1 [.+*/] .. > mres\n", argv[0]); return(1); }