Merge commit 'origin/stable'
authorJohn Darrington <john@darrington.wattle.id.au>
Tue, 7 Apr 2009 11:30:23 +0000 (19:30 +0800)
committerJohn Darrington <john@darrington.wattle.id.au>
Tue, 7 Apr 2009 11:30:23 +0000 (19:30 +0800)
Conflicts:

src/language/stats/crosstabs.q
src/language/stats/examine.q
src/language/stats/frequencies.q
src/language/stats/oneway.q
tests/command/examine-extremes.sh
tests/command/examine.sh

18 files changed:
1  2 
src/language/stats/binomial.c
src/language/stats/chisquare.c
src/language/stats/crosstabs.q
src/language/stats/descriptives.c
src/language/stats/examine.q
src/language/stats/frequencies.q
src/language/stats/npar-summary.c
src/language/stats/oneway.q
src/language/stats/regression.q
src/language/stats/reliability.q
src/language/stats/t-test.q
src/language/stats/wilcoxon.c
tests/automake.mk
tests/command/examine-extremes.sh
tests/command/examine.sh
tests/command/npar-binomial.sh
tests/command/npar-wilcoxon.sh
tests/command/reliability.sh

index b7b672ef682b651ca5d737b5b862761456577afe,7a0ac72292e802587312f43cfe8eac18894c21cc..f4344b76e86010603e10e0af33a12e8f717632af
@@@ -153,11 -144,10 +154,12 @@@ voi
  binomial_execute (const struct dataset *ds,
                  struct casereader *input,
                    enum mv_class exclude,
 -                const struct npar_test *test)
 +                const struct npar_test *test,
 +                bool exact UNUSED,
 +                double timer UNUSED)
  {
    int v;
+   const struct dictionary *dict = dataset_dict (ds);
    const struct binomial_test *bst = (const struct binomial_test *) test;
    const struct one_sample_test *ost = (const struct one_sample_test*) test;
  
  
    if ( bst->category2 != SYSMIS )
      {
 +      int i;
        union value v;
        v.f = bst->category2;
 -      cat2->value = value_dup (&v, 0);
 +      for (i = 0; i < ost->n_vars; i++)
 +      cat2[i].value = value_dup (&v, 0);
      }
  
-   if (do_binomial (dataset_dict(ds), input, bst, cat1, cat2, exclude))
+   if (do_binomial (dict, input, bst, cat1, cat2, exclude))
      {
+       const struct variable *wvar = dict_get_weight (dict);
+       const struct fmt_spec *wfmt = wvar ?
+       var_get_print_format (wvar) : & F_8_0;
        struct tab_table *table = tab_create (7, ost->n_vars * 3 + 1, 0);
  
        tab_dim (table, tab_natural_dimensions);
          tab_text (table, 2, 2 + v * 3, TAB_NONE, ds_cstr (&catstr2));
  
            /* Observed N */
-           tab_float (table, 3, 1 + v * 3, TAB_NONE, cat1[v].count, 8, 0);
-           tab_float (table, 3, 2 + v * 3, TAB_NONE, cat2[v].count, 8, 0);
+           tab_double (table, 3, 1 + v * 3, TAB_NONE, cat1[v].count, wfmt);
+           tab_double (table, 3, 2 + v * 3, TAB_NONE, cat2[v].count, wfmt);
  
            n_total = cat1[v].count + cat2[v].count;
-           tab_float (table, 3, 3 + v * 3, TAB_NONE, n_total, 8, 0);
+           tab_double (table, 3, 3 + v * 3, TAB_NONE, n_total, wfmt);
  
            /* Observed Proportions */
-           tab_float (table, 4, 1 + v * 3, TAB_NONE,
-                      cat1[v].count / n_total, 8, 3);
-           tab_float (table, 4, 2 + v * 3, TAB_NONE,
-                      cat2[v].count / n_total, 8, 3);
-           tab_float (table, 4, 3 + v * 3, TAB_NONE,
-                      (cat1[v].count + cat2[v].count) / n_total, 8, 2);
+           tab_double (table, 4, 1 + v * 3, TAB_NONE,
+                      cat1[v].count / n_total, NULL);
+           tab_double (table, 4, 2 + v * 3, TAB_NONE,
+                      cat2[v].count / n_total, NULL);
+           tab_double (table, 4, 3 + v * 3, TAB_NONE,
 -                     (cat1[v].count + cat2[v].count) / n_total, wfmt);
++                     (cat1[v].count + cat2[v].count) / n_total, NULL);
  
            /* Significance */
            sig = calculate_binomial (cat1[v].count, cat2[v].count, bst->p);
Simple merge
index 68d11e307e0ff41584d1ffae0ef4abd6d8c9ff74,186ee12b995551b51b66851b502445ec008fe0b1..309b27fc3c51cb136ae5f9d012e5d538625ade5d
@@@ -177,9 -177,9 +177,10 @@@ static struct pool *pl_col;       /* For colu
  
  static int internal_cmd_crosstabs (struct lexer *lexer, struct dataset *ds);
  static void precalc (struct casereader *, const struct dataset *);
 -static void calc_general (struct ccase *, const struct dataset *);
 -static void calc_integer (struct ccase *, const struct dataset *);
 +static void calc_general (const struct ccase *, const struct dataset *);
 +static void calc_integer (const struct ccase *, const struct dataset *);
- static void postcalc (void);
+ static void postcalc (const struct dataset *);
++
  static void submit (struct tab_table *);
  
  static void format_short (char *s, const struct fmt_spec *fp,
Simple merge
index 2649968b31485b105f6a80f3119ab39bdc851eea,febb60fedeeb5d5146253c5b3c434bece64ff79e..51f2832052e57461e628b96353c4d16b3101f6d4
  static struct cmd_examine cmd;
  
  static const struct variable **dependent_vars;
 -
  static size_t n_dependent_vars;
  
 +/* PERCENTILES */
 +
 +static subc_list_double percentile_list;
 +static enum pc_alg percentile_algorithm;
  
 -struct factor
 +struct factor_metrics
  {
 -  /* The independent variable */
 -  struct variable *indep_var[2];
 +  struct moments1 *moments;
 +
 +  struct percentile **ptl;
 +  size_t n_ptiles;
 +
 +  struct statistic *tukey_hinges;
 +  struct statistic *box_whisker;
 +  struct statistic *trimmed_mean;
 +  struct statistic *histogram;
 +  struct order_stats *np;
 +
 +  /* Three quartiles indexing into PTL */
 +  struct percentile **quartiles;
 +
 +  /* A reader sorted in ASCENDING order */
 +  struct casereader *up_reader;
 +
 +  /* The minimum value of all the weights */
 +  double cmin;
 +
 +  /* Sum of all weights, including those for missing values */
 +  double n;
 +
 +  /* Sum of weights of non_missing values */
 +  double n_valid;
  
 +  double mean;
  
 -  /* Hash table of factor stats indexed by 2 values */
 -  struct hsh_table *fstats;
 +  double variance;
  
 -  /* The hash table after it has been crunched */
 -  struct factor_statistics **fs;
 +  double skewness;
  
 -  struct factor *next;
 +  double kurtosis;
  
 +  double se_mean;
 +
 +  struct extrema *minima;
 +  struct extrema *maxima;
  };
  
 -/* Linked list of factors */
 -static struct factor *factors = 0;
 +struct factor_result
 +{
 +  struct ll ll;
  
 -static struct metrics *totals = 0;
 +  union value *value[2];
  
 -/* Parse the clause specifying the factors */
 -static int examine_parse_independent_vars (struct lexer *lexer, const struct dictionary *dict, struct cmd_examine *cmd);
 +  /* An array of factor metrics, one for each variable */
 +  struct factor_metrics *metrics;
 +};
  
 +struct xfactor
 +{
 +  /* We need to make a list of this structure */
 +  struct ll ll;
  
 +  /* The independent variable */
 +  const struct variable const* indep_var[2];
  
 -/* Output functions */
 -static void show_summary (const struct variable **dependent_var, int n_dep_var,
 -                        const struct dictionary *dict,
 -                        const struct factor *f);
 +  /* A list of results for this factor */
 +  struct ll_list result_list ;
 +};
  
 -static void show_extremes (const struct variable **dependent_var,
 -                         int n_dep_var,
 -                         const struct factor *factor,
 -                         int n_extremities);
  
 -static void show_descriptives (const struct variable **dependent_var,
 -                            int n_dep_var,
 -                            struct factor *factor);
 +static void
 +factor_destroy (struct xfactor *fctr)
 +{
 +  struct ll *ll = ll_head (&fctr->result_list);
 +  while (ll != ll_null (&fctr->result_list))
 +    {
 +      int v;
 +      struct factor_result *result =
 +      ll_data (ll, struct factor_result, ll);
  
 -static void show_percentiles (const struct variable **dependent_var,
 -                           int n_dep_var,
 -                           struct factor *factor);
 +      for (v = 0; v < n_dependent_vars; ++v)
 +      {
 +        int i;
 +        moments1_destroy (result->metrics[v].moments);
 +        extrema_destroy (result->metrics[v].minima);
 +        extrema_destroy (result->metrics[v].maxima);
 +        statistic_destroy (result->metrics[v].trimmed_mean);
 +        statistic_destroy (result->metrics[v].tukey_hinges);
 +        statistic_destroy (result->metrics[v].box_whisker);
 +        statistic_destroy (result->metrics[v].histogram);
 +        for (i = 0 ; i < result->metrics[v].n_ptiles; ++i)
 +          statistic_destroy ((struct statistic *) result->metrics[v].ptl[i]);
 +        free (result->metrics[v].ptl);
 +        free (result->metrics[v].quartiles);
 +        casereader_destroy (result->metrics[v].up_reader);
 +      }
 +
 +      free (result->value[0]);
 +      free (result->value[1]);
 +      free (result->metrics);
 +      ll = ll_next (ll);
 +      free (result);
 +    }
 +}
  
 +static struct xfactor level0_factor;
 +static struct ll_list factor_list;
 +
 +/* Parse the clause specifying the factors */
 +static int examine_parse_independent_vars (struct lexer *lexer,
 +                                         const struct dictionary *dict,
 +                                         struct cmd_examine *cmd);
  
 +/* Output functions */
 +static void show_summary (const struct variable **dependent_var, int n_dep_var,
++                        const struct dictionary *dict,
 +                        const struct xfactor *f);
  
  
 -void np_plot (const struct metrics *m, const char *factorname);
 +static void show_descriptives (const struct variable **dependent_var,
 +                             int n_dep_var,
 +                             const struct xfactor *f);
  
  
 -void box_plot_group (const struct factor *fctr,
 -                  const struct variable **vars, int n_vars,
 -                  const struct variable *id
 -                  ) ;
 +static void show_percentiles (const struct variable **dependent_var,
 +                             int n_dep_var,
 +                             const struct xfactor *f);
  
  
 -void box_plot_variables (const struct factor *fctr,
 -                      const struct variable **vars, int n_vars,
 -                      const struct variable *id
 -                      );
 +static void show_extremes (const struct variable **dependent_var,
 +                         int n_dep_var,
 +                         const struct xfactor *f);
 +
  
  
  
@@@ -626,66 -406,36 +627,66 @@@ show_boxplot_variables (const struct va
  }
  
  
 -/* Create a hash table of percentiles and their values from the list of
 -   percentiles */
 -static struct hsh_table *
 -list_to_ptile_hash (const subc_list_double *l)
 +/* Show all the appropriate tables */
 +static void
- output_examine (void)
++output_examine (const struct dictionary *dict)
  {
 -  int i;
 +  struct ll *ll;
 +
-   show_summary (dependent_vars, n_dependent_vars, &level0_factor);
++  show_summary (dependent_vars, n_dependent_vars, dict, &level0_factor);
  
 -  struct hsh_table *h ;
 +  if ( cmd.a_statistics[XMN_ST_EXTREME] )
 +    show_extremes (dependent_vars, n_dependent_vars, &level0_factor);
  
 -  h = hsh_create (subc_list_double_count (l),
 -               (hsh_compare_func *) ptile_compare,
 -               (hsh_hash_func *) ptile_hash,
 -               (hsh_free_func *) free,
 -               0);
 +  if ( cmd.a_statistics[XMN_ST_DESCRIPTIVES] )
 +    show_descriptives (dependent_vars, n_dependent_vars, &level0_factor);
  
 +  if ( cmd.sbc_percentiles)
 +    show_percentiles (dependent_vars, n_dependent_vars, &level0_factor);
  
 -  for ( i = 0 ; i < subc_list_double_count (l) ; ++i )
 +  if ( cmd.sbc_plot)
      {
 -      struct percentile *p = xmalloc (sizeof *p);
 -
 -      p->p = subc_list_double_at (l,i);
 -      p->v = SYSMIS;
 +      if (cmd.a_plot[XMN_PLT_BOXPLOT])
 +      show_boxplot_groups (dependent_vars, n_dependent_vars, &level0_factor);
  
 -      hsh_insert (h, p);
 +      if (cmd.a_plot[XMN_PLT_HISTOGRAM])
 +      show_histogram (dependent_vars, n_dependent_vars, &level0_factor);
  
 +      if (cmd.a_plot[XMN_PLT_NPPLOT])
 +      show_npplot (dependent_vars, n_dependent_vars, &level0_factor);
      }
  
 -  return h;
 +  for (ll = ll_head (&factor_list);
 +       ll != ll_null (&factor_list); ll = ll_next (ll))
 +    {
 +      struct xfactor *factor = ll_data (ll, struct xfactor, ll);
-       show_summary (dependent_vars, n_dependent_vars, factor);
++      show_summary (dependent_vars, n_dependent_vars, dict, factor);
 +
 +      if ( cmd.a_statistics[XMN_ST_EXTREME] )
 +      show_extremes (dependent_vars, n_dependent_vars, factor);
  
 +      if ( cmd.a_statistics[XMN_ST_DESCRIPTIVES] )
 +      show_descriptives (dependent_vars, n_dependent_vars, factor);
 +
 +      if ( cmd.sbc_percentiles)
 +      show_percentiles (dependent_vars, n_dependent_vars, factor);
 +
 +      if (cmd.a_plot[XMN_PLT_BOXPLOT] &&
 +        cmd.cmp == XMN_GROUPS)
 +      show_boxplot_groups (dependent_vars, n_dependent_vars, factor);
 +
 +
 +      if (cmd.a_plot[XMN_PLT_BOXPLOT] &&
 +        cmd.cmp == XMN_VARIABLES)
 +      show_boxplot_variables (dependent_vars, n_dependent_vars,
 +                              factor);
 +
 +      if (cmd.a_plot[XMN_PLT_HISTOGRAM])
 +      show_histogram (dependent_vars, n_dependent_vars, factor);
 +
 +      if (cmd.a_plot[XMN_PLT_NPPLOT])
 +      show_npplot (dependent_vars, n_dependent_vars, factor);
 +    }
  }
  
  /* Parse the PERCENTILES subcommand */
@@@ -867,350 -620,312 +868,354 @@@ examine_parse_independent_vars (struct 
    return success;
  }
  
 +static void
 +examine_group (struct cmd_examine *cmd, struct casereader *reader, int level,
 +             const struct dictionary *dict, struct xfactor *factor)
 +{
 +  struct ccase *c;
 +  const struct variable *wv = dict_get_weight (dict);
 +  int v;
 +  int n_extrema = 1;
 +  struct factor_result *result = xzalloc (sizeof (*result));
 +
 +  result->metrics = xcalloc (n_dependent_vars, sizeof (*result->metrics));
  
 +  if ( cmd->a_statistics[XMN_ST_EXTREME] )
 +    n_extrema = cmd->st_n;
  
  
 -static void populate_percentiles (struct tab_table *tbl, int col, int row,
 -                                const struct metrics *m);
 +  c = casereader_peek (reader, 0);
 +  if (c != NULL)
 +    {
 +      if ( level > 0)
 +      {
 +        result->value[0] =
 +          value_dup (case_data (c, factor->indep_var[0]),
 +                     var_get_width (factor->indep_var[0]));
 +
 +        if ( level > 1)
 +          result->value[1] =
 +            value_dup (case_data (c, factor->indep_var[1]),
 +                       var_get_width (factor->indep_var[1]));
 +      }
 +      case_unref (c);
 +    }
  
 -static void populate_descriptives (struct tab_table *t, int col, int row,
 -                                 const struct variable *,
 -                                 const struct metrics *fs);
 +  for (v = 0; v < n_dependent_vars; ++v)
 +    {
 +      struct casewriter *writer;
 +      struct casereader *input = casereader_clone (reader);
 +
 +      result->metrics[v].moments = moments1_create (MOMENT_KURTOSIS);
 +      result->metrics[v].minima = extrema_create (n_extrema, EXTREME_MINIMA);
 +      result->metrics[v].maxima = extrema_create (n_extrema, EXTREME_MAXIMA);
 +      result->metrics[v].cmin = DBL_MAX;
 +
 +      if (cmd->a_statistics[XMN_ST_DESCRIPTIVES] ||
 +        cmd->a_plot[XMN_PLT_BOXPLOT] ||
 +        cmd->a_plot[XMN_PLT_NPPLOT] ||
 +        cmd->sbc_percentiles)
 +      {
 +        /* In this case, we need to sort the data, so we create a sorting
 +           casewriter */
 +        struct subcase up_ordering;
 +          subcase_init_var (&up_ordering, dependent_vars[v], SC_ASCEND);
 +        writer = sort_create_writer (&up_ordering,
 +                                     casereader_get_value_cnt (reader));
 +          subcase_destroy (&up_ordering);
 +      }
 +      else
 +      {
 +        /* but in this case, sorting is unnecessary, so an ordinary
 +           casewriter is sufficient */
 +        writer =
 +          autopaging_writer_create (casereader_get_value_cnt (reader));
 +      }
  
 -static void populate_extremes (struct tab_table *t, int col, int row, int n,
 -                             const struct variable *var,
 -                             const struct metrics *m);
  
 -static void populate_summary (struct tab_table *t, int col, int row,
 -                            const struct dictionary *dict,
 -                            const struct metrics *m);
 +      /* Sort or just iterate, whilst calculating moments etc */
 +      while ((c = casereader_read (input)) != NULL)
 +      {
 +        const casenumber loc =
 +            case_data_idx (c, casereader_get_value_cnt (reader) - 1)->f;
  
 +        const double weight = wv ? case_data (c, wv)->f : 1.0;
 +        const union value *value = case_data (c, dependent_vars[v]);
  
 +        if (weight != SYSMIS)
 +          minimize (&result->metrics[v].cmin, weight);
  
 +        moments1_add (result->metrics[v].moments,
 +                      value->f,
 +                      weight);
  
 -/* Perform calculations for the sub factors */
 -void
 -factor_calc (const struct ccase *c, int case_no, double weight,
 -           bool case_missing)
 -{
 -  size_t v;
 -  struct factor *fctr = factors;
 +        result->metrics[v].n += weight;
  
 -  while ( fctr)
 -    {
 -      struct factor_statistics **foo ;
 -      union value *indep_vals[2] ;
 +        if ( ! var_is_value_missing (dependent_vars[v], value, MV_ANY) )
 +          result->metrics[v].n_valid += weight;
  
 -      indep_vals[0] = value_dup (
 -                               case_data (c, fctr->indep_var[0]),
 -                               var_get_width (fctr->indep_var[0])
 -                               );
 +        extrema_add (result->metrics[v].maxima,
 +                     value->f,
 +                     weight,
 +                     loc);
  
 -      if ( fctr->indep_var[1] )
 -      indep_vals[1] = value_dup (
 -                                 case_data (c, fctr->indep_var[1]),
 -                                 var_get_width (fctr->indep_var[1])
 -                                 );
 -      else
 -      {
 -        const union value sm = {SYSMIS};
 -        indep_vals[1] = value_dup (&sm, 0);
 +        extrema_add (result->metrics[v].minima,
 +                     value->f,
 +                     weight,
 +                     loc);
 +
 +        casewriter_write (writer, c);
        }
 +      casereader_destroy (input);
 +      result->metrics[v].up_reader = casewriter_make_reader (writer);
 +    }
  
 -      assert (fctr->fstats);
 +  /* If percentiles or descriptives have been requested, then a
 +     second pass through the data (which has now been sorted)
 +     is necessary */
 +  if ( cmd->a_statistics[XMN_ST_DESCRIPTIVES] ||
 +       cmd->a_plot[XMN_PLT_BOXPLOT] ||
 +       cmd->a_plot[XMN_PLT_NPPLOT] ||
 +       cmd->sbc_percentiles)
 +    {
 +      for (v = 0; v < n_dependent_vars; ++v)
 +      {
 +        int i;
 +        int n_os;
 +        struct order_stats **os ;
 +        struct factor_metrics *metric = &result->metrics[v];
  
 -      foo = ( struct factor_statistics ** )
 -      hsh_probe (fctr->fstats, (void *) &indep_vals);
 +        metric->n_ptiles = percentile_list.n_data;
  
 -      if ( !*foo )
 -      {
 +        metric->ptl = xcalloc (metric->n_ptiles,
 +                               sizeof (struct percentile *));
  
 -        *foo = create_factor_statistics (n_dependent_vars,
 -                                        indep_vals[0],
 -                                        indep_vals[1]);
 +        metric->quartiles = xcalloc (3, sizeof (*metric->quartiles));
  
 -        for ( v =  0 ; v  < n_dependent_vars ; ++v )
 +        for (i = 0 ; i < metric->n_ptiles; ++i)
            {
 -            metrics_precalc ( & (*foo)->m[v] );
 +            metric->ptl[i] = (struct percentile *)
 +              percentile_create (percentile_list.data[i] / 100.0, metric->n_valid);
 +
 +            if ( percentile_list.data[i] == 25)
 +              metric->quartiles[0] = metric->ptl[i];
 +            else if ( percentile_list.data[i] == 50)
 +              metric->quartiles[1] = metric->ptl[i];
 +            else if ( percentile_list.data[i] == 75)
 +              metric->quartiles[2] = metric->ptl[i];
            }
  
 -      }
 -      else
 -      {
 -        free (indep_vals[0]);
 -        free (indep_vals[1]);
 -      }
 +        metric->tukey_hinges = tukey_hinges_create (metric->n, metric->cmin);
 +        metric->trimmed_mean = trimmed_mean_create (metric->n, 0.05);
  
 -      for ( v =  0 ; v  < n_dependent_vars ; ++v )
 -      {
 -        const struct variable *var = dependent_vars[v];
 -        union value *val = value_dup (
 -                                      case_data (c, var),
 -                                      var_get_width (var)
 -                                      );
 +        n_os = metric->n_ptiles + 2;
  
 -        if (case_missing || var_is_value_missing (var, val, exclude_values))
 +       if ( cmd->a_plot[XMN_PLT_NPPLOT] )
            {
 -            free (val);
 -            val = NULL;
 +            metric->np = np_create (metric->moments);
 +            n_os ++;
            }
  
 -        metrics_calc ( & (*foo)->m[v], val, weight, case_no);
 +        os = xcalloc (sizeof (struct order_stats *), n_os);
  
 -        free (val);
 -      }
 +        for (i = 0 ; i < metric->n_ptiles ; ++i )
 +          {
 +            os[i] = (struct order_stats *) metric->ptl[i];
 +          }
  
 -      fctr = fctr->next;
 -    }
 -}
 +        os[i] = (struct order_stats *) metric->tukey_hinges;
 +        os[i+1] = (struct order_stats *) metric->trimmed_mean;
  
 -static void
 -run_examine (struct cmd_examine *cmd, struct casereader *input,
 -             struct dataset *ds)
 -{
 -  struct dictionary *dict = dataset_dict (ds);
 -  casenumber case_no;
 -  struct ccase c;
 -  int v;
 -  bool ok;
 +        if (cmd->a_plot[XMN_PLT_NPPLOT])
 +          os[i+2] = metric->np;
  
 -  struct factor *fctr;
 -
 -  if (!casereader_peek (input, 0, &c))
 -    {
 -      casereader_destroy (input);
 -      return;
 +        order_stats_accumulate (os, n_os,
 +                                casereader_clone (metric->up_reader),
 +                                wv, dependent_vars[v], MV_ANY);
 +        free (os);
 +      }
      }
 -  output_split_file_values (ds, &c);
 -  case_destroy (&c);
 -
 -  input = casereader_create_filter_weight (input, dict, NULL, NULL);
 -  input = casereader_create_counter (input, &case_no, 0);
  
 -  /* Make sure we haven't got rubbish left over from a
 -     previous split. */
 -  fctr = factors;
 -  while (fctr)
 +  /* FIXME: Do this in the above loop */
 +  if ( cmd->a_plot[XMN_PLT_HISTOGRAM] )
      {
 -      struct factor *next = fctr->next;
 +      struct ccase *c;
 +      struct casereader *input = casereader_clone (reader);
  
 -      hsh_clear (fctr->fstats);
 +      for (v = 0; v < n_dependent_vars; ++v)
 +      {
 +        const struct extremum  *max, *min;
 +        struct factor_metrics *metric = &result->metrics[v];
  
 -      fctr->fs = 0;
 +        const struct ll_list *max_list =
 +          extrema_list (result->metrics[v].maxima);
  
 -      fctr = next;
 -    }
 +        const struct ll_list *min_list =
 +          extrema_list (result->metrics[v].minima);
  
 -  for ( v = 0 ; v < n_dependent_vars ; ++v )
 -    metrics_precalc (&totals[v]);
 +        if ( ll_is_empty (max_list))
 +          {
 +            msg (MW, _("Not creating plot because data set is empty."));
 +            continue;
 +          }
  
 -  for (; casereader_read (input, &c); case_destroy (&c))
 -    {
 -      bool case_missing = false;
 -      const double weight = dict_get_case_weight (dict, &c, NULL);
 +        assert (! ll_is_empty (min_list));
  
 -      if ( cmd->miss == XMN_LISTWISE )
 -      {
 -        for ( v = 0 ; v < n_dependent_vars ; ++v )
 -          {
 -            const struct variable *var = dependent_vars[v];
 -            union value *val = value_dup (
 -                                                case_data (&c, var),
 -                                                var_get_width (var)
 -                                                );
 +        max = (const struct extremum *)
 +          ll_data (ll_head(max_list), struct extremum, ll);
  
 -            if ( var_is_value_missing (var, val, exclude_values))
 -              case_missing = true;
 +          min = (const struct extremum *)
 +          ll_data (ll_head (min_list), struct extremum, ll);
  
 -            free (val);
 -          }
 +                metric->histogram = histogram_create (10, min->value, max->value);
        }
  
 -      for ( v = 0 ; v < n_dependent_vars ; ++v )
 +      while ((c = casereader_read (input)) != NULL)
        {
 -        const struct variable *var = dependent_vars[v];
 -        union value *val = value_dup (
 -                                      case_data (&c, var),
 -                                      var_get_width (var)
 -                                      );
 -
 -        if ( var_is_value_missing (var, val, exclude_values)
 -               || case_missing )
 +        const double weight = wv ? case_data (c, wv)->f : 1.0;
 +
 +        for (v = 0; v < n_dependent_vars; ++v)
            {
 -            free (val) ;
 -            val = NULL;
 +            struct factor_metrics *metric = &result->metrics[v];
 +            if ( metric->histogram)
 +              histogram_add ((struct histogram *) metric->histogram,
 +                             case_data (c, dependent_vars[v])->f, weight);
            }
 -
 -        metrics_calc (&totals[v], val, weight, case_no);
 -
 -        free (val);
 +        case_unref (c);
        }
 -
 -      factor_calc (&c, case_no, weight, case_missing);
 +      casereader_destroy (input);
      }
 -  ok = casereader_destroy (input);
  
 -  for ( v = 0 ; v < n_dependent_vars ; ++v)
 +  /* In this case, a third iteration is required */
 +  if (cmd->a_plot[XMN_PLT_BOXPLOT])
      {
 -      fctr = factors;
 -      while ( fctr )
 +      for (v = 0; v < n_dependent_vars; ++v)
        {
 -        struct hsh_iterator hi;
 -        struct factor_statistics *fs;
 +        struct factor_metrics *metric = &result->metrics[v];
 +
 +        metric->box_whisker =
 +          box_whisker_create ((struct tukey_hinges *) metric->tukey_hinges,
 +                              cmd->v_id,
 +                              casereader_get_value_cnt (metric->up_reader)
 +                              - 1);
 +
 +        order_stats_accumulate ((struct order_stats **) &metric->box_whisker,
 +                                1,
 +                                casereader_clone (metric->up_reader),
 +                                wv, dependent_vars[v], MV_ANY);
 +      }
 +    }
  
 -        for ( fs = hsh_first (fctr->fstats, &hi);
 -              fs != 0 ;
 -              fs = hsh_next (fctr->fstats, &hi))
 -          {
 +  ll_push_tail (&factor->result_list, &result->ll);
 +  casereader_destroy (reader);
 +}
  
 -            fs->m[v].ptile_hash = list_to_ptile_hash (&percentile_list);
 -            fs->m[v].ptile_alg = percentile_algorithm;
 -            metrics_postcalc (&fs->m[v]);
 -          }
  
 -        fctr = fctr->next;
 -      }
 +static void
 +run_examine (struct cmd_examine *cmd, struct casereader *input,
 +             struct dataset *ds)
 +{
 +  struct ll *ll;
 +  const struct dictionary *dict = dataset_dict (ds);
 +  struct ccase *c;
 +  struct casereader *level0 = casereader_clone (input);
  
 -      totals[v].ptile_hash = list_to_ptile_hash (&percentile_list);
 -      totals[v].ptile_alg = percentile_algorithm;
 -      metrics_postcalc (&totals[v]);
 +  c = casereader_peek (input, 0);
 +  if (c == NULL)
 +    {
 +      casereader_destroy (input);
 +      return;
      }
  
 +  output_split_file_values (ds, c);
 +  case_unref (c);
  
 -  /* Make sure that the combination of factors are complete */
 -
 -  fctr = factors;
 -  while ( fctr )
 -    {
 -      struct hsh_iterator hi;
 -      struct hsh_iterator hi0;
 -      struct hsh_iterator hi1;
 -      struct factor_statistics *fs;
 +  ll_init (&level0_factor.result_list);
  
 -      struct hsh_table *idh0 = NULL;
 -      struct hsh_table *idh1 = NULL;
 -      union value **val0;
 -      union value **val1;
 +  examine_group (cmd, level0, 0, dict, &level0_factor);
  
 -      idh0 = hsh_create (4, (hsh_compare_func *) compare_ptr_values,
 -                       (hsh_hash_func *) hash_ptr_value,
 -                      0,0);
 +  for (ll = ll_head (&factor_list);
 +       ll != ll_null (&factor_list);
 +       ll = ll_next (ll))
 +    {
 +      struct xfactor *factor = ll_data (ll, struct xfactor, ll);
  
 -      idh1 = hsh_create (4, (hsh_compare_func *) compare_ptr_values,
 -                       (hsh_hash_func *) hash_ptr_value,
 -                      0,0);
 +      struct casereader *group = NULL;
 +      struct casereader *level1;
 +      struct casegrouper *grouper1 = NULL;
  
 +      level1 = casereader_clone (input);
 +      level1 = sort_execute_1var (level1, factor->indep_var[0]);
 +      grouper1 = casegrouper_create_vars (level1, &factor->indep_var[0], 1);
  
 -      for ( fs = hsh_first (fctr->fstats, &hi);
 -          fs != 0 ;
 -          fs = hsh_next (fctr->fstats, &hi))
 +      while (casegrouper_get_next_group (grouper1, &group))
        {
 -        hsh_insert (idh0, &fs->id[0]);
 -        hsh_insert (idh1, &fs->id[1]);
 -      }
 +        struct casereader *group_copy = casereader_clone (group);
  
 -      /* Ensure that the factors combination is complete */
 -      for ( val0 = hsh_first (idh0, &hi0);
 -          val0 != 0 ;
 -          val0 = hsh_next (idh0, &hi0))
 -      {
 -        for ( val1 = hsh_first (idh1, &hi1);
 -              val1 != 0 ;
 -              val1 = hsh_next (idh1, &hi1))
 +        if ( !factor->indep_var[1])
 +          examine_group (cmd, group_copy, 1, dict, factor);
 +        else
            {
 -            struct factor_statistics **ffs;
 -            union value *key[2];
 -            key[0] = *val0;
 -            key[1] = *val1;
 -
 -            ffs = (struct factor_statistics **)
 -              hsh_probe (fctr->fstats, &key );
 -
 -            if ( !*ffs ) {
 -              size_t i;
 -               (*ffs) = create_factor_statistics (n_dependent_vars,
 -                                                 key[0], key[1]);
 -              for ( i = 0 ; i < n_dependent_vars ; ++i )
 -                metrics_precalc ( & (*ffs)->m[i]);
 -            }
 -          }
 -      }
 +            int n_groups = 0;
 +            struct casereader *group2 = NULL;
 +            struct casegrouper *grouper2 = NULL;
  
 -      hsh_destroy (idh0);
 -      hsh_destroy (idh1);
 +            group_copy = sort_execute_1var (group_copy,
 +                                              factor->indep_var[1]);
  
 -      fctr->fs = (struct factor_statistics **) hsh_sort_copy (fctr->fstats);
 +            grouper2 = casegrouper_create_vars (group_copy,
 +                                                  &factor->indep_var[1], 1);
 +
 +            while (casegrouper_get_next_group (grouper2, &group2))
 +              {
 +                examine_group (cmd, group2, 2, dict, factor);
 +                n_groups++;
 +              }
 +            casegrouper_destroy (grouper2);
 +          }
  
 -      fctr = fctr->next;
 +        casereader_destroy (group);
 +      }
 +      casegrouper_destroy (grouper1);
      }
  
 -  if (ok)
 -    output_examine (dict);
 +  casereader_destroy (input);
  
-   output_examine ();
++  output_examine (dict);
 +
 +  factor_destroy (&level0_factor);
 +
 +  {
 +    struct ll *ll;
 +    for (ll = ll_head (&factor_list);
 +       ll != ll_null (&factor_list);
 +       ll = ll_next (ll))
 +      {
 +      struct xfactor *f = ll_data (ll, struct xfactor, ll);
 +      factor_destroy (f);
 +      }
 +  }
  
 -  if ( totals )
 -    {
 -      size_t i;
 -      for ( i = 0 ; i < n_dependent_vars ; ++i )
 -      {
 -        metrics_destroy (&totals[i]);
 -      }
 -    }
  }
  
  
  static void
  show_summary (const struct variable **dependent_var, int n_dep_var,
 -            const struct factor *fctr)
+             const struct dictionary *dict,
 +            const struct xfactor *fctr)
  {
++  const struct variable *wv = dict_get_weight (dict);
++  const struct fmt_spec *wfmt = wv ? var_get_print_format (wv) : & F_8_0;
++
    static const char *subtitle[]=
      {
 -      N_ ("Valid"),
 -      N_ ("Missing"),
 -      N_ ("Total")
 +      N_("Valid"),
 +      N_("Missing"),
 +      N_("Total")
      };
  
 -  int i;
 -  int heading_columns ;
 +  int v, j;
 +  int heading_columns = 1;
    int n_cols;
    const int heading_rows = 3;
    struct tab_table *tbl;
        }
      }
  
 -
 -  for ( i = 0 ; i < n_dep_var ; ++i )
 +  for (v = 0 ; v < n_dep_var ; ++v)
      {
 -      int n_factors = 1;
 -      if ( fctr )
 -      n_factors = hsh_count (fctr->fstats);
 +      int j = 0;
 +      struct ll *ll;
 +      union value *last_value = NULL;
  
 -      if ( i > 0 )
 -      tab_hline (tbl, TAL_1, 0, n_cols -1 , i * n_factors + heading_rows);
 +      if ( v > 0 )
 +      tab_hline (tbl, TAL_1, 0, n_cols -1 ,
 +                 v * ll_count (&fctr->result_list)
 +                 + heading_rows);
  
        tab_text (tbl,
 -              0, i * n_factors + heading_rows,
 +              0,
 +              v * ll_count (&fctr->result_list) + heading_rows,
                TAB_LEFT | TAT_TITLE,
 -              var_to_string (dependent_var[i])
 +              var_to_string (dependent_var[v])
                );
  
 -      if ( !fctr )
 -      populate_summary (tbl, heading_columns,
 -                       (i * n_factors) + heading_rows,
 -                        dict,
 -                       &totals[i]);
 -      else
 +
 +      for (ll = ll_head (&fctr->result_list);
 +         ll != ll_null (&fctr->result_list); ll = ll_next (ll))
        {
 -        struct factor_statistics **fs = fctr->fs;
 -        int count = 0 ;
 -        const union value *prev = NULL;
 +        double n;
 +        const struct factor_result *result =
 +          ll_data (ll, struct factor_result, ll);
  
 -        while (*fs)
 +        if ( fctr->indep_var[0] )
            {
 -            if ( !prev ||
 -                 0 != compare_values (prev, (*fs)->id[0],
 -                                 var_get_width (fctr->indep_var[0])))
 +
 +            if ( last_value == NULL ||
 +                 compare_values_short (last_value, result->value[0],
 +                                         fctr->indep_var[0]))
                {
 -                struct string vstr;
 -                ds_init_empty (&vstr);
 -                var_append_value_name (fctr->indep_var[0],
 -                                    (*fs)->id[0], &vstr);
 -
 -                tab_text (tbl,
 -                          1,
 -                          (i * n_factors ) + count +
 -                          heading_rows,
 +                struct string str;
 +
 +                last_value = result->value[0];
 +                ds_init_empty (&str);
 +
 +                var_append_value_name (fctr->indep_var[0], result->value[0],
 +                                       &str);
 +
 +                tab_text (tbl, 1,
 +                          heading_rows + j +
 +                          v * ll_count (&fctr->result_list),
                            TAB_LEFT | TAT_TITLE,
 -                          ds_cstr (&vstr)
 -                          );
 +                          ds_cstr (&str));
  
 -                ds_destroy (&vstr);
 +                ds_destroy (&str);
  
 -                if (fctr->indep_var[1] && count > 0 )
 +                if ( fctr->indep_var[1] && j > 0)
                    tab_hline (tbl, TAL_1, 1, n_cols - 1,
 -                            (i * n_factors ) + count + heading_rows);
 +                             heading_rows + j +
 +                             v * ll_count (&fctr->result_list));
                }
  
 -            prev = (*fs)->id[0];
 -
              if ( fctr->indep_var[1])
                {
 -                struct string vstr;
 -                ds_init_empty (&vstr);
 +                struct string str;
 +
 +                ds_init_empty (&str);
 +
                  var_append_value_name (fctr->indep_var[1],
 -                                       (*fs)->id[1], &vstr);
 -                tab_text (tbl,
 -                          2,
 -                          (i * n_factors ) + count +
 -                          heading_rows,
 +                                       result->value[1], &str);
 +
 +                tab_text (tbl, 2,
 +                          heading_rows + j +
 +                          v * ll_count (&fctr->result_list),
                            TAB_LEFT | TAT_TITLE,
 -                          ds_cstr (&vstr)
 -                          );
 -                ds_destroy (&vstr);
 +                          ds_cstr (&str));
 +
 +                ds_destroy (&str);
                }
 +          }
  
 -            populate_summary (tbl, heading_columns,
 -                              (i * n_factors) + count
 -                              + heading_rows,
 -                              dict,
 -                              & (*fs)->m[i]);
  
 -            count++ ;
 -            fs++;
 -          }
 +        moments1_calculate (result->metrics[v].moments,
 +                            &n, &result->metrics[v].mean,
 +                            &result->metrics[v].variance,
 +                            &result->metrics[v].skewness,
 +                            &result->metrics[v].kurtosis);
 +
 +        result->metrics[v].se_mean = sqrt (result->metrics[v].variance / n) ;
 +
 +        /* Total Valid */
