covariance-matrix.c (covariance_accumulator_to_matrix): Use sum_i and
[pspp-builds.git] / src / math / covariance-matrix.c
index a33c33b243e46c07c8997a8825f27b00cfbc458b..2ab5f406fade36931a94412bbf42196541b24874 100644 (file)
@@ -57,7 +57,7 @@ struct covariance_matrix
 {
   struct design_matrix *cov;
   struct design_matrix *ssize;
-  struct design_matrix *means;
+  struct design_matrix *sums;
   struct hsh_table *ca;
   struct moments1 **m1;
   struct moments **m;
@@ -182,7 +182,7 @@ covariance_matrix_destroy (struct covariance_matrix *cov)
   assert (cov != NULL);
   design_matrix_destroy (cov->cov);
   design_matrix_destroy (cov->ssize);
-  design_matrix_destroy (cov->means);
+  design_matrix_destroy (cov->sums);
   hsh_destroy (cov->ca);
   if (cov->n_pass == ONE_PASS)
     {
@@ -811,6 +811,37 @@ is_covariance_contributor (const struct covariance_accumulator *ca, const struct
     }
   return false;
 }
+static double
+get_sum (const struct covariance_matrix *cov, size_t i)
+{
+  size_t k;
+  const struct variable *var;
+  const union value *val = NULL;
+  struct covariance_accumulator ca;
+  struct covariance_accumulator *c;
+
+  assert ( cov != NULL);
+  var = design_matrix_col_to_var (cov->cov, i);
+  if (var != NULL)
+    {
+      if (var_is_alpha (var))
+       {
+         k = design_matrix_var_to_column (cov->cov, var);
+         i -= k;
+         val = cat_subscript_to_value (i, var);
+       }
+      ca.v1 = var;
+      ca.v2 = var;
+      ca.val1 = val;
+      ca.val2 = val;
+      c = (struct covariance_accumulator *) hsh_find (cov->ca, &ca);
+      if (c != NULL)
+       {
+         return c->sum1;
+       }
+    }
+  return 0.0;
+}
 static void
 update_ssize (struct design_matrix *dm, size_t i, size_t j, struct covariance_accumulator *ca)
 {
@@ -833,23 +864,26 @@ covariance_accumulator_to_matrix (struct covariance_matrix *cov)
 {
   size_t i;
   size_t j;
-  double tmp;
+  double sum_i = 0.0;
+  double sum_j = 0.0;
+  double tmp = 0.0;
   struct covariance_accumulator *entry;
   struct hsh_iterator iter;
 
   cov->cov = covariance_matrix_create (cov->n_variables, cov->v_variables);
   cov->ssize = covariance_matrix_create (cov->n_variables, cov->v_variables);
-  cov->means = covariance_matrix_create (cov->n_variables, cov->v_variables);
+  cov->sums = covariance_matrix_create (cov->n_variables, cov->v_variables);
   for (i = 0; i < design_matrix_get_n_cols (cov->cov); i++)
     {
+      sum_i = get_sum (cov, i);
       for (j = i; j < design_matrix_get_n_cols (cov->cov); j++)
        {
+         sum_j = get_sum (cov, j);
          entry = hsh_first (cov->ca, &iter);
-         
+         gsl_matrix_set (cov->sums->m, i, j, sum_i);     
          while (entry != NULL)
            {
              update_ssize (cov->ssize, i, j, entry);
-
              /*
                We compute the centered, un-normalized covariance matrix.
              */
@@ -857,13 +891,11 @@ covariance_accumulator_to_matrix (struct covariance_matrix *cov)
                {
                  covariance_matrix_insert (cov->cov, entry->v1, entry->v2, entry->val1,
                                            entry->val2, entry->dot_product);
-                 covariance_matrix_insert (cov->cov, entry->v1, entry->v2, entry->val1,
-                                           entry->val2, entry->sum1 * entry->sum2);
                }
              entry = hsh_next (cov->ca, &iter);
            }
          tmp = gsl_matrix_get (cov->cov->m, i, j);
-         tmp -= gsl_matrix_get (cov->means->m, i, j) / gsl_matrix_get (cov->ssize->m, i, j);
+         tmp -= sum_i * sum_j / gsl_matrix_get (cov->ssize->m, i, j);
          gsl_matrix_set (cov->cov->m, i, j, tmp);
        } 
     }