Please send PSPP bug reports to bug-gnu-pspp@gnu.org.
- Changes from 0.6.1 to 0.7.0:
+Changes from 0.7.1 to 0.7.2:
+
+ * Updated Perl module interface.
+
+ * Value labels for long string variables are now supported.
+
+ * Missing values for long string variables are now supported.
+
+Changes from 0.7.0 to 0.7.1:
+
+ * Added a perl module to facilitate reading and writing of pspp system
+ files from perl programs.
+
++Changes from 0.6.2-pre6 to 0.7.0:
+
+ * Custom variable and data file attributes are now supported.
+ Commands VARIABLE ATTRIBUTE and DATAFILE ATTRIBUTE have been added
+ for setting and clear attributes. Support for attributes has also
+ been added to commands that read and write system files, such as
+ SAVE and GET, as well as to the DISPLAY command.
+
+ Changes from 0.6.1 to 0.6.2-pre6:
+
+ * New translations:
+
+ - Dutch, thanks to Harry Thijssen.
+
+ - Brazilian Portuguese, thanks to Michel Boaventura.
+
+ Thanks for translations are also due to the coordinators at
+ translationproject.org.
+
+ * Statistical bug fixes:
+
+ - REGRESSION: Report correct standard error of the estimate (bug
+ #25677).
+
+ - T-TEST: Report correct significance of paired sample T-test in
+ the common case (bug #26936) and corner cases. Thanks to Mike
+ Griffiths and Matej Cepl for reporting these bugs.
+
+ * Build fixes and changes:
+
+ - Make running "make" after running "configure" with different
+ settings reliably rebuild version.c.
+
+ - Cygwin and MinGW build fixes.
+
+ - Fixes for building with recent gnulib.
+
+ - The Makefile now honors two new variables, PSPP_LDFLAGS and
+ PSPPIRE_LDFLAGS, that affect linking of the PSPP and PSPPIRE
+ binaries, respectively. This makes building easier for some
+ packagers.
+
+ - Fixes for "configure --enable-relocatable" (bug #25508).
+
+ * Data file bug fixes and changes:
+
+ - Fix reading text data files that contain a mix of white space
+ and commas. Now "a ,b" is treated as two fields containing "a"
+ and "b"; previously it was treated as three, with an empty field
+ in the middle.
+
+ - Fix writing corrupted .sav files on Windows.
+
+ - Fix writing corrupted .por files (bug #26034).
+
+ - Fix reading .por files whose initial lines are not padded out
+ with spaces as expected.
+
+ - PSPP will no longer issue warnings about some .sav file records
+ or values that it does not understand. These warnings were
+ harmless, but needlessly alarmed some users.
+
+ - Fix crash reading empty string fields from PostgreSQL databases.
+
+ * Bug fixes that affect PSPP and PSPPIRE:
+
+ - Users may now control precision of output statistics. Instead
+ of hard coding the width and decimals of output numbers, respect
+ the default format in most instances. Counts are now normally
+ displayed with the format of the weight variable, if any.
+
+ - Fix crash when an INSERT command specifies the name of a file
+ that does not exist (bug #24569).
+
+ - Fix crash when CROSSTABS specifies a long-string variable (bugs
+ #24557 and #26131).
+
+ - Fix crash drawing pie charts with many segments.
+
+ - Fix crash when NUMERIC specifies an invalid format.
+
+ * PSPPIRE bug fixes and changes:
+
+ - On Windows, write the output file to the user's home directory
+ instead of the current directory, to better match user
+ expectations.
+
+ - Some data editor fixes.
+
+ * Documentation:
+
+ - Fix typo in BINOMIAL section of user manual (bug #25892).
++>>>>>>> origin/stable:NEWS
+
Changes from 0.6.0 to 0.6.1:
* Statistical bug fixes:
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);
+ tab_text_format (tbl, n_cols - 3,
+ heading_rows + row_var_start + row_result_start + e - 1,
+ TAB_RIGHT,
+ "%d", e);
+
+ tab_text_format (tbl, n_cols - 3,
+ heading_rows + row_var_start + row_result_start + cmd.st_n + e - 1,
+ TAB_RIGHT,
+ "%d", e);
+ }
- 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)
- );
+ 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;
- ds_destroy (&vstr);
+ while (weight-- > 0 && e < cmd.st_n)
+ {
+ tab_double (tbl, n_cols - 1,
+ heading_rows + row_var_start + row_result_start + cmd.st_n + e,
+ TAB_RIGHT,
+ minimum->value,
+ NULL);
+
+
+ tab_fixed (tbl, n_cols - 2,
+ heading_rows + row_var_start +
+ row_result_start + cmd.st_n + e,
+ TAB_RIGHT,
+ minimum->location,
+ 10, 0);
+ ++e;
}
- prev = (*fs)->id[0];
+ min_ll = ll_next (min_ll);
+ }
-
- if (fctr->indep_var[1] && count > 0 )
- tab_hline (tbl, TAL_1, 2, n_cols - 1, row);
+ 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;
- if ( fctr->indep_var[1])
+ while (weight-- > 0 && e < cmd.st_n)
{
- 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 + e,
+ TAB_RIGHT,
+ maximum->value,
+ NULL);
+
+
+ tab_fixed (tbl, n_cols - 2,
+ heading_rows + row_var_start +
+ row_result_start + e,
+ TAB_RIGHT,
+ maximum->location,
+ 10, 0);
+ ++e;
}
- populate_descriptives (tbl, heading_columns - 2,
- row,
- dependent_var[i],
- & (*fs)->m[i]);
-
- count++ ;
- fs++;
+ max_ll = ll_next (max_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 ();
- if (ch == NULL)
- break;
-
- ds_init_empty (&str);
- factor_to_string (fctr, *fs, 0, &str );
-
- chart_write_title (ch, "%s", 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 ();
- if (ch == NULL)
- break;
-
- boxplot_draw_yscale (ch, totals[i].max, totals[i].min);
-
- if ( fctr )
- {
- int n_factors = 0;
- int f=0;
- for ( fs = fctr->fs ; *fs ; ++fs )
- ++n_factors;
-
- 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, heading_columns, 0, heading_rows, 0);
- tab_headers (tbl, n_heading_columns + 1, 0, n_heading_rows, 0);
-
- tab_dim (tbl, tab_natural_dimensions);
+ tab_dim (tbl, tab_natural_dimensions, NULL);
- /* Outline the box and have no internal lines*/
+ /* Outline the box */
tab_box (tbl,
TAL_2, TAL_2,
-1, -1,
#include <output/table.h>
#include <data/format.h>
++#include "minmax.h"
#include "xalloc.h"
+#include "xmemdup0.h"
#include "gettext.h"
#define _(msgid) gettext (msgid)
struct tab_table *table;
- table = tab_create (cols,rows,0);
+ table = tab_create (cols, rows, 0);
tab_columns (table, SOM_COL_DOWN, 1);
- tab_headers (table,0,0,1,0);
- tab_box (table, TAL_2, TAL_2, TAL_0, TAL_1, 0, 0, cols -1, rows -1 );
+ tab_headers (table, 0, 0, 1, 0);
+ tab_box (table, TAL_2, TAL_2, TAL_0, TAL_1, 0, 0, cols - 1, rows - 1);
tab_hline (table, TAL_2, 0, cols - 1, 1);
tab_vline (table, TAL_2, 2, 0, rows - 1);
- tab_dim (table, tab_natural_dimensions);
- tab_title (table, _ ("Paired Samples Correlations"));
+ tab_dim (table, tab_natural_dimensions, NULL);
+ tab_title (table, _("Paired Samples Correlations"));
/* column headings */
- tab_text (table, 2,0, TAB_CENTER | TAT_TITLE, _ ("N"));
- tab_text (table, 3,0, TAB_CENTER | TAT_TITLE, _ ("Correlation"));
- tab_text (table, 4,0, TAB_CENTER | TAT_TITLE, _ ("Sig."));
+ tab_text (table, 2, 0, TAB_CENTER | TAT_TITLE, _("N"));
+ tab_text (table, 3, 0, TAB_CENTER | TAT_TITLE, _("Correlation"));
+ tab_text (table, 4, 0, TAB_CENTER | TAT_TITLE, _("Sig."));
- for (i=0; i < n_pairs; ++i)
+ for (i = 0; i < proc->n_pairs; i++)
{
- double p,q;
-
- double df = pairs[i].n -2;
+ struct pair *pair = &proc->pairs[i];
++ double df = pair->n - 2;
+ double p, q;
- double df = pair->n -2;
- double correlation_t = (pair->correlation * sqrt (df) /
- sqrt (1 - pow2 (pair->correlation)));
+
+ /* corr2 will mathematically always be in the range [0, 1.0]. Inaccurate
+ calculations sometimes cause it to be slightly greater than 1.0, so
+ force it into the correct range to avoid NaN from sqrt(). */
- double corr2 = MIN (1.0, pow2 (pairs[i].correlation));
- double correlation_t =
- pairs[i].correlation * sqrt (df) /
- sqrt (1 - corr2);
-
++ double corr2 = MIN (1.0, pow2 (pair->correlation));
++ double correlation_t = pair->correlation * sqrt (df) / sqrt (1 - corr2);
/* row headings */
- tab_text (table, 0,i+1, TAB_LEFT | TAT_TITLE | TAT_PRINTF,
- _ ("Pair %d"), i);
-
- tab_text (table, 1,i+1, TAB_LEFT | TAT_TITLE | TAT_PRINTF,
- _ ("%s & %s"),
- var_get_name (pairs[i].v[0]),
- var_get_name (pairs[i].v[1]));
-
+ tab_text_format (table, 0, i + 1, TAB_LEFT | TAT_TITLE,
+ _("Pair %d"), i);
+ tab_text_format (table, 1, i + 1, TAB_LEFT | TAT_TITLE,
+ _("%s & %s"),
+ var_get_name (pair->v[0]),
+ var_get_name (pair->v[1]));
/* row data */
- tab_double (table, 2, i+1, TAB_RIGHT, pairs[i].n, wfmt);
- tab_double (table, 3, i+1, TAB_RIGHT, pairs[i].correlation, NULL);
+ tab_double (table, 2, i + 1, TAB_RIGHT, pair->n, &proc->weight_format);
+ tab_double (table, 3, i + 1, TAB_RIGHT, pair->correlation, NULL);
p = gsl_cdf_tdist_P (correlation_t, df);
q = gsl_cdf_tdist_Q (correlation_t, df);