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. */
41 struct sort_key *keys;
45 /* Creates and returns a new case ordering for comparing cases
46 that represent dictionary DICT. The case ordering initially
47 contains no variables, so that all cases will compare as
49 struct case_ordering *
50 case_ordering_create (void)
52 struct case_ordering *co = xmalloc (sizeof *co);
58 /* Creates and returns a clone of case ordering ORIG. */
59 struct case_ordering *
60 case_ordering_clone (const struct case_ordering *orig)
62 struct case_ordering *co = xmalloc (sizeof *co);
63 co->keys = xmemdup (orig->keys, orig->key_cnt * sizeof *orig->keys);
64 co->key_cnt = orig->key_cnt;
68 /* Destroys case ordering CO. */
70 case_ordering_destroy (struct case_ordering *co)
79 /* Compares cases A and B given case ordering CO and returns a
80 strcmp()-type result. */
82 case_ordering_compare_cases (const struct ccase *a, const struct ccase *b,
83 const struct case_ordering *co)
87 for (i = 0; i < co->key_cnt; i++)
89 const struct sort_key *key = &co->keys[i];
90 int width = var_get_width (key->var);
95 double af = case_num (a, key->var);
96 double bf = case_num (b, key->var);
99 cmp = af > bf ? 1 : -1;
103 const char *as = case_str (a, key->var);
104 const char *bs = case_str (b, key->var);
105 cmp = memcmp (as, bs, width);
110 return key->dir == SRT_ASCEND ? cmp : -cmp;
115 /* Adds VAR to case ordering CO as an additional sort key in sort
116 direction DIR. Returns true if successful, false if VAR was
117 already part of the ordering for CO. */
119 case_ordering_add_var (struct case_ordering *co,
120 const struct variable *var, enum sort_direction dir)
122 struct sort_key *key;
125 for (i = 0; i < co->key_cnt; i++)
126 if (var_get_case_index (co->keys[i].var) == var_get_case_index (var))
129 co->keys = xnrealloc (co->keys, co->key_cnt + 1, sizeof *co->keys);
130 key = &co->keys[co->key_cnt++];
136 /* Returns the number of variables used for ordering within
139 case_ordering_get_var_cnt (const struct case_ordering *co)
144 /* Returns sort variable IDX within CO. An IDX of 0 returns the
145 primary sort key (the one added first), an IDX of 1 returns
146 the secondary sort key, and so on. IDX must be less than the
147 number of sort variables. */
148 const struct variable *
149 case_ordering_get_var (const struct case_ordering *co, size_t idx)
151 assert (idx < co->key_cnt);
152 return co->keys[idx].var;
155 /* Returns the sort direction for sort variable IDX within CO. */
157 case_ordering_get_direction (const struct case_ordering *co, size_t idx)
159 assert (idx < co->key_cnt);
160 return co->keys[idx].dir;
163 /* Stores an array listing all of the variables used for sorting
164 within CO into *VARS and the number of variables into
165 *VAR_CNT. The caller is responsible for freeing *VARS when it
166 is no longer needed. */
168 case_ordering_get_vars (const struct case_ordering *co,
169 const struct variable ***vars, size_t *var_cnt)
173 *var_cnt = co->key_cnt;
174 *vars = xnmalloc (*var_cnt, sizeof **vars);
175 for (i = 0; i < co->key_cnt; i++)
176 (*vars)[i] = co->keys[i].var;