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, NULL);
282 if (agr.sink->class->open != NULL)
283 agr.sink->class->open (agr.sink);
285 create_case_sink (&null_sink_class, dict, NULL));
287 while (proc_read (ds, &c))
288 if (aggregate_single_case (&agr, c, &agr.agr_case))
289 if (!agr.sink->class->write (agr.sink, &agr.agr_case))
294 if (!proc_close (ds))
296 if (agr.case_cnt > 0)
298 dump_aggregate_info (&agr, &agr.agr_case);
299 if (!agr.sink->class->write (agr.sink, &agr.agr_case))
302 discard_variables (ds);
304 dataset_set_dict (ds, agr.dict);
306 proc_set_source (ds, agr.sink->class->make_source (agr.sink));
307 free_case_sink (agr.sink);
311 agr.writer = any_writer_open (out_file, agr.dict);
312 if (agr.writer == NULL)
315 if (agr.sort != NULL && !presorted)
317 /* Sorting is needed. */
318 struct casefile *dst;
319 struct casereader *reader;
323 dst = sort_active_file_to_casefile (ds, agr.sort);
326 reader = casefile_get_destructive_reader (dst);
327 while (ok && casereader_read_xfer (reader, &c))
329 if (aggregate_single_case (&agr, &c, &agr.agr_case))
330 ok = any_writer_write (agr.writer, &agr.agr_case);
333 casereader_destroy (reader);
335 ok = !casefile_error (dst);
336 casefile_destroy (dst);
342 /* Active file is already sorted. */
346 while (proc_read (ds, &c))
347 if (aggregate_single_case (&agr, c, &agr.agr_case))
348 if (!any_writer_write (agr.writer, &agr.agr_case))
353 if (!proc_close (ds))
357 if (agr.case_cnt > 0)
359 dump_aggregate_info (&agr, &agr.agr_case);
360 any_writer_write (agr.writer, &agr.agr_case);
362 if (any_writer_error (agr.writer))
371 return CMD_CASCADING_FAILURE;
374 /* Parse all the aggregate functions. */
376 parse_aggregate_functions (struct lexer *lexer, const struct dictionary *dict, struct agr_proc *agr)
378 struct agr_var *tail; /* Tail of linked list starting at agr->vars. */
380 /* Parse everything. */
387 struct string function_name;
390 const struct agr_func *function;
393 union agr_argument arg[2];
395 struct variable **src;
409 /* Parse the list of target variables. */
410 while (!lex_match (lexer, '='))
412 size_t n_dest_prev = n_dest;
414 if (!parse_DATA_LIST_vars (lexer, &dest, &n_dest,
415 PV_APPEND | PV_SINGLE | PV_NO_SCRATCH))
418 /* Assign empty labels. */
422 dest_label = xnrealloc (dest_label, n_dest, sizeof *dest_label);
423 for (j = n_dest_prev; j < n_dest; j++)
424 dest_label[j] = NULL;
429 if (lex_token (lexer) == T_STRING)
432 ds_init_string (&label, lex_tokstr (lexer));
434 ds_truncate (&label, 255);
435 dest_label[n_dest - 1] = ds_xstrdup (&label);
441 /* Get the name of the aggregation function. */
442 if (lex_token (lexer) != T_ID)
444 lex_error (lexer, _("expecting aggregation function"));
450 ds_init_string (&function_name, lex_tokstr (lexer));
452 ds_chomp (&function_name, '.');
454 if (lex_tokid(lexer)[strlen (lex_tokid (lexer)) - 1] == '.')
457 for (function = agr_func_tab; function->name; function++)
458 if (!strcasecmp (function->name, ds_cstr (&function_name)))
460 if (NULL == function->name)
462 msg (SE, _("Unknown aggregation function %s."),
463 ds_cstr (&function_name));
466 ds_destroy (&function_name);
467 func_index = function - agr_func_tab;
470 /* Check for leading lparen. */
471 if (!lex_match (lexer, '('))
474 func_index = N_NO_VARS;
475 else if (func_index == NU)
476 func_index = NU_NO_VARS;
479 lex_error (lexer, _("expecting `('"));
485 /* Parse list of source variables. */
487 int pv_opts = PV_NO_SCRATCH;
489 if (func_index == SUM || func_index == MEAN || func_index == SD)
490 pv_opts |= PV_NUMERIC;
491 else if (function->n_args)
492 pv_opts |= PV_SAME_TYPE;
494 if (!parse_variables (lexer, dict, &src, &n_src, pv_opts))
498 /* Parse function arguments, for those functions that
499 require arguments. */
500 if (function->n_args != 0)
501 for (i = 0; i < function->n_args; i++)
505 lex_match (lexer, ',');
506 if (lex_token (lexer) == T_STRING)
508 arg[i].c = ds_xstrdup (lex_tokstr (lexer));
511 else if (lex_is_number (lexer))
513 arg[i].f = lex_tokval (lexer);
518 msg (SE, _("Missing argument %d to %s."), i + 1,
525 if (type != var_get_type (src[0]))
527 msg (SE, _("Arguments to %s must be of same type as "
528 "source variables."),
534 /* Trailing rparen. */
535 if (!lex_match (lexer, ')'))
537 lex_error (lexer, _("expecting `)'"));
541 /* Now check that the number of source variables match
542 the number of target variables. If we check earlier
543 than this, the user can get very misleading error
544 message, i.e. `AGGREGATE x=SUM(y t).' will get this
545 error message when a proper message would be more
546 like `unknown variable t'. */
549 msg (SE, _("Number of source variables (%u) does not match "
550 "number of target variables (%u)."),
551 (unsigned) n_src, (unsigned) n_dest);
555 if ((func_index == PIN || func_index == POUT
556 || func_index == FIN || func_index == FOUT)
557 && (var_is_numeric (src[0])
558 ? arg[0].f > arg[1].f
559 : str_compare_rpad (arg[0].c, arg[1].c) > 0))
561 union agr_argument t = arg[0];
565 msg (SW, _("The value arguments passed to the %s function "
566 "are out-of-order. They will be treated as if "
567 "they had been specified in the correct order."),
572 /* Finally add these to the linked list of aggregation
574 for (i = 0; i < n_dest; i++)
576 struct agr_var *v = xmalloc (sizeof *v);
578 /* Add variable to chain. */
579 if (agr->agr_vars != NULL)
587 /* Create the target variable in the aggregate
590 struct variable *destvar;
592 v->function = func_index;
598 if (var_is_alpha (src[i]))
600 v->function |= FSTRING;
601 v->string = xmalloc (var_get_width (src[i]));
604 if (function->alpha_type == VAR_STRING)
605 destvar = dict_clone_var (agr->dict, v->src, dest[i]);
608 assert (var_is_numeric (v->src)
609 || function->alpha_type == VAR_NUMERIC);
610 destvar = dict_create_var (agr->dict, dest[i], 0);
614 if ((func_index == N || func_index == NMISS)
615 && dict_get_weight (dict) != NULL)
616 f = fmt_for_output (FMT_F, 8, 2);
618 f = function->format;
619 var_set_both_formats (destvar, &f);
625 destvar = dict_create_var (agr->dict, dest[i], 0);
626 if (func_index == N_NO_VARS && dict_get_weight (dict) != NULL)
627 f = fmt_for_output (FMT_F, 8, 2);
629 f = function->format;
630 var_set_both_formats (destvar, &f);
635 msg (SE, _("Variable name %s is not unique within the "
636 "aggregate file dictionary, which contains "
637 "the aggregate variables and the break "
645 var_set_label (destvar, dest_label[i]);
650 v->include_missing = include_missing;
656 if (var_is_numeric (v->src))
657 for (j = 0; j < function->n_args; j++)
658 v->arg[j].f = arg[j].f;
660 for (j = 0; j < function->n_args; j++)
661 v->arg[j].c = xstrdup (arg[j].c);
665 if (src != NULL && var_is_alpha (src[0]))
666 for (i = 0; i < function->n_args; i++)
676 if (!lex_match (lexer, '/'))
678 if (lex_token (lexer) == '.')
681 lex_error (lexer, "expecting end of command");
687 ds_destroy (&function_name);
688 for (i = 0; i < n_dest; i++)
691 free (dest_label[i]);
697 if (src && n_src && var_is_alpha (src[0]))
698 for (i = 0; i < function->n_args; i++)
711 agr_destroy (struct agr_proc *agr)
713 struct agr_var *iter, *next;
715 any_writer_close (agr->writer);
716 if (agr->sort != NULL)
717 sort_destroy_criteria (agr->sort);
718 free (agr->break_vars);
719 case_destroy (&agr->break_case);
720 for (iter = agr->agr_vars; iter; iter = next)
724 if (iter->function & FSTRING)
729 n_args = agr_func_tab[iter->function & FUNC].n_args;
730 for (i = 0; i < n_args; i++)
731 free (iter->arg[i].c);
734 else if (iter->function == SD)
735 moments1_destroy (iter->moments);
738 if (agr->dict != NULL)
739 dict_destroy (agr->dict);
741 case_destroy (&agr->agr_case);
746 static void accumulate_aggregate_info (struct agr_proc *,
747 const struct ccase *);
748 static void dump_aggregate_info (struct agr_proc *, struct ccase *);
750 /* Processes a single case INPUT for aggregation. If output is
751 warranted, writes it to OUTPUT and returns true.
752 Otherwise, returns false and OUTPUT is unmodified. */
754 aggregate_single_case (struct agr_proc *agr,
755 const struct ccase *input, struct ccase *output)
757 bool finished_group = false;
759 if (agr->case_cnt++ == 0)
760 initialize_aggregate_info (agr, input);
761 else if (case_compare (&agr->break_case, input,
762 agr->break_vars, agr->break_var_cnt))
764 dump_aggregate_info (agr, output);
765 finished_group = true;
767 initialize_aggregate_info (agr, input);
770 accumulate_aggregate_info (agr, input);
771 return finished_group;
774 /* Accumulates aggregation data from the case INPUT. */
776 accumulate_aggregate_info (struct agr_proc *agr,
777 const struct ccase *input)
779 struct agr_var *iter;
781 bool bad_warn = true;
783 weight = dict_get_case_weight (agr->src_dict, input, &bad_warn);
785 for (iter = agr->agr_vars; iter; iter = iter->next)
788 const union value *v = case_data (input, iter->src);
789 int src_width = var_get_width (iter->src);
791 if (iter->include_missing
792 ? var_is_numeric (iter->src) && v->f == SYSMIS
793 : var_is_value_missing (iter->src, v))
795 switch (iter->function)
798 case NMISS | FSTRING:
799 iter->dbl[0] += weight;
802 case NUMISS | FSTRING:
810 /* This is horrible. There are too many possibilities. */
811 switch (iter->function)
814 iter->dbl[0] += v->f * weight;
818 iter->dbl[0] += v->f * weight;
819 iter->dbl[1] += weight;
822 moments1_add (iter->moments, v->f, weight);
825 iter->dbl[0] = MAX (iter->dbl[0], v->f);
829 if (memcmp (iter->string, v->s, src_width) < 0)
830 memcpy (iter->string, v->s, src_width);
834 iter->dbl[0] = MIN (iter->dbl[0], v->f);
838 if (memcmp (iter->string, v->s, src_width) > 0)
839 memcpy (iter->string, v->s, src_width);
844 if (v->f > iter->arg[0].f)
845 iter->dbl[0] += weight;
846 iter->dbl[1] += weight;
850 if (memcmp (iter->arg[0].c, v->s, src_width) < 0)
851 iter->dbl[0] += weight;
852 iter->dbl[1] += weight;
856 if (v->f < iter->arg[0].f)
857 iter->dbl[0] += weight;
858 iter->dbl[1] += weight;
862 if (memcmp (iter->arg[0].c, v->s, src_width) > 0)
863 iter->dbl[0] += weight;
864 iter->dbl[1] += weight;
868 if (iter->arg[0].f <= v->f && v->f <= iter->arg[1].f)
869 iter->dbl[0] += weight;
870 iter->dbl[1] += weight;
874 if (memcmp (iter->arg[0].c, v->s, src_width) <= 0
875 && memcmp (iter->arg[1].c, v->s, src_width) >= 0)
876 iter->dbl[0] += weight;
877 iter->dbl[1] += weight;
881 if (iter->arg[0].f > v->f || v->f > iter->arg[1].f)
882 iter->dbl[0] += weight;
883 iter->dbl[1] += weight;
887 if (memcmp (iter->arg[0].c, v->s, src_width) > 0
888 || memcmp (iter->arg[1].c, v->s, src_width) < 0)
889 iter->dbl[0] += weight;
890 iter->dbl[1] += weight;
894 iter->dbl[0] += weight;
907 case FIRST | FSTRING:
910 memcpy (iter->string, v->s, src_width);
919 memcpy (iter->string, v->s, src_width);
923 case NMISS | FSTRING:
925 case NUMISS | FSTRING:
926 /* Our value is not missing or it would have been
927 caught earlier. Nothing to do. */
933 switch (iter->function)
936 iter->dbl[0] += weight;
947 /* We've come to a record that differs from the previous in one or
948 more of the break variables. Make an output record from the
949 accumulated statistics in the OUTPUT case. */
951 dump_aggregate_info (struct agr_proc *agr, struct ccase *output)
957 for (i = 0; i < agr->break_var_cnt; i++)
959 struct variable *v = agr->break_vars[i];
960 size_t value_cnt = var_get_value_cnt (v);
961 memcpy (case_data_rw_idx (output, value_idx),
962 case_data (&agr->break_case, v),
963 sizeof (union value) * value_cnt);
964 value_idx += value_cnt;
971 for (i = agr->agr_vars; i; i = i->next)
973 union value *v = case_data_rw (output, i->dest);
975 if (agr->missing == COLUMNWISE && i->missing != 0
976 && (i->function & FUNC) != N && (i->function & FUNC) != NU
977 && (i->function & FUNC) != NMISS && (i->function & FUNC) != NUMISS)
979 if (var_is_alpha (i->dest))
980 memset (v->s, ' ', var_get_width (i->dest));
989 v->f = i->int1 ? i->dbl[0] : SYSMIS;
992 v->f = i->dbl[1] != 0.0 ? i->dbl[0] / i->dbl[1] : SYSMIS;
998 /* FIXME: we should use two passes. */
999 moments1_calculate (i->moments, NULL, NULL, &variance,
1001 if (variance != SYSMIS)
1002 v->f = sqrt (variance);
1009 v->f = i->int1 ? i->dbl[0] : SYSMIS;
1014 memcpy (v->s, i->string, var_get_width (i->dest));
1016 memset (v->s, ' ', var_get_width (i->dest));
1025 case FOUT | FSTRING:
1026 v->f = i->dbl[1] ? i->dbl[0] / i->dbl[1] : SYSMIS;
1035 case POUT | FSTRING:
1036 v->f = i->dbl[1] ? i->dbl[0] / i->dbl[1] * 100.0 : SYSMIS;
1048 v->f = i->int1 ? i->dbl[0] : SYSMIS;
1050 case FIRST | FSTRING:
1051 case LAST | FSTRING:
1053 memcpy (v->s, i->string, var_get_width (i->dest));
1055 memset (v->s, ' ', var_get_width (i->dest));
1064 case NMISS | FSTRING:
1068 case NUMISS | FSTRING:
1078 /* Resets the state for all the aggregate functions. */
1080 initialize_aggregate_info (struct agr_proc *agr, const struct ccase *input)
1082 struct agr_var *iter;
1084 case_destroy (&agr->break_case);
1085 case_clone (&agr->break_case, input);
1087 for (iter = agr->agr_vars; iter; iter = iter->next)
1090 iter->dbl[0] = iter->dbl[1] = iter->dbl[2] = 0.0;
1091 iter->int1 = iter->int2 = 0;
1092 switch (iter->function)
1095 iter->dbl[0] = DBL_MAX;
1098 memset (iter->string, 255, var_get_width (iter->src));
1101 iter->dbl[0] = -DBL_MAX;
1104 memset (iter->string, 0, var_get_width (iter->src));
1107 if (iter->moments == NULL)
1108 iter->moments = moments1_create (MOMENT_VARIANCE);
1110 moments1_clear (iter->moments);