--- ray/src/cal/total.c 2008/04/18 16:32:27 1.6 +++ ray/src/cal/total.c 2022/03/24 22:26:50 1.16 @@ -1,5 +1,5 @@ #ifndef lint -static const char RCSid[] = "$Id: total.c,v 1.6 2008/04/18 16:32:27 greg Exp $"; +static const char RCSid[] = "$Id: total.c,v 1.16 2022/03/24 22:26:50 greg Exp $"; #endif /* * total.c - program to reduce columns of data. @@ -7,13 +7,13 @@ static const char RCSid[] = "$Id: total.c,v 1.6 2008/0 * 5/18/88 */ -#include #include #include #include #include "platform.h" +#include "rtio.h" -#define MAXCOL 2048 /* maximum number of columns */ +#define MAXCOL 8192 /* maximum number of columns */ #define ADD 0 /* add numbers */ #define MULT 1 /* multiply numbers */ @@ -22,6 +22,9 @@ static const char RCSid[] = "$Id: total.c,v 1.6 2008/0 double init_val[] = {0., 1., -1e12, 1e12}; /* initial values */ +long incnt = 0; /* limit number of input records? */ +long outcnt = 0; /* limit number of output records? */ + int func = ADD; /* default function */ double power = 0.0; /* power for sum */ int mean = 0; /* compute mean */ @@ -30,6 +33,7 @@ int nbicols = 0; /* number of binary input columns int bocols = 0; /* produce binary output columns */ int tabc = '\t'; /* default separator */ int subtotal = 0; /* produce subtotals? */ +int nrecsout = 0; /* number of records produced */ static int execute(char *fname); @@ -55,7 +59,6 @@ char *argv[] func = MULT; break; case 's': - func = ADD; power = atof(argv[a]+2); break; case 'u': @@ -72,6 +75,9 @@ char *argv[] break; case 'i': switch (argv[a][2]) { + case 'n': + incnt = atol(argv[++a]); + break; case 'a': nbicols = 0; break; @@ -105,6 +111,9 @@ char *argv[] break; case 'o': switch (argv[a][2]) { + case 'n': + outcnt = atol(argv[++a]); + break; case 'a': bocols = 0; break; @@ -127,6 +136,10 @@ char *argv[] } else break; + if ((power != 0.0) & (func != ADD)) { + fprintf(stderr, "%s: -sE option requires summation\n", argv[0]); + exit(1); + } if (mean) { if (func == MAX) { fprintf(stderr, "%s: average maximum?!\n", argv[0]); @@ -143,7 +156,7 @@ char *argv[] if (a >= argc) status = execute(NULL) == -1 ? 1 : status; else - for ( ; a < argc; a++) + for ( ; a < argc && (outcnt <= 0 || nrecsout < outcnt); a++) status = execute(argv[a]) == -1 ? 2 : status; exit(status); } @@ -160,11 +173,11 @@ getrecord( /* read next input record */ int nf; /* reading binary input? */ if (nbicols > 0) - return(fread(field, sizeof(double), nbicols, fp)); + return(getbinary(field, sizeof(double), nbicols, fp)); if (nbicols < 0) { float *fbuf = (float *)buf; int i; - nf = fread(fbuf, sizeof(float), -nbicols, fp); + nf = getbinary(fbuf, sizeof(float), -nbicols, fp); for (i = nf; i-- > 0; ) field[i] = fbuf[i]; return(nf); @@ -201,21 +214,25 @@ putrecord( /* write out results record */ { /* binary output? */ if (bocols > 0) { - fwrite(field, sizeof(double), n, fp); + putbinary(field, sizeof(double), n, fp); return; } if (bocols < 0) { float fv; while (n-- > 0) { fv = *field++; - fwrite(&fv, sizeof(float), 1, fp); + putbinary(&fv, sizeof(float), 1, fp); } return; } /* ASCII output */ - while (n-- > 0) - fprintf(fp, "%.9g%c", *field++, tabc); + while (n-- > 0) { + fprintf(fp, "%.9g", *field++); + if (n) fputc(tabc, fp); + } fputc('\n', fp); + if (!subtotal) + fflush(fp); /* flush unless -r */ } @@ -226,8 +243,9 @@ char *fname { double inpval[MAXCOL]; double tally[MAXCOL]; + short rsign[MAXCOL]; double result[MAXCOL]; - register int n; + int n; int nread, ncol; long nlin, ltotal; FILE *fp; @@ -240,18 +258,25 @@ char *fname } if (nbicols) SET_FILE_BINARY(fp); +#ifdef getc_unlocked /* avoid lock/unlock overhead */ + flockfile(fp); +#endif + ltotal = 0; while (!feof(fp)) { if (ltotal == 0) { /* initialize */ if (func == MULT) /* special case */ - for (n = 0; n < MAXCOL; n++) + for (n = 0; n < MAXCOL; n++) { tally[n] = 0.0; + rsign[n] = 1; + } else for (n = 0; n < MAXCOL; n++) tally[n] = init_val[func]; } ncol = 0; for (nlin = 0; (count <= 0 || nlin < count) && + (incnt <= 0 || nlin < incnt) && (nread = getrecord(inpval, fp)) > 0; nlin++) { /* compute */ @@ -260,15 +285,24 @@ char *fname case ADD: if (inpval[n] == 0.0) break; - if (power != 0.0) - tally[n] += pow(fabs(inpval[n]),power); - else + if (power == 0.0) tally[n] += inpval[n]; + else if (power == 1.0) + tally[n] += fabs(inpval[n]); + else if (power == -1.0) + tally[n] += 1.0/fabs(inpval[n]); + else + tally[n] += pow(fabs(inpval[n]), power); break; case MULT: if (inpval[n] == 0.0) - break; - tally[n] += log(fabs(inpval[n])); + rsign[n] = 0; + else if (inpval[n] < 0.0) { + rsign[n] = -rsign[n]; + inpval[n] = -inpval[n]; + } + if (rsign[n]) + tally[n] += log(inpval[n]); break; case MAX: if (inpval[n] > tally[n]) @@ -294,12 +328,17 @@ char *fname result[n] = pow(result[n], 1.0/power); } if (func == MULT) - result[n] = exp(result[n]); + result[n] = rsign[n] * exp(result[n]); } putrecord(result, ncol, stdout); + ++nrecsout; + if (outcnt > 0 && nrecsout >= outcnt) + break; if (!subtotal) ltotal = 0; + if (incnt > 0 && nlin >= incnt) + break; } /* close input */ - return(fclose(fp)); + return(fclose(fp) == EOF ? 1 : 0); }