|
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 ); }