From ee2ee85900cb6e917678ff8621da0c8ef275f12a Mon Sep 17 00:00:00 2001 From: John Darrington Date: Fri, 8 Oct 2010 11:12:04 +0200 Subject: [PATCH] Replace npar.q with npar.c --- src/language/stats/.gitignore | 1 - src/language/stats/automake.mk | 2 +- src/language/stats/{npar.q => npar.c} | 402 +++++++++++++++++++------- 3 files changed, 296 insertions(+), 109 deletions(-) rename src/language/stats/{npar.q => npar.c} (59%) diff --git a/src/language/stats/.gitignore b/src/language/stats/.gitignore index dddbdb32..8b9a1e75 100644 --- a/src/language/stats/.gitignore +++ b/src/language/stats/.gitignore @@ -1,7 +1,6 @@ crosstabs.c examine.c frequencies.c -npar.c rank.c regression.c t-test.c diff --git a/src/language/stats/automake.mk b/src/language/stats/automake.mk index eb0a6eb3..e11a8de5 100644 --- a/src/language/stats/automake.mk +++ b/src/language/stats/automake.mk @@ -6,7 +6,6 @@ src_language_stats_built_sources = \ src/language/stats/crosstabs.c \ src/language/stats/examine.c \ src/language/stats/frequencies.c \ - src/language/stats/npar.c \ src/language/stats/rank.c \ src/language/stats/regression.c \ src/language/stats/t-test.c @@ -30,6 +29,7 @@ language_stats_sources = \ src/language/stats/freq.c \ src/language/stats/freq.h \ src/language/stats/glm.c \ + src/language/stats/npar.c \ src/language/stats/npar-summary.c \ src/language/stats/npar-summary.h \ src/language/stats/oneway.c \ diff --git a/src/language/stats/npar.q b/src/language/stats/npar.c similarity index 59% rename from src/language/stats/npar.q rename to src/language/stats/npar.c index 53579722..1b4af1a0 100644 --- a/src/language/stats/npar.q +++ b/src/language/stats/npar.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. -*-c-*- - Copyright (C) 2006, 2008, 2009 Free Software Foundation, Inc. + Copyright (C) 2006, 2008, 2009, 2010 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,16 +16,20 @@ #include - #include +#include "npar-summary.h" +#include #include +#include "xalloc.h" #include #include #include #include #include +#include +#include #include #include #include @@ -33,39 +37,68 @@ #include #include #include +#include #include #include +#include #include +#include #include #include -#include "npar-summary.h" - #include "gettext.h" #define _(msgid) gettext (msgid) -/* (headers) */ - -/* (specification) - "NPAR TESTS" (npar_): - +chisquare=custom; - +binomial=custom; - +wilcoxon=custom; - +mcnemar=custom; - +sign=custom; - +cochran=varlist; - +friedman=varlist; - +kendall=varlist; - missing=miss:!analysis/listwise, - incl:include/!exclude; - method=custom; - +statistics[st_]=descriptives,quartiles,all. -*/ -/* (declarations) */ -/* (functions) */ - - -static struct cmd_npar_tests cmd; +struct dataset; +/* Settings for subcommand specifiers. */ +enum + { + NPAR_ANALYSIS, + NPAR_LISTWISE, + }; + +enum + { + NPAR_INCLUDE, + NPAR_EXCLUDE + }; + +/* Array indices for STATISTICS subcommand. */ +enum + { + NPAR_ST_DESCRIPTIVES = 0, + NPAR_ST_QUARTILES = 1, + NPAR_ST_ALL = 2, + NPAR_ST_count + }; + +/* NPAR TESTS structure. */ +struct cmd_npar_tests + { + /* CHISQUARE subcommand. */ + int chisquare; + + /* BINOMIAL subcommand. */ + int binomial; + + /* WILCOXON subcommand. */ + int wilcoxon; + + /* SIGN subcommand. */ + int sign; + + /* MISSING subcommand. */ + int missing; + long miss; + long incl; + + /* METHOD subcommand. */ + int method; + + /* STATISTICS subcommand. */ + int statistics; + int a_statistics[NPAR_ST_count]; + }; struct npar_specs @@ -74,7 +107,7 @@ struct npar_specs struct npar_test **test; size_t n_tests; - const struct variable ** vv; /* Compendium of all variables + const struct variable **vv; /* Compendium of all variables (those mentioned on ANY subcommand */ int n_vars; /* Number of variables in vv */ @@ -87,6 +120,198 @@ struct npar_specs double timer; /* Maximum time (in minutes) to wait for exact calculations */ }; + +/* Prototype for custom subcommands of NPAR TESTS. */ +static int npar_chisquare (struct lexer *, struct dataset *, struct npar_specs *); +static int npar_binomial (struct lexer *, struct dataset *, struct npar_specs *); +static int npar_wilcoxon (struct lexer *, struct dataset *, struct npar_specs *); +static int npar_sign (struct lexer *, struct dataset *, struct npar_specs *); +static int npar_method (struct lexer *, struct npar_specs *); + +/* Command parsing functions. */ +static int parse_npar_tests (struct lexer *lexer, struct dataset *ds, struct cmd_npar_tests *p, + struct npar_specs *npar_specs ); + +static int +parse_npar_tests (struct lexer *lexer, struct dataset *ds, struct cmd_npar_tests *npt, + struct npar_specs *nps) +{ + npt->chisquare = 0; + npt->binomial = 0; + npt->wilcoxon = 0; + npt->sign = 0; + npt->missing = 0; + npt->miss = NPAR_ANALYSIS; + npt->incl = NPAR_EXCLUDE; + npt->method = 0; + npt->statistics = 0; + memset (npt->a_statistics, 0, sizeof npt->a_statistics); + for (;;) + { + if (lex_match_hyphenated_word (lexer, "CHISQUARE")) + { + lex_match (lexer, '='); + npt->chisquare++; + switch (npar_chisquare (lexer, ds, nps)) + { + case 0: + goto lossage; + case 1: + break; + case 2: + lex_error (lexer, NULL); + goto lossage; + default: + NOT_REACHED (); + } + } + else if (lex_match_hyphenated_word (lexer, "BINOMIAL")) + { + lex_match (lexer, '='); + npt->binomial++; + switch (npar_binomial (lexer, ds, nps)) + { + case 0: + goto lossage; + case 1: + break; + case 2: + lex_error (lexer, NULL); + goto lossage; + default: + NOT_REACHED (); + } + } + else if (lex_match_hyphenated_word (lexer, "WILCOXON")) + { + lex_match (lexer, '='); + npt->wilcoxon++; + switch (npar_wilcoxon (lexer, ds, nps)) + { + case 0: + goto lossage; + case 1: + break; + case 2: + lex_error (lexer, NULL); + goto lossage; + default: + NOT_REACHED (); + } + } + else if (lex_match_hyphenated_word (lexer, "SIGN")) + { + lex_match (lexer, '='); + npt->sign++; + switch (npar_sign (lexer, ds, nps)) + { + case 0: + goto lossage; + case 1: + break; + case 2: + lex_error (lexer, NULL); + goto lossage; + default: + NOT_REACHED (); + } + } + else if (lex_match_hyphenated_word (lexer, "MISSING")) + { + lex_match (lexer, '='); + npt->missing++; + if (npt->missing > 1) + { + msg (SE, _ ("MISSING subcommand may be given only once.")); + goto lossage; + } + while (lex_token (lexer) != '/' && lex_token (lexer) != '.') + { + if (lex_match_hyphenated_word (lexer, "ANALYSIS")) + npt->miss = NPAR_ANALYSIS; + else if (lex_match_hyphenated_word (lexer, "LISTWISE")) + npt->miss = NPAR_LISTWISE; + else if (lex_match_hyphenated_word (lexer, "INCLUDE")) + npt->incl = NPAR_INCLUDE; + else if (lex_match_hyphenated_word (lexer, "EXCLUDE")) + npt->incl = NPAR_EXCLUDE; + else + { + lex_error (lexer, NULL); + goto lossage; + } + lex_match (lexer, ','); + } + } + else if (lex_match_hyphenated_word (lexer, "METHOD")) + { + lex_match (lexer, '='); + npt->method++; + if (npt->method > 1) + { + msg (SE, _ ("METHOD subcommand may be given only once.")); + goto lossage; + } + switch (npar_method (lexer, nps)) + { + case 0: + goto lossage; + case 1: + break; + case 2: + lex_error (lexer, NULL); + goto lossage; + default: + NOT_REACHED (); + } + } + else if (lex_match_hyphenated_word (lexer, "STATISTICS")) + { + lex_match (lexer, '='); + npt->statistics++; + while (lex_token (lexer) != '/' && lex_token (lexer) != '.') + { + if (lex_match_hyphenated_word (lexer, "DESCRIPTIVES")) + npt->a_statistics[NPAR_ST_DESCRIPTIVES] = 1; + else if (lex_match_hyphenated_word (lexer, "QUARTILES")) + npt->a_statistics[NPAR_ST_QUARTILES] = 1; + else if (lex_match (lexer, T_ALL)) + npt->a_statistics[NPAR_ST_ALL] = 1; + else + { + lex_error (lexer, NULL); + goto lossage; + } + lex_match (lexer, ','); + } + } + else if ( settings_get_syntax () != COMPATIBLE && lex_match_id (lexer, "ALGORITHM")) + { + lex_match (lexer, '='); + if (lex_match_id (lexer, "COMPATIBLE")) + settings_set_cmd_algorithm (COMPATIBLE); + else if (lex_match_id (lexer, "ENHANCED")) + settings_set_cmd_algorithm (ENHANCED); + } + if (!lex_match (lexer, '/')) + break; + } + + if (lex_token (lexer) != '.') + { + lex_error (lexer, _ ("expecting end of command")); + goto lossage; + } + + return true; + +lossage: + return false; +} + + + + static void one_sample_insert_variables (const struct npar_test *test, struct const_hsh_table *variables); @@ -94,9 +319,8 @@ static void two_sample_insert_variables (const struct npar_test *test, struct const_hsh_table *variables); - static void -npar_execute(struct casereader *input, +npar_execute (struct casereader *input, const struct npar_specs *specs, const struct dataset *ds) { @@ -108,7 +332,7 @@ npar_execute(struct casereader *input, const struct npar_test *test = specs->test[t]; if ( NULL == test->execute ) { - msg (SW, _("NPAR subcommand not currently implemented.")); + msg (SW, _ ("NPAR subcommand not currently implemented.")); continue; } test->execute (ds, casereader_clone (input), specs->filter, test, specs->exact, specs->timer); @@ -138,6 +362,7 @@ npar_execute(struct casereader *input, int cmd_npar_tests (struct lexer *lexer, struct dataset *ds) { + struct cmd_npar_tests cmd; bool ok; int i; struct npar_specs npar_specs = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; @@ -166,7 +391,7 @@ cmd_npar_tests (struct lexer *lexer, struct dataset *ds) npar_specs.vv = (const struct variable **) const_hsh_sort (var_hash); npar_specs.n_vars = const_hsh_count (var_hash); - if ( cmd.sbc_statistics ) + if ( cmd.statistics ) { int i; @@ -187,7 +412,7 @@ cmd_npar_tests (struct lexer *lexer, struct dataset *ds) npar_specs.descriptives = true; break; default: - NOT_REACHED(); + NOT_REACHED (); }; } } @@ -219,13 +444,11 @@ cmd_npar_tests (struct lexer *lexer, struct dataset *ds) return ok ? CMD_SUCCESS : CMD_CASCADING_FAILURE; } -int -npar_custom_chisquare (struct lexer *lexer, struct dataset *ds, - struct cmd_npar_tests *cmd UNUSED, void *aux ) +static int +npar_chisquare (struct lexer *lexer, struct dataset *ds, + struct npar_specs *specs) { - struct npar_specs *specs = aux; - - struct chisquare_test *cstp = pool_alloc(specs->pool, sizeof(*cstp)); + struct chisquare_test *cstp = pool_alloc (specs->pool, sizeof (*cstp)); struct one_sample_test *tp = &cstp->parent; struct npar_test *nt = &tp->parent; @@ -252,8 +475,8 @@ npar_custom_chisquare (struct lexer *lexer, struct dataset *ds, cstp->hi = lex_integer (lexer); if ( cstp->lo >= cstp->hi ) { - msg(ME, - _("The specified value of HI (%d) is " + msg (ME, + _ ("The specified value of HI (%d) is " "lower than the specified value of LO (%d)"), cstp->hi, cstp->lo); return 0; @@ -273,7 +496,7 @@ npar_custom_chisquare (struct lexer *lexer, struct dataset *ds, { double f; int n; - while ( lex_is_number(lexer) ) + while ( lex_is_number (lexer) ) { int i; n = 1; @@ -290,7 +513,7 @@ npar_custom_chisquare (struct lexer *lexer, struct dataset *ds, cstp->n_expected += n; cstp->expected = pool_realloc (specs->pool, cstp->expected, - sizeof(double) * + sizeof (double) * cstp->n_expected); for ( i = cstp->n_expected - n ; i < cstp->n_expected; @@ -307,8 +530,8 @@ npar_custom_chisquare (struct lexer *lexer, struct dataset *ds, if ( cstp->ranged && cstp->n_expected > 0 && cstp->n_expected != cstp->hi - cstp->lo + 1 ) { - msg(ME, - _("%d expected values were given, but the specified " + msg (ME, + _ ("%d expected values were given, but the specified " "range (%d-%d) requires exactly %d values."), cstp->n_expected, cstp->lo, cstp->hi, cstp->hi - cstp->lo +1); @@ -318,7 +541,7 @@ npar_custom_chisquare (struct lexer *lexer, struct dataset *ds, specs->n_tests++; specs->test = pool_realloc (specs->pool, specs->test, - sizeof(*specs->test) * specs->n_tests); + sizeof (*specs->test) * specs->n_tests); specs->test[specs->n_tests - 1] = nt; @@ -326,12 +549,11 @@ npar_custom_chisquare (struct lexer *lexer, struct dataset *ds, } -int -npar_custom_binomial (struct lexer *lexer, struct dataset *ds, - struct cmd_npar_tests *cmd UNUSED, void *aux) +static int +npar_binomial (struct lexer *lexer, struct dataset *ds, + struct npar_specs *specs) { - struct npar_specs *specs = aux; - struct binomial_test *btp = pool_alloc(specs->pool, sizeof(*btp)); + struct binomial_test *btp = pool_alloc (specs->pool, sizeof (*btp)); struct one_sample_test *tp = &btp->parent; struct npar_test *nt = &tp->parent; @@ -357,14 +579,13 @@ npar_custom_binomial (struct lexer *lexer, struct dataset *ds, /* Kludge: q2c swallows the '=' so put it back here */ lex_put_back (lexer, '='); - - if ( lex_match (lexer, '=') ) + if (lex_match (lexer, '=') ) { if (parse_variables_const_pool (lexer, specs->pool, dataset_dict (ds), &tp->vars, &tp->n_vars, PV_NUMERIC | PV_NO_SCRATCH | PV_NO_DUPLICATE) ) { - if ( lex_match (lexer, '(')) + if (lex_match (lexer, '(')) { lex_force_num (lexer); btp->category1 = lex_number (lexer); @@ -391,7 +612,7 @@ npar_custom_binomial (struct lexer *lexer, struct dataset *ds, specs->n_tests++; specs->test = pool_realloc (specs->pool, specs->test, - sizeof(*specs->test) * specs->n_tests); + sizeof (*specs->test) * specs->n_tests); specs->test[specs->n_tests - 1] = nt; @@ -399,18 +620,17 @@ npar_custom_binomial (struct lexer *lexer, struct dataset *ds, } -bool parse_two_sample_related_test (struct lexer *lexer, +static bool +parse_two_sample_related_test (struct lexer *lexer, const struct dictionary *dict, - struct cmd_npar_tests *cmd, struct two_sample_test *test_parameters, struct pool *pool ); -bool +static bool parse_two_sample_related_test (struct lexer *lexer, const struct dictionary *dict, - struct cmd_npar_tests *cmd UNUSED, struct two_sample_test *test_parameters, struct pool *pool ) @@ -432,7 +652,7 @@ parse_two_sample_related_test (struct lexer *lexer, PV_NUMERIC | PV_NO_SCRATCH | PV_NO_DUPLICATE) ) return false; - if ( lex_match(lexer, T_WITH)) + if ( lex_match (lexer, T_WITH)) { with = true; if ( !parse_variables_const_pool (lexer, pool, dict, @@ -450,7 +670,7 @@ parse_two_sample_related_test (struct lexer *lexer, if (paired) { if ( n_vlist1 != n_vlist2) - msg (SE, _("PAIRED was specified but the number of variables " + msg (SE, _ ("PAIRED was specified but the number of variables " "preceding WITH (%zu) did not match the number " "following (%zu)."), n_vlist1, n_vlist2); @@ -516,74 +736,47 @@ parse_two_sample_related_test (struct lexer *lexer, return true; } -int -npar_custom_wilcoxon (struct lexer *lexer, - struct dataset *ds, - struct cmd_npar_tests *cmd, void *aux ) +static int +npar_wilcoxon (struct lexer *lexer, + struct dataset *ds, + struct npar_specs *specs ) { - struct npar_specs *specs = aux; - - struct two_sample_test *tp = pool_alloc (specs->pool, sizeof(*tp)); - struct npar_test *nt = &tp->parent; - nt->execute = wilcoxon_execute; - if (!parse_two_sample_related_test (lexer, dataset_dict (ds), cmd, - tp, specs->pool) ) - return 0; - specs->n_tests++; - specs->test = pool_realloc (specs->pool, - specs->test, - sizeof(*specs->test) * specs->n_tests); - specs->test[specs->n_tests - 1] = nt; - - return 1; -} - -int -npar_custom_mcnemar (struct lexer *lexer, - struct dataset *ds, - struct cmd_npar_tests *cmd, void *aux ) -{ - struct npar_specs *specs = aux; - - struct two_sample_test *tp = pool_alloc(specs->pool, sizeof(*tp)); + struct two_sample_test *tp = pool_alloc (specs->pool, sizeof (*tp)); struct npar_test *nt = &tp->parent; - nt->execute = NULL; - + nt->execute = wilcoxon_execute; if (!parse_two_sample_related_test (lexer, dataset_dict (ds), - cmd, tp, specs->pool) ) + tp, specs->pool) ) return 0; specs->n_tests++; specs->test = pool_realloc (specs->pool, specs->test, - sizeof(*specs->test) * specs->n_tests); + sizeof (*specs->test) * specs->n_tests); specs->test[specs->n_tests - 1] = nt; return 1; } -int -npar_custom_sign (struct lexer *lexer, struct dataset *ds, - struct cmd_npar_tests *cmd, void *aux ) +static int +npar_sign (struct lexer *lexer, struct dataset *ds, + struct npar_specs *specs) { - struct npar_specs *specs = aux; - - struct two_sample_test *tp = pool_alloc(specs->pool, sizeof(*tp)); + struct two_sample_test *tp = pool_alloc (specs->pool, sizeof (*tp)); struct npar_test *nt = &tp->parent; nt->execute = sign_execute; - if (!parse_two_sample_related_test (lexer, dataset_dict (ds), cmd, + if (!parse_two_sample_related_test (lexer, dataset_dict (ds), tp, specs->pool) ) return 0; specs->n_tests++; specs->test = pool_realloc (specs->pool, specs->test, - sizeof(*specs->test) * specs->n_tests); + sizeof (*specs->test) * specs->n_tests); specs->test[specs->n_tests - 1] = nt; return 1; @@ -616,16 +809,11 @@ two_sample_insert_variables (const struct npar_test *test, const_hsh_insert (var_hash, (*pair)[0]); const_hsh_insert (var_hash, (*pair)[1]); } - } - static int -npar_custom_method (struct lexer *lexer, struct dataset *ds UNUSED, - struct cmd_npar_tests *test UNUSED, void *aux) +npar_method (struct lexer *lexer, struct npar_specs *specs) { - struct npar_specs *specs = aux; - if ( lex_match_id (lexer, "EXACT") ) { specs->exact = true; -- 2.30.2