From 6fad5485ff9ba8e6decd8625cb79eb2910e934f2 Mon Sep 17 00:00:00 2001 From: Jason H Stover Date: Mon, 12 Jan 2009 11:18:44 -0500 Subject: [PATCH] Rewrote interaction.[ch] --- src/math/interaction.c | 139 +++++++++++++++++++++++++---------------- src/math/interaction.h | 16 ++++- 2 files changed, 98 insertions(+), 57 deletions(-) diff --git a/src/math/interaction.c b/src/math/interaction.c index c8ead429..ff2c5357 100644 --- a/src/math/interaction.c +++ b/src/math/interaction.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2009 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 @@ -24,80 +24,111 @@ OBS_VALS member. If there are K categorical variables, each with N_1, N_2, ..., N_K categories, then the interaction will have N_1 * N_2 * N_3 *...* N_K - 1 entries. + + When using these functions, make sure the orders of variables and + values match when appropriate. */ #include #include #include #include -#include +#include #include -#include "interaction.h" +#include +#include +#include -#include "xalloc.h" +struct interaction_variable +{ + int n_vars; + const struct variable **members; + struct variable *intr; +}; -/* - Convert a list of values to a binary vector. The order of VALS must - correspond to the order of V. - */ -gsl_vector * -get_interaction (union value **vals, const struct variable **v, size_t n_vars) +struct interaction_value { - gsl_vector *result = NULL; - size_t *subs = NULL; - size_t length = 1; + const struct interaction_variable *intr; + union value *strings; /* Concatenation of the string values in this interaction's value. */ + double f; /* Product of the numerical values in this interaction's value. */ +}; + +struct interaction_variable * +interaction_variable_create (const struct variable **vars, int n_vars) +{ + struct interaction_variable *result = NULL; size_t i; - size_t j; - double tmp = 1.0; - assert (n_vars > 0); - for (i = 0; i < n_vars; i++) + if (n_vars > 0) { - if (var_is_alpha (v[i])) - { - length *= cat_get_n_categories (v[i]); - } - else + result = xmalloc (sizeof (*result)); + result->members = xnmalloc (n_vars, sizeof (*result->members)); + result->intr = var_create_internal (0); + result->n_vars = n_vars; + for (i = 0; i < n_vars; i++) { - length = (length > 0) ? length : 1; + result->members[i] = vars[i]; } } - if (length > 0) - { - length--; - } + return result; +} - result = gsl_vector_calloc (length); - subs = xnmalloc (n_vars, sizeof (*subs)); - for (j = 0; j < n_vars; j++) - { - if (var_is_alpha (v[j])) - { - subs[j] = cat_value_find (v[j], vals[j]); - } - } - j = subs[0]; - for (i = 1; i < n_vars; i++) - { - j = j * cat_get_n_categories (v[i]) + subs[i]; - } - gsl_vector_set (result, j, 1.0); - /* - If any of the variables are numeric, the interaction of that - variable with another is just a scalar product. - */ - for (i = 1; i < n_vars; i++) +void interaction_variable_destroy (struct interaction_variable *iv) +{ + var_destroy (iv->intr); + free (iv->members); + free (iv); +} + +size_t +interaction_variable_get_n_vars (const struct interaction_variable *iv) +{ + return (iv == NULL) ? 0 : iv->n_vars; +} + +/* + Given list of values, compute the value of the corresponding + interaction. This "value" is not stored as the typical vector of + 0's and one double, but rather the string values are concatenated to + make one big string value, and the numerical values are multiplied + together to give the non-zero entry of the corresponding vector. + */ +struct interaction_value * +interaction_value_create (const struct interaction_variable *var, const union value **vals) +{ + struct interaction_value *result = NULL; + size_t i; + size_t n_vars; + + if (var != NULL) { - if (var_is_numeric (v[i])) + result = xmalloc (sizeof (*result)); + result->intr = var; + n_vars = interaction_variable_get_n_vars (var); + result->strings = value_create (n_vars * MAX_SHORT_STRING + 1); + result->f = 1.0; + for (i = 0; i < n_vars; i++) { - tmp *= vals[i]->f; + if (var_is_alpha (var->members[i])) + { + strncat (result->strings->s, vals[i]->s, MAX_SHORT_STRING); + } + else if (var_is_numeric (var->members[i])) + { + result->f *= vals[i]->f; + } } } - if (fabs (tmp - 1.0) > GSL_DBL_EPSILON) + return result; +} + +void +interaction_value_destroy (struct interaction_value *val) +{ + if (val != NULL) { - gsl_vector_set (result, j, tmp); + free (val->strings); + free (val); } - free (subs); - - return result; } + diff --git a/src/math/interaction.h b/src/math/interaction.h index 07006078..bc1e63a4 100644 --- a/src/math/interaction.h +++ b/src/math/interaction.h @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2009 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 @@ -14,5 +14,15 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -gsl_vector * -get_interaction (union value **, const struct variable **, size_t); +#ifndef INTERACTION_H +#define INTERACTION_H +struct interaction_variable; +struct interaction_value; + +struct interaction_variable * interaction_variable_create (const struct variable **, int); +void interaction_variable_destroy (struct interaction_variable *); +struct interaction_value * interaction_value_create (const struct interaction_variable *, const union value **); +void interaction_value_destroy (struct interaction_value *); +size_t interaction_variable_get_n_vars (const struct interaction_variable *); + +#endif -- 2.30.2