~ubuntu-branches/ubuntu/maverick/ploticus/maverick

« back to all changes in this revision

Viewing changes to src/proc_tabulate.c

  • Committer: Bazaar Package Importer
  • Author(s): James W. Penny
  • Date: 2002-04-10 23:02:04 UTC
  • Revision ID: james.westby@ubuntu.com-20020410230204-64em4ns2f57c5u3l
Tags: 2.0.3-1
* The "That Tears it, Now You Have to Update Docs Package" Release.
* New upstream release (well, not so new :-( )   closes: Bug#137578
* Correct missing libpng2-dev in build-depends.  closes: Bug#142205
* Use correct syntax to:
* close URL type.                                closes: Bug#137577
* fix Architecture                               closes: Bug#141657
* close ITP                                      closes: Bug#132878

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ploticus data display engine.  Software, documentation, and examples.  
 
2
 * Copyright 1998-2002 Stephen C. Grubb  (scg@jax.org).
 
3
 * Covered by GPL; see the file ./Copyright for details. */
 
4
 
 
5
/* PROC TABULATE - do frequency distributions, 1-D or 2-D */
 
6
 
 
7
/* Uses data read by most recent getdata; result becomes "current data set"
 
8
 
 
9
   scg 1/11/00  - added support for special units even when categories not in use
 
10
   scg 1/21/00  - changed tab[][], total[], and grantotal from int to double.
 
11
                  added accumfield option.
 
12
   scg 1/21/00  - for 2-way dist, column tags are used to set getdata field names
 
13
 
 
14
*/
 
15
#include "pl.h"
 
16
 
 
17
#define WORDLEN 40
 
18
#define MAXBINS 200
 
19
#define MAXROWS 200
 
20
#define MAXCOLS 60
 
21
 
 
22
 
 
23
static int fsort(), freqsort();
 
24
 
 
25
PLP_tabulate()
 
26
{
 
27
int i;
 
28
char attr[40], val[256];
 
29
char *line, *lineval;
 
30
int nt, lvp;
 
31
int first;
 
32
 
 
33
char buf[256];
 
34
double tab[MAXROWS][MAXCOLS];
 
35
double total[2][MAXROWS];
 
36
double grantotal;
 
37
char list[2][MAXROWS][WORDLEN];
 
38
 
 
39
int stat;
 
40
int align;
 
41
double adjx, adjy;
 
42
 
 
43
int j, m, fld, nlist[3];
 
44
int select[3], ndim;
 
45
int order[2][MAXROWS], valuesgiven[2], nval, dopercents;
 
46
int forcevertical, forcehorizontal;
 
47
/* int outputbyfreq[2], reverse[2]; */
 
48
char ordering[2];
 
49
char tmp[WORDLEN];
 
50
char *GL_getok();
 
51
double atof(), f;
 
52
/* --- */
 
53
char valuelist[2][256];
 
54
int field[2];
 
55
int ix;
 
56
double tmpd;
 
57
char savetable[80];
 
58
int len;
 
59
int irow;
 
60
double gran[2];
 
61
int davail;
 
62
int curd;
 
63
char numbuf[80];
 
64
char selectex[80];
 
65
int result;
 
66
int doranges[2];
 
67
char axis[2];
 
68
int ixx;
 
69
char hival[80], lowval[80];
 
70
double hiv[MAXBINS], lowv[MAXBINS];
 
71
double fval;
 
72
char rangesepchar[5];
 
73
char showrange[20];
 
74
FILE *sfp;
 
75
char rangespec[2][80];
 
76
int axisset[2]; /* added 1/11/00 scg */
 
77
char tag[80];   /* added 1/11/00 scg */
 
78
char fieldnamelist[256]; /* added 1/21/00 scg */
 
79
int accumfield;
 
80
double inc;
 
81
 
 
82
 
 
83
TDH_errprog( "pl proc tabulate" );
 
84
 
 
85
 
 
86
/* initialize */
 
87
field[0] = -1; field[1] = -1;
 
88
ndim = -1;
 
89
valuesgiven[0] = valuesgiven[1] = 0;
 
90
dopercents = 0;
 
91
forcevertical = 1; forcehorizontal = 0;
 
92
ordering[0] = '?'; ordering[1] = '?';
 
93
strcpy( savetable, "" );
 
94
gran[0] = gran[1] = 0.0;
 
95
strcpy( selectex, "" );
 
96
doranges[0] = doranges[1] = 0;
 
97
axis[0] = 'x';
 
98
axis[1] = 'y';
 
99
strcpy( rangesepchar, "-" );
 
100
strcpy( showrange, "" );
 
101
strcpy( rangespec[0], "" );
 
102
strcpy( rangespec[1], "" );
 
103
axisset[0] = axisset[1] = 0; /* was axis1 or axis2 set explicitly - added 1/11/00 scg */
 
104
accumfield = -1;
 
105
 
 
106
 
 
107
/* get attributes.. */
 
108
first = 1;
 
109
while( 1 ) {
 
110
        line = getnextattr( first, attr, val, &lvp, &nt );
 
111
        if( line == NULL ) break;
 
112
        first = 0;
 
113
        lineval = &line[lvp];
 
114
 
 
115
        if( stricmp( attr, "datafield1" )==0 ) {
 
116
                field[0] = fref( val ) - 1;
 
117
                ndim = 1;
 
118
                }
 
119
        else if( stricmp( attr, "datafield2" )==0 ) {
 
120
                field[1] = fref( val ) - 1;
 
121
                ndim = 2;
 
122
                }
 
123
        else if( stricmp( attr, "accumfield" )==0 ) {
 
124
                accumfield = fref( val ) -1;
 
125
                }
 
126
        else if( stricmp( attr, "valuelist1" )==0 ) strcpy( valuelist[0], lineval );
 
127
        else if( stricmp( attr, "valuelist2" )==0 ) strcpy( valuelist[1], lineval );
 
128
        else if( stricmp( attr, "doranges1" )==0 ) {
 
129
                if( strnicmp( val, YESANS, 1 )==0 ) doranges[0] = 1;
 
130
                else doranges[0] = 0;
 
131
                }
 
132
        else if( stricmp( attr, "doranges2" )==0 ) {
 
133
                if( strnicmp( val, YESANS, 1 )==0 ) doranges[1] = 1;
 
134
                else doranges[1] = 0;
 
135
                }
 
136
        else if( stricmp( attr, "showrangelowonly" )==0 ) { 
 
137
                if( strnicmp( val, YESANS, 1 )==0 ) strcpy( showrange, "low" );
 
138
                }
 
139
        else if( stricmp( attr, "showrange" )==0 ) strcpy( showrange, val );
 
140
        else if( stricmp( attr, "rangesepchar" )==0 ) strcpy( rangesepchar, val );
 
141
        else if( stricmp( attr, "order1" )==0 ) {
 
142
                if( strnicmp( val, "mag", 3 )==0 ) ordering[0] = 'm';
 
143
                else if( strnicmp( val, "rev", 3 )==0 ) ordering[0] = 'r';
 
144
                else if( strnicmp( val, "nat", 3 )==0 ) ordering[0] = 'n';
 
145
                else if( stricmp( val, "none" )==0 ) ordering[0] = '0';
 
146
                }
 
147
        else if( stricmp( attr, "ordering2" )==0 ) {
 
148
                if( strnicmp( val, "mag", 3 ) == 0 ) ordering[1] = 'm';
 
149
                else if( strnicmp( val, "rev", 3 ) == 0 ) ordering[1] = 'r';
 
150
                else if( strnicmp( val, "nat", 3 ) == 0 ) ordering[1] = 'n';
 
151
                else if( stricmp( val, "none" ) == 0 ) ordering[1] = '0';
 
152
                }
 
153
 
 
154
        else if( stricmp( attr, "percents" )==0 ) {
 
155
                if( strnicmp( val, YESANS, 1 )==0 ) dopercents = 1;
 
156
                else dopercents = 0;
 
157
                }
 
158
        else if( stricmp( attr, "savetable" )==0 ) strcpy( savetable, val );
 
159
 
 
160
        else if( stricmp( attr, "select" )==0 ) strcpy( selectex, lineval );
 
161
 
 
162
        else if( stricmp( attr, "axis1" )==0 ) {
 
163
                axis[0] = tolower(val[0]);
 
164
                axisset[0] = 1;
 
165
                }
 
166
        else if( stricmp( attr, "axis2" )==0 ) {
 
167
                axis[1] = tolower(val[0]);
 
168
                axisset[1] = 1;
 
169
                }
 
170
 
 
171
        else if( stricmp( attr, "rangespec1" )==0 ) strcpy( rangespec[0], lineval );
 
172
        else if( stricmp( attr, "rangespec2" )==0 ) strcpy( rangespec[1], lineval );
 
173
 
 
174
        else Eerr( 1, "tabulate attribute not recognized", attr );
 
175
        }
 
176
 
 
177
 
 
178
/* overrides and degenerate cases */
 
179
/* -------------------------- */
 
180
if( field[0] < 0 ) return( Eerr( 4984, "datafield1 must be specified", "" ) );
 
181
 
 
182
if( ordering[0] == '?' ) {
 
183
        if( valuelist[0][0] != '\0' ) ordering[0] = '0';
 
184
        else ordering[0] = 'n';
 
185
        }
 
186
if( ordering[1] == '?' ) {
 
187
        if( valuelist[1][0] != '\0' ) ordering[1] = '0';
 
188
        else ordering[1] = 'n';
 
189
        }
 
190
 
 
191
 
 
192
 
 
193
/* now do the computation work.. */
 
194
/* -------------------------- */
 
195
 
 
196
if( savetable[0] != '\0' ) {
 
197
        if( stricmp( savetable, "stdout" )==0 ) sfp = stdout;
 
198
        else if( stricmp( savetable, "stderr" )==0 ) sfp = stderr;
 
199
        else sfp = fopen( savetable, "w" );  /* diagnostics */
 
200
        if( sfp == NULL ) sfp = Diagfp;
 
201
        }
 
202
 
 
203
 
 
204
/* initialize tables */
 
205
grantotal = 0.0;
 
206
for( i = 0; i < MAXROWS; i++ ) {
 
207
        if( i < 2 )nlist[i] = 0;
 
208
        for( j = 0; j < MAXCOLS; j++ ) { tab[i][j] = 0.0; if( i < 2 ) { total[i][j] = 0.0; } }
 
209
        order[0][i] = order[1][i] = i;
 
210
        }
 
211
 
 
212
/* get value list (a comma or space delimited list of values; output distribution will
 
213
   be for only these values (in the order given?) */
 
214
for( j = 0; j < ndim; j++ ) { /* for all dimensions (1 or 2).. */
 
215
        if( valuelist[j][0] != '\0' ) {
 
216
            int ix;
 
217
            for( i = 0, ix = 0;  ; i++ ) {
 
218
                if( GL_getseg( tmp, valuelist[j], &ix, " ," ) ) break;
 
219
                strcpy( list[j][i], tmp ); 
 
220
                nlist[j]++;
 
221
                if( doranges[j] ) { /* find lowv and hiv */
 
222
                        if( i >= MAXBINS ) return( Eerr( 9285, "Sorry, max number of bins exceeded","" ) );
 
223
                        ixx = 0;
 
224
                        GL_getseg( lowval, tmp, &ixx, rangesepchar );
 
225
                        strcpy( hival, &tmp[ixx] );
 
226
                        if( stricmp( lowval, "c" )==0 && i > 0 ) lowv[i] = hiv[i-1]; /* contiguous*/
 
227
                        else lowv[i] = Econv( axis[j], lowval );
 
228
                        if( Econv_error( ) ) {   /* a non-conformant value.. */
 
229
                                lowv[i] = PLHUGE; /* so that we know to compare 
 
230
                                                        to value for non-numerics */
 
231
                                hiv[i] = NEGHUGE;
 
232
                                }
 
233
                        else    {
 
234
                                hiv[i] = Econv( axis[j], hival );
 
235
                                Euprint( lowval, axis[j], lowv[i], "" );
 
236
                                if( tolower(showrange[0]) == 'l' ) strcpy( list[j][i], lowval );
 
237
                                else if( tolower(showrange[0]) == 'a' ) Euprint( list[j][i], axis[j], (lowv[i]+hiv[i])/2.0, "" );
 
238
 
 
239
                                else sprintf( list[j][i], "%s%s%s", lowval, rangesepchar, hival );
 
240
                                }
 
241
                        }
 
242
                }
 
243
            valuesgiven[j] = 1;
 
244
            }
 
245
 
 
246
        /* automatic bins */
 
247
        if( rangespec[j][0] != '\0' ) {
 
248
                double binsiz, hilimit, rw;
 
249
                doranges[j] = 1; /* implied */
 
250
                nt = sscanf( rangespec[j], "%s %lf %s", lowval, &binsiz, hival );
 
251
                if( nt < 2 || nt > 3 ) return( Eerr( 2740, "2 or 3 values expected in rangespec", 
 
252
                        rangespec[j] ) );
 
253
                rw = Econv( axis[j], lowval );
 
254
                if( Econv_error() ) return( Eerr( 2750, "warning: error on rangespec lowlimit", rangespec[j] ) );
 
255
                if( nt == 3 ) {
 
256
                        hilimit = Econv(axis[j], hival );
 
257
                        if( Econv_error() ) return( Eerr( 2750, "warning: error on rangespec hilimit", rangespec[j] ) );
 
258
                        }
 
259
                else if( nt == 2 ) {
 
260
                        if( !scalebeenset() ) return( Eerr( 2479, "rangespec must have 3 values since scaleing has not yet been set", "" ));
 
261
                        hilimit = Elimit( axis[j], 'h', 's' );
 
262
                        }
 
263
                for( i = 0; i < MAXBINS ; i++ ) {
 
264
                        lowv[i] = rw;
 
265
                        rw += binsiz;
 
266
                        hiv[i] = rw;
 
267
                        Euprint( lowval, axis[j], lowv[i], "" );
 
268
                        Euprint( hival, axis[j], hiv[i], "" );
 
269
                        if( tolower(showrange[0]) == 'l' ) strcpy( list[j][i], lowval );
 
270
                        else if( tolower(showrange[0]) == 'a' ) Euprint( list[j][i], axis[j], (lowv[i]+hiv[i])/2.0, "" );
 
271
                        else sprintf( list[j][i], "%s%s%s", lowval, rangesepchar, hival );
 
272
                        nlist[j]++;
 
273
                        if( rw > hilimit ) break;
 
274
                        }
 
275
                valuesgiven[j] = 1;
 
276
                }
 
277
 
 
278
        if( doranges[j] && !valuesgiven[j] ) 
 
279
                return( Eerr( 2052, "A values list must be given when doing ranges.", "" ));
 
280
        }
 
281
 
 
282
/* make a description string */
 
283
if( ndim == 1 ) sprintf( buf, "// 1-way distribution on field %d %s", field[0]+1, selectex ); 
 
284
if( ndim == 2 ) sprintf( buf, "// 2-way distribution on field %d (down) by field %d (across) %s", 
 
285
        field[0]+1, field[1]+1, selectex ); 
 
286
/* set a DMS variable to the description? */
 
287
if( savetable[0] != '\0' ) fprintf( sfp, "%s\n", buf );
 
288
 
 
289
 
 
290
/* process from data already read in earlier.. */
 
291
Dsel = 0;
 
292
 
 
293
if( Nrecords[Dsel] < 1 ) return( Eerr( 32, "No data has been read yet.", "" ) );
 
294
 
 
295
/* process input data.. */
 
296
ix = 0;
 
297
for( irow = 0; irow < Nrecords[Dsel]; irow++ ) {
 
298
 
 
299
        if( selectex[0] != '\0' ) { /* process against selection condition if any.. */
 
300
                stat = do_select( selectex, irow, &result );
 
301
                if( stat != 0 ) { Eerr( stat, "Select error", selectex ); continue; }
 
302
                if( result == 0 ) continue; /* reject */
 
303
                }
 
304
 
 
305
        /* for each item requested (1 or 2) */
 
306
        for( i = 0; i < ndim; i++ ) {
 
307
 
 
308
                /* strcpy( val, data[ field[i] ] ); */
 
309
                strcpy( val, da( irow, field[i] ));
 
310
                val[WORDLEN-1] = '\0';
 
311
 
 
312
 
 
313
 
 
314
                /****  if ranges have not been pre defined... */
 
315
                if( !doranges[i] ) { /* classify by value */
 
316
 
 
317
                        /**** a. if axis has been set, use special units, Econv, etc. */
 
318
                        if( axisset[i] ) { /* code copied from below; uses fval instead of val */
 
319
                                fval = Econv( axis[i], val );
 
320
 
 
321
                                /* see if already encountered (compare fval) */
 
322
                                for( j = 0; j < nlist[i]; j++ ) 
 
323
                                        if( GL_close_to( fval, atof(list[i][j]), 0.001 ))
 
324
                                                { select[i] = j; break; }
 
325
 
 
326
                                if( j == nlist[i] && valuesgiven[i] ) goto NEXT; 
 
327
 
 
328
                                /* otherwise, add the internal representation to list */
 
329
                                if( j == nlist[i] ) {
 
330
                                        if( (i == 0 && nlist[i] >= MAXROWS) || (i == 1 && nlist[i] >= MAXCOLS) ) 
 
331
                                            fprintf( Errfp, "tabulate warning, sorry, table capacity exceeded, skipping %s\n", val );
 
332
                                        else    {
 
333
                                                if( !Econv_error()) 
 
334
                                                        sprintf( list[i][j], "%f", fval );
 
335
                                                else strcpy( list[i][j], val );
 
336
                                                select[i] = j; 
 
337
                                                nlist[i] ++; 
 
338
                                                }
 
339
                                        }
 
340
                                }
 
341
                        
 
342
 
 
343
                        /**** b. axis has not been set, dont use Econv */
 
344
                        else    {
 
345
 
 
346
                                /* see if we've already encountered current val */
 
347
                                for( j = 0; j < nlist[i]; j++ ) if( strcmp( val, list[i][j] )== 0 ) 
 
348
                                                                        { select[i] = j; break; }
 
349
        
 
350
                                if( j == nlist[i] && valuesgiven[i] ) goto NEXT; /* not in value list-
 
351
                                                                                   discard */
 
352
        
 
353
                                /* add it to list */
 
354
                                if( j == nlist[i] ) { 
 
355
                                        if( (i == 0 && nlist[i] >= MAXROWS) || (i == 1 && nlist[i] >= MAXCOLS) ) 
 
356
                                                fprintf( Errfp, "tabulate warning, sorry, table capacity exceeded, skipping %s\n", val );
 
357
                                        else    {
 
358
                                                strcpy( list[i][j], val ); 
 
359
                                                select[i] = j; 
 
360
                                                nlist[i] ++; 
 
361
                                                }
 
362
                                        }
 
363
                                }
 
364
                        }
 
365
 
 
366
 
 
367
                /**** if ranges have been defined.. */
 
368
                else if( doranges[i] ) {
 
369
                        fval = Econv( axis[i], val );
 
370
 
 
371
                        /* go through list backwards so that boundary values are 
 
372
                           put into higher category.. */
 
373
                        for( j = nlist[i] - 1; j >= 0; j-- ) {
 
374
                                if( lowv[j] >= PLHUGE && hiv[j] <= NEGHUGE ) {
 
375
                                        if( strcmp( list[i][j], val )==0 ) {
 
376
                                                select[i] = j;
 
377
                                                break;
 
378
                                                }
 
379
                                        }
 
380
                                if( Econv_error() ) continue;
 
381
                                if( fval >= lowv[j] && fval <= hiv[j] ) {
 
382
                                        select[i] = j;
 
383
                                        break;
 
384
                                        }
 
385
                                }
 
386
                        /* if( j == nlist[i] ) goto NEXT; */ /* not in value list- discard */
 
387
                        if( j < 0 ) goto NEXT;  /* not in value list- discard */
 
388
                        }
 
389
 
 
390
                }
 
391
        if( accumfield >= 0 ) inc = atof( da( irow, accumfield ) );
 
392
        else inc = 1.0;
 
393
 
 
394
        if( ndim == 1 ) { 
 
395
                tab[ 0 ][ select[ 0 ] ] += inc; 
 
396
                total[0][0] += inc; 
 
397
                }
 
398
        else if( ndim == 2 ) { 
 
399
                ( tab[ select[0] ][ select[1] ] ) += inc; 
 
400
                total[0][select[0]] += inc; 
 
401
                total[1][select[1]] += inc; 
 
402
                grantotal += inc; 
 
403
                }
 
404
 
 
405
        NEXT: continue;
 
406
        }
 
407
 
 
408
 
 
409
 
 
410
 
 
411
/* put rows/cols in some kind of order */
 
412
if( ndim == 1 ) {
 
413
        if( ordering[0] == 'n' ) fsort( list[0], nlist[0], order[0] );
 
414
        else if( ordering[0] == 'm' ) freqsort(tab[0], nlist[0], order[0], 0 );
 
415
        else if( ordering[0] == 'r' ) freqsort(tab[0], nlist[0], order[0], 1 );
 
416
        }
 
417
else if( ndim == 2 ) {
 
418
        if( ordering[0] == 'n' ) fsort( list[0], nlist[0], order[0] );
 
419
        else if( ordering[0] == 'm' ) freqsort(tab[0], nlist[0], order[0], 0 );
 
420
        else if( ordering[0] == 'r' ) freqsort(tab[0], nlist[0], order[0], 1 );
 
421
 
 
422
        if( ordering[1] == 'n' ) fsort( list[1], nlist[1], order[1] );
 
423
        else if( ordering[1] == 'm' ) freqsort(total[1], nlist[1], order[1], 0 );
 
424
        else if( ordering[1] == 'r' ) freqsort(total[1], nlist[1], order[1], 1 );
 
425
        }
 
426
 
 
427
 
 
428
/* --------------------- */
 
429
/* generate the results */
 
430
/* --------------------- */
 
431
 
 
432
Dsel = 1;
 
433
 
 
434
davail = Dsize;
 
435
ND[Dsel] = 0;
 
436
StartD[Dsel] = ND[0];
 
437
curd = StartD[Dsel];
 
438
 
 
439
 
 
440
/* ------------------ */
 
441
/* for 1-way tables.. */
 
442
/* ------------------ */
 
443
if( ndim == 1 ) {
 
444
 
 
445
        /* set PL data array dimensions for slot 2 */
 
446
        Nfields[Dsel] = 2;
 
447
        Nrecords[Dsel] = nlist[0];
 
448
 
 
449
        sprintf( buf, "//%-20s    N", "Value" );
 
450
        if( dopercents ) {
 
451
                sprintf( buf, "%s  Pct", buf );
 
452
                Nfields[Dsel] = 3;
 
453
                }
 
454
        if( savetable[0] != '\0' ) fprintf( sfp, "%s\n\n", buf );
 
455
 
 
456
 
 
457
        /* do output lines.. */
 
458
        for( i = 0; i < nlist[0]; i++ ) {
 
459
                if( !doranges[0] && axisset[0] ) 
 
460
                        Euprint( tag, axis[0], atof(list[0][order[0][i]]), "" );
 
461
                else strcpy( tag, list[0][order[0][i]] );
 
462
 
 
463
                sprintf( buf, "%-20s  %5.0f", tag, tab[0][order[0][i]] );
 
464
                if( dopercents ) sprintf( buf, "%s  %3.0f", buf, 
 
465
                        (tab[0][order[0][i]])/(total[0][0]+0.0001)*100  );
 
466
                if( savetable[0] != '\0' ) fprintf( sfp, " %s\n", buf );
 
467
                
 
468
                /* put the results into the PL data array.. */
 
469
 
 
470
                /* label */
 
471
                catitem( tag, &curd, &davail );
 
472
 
 
473
                /* n */
 
474
                sprintf( buf, "%g", tab[0][order[0][i]] ); 
 
475
                catitem( buf, &curd, &davail );
 
476
 
 
477
                if( dopercents ) {
 
478
                        sprintf( buf, "%g", (double)(tab[0][order[0][i]])/(total[0][0]+0.0001)*100  );
 
479
                        catitem( buf, &curd, &davail );
 
480
                        }
 
481
                }
 
482
        ND[Dsel] = curd - StartD[Dsel];
 
483
 
 
484
        /* lastly, do total line */
 
485
        sprintf( buf, "%-20s  %5.0f", "//Total:", total[0][0] );
 
486
        if( dopercents ) sprintf( buf, "%s  100", buf );
 
487
 
 
488
        /* Use DMS variable here? */
 
489
        if( savetable[0] != '\0' ) fprintf( sfp, " %s\n", buf );
 
490
        }
 
491
 
 
492
 
 
493
/* ------------------ */
 
494
/* for 2-way tables.. */
 
495
/* ------------------ */
 
496
else if( ndim == 2 ) { 
 
497
 
 
498
        /* set PL data array dimensions for slot 2 */
 
499
        if( dopercents ) Nfields[Dsel] = ((nlist[1]+1)*2) + 1;
 
500
        else Nfields[Dsel] = (nlist[1]+1) + 1; /* label, cols, rowtotal */
 
501
        Nrecords[Dsel] = nlist[0];
 
502
 
 
503
 
 
504
        /* build header */
 
505
        sprintf( buf, "//%-20s", "" );
 
506
        strcpy( fieldnamelist, "rowname" );
 
507
        for( i = 0; i < nlist[1]; i++ ) {
 
508
                if( !doranges[1] && axisset[1] ) 
 
509
                        Euprint( tag, axis[1], atof(list[1][order[1][i]]), "" );
 
510
                else strcpy( tag, list[1][order[1][i]] );
 
511
 
 
512
                sprintf( buf, "%s%6s  ", buf, tag );
 
513
                if( dopercents ) sprintf( buf, "%s%s", buf, " Pct    " );
 
514
 
 
515
                /* set up the column tags as data field names.. */
 
516
                strcat( fieldnamelist, "," );
 
517
                strcat( fieldnamelist, tag );
 
518
                }
 
519
 
 
520
        if( fieldnamelist[0] != '\0' ) {
 
521
                definefieldnames( fieldnamelist );
 
522
                fprintf( Diagfp, "proc tabulate: field names are now: %s\n", fieldnamelist );
 
523
                }
 
524
         
 
525
        sprintf( buf, "%s%s  ", buf, "  Total" );
 
526
        if( dopercents ) sprintf( buf, "%s%s", buf, " Pct    " );
 
527
        if( savetable[0] != '\0' ) fprintf( sfp, "%s\n\n", buf );
 
528
 
 
529
        /* do output lines.. */
 
530
        for( j = 0; j < nlist[0]; j++ ) {
 
531
                if( !doranges[0] && axisset[0] ) 
 
532
                        Euprint( tag, axis[0], atof(list[0][order[0][j]]), "" );
 
533
                else strcpy( tag, list[0][order[0][j]] );
 
534
 
 
535
                sprintf( buf, "%-20s", tag ); 
 
536
 
 
537
                /* put label into PL data */
 
538
                catitem( tag, &curd, &davail );
 
539
 
 
540
                for( i = 0; i < nlist[1]; i++ ) {
 
541
                        sprintf( buf, "%s %5.0f  ", buf, tab[order[0][j]][order[1][i]] ); 
 
542
 
 
543
                        /* n */
 
544
                        sprintf( numbuf, "%g", tab[order[0][j]] [order[1][i]] );
 
545
                        catitem( numbuf, &curd, &davail );
 
546
 
 
547
                        if( dopercents ) {
 
548
                                sprintf( buf, "%s %3.0f    ", buf, 
 
549
                                  (double)(tab[order[0][j]][order[1][i]])/
 
550
                                        (total[1][order[1][i]]+0.00001) * 100 ); 
 
551
 
 
552
                                sprintf( numbuf, "%g", 
 
553
                                  (double)(tab[order[0][j]][order[1][i]])/
 
554
                                        (total[1][order[1][i]]+0.00001) * 100 ); 
 
555
                                catitem( numbuf, &curd, &davail );
 
556
                                }
 
557
                        }
 
558
                
 
559
                sprintf( buf, "%s%5.0f  ", buf, total[0][order[0][j]] );
 
560
                /* row total */
 
561
                sprintf( numbuf, "%g", total[0][order[0][j]] );
 
562
                catitem( numbuf, &curd, &davail );
 
563
 
 
564
                if( dopercents ) {
 
565
                        sprintf( buf, "%s   %3.0f", buf, 
 
566
                          (double)(total[0][order[0][j]]) / (grantotal+0.00001) * 100 ); 
 
567
                        sprintf( numbuf, "%g", 
 
568
                          (double)(total[0][order[0][j]]) / (grantotal+0.00001) * 100 ); 
 
569
                        catitem( numbuf, &curd, &davail );
 
570
                        }
 
571
                
 
572
                if( savetable[0] != '\0' ) fprintf( sfp, " %s\n", buf );
 
573
                }
 
574
        ND[Dsel] = curd - StartD[Dsel];
 
575
 
 
576
        /* lastly, do total line.. */
 
577
        sprintf( buf, "%-19s", "//Total:" );
 
578
        for( i = 0; i < nlist[1]; i++ ) {
 
579
                sprintf( buf, "%s  %5.0f ", buf, total[1][order[1][i]] );
 
580
                if( dopercents ) sprintf( buf, "%s  100   ", buf ); 
 
581
                }
 
582
        sprintf( buf, "%s %5.0f", buf, grantotal );
 
583
        if( dopercents ) sprintf( buf, "%s     100", buf );
 
584
        /* set DMS var here?? */
 
585
        if( savetable[0] != '\0' ) fprintf( sfp, " %s\n", buf );
 
586
        }
 
587
 
 
588
 
 
589
/* fprintf( Diagfp, "After Xtab:     ND=%d Nrecords=%d Nfields=%d\n", 
 
590
        ND[Dsel], Nrecords[Dsel], Nfields[Dsel] ); */
 
591
 
 
592
setintvar( "NRECORDS", Nrecords[Dsel] );
 
593
setintvar( "NFIELDS", Nfields[Dsel] );
 
594
 
 
595
/* for( i = 0; i < Nrecords[Dsel]; i++ ) {
 
596
 *      for( j = 0; j < Nfields[Dsel]; j++ ) fprintf( Diagfp, "|%s| ", da(i,j) );
 
597
 *      fprintf( Diagfp, "\n" );
 
598
 *      }
 
599
 */
 
600
 
 
601
 
 
602
return( 0 );
 
603
}
 
604
 
 
605
 
 
606
 
 
607
/* ================ */
 
608
/* sort bin names numerically if all numeric, alphabetically otherwise */
 
609
static int
 
610
fsort( data, nd, order )
 
611
char data[][WORDLEN];
 
612
int nd, order[];
 
613
{
 
614
int i, j, used[MAXROWS], mincell, first, allnum, foo, idiff;
 
615
double atof(), diff;
 
616
 
 
617
allnum = YES;
 
618
for( i = 0; i < nd; i++ ) { 
 
619
        used[i] = 0; 
 
620
        if( atof( data[i] ) < -31999) strcpy( data[i], "-31000" );
 
621
        if( !GL_goodnum( data[i], &foo )) { allnum = NO; }
 
622
        }
 
623
 
 
624
for( i = 0; i < nd; i++ ) {
 
625
        first = YES;
 
626
        for( j = 0; j < nd; j++ ) {
 
627
                if( used[j] ) continue;
 
628
                if( first ) { mincell = j; first = NO; }
 
629
                if( allnum ) {
 
630
                        diff = atof( data[j] ) - atof( data[mincell] );
 
631
                        if( diff <= 0.0 ) mincell = j;
 
632
                        }
 
633
                else    {
 
634
                        idiff = (strcmp( data[j], data[mincell] ));
 
635
                        if( idiff <= 0 ) mincell = j; 
 
636
                        }
 
637
                }
 
638
        order[i] = mincell;
 
639
        used[mincell] = 1;
 
640
        }
 
641
}
 
642
 
 
643
/* ================ */
 
644
static int
 
645
freqsort( counts, nd, order, reverse )
 
646
double counts[];
 
647
int nd, order[], reverse;
 
648
{
 
649
int i, j, used[MAXROWS], firstcell, first, diff;
 
650
 
 
651
for( i = 0; i < nd; i++ )
 
652
        used[i] = NO;
 
653
 
 
654
for( i = 0; i < nd; i++ ) {
 
655
        first = YES;
 
656
        for( j = 0; j < nd; j++ ) {
 
657
                if( used[j] ) continue;
 
658
                if( first ) { firstcell = j; first = NO; }
 
659
                diff = counts[j] - counts[firstcell];
 
660
                switch (reverse)
 
661
                    {
 
662
                    case YES: if (diff >= 0) firstcell = j; break;
 
663
                    case NO:  if (diff <= 0) firstcell = j; break;
 
664
                    }
 
665
                }
 
666
        order[i] = firstcell;
 
667
        used[firstcell] = 1;
 
668
        }
 
669
}