ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cal/total.c
Revision: 1.16
Committed: Thu Mar 24 22:26:50 2022 UTC (2 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R4, HEAD
Changes since 1.15: +12 -5 lines
Log Message:
fix(total): Improved option error checking

File Contents

# User Rev Content
1 greg 1.1 #ifndef lint
2 greg 1.16 static const char RCSid[] = "$Id: total.c,v 1.15 2021/11/16 03:30:45 greg Exp $";
3 greg 1.1 #endif
4     /*
5     * total.c - program to reduce columns of data.
6     *
7     * 5/18/88
8     */
9    
10     #include <stdlib.h>
11     #include <ctype.h>
12     #include <math.h>
13 greg 1.4 #include "platform.h"
14 greg 1.13 #include "rtio.h"
15 greg 1.1
16 greg 1.8 #define MAXCOL 8192 /* maximum number of columns */
17 greg 1.1
18     #define ADD 0 /* add numbers */
19     #define MULT 1 /* multiply numbers */
20     #define MAX 2 /* maximum */
21     #define MIN 3 /* minimum */
22    
23     double init_val[] = {0., 1., -1e12, 1e12}; /* initial values */
24    
25 greg 1.11 long incnt = 0; /* limit number of input records? */
26     long outcnt = 0; /* limit number of output records? */
27    
28 greg 1.1 int func = ADD; /* default function */
29     double power = 0.0; /* power for sum */
30     int mean = 0; /* compute mean */
31     int count = 0; /* number to sum */
32 greg 1.4 int nbicols = 0; /* number of binary input columns */
33     int bocols = 0; /* produce binary output columns */
34 greg 1.1 int tabc = '\t'; /* default separator */
35     int subtotal = 0; /* produce subtotals? */
36 greg 1.11 int nrecsout = 0; /* number of records produced */
37 greg 1.1
38 schorsch 1.2 static int execute(char *fname);
39 greg 1.1
40 schorsch 1.2 int
41     main(
42     int argc,
43     char *argv[]
44     )
45 greg 1.1 {
46     int status;
47     int a;
48    
49     for (a = 1; a < argc; a++)
50     if (argv[a][0] == '-')
51     if (argv[a][1] >= '0' && argv[a][1] <= '9')
52     count = atoi(argv[a]+1);
53     else
54     switch (argv[a][1]) {
55     case 'm':
56     mean = !mean;
57     break;
58     case 'p':
59     func = MULT;
60     break;
61     case 's':
62     power = atof(argv[a]+2);
63     break;
64     case 'u':
65     func = MAX;
66     break;
67     case 'l':
68     func = MIN;
69     break;
70     case 't':
71     tabc = argv[a][2];
72     break;
73     case 'r':
74     subtotal = !subtotal;
75     break;
76 greg 1.4 case 'i':
77     switch (argv[a][2]) {
78 greg 1.11 case 'n':
79     incnt = atol(argv[++a]);
80     break;
81 greg 1.4 case 'a':
82     nbicols = 0;
83     break;
84     case 'd':
85     if (isdigit(argv[a][3]))
86     nbicols = atoi(argv[a]+3);
87     else
88     nbicols = 1;
89     if (nbicols > MAXCOL) {
90     fprintf(stderr,
91     "%s: too many input columns\n",
92     argv[0]);
93     exit(1);
94     }
95     break;
96     case 'f':
97     if (isdigit(argv[a][3]))
98     nbicols = -atoi(argv[a]+3);
99     else
100     nbicols = -1;
101     if (-nbicols > MAXCOL) {
102     fprintf(stderr,
103     "%s: too many input columns\n",
104     argv[0]);
105     exit(1);
106     }
107     break;
108     default:
109     goto userr;
110     }
111     break;
112     case 'o':
113     switch (argv[a][2]) {
114 greg 1.11 case 'n':
115     outcnt = atol(argv[++a]);
116     break;
117 greg 1.4 case 'a':
118     bocols = 0;
119     break;
120     case 'd':
121     bocols = 1;
122     break;
123     case 'f':
124     bocols = -1;
125     break;
126     default:
127     goto userr;
128     }
129     break;
130     default:;
131     userr:
132 greg 1.1 fprintf(stderr,
133 greg 1.4 "Usage: %s [-m][-sE|p|u|l][-tC][-i{f|d}[N]][-o{f|d}][-count [-r]] [file..]\n",
134 greg 1.1 argv[0]);
135     exit(1);
136     }
137     else
138     break;
139 greg 1.16 if ((power != 0.0) & (func != ADD)) {
140     fprintf(stderr, "%s: -sE option requires summation\n", argv[0]);
141     exit(1);
142     }
143 greg 1.1 if (mean) {
144     if (func == MAX) {
145     fprintf(stderr, "%s: average maximum?!\n", argv[0]);
146     exit(1);
147     }
148     if (func == MIN) {
149     fprintf(stderr, "%s: average minimum?!\n", argv[0]);
150     exit(1);
151     }
152     }
153 greg 1.4 if (bocols)
154     SET_FILE_BINARY(stdout);
155 greg 1.1 status = 0;
156     if (a >= argc)
157     status = execute(NULL) == -1 ? 1 : status;
158     else
159 greg 1.11 for ( ; a < argc && (outcnt <= 0 || nrecsout < outcnt); a++)
160 greg 1.1 status = execute(argv[a]) == -1 ? 2 : status;
161     exit(status);
162     }
163    
164    
165 schorsch 1.2 static int
166 greg 1.4 getrecord( /* read next input record */
167     double field[MAXCOL],
168     FILE *fp
169     )
170     {
171     char buf[16*MAXCOL];
172     char *cp, *num;
173     int nf;
174     /* reading binary input? */
175     if (nbicols > 0)
176 greg 1.13 return(getbinary(field, sizeof(double), nbicols, fp));
177 greg 1.4 if (nbicols < 0) {
178     float *fbuf = (float *)buf;
179     int i;
180 greg 1.13 nf = getbinary(fbuf, sizeof(float), -nbicols, fp);
181 greg 1.4 for (i = nf; i-- > 0; )
182     field[i] = fbuf[i];
183     return(nf);
184     }
185     /* reading ASCII input */
186     cp = fgets(buf, sizeof(buf), fp);
187     if (cp == NULL)
188     return(0);
189     for (nf = 0; nf < MAXCOL; nf++) {
190     while (isspace(*cp))
191     cp++;
192     if (!*cp)
193     break;
194     num = cp;
195     while (*cp && !(isspace(tabc)?isspace(*cp):*cp==tabc))
196     cp++;
197     if (*cp)
198     *cp++ = '\0';
199     if (!*num || isspace(*num))
200     field[nf] = init_val[func];
201     else
202     field[nf] = atof(num);
203     }
204     return(nf);
205     }
206    
207    
208     static void
209     putrecord( /* write out results record */
210     const double *field,
211     int n,
212     FILE *fp
213     )
214     {
215     /* binary output? */
216     if (bocols > 0) {
217 greg 1.13 putbinary(field, sizeof(double), n, fp);
218 greg 1.4 return;
219     }
220     if (bocols < 0) {
221     float fv;
222     while (n-- > 0) {
223     fv = *field++;
224 greg 1.13 putbinary(&fv, sizeof(float), 1, fp);
225 greg 1.4 }
226     return;
227     }
228     /* ASCII output */
229 greg 1.10 while (n-- > 0) {
230     fprintf(fp, "%.9g", *field++);
231     if (n) fputc(tabc, fp);
232     }
233 greg 1.4 fputc('\n', fp);
234 greg 1.15 if (!subtotal)
235     fflush(fp); /* flush unless -r */
236 greg 1.4 }
237    
238    
239     static int
240 schorsch 1.2 execute( /* compute result */
241     char *fname
242     )
243 greg 1.1 {
244 greg 1.4 double inpval[MAXCOL];
245     double tally[MAXCOL];
246 greg 1.7 short rsign[MAXCOL];
247 greg 1.1 double result[MAXCOL];
248 greg 1.7 int n;
249 greg 1.4 int nread, ncol;
250 greg 1.1 long nlin, ltotal;
251     FILE *fp;
252     /* open file */
253     if (fname == NULL)
254     fp = stdin;
255     else if ((fp = fopen(fname, "r")) == NULL) {
256     fprintf(stderr, "%s: cannot open\n", fname);
257     return(-1);
258     }
259 greg 1.4 if (nbicols)
260     SET_FILE_BINARY(fp);
261 greg 1.9 #ifdef getc_unlocked /* avoid lock/unlock overhead */
262     flockfile(fp);
263     #endif
264    
265 greg 1.1 ltotal = 0;
266     while (!feof(fp)) {
267 schorsch 1.3 if (ltotal == 0) { /* initialize */
268 greg 1.1 if (func == MULT) /* special case */
269 greg 1.7 for (n = 0; n < MAXCOL; n++) {
270 greg 1.4 tally[n] = 0.0;
271 greg 1.7 rsign[n] = 1;
272     }
273 greg 1.1 else
274     for (n = 0; n < MAXCOL; n++)
275 greg 1.4 tally[n] = init_val[func];
276 schorsch 1.3 }
277 greg 1.1 ncol = 0;
278     for (nlin = 0; (count <= 0 || nlin < count) &&
279 greg 1.11 (incnt <= 0 || nlin < incnt) &&
280 greg 1.4 (nread = getrecord(inpval, fp)) > 0;
281 greg 1.1 nlin++) {
282     /* compute */
283 greg 1.4 for (n = 0; n < nread; n++)
284 greg 1.1 switch (func) {
285     case ADD:
286 greg 1.4 if (inpval[n] == 0.0)
287 greg 1.1 break;
288 greg 1.16 if (power == 0.0)
289     tally[n] += inpval[n];
290     else if (power == 1.0)
291     tally[n] += fabs(inpval[n]);
292     else if (power == -1.0)
293     tally[n] += 1.0/fabs(inpval[n]);
294 greg 1.1 else
295 greg 1.16 tally[n] += pow(fabs(inpval[n]), power);
296 greg 1.1 break;
297     case MULT:
298 greg 1.4 if (inpval[n] == 0.0)
299 greg 1.7 rsign[n] = 0;
300     else if (inpval[n] < 0.0) {
301     rsign[n] = -rsign[n];
302     inpval[n] = -inpval[n];
303     }
304     if (rsign[n])
305     tally[n] += log(inpval[n]);
306 greg 1.1 break;
307     case MAX:
308 greg 1.4 if (inpval[n] > tally[n])
309     tally[n] = inpval[n];
310 greg 1.1 break;
311     case MIN:
312 greg 1.4 if (inpval[n] < tally[n])
313     tally[n] = inpval[n];
314 greg 1.1 break;
315     }
316 greg 1.4 if (nread > ncol)
317     ncol = nread;
318 greg 1.1 }
319     if (nlin == 0)
320     break;
321     /* compute and print */
322     ltotal += nlin;
323     for (n = 0; n < ncol; n++) {
324 greg 1.4 result[n] = tally[n];
325 greg 1.1 if (mean) {
326 greg 1.4 result[n] /= (double)ltotal;
327     if (func == ADD && power != 0.0 && result[n] != 0.0)
328     result[n] = pow(result[n], 1.0/power);
329 greg 1.1 }
330     if (func == MULT)
331 greg 1.7 result[n] = rsign[n] * exp(result[n]);
332 greg 1.1 }
333 greg 1.4 putrecord(result, ncol, stdout);
334 greg 1.11 ++nrecsout;
335     if (outcnt > 0 && nrecsout >= outcnt)
336     break;
337 greg 1.1 if (!subtotal)
338     ltotal = 0;
339 greg 1.12 if (incnt > 0 && nlin >= incnt)
340     break;
341 greg 1.1 }
342 greg 1.4 /* close input */
343 greg 1.15 return(fclose(fp) == EOF ? 1 : 0);
344 greg 1.1 }