diff options
author | William Joye <wjoye@cfa.harvard.edu> | 2016-10-25 20:57:49 (GMT) |
---|---|---|
committer | William Joye <wjoye@cfa.harvard.edu> | 2016-10-25 20:57:49 (GMT) |
commit | d1c4bf158203c4e8ec29fdeb83fd311e36320885 (patch) | |
tree | 15874534e282f67505ce4af5ba805a1ff70ec43e /funtools/funtest/group.calc | |
parent | e19a18e035dc4d0e8e215f9b452bb9ef6f58b9d7 (diff) | |
parent | 339420dd5dd874c41f6bab5808291fb4036dd022 (diff) | |
download | blt-d1c4bf158203c4e8ec29fdeb83fd311e36320885.zip blt-d1c4bf158203c4e8ec29fdeb83fd311e36320885.tar.gz blt-d1c4bf158203c4e8ec29fdeb83fd311e36320885.tar.bz2 |
Merge commit '339420dd5dd874c41f6bab5808291fb4036dd022' as 'funtools'
Diffstat (limited to 'funtools/funtest/group.calc')
-rw-r--r-- | funtools/funtest/group.calc | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/funtools/funtest/group.calc b/funtools/funtest/group.calc new file mode 100644 index 0000000..ef5543f --- /dev/null +++ b/funtools/funtest/group.calc @@ -0,0 +1,125 @@ +/* globals go before main */ +global +#define SAVEINC 100 +/* not available before 1.3.0b25 */ +#define I __i +/* our save record contains a funcalc row record and a place for raw data */ +typedef struct savestruct{ + RowRec row; + char *raw; +} *Save, SaveRec; + +/* qsort comparison routine -- reverse order of x */ +static int _Cmp(const void *s1, const void *s2) +{ + Save f1 = (Save)s1; + Save f2 = (Save)s2; + /* order flag */ + if( f1->row.x < f2->row.x ) + return -1; + if( f1->row.x > f2->row.x ) + return 1; + else + return 0; +} + +/* this is the heart of the algorithm */ +static void ProcessRows(Fun fun, Fun ofun, Save save, int nsave) +{ + int i; + /* sort rows */ + qsort(save, nsave, sizeof(SaveRec), _Cmp); + /* output rows in new order */ + for(i=0; i<nsave; i++){ + /* re-associate raw data with this row */ + FunInfoPut(fun, FUN_RAWBUF, &save[i].raw, 0); + /* write the row */ + FunTableRowPut(ofun, &save[i].row, 1, 0, NULL); + } +} +end + +/* locals go immediately after local variables in main */ +local + char *cptr=NULL; + char *rptr=NULL; + int i=0; + int group=0; + int rawsize=0; + int lastkey=0; + int maxsave=0; + int nsave=0; + Save save=NULL; +end + +/* execute this before we enter inner loop */ +before + /* get size of raw input record */ + FunInfoGet(fun, FUN_RAWSIZE, &rawsize, 0); +end + +/* MAIN ROW PROCESSING LOOP */ + +/* first time through, just seed last key */ +if( NROW == 0 ) lastkey=cur->key; + +/* save raw data for this set of rows */ +FunInfoGet(fun, FUN_RAWBUF, &rptr, 0); + +/* if this key starts a new group, process and output previous group */ +if( cur->key != lastkey ){ + /* process current group */ + ProcessRows(fun, ofun, save, nsave); + /* restore the current row pointers so we can process the next row */ + FunInfoPut(fun, FUN_RAWBUF, &rptr, 0); + /* reset number of keys in this group */ + nsave = 0; + /* got another group */ + group++; +} + +/* user manipulation */ +/* set values of a new column */ +cur->group:I = group; +/* manipulate one of the user columns */ +cur->x = -cur->x; + +/* save this row ... first make sure we have enough space */ +if( nsave >= maxsave ){ + maxsave += SAVEINC; + if( !save ) + save = xmalloc(maxsave*sizeof(SaveRec)); + else + save = xrealloc(save, maxsave*sizeof(SaveRec)); + /* clear what we just alloc'ed (wish realloc() would do this! */ + memset(save+((maxsave-SAVEINC)*sizeof(SaveRec)), 0, SAVEINC*sizeof(SaveRec)); +} +/* save the user part of this row */ +memcpy(&(save[nsave].row), cur, sizeof(RowRec)); +/* might have to allocate space for raw */ +if( !save[nsave].raw ) save[nsave].raw = xmalloc(rawsize); +/* save raw data for this row */ +memcpy(save[nsave].raw, rptr+(I*rawsize), rawsize); +/* saved another key in this group */ +nsave++; + +/* this key becomes last key */ +lastkey = cur->key; + +/* prevent funcalc from writing out the current record */ +continue; + +/* END OF INNER LOOP */ + +/* after we leave inner loop */ +after + /* process rows in last group */ + ProcessRows(fun, ofun, save, nsave); + /* restore raw buf pointer so FunClose can free it properly */ + FunInfoPut(fun, FUN_RAWBUF, &rptr, 0); + /* clean up saved data */ + for(i=0; i<maxsave; i++){ + if( save[i].raw ) xfree(save[i].raw); + } + if( save ) xfree(save); +end |