1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2008, 2009 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 Create and update the values in the covariance matrix.
22 #include <data/case.h>
23 #include <data/category.h>
24 #include <data/variable.h>
25 #include <data/value.h>
26 #include <libpspp/hash.h>
27 #include <libpspp/hash-functions.h>
28 #include <math/covariance-matrix.h>
29 #include <math/moments.h>
34 Structure used to accumulate the covariance matrix in a single data
35 pass. Before passing the data, we do not know how many categories
36 there are in each categorical variable. Therefore we do not know the
37 size of the covariance matrix. To get around this problem, we
38 accumulate the elements of the covariance matrix in pointers to
39 COVARIANC_ACCUMULATOR. These values are then used to populate
40 the covariance matrix.
42 struct covariance_accumulator
44 const struct variable *v1;
45 const struct variable *v2;
46 const union value *val1;
47 const union value *val2;
56 struct covariance_matrix
58 struct design_matrix *cov;
59 struct design_matrix *ssize;
63 const struct variable **v_variables;
64 const struct interaction_variable **interactions;
69 enum mv_class missing_value;
70 void (*accumulate) (struct covariance_matrix *, const struct ccase *,
71 const struct interaction_variable **, size_t);
72 void (*update_moments) (struct covariance_matrix *, size_t, double);
77 static struct hsh_table *covariance_hsh_create (size_t *);
78 static hsh_hash_func covariance_accumulator_hash;
79 static unsigned int hash_numeric_alpha (const struct variable *,
80 const struct variable *,
81 const union value *, size_t);
82 static hsh_compare_func covariance_accumulator_compare;
83 static hsh_free_func covariance_accumulator_free;
84 static void update_moments1 (struct covariance_matrix *, size_t, double);
85 static void update_moments2 (struct covariance_matrix *, size_t, double);
86 static struct covariance_accumulator *get_new_covariance_accumulator (const
101 static void covariance_accumulate_listwise (struct covariance_matrix *,
102 const struct ccase *,
103 const struct interaction_variable **,
105 static void covariance_accumulate_pairwise (struct covariance_matrix *,
106 const struct ccase *,
107 const struct interaction_variable **,
110 struct covariance_matrix *
111 covariance_matrix_init (size_t n_variables,
112 const struct variable *v_variables[], int n_pass,
113 int missing_handling, enum mv_class missing_value)
116 struct covariance_matrix *result = NULL;
118 result = xmalloc (sizeof (*result));
120 result->n_variables = n_variables;
121 result->ca = covariance_hsh_create (&result->n_variables);
125 result->missing_handling = missing_handling;
126 result->missing_value = missing_value;
127 result->accumulate = (result->missing_handling == LISTWISE) ?
128 covariance_accumulate_listwise : covariance_accumulate_pairwise;
129 if (n_pass == ONE_PASS)
131 result->update_moments = update_moments1;
132 result->m1 = xnmalloc (n_variables, sizeof (*result->m1));
133 for (i = 0; i < n_variables; i++)
135 result->m1[i] = moments1_create (MOMENT_MEAN);
140 result->update_moments = update_moments2;
141 result->m = xnmalloc (n_variables, sizeof (*result->m));
142 for (i = 0; i < n_variables; i++)
144 result->m[i] = moments_create (MOMENT_MEAN);
147 result->v_variables = v_variables;
149 result->n_pass = n_pass;
154 covariance_interaction_set (struct covariance_matrix *cov,
155 const struct interaction_variable **intr, size_t n_intr)
157 cov->interactions = intr;
158 cov->n_intr = n_intr;
162 get_n_rows (size_t n_variables, const struct variable *v_variables[])
166 for (i = 0; i < n_variables; i++)
168 if (var_is_numeric (v_variables[i]))
172 else if (var_is_alpha (v_variables[i]))
174 size_t n_categories = cat_get_n_categories (v_variables[i]);
175 result += n_categories - 1;
181 The covariances are stored in a DESIGN_MATRIX structure.
183 struct design_matrix *
184 covariance_matrix_create (size_t n_variables,
185 const struct variable *v_variables[])
187 size_t n_rows = get_n_rows (n_variables, v_variables);
188 return design_matrix_create (n_variables, v_variables, n_rows);
192 get_n_rows_s (const struct variable *var)
195 if (var_is_numeric (var))
201 result += cat_get_n_categories (var) - 1;
205 static struct design_matrix *
206 covariance_matrix_create_s (struct covariance_matrix *cov)
208 struct variable **v_variables;
214 n_variables = cov->n_variables + cov->n_intr;
215 v_variables = xnmalloc (n_variables, sizeof (*v_variables));
216 for (i = 0; i < cov->n_variables; i++)
218 v_variables[i] = cov->v_variables[i];
219 n_rows += get_n_rows_s (v_variables[i]);
221 for (j = 0; j < cov->n_intr; j++)
223 v_variables[i + j] = interaction_get_variable (cov->interactions[j]);
224 n_rows += get_n_rows_s (v_variables[i]);
226 return design_matrix_create (n_variables, v_variables, n_rows);
230 update_moments1 (struct covariance_matrix *cov, size_t i, double x)
232 assert (cov->m1 != NULL);
233 moments1_add (cov->m1[i], x, 1.0);
237 update_moments2 (struct covariance_matrix *cov, size_t i, double x)
239 assert (cov->m != NULL);
240 moments_pass_one (cov->m[i], x, 1.0);
244 covariance_matrix_destroy (struct covariance_matrix *cov)
248 assert (cov != NULL);
249 design_matrix_destroy (cov->cov);
250 design_matrix_destroy (cov->ssize);
251 hsh_destroy (cov->ca);
252 if (cov->n_pass == ONE_PASS)
254 for (i = 0; i < cov->n_variables; i++)
256 moments1_destroy (cov->m1[i]);
262 for (i = 0; i < cov->n_variables; i++)
264 moments_destroy (cov->m[i]);
271 Update the covariance matrix with the new entries, assuming that ROW
272 corresponds to a categorical variable and V2 is numeric.
275 covariance_update_categorical_numeric (struct design_matrix *cov, double mean,
277 const struct variable *v2, double x,
278 const union value *val2)
283 assert (var_is_numeric (v2));
285 col = design_matrix_var_to_column (cov, v2);
286 assert (val2 != NULL);
287 tmp = design_matrix_get_element (cov, row, col);
288 design_matrix_set_element (cov, row, col, (val2->f - mean) * x + tmp);
289 design_matrix_set_element (cov, col, row, (val2->f - mean) * x + tmp);
292 column_iterate (struct design_matrix *cov, const struct variable *v,
293 double ssize, double x, const union value *val1, size_t row)
295 int width = var_get_width (v);
300 const union value *tmp_val;
302 col = design_matrix_var_to_column (cov, v);
303 for (i = 0; i < cat_get_n_categories (v) - 1; i++)
306 y = -1.0 * cat_get_category_count (i, v) / ssize;
307 tmp_val = cat_subscript_to_value (i, v);
308 if (!value_equal (tmp_val, val1, width))
312 tmp = design_matrix_get_element (cov, row, col);
313 design_matrix_set_element (cov, row, col, x * y + tmp);
314 design_matrix_set_element (cov, col, row, x * y + tmp);
319 Call this function in the second data pass. The central moments are
320 MEAN1 and MEAN2. Any categorical variables should already have their
321 values summarized in in its OBS_VALS element.
324 covariance_pass_two (struct design_matrix *cov, double mean1, double mean2,
325 double ssize, const struct variable *v1,
326 const struct variable *v2, const union value *val1,
327 const union value *val2)
333 const union value *tmp_val;
335 if (var_is_alpha (v1))
337 row = design_matrix_var_to_column (cov, v1);
338 for (i = 0; i < cat_get_n_categories (v1) - 1; i++)
341 x = -1.0 * cat_get_category_count (i, v1) / ssize;
342 tmp_val = cat_subscript_to_value (i, v1);
343 if (!value_equal (tmp_val, val1, var_get_width (v1)))
347 if (var_is_numeric (v2))
349 covariance_update_categorical_numeric (cov, mean2, row,
354 column_iterate (cov, v1, ssize, x, val1, row);
355 column_iterate (cov, v2, ssize, x, val2, row);
359 else if (var_is_alpha (v2))
362 Reverse the orders of V1, V2, etc. and put ourselves back
363 in the previous IF scope.
365 covariance_pass_two (cov, mean2, mean1, ssize, v2, v1, val2, val1);
370 Both variables are numeric.
372 row = design_matrix_var_to_column (cov, v1);
373 col = design_matrix_var_to_column (cov, v2);
374 x = (val1->f - mean1) * (val2->f - mean2);
375 x += design_matrix_get_element (cov, col, row);
376 design_matrix_set_element (cov, row, col, x);
377 design_matrix_set_element (cov, col, row, x);
382 covariance_accumulator_hash (const void *h, const void *aux)
384 struct covariance_accumulator *ca = (struct covariance_accumulator *) h;
385 size_t *n_vars = (size_t *) aux;
388 const struct variable *v_min;
389 const struct variable *v_max;
390 const union value *val_min;
391 const union value *val_max;
394 Order everything by the variables' indices. This ensures we get the
395 same key regardless of the order in which the variables are stored
399 (var_get_dict_index (ca->v1) <
400 var_get_dict_index (ca->v2)) ? ca->v1 : ca->v2;
401 v_max = (ca->v1 == v_min) ? ca->v2 : ca->v1;
403 val_min = (v_min == ca->v1) ? ca->val1 : ca->val2;
404 val_max = (ca->val1 == val_min) ? ca->val2 : ca->val1;
406 idx_min = var_get_dict_index (v_min);
407 idx_max = var_get_dict_index (v_max);
409 if (var_is_numeric (v_max) && var_is_numeric (v_min))
411 return (*n_vars * idx_max + idx_min);
413 if (var_is_numeric (v_max) && var_is_alpha (v_min))
415 return hash_numeric_alpha (v_max, v_min, val_min, *n_vars);
417 if (var_is_alpha (v_max) && var_is_numeric (v_min))
419 return (hash_numeric_alpha (v_min, v_max, val_max, *n_vars));
421 if (var_is_alpha (v_max) && var_is_alpha (v_min))
423 unsigned hash = value_hash (val_max, var_get_width (v_max), 0);
424 hash = value_hash (val_min, var_get_width (v_min), hash);
425 return hash_int (*n_vars * (*n_vars + 1 + idx_max) + idx_min, hash);
431 Make a hash table consisting of struct covariance_accumulators.
432 This allows the accumulation of the elements of a covariance matrix
433 in a single data pass. Call covariance_accumulate () for each case
436 static struct hsh_table *
437 covariance_hsh_create (size_t *n_vars)
439 return hsh_create (*n_vars * *n_vars, covariance_accumulator_compare,
440 covariance_accumulator_hash, covariance_accumulator_free,
445 covariance_accumulator_free (void *c_, const void *aux UNUSED)
447 struct covariance_accumulator *c = c_;
453 ordered_match_nodes (const struct covariance_accumulator *c, const struct variable *v1,
454 const struct variable *v2, const union value *val1, const union value *val2)
459 result = var_get_dict_index (v1) ^ var_get_dict_index (c->v1);
460 m = var_get_dict_index (v2) ^ var_get_dict_index (c->v2);
462 if (var_is_alpha (v1))
464 result |= value_compare_3way (val1, c->val1, var_get_width (v1));
465 if (var_is_alpha (v2))
467 result |= value_compare_3way (val2, c->val2, var_get_width (v2));
470 else if (var_is_alpha (v2))
472 result |= value_compare_3way (val2, c->val2, var_get_width (v2));
478 Hash comparison. Returns 0 for a match, or a non-zero int
479 otherwise. The sign of a non-zero return value *should* indicate the
480 position of C relative to the covariance_accumulator described by
481 the other arguments. But for now, it just returns 1 for any
482 non-match. This should be changed when someone figures out how to
483 compute a sensible sign for the return value.
486 match_nodes (const struct covariance_accumulator *c,
487 const struct variable *v1, const struct variable *v2,
488 const union value *val1, const union value *val2)
493 n = ordered_match_nodes (c, v1, v2, val1, val2);
494 m = ordered_match_nodes (c, v2, v1, val2, val1);
499 This function is meant to be used as a comparison function for
500 a struct hsh_table in src/libpspp/hash.c.
503 covariance_accumulator_compare (const void *a1_, const void *a2_,
504 const void *aux UNUSED)
506 const struct covariance_accumulator *a1 = a1_;
507 const struct covariance_accumulator *a2 = a2_;
509 if (a1 == NULL && a2 == NULL)
512 if (a1 == NULL || a2 == NULL)
515 return match_nodes (a1, a2->v1, a2->v2, a2->val1, a2->val2);
519 hash_numeric_alpha (const struct variable *v1, const struct variable *v2,
520 const union value *val, size_t n_vars)
522 unsigned int result = -1u;
523 if (var_is_numeric (v1) && var_is_alpha (v2))
525 result = n_vars * ((n_vars + 1) + var_get_dict_index (v1))
526 + var_get_dict_index (v2) + value_hash (val, var_get_width (v2), 0);
528 else if (var_is_alpha (v1) && var_is_numeric (v2))
530 result = hash_numeric_alpha (v2, v1, val, n_vars);
537 update_product (const struct variable *v1, const struct variable *v2,
538 const union value *val1, const union value *val2)
542 assert (val1 != NULL);
543 assert (val2 != NULL);
544 if (var_is_alpha (v1) && var_is_alpha (v2))
548 if (var_is_numeric (v1) && var_is_numeric (v2))
550 return (val1->f * val2->f);
552 if (var_is_numeric (v1) && var_is_alpha (v2))
556 if (var_is_numeric (v2) && var_is_alpha (v1))
566 update_sum (const struct variable *var, const union value *val, double weight)
568 assert (var != NULL);
569 assert (val != NULL);
570 if (var_is_alpha (var))
576 static struct covariance_accumulator *
577 get_new_covariance_accumulator (const struct variable *v1,
578 const struct variable *v2,
579 const union value *val1,
580 const union value *val2)
582 if ((v1 != NULL) && (v2 != NULL) && (val1 != NULL) && (val2 != NULL))
584 struct covariance_accumulator *ca;
585 ca = xmalloc (sizeof (*ca));
595 static const struct variable **
596 get_covariance_variables (const struct covariance_matrix *cov)
598 return cov->v_variables;
602 update_hash_entry_intr (struct hsh_table *c,
603 const struct variable *v1,
604 const struct variable *v2,
605 const union value *val1, const union value *val2,
606 const struct interaction_value *i_val1,
607 const struct interaction_value *i_val2)
609 struct covariance_accumulator *ca;
610 struct covariance_accumulator *new_entry;
614 iv_f1 = interaction_value_get_nonzero_entry (i_val1);
615 iv_f2 = interaction_value_get_nonzero_entry (i_val2);
616 ca = get_new_covariance_accumulator (v1, v2, val1, val2);
617 ca->dot_product = update_product (ca->v1, ca->v2, ca->val1, ca->val2);
618 ca->dot_product *= iv_f1 * iv_f2;
619 ca->sum1 = update_sum (ca->v1, ca->val1, iv_f1);
620 ca->sum2 = update_sum (ca->v2, ca->val2, iv_f2);
622 new_entry = hsh_insert (c, ca);
624 if (new_entry != NULL)
626 new_entry->dot_product += ca->dot_product;
627 new_entry->ssize += 1.0;
628 new_entry->sum1 += ca->sum1;
629 new_entry->sum2 += ca->sum2;
631 If DOT_PRODUCT is null, CA was not already in the hash
632 hable, so we don't free it because it was just inserted.
633 If DOT_PRODUCT was not null, CA is already in the hash table.
634 Unnecessary now, it must be freed here.
641 update_hash_entry (struct hsh_table *c,
642 const struct variable *v1,
643 const struct variable *v2,
644 const union value *val1, const union value *val2)
646 struct covariance_accumulator *ca;
647 struct covariance_accumulator *new_entry;
649 ca = get_new_covariance_accumulator (v1, v2, val1, val2);
650 ca->dot_product = update_product (ca->v1, ca->v2, ca->val1, ca->val2);
651 ca->sum1 = update_sum (ca->v1, ca->val1, 1.0);
652 ca->sum2 = update_sum (ca->v2, ca->val2, 1.0);
654 new_entry = hsh_insert (c, ca);
656 if (new_entry != NULL)
658 new_entry->dot_product += ca->dot_product;
659 new_entry->ssize += 1.0;
660 new_entry->sum1 += ca->sum1;
661 new_entry->sum2 += ca->sum2;
663 If DOT_PRODUCT is null, CA was not already in the hash
664 hable, so we don't free it because it was just inserted.
665 If DOT_PRODUCT was not null, CA is already in the hash table.
666 Unnecessary now, it must be freed here.
673 inner_intr_loop (struct covariance_matrix *cov, const struct ccase *ccase, const struct variable *var1,
674 const union value *val1, const struct interaction_variable **i_var,
675 const struct interaction_value *i_val1, size_t j)
677 struct variable *var2;
679 struct interaction_value *i_val2;
681 var2 = interaction_get_variable (i_var[j]);
682 i_val2 = interaction_case_data (ccase, i_var[j]);
683 val2 = interaction_value_get (i_val2);
685 if (!var_is_value_missing (var2, val2, cov->missing_value))
687 update_hash_entry_intr (cov->ca, var1, var2, val1, val2, i_val1, i_val2);
691 Compute the covariance matrix in a single data-pass. Cases with
692 missing values are dropped pairwise, in other words, only if one of
693 the two values necessary to accumulate the inner product is missing.
695 Do not call this function directly. Call it through the struct
696 covariance_matrix ACCUMULATE member function, for example,
697 cov->accumulate (cov, ccase).
700 covariance_accumulate_pairwise (struct covariance_matrix *cov,
701 const struct ccase *ccase,
702 const struct interaction_variable **i_var,
707 const union value *val1;
708 const union value *val2;
709 const struct variable **v_variables;
710 const struct variable *var1;
711 const struct variable *var2;
712 struct interaction_value *i_val1 = NULL;
713 struct interaction_value *i_val2 = NULL;
715 assert (cov != NULL);
716 assert (ccase != NULL);
718 v_variables = get_covariance_variables (cov);
719 assert (v_variables != NULL);
721 for (i = 0; i < cov->n_variables; ++i)
723 var1 = v_variables[i];
724 val1 = case_data (ccase, var1);
725 if (!var_is_value_missing (var1, val1, cov->missing_value))
727 cat_value_update (var1, val1);
728 if (var_is_numeric (var1))
729 cov->update_moments (cov, i, val1->f);
731 for (j = i; j < cov->n_variables; j++)
733 var2 = v_variables[j];
734 val2 = case_data (ccase, var2);
735 if (!var_is_value_missing
736 (var2, val2, cov->missing_value))
738 update_hash_entry (cov->ca, var1, var2, val1, val2);
741 for (j = 0; j < cov->n_intr; j++)
743 inner_intr_loop (cov, ccase, var1, val1, i_var, i_val1, j);
747 for (i = 0; i < cov->n_intr; i++)
749 var1 = interaction_get_variable (i_var[i]);
750 i_val1 = interaction_case_data (ccase, i_var[i]);
751 val1 = interaction_value_get (i_val1);
752 cat_value_update (var1, val1);
753 if (!var_is_value_missing (var1, val1, cov->missing_value))
755 for (j = i; j < cov->n_intr; j++)
757 inner_intr_loop (cov, ccase, var1, val1, i_var, i_val1, j);
764 Compute the covariance matrix in a single data-pass. Cases with
765 missing values are dropped listwise. In other words, if one of the
766 values for any variable in a case is missing, the entire case is
769 The caller must use a casefilter to remove the cases with missing
770 values before calling covariance_accumulate_listwise. This function
771 assumes that CCASE has already passed through this filter, and
772 contains no missing values.
774 Do not call this function directly. Call it through the struct
775 covariance_matrix ACCUMULATE member function, for example,
776 cov->accumulate (cov, ccase).
779 covariance_accumulate_listwise (struct covariance_matrix *cov,
780 const struct ccase *ccase,
781 const struct interaction_variable **i_var,
786 const union value *val1;
787 const union value *val2;
788 const struct variable **v_variables;
789 struct interaction_value *i_val1 = NULL;
790 struct interaction_value *i_val2 = NULL;
792 assert (cov != NULL);
793 assert (ccase != NULL);
795 v_variables = get_covariance_variables (cov);
796 assert (v_variables != NULL);
798 for (i = 0; i < cov->n_variables; ++i)
800 val1 = case_data (ccase, v_variables[i]);
801 cat_value_update (v_variables[i], val1);
802 if (var_is_numeric (v_variables[i]))
803 cov->update_moments (cov, i, val1->f);
805 for (j = i; j < cov->n_variables; j++)
807 update_hash_entry (cov->ca, v_variables[i], v_variables[j],
814 Call this function during the data pass. Each case will be added to
815 a hash containing all values of the covariance matrix. After the
816 data have been passed, call covariance_matrix_compute to put the
817 values in the struct covariance_matrix.
820 covariance_matrix_accumulate (struct covariance_matrix *cov,
821 const struct ccase *ccase, void **aux, size_t n_intr)
823 cov->accumulate (cov, ccase, (const struct interaction_variable **) aux, n_intr);
827 Return the value corresponding to subscript TARGET. If that value corresponds
828 to the origin, return NULL.
830 static const union value *
831 get_value_from_subscript (const struct design_matrix *dm, size_t target)
833 const union value *result = NULL;
834 const struct variable *var;
837 var = design_matrix_col_to_var (dm, target);
838 if (var_is_numeric (var))
842 for (i = 0; i < cat_get_n_categories (var); i++)
844 result = cat_subscript_to_value (i, var);
845 if (dm_get_exact_subscript (dm, var, result) == target)
854 is_covariance_contributor (const struct covariance_accumulator *ca, const struct design_matrix *dm,
858 const struct variable *v1;
859 const struct variable *v2;
862 v1 = design_matrix_col_to_var (dm, i);
863 v2 = design_matrix_col_to_var (dm, j);
864 if (var_get_dict_index (v1) == var_get_dict_index(ca->v1))
866 if (var_get_dict_index (v2) == var_get_dict_index (ca->v2))
868 k = dm_get_exact_subscript (dm, v1, ca->val1);
871 k = dm_get_exact_subscript (dm, v2, ca->val2);
879 else if (var_get_dict_index (v1) == var_get_dict_index (ca->v2))
881 if (var_get_dict_index (v2) == var_get_dict_index (ca->v1))
883 k = dm_get_exact_subscript (dm, v1, ca->val2);
886 k = dm_get_exact_subscript (dm, v2, ca->val1);
898 get_sum (const struct covariance_matrix *cov, size_t i)
903 const struct variable *var;
904 const union value *val = NULL;
906 assert ( cov != NULL);
907 var = design_matrix_col_to_var (cov->cov, i);
910 if (var_is_alpha (var))
912 val = get_value_from_subscript (cov->cov, i);
913 k = cat_value_find (var, val);
914 return cat_get_category_count (k, var);
919 while (cov->v_variables[k] != var && k < cov->n_variables)
923 if (k < cov->n_variables)
925 moments1_calculate (cov->m1[k], &n, &mean, NULL, NULL, NULL);
934 update_ssize (struct design_matrix *dm, size_t i, size_t j, struct covariance_accumulator *ca)
936 const struct variable *var;
938 var = design_matrix_col_to_var (dm, i);
939 if (var_get_dict_index (ca->v1) == var_get_dict_index (var))
941 var = design_matrix_col_to_var (dm, j);
942 if (var_get_dict_index (ca->v2) == var_get_dict_index (var))
944 tmp = design_matrix_get_element (dm, i, j);
946 design_matrix_set_element (dm, i, j, tmp);
951 covariance_accumulator_to_matrix (struct covariance_matrix *cov)
958 struct covariance_accumulator *entry;
959 struct hsh_iterator iter;
961 cov->cov = covariance_matrix_create_s (cov);
962 cov->ssize = covariance_matrix_create_s (cov);
963 entry = hsh_first (cov->ca, &iter);
964 while (entry != NULL)
966 entry = hsh_next (cov->ca, &iter);
969 for (i = 0; i < design_matrix_get_n_cols (cov->cov); i++)
971 sum_i = get_sum (cov, i);
972 for (j = i; j < design_matrix_get_n_cols (cov->cov); j++)
974 sum_j = get_sum (cov, j);
975 entry = hsh_first (cov->ca, &iter);
976 while (entry != NULL)
978 update_ssize (cov->ssize, i, j, entry);
980 We compute the centered, un-normalized covariance matrix.
982 if (is_covariance_contributor (entry, cov->cov, i, j))
984 design_matrix_set_element (cov->cov, i, j, entry->dot_product);
986 entry = hsh_next (cov->ca, &iter);
988 tmp = design_matrix_get_element (cov->cov, i, j);
989 tmp -= sum_i * sum_j / design_matrix_get_element (cov->ssize, i, j);
990 design_matrix_set_element (cov->cov, i, j, tmp);
991 design_matrix_set_element (cov->cov, j, i, tmp);
998 Call this function after passing the data.
1001 covariance_matrix_compute (struct covariance_matrix *cov)
1003 if (cov->n_pass == ONE_PASS)
1005 covariance_accumulator_to_matrix (cov);
1009 struct design_matrix *
1010 covariance_to_design (const struct covariance_matrix *c)
1019 covariance_matrix_get_n_rows (const struct covariance_matrix *c)
1021 return design_matrix_get_n_rows (c->cov);
1025 covariance_matrix_get_element (const struct covariance_matrix *c, size_t row, size_t col)
1027 return (design_matrix_get_element (c->cov, row, col));