ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhoptimize.c
Revision: 3.3
Committed: Fri Nov 6 16:54:23 1998 UTC (25 years, 4 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.2: +35 -18 lines
Log Message:
added check to see if single argument is writeable
fixed bug in copysect() due to a wrong index
added automatic temporary file removal on interrupt or error

File Contents

# Content
1 /* Copyright (c) 1998 Silicon Graphics, Inc. */
2
3 #ifndef lint
4 static char SCCSid[] = "$SunId$ SGI";
5 #endif
6
7 /*
8 * Optimize holodeck for quick access.
9 *
10 * 11/4/98 Greg Ward Larson
11 */
12
13 #include "holo.h"
14
15 #include <signal.h>
16
17 #ifndef BKBSIZE
18 #define BKBSIZE 256 /* beam clump size (kilobytes) */
19 #endif
20
21 #define flgop(p,i,op) ((p)[(i)>>5] op (1L<<((i)&0x1f)))
22 #define isset(p,i) flgop(p,i,&)
23 #define setfl(p,i) flgop(p,i,|=)
24 #define clrfl(p,i) flgop(p,i,&=~)
25
26 char *progname;
27 char tempfile[128];
28
29 extern char *rindex();
30 extern int quit();
31 extern long rhinitcopy();
32
33
34 main(argc, argv)
35 int argc;
36 char *argv[];
37 {
38 char *inpname, *outname;
39 int hdfd[2];
40 long nextipos, lastopos, thisopos;
41
42 progname = argv[0];
43 if (argc < 2 | argc > 3) {
44 fprintf(stderr, "Usage: %s input.hdk [output.hdk]\n", progname);
45 exit(1);
46 }
47 inpname = argv[1];
48 if (argc == 3) /* use given output file */
49 outname = argv[2];
50 else { /* else use temporary file */
51 if (access(inpname, R_OK|W_OK) < 0) { /* check permissions */
52 sprintf(errmsg, "cannot access \"%s\"", inpname);
53 error(SYSTEM, errmsg);
54 }
55 strcpy(tempfile, inpname);
56 if ((outname = rindex(tempfile, '/')) != NULL)
57 outname++;
58 else
59 outname = tempfile;
60 sprintf(outname, "rho%d.hdk", getpid());
61 outname = tempfile;
62 }
63 /* copy holodeck file header */
64 nextipos = rhinitcopy(hdfd, inpname, outname);
65 lastopos = 0L; /* copy sections one by one */
66 while (nextipos != 0L) {
67 /* set input position; get next */
68 lseek(hdfd[0], nextipos, 0);
69 read(hdfd[0], (char *)&nextipos, sizeof(nextipos));
70 /* get output position; set last */
71 thisopos = lseek(hdfd[1], 0L, 2);
72 if (lastopos > 0L) {
73 lseek(hdfd[1], lastopos, 0);
74 write(hdfd[1], (char *)&thisopos, sizeof(thisopos));
75 lseek(hdfd[1], 0L, 2);
76 }
77 lastopos = thisopos;
78 thisopos = 0L; /* write place holder */
79 write(hdfd[1], (char *)&thisopos, sizeof(thisopos));
80 /* copy holodeck section */
81 copysect(hdfd[0], hdfd[1]);
82 }
83 /* clean up */
84 close(hdfd[0]);
85 close(hdfd[1]);
86 if (outname == tempfile && rename(outname, inpname) < 0) {
87 sprintf(errmsg, "cannot rename \"%s\" to \"%s\"",
88 outname, inpname);
89 error(SYSTEM, errmsg);
90 }
91 exit(0);
92 }
93
94
95 long
96 rhinitcopy(hfd, infn, outfn) /* open files and copy header */
97 int hfd[2]; /* returned file descriptors */
98 char *infn, *outfn;
99 {
100 FILE *infp, *outfp;
101 long ifpos;
102 /* open files for i/o */
103 if ((infp = fopen(infn, "r")) == NULL) {
104 sprintf(errmsg, "cannot open \"%s\" for reading", infn);
105 error(SYSTEM, errmsg);
106 }
107 if ((outfp = fopen(outfn, "w+")) == NULL) {
108 sprintf(errmsg, "cannot open \"%s\" for writing", outfn);
109 error(SYSTEM, errmsg);
110 }
111 /* set up signal handling */
112 if (signal(SIGINT, quit) == SIG_IGN) signal(SIGINT, SIG_IGN);
113 if (signal(SIGHUP, quit) == SIG_IGN) signal(SIGHUP, SIG_IGN);
114 if (signal(SIGTERM, quit) == SIG_IGN) signal(SIGTERM, SIG_IGN);
115 #ifdef SIGXCPU
116 if (signal(SIGXCPU, quit) == SIG_IGN) signal(SIGXCPU, SIG_IGN);
117 if (signal(SIGXFSZ, quit) == SIG_IGN) signal(SIGXFSZ, SIG_IGN);
118 #endif
119 /* copy and verify header */
120 if (checkheader(infp, HOLOFMT, outfp) < 0 || getw(infp) != HOLOMAGIC)
121 error(USER, "input not in holodeck format");
122 fputformat(HOLOFMT, outfp);
123 fputc('\n', outfp);
124 putw(HOLOMAGIC, outfp);
125 /* get descriptors and free stdio */
126 if ((hfd[0] = dup(fileno(infp))) < 0 ||
127 (hfd[1] = dup(fileno(outfp))) < 0)
128 error(SYSTEM, "dup call failed in rhinitcopy");
129 ifpos = ftell(infp);
130 fclose(infp);
131 if (fclose(outfp) == EOF)
132 error(SYSTEM, "file flushing error in rhinitcopy");
133 /* flush everything manually hence */
134 hdcachesize = 0;
135 /* return input position */
136 return(ifpos);
137 }
138
139
140 gcshifti(gc, ia, di, hp) /* shift cell row or column */
141 register GCOORD *gc;
142 int ia, di;
143 register HOLO *hp;
144 {
145 int nw;
146
147 if (di > 0) {
148 if (++gc->i[ia] >= hp->grid[((gc->w>>1)+1+ia)%3]) {
149 nw = ((gc->w&~1) + (ia<<1) + 3) % 6;
150 gc->i[ia] = gc->i[1-ia];
151 gc->i[1-ia] = gc->w&1 ? hp->grid[((nw>>1)+2-ia)%3]-1 : 0;
152 gc->w = nw;
153 }
154 } else if (di < 0) {
155 if (--gc->i[ia] < 0) {
156 nw = ((gc->w&~1) + (ia<<1) + 2) % 6;
157 gc->i[ia] = gc->i[1-ia];
158 gc->i[1-ia] = gc->w&1 ? hp->grid[((nw>>1)+2-ia)%3]-1 : 0;
159 gc->w = nw;
160 }
161 }
162 }
163
164
165 mkneighgrid(ng, hp, gc) /* compute neighborhood for grid cell */
166 GCOORD ng[3*3];
167 HOLO *hp;
168 GCOORD *gc;
169 {
170 GCOORD gci0;
171 register int i, j;
172
173 for (i = 3; i--; ) {
174 copystruct(&gci0, gc);
175 gcshifti(&gci0, 0, i-1, hp);
176 for (j = 3; j--; ) {
177 copystruct(ng+(3*i+j), &gci0);
178 gcshifti(ng+(3*i+j), gci0.w==gc->w, j-1, hp);
179 }
180 }
181 }
182
183
184 int bneighlist[9*9-1];
185 int bneighrem;
186
187 #define nextneigh() (bneighrem<=0 ? 0 : bneighlist[--bneighrem])
188
189 int
190 firstneigh(hp, b) /* initialize neighbor list and return first */
191 HOLO *hp;
192 int b;
193 {
194 GCOORD wg0[9], wg1[9], bgc[2];
195 int i, j;
196
197 hdbcoord(bgc, hp, b);
198 mkneighgrid(wg0, hp, bgc);
199 mkneighgrid(wg1, hp, bgc+1);
200 bneighrem = 0;
201 for (i = 9; i--; )
202 for (j = 9; j--; ) {
203 if (i == 4 & j == 4) /* don't copy starting beam */
204 continue;
205 if (wg0[i].w == wg1[j].w)
206 continue;
207 copystruct(bgc, wg0+i);
208 copystruct(bgc+1, wg1+j);
209 bneighlist[bneighrem++] = hdbindex(hp, bgc);
210 #ifdef DEBUG
211 if (bneighlist[bneighrem-1] <= 0)
212 error(CONSISTENCY, "bad beam in firstneigh");
213 #endif
214 }
215 return(nextneigh());
216 }
217
218
219 BEAMI *beamdir;
220
221 int
222 bpcmp(b1p, b2p) /* compare beam positions on disk */
223 int *b1p, *b2p;
224 {
225 register long pdif = beamdir[*b1p].fo - beamdir[*b2p].fo;
226
227 if (pdif > 0L) return(1);
228 if (pdif < 0L) return(-1);
229 return(0);
230 }
231
232
233 copysect(ifd, ofd) /* copy holodeck section from ifd to ofd */
234 int ifd, ofd;
235 {
236 static short primes[] = {9431,6803,4177,2659,1609,887,587,251,47,1};
237 register HOLO *hinp;
238 HOLO *hout;
239 register BEAM *bp;
240 unsigned int4 *bflags;
241 int *bqueue;
242 int bqlen;
243 int4 bqtotal;
244 int bc, bci, bqc, myprime;
245 register int i;
246 /* load input section directory */
247 hinp = hdinit(ifd, NULL);
248 /* create output section directory */
249 hout = hdinit(ofd, (HDGRID *)hinp);
250 /* allocate beam queue */
251 bqueue = (int *)malloc(nbeams(hinp)*sizeof(int));
252 bflags = (unsigned int4 *)calloc((nbeams(hinp)>>5)+1,
253 sizeof(unsigned int4));
254 if (bqueue == NULL | bflags == NULL)
255 error(SYSTEM, "out of memory in copysect");
256 /* mark empty beams as done */
257 for (i = nbeams(hinp); i > 0; i--)
258 if (!hinp->bi[i].nrd)
259 setfl(bflags, i);
260 /* pick a good prime step size */
261 for (i = 0; primes[i]<<5 >= nbeams(hinp); i++)
262 ;
263 while ((myprime = primes[i++]) > 1)
264 if (nbeams(hinp) % myprime)
265 break;
266 /* add each input beam and neighbors */
267 for (bc = bci = nbeams(hinp); bc > 0; bc--,
268 bci += bci>myprime ? -myprime : nbeams(hinp)-myprime) {
269 if (isset(bflags, bci))
270 continue;
271 bqueue[0] = bci; /* initialize queue */
272 bqlen = 1;
273 bqtotal = hinp->bi[bci].nrd;
274 setfl(bflags, bci);
275 /* run through growing queue */
276 for (bqc = 0; bqc < bqlen; bqc++) {
277 /* add neighbors until full */
278 for (i = firstneigh(hinp,bqueue[bqc]); i > 0;
279 i = nextneigh()) {
280 if (isset(bflags, i)) /* done already? */
281 continue;
282 bqueue[bqlen++] = i; /* add it */
283 bqtotal += hinp->bi[i].nrd;
284 setfl(bflags, i);
285 if (bqtotal >= BKBSIZE*1024/sizeof(RAYVAL))
286 break; /* queue full */
287 }
288 if (i > 0)
289 break;
290 }
291 beamdir = hinp->bi; /* sort queue */
292 qsort((char *)bqueue, bqlen, sizeof(*bqueue), bpcmp);
293 /* transfer each beam */
294 for (i = 0; i < bqlen; i++) {
295 bp = hdgetbeam(hinp, bqueue[i]);
296 bcopy((char *)hdbray(bp),
297 (char *)hdnewrays(hout,bqueue[i],bp->nrm),
298 bp->nrm*sizeof(RAYVAL));
299 hdfreebeam(hinp, bqueue[i]);
300 }
301 hdfreebeam(hout, 0); /* flush output block */
302 #ifdef DEBUG
303 hdsync(hout, 0);
304 #endif
305 }
306 /* we're done -- clean up */
307 free((char *)bqueue);
308 free((char *)bflags);
309 hddone(hinp);
310 hddone(hout);
311 }
312
313
314 eputs(s) /* put error message to stderr */
315 register char *s;
316 {
317 static int midline = 0;
318
319 if (!*s)
320 return;
321 if (!midline++) { /* prepend line with program name */
322 fputs(progname, stderr);
323 fputs(": ", stderr);
324 }
325 fputs(s, stderr);
326 if (s[strlen(s)-1] == '\n') {
327 fflush(stderr);
328 midline = 0;
329 }
330 }
331
332
333 quit(code) /* exit the program gracefully */
334 int code;
335 {
336 if (tempfile[0])
337 unlink(tempfile);
338 exit(code);
339 }