-         tab_float (tbl, heading_columns,
++        tab_double (tbl, heading_columns,
 +                   heading_rows + j + v * ll_count (&fctr->result_list),
 +                   TAB_LEFT,
-                    n, 8, 0);
++                   n, wfmt);
 +
 +        tab_text (tbl, heading_columns + 1,
 +                  heading_rows + j + v * ll_count (&fctr->result_list),
 +                  TAB_RIGHT | TAT_PRINTF,
 +                  "%g%%", n * 100.0 / result->metrics[v].n);
 +
 +        /* Total Missing */
-         tab_float (tbl, heading_columns + 2,
++        tab_double (tbl, heading_columns + 2,
 +                   heading_rows + j + v * ll_count (&fctr->result_list),
 +                   TAB_LEFT,
 +                   result->metrics[v].n - n,
-                    8, 0);
++                   wfmt);
 +
 +        tab_text (tbl, heading_columns + 3,
 +                  heading_rows + j + v * ll_count (&fctr->result_list),
 +                  TAB_RIGHT | TAT_PRINTF,
 +                  "%g%%",
 +                  (result->metrics[v].n - n) * 100.0 / result->metrics[v].n
 +                  );
 +
 +        /* Total Valid + Missing */
-         tab_float (tbl, heading_columns + 4,
++        tab_double (tbl, heading_columns + 4,
 +                   heading_rows + j + v * ll_count (&fctr->result_list),
 +                   TAB_LEFT,
 +                   result->metrics[v].n,
-                    8, 0);
++                   wfmt);
 +
 +        tab_text (tbl, heading_columns + 5,
 +                  heading_rows + j + v * ll_count (&fctr->result_list),
 +                  TAB_RIGHT | TAT_PRINTF,
 +                  "%g%%",
 +                  (result->metrics[v].n) * 100.0 / result->metrics[v].n
 +                  );
 +
 +        ++j;
        }
      }
  
