Update all #include directives to the currently preferred style.
[pspp-builds.git] / src / math / interaction.c
index 33da8423bd7c7545a69e4c51a1d0a9a5abd4318d..87f4836da23479ced8fa9a2069841ada800408d9 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 2009 Free Software Foundation, Inc.
+   Copyright (C) 2009, 2010, 2011 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
@@ -15,7 +15,7 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
 /*
-  An interaction is a gsl_vector containing a "product" of other
+  An interaction is a structure containing a "product" of other
   variables. The variables can be either categorical or numeric.
   If the variables are all numeric, the interaction is just the
   scalar product. If any of the variables are categorical, their
  */
 
 #include <config.h>
+
+#include "math/interaction.h"
+
 #include <assert.h>
-#include <gsl/gsl_math.h>
-#include <gsl/gsl_vector.h>
-#include <data/value.h>
-#include <data/variable.h>
-#include <math/interaction.h>
 #include <string.h>
-#include <xalloc.h>
+#include <unistr.h>
+
+#include "data/dictionary.h"
+#include "data/value.h"
+#include "data/variable.h"
+
+#include "gl/xalloc.h"
 
 struct interaction_variable
 {
@@ -50,10 +54,10 @@ struct interaction_variable
 struct interaction_value
 {
   const struct interaction_variable *intr;
-  union value *val; /* Concatenation of the string values in this
-                      interaction's value, or the product of a bunch
-                      of numeric values for a purely numeric
-                      interaction.
+  union value val; /* Concatenation of the string values in this
+                      interaction's value, or the product of a bunch
+                      of numeric values for a purely numeric
+                      interaction.
                    */
   double f; /* Product of the numerical values in this interaction's value. */
 };
@@ -70,10 +74,11 @@ interaction_variable_create (const struct variable **vars, int n_vars)
 
   if (n_vars > 0)
     {
+      int width = 0;
+
       result = xmalloc (sizeof (*result));
       result->n_alpha = 0;
       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++)
        {
@@ -81,19 +86,17 @@ interaction_variable_create (const struct variable **vars, int n_vars)
          if (var_is_alpha (vars[i]))
            {
              result->n_alpha++;
+             width += var_get_width (vars[i]);
            }
        }
+      result->intr = dict_create_internal_var (0, width);
     }
-  /*
-    VAR_SET_WIDTH sets the type of the variable.
-   */
-  var_set_width (result->intr, MAX_SHORT_STRING * result->n_alpha + 1);
 
   return result;
 }
 void interaction_variable_destroy (struct interaction_variable *iv)
 {
-  var_destroy (iv->intr);
+  dict_destroy_internal_var (iv->intr);
   free (iv->members);
   free (iv);
 }
@@ -102,7 +105,7 @@ void interaction_variable_destroy (struct interaction_variable *iv)
   Get one of the member variables.
  */
 const struct variable *
-interaction_variable_get_member (const struct interaction_variable *iv, size_t i)
+interaction_get_member (const struct interaction_variable *iv, size_t i)
 {
   return iv->members[i];
 }
@@ -126,10 +129,10 @@ interaction_get_n_numeric (const struct interaction_variable *iv)
 }
 
 /*
-  Get the interaction varibale itself.
+  Get the interaction variable itself.
  */
 const struct variable *
-interaction_variable_get_var (const struct interaction_variable *iv)
+interaction_get_variable (const struct interaction_variable *iv)
 {
   return iv->intr;
 }
