ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rholo3.c
Revision: 3.41
Committed: Thu Jan 1 11:21:55 2004 UTC (20 years, 3 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 3.40: +53 -33 lines
Log Message:
Ansification and prototypes.

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: rholo3.c,v 3.40 2003/07/21 22:30:18 schorsch Exp $";
3 #endif
4 /*
5 * Routines for tracking beam compuatations
6 */
7
8 #include <time.h>
9 #include <string.h>
10 #include <stdio.h>
11
12 #include "view.h"
13 #include "rholo.h"
14
15 #ifndef NFRAG2CHUNK
16 #define NFRAG2CHUNK 4096 /* number of fragments to start chunking */
17 #endif
18
19 #ifndef abs
20 #define abs(x) ((x) > 0 ? (x) : -(x))
21 #endif
22 #ifndef sgn
23 #define sgn(x) ((x) > 0 ? 1 : (x) < 0 ? -1 : 0)
24 #endif
25
26 #define rchunk(n) (((n)+(RPACKSIZ/2))/RPACKSIZ)
27
28 int chunkycmp = 0; /* clump beams together on disk */
29
30 static PACKHEAD *complist=NULL; /* list of beams to compute */
31 static int complen=0; /* length of complist */
32 static int listpos=0; /* current list position for next_packet */
33 static int lastin= -1; /* last ordered position in list */
34
35 static void sortcomplist(void);
36 static void mergeclists(PACKHEAD *cdest, PACKHEAD *cl1, int n1, PACKHEAD *cl2, int n2);
37 static void view_list(FILE *fp);
38 static void ambient_list(void);
39 static double beamvolume(HOLO *hp, int bi);
40 static void dispbeam(BEAM *b, HDBEAMI *hb);
41
42
43
44 static int
45 beamcmp(b0, b1) /* comparison for compute order */
46 register PACKHEAD *b0, *b1;
47 {
48 BEAMI *bip0, *bip1;
49 register long c;
50 /* first check desired quantities */
51 if (chunkycmp)
52 c = rchunk(b1->nr)*(rchunk(b0->nc)+1L) -
53 rchunk(b0->nr)*(rchunk(b1->nc)+1L);
54 else
55 c = b1->nr*(b0->nc+1L) - b0->nr*(b1->nc+1L);
56 if (c > 0) return(1);
57 if (c < 0) return(-1);
58 /* only one file, so skip the following: */
59 #if 0
60 /* next, check file descriptors */
61 c = hdlist[b0->hd]->fd - hdlist[b1->hd]->fd;
62 if (c) return(c);
63 #endif
64 /* finally, check file positions */
65 bip0 = &hdlist[b0->hd]->bi[b0->bi];
66 bip1 = &hdlist[b1->hd]->bi[b1->bi];
67 /* put diskless beams last */
68 if (!bip0->nrd)
69 return(bip1->nrd > 0);
70 if (!bip1->nrd)
71 return(-1);
72 c = bip0->fo - bip1->fo;
73 return(c < 0 ? -1 : c > 0);
74 }
75
76
77 int
78 beamidcmp(b0, b1) /* comparison for beam searching */
79 register PACKHEAD *b0, *b1;
80 {
81 register int c = b0->hd - b1->hd;
82
83 if (c) return(c);
84 return(b0->bi - b1->bi);
85 }
86
87
88 static void
89 dispbeam( /* display a holodeck beam */
90 register BEAM *b,
91 register HDBEAMI *hb
92 )
93 {
94 static int n = 0;
95 static PACKHEAD *p = NULL;
96
97 if (b == NULL)
98 return;
99 if (b->nrm > n) { /* (re)allocate packet holder */
100 n = b->nrm;
101 if (p == NULL) p = (PACKHEAD *)malloc(packsiz(n));
102 else p = (PACKHEAD *)realloc((void *)p, packsiz(n));
103 CHECK(p==NULL, SYSTEM, "out of memory in dispbeam");
104 }
105 /* assign packet fields */
106 memcpy((void *)packra(p), (void *)hdbray(b), b->nrm*sizeof(RAYVAL));
107 p->nr = p->nc = b->nrm;
108 for (p->hd = 0; hdlist[p->hd] != hb->h; p->hd++)
109 if (hdlist[p->hd] == NULL)
110 error(CONSISTENCY, "unregistered holodeck in dispbeam");
111 p->bi = hb->b;
112 disp_packet(p); /* display it */
113 if (n >= 1024) { /* free ridiculous packets */
114 free((void *)p);
115 p = NULL; n = 0;
116 }
117 }
118
119
120 extern void
121 bundle_set( /* bundle set operation */
122 int op,
123 PACKHEAD *clist,
124 int nents
125 )
126 {
127 int oldnr, n;
128 HDBEAMI *hbarr;
129 register PACKHEAD *csm;
130 register int i;
131 /* search for common members */
132 for (csm = clist+nents; csm-- > clist; )
133 csm->nc = -1;
134 qsort((void *)clist, nents, sizeof(PACKHEAD), beamidcmp);
135 for (i = 0; i < complen; i++) {
136 csm = (PACKHEAD *)bsearch((void *)(complist+i), (void *)clist,
137 nents, sizeof(PACKHEAD), beamidcmp);
138 if (csm == NULL)
139 continue;
140 oldnr = complist[i].nr;
141 csm->nc = complist[i].nc;
142 switch (op) {
143 case BS_ADD: /* add to count */
144 complist[i].nr += csm->nr;
145 csm->nr = 0;
146 break;
147 case BS_MAX: /* maximum of counts */
148 if (csm->nr > complist[i].nr)
149 complist[i].nr = csm->nr;
150 csm->nr = 0;
151 break;
152 case BS_ADJ: /* reset count */
153 complist[i].nr = csm->nr;
154 csm->nr = 0;
155 break;
156 case BS_DEL: /* delete count */
157 if (csm->nr == 0 || csm->nr >= complist[i].nr)
158 complist[i].nr = 0;
159 else
160 complist[i].nr -= csm->nr;
161 break;
162 }
163 if (complist[i].nr != oldnr)
164 lastin = -1; /* flag sort */
165 }
166 /* record computed rays for uncommon beams */
167 for (csm = clist+nents; csm-- > clist; )
168 if (csm->nc < 0)
169 csm->nc = bnrays(hdlist[csm->hd], csm->bi);
170 /* complete list operations */
171 switch (op) {
172 case BS_NEW: /* new computation set */
173 listpos = 0; lastin = -1;
174 if (complen) /* free old list */
175 free((void *)complist);
176 complist = NULL;
177 if (!(complen = nents))
178 return;
179 complist = (PACKHEAD *)malloc(nents*sizeof(PACKHEAD));
180 if (complist == NULL)
181 goto memerr;
182 memcpy((void *)complist, (void *)clist, nents*sizeof(PACKHEAD));
183 break;
184 case BS_ADD: /* add to computation set */
185 case BS_MAX: /* maximum of quantities */
186 case BS_ADJ: /* adjust set quantities */
187 if (nents <= 0)
188 return;
189 sortcomplist(); /* sort updated list & new entries */
190 qsort((void *)clist, nents, sizeof(PACKHEAD), beamcmp);
191 /* what can't we satisfy? */
192 for (i = nents, csm = clist; i-- && csm->nr > csm->nc; csm++)
193 ;
194 n = csm - clist;
195 if (op != BS_ADD) { /* don't regenerate adjusted beams */
196 for (++i; i-- && csm->nr > 0; csm++)
197 ;
198 nents = csm - clist;
199 }
200 if (n) { /* allocate space for merged list */
201 PACKHEAD *newlist;
202 newlist = (PACKHEAD *)malloc(
203 (complen+n)*sizeof(PACKHEAD) );
204 if (newlist == NULL)
205 goto memerr;
206 /* merge lists */
207 mergeclists(newlist, clist, n, complist, complen);
208 if (complen)
209 free((void *)complist);
210 complist = newlist;
211 complen += n;
212 }
213 listpos = 0;
214 lastin = complen-1; /* list is now sorted */
215 break;
216 case BS_DEL: /* delete from computation set */
217 return; /* already done */
218 default:
219 error(CONSISTENCY, "bundle_set called with unknown operation");
220 }
221 if (outdev == NULL || !nents) /* nothing to display? */
222 return;
223 /* load and display beams we have */
224 hbarr = (HDBEAMI *)malloc(nents*sizeof(HDBEAMI));
225 for (i = nents; i--; ) {
226 hbarr[i].h = hdlist[clist[i].hd];
227 hbarr[i].b = clist[i].bi;
228 }
229 hdloadbeams(hbarr, nents, dispbeam);
230 free((void *)hbarr);
231 if (hdfragflags&FF_READ) {
232 listpos = 0;
233 lastin = -1; /* need to re-sort list */
234 }
235 return;
236 memerr:
237 error(SYSTEM, "out of memory in bundle_set");
238 }
239
240
241 static double
242 beamvolume( /* compute approximate volume of a beam */
243 HOLO *hp,
244 int bi
245 )
246 {
247 GCOORD gc[2];
248 FVECT cp[4], edgeA, edgeB, cent[2];
249 FVECT crossp[2], diffv;
250 double vol[2];
251 register int i;
252 /* get grid coordinates */
253 if (!hdbcoord(gc, hp, bi))
254 error(CONSISTENCY, "bad beam index in beamvolume");
255 for (i = 0; i < 2; i++) { /* compute cell area vectors */
256 hdcell(cp, hp, gc+i);
257 VSUM(edgeA, cp[1], cp[0], -1.0);
258 VSUM(edgeB, cp[3], cp[1], -1.0);
259 fcross(crossp[i], edgeA, edgeB);
260 /* compute center */
261 cent[i][0] = 0.5*(cp[0][0] + cp[2][0]);
262 cent[i][1] = 0.5*(cp[0][1] + cp[2][1]);
263 cent[i][2] = 0.5*(cp[0][2] + cp[2][2]);
264 }
265 /* compute difference vector */
266 VSUM(diffv, cent[1], cent[0], -1.0);
267 for (i = 0; i < 2; i++) { /* compute volume contributions */
268 vol[i] = 0.5*DOT(crossp[i], diffv);
269 if (vol[i] < 0.) vol[i] = -vol[i];
270 }
271 return(vol[0] + vol[1]); /* return total volume */
272 }
273
274
275 static void
276 ambient_list(void) /* compute ambient beam list */
277 {
278 int32 wtotal, minrt;
279 double frac;
280 int i;
281 register int j, k;
282
283 complen = 0;
284 for (j = 0; hdlist[j] != NULL; j++)
285 complen += nbeams(hdlist[j]);
286 complist = (PACKHEAD *)malloc(complen*sizeof(PACKHEAD));
287 CHECK(complist==NULL, SYSTEM, "out of memory in ambient_list");
288 /* compute beam weights */
289 k = 0; wtotal = 0;
290 for (j = 0; hdlist[j] != NULL; j++) {
291 frac = 512. * VLEN(hdlist[j]->wg[0]) *
292 VLEN(hdlist[j]->wg[1]) *
293 VLEN(hdlist[j]->wg[2]);
294 for (i = nbeams(hdlist[j]); i > 0; i--) {
295 complist[k].hd = j;
296 complist[k].bi = i;
297 complist[k].nr = frac*beamvolume(hdlist[j], i) + 0.5;
298 complist[k].nc = bnrays(hdlist[j], i);
299 wtotal += complist[k++].nr;
300 }
301 }
302 /* adjust sample weights */
303 if (vdef(DISKSPACE))
304 frac = 1024.*1024.*vflt(DISKSPACE) / (wtotal*sizeof(RAYVAL));
305 else
306 frac = 1024.*1024.*2048. / (wtotal*sizeof(RAYVAL));
307 minrt = .02*frac*wtotal/complen + .5; /* heuristic mimimum */
308 if (minrt > RPACKSIZ)
309 minrt = RPACKSIZ;
310 for (k = complen; k--; )
311 if ((complist[k].nr = frac*complist[k].nr + 0.5) < minrt)
312 complist[k].nr = minrt;
313 listpos = 0; lastin = -1; /* flag initial sort */
314 }
315
316
317 static void
318 view_list( /* assign beam priority from view list */
319 FILE *fp
320 )
321 {
322 double pa = 1.;
323 VIEW curview;
324 int xr, yr;
325 char *err;
326 BEAMLIST blist;
327
328 curview = stdview;
329 while (nextview(&curview, fp) != EOF) {
330 if ((err = setview(&curview)) != NULL) {
331 error(WARNING, err);
332 continue;
333 }
334 xr = yr = 1024;
335 normaspect(viewaspect(&curview), &pa, &xr, &yr);
336 viewbeams(&curview, xr, yr, &blist);
337 bundle_set(BS_MAX, blist.bl, blist.nb);
338 free((void *)blist.bl);
339 }
340 }
341
342
343 extern void
344 init_global(void) /* initialize global ray computation */
345 {
346 /* free old list and empty queue */
347 if (complen > 0) {
348 free((void *)complist);
349 done_packets(flush_queue());
350 }
351 /* reseed random number generator */
352 srandom(time(NULL));
353 /* allocate beam list */
354 if (readinp)
355 view_list(stdin);
356 else
357 ambient_list();
358 /* no view vicinity */
359 myeye.rng = 0;
360 }
361
362
363 static void
364 mergeclists( /* merge two sorted lists */
365 register PACKHEAD *cdest,
366 register PACKHEAD *cl1,
367 int n1,
368 register PACKHEAD *cl2,
369 int n2
370 )
371 {
372 register int cmp;
373
374 while (n1 | n2) {
375 if (!n1) cmp = 1;
376 else if (!n2) cmp = -1;
377 else cmp = beamcmp(cl1, cl2);
378 if (cmp > 0) {
379 *cdest = *cl2;
380 cl2++; n2--;
381 } else {
382 *cdest = *cl1;
383 cl1++; n1--;
384 }
385 cdest++;
386 }
387 }
388
389
390 static void
391 sortcomplist(void) /* fix our list order */
392 {
393 PACKHEAD *list2;
394 int listlen;
395 register int i;
396
397 if (complen <= 0) /* check to see if there is even a list */
398 return;
399 if (!chunkycmp) /* check to see if fragment list is full */
400 if (!hdfragOK(hdlist[0]->fd, &listlen, NULL)
401 #if NFRAG2CHUNK
402 || listlen >= NFRAG2CHUNK
403 #endif
404 ) {
405 chunkycmp++; /* use "chunky" comparison */
406 lastin = -1; /* need to re-sort list */
407 #ifdef DEBUG
408 error(WARNING, "using chunky comparison mode");
409 #endif
410 }
411 if (lastin < 0 || listpos*4 >= complen*3)
412 qsort((void *)complist, complen, sizeof(PACKHEAD), beamcmp);
413 else if (listpos) { /* else sort and merge sublist */
414 list2 = (PACKHEAD *)malloc(listpos*sizeof(PACKHEAD));
415 CHECK(list2==NULL, SYSTEM, "out of memory in sortcomplist");
416 memcpy((void *)list2,(void *)complist,listpos*sizeof(PACKHEAD));
417 qsort((void *)list2, listpos, sizeof(PACKHEAD), beamcmp);
418 mergeclists(complist, list2, listpos,
419 complist+listpos, complen-listpos);
420 free((void *)list2);
421 }
422 /* drop satisfied requests */
423 for (i = complen; i-- && complist[i].nr <= complist[i].nc; )
424 ;
425 if (i < 0) {
426 free((void *)complist);
427 complist = NULL;
428 complen = 0;
429 } else if (i < complen-1) {
430 list2 = (PACKHEAD *)realloc((void *)complist,
431 (i+1)*sizeof(PACKHEAD));
432 if (list2 != NULL)
433 complist = list2;
434 complen = i+1;
435 }
436 listpos = 0; lastin = i;
437 }
438
439
440 /*
441 * The following routine works on the assumption that the bundle weights are
442 * more or less evenly distributed, such that computing a packet causes
443 * a given bundle to move way down in the computation order. We keep
444 * track of where the computed bundle with the highest priority would end
445 * up, and if we get further in our compute list than this, we re-sort the
446 * list and start again from the beginning. Since
447 * a merge sort is used, the sorting costs are minimal.
448 */
449 extern int
450 next_packet( /* prepare packet for computation */
451 register PACKET *p,
452 int n
453 )
454 {
455 if (listpos > lastin) /* time to sort the list */
456 sortcomplist();
457 if (complen <= 0)
458 return(0);
459 p->hd = complist[listpos].hd;
460 p->bi = complist[listpos].bi;
461 p->nc = complist[listpos].nc;
462 p->nr = complist[listpos].nr - p->nc;
463 if (p->nr <= 0)
464 return(0);
465 DCHECK(n < 1 | n > RPACKSIZ,
466 CONSISTENCY, "next_packet called with bad n value");
467 if (p->nr > n)
468 p->nr = n;
469 complist[listpos].nc += p->nr; /* find where this one would go */
470 if (hdgetbeam(hdlist[p->hd], p->bi) != NULL)
471 hdfreefrag(hdlist[p->hd], p->bi);
472 while (lastin > listpos &&
473 beamcmp(complist+lastin, complist+listpos) > 0)
474 lastin--;
475 listpos++;
476 return(1);
477 }