AGGREGATE: Fix crash with temporary transformations.
[pspp] / src / language / commands / aggregate.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 1997-9, 2000, 2006, 2008, 2009, 2010, 2011, 2012, 2014 Free Software Foundation, Inc.
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16
17 #include <config.h>
18
19 #include "language/commands/aggregate.h"
20
21 #include <stdlib.h>
22
23 #include "data/any-writer.h"
24 #include "data/case.h"
25 #include "data/casegrouper.h"
26 #include "data/casereader.h"
27 #include "data/casewriter.h"
28 #include "data/dataset.h"
29 #include "data/dictionary.h"
30 #include "data/file-handle-def.h"
31 #include "data/format.h"
32 #include "data/settings.h"
33 #include "data/subcase.h"
34 #include "data/sys-file-writer.h"
35 #include "data/variable.h"
36 #include "language/command.h"
37 #include "language/commands/file-handle.h"
38 #include "language/lexer/lexer.h"
39 #include "language/lexer/variable-parser.h"
40 #include "language/commands/sort-criteria.h"
41 #include "libpspp/assertion.h"
42 #include "libpspp/i18n.h"
43 #include "libpspp/message.h"
44 #include "libpspp/misc.h"
45 #include "libpspp/pool.h"
46 #include "libpspp/str.h"
47 #include "math/moments.h"
48 #include "math/percentiles.h"
49 #include "math/sort.h"
50 #include "math/statistic.h"
51
52 #include "gl/c-strcase.h"
53 #include "gl/minmax.h"
54 #include "gl/xalloc.h"
55
56 #include "gettext.h"
57 #define _(msgid) gettext (msgid)
58 #define N_(msgid) msgid
59
60 /* Argument for AGGREGATE function.
61
62    Only one of the members is used, so this could be a union, but it's simpler
63    to just have both. */
64 struct agr_argument
65   {
66     double f;                           /* Numeric. */
67     struct substring s;                 /* String. */
68   };
69
70 /* Specifies how to make an aggregate variable. */
71 struct agr_var
72   {
73     /* Collected during parsing. */
74     const struct variable *src; /* Source variable. */
75     struct variable *dest;      /* Target variable. */
76     enum agr_function function; /* Function. */
77     enum mv_class exclude;      /* Classes of missing values to exclude. */
78     struct agr_argument arg[2]; /* Arguments. */
79
80     /* Accumulated during AGGREGATE execution. */
81     double dbl;
82     double W;                   /* Total non-missing weight. */
83     int int1;
84     char *string;
85     bool saw_missing;
86     struct moments1 *moments;
87
88     struct variable *subject;
89     struct variable *weight;
90     struct casewriter *writer;
91   };
92
93 /* Attributes of aggregation functions. */
94 const struct agr_func agr_func_tab[] =
95   {
96 #define AGRF(ENUM, NAME, DESCRIPTION, SRC_VARS, N_ARGS, ALPHA_TYPE, W, D) \
97     [ENUM] = { NAME, DESCRIPTION, SRC_VARS, N_ARGS, ALPHA_TYPE, \
98                { .type = (W) > 0 ? FMT_F : -1, .w = W, .d = D } },
99 AGGREGATE_FUNCTIONS
100 #undef AGRF
101     {NULL, NULL, AGR_SV_NO, 0, -1, {-1, -1, -1}},
102   };
103
104 /* Missing value types. */
105 enum missing_treatment
106   {
107     ITEMWISE,           /* Missing values item by item. */
108     COLUMNWISE          /* Missing values column by column. */
109   };
110
111 /* An entire AGGREGATE procedure. */
112 struct agr_proc
113   {
114     /* Break variables. */
115     struct subcase sort;                /* Sort criteria (break variables). */
116     const struct variable **break_vars;       /* Break variables. */
117     size_t break_n_vars;                /* Number of break variables. */
118
119     enum missing_treatment missing;     /* How to treat missing values. */
120     struct agr_var *agr_vars;           /* Aggregate variables. */
121     size_t n_agr_vars;
122     struct dictionary *dict;            /* Aggregate dictionary. */
123     const struct dictionary *src_dict;  /* Dict of the source */
124     int n_cases;                        /* Counts aggregated cases. */
125
126     bool add_variables;                 /* True iff the aggregated variables should
127                                            be appended to the existing dictionary */
128   };
129
130 static void initialize_aggregate_info (struct agr_proc *);
131
132 static void accumulate_aggregate_info (struct agr_proc *,
133                                        const struct ccase *);
134 /* Prototypes. */
135 static bool parse_aggregate_functions (struct lexer *, const struct dictionary *,
136                                        struct agr_proc *);
137 static void agr_destroy (struct agr_proc *);
138 static void dump_aggregate_info (const struct agr_proc *agr,
139                                  struct casewriter *output,
140                                  const struct ccase *break_case);
141 \f
142 /* Parsing. */
143
144 /* Parses and executes the AGGREGATE procedure. */
145 int
146 cmd_aggregate (struct lexer *lexer, struct dataset *ds)
147 {
148   struct dictionary *dict = dataset_dict (ds);
149   struct agr_proc agr = {
150     .missing = ITEMWISE,
151     .src_dict = dict,
152   };
153   struct file_handle *out_file = NULL;
154   struct casereader *input = NULL;
155   struct casewriter *output = NULL;
156
157   bool copy_documents = false;
158   bool presorted = false;
159   int addvariables_ofs = 0;
160
161   /* OUTFILE subcommand must be first. */
162   if (lex_match_phrase (lexer, "/OUTFILE") || lex_match_id (lexer, "OUTFILE"))
163     {
164       lex_match (lexer, T_EQUALS);
165       if (!lex_match (lexer, T_ASTERISK))
166         {
167           out_file = fh_parse (lexer, FH_REF_FILE, dataset_session (ds));
168           if (out_file == NULL)
169             goto error;
170         }
171
172       if (!out_file && lex_match_id (lexer, "MODE"))
173         {
174           lex_match (lexer, T_EQUALS);
175           if (lex_match_id (lexer, "ADDVARIABLES"))
176             {
177               addvariables_ofs = lex_ofs (lexer) - 1;
178               agr.add_variables = true;
179               presorted = true;
180             }
181           else if (lex_match_id (lexer, "REPLACE"))
182             agr.add_variables = false;
183           else
184             {
185               lex_error_expecting (lexer, "ADDVARIABLES", "REPLACE");
186               goto error;
187             }
188         }
189     }
190   else
191     {
192       agr.add_variables = true;
193       presorted = true;
194     }
195
196   if (lex_match_phrase (lexer, "/MISSING"))
197     {
198       lex_match (lexer, T_EQUALS);
199       if (!lex_match_id (lexer, "COLUMNWISE"))
200         {
201           lex_error_expecting (lexer, "COLUMNWISE");
202           goto error;
203         }
204       agr.missing = COLUMNWISE;
205     }
206
207   int presorted_ofs = 0;
208   for (;;)
209     if (lex_match_phrase (lexer, "/DOCUMENT"))
210       copy_documents = true;
211     else if (lex_match_phrase (lexer, "/PRESORTED"))
212       {
213         presorted = true;
214         presorted_ofs = lex_ofs (lexer) - 1;
215       }
216     else
217       break;
218
219   if (agr.add_variables)
220     agr.dict = dict_clone (dict);
221   else
222     agr.dict = dict_create (dict_get_encoding (dict));
223
224   dict_set_label (agr.dict, dict_get_label (dict));
225   dict_set_documents (agr.dict, dict_get_documents (dict));
226
227   if (lex_match_phrase (lexer, "/BREAK"))
228     {
229       lex_match (lexer, T_EQUALS);
230       bool saw_direction;
231       int break_start = lex_ofs (lexer);
232       if (!parse_sort_criteria (lexer, dict, &agr.sort, &agr.break_vars,
233                                 &saw_direction))
234         goto error;
235       int break_end = lex_ofs (lexer) - 1;
236       agr.break_n_vars = subcase_get_n_fields (&agr.sort);
237
238       if  (! agr.add_variables)
239         for (size_t i = 0; i < agr.break_n_vars; i++)
240           dict_clone_var_assert (agr.dict, agr.break_vars[i]);
241
242       if (presorted && saw_direction)
243         {
244           lex_ofs_msg (lexer, SW, break_start, break_end,
245                        _("When the input data is presorted, specifying "
246                          "sorting directions with (A) or (D) has no effect.  "
247                          "Output data will be sorted the same way as the "
248                          "input data."));
249           if (presorted_ofs)
250             lex_ofs_msg (lexer, SN, presorted_ofs, presorted_ofs,
251                          _("The PRESORTED subcommand state that the "
252                            "input data is presorted."));
253           else if (addvariables_ofs)
254             lex_ofs_msg (lexer, SN, addvariables_ofs, addvariables_ofs,
255                          _("ADDVARIABLES implies that the input data "
256                            "is presorted."));
257           else
258             msg (SN, _("The input data must be presorted because the "
259                        "OUTFILE subcommand is not specified."));
260         }
261     }
262
263   /* Read in the aggregate functions. */
264   if (!parse_aggregate_functions (lexer, dict, &agr))
265     goto error;
266
267   /* Delete documents. */
268   if (!copy_documents)
269     dict_clear_documents (agr.dict);
270
271   /* Cancel SPLIT FILE. */
272   dict_clear_split_vars (agr.dict);
273
274   /* Initialize. */
275   agr.n_cases = 0;
276
277   if (out_file == NULL)
278     {
279       /* The active dataset will be replaced by the aggregated data,
280          so TEMPORARY is moot. */
281       proc_make_temporary_transformations_permanent (ds);
282       proc_discard_output (ds);
283       output = autopaging_writer_create (dict_get_proto (agr.dict));
284     }
285   else
286     {
287       output = any_writer_open (out_file, agr.dict);
288       if (output == NULL)
289         goto error;
290     }
291
292   input = proc_open (ds);
293   if (!subcase_is_empty (&agr.sort) && !presorted)
294     {
295       input = sort_execute (input, &agr.sort);
296       subcase_clear (&agr.sort);
297     }
298
299   struct casegrouper *grouper;
300   struct casereader *group;
301   for (grouper = casegrouper_create_vars (input, agr.break_vars,
302                                           agr.break_n_vars);
303        casegrouper_get_next_group (grouper, &group);
304        casereader_destroy (group))
305     {
306       struct casereader *placeholder = NULL;
307       struct ccase *c = casereader_peek (group, 0);
308
309       if (c == NULL)
310         {
311           casereader_destroy (group);
312           continue;
313         }
314
315       initialize_aggregate_info (&agr);
316
317       if (agr.add_variables)
318         placeholder = casereader_clone (group);
319
320       {
321         struct ccase *cg;
322         for (; (cg = casereader_read (group)) != NULL; case_unref (cg))
323           accumulate_aggregate_info (&agr, cg);
324       }
325
326
327       if  (agr.add_variables)
328         {
329           struct ccase *cg;
330           for (; (cg = casereader_read (placeholder)) != NULL; case_unref (cg))
331             dump_aggregate_info (&agr, output, cg);
332
333           casereader_destroy (placeholder);
334         }
335       else
336         {
337           dump_aggregate_info (&agr, output, c);
338         }
339       case_unref (c);
340     }
341   if (!casegrouper_destroy (grouper))
342     goto error;
343
344   bool ok = proc_commit (ds);
345   input = NULL;
346   if (!ok)
347     goto error;
348
349   if (out_file == NULL)
350     {
351       struct casereader *next_input = casewriter_make_reader (output);
352       if (next_input == NULL)
353         goto error;
354
355       dataset_set_dict (ds, agr.dict);
356       dataset_set_source (ds, next_input);
357       agr.dict = NULL;
358     }
359   else
360     {
361       ok = casewriter_destroy (output);
362       output = NULL;
363       if (!ok)
364         goto error;
365     }
366
367   agr_destroy (&agr);
368   fh_unref (out_file);
369   return CMD_SUCCESS;
370
371 error:
372   if (input != NULL)
373     proc_commit (ds);
374   casewriter_destroy (output);
375   agr_destroy (&agr);
376   fh_unref (out_file);
377   return CMD_CASCADING_FAILURE;
378 }
379
380 static bool
381 parse_agr_func_name (struct lexer *lexer, int *func_index,
382                      enum mv_class *exclude)
383 {
384   if (lex_token (lexer) != T_ID)
385     {
386       lex_error (lexer, _("Syntax error expecting aggregation function."));
387       return false;
388     }
389
390   struct substring name = lex_tokss (lexer);
391   *exclude = ss_chomp_byte (&name, '.') ? MV_SYSTEM : MV_ANY;
392
393   for (const struct agr_func *f = agr_func_tab; f->name; f++)
394     if (ss_equals_case (ss_cstr (f->name), name))
395       {
396         *func_index = f - agr_func_tab;
397         lex_get (lexer);
398         return true;
399       }
400   lex_error (lexer, _("Unknown aggregation function %s."), lex_tokcstr (lexer));
401   return false;
402 }
403
404 /* Parse all the aggregate functions. */
405 static bool
406 parse_aggregate_functions (struct lexer *lexer, const struct dictionary *dict,
407                            struct agr_proc *agr)
408 {
409   if (!lex_force_match (lexer, T_SLASH))
410     return false;
411
412   size_t starting_n_vars = dict_get_n_vars (dict);
413   size_t allocated_agr_vars = 0;
414
415   /* Parse everything. */
416   for (;;)
417     {
418       char **dest = NULL;
419       char **dest_label = NULL;
420       size_t n_vars = 0;
421
422       struct agr_argument arg[2] = { { .f = 0 }, { .f = 0 } };
423
424       const struct variable **src = NULL;
425
426       /* Parse the list of target variables. */
427       int dst_start_ofs = lex_ofs (lexer);
428       while (!lex_match (lexer, T_EQUALS))
429         {
430           size_t n_vars_prev = n_vars;
431
432           if (!parse_DATA_LIST_vars (lexer, dict, &dest, &n_vars,
433                                      (PV_APPEND | PV_SINGLE | PV_NO_SCRATCH
434                                       | PV_NO_DUPLICATE)))
435             goto error;
436
437           /* Assign empty labels. */
438           dest_label = xnrealloc (dest_label, n_vars, sizeof *dest_label);
439           for (size_t j = n_vars_prev; j < n_vars; j++)
440             dest_label[j] = NULL;
441
442           if (lex_is_string (lexer))
443             {
444               dest_label[n_vars - 1] = xstrdup (lex_tokcstr (lexer));
445               lex_get (lexer);
446             }
447         }
448       int dst_end_ofs = lex_ofs (lexer) - 2;
449
450       /* Get the name of the aggregation function. */
451       int func_index;
452       enum mv_class exclude;
453       if (!parse_agr_func_name (lexer, &func_index, &exclude))
454         goto error;
455       const struct agr_func *function = &agr_func_tab[func_index];
456
457       /* Check for leading lparen. */
458       if (!lex_match (lexer, T_LPAREN))
459         {
460           if (function->src_vars == AGR_SV_YES)
461             {
462               bool ok UNUSED = lex_force_match (lexer, T_LPAREN);
463               goto error;
464             }
465         }
466       else
467         {
468           /* Parse list of source variables. */
469           int pv_opts = PV_NO_SCRATCH;
470           if (func_index == AGRF_SUM || func_index == AGRF_MEAN
471               || func_index == AGRF_MEDIAN || func_index == AGRF_SD)
472             pv_opts |= PV_NUMERIC;
473           else if (function->n_args)
474             pv_opts |= PV_SAME_TYPE;
475
476           int src_start_ofs = lex_ofs (lexer);
477           size_t n_src;
478           if (!parse_variables_const (lexer, dict, &src, &n_src, pv_opts))
479             goto error;
480           int src_end_ofs = lex_ofs (lexer) - 1;
481
482           /* Parse function arguments, for those functions that
483              require arguments. */
484           int args_start_ofs = 0;
485           if (function->n_args != 0)
486             for (size_t i = 0; i < function->n_args; i++)
487               {
488                 lex_match (lexer, T_COMMA);
489
490                 enum val_type type;
491                 if (lex_is_string (lexer))
492                   type = VAL_STRING;
493                 else if (lex_is_number (lexer))
494                   type = VAL_NUMERIC;
495                 else
496                   {
497                     lex_error (lexer, _("Missing argument %zu to %s."),
498                                i + 1, function->name);
499                     goto error;
500                   }
501
502                 if (type != var_get_type (src[0]))
503                   {
504                     msg (SE, _("Arguments to %s must be of same type as "
505                                "source variables."),
506                          function->name);
507                     if (type == VAL_NUMERIC)
508                       {
509                         lex_next_msg (lexer, SN, 0, 0,
510                                       _("The argument is numeric."));
511                         lex_ofs_msg (lexer, SN, src_start_ofs, src_end_ofs,
512                                      _("The variables have string type."));
513                       }
514                     else
515                       {
516                         lex_next_msg (lexer, SN, 0, 0,
517                                       _("The argument is a string."));
518                         lex_ofs_msg (lexer, SN, src_start_ofs, src_end_ofs,
519                                      _("The variables are numeric."));
520                       }
521                     goto error;
522                   }
523
524                 if (i == 0)
525                   args_start_ofs = lex_ofs (lexer);
526                 if (type == VAL_NUMERIC)
527                   arg[i].f = lex_tokval (lexer);
528                 else
529                   arg[i].s = recode_substring_pool (dict_get_encoding (agr->dict),
530                                                     "UTF-8", lex_tokss (lexer),
531                                                     NULL);
532                 lex_get (lexer);
533               }
534           int args_end_ofs = lex_ofs (lexer) - 1;
535
536           /* Trailing rparen. */
537           if (!lex_force_match (lexer, T_RPAREN))
538             goto error;
539
540           /* Now check that the number of source variables match
541              the number of target variables.  If we check earlier
542              than this, the user can get very misleading error
543              message, i.e. `AGGREGATE x=SUM(y t).' will get this
544              error message when a proper message would be more
545              like `unknown variable t'. */
546           if (n_src != n_vars)
547             {
548               msg (SE, _("Number of source variables (%zu) does not match "
549                          "number of target variables (%zu)."),
550                    n_src, n_vars);
551               lex_ofs_msg (lexer, SN, src_start_ofs, src_end_ofs,
552                            _("These are the source variables."));
553               lex_ofs_msg (lexer, SN, dst_start_ofs, dst_end_ofs,
554                            _("These are the target variables."));
555               goto error;
556             }
557
558           if ((func_index == AGRF_PIN || func_index == AGRF_POUT
559               || func_index == AGRF_FIN || func_index == AGRF_FOUT)
560               && (var_is_numeric (src[0])
561                   ? arg[0].f > arg[1].f
562                   : buf_compare_rpad (arg[0].s.string, arg[0].s.length,
563                                       arg[1].s.string, arg[1].s.length) > 0))
564             {
565               struct agr_argument tmp = arg[0];
566               arg[0] = arg[1];
567               arg[1] = tmp;
568
569               lex_ofs_msg (lexer, SW, args_start_ofs, args_end_ofs,
570                            _("The value arguments passed to the %s function "
571                              "are out of order.  They will be treated as if "
572                              "they had been specified in the correct order."),
573                            function->name);
574             }
575         }
576
577       /* Finally add these to the aggregation variables. */
578       for (size_t i = 0; i < n_vars; i++)
579         {
580           const struct variable *existing_var = dict_lookup_var (agr->dict,
581                                                                  dest[i]);
582           if (existing_var)
583             {
584               if (var_get_dict_index (existing_var) >= starting_n_vars)
585                 lex_ofs_error (lexer, dst_start_ofs, dst_end_ofs,
586                                _("Duplicate target variable name %s."),
587                                dest[i]);
588               else if (agr->add_variables)
589                 lex_ofs_error (lexer, dst_start_ofs, dst_end_ofs,
590                                _("Variable name %s duplicates the name of a "
591                                  "variable in the active file dictionary."),
592                                dest[i]);
593               else
594                 lex_ofs_error (lexer, dst_start_ofs, dst_end_ofs,
595                                _("Variable name %s duplicates the name of a "
596                                  "break variable."), dest[i]);
597               goto error;
598             }
599
600           /* Add variable. */
601           if (agr->n_agr_vars >= allocated_agr_vars)
602             agr->agr_vars = x2nrealloc (agr->agr_vars, &allocated_agr_vars,
603                                         sizeof *agr->agr_vars);
604           struct agr_var *v = &agr->agr_vars[agr->n_agr_vars++];
605           *v = (struct agr_var) {
606             .exclude = exclude,
607             .moments = NULL,
608             .function = func_index,
609             .src = src ? src[i] : NULL,
610           };
611
612           /* Create the target variable in the aggregate dictionary. */
613           if (v->src && var_is_alpha (v->src))
614             v->string = xmalloc (var_get_width (v->src));
615
616           if (v->src && function->alpha_type == VAL_STRING)
617             v->dest = dict_clone_var_as_assert (agr->dict, v->src, dest[i]);
618           else
619             {
620               v->dest = dict_create_var_assert (agr->dict, dest[i], 0);
621
622               struct fmt_spec f;
623               if ((func_index == AGRF_N || func_index == AGRF_NMISS)
624                   && dict_get_weight (dict) != NULL)
625                 f = fmt_for_output (FMT_F, 8, 2);
626               else
627                 f = function->format;
628               var_set_both_formats (v->dest, &f);
629             }
630           if (dest_label[i])
631             var_set_label (v->dest, dest_label[i]);
632
633           if (v->src != NULL)
634             for (size_t j = 0; j < function->n_args; j++)
635               v->arg[j] = (struct agr_argument) {
636                 .f = arg[j].f,
637                 .s = arg[j].s.string ? ss_clone (arg[j].s) : ss_empty (),
638               };
639         }
640
641       ss_dealloc (&arg[0].s);
642       ss_dealloc (&arg[1].s);
643
644       free (src);
645       for (size_t i = 0; i < n_vars; i++)
646         {
647           free (dest[i]);
648           free (dest_label[i]);
649         }
650       free (dest);
651       free (dest_label);
652
653       if (!lex_match (lexer, T_SLASH))
654         {
655           if (lex_token (lexer) == T_ENDCMD)
656             return true;
657
658           lex_error (lexer, "Syntax error expecting end of command.");
659           return false;
660         }
661       continue;
662
663     error:
664       for (size_t i = 0; i < n_vars; i++)
665         {
666           free (dest[i]);
667           free (dest_label[i]);
668         }
669       free (dest);
670       free (dest_label);
671       ss_dealloc (&arg[0].s);
672       ss_dealloc (&arg[1].s);
673       free (src);
674
675       return false;
676     }
677 }
678
679 /* Destroys AGR. */
680 static void
681 agr_destroy (struct agr_proc *agr)
682 {
683   subcase_uninit (&agr->sort);
684   free (agr->break_vars);
685   for (size_t i = 0; i < agr->n_agr_vars; i++)
686     {
687       struct agr_var *av = &agr->agr_vars[i];
688
689       ss_dealloc (&av->arg[0].s);
690       ss_dealloc (&av->arg[1].s);
691       free (av->string);
692
693       if (av->function == AGRF_SD)
694         moments1_destroy (av->moments);
695
696       dict_destroy_internal_var (av->subject);
697       dict_destroy_internal_var (av->weight);
698     }
699   free (agr->agr_vars);
700   if (agr->dict != NULL)
701     dict_unref (agr->dict);
702 }
703 \f
704 /* Execution. */
705
706 /* Accumulates aggregation data from the case INPUT. */
707 static void
708 accumulate_aggregate_info (struct agr_proc *agr, const struct ccase *input)
709 {
710   bool bad_warn = true;
711   double weight = dict_get_case_weight (agr->src_dict, input, &bad_warn);
712   for (size_t i = 0; i < agr->n_agr_vars; i++)
713     {
714       struct agr_var *av = &agr->agr_vars[i];
715       if (av->src)
716         {
717           bool is_string = var_is_alpha (av->src);
718           const union value *v = case_data (input, av->src);
719           int src_width = var_get_width (av->src);
720           const struct substring vs = (src_width > 0
721                                        ? value_ss (v, src_width)
722                                        : ss_empty ());
723
724           if (var_is_value_missing (av->src, v) & av->exclude)
725             {
726               switch (av->function)
727                 {
728                 case AGRF_NMISS:
729                   av->dbl += weight;
730                   break;
731
732                 case AGRF_NUMISS:
733                   av->int1++;
734                   break;
735
736                 case AGRF_SUM:
737                 case AGRF_MEAN:
738                 case AGRF_MEDIAN:
739                 case AGRF_SD:
740                 case AGRF_MAX:
741                 case AGRF_MIN:
742                 case AGRF_PGT:
743                 case AGRF_PLT:
744                 case AGRF_PIN:
745                 case AGRF_POUT:
746                 case AGRF_FGT:
747                 case AGRF_FLT:
748                 case AGRF_FIN:
749                 case AGRF_FOUT:
750                 case AGRF_CGT:
751                 case AGRF_CLT:
752                 case AGRF_CIN:
753                 case AGRF_COUT:
754                 case AGRF_N:
755                 case AGRF_NU:
756                 case AGRF_FIRST:
757                 case AGRF_LAST:
758                   break;
759                 }
760               av->saw_missing = true;
761               continue;
762             }
763
764           /* This is horrible.  There are too many possibilities. */
765           av->W += weight;
766           switch (av->function)
767             {
768             case AGRF_SUM:
769               av->dbl += v->f * weight;
770               av->int1 = 1;
771               break;
772
773             case AGRF_MEAN:
774               av->dbl += v->f * weight;
775               break;
776
777             case AGRF_MEDIAN:
778               {
779                 struct ccase *cout = case_create (casewriter_get_proto (av->writer));
780                 *case_num_rw (cout, av->subject) = case_num (input, av->src);
781                 *case_num_rw (cout, av->weight) = weight;
782                 casewriter_write (av->writer, cout);
783               }
784               break;
785
786             case AGRF_SD:
787               moments1_add (av->moments, v->f, weight);
788               break;
789
790             case AGRF_MAX:
791               if (!is_string)
792                 av->dbl = MAX (av->dbl, v->f);
793               else if (memcmp (av->string, v->s, src_width) < 0)
794                 memcpy (av->string, v->s, src_width);
795               av->int1 = 1;
796               break;
797
798             case AGRF_MIN:
799               if (!is_string)
800                 av->dbl = MIN (av->dbl, v->f);
801               else if (memcmp (av->string, v->s, src_width) > 0)
802                 memcpy (av->string, v->s, src_width);
803               av->dbl = MIN (av->dbl, v->f);
804               av->int1 = 1;
805               break;
806
807             case AGRF_FGT:
808             case AGRF_PGT:
809             case AGRF_CGT:
810               if (is_string
811                   ? ss_compare_rpad (av->arg[0].s, vs) < 0
812                   : v->f > av->arg[0].f)
813                 av->dbl += weight;
814               break;
815
816             case AGRF_FLT:
817             case AGRF_PLT:
818             case AGRF_CLT:
819               if (is_string
820                   ? ss_compare_rpad (av->arg[0].s, vs) > 0
821                   : v->f < av->arg[0].f)
822                 av->dbl += weight;
823               break;
824
825             case AGRF_FIN:
826             case AGRF_PIN:
827             case AGRF_CIN:
828               if (is_string
829                   ? (ss_compare_rpad (av->arg[0].s, vs) <= 0
830                      && ss_compare_rpad (av->arg[1].s, vs) >= 0)
831                   : av->arg[0].f <= v->f && v->f <= av->arg[1].f)
832                 av->dbl += weight;
833               break;
834
835             case AGRF_FOUT:
836             case AGRF_POUT:
837             case AGRF_COUT:
838               if (is_string
839                   ? (ss_compare_rpad (av->arg[0].s, vs) > 0
840                      || ss_compare_rpad (av->arg[1].s, vs) < 0)
841                   : av->arg[0].f > v->f || v->f > av->arg[1].f)
842                 av->dbl += weight;
843               break;
844
845             case AGRF_N:
846               av->dbl += weight;
847               break;
848
849             case AGRF_NU:
850               av->int1++;
851               break;
852
853             case AGRF_FIRST:
854               if (av->int1 == 0)
855                 {
856                   if (is_string)
857                     memcpy (av->string, v->s, src_width);
858                   else
859                     av->dbl = v->f;
860                   av->int1 = 1;
861                 }
862               break;
863
864             case AGRF_LAST:
865               if (is_string)
866                 memcpy (av->string, v->s, src_width);
867               else
868                 av->dbl = v->f;
869               av->int1 = 1;
870               break;
871
872             case AGRF_NMISS:
873             case AGRF_NUMISS:
874               /* Our value is not missing or it would have been
875                  caught earlier.  Nothing to do. */
876               break;
877             }
878         }
879       else
880         {
881           av->W += weight;
882           switch (av->function)
883             {
884             case AGRF_N:
885               break;
886
887             case AGRF_NU:
888               av->int1++;
889               break;
890
891             case AGRF_SUM:
892             case AGRF_MEAN:
893             case AGRF_MEDIAN:
894             case AGRF_SD:
895             case AGRF_MAX:
896             case AGRF_MIN:
897             case AGRF_PGT:
898             case AGRF_PLT:
899             case AGRF_PIN:
900             case AGRF_POUT:
901             case AGRF_FGT:
902             case AGRF_FLT:
903             case AGRF_FIN:
904             case AGRF_FOUT:
905             case AGRF_CGT:
906             case AGRF_CLT:
907             case AGRF_CIN:
908             case AGRF_COUT:
909             case AGRF_NMISS:
910             case AGRF_NUMISS:
911             case AGRF_FIRST:
912             case AGRF_LAST:
913               NOT_REACHED ();
914             }
915         }
916     }
917 }
918
919 /* Writes an aggregated record to OUTPUT. */
920 static void
921 dump_aggregate_info (const struct agr_proc *agr, struct casewriter *output, const struct ccase *break_case)
922 {
923   struct ccase *c = case_create (dict_get_proto (agr->dict));
924
925   if (agr->add_variables)
926     {
927       case_copy (c, 0, break_case, 0, dict_get_n_vars (agr->src_dict));
928     }
929   else
930     {
931       int value_idx = 0;
932
933       for (size_t i = 0; i < agr->break_n_vars; i++)
934         {
935           const struct variable *v = agr->break_vars[i];
936           value_copy (case_data_rw_idx (c, value_idx),
937                       case_data (break_case, v),
938                       var_get_width (v));
939           value_idx++;
940         }
941     }
942
943   for (size_t i = 0; i < agr->n_agr_vars; i++)
944     {
945       struct agr_var *av = &agr->agr_vars[i];
946       union value *v = case_data_rw (c, av->dest);
947       int width = var_get_width (av->dest);
948
949       if (agr->missing == COLUMNWISE && av->saw_missing
950           && av->function != AGRF_N
951           && av->function != AGRF_NU
952           && av->function != AGRF_NMISS
953           && av->function != AGRF_NUMISS)
954         {
955           value_set_missing (v, width);
956           casewriter_destroy (av->writer);
957           continue;
958         }
959
960       switch (av->function)
961         {
962         case AGRF_SUM:
963           v->f = av->int1 ? av->dbl : SYSMIS;
964           break;
965
966         case AGRF_MEAN:
967           v->f = av->W != 0.0 ? av->dbl / av->W : SYSMIS;
968           break;
969
970         case AGRF_MEDIAN:
971           {
972             if (av->writer)
973               {
974                 struct percentile *median = percentile_create (0.5, av->W);
975                 struct order_stats *os = &median->parent;
976                 struct casereader *sorted_reader = casewriter_make_reader (av->writer);
977                 av->writer = NULL;
978
979                 order_stats_accumulate (&os, 1,
980                                         sorted_reader,
981                                         av->weight,
982                                         av->subject,
983                                         av->exclude);
984                 av->dbl = percentile_calculate (median, PC_HAVERAGE);
985                 statistic_destroy (&median->parent.parent);
986               }
987             v->f = av->dbl;
988           }
989           break;
990
991         case AGRF_SD:
992           {
993             double variance;
994
995             moments1_calculate (av->moments, NULL, NULL, &variance,
996                                 NULL, NULL);
997             v->f = variance != SYSMIS ? sqrt (variance) : SYSMIS;
998           }
999           break;
1000
1001         case AGRF_MAX:
1002         case AGRF_MIN:
1003         case AGRF_FIRST:
1004         case AGRF_LAST:
1005           if (!width)
1006             v->f = av->int1 ? av->dbl : SYSMIS;
1007           else
1008             {
1009               if (av->int1)
1010                 memcpy (v->s, av->string, width);
1011               else
1012                 value_set_missing (v, width);
1013             }
1014           break;
1015
1016         case AGRF_FGT:
1017         case AGRF_FLT:
1018         case AGRF_FIN:
1019         case AGRF_FOUT:
1020           v->f = av->W ? av->dbl / av->W : SYSMIS;
1021           break;
1022
1023         case AGRF_PGT:
1024         case AGRF_PLT:
1025         case AGRF_PIN:
1026         case AGRF_POUT:
1027           v->f = av->W ? av->dbl / av->W * 100.0 : SYSMIS;
1028           break;
1029
1030         case AGRF_CGT:
1031         case AGRF_CLT:
1032         case AGRF_CIN:
1033         case AGRF_COUT:
1034           v->f = av->dbl;
1035           break;
1036
1037         case AGRF_N:
1038           v->f = av->W;
1039           break;
1040
1041         case AGRF_NU:
1042         case AGRF_NUMISS:
1043           v->f = av->int1;
1044           break;
1045
1046         case AGRF_NMISS:
1047           v->f = av->dbl;
1048           break;
1049         }
1050     }
1051
1052   casewriter_write (output, c);
1053 }
1054
1055 /* Resets the state for all the aggregate functions. */
1056 static void
1057 initialize_aggregate_info (struct agr_proc *agr)
1058 {
1059   for (size_t i = 0; i < agr->n_agr_vars; i++)
1060     {
1061       struct agr_var *av = &agr->agr_vars[i];
1062       av->saw_missing = false;
1063       av->dbl = av->W = 0.0;
1064       av->int1 = 0;
1065
1066       int width = av->src ? var_get_width (av->src) : 0;
1067       switch (av->function)
1068         {
1069         case AGRF_MIN:
1070           if (!width)
1071             av->dbl = DBL_MAX;
1072           else
1073             memset (av->string, 255, width);
1074           break;
1075
1076         case AGRF_MAX:
1077           if (!width)
1078             av->dbl = -DBL_MAX;
1079           else
1080             memset (av->string, 0, width);
1081           break;
1082
1083         case AGRF_MEDIAN:
1084           {
1085             struct caseproto *proto = caseproto_create ();
1086             proto = caseproto_add_width (proto, 0);
1087             proto = caseproto_add_width (proto, 0);
1088
1089             if (! av->subject)
1090               av->subject = dict_create_internal_var (0, 0);
1091
1092             if (! av->weight)
1093               av->weight = dict_create_internal_var (1, 0);
1094
1095             struct subcase ordering;
1096             subcase_init_var (&ordering, av->subject, SC_ASCEND);
1097             av->writer = sort_create_writer (&ordering, proto);
1098             subcase_uninit (&ordering);
1099             caseproto_unref (proto);
1100           }
1101           break;
1102
1103         case AGRF_SD:
1104           if (av->moments == NULL)
1105             av->moments = moments1_create (MOMENT_VARIANCE);
1106           else
1107             moments1_clear (av->moments);
1108           break;
1109
1110         case AGRF_SUM:
1111         case AGRF_MEAN:
1112         case AGRF_PGT:
1113         case AGRF_PLT:
1114         case AGRF_PIN:
1115         case AGRF_POUT:
1116         case AGRF_FGT:
1117         case AGRF_FLT:
1118         case AGRF_FIN:
1119         case AGRF_FOUT:
1120         case AGRF_CGT:
1121         case AGRF_CLT:
1122         case AGRF_CIN:
1123         case AGRF_COUT:
1124         case AGRF_N:
1125         case AGRF_NU:
1126         case AGRF_NMISS:
1127         case AGRF_NUMISS:
1128         case AGRF_FIRST:
1129         case AGRF_LAST:
1130           break;
1131         }
1132     }
1133 }