1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2008, 2009 Free Software Foundation, Inc.
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.
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.
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/>. */
18 #include <data/subcase.h>
20 #include <data/case.h>
21 #include <data/variable.h>
22 #include <libpspp/assertion.h>
26 /* Initializes SC as a subcase that contains no fields. */
28 subcase_init_empty (struct subcase *sc)
35 /* Initializes SC as a subcase with fields extracted from the
36 N_VARS variables in VARS, with ascending sort order. */
38 subcase_init_vars (struct subcase *sc,
39 const struct variable *const *vars, size_t n_vars)
43 sc->fields = xnmalloc (n_vars, sizeof *sc->fields);
44 sc->n_fields = n_vars;
46 for (i = 0; i < n_vars; i++)
48 struct subcase_field *field = &sc->fields[i];
49 field->case_index = var_get_case_index (vars[i]);
50 field->width = var_get_width (vars[i]);
51 field->direction = SC_ASCEND;
52 sc->n_values += value_cnt_from_width (field->width);
56 /* Initializes SC as a subcase with a single field extracted
57 from VAR, with the sort order specified by DIRECTION. */
59 subcase_init_var (struct subcase *sc, const struct variable *var,
60 enum subcase_direction direction)
62 subcase_init_empty (sc);
63 subcase_add_var (sc, var, direction);
66 /* Removes all the fields from SC. */
68 subcase_clear (struct subcase *sc)
74 /* Initializes SC with the same fields as ORIG. */
76 subcase_clone (struct subcase *sc, const struct subcase *orig)
78 sc->fields = xmemdup (orig->fields, orig->n_fields * sizeof *orig->fields);
79 sc->n_fields = orig->n_fields;
80 sc->n_values = orig->n_values;
83 /* Frees the memory owned by SC (but not SC itself). */
85 subcase_destroy (struct subcase *sc)
90 /* Add a field for VAR to SC, with DIRECTION as the sort order.
91 Returns true if successful, false if VAR already has a field
94 subcase_add_var (struct subcase *sc, const struct variable *var,
95 enum subcase_direction direction)
97 size_t case_index = var_get_case_index (var);
98 struct subcase_field *field;
101 for (i = 0; i < sc->n_fields; i++)
102 if (sc->fields[i].case_index == case_index)
105 sc->fields = xnrealloc (sc->fields, sc->n_fields + 1, sizeof *sc->fields);
106 field = &sc->fields[sc->n_fields++];
107 field->case_index = case_index;
108 field->width = var_get_width (var);
109 field->direction = direction;
110 sc->n_values += value_cnt_from_width (field->width);
114 /* Returns true if and only if A and B are conformable, which
115 means that they have the same number of fields and that each
116 corresponding field in A and B have the same width. */
118 subcase_conformable (const struct subcase *a, const struct subcase *b)
124 if (a->n_values != b->n_values || a->n_fields != b->n_fields)
126 for (i = 0; i < a->n_fields; i++)
127 if (a->fields[i].width != b->fields[i].width)
132 /* Copies the fields represented by SC from C into VALUES.
133 VALUES must have space for at least subcase_get_n_values(SC)
136 subcase_extract (const struct subcase *sc, const struct ccase *c,
137 union value values[])
141 for (i = 0; i < sc->n_fields; i++)
143 const struct subcase_field *field = &sc->fields[i];
144 value_copy (values, case_data_idx (c, field->case_index), field->width);
145 values += value_cnt_from_width (field->width);
149 /* Copies the data in VALUES into the fields in C represented by
150 SC. VALUES must have at least subcase_get_n_values(SC) array
151 elements, and C must be large enough to contain all the fields
154 subcase_inject (const struct subcase *sc,
155 const union value values[], struct ccase *c)
159 for (i = 0; i < sc->n_fields; i++)
161 const struct subcase_field *field = &sc->fields[i];
162 value_copy (case_data_rw_idx (c, field->case_index), values,
164 values += value_cnt_from_width (field->width);
168 /* Copies the fields in SRC represented by SRC_SC into the
169 corresponding fields in DST respresented by DST_SC. SRC_SC
170 and DST_SC must be conformable (as tested by
171 subcase_conformable()).
173 DST must not be shared. */
175 subcase_copy (const struct subcase *src_sc, const struct ccase *src,
176 const struct subcase *dst_sc, struct ccase *dst)
180 expensive_assert (subcase_conformable (src_sc, dst_sc));
181 for (i = 0; i < src_sc->n_fields; i++)
183 const struct subcase_field *src_field = &src_sc->fields[i];
184 const struct subcase_field *dst_field = &dst_sc->fields[i];
185 value_copy (case_data_rw_idx (dst, dst_field->case_index),
186 case_data_idx (src, src_field->case_index),
191 /* Compares the fields in A specified in A_SC against the fields
192 in B specified in B_SC. Returns -1, 0, or 1 if A's fields are
193 lexicographically less than, equal to, or greater than B's
194 fields, respectively.
196 A_SC and B_SC must be conformable (as tested by
197 subcase_conformable()). */
199 subcase_compare_3way (const struct subcase *a_sc, const struct ccase *a,
200 const struct subcase *b_sc, const struct ccase *b)
204 expensive_assert (subcase_conformable (a_sc, b_sc));
205 for (i = 0; i < a_sc->n_fields; i++)
207 const struct subcase_field *a_field = &a_sc->fields[i];
208 const struct subcase_field *b_field = &b_sc->fields[i];
209 int cmp = value_compare_3way (case_data_idx (a, a_field->case_index),
210 case_data_idx (b, b_field->case_index),
213 return a_field->direction == SC_ASCEND ? cmp : -cmp;
218 /* Compares the values in A against the values in B specified by
219 SC's fields. Returns -1, 0, or 1 if A's values are
220 lexicographically less than, equal to, or greater than B's
221 values, respectively. */
223 subcase_compare_3way_xc (const struct subcase *sc,
224 const union value a[], const struct ccase *b)
228 for (i = 0; i < sc->n_fields; i++)
230 const struct subcase_field *field = &sc->fields[i];
231 int cmp = value_compare_3way (a, case_data_idx (b, field->case_index),
234 return field->direction == SC_ASCEND ? cmp : -cmp;
235 a += value_cnt_from_width (field->width);
240 /* Compares the values in A specified by SC's fields against the
241 values in B. Returns -1, 0, or 1 if A's values are
242 lexicographically less than, equal to, or greater than B's
243 values, respectively. */
245 subcase_compare_3way_cx (const struct subcase *sc,
246 const struct ccase *a, const union value b[])
248 return -subcase_compare_3way_xc (sc, b, a);
251 /* Compares the values in A against the values in B, using SC to
252 obtain the number and width of each value. Returns -1, 0, or
253 1 if A's values are lexicographically less than, equal to, or
254 greater than B's values, respectively. */
256 subcase_compare_3way_xx (const struct subcase *sc,
257 const union value a[], const union value b[])
261 for (i = 0; i < sc->n_fields; i++)
263 const struct subcase_field *field = &sc->fields[i];
267 cmp = value_compare_3way (a, b, field->width);
269 return field->direction == SC_ASCEND ? cmp : -cmp;
271 n_values = value_cnt_from_width (field->width);
278 /* Compares the fields in A specified in A_SC against the fields
279 in B specified in B_SC. Returns true if the fields' values
280 are equal, false otherwise.
282 A_SC and B_SC must be conformable (as tested by
283 subcase_conformable()). */
285 subcase_equal (const struct subcase *a_sc, const struct ccase *a,
286 const struct subcase *b_sc, const struct ccase *b)
288 return subcase_compare_3way (a_sc, a, b_sc, b) == 0;
291 /* Compares the values in A against the values in B specified by
292 SC's fields. Returns true if A's values are equal to B's
293 values, otherwise false. */
295 subcase_equal_xc (const struct subcase *sc,
296 const union value a[], const struct ccase *b)
298 return subcase_compare_3way_xc (sc, a, b) == 0;
301 /* Compares the values in A specified by SC's fields against the
302 values in B. Returns true if A's values are equal to B's
303 values, otherwise false. */
305 subcase_equal_cx (const struct subcase *sc,
306 const struct ccase *a, const union value b[])
308 return subcase_compare_3way_cx (sc, a, b) == 0;
311 /* Compares the values in A against the values in B, using SC to
312 obtain the number and width of each value. Returns true if
313 A's values are equal to B's values, otherwise false. */
315 subcase_equal_xx (const struct subcase *sc,
316 const union value a[], const union value b[])
318 return subcase_compare_3way_xx (sc, a, b) == 0;