pspp-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[bug37999 11/11] RANK: Add support for temporary transformations.


From: Ben Pfaff
Subject: [bug37999 11/11] RANK: Add support for temporary transformations.
Date: Thu, 31 Jan 2013 22:03:33 -0800

Bug #37999.
Reported by Zoltan Fabian.
---
 src/data/dataset.c           |   35 +++++++++++++++++++++++++-
 src/data/dataset.h           |    3 ++-
 src/data/dictionary.c        |   26 +++++++++++++++++---
 src/data/dictionary.h        |    5 +++-
 src/language/stats/rank.c    |   19 +-------------
 tests/language/stats/rank.at |   56 ++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 119 insertions(+), 25 deletions(-)

diff --git a/src/data/dataset.c b/src/data/dataset.c
index 26c3a49..9c3fe8c 100644
--- a/src/data/dataset.c
+++ b/src/data/dataset.c
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2006, 2007, 2009, 2010, 2011 Free Software 
Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2006, 2007, 2009, 2010, 2011, 2013 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
@@ -805,6 +805,39 @@ proc_cancel_all_transformations (struct dataset *ds)
 
   return ok;
 }
+
+static int
+store_case_num (void *var_, struct ccase **cc, casenumber case_num)
+{
+  struct variable *var = var_;
+
+  *cc = case_unshare (*cc);
+  case_data_rw (*cc, var)->f = case_num;
+
+  return TRNS_CONTINUE;
+}
+
+/* Add a variable which we can sort by to get back the original order. */
+struct variable *
+add_permanent_ordering_transformation (struct dataset *ds)
+{
+  struct variable *temp_var;
+
+  temp_var = dict_create_var_assert (ds->dict, "$ORDER", 0);
+  if (proc_in_temporary_transformations (ds))
+    {
+      struct variable *perm_var;
+
+      perm_var = dict_clone_var_in_place_assert (ds->permanent_dict, temp_var);
+      trns_chain_append (ds->permanent_trns_chain, NULL, store_case_num,
+                         NULL, perm_var);
+      trns_chain_finalize (ds->permanent_trns_chain);
+    }
+  else
+    add_transformation (ds, store_case_num, NULL, temp_var);
+
+  return temp_var;
+}
 
 /* Causes output from the next procedure to be discarded, instead
    of being preserved for use as input for the next procedure. */
diff --git a/src/data/dataset.h b/src/data/dataset.h
index 8445094..ce8b980 100644
--- a/src/data/dataset.h
+++ b/src/data/dataset.h
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2006, 2007, 2009, 2010, 2011 Free Software 
Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2006, 2007, 2009, 2010, 2011, 2013 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
@@ -93,6 +93,7 @@ void proc_start_temporary_transformations (struct dataset 
*ds);
 bool proc_in_temporary_transformations (const struct dataset *ds);
 bool proc_make_temporary_transformations_permanent (struct dataset *ds);
 bool proc_cancel_temporary_transformations (struct dataset *ds);
+struct variable *add_permanent_ordering_transformation (struct dataset *);
 
 /* Procedures. */
 
diff --git a/src/data/dictionary.c b/src/data/dictionary.c
index 024f97b..04c082f 100644
--- a/src/data/dictionary.c
+++ b/src/data/dictionary.c
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2006, 2007, 2009, 2010, 2011, 2012 Free 
Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2006, 2007, 2009, 2010, 2011, 2012, 2013 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
@@ -363,10 +363,13 @@ dict_get_vars_mutable (const struct dictionary *d, struct 
variable ***vars,
 }
 
 static struct variable *
