[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
- [bug37999 05/11] RANK: Remove write-only struct member 'ascending'., (continued)
- [bug37999 05/11] RANK: Remove write-only struct member 'ascending'., Ben Pfaff, 2013/02/01
- [bug37999 03/11] transformations: Relax the rules for transformation finalizing., Ben Pfaff, 2013/02/01
- [bug37999 06/11] RANK: Put #include directives into typical order., Ben Pfaff, 2013/02/01
- [bug37999 02/11] subcase: New function subcase_add_vars_always()., Ben Pfaff, 2013/02/01
- [bug37999 07/11] RANK: Simplify fraction_name() function., Ben Pfaff, 2013/02/01
- [bug37999 08/11] RANK: Simplify rank_sorted_file() with new function sum_weights()., Ben Pfaff, 2013/02/01
- [bug37999 09/11] RANK: Create all variables together, in order., Ben Pfaff, 2013/02/01
- [bug37999 11/11] RANK: Add support for temporary transformations.,
Ben Pfaff <=
- [bug37999 10/11] RANK: Adopt a new ranking implementation., Ben Pfaff, 2013/02/01