home *** CD-ROM | disk | FTP | other *** search
- /*
- * 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 );
- }
-