|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T g
Length: 4186 (0x105a)
Types: TextFile
Names: »group.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦this⟧ »EUUGD11/euug-87hel/sec1/graph/group.c«
/*
* Copyright (C) 1986 Alan Kent
*
* Permission is granted to freely distribute part or
* all of this code as long as it is not for profit
* and this message is retained in the code.
*
* No resposibility is taken for any damage or incorect
* results this program generates.
*
*/
#include <stdio.h>
#include "graph.h"
#include "y.tab.h"
/*#define DEBUG(parms) fprintf parms*/
#define DEBUG(parms)
/* This produces a 3 column table: $1 = lower bound of range, $2 = upper */
/* bound of range, $3 = result for range */
extern table_st *new_table ();
extern double ceil ();
extern tnode_st *tab_node ();
extern double call_var_fun ();
extern double min_fun ();
extern double max_fun ();
table_st *
group ( table , range , interval , fun_name )
table_st *table; /* table of data to group */
range_st *range; /* contains min,max and interval sizes */
int_st *interval;
char *fun_name; /* expression to evaluate per interval */
{
double low , high;
double value;
int i , intv , num_intervals , new_index;
table_st *newtab;
table_st *temptab;
int intv_from , intv_to;
range_st st_range;
parm_st parm;
if ( interval == NULL )
abort ( "code error for group(): NULL interval pointer" );
if ( num_cols ( table ) != 2 )
abort ( "GROUP requires two column tables" );
if ( range == NULL ) {
range = &st_range;
st_range.min = min_fun ( table , 0 , table->size );
st_range.max = max_fun ( table , 0 , table->size );
}
if ( interval->int_type == INUMINT ) {
num_intervals = (int) ceil ( interval->value );
}
else {
num_intervals = 0;
for ( low = range->min; low <= range->max; low += interval->value )
num_intervals++;
}
newtab = new_table ( 3 , num_intervals );
DEBUG((stderr,"min %f, max %f, num_int %d\n",range->min,range->max,num_intervals));
/* now scan through each interval and determine range from table */
/* that lie within that interval */
intv_to = 0;
while ( intv_to < table->size && table->data[intv_to] < range->min )
intv_to++;
intv_to--;
intv = 0;
new_index = 0;
low = range->min;
high = range->min;
while ( intv < num_intervals ) {
if ( interval->int_type == INUMINT )
high = range->min + ( ((double)intv + 1)
* ( range->max - range->min ) / (double)num_intervals );
else
high += interval->value;
DEBUG((stderr,"intv %d of %d, low = %f, high = %f\n",intv,num_intervals,low,high));
for ( i = intv_to + 1; i < table->size; i++ ) {
value = table->data[i];
if ( value < low )
abort ( "table must be sorted on group (first) field for GROUP" );
/* on last interval, include upper bound */
if ( intv + 1 == num_intervals ) {
if ( value > high )
break;
}
else {
if ( value >= high )
break;
}
}
intv_from = intv_to + 1;
intv_to = i - 1;
/* only do something if the interval contains data */
if ( intv_to > intv_from ) {
DEBUG((stderr,"intv_to %d > intv_from %d\n",intv_to,intv_from));
if ( interval->int_type == INUMINT )
value = range->min + ( ((double)(intv+1))
* ( range->max - range->min ) / (double)num_intervals );
else
value = ((double)(intv+1)) * interval->value;
newtab->next->data[ new_index ] = value;
if ( interval->int_type == INUMINT )
value = range->min + ( ((double)intv)
* ( range->max - range->min ) / (double)num_intervals );
else
value = ((double)intv) * interval->value;
newtab->data[ new_index ] = value;
temptab = new_table ( 1 , intv_to - intv_from + 1 );
for ( i = 0; i < temptab->size; i++ )
temptab->data[i] = table->next->data[ i + intv_from ];
parm.next = NULL;
parm.parm_type = TABLE;
parm.tab_expr = tab_node ( TAB_CONST );
parm.tab_expr->table = temptab;
value = call_var_fun ( fun_name , &parm , NULL , 0 );
free_table ( temptab );
DEBUG((stderr,"Function returns %f\n",value));
newtab->next->next->data[ new_index ] = value;
new_index++;
}
else
DEBUG((stderr,"intv_from %d <= intv_to %d\n",intv_from,intv_to));
intv++;
low = high;
}
newtab->size = new_index;
free_table ( table );
return ( newtab );
}