summaryrefslogtreecommitdiffstats
path: root/funtools/funtest/group.calc
diff options
context:
space:
mode:
authorWilliam Joye <wjoye@cfa.harvard.edu>2016-10-25 20:57:49 (GMT)
committerWilliam Joye <wjoye@cfa.harvard.edu>2016-10-25 20:57:49 (GMT)
commitd1c4bf158203c4e8ec29fdeb83fd311e36320885 (patch)
tree15874534e282f67505ce4af5ba805a1ff70ec43e /funtools/funtest/group.calc
parente19a18e035dc4d0e8e215f9b452bb9ef6f58b9d7 (diff)
parent339420dd5dd874c41f6bab5808291fb4036dd022 (diff)
downloadblt-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.calc125
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