ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/meta/sort.c
Revision: 1.1
Committed: Sat Feb 22 02:07:26 2003 UTC (21 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R5
Log Message:
Changes and check-in for 3.5 release
Includes new source files and modifications not recorded for many years
See ray/doc/notes/ReleaseNotes for notes between 3.1 and 3.5 release

File Contents

# User Rev Content
1 greg 1.1 #ifndef lint
2     static const char RCSid[] = "$Id$";
3     #endif
4     /*
5     * Sorting routines for meta-files
6     */
7    
8    
9     #define PBSIZE 1000 /* max size of sort block */
10     /* maxalloc must be >= this */
11    
12    
13     #define NFILES 4 /* number of sort files */
14    
15    
16    
17     #include "meta.h"
18    
19    
20    
21    
22    
23    
24    
25     /*
26     * This sort routine does a combination quicksort and
27     * n-ary mergesort
28     */
29    
30    
31     sort(infp, pcmp) /* sort primitives according to pcmp */
32    
33     FILE *infp;
34     int (*pcmp)(); /* compares pointers to pointers to primitives! */
35    
36     {
37     PRIMITIVE *prims[PBSIZE]; /* pointers to primitives */
38     PLIST primlist; /* our primitives list */
39     int nprims;
40     short done;
41    
42     do {
43    
44     for (nprims = 0; nprims < PBSIZE; nprims++) { /* read to global */
45    
46     if ((prims[nprims] = palloc()) == NULL)
47     error(SYSTEM, "memory exhausted in sort");
48    
49     readp(prims[nprims], infp);
50    
51     if (isglob(prims[nprims]->com))
52     break;
53     }
54    
55     qsort(prims, nprims, sizeof(*prims), pcmp); /* sort pointer array */
56    
57     if (nprims < PBSIZE) /* tack on global if one */
58     nprims++;
59    
60     order(prims, nprims, &primlist); /* make array into list */
61    
62     sendsort(&primlist, pcmp); /* send to merge sorter */
63    
64     done = primlist.pbot->com == PEOF;
65    
66     plfree(&primlist); /* free up array */
67    
68     } while (!done);
69    
70     }
71    
72    
73    
74    
75    
76     /*
77     * The following routine merges up to NFILES sorted primitive files
78     * with 0 or 1 primitive lists. Each set of primitives can end with
79     * 0 or 1 global commands.
80     */
81    
82     mergesort(fi, nf, pl, pcmp, ofp) /* merge sorted files with list */
83    
84     FILE *fi[]; /* array of input files */
85     int nf; /* number of input files */
86     PLIST *pl; /* sorted list */
87     int (*pcmp)(); /* comparison function, takes primitive handles */
88     FILE *ofp; /* output file */
89    
90     {
91     PRIMITIVE *plp; /* position in list */
92     PRIMITIVE *pp[NFILES]; /* input primitives */
93     int minf;
94     PRIMITIVE *minp;
95     register int i;
96    
97     if (pl == NULL)
98     plp = NULL; /* initialize list */
99     else
100     plp = pl->ptop;
101    
102     for (i = 0; i < nf; i++) { /* initialize input files */
103     if ((pp[i] = palloc()) == NULL)
104     error(SYSTEM, "memory exhausted in mergesort");
105     readp(pp[i], fi[i]);
106     }
107    
108     for ( ; ; ) {
109    
110     if (plp != NULL && isprim(plp->com))
111     minp = plp;
112     else
113     minp = NULL;
114    
115     for (i = 0; i < nf; i++)
116     if (isprim(pp[i]->com) &&
117     (minp == NULL || (*pcmp)(&pp[i], &minp) < 0))
118     minp = pp[minf=i];
119    
120     if (minp == NULL)
121     break;
122    
123     writep(minp, ofp);
124    
125     if (minp == plp)
126     plp = plp->pnext;
127     else {
128     fargs(pp[minf]);
129     readp(pp[minf], fi[minf]);
130     }
131     }
132    
133     if (plp != NULL && plp->com != PEOF)
134     writep(plp, ofp);
135    
136     for (i = 0; i < nf; i++) {
137     if (pp[i]->com != PEOF)
138     writep(pp[i], ofp);
139     pfree(pp[i]);
140     }
141    
142     }
143    
144    
145    
146     static
147     treemerge(height, nt, nf, pl, pcmp, ofp) /* merge into one file */
148    
149     int height, nt, nf;
150     PLIST *pl;
151     int (*pcmp)();
152     FILE *ofp;
153    
154     {
155     char *tfname();
156     FILE *fi[NFILES], *fp;
157     int i;
158    
159     if (nf <= NFILES) {
160    
161     for (i = 0; i < nf; i++)
162     fi[i] = efopen(tfname(height, i + nt*NFILES), "r");
163    
164     if ((fp = ofp) == NULL)
165     fp = efopen(tfname(height + 1, nt), "w");
166    
167     mergesort(fi, nf, pl, pcmp, fp);
168    
169     for (i = 0; i < nf; i++) {
170     fclose(fi[i]);
171     unlink(tfname(height, i + nt*NFILES));
172     }
173     if (ofp == NULL) {
174     writeof(fp);
175     fclose(fp);
176     }
177    
178     } else {
179    
180     for (i = 0; i < (nf-1)/NFILES; i++)
181     treemerge(height, i, NFILES, NULL, pcmp, NULL);
182    
183     treemerge(height, (nf-1)/NFILES, (nf-1)%NFILES + 1, pl, pcmp, NULL);
184    
185     treemerge(height + 1, 0, (nf-1)/NFILES + 1, NULL, pcmp, ofp);
186    
187     }
188    
189     }
190    
191    
192    
193    
194     static
195     sendsort(pl, pcmp) /* send a sorted list */
196    
197     PLIST *pl;
198     int (*pcmp)();
199    
200     {
201     static int nf = 0,
202     intree = FALSE;
203     FILE *fp;
204    
205     if (isglob(pl->pbot->com)) {
206    
207     /* send sorted output to stdout */
208     if (intree && nf <= NFILES)
209    
210     treemerge(0, 0, nf, pl, pcmp, stdout);
211    
212     else if (nf%NFILES == 0)
213    
214     if (intree) {
215     treemerge(0, nf/NFILES - 1, NFILES, pl, pcmp, NULL);
216     treemerge(1, 0, nf/NFILES, NULL, pcmp, stdout);
217     } else
218     treemerge(1, 0, nf/NFILES, pl, pcmp, stdout);
219    
220     else {
221    
222     treemerge(0, nf/NFILES, nf%NFILES, pl, pcmp, NULL);
223     treemerge(1, 0, nf/NFILES + 1, NULL, pcmp, stdout);
224    
225     }
226    
227     nf = 0; /* all done */
228     intree = FALSE; /* reset for next time */
229    
230     } else if (intree && nf%NFILES == 0) {
231    
232     /* merge NFILES with list */
233     treemerge(0, nf/NFILES - 1, NFILES, pl, pcmp, NULL);
234     intree = FALSE;
235    
236     } else {
237    
238     /* output straight to temp file */
239     treemerge(-1, nf++, 0, pl, pcmp, NULL);
240     intree = TRUE;
241    
242     }
243    
244    
245    
246     }
247    
248    
249    
250    
251     static
252     order(pa, n, pl) /* order the first n array primitives into list */
253    
254     PRIMITIVE *pa[];
255     int n;
256     PLIST *pl;
257    
258     {
259     register int i;
260    
261     for (i = 1; i < n; i++)
262     pa[i-1]->pnext = pa[i];
263    
264     pa[n-1]->pnext = NULL;
265     pl->ptop = pa[0];
266     pl->pbot = pa[n-1];
267    
268     }
269    
270    
271    
272    
273     static char *
274     tfname(lvl, num) /* create temporary file name */
275    
276     int lvl, num;
277    
278     {
279     static char fnbuf[32];
280    
281     sprintf(fnbuf, "%sS%d%c%d", TDIR, getpid(), lvl+'A', num);
282    
283     return(fnbuf);
284     }