@@@ -1484,272 -1195,209 +1489,272 @@@ show_descriptives (const struct variabl
           0, 0,
           n_cols - 1, n_rows - 1);
  
 -  tab_hline (tbl, TAL_2, 0, n_cols - 1, heading_rows );
  
 -  tab_title (tbl, _ ("Extreme Values"));
 +  tab_hline (tbl, TAL_2, 0, n_cols - 1, heading_rows );
 +  tab_hline (tbl, TAL_2, 1, n_cols - 1, heading_rows );
  
 -  tab_vline (tbl, TAL_2, n_cols - 2, 0, n_rows -1);
 -  tab_vline (tbl, TAL_1, n_cols - 1, 0, n_rows -1);
 +  tab_vline (tbl, TAL_1, n_cols - 1, 0, n_rows - 1);
  
 -  if ( fctr )
 -    {
 -      tab_text (tbl, 1, heading_rows - 1, TAB_CENTER | TAT_TITLE,
 -              var_to_string (fctr->indep_var[0]));
  
 -      if ( fctr->indep_var[1] )
 -      tab_text (tbl, 2, heading_rows - 1, TAB_CENTER | TAT_TITLE,
 -                var_to_string (fctr->indep_var[1]));
 -    }
 +  if ( fctr->indep_var[0])
 +    tab_text (tbl, 1, 0, TAT_TITLE, var_to_string (fctr->indep_var[0]));
  
 -  tab_text (tbl, n_cols - 1, 0, TAB_CENTER | TAT_TITLE, _ ("Value"));
 -  tab_text (tbl, n_cols - 2, 0, TAB_CENTER | TAT_TITLE, _ ("Case Number"));
 +  if ( fctr->indep_var[1])
 +    tab_text (tbl, 2, 0, TAT_TITLE, var_to_string (fctr->indep_var[1]));
  
 -  for ( i = 0 ; i < n_dep_var ; ++i )
 +  for (v = 0 ; v < n_dep_var ; ++v )
      {
 +      struct ll *ll;
 +      int i = 0;
  
 -      if ( i > 0 )
 -      tab_hline (tbl, TAL_1, 0, n_cols -1 ,
 -                i * 2 * n_extremities * n_factors + heading_rows);
 +      const int row_var_start =
 +      v * DESCRIPTIVE_ROWS * ll_count(&fctr->result_list);
  
 -      tab_text (tbl, 0,
 -              i * 2 * n_extremities * n_factors  + heading_rows,
 +      tab_text (tbl,
 +              0,
 +              heading_rows + row_var_start,
                TAB_LEFT | TAT_TITLE,
 -              var_to_string (dependent_var[i])
 +              var_to_string (dependent_var[v])
                );
  
 -
 -      if ( !fctr )
 -      populate_extremes (tbl, heading_columns - 2,
 -                         i * 2 * n_extremities * n_factors  + heading_rows,
 -                         n_extremities,
 -                         dependent_var[i],
 -                         &totals[i]);
 -      else
 +      for (ll = ll_head (&fctr->result_list);
 +         ll != ll_null (&fctr->result_list); i++, ll = ll_next (ll))
        {
 -        struct factor_statistics **fs = fctr->fs;
 -        int count = 0 ;
 -        const union value *prev  = NULL;
 -
 -        while (*fs)
 -          {
 -            const int row = heading_rows + ( 2 * n_extremities )  *
 -               ( ( i  * n_factors  ) +  count );
 -
 -
 -            if ( !prev || 0 != compare_values (prev, (*fs)->id[0],
 -                                        var_get_width (fctr->indep_var[0])))
 -              {
 -                struct string vstr;
 -                ds_init_empty (&vstr);
 -                var_append_value_name (fctr->indep_var[0],
 -                                    (*fs)->id[0], &vstr);
 -
 -                if ( count > 0 )
 -                  tab_hline (tbl, TAL_1, 1, n_cols - 1, row);
 -
 -                tab_text (tbl,
 -                          1, row,
 -                          TAB_LEFT | TAT_TITLE,
 -                          ds_cstr (&vstr)
 -                          );
 -
 -                ds_destroy (&vstr);
 -              }
 -
 -            prev = (*fs)->id[0];
 -
 -            if (fctr->indep_var[1] && count > 0 )
 -              tab_hline (tbl, TAL_1, 2, n_cols - 1, row);
 -
 -            if ( fctr->indep_var[1])
 -              {
 -                struct string vstr;
 -                ds_init_empty (&vstr);
 -                var_append_value_name (fctr->indep_var[1], (*fs)->id[1], &vstr);
 -
 -              tab_text (tbl, 2, row,
 -                        TAB_LEFT | TAT_TITLE,
 -                          ds_cstr (&vstr)
 -                        );
 -
 -                ds_destroy (&vstr);
 -              }
 +        const struct factor_result *result =
 +          ll_data (ll, struct factor_result, ll);
  
 -            populate_extremes (tbl, heading_columns - 2,
 -                               row, n_extremities,
 -                               dependent_var[i],
 -                               & (*fs)->m[i]);
 +        const double t =
 +          gsl_cdf_tdist_Qinv ((1 - cmd.n_cinterval[0] / 100.0) / 2.0,
 +                                      result->metrics[v].n - 1);
  
 -            count++ ;
 -            fs++;
 +        if ( i > 0 || v > 0 )
 +          {
 +            const int left_col = (i == 0) ? 0 : 1;
 +            tab_hline (tbl, TAL_1, left_col, n_cols - 1,
 +                       heading_rows + row_var_start + i * DESCRIPTIVE_ROWS);
            }
 -      }
 -    }
 -
 -  tab_submit (tbl);
 -}
 -
 -
  
 -/* Fill in the extremities table */
 -static void
 -populate_extremes (struct tab_table *t,
 -                 int col, int row, int n,
 -                 const struct variable *var,
 -                 const struct metrics *m)
 -{
 -  int extremity;
 -  int idx=0;
 -
 -  tab_text (t, col, row,
 -         TAB_RIGHT | TAT_TITLE ,
 -         _ ("Highest")
 -         );
 -
 -  tab_text (t, col, row + n ,
 -         TAB_RIGHT | TAT_TITLE ,
 -         _ ("Lowest")
 -         );
 -
 -
 -  tab_hline (t, TAL_1, col, col + 3, row + n );
 -
 -  for (extremity = 0; extremity < n ; ++extremity )
 -    {
 -      /* Highest */
 -      tab_fixed (t, col + 1, row + extremity,
 -              TAB_RIGHT,
 -              extremity + 1, 8, 0);
 -
 -
 -      /* Lowest */
 -      tab_fixed (t, col + 1, row + extremity + n,
 -              TAB_RIGHT,
 -              extremity + 1, 8, 0);
 -
 -    }
 -
 -
 -  /* Lowest */
 -  for (idx = 0, extremity = 0; extremity < n && idx < m->n_data ; ++idx )
 -    {
 -      int j;
 -      const struct weighted_value *wv = m->wvp[idx];
 -      struct case_node *cn = wv->case_nos;
 -
 -
 -      for (j = 0 ; j < wv->w ; ++j  )
 -      {
 -        if ( extremity + j >= n )
 -          break ;
 -
 -        tab_value (t, col + 3, row + extremity + j  + n,
 -                   TAB_RIGHT,
 -                   &wv->v, var_get_print_format (var));
 +        if ( fctr->indep_var[0])
 +          {
 +            struct string vstr;
 +            ds_init_empty (&vstr);
 +            var_append_value_name (fctr->indep_var[0],
 +                                   result->value[0], &vstr);
 +
 +            tab_text (tbl, 1,
 +                      heading_rows + row_var_start + i * DESCRIPTIVE_ROWS,
 +                      TAB_LEFT,
 +                      ds_cstr (&vstr)
 +                      );
  
 -        tab_fixed (t, col + 2, row + extremity + j  + n,
 -                    TAB_RIGHT,
 -                    cn->num, 10, 0);
 +            ds_destroy (&vstr);
 +          }
  
 -        if ( cn->next )
 -          cn = cn->next;
  
-         tab_float (tbl, n_cols - 2,
 +        tab_text (tbl, n_cols - 4,
 +                  heading_rows + row_var_start + i * DESCRIPTIVE_ROWS,
 +                  TAB_LEFT,
 +                  _("Mean"));
 +
 +        tab_text (tbl, n_cols - 4,
 +                  heading_rows + row_var_start + 1 + i * DESCRIPTIVE_ROWS,
 +                  TAB_LEFT | TAT_PRINTF,
 +                  _("%g%% Confidence Interval for Mean"),
 +                  cmd.n_cinterval[0]);
 +
 +        tab_text (tbl, n_cols - 3,
 +                  heading_rows + row_var_start + 1 + i * DESCRIPTIVE_ROWS,
 +                  TAB_LEFT,
 +                  _("Lower Bound"));
 +
 +        tab_text (tbl, n_cols - 3,
 +                  heading_rows + row_var_start + 2 + i * DESCRIPTIVE_ROWS,
 +                  TAB_LEFT,
 +                  _("Upper Bound"));
 +
 +        tab_text (tbl, n_cols - 4,
 +                  heading_rows + row_var_start + 3 + i * DESCRIPTIVE_ROWS,
 +                  TAB_LEFT | TAT_PRINTF,
 +                  _("5%% Trimmed Mean"));
 +
 +        tab_text (tbl, n_cols - 4,
 +                  heading_rows + row_var_start + 4 + i * DESCRIPTIVE_ROWS,
 +                  TAB_LEFT,
 +                  _("Median"));
 +
 +        tab_text (tbl, n_cols - 4,
 +                  heading_rows + row_var_start + 5 + i * DESCRIPTIVE_ROWS,
 +                  TAB_LEFT,
 +                  _("Variance"));
 +
 +        tab_text (tbl, n_cols - 4,
 +                  heading_rows + row_var_start + 6 + i * DESCRIPTIVE_ROWS,
 +                  TAB_LEFT,
 +                  _("Std. Deviation"));
 +
 +        tab_text (tbl, n_cols - 4,
 +                  heading_rows + row_var_start + 7 + i * DESCRIPTIVE_ROWS,
 +                  TAB_LEFT,
 +                  _("Minimum"));
 +
 +        tab_text (tbl, n_cols - 4,
 +                  heading_rows + row_var_start + 8 + i * DESCRIPTIVE_ROWS,
 +                  TAB_LEFT,
 +                  _("Maximum"));
 +
 +        tab_text (tbl, n_cols - 4,
 +                  heading_rows + row_var_start + 9 + i * DESCRIPTIVE_ROWS,
 +                  TAB_LEFT,
 +                  _("Range"));
 +
 +        tab_text (tbl, n_cols - 4,
 +                  heading_rows + row_var_start + 10 + i * DESCRIPTIVE_ROWS,
 +                  TAB_LEFT,
 +                  _("Interquartile Range"));
 +
 +
 +        tab_text (tbl, n_cols - 4,
 +                  heading_rows + row_var_start + 11 + i * DESCRIPTIVE_ROWS,
 +                  TAB_LEFT,
 +                  _("Skewness"));
 +
 +        tab_text (tbl, n_cols - 4,
 +                  heading_rows + row_var_start + 12 + i * DESCRIPTIVE_ROWS,
 +                  TAB_LEFT,
 +                  _("Kurtosis"));
 +
 +
 +        /* Now the statistics ... */
 +
-                    8, 2);
++        tab_double (tbl, n_cols - 2,
 +                  heading_rows + row_var_start + i * DESCRIPTIVE_ROWS,
 +                   TAB_CENTER,
 +                   result->metrics[v].mean,
-         tab_float (tbl, n_cols - 1,
++                   NULL);
 +
-                    8, 3);
++        tab_double (tbl, n_cols - 1,
 +                  heading_rows + row_var_start + i * DESCRIPTIVE_ROWS,
 +                   TAB_CENTER,
 +                   result->metrics[v].se_mean,
-         tab_float (tbl, n_cols - 2,
++                   NULL);
 +
 +
-                    8, 3);
++        tab_double (tbl, n_cols - 2,
 +                   heading_rows + row_var_start + 1 + i * DESCRIPTIVE_ROWS,
 +                   TAB_CENTER,
 +                   result->metrics[v].mean - t *
 +                    result->metrics[v].se_mean,
-         tab_float (tbl, n_cols - 2,
++                   NULL);
 +
-                    8, 3);
++        tab_double (tbl, n_cols - 2,
 +                   heading_rows + row_var_start + 2 + i * DESCRIPTIVE_ROWS,
 +                   TAB_CENTER,
 +                   result->metrics[v].mean + t *
 +                    result->metrics[v].se_mean,
-         tab_float (tbl, n_cols - 2,
++                   NULL);
 +
 +
-                    8, 2);
++        tab_double (tbl, n_cols - 2,
 +                   heading_rows + row_var_start + 3 + i * DESCRIPTIVE_ROWS,
 +                   TAB_CENTER,
 +                   trimmed_mean_calculate ((struct trimmed_mean *) result->metrics[v].trimmed_mean),
-         tab_float (tbl, n_cols - 2,
++                   NULL);
 +
 +
-                    8, 2);
++        tab_double (tbl, n_cols - 2,
 +                   heading_rows + row_var_start + 4 + i * DESCRIPTIVE_ROWS,
 +                   TAB_CENTER,
 +                   percentile_calculate (result->metrics[v].quartiles[1], percentile_algorithm),
-         tab_float (tbl, n_cols - 2,
++                   NULL);
 +
 +
-                    8, 3);
++        tab_double (tbl, n_cols - 2,
 +                   heading_rows + row_var_start + 5 + i * DESCRIPTIVE_ROWS,
 +                   TAB_CENTER,
 +                   result->metrics[v].variance,
-         tab_float (tbl, n_cols - 2,
++                   NULL);
 +
-                    8, 3);
++        tab_double (tbl, n_cols - 2,
 +                   heading_rows + row_var_start + 6 + i * DESCRIPTIVE_ROWS,
 +                   TAB_CENTER,
 +                   sqrt (result->metrics[v].variance),
-         tab_float (tbl, n_cols - 2,
++                   NULL);
 +
-                    8, 2);
++        tab_double (tbl, n_cols - 2,
 +                   heading_rows + row_var_start + 10 + i * DESCRIPTIVE_ROWS,
 +                   TAB_CENTER,
 +                   percentile_calculate (result->metrics[v].quartiles[2],
 +                                         percentile_algorithm) -
 +                   percentile_calculate (result->metrics[v].quartiles[0],
 +                                         percentile_algorithm),
-         tab_float (tbl, n_cols - 2,
++                   NULL);
 +
 +
-                    8, 3);
++        tab_double (tbl, n_cols - 2,
 +                   heading_rows + row_var_start + 11 + i * DESCRIPTIVE_ROWS,
 +                   TAB_CENTER,
 +                   result->metrics[v].skewness,
-         tab_float (tbl, n_cols - 2,
++                   NULL);
 +
-                    8, 3);
++        tab_double (tbl, n_cols - 2,
 +                   heading_rows + row_var_start + 12 + i * DESCRIPTIVE_ROWS,
 +                   TAB_CENTER,
 +                   result->metrics[v].kurtosis,
-         tab_float (tbl, n_cols - 1,
++                   NULL);
 +
-                    8, 3);
++        tab_double (tbl, n_cols - 1,
 +                   heading_rows + row_var_start + 11 + i * DESCRIPTIVE_ROWS,
 +                   TAB_CENTER,
 +                   calc_seskew (result->metrics[v].n),
-         tab_float (tbl, n_cols - 1,
++                   NULL);
 +
-                    8, 3);
++        tab_double (tbl, n_cols - 1,
 +                   heading_rows + row_var_start + 12 + i * DESCRIPTIVE_ROWS,
 +                   TAB_CENTER,
 +                   calc_sekurt (result->metrics[v].n),
-           tab_float (tbl, n_cols - 2,
++                   NULL);
 +
 +        {
 +          struct extremum *minimum, *maximum ;
 +
 +          struct ll *max_ll = ll_head (extrema_list (result->metrics[v].maxima));
 +          struct ll *min_ll = ll_head (extrema_list (result->metrics[v].minima));
 +
 +          maximum = ll_data (max_ll, struct extremum, ll);
 +          minimum = ll_data (min_ll, struct extremum, ll);
 +
-                      8, 3);
++          tab_double (tbl, n_cols - 2,
 +                     heading_rows + row_var_start + 7 + i * DESCRIPTIVE_ROWS,
 +                     TAB_CENTER,
 +                     minimum->value,
-           tab_float (tbl, n_cols - 2,
++                     NULL);
 +
-                      8, 3);
++          tab_double (tbl, n_cols - 2,
 +                     heading_rows + row_var_start + 8 + i * DESCRIPTIVE_ROWS,
 +                     TAB_CENTER,
 +                     maximum->value,
-           tab_float (tbl, n_cols - 2,
++                     NULL);
 +
-                      8, 3);
++          tab_double (tbl, n_cols - 2,
 +                     heading_rows + row_var_start + 9 + i * DESCRIPTIVE_ROWS,
 +                     TAB_CENTER,
 +                     maximum->value - minimum->value,
++                     NULL);
 +        }
        }
 -
 -      extremity +=  wv->w ;
      }
  
 +  tab_vline (tbl, TAL_2, heading_columns, 0, n_rows - 1);
  
 -  /* Highest */
 -  for (idx = m->n_data - 1, extremity = 0; extremity < n && idx >= 0; --idx )
 -    {
 -      int j;
 -      const struct weighted_value *wv = m->wvp[idx];
 -      struct case_node *cn = wv->case_nos;
 -
 -      for (j = 0 ; j < wv->w ; ++j  )
 -      {
 -        if ( extremity + j >= n )
 -          break ;
 -
 -        tab_value (t, col + 3, row + extremity + j,
 -                   TAB_RIGHT,
 -                   &wv->v, var_get_print_format (var));
 -
 -        tab_fixed (t, col + 2, row + extremity + j,
 -                  TAB_RIGHT,
 -                    cn->num, 10, 0);
 +  tab_title (tbl, _("Descriptives"));
  
 -        if ( cn->next )
 -          cn = cn->next;
 +  tab_text (tbl, n_cols - 2, 0, TAB_CENTER | TAT_TITLE,
 +          _("Statistic"));
  
 -      }
 +  tab_text (tbl, n_cols - 1, 0, TAB_CENTER | TAT_TITLE,
 +          _("Std. Error"));
  
 -      extremity +=  wv->w ;
 -    }
 +  tab_submit (tbl);
  }
  
  
@@@ -1797,198 -1453,596 +1802,201 @@@ show_extremes (const struct variable **
           0, 0,
           n_cols - 1, n_rows - 1);
  
 -  tab_hline (tbl, TAL_2, 0, n_cols - 1, heading_rows );
  
 -  tab_vline (tbl, TAL_1, heading_columns, 0, n_rows - 1);
 -  tab_vline (tbl, TAL_2, n_cols - 2, 0, n_rows - 1);
 +  tab_hline (tbl, TAL_2, 0, n_cols - 1, heading_rows );
 +  tab_hline (tbl, TAL_2, 1, n_cols - 1, heading_rows );
    tab_vline (tbl, TAL_1, n_cols - 1, 0, n_rows - 1);
  
 -  tab_text (tbl, n_cols - 2, 0, TAB_CENTER | TAT_TITLE, _ ("Statistic"));
 -  tab_text (tbl, n_cols - 1, 0, TAB_CENTER | TAT_TITLE, _ ("Std. Error"));
 +  if ( fctr->indep_var[0])
 +    tab_text (tbl, 1, 0, TAT_TITLE, var_to_string (fctr->indep_var[0]));
  
 -  tab_title (tbl, _ ("Descriptives"));
 +  if ( fctr->indep_var[1])
 +    tab_text (tbl, 2, 0, TAT_TITLE, var_to_string (fctr->indep_var[1]));
  
 -
 -  for ( i = 0 ; i < n_dep_var ; ++i )
 +  for (v = 0 ; v < n_dep_var ; ++v )
      {
 -      const int row = heading_rows + i * n_stat_rows * n_factors ;
 -
 -      if ( i > 0 )
 -      tab_hline (tbl, TAL_1, 0, n_cols - 1, row );
 +      struct ll *ll;
 +      int i = 0;
 +      const int row_var_start = v * cmd.st_n * 2 * ll_count(&fctr->result_list);
  
 -      tab_text (tbl, 0,
 -              i * n_stat_rows * n_factors  + heading_rows,
 +      tab_text (tbl,
 +              0,
 +              heading_rows + row_var_start,
                TAB_LEFT | TAT_TITLE,
 -              var_to_string (dependent_var[i])
 +              var_to_string (dependent_var[v])
                );
  
 -
 -      if ( fctr  )
 +      for (ll = ll_head (&fctr->result_list);
 +         ll != ll_null (&fctr->result_list); i++, ll = ll_next (ll))
        {
 -        const union value *prev = NULL;
 +        int e ;
 +        struct ll *min_ll;
 +        struct ll *max_ll;
 +        const int row_result_start = i * cmd.st_n * 2;
  
 -        struct factor_statistics **fs = fctr->fs;
 -        int count = 0;
 +        const struct factor_result *result =
 +          ll_data (ll, struct factor_result, ll);
  
 -        tab_text (tbl, 1, heading_rows - 1, TAB_CENTER | TAT_TITLE,
 -                  var_to_string (fctr->indep_var[0]));
 +        if (i > 0 || v > 0)
 +          tab_hline (tbl, TAL_1, 1, n_cols - 1,
 +                     heading_rows + row_var_start + row_result_start);
  
 +        tab_hline (tbl, TAL_1, heading_columns - 2, n_cols - 1,
 +                   heading_rows + row_var_start + row_result_start + cmd.st_n);
  
 -        if ( fctr->indep_var[1])
 -          tab_text (tbl, 2, heading_rows - 1, TAB_CENTER | TAT_TITLE,
 -                    var_to_string (fctr->indep_var[1]));
 -
 -        while ( *fs )
 +        for ( e = 1; e <= cmd.st_n; ++e )
            {
 -            const int row = heading_rows + n_stat_rows  *
 -               ( ( i  * n_factors  ) +  count );
 -
 -
 -            if ( !prev || 0 != compare_values (prev, (*fs)->id[0],
 -                                        var_get_width (fctr->indep_var[0])))
 -              {
 -                struct string vstr;
 -                ds_init_empty (&vstr);
 -                var_append_value_name (fctr->indep_var[0],
 -                                    (*fs)->id[0], &vstr);
 -
 -                if ( count > 0 )
 -                  tab_hline (tbl, TAL_1, 1, n_cols - 1, row);
 -
 -                tab_text (tbl,
 -                          1, row,
 -                          TAB_LEFT | TAT_TITLE,
 -                          ds_cstr (&vstr)
 -                          );
 -
 -                ds_destroy (&vstr);
 -              }
 +            tab_text (tbl, n_cols - 3,
 +                      heading_rows + row_var_start + row_result_start + e - 1,
 +                      TAB_RIGHT | TAT_PRINTF,
 +                      _("%d"), e);
 +
 +            tab_text (tbl, n_cols - 3,
 +                      heading_rows + row_var_start + row_result_start + cmd.st_n + e - 1,
 +                      TAB_RIGHT | TAT_PRINTF,
 +                      _("%d"), e);
 +          }
  
 -            prev = (*fs)->id[0];
  
 -            if (fctr->indep_var[1] && count > 0 )
 -              tab_hline (tbl, TAL_1, 2, n_cols - 1, row);
 +        min_ll = ll_head (extrema_list (result->metrics[v].minima));
 +        for (e = 0; e < cmd.st_n;)
 +          {
 +            struct extremum *minimum = ll_data (min_ll, struct extremum, ll);
 +            double weight = minimum->weight;
  
 -            if ( fctr->indep_var[1])
 +            while (weight-- > 0 && e < cmd.st_n)
                {
-                 tab_float (tbl, n_cols - 1,
 -                struct string vstr;
 -                ds_init_empty (&vstr);
 -                var_append_value_name (fctr->indep_var[1], (*fs)->id[1], &vstr);
 -
 -              tab_text (tbl, 2, row,
 -                        TAB_LEFT | TAT_TITLE,
 -                          ds_cstr (&vstr)
 -                        );
 -
 -                ds_destroy (&vstr);
++                tab_double (tbl, n_cols - 1,
 +                           heading_rows + row_var_start + row_result_start + cmd.st_n + e,
 +                           TAB_RIGHT,
 +                           minimum->value,
-                            8, 2);
++                           NULL);
 +
 +
-                 tab_float (tbl, n_cols - 2,
-                            heading_rows + row_var_start + row_result_start + cmd.st_n + e,
++                tab_fixed (tbl, n_cols - 2,
++                           heading_rows + row_var_start +
++                           row_result_start + cmd.st_n + e,
 +                           TAB_RIGHT,
 +                           minimum->location,
-                            8, 0);
++                           10, 0);
 +                ++e;
                }
  
 -            populate_descriptives (tbl, heading_columns - 2,
 -                                   row,
 -                                   dependent_var[i],
 -                                   & (*fs)->m[i]);
 -
 -            count++ ;
 -            fs++;
 +            min_ll = ll_next (min_ll);
            }
  
 -      }
 -
 -      else
 -      {
 -
 -        populate_descriptives (tbl, heading_columns - 2,
 -                               i * n_stat_rows * n_factors  + heading_rows,
 -                               dependent_var[i],
 -                               &totals[i]);
 -      }
 -    }
 -
 -  tab_submit (tbl);
 -}
 -
  
 -/* Fill in the descriptives data */
 -static void
 -populate_descriptives (struct tab_table *tbl, int col, int row,
 -                     const struct variable *var,
 -                     const struct metrics *m)
 -{
 -  const double t = gsl_cdf_tdist_Qinv ((1 - cmd.n_cinterval[0] / 100.0)/2.0,
 -                                     m->n -1);
 -
 -  tab_text (tbl, col,
 -          row,
 -          TAB_LEFT | TAT_TITLE,
 -          _ ("Mean"));
 -
 -  tab_double (tbl, col + 2,
 -            row,
 -            TAB_CENTER,
 -            m->mean,
 -            NULL);
 -
 -  tab_double (tbl, col + 3,
 -            row,
 -            TAB_CENTER,
 -            m->se_mean,
 -            NULL);
 -
 -
 -  tab_text (tbl, col,
 -          row + 1,
 -          TAB_LEFT | TAT_TITLE | TAT_PRINTF,
 -          _ ("%g%% Confidence Interval for Mean"), cmd.n_cinterval[0]);
 -
 -
 -  tab_text (tbl, col + 1,
 -          row  + 1,
 -          TAB_LEFT | TAT_TITLE,
 -          _ ("Lower Bound"));
 -
 -  tab_double (tbl, col + 2,
 -            row + 1,
 -            TAB_CENTER,
 -            m->mean - t * m->se_mean,
 -            NULL);
 -
 -  tab_text (tbl, col + 1,
 -          row + 2,
 -          TAB_LEFT | TAT_TITLE,
 -          _ ("Upper Bound"));
 -
 -
 -  tab_double (tbl, col + 2,
 -            row + 2,
 -            TAB_CENTER,
 -            m->mean + t * m->se_mean,
 -            NULL);
 -
 -  tab_text (tbl, col,
 -          row + 3,
 -          TAB_LEFT | TAT_TITLE | TAT_PRINTF,
 -          _ ("5%% Trimmed Mean"));
 -
 -  tab_double (tbl, col + 2,
 -            row + 3,
 -            TAB_CENTER,
 -            m->trimmed_mean,
 -            NULL);
 -
 -  tab_text (tbl, col,
 -          row + 4,
 -          TAB_LEFT | TAT_TITLE,
 -          _ ("Median"));
 -
 -  {
 -    struct percentile *p;
 -    double d = 50;
 -
 -    p = hsh_find (m->ptile_hash, &d);
 -
 -    assert (p);
 -
 -
 -    tab_double (tbl, col + 2,
 -              row + 4,
 -              TAB_CENTER,
 -              p->v,
 -              NULL);
 -  }
 -
 -
 -  tab_text (tbl, col,
 -          row + 5,
 -          TAB_LEFT | TAT_TITLE,
 -          _ ("Variance"));
 -
 -  tab_double (tbl, col + 2,
 -            row + 5,
 -            TAB_CENTER,
 -            m->var,
 -            NULL);
 -
 -
 -  tab_text (tbl, col,
 -          row + 6,
 -          TAB_LEFT | TAT_TITLE,
 -          _ ("Std. Deviation"));
 -
 -
 -  tab_double (tbl, col + 2,
 -            row + 6,
 -            TAB_CENTER,
 -            m->stddev,
 -            NULL);
 -
 -
 -  tab_text (tbl, col,
 -          row + 7,
 -          TAB_LEFT | TAT_TITLE,
 -          _ ("Minimum"));
 -
 -  tab_double (tbl, col + 2,
 -            row + 7,
 -            TAB_CENTER,
 -            m->min, var_get_print_format (var));
 -
 -  tab_text (tbl, col,
 -          row + 8,
 -          TAB_LEFT | TAT_TITLE,
 -          _ ("Maximum"));
 -
 -  tab_double (tbl, col + 2,
 -            row + 8,
 -            TAB_CENTER,
 -            m->max, var_get_print_format (var));
 -
 -  tab_text (tbl, col,
 -          row + 9,
 -          TAB_LEFT | TAT_TITLE,
 -          _ ("Range"));
 -
 -
 -  tab_double (tbl, col + 2,
 -            row + 9,
 -            TAB_CENTER,
 -            m->max - m->min,
 -            NULL);
 -
 -  tab_text (tbl, col,
 -          row + 10,
 -          TAB_LEFT | TAT_TITLE,
 -          _ ("Interquartile Range"));
 -
 -  {
 -    struct percentile *p1;
 -    struct percentile *p2;
 -
 -    double d = 75;
 -    p1 = hsh_find (m->ptile_hash, &d);
 -
 -    d = 25;
 -    p2 = hsh_find (m->ptile_hash, &d);
 -
 -    assert (p1);
 -    assert (p2);
 -
 -    tab_double (tbl, col + 2,
 -              row + 10,
 -              TAB_CENTER,
 -              p1->v - p2->v,
 -              NULL);
 -  }
 -
 -  tab_text (tbl, col,
 -          row + 11,
 -          TAB_LEFT | TAT_TITLE,
 -          _ ("Skewness"));
 -
 -
 -  tab_double (tbl, col + 2,
 -            row + 11,
 -            TAB_CENTER,
 -            m->skewness,
 -            NULL);
 -
 -  /* stderr of skewness */
 -  tab_double (tbl, col + 3,
 -            row + 11,
 -            TAB_CENTER,
 -            calc_seskew (m->n),
 -            NULL);
 -
 -  tab_text (tbl, col,
 -          row + 12,
 -          TAB_LEFT | TAT_TITLE,
 -          _ ("Kurtosis"));
 -
 -
 -  tab_double (tbl, col + 2,
 -            row + 12,
 -            TAB_CENTER,
 -            m->kurtosis,
 -            NULL);
 -
 -  /* stderr of kurtosis */
 -  tab_double (tbl, col + 3,
 -            row + 12,
 -            TAB_CENTER,
 -            calc_sekurt (m->n),
 -            NULL);
 -}
 -
 -
 -
 -void
 -box_plot_variables (const struct factor *fctr,
 -                 const struct variable **vars, int n_vars,
 -                 const struct variable *id)
 -{
 -
 -  int i;
 -  struct factor_statistics **fs ;
 -
 -  if ( ! fctr )
 -    {
 -      box_plot_group (fctr, vars, n_vars, id);
 -      return;
 -    }
 -
 -  for ( fs = fctr->fs ; *fs ; ++fs )
 -    {
 -      struct string str;
 -      double y_min = DBL_MAX;
 -      double y_max = -DBL_MAX;
 -      struct chart *ch = chart_create ();
 -      ds_init_empty (&str);
 -      factor_to_string (fctr, *fs, 0, &str );
 -
 -      chart_write_title (ch, ds_cstr (&str));
 -
 -      for ( i = 0 ; i < n_vars ; ++i )
 -      {
 -        y_max = MAX (y_max, (*fs)->m[i].max);
 -        y_min = MIN (y_min, (*fs)->m[i].min);
 -      }
 -
 -      boxplot_draw_yscale (ch, y_max, y_min);
 -
 -      for ( i = 0 ; i < n_vars ; ++i )
 -      {
 -
 -        const double box_width = (ch->data_right - ch->data_left)
 -          / (n_vars * 2.0 ) ;
 -
 -        const double box_centre = ( i * 2 + 1) * box_width
 -          + ch->data_left;
 -
 -        boxplot_draw_boxplot (ch,
 -                             box_centre, box_width,
 -                             & (*fs)->m[i],
 -                             var_to_string (vars[i]));
 -
 -
 -      }
 -
 -      chart_submit (ch);
 -      ds_destroy (&str);
 -    }
 -}
 -
 -
 -
 -/* Do a box plot, grouping all factors into one plot ;
 -   each dependent variable has its own plot.
 -*/
 -void
 -box_plot_group (const struct factor *fctr,
 -             const struct variable **vars,
 -             int n_vars,
 -             const struct variable *id UNUSED)
 -{
 -
 -  int i;
 -
 -  for ( i = 0 ; i < n_vars ; ++i )
 -    {
 -      struct factor_statistics **fs ;
 -      struct chart *ch;
 -
 -      ch = chart_create ();
 +        max_ll = ll_head (extrema_list (result->metrics[v].maxima));
 +        for (e = 0; e < cmd.st_n;)
 +          {
 +            struct extremum *maximum = ll_data (max_ll, struct extremum, ll);
 +            double weight = maximum->weight;
  
 -      boxplot_draw_yscale (ch, totals[i].max, totals[i].min);
 +            while (weight-- > 0 && e < cmd.st_n)
 +              {
-                 tab_float (tbl, n_cols - 1,
-                            heading_rows + row_var_start + row_result_start + e,
++                tab_double (tbl, n_cols - 1,
++                           heading_rows + row_var_start +
++                            row_result_start + e,
 +                           TAB_RIGHT,
 +                           maximum->value,
-                            8, 2);
++                           NULL);
 +
 +
-                 tab_float (tbl, n_cols - 2,
-                            heading_rows + row_var_start + row_result_start + e,
++                tab_fixed (tbl, n_cols - 2,
++                           heading_rows + row_var_start +
++                           row_result_start + e,
 +                           TAB_RIGHT,
 +                           maximum->location,
-                            8, 0);
++                           10, 0);
 +                ++e;
 +              }
  
 -      if ( fctr )
 -      {
 -        int n_factors = 0;
 -        int f=0;
 -        for ( fs = fctr->fs ; *fs ; ++fs )
 -          ++n_factors;
 +            max_ll = ll_next (max_ll);
 +          }
  
 -        chart_write_title (ch, _ ("Boxplot of %s vs. %s"),
 -                          var_to_string (vars[i]), var_to_string (fctr->indep_var[0]) );
  
 -        for ( fs = fctr->fs ; *fs ; ++fs )
 +        if ( fctr->indep_var[0])
            {
 -            struct string str;
 -            const double box_width = (ch->data_right - ch->data_left)
 -              / (n_factors * 2.0 ) ;
 -
 -            const double box_centre = ( f++ * 2 + 1) * box_width
 -              + ch->data_left;
 -
 -            ds_init_empty (&str);
 -            factor_to_string_concise (fctr, *fs, &str);
 +            struct string vstr;
 +            ds_init_empty (&vstr);
 +            var_append_value_name (fctr->indep_var[0],
 +                                   result->value[0], &vstr);
 +
 +            tab_text (tbl, 1,
 +                      heading_rows + row_var_start + row_result_start,
 +                      TAB_LEFT,
 +                      ds_cstr (&vstr)
 +                      );
  
 -            boxplot_draw_boxplot (ch,
 -                                 box_centre, box_width,
 -                                 & (*fs)->m[i],
 -                                 ds_cstr (&str));
 -              ds_destroy (&str);
 +            ds_destroy (&vstr);
            }
 -      }
 -      else if ( ch )
 -      {
 -        const double box_width = (ch->data_right - ch->data_left) / 3.0;
 -        const double box_centre = (ch->data_right + ch->data_left) / 2.0;
  
 -        chart_write_title (ch, _ ("Boxplot"));
  
 -        boxplot_draw_boxplot (ch,
 -                             box_centre,    box_width,
 -                             &totals[i],
 -                             var_to_string (vars[i]) );
 +        tab_text (tbl, n_cols - 4,
 +                  heading_rows + row_var_start + row_result_start,
 +                  TAB_RIGHT,
 +                  _("Highest"));
  
 +        tab_text (tbl, n_cols - 4,
 +                  heading_rows + row_var_start + row_result_start + cmd.st_n,
 +                  TAB_RIGHT,
 +                  _("Lowest"));
        }
 -
 -      chart_submit (ch);
      }
 -}
 -
  
 -/* Plot the normal and detrended normal plots for m
 -   Label the plots with factorname */
 -void
 -np_plot (const struct metrics *m, const char *factorname)
 -{
 -  int i;
 -  double yfirst=0, ylast=0;
 -
 -  /* Normal Plot */
 -  struct chart *np_chart;
 -
 -  /* Detrended Normal Plot */
 -  struct chart *dnp_chart;
 -
 -  /* The slope and intercept of the ideal normal probability line */
 -  const double slope = 1.0 / m->stddev;
 -  const double intercept = - m->mean / m->stddev;
 -
 -  /* Cowardly refuse to plot an empty data set */
 -  if ( m->n_data == 0 )
 -    return ;
 -
 -  np_chart = chart_create ();
 -  dnp_chart = chart_create ();
 -
 -  if ( !np_chart || ! dnp_chart )
 -    return ;
 -
 -  chart_write_title (np_chart, _ ("Normal Q-Q Plot of %s"), factorname);
 -  chart_write_xlabel (np_chart, _ ("Observed Value"));
 -  chart_write_ylabel (np_chart, _ ("Expected Normal"));
 -
 -
 -  chart_write_title (dnp_chart, _ ("Detrended Normal Q-Q Plot of %s"),
 -                  factorname);
 -  chart_write_xlabel (dnp_chart, _ ("Observed Value"));
 -  chart_write_ylabel (dnp_chart, _ ("Dev from Normal"));
 -
 -  yfirst = gsl_cdf_ugaussian_Pinv (m->wvp[0]->rank / ( m->n + 1));
 -  ylast =  gsl_cdf_ugaussian_Pinv (m->wvp[m->n_data-1]->rank / ( m->n + 1));
 -
 -
 -  {
 -    /* Need to make sure that both the scatter plot and the ideal fit into the
 -       plot */
 -    double x_lower = MIN (m->min, (yfirst - intercept) / slope) ;
 -    double x_upper = MAX (m->max, (ylast  - intercept) / slope) ;
 -    double slack = (x_upper - x_lower)  * 0.05 ;
 -
 -    chart_write_xscale (np_chart, x_lower - slack, x_upper + slack, 5);
 -
 -    chart_write_xscale (dnp_chart, m->min, m->max, 5);
 -
 -  }
 -
 -  chart_write_yscale (np_chart, yfirst, ylast, 5);
 -
 -  {
 -    /* We have to cache the detrended data, beacause we need to
 -       find its limits before we can plot it */
 -    double *d_data = xnmalloc (m->n_data, sizeof *d_data);
 -    double d_max = -DBL_MAX;
 -    double d_min = DBL_MAX;
 -    for ( i = 0 ; i < m->n_data; ++i )
 -      {
 -      const double ns = gsl_cdf_ugaussian_Pinv (m->wvp[i]->rank / ( m->n + 1));
 +  tab_vline (tbl, TAL_2, heading_columns, 0, n_rows - 1);
  
 -      chart_datum (np_chart, 0, m->wvp[i]->v.f, ns);
  
 -      d_data[i] = (m->wvp[i]->v.f - m->mean) / m->stddev  - ns;
 +  tab_title (tbl, _("Extreme Values"));
  
 -      if ( d_data[i] < d_min ) d_min = d_data[i];
 -      if ( d_data[i] > d_max ) d_max = d_data[i];
 -      }
 -    chart_write_yscale (dnp_chart, d_min, d_max, 5);
  
 -    for ( i = 0 ; i < m->n_data; ++i )
 -      chart_datum (dnp_chart, 0, m->wvp[i]->v.f, d_data[i]);
 +  tab_text (tbl, n_cols - 2, 0, TAB_CENTER | TAT_TITLE,
 +          _("Case Number"));
  
 -    free (d_data);
 -  }
  
 -  chart_line (np_chart, slope, intercept, yfirst, ylast , CHART_DIM_Y);
 -  chart_line (dnp_chart, 0, 0, m->min, m->max , CHART_DIM_X);
 +  tab_text (tbl, n_cols - 1, 0, TAB_CENTER | TAT_TITLE,
 +          _("Value"));
  
 -  chart_submit (np_chart);
 -  chart_submit (dnp_chart);
 +  tab_submit (tbl);
  }
  
 +#define PERCENTILE_ROWS 2
  
 -
 -
 -/* Show the percentiles */
 -void
 +static void
  show_percentiles (const struct variable **dependent_var,
 -               int n_dep_var,
 -               struct factor *fctr)
 +                int n_dep_var,
 +                const struct xfactor *fctr)
  {
 -  struct tab_table *tbl;
    int i;
 +  int v;
 +  int heading_columns = 2;
 +  int n_cols;
 +  const int n_percentiles = subc_list_double_count (&percentile_list);
 +  const int heading_rows = 2;
 +  struct tab_table *tbl;
  
 -  int n_cols, n_rows;
 -  int n_factors;
 -
 -  struct hsh_table *ptiles ;
 -
 -  int n_heading_columns;
 -  const int n_heading_rows = 2;
 -  const int n_stat_rows = 2;
 +  int n_rows ;
 +  n_rows = n_dep_var;
  
 -  int n_ptiles ;
 +  assert (fctr);
  
 -  if ( fctr )
 +  if ( fctr->indep_var[0] )
      {
 -      struct factor_statistics **fs = fctr->fs ;
 -      n_heading_columns = 3;
 -      n_factors = hsh_count (fctr->fstats);
 -
 -      ptiles = (*fs)->m[0].ptile_hash;
 +      heading_columns = 3;
  
        if ( fctr->indep_var[1] )
 -      n_heading_columns = 4;
 -    }
 -  else
 -    {
 -      n_factors = 1;
 -      n_heading_columns = 2;
 -
 -      ptiles = totals[0].ptile_hash;
 +      {
 +        heading_columns = 4;
 +      }
      }
  
 -  n_ptiles = hsh_count (ptiles);
 -
 -  n_rows = n_heading_rows + n_dep_var * n_stat_rows * n_factors;
 +  n_rows *= ll_count (&fctr->result_list) * PERCENTILE_ROWS;
 +  n_rows += heading_rows;
  
 -  n_cols = n_heading_columns + n_ptiles ;
 +  n_cols = heading_columns + n_percentiles;
  
    tbl = tab_create (n_cols, n_rows, 0);
 -
 -  tab_headers (tbl, n_heading_columns + 1, 0, n_heading_rows, 0);
 +  tab_headers (tbl, heading_columns, 0, heading_rows, 0);
  
    tab_dim (tbl, tab_natural_dimensions);
  
           0, 0,
           n_cols - 1, n_rows - 1);
  
 -  tab_hline (tbl, TAL_2, 0, n_cols - 1, n_heading_rows );
 -
 -  tab_vline (tbl, TAL_2, n_heading_columns, 0, n_rows - 1);
 -
 -
 -  tab_title (tbl, _ ("Percentiles"));
 -
 -
 -  tab_hline (tbl, TAL_1, n_heading_columns, n_cols - 1, 1 );
 -
  
 -  tab_box (tbl,
 -         -1, -1,
 -         -1, TAL_1,
 -         0, n_heading_rows,
 -         n_heading_columns - 1, n_rows - 1);
 -
 -
 -  tab_box (tbl,
 -         -1, -1,
 -         -1, TAL_1,
 -         n_heading_columns, n_heading_rows - 1,
 -         n_cols - 1, n_rows - 1);
 -
 -  tab_joint_text (tbl, n_heading_columns + 1, 0,
 -               n_cols - 1 , 0,
 -               TAB_CENTER | TAT_TITLE ,
 -               _ ("Percentiles"));
 -
 -
 -  {
 -    /* Put in the percentile break points as headings */
 +  tab_hline (tbl, TAL_2, 0, n_cols - 1, heading_rows );
 +  tab_hline (tbl, TAL_2, 1, n_cols - 1, heading_rows );
  
 -    struct percentile **p = (struct percentile **) hsh_sort (ptiles);
 +  if ( fctr->indep_var[0])
 +    tab_text (tbl, 1, 1, TAT_TITLE, var_to_string (fctr->indep_var[0]));
  
 -    i = 0;
 -    while ( (*p)  )
 -      {
 -      tab_fixed (tbl, n_heading_columns + i++ , 1,
 -                  TAB_CENTER,
 -                  (*p)->p,
 -                  8, 0);
 -      p++;
 -      }
 +  if ( fctr->indep_var[1])
 +    tab_text (tbl, 2, 1, TAT_TITLE, var_to_string (fctr->indep_var[1]));
  
 -  }
 -
 -  for ( i = 0 ; i < n_dep_var ; ++i )
 +  for (v = 0 ; v < n_dep_var ; ++v )
      {
 -      const int n_stat_rows = 2;
 -      const int row = n_heading_rows + i * n_stat_rows * n_factors ;
 +      double hinges[3];
 +      struct ll *ll;
 +      int i = 0;
  
 -      if ( i > 0 )
 -      tab_hline (tbl, TAL_1, 0, n_cols - 1, row );
 +      const int row_var_start =
 +      v * PERCENTILE_ROWS * ll_count(&fctr->result_list);
  
 -      tab_text (tbl, 0,
 -              i * n_stat_rows * n_factors  + n_heading_rows,
 +      tab_text (tbl,
 +              0,
 +              heading_rows + row_var_start,
                TAB_LEFT | TAT_TITLE,
 -              var_to_string (dependent_var[i])
 +              var_to_string (dependent_var[v])
                );
  
 -      if ( fctr  )
 +      for (ll = ll_head (&fctr->result_list);
 +         ll != ll_null (&fctr->result_list); i++, ll = ll_next (ll))
        {
 -        const union value *prev  = NULL ;
 -        struct factor_statistics **fs = fctr->fs;
 -        int count = 0;
 +        int j;
 +        const struct factor_result *result =
 +          ll_data (ll, struct factor_result, ll);
  
 -        tab_text (tbl, 1, n_heading_rows - 1,
 -                  TAB_CENTER | TAT_TITLE,
 -                  var_to_string (fctr->indep_var[0]));
 +        if ( i > 0 || v > 0 )
 +          {
 +            const int left_col = (i == 0) ? 0 : 1;
 +            tab_hline (tbl, TAL_1, left_col, n_cols - 1,
 +                       heading_rows + row_var_start + i * PERCENTILE_ROWS);
 +          }
  
 +        if ( fctr->indep_var[0])
 +          {
 +            struct string vstr;
 +            ds_init_empty (&vstr);
 +            var_append_value_name (fctr->indep_var[0],
 +                                   result->value[0], &vstr);
 +
 +            tab_text (tbl, 1,
 +                      heading_rows + row_var_start + i * PERCENTILE_ROWS,
 +                      TAB_LEFT,
 +                      ds_cstr (&vstr)
 +                      );
  
 -        if ( fctr->indep_var[1])
 -          tab_text (tbl, 2, n_heading_rows - 1, TAB_CENTER | TAT_TITLE,
 -                    var_to_string (fctr->indep_var[1]));
 +            ds_destroy (&vstr);
 +          }
  
 -        while ( *fs )
 -          {
 -            const int row = n_heading_rows + n_stat_rows  *
 -               ( ( i  * n_factors  ) +  count );
  
 +        tab_text (tbl, n_cols - n_percentiles - 1,
 +                  heading_rows + row_var_start + i * PERCENTILE_ROWS,
 +                  TAB_LEFT,
 +                  ptile_alg_desc [percentile_algorithm]);
  
 -            if ( !prev || 0 != compare_values (prev, (*fs)->id[0],
 -                                        var_get_width (fctr->indep_var[0])))
 -              {
 -                struct string vstr;
 -                ds_init_empty (&vstr);
 -                var_append_value_name (fctr->indep_var[0],
 -                                    (*fs)->id[0], &vstr);
  
 +        tab_text (tbl, n_cols - n_percentiles - 1,
 +                  heading_rows + row_var_start + 1 + i * PERCENTILE_ROWS,
 +                  TAB_LEFT,
 +                  _("Tukey's Hinges"));
  
 -                if ( count > 0 )
 -                  tab_hline (tbl, TAL_1, 1, n_cols - 1, row);
  
 -                tab_text (tbl,
 -                          1, row,
 -                          TAB_LEFT | TAT_TITLE,
 -                          ds_cstr (&vstr)
 -                          );
 +        tab_vline (tbl, TAL_1, n_cols - n_percentiles -1, heading_rows, n_rows - 1);
  
 -                ds_destroy (&vstr);
 -              }
 +        tukey_hinges_calculate ((struct tukey_hinges *) result->metrics[v].tukey_hinges,
 +                                hinges);
  
 -            prev = (*fs)->id[0];
 +        for (j = 0; j < n_percentiles; ++j)
 +          {
 +            double hinge = SYSMIS;
-             tab_float (tbl, n_cols - n_percentiles + j,
++            tab_double (tbl, n_cols - n_percentiles + j,
 +                       heading_rows + row_var_start + i * PERCENTILE_ROWS,
 +                       TAB_CENTER,
 +                       percentile_calculate (result->metrics[v].ptl[j],
 +                                             percentile_algorithm),
-                        8, 2
++                       NULL
 +                       );
 +
 +            if ( result->metrics[v].ptl[j]->ptile == 0.5)
 +              hinge = hinges[1];
 +            else if ( result->metrics[v].ptl[j]->ptile == 0.25)
 +              hinge = hinges[0];
 +            else if ( result->metrics[v].ptl[j]->ptile == 0.75)
 +              hinge = hinges[2];
 +
 +            if ( hinge != SYSMIS)
-               tab_float (tbl, n_cols - n_percentiles + j,
++              tab_double (tbl, n_cols - n_percentiles + j,
 +                         heading_rows + row_var_start + 1 + i * PERCENTILE_ROWS,
 +                         TAB_CENTER,
 +                         hinge,
-                          8, 2
++                         NULL
 +                         );
  
 -            if (fctr->indep_var[1] && count > 0 )
 -              tab_hline (tbl, TAL_1, 2, n_cols - 1, row);
 +          }
 +      }
 +    }
  
 -            if ( fctr->indep_var[1])
 -              {
 -                struct string vstr;
 -                ds_init_empty (&vstr);
 -                var_append_value_name (fctr->indep_var[1], (*fs)->id[1], &vstr);
 +  tab_vline (tbl, TAL_2, heading_columns, 0, n_rows - 1);
  
 -              tab_text (tbl, 2, row,
 -                        TAB_LEFT | TAT_TITLE,
 -                          ds_cstr (&vstr)
 -                        );
 +  tab_title (tbl, _("Percentiles"));
  
 -                ds_destroy (&vstr);
 -              }
  
 +  for (i = 0 ; i < n_percentiles; ++i )
 +    {
 +      tab_text (tbl, n_cols - n_percentiles + i, 1,
 +              TAB_CENTER | TAT_TITLE | TAT_PRINTF,
 +              _("%g"),
 +              subc_list_double_at (&percentile_list, i)
 +              );
  
 -            populate_percentiles (tbl, n_heading_columns - 1,
 -                                  row,
 -                                  & (*fs)->m[i]);
  
 +    }
  
 -            count++ ;
 -            fs++;
 -          }
 +  tab_joint_text (tbl,
 +                n_cols - n_percentiles, 0,
 +                n_cols - 1, 0,
 +                TAB_CENTER | TAT_TITLE,
 +                _("Percentiles"));
  
 +  /* Vertical lines for the data only */
 +  tab_box (tbl,
 +         -1, -1,
 +         -1, TAL_1,
 +         n_cols - n_percentiles, 1,
 +         n_cols - 1, n_rows - 1);
  
 -      }
 -      else
 -      {
 -        populate_percentiles (tbl, n_heading_columns - 1,
 -                              i * n_stat_rows * n_factors  + n_heading_rows,
 -                              &totals[i]);
 -      }
 -    }
 +  tab_hline (tbl, TAL_1, n_cols - n_percentiles, n_cols - 1, 1);
  
  
    tab_submit (tbl);
index cd370be821c8db73f2d88da8350613a7ea8c07b0,a09ecc100759b76d2ecf4d682a050c9999be79f5..25866a417acd109d1c715dec892bdef27294f2f5
@@@ -376,12 -376,12 +376,12 @@@ internal_cmd_frequencies (struct lexer 
    for (; casegrouper_get_next_group (grouper, &group);
         casereader_destroy (group))
      {
 -      struct ccase c;
 +      struct ccase *c;
  
        precalc (group, ds);
 -      for (; casereader_read (group, &c); case_destroy (&c))
 -        calc (&c, ds);
 +      for (; (c = casereader_read (group)) != NULL; case_unref (c))
 +        calc (c, ds);
-       postcalc ();
+       postcalc (ds);
      }
    ok = casegrouper_destroy (grouper);
    ok = proc_commit (ds) && ok;
Simple merge
index be57eb24d5fbf6ac9830f5582655bd1028f89f30,34f2a216a1cc26571cd72d17c8e388ee4ac564b7..40107f77c877205af42c9555ac1c329f29b39d47
@@@ -88,19 -89,19 +89,19 @@@ static void run_oneway (struct cmd_onew
  
  
  /* Routines to show the output tables */
- static void show_anova_table (void);
- static void show_descriptives (void);
- static void show_homogeneity (void);
+ static void show_anova_table(void);
+ static void show_descriptives (const struct dictionary *dict);
+ static void show_homogeneity(void);
  
 -static void show_contrast_coeffs(short *);
 -static void show_contrast_tests(short *);
 +static void show_contrast_coeffs (short *);
 +static void show_contrast_tests (short *);
  
  
  enum stat_table_t {STAT_DESC = 1, STAT_HOMO = 2};
  
 -static enum stat_table_t stat_tables ;
 +static enum stat_table_t stat_tables;
  
void output_oneway (void);
static void output_oneway (const struct dictionary *dict);
  
  
  int
@@@ -148,11 -148,11 +149,11 @@@ cmd_oneway (struct lexer *lexer, struc
  }
  
  
- void
- output_oneway (void)
static void
+ output_oneway (const struct dictionary *dict)
  {
    size_t i;
 -  short *bad_contrast ;
 +  short *bad_contrast;
  
    bad_contrast = xnmalloc (cmd.sbc_contrast, sizeof *bad_contrast);
  
      }
  
    if ( stat_tables & STAT_DESC )
-     show_descriptives ();
+     show_descriptives (dict);
  
    if ( stat_tables & STAT_HOMO )
 -    show_homogeneity();
 +    show_homogeneity ();
  
 -  show_anova_table();
 +  show_anova_table ();
  
    if (cmd.sbc_contrast )
      {
@@@ -323,24 -326,27 +324,24 @@@ show_anova_table (void
  
  
        /* Degrees of freedom */
-       tab_float (t, 3, i * 3 + 1, 0, df1, 4, 0);
-       tab_float (t, 3, i * 3 + 2, 0, df2, 4, 0);
-       tab_float (t, 3, i * 3 + 3, 0, totals->n - 1, 4, 0);
+       tab_fixed (t, 3, i * 3 + 1, 0, df1, 4, 0);
+       tab_fixed (t, 3, i * 3 + 2, 0, df2, 4, 0);
+       tab_fixed (t, 3, i * 3 + 3, 0, totals->n - 1, 4, 0);
  
        /* Mean Squares */
-       tab_float (t, 4, i * 3 + 1, TAB_RIGHT, msa, 8, 3);
-       tab_float (t, 4, i * 3 + 2, TAB_RIGHT, gp->mse, 8, 3);
+       tab_double (t, 4, i * 3 + 1, TAB_RIGHT, msa, NULL);
+       tab_double (t, 4, i * 3 + 2, TAB_RIGHT, gp->mse, NULL);
  
 -
        {
-         const double F = msa/gp->mse;
+         const double F = msa / gp->mse ;
  
          /* The F value */
-         tab_float (t, 5, i * 3 + 1, 0,  F, 8, 3);
+         tab_double (t, 5, i * 3 + 1, 0,  F, NULL);
  
          /* The significance */
-         tab_float (t, 6, i * 3 + 1, 0, gsl_cdf_fdist_Q (F, df1, df2), 8, 3);
 -        tab_double (t, 6, i * 3 + 1, 0, gsl_cdf_fdist_Q (F, df1,df2), NULL);
++        tab_double (t, 6, i * 3 + 1, 0, gsl_cdf_fdist_Q (F, df1, df2), NULL);
        }
 -
        }
 -
      }
  
  
@@@ -361,13 -367,15 +362,15 @@@ show_descriptives (const struct diction
    const double confidence = 0.95;
    const double q = (1.0 - confidence) / 2.0;
  
+   const struct variable *wv = dict_get_weight (dict);
+   const struct fmt_spec *wfmt = wv ? var_get_print_format (wv) : & F_8_0;
  
 -  int n_rows = 2 ;
 +  int n_rows = 2;
  
 -  for ( v = 0 ; v < n_vars ; ++v )
 +  for ( v = 0; v < n_vars; ++v )
      n_rows += group_proc_get (vars[v])->n_groups + 1;
  
 -  t = tab_create (n_cols,n_rows,0);
 +  t = tab_create (n_cols, n_rows, 0);
    tab_headers (t, 2, 0, 2, 0);
    tab_dim (t, tab_natural_dimensions);
  
        struct group_statistics *totals = &gp->ugs;
  
        const char *s = var_to_string (vars[v]);
+       const struct fmt_spec *fmt = var_get_print_format (vars[v]);
  
        struct group_statistics *const *gs_array =
 -      (struct group_statistics *const *) hsh_sort(gp->group_hash);
 +      (struct group_statistics *const *) hsh_sort (gp->group_hash);
        int count = 0;
  
        tab_text (t, 0, row, TAB_LEFT | TAT_TITLE, s);
        }
  
        tab_text (t, 1, row + count,
 -              TAB_LEFT | TAT_TITLE ,_("Total"));
 +              TAB_LEFT | TAT_TITLE_("Total"));
  
-       tab_float (t, 2, row + count, 0, totals->n, 8, 0);
+       tab_double (t, 2, row + count, 0, totals->n, wfmt);
  
-       tab_float (t, 3, row + count, 0, totals->mean, 8, 2);
+       tab_double (t, 3, row + count, 0, totals->mean, NULL);
  
-       tab_float (t, 4, row + count, 0, totals->std_dev, 8, 2);
+       tab_double (t, 4, row + count, 0, totals->std_dev, NULL);
  
-       std_error = totals->std_dev/sqrt (totals->n);
+       std_error = totals->std_dev / sqrt (totals->n) ;
  
-       tab_float (t, 5, row + count, 0, std_error, 8, 2);
+       tab_double (t, 5, row + count, 0, std_error, NULL);
  
        /* Now the confidence interval */
  
@@@ -761,25 -773,25 +767,25 @@@ show_contrast_tests (short *bad_contras
              df_numerator += (coef * coef) * winv;
              df_denominator += pow2((coef * coef) * winv) / (gs->n - 1);
            }
 -        sec_vneq = sqrt(sec_vneq);
 +        sec_vneq = sqrt (sec_vneq);
  
-         df_numerator = pow2(df_numerator);
+         df_numerator = pow2 (df_numerator);
  
-         tab_float (t,  3, (v * lines_per_variable) + i + 1,
-                    TAB_RIGHT, contrast_value, 8, 2);
+         tab_double (t,  3, (v * lines_per_variable) + i + 1,
+                    TAB_RIGHT, contrast_value, NULL);
  
-         tab_float (t,  3, (v * lines_per_variable) + i + 1 +
+         tab_double (t,  3, (v * lines_per_variable) + i + 1 +
                     cmd.sbc_contrast,
-                    TAB_RIGHT, contrast_value, 8, 2);
+                    TAB_RIGHT, contrast_value, NULL);
  
          std_error_contrast = sqrt (grp_data->mse * coef_msq);
  
          /* Std. Error */
-         tab_float (t,  4, (v * lines_per_variable) + i + 1,
+         tab_double (t,  4, (v * lines_per_variable) + i + 1,
                     TAB_RIGHT, std_error_contrast,
-                    8, 3);
+                    NULL);
  
 -        T = fabs(contrast_value / std_error_contrast) ;
 +        T = fabs (contrast_value / std_error_contrast);
  
          /* T Statistic */
  
  
  
          /* Significance TWO TAILED !!*/
-         tab_float (t,  7, (v * lines_per_variable) + i + 1,
+         tab_double (t,  7, (v * lines_per_variable) + i + 1,
                     TAB_RIGHT,  2 * gsl_cdf_tdist_Q (T, df),
-                    8, 3);
+                    NULL);
  
 -
          /* Now for the Variances NOT Equal case */
  
          /* Std. Error */
-         tab_float (t,  4,
+         tab_double (t,  4,
                     (v * lines_per_variable) + i + 1 + cmd.sbc_contrast,
                     TAB_RIGHT, sec_vneq,
-                    8, 3);
+                    NULL);
  
 -
          T = contrast_value / sec_vneq;
-         tab_float (t,  5,
+         tab_double (t,  5,
                     (v * lines_per_variable) + i + 1 + cmd.sbc_contrast,
                     TAB_RIGHT, T,
-                    8, 3);
+                    NULL);
  
 -
          df = df_numerator / df_denominator;
  
-         tab_float (t,  6,
+         tab_double (t,  6,
                     (v * lines_per_variable) + i + 1 + cmd.sbc_contrast,
                     TAB_RIGHT, df,
-                    8, 3);
+                    NULL);
  
          /* The Significance */
  
-         tab_float (t, 7, (v * lines_per_variable) + i + 1 + cmd.sbc_contrast,
-                    TAB_RIGHT,  2 * gsl_cdf_tdist_Q (T, df),
-                    8, 3);
+         tab_double (t, 7, (v * lines_per_variable) + i + 1 + cmd.sbc_contrast,
+                    TAB_RIGHT,  2 * gsl_cdf_tdist_Q (T,df),
+                    NULL);
 -
 -
        }
  
        if ( v > 0 )
Simple merge
index 25aff211dd739b8d63f8af886a565cadafdde11d,0000000000000000000000000000000000000000..0e7f91a02629776213b18938045cd0a0dfb7afdd
mode 100644,000000..100644
--- /dev/null
@@@ -1,812 -1,0 +1,824 @@@
-   struct reliability rel = {
 +/* PSPP - a program for statistical analysis.
 +   Copyright (C) 2008, 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
 +   the Free Software Foundation, either version 3 of the License, or
 +   (at your option) any later version.
 +
 +   This program is distributed in the hope that it will be useful,
 +   but WITHOUT ANY WARRANTY; without even the implied warranty of
 +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +   GNU General Public License for more details.
 +
 +   You should have received a copy of the GNU General Public License
 +   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 +
 +#include <config.h>
 +
 +#include "xalloc.h"
 +#include "xmalloca.h"
 +
 +#include "gettext.h"
 +#define _(msgid) gettext (msgid)
 +#define N_(msgid) msgid
 +
 +#include <data/variable.h>
 +#include <data/dictionary.h>
 +#include <data/procedure.h>
 +#include <data/casereader.h>
 +#include <data/casegrouper.h>
 +#include <math/moments.h>
 +#include <data/case.h>
 +
 +#include <language/command.h>
 +
 +#include <output/manager.h>
 +#include <output/table.h>
 +
 +/* (headers) */
 +
 +/* (specification)
 +   reliability (rel_):
 +     *^variables=varlist("PV_NO_SCRATCH | PV_NUMERIC");
 +     scale=custom;
 +     missing=miss:!exclude/include;
 +     model=custom;
 +     method=covariance;
 +     +summary[sum_]=total.
 +*/
 +/* (declarations) */
 +/* (functions) */
 +
 +
 +static int rel_custom_scale (struct lexer *lexer, struct dataset *ds,
 +                    struct cmd_reliability *p, void *aux);
 +
 +static int rel_custom_model (struct lexer *, struct dataset *,
 +                           struct cmd_reliability *, void *);
 +
 +int cmd_reliability (struct lexer *lexer, struct dataset *ds);
 +
 +struct cronbach
 +{
 +  const struct variable **items;
 +  size_t n_items;
 +  double alpha;
 +  double sum_of_variances;
 +  double variance_of_sums;
 +  int totals_idx;          /* Casereader index into the totals */
 +
 +  struct moments1 **m ;    /* Moments of the items */
 +  struct moments1 *total ; /* Moments of the totals */
 +};
 +
 +#if 0
 +static void
 +dump_cronbach (const struct cronbach *s)
 +{
 +  int i;
 +  printf ("N items %d\n", s->n_items);
 +  for (i = 0 ; i < s->n_items; ++i)
 +    {
 +      printf ("%s\n", var_get_name (s->items[i]));
 +    }
 +
 +  printf ("Totals idx %d\n", s->totals_idx);
 +
 +  printf ("scale variance %g\n", s->variance_of_sums);
 +  printf ("alpha %g\n", s->alpha);
 +  putchar ('\n');
 +}
 +#endif
 +
 +enum model
 +  {
 +    MODEL_ALPHA,
 +    MODEL_SPLIT
 +  };
 +
 +
 +struct reliability
 +{
++  const struct dictionary *dict;
 +  const struct variable **variables;
 +  int n_variables;
 +  enum mv_class exclude;
 +
 +  struct cronbach *sc;
 +  int n_sc;
 +
 +  int total_start;
 +
 +  struct string scale_name;
 +
 +  enum model model;
 +  int split_point;
 +};
 +
 +
 +static double
 +alpha (int k, double sum_of_variances, double variance_of_sums)
 +{
 +  return k / ( k - 1.0) * ( 1 - sum_of_variances / variance_of_sums);
 +}
 +
 +static void reliability_summary_total (const struct reliability *rel);
 +
 +static void reliability_statistics (const struct reliability *rel);
 +
 +
 +
 +static void
 +run_reliability (struct casereader *group, struct dataset *ds,
 +               struct reliability *rel);
 +
 +
 +int
 +cmd_reliability (struct lexer *lexer, struct dataset *ds)
 +{
 +  int i;
 +  bool ok = false;
 +  struct casegrouper *grouper;
 +  struct casereader *group;
 +  struct cmd_reliability cmd;
 +
- static void case_processing_summary (casenumber n_valid, casenumber n_missing);
++  struct reliability rel = {NULL,
 +    NULL, 0, MV_ANY, NULL, 0, -1,
 +    DS_EMPTY_INITIALIZER,
 +    MODEL_ALPHA, 0};
 +
 +  cmd.v_variables = NULL;
 +
 +  if ( ! parse_reliability (lexer, ds, &cmd, &rel) )
 +    {
 +      goto done;
 +    }
 +
++  rel.dict = dataset_dict (ds);
 +  rel.variables = cmd.v_variables;
 +  rel.n_variables = cmd.n_variables;
 +  rel.exclude = MV_ANY;
 +
 +
 +  if (NULL == rel.sc)
 +    {
 +      struct cronbach *c;
 +      /* Create a default Scale */
 +
 +      rel.n_sc = 1;
 +      rel.sc = xzalloc (sizeof (struct cronbach) * rel.n_sc);
 +
 +      ds_init_cstr (&rel.scale_name, "ANY");
 +
 +      c = &rel.sc[0];
 +      c->n_items = cmd.n_variables;
 +      c->items = xzalloc (sizeof (struct variable*) * c->n_items);
 +
 +      for (i = 0 ; i < c->n_items ; ++i)
 +      c->items[i] = cmd.v_variables[i];
 +    }
 +
 +  if ( cmd.miss == REL_INCLUDE)
 +    rel.exclude = MV_SYSTEM;
 +
 +  if ( rel.model == MODEL_SPLIT)
 +    {
 +      int i;
 +      const struct cronbach *s;
 +
 +      rel.n_sc += 2 ;
 +      rel.sc = xrealloc (rel.sc, sizeof (struct cronbach) * rel.n_sc);
 +
 +      s = &rel.sc[0];
 +
 +      rel.sc[1].n_items =
 +      (rel.split_point == -1) ? s->n_items / 2 : rel.split_point;
 +
 +      rel.sc[2].n_items = s->n_items - rel.sc[1].n_items;
 +      rel.sc[1].items = xzalloc (sizeof (struct variable *)
 +                               * rel.sc[1].n_items);
 +
 +      rel.sc[2].items = xzalloc (sizeof (struct variable *) *
 +                               rel.sc[2].n_items);
 +
 +      for  (i = 0; i < rel.sc[1].n_items ; ++i)
 +      rel.sc[1].items[i] = s->items[i];
 +
 +      while (i < s->n_items)
 +      {
 +        rel.sc[2].items[i - rel.sc[1].n_items] = s->items[i];
 +        i++;
 +      }
 +    }
 +
 +  if (cmd.a_summary[REL_SUM_TOTAL])
 +    {
 +      int i;
 +      const int base_sc = rel.n_sc;
 +
 +      rel.total_start = base_sc;
 +
 +      rel.n_sc +=  rel.sc[0].n_items ;
 +      rel.sc = xrealloc (rel.sc, sizeof (struct cronbach) * rel.n_sc);
 +
 +      for (i = 0 ; i < rel.sc[0].n_items; ++i )
 +      {
 +        int v_src;
 +        int v_dest = 0;
 +        struct cronbach *s = &rel.sc[i + base_sc];
 +
 +        s->n_items = rel.sc[0].n_items - 1;
 +        s->items = xzalloc (sizeof (struct variable *) * s->n_items);
 +        for (v_src = 0 ; v_src < rel.sc[0].n_items ; ++v_src)
 +          {
 +            if ( v_src != i)
 +              s->items[v_dest++] = rel.sc[0].items[v_src];
 +          }
 +      }
 +    }
 +
 +  /* Data pass. */
 +  grouper = casegrouper_create_splits (proc_open (ds), dataset_dict (ds));
 +  while (casegrouper_get_next_group (grouper, &group))
 +    {
 +      run_reliability (group, ds, &rel);
 +
 +      reliability_statistics (&rel);
 +
 +      if (cmd.a_summary[REL_SUM_TOTAL])
 +      reliability_summary_total (&rel);
 +    }
 +  ok = casegrouper_destroy (grouper);
 +  ok = proc_commit (ds) && ok;
 +
 +  free_reliability (&cmd);
 +
 + done:
 +
 +  /* Free all the stuff */
 +  for (i = 0 ; i < rel.n_sc; ++i)
 +    {
 +      int x;
 +      struct cronbach *c = &rel.sc[i];
 +      free (c->items);
 +
 +      moments1_destroy (c->total);
 +
 +      if ( c->m)
 +      for (x = 0 ; x < c->n_items; ++x)
 +        moments1_destroy (c->m[x]);
 +
 +      free (c->m);
 +    }
 +
 +  ds_destroy (&rel.scale_name);
 +  free (rel.sc);
 +
 +  if (ok)
 +    return CMD_SUCCESS;
 +
 +  return CMD_FAILURE;
 +}
 +
 +/* Return the sum of all the item variables in S */
 +static  double
 +append_sum (const struct ccase *c, casenumber n UNUSED, void *aux)
 +{
 +  double sum = 0;
 +  const struct cronbach *s = aux;
 +
 +  int v;
 +  for (v = 0 ; v < s->n_items; ++v)
 +    {
 +      sum += case_data (c, s->items[v])->f;
 +    }
 +
 +  return sum;
 +};
 +
 +
- run_reliability (struct casereader *input, struct dataset *ds UNUSED,
++static void case_processing_summary (casenumber n_valid, casenumber n_missing, 
++                                   const struct dictionary *dict);
 +
 +static void
-   case_processing_summary (n_valid, n_missing);
++run_reliability (struct casereader *input, struct dataset *ds,
 +               struct reliability *rel)
 +{
 +  int i;
 +  int si;
 +  struct ccase *c;
 +  casenumber n_missing ;
 +  casenumber n_valid = 0;
 +
 +
 +  for (si = 0 ; si < rel->n_sc; ++si)
 +    {
 +      struct cronbach *s = &rel->sc[si];
 +
 +      s->m = xzalloc (sizeof (s->m) * s->n_items);
 +      s->total = moments1_create (MOMENT_VARIANCE);
 +
 +      for (i = 0 ; i < s->n_items ; ++i )
 +      s->m[i] = moments1_create (MOMENT_VARIANCE);
 +    }
 +
 +  input = casereader_create_filter_missing (input,
 +                                          rel->variables,
 +                                          rel->n_variables,
 +                                          rel->exclude,
 +                                          &n_missing,
 +                                          NULL);
 +
 +  for (si = 0 ; si < rel->n_sc; ++si)
 +    {
 +      struct cronbach *s = &rel->sc[si];
 +
 +
 +      s->totals_idx = casereader_get_value_cnt (input);
 +      input =
 +      casereader_create_append_numeric (input, append_sum,
 +                                        s, NULL);
 +    }
 +
 +  for (; (c = casereader_read (input)) != NULL; case_unref (c))
 +    {
 +      double weight = 1.0;
 +      n_valid ++;
 +
 +      for (si = 0; si < rel->n_sc; ++si)
 +      {
 +        struct cronbach *s = &rel->sc[si];
 +
 +        for (i = 0 ; i < s->n_items ; ++i )
 +          moments1_add (s->m[i], case_data (c, s->items[i])->f, weight);
 +
 +        moments1_add (s->total, case_data_idx (c, s->totals_idx)->f, weight);
 +      }
 +    }
 +  casereader_destroy (input);
 +
 +  for (si = 0; si < rel->n_sc; ++si)
 +    {
 +      struct cronbach *s = &rel->sc[si];
 +
 +      s->sum_of_variances = 0;
 +      for (i = 0 ; i < s->n_items ; ++i )
 +      {
 +        double weight, mean, variance;
 +        moments1_calculate (s->m[i], &weight, &mean, &variance, NULL, NULL);
 +
 +        s->sum_of_variances += variance;
 +      }
 +
 +      moments1_calculate (s->total, NULL, NULL, &s->variance_of_sums,
 +                        NULL, NULL);
 +
 +      s->alpha =
 +      alpha (s->n_items, s->sum_of_variances, s->variance_of_sums);
 +    }
 +
 +
 +  {
 +    struct tab_table *tab = tab_create(1, 1, 0);
 +
 +    tab_dim (tab, tab_natural_dimensions);
 +    tab_flags (tab, SOMF_NO_TITLE );
 +
 +    tab_text(tab, 0, 0, TAT_PRINTF, "Scale: %s", ds_cstr (&rel->scale_name));
 +
 +    tab_submit(tab);
 +  }
 +
 +
-   void (*populate)(struct tab_table *, const struct reliability *);
++  case_processing_summary (n_valid, n_missing, dataset_dict (ds));
 +}
 +
 +
 +static void reliability_statistics_model_alpha (struct tab_table *tbl,
 +                                              const struct reliability *rel);
 +
 +static void reliability_statistics_model_split (struct tab_table *tbl,
 +                                              const struct reliability *rel);
 +
 +struct reliability_output_table
 +{
 +  int n_cols;
 +  int n_rows;
 +  int heading_cols;
 +  int heading_rows;
-       tab_float (tbl, 1, heading_rows + i, TAB_RIGHT,
-                mean, 8, 3);
++  void (*populate) (struct tab_table *, const struct reliability *);
 +};
 +
 +static struct reliability_output_table rol[2] =
 +  {
 +    { 2, 2, 1, 1, reliability_statistics_model_alpha},
 +    { 4, 9, 3, 0, reliability_statistics_model_split}
 +  };
 +
 +static void
 +reliability_statistics (const struct reliability *rel)
 +{
 +  int n_cols = rol[rel->model].n_cols;
 +  int n_rows = rol[rel->model].n_rows;
 +  int heading_columns = rol[rel->model].heading_cols;
 +  int heading_rows = rol[rel->model].heading_rows;
 +
 +  struct tab_table *tbl = tab_create (n_cols, n_rows, 0);
 +  tab_headers (tbl, heading_columns, 0, heading_rows, 0);
 +
 +  tab_dim (tbl, tab_natural_dimensions);
 +
 +  tab_title (tbl, _("Reliability Statistics"));
 +
 +  /* Vertical lines for the data only */
 +  tab_box (tbl,
 +         -1, -1,
 +         -1, TAL_1,
 +         heading_columns, 0,
 +         n_cols - 1, n_rows - 1);
 +
 +  /* Box around table */
 +  tab_box (tbl,
 +         TAL_2, TAL_2,
 +         -1, -1,
 +         0, 0,
 +         n_cols - 1, n_rows - 1);
 +
 +
 +  tab_hline (tbl, TAL_2, 0, n_cols - 1, heading_rows);
 +
 +  tab_vline (tbl, TAL_2, heading_columns, 0, n_rows - 1);
 +
 +  if ( rel->model == MODEL_ALPHA )
 +    reliability_statistics_model_alpha (tbl, rel);
 +  else if (rel->model == MODEL_SPLIT )
 +    reliability_statistics_model_split (tbl, rel);
 +
 +  tab_submit (tbl);
 +}
 +
 +static void
 +reliability_summary_total (const struct reliability *rel)
 +{
 +  int i;
 +  const int n_cols = 5;
 +  const int heading_columns = 1;
 +  const int heading_rows = 1;
 +  const int n_rows = rel->sc[0].n_items + heading_rows ;
 +
 +  struct tab_table *tbl = tab_create (n_cols, n_rows, 0);
 +  tab_headers (tbl, heading_columns, 0, heading_rows, 0);
 +
 +  tab_dim (tbl, tab_natural_dimensions);
 +
 +  tab_title (tbl, _("Item-Total Statistics"));
 +
 +  /* Vertical lines for the data only */
 +  tab_box (tbl,
 +         -1, -1,
 +         -1, TAL_1,
 +         heading_columns, 0,
 +         n_cols - 1, n_rows - 1);
 +
 +  /* Box around table */
 +  tab_box (tbl,
 +         TAL_2, TAL_2,
 +         -1, -1,
 +         0, 0,
 +         n_cols - 1, n_rows - 1);
 +
 +
 +  tab_hline (tbl, TAL_2, 0, n_cols - 1, heading_rows);
 +
 +  tab_vline (tbl, TAL_2, heading_columns, 0, n_rows - 1);
 +
 +  tab_text (tbl, 1, 0, TAB_CENTER | TAT_TITLE,
 +          _("Scale Mean if Item Deleted"));
 +
 +  tab_text (tbl, 2, 0, TAB_CENTER | TAT_TITLE,
 +          _("Scale Variance if Item Deleted"));
 +
 +  tab_text (tbl, 3, 0, TAB_CENTER | TAT_TITLE,
 +          _("Corrected Item-Total Correlation"));
 +
 +  tab_text (tbl, 4, 0, TAB_CENTER | TAT_TITLE,
 +          _("Cronbach's Alpha if Item Deleted"));
 +
 +
 +  for (i = 0 ; i < rel->sc[0].n_items; ++i)
 +    {
 +      double cov, item_to_total_r;
 +      double mean, weight, var;
 +
 +      const struct cronbach *s = &rel->sc[rel->total_start + i];
 +      tab_text (tbl, 0, heading_rows + i, TAB_LEFT| TAT_TITLE,
 +              var_to_string (rel->sc[0].items[i]));
 +
 +      moments1_calculate (s->total, &weight, &mean, &var, 0, 0);
 +
-       tab_float (tbl, 2, heading_rows + i, TAB_RIGHT,
-                s->variance_of_sums, 8, 3);
++      tab_double (tbl, 1, heading_rows + i, TAB_RIGHT,
++               mean, NULL);
 +
-       tab_float (tbl, 4, heading_rows + i, TAB_RIGHT,
-                s->alpha, 8, 3);
++      tab_double (tbl, 2, heading_rows + i, TAB_RIGHT,
++               s->variance_of_sums, NULL);
 +
-       tab_float (tbl, 3, heading_rows + i, TAB_RIGHT,
-                item_to_total_r, 8, 3);
++      tab_double (tbl, 4, heading_rows + i, TAB_RIGHT,
++               s->alpha, NULL);
 +
 +
 +      moments1_calculate (rel->sc[0].m[i], &weight, &mean, &var, 0,0);
 +      cov = rel->sc[0].variance_of_sums + var - s->variance_of_sums;
 +      cov /= 2.0;
 +
 +      item_to_total_r = (cov - var) / (sqrt(var) * sqrt (s->variance_of_sums));
 +
 +
-   tab_float (tbl, 0, 1, TAB_RIGHT, s->alpha, 8, 3);
++      tab_double (tbl, 3, heading_rows + i, TAB_RIGHT,
++               item_to_total_r, NULL);
 +    }
 +
 +
 +  tab_submit (tbl);
 +}
 +
 +
 +static void
 +reliability_statistics_model_alpha (struct tab_table *tbl,
 +                                  const struct reliability *rel)
 +{
++  const struct variable *wv = dict_get_weight (rel->dict);
++  const struct fmt_spec *wfmt = wv ? var_get_print_format (wv) : & F_8_0;
++
 +  const struct cronbach *s = &rel->sc[0];
 +
 +  tab_text (tbl, 0, 0, TAB_CENTER | TAT_TITLE,
 +              _("Cronbach's Alpha"));
 +
 +  tab_text (tbl, 1, 0, TAB_CENTER | TAT_TITLE,
 +              _("N of items"));
 +
-   tab_float (tbl, 1, 1, TAB_RIGHT, s->n_items, 8, 0);
++  tab_double (tbl, 0, 1, TAB_RIGHT, s->alpha, NULL);
 +
-   tab_float (tbl, 3, 0, TAB_RIGHT, rel->sc[1].alpha, 8, 3);
-   tab_float (tbl, 3, 2, TAB_RIGHT, rel->sc[2].alpha, 8, 3);
++  tab_double (tbl, 1, 1, TAB_RIGHT, s->n_items, wfmt);
 +}
 +
 +
 +static void
 +reliability_statistics_model_split (struct tab_table *tbl,
 +                                  const struct reliability *rel)
 +{
++  const struct variable *wv = dict_get_weight (rel->dict);
++  const struct fmt_spec *wfmt = wv ? var_get_print_format (wv) : & F_8_0;
++
 +  tab_text (tbl, 0, 0, TAB_LEFT,
 +          _("Cronbach's Alpha"));
 +
 +  tab_text (tbl, 1, 0, TAB_LEFT,
 +          _("Part 1"));
 +
 +  tab_text (tbl, 2, 0, TAB_LEFT,
 +          _("Value"));
 +
 +  tab_text (tbl, 2, 1, TAB_LEFT,
 +          _("N of Items"));
 +
 +
 +
 +  tab_text (tbl, 1, 2, TAB_LEFT,
 +          _("Part 2"));
 +
 +  tab_text (tbl, 2, 2, TAB_LEFT,
 +          _("Value"));
 +
 +  tab_text (tbl, 2, 3, TAB_LEFT,
 +          _("N of Items"));
 +
 +
 +
 +  tab_text (tbl, 1, 4, TAB_LEFT,
 +          _("Total N of Items"));
 +
 +  tab_text (tbl, 0, 5, TAB_LEFT,
 +          _("Correlation Between Forms"));
 +
 +
 +  tab_text (tbl, 0, 6, TAB_LEFT,
 +          _("Spearman-Brown Coefficient"));
 +
 +  tab_text (tbl, 1, 6, TAB_LEFT,
 +          _("Equal Length"));
 +
 +  tab_text (tbl, 1, 7, TAB_LEFT,
 +          _("Unequal Length"));
 +
 +
 +  tab_text (tbl, 0, 8, TAB_LEFT,
 +          _("Guttman Split-Half Coefficient"));
 +
 +
 +
-   tab_float (tbl, 3, 1, TAB_RIGHT, rel->sc[1].n_items, 8, 0);
-   tab_float (tbl, 3, 3, TAB_RIGHT, rel->sc[2].n_items, 8, 0);
++  tab_double (tbl, 3, 0, TAB_RIGHT, rel->sc[1].alpha, NULL);
++  tab_double (tbl, 3, 2, TAB_RIGHT, rel->sc[2].alpha, NULL);
 +
-   tab_float (tbl, 3, 4, TAB_RIGHT,
-            rel->sc[1].n_items + rel->sc[2].n_items, 8, 0);
++  tab_double (tbl, 3, 1, TAB_RIGHT, rel->sc[1].n_items, wfmt);
++  tab_double (tbl, 3, 3, TAB_RIGHT, rel->sc[2].n_items, wfmt);
 +
-     tab_float (tbl, 3, 5, TAB_RIGHT, r, 8, 3);
++  tab_double (tbl, 3, 4, TAB_RIGHT,
++           rel->sc[1].n_items + rel->sc[2].n_items, wfmt);
 +
 +  {
 +    /* R is the correlation between the two parts */
 +    double r = rel->sc[0].variance_of_sums -
 +      rel->sc[1].variance_of_sums -
 +      rel->sc[2].variance_of_sums ;
 +
 +    /* Guttman Split Half Coefficient */
 +    double g = 2 * r / rel->sc[0].variance_of_sums;
 +
 +    /* Unequal Length Spearman Brown Coefficient, and
 +     intermediate value used in the computation thereof */
 +    double uly, tmp;
 +
 +    r /= sqrt (rel->sc[1].variance_of_sums);
 +    r /= sqrt (rel->sc[2].variance_of_sums);
 +    r /= 2.0;
 +
-     tab_float (tbl, 3, 6, TAB_RIGHT, 2 * r / (1.0 + r), 8, 3);
++    tab_double (tbl, 3, 5, TAB_RIGHT, r, NULL);
 +
 +    /* Equal length Spearman-Brown Coefficient */
-     tab_float (tbl, 3, 8, TAB_RIGHT, g, 8, 3);
++    tab_double (tbl, 3, 6, TAB_RIGHT, 2 * r / (1.0 + r), NULL);
 +
-     tab_float (tbl, 3, 7, TAB_RIGHT, uly, 8, 3);
++    tab_double (tbl, 3, 8, TAB_RIGHT, g, NULL);
 +
 +    tmp = (1.0 - r*r) * rel->sc[1].n_items * rel->sc[2].n_items /
 +      pow2 (rel->sc[0].n_items);
 +
 +    uly = sqrt( pow4 (r) + 4 * pow2 (r) * tmp);
 +    uly -= pow2 (r);
 +    uly /= 2 * tmp;
 +
- case_processing_summary (casenumber n_valid, casenumber n_missing)
++    tab_double (tbl, 3, 7, TAB_RIGHT, uly, NULL);
 +  }
 +}
 +
 +
 +
 +static void
-   tab_float (tbl, 2, heading_rows, TAB_RIGHT,
-            n_valid, 8, 0);
++case_processing_summary (casenumber n_valid, casenumber n_missing,
++                       const struct dictionary *dict)
 +{
++  const struct variable *wv = dict_get_weight (dict);
++  const struct fmt_spec *wfmt = wv ? var_get_print_format (wv) : & F_8_0;
++
 +  casenumber total;
 +  int n_cols = 4;
 +  int n_rows = 4;
 +  int heading_columns = 2;
 +  int heading_rows = 1;
 +  struct tab_table *tbl;
 +  tbl = tab_create (n_cols, n_rows, 0);
 +  tab_headers (tbl, heading_columns, 0, heading_rows, 0);
 +
 +  tab_dim (tbl, tab_natural_dimensions);
 +
 +  tab_title (tbl, _("Case Processing Summary"));
 +
 +  /* Vertical lines for the data only */
 +  tab_box (tbl,
 +         -1, -1,
 +         -1, TAL_1,
 +         heading_columns, 0,
 +         n_cols - 1, n_rows - 1);
 +
 +  /* Box around table */
 +  tab_box (tbl,
 +         TAL_2, TAL_2,
 +         -1, -1,
 +         0, 0,
 +         n_cols - 1, n_rows - 1);
 +
 +
 +  tab_hline (tbl, TAL_2, 0, n_cols - 1, heading_rows);
 +
 +  tab_vline (tbl, TAL_2, heading_columns, 0, n_rows - 1);
 +
 +
 +  tab_text (tbl, 0, heading_rows, TAB_LEFT | TAT_TITLE,
 +              _("Cases"));
 +
 +  tab_text (tbl, 1, heading_rows, TAB_LEFT | TAT_TITLE,
 +              _("Valid"));
 +
 +  tab_text (tbl, 1, heading_rows + 1, TAB_LEFT | TAT_TITLE,
 +              _("Excluded"));
 +
 +  tab_text (tbl, 1, heading_rows + 2, TAB_LEFT | TAT_TITLE,
 +              _("Total"));
 +
 +  tab_text (tbl, heading_columns, 0, TAB_CENTER | TAT_TITLE,
 +              _("N"));
 +
 +  tab_text (tbl, heading_columns + 1, 0, TAB_CENTER | TAT_TITLE | TAT_PRINTF,
 +              _("%%"));
 +
 +  total = n_missing + n_valid;
 +
-   tab_float (tbl, 2, heading_rows + 1, TAB_RIGHT,
-            n_missing, 8, 0);
++  tab_double (tbl, 2, heading_rows, TAB_RIGHT,
++           n_valid, wfmt);
 +
 +
-   tab_float (tbl, 2, heading_rows + 2, TAB_RIGHT,
-            total, 8, 0);
++  tab_double (tbl, 2, heading_rows + 1, TAB_RIGHT,
++           n_missing, wfmt);
 +
 +
-   tab_float (tbl, 3, heading_rows, TAB_RIGHT,
-            100 * n_valid / (double) total, 8, 1);
++  tab_double (tbl, 2, heading_rows + 2, TAB_RIGHT,
++           total, wfmt);
 +
 +
-   tab_float (tbl, 3, heading_rows + 1, TAB_RIGHT,
-            100 * n_missing / (double) total, 8, 1);
++  tab_double (tbl, 3, heading_rows, TAB_RIGHT,
++           100 * n_valid / (double) total, NULL);
 +
 +
-   tab_float (tbl, 3, heading_rows + 2, TAB_RIGHT,
-            100 * total / (double) total, 8, 1);
++  tab_double (tbl, 3, heading_rows + 1, TAB_RIGHT,
++           100 * n_missing / (double) total, NULL);
 +
 +
++  tab_double (tbl, 3, heading_rows + 2, TAB_RIGHT,
++           100 * total / (double) total, NULL);
 +
 +
 +  tab_submit (tbl);
 +}
 +
 +static int
 +rel_custom_model (struct lexer *lexer, struct dataset *ds UNUSED,
 +                struct cmd_reliability *cmd UNUSED, void *aux)
 +{
 +  struct reliability *rel = aux;
 +
 +  if (lex_match_id (lexer, "ALPHA"))
 +    {
 +      rel->model = MODEL_ALPHA;
 +    }
 +  else if (lex_match_id (lexer, "SPLIT"))
 +    {
 +      rel->model = MODEL_SPLIT;
 +      rel->split_point = -1;
 +      if ( lex_match (lexer, '('))
 +      {
 +        lex_force_num (lexer);
 +        rel->split_point = lex_number (lexer);
 +        lex_get (lexer);
 +        lex_force_match (lexer, ')');
 +      }
 +    }
 +  else
 +    return 0;
 +
 +  return 1;
 +}
 +
 +
 +
 +static int
 +rel_custom_scale (struct lexer *lexer, struct dataset *ds UNUSED,
 +                struct cmd_reliability *p, void *aux)
 +{
 +  struct const_var_set *vs;
 +  struct reliability *rel = aux;
 +  struct cronbach *scale;
 +
 +  rel->n_sc = 1;
 +  rel->sc = xzalloc (sizeof (struct cronbach) * rel->n_sc);
 +  scale = &rel->sc[0];
 +
 +  if ( ! lex_force_match (lexer, '(')) return 0;
 +
 +  if ( ! lex_force_string (lexer) ) return 0;
 +
 +  ds_init_string (&rel->scale_name, lex_tokstr (lexer));
 +
 +  lex_get (lexer);
 +
 +  if ( ! lex_force_match (lexer, ')')) return 0;
 +
 +  lex_match (lexer, '=');
 +
 +  vs = const_var_set_create_from_array (p->v_variables, p->n_variables);
 +
 +  if (!parse_const_var_set_vars (lexer, vs, &scale->items, &scale->n_items, 0))
 +    {
 +      const_var_set_destroy (vs);
 +      return 2;
 +    }
 +
 +  const_var_set_destroy (vs);
 +  return 1;
 +}
 +
 +/*
 +   Local Variables:
 +   mode: c
 +   End:
 +*/
Simple merge
index 1bdcc06dc252851f93c7172a13c35fdfaba62367,0000000000000000000000000000000000000000..c0329f6c01e5277e33304377d7ed07c56f99dca5
mode 100644,000000..100644
--- /dev/null
@@@ -1,361 -1,0 +1,369 @@@
-                           const struct two_sample_test *);
 +/* Pspp - a program for statistical analysis.
 +   Copyright (C) 2008, 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
 +   the Free Software Foundation, either version 3 of the License, or
 +   (at your option) any later version.
 +
 +   This program is distributed in the hope that it will be useful,
 +   but WITHOUT ANY WARRANTY; without even the implied warranty of
 +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +   GNU General Public License for more details.
 +
 +   You should have received a copy of the GNU General Public License
 +   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 +
 +
 +
 +#include <config.h>
 +#include "wilcoxon.h"
 +#include <data/variable.h>
 +#include <data/casereader.h>
 +#include <data/casewriter.h>
 +#include <data/subcase.h>
 +#include <math/sort.h>
 +#include <libpspp/message.h>
 +#include <xalloc.h>
 +#include <output/table.h>
 +#include <data/procedure.h>
 +#include <data/dictionary.h>
 +#include <math/wilcoxon-sig.h>
 +#include <gsl/gsl_cdf.h>
 +#include <unistd.h>
 +#include <signal.h>
 +#include <libpspp/assertion.h>
++#include <data/format.h>
 +
 +static double
 +append_difference (const struct ccase *c, casenumber n UNUSED, void *aux)
 +{
 +  const variable_pair *vp = aux;
 +
 +  return case_data (c, (*vp)[0])->f - case_data (c, (*vp)[1])->f;
 +}
 +
 +static void show_ranks_box (const struct wilcoxon_state *,
-   show_ranks_box (ws, t2s);
++                          const struct two_sample_test *,
++                          const struct dictionary *);
 +
 +static void show_tests_box (const struct wilcoxon_state *,
 +                          const struct two_sample_test *,
 +                          bool exact, double timer);
 +
 +
 +
 +static void
 +distinct_callback (double v UNUSED, casenumber n, double w UNUSED, void *aux)
 +{
 +  struct wilcoxon_state *ws = aux;
 +
 +  ws->tiebreaker += pow3 (n) - n;
 +}
 +
 +#define WEIGHT_IDX 2
 +
 +void
 +wilcoxon_execute (const struct dataset *ds,
 +                struct casereader *input,
 +                enum mv_class exclude,
 +                const struct npar_test *test,
 +                bool exact,
 +                double timer)
 +{
 +  int i;
 +  bool warn = true;
 +  const struct dictionary *dict = dataset_dict (ds);
 +  const struct two_sample_test *t2s = (struct two_sample_test *) test;
 +
 +  struct wilcoxon_state *ws = xcalloc (sizeof (*ws), t2s->n_pairs);
 +  const struct variable *weight = dict_get_weight (dict);
 +  struct variable *weightx = var_create_internal (WEIGHT_IDX);
 +
 +  input =
 +    casereader_create_filter_weight (input, dict, &warn, NULL);
 +
 +  for (i = 0 ; i < t2s->n_pairs; ++i )
 +    {
 +      struct casereader *r = casereader_clone (input);
 +      struct casewriter *writer;
 +      struct ccase *c;
 +      struct subcase ordering;
 +      variable_pair *vp = &t2s->pairs[i];
 +
 +      const int reader_width = weight ? 3 : 2;
 +
 +      ws[i].sign = var_create_internal (0);
 +      ws[i].absdiff = var_create_internal (1);
 +
 +      r = casereader_create_filter_missing (r, *vp, 2,
 +                                          exclude,
 +                                          NULL, NULL);
 +
 +      subcase_init_var (&ordering, ws[i].absdiff, SC_ASCEND);
 +      writer = sort_create_writer (&ordering, reader_width);
 +      subcase_destroy (&ordering);
 +
 +      for (; (c = casereader_read (r)) != NULL; case_unref (c))
 +      {
 +        struct ccase *output = case_create (reader_width);
 +        double d = append_difference (c, 0, vp);
 +
 +        if (d > 0)
 +          {
 +            case_data_rw (output, ws[i].sign)->f = 1.0;
 +
 +          }
 +        else if (d < 0)
 +          {
 +            case_data_rw (output, ws[i].sign)->f = -1.0;
 +          }
 +        else
 +          {
 +            double w = 1.0;
 +            if (weight)
 +              w = case_data (c, weight)->f;
 +
 +            /* Central point values should be dropped */
 +            ws[i].n_zeros += w;
 +              case_unref (output);
 +              continue;
 +          }
 +
 +        case_data_rw (output, ws[i].absdiff)->f = fabs (d);
 +
 +        if (weight)
 +         case_data_rw (output, weightx)->f = case_data (c, weight)->f;
 +
 +        casewriter_write (writer, output);
 +      }
 +      casereader_destroy (r);
 +      ws[i].reader = casewriter_make_reader (writer);
 +    }
 +
 +  for (i = 0 ; i < t2s->n_pairs; ++i )
 +    {
 +      struct casereader *rr ;
 +      struct ccase *c;
 +      enum rank_error err = 0;
 +
 +      rr = casereader_create_append_rank (ws[i].reader, ws[i].absdiff,
 +                                        weight ? weightx : NULL, &err,
 +                                        distinct_callback, &ws[i]
 +                                        );
 +
 +      for (; (c = casereader_read (rr)) != NULL; case_unref (c))
 +      {
 +        double sign = case_data (c, ws[i].sign)->f;
 +        double rank = case_data_idx (c, weight ? 3 : 2)->f;
 +        double w = 1.0;
 +        if (weight)
 +          w = case_data (c, weightx)->f;
 +
 +        if ( sign > 0 )
 +          {
 +            ws[i].positives.sum += rank * w;
 +            ws[i].positives.n += w;
 +          }
 +        else if (sign < 0)
 +          {
 +            ws[i].negatives.sum += rank * w;
 +            ws[i].negatives.n += w;
 +          }
 +        else
 +          NOT_REACHED ();
 +      }
 +
 +      casereader_destroy (rr);
 +    }
 +
 +  casereader_destroy (input);
 +
 +  var_destroy (weightx);
 +
