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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: sort.c,v 1.5 2003/06/16 14:54:54 greg Exp $";
3 #endif
4 /*
5 * Sorting routines for meta-files
6 */
7
8 #include "rtprocess.h" /* getpid() */
9 #include "rterror.h"
10 #include "meta.h"
11
12
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 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
25 /*
26 * This sort routine does a combination quicksort and
27 * n-ary mergesort
28 */
29
30
31 void
32 sort( /* sort primitives according to pcmp */
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 void
83 pmergesort( /* merge sorted files with list */
84
85 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 {
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 error(SYSTEM, "memory exhausted in pmergesort");
106 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 static void
148 treemerge( /* merge into one file */
149
150 int height, int nt, int nf,
151 PLIST *pl,
152 int (*pcmp)(),
153 FILE *ofp
154 )
155 {
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 pmergesort(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 void
195 sendsort( /* 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 static void
251 order( /* order the first n array primitives into list */
252
253 PRIMITIVE *pa[],
254 int n,
255 PLIST *pl
256 )
257 {
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 tfname( /* create temporary file name */
274
275 int lvl, int num
276 )
277 {
278 static char pathbuf[PATH_MAX];
279 static char fnbuf[PATH_MAX];
280 static size_t psiz;
281
282 if (pathbuf[0] == '\0') { /* first time */
283 temp_directory(pathbuf, sizeof(pathbuf));
284 psiz = strlen(pathbuf);
285 }
286 snprintf(fnbuf, sizeof(pathbuf)-psiz,
287 "%s/S%d%c%d", pathbuf, getpid(), lvl+'A', num);
288 /*sprintf(fnbuf, "%sS%d%c%d", TDIR, getpid(), lvl+'A', num);*/
289
290 return(fnbuf);
291 }