@@ -144,24 +147,27 @@ struct interaction_value *
 interaction_value_create (const struct interaction_variable *var, const union value **vals)
 {
   struct interaction_value *result = NULL;
-  const struct variable *member;
-  size_t i;
-  size_t n_vars;
   
   if (var != NULL)
     {
+      size_t i;
+      int val_width = var_get_width (interaction_get_variable (var));
+      int offset = 0;
+      size_t n_vars = interaction_get_n_vars (var);
+
       result = xmalloc (sizeof (*result));
       result->intr = var;
-      n_vars = interaction_get_n_vars (var);
-      result->val = value_create (n_vars * MAX_SHORT_STRING + 1);
+
+      value_init (&result->val, val_width);
+
       result->f = 1.0;
       for (i = 0; i < n_vars; i++)
        {
-         member = interaction_variable_get_member (var, i);
+          const struct variable *member = interaction_get_member (var, i);
 
          if (var_is_value_missing (member, vals[i], MV_ANY))
            {
-             value_set_missing (result->val, MAX_SHORT_STRING);
+             value_set_missing (&result->val, val_width);
              result->f = SYSMIS;
              break;
            }
@@ -169,7 +175,10 @@ interaction_value_create (const struct interaction_variable *var, const union va
            {
              if (var_is_alpha (var->members[i]))
                {
-                 strncat (result->val->s, vals[i]->s, MAX_SHORT_STRING);
+                 uint8_t *val = value_str_rw (&result->val, val_width);
+                  int w = var_get_width (var->members[i]);
+                  u8_cpy (val + offset, value_str (vals[i], w), w);
+                  offset += w;
                }
              else if (var_is_numeric (var->members[i]))
                {
@@ -192,23 +201,23 @@ interaction_value_create (const struct interaction_variable *var, const union va
            avoid the error, we set result->f to 1.0 for numeric
            interactions.
           */
-         result->val->f = result->f;
+         result->val.f = result->f;
          result->f = 1.0;
        }
     }
   return result;
 }
 
-union value *
+const union value *
 interaction_value_get (const struct interaction_value *val)
 {
-  return val->val;
+  return &val->val;
 }
 
 /*
   Returns the numeric value of the non-zero entry for the vector
   corresponding to this interaction.  Do not use this function to get
-  the numeric value of a purley numeric interaction. Instead, use the
+  the numeric value of a purely numeric interaction. Instead, use the
   union value * returned by interaction_value_get.
  */
 double 
@@ -224,7 +233,9 @@ interaction_value_destroy (struct interaction_value *val)
 {
   if (val != NULL)
     {
-      free (val->val);
+      int val_width = var_get_width (interaction_get_variable (val->intr));
+
+      value_destroy (&val->val, val_width);
       free (val);
     }
 }
@@ -233,32 +244,22 @@ interaction_value_destroy (struct interaction_value *val)
   Return a value from a variable that is an interaction. 
  */
 struct interaction_value *
-interaction_case_data (const struct ccase *ccase, const struct variable *var, 
-                      const struct interaction_variable **intr_vars, size_t n_intr)
+interaction_case_data (const struct ccase *ccase, const struct interaction_variable *iv)
 {
   size_t i;
   size_t n_vars;
-  const struct interaction_variable *iv;
-  const struct variable *intr;
   const struct variable *member;
   const union value **vals = NULL;
 
-  for (i = 0; i < n_intr; i++)
-    {
-      iv = intr_vars[i];
-      intr = interaction_variable_get_var (iv);
-      if (var_get_dict_index (intr) == var_get_dict_index (var))
-       {
-         break;
-       }
-    }
   n_vars = interaction_get_n_vars (iv);
   vals = xnmalloc (n_vars, sizeof (*vals));
+
   for (i = 0; i < n_vars; i++)
-    {
-      member = interaction_variable_get_member (iv, i);
-      vals[i] = case_data (ccase, member);
-    }
+       {
+         member = interaction_get_member (iv, i);
+         vals[i] = case_data (ccase, member);
+       }
+
   return interaction_value_create (iv, vals);
 }
 
@@ -270,8 +271,8 @@ is_interaction (const struct variable *var, const struct interaction_variable **
   
   for (i = 0; i < n_intr; i++)
     {
-      intr = interaction_variable_get_var (iv[i]);
-      if (var_get_dict_index (intr) == var_get_dict_index (var))
+      intr = interaction_get_variable (iv[i]);
+      if (intr == var)
        {
          return true;
        }