ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/meta/sort.c
Revision: 1.6
Committed: Mon Jul 14 20:02:29 2003 UTC (21 years, 5 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 1.5: +3 -6 lines
Log Message:
Moved some more platform dependencies to common header files.
Included a few necessary system headers.

File Contents

# User Rev Content
1 greg 1.1 #ifndef lint
2 schorsch 1.6 static const char RCSid[] = "$Id: sort.c,v 1.5 2003/06/16 14:54:54 greg Exp $";
3 greg 1.1 #endif
4     /*
5     * Sorting routines for meta-files
6     */
7    
8 schorsch 1.6 #include "rtprocess.h" /* getpid() */
9     #include "rterror.h"
10 schorsch 1.2 #include "meta.h"
11 schorsch 1.3
12 greg 1.1
13     #define PBSIZE 1000 /* max size of sort block */
14     /* maxalloc must be >= this */
15    
16     #define NFILES 4 /* number of sort files */
17    
18    
19 schorsch 1.2 static void treemerge(int height, int nt, int nf, PLIST *pl,
20     int (*pcmp)(), FILE *ofp);
21     static void sendsort( PLIST *pl, int (*pcmp)());
22     static void order(PRIMITIVE *pa[], int n, PLIST *pl);
23     static char * tfname( int lvl, int num);
24 greg 1.1
25     /*
26     * This sort routine does a combination quicksort and
27     * n-ary mergesort
28     */
29    
30    
31 schorsch 1.2 void
32     sort( /* sort primitives according to pcmp */
33     FILE *infp,
34     int (*pcmp)() /* compares pointers to pointers to primitives! */
35     )
36 greg 1.1 {
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 schorsch 1.2 void
83 greg 1.5 pmergesort( /* merge sorted files with list */
84 greg 1.1
85 schorsch 1.2 FILE *fi[], /* array of input files */
86     int nf, /* number of input files */
87     PLIST *pl, /* sorted list */
88     int (*pcmp)(), /* comparison function, takes primitive handles */
89     FILE *ofp /* output file */
90     )
91 greg 1.1 {
92     PRIMITIVE *plp; /* position in list */
93     PRIMITIVE *pp[NFILES]; /* input primitives */
94     int minf;
95     PRIMITIVE *minp;
96     register int i;
97    
98     if (pl == NULL)
99     plp = NULL; /* initialize list */
100     else
101     plp = pl->ptop;
102    
103     for (i = 0; i < nf; i++) { /* initialize input files */
104     if ((pp[i] = palloc()) == NULL)
105 greg 1.5 error(SYSTEM, "memory exhausted in pmergesort");
106 greg 1.1 readp(pp[i], fi[i]);
107     }
108    
109     for ( ; ; ) {
110    
111     if (plp != NULL && isprim(plp->com))
112     minp = plp;
113     else
114     minp = NULL;
115    
116     for (i = 0; i < nf; i++)
117     if (isprim(pp[i]->com) &&
118     (minp == NULL || (*pcmp)(&pp[i], &minp) < 0))
119     minp = pp[minf=i];
120    
121     if (minp == NULL)
122     break;
123    
124     writep(minp, ofp);
125    
126     if (minp == plp)
127     plp = plp->pnext;
128     else {
129     fargs(pp[minf]);
130     readp(pp[minf], fi[minf]);
131     }
132     }
133    
134     if (plp != NULL && plp->com != PEOF)
135     writep(plp, ofp);
136    
137     for (i = 0; i < nf; i++) {
138     if (pp[i]->com != PEOF)
139     writep(pp[i], ofp);
140     pfree(pp[i]);
141     }
142    
143     }
144    
145    
146    
147 schorsch 1.2 static void
148     treemerge( /* merge into one file */
149 greg 1.1
150 schorsch 1.2 int height, int nt, int nf,
151     PLIST *pl,
152     int (*pcmp)(),
153     FILE *ofp
154     )
155 greg 1.1 {
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 greg 1.5 pmergesort(fi, nf, pl, pcmp, fp);
168 greg 1.1
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 schorsch 1.2 static void
195     sendsort( /* send a sorted list */
196 greg 1.1
197 schorsch 1.2 PLIST *pl,
198     int (*pcmp)()
199     )
200 greg 1.1 {
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 schorsch 1.2 static void
251     order( /* order the first n array primitives into list */
252 greg 1.1
253 schorsch 1.2 PRIMITIVE *pa[],
254     int n,
255     PLIST *pl
256     )
257 greg 1.1 {
258     register int i;
259    
260     for (i = 1; i < n; i++)
261     pa[i-1]->pnext = pa[i];
262    
263     pa[n-1]->pnext = NULL;
264     pl->ptop = pa[0];
265     pl->pbot = pa[n-1];
266    
267     }
268    
269    
270    
271    
272     static char *
273 schorsch 1.2 tfname( /* create temporary file name */
274 greg 1.1
275 schorsch 1.2 int lvl, int num
276     )
277 greg 1.1 {
278 schorsch 1.2 static char pathbuf[PATH_MAX];
279 schorsch 1.3 static char fnbuf[PATH_MAX];
280     static size_t psiz;
281 greg 1.1
282 schorsch 1.3 if (pathbuf[0] == '\0') { /* first time */
283     temp_directory(pathbuf, sizeof(pathbuf));
284     psiz = strlen(pathbuf);
285     }
286 schorsch 1.4 snprintf(fnbuf, sizeof(pathbuf)-psiz,
287 schorsch 1.3 "%s/S%d%c%d", pathbuf, getpid(), lvl+'A', num);
288 schorsch 1.2 /*sprintf(fnbuf, "%sS%d%c%d", TDIR, getpid(), lvl+'A', num);*/
289 greg 1.1
290 schorsch 1.3 return(fnbuf);
291 greg 1.1 }