ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cal/total.c
Revision: 1.15
Committed: Tue Nov 16 03:30:45 2021 UTC (2 years, 5 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.14: +4 -2 lines
Log Message:
feat(total): added automatic output flushing unless -r option is present

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: total.c,v 1.14 2019/12/28 18:05:13 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 func = ADD;
63 power = atof(argv[a]+2);
64 break;
65 case 'u':
66 func = MAX;
67 break;
68 case 'l':
69 func = MIN;
70 break;
71 case 't':
72 tabc = argv[a][2];
73 break;
74 case 'r':
75 subtotal = !subtotal;
76 break;
77 case 'i':
78 switch (argv[a][2]) {
79 case 'n':
80 incnt = atol(argv[++a]);
81 break;
82 case 'a':
83 nbicols = 0;
84 break;
85 case 'd':
86 if (isdigit(argv[a][3]))
87 nbicols = atoi(argv[a]+3);
88 else
89 nbicols = 1;
90 if (nbicols > MAXCOL) {
91 fprintf(stderr,
92 "%s: too many input columns\n",
93 argv[0]);
94 exit(1);
95 }
96 break;
97 case 'f':
98 if (isdigit(argv[a][3]))
99 nbicols = -atoi(argv[a]+3);
100 else
101 nbicols = -1;
102 if (-nbicols > MAXCOL) {
103 fprintf(stderr,
104 "%s: too many input columns\n",
105 argv[0]);
106 exit(1);
107 }
108 break;
109 default:
110 goto userr;
111 }
112 break;
113 case 'o':
114 switch (argv[a][2]) {
115 case 'n':
116 outcnt = atol(argv[++a]);
117 break;
118 case 'a':
119 bocols = 0;
120 break;
121 case 'd':
122 bocols = 1;
123 break;
124 case 'f':
125 bocols = -1;
126 break;
127 default:
128 goto userr;
129 }
130 break;
131 default:;
132 userr:
133 fprintf(stderr,
134 "Usage: %s [-m][-sE|p|u|l][-tC][-i{f|d}[N]][-o{f|d}][-count [-r]] [file..]\n",
135 argv[0]);
136 exit(1);
137 }
138 else
139 break;
140 if (mean) {
141 if (func == MAX) {
142 fprintf(stderr, "%s: average maximum?!\n", argv[0]);
143 exit(1);
144 }
145 if (func == MIN) {
146 fprintf(stderr, "%s: average minimum?!\n", argv[0]);
147 exit(1);
148 }
149 }
150 if (bocols)
151 SET_FILE_BINARY(stdout);
152 status = 0;
153 if (a >= argc)
154 status = execute(NULL) == -1 ? 1 : status;
155 else
156 for ( ; a < argc && (outcnt <= 0 || nrecsout < outcnt); a++)
157 status = execute(argv[a]) == -1 ? 2 : status;
158 exit(status);
159 }
160
161
162 static int
163 getrecord( /* read next input record */
164 double field[MAXCOL],
165 FILE *fp
166 )
167 {
168 char buf[16*MAXCOL];
169 char *cp, *num;
170 int nf;
171 /* reading binary input? */
172 if (nbicols > 0)
173 return(getbinary(field, sizeof(double), nbicols, fp));
174 if (nbicols < 0) {
175 float *fbuf = (float *)buf;
176 int i;
177 nf = getbinary(fbuf, sizeof(float), -nbicols, fp);
178 for (i = nf; i-- > 0; )
179 field[i] = fbuf[i];
180 return(nf);
181 }
182 /* reading ASCII input */
183 cp = fgets(buf, sizeof(buf), fp);
184 if (cp == NULL)
185 return(0);
186 for (nf = 0; nf < MAXCOL; nf++) {
187 while (isspace(*cp))
188 cp++;
189 if (!*cp)
190 break;
191 num = cp;
192 while (*cp && !(isspace(tabc)?isspace(*cp):*cp==tabc))
193 cp++;
194 if (*cp)
195 *cp++ = '\0';
196 if (!*num || isspace(*num))
197 field[nf] = init_val[func];
198 else
199 field[nf] = atof(num);
200 }
201 return(nf);
202 }
203
204
205 static void
206 putrecord( /* write out results record */
207 const double *field,
208 int n,
209 FILE *fp
210 )
211 {
212 /* binary output? */
213 if (bocols > 0) {
214 putbinary(field, sizeof(double), n, fp);
215 return;
216 }
217 if (bocols < 0) {
218 float fv;
219 while (n-- > 0) {
220 fv = *field++;
221 putbinary(&fv, sizeof(float), 1, fp);
222 }
223 return;
224 }
225 /* ASCII output */
226 while (n-- > 0) {
227 fprintf(fp, "%.9g", *field++);
228 if (n) fputc(tabc, fp);
229 }
230 fputc('\n', fp);
231 if (!subtotal)
232 fflush(fp); /* flush unless -r */
233 }
234
235
236 static int
237 execute( /* compute result */
238 char *fname
239 )
240 {
241 double inpval[MAXCOL];
242 double tally[MAXCOL];
243 short rsign[MAXCOL];
244 double result[MAXCOL];
245 int n;
246 int nread, ncol;
247 long nlin, ltotal;
248 FILE *fp;
249 /* open file */
250 if (fname == NULL)
251 fp = stdin;
252 else if ((fp = fopen(fname, "r")) == NULL) {
253 fprintf(stderr, "%s: cannot open\n", fname);
254 return(-1);
255 }
256 if (nbicols)
257 SET_FILE_BINARY(fp);
258 #ifdef getc_unlocked /* avoid lock/unlock overhead */
259 flockfile(fp);
260 #endif
261
262 ltotal = 0;
263 while (!feof(fp)) {
264 if (ltotal == 0) { /* initialize */
265 if (func == MULT) /* special case */
266 for (n = 0; n < MAXCOL; n++) {
267 tally[n] = 0.0;
268 rsign[n] = 1;
269 }
270 else
271 for (n = 0; n < MAXCOL; n++)
272 tally[n] = init_val[func];
273 }
274 ncol = 0;
275 for (nlin = 0; (count <= 0 || nlin < count) &&
276 (incnt <= 0 || nlin < incnt) &&
277 (nread = getrecord(inpval, fp)) > 0;
278 nlin++) {
279 /* compute */
280 for (n = 0; n < nread; n++)
281 switch (func) {
282 case ADD:
283 if (inpval[n] == 0.0)
284 break;
285 if (power != 0.0)
286 tally[n] += pow(fabs(inpval[n]),power);
287 else
288 tally[n] += inpval[n];
289 break;
290 case MULT:
291 if (inpval[n] == 0.0)
292 rsign[n] = 0;
293 else if (inpval[n] < 0.0) {
294 rsign[n] = -rsign[n];
295 inpval[n] = -inpval[n];
296 }
297 if (rsign[n])
298 tally[n] += log(inpval[n]);
299 break;
300 case MAX:
301 if (inpval[n] > tally[n])
302 tally[n] = inpval[n];
303 break;
304 case MIN:
305 if (inpval[n] < tally[n])
306 tally[n] = inpval[n];
307 break;
308 }
309 if (nread > ncol)
310 ncol = nread;
311 }
312 if (nlin == 0)
313 break;
314 /* compute and print */
315 ltotal += nlin;
316 for (n = 0; n < ncol; n++) {
317 result[n] = tally[n];
318 if (mean) {
319 result[n] /= (double)ltotal;
320 if (func == ADD && power != 0.0 && result[n] != 0.0)
321 result[n] = pow(result[n], 1.0/power);
322 }
323 if (func == MULT)
324 result[n] = rsign[n] * exp(result[n]);
325 }
326 putrecord(result, ncol, stdout);
327 ++nrecsout;
328 if (outcnt > 0 && nrecsout >= outcnt)
329 break;
330 if (!subtotal)
331 ltotal = 0;
332 if (incnt > 0 && nlin >= incnt)
333 break;
334 }
335 /* close input */
336 return(fclose(fp) == EOF ? 1 : 0);
337 }