home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume8 / graph+ / part03 / group.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-03-01  |  4.1 KB  |  155 lines

  1. /*
  2.  * Copyright (C) 1986   Alan Kent
  3.  *
  4.  * Permission is granted to freely distribute part or
  5.  * all of this code as long as it is not for profit
  6.  * and this message is retained in the code.
  7.  *
  8.  * No resposibility is taken for any damage or incorect
  9.  * results this program generates.
  10.  * 
  11.  */
  12.  
  13.  
  14. #include <stdio.h>
  15. #include "graph.h"
  16. #include "y.tab.h"
  17.  
  18.  
  19. /*#define DEBUG(parms)    fprintf parms*/
  20. #define DEBUG(parms)
  21.  
  22.  
  23. /* This produces a 3 column table: $1 = lower bound of range, $2 = upper */
  24. /* bound of range, $3 = result for range */
  25.  
  26.  
  27. extern table_st *new_table ();
  28. extern double ceil ();
  29. extern tnode_st *tab_node ();
  30. extern double call_var_fun ();
  31. extern double min_fun ();
  32. extern double max_fun ();
  33.  
  34.  
  35.  
  36. table_st *
  37. group ( table , range , interval , fun_name )
  38. table_st *table;    /* table of data to group */
  39. range_st *range;    /* contains min,max and interval sizes */
  40. int_st *interval;
  41. char *fun_name;        /* expression to evaluate per interval */
  42. {
  43.     double low , high;
  44.     double value;
  45.     int i , intv , num_intervals , new_index;
  46.     table_st *newtab;
  47.     table_st *temptab;
  48.     int intv_from , intv_to;
  49.     range_st st_range;
  50.     parm_st parm;
  51.  
  52.  
  53.     if ( interval == NULL )
  54.     abort ( "code error for group(): NULL interval pointer" );
  55.     if ( num_cols ( table ) != 2 )
  56.     abort ( "GROUP requires two column tables" );
  57.  
  58.     if ( range == NULL ) {
  59.     range = &st_range;
  60.     st_range.min = min_fun ( table , 0 , table->size );
  61.     st_range.max = max_fun ( table , 0 , table->size );
  62.     }
  63.  
  64.     if ( interval->int_type == INUMINT ) {
  65.     num_intervals = (int) ceil ( interval->value );
  66.     }
  67.     else {
  68.     num_intervals = 0;
  69.     for ( low = range->min; low <= range->max; low += interval->value )
  70.         num_intervals++;
  71.     }
  72.     newtab = new_table ( 3 , num_intervals );
  73.  
  74. DEBUG((stderr,"min %f, max %f, num_int %d\n",range->min,range->max,num_intervals));
  75.  
  76.     /* now scan through each interval and determine range from table */
  77.     /* that lie within that interval */
  78.  
  79.     intv_to = 0;
  80.     while ( intv_to < table->size  &&  table->data[intv_to] < range->min )
  81.     intv_to++;
  82.     intv_to--;
  83.     intv = 0;
  84.     new_index = 0;
  85.     low = range->min;
  86.     high = range->min;
  87.     while ( intv < num_intervals ) {
  88.     if ( interval->int_type == INUMINT )
  89.         high = range->min + ( ((double)intv + 1)
  90.         * ( range->max - range->min ) / (double)num_intervals );
  91.     else
  92.         high += interval->value;
  93. DEBUG((stderr,"intv %d of %d, low = %f, high = %f\n",intv,num_intervals,low,high));
  94.     for ( i = intv_to + 1; i < table->size; i++ ) {
  95.         value = table->data[i];
  96.         if ( value < low )
  97.         abort ( "table must be sorted on group (first) field for GROUP" );
  98.         /* on last interval, include upper bound */
  99.         if ( intv + 1 == num_intervals ) {
  100.         if ( value > high )
  101.             break;
  102.         }
  103.         else {
  104.         if ( value >= high )
  105.             break;
  106.         }
  107.     }
  108.     intv_from = intv_to + 1;
  109.     intv_to = i - 1;
  110.  
  111.     /* only do something if the interval contains data */
  112.  
  113.     if ( intv_to > intv_from ) {
  114.  
  115. DEBUG((stderr,"intv_to %d > intv_from %d\n",intv_to,intv_from));
  116.  
  117.         if ( interval->int_type == INUMINT )
  118.         value = range->min + ( ((double)(intv+1))
  119.             * ( range->max - range->min ) / (double)num_intervals );
  120.         else
  121.         value = ((double)(intv+1)) * interval->value;
  122.         newtab->next->data[ new_index ] = value;
  123.  
  124.         if ( interval->int_type == INUMINT )
  125.         value = range->min + ( ((double)intv)
  126.             * ( range->max - range->min ) / (double)num_intervals );
  127.         else
  128.         value = ((double)intv) * interval->value;
  129.         newtab->data[ new_index ] = value;
  130.  
  131.         temptab = new_table ( 1 , intv_to - intv_from + 1 );
  132.         for ( i = 0; i < temptab->size; i++ )
  133.         temptab->data[i] = table->next->data[ i + intv_from ];
  134.         parm.next = NULL;
  135.         parm.parm_type = TABLE;
  136.         parm.tab_expr = tab_node ( TAB_CONST );
  137.         parm.tab_expr->table = temptab;
  138.         value = call_var_fun ( fun_name , &parm , NULL , 0 );
  139.         free_table ( temptab );
  140. DEBUG((stderr,"Function returns %f\n",value));
  141.  
  142.         newtab->next->next->data[ new_index ] = value;
  143.  
  144.         new_index++;
  145.     }
  146. else
  147. DEBUG((stderr,"intv_from %d <= intv_to %d\n",intv_from,intv_to));
  148.     intv++;
  149.     low = high;
  150.     }
  151.     newtab->size = new_index;
  152.     free_table ( table );
  153.     return ( newtab );
  154. }
  155.