- show_ranks_box (const struct wilcoxon_state *ws, const struct two_sample_test *t2s)
++  show_ranks_box (ws, t2s, dict);
 +  show_tests_box (ws, t2s, exact, timer);
 +
 +  for (i = 0 ; i < t2s->n_pairs; ++i )
 +    {
 +      var_destroy (ws[i].sign);
 +      var_destroy (ws[i].absdiff);
 +    }
 +
 +  free (ws);
 +}
 +
 +
 +\f
 +
 +#include "gettext.h"
 +#define _(msgid) gettext (msgid)
 +
 +static void
-       tab_float (table, 2, 1 + i * 4, TAB_RIGHT, ws[i].negatives.n, 8, 0);
-       tab_float (table, 2, 2 + i * 4, TAB_RIGHT, ws[i].positives.n, 8, 0);
-       tab_float (table, 2, 3 + i * 4, TAB_RIGHT, ws[i].n_zeros, 8, 0);
++show_ranks_box (const struct wilcoxon_state *ws,
++              const struct two_sample_test *t2s,
++              const struct dictionary *dict)
 +{
 +  size_t i;
++
++  const struct variable *wv = dict_get_weight (dict);
++  const struct fmt_spec *wfmt = wv ? var_get_print_format (wv) : & F_8_0;
++
 +  struct tab_table *table = tab_create (5, 1 + 4 * t2s->n_pairs, 0);
 +
 +  tab_dim (table, tab_natural_dimensions);
 +
 +  tab_title (table, _("Ranks"));
 +
 +  tab_headers (table, 2, 0, 1, 0);
 +
 +  /* Vertical lines inside the box */
 +  tab_box (table, 0, 0, -1, TAL_1,
 +         1, 0, table->nc - 1, tab_nr (table) - 1 );
 +
 +  /* Box around entire table */
 +  tab_box (table, TAL_2, TAL_2, -1, -1,
 +         0, 0, table->nc - 1, tab_nr (table) - 1 );
 +
 +
 +  tab_text (table,  2, 0,  TAB_CENTER, _("N"));
 +  tab_text (table,  3, 0,  TAB_CENTER, _("Mean Rank"));
 +  tab_text (table,  4, 0,  TAB_CENTER, _("Sum of Ranks"));
 +
 +
 +  for (i = 0 ; i < t2s->n_pairs; ++i)
 +    {
 +      variable_pair *vp = &t2s->pairs[i];
 +
 +      struct string pair_name;
 +      ds_init_cstr (&pair_name, var_to_string ((*vp)[0]));
 +      ds_put_cstr (&pair_name, " - ");
 +      ds_put_cstr (&pair_name, var_to_string ((*vp)[1]));
 +
 +      tab_text (table, 1, 1 + i * 4, TAB_LEFT, _("Negative Ranks"));
 +      tab_text (table, 1, 2 + i * 4, TAB_LEFT, _("Positive Ranks"));
 +      tab_text (table, 1, 3 + i * 4, TAB_LEFT, _("Ties"));
 +      tab_text (table, 1, 4 + i * 4, TAB_LEFT, _("Total"));
 +
 +      tab_hline (table, TAL_1, 0, table->nc - 1, 1 + i * 4);
 +
 +
 +      tab_text (table, 0, 1 + i * 4, TAB_LEFT, ds_cstr (&pair_name));
 +      ds_destroy (&pair_name);
 +
 +
 +      /* N */
-       tab_float (table, 2, 4 + i * 4, TAB_RIGHT,
-                ws[i].n_zeros + ws[i].positives.n + ws[i].negatives.n, 8, 0);
++      tab_double (table, 2, 1 + i * 4, TAB_RIGHT, ws[i].negatives.n, wfmt);
++      tab_double (table, 2, 2 + i * 4, TAB_RIGHT, ws[i].positives.n, wfmt);
++      tab_double (table, 2, 3 + i * 4, TAB_RIGHT, ws[i].n_zeros, wfmt);
 +
-       tab_float (table, 4, 1 + i * 4, TAB_RIGHT, ws[i].negatives.sum, 8, 2);
-       tab_float (table, 4, 2 + i * 4, TAB_RIGHT, ws[i].positives.sum, 8, 2);
++      tab_double (table, 2, 4 + i * 4, TAB_RIGHT,
++               ws[i].n_zeros + ws[i].positives.n + ws[i].negatives.n, wfmt);
 +
 +      /* Sums */
-       tab_float (table, 3, 1 + i * 4, TAB_RIGHT,
-                ws[i].negatives.sum / (double) ws[i].negatives.n, 8, 2);
++      tab_double (table, 4, 1 + i * 4, TAB_RIGHT, ws[i].negatives.sum, NULL);
++      tab_double (table, 4, 2 + i * 4, TAB_RIGHT, ws[i].positives.sum, NULL);
 +
 +
 +      /* Means */
-       tab_float (table, 3, 2 + i * 4, TAB_RIGHT,
-                ws[i].positives.sum / (double) ws[i].positives.n, 8, 2);
++      tab_double (table, 3, 1 + i * 4, TAB_RIGHT,
++               ws[i].negatives.sum / (double) ws[i].negatives.n, NULL);
 +
-       tab_float (table, 1 + i, 1, TAB_RIGHT, z, 8, 3);
++      tab_double (table, 3, 2 + i * 4, TAB_RIGHT,
++               ws[i].positives.sum / (double) ws[i].positives.n, NULL);
 +
 +    }
 +
 +  tab_hline (table, TAL_2, 0, table->nc - 1, 1);
 +  tab_vline (table, TAL_2, 2, 0, table->nr - 1);
 +
 +
 +  tab_submit (table);
 +}
 +
 +
 +static void
 +show_tests_box (const struct wilcoxon_state *ws,
 +              const struct two_sample_test *t2s,
 +              bool exact,
 +              double timer UNUSED
 +              )
 +{
 +  size_t i;
 +  struct tab_table *table = tab_create (1 + t2s->n_pairs, exact ? 5 : 3, 0);
 +
 +  tab_dim (table, tab_natural_dimensions);
 +
 +  tab_title (table, _("Test Statistics"));
 +
 +  tab_headers (table, 1, 0, 1, 0);
 +
 +  /* Vertical lines inside the box */
 +  tab_box (table, 0, 0, -1, TAL_1,
 +         0, 0, table->nc - 1, tab_nr (table) - 1 );
 +
 +  /* Box around entire table */
 +  tab_box (table, TAL_2, TAL_2, -1, -1,
 +         0, 0, table->nc - 1, tab_nr (table) - 1 );
 +
 +
 +  tab_text (table,  0, 1,  TAB_LEFT, _("Z"));
 +  tab_text (table,  0, 2,  TAB_LEFT, _("Asymp. Sig (2-tailed)"));
 +
 +  if ( exact )
 +    {
 +      tab_text (table,  0, 3,  TAB_LEFT, _("Exact Sig (2-tailed)"));
 +      tab_text (table,  0, 4,  TAB_LEFT, _("Exact Sig (1-tailed)"));
 +
 +#if 0
 +      tab_text (table,  0, 5,  TAB_LEFT, _("Point Probability"));
 +#endif
 +    }
 +
 +  for (i = 0 ; i < t2s->n_pairs; ++i)
 +    {
 +      double z;
 +      double n = ws[i].positives.n + ws[i].negatives.n;
 +      variable_pair *vp = &t2s->pairs[i];
 +
 +      struct string pair_name;
 +      ds_init_cstr (&pair_name, var_to_string ((*vp)[0]));
 +      ds_put_cstr (&pair_name, " - ");
 +      ds_put_cstr (&pair_name, var_to_string ((*vp)[1]));
 +
 +
 +      tab_text (table, 1 + i, 0, TAB_CENTER, ds_cstr (&pair_name));
 +      ds_destroy (&pair_name);
 +
 +      z = MIN (ws[i].positives.sum, ws[i].negatives.sum);
 +      z -= n * (n + 1)/ 4.0;
 +
 +      z /= sqrt (n * (n + 1) * (2*n + 1)/24.0 - ws[i].tiebreaker / 48.0);
 +
-       tab_float (table, 1 + i, 2, TAB_RIGHT,
++      tab_double (table, 1 + i, 1, TAB_RIGHT, z, NULL);
 +
-                8, 3);
++      tab_double (table, 1 + i, 2, TAB_RIGHT,
 +               2.0 * gsl_cdf_ugaussian_P (z),
-             tab_float (table, 1 + i, 3, TAB_RIGHT, p, 8, 3);
-             tab_float (table, 1 + i, 4, TAB_RIGHT, p / 2.0, 8, 3);
++               NULL);
 +
 +      if (exact)
 +      {
 +        double p = LevelOfSignificanceWXMPSR (ws[i].positives.sum, n);
 +        if (p < 0)
 +          {
 +            msg (MW, ("Too many pairs to calculate exact significance."));
 +          }
 +        else
 +          {
++            tab_double (table, 1 + i, 3, TAB_RIGHT, p, NULL);
++            tab_double (table, 1 + i, 4, TAB_RIGHT, p / 2.0, NULL);
 +          }
 +      }
 +    }
 +
 +  tab_hline (table, TAL_2, 0, table->nc - 1, 1);
 +  tab_vline (table, TAL_2, 1, 0, table->nr - 1);
 +
 +
 +  tab_submit (table);
 +}
