ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/modobject.c
Revision: 2.26
Committed: Sun Jun 22 17:21:37 2025 UTC (31 hours, 47 minutes ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 2.25: +11 -8 lines
Log Message:
perf: Minor code tweaks to speed initial search, check case OVOID==0

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: modobject.c,v 2.25 2025/06/21 17:42:17 greg Exp $";
3 #endif
4 /*
5 * Routines for tracking object modifiers
6 *
7 * External symbols declared in object.h
8 */
9
10 #include "copyright.h"
11
12 #include "standard.h"
13 #include "object.h"
14 #include "otypes.h"
15
16
17 static struct ohtab {
18 int hsiz; /* current table size */
19 OBJECT *htab; /* table, if allocated */
20 } modtab = {100, NULL}, objtab = {1000, NULL}; /* modifiers and objects */
21
22 static int otndx(char *, struct ohtab *);
23
24
25 OBJECT
26 objndx( /* get object number from pointer */
27 OBJREC *op
28 )
29 {
30 #ifndef ONCACHESIZ
31 #define ONCACHESIZ 907 /* keep a cache of previous searches */
32 #endif
33 static OBJECT oncache[ONCACHESIZ];
34 const int ent = (size_t)op % ONCACHESIZ; /* hash on pointer */
35 int i, lastblock;
36
37 #if OVOID != 0 /* clear cache on first call */
38 for (i = ONCACHESIZ*(!oncache[0] & !oncache[1]); i--; )
39 oncache[i] = OVOID;
40 #endif
41 /* is this pointer in cache? */
42 if ((oncache[ent] != OVOID) & (oncache[ent] < nobjects) &&
43 objptr(oncache[ent]) == op)
44 return(oncache[ent]); /* matches previous search */
45 /* else search for our block from first */
46 lastblock = (nobjects-1)>>OBJBLKSHFT;
47 for (i = 0; i <= lastblock; i++)
48 if ((objblock[i] <= op) & (op < objblock[i]+OBJBLKSIZ)) {
49 /* found it -- cache corresponding index */
50 oncache[ent] = ((OBJECT)i << OBJBLKSHFT) +
51 (op - objblock[i]);
52 return(oncache[ent]);
53 }
54 return(OVOID); /* not allocated -- may still be valid */
55 }
56
57
58 OBJECT
59 lastmod( /* find modifier definition before obj */
60 OBJECT obj,
61 char *mname
62 )
63 {
64 OBJREC *op;
65 OBJECT i;
66
67 i = modifier(mname); /* try hash table first */
68 if ((obj == OVOID) | (i < obj))
69 return(i);
70 for (i = obj; i-- > 0; ) { /* need to search */
71 op = objptr(i);
72 if ((ismodifier(op->otype) != 0) & (op->oname[0] == mname[0])
73 && !strcmp(op->oname, mname))
74 return(i);
75 }
76 return(OVOID);
77 }
78
79
80 OBJECT
81 modifier( /* get a modifier number from its name */
82 char *mname
83 )
84 {
85 int ndx;
86
87 ndx = otndx(mname, &modtab);
88 return(modtab.htab[ndx]);
89 }
90
91
92 #ifdef GETOBJ
93 OBJECT
94 object( /* get an object number from its name */
95 char *oname
96 )
97 {
98 int ndx;
99
100 ndx = otndx(oname, &objtab);
101 return(objtab.htab[ndx]);
102 }
103 #endif
104
105
106 int
107 eqreal( /* are two real values close enough to equal? */
108 double d1,
109 double d2
110 )
111 {
112 if (d2 != 0.0)
113 d1 = d1/d2 - 1.0;
114 return((-FTINY <= d1) & (d1 <= FTINY));
115 }
116
117
118 int
119 eqobjects( /* check if two objects are equal */
120 OBJECT obj1,
121 OBJECT obj2
122 )
123 {
124 OBJREC *op1, *op2;
125 int i, n;
126
127 while (obj1 != obj2) {
128 if (obj1 == OVOID)
129 return(0);
130 if (obj2 == OVOID)
131 return(0);
132 op1 = objptr(obj1);
133 op2 = objptr(obj2);
134 if (op1->otype != op2->otype)
135 return(0);
136 if (op1->oargs.nsargs != op2->oargs.nsargs)
137 return(0);
138 if (op1->oargs.nfargs != op2->oargs.nfargs)
139 return(0);
140 #ifdef IARGS
141 if (op1->oargs.niargs != op2->oargs.niargs)
142 return(0);
143 for (i = op1->oargs.niargs; i-- > 0; )
144 if (op1->oargs.iarg[i] != op2->oargs.iarg[i])
145 return(0);
146 #endif
147 for (i = op1->oargs.nfargs; i-- > 0; )
148 if (!eqreal(op1->oargs.farg[i], op2->oargs.farg[i]))
149 return(0);
150 n = 0;
151 switch (op1->otype) { /* special cases (KEEP CONSISTENT!) */
152 case MOD_ALIAS:
153 case MAT_ILLUM:
154 case MAT_MIRROR:
155 n = (op1->oargs.nsargs > 0);
156 break;
157 case MIX_FUNC:
158 case MIX_DATA:
159 case MIX_TEXT:
160 case MIX_PICT:
161 n = 2*(op1->oargs.nsargs >= 2);
162 break;
163 case MAT_CLIP:
164 n = op1->oargs.nsargs;
165 break;
166 }
167 /* check other string arguments */
168 for (i = op1->oargs.nsargs; i-- > n; )
169 if (strcmp(op1->oargs.sarg[i], op2->oargs.sarg[i]))
170 return(0);
171 while (n-- > 0) /* check modifier references */
172 if (!eqobjects( lastmod(obj1, op1->oargs.sarg[n]),
173 lastmod(obj2, op2->oargs.sarg[n]) ))
174 return(0);
175 obj1 = op1->omod;
176 obj2 = op2->omod;
177 }
178 return(1);
179 }
180
181
182 void
183 insertobject( /* insert new object into our list */
184 OBJECT obj
185 )
186 {
187 int i;
188
189 if (ismodifier(objptr(obj)->otype)) {
190 i = otndx(objptr(obj)->oname, &modtab);
191 if (eqobjects(obj, modtab.htab[i]))
192 return; /* don't index if same as earlier def. */
193 modtab.htab[i] = obj;
194 }
195 #ifdef GETOBJ
196 else {
197 i = otndx(objptr(obj)->oname, &objtab);
198 objtab.htab[i] = obj;
199 }
200 #endif
201 for (i = 0; addobjnotify[i] != NULL; i++)
202 (*addobjnotify[i])(obj);
203 }
204
205
206 void
207 truncobjndx(void) /* remove bogus table entries past end */
208 {
209 int ndx;
210
211 if (nobjects <= 0) {
212 if (modtab.htab != NULL) {
213 free(modtab.htab);
214 modtab.htab = NULL;
215 modtab.hsiz = 100;
216 }
217 if (objtab.htab != NULL) {
218 free(objtab.htab);
219 objtab.htab = NULL;
220 objtab.hsiz = 100;
221 }
222 return;
223 }
224 for (ndx = modtab.hsiz*(modtab.htab != NULL); ndx--; )
225 if (modtab.htab[ndx] >= nobjects)
226 modtab.htab[ndx] = OVOID;
227
228 for (ndx = objtab.hsiz*(objtab.htab != NULL); ndx--; )
229 if (objtab.htab[ndx] >= nobjects)
230 objtab.htab[ndx] = OVOID;
231 }
232
233
234 static int
235 nexthsiz( /* return next hash table size */
236 int oldsiz
237 )
238 {
239 static int hsiztab[] = {
240 251, 509, 1021, 2039, 4093, 8191, 16381,
241 32749, 65521, 131071, 262139, 0
242 };
243 int *hsp;
244
245 for (hsp = hsiztab; *hsp; hsp++)
246 if (*hsp > oldsiz)
247 return(*hsp);
248 return(oldsiz*2 + 1); /* not always prime */
249 }
250
251
252 static int
253 otndx( /* get object table index for name */
254 char *name,
255 struct ohtab *tab
256 )
257 {
258 char *onm;
259 OBJECT *oldhtab;
260 int hval, i;
261 int ndx;
262
263 if (tab->htab == NULL) { /* new table */
264 tab->hsiz = nexthsiz(tab->hsiz);
265 tab->htab = (OBJECT *)malloc(tab->hsiz*sizeof(OBJECT));
266 if (tab->htab == NULL)
267 error(SYSTEM, "out of memory in otndx");
268 ndx = tab->hsiz;
269 while (ndx--) /* empty it */
270 tab->htab[ndx] = OVOID;
271 }
272 /* look up object */
273 hval = shash(name);
274 tryagain:
275 for (i = 0; i < tab->hsiz; i++) {
276 ndx = (hval + (unsigned long)i*i) % tab->hsiz;
277 if (tab->htab[ndx] == OVOID)
278 return(ndx);
279 onm = objptr(tab->htab[ndx])->oname;
280 if (onm != NULL && !strcmp(onm, name))
281 return(ndx);
282 }
283 /* table is full, reallocate */
284 oldhtab = tab->htab;
285 ndx = tab->hsiz;
286 tab->htab = NULL;
287 while (ndx--)
288 if (oldhtab[ndx] != OVOID) {
289 onm = objptr(oldhtab[ndx])->oname;
290 if (onm == NULL)
291 continue;
292 i = otndx(onm, tab);
293 tab->htab[i] = oldhtab[ndx];
294 }
295 free(oldhtab);
296 goto tryagain; /* should happen only once! */
297 }