ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/hd/rholo3.c
Revision: 3.22
Committed: Wed Jul 8 17:59:58 1998 UTC (25 years, 9 months ago) by gwlarson
Content type: text/plain
Branch: MAIN
Changes since 3.21: +15 -18 lines
Log Message:
fixed bundle_set() with BS_ADJ to send satisfiable requests

File Contents

# User Rev Content
1 gregl 3.1 /*
2     * Routines for tracking beam compuatations
3     */
4    
5     #include "rholo.h"
6    
7     #define abs(x) ((x) > 0 ? (x) : -(x))
8     #define sgn(x) ((x) > 0 ? 1 : (x) < 0 ? -1 : 0)
9    
10 gregl 3.4 static PACKHEAD *complist=NULL; /* list of beams to compute */
11     static int complen=0; /* length of complist */
12     static int listpos=0; /* current list position for next_packet */
13     static int lastin= -1; /* last ordered position in list */
14 gregl 3.1
15    
16     int
17 gregl 3.2 beamcmp(b0, b1) /* comparison for descending compute order */
18     register PACKHEAD *b0, *b1;
19     {
20 gregl 3.11 return( b1->nr*(b0->nc+1) - b0->nr*(b1->nc+1) );
21 gregl 3.2 }
22    
23    
24 gregl 3.14 int
25     dispbeam(b, hp, bi) /* display a holodeck beam */
26     register BEAM *b;
27     HOLO *hp;
28     int bi;
29     {
30     static int n = 0;
31     static PACKHEAD *p = NULL;
32    
33     if (b == NULL)
34     return;
35     if (b->nrm > n) { /* (re)allocate packet holder */
36     n = b->nrm;
37     if (p == NULL) p = (PACKHEAD *)malloc(packsiz(n));
38     else p = (PACKHEAD *)realloc((char *)p, packsiz(n));
39     if (p == NULL)
40     error(SYSTEM, "out of memory in dispbeam");
41     }
42     /* assign packet fields */
43     bcopy((char *)hdbray(b), (char *)packra(p), b->nrm*sizeof(RAYVAL));
44     p->nr = p->nc = b->nrm;
45     for (p->hd = 0; hdlist[p->hd] != hp; p->hd++)
46     if (hdlist[p->hd] == NULL)
47     error(CONSISTENCY, "unregistered holodeck in dispbeam");
48     p->bi = bi;
49     disp_packet(p); /* display it */
50     }
51    
52    
53 gregl 3.2 bundle_set(op, clist, nents) /* bundle set operation */
54     int op;
55 gregl 3.14 register PACKHEAD *clist;
56 gregl 3.2 int nents;
57     {
58 gregl 3.20 int oldnr;
59 gwlarson 3.22 register HDBEAMI *hb;
60 gregl 3.2 register int i, n;
61 gregl 3.20 /* look for common members */
62     for (n = 0; n < nents; n++) {
63     for (i = 0; i < complen; i++)
64     if (clist[n].bi == complist[i].bi &&
65     clist[n].hd == complist[i].hd) {
66     oldnr = complist[i].nr;
67     clist[n].nc = complist[i].nc;
68     switch (op) {
69     case BS_ADD: /* add to count */
70     complist[i].nr += clist[n].nr;
71     clist[n].nr = 0;
72     break;
73     case BS_ADJ: /* reset count */
74     complist[i].nr = clist[n].nr;
75     clist[n].nr = 0;
76     break;
77     case BS_DEL: /* delete count */
78     if (clist[n].nr == 0 ||
79     clist[n].nr >= complist[i].nr)
80     complist[i].nr = 0;
81     else
82     complist[i].nr -= clist[n].nr;
83     break;
84     }
85     if (complist[i].nr != oldnr)
86     lastin = -1; /* flag sort */
87     break;
88     }
89     if (i >= complen)
90     clist[n].nc = bnrays(hdlist[clist[n].hd], clist[n].bi);
91     }
92     /* complete list operations */
93 gregl 3.2 switch (op) {
94     case BS_NEW: /* new computation set */
95 gwlarson 3.21 listpos = 0; lastin = -1;
96 gregl 3.20 if (complen) /* free old list */
97 gregl 3.2 free((char *)complist);
98 gregl 3.20 complist = NULL;
99     if (!(complen = nents))
100 gregl 3.2 return;
101     complist = (PACKHEAD *)malloc(nents*sizeof(PACKHEAD));
102     if (complist == NULL)
103     goto memerr;
104     bcopy((char *)clist, (char *)complist, nents*sizeof(PACKHEAD));
105     break;
106     case BS_ADD: /* add to computation set */
107 gregl 3.11 case BS_ADJ: /* adjust set quantities */
108 gregl 3.2 if (nents <= 0)
109     return;
110 gregl 3.20 sortcomplist(); /* sort updated list & new entries */
111 gregl 3.2 qsort((char *)clist, nents, sizeof(PACKHEAD), beamcmp);
112     /* what can't we satisfy? */
113 gregl 3.11 for (n = 0; n < nents && clist[n].nr > clist[n].nc; n++)
114 gregl 3.2 ;
115 gwlarson 3.22 if (op == BS_ADJ) { /* don't regenerate adjusted beams */
116     for (i = n; i < nents && clist[i].nr > 0; i++)
117     ;
118     nents = i;
119     }
120 gregl 3.2 if (n) { /* allocate space for merged list */
121     PACKHEAD *newlist;
122     newlist = (PACKHEAD *)malloc(
123     (complen+n)*sizeof(PACKHEAD) );
124     if (newlist == NULL)
125     goto memerr;
126     /* merge lists */
127     mergeclists(newlist, clist, n, complist, complen);
128     if (complen)
129     free((char *)complist);
130     complist = newlist;
131     complen += n;
132     }
133     listpos = 0;
134     lastin = complen-1; /* list is now sorted */
135     break;
136     case BS_DEL: /* delete from computation set */
137 gregl 3.20 return; /* already done */
138 gregl 3.2 default:
139     error(CONSISTENCY, "bundle_set called with unknown operation");
140     }
141 gwlarson 3.22 if (outdev == NULL) /* nothing to display? */
142     return;
143     /* load and display beams we have */
144     hb = (HDBEAMI *)malloc(nents*sizeof(HDBEAMI));
145     for (i = 0; i < nents; i++) {
146     hb[i].h = hdlist[clist[i].hd];
147     hb[i].b = clist[i].bi;
148 gregl 3.11 }
149 gwlarson 3.22 hdloadbeams(hb, nents, dispbeam);
150     free((char *)hb);
151 gregl 3.2 return;
152     memerr:
153     error(SYSTEM, "out of memory in bundle_set");
154     }
155    
156    
157 gregl 3.13 double
158     beamvolume(hp, bi) /* compute approximate volume of a beam */
159 gregl 3.1 HOLO *hp;
160 gregl 3.13 int bi;
161 gregl 3.1 {
162 gregl 3.13 GCOORD gc[2];
163     FVECT cp[4], edgeA, edgeB, cent[2];
164     FVECT v, crossp[2], diffv;
165     double vol[2];
166     register int i;
167     /* get grid coordinates */
168     if (!hdbcoord(gc, hp, bi))
169     error(CONSISTENCY, "bad beam index in beamvolume");
170     for (i = 0; i < 2; i++) { /* compute cell area vectors */
171     hdcell(cp, hp, gc+i);
172     VSUM(edgeA, cp[1], cp[0], -1.0);
173     VSUM(edgeB, cp[3], cp[1], -1.0);
174     fcross(crossp[i], edgeA, edgeB);
175     /* compute center */
176     cent[i][0] = 0.5*(cp[0][0] + cp[2][0]);
177     cent[i][1] = 0.5*(cp[0][1] + cp[2][1]);
178     cent[i][2] = 0.5*(cp[0][2] + cp[2][2]);
179 gregl 3.1 }
180 gregl 3.13 /* compute difference vector */
181     VSUM(diffv, cent[1], cent[0], -1.0);
182     for (i = 0; i < 2; i++) { /* compute volume contributions */
183 gregl 3.15 vol[i] = 0.5*DOT(crossp[i], diffv);
184 gregl 3.13 if (vol[i] < 0.) vol[i] = -vol[i];
185     }
186     return(vol[0] + vol[1]); /* return total volume */
187 gregl 3.1 }
188    
189    
190     init_global() /* initialize global ray computation */
191     {
192     long wtotal = 0;
193     double frac;
194 gregl 3.13 int i;
195     register int j, k;
196 gregl 3.18 /* free old list and empty queue */
197     if (complen > 0) {
198 gregl 3.3 free((char *)complist);
199 gregl 3.18 done_packets(flush_queue());
200     }
201 gregl 3.1 /* allocate beam list */
202     complen = 0;
203     for (j = 0; hdlist[j] != NULL; j++)
204     complen += nbeams(hdlist[j]);
205     complist = (PACKHEAD *)malloc(complen*sizeof(PACKHEAD));
206     if (complist == NULL)
207     error(SYSTEM, "out of memory in init_global");
208     /* compute beam weights */
209     k = 0;
210 gregl 3.13 for (j = 0; hdlist[j] != NULL; j++) {
211 gregl 3.19 frac = 512. * VLEN(hdlist[j]->wg[0]) *
212     VLEN(hdlist[j]->wg[1]) *
213     VLEN(hdlist[j]->wg[2]);
214 gregl 3.1 for (i = nbeams(hdlist[j]); i > 0; i--) {
215     complist[k].hd = j;
216     complist[k].bi = i;
217 gregl 3.13 complist[k].nr = frac*beamvolume(hdlist[j], i) + 0.5;
218 gregl 3.18 complist[k].nc = bnrays(hdlist[j], i);
219 gregl 3.1 wtotal += complist[k++].nr;
220     }
221 gregl 3.13 }
222 gregl 3.1 /* adjust weights */
223 gregl 3.12 if (vdef(DISKSPACE))
224 gregl 3.1 frac = 1024.*1024.*vflt(DISKSPACE) / (wtotal*sizeof(RAYVAL));
225 gregl 3.12 else
226     frac = 1024.*1024.*16384. / (wtotal*sizeof(RAYVAL));
227     while (k--)
228     complist[k].nr = frac * complist[k].nr;
229 gwlarson 3.21 listpos = 0; lastin = -1; /* perform initial sort */
230     sortcomplist();
231 gregl 3.1 }
232    
233    
234     mergeclists(cdest, cl1, n1, cl2, n2) /* merge two sorted lists */
235 gregl 3.16 register PACKHEAD *cdest;
236     register PACKHEAD *cl1, *cl2;
237 gregl 3.1 int n1, n2;
238     {
239 gregl 3.16 register int cmp;
240 gregl 3.1
241     while (n1 | n2) {
242     if (!n1) cmp = 1;
243     else if (!n2) cmp = -1;
244     else cmp = beamcmp(cl1, cl2);
245     if (cmp > 0) {
246     copystruct(cdest, cl2);
247     cl2++; n2--;
248     } else {
249     copystruct(cdest, cl1);
250     cl1++; n1--;
251     }
252     cdest++;
253     }
254     }
255    
256    
257     sortcomplist() /* fix our list order */
258     {
259     PACKHEAD *list2;
260 gregl 3.2 register int i;
261    
262 gregl 3.3 if (complen <= 0) /* check to see if there is even a list */
263 gregl 3.2 return;
264 gregl 3.6 if (lastin < 0 || listpos*4 >= complen*3)
265 gregl 3.1 qsort((char *)complist, complen, sizeof(PACKHEAD), beamcmp);
266     else if (listpos) { /* else sort and merge sublist */
267     list2 = (PACKHEAD *)malloc(listpos*sizeof(PACKHEAD));
268     if (list2 == NULL)
269     error(SYSTEM, "out of memory in sortcomplist");
270     bcopy((char *)complist,(char *)list2,listpos*sizeof(PACKHEAD));
271     qsort((char *)list2, listpos, sizeof(PACKHEAD), beamcmp);
272     mergeclists(complist, list2, listpos,
273     complist+listpos, complen-listpos);
274     free((char *)list2);
275     }
276 gregl 3.2 /* drop satisfied requests */
277 gregl 3.11 for (i = complen; i-- && complist[i].nr <= complist[i].nc; )
278 gregl 3.2 ;
279 gregl 3.4 if (i < 0) {
280     free((char *)complist);
281     complist = NULL;
282     complen = 0;
283     } else if (i < complen-1) {
284 gregl 3.2 list2 = (PACKHEAD *)realloc((char *)complist,
285     (i+1)*sizeof(PACKHEAD));
286     if (list2 != NULL) {
287     complist = list2;
288     complen = i+1;
289     }
290     }
291     listpos = 0; lastin = i;
292 gregl 3.1 }
293    
294    
295     /*
296     * The following routine works on the assumption that the bundle weights are
297     * more or less evenly distributed, such that computing a packet causes
298     * a given bundle to move way down in the computation order. We keep
299     * track of where the computed bundle with the highest priority would end
300     * up, and if we get further in our compute list than this, we resort the
301 gregl 3.11 * list and start again from the beginning. Since
302     * a merge sort is used, the sorting costs are minimal.
303 gregl 3.1 */
304 gregl 3.17 next_packet(p, n) /* prepare packet for computation */
305 gregl 3.1 register PACKET *p;
306 gregl 3.17 int n;
307 gregl 3.1 {
308     register int i;
309    
310 gregl 3.10 if (listpos > lastin) /* time to sort the list */
311     sortcomplist();
312 gregl 3.1 if (complen <= 0)
313     return(0);
314     p->hd = complist[listpos].hd;
315     p->bi = complist[listpos].bi;
316 gregl 3.11 p->nc = complist[listpos].nc;
317     p->nr = complist[listpos].nr - p->nc;
318 gregl 3.1 if (p->nr <= 0)
319     return(0);
320 gregl 3.17 #ifdef DEBUG
321     if (n < 1 | n > RPACKSIZ)
322     error(CONSISTENCY, "next_packet called with bad n value");
323     #endif
324     if (p->nr > n)
325     p->nr = n;
326 gregl 3.11 complist[listpos].nc += p->nr; /* find where this one would go */
327     while (lastin > listpos &&
328     beamcmp(complist+lastin, complist+listpos) > 0)
329 gregl 3.1 lastin--;
330     listpos++;
331     return(1);
332     }