Simple merge
index 8524bf5e52807d0f0df5a3ee9bd43d30d91c763c,6e789c7b25a0f6421796a252fa6b85a90fb85b7b..67dfed0a5757fa0d859d743e6a407ef26a3a10eb
@@@ -102,33 -102,33 +102,33 @@@ activity="compare results
  perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.list
  diff -b  $TEMPDIR/pspp.list - << EOF
  1.1 EXAMINE.  Case Processing Summary
- #==#===============================#
- #  #             Cases             #
- #  #----------+---------+----------#
- #  #   Valid  | Missing |   Total  #
- #  #--+-------+-+-------+--+-------#
- #  # N|Percent|N|Percent| N|Percent#
- #==#==#=======#=#=======#==#=======#
- #V1#23|   100%|0|     0%|23|   100%#
- #==#==#=======#=#=======#==#=======#
+ #==#=======================================#
+ #  #                 Cases                 #
+ #  #-------------+-----------+-------------#
+ #  #    Valid    |  Missing  |    Total    #
+ #  #-----+-------+---+-------+-----+-------#
+ #  #  N  |Percent| N |Percent|  N  |Percent#
+ #==#=====#=======#===#=======#=====#=======#
+ #V1#23.00|   100%|.00|     0%|23.00|   100%#
+ #==#=====#=======#===#=======#=====#=======#
  1.2 EXAMINE.  Extreme Values
 -#============#===========#========#
 -#            #Case Number|  Value #
 -#============#===========#========#
 -#V1 Highest 1#         21|   20.00#
 -#           2#         20|   19.00#
 -#           3#         19|   18.00#
 -#           4#         19|   18.00#
 -#           5#         18|   17.00#
 -#           6#         17|   16.00#
 -#  ----------#-----------+--------#
 -#    Lowest 1#          1|    1.00#
 -#           2#          2|    2.00#
 -#           3#          4|    3.00#
 -#           4#          3|    3.00#
 -#           5#          3|    3.00#
 -#           6#          5|    4.00#
 -#============#===========#========#
 +#============#===========#=====#
 +#            #Case Number|Value#
 +#============#===========#=====#
 +#V1 Highest 1#         21|20.00#
 +#           2#         20|19.00#
 +#           3#         19|18.00#
 +#           4#         19|18.00#
 +#           5#         18|17.00#
 +#           6#         17|16.00#
 +#  ----------#-----------+-----#
 +#    Lowest 1#          1| 1.00#
 +#           2#          2| 2.00#
 +#           3#          3| 3.00#
 +#           4#          3| 3.00#
 +#           5#          4| 3.00#
 +#           6#          5| 4.00#
 +#============#===========#=====#
  EOF
  if [ $? -ne 0 ] ; then fail ; fi
  
