ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rhoptimize.c
Revision: 3.1
Committed: Wed Nov 4 16:37:19 1998 UTC (25 years, 4 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Log Message:
Initial revision

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 #ifndef BKBSIZE
16 #define BKBSIZE 64 /* beam clump size (kilobytes) */
17 #endif
18
19
20 char *progname;
21
22 extern long rhinitcopy();
23
24
25 main(argc, argv)
26 int argc;
27 char *argv[];
28 {
29 char nambuf[128];
30 char *inpname, *outname;
31 int hdfd[2];
32 long nextipos, lastopos, thisopos;
33
34 progname = argv[0];
35 if (argc < 2 | argc > 3) {
36 fprintf(stderr, "Usage: %s input.hdk [output.hdk]\n", progname);
37 exit(1);
38 }
39 inpname = argv[1];
40 if (argc == 3) /* use given output file */
41 outname = argv[2];
42 else { /* else create temporary file */
43 strcpy(nambuf, inpname);
44 if ((outname = strrchr(nambuf, '/')) != NULL)
45 outname++;
46 else
47 outname = nambuf;
48 sprintf(outname, "rho%d.hdk", getpid());
49 outname = nambuf;
50 }
51 /* copy holodeck file header */
52 nextipos = rhinitcopy(hdfd, inpname, outname);
53 lastopos = 0L; /* copy sections one by one */
54 while (nextipos != 0L) {
55 /* set input position; get next */
56 lseek(hdfd[0], nextipos, 0);
57 read(hdfd[0], (char *)&nextipos, sizeof(nextipos));
58 /* get output position; set last */
59 thisopos = lseek(hdfd[1], 0L, 2);
60 if (lastopos > 0L) {
61 lseek(hdfd[1], lastopos, 0);
62 write(hdfd[1], (char *)&thisopos, sizeof(thisopos));
63 lseek(hdfd[1], 0L, 2);
64 }
65 lastopos = thisopos;
66 thisopos = 0L; /* write place holder */
67 write(hdfd[1], (char *)&thisopos, sizeof(thisopos));
68 /* copy holodeck section */
69 copysect(hdfd[0], hdfd[1]);
70 }
71 /* clean up */
72 close(hdfd[0]);
73 close(hdfd[1]);
74 if (argc == 2 && rename(outname, inpname) < 0) {
75 sprintf(errmsg, "cannot rename \"%s\" to \"%s\"",
76 outname, inpname);
77 error(SYSTEM, errmsg);
78 }
79 exit(0);
80 }
81
82
83 long
84 rhinitcopy(hfd, infn, outfn) /* open files and copy header */
85 int hfd[2]; /* returned file descriptors */
86 char *infn, *outfn;
87 {
88 FILE *infp, *outfp;
89 long ifpos;
90 /* open files for i/o */
91 if ((infp = fopen(infn, "r")) == NULL) {
92 sprintf(errmsg, "cannot open \"%s\" for reading", infn);
93 error(SYSTEM, errmsg);
94 }
95 if ((outfp = fopen(outfn, "w+")) == NULL) {
96 sprintf(errmsg, "cannot open \"%s\" for writing", outfn);
97 error(SYSTEM, errmsg);
98 }
99 /* copy and verify header */
100 if (checkheader(infp, HOLOFMT, outfp) < 0 ||
101 getw(infp) != HOLOMAGIC)
102 error(USER, "input not in holodeck format");
103 fputformat(HOLOFMT, outfp);
104 fputc('\n', outfp);
105 putw(HOLOMAGIC, outfp);
106 /* get descriptors and free stdio */
107 if ((hfd[0] = dup(fileno(infp))) < 0 ||
108 (hfd[1] = dup(fileno(outfp))) < 0)
109 error(SYSTEM, "dup call failed in rhinitcopy");
110 ifpos = ftell(infp);
111 fclose(infp);
112 if (fclose(outfp) == EOF)
113 error(SYSTEM, "file flushing error in rhinitcopy");
114 /* we flush everything manually */
115 hdcachesize = 0;
116 /* return input position */
117 return(ifpos);
118 }
119
120
121 gcshifti(gc, ia, di, hp) /* shift cell row or column */
122 register GCOORD *gc;
123 int ia, di;
124 register HOLO *hp;
125 {
126 int nw;
127
128 if (di > 0) {
129 if (++gc->i[ia] >= hp->grid[((gc->w>>1)+1+ia)%3]) {
130 nw = ((gc->w&~1) + (ia<<1) + 3) % 6;
131 gc->i[ia] = gc->i[1-ia];
132 gc->i[1-ia] = gc->w&1 ? hp->grid[((nw>>1)+2-ia)%3]-1 : 0;
133 gc->w = nw;
134 }
135 } else if (di < 0) {
136 if (--gc->i[ia] < 0) {
137 nw = ((gc->w&~1) + (ia<<1) + 2) % 6;
138 gc->i[ia] = gc->i[1-ia];
139 gc->i[1-ia] = gc->w&1 ? hp->grid[((nw>>1)+2-ia)%3]-1 : 0;
140 gc->w = nw;
141 }
142 }
143 }
144
145
146 mkneighgrid(ng, hp, gc) /* compute neighborhood for grid cell */
147 GCOORD ng[3*3];
148 HOLO *hp;
149 GCOORD *gc;
150 {
151 GCOORD gci0;
152 int i, j;
153
154 for (i = 3; i--; ) {
155 copystruct(&gci0, gc);
156 gcshifti(&gci0, 0, i-1, hp);
157 for (j = 3; j--; ) {
158 copystruct(ng+(3*i+j), &gci0);
159 gcshifti(ng+(3*i+j), 1, j-1, hp);
160 }
161 }
162 }
163
164
165 int bneighlist[9*9-1];
166 int bneighrem;
167
168 #define nextneigh() (bneighrem<=0 ? 0 : bneighlist[--bneighrem])
169
170 int
171 firstneigh(hp, b) /* initialize neighbor list and return first */
172 HOLO *hp;
173 int b;
174 {
175 GCOORD wg0[9], wg1[9], bgc[2];
176 int i, j;
177
178 hdbcoord(bgc, hp, b);
179 mkneighgrid(wg0, hp, bgc);
180 mkneighgrid(wg1, hp, bgc+1);
181 bneighrem = 0;
182 for (i = 9; i--; )
183 for (j = 9; j--; ) {
184 if (i == 4 & j == 4)
185 continue;
186 copystruct(bgc, wg0+i);
187 copystruct(bgc+1, wg1+j);
188 bneighlist[bneighrem++] = hdbindex(hp, bgc);
189 }
190 return(nextneigh());
191 }
192
193
194 copysect(ifd, ofd) /* copy holodeck section from ifd to ofd */
195 int ifd, ofd;
196 {
197 #define beamdone(b) (!hinp->bi[b].nrd || bnrays(hout,b))
198 static short primes[] = {9431,6803,4177,2659,1609,887,587,251,47,1};
199 register HOLO *hinp, *hout;
200 register BEAM *bp;
201 int *bqueue;
202 int bqlen;
203 int4 bqtotal;
204 int bc, bci, bqc, bnc, myprime;
205 register int i;
206 /* load input section directory */
207 hinp = hdinit(ifd, NULL);
208 /* create output section directory */
209 hout = hdinit(ofd, (HDGRID *)hinp);
210 /* allocate beam queue */
211 if ((bqueue = (int *)malloc(nbeams(hinp)*sizeof(int))) == NULL)
212 error(SYSTEM, "out of memory in copysect");
213 /* pick a good prime step size */
214 for (i = 0; primes[i]<<5 >= nbeams(hinp); i++)
215 ;
216 while ((myprime = primes[i++]) > 1)
217 if (nbeams(hinp) % myprime)
218 break;
219 /* add each input beam and neighbors */
220 for (bc = bci = nbeams(hinp); bc > 0; bc--,
221 bci += bci>myprime ? -myprime : nbeams(hinp)-myprime) {
222 if (beamdone(bci))
223 continue;
224 bqueue[0] = bci; /* initialize queue */
225 bqlen = 1;
226 bqtotal = bnrays(hinp, bci);
227 /* run through growing queue */
228 for (bqc = 0; bqc < bqlen; bqc++) {
229 /* transfer the beam */
230 bp = hdgetbeam(hinp, bqueue[bqc]);
231 bcopy((char *)hdbray(bp),
232 (char *)hdnewrays(hout,bqueue[bqc],bp->nrm),
233 bp->nrm*sizeof(RAYVAL));
234 hdfreebeam(hinp, bqueue[bqc]);
235 /* check queue size */
236 if (bqtotal >= BKBSIZE*1024/sizeof(RAYVAL))
237 continue;
238 /* add neighbors to queue */
239 for (bnc = firstneigh(hinp,bqueue[bqc]); bnc > 0;
240 bnc = nextneigh()) {
241 if (beamdone(bnc)) /* see if valid */
242 continue;
243 for (i = bqlen; i--; )
244 if (bqueue[i] == bnc) break;
245 if (i >= 0)
246 continue;
247 bqueue[bqlen++] = bnc; /* add it */
248 bqtotal += bnrays(hinp, bnc);
249 if (bqtotal >= BKBSIZE*1024/sizeof(RAYVAL))
250 break; /* queue full */
251 }
252 }
253 hdfreebeam(hout, 0); /* flush output block */
254 }
255 /* we're done -- clean up */
256 free((char *)bqueue);
257 hddone(hinp);
258 hddone(hout);
259 #undef beamdone
260 }
261
262
263 eputs(s) /* put error message to stderr */
264 register char *s;
265 {
266 static int midline = 0;
267
268 if (!*s)
269 return;
270 if (!midline++) { /* prepend line with program name */
271 fputs(progname, stderr);
272 fputs(": ", stderr);
273 }
274 fputs(s, stderr);
275 if (s[strlen(s)-1] == '\n') {
276 fflush(stderr);
277 midline = 0;
278 }
279 }
280
281
282 quit(code) /* exit the program gracefully */
283 int code;
284 {
285 hdsync(NULL, 1); /* write out any buffered data */
286 exit(code);
287 }