1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2007 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/>. */
19 #include <data/case-ordering.h>
25 #include <data/dictionary.h>
26 #include <data/variable.h>
30 /* One key used for sorting. */
33 const struct variable *var; /* Variable. */
34 enum sort_direction dir; /* Sort direction. */
37 /* A set of criteria for ordering cases. */
40 size_t value_cnt; /* Number of `union value's per case. */
43 struct sort_key *keys;
47 /* Creates and returns a new case ordering for comparing cases
48 that represent dictionary DICT. The case ordering initially
49 contains no variables, so that all cases will compare as
51 struct case_ordering *
52 case_ordering_create (const struct dictionary *dict)
54 struct case_ordering *co = xmalloc (sizeof *co);
55 co->value_cnt = dict_get_next_value_idx (dict);
61 /* Creates and returns a clone of case ordering ORIG. */
62 struct case_ordering *
63 case_ordering_clone (const struct case_ordering *orig)
65 struct case_ordering *co = xmalloc (sizeof *co);
66 co->value_cnt = orig->value_cnt;
67 co->keys = xmemdup (orig->keys, orig->key_cnt * sizeof *orig->keys);
68 co->key_cnt = orig->key_cnt;
72 /* Destroys case ordering CO. */
74 case_ordering_destroy (struct case_ordering *co)
83 /* Returns the number of `union value's in the cases that case
84 ordering CO compares (taken from the dictionary used to
87 case_ordering_get_value_cnt (const struct case_ordering *co)
92 /* Compares cases A and B given case ordering CO and returns a
93 strcmp()-type result. */
95 case_ordering_compare_cases (const struct ccase *a, const struct ccase *b,
96 const struct case_ordering *co)
100 for (i = 0; i < co->key_cnt; i++)
102 const struct sort_key *key = &co->keys[i];
103 int width = var_get_width (key->var);
108 double af = case_num (a, key->var);
109 double bf = case_num (b, key->var);
112 cmp = af > bf ? 1 : -1;
116 const char *as = case_str (a, key->var);
117 const char *bs = case_str (b, key->var);
118 cmp = memcmp (as, bs, width);
123 return key->dir == SRT_ASCEND ? cmp : -cmp;
128 /* Adds VAR to case ordering CO as an additional sort key in sort
129 direction DIR. Returns true if successful, false if VAR was
130 already part of the ordering for CO. */
132 case_ordering_add_var (struct case_ordering *co,
133 const struct variable *var, enum sort_direction dir)
135 struct sort_key *key;
138 for (i = 0; i < co->key_cnt; i++)
139 if (var_get_case_index (co->keys[i].var) == var_get_case_index (var))
142 co->keys = xnrealloc (co->keys, co->key_cnt + 1, sizeof *co->keys);
143 key = &co->keys[co->key_cnt++];
149 /* Returns the number of variables used for ordering within
152 case_ordering_get_var_cnt (const struct case_ordering *co)
157 /* Returns sort variable IDX within CO. An IDX of 0 returns the
158 primary sort key (the one added first), an IDX of 1 returns
159 the secondary sort key, and so on. IDX must be less than the
160 number of sort variables. */
161 const struct variable *
162 case_ordering_get_var (const struct case_ordering *co, size_t idx)
164 assert (idx < co->key_cnt);
165 return co->keys[idx].var;
168 /* Returns the sort direction for sort variable IDX within CO. */
170 case_ordering_get_direction (const struct case_ordering *co, size_t idx)
172 assert (idx < co->key_cnt);
173 return co->keys[idx].dir;
176 /* Stores an array listing all of the variables used for sorting
177 within CO into *VARS and the number of variables into
178 *VAR_CNT. The caller is responsible for freeing *VARS when it
179 is no longer needed. */
181 case_ordering_get_vars (const struct case_ordering *co,
182 const struct variable ***vars, size_t *var_cnt)
186 *var_cnt = co->key_cnt;
187 *vars = xnmalloc (*var_cnt, sizeof **vars);
188 for (i = 0; i < co->key_cnt; i++)
189 (*vars)[i] = co->keys[i].var;