You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA. */
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
/* FIXME:
*/
-/* AIX requires this to be the first thing in the file. */
#include <config.h>
-#if __GNUC__
-#define alloca __builtin_alloca
-#else
-#if HAVE_ALLOCA_H
-#include <alloca.h>
-#else
-#ifdef _AIX
-#pragma alloca
-#else
-#ifndef alloca /* predefined by HP cc +Olibcalls */
-char *alloca ();
-#endif
-#endif
-#endif
-#endif
-
-#include <assert.h>
+#include "error.h"
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
+#include <gsl/gsl_cdf.h>
+#include "algorithm.h"
#include "alloc.h"
-#include "avl.h"
+#include "case.h"
+#include "dictionary.h"
#include "hash.h"
#include "pool.h"
-#include "dcdflib/cdflib.h"
#include "command.h"
#include "lexer.h"
#include "error.h"
#include "magic.h"
#include "misc.h"
-#include "stats.h"
#include "output.h"
+#include "str.h"
#include "tab.h"
+#include "value-labels.h"
#include "var.h"
#include "vfm.h"
-#undef DEBUGGING
-/*#define DEBUGGING 1*/
+/* (headers) */
+
#include "debug-print.h"
/* (specification)
crosstabs (crs_):
- *tables=custom;
+ *^tables=custom;
+variables=custom;
+missing=miss:!table/include/report;
+write[wr_]=none,cells,all;
tabl:!tables/notables,
box:!box/nobox,
pivot:!pivot/nopivot;
- +cells[cl_]=count,none,row,column,total,expected,residual,sresidual,
+ +cells[cl_]=count,none,expected,row,column,total,residual,sresidual,
asresidual,all;
+statistics[st_]=chisq,phi,cc,lambda,uc,none,btau,ctau,risk,gamma,d,
kappa,eta,corr,all.
double *data; /* Crosstabulation table for integer mode. */
}
u;
- union value v[1]; /* Values. */
+ union value values[1]; /* Values. */
};
/* A crosstabulation. */
int nvar; /* Number of variables. */
double missing; /* Missing cases count. */
int ofs; /* Integer mode: Offset into sorted_tab[]. */
- struct variable *v[2]; /* At least two variables; sorted by
+ struct variable *vars[2]; /* At least two variables; sorted by
larger indices first. */
};
+/* Integer mode variable info. */
+struct var_range
+ {
+ int min; /* Minimum value. */
+ int max; /* Maximum value + 1. */
+ int count; /* max - min. */
+ };
+
+static inline struct var_range *
+get_var_range (struct variable *v)
+{
+ assert (v != NULL);
+ assert (v->aux != NULL);
+ return v->aux;
+}
+
/* Indexes into crosstab.v. */
enum
{
static int n_sorted_tab; /* Number of entries in sorted_tab. */
static struct table_entry **sorted_tab; /* Sorted table. */
-/* VARIABLES dictionary. */
-static struct dictionary *var_dict;
+/* Variables specifies on VARIABLES. */
+static struct variable **variables;
+static size_t variables_cnt;
/* TABLES. */
static struct crosstab **xtab;
/* CELLS. */
static int num_cells; /* Number of cells requested. */
static int cells[8]; /* Cells requested. */
-static int expected; /* Nonzero if expected value is needed. */
/* WRITE. */
static int write; /* One of WR_* that specifies the WRITE style. */
static struct pool *pl_col; /* For column data. */
static int internal_cmd_crosstabs (void);
-static void free_var_dict (void);
-static void precalc (void);
-static int calc_general (struct ccase *);
-static int calc_integer (struct ccase *);
-static void postcalc (void);
+static void precalc (void *);
+static int calc_general (struct ccase *, void *);
+static int calc_integer (struct ccase *, void *);
+static void postcalc (void *);
static void submit (struct tab_table *);
-#if DEBUGGING
-static void debug_print (void);
-static void print_table_entries (struct table_entry **tab);
-#endif
+static void format_short (char *s, const struct fmt_spec *fp,
+ const union value *v);
/* Parse and execute CROSSTABS, then clean up. */
int
{
int result = internal_cmd_crosstabs ();
- free_var_dict ();
+ free (variables);
pool_destroy (pl_tc);
pool_destroy (pl_col);
static int
internal_cmd_crosstabs (void)
{
- var_dict = NULL;
+ int i;
+
+ variables = NULL;
+ variables_cnt = 0;
xtab = NULL;
nxtab = 0;
pl_tc = pool_create ();
pl_col = pool_create ();
- lex_match_id ("CROSSTABS");
if (!parse_crosstabs (&cmd))
return CMD_FAILURE;
-#if DEBUGGING
- /* Needs var_dict. */
- debug_print ();
-#endif
-
- mode = var_dict ? INTEGER : GENERAL;
- free_var_dict();
+ mode = variables ? INTEGER : GENERAL;
/* CELLS. */
- expected = 0;
if (!cmd.sbc_cells)
{
cmd.a_cells[CRS_CL_COUNT] = 1;
- num_cells = 1;
}
else
{
- int i;
int count = 0;
for (i = 0; i < CRS_CL_count; i++)
cmd.a_cells[CRS_CL_ALL] = 0;
}
cmd.a_cells[CRS_CL_NONE] = 0;
- for (num_cells = i = 0; i < CRS_CL_count; i++)
- if (cmd.a_cells[i])
- {
- if (i >= CRS_CL_EXPECTED)
- expected = 1;
- cmd.a_cells[num_cells++] = i;
- }
}
+ for (num_cells = i = 0; i < CRS_CL_count; i++)
+ if (cmd.a_cells[i])
+ cells[num_cells++] = i;
/* STATISTICS. */
if (cmd.sbc_statistics)
else
write = CRS_WR_NONE;
- update_weighting (&default_dict);
- procedure (precalc, mode == GENERAL ? calc_general : calc_integer, postcalc);
+ procedure_with_splits (precalc,
+ mode == GENERAL ? calc_general : calc_integer,
+ postcalc, NULL);
return CMD_SUCCESS;
}
-/* Frees var_dict once it's no longer needed. */
-static void
-free_var_dict (void)
-{
- if (!var_dict)
- return;
-
- {
- int i;
-
- if (var_dict->var_by_name)
- {
- avl_destroy (var_dict->var_by_name, NULL);
- var_dict->var_by_name = NULL;
- }
-
- for (i = 0; i < var_dict->nvar; i++)
- free (var_dict->var[i]);
- free (var_dict->var);
- var_dict->var = NULL;
- var_dict->nvar = 0;
-
- free_dictionary (var_dict);
-
- var_dict = NULL;
- }
-}
-
/* Parses the TABLES subcommand. */
static int
-crs_custom_tables (struct cmd_crosstabs *cmd unused)
+crs_custom_tables (struct cmd_crosstabs *cmd UNUSED)
{
- struct dictionary *dict;
+ struct var_set *var_set;
int n_by;
struct variable ***by = NULL;
int *by_nvar = NULL;
/* Ensure that this is a TABLES subcommand. */
if (!lex_match_id ("TABLES")
- && (token != T_ID || !is_varname (tokid))
+ && (token != T_ID || dict_lookup_var (default_dict, tokid) == NULL)
&& token != T_ALL)
return 2;
lex_match ('=');
- dict = var_dict ? var_dict : &default_dict;
+ if (variables != NULL)
+ var_set = var_set_create_from_array (variables, variables_cnt);
+ else
+ var_set = var_set_create_from_dict (default_dict);
+ assert (var_set != NULL);
for (n_by = 0; ;)
{
by = xrealloc (by, sizeof *by * (n_by + 1));
by_nvar = xrealloc (by_nvar, sizeof *by_nvar * (n_by + 1));
- if (!parse_variables (dict, &by[n_by], &by_nvar[n_by],
- PV_NO_DUPLICATE | PV_NO_SCRATCH))
- goto lossage;
+ if (!parse_var_set_vars (var_set, &by[n_by], &by_nvar[n_by],
+ PV_NO_DUPLICATE | PV_NO_SCRATCH))
+ goto done;
nx *= by_nvar[n_by];
n_by++;
if (n_by < 1)
{
lex_error (_("expecting BY"));
- goto lossage;
+ goto done;
}
else
break;
{
int i;
- if (var_dict == NULL)
- for (i = 0; i < n_by; i++)
- x->v[i] = by[i][by_iter[i]];
- else
- for (i = 0; i < n_by; i++)
- x->v[i] = default_dict.var[by[i][by_iter[i]]->foo];
+ for (i = 0; i < n_by; i++)
+ x->vars[i] = by[i][by_iter[i]];
}
{
}
free (by_iter);
}
-
success = 1;
- /* Despite the name, we come here whether we're successful or
- not. */
- lossage:
+
+ done:
+ /* All return paths lead here. */
{
int i;
free (by_nvar);
}
+ var_set_destroy (var_set);
+
return success;
}
/* Parses the VARIABLES subcommand. */
static int
-crs_custom_variables (struct cmd_crosstabs *cmd unused)
+crs_custom_variables (struct cmd_crosstabs *cmd UNUSED)
{
- struct variable **v = NULL;
- int nv = 0;
-
if (nxtab)
{
msg (SE, _("VARIABLES must be specified before TABLES."));
for (;;)
{
- int orig_nv = nv;
+ int orig_nv = variables_cnt;
int i;
long min, max;
- if (!parse_variables (&default_dict, &v, &nv,
+ if (!parse_variables (default_dict, &variables, &variables_cnt,
(PV_APPEND | PV_NUMERIC
| PV_NO_DUPLICATE | PV_NO_SCRATCH)))
return 0;
}
lex_get ();
- for (i = orig_nv; i < nv; i++)
- {
- v[i]->p.crs.min = min;
- v[i]->p.crs.max = max + 1.;
- v[i]->p.crs.count = max - min + 1;
+ for (i = orig_nv; i < variables_cnt; i++)
+ {
+ struct var_range *vr = xmalloc (sizeof *vr);
+ vr->min = min;
+ vr->max = max + 1.;
+ vr->count = max - min + 1;
+ var_attach_aux (variables[i], vr, var_dtor_free);
}
if (token == '/')
break;
}
- {
- int i;
-
- var_dict = new_dictionary (0);
- var_dict->var = xmalloc (sizeof *var_dict->var * nv);
- var_dict->nvar = nv;
- for (i = 0; i < nv; i++)
- {
- struct variable *var = xmalloc (offsetof (struct variable, width));
- strcpy (var->name, v[i]->name);
- var->index = i;
- var->type = v[i]->type;
- var->foo = v[i]->index;
- var_dict->var[i] = var;
- avl_force_insert (var_dict->var_by_name, var);
- }
-
- free (v);
- return 1;
- }
+ return 1;
lossage:
- free (v);
+ free (variables);
+ variables = NULL;
return 0;
}
-
-#if DEBUGGING
-static void
-debug_print (void)
-{
- printf ("CROSSTABS\n");
-
- if (var_dict)
- {
- int i;
-
- printf ("\t/VARIABLES=");
- for (i = 0; i < var_dict->nvar; i++)
- {
- struct variable *v = var_dict->var[i];
- struct variable *iv = default_dict.var[v->foo];
-
- printf ("%s ", v->name);
- if (i < var_dict->nvar - 1)
- {
- struct variable *nv = var_dict->var[i + 1];
- struct variable *niv = default_dict.var[nv->foo];
-
- if (iv->p.crs.min == niv->p.crs.min
- && iv->p.crs.max == niv->p.crs.max)
- continue;
- }
- printf ("(%d,%d) ", iv->p.crs.min, iv->p.crs.max - 1);
- }
- printf ("\n");
- }
-
- {
- int i;
-
- printf ("\t/TABLES=");
- for (i = 0; i < nxtab; i++)
- {
- struct crosstab *x = xtab[i];
- int j;
-
- if (i)
- printf("\t\t");
- for (j = 0; j < x->nvar; j++)
- {
- if (j)
- printf (" BY ");
- printf ("%s", x->v[j]->name);
- }
- printf ("\n");
- }
- }
-}
-#endif /* DEBUGGING */
\f
/* Data file processing. */
/* Set up the crosstabulation tables for processing. */
static void
-precalc (void)
+precalc (void *aux UNUSED)
{
if (mode == GENERAL)
{
x->ofs = n_sorted_tab;
- for (j = 2; j < x->nvar; j++)
- count *= x->v[j - 2]->p.crs.count;
-
+ for (j = 2; j < x->nvar; j++)
+ count *= get_var_range (x->vars[j - 2])->count;
+
sorted_tab = xrealloc (sorted_tab,
sizeof *sorted_tab * (n_sorted_tab + count));
v = local_alloc (sizeof *v * x->nvar);
- for (j = 2; j < x->nvar; j++)
- v[j] = x->v[j]->p.crs.min;
+ for (j = 2; j < x->nvar; j++)
+ v[j] = get_var_range (x->vars[j])->min;
for (j = 0; j < count; j++)
{
struct table_entry *te;
te->table = i;
{
- const int mat_size = (x->v[0]->p.crs.count
- * x->v[1]->p.crs.count);
+ int row_cnt = get_var_range (x->vars[0])->count;
+ int col_cnt = get_var_range (x->vars[1])->count;
+ const int mat_size = row_cnt * col_cnt;
int m;
te->u.data = xmalloc (sizeof *te->u.data * mat_size);
}
for (k = 2; k < x->nvar; k++)
- te->v[k].f = v[k];
- for (k = 2; k < x->nvar; k++)
- if (++v[k] >= x->v[k]->p.crs.max)
- v[k] = x->v[k]->p.crs.min;
- else
- break;
+ te->values[k].f = v[k];
+ for (k = 2; k < x->nvar; k++)
+ {
+ struct var_range *vr = get_var_range (x->vars[k]);
+ if (++v[k] >= vr->max)
+ v[k] = vr->min;
+ else
+ break;
+ }
}
local_free (v);
}
/* Form crosstabulations for general mode. */
static int
-calc_general (struct ccase *c)
+calc_general (struct ccase *c, void *aux UNUSED)
{
+ int bad_warn = 1;
+
/* Case weight. */
- double w = (default_dict.weight_index != -1
- ? c->data[default_dict.var[default_dict.weight_index]->fv].f
- : 1.0);
+ double weight = dict_get_case_weight (default_dict, c, &bad_warn);
/* Flattened current table index. */
int t;
for (j = 0; j < x->nvar; j++)
{
if ((cmd.miss == CRS_TABLE
- && is_missing (&c->data[x->v[j]->fv], x->v[j]))
+ && is_missing (case_data (c, x->vars[j]->fv), x->vars[j]))
|| (cmd.miss == CRS_INCLUDE
- && is_system_missing (&c->data[x->v[j]->fv], x->v[j])))
+ && is_system_missing (case_data (c, x->vars[j]->fv),
+ x->vars[j])))
{
- x->missing += w;
+ x->missing += weight;
goto next_crosstab;
}
- if (x->v[j]->type == NUMERIC)
- te->v[j].f = c->data[x->v[j]->fv].f;
+ if (x->vars[j]->type == NUMERIC)
+ te->values[j].f = case_num (c, x->vars[j]->fv);
else
{
- memcpy (te->v[j].s, c->data[x->v[j]->fv].s, x->v[j]->width);
+ memcpy (te->values[j].s, case_str (c, x->vars[j]->fv),
+ x->vars[j]->width);
/* Necessary in order to simplify comparisons. */
- memset (&te->v[j].s[x->v[j]->width], 0,
- sizeof (union value) - x->v[j]->width);
+ memset (&te->values[j].s[x->vars[j]->width], 0,
+ sizeof (union value) - x->vars[j]->width);
}
}
}
/* Add record to hash table. */
{
- struct table_entry **tepp = (struct table_entry **) hsh_probe (gen_tab, te);
- if (NULL == *tepp)
+ struct table_entry **tepp
+ = (struct table_entry **) hsh_probe (gen_tab, te);
+ if (*tepp == NULL)
{
struct table_entry *tep = pool_alloc (pl_tc, entry_size);
- te->u.freq = w;
+ te->u.freq = weight;
memcpy (tep, te, entry_size);
*tepp = tep;
}
else
- (*tepp)->u.freq += w;
+ (*tepp)->u.freq += weight;
}
next_crosstab:
}
static int
-calc_integer (struct ccase *c)
+calc_integer (struct ccase *c, void *aux UNUSED)
{
+ int bad_warn = 1;
+
/* Case weight. */
- double w = (default_dict.weight_index != -1
- ? c->data[default_dict.var[default_dict.weight_index]->fv].f
- : 1.0);
+ double weight = dict_get_case_weight (default_dict, c, &bad_warn);
/* Flattened current table index. */
int t;
ofs = x->ofs;
for (i = 0; i < x->nvar; i++)
{
- struct variable *const v = x->v[i];
- double value = c->data[v->fv].f;
+ struct variable *const v = x->vars[i];
+ struct var_range *vr = get_var_range (v);
+ double value = case_num (c, v->fv);
/* Note that the first test also rules out SYSMIS. */
- if ((value < v->p.crs.min || value >= v->p.crs.max)
+ if ((value < vr->min || value >= vr->max)
|| (cmd.miss == CRS_TABLE && is_num_user_missing (value, v)))
{
- x->missing += w;
+ x->missing += weight;
goto next_crosstab;
}
if (i > 1)
{
- ofs += fact * ((int) value - v->p.crs.min);
- fact *= v->p.crs.count;
+ ofs += fact * ((int) value - vr->min);
+ fact *= vr->count;
}
}
{
- const int row = c->data[x->v[ROW_VAR]->fv].f - x->v[ROW_VAR]->p.crs.min;
- const int col = c->data[x->v[COL_VAR]->fv].f - x->v[COL_VAR]->p.crs.min;
- const int col_dim = x->v[COL_VAR]->p.crs.count;
+ struct variable *row_var = x->vars[ROW_VAR];
+ const int row = case_num (c, row_var->fv) - get_var_range (row_var)->min;
+
+ struct variable *col_var = x->vars[COL_VAR];
+ const int col = case_num (c, col_var->fv) - get_var_range (col_var)->min;
+
+ const int col_dim = get_var_range (col_var)->count;
- sorted_tab[ofs]->u.data[col + row * col_dim] += w;
+ sorted_tab[ofs]->u.data[col + row * col_dim] += weight;
}
next_crosstab: ;
return 1;
}
-#if DEBUGGING
-/* Print out all table entries in NULL-terminated TAB for use by a
- debugger (a person, not a program). */
-static void
-print_table_entries (struct table_entry **tab)
-{
- printf ("raw crosstabulation data:\n");
- for (; *tab; tab++)
- {
- const struct crosstab *x = xtab[(*tab)->table];
- int i;
-
- printf ("(%g) table:%d ", (*tab)->u.freq, (*tab)->table);
- for (i = 0; i < x->nvar; i++)
- {
- if (i)
- printf (", ");
- printf ("%s:", x->v[i]->name);
-
- if (x->v[i]->type == NUMERIC)
- printf ("%g", (*tab)->v[i].f);
- else
- printf ("%.*s", x->v[i]->width, (*tab)->v[i].s);
- }
- printf ("\n");
- }
- fflush (stdout);
-}
-#endif
-
-/* Compare the table_entry's at PA and PB and return a strcmp()-type
+/* Compare the table_entry's at A and B and return a strcmp()-type
result. */
static int
-compare_table_entry (const void *pa, const void *pb, void *foo unused)
+compare_table_entry (const void *a_, const void *b_, void *foo UNUSED)
{
- const struct table_entry *a = pa;
- const struct table_entry *b = pb;
-
- {
- const int difftable = a->table - b->table;
- if (difftable)
- return difftable;
- }
+ const struct table_entry *a = a_;
+ const struct table_entry *b = b_;
+
+ if (a->table > b->table)
+ return 1;
+ else if (a->table < b->table)
+ return -1;
{
const struct crosstab *x = xtab[a->table];
int i;
for (i = x->nvar - 1; i >= 0; i--)
- if (x->v[i]->type == NUMERIC)
+ if (x->vars[i]->type == NUMERIC)
{
- const double diffnum = a->v[i].f - b->v[i].f;
+ const double diffnum = a->values[i].f - b->values[i].f;
if (diffnum < 0)
return -1;
else if (diffnum > 0)
}
else
{
- assert (x->v[i]->type == ALPHA);
+ assert (x->vars[i]->type == ALPHA);
{
- const int diffstr = strncmp (a->v[i].s, b->v[i].s, x->v[i]->width);
+ const int diffstr = strncmp (a->values[i].s, b->values[i].s,
+ x->vars[i]->width);
if (diffstr)
return diffstr;
}
return 0;
}
-/* Calculate a hash value from table_entry PA. */
+/* Calculate a hash value from table_entry A. */
static unsigned
-hash_table_entry (const void *pa, void *foo unused)
+hash_table_entry (const void *a_, void *foo UNUSED)
{
- const struct table_entry *a = pa;
- unsigned long hash = a->table;
+ const struct table_entry *a = a_;
+ unsigned long hash;
int i;
- /* Hash formula from _SPSS Statistical Algorithms_. */
+ hash = a->table;
for (i = 0; i < xtab[a->table]->nvar; i++)
- {
- hash = (hash << 3) | (hash >> (CHAR_BIT * SIZEOF_LONG - 3));
- hash ^= a->v[i].hash[0];
-#if SIZEOF_DOUBLE / SIZEOF_LONG > 1
- hash ^= a->v[i].hash[1];
-#endif
- }
+ hash ^= hsh_hash_bytes (&a->values[i], sizeof a->values[i]);
return hash;
}
\f
/* Post-data reading calculations. */
-static struct table_entry **find_pivot_extent (struct table_entry **, int *cnt, int pivot);
-static void enum_var_values (struct table_entry **beg, int cnt,
- union value **values, int *nvalues,
- int var_index);
+static struct table_entry **find_pivot_extent (struct table_entry **,
+ int *cnt, int pivot);
+static void enum_var_values (struct table_entry **entries, int entry_cnt,
+ int var_idx,
+ union value **values, int *value_cnt);
static void output_pivot_table (struct table_entry **, struct table_entry **,
double **, double **, double **,
int *, int *, int *);
static void make_summary_table (void);
static void
-postcalc (void)
+postcalc (void *aux UNUSED)
{
if (mode == GENERAL)
{
n_sorted_tab = hsh_count (gen_tab);
sorted_tab = (struct table_entry **) hsh_sort (gen_tab);
-#if DEBUGGING
- print_table_entries (sorted_tab);
-#endif
}
make_summary_table ();
else
{
const struct crosstab *const x = xtab[(*pb)->table];
- const int n_cols = x->v[COL_VAR]->p.crs.count;
- const int n_rows = x->v[ROW_VAR]->p.crs.count;
+ const int n_cols = get_var_range (x->vars[COL_VAR])->count;
+ const int n_rows = get_var_range (x->vars[ROW_VAR])->count;
const int count = n_cols * n_rows;
for (valid = 0.; pb < pe; pb++)
if (i > 0)
cp = stpcpy (cp, " * ");
- cp = stpcpy (cp, x->v[i]->label ? x->v[i]->label : x->v[i]->name);
+ cp = stpcpy (cp,
+ x->vars[i]->label ? x->vars[i]->label : x->vars[i]->name);
}
tab_text (t, 0, 0, TAB_LEFT, buf);
int tc = pe - pb; /* Table count. */
/* Table entry for header comparison. */
- struct table_entry *cmp;
+ struct table_entry *cmp = NULL;
x = xtab[(*pb)->table];
- enum_var_values (pb, pe - pb, &cols, &n_cols, COL_VAR);
+ enum_var_values (pb, pe - pb, COL_VAR, &cols, &n_cols);
nvar = cmd.pivot == CRS_PIVOT ? x->nvar : 2;
/* First header line. */
tab_joint_text (table, nvar - 1, 0, (nvar - 1) + (n_cols - 1), 0,
- TAB_CENTER | TAT_TITLE, x->v[COL_VAR]->name);
+ TAB_CENTER | TAT_TITLE, x->vars[COL_VAR]->name);
tab_hline (table, TAL_1, nvar - 1, nvar + n_cols - 2, 1);
for (i = 2; i < nvar; i++)
tab_joint_text (table, nvar - i - 1, 0, nvar - i - 1, 1,
TAB_RIGHT | TAT_TITLE,
- x->v[i]->label ? x->v[i]->label : x->v[i]->name);
+ (x->vars[i]->label
+ ? x->vars[i]->label : x->vars[i]->name));
tab_text (table, nvar - 2, 1, TAB_RIGHT | TAT_TITLE,
- x->v[ROW_VAR]->name);
+ x->vars[ROW_VAR]->name);
for (i = 0; i < n_cols; i++)
table_value_missing (table, nvar + i - 1, 1, TAB_RIGHT, &cols[i],
- x->v[COL_VAR]);
+ x->vars[COL_VAR]);
tab_text (table, nvar + n_cols - 1, 1, TAB_CENTER, _("Total"));
}
{
if (i)
cp = stpcpy (cp, " by ");
- cp = stpcpy (cp, x->v[i]->name);
+ cp = stpcpy (cp, x->vars[i]->name);
}
else
{
- cp = spprintf (cp, "%s by %s for", x->v[0]->name, x->v[1]->name);
+ cp = spprintf (cp, "%s by %s for",
+ x->vars[0]->name, x->vars[1]->name);
for (i = 2; i < nvar; i++)
{
char buf[64], *bufp;
if (i > 2)
*cp++ = ',';
*cp++ = ' ';
- cp = stpcpy (cp, x->v[i]->name);
+ cp = stpcpy (cp, x->vars[i]->name);
*cp++ = '=';
- data_out (buf, &x->v[i]->print, &(*pb)->v[i]);
+ format_short (buf, &x->vars[i]->print, &(*pb)->values[i]);
for (bufp = buf; isspace ((unsigned char) *bufp); bufp++)
;
cp = stpcpy (cp, bufp);
break;
/* Find all the row variable values. */
- enum_var_values (tb, te - tb, &rows, &n_rows, ROW_VAR);
+ enum_var_values (tb, te - tb, ROW_VAR, &rows, &n_rows);
/* Allocate memory space for the column and row totals. */
if (n_rows > *maxrows)
*cp = 0.;
for (p = &tb[0]; p < te; p++)
{
- for (; memcmp (cur_col, &(*p)->v[COL_VAR], sizeof *cur_col);
+ for (; memcmp (cur_col, &(*p)->values[COL_VAR], sizeof *cur_col);
cur_row = rows)
{
*++cp = 0.;
mp = &mat[cur_col - cols];
}
- for (; memcmp (cur_row, &(*p)->v[ROW_VAR], sizeof *cur_row);
+ for (; memcmp (cur_row, &(*p)->values[ROW_VAR], sizeof *cur_row);
cur_row++)
{
*mp = 0.;
W = cum;
}
-#if DEBUGGING
- /* Print the matrix. */
- {
- int i, r, c;
-
- printf ("%s by %s for", x->v[0]->name, x->v[1]->name);
- for (i = 2; i < nvar; i++)
- printf (" %s=%g", x->v[i]->name, tb[0]->v[i].f);
- printf ("\n");
- printf (" ");
- for (c = 0; c < n_cols; c++)
- printf ("%4g", cols[c].f);
- printf ("\n");
- for (r = 0; r < n_rows; r++)
- {
- printf ("%4g:", rows[r].f);
- for (c = 0; c < n_cols; c++)
- printf ("%4g", mat[c + r * n_cols]);
- printf ("%4g", row_tot[r]);
- printf ("\n");
- }
- printf (" ");
- for (c = 0; c < n_cols; c++)
- printf ("%4g", col_tot[c]);
- printf ("%4g", W);
- printf ("\n\n");
- }
-#endif
-
/* Find the first variable that differs from the last subtable,
then display the values of the dimensioning variables for
each table that needs it. */
for (; ; first_difference--)
{
assert (first_difference >= 2);
- if (memcmp (&cmp->v[first_difference],
- &(*tb)->v[first_difference], sizeof *cmp->v))
+ if (memcmp (&cmp->values[first_difference],
+ &(*tb)->values[first_difference],
+ sizeof *cmp->values))
break;
}
cmp = *tb;
int r;
for (r = 0; r < n_rows; r++)
- if (is_num_user_missing (rows[r].f, x->v[ROW_VAR]))
+ if (is_num_user_missing (rows[r].f, x->vars[ROW_VAR]))
{
int c;
int c;
for (c = 0; c < n_cols; c++)
- if (is_num_user_missing (cols[c].f, x->v[COL_VAR]))
+ if (is_num_user_missing (cols[c].f, x->vars[COL_VAR]))
{
int r;
if (t != table)
for (i = 2; i < nvar; i++)
tab_text (t, nvar - i - 1, 0, TAB_RIGHT | TAT_TITLE,
- x->v[i]->label ? x->v[i]->label : x->v[i]->name);
+ x->vars[i]->label ? x->vars[i]->label : x->vars[i]->name);
tab_box (t, TAL_2, TAL_2, -1, -1, 0, 0, tab_nc (t) - 1, tab_nr (t) - 1);
tab_box (t, -1, -1, -1, TAL_1, tab_l (t), tab_t (t) - 1, tab_nc (t) - 1,
tab_nr (t) - 1);
if (pivot)
continue;
- if (memcmp (&(*tp)->v[2], &fp->v[2], sizeof (union value) * (x->nvar - 2)))
+ if (memcmp (&(*tp)->values[2], &fp->values[2], sizeof (union value) * (x->nvar - 2)))
break;
}
/* Integer mode correspondent to find_pivot_extent_general(). This
could be optimized somewhat, but I just don't give a crap about
- CROSSTABS performance in integer mode, which is just a wart on
- CROSSTABS' ass as far as I'm concerned.
+ CROSSTABS performance in integer mode, which is just a
+ CROSSTABS wart as far as I'm concerned.
That said, feel free to send optimization patches to me. */
static struct table_entry **
if (pivot)
continue;
- if (memcmp (&(*tp)->v[2], &fp->v[2], sizeof (union value) * (x->nvar - 2)))
+ if (memcmp (&(*tp)->values[2], &fp->values[2],
+ sizeof (union value) * (x->nvar - 2)))
break;
}
return tp;
}
-/* Compare value * A and B, where WIDTH is the string width or 0 for
- numerics, and return a strcmp()-type result. */
+/* Compares `union value's A_ and B_ and returns a strcmp()-like
+ result. WIDTH_ points to an int which is either 0 for a
+ numeric value or a string width for a string value. */
static int
-compare_value (const void *pa, const void *pb, void *pwidth)
+compare_value (const void *a_, const void *b_, void *width_)
{
- const union value *a = pa;
- const union value *b = pb;
- const int width = (int) pwidth;
+ const union value *a = a_;
+ const union value *b = b_;
+ const int *pwidth = width_;
+ const int width = *pwidth;
- if (width)
- return strncmp (a->s, b->s, width);
+ if (width == 0)
+ return (a->f < b->f) ? -1 : (a->f > b->f);
else
- return a->f < b->f ? -1 : (a->f > b->f ? 1 : 0);
+ return strncmp (a->s, b->s, width);
}
-/* Given a list of CNT table_entry's starting at BEG, creates a list
- of *NVALUES values *VALUES of variable with index VAR_INDEX. */
+/* Given an array of ENTRY_CNT table_entry structures starting at
+ ENTRIES, creates a sorted list of the values that the variable
+ with index VAR_IDX takes on. The values are returned as a
+ malloc()'darray stored in *VALUES, with the number of values
+ stored in *VALUE_CNT.
+ */
static void
-enum_var_values (struct table_entry **beg, int cnt, union value **values, int *nvalues,
- int var_index)
+enum_var_values (struct table_entry **entries, int entry_cnt, int var_idx,
+ union value **values, int *value_cnt)
{
+ struct variable *v = xtab[(*entries)->table]->vars[var_idx];
+
if (mode == GENERAL)
{
- avl_tree *tree;
-
- tree = avl_create (pl_col, compare_value,
- (void *) (xtab[(*beg)->table]->v[var_index]->width));
-
- {
- int i;
-
- for (i = 0; i < cnt; i++)
- avl_insert (tree, &beg[i]->v[var_index]);
- *values = xmalloc (sizeof **values * avl_count (tree));
- }
-
- {
- avl_traverser trav;
- union value *v;
- int i;
-
- i = 0;
- while (NULL != (v = avl_traverse (tree, &trav)))
- (*values)[i++] = *v;
- *nvalues = i;
- }
+ int width = v->width;
+ int i;
- /* Destroy tree. */
- pool_destroy (pl_col);
- pl_col = pool_create ();
+ *values = xmalloc (sizeof **values * entry_cnt);
+ for (i = 0; i < entry_cnt; i++)
+ (*values)[i] = entries[i]->values[var_idx];
+ *value_cnt = sort_unique (*values, entry_cnt, sizeof **values,
+ compare_value, &width);
}
else
{
- struct crosstab_proc *crs = &xtab[(*beg)->table]->v[var_index]->p.crs;
+ struct var_range *vr = get_var_range (v);
int i;
assert (mode == INTEGER);
- *values = xmalloc (sizeof **values * crs->count);
- for (i = 0; i < crs->count; i++)
- (*values)[i].f = i + crs->min;
- *nvalues = crs->count;
+ *values = xmalloc (sizeof **values * vr->count);
+ for (i = 0; i < vr->count; i++)
+ (*values)[i].f = i + vr->min;
+ *value_cnt = vr->count;
}
}
table_value_missing (struct tab_table *table, int c, int r, unsigned char opt,
const union value *v, const struct variable *var)
{
- struct len_string s;
+ struct fixed_string s;
- char *label = get_val_lab (var, *v, 0);
+ const char *label = val_labs_find (var->val_labs, *v);
if (label)
{
tab_text (table, c, r, TAB_LEFT, label);
return;
}
- s.length = var->print.w;
- s.string = tab_alloc (table, s.length + 1);
- data_out (s.string, &var->print, v);
+ s.string = tab_alloc (table, var->print.w);
+ format_short (s.string, &var->print, v);
+ s.length = strlen (s.string);
if (cmd.miss == CRS_REPORT && is_num_user_missing (v->f, var))
s.string[s.length++] = 'M';
while (s.length && *s.string == ' ')
for (; first_difference >= 2; first_difference--)
table_value_missing (table, nvar - first_difference - 1, 0,
- TAB_RIGHT, &tb->v[first_difference],
- x->v[first_difference]);
+ TAB_RIGHT, &tb->values[first_difference],
+ x->vars[first_difference]);
}
-/* Put value V into cell (C,R) of TABLE, suffixed with letter M. */
+/* Put VALUE into cell (C,R) of TABLE, suffixed with character
+ SUFFIX if nonzero. If MARK_MISSING is nonzero the entry is
+ additionally suffixed with a letter `M'. */
static void
-float_M_suffix (struct tab_table *table, int c, int r, double v)
+format_cell_entry (struct tab_table *table, int c, int r, double value,
+ char suffix, int mark_missing)
{
- static const struct fmt_spec f = {FMT_F, 8, 0};
- struct len_string s;
-
- s.length = 9;
- s.string = tab_alloc (table, 9);
- s.string[8] = 'M';
- data_out (s.string, &f, (union value *) &v);
+ const struct fmt_spec f = {FMT_F, 10, 1};
+ union value v;
+ struct fixed_string s;
+
+ s.length = 10;
+ s.string = tab_alloc (table, 16);
+ v.f = value;
+ data_out (s.string, &f, &v);
while (*s.string == ' ')
{
s.length--;
s.string++;
}
+ if (suffix != 0)
+ s.string[s.length++] = suffix;
+ if (mark_missing)
+ s.string[s.length++] = 'M';
+
tab_raw (table, c, r, TAB_RIGHT, &s);
}
for (r = 0; r < n_rows; r++)
table_value_missing (table, nvar - 2, r * num_cells,
- TAB_RIGHT, &rows[r], x->v[ROW_VAR]);
+ TAB_RIGHT, &rows[r], x->vars[ROW_VAR]);
}
tab_text (table, nvar - 2, n_rows * num_cells,
TAB_LEFT, _("Total"));
tab_hline (table, TAL_1, -1, n_cols, 0);
for (c = 0; c < n_cols; c++)
{
- double expected_value;
-
- if (expected)
- expected_value = row_tot[r] * col_tot[c] / W;
+ int mark_missing = 0;
+ double expected_value = row_tot[r] * col_tot[c] / W;
+ if (cmd.miss == CRS_REPORT
+ && (is_num_user_missing (cols[c].f, x->vars[COL_VAR])
+ || is_num_user_missing (rows[r].f, x->vars[ROW_VAR])))
+ mark_missing = 1;
for (i = 0; i < num_cells; i++)
{
double v;
+ int suffix = 0;
switch (cells[i])
{
break;
case CRS_CL_ROW:
v = *mp / row_tot[r] * 100.;
+ suffix = '%';
break;
case CRS_CL_COLUMN:
v = *mp / col_tot[c] * 100.;
+ suffix = '%';
break;
case CRS_CL_TOTAL:
v = *mp / W * 100.;
+ suffix = '%';
break;
case CRS_CL_EXPECTED:
v = expected_value;
break;
default:
assert (0);
+ abort ();
}
- if (cmd.miss == CRS_REPORT
- && (is_num_user_missing (cols[c].f, x->v[COL_VAR])
- || is_num_user_missing (rows[r].f, x->v[ROW_VAR])))
- float_M_suffix (table, c, i, v);
- else if (v != 0.)
- tab_float (table, c, i, TAB_RIGHT, v, 8, 0);
+ format_cell_entry (table, c, i, v, suffix, mark_missing);
}
mp++;
int r, i;
tab_offset (table, -1, tab_row (table) - num_cells * n_rows);
- for (r = 0; r < n_rows; r++)
- for (i = 0; i < num_cells; i++)
- {
- double v;
-
- switch (cells[i])
- {
- case CRS_CL_COUNT:
- v = row_tot[r];
- break;
- case CRS_CL_ROW:
- v = 100.;
- break;
- case CRS_CL_COLUMN:
- v = row_tot[r] / W * 100.;
- break;
- case CRS_CL_TOTAL:
- v = row_tot[r] / W * 100.;
- break;
- case CRS_CL_EXPECTED:
- case CRS_CL_RESIDUAL:
- case CRS_CL_SRESIDUAL:
- case CRS_CL_ASRESIDUAL:
- v = 0.;
- break;
- default:
- assert (0);
- }
-
- if (cmd.miss == CRS_REPORT
- && is_num_user_missing (rows[r].f, x->v[ROW_VAR]))
- float_M_suffix (table, n_cols, 0, v);
- else if (v != 0.)
- tab_float (table, n_cols, 0, TAB_RIGHT, v, 8, 0);
-
- tab_next_row (table);
- }
+ for (r = 0; r < n_rows; r++)
+ {
+ char suffix = 0;
+ int mark_missing = 0;
+
+ if (cmd.miss == CRS_REPORT
+ && is_num_user_missing (rows[r].f, x->vars[ROW_VAR]))
+ mark_missing = 1;
+
+ for (i = 0; i < num_cells; i++)
+ {
+ double v;
+
+ switch (cells[i])
+ {
+ case CRS_CL_COUNT:
+ v = row_tot[r];
+ break;
+ case CRS_CL_ROW:
+ v = 100.;
+ suffix = '%';
+ break;
+ case CRS_CL_COLUMN:
+ v = row_tot[r] / W * 100.;
+ suffix = '%';
+ break;
+ case CRS_CL_TOTAL:
+ v = row_tot[r] / W * 100.;
+ suffix = '%';
+ break;
+ case CRS_CL_EXPECTED:
+ case CRS_CL_RESIDUAL:
+ case CRS_CL_SRESIDUAL:
+ case CRS_CL_ASRESIDUAL:
+ v = 0.;
+ break;
+ default:
+ assert (0);
+ abort ();
+ }
+
+ format_cell_entry (table, n_cols, 0, v, suffix, mark_missing);
+ tab_next_row (table);
+ }
+ }
}
/* Column totals, grand total. */
{
- int c, j;
+ int c;
+ int last_row = 0;
if (num_cells > 1)
tab_hline (table, TAL_1, -1, n_cols, 0);
for (c = 0; c <= n_cols; c++)
{
double ct = c < n_cols ? col_tot[c] : W;
- int i;
+ int mark_missing = 0;
+ char suffix = 0;
+ int i;
- for (i = j = 0; i < num_cells; i++)
+ if (cmd.miss == CRS_REPORT && c < n_cols
+ && is_num_user_missing (cols[c].f, x->vars[COL_VAR]))
+ mark_missing = 1;
+
+ for (i = 0; i < num_cells; i++)
{
double v;
{
case CRS_CL_COUNT:
v = ct;
+ suffix = '%';
break;
case CRS_CL_ROW:
v = ct / W * 100.;
+ suffix = '%';
break;
case CRS_CL_COLUMN:
v = 100.;
+ suffix = '%';
break;
case CRS_CL_TOTAL:
v = ct / W * 100.;
+ suffix = '%';
break;
case CRS_CL_EXPECTED:
case CRS_CL_RESIDUAL:
continue;
default:
assert (0);
+ abort ();
}
- if (cmd.miss == CRS_REPORT && c < n_cols
- && is_num_user_missing (cols[c].f, x->v[COL_VAR]))
- float_M_suffix (table, c, j, v);
- else if (v != 0.)
- tab_float (table, c, j, TAB_RIGHT, v, 8, 0);
-
- j++;
+ format_cell_entry (table, c, i, v, suffix, mark_missing);
}
+ last_row = i;
}
- tab_offset (table, -1, tab_row (table) + j);
+ tab_offset (table, -1, tab_row (table) + last_row);
}
tab_offset (table, 0, -1);
tab_float (chisq, 1, 0, TAB_RIGHT, chisq_v[i], 8, 3);
tab_float (chisq, 2, 0, TAB_RIGHT, df[i], 8, 0);
tab_float (chisq, 3, 0, TAB_RIGHT,
- chisq_sig (chisq_v[i], df[i]), 8, 3);
+ gsl_cdf_chisq_Q (chisq_v[i], df[i]), 8, 3);
}
else
{
switch (i)
{
case 0:
- if (x->v[COL_VAR]->type == NUMERIC)
+ if (x->vars[COL_VAR]->type == NUMERIC)
sprintf (buf, _("Odds Ratio for %s (%g / %g)"),
- x->v[COL_VAR]->name, c[0].f, c[1].f);
+ x->vars[COL_VAR]->name, c[0].f, c[1].f);
else
sprintf (buf, _("Odds Ratio for %s (%.*s / %.*s)"),
- x->v[COL_VAR]->name,
- x->v[COL_VAR]->width, c[0].s,
- x->v[COL_VAR]->width, c[1].s);
+ x->vars[COL_VAR]->name,
+ x->vars[COL_VAR]->width, c[0].s,
+ x->vars[COL_VAR]->width, c[1].s);
break;
case 1:
case 2:
- if (x->v[ROW_VAR]->type == NUMERIC)
+ if (x->vars[ROW_VAR]->type == NUMERIC)
sprintf (buf, _("For cohort %s = %g"),
- x->v[ROW_VAR]->name, rows[i - 1].f);
+ x->vars[ROW_VAR]->name, rows[i - 1].f);
else
sprintf (buf, _("For cohort %s = %.*s"),
- x->v[ROW_VAR]->name,
- x->v[ROW_VAR]->width, rows[i - 1].s);
+ x->vars[ROW_VAR]->name,
+ x->vars[ROW_VAR]->width, rows[i - 1].s);
break;
}
if (k == 0)
string = NULL;
else if (k == 1)
- string = x->v[0]->name;
+ string = x->vars[0]->name;
else
- string = x->v[1]->name;
+ string = x->vars[1]->name;
tab_text (direct, j, 0, TAB_LEFT | TAT_PRINTF,
gettext (stats_names[j][k]), string);
/* Returns the value of the gamma (factorial) function for an integer
argument X. */
-double
+static double
gamma_int (double x)
{
double r = 1;
const double freq = mat[n_cols * r + c];
const double residual = freq - expected;
- if (expected)
- chisq[0] += residual * residual / expected;
+ chisq[0] += residual * residual / expected;
if (freq)
chisq[1] += freq * log (expected / freq);
}
}
/* Calculate Mantel-Haenszel. */
- if (x->v[ROW_VAR]->type == NUMERIC && x->v[COL_VAR]->type == NUMERIC)
+ if (x->vars[ROW_VAR]->type == NUMERIC && x->vars[COL_VAR]->type == NUMERIC)
{
double r, ase_0, ase_1;
calc_r ((double *) rows, (double *) cols, &r, &ase_0, &ase_1);
const double freq = mat[n_cols * r + c];
const double residual = freq - expected;
- if (expected)
- Xp += residual * residual / expected;
+ Xp += residual * residual / expected;
}
}
if (cmd.a_statistics[CRS_ST_D])
{
- d_yx_cum += fij * sqr (Dr * (Cij - Dij)
- - (P - Q) * (W - row_tot[i]));
- d_xy_cum += fij * sqr (Dc * (Dij - Cij)
- - (Q - P) * (W - col_tot[j]));
+ d_yx_cum += fij * pow2 (Dr * (Cij - Dij)
+ - (P - Q) * (W - row_tot[i]));
+ d_xy_cum += fij * pow2 (Dc * (Dij - Cij)
+ - (Q - P) * (W - col_tot[j]));
}
if (++j == n_cols)
}
btau_var = ((btau_cum
- - (W * sqr (W * (P - Q) / sqrt (Dr * Dc) * (Dr + Dc))))
- / sqr (Dr * Dc));
+ - (W * pow2 (W * (P - Q) / sqrt (Dr * Dc) * (Dr + Dc))))
+ / pow2 (Dr * Dc));
if (cmd.a_statistics[CRS_ST_BTAU])
{
ase[3] = sqrt (btau_var);
somers_d_ase[0] = 2. * btau_var / (Dr + Dc) * sqrt (Dr * Dc);
somers_d_t[0] = (somers_d_v[0]
/ (4 / (Dc + Dr)
- * sqrt (ctau_cum - sqr (P - Q) / W)));
+ * sqrt (ctau_cum - pow2 (P - Q) / W)));
somers_d_v[1] = (P - Q) / Dc;
- somers_d_ase[1] = 2. / sqr (Dc) * sqrt (d_xy_cum);
+ somers_d_ase[1] = 2. / pow2 (Dc) * sqrt (d_xy_cum);
somers_d_t[1] = (somers_d_v[1]
/ (2. / Dc
- * sqrt (ctau_cum - sqr (P - Q) / W)));
+ * sqrt (ctau_cum - pow2 (P - Q) / W)));
somers_d_v[2] = (P - Q) / Dr;
- somers_d_ase[2] = 2. / sqr (Dr) * sqrt (d_yx_cum);
+ somers_d_ase[2] = 2. / pow2 (Dr) * sqrt (d_yx_cum);
somers_d_t[2] = (somers_d_v[2]
/ (2. / Dr
- * sqrt (ctau_cum - sqr (P - Q) / W)));
+ * sqrt (ctau_cum - pow2 (P - Q) / W)));
}
free (cum);
/ (W * (W * W - sum_rici) * (W * W - sum_rici)));
#if 0
t[8] = v[8] / sqrt (W * (((sum_fii * (W - sum_fii))
- / sqr (W * W - sum_rici))
+ / pow2 (W * W - sum_rici))
+ ((2. * (W - sum_fii)
* (2. * sum_fii * sum_rici
- W * sum_fiiri_ci))
/ cube (W * W - sum_rici))
- + (sqr (W - sum_fii)
+ + (pow2 (W - sum_fii)
* (W * sum_fijri_ci2 - 4.
* sum_rici * sum_rici)
- / hypercube (W * W - sum_rici))));
+ / pow4 (W * W - sum_rici))));
#else
t[8] = v[8] / ase[8];
#endif
{
const int deltaj = j == cm_index;
accum += (mat[j + i * n_cols]
- * sqr ((j == fim_index[i])
+ * pow2 ((j == fim_index[i])
- deltaj
+ v[0] * deltaj));
}
if (cm_index != fim_index[i])
accum += (mat[i * n_cols + fim_index[i]]
+ mat[i * n_cols + cm_index]);
- t[2] = v[2] / (sqrt (accum - sqr (sum_fim - cm) / W) / (W - cm));
+ t[2] = v[2] / (sqrt (accum - pow2 (sum_fim - cm) / W) / (W - cm));
}
/* ASE1 for X given Y. */
{
const int deltaj = i == rm_index;
accum += (mat[j + i * n_cols]
- * sqr ((i == fmj_index[j])
+ * pow2 ((i == fmj_index[j])
- deltaj
+ v[0] * deltaj));
}
if (rm_index != fmj_index[j])
accum += (mat[j + n_cols * fmj_index[j]]
+ mat[j + n_cols * rm_index]);
- t[1] = v[1] / (sqrt (accum - sqr (sum_fmj - rm) / W) / (W - rm));
+ t[1] = v[1] / (sqrt (accum - pow2 (sum_fmj - rm) / W) / (W - rm));
}
/* Symmetric ASE0 and ASE1. */
{
int temp0 = (fmj_index[j] == i) + (fim_index[i] == j);
int temp1 = (i == rm_index) + (j == cm_index);
- accum0 += mat[j + i * n_cols] * sqr (temp0 - temp1);
+ accum0 += mat[j + i * n_cols] * pow2 (temp0 - temp1);
accum1 += (mat[j + i * n_cols]
- * sqr (temp0 + (v[0] - 1.) * temp1));
+ * pow2 (temp0 + (v[0] - 1.) * temp1));
}
ase[0] = sqrt (accum1 - 4. * W * v[0] * v[0]) / (2. * W - rm - cm);
- t[0] = v[0] / (sqrt (accum0 - sqr ((sum_fim + sum_fmj - cm - rm) / W))
+ t[0] = v[0] / (sqrt (accum0 - pow2 ((sum_fim + sum_fmj - cm - rm) / W))
/ (2. * W - rm - cm));
}
for (sum_fij2_ri = sum_fij2_ci = 0., i = 0; i < n_rows; i++)
for (j = 0; j < n_cols; j++)
{
- double temp = sqr (mat[j + i * n_cols]);
+ double temp = pow2 (mat[j + i * n_cols]);
sum_fij2_ri += temp / row_tot[i];
sum_fij2_ci += temp / col_tot[j];
}
if (entry <= 0.)
continue;
- P += entry * sqr (log (col_tot[j] * row_tot[i] / (W * entry)));
+ P += entry * pow2 (log (col_tot[j] * row_tot[i] / (W * entry)));
UXY -= entry / W * log (entry / W);
}
if (entry <= 0.)
continue;
- ase1_yx += entry * sqr (UY * log (entry / row_tot[i])
+ ase1_yx += entry * pow2 (UY * log (entry / row_tot[i])
+ (UX - UXY) * log (col_tot[j] / W));
- ase1_xy += entry * sqr (UX * log (entry / col_tot[j])
+ ase1_xy += entry * pow2 (UX * log (entry / col_tot[j])
+ (UY - UXY) * log (row_tot[i] / W));
- ase1_sym += entry * sqr ((UXY
+ ase1_sym += entry * pow2 ((UXY
* log (row_tot[i] * col_tot[j] / (W * W)))
- (UX + UY) * log (entry / W));
}
v[5] = 2. * ((UX + UY - UXY) / (UX + UY));
- ase[5] = (2. / (W * sqr (UX + UY))) * sqrt (ase1_sym);
+ ase[5] = (2. / (W * pow2 (UX + UY))) * sqrt (ase1_sym);
t[5] = v[5] / ((2. / (W * (UX + UY)))
- * sqrt (P - sqr (UX + UY - UXY) / W));
+ * sqrt (P - pow2 (UX + UY - UXY) / W));
v[6] = (UX + UY - UXY) / UX;
ase[6] = sqrt (ase1_xy) / (W * UX * UX);
- t[6] = v[6] / (sqrt (P - W * sqr (UX + UY - UXY)) / (W * UX));
+ t[6] = v[6] / (sqrt (P - W * pow2 (UX + UY - UXY)) / (W * UX));
v[7] = (UX + UY - UXY) / UY;
ase[7] = sqrt (ase1_yx) / (W * UY * UY);
- t[7] = v[7] / (sqrt (P - W * sqr (UX + UY - UXY)) / (W * UY));
+ t[7] = v[7] / (sqrt (P - W * pow2 (UX + UY - UXY)) / (W * UY));
}
/* Somers' D. */
return 1;
}
+/* A wrapper around data_out() that limits string output to short
+ string width and null terminates the result. */
+static void
+format_short (char *s, const struct fmt_spec *fp, const union value *v)
+{
+ struct fmt_spec fmt_subst;
+
+ /* Limit to short string width. */
+ if (formats[fp->type].cat & FCAT_STRING)
+ {
+ fmt_subst = *fp;
+
+ assert (fmt_subst.type == FMT_A || fmt_subst.type == FMT_AHEX);
+ if (fmt_subst.type == FMT_A)
+ fmt_subst.w = min (8, fmt_subst.w);
+ else
+ fmt_subst.w = min (16, fmt_subst.w);
+
+ fp = &fmt_subst;
+ }
+
+ /* Format. */
+ data_out (s, fp, v);
+
+ /* Null terminate. */
+ s[fp->w] = '\0';
+}
+
/*
Local Variables:
mode: c