index 095ee0fb93987fcc9735139c39618780c61acabd,6468e8143e4fb37f36d6b0be09f27003be4c1ce4..11534385ce509ff3f8f5153aa6cb88c09b0cfd0e
@@@ -116,147 -116,147 +116,147 @@@ diff -b  $TEMPDIR/pspp.list - << EO
  +--------+------+
  Case#  QUALITY        W    BRAND
  ----- -------- -------- --------
-     1     3.00     1.00     1.00
-     2     2.00     2.00     1.00
-     3     1.00     2.00     1.00
-     4     1.00     1.00     1.00
-     5     4.00     1.00     1.00
-     6     4.00     1.00     1.00
-     7     5.00     1.00     2.00
-     8     2.00     1.00     2.00
-     9     4.00     4.00     2.00
-    10     2.00     1.00     2.00
-    11     3.00     1.00     2.00
-    12     7.00     1.00     3.00
-    13     4.00     2.00     3.00
-    14     5.00     3.00     3.00
-    15     3.00     1.00     3.00
-    16     6.00     1.00     3.00
+     1     3.00     1.00     1.00 
+     2     2.00     2.00     1.00 
+     3     1.00     2.00     1.00 
+     4     1.00     1.00     1.00 
+     5     4.00     1.00     1.00 
+     6     4.00     1.00     1.00 
+     7     5.00     1.00     2.00 
+     8     2.00     1.00     2.00 
+     9     4.00     4.00     2.00 
+    10     2.00     1.00     2.00 
+    11     3.00     1.00     2.00 
+    12     7.00     1.00     3.00 
+    13     4.00     2.00     3.00 
+    14     5.00     3.00     3.00 
+    15     3.00     1.00     3.00 
+    16     6.00     1.00     3.00 
  2.1 EXAMINE.  Case Processing Summary
