From 576237eae45fe54ea5ee41d44e257f6aa7e88861 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Thu, 7 Jun 2007 05:38:56 +0000 Subject: [PATCH] Add interface to lexicographical ordering of cases. --- src/data/ChangeLog | 10 +++ src/data/automake.mk | 2 + src/data/case-ordering.c | 168 +++++++++++++++++++++++++++++++++++++++ src/data/case-ordering.h | 51 ++++++++++++ 4 files changed, 231 insertions(+) create mode 100644 src/data/case-ordering.c create mode 100644 src/data/case-ordering.h diff --git a/src/data/ChangeLog b/src/data/ChangeLog index 54a53a4d..9ab2176a 100644 --- a/src/data/ChangeLog +++ b/src/data/ChangeLog @@ -1,3 +1,13 @@ +2007-06-06 Ben Pfaff + + Add interface to lexicographical ordering of cases. + + * automake.mk: Add new files. + + * case-ordering.c: New file. + + * case-ordering.h: New file. + 2007-06-06 Ben Pfaff Add casereaders and casewriters, the basis of the new data processing diff --git a/src/data/automake.mk b/src/data/automake.mk index 3f2b503f..3b97ed90 100644 --- a/src/data/automake.mk +++ b/src/data/automake.mk @@ -8,6 +8,8 @@ src_data_libdata_a_SOURCES = \ src/data/any-writer.h \ src/data/calendar.c \ src/data/calendar.h \ + src/data/case-ordering.c \ + src/data/case-ordering.h \ src/data/case-sink.c \ src/data/case-sink.h \ src/data/case-source.c \ diff --git a/src/data/case-ordering.c b/src/data/case-ordering.c new file mode 100644 index 00000000..54f1c7f2 --- /dev/null +++ b/src/data/case-ordering.c @@ -0,0 +1,168 @@ +/* PSPP - computes sample statistics. + Copyright (C) 2007 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#include + +#include + +#include +#include +#include + +#include +#include + +#include "xalloc.h" + +/* One key used for sorting. */ +struct sort_key + { + struct variable *var; /* Variable. */ + enum sort_direction dir; /* Sort direction. */ + }; + +/* A set of criteria for ordering cases. */ +struct case_ordering + { + size_t value_cnt; /* Number of `union value's per case. */ + + /* Sort keys. */ + struct sort_key *keys; + size_t key_cnt; + }; + +struct case_ordering * +case_ordering_create (const struct dictionary *dict) +{ + struct case_ordering *co = xmalloc (sizeof *co); + co->value_cnt = dict_get_next_value_idx (dict); + co->keys = NULL; + co->key_cnt = 0; + return co; +} + +struct case_ordering * +case_ordering_clone (const struct case_ordering *orig) +{ + struct case_ordering *co = xmalloc (sizeof *co); + co->value_cnt = orig->value_cnt; + co->keys = xmemdup (orig->keys, orig->key_cnt * sizeof *orig->keys); + co->key_cnt = orig->key_cnt; + return co; +} + +void +case_ordering_destroy (struct case_ordering *co) +{ + if (co != NULL) + { + free (co->keys); + free (co); + } +} + +size_t +case_ordering_get_value_cnt (const struct case_ordering *co) +{ + return co->value_cnt; +} + +int +case_ordering_compare_cases (const struct ccase *a, const struct ccase *b, + const struct case_ordering *co) +{ + size_t i; + + for (i = 0; i < co->key_cnt; i++) + { + const struct sort_key *key = &co->keys[i]; + int width = var_get_width (key->var); + int cmp; + + if (width == 0) + { + double af = case_num (a, key->var); + double bf = case_num (b, key->var); + if (af == bf) + continue; + cmp = af > bf ? 1 : -1; + } + else + { + const char *as = case_str (a, key->var); + const char *bs = case_str (b, key->var); + cmp = memcmp (as, bs, width); + if (cmp == 0) + continue; + } + + return key->dir == SRT_ASCEND ? cmp : -cmp; + } + return 0; +} + +bool +case_ordering_add_var (struct case_ordering *co, + struct variable *var, enum sort_direction dir) +{ + struct sort_key *key; + size_t i; + + for (i = 0; i < co->key_cnt; i++) + if (var_get_case_index (co->keys[i].var) == var_get_case_index (var)) + return false; + + co->keys = xnrealloc (co->keys, co->key_cnt + 1, sizeof *co->keys); + key = &co->keys[co->key_cnt++]; + key->var = var; + key->dir = dir; + return true; +} + +size_t +case_ordering_get_var_cnt (const struct case_ordering *co) +{ + return co->key_cnt; +} + +struct variable * +case_ordering_get_var (const struct case_ordering *co, size_t idx) +{ + assert (idx < co->key_cnt); + return co->keys[idx].var; +} + +enum sort_direction +case_ordering_get_direction (const struct case_ordering *co, size_t idx) +{ + assert (idx < co->key_cnt); + return co->keys[idx].dir; +} + +void +case_ordering_get_vars (const struct case_ordering *co, + struct variable ***vars, size_t *var_cnt) +{ + size_t i; + + *var_cnt = co->key_cnt; + *vars = xnmalloc (*var_cnt, sizeof **vars); + for (i = 0; i < co->key_cnt; i++) + (*vars)[i] = co->keys[i].var; +} + diff --git a/src/data/case-ordering.h b/src/data/case-ordering.h new file mode 100644 index 00000000..f1b6c30f --- /dev/null +++ b/src/data/case-ordering.h @@ -0,0 +1,51 @@ +/* PSPP - computes sample statistics. + Copyright (C) 2007 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +#ifndef DATA_CASE_ORDERING_H +#define DATA_CASE_ORDERING_H 1 + +#include +#include + +struct dictionary; + +/* Sort direction. */ +enum sort_direction + { + SRT_ASCEND, /* A, B, C, ..., X, Y, Z. */ + SRT_DESCEND /* Z, Y, X, ..., C, B, A. */ + }; + +struct case_ordering *case_ordering_create (const struct dictionary *); +struct case_ordering *case_ordering_clone (const struct case_ordering *); +void case_ordering_destroy (struct case_ordering *); + +size_t case_ordering_get_value_cnt (const struct case_ordering *); +int case_ordering_compare_cases (const struct ccase *, const struct ccase *, + const struct case_ordering *); + +bool case_ordering_add_var (struct case_ordering *, + struct variable *, enum sort_direction); +size_t case_ordering_get_var_cnt (const struct case_ordering *); +struct variable *case_ordering_get_var (const struct case_ordering *, size_t); +enum sort_direction case_ordering_get_direction (const struct case_ordering *, + size_t); +void case_ordering_get_vars (const struct case_ordering *, + struct variable ***, size_t *); + +#endif /* data/case-ordering.h */ -- 2.30.2