/[pspp]/pspp/src/aggregate.c
ViewVC logotype

Diff of /pspp/src/aggregate.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.32 by jmd, Wed Apr 13 10:09:59 2005 UTC revision 1.33 by blp, Tue Apr 26 06:32:02 2005 UTC
# Line 124  struct agr_proc Line 124  struct agr_proc
124      struct sort_criteria *sort;         /* Sort criteria. */      struct sort_criteria *sort;         /* Sort criteria. */
125      struct variable **break_vars;       /* Break variables. */      struct variable **break_vars;       /* Break variables. */
126      size_t break_var_cnt;               /* Number of break variables. */      size_t break_var_cnt;               /* Number of break variables. */
127      union value *prev_break;            /* Last values of break variables. */      struct ccase break_case;            /* Last values of break variables. */
128    
129      enum missing_treatment missing;     /* How to treat missing values. */      enum missing_treatment missing;     /* How to treat missing values. */
130      struct agr_var *agr_vars;           /* First aggregate variable. */      struct agr_var *agr_vars;           /* First aggregate variable. */
# Line 133  struct agr_proc Line 133  struct agr_proc
133      struct ccase agr_case;              /* Aggregate case for output. */      struct ccase agr_case;              /* Aggregate case for output. */
134    };    };
135    
136  static void initialize_aggregate_info (struct agr_proc *);  static void initialize_aggregate_info (struct agr_proc *,
137                                           const struct ccase *);
138    
139  /* Prototypes. */  /* Prototypes. */
140  static int parse_aggregate_functions (struct agr_proc *);  static int parse_aggregate_functions (struct agr_proc *);
# Line 164  cmd_aggregate (void) Line 165  cmd_aggregate (void)
165    
166    memset(&agr, 0 , sizeof (agr));    memset(&agr, 0 , sizeof (agr));
167    agr.missing = ITEMWISE;    agr.missing = ITEMWISE;
168      case_nullify (&agr.break_case);
169        
170    agr.dict = dict_create ();    agr.dict = dict_create ();
171    dict_set_label (agr.dict, dict_get_label (default_dict));    dict_set_label (agr.dict, dict_get_label (default_dict));
# Line 248  cmd_aggregate (void) Line 250  cmd_aggregate (void)
250    /* Initialize. */    /* Initialize. */
251    agr.case_cnt = 0;    agr.case_cnt = 0;
252    case_create (&agr.agr_case, dict_get_next_value_idx (agr.dict));    case_create (&agr.agr_case, dict_get_next_value_idx (agr.dict));
   initialize_aggregate_info (&agr);  
