1 /* PSPP - computes sample statistics.
2 Copyright (C) 2004 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
24 #include <libpspp/alloc.h>
25 #include <libpspp/str.h>
37 /* Changes C not to share data with any other case.
38 C must be a case with a reference count greater than 1.
39 There should be no reason for external code to call this
40 function explicitly. It will be called automatically when
43 case_unshare (struct ccase *c)
47 assert (c->case_data->ref_cnt > 1);
51 case_create (c, c->case_data->value_cnt);
52 memcpy (c->case_data->values, cd->values,
53 sizeof *cd->values * cd->value_cnt);
56 /* Returns the number of bytes needed by a case with VALUE_CNT
59 case_size (size_t value_cnt)
61 return (offsetof (struct case_data, values)
62 + value_cnt * sizeof (union value));
66 /* Initializes C as a null case. */
68 case_nullify (struct ccase *c)
72 #endif /* DEBUGGING */
75 /* Returns true iff C is a null case. */
77 case_is_null (const struct ccase *c)
79 return c->case_data == NULL;
81 #endif /* DEBUGGING */
83 /* Initializes C as a new case that can store VALUE_CNT values.
84 The values have indeterminate contents until explicitly
87 case_create (struct ccase *c, size_t value_cnt)
89 if (!case_try_create (c, value_cnt))
94 /* Initializes CLONE as a copy of ORIG. */
96 case_clone (struct ccase *clone, const struct ccase *orig)
98 assert (orig->case_data->ref_cnt > 0);
102 orig->case_data->ref_cnt++;
104 #endif /* DEBUGGING */
107 /* Replaces DST by SRC and nullifies SRC.
108 DST and SRC must be initialized cases at entry. */
110 case_move (struct ccase *dst, struct ccase *src)
112 assert (src->case_data->ref_cnt > 0);
120 #endif /* DEBUGGING */
123 /* Destroys case C. */
125 case_destroy (struct ccase *c)
127 struct case_data *cd;
132 if (cd != NULL && --cd->ref_cnt == 0)
134 memset (cd->values, 0xcc, sizeof *cd->values * cd->value_cnt);
135 cd->value_cnt = 0xdeadbeef;
139 #endif /* DEBUGGING */
141 /* Resizes case C from OLD_CNT to NEW_CNT values. */
143 case_resize (struct ccase *c, size_t old_cnt, size_t new_cnt)
147 case_create (&new, new_cnt);
148 case_copy (&new, 0, c, 0, old_cnt < new_cnt ? old_cnt : new_cnt);
153 /* Swaps cases A and B. */
155 case_swap (struct ccase *a, struct ccase *b)
157 struct case_data *t = a->case_data;
158 a->case_data = b->case_data;
162 /* Attempts to create C as a new case that holds VALUE_CNT
163 values. Returns true if successful, false if memory
164 allocation failed. */
166 case_try_create (struct ccase *c, size_t value_cnt)
168 c->case_data = malloc (case_size (value_cnt));
169 if (c->case_data != NULL)
171 c->case_data->value_cnt = value_cnt;
172 c->case_data->ref_cnt = 1;
179 /* Tries to initialize CLONE as a copy of ORIG.
180 Returns true if successful, false if memory allocation
183 case_try_clone (struct ccase *clone, const struct ccase *orig)
185 case_clone (clone, orig);
190 /* Copies VALUE_CNT values from SRC (starting at SRC_IDX) to DST
191 (starting at DST_IDX). */
193 case_copy (struct ccase *dst, size_t dst_idx,
194 const struct ccase *src, size_t src_idx,
197 assert (dst->case_data->ref_cnt > 0);
198 assert (dst_idx + value_cnt <= dst->case_data->value_cnt);
200 assert (src->case_data->ref_cnt > 0);
201 assert (src_idx + value_cnt <= src->case_data->value_cnt);
203 if (dst->case_data != src->case_data || dst_idx != src_idx)
205 if (dst->case_data->ref_cnt > 1)
207 memmove (dst->case_data->values + dst_idx,
208 src->case_data->values + src_idx,
209 sizeof *dst->case_data->values * value_cnt);
212 #endif /* DEBUGGING */
215 /* Copies case C to OUTPUT.
216 OUTPUT_SIZE is the number of `union values' in OUTPUT,
217 which must match the number of `union values' in C. */
219 case_to_values (const struct ccase *c, union value *output,
220 size_t output_size UNUSED)
222 assert (c->case_data->ref_cnt > 0);
223 assert (output_size == c->case_data->value_cnt);
224 assert (output != NULL || output_size == 0);
226 memcpy (output, c->case_data->values,
227 c->case_data->value_cnt * sizeof *output);
229 #endif /* DEBUGGING */
232 /* Copies INPUT into case C.
233 INPUT_SIZE is the number of `union values' in INPUT,
234 which must match the number of `union values' in C. */
236 case_from_values (struct ccase *c, const union value *input,
237 size_t input_size UNUSED)
240 assert (c->case_data != NULL);
241 assert (c->case_data->ref_cnt > 0);
242 assert (input_size == c->case_data->value_cnt);
243 assert (input != NULL || input_size == 0);
245 if (c->case_data->ref_cnt > 1)
247 memcpy (c->case_data->values, input,
248 c->case_data->value_cnt * sizeof *input);
250 #endif /* DEBUGGING */
253 /* Returns a pointer to the `union value' used for the
254 element of C numbered IDX.
255 The caller must not modify the returned data. */
257 case_data_idx (const struct ccase *c, size_t idx)
260 assert (c->case_data != NULL);
261 assert (c->case_data->ref_cnt > 0);
262 assert (idx < c->case_data->value_cnt);
264 return &c->case_data->values[idx];
266 #endif /* DEBUGGING */
269 /* Returns the numeric value of the `union value' in C numbered
272 case_num_idx (const struct ccase *c, size_t idx)
275 assert (c->case_data != NULL);
276 assert (c->case_data->ref_cnt > 0);
277 assert (idx < c->case_data->value_cnt);
279 return c->case_data->values[idx].f;
281 #endif /* DEBUGGING */
284 /* Returns the string value of the `union value' in C numbered
286 (Note that the value is not null-terminated.)
287 The caller must not modify the return value. */
289 case_str_idx (const struct ccase *c, size_t idx)
292 assert (c->case_data != NULL);
293 assert (c->case_data->ref_cnt > 0);
294 assert (idx < c->case_data->value_cnt);
296 return c->case_data->values[idx].s;
298 #endif /* DEBUGGING */
301 /* Returns a pointer to the `union value' used for the
302 element of C numbered IDX.
303 The caller is allowed to modify the returned data. */
305 case_data_rw_idx (struct ccase *c, size_t idx)
308 assert (c->case_data != NULL);
309 assert (c->case_data->ref_cnt > 0);
310 assert (idx < c->case_data->value_cnt);
312 if (c->case_data->ref_cnt > 1)
314 return &c->case_data->values[idx];
316 #endif /* DEBUGGING */
318 /* Compares the values of the VAR_CNT variables in VP
319 in cases A and B and returns a strcmp()-type result. */
321 case_compare (const struct ccase *a, const struct ccase *b,
322 struct variable *const *vp, size_t var_cnt)
324 return case_compare_2dict (a, b, vp, vp, var_cnt);
327 /* Compares the values of the VAR_CNT variables in VAP in case CA
328 to the values of the VAR_CNT variables in VBP in CB
329 and returns a strcmp()-type result. */
331 case_compare_2dict (const struct ccase *ca, const struct ccase *cb,
332 struct variable *const *vap, struct variable *const *vbp,
335 for (; var_cnt-- > 0; vap++, vbp++)
337 const struct variable *va = *vap;
338 const struct variable *vb = *vbp;
340 assert (var_get_width (va) == var_get_width (vb));
342 if (var_get_width (va) == 0)
344 double af = case_num (ca, va);
345 double bf = case_num (cb, vb);
348 return af > bf ? 1 : -1;
352 const char *as = case_str (ca, va);
353 const char *bs = case_str (cb, vb);
354 int cmp = memcmp (as, bs, var_get_width (va));
363 /* Returns a pointer to the array of `union value's used for C.
364 The caller must *not* modify the returned data.
366 NOTE: This function breaks the case abstraction. It should
367 *not* be used often. Prefer the other case functions. */
369 case_data_all (const struct ccase *c)
372 assert (c->case_data != NULL);
373 assert (c->case_data->ref_cnt > 0);
375 return c->case_data->values;
378 /* Returns a pointer to the array of `union value's used for C.
379 The caller is allowed to modify the returned data.
381 NOTE: This function breaks the case abstraction. It should
382 *not* be used often. Prefer the other case functions. */
384 case_data_all_rw (struct ccase *c)
387 assert (c->case_data != NULL);
388 assert (c->case_data->ref_cnt > 0);
390 if (c->case_data->ref_cnt > 1)
392 return c->case_data->values;