Fixed a bug where contrasts with negative T where incorrectly processed.
[pspp] / src / language / stats / oneway.c
index 9f660142f18fca876a7586978b7bd5b0777bee56..a64b760eb9174ab0ac0c61821c16a2fd4b8589c2 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-9, 2000, 2007, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
+   Copyright (C) 1997-9, 2000, 2007, 2009, 2010, 2011, 2012, 2013, 2014 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
@@ -16,6 +16,7 @@
 
 #include <config.h>
 
+#include <float.h>
 #include <gsl/gsl_cdf.h>
 #include <gsl/gsl_matrix.h>
 #include <math.h>
@@ -52,6 +53,7 @@
 /* Workspace variable for each dependent variable */
 struct per_var_ws
 {
+  struct interaction *iact;
   struct categoricals *cat;
   struct covariance *cov;
   struct levene *nl;
@@ -384,6 +386,37 @@ static void show_homogeneity (const struct oneway_spec *, const struct oneway_wo
 static void output_oneway (const struct oneway_spec *, struct oneway_workspace *ws);
 static void run_oneway (const struct oneway_spec *cmd, struct casereader *input, const struct dataset *ds);
 
+
+static void
+destroy_coeff_list (struct contrasts_node *coeff_list)
+{
+  struct coeff_node *cn = NULL;
+  struct coeff_node *cnx = NULL;
+  struct ll_list *cl = &coeff_list->coefficient_list;
+  
+  ll_for_each_safe (cn, cnx, struct coeff_node, ll, cl)
+    {
+      free (cn);
+    }
+  
+  free (coeff_list);
+}
+
+static void
+oneway_cleanup (struct oneway_spec *cmd)
+{
+  struct contrasts_node *coeff_list  = NULL;
+  struct contrasts_node *coeff_next  = NULL;
+  ll_for_each_safe (coeff_list, coeff_next, struct contrasts_node, ll, &cmd->contrast_list)
+    {
+      destroy_coeff_list (coeff_list);
+    }
+
+  free (cmd->posthoc);
+}
+
+
+
 int
 cmd_oneway (struct lexer *lexer, struct dataset *ds)
 {
@@ -505,6 +538,7 @@ cmd_oneway (struct lexer *lexer, struct dataset *ds)
                }
              else
                {
+                 destroy_coeff_list (cl);
                  lex_error (lexer, NULL);
                  goto error;
                }
@@ -560,10 +594,12 @@ cmd_oneway (struct lexer *lexer, struct dataset *ds)
     ok = proc_commit (ds) && ok;
   }
 
+  oneway_cleanup (&oneway);
   free (oneway.vars);
   return CMD_SUCCESS;
 
  error:
+  oneway_cleanup (&oneway);
   free (oneway.vars);
   return CMD_FAILURE;
 }
@@ -602,6 +638,15 @@ makeit (const void *aux1, void *aux2 UNUSED)
   return dd;
 }
 
+static void 
+killit (const void *aux1 UNUSED, void *aux2 UNUSED, void *user_data)
+{
+  struct descriptive_data *dd = user_data;
+
+  dd_destroy (dd);
+}
+
+
 static void 
 updateit (const void *aux1, void *aux2, void *user_data,
          const struct ccase *c, double weight)
