ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/modobject.c
Revision: 2.25
Committed: Sat Jun 21 17:42:17 2025 UTC (5 weeks ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.24: +21 -9 lines
Log Message:
perf: Optimized objndx() call with hashed cache table

File Contents

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