- #===============#===============================#
- #               #             Cases             #
- #               #----------+---------+----------#
- #               #   Valid  | Missing |   Total  #
- #               #--+-------+-+-------+--+-------#
- #               # N|Percent|N|Percent| N|Percent#
- #===============#==#=======#=#=======#==#=======#
- #Breaking Strain#24|   100%|0|     0%|24|   100%#
- #===============#==#=======#=#=======#==#=======#
+ #===============#=======================================#
+ #               #                 Cases                 #
+ #               #-------------+-----------+-------------#
+ #               #    Valid    |  Missing  |    Total    #
+ #               #-----+-------+---+-------+-----+-------#
+ #               #  N  |Percent| N |Percent|  N  |Percent#
+ #===============#=====#=======#===#=======#=====#=======#
+ #Breaking Strain#24.00|   100%|.00|     0%|24.00|   100%#
+ #===============#=====#=======#===#=======#=====#=======#
  2.2 EXAMINE.  Extreme Values
 -#=========================#===========#========#
 -#                         #Case Number|  Value #
 -#=========================#===========#========#
 -#Breaking Strain Highest 1#         12|    7.00#
 -#                        2#         16|    6.00#
 -#                        3#         14|    5.00#
 -#               ----------#-----------+--------#
 -#                 Lowest 1#          4|    1.00#
 -#                        2#          3|    1.00#
 -#                        3#          3|    1.00#
 -#=========================#===========#========#
 +#=========================#===========#=====#
 +#                         #Case Number|Value#
 +#=========================#===========#=====#
 +#Breaking Strain Highest 1#         12| 7.00#
 +#                        2#         16| 6.00#
 +#                              3#          7| 5.00#
 +#               ----------#-----------+-----#
 +#                 Lowest 1#          3| 1.00#
 +#                        2#          3| 1.00#
 +#                        3#          4| 1.00#
 +#=========================#===========#=====#
  2.3 EXAMINE.  Descriptives
  #============================================================#=========#==========#
  #                                                            #Statistic|Std. Error#
  #============================================================#=========#==========#
- #Breaking Strain Mean                                        #   3.54  |   .324   #
- #                95% Confidence Interval for Mean Lower Bound#  2.871  |          #
- #                                                 Upper Bound#  4.212  |          #
+ #Breaking Strain Mean                                        #   3.54  |    .32   #
+ #                95% Confidence Interval for Mean Lower Bound#   2.87  |          #
+ #                                                 Upper Bound#   4.21  |          #
  #                5% Trimmed Mean                             #   3.50  |          #
  #                Median                                      #   4.00  |          #
- #                Variance                                    #  2.520  |          #
- #                Std. Deviation                              #  1.587  |          #
- #                Minimum                                     #  1.000  |          #
- #                Maximum                                     #  7.000  |          #
- #                Range                                       #  6.000  |          #
+ #                Variance                                    #   2.52  |          #
+ #                Std. Deviation                              #   1.59  |          #
+ #                Minimum                                     #   1.00  |          #
+ #                Maximum                                     #   7.00  |          #
+ #                Range                                       #   6.00  |          #
  #                Interquartile Range                         #   2.75  |          #
- #                Skewness                                    #   .059  |   .472   #
- #                Kurtosis                                    #  -.358  |   .918   #
+ #                Skewness                                    #   .06   |    .47   #
+ #                Kurtosis                                    #   -.36  |    .92   #
  #============================================================#=========#==========#
  2.4 EXAMINE.  Case Processing Summary
- #============================#=============================#
- #                            #            Cases            #
- #                            #---------+---------+---------#
- #                            #  Valid  | Missing |  Total  #
- #                            #-+-------+-+-------+-+-------#
- #                Manufacturer#N|Percent|N|Percent|N|Percent#
- #============================#=#=======#=#=======#=#=======#
- #Breaking Strain Aspeger     #8|   100%|0|     0%|8|   100%#
- #                Bloggs      #8|   100%|0|     0%|8|   100%#
- #                Charlies    #8|   100%|0|     0%|8|   100%#
- #============================#=#=======#=#=======#=#=======#
+ #============================#=====================================#
+ #                            #                Cases                #
+ #                            #------------+-----------+------------#
+ #                            #    Valid   |  Missing  |    Total   #
+ #                            #----+-------+---+-------+----+-------#
+ #                Manufacturer#  N |Percent| N |Percent|  N |Percent#
+ #============================#====#=======#===#=======#====#=======#
+ #Breaking Strain Aspeger     #8.00|   100%|.00|     0%|8.00|   100%#
+ #                Bloggs      #8.00|   100%|.00|     0%|8.00|   100%#
+ #                Charlies    #8.00|   100%|.00|     0%|8.00|   100%#
+ #============================#====#=======#===#=======#====#=======#
  2.5 EXAMINE.  Extreme Values
 -#======================================#===========#========#
 -#                Manufacturer          #Case Number|  Value #
 -#======================================#===========#========#
 -#Breaking Strain Aspeger      Highest 1#          6|    4.00#
 -#                                     2#          5|    4.00#
 -#                                     3#          1|    3.00#
 -#                            ----------#-----------+--------#
 -#                              Lowest 1#          4|    1.00#
 -#                                     2#          3|    1.00#
 -#                                     3#          3|    1.00#
 -#               -----------------------#-----------+--------#
 -#                Bloggs       Highest 1#          7|    5.00#
 -#                                     2#          9|    4.00#
 -#                                     3#          9|    4.00#
 -#                            ----------#-----------+--------#
 -#                              Lowest 1#         10|    2.00#
 -#                                     2#          8|    2.00#
 -#                                     3#         11|    3.00#
 -#               -----------------------#-----------+--------#
 -#                Charlies     Highest 1#         12|    7.00#
 -#                                     2#         16|    6.00#
 -#                                     3#         14|    5.00#
 -#                            ----------#-----------+--------#
 -#                              Lowest 1#         15|    3.00#
 -#                                     2#         13|    4.00#
 -#                                     3#         13|    4.00#
 -#======================================#===========#========#
 +#======================================#===========#=====#
 +#                Manufacturer          #Case Number|Value#
 +#======================================#===========#=====#
 +#Breaking Strain Aspeger      Highest 1#          5| 4.00#
 +#                                     2#          6| 4.00#
 +#                                     3#          1| 3.00#
 +#                            ----------#-----------+-----#
 +#                              Lowest 1#          3| 1.00#
 +#                                     2#          3| 1.00#
 +#                                     3#          4| 1.00#
 +#               -----------------------#-----------+-----#
 +#                Bloggs       Highest 1#          7| 5.00#
 +#                                     2#          9| 4.00#
 +#                                     3#          9| 4.00#
 +#                            ----------#-----------+-----#
 +#                              Lowest 1#          8| 2.00#
 +#                                     2#         10| 2.00#
 +#                                     3#         11| 3.00#
 +#               -----------------------#-----------+-----#
 +#                      Charlies     Highest 1#         12| 7.00#
 +#                                     2#         16| 6.00#
 +#                                     3#         14| 5.00#
 +#                            ----------#-----------+-----#
 +#                              Lowest 1#         15| 3.00#
 +#                                     2#         13| 4.00#
 +#                                     3#         13| 4.00#
 +#======================================#===========#=====#
  2.6 EXAMINE.  Descriptives
  #=========================================================================#=========#==========#
- #                Manufacturer                                            #Statistic|Std. Error#
+ #                Manufacturer                                             #Statistic|Std. Error#
  #=========================================================================#=========#==========#
- #Breaking Strain Aspeger      Mean                                        #   2.25  |   .453   #
- #                             95% Confidence Interval for Mean Lower Bound#  1.178  |          #
- #                                                              Upper Bound#  3.322  |          #
+ #Breaking Strain Aspeger      Mean                                        #   2.25  |    .45   #
+ #                             95% Confidence Interval for Mean Lower Bound#   1.18  |          #
+ #                                                              Upper Bound#   3.32  |          #
  #                             5% Trimmed Mean                             #   2.22  |          #
  #                             Median                                      #   2.00  |          #
- #                             Variance                                    #  1.643  |          #
- #                             Std. Deviation                              #  1.282  |          #
- #                             Minimum                                     #  1.000  |          #
- #                             Maximum                                     #  4.000  |          #
- #                             Range                                       #  3.000  |          #
+ #                             Variance                                    #   1.64  |          #
+ #                             Std. Deviation                              #   1.28  |          #
+ #                             Minimum                                     #   1.00  |          #
+ #                             Maximum                                     #   4.00  |          #
+ #                             Range                                       #   3.00  |          #
  #                             Interquartile Range                         #   2.75  |          #
- #                             Skewness                                    #   .475  |   .752   #
- #                             Kurtosis                                    #  -1.546 |   1.481  #
+ #                             Skewness                                    #   .47   |    .75   #
+ #                             Kurtosis                                    #  -1.55  |   1.48   #
  #               ----------------------------------------------------------#---------+----------#
- #                Bloggs       Mean                                        #   3.50  |   .378   #
- #                             95% Confidence Interval for Mean Lower Bound#  2.606  |          #
- #                                                              Upper Bound#  4.394  |          #
+ #                Bloggs       Mean                                        #   3.50  |    .38   #
+ #                             95% Confidence Interval for Mean Lower Bound#   2.61  |          #
+ #                                                              Upper Bound#   4.39  |          #
  #                             5% Trimmed Mean                             #   3.50  |          #
  #                             Median                                      #   4.00  |          #
- #                             Variance                                    #  1.143  |          #
- #                             Std. Deviation                              #  1.069  |          #
- #                             Minimum                                     #  2.000  |          #
- #                             Maximum                                     #  5.000  |          #
- #                             Range                                       #  3.000  |          #
+ #                             Variance                                    #   1.14  |          #
+ #                             Std. Deviation                              #   1.07  |          #
+ #                             Minimum                                     #   2.00  |          #
+ #                             Maximum                                     #   5.00  |          #
+ #                             Range                                       #   3.00  |          #
  #                             Interquartile Range                         #   1.75  |          #
- #                             Skewness                                    #  -.468  |   .752   #
- #                             Kurtosis                                    #  -.831  |   1.481  #
+ #                             Skewness                                    #   -.47  |    .75   #
+ #                             Kurtosis                                    #   -.83  |   1.48   #
  #               ----------------------------------------------------------#---------+----------#
- #                Charlies     Mean                                        #   4.88  |   .441   #
- #                             95% Confidence Interval for Mean Lower Bound#  3.833  |          #
- #                                                              Upper Bound#  5.917  |          #
+ #                Charlies     Mean                                        #   4.88  |    .44   #
+ #                             95% Confidence Interval for Mean Lower Bound#   3.83  |          #
+ #                                                              Upper Bound#   5.92  |          #
  #                             5% Trimmed Mean                             #   4.86  |          #
  #                             Median                                      #   5.00  |          #
- #                             Variance                                    #  1.554  |          #
- #                             Std. Deviation                              #  1.246  |          #
- #                             Minimum                                     #  3.000  |          #
- #                             Maximum                                     #  7.000  |          #
- #                             Range                                       #  4.000  |          #
+ #                             Variance                                    #   1.55  |          #
+ #                             Std. Deviation                              #   1.25  |          #
+ #                             Minimum                                     #   3.00  |          #
+ #                             Maximum                                     #   7.00  |          #
+ #                             Range                                       #   4.00  |          #
  #                             Interquartile Range                         #   1.75  |          #
- #                             Skewness                                    #   .304  |   .752   #
- #                             Kurtosis                                    #   .146  |   1.481  #
+ #                             Skewness                                    #   .30   |    .75   #
+ #                             Kurtosis                                    #   .15   |   1.48   #
  #=========================================================================#=========#==========#
  EOF
  if [ $? -ne 0 ] ; then fail ; fi
index 29ad2fab86f90558f692cefbd5a26d1b1502058e,439398e2172e02d24ff4e5eacafff5e22d1404ef..0db048dd34703054bd88b7da91a17f81ae579812
@@@ -251,103 -225,85 +255,103 @@@ perl -pi -e 's/^\s*$//g' $TEMPDIR/pspp.
  diff -b $TEMPDIR/pspp.list - << EOF
  P < 0.5; N1/N2 < 1
  1.1 NPAR TESTS.  Binomial Test
- +-+------#--------+--+--------------+----------+---------------------+
- | |      #Category| N|Observed Prop.|Test Prop.|Exact Sig. (1-tailed)|
- +-+------#--------+--+--------------+----------+---------------------+
- |x|Group1#    1.00| 6|          .286|      .300|                 .551|
- | |Group2#    2.00|15|          .714|          |                     |
- | |Total #        |21|          1.00|          |                     |
- +-+------#--------+--+--------------+----------+---------------------+
+ +-+------#--------+-----+--------------+----------+---------------------+
+ | |      #Category|  N  |Observed Prop.|Test Prop.|Exact Sig. (1-tailed)|
+ +-+------#--------+-----+--------------+----------+---------------------+
+ |x|Group1#    1.00| 6.00|          .286|      .300|                 .551|
+ | |Group2#    2.00|15.00|          .714|          |                     |
 -| |Total #        |21.00|          1.00|          |                     |
++| |Total #        |21.00|         1.000|          |                     |
+ +-+------#--------+-----+--------------+----------+---------------------+
  P < 0.5; N1/N2 > 1
  2.1 NPAR TESTS.  Binomial Test
  +-+------#--------+--+--------------+----------+---------------------+
  | |      #Category| N|Observed Prop.|Test Prop.|Exact Sig. (1-tailed)|
  +-+------#--------+--+--------------+----------+---------------------+
- |x|Group1#    1.00| 7|          .538|      .400|                 .229|
- | |Group2#    2.00| 6|          .462|          |                     |
- | |Total #        |13|          1.00|          |                     |
+ |x|Group1#       1| 7|          .538|      .400|                 .229|
+ | |Group2#       2| 6|          .462|          |                     |
 -| |Total #        |13|             1|          |                     |
++| |Total #        |13|         1.000|          |                     |
  +-+------#--------+--+--------------+----------+---------------------+
  P < 0.5; N1/N2 = 1
  3.1 NPAR TESTS.  Binomial Test
  +-+------#--------+--+--------------+----------+---------------------+
  | |      #Category| N|Observed Prop.|Test Prop.|Exact Sig. (1-tailed)|
  +-+------#--------+--+--------------+----------+---------------------+
- |x|Group1#    1.00| 8|          .500|      .400|                 .284|
- | |Group2#    2.00| 8|          .500|          |                     |
- | |Total #        |16|          1.00|          |                     |
+ |x|Group1#       1| 8|          .500|      .400|                 .284|
+ | |Group2#       2| 8|          .500|          |                     |
 -| |Total #        |16|             1|          |                     |
++| |Total #        |16|         1.000|          |                     |
  +-+------#--------+--+--------------+----------+---------------------+
  P > 0.5; N1/N2 < 1
  4.1 NPAR TESTS.  Binomial Test
  +-+------#--------+--+--------------+----------+---------------------+
  | |      #Category| N|Observed Prop.|Test Prop.|Exact Sig. (1-tailed)|
  +-+------#--------+--+--------------+----------+---------------------+
- |x|Group1#    1.00|11|          .478|      .600|                 .164|
- | |Group2#    2.00|12|          .522|          |                     |
- | |Total #        |23|          1.00|          |                     |
+ |x|Group1#       1|11|          .478|      .600|                 .164|
+ | |Group2#       2|12|          .522|          |                     |
 -| |Total #        |23|             1|          |                     |
++| |Total #        |23|         1.000|          |                     |
  +-+------#--------+--+--------------+----------+---------------------+
  P > 0.5; N1/N2 > 1
  5.1 NPAR TESTS.  Binomial Test
  +-+------#--------+--+--------------+----------+---------------------+
  | |      #Category| N|Observed Prop.|Test Prop.|Exact Sig. (1-tailed)|
  +-+------#--------+--+--------------+----------+---------------------+
- |x|Group1#    1.00|11|          .550|      .600|                 .404|
- | |Group2#    2.00| 9|          .450|          |                     |
- | |Total #        |20|          1.00|          |                     |
+ |x|Group1#       1|11|          .550|      .600|                 .404|
+ | |Group2#       2| 9|          .450|          |                     |
 -| |Total #        |20|             1|          |                     |
++| |Total #        |20|         1.000|          |                     |
  +-+------#--------+--+--------------+----------+---------------------+
  P > 0.5; N1/N2 == 1
  6.1 NPAR TESTS.  Binomial Test
  +-+------#--------+--+--------------+----------+---------------------+
  | |      #Category| N|Observed Prop.|Test Prop.|Exact Sig. (1-tailed)|
  +-+------#--------+--+--------------+----------+---------------------+
- |x|Group1#    1.00|11|          .500|      .600|                 .228|
- | |Group2#    2.00|11|          .500|          |                     |
- | |Total #        |22|          1.00|          |                     |
+ |x|Group1#       1|11|          .500|      .600|                 .228|
+ | |Group2#       2|11|          .500|          |                     |
 -| |Total #        |22|             1|          |                     |
++| |Total #        |22|         1.000|          |                     |
  +-+------#--------+--+--------------+----------+---------------------+
  P == 0.5; N1/N2 < 1
  7.1 NPAR TESTS.  Binomial Test
  +-+------#--------+--+--------------+----------+---------------------+
  | |      #Category| N|Observed Prop.|Test Prop.|Exact Sig. (2-tailed)|
  +-+------#--------+--+--------------+----------+---------------------+
- |x|Group1#    1.00| 8|          .348|      .500|                 .210|
- | |Group2#    2.00|15|          .652|          |                     |
- | |Total #        |23|          1.00|          |                     |
+ |x|Group1#       1| 8|          .348|      .500|                 .210|
+ | |Group2#       2|15|          .652|          |                     |
 -| |Total #        |23|             1|          |                     |
++| |Total #        |23|         1.000|          |                     |
  +-+------#--------+--+--------------+----------+---------------------+
  P == 0.5; N1/N2 > 1
  8.1 NPAR TESTS.  Binomial Test
  +-+------#--------+--+--------------+----------+---------------------+
  | |      #Category| N|Observed Prop.|Test Prop.|Exact Sig. (2-tailed)|
  +-+------#--------+--+--------------+----------+---------------------+
- |x|Group1#    1.00|12|          .667|      .500|                 .238|
- | |Group2#    2.00| 6|          .333|          |                     |
- | |Total #        |18|          1.00|          |                     |
+ |x|Group1#       1|12|          .667|      .500|                 .238|
+ | |Group2#       2| 6|          .333|          |                     |
 -| |Total #        |18|             1|          |                     |
++| |Total #        |18|         1.000|          |                     |
  +-+------#--------+--+--------------+----------+---------------------+
  P == 0.5; N1/N2 == 1
  9.1 NPAR TESTS.  Binomial Test
  +-+------#--------+--+--------------+----------+---------------------+
  | |      #Category| N|Observed Prop.|Test Prop.|Exact Sig. (2-tailed)|
  +-+------#--------+--+--------------+----------+---------------------+