-add_var (struct dictionary *d, struct variable *v)
+add_var_with_case_index (struct dictionary *d, struct variable *v,
+                         int case_index)
 {
   struct vardict_info *vardict;
 
+  assert (case_index >= d->next_value_idx);
+
   /* Update dictionary. */
   if (d->var_cnt >= d->var_cap)
     {
@@ -387,19 +390,25 @@ add_var (struct dictionary *d, struct variable *v)
   vardict->var = v;
   hmap_insert (&d->name_map, &vardict->name_node,
                utf8_hash_case_string (var_get_name (v), 0));
-  vardict->case_index = d->next_value_idx;
+  vardict->case_index = case_index;
   var_set_vardict (v, vardict);
 
   if ( d->changed ) d->changed (d, d->changed_data);
   if ( d->callbacks &&  d->callbacks->var_added )
     d->callbacks->var_added (d, var_get_dict_index (v), d->cb_data);
 
-  d->next_value_idx++;
   invalidate_proto (d);
+  d->next_value_idx = case_index + 1;
 
   return v;
 }
 
+static struct variable *
+add_var (struct dictionary *d, struct variable *v)
+{
+  return add_var_with_case_index (d, v, d->next_value_idx);
+}
+
 /* Creates and returns a new variable in D with the given NAME
    and WIDTH.  Returns a null pointer if the given NAME would
    duplicate that of an existing variable in the dictionary. */
@@ -468,6 +477,15 @@ dict_clone_var_as_assert (struct dictionary *d, const 
struct variable *old_var,
   return add_var (d, new_var);
 }
 
+struct variable *
+dict_clone_var_in_place_assert (struct dictionary *d,
+                                const struct variable *old_var)
+{
+  assert (dict_lookup_var (d, var_get_name (old_var)) == NULL);
+  return add_var_with_case_index (d, var_clone (old_var),
+                                  var_get_case_index (old_var));
+}
+
 /* Returns the variable named NAME in D, or a null pointer if no
    variable has that name. */
 struct variable *
diff --git a/src/data/dictionary.h b/src/data/dictionary.h
index 4050756..c725d5a 100644
--- a/src/data/dictionary.h
+++ b/src/data/dictionary.h
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 2004, 2007, 2009, 2010, 2011, 2012 Free Software Foundation, 
Inc.
+   Copyright (C) 2004, 2007, 2009, 2010, 2011, 2012, 2013 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
@@ -64,6 +64,9 @@ struct variable *dict_clone_var_as_assert (struct dictionary 
*,
                                            const struct variable *,
                                            const char *);
 
+struct variable *dict_clone_var_in_place_assert (struct dictionary *,
+                                                 const struct variable *);
+
 /* Deleting variables. */
 void dict_delete_var (struct dictionary *, struct variable *);
 void dict_delete_vars (struct dictionary *,
diff --git a/src/language/stats/rank.c b/src/language/stats/rank.c
index 19861cc..5f5591a 100644
--- a/src/language/stats/rank.c
+++ b/src/language/stats/rank.c
@@ -589,22 +589,9 @@ rank_sorted_file (struct casereader *input,
 }
 
 
-/* Transformation function to enumerate all the cases */
-static int
-create_resort_key (void *key_var_, struct ccase **cc, casenumber case_num)
-{
-  struct variable *key_var = key_var_;
-
-  *cc = case_unshare (*cc);
-  case_data_rw (*cc, key_var)->f = case_num;
-
-  return TRNS_CONTINUE;
-}
-
 static bool
 rank_cmd (struct dataset *ds,  const struct rank *cmd);
 
-
 static const char *
 fraction_name (const struct rank *cmd)
 {
@@ -1000,11 +987,7 @@ rank_cmd (struct dataset *ds, const struct rank *cmd)
   bool ok = true;
   int i;
 
-  /* Add a variable which we can sort by to get back the original
-     order */
-  order_var = dict_create_var_assert (dataset_dict (ds), "$ORDER", 0);
-
-  add_transformation (ds, create_resort_key, 0, order_var);
+  order_var = add_permanent_ordering_transformation (ds);
 
   /* Create output files. */
   {
diff --git a/tests/language/stats/rank.at b/tests/language/stats/rank.at
index 61c4180..45ca41a 100644
--- a/tests/language/stats/rank.at
+++ b/tests/language/stats/rank.at
@@ -411,6 +411,62 @@ x,w,xl,xh,xc,Nx
 ])
 AT_CLEANUP
 
+AT_SETUP([RANK and TEMPORARY])
+AT_DATA([rank.sps], [dnl
+DATA LIST LIST NOTABLE /age (f2) gender (a1).
+BEGIN DATA.
+44 m
+32 f
+43 m
+49 m
+33 f
+35 f
+29 f
+50 m
+42 m
+33 f
+48 m
+END DATA.
+
+TEMPORARY.
+SELECT IF gender = 'm'.
+RANK age /RANK INTO Rm.
+
+TEMPORARY.
+SELECT IF gender = 'f'.
+RANK age /RANK INTO Rf.
+
+LIST.
+])
+AT_CHECK([pspp -O format=csv rank.sps], [0], [dnl
+Variables Created By RANK
+
+
+
+age into Rm(RANK of age)
+
+Variables Created By RANK
+
+
+
+age into Rf(RANK of age)
+
+Table: Data List
+age,gender,Rm,Rf
+44,m,3.000,.   @&t@
+32,f,.   ,2.000
+43,m,2.000,.   @&t@
+49,m,5.000,.   @&t@
+33,f,.   ,3.500
+35,f,.   ,5.000
+29,f,.   ,1.000
+50,m,6.000,.   @&t@
+42,m,1.000,.   @&t@
+33,f,.   ,3.500
+48,m,4.000,.   @&t@
+])
+AT_CLEANUP
+
 AT_SETUP([RANK variable name fallback])
 AT_DATA([rank.sps], [dnl
 DATA LIST LIST NOTABLE /foo * rfoo * ran003 *.
-- 
1.7.10.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]