1 /* PSPP - computes sample statistics.
2 Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 #include <data/any-writer.h>
24 #include <data/case-sink.h>
25 #include <data/case.h>
26 #include <data/casefile.h>
27 #include <data/dictionary.h>
28 #include <data/file-handle-def.h>
29 #include <data/format.h>
30 #include <data/procedure.h>
31 #include <data/settings.h>
32 #include <data/storage-stream.h>
33 #include <data/sys-file-writer.h>
34 #include <data/variable.h>
35 #include <language/command.h>
36 #include <language/data-io/file-handle.h>
37 #include <language/lexer/lexer.h>
38 #include <language/lexer/variable-parser.h>
39 #include <language/stats/sort-criteria.h>
40 #include <libpspp/alloc.h>
41 #include <libpspp/assertion.h>
42 #include <libpspp/message.h>
43 #include <libpspp/misc.h>
44 #include <libpspp/pool.h>
45 #include <libpspp/str.h>
46 #include <math/moments.h>
47 #include <math/sort.h>
52 #define _(msgid) gettext (msgid)
54 /* Argument for AGGREGATE function. */
57 double f; /* Numeric. */
58 char *c; /* Short or long string. */
61 /* Specifies how to make an aggregate variable. */
64 struct agr_var *next; /* Next in list. */
66 /* Collected during parsing. */
67 struct variable *src; /* Source variable. */
68 struct variable *dest; /* Target variable. */
69 int function; /* Function. */
70 int include_missing; /* 1=Include user-missing values. */
71 union agr_argument arg[2]; /* Arguments. */
73 /* Accumulated during AGGREGATE execution. */
78 struct moments1 *moments;
81 /* Aggregation functions. */
84 NONE, SUM, MEAN, SD, MAX, MIN, PGT, PLT, PIN, POUT, FGT, FLT, FIN,
85 FOUT, N, NU, NMISS, NUMISS, FIRST, LAST,
86 N_AGR_FUNCS, N_NO_VARS, NU_NO_VARS,
87 FUNC = 0x1f, /* Function mask. */
88 FSTRING = 1<<5, /* String function bit. */
91 /* Attributes of an aggregation function. */
94 const char *name; /* Aggregation function name. */
95 size_t n_args; /* Number of arguments. */
96 enum var_type alpha_type; /* When given ALPHA arguments, output type. */
97 struct fmt_spec format; /* Format spec if alpha_type != ALPHA. */
100 /* Attributes of aggregation functions. */
101 static const struct agr_func agr_func_tab[] =
103 {"<NONE>", 0, -1, {0, 0, 0}},
104 {"SUM", 0, -1, {FMT_F, 8, 2}},
105 {"MEAN", 0, -1, {FMT_F, 8, 2}},
106 {"SD", 0, -1, {FMT_F, 8, 2}},
107 {"MAX", 0, VAR_STRING, {-1, -1, -1}},
108 {"MIN", 0, VAR_STRING, {-1, -1, -1}},
109 {"PGT", 1, VAR_NUMERIC, {FMT_F, 5, 1}},
110 {"PLT", 1, VAR_NUMERIC, {FMT_F, 5, 1}},
111 {"PIN", 2, VAR_NUMERIC, {FMT_F, 5, 1}},
112 {"POUT", 2, VAR_NUMERIC, {FMT_F, 5, 1}},
113 {"FGT", 1, VAR_NUMERIC, {FMT_F, 5, 3}},
114 {"FLT", 1, VAR_NUMERIC, {FMT_F, 5, 3}},
115 {"FIN", 2, VAR_NUMERIC, {FMT_F, 5, 3}},
116 {"FOUT", 2, VAR_NUMERIC, {FMT_F, 5, 3}},
117 {"N", 0, VAR_NUMERIC, {FMT_F, 7, 0}},
118 {"NU", 0, VAR_NUMERIC, {FMT_F, 7, 0}},
119 {"NMISS", 0, VAR_NUMERIC, {FMT_F, 7, 0}},
120 {"NUMISS", 0, VAR_NUMERIC, {FMT_F, 7, 0}},
121 {"FIRST", 0, VAR_STRING, {-1, -1, -1}},
122 {"LAST", 0, VAR_STRING, {-1, -1, -1}},
123 {NULL, 0, -1, {-1, -1, -1}},
124 {"N", 0, VAR_NUMERIC, {FMT_F, 7, 0}},
125 {"NU", 0, VAR_NUMERIC, {FMT_F, 7, 0}},
128 /* Missing value types. */
129 enum missing_treatment
131 ITEMWISE, /* Missing values item by item. */
132 COLUMNWISE /* Missing values column by column. */
135 /* An entire AGGREGATE procedure. */
138 /* We have either an output file or a sink. */
139 struct any_writer *writer; /* Output file, or null if none. */
140 struct case_sink *sink; /* Sink, or null if none. */
142 /* Break variables. */
143 struct sort_criteria *sort; /* Sort criteria. */
144 struct variable **break_vars; /* Break variables. */
145 size_t break_var_cnt; /* Number of break variables. */
146 struct ccase break_case; /* Last values of break variables. */
148 enum missing_treatment missing; /* How to treat missing values. */
149 struct agr_var *agr_vars; /* First aggregate variable. */
150 struct dictionary *dict; /* Aggregate dictionary. */
151 const struct dictionary *src_dict; /* Dict of the source */
152 int case_cnt; /* Counts aggregated cases. */
153 struct ccase agr_case; /* Aggregate case for output. */
156 static void initialize_aggregate_info (struct agr_proc *,
157 const struct ccase *);
160 static bool parse_aggregate_functions (struct lexer *, const struct dictionary *,
162 static void agr_destroy (struct agr_proc *);
163 static bool aggregate_single_case (struct agr_proc *agr,
164 const struct ccase *input,
165 struct ccase *output);
166 static void dump_aggregate_info (struct agr_proc *agr, struct ccase *output);
170 /* Parses and executes the AGGREGATE procedure. */
172 cmd_aggregate (struct lexer *lexer, struct dataset *ds)
174 struct dictionary *dict = dataset_dict (ds);
176 struct file_handle *out_file = NULL;
178 bool copy_documents = false;
179 bool presorted = false;
182 memset(&agr, 0 , sizeof (agr));
183 agr.missing = ITEMWISE;
184 case_nullify (&agr.break_case);
186 agr.dict = dict_create ();
188 dict_set_label (agr.dict, dict_get_label (dict));
189 dict_set_documents (agr.dict, dict_get_documents (dict));
191 /* OUTFILE subcommand must be first. */
192 if (!lex_force_match_id (lexer, "OUTFILE"))
194 lex_match (lexer, '=');
195 if (!lex_match (lexer, '*'))
197 out_file = fh_parse (lexer, FH_REF_FILE | FH_REF_SCRATCH);
198 if (out_file == NULL)
202 /* Read most of the subcommands. */
205 lex_match (lexer, '/');
207 if (lex_match_id (lexer, "MISSING"))
209 lex_match (lexer, '=');
210 if (!lex_match_id (lexer, "COLUMNWISE"))
212 lex_error (lexer, _("while expecting COLUMNWISE"));
215 agr.missing = COLUMNWISE;
217 else if (lex_match_id (lexer, "DOCUMENT"))
218 copy_documents = true;
219 else if (lex_match_id (lexer, "PRESORTED"))
221 else if (lex_match_id (lexer, "BREAK"))
225 lex_match (lexer, '=');
226 agr.sort = sort_parse_criteria (lexer, dict,
227 &agr.break_vars, &agr.break_var_cnt,
228 &saw_direction, NULL);
229 if (agr.sort == NULL)
232 for (i = 0; i < agr.break_var_cnt; i++)
233 dict_clone_var_assert (agr.dict, agr.break_vars[i],
234 var_get_name (agr.break_vars[i]));
236 /* BREAK must follow the options. */
241 lex_error (lexer, _("expecting BREAK"));
245 if (presorted && saw_direction)
246 msg (SW, _("When PRESORTED is specified, specifying sorting directions "
247 "with (A) or (D) has no effect. Output data will be sorted "
248 "the same way as the input data."));
250 /* Read in the aggregate functions. */
251 lex_match (lexer, '/');
252 if (!parse_aggregate_functions (lexer, dict, &agr))
255 /* Delete documents. */
257 dict_set_documents (agr.dict, NULL);
259 /* Cancel SPLIT FILE. */
260 dict_set_split_vars (agr.dict, NULL, 0);
264 case_create (&agr.agr_case, dict_get_next_value_idx (agr.dict));
266 /* Output to active file or external file? */
267 if (out_file == NULL)
271 /* The active file will be replaced by the aggregated data,
272 so TEMPORARY is moot. */
273 proc_cancel_temporary_transformations (ds);
275 if (agr.sort != NULL && !presorted)
277 if (!sort_active_file_in_place (ds, agr.sort))
281 agr.sink = create_case_sink (&storage_sink_class, agr.dict,
282 dataset_get_casefile_factory (ds),
284 if (agr.sink->class->open != NULL)
285 agr.sink->class->open (agr.sink);
287 create_case_sink (&null_sink_class, dict,
288 dataset_get_casefile_factory (ds),
291 while (proc_read (ds, &c))
292 if (aggregate_single_case (&agr, c, &agr.agr_case))
293 if (!agr.sink->class->write (agr.sink, &agr.agr_case))
298 if (!proc_close (ds))
301 if (agr.case_cnt > 0)
303 dump_aggregate_info (&agr, &agr.agr_case);
304 if (!agr.sink->class->write (agr.sink, &agr.agr_case))
307 discard_variables (ds);
309 dataset_set_dict (ds, agr.dict);
311 proc_set_source (ds, agr.sink->class->make_source (agr.sink));
312 free_case_sink (agr.sink);
316 agr.writer = any_writer_open (out_file, agr.dict);
317 if (agr.writer == NULL)
320 if (agr.sort != NULL && !presorted)
322 /* Sorting is needed. */
323 struct casefile *dst;
324 struct casereader *reader;
328 dst = sort_active_file_to_casefile (ds, agr.sort);
331 reader = casefile_get_destructive_reader (dst);
332 while (ok && casereader_read_xfer (reader, &c))
334 if (aggregate_single_case (&agr, &c, &agr.agr_case))
335 ok = any_writer_write (agr.writer, &agr.agr_case);
338 casereader_destroy (reader);
340 ok = !casefile_error (dst);
341 casefile_destroy (dst);
347 /* Active file is already sorted. */
351 while (proc_read (ds, &c))
352 if (aggregate_single_case (&agr, c, &agr.agr_case))
353 if (!any_writer_write (agr.writer, &agr.agr_case))
358 if (!proc_close (ds))
362 if (agr.case_cnt > 0)
364 dump_aggregate_info (&agr, &agr.agr_case);
365 any_writer_write (agr.writer, &agr.agr_case);
367 if (any_writer_error (agr.writer))
376 return CMD_CASCADING_FAILURE;
379 /* Parse all the aggregate functions. */
381 parse_aggregate_functions (struct lexer *lexer, const struct dictionary *dict, struct agr_proc *agr)
383 struct agr_var *tail; /* Tail of linked list starting at agr->vars. */
385 /* Parse everything. */
392 struct string function_name;
395 const struct agr_func *function;
398 union agr_argument arg[2];
400 struct variable **src;
414 /* Parse the list of target variables. */
415 while (!lex_match (lexer, '='))
417 size_t n_dest_prev = n_dest;
419 if (!parse_DATA_LIST_vars (lexer, &dest, &n_dest,
420 PV_APPEND | PV_SINGLE | PV_NO_SCRATCH))
423 /* Assign empty labels. */
427 dest_label = xnrealloc (dest_label, n_dest, sizeof *dest_label);
428 for (j = n_dest_prev; j < n_dest; j++)
429 dest_label[j] = NULL;
434 if (lex_token (lexer) == T_STRING)
437 ds_init_string (&label, lex_tokstr (lexer));
439 ds_truncate (&label, 255);
440 dest_label[n_dest - 1] = ds_xstrdup (&label);
446 /* Get the name of the aggregation function. */
447 if (lex_token (lexer) != T_ID)
449 lex_error (lexer, _("expecting aggregation function"));
455 ds_init_string (&function_name, lex_tokstr (lexer));
457 ds_chomp (&function_name, '.');
459 if (lex_tokid(lexer)[strlen (lex_tokid (lexer)) - 1] == '.')
462 for (function = agr_func_tab; function->name; function++)
463 if (!strcasecmp (function->name, ds_cstr (&function_name)))
465 if (NULL == function->name)
467 msg (SE, _("Unknown aggregation function %s."),
468 ds_cstr (&function_name));
471 ds_destroy (&function_name);
472 func_index = function - agr_func_tab;
475 /* Check for leading lparen. */
476 if (!lex_match (lexer, '('))
479 func_index = N_NO_VARS;
480 else if (func_index == NU)
481 func_index = NU_NO_VARS;
484 lex_error (lexer, _("expecting `('"));
490 /* Parse list of source variables. */
492 int pv_opts = PV_NO_SCRATCH;
494 if (func_index == SUM || func_index == MEAN || func_index == SD)
495 pv_opts |= PV_NUMERIC;
496 else if (function->n_args)
497 pv_opts |= PV_SAME_TYPE;
499 if (!parse_variables (lexer, dict, &src, &n_src, pv_opts))
503 /* Parse function arguments, for those functions that
504 require arguments. */
505 if (function->n_args != 0)
506 for (i = 0; i < function->n_args; i++)
510 lex_match (lexer, ',');
511 if (lex_token (lexer) == T_STRING)
513 arg[i].c = ds_xstrdup (lex_tokstr (lexer));
516 else if (lex_is_number (lexer))
518 arg[i].f = lex_tokval (lexer);
523 msg (SE, _("Missing argument %d to %s."), i + 1,
530 if (type != var_get_type (src[0]))
532 msg (SE, _("Arguments to %s must be of same type as "
533 "source variables."),
539 /* Trailing rparen. */
540 if (!lex_match (lexer, ')'))
542 lex_error (lexer, _("expecting `)'"));
546 /* Now check that the number of source variables match
547 the number of target variables. If we check earlier
548 than this, the user can get very misleading error
549 message, i.e. `AGGREGATE x=SUM(y t).' will get this
550 error message when a proper message would be more
551 like `unknown variable t'. */
554 msg (SE, _("Number of source variables (%u) does not match "
555 "number of target variables (%u)."),
556 (unsigned) n_src, (unsigned) n_dest);
560 if ((func_index == PIN || func_index == POUT
561 || func_index == FIN || func_index == FOUT)
562 && (var_is_numeric (src[0])
563 ? arg[0].f > arg[1].f
564 : str_compare_rpad (arg[0].c, arg[1].c) > 0))
566 union agr_argument t = arg[0];
570 msg (SW, _("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."),
577 /* Finally add these to the linked list of aggregation
579 for (i = 0; i < n_dest; i++)
581 struct agr_var *v = xmalloc (sizeof *v);
583 /* Add variable to chain. */
584 if (agr->agr_vars != NULL)
592 /* Create the target variable in the aggregate
595 struct variable *destvar;
597 v->function = func_index;
603 if (var_is_alpha (src[i]))
605 v->function |= FSTRING;
606 v->string = xmalloc (var_get_width (src[i]));
609 if (function->alpha_type == VAR_STRING)
610 destvar = dict_clone_var (agr->dict, v->src, dest[i]);
613 assert (var_is_numeric (v->src)
614 || function->alpha_type == VAR_NUMERIC);
615 destvar = dict_create_var (agr->dict, dest[i], 0);
619 if ((func_index == N || func_index == NMISS)
620 && dict_get_weight (dict) != NULL)
621 f = fmt_for_output (FMT_F, 8, 2);
623 f = function->format;
624 var_set_both_formats (destvar, &f);
630 destvar = dict_create_var (agr->dict, dest[i], 0);
631 if (func_index == N_NO_VARS && dict_get_weight (dict) != NULL)
632 f = fmt_for_output (FMT_F, 8, 2);
634 f = function->format;
635 var_set_both_formats (destvar, &f);
640 msg (SE, _("Variable name %s is not unique within the "
641 "aggregate file dictionary, which contains "
642 "the aggregate variables and the break "
650 var_set_label (destvar, dest_label[i]);
655 v->include_missing = include_missing;
661 if (var_is_numeric (v->src))
662 for (j = 0; j < function->n_args; j++)
663 v->arg[j].f = arg[j].f;
665 for (j = 0; j < function->n_args; j++)
666 v->arg[j].c = xstrdup (arg[j].c);
670 if (src != NULL && var_is_alpha (src[0]))
671 for (i = 0; i < function->n_args; i++)
681 if (!lex_match (lexer, '/'))
683 if (lex_token (lexer) == '.')
686 lex_error (lexer, "expecting end of command");
692 ds_destroy (&function_name);
693 for (i = 0; i < n_dest; i++)
696 free (dest_label[i]);
702 if (src && n_src && var_is_alpha (src[0]))
703 for (i = 0; i < function->n_args; i++)
716 agr_destroy (struct agr_proc *agr)
718 struct agr_var *iter, *next;
720 any_writer_close (agr->writer);
721 if (agr->sort != NULL)
722 sort_destroy_criteria (agr->sort);
723 free (agr->break_vars);
724 case_destroy (&agr->break_case);
725 for (iter = agr->agr_vars; iter; iter = next)
729 if (iter->function & FSTRING)
734 n_args = agr_func_tab[iter->function & FUNC].n_args;
735 for (i = 0; i < n_args; i++)
736 free (iter->arg[i].c);
739 else if (iter->function == SD)
740 moments1_destroy (iter->moments);
743 if (agr->dict != NULL)
744 dict_destroy (agr->dict);
746 case_destroy (&agr->agr_case);
751 static void accumulate_aggregate_info (struct agr_proc *,
752 const struct ccase *);
753 static void dump_aggregate_info (struct agr_proc *, struct ccase *);
755 /* Processes a single case INPUT for aggregation. If output is
756 warranted, writes it to OUTPUT and returns true.
757 Otherwise, returns false and OUTPUT is unmodified. */
759 aggregate_single_case (struct agr_proc *agr,
760 const struct ccase *input, struct ccase *output)
762 bool finished_group = false;
764 if (agr->case_cnt++ == 0)
765 initialize_aggregate_info (agr, input);
766 else if (case_compare (&agr->break_case, input,
767 agr->break_vars, agr->break_var_cnt))
769 dump_aggregate_info (agr, output);
770 finished_group = true;
772 initialize_aggregate_info (agr, input);
775 accumulate_aggregate_info (agr, input);
776 return finished_group;
779 /* Accumulates aggregation data from the case INPUT. */
781 accumulate_aggregate_info (struct agr_proc *agr,
782 const struct ccase *input)
784 struct agr_var *iter;
786 bool bad_warn = true;
788 weight = dict_get_case_weight (agr->src_dict, input, &bad_warn);
790 for (iter = agr->agr_vars; iter; iter = iter->next)
793 const union value *v = case_data (input, iter->src);
794 int src_width = var_get_width (iter->src);
796 if (iter->include_missing
797 ? var_is_numeric (iter->src) && v->f == SYSMIS
798 : var_is_value_missing (iter->src, v))
800 switch (iter->function)
803 case NMISS | FSTRING:
804 iter->dbl[0] += weight;
807 case NUMISS | FSTRING:
815 /* This is horrible. There are too many possibilities. */
816 switch (iter->function)
819 iter->dbl[0] += v->f * weight;
823 iter->dbl[0] += v->f * weight;
824 iter->dbl[1] += weight;
827 moments1_add (iter->moments, v->f, weight);
830 iter->dbl[0] = MAX (iter->dbl[0], v->f);
834 if (memcmp (iter->string, v->s, src_width) < 0)
835 memcpy (iter->string, v->s, src_width);
839 iter->dbl[0] = MIN (iter->dbl[0], v->f);
843 if (memcmp (iter->string, v->s, src_width) > 0)
844 memcpy (iter->string, v->s, src_width);
849 if (v->f > iter->arg[0].f)
850 iter->dbl[0] += weight;
851 iter->dbl[1] += weight;
855 if (memcmp (iter->arg[0].c, v->s, src_width) < 0)
856 iter->dbl[0] += weight;
857 iter->dbl[1] += weight;
861 if (v->f < iter->arg[0].f)
862 iter->dbl[0] += weight;
863 iter->dbl[1] += weight;
867 if (memcmp (iter->arg[0].c, v->s, src_width) > 0)
868 iter->dbl[0] += weight;
869 iter->dbl[1] += weight;
873 if (iter->arg[0].f <= v->f && v->f <= iter->arg[1].f)
874 iter->dbl[0] += weight;
875 iter->dbl[1] += weight;
879 if (memcmp (iter->arg[0].c, v->s, src_width) <= 0
880 && memcmp (iter->arg[1].c, v->s, src_width) >= 0)
881 iter->dbl[0] += weight;
882 iter->dbl[1] += weight;
886 if (iter->arg[0].f > v->f || v->f > iter->arg[1].f)
887 iter->dbl[0] += weight;
888 iter->dbl[1] += weight;
892 if (memcmp (iter->arg[0].c, v->s, src_width) > 0
893 || memcmp (iter->arg[1].c, v->s, src_width) < 0)
894 iter->dbl[0] += weight;
895 iter->dbl[1] += weight;
899 iter->dbl[0] += weight;
912 case FIRST | FSTRING:
915 memcpy (iter->string, v->s, src_width);
924 memcpy (iter->string, v->s, src_width);
928 case NMISS | FSTRING:
930 case NUMISS | FSTRING:
931 /* Our value is not missing or it would have been
932 caught earlier. Nothing to do. */
938 switch (iter->function)
941 iter->dbl[0] += weight;
952 /* We've come to a record that differs from the previous in one or
953 more of the break variables. Make an output record from the
954 accumulated statistics in the OUTPUT case. */
956 dump_aggregate_info (struct agr_proc *agr, struct ccase *output)
962 for (i = 0; i < agr->break_var_cnt; i++)
964 struct variable *v = agr->break_vars[i];
965 size_t value_cnt = var_get_value_cnt (v);
966 memcpy (case_data_rw_idx (output, value_idx),
967 case_data (&agr->break_case, v),
968 sizeof (union value) * value_cnt);
969 value_idx += value_cnt;
976 for (i = agr->agr_vars; i; i = i->next)
978 union value *v = case_data_rw (output, i->dest);
980 if (agr->missing == COLUMNWISE && i->missing != 0
981 && (i->function & FUNC) != N && (i->function & FUNC) != NU
982 && (i->function & FUNC) != NMISS && (i->function & FUNC) != NUMISS)
984 if (var_is_alpha (i->dest))
985 memset (v->s, ' ', var_get_width (i->dest));
994 v->f = i->int1 ? i->dbl[0] : SYSMIS;
997 v->f = i->dbl[1] != 0.0 ? i->dbl[0] / i->dbl[1] : SYSMIS;
1003 /* FIXME: we should use two passes. */
1004 moments1_calculate (i->moments, NULL, NULL, &variance,
1006 if (variance != SYSMIS)
1007 v->f = sqrt (variance);
1014 v->f = i->int1 ? i->dbl[0] : SYSMIS;
1019 memcpy (v->s, i->string, var_get_width (i->dest));
1021 memset (v->s, ' ', var_get_width (i->dest));
1030 case FOUT | FSTRING:
1031 v->f = i->dbl[1] ? i->dbl[0] / i->dbl[1] : SYSMIS;
1040 case POUT | FSTRING:
1041 v->f = i->dbl[1] ? i->dbl[0] / i->dbl[1] * 100.0 : SYSMIS;
1053 v->f = i->int1 ? i->dbl[0] : SYSMIS;
1055 case FIRST | FSTRING:
1056 case LAST | FSTRING:
1058 memcpy (v->s, i->string, var_get_width (i->dest));
1060 memset (v->s, ' ', var_get_width (i->dest));
1069 case NMISS | FSTRING:
1073 case NUMISS | FSTRING:
1083 /* Resets the state for all the aggregate functions. */
1085 initialize_aggregate_info (struct agr_proc *agr, const struct ccase *input)
1087 struct agr_var *iter;
1089 case_destroy (&agr->break_case);
1090 case_clone (&agr->break_case, input);
1092 for (iter = agr->agr_vars; iter; iter = iter->next)
1095 iter->dbl[0] = iter->dbl[1] = iter->dbl[2] = 0.0;
1096 iter->int1 = iter->int2 = 0;
1097 switch (iter->function)
1100 iter->dbl[0] = DBL_MAX;
1103 memset (iter->string, 255, var_get_width (iter->src));
1106 iter->dbl[0] = -DBL_MAX;
1109 memset (iter->string, 0, var_get_width (iter->src));
1112 if (iter->moments == NULL)
1113 iter->moments = moments1_create (MOMENT_VARIANCE);
1115 moments1_clear (iter->moments);