- |x|Group1#    1.00|10|          .500|      .500|                1.000|
- | |Group2#    2.00|10|          .500|          |                     |
- | |Total #        |20|          1.00|          |                     |
+ |x|Group1#       1|10|          .500|      .500|                1.000|
+ | |Group2#       2|10|          .500|          |                     |
 -| |Total #        |20|             1|          |                     |
++| |Total #        |20|         1.000|          |                     |
  +-+------#--------+--+--------------+----------+---------------------+
- +-+------#--------+--+--------------+----------+---------------------+
- | |      #Category| N|Observed Prop.|Test Prop.|Exact Sig. (2-tailed)|
- +-+------#--------+--+--------------+----------+---------------------+
- |x|Group1#   <= 10|10|          .385|      .500|                 .327|
- | |Group2#        |16|          .615|          |                     |
- | |Total #        |26|          1.00|          |                     |
- +-+------#--------+--+--------------+----------+---------------------+
 +P == 0.5; N1/N2 == 1 Cutpoint
 +10.1 NPAR TESTS.  Binomial Test
- +-+------#--------+--+--------------+----------+---------------------+
- | |      #Category| N|Observed Prop.|Test Prop.|Exact Sig. (2-tailed)|
- +-+------#--------+--+--------------+----------+---------------------+
- |x|Group1#   10.00|10|          .435|      .500|                 .678|
- | |Group2#   20.00|13|          .565|          |                     |
- | |Total #        |23|          1.00|          |                     |
- +-+------#--------+--+--------------+----------+---------------------+
+++-+------#--------+------+--------------+----------+---------------------+
++| |      #Category|   N  |Observed Prop.|Test Prop.|Exact Sig. (2-tailed)|
+++-+------#--------+------+--------------+----------+---------------------+
++|x|Group1#   <= 10|10.000|          .385|      .500|                 .327|
++| |Group2#        |16.000|          .615|          |                     |
++| |Total #        |26.000|         1.000|          |                     |
+++-+------#--------+------+--------------+----------+---------------------+
 +P == 0.5; N1/N2 == 1 Named values
 +11.1 NPAR TESTS.  Binomial Test
+++-+------#--------+------+--------------+----------+---------------------+
++| |      #Category|   N  |Observed Prop.|Test Prop.|Exact Sig. (2-tailed)|
+++-+------#--------+------+--------------+----------+---------------------+
++|x|Group1#  10.000|10.000|          .435|      .500|                 .678|
++| |Group2#  20.000|13.000|          .565|          |                     |
++| |Total #        |23.000|         1.000|          |                     |
+++-+------#--------+------+--------------+----------+---------------------+
  EOF
  if [ $? -ne 0 ] ; then fail ; fi
  
index c4a5d825f4895daff1035d489daeb82e7b9a094c,0000000000000000000000000000000000000000..ae0d39fcba50afedfa9c7f66db21af4310387d96
mode 100755,000000..100755
--- /dev/null
@@@ -1,174 -1,0 +1,173 @@@
- data list notable list /foo * bar * w *.
 +#!/bin/sh
 +
 +# This program tests the wilcoxon subcommand of npar tests
 +
 +TEMPDIR=/tmp/pspp-tst-$$
 +TESTFILE=$TEMPDIR/`basename $0`.sps
 +
 +# ensure that top_srcdir and top_builddir  are absolute
 +if [ -z "$top_srcdir" ] ; then top_srcdir=. ; fi
 +if [ -z "$top_builddir" ] ; then top_builddir=. ; fi
 +top_srcdir=`cd $top_srcdir; pwd`
 +top_builddir=`cd $top_builddir; pwd`
 +
 +PSPP=$top_builddir/src/ui/terminal/pspp
 +
 +STAT_CONFIG_PATH=$top_srcdir/config
 +export STAT_CONFIG_PATH
 +
 +LANG=C
 +export LANG
 +
 +
 +cleanup()
 +{
 +     if [ x"$PSPP_TEST_NO_CLEANUP" != x ] ; then 
 +      echo "NOT cleaning $TEMPDIR"
 +      return ; 
 +     fi
 +     rm -rf $TEMPDIR
 +}
 +
 +
 +fail()
 +{
 +    echo $activity
 +    echo FAILED
 +    cleanup;
 +    exit 1;
 +}
 +
 +
 +no_result()
 +{
 +    echo $activity
 +    echo NO RESULT;
 +    cleanup;
 +    exit 2;
 +}
 +
 +pass()
 +{
 +    cleanup;
 +    exit 0;
 +}
 +
 +mkdir -p $TEMPDIR
 +
 +cd $TEMPDIR
 +
 +activity="create program 1"
 +cat > $TESTFILE <<  EOF
++data list notable list /foo * bar * w (f8.0).
 +begin data.
 +1.00     1.00   1
 +1.00     2.00   1
 +2.00     1.00   1
 +1.00     4.00   1
 +2.00     5.00   1
 +1.00    19.00   1
 +2.00     7.00   1
 +4.00     5.00   1
 +1.00    12.00   1
 +2.00    13.00   1
 +2.00     2.00   1
 +12.00      .00  2
 +12.00     1.00  1
 +13.00     1.00  1
 +end data
 +
 +variable labels foo "first" bar "second".
 +
 +weight by w.
 +
 +npar test
 + /wilcoxon=foo with bar (paired)
 + /missing analysis
 + /method=exact.
 +
 +EOF
 +if [ $? -ne 0 ] ; then no_result ; fi
 +
 +
 +activity="run program 1"
 +$SUPERVISOR $PSPP --testing-mode -o raw-ascii $TESTFILE
 +if [ $? -ne 0 ] ; then no_result ; fi
 +
- #Z                    #         -.175#
- #Asymp. Sig (2-tailed)#          .861#
- #Exact Sig (2-tailed) #          .893#
- #Exact Sig (1-tailed) #          .446#
 +activity="generate results"
 +cat > $TEMPDIR/results.txt <<EOF
 +1.1 NPAR TESTS.  Ranks
 +#============================#==#=========#============#
 +#                            # N|Mean Rank|Sum of Ranks#
 +#============================#==#=========#============#
 +#second - firstNegative Ranks# 5|     8.60|       43.00#
 +#              Positive Ranks# 8|     6.00|       48.00#
 +#              Ties          # 2|         |            #
 +#              Total         #15|         |            #
 +#============================#==#=========#============#
 +
 +1.2 NPAR TESTS.  Test Statistics
 +#=====================#==============#
 +#                     #second - first#
 +#=====================#==============#
++#Z                    #          -.18#
++#Asymp. Sig (2-tailed)#           .86#
++#Exact Sig (2-tailed) #           .89#
++#Exact Sig (1-tailed) #           .45#
 +#=====================#==============#
 +
 +EOF
 +if [ $? -ne 0 ] ; then no_result ; fi
 +
 +
 +activity="compare output 1"
 +diff pspp.list $TEMPDIR/results.txt
 +if [ $? -ne 0 ] ; then fail ; fi
 +
 +
++
 +# No weights this time. But some missing values
 +activity="create program 2"
 +cat > $TESTFILE <<  EOF
 +data list notable list /foo * bar * dummy *.
 +begin data.
 +1.00     1.00    1
 +1.00     2.00    1
 +2.00     1.00    1
 +1.00     4.00    .
 +2.00     5.00    .
 +1.00    19.00    .
 +2.00     7.00    1
 +4.00     5.00    1
 +1.00    12.00    1
 +2.00    13.00    1
 +2.00     2.00    1
 +12.00      .00   1
 +12.00      .00   1
 +34.2       .     1
 +12.00     1.00   1  
 +13.00     1.00   1
 +end data
 +
 +variable labels foo "first" bar "second".
 +
 +npar test
 + /wilcoxon=foo with bar (paired)
 + /missing analysis
 + /method=exact.
 +
 +EOF
 +if [ $? -ne 0 ] ; then no_result ; fi
 +
 +
 +activity="run program 2"
 +$SUPERVISOR $PSPP --testing-mode -o raw-ascii $TESTFILE
 +if [ $? -ne 0 ] ; then no_result ; fi
 +
 +activity="compare output 2"
 +diff pspp.list $TEMPDIR/results.txt
 +if [ $? -ne 0 ] ; then fail ; fi
 +
 +
 +
 +pass;
index 0bfa7336b23e7b43ca71070b3debf8c3a6e920af,0000000000000000000000000000000000000000..ed4b4b854c4a67f416be869d0705b8839fda9318
mode 100755,000000..100755
--- /dev/null
@@@ -1,345 -1,0 +1,345 @@@
- #==============#===#=====#
- #              # N |  %  #
- #==============#===#=====#
- #Cases Valid   #131| 92.9#
- #      Excluded# 10|  7.1#
- #      Total   #141|100.0#
- #==============#===#=====#
 +#!/bin/sh
 +
 +# This program tests the reliability command.
 +
 +TEMPDIR=/tmp/pspp-tst-$$
 +TESTFILE=$TEMPDIR/`basename $0`.sps
 +
 +# ensure that top_srcdir and top_builddir  are absolute
 +if [ -z "$top_srcdir" ] ; then top_srcdir=. ; fi
 +if [ -z "$top_builddir" ] ; then top_builddir=. ; fi
 +top_srcdir=`cd $top_srcdir; pwd`
 +top_builddir=`cd $top_builddir; pwd`
 +
 +PSPP=$top_builddir/src/ui/terminal/pspp
 +
 +STAT_CONFIG_PATH=$top_srcdir/config
 +export STAT_CONFIG_PATH
 +
 +LANG=C
 +export LANG
 +
 +
 +cleanup()
 +{
 +     if [ x"$PSPP_TEST_NO_CLEANUP" != x ] ; then 
 +      echo "NOT cleaning $TEMPDIR"
 +      return ; 
 +     fi
 +     rm -rf $TEMPDIR
 +}
 +
 +
 +fail()
 +{
 +    echo $activity
 +    echo FAILED
 +    cleanup;
 +    exit 1;
 +}
 +
 +
 +no_result()
 +{
 +    echo $activity
 +    echo NO RESULT;
 +    cleanup;
 +    exit 2;
 +}
 +
 +pass()
 +{
 +    cleanup;
 +    exit 0;
 +}
 +
 +mkdir -p $TEMPDIR
 +
 +cd $TEMPDIR
 +
 +
 +activity="create program"
 +cat > $TESTFILE <<EOF
 +
 +data list notable list  /var1 *
 +      var2  *
 +      var6  *
 +      var7  *
 +      var8  *
 +      var9  *
 +      var11 *
 +      var12 *
 +      var15 *
 +      var16 *
 +      var17 *
 +      var19 *
 +      .
 +
 +begin data.
 +6 7 7 5 7 7 7 7 7 7 6 6
 +6 7 7 6 7 6 7 5 6 5 7 7
 +6 6 7 6 5 3 6 4 5 6 4 5
 +4 6 5 6 6 5 4 3 5 6 5 6
 +5 6 5 5 6 5 4 4 6 6 5 5
 +6 6 7 6 6 5 6 5 6 6 5 6
 +5 6 6 5 6 5 5 4 6 5 5 5
 +5 7 7 7 7 7 6 5 7 7 7 7
 +6 6 6 5 5 7 6 5 6 6 5 6
 +. . . . . . . . . . . .
 +6 6 5 5 5 6 6 4 6 5 5 5
 +7 7 7 6 7 6 7 6 6 6 7 6
 +4 7 6 6 6 5 5 4 4 5 5 6
 +5 6 3 5 4 1 4 6 2 3 3 2
 +3 6 6 5 6 2 4 2 2 4 4 5
 +6 6 7 5 6 5 7 6 5 6 6 5
 +6 5 6 6 5 6 6 6 6 4 5 5
 +5 7 7 . 6 6 6 5 6 6 6 6
 +5 7 5 5 4 6 7 6 5 4 6 5
 +7 7 7 6 7 7 7 6 7 7 7 6
 +3 6 5 6 5 7 7 3 4 7 5 7
 +6 7 7 6 5 6 5 5 6 6 6 6
 +5 5 6 5 5 5 5 4 5 5 5 6
 +6 6 7 4 5 6 6 6 6 5 5 6
 +6 5 6 6 4 4 5 4 5 6 4 5
 +5 6 7 6 6 7 7 5 6 6 6 5
 +5 6 5 7 4 6 6 5 7 7 5 6
 +. . . . . . . . . . . .
 +7 6 6 5 6 6 7 6 6 5 5 6
 +6 6 7 7 7 7 7 6 7 6 6 7
 +7 5 5 . 5 . 7 3 5 4 5 3
 +7 6 7 5 4 5 7 5 7 5 5 6
 +6 5 6 6 6 5 5 5 5 6 5 6
 +7 7 7 7 7 7 7 7 5 6 7 7
 +. . . . . . . . . . . .
 +5 5 6 7 5 6 6 4 6 6 6 5
 +6 6 5 7 5 6 7 5 6 5 4 6
 +7 6 7 6 7 5 6 7 7 6 6 6
 +5 6 5 6 5 6 7 2 5 7 3 7
 +6 6 5 6 5 6 6 6 6 6 5 6
 +7 6 7 6 6 6 6 6 6 7 6 7
 +7 7 6 5 6 6 7 7 7 4 6 5
 +3 7 7 6 6 7 7 7 6 6 6 4
 +3 5 3 4 3 3 3 3 3 3 3 5
 +5 7 7 7 5 7 6 2 6 7 6 7
 +7 7 7 7 7 7 7 6 7 7 7 6
 +6 5 7 4 4 4 5 6 5 5 4 5
 +4 7 7 4 4 3 6 3 5 3 4 5
 +7 7 7 7 7 7 7 7 7 7 7 5
 +3 6 5 5 4 5 4 4 5 5 3 5
 +6 7 6 6 6 7 7 6 6 6 7 6
 +2 5 4 6 3 2 2 2 2 7 2 2
 +4 6 6 5 5 5 6 5 5 6 6 5
 +5 7 4 5 6 6 6 5 6 6 5 6
 +5 7 7 5 6 5 6 5 5 4 5 4
 +4 5 6 5 6 4 5 5 5 4 5 5
 +7 6 6 5 5 6 7 5 6 5 7 6
 +5 6 6 5 4 5 5 3 4 5 5 5
 +5 7 6 4 4 5 6 5 6 4 4 6
 +6 6 6 6 5 7 7 6 5 5 6 6
 +6 6 7 6 7 6 6 5 6 7 6 5
 +7 6 7 6 7 6 7 7 5 5 6 6
 +5 6 6 5 5 5 6 5 6 7 7 5
 +5 6 6 5 6 5 6 6 6 6 6 6
 +5 5 5 5 6 4 5 3 4 7 6 5
 +5 7 7 6 6 6 6 5 6 7 6 7
 +6 6 7 7 7 5 6 5 5 5 5 4
 +2 7 5 4 6 5 5 2 5 6 4 6
 +6 7 7 5 6 6 7 6 6 7 5 7
 +5 6 7 6 6 3 5 7 6 6 5 6
 +6 6 6 3 5 5 5 6 6 6 4 5
 +4 7 7 4 7 4 5 5 5 7 4 4
 +. . . . . . . . . . . .
 +6 6 7 6 7 6 7 7 6 7 7 6
 +. . . . . . . . . . . .
 +5 6 5 7 6 5 6 6 5 6 4 6
 +5 5 5 5 4 5 5 5 7 5 5 5
 +6 6 6 4 5 4 6 6 6 4 5 4
 +6 5 7 4 6 4 6 5 6 6 6 3
 +5 7 6 5 5 5 5 5 6 7 6 6
 +5 5 7 7 5 5 6 6 5 5 5 7
 +5 6 7 6 7 5 6 4 6 7 6 7
 +4 5 5 5 6 5 6 5 6 6 5 6
 +6 5 5 5 6 3 4 5 5 4 5 3
 +6 6 6 5 5 5 4 3 4 5 5 5
 +6 7 7 6 2 3 6 6 6 5 7 7
 +6 7 5 5 6 6 6 5 6 6 6 6
 +6 7 7 6 7 7 7 5 5 6 6 6
 +6 6 6 6 7 6 6 7 6 6 6 6
 +5 6 6 6 3 5 6 6 5 5 4 6
 +4 6 5 6 6 5 6 5 6 6 5 5
 +6 4 6 5 4 6 7 4 5 6 5 5
 +6 7 6 4 6 5 7 6 7 7 6 5
 +6 7 7 6 7 6 7 7 7 6 6 6
 +6 6 6 4 5 6 7 7 5 6 4 4
 +3 3 5 3 3 1 5 6 3 2 3 3
 +7 7 5 6 6 7 7 6 7 7 7 7
 +5 6 6 6 7 5 4 5 4 7 6 7
 +3 6 5 4 3 3 3 5 5 6 3 4
 +5 7 6 4 6 5 5 6 6 7 5 6
 +5 7 6 6 6 6 6 5 6 7 7 6
 +7 7 5 6 7 7 7 7 6 5 7 7
 +6 7 6 6 5 6 7 7 6 5 6 6
 +6 7 7 7 7 6 6 7 6 7 7 7
 +4 6 4 7 3 6 5 5 4 3 5 6
 +5 5 7 5 4 6 7 5 4 6 6 5
 +5 5 6 4 6 5 7 6 5 5 5 6
 +. . . . . . . . . . . .
 +. . . . . . . . . . . .
 +5 7 7 5 6 6 7 7 6 6 6 7
 +6 7 7 1 2 1 7 7 5 5 5 2
 +. . . . . . . . . . . .
 +3 7 4 6 4 7 4 6 4 7 4 7
 +5 7 3 5 5 6 7 5 4 7 7 4
 +4 7 7 5 4 6 7 7 6 5 4 4
 +6 6 2 2 6 4 6 5 5 1 5 2
 +5 5 6 4 5 4 6 5 5 6 5 5
 +. . . . . . . . . . . .
 +5 7 6 6 6 6 6 6 5 6 6 6
 +6 6 6 5 6 6 6 6 7 5 6 7
 +3 6 3 3 5 3 3 5 3 5 7 4
 +4 4 6 3 3 3 4 3 4 2 3 6
 +5 7 7 6 5 4 7 5 7 7 3 7
 +4 5 4 4 4 4 3 3 3 4 3 3
 +6 7 7 5 6 6 7 5 4 5 5 5
 +3 5 3 3 1 3 4 3 4 7 6 7
 +4 5 4 4 4 3 4 5 6 6 4 5
 +5 6 3 4 5 3 5 3 4 5 6 4
 +5 5 5 6 6 6 6 4 5 6 6 5
 +6 7 7 2 2 6 7 7 7 7 5 7
 +5 7 7 4 6 5 7 5 5 5 6 6
 +6 6 7 7 5 5 5 7 6 7 7 7
 +6 5 7 3 6 5 6 5 5 6 5 4
 +5 7 6 5 6 6 6 5 6 5 5 6
 +4 5 5 5 6 3 5 3 3 6 5 5
 +. . . . . . . . . . . .
 +5 6 6 4 4 4 5 3 5 5 2 6
 +5 6 7 5 5 6 6 5 5 6 6 6
 +6 7 7 6 4 7 7 6 7 5 6 7
 +6 6 5 4 5 2 7 6 6 5 6 6
 +2 2 2 2 2 2 3 2 3 1 1 2
 +end data.
 +
 +RELIABILITY
 +  /VARIABLES=var2 var8 var15 var17 var6
 +  /SCALE('Everything') var6 var8 var15 var17
 +  /MODEL=ALPHA.
 +
 +RELIABILITY
 +  /VARIABLES=var6 var8 var15 var17
 +  /SCALE('Nothing') ALL
 +  /MODEL=SPLIT(2)
 + .
 +
 +RELIABILITY
 +  /VARIABLES=var2 var6 var8 var15 var17 var19
 +  /SCALE('Totals') var6 var8 var15 var17 
 +  /SUMMARY = total
 + .
 +
 +
 +RELIABILITY
 +  /VARIABLES=var6 var8 var15 var17 
 +  .
 +
 +EOF
 +if [ $? -ne 0 ] ; then no_result ; fi
 +
 +activity="run program"
 +$SUPERVISOR $PSPP --testing-mode -o raw-ascii $TESTFILE
 +if [ $? -ne 0 ] ; then no_result ; fi
 +
 +activity="compare output"
 +diff pspp.list - << EOF
 +Scale: Everything
 +
 +1.1 RELIABILITY.  Case Processing Summary
- #            .748#         4#
++#==============#===#======#
++#              # N |   %  #
++#==============#===#======#
++#Cases Valid   #131| 92.91#
++#      Excluded# 10|  7.09#
++#      Total   #141|100.00#
++#==============#===#======#
 +
 +1.2 RELIABILITY.  Reliability Statistics
 +#================#==========#
 +#Cronbach's Alpha#N of items#
 +#================#==========#
- #==============#===#=====#
- #              # N |  %  #
- #==============#===#=====#
- #Cases Valid   #131| 92.9#
- #      Excluded# 10|  7.1#
- #      Total   #141|100.0#
- #==============#===#=====#
++#             .75#         4#
 +#================#==========#
 +
 +Scale: Nothing
 +
 +2.1 RELIABILITY.  Case Processing Summary
- #==========================================================#====#
- #Cronbach's Alpha               Part 1           Value     #.550#
- #                                                N of Items#   2#
- #                               Part 2           Value     #.631#
- #                                                N of Items#   2#
- #                               Total N of Items           #   4#
- #Correlation Between Forms                                 #.606#
- #Spearman-Brown Coefficient     Equal Length               #.755#
- #                               Unequal Length             #.755#
- #Guttman Split-Half Coefficient                            #.754#
- #==========================================================#====#
++#==============#===#======#
++#              # N |   %  #
++#==============#===#======#
++#Cases Valid   #131| 92.91#
++#      Excluded# 10|  7.09#
++#      Total   #141|100.00#
++#==============#===#======#
 +
 +2.2 RELIABILITY.  Reliability Statistics
- #==============#===#=====#
- #              # N |  %  #
- #==============#===#=====#
- #Cases Valid   #131| 92.9#
- #      Excluded# 10|  7.1#
- #      Total   #141|100.0#
- #==============#===#=====#
++#==========================================================#===#
++#Cronbach's Alpha               Part 1           Value     #.55#
++#                                                N of Items#  2#
++#                               Part 2           Value     #.63#
++#                                                N of Items#  2#
++#                               Total N of Items           #  4#
++#Correlation Between Forms                                 #.61#
++#Spearman-Brown Coefficient     Equal Length               #.75#
++#                               Unequal Length             #.75#
++#Guttman Split-Half Coefficient                            #.75#
++#==========================================================#===#
 +
 +Scale: Totals
 +
 +3.1 RELIABILITY.  Case Processing Summary
- #            .748#         4#
++#==============#===#======#
++#              # N |   %  #
++#==============#===#======#
++#Cases Valid   #131| 92.91#
++#      Excluded# 10|  7.09#
++#      Total   #141|100.00#
++#==============#===#======#
 +
 +3.2 RELIABILITY.  Reliability Statistics
 +#================#==========#
 +#Cronbach's Alpha#N of items#
 +#================#==========#
- #var6 #                    15.969|                         8.430|                            .513|                            .705#
- #var8 #                    16.565|                         7.863|                            .530|                            .698#
- #var15#                    16.473|                         8.451|                            .558|                            .682#
- #var17#                    16.603|                         7.995|                            .570|                            .673#
++#             .75#         4#
 +#================#==========#
 +
 +3.3 RELIABILITY.  Item-Total Statistics
 +#=====#==========================#==============================#================================#================================#
 +#     #Scale Mean if Item Deleted|Scale Variance if Item Deleted|Corrected Item-Total Correlation|Cronbach's Alpha if Item Deleted#
 +#=====#==========================#==============================#================================#================================#
- #==============#===#=====#
- #              # N |  %  #
- #==============#===#=====#
- #Cases Valid   #131| 92.9#
- #      Excluded# 10|  7.1#
- #      Total   #141|100.0#
- #==============#===#=====#
++#var6 #                     15.97|                          8.43|                             .51|                             .71#
++#var8 #                     16.56|                          7.86|                             .53|                             .70#
++#var15#                     16.47|                          8.45|                             .56|                             .68#
++#var17#                     16.60|                          8.00|                             .57|                             .67#
 +#=====#==========================#==============================#================================#================================#
 +
 +Scale: ANY
 +
 +4.1 RELIABILITY.  Case Processing Summary
- #            .748#         4#
++#==============#===#======#
++#              # N |   %  #
++#==============#===#======#
++#Cases Valid   #131| 92.91#
++#      Excluded# 10|  7.09#
++#      Total   #141|100.00#
++#==============#===#======#
 +
 +4.2 RELIABILITY.  Reliability Statistics
 +#================#==========#
 +#Cronbach's Alpha#N of items#
 +#================#==========#
++#             .75#         4#
 +#================#==========#
 +
 +EOF
 +if [ $? -ne 0 ] ; then fail ; fi
 +
 +
 +pass;