253    
254    /* Output to active file or external file? */    /* Output to active file or external file? */
255    if (out_file == NULL)    if (out_file == NULL)
# Line 655  agr_destroy (struct agr_proc *agr) Line 656  agr_destroy (struct agr_proc *agr)
656    if (agr->sort != NULL)    if (agr->sort != NULL)
657      sort_destroy_criteria (agr->sort);      sort_destroy_criteria (agr->sort);
658    free (agr->break_vars);    free (agr->break_vars);
659    free (agr->prev_break);    case_destroy (&agr->break_case);
660    for (iter = agr->agr_vars; iter; iter = next)    for (iter = agr->agr_vars; iter; iter = next)
661      {      {
662        next = iter->next;        next = iter->next;
# Line 693  static int Line 694  static int
694  aggregate_single_case (struct agr_proc *agr,  aggregate_single_case (struct agr_proc *agr,
695                         const struct ccase *input, struct ccase *output)                         const struct ccase *input, struct ccase *output)
696  {  {
697    /* The first case always begins a new break group.  We also need to    bool finished_group = false;
698       preserve the values of the case for later comparison. */    
699    if (agr->case_cnt++ == 0)    if (agr->case_cnt++ == 0)
700        initialize_aggregate_info (agr, input);
701      else if (case_compare (&agr->break_case, input,
702                             agr->break_vars, agr->break_var_cnt))
703      {      {
704        int n_elem = 0;        dump_aggregate_info (agr, output);
705                finished_group = true;
       {  
         int i;  
   
         for (i = 0; i < agr->break_var_cnt; i++)  
           n_elem += agr->break_vars[i]->nv;  
       }  
         
       agr->prev_break = xmalloc (sizeof *agr->prev_break * n_elem);  
   
       /* Copy INPUT into prev_break. */  
       {  
         union value *iter = agr->prev_break;  
         int i;  
706    
707          for (i = 0; i < agr->break_var_cnt; i++)        initialize_aggregate_info (agr, input);
           {  
             struct variable *v = agr->break_vars[i];  
               
             if (v->type == NUMERIC)  
               (iter++)->f = case_num (input, v->fv);  
             else  
               {  
                 memcpy (iter->s, case_str (input, v->fv), v->width);  
                 iter += v->nv;  
               }  
           }  
       }  
               
       accumulate_aggregate_info (agr, input);  
           
       return 0;  
708      }      }
         
   /* Compare the value of each break variable to the values on the  
      previous case. */  
   {  
     union value *iter = agr->prev_break;  
     int i;  
       
     for (i = 0; i < agr->break_var_cnt; i++)  
       {  
         struct variable *v = agr->break_vars[i];  
         
         switch (v->type)  
           {  
           case NUMERIC:  
             if (case_num (input, v->fv) != iter->f)  
               goto not_equal;  
             iter++;  
             break;  
           case ALPHA:  
             if (memcmp (case_str (input, v->fv), iter->s, v->width))  
               goto not_equal;  
             iter += v->nv;  
             break;  
           default:  
             assert (0);  
           }  
       }  
   }  
   
   accumulate_aggregate_info (agr, input);  
709    
   return 0;  
     
 not_equal:  
   /* The values of the break variable are different from the values on  
      the previous case.  That means that it's time to dump aggregate  
      info. */  
   dump_aggregate_info (agr, output);  
   initialize_aggregate_info (agr);  
710    accumulate_aggregate_info (agr, input);    accumulate_aggregate_info (agr, input);
711      return finished_group;
   /* Copy INPUT into prev_break. */  
   {  
     union value *iter = agr->prev_break;  
     int i;  
   
     for (i = 0; i < agr->break_var_cnt; i++)  
       {  
         struct variable *v = agr->break_vars[i];  
               
         if (v->type == NUMERIC)  
           (iter++)->f = case_num (input, v->fv);  
         else  
           {  
             memcpy (iter->s, case_str (input, v->fv), v->width);  
             iter += v->nv;  
           }  
       }  
   }  
     
   return 1;  
712  }  }
713    
714  /* Accumulates aggregation data from the case INPUT. */  /* Accumulates aggregation data from the case INPUT. */
# Line 978  dump_aggregate_info (struct agr_proc *ag Line 895  dump_aggregate_info (struct agr_proc *ag
895    
896      for (i = 0; i < agr->break_var_cnt; i++)      for (i = 0; i < agr->break_var_cnt; i++)
897        {        {
898          int nv = agr->break_vars[i]->nv;          struct variable *v = agr->break_vars[i];
899          memcpy (case_data_rw (output, value_idx),          memcpy (case_data_rw (output, value_idx),
900                  &agr->prev_break[value_idx],                  case_data (&agr->break_case, v->fv),
901                  sizeof (union value) * nv);                  sizeof (union value) * v->nv);
902          value_idx += nv;          value_idx += v->nv;
903        }        }
904    }    }
905        
# Line 1098  dump_aggregate_info (struct agr_proc *ag Line 1015  dump_aggregate_info (struct agr_proc *ag
1015    
1016  /* Resets the state for all the aggregate functions. */  /* Resets the state for all the aggregate functions. */
1017  static void  static void
1018  initialize_aggregate_info (struct agr_proc *agr)  initialize_aggregate_info (struct agr_proc *agr, const struct ccase *input)
1019  {  {
1020    struct agr_var *iter;    struct agr_var *iter;
1021    
1022      case_destroy (&agr->break_case);
1023      case_clone (&agr->break_case, input);
1024    
1025    for (iter = agr->agr_vars; iter; iter = iter->next)    for (iter = agr->agr_vars; iter; iter = iter->next)
1026      {      {
1027        iter->missing = 0;        iter->missing = 0;

Legend:
Removed from v.1.32  
changed lines
  Added in v.1.33

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26