ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rholo3.c
Revision: 3.29
Committed: Sat Jan 9 19:48:28 1999 UTC (25 years, 3 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.28: +4 -0 lines
Log Message:
added packet deallocation to dispbeam()

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