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, 5 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

# User Rev Content
1 gwlarson 3.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 gwlarson 3.3 #include <signal.h>
16    
17 gwlarson 3.1 #ifndef BKBSIZE
18 gwlarson 3.2 #define BKBSIZE 256 /* beam clump size (kilobytes) */
19 gwlarson 3.1 #endif
20    
21 gwlarson 3.2 #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 gwlarson 3.1
26     char *progname;
27 gwlarson 3.3 char tempfile[128];
28 gwlarson 3.1
29 gwlarson 3.3 extern char *rindex();
30     extern int quit();
31 gwlarson 3.1 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 gwlarson 3.3 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 gwlarson 3.1 outname++;
58     else
59 gwlarson 3.3 outname = tempfile;
60 gwlarson 3.1 sprintf(outname, "rho%d.hdk", getpid());
61 gwlarson 3.3 outname = tempfile;
62 gwlarson 3.1 }
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 gwlarson 3.3 if (outname == tempfile && rename(outname, inpname) < 0) {
87 gwlarson 3.1 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 gwlarson 3.3 /* 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 gwlarson 3.1 /* copy and verify header */
120 gwlarson 3.3 if (checkheader(infp, HOLOFMT, outfp) < 0 || getw(infp) != HOLOMAGIC)
121 gwlarson 3.1 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 gwlarson 3.3 /* flush everything manually hence */
134 gwlarson 3.1 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 gwlarson 3.2 register int i, j;
172 gwlarson 3.1
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 gwlarson 3.2 gcshifti(ng+(3*i+j), gci0.w==gc->w, j-1, hp);
179 gwlarson 3.1 }
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 gwlarson 3.3 if (i == 4 & j == 4) /* don't copy starting beam */
204 gwlarson 3.1 continue;
205 gwlarson 3.2 if (wg0[i].w == wg1[j].w)
206     continue;
207 gwlarson 3.1 copystruct(bgc, wg0+i);
208     copystruct(bgc+1, wg1+j);
209     bneighlist[bneighrem++] = hdbindex(hp, bgc);
210 gwlarson 3.2 #ifdef DEBUG
211     if (bneighlist[bneighrem-1] <= 0)
212     error(CONSISTENCY, "bad beam in firstneigh");
213     #endif
214 gwlarson 3.1 }
215     return(nextneigh());
216     }
217    
218    
219 gwlarson 3.2 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 gwlarson 3.3 if (pdif > 0L) return(1);
228     if (pdif < 0L) return(-1);
229 gwlarson 3.2 return(0);
230     }
231    
232    
233 gwlarson 3.1 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 gwlarson 3.2 register HOLO *hinp;
238     HOLO *hout;
239 gwlarson 3.1 register BEAM *bp;
240 gwlarson 3.2 unsigned int4 *bflags;
241 gwlarson 3.1 int *bqueue;
242     int bqlen;
243     int4 bqtotal;
244 gwlarson 3.2 int bc, bci, bqc, myprime;
245 gwlarson 3.1 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 gwlarson 3.2 bqueue = (int *)malloc(nbeams(hinp)*sizeof(int));
252 gwlarson 3.3 bflags = (unsigned int4 *)calloc((nbeams(hinp)>>5)+1,
253     sizeof(unsigned int4));
254 gwlarson 3.2 if (bqueue == NULL | bflags == NULL)
255 gwlarson 3.1 error(SYSTEM, "out of memory in copysect");
256 gwlarson 3.2 /* mark empty beams as done */
257 gwlarson 3.3 for (i = nbeams(hinp); i > 0; i--)
258 gwlarson 3.2 if (!hinp->bi[i].nrd)
259     setfl(bflags, i);
260 gwlarson 3.1 /* 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 gwlarson 3.2 if (isset(bflags, bci))
270 gwlarson 3.1 continue;
271     bqueue[0] = bci; /* initialize queue */
272     bqlen = 1;
273 gwlarson 3.3 bqtotal = hinp->bi[bci].nrd;
274 gwlarson 3.2 setfl(bflags, bci);
275 gwlarson 3.1 /* run through growing queue */
276     for (bqc = 0; bqc < bqlen; bqc++) {
277 gwlarson 3.2 /* add neighbors until full */
278     for (i = firstneigh(hinp,bqueue[bqc]); i > 0;
279     i = nextneigh()) {
280     if (isset(bflags, i)) /* done already? */
281 gwlarson 3.1 continue;
282 gwlarson 3.2 bqueue[bqlen++] = i; /* add it */
283 gwlarson 3.3 bqtotal += hinp->bi[i].nrd;
284 gwlarson 3.2 setfl(bflags, i);
285 gwlarson 3.1 if (bqtotal >= BKBSIZE*1024/sizeof(RAYVAL))
286     break; /* queue full */
287     }
288 gwlarson 3.2 if (i > 0)
289     break;
290 gwlarson 3.1 }
291 gwlarson 3.2 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 gwlarson 3.1 hdfreebeam(hout, 0); /* flush output block */
302 gwlarson 3.2 #ifdef DEBUG
303     hdsync(hout, 0);
304     #endif
305 gwlarson 3.1 }
306     /* we're done -- clean up */
307     free((char *)bqueue);
308 gwlarson 3.2 free((char *)bflags);
309 gwlarson 3.1 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 gwlarson 3.3 if (tempfile[0])
337     unlink(tempfile);
338 gwlarson 3.1 exit(code);
339     }