@@ -659,14 +704,14 @@ run_oneway (const struct oneway_spec *cmd,
 
   for (v = 0; v < cmd->n_vars; ++v)
     {
-      struct interaction *inter = interaction_create (cmd->indep_var);
-
       struct payload payload;
       payload.create = makeit;
       payload.update = updateit;
-      payload.destroy = NULL;
+      payload.calculate = NULL;
+      payload.destroy = killit;
 
-      ws.vws[v].cat = categoricals_create (&inter, 1, cmd->wv,
+      ws.vws[v].iact = interaction_create (cmd->indep_var);
+      ws.vws[v].cat = categoricals_create (&ws.vws[v].iact, 1, cmd->wv,
                                            cmd->exclude, cmd->exclude);
 
       categoricals_set_payload (ws.vws[v].cat, &payload, 
@@ -771,10 +816,11 @@ run_oneway (const struct oneway_spec *cmd,
 
   for (v = 0; v < cmd->n_vars; ++v)
     {
+      const gsl_matrix *ucm;
       gsl_matrix *cm;
       struct per_var_ws *pvw = &ws.vws[v];
       const struct categoricals *cats = covariance_get_categoricals (pvw->cov);
-      const bool ok = categoricals_done (cats);
+      const bool ok = categoricals_sane (cats);
 
       if ( ! ok)
        {
@@ -784,7 +830,10 @@ run_oneway (const struct oneway_spec *cmd,
          continue;
        }
 
-      cm = covariance_calculate_unnormalized (pvw->cov);
+      ucm = covariance_calculate_unnormalized (pvw->cov);
+
+      cm = gsl_matrix_alloc (ucm->size1, ucm->size2);
+      gsl_matrix_memcpy (cm, ucm);
 
       moments1_calculate (ws.dd_total[v]->mom, &pvw->n, NULL, NULL, NULL, NULL);
 
@@ -793,14 +842,13 @@ run_oneway (const struct oneway_spec *cmd,
       reg_sweep (cm, 0);
 
       pvw->sse = gsl_matrix_get (cm, 0, 0);
+      gsl_matrix_free (cm);
 
       pvw->ssa = pvw->sst - pvw->sse;
 
       pvw->n_groups = categoricals_n_total (cats);
 
       pvw->mse = (pvw->sst - pvw->ssa) / (pvw->n - pvw->n_groups);
-
-      gsl_matrix_free (cm);
     }
 
   for (v = 0; v < cmd->n_vars; ++v)
@@ -824,12 +872,15 @@ run_oneway (const struct oneway_spec *cmd,
   taint_destroy (taint);
 
  finish:
+
   for (v = 0; v < cmd->n_vars; ++v)
     {
       covariance_destroy (ws.vws[v].cov);
       levene_destroy (ws.vws[v].nl);
       dd_destroy (ws.dd_total[v]);
+      interaction_destroy (ws.vws[v].iact);
     }
+
   free (ws.vws);
   free (ws.dd_total);
 }
@@ -860,6 +911,7 @@ output_oneway (const struct oneway_spec *cmd, struct oneway_workspace *ws)
               i, ll_count (cl), ws->actual_number_of_groups);
 
          ll_remove (&coeff_list->ll);
+         destroy_coeff_list (coeff_list);
          continue;
        }
 
@@ -924,7 +976,7 @@ show_anova_table (const struct oneway_spec *cmd, const struct oneway_workspace *
   tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("df"));
   tab_text (t, 4, 0, TAB_CENTER | TAT_TITLE, _("Mean Square"));
   tab_text (t, 5, 0, TAB_CENTER | TAT_TITLE, _("F"));
-  tab_text (t, 6, 0, TAB_CENTER | TAT_TITLE, _("Significance"));
+  tab_text (t, 6, 0, TAB_CENTER | TAT_TITLE, _("Sig."));
 
 
   for (i = 0; i < cmd->n_vars; ++i)
@@ -1171,7 +1223,7 @@ show_homogeneity (const struct oneway_spec *cmd, const struct oneway_workspace *
   tab_text (t, 1, 0, TAB_CENTER | TAT_TITLE, _("Levene Statistic"));
   tab_text (t, 2, 0, TAB_CENTER | TAT_TITLE, _("df1"));
   tab_text (t, 3, 0, TAB_CENTER | TAT_TITLE, _("df2"));
-  tab_text (t, 4, 0, TAB_CENTER | TAT_TITLE, _("Significance"));
+  tab_text (t, 4, 0, TAB_CENTER | TAT_TITLE, _("Sig."));
 
   tab_title (t, _("Test of Homogeneity of Variances"));
 
@@ -1281,7 +1333,8 @@ show_contrast_coeffs (const struct oneway_spec *cmd, const struct oneway_workspa
 
          ds_destroy (&vstr);
 
-         tab_text_format (t, count + 2, c_num + 2, TAB_RIGHT, "%g", coeffn->coeff);
+         tab_text_format (t, count + 2, c_num + 2, TAB_RIGHT, "%.*g",
+                           DBL_DIG + 1, coeffn->coeff);
        }
       ++c_num;
     }
@@ -1475,10 +1528,15 @@ show_contrast_tests (const struct oneway_spec *cmd, const struct oneway_workspac
                      TAB_RIGHT, df,
                      NULL);
 
-         /* The Significance */
-         tab_double (t, 7, (v * lines_per_variable) + i + 1 + n_contrasts,
-                     TAB_RIGHT,  2 * gsl_cdf_tdist_Q (T,df),
-                     NULL);
+         {
+           double p = gsl_cdf_tdist_P (T, df);
+           double q = gsl_cdf_tdist_Q (T, df);
+
+           /* The Significance */
+           tab_double (t, 7, (v * lines_per_variable) + i + 1 + n_contrasts,
+                       TAB_RIGHT,  2 * ((T > 0) ? q : p),
+                       NULL);
+         }
        }
 
       if ( v > 0 )
@@ -1523,7 +1581,7 @@ show_comparisons (const struct oneway_spec *cmd, const struct oneway_workspace *
 
   tab_vline (t, TAL_2, heading_cols, 0, n_rows - 1);
 
-  tab_title (t, _("Multiple Comparisons"));
+  tab_title (t, _("Multiple Comparisons (%s)"), var_to_string (cmd->vars[v]));
 
   tab_text_format (t,  1, 1, TAB_LEFT | TAT_TITLE, _("(I) %s"), var_to_string (cmd->indep_var));
   tab_text_format (t,  2, 1, TAB_LEFT | TAT_TITLE, _("(J) %s"), var_to_string (cmd->indep_var));