ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/cal/total.c
Revision: 1.5
Committed: Sat Oct 8 04:18:16 2005 UTC (18 years, 5 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R8
Changes since 1.4: +2 -2 lines
Log Message:
Bug fix in combination of -p and -m options in total that broke compamb

File Contents

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