ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/objset.c
Revision: 2.18
Committed: Sat Mar 18 15:21:17 2023 UTC (19 months, 3 weeks ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R4, HEAD
Changes since 2.17: +2 -2 lines
Error occurred while calculating annotation data.
Log Message:
perf: Bumped object set hash table size to improve performance on large scenes

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: objset.c,v 2.17 2015/04/28 16:56:10 greg Exp $";
3 #endif
4 /*
5 * objset.c - routines for maintaining object sets.
6 *
7 * External symbols declared in object.h
8 */
9
10 #include "copyright.h"
11
12 #include "standard.h"
13
14 #include "octree.h"
15
16 #include "object.h"
17
18 #ifndef OSTSIZ
19 #ifdef SMLMEM
20 #define OSTSIZ 32749 /* object table size (a prime!) */
21 #else
22 #define OSTSIZ 1002583 /* object table size (a prime!) */
23 #endif
24 #endif
25
26 #undef xtra_long
27 #ifdef _WIN64
28 typedef unsigned long long int xtra_long;
29 #else
30 typedef unsigned long int xtra_long;
31 #endif
32
33 static OBJECT *ostable[OSTSIZ]; /* the object set table */
34
35
36 void
37 insertelem( /* insert obj into os, no questions */
38 OBJECT *os,
39 OBJECT obj
40 )
41 {
42 int i;
43
44 for (i = os[0]++; i > 0; i--)
45 if (os[i] > obj)
46 os[i+1] = os[i];
47 else
48 break;
49 os[i+1] = obj;
50 }
51
52
53 void
54 deletelem( /* delete obj from os, no questions */
55 OBJECT *os,
56 OBJECT obj
57 )
58 {
59 int i;
60
61 i = (*os)--;
62 os++;
63 while (i > 0 && *os < obj) {
64 i--;
65 os++;
66 }
67 while (--i > 0) {
68 os[0] = os[1];
69 os++;
70 }
71 }
72
73
74 int
75 inset( /* determine if object is in set */
76 OBJECT *os,
77 OBJECT obj
78 )
79 {
80 int upper, lower;
81 int cm, i;
82
83 if ((i = os[0]) <= 12) { /* linear search algorithm */
84 cm = obj;
85 while (i-- > 0)
86 if (*++os == cm)
87 return(1);
88 return(0);
89 }
90 lower = 1;
91 upper = cm = i + 1;
92 /* binary search algorithm */
93 while ((i = (lower + upper) >> 1) != cm) {
94 cm = obj - os[i];
95 if (cm > 0)
96 lower = i;
97 else if (cm < 0)
98 upper = i;
99 else
100 return(1);
101 cm = i;
102 }
103 return(0);
104 }
105
106
107 int
108 setequal( /* determine if two sets are equal */
109 OBJECT *os1,
110 OBJECT *os2
111 )
112 {
113 int i;
114
115 for (i = *os1; i-- >= 0; )
116 if (*os1++ != *os2++)
117 return(0);
118 return(1);
119 }
120
121
122 void
123 setcopy( /* copy object set os2 into os1 */
124 OBJECT *os1,
125 OBJECT *os2
126 )
127 {
128 int i;
129
130 for (i = *os2; i-- >= 0; )
131 *os1++ = *os2++;
132 }
133
134
135 OBJECT *
136 setsave( /* allocate space and save set */
137 OBJECT *os
138 )
139 {
140 OBJECT *osnew;
141 OBJECT *oset;
142 int i;
143
144 if ((osnew = oset = (OBJECT *)malloc((*os+1)*sizeof(OBJECT))) == NULL)
145 error(SYSTEM, "out of memory in setsave\n");
146 for (i = *os; i-- >= 0; ) /* inline setcopy */
147 *oset++ = *os++;
148 return(osnew);
149 }
150
151
152 void
153 setunion( /* osr = os1 Union os2 */
154 OBJECT *osr,
155 OBJECT *os1,
156 OBJECT *os2
157 )
158 {
159 int i1, i2;
160
161 osr[0] = 0;
162 for (i1 = i2 = 1; i1 <= os1[0] || i2 <= os2[0]; ) {
163 while (i1 <= os1[0] && (i2 > os2[0] || os1[i1] <= os2[i2])) {
164 osr[++osr[0]] = os1[i1];
165 if (i2 <= os2[0] && os2[i2] == os1[i1])
166 i2++;
167 i1++;
168 }
169 while (i2 <= os2[0] && (i1 > os1[0] || os2[i2] < os1[i1]))
170 osr[++osr[0]] = os2[i2++];
171 }
172 }
173
174
175 void
176 setintersect( /* osr = os1 Intersect os2 */
177 OBJECT *osr,
178 OBJECT *os1,
179 OBJECT *os2
180 )
181 {
182 int i1, i2;
183
184 osr[0] = 0;
185 if (os1[0] <= 0)
186 return;
187 for (i1 = i2 = 1; i2 <= os2[0]; ) {
188 while (os1[i1] < os2[i2])
189 if (++i1 > os1[0])
190 return;
191 while (os2[i2] < os1[i1])
192 if (++i2 > os2[0])
193 return;
194 if (os1[i1] == os2[i2])
195 osr[++osr[0]] = os2[i2++];
196 }
197 }
198
199
200 OCTREE
201 fullnode( /* return octree for object set */
202 OBJECT *oset
203 )
204 {
205 unsigned int ntries;
206 xtra_long hval;
207 OCTREE ot;
208 int osentry, i;
209 OBJECT *os;
210 /* hash on set */
211 hval = 0;
212 os = oset;
213 i = *os++;
214 while (i-- > 0)
215 hval += *os++;
216 ntries = 0;
217 tryagain:
218 osentry = (hval + (xtra_long)ntries*ntries) % OSTSIZ;
219 os = ostable[osentry];
220 if (os == NULL) {
221 os = ostable[osentry] = (OBJECT *)malloc(
222 (unsigned)(oset[0]+2)*sizeof(OBJECT));
223 if (os == NULL)
224 goto memerr;
225 ot = oseti(osentry);
226 } else {
227 /* look for set */
228 for (i = 0; *os > 0; i++, os += *os + 1)
229 if (setequal(os, oset))
230 break;
231 ot = oseti(i*OSTSIZ + osentry);
232 if (*os > 0) /* found it */
233 return(ot);
234 if (!isfull(ot)) { /* entry overflow */
235 if (++ntries < OSTSIZ)
236 goto tryagain;
237 else
238 error(INTERNAL, "hash table overflow in fullnode");
239 }
240 /* remember position */
241 i = os - ostable[osentry];
242 os = ostable[osentry] = (OBJECT *)realloc(
243 (void *)ostable[osentry],
244 (unsigned)(i+oset[0]+2)*sizeof(OBJECT));
245 if (os == NULL)
246 goto memerr;
247 os += i; /* last entry */
248 }
249 setcopy(os, oset); /* add new set */
250 os += *os + 1;
251 *os = 0; /* terminator */
252 return(ot);
253 memerr:
254 error(SYSTEM, "out of memory in fullnode");
255 return 0; /* pro forma return */
256 }
257
258
259 void
260 objset( /* get object set for full node */
261 OBJECT *oset,
262 OCTREE ot
263 )
264 {
265 OBJECT *os;
266 int i;
267
268 if (!isfull(ot))
269 goto noderr;
270 ot = oseti(ot);
271 if ((os = ostable[ot%OSTSIZ]) == NULL)
272 goto noderr;
273 for (i = ot/OSTSIZ; i--; os += *os + 1)
274 if (*os <= 0)
275 goto noderr;
276 for (i = *os; i-- >= 0; ) /* copy set here */
277 *oset++ = *os++;
278 return;
279 noderr:
280 error(CONSISTENCY, "bad node in objset");
281 }
282
283
284 void
285 donesets(void) /* free ALL SETS in our table */
286 {
287 int n;
288
289 for (n = 0; n < OSTSIZ; n++)
290 if (ostable[n] != NULL) {
291 free((void *)ostable[n]);
292 ostable[n] = NULL;
293 }
294 }