Added the /BARCHART option to CROSSTABS
[pspp] / src / language / stats / freq.c
index ae35b8a7a1580ad873da25b62ffc2dc5bab95e22..535b39c440c44c26b4e0484562c09bd088ff9dc9 100644 (file)
-/* PSPP - computes sample statistics.
-   Copyright (C) 2006 Free Software Foundation, Inc.
+/* PSPP - a program for statistical analysis.
+   Copyright (C) 2006, 2009, 2010 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 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 3 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.
+   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. */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
 #include <config.h>
-#include <data/variable.h>
-#include <data/value.h>
-#include <libpspp/compiler.h>
+
+#include "language/stats/freq.h"
 
 #include <stdlib.h>
 
-#include "freq.h"
+#include "data/variable.h"
+#include "data/value.h"
+#include "libpspp/array.h"
+#include "libpspp/compiler.h"
 
-int
-compare_freq ( const void *_f1, const void *_f2, const void *_var)
+struct freq *
+freq_clone (const struct freq *in, int values, int *widths)
 {
-  const struct freq *f1 = _f1;
-  const struct freq *f2 = _f2;
-  const struct variable *var = _var;
+  int i;
+  struct freq *f = xmalloc (sizeof (struct freq) +
+                           (sizeof (union value) * (values - 1)));
 
-  return  compare_values (f1->value, f2->value, var_get_width (var) );
+  f->node = in->node;
+  f->count = in->count;
+  for (i = 0; i < values; ++i)
+    {
+      value_init (&f->values[i],  widths[i]);
+      value_copy (&f->values[i], &in->values[i], widths[i]);
+    }
+
+  return f;
 }
 
-unsigned int
-hash_freq (const void *_f, const void *_var)
+void
+freq_destroy (struct freq *f, int values, int *widths)
 {
-  const struct freq *f = _f;
-  const struct variable *var  = _var;
+  int i;
+  for (i = 0; i < values; ++i)
+    {
+      value_destroy (&f->values[i],  widths[i]);
+    }
 
-  return hash_value (f->value, var_get_width (var));
+  free (f);
 }
 
-/* Free function to be used on FR whose value parameter has been copied */
+
+
 void
-free_freq_mutable_hash (void *fr, const void *var UNUSED)
+freq_hmap_destroy (struct hmap *hmap, int width)
 {
-  struct freq_mutable *freq = fr;
-  free (freq->value);
-  free (freq);
+  struct freq *f, *next;
+
+  HMAP_FOR_EACH_SAFE (f, next, struct freq, node, hmap)
+    {
+      value_destroy (&f->values[0], width);
+      hmap_delete (hmap, &f->node);
+      free (f);
+    }
+  hmap_destroy (hmap);
 }
 
-void
-free_freq_hash (void *fr, const void *var UNUSED)
+struct freq *
+freq_hmap_search (struct hmap *hmap,
+                  const union value *value, int width, size_t hash)
+{
+  struct freq *f;
+
+  HMAP_FOR_EACH_WITH_HASH (f, struct freq, node, hash, hmap)
+    if (value_equal (value, &f->values[0], width))
+      return f;
+
+  return NULL;
+}
+
+struct freq *
+freq_hmap_insert (struct hmap *hmap,
+                  const union value *value, int width, size_t hash)
+{
+  struct freq *f = xmalloc (sizeof *f);
+  value_clone (&f->values[0], value, width);
+  f->count = 0;
+  hmap_insert (hmap, &f->node, hash);
+  return f;
+}
+
+int
+compare_freq_ptr_3way (const void *a_, const void *b_, const void *width_)
 {
-  free (fr);
+  const struct freq *const *ap = a_;
+  const struct freq *const *bp = b_;
+  const int *widthp = width_;
+
+  return value_compare_3way (&(*ap)->values[0], &(*bp)->values[0], *widthp);
 }
+
+struct freq **
+freq_hmap_sort (struct hmap *hmap, int width)
+{
+  size_t n_entries = hmap_count (hmap);
+  struct freq **entries;
+  struct freq *f;
+  size_t i;
+
+  entries = xnmalloc (n_entries, sizeof *entries);
+  i = 0;
+  HMAP_FOR_EACH (f, struct freq, node, hmap)
+    entries[i++] = f;
+  assert (i == n_entries);
+
+  sort (entries, n_entries, sizeof *entries, compare_freq_ptr_3way, &width);
+
+  return entries;
+}
+
+struct freq *
+freq_hmap_extract (struct hmap *hmap)
+{
+  struct freq *freqs, *f;
+  size_t n_freqs;
+  size_t i;
+
+  n_freqs = hmap_count (hmap);
+  freqs = xnmalloc (n_freqs, sizeof *freqs);
+  i = 0;
+  HMAP_FOR_EACH (f, struct freq, node, hmap)
+    freqs[i++] = *f;
+  assert (i == n_freqs);
+
+  return freqs;
+}
+