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, 1 month 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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: total.c,v 1.15 2021/11/16 03:30:45 greg Exp $";
3 #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 #include "platform.h"
14 #include "rtio.h"
15
16 #define MAXCOL 8192 /* maximum number of columns */
17
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 long incnt = 0; /* limit number of input records? */
26 long outcnt = 0; /* limit number of output records? */
27
28 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 int nbicols = 0; /* number of binary input columns */
33 int bocols = 0; /* produce binary output columns */
34 int tabc = '\t'; /* default separator */
35 int subtotal = 0; /* produce subtotals? */
36 int nrecsout = 0; /* number of records produced */
37
38 static int execute(char *fname);
39
40 int
41 main(
42 int argc,
43 char *argv[]
44 )
45 {
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 case 'i':
77 switch (argv[a][2]) {
78 case 'n':
79 incnt = atol(argv[++a]);
80 break;
81 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 case 'n':
115 outcnt = atol(argv[++a]);
116 break;
117 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 fprintf(stderr,
133 "Usage: %s [-m][-sE|p|u|l][-tC][-i{f|d}[N]][-o{f|d}][-count [-r]] [file..]\n",
134 argv[0]);
135 exit(1);
136 }
137 else
138 break;
139 if ((power != 0.0) & (func != ADD)) {
140 fprintf(stderr, "%s: -sE option requires summation\n", argv[0]);
141 exit(1);
142 }
143 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 if (bocols)
154 SET_FILE_BINARY(stdout);
155 status = 0;
156 if (a >= argc)
157 status = execute(NULL) == -1 ? 1 : status;
158 else
159 for ( ; a < argc && (outcnt <= 0 || nrecsout < outcnt); a++)
160 status = execute(argv[a]) == -1 ? 2 : status;
161 exit(status);
162 }
163
164
165 static int
166 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 return(getbinary(field, sizeof(double), nbicols, fp));
177 if (nbicols < 0) {
178 float *fbuf = (float *)buf;
179 int i;
180 nf = getbinary(fbuf, sizeof(float), -nbicols, fp);
181 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 putbinary(field, sizeof(double), n, fp);
218 return;
219 }
220 if (bocols < 0) {
221 float fv;
222 while (n-- > 0) {
223 fv = *field++;
224 putbinary(&fv, sizeof(float), 1, fp);
225 }
226 return;
227 }
228 /* ASCII output */
229 while (n-- > 0) {
230 fprintf(fp, "%.9g", *field++);
231 if (n) fputc(tabc, fp);
232 }
233 fputc('\n', fp);
234 if (!subtotal)
235 fflush(fp); /* flush unless -r */
236 }
237
238
239 static int
240 execute( /* compute result */
241 char *fname
242 )
243 {
244 double inpval[MAXCOL];
245 double tally[MAXCOL];
246 short rsign[MAXCOL];
247 double result[MAXCOL];
248 int n;
249 int nread, ncol;
250 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 if (nbicols)
260 SET_FILE_BINARY(fp);
261 #ifdef getc_unlocked /* avoid lock/unlock overhead */
262 flockfile(fp);
263 #endif
264
265 ltotal = 0;
266 while (!feof(fp)) {
267 if (ltotal == 0) { /* initialize */
268 if (func == MULT) /* special case */
269 for (n = 0; n < MAXCOL; n++) {
270 tally[n] = 0.0;
271 rsign[n] = 1;
272 }
273 else
274 for (n = 0; n < MAXCOL; n++)
275 tally[n] = init_val[func];
276 }
277 ncol = 0;
278 for (nlin = 0; (count <= 0 || nlin < count) &&
279 (incnt <= 0 || nlin < incnt) &&
280 (nread = getrecord(inpval, fp)) > 0;
281 nlin++) {
282 /* compute */
283 for (n = 0; n < nread; n++)
284 switch (func) {
285 case ADD:
286 if (inpval[n] == 0.0)
287 break;
288 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 else
295 tally[n] += pow(fabs(inpval[n]), power);
296 break;
297 case MULT:
298 if (inpval[n] == 0.0)
299 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 break;
307 case MAX:
308 if (inpval[n] > tally[n])
309 tally[n] = inpval[n];
310 break;
311 case MIN:
312 if (inpval[n] < tally[n])
313 tally[n] = inpval[n];
314 break;
315 }
316 if (nread > ncol)
317 ncol = nread;
318 }
319 if (nlin == 0)
320 break;
321 /* compute and print */
322 ltotal += nlin;
323 for (n = 0; n < ncol; n++) {
324 result[n] = tally[n];
325 if (mean) {
326 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 }
330 if (func == MULT)
331 result[n] = rsign[n] * exp(result[n]);
332 }
333 putrecord(result, ncol, stdout);
334 ++nrecsout;
335 if (outcnt > 0 && nrecsout >= outcnt)
336 break;
337 if (!subtotal)
338 ltotal = 0;
339 if (incnt > 0 && nlin >= incnt)
340 break;
341 }
342 /* close input */
343 return(fclose(fp) == EOF ? 1 : 0);
344 }