X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flanguage%2Fstats%2Fnpar.c;h=eada5d16496db6195b78eb6463db9f03a5c4ec30;hb=c5d4a219c4f28f2a0adb223be62fe4bb8df02f8f;hp=7dd94f7813df4f4f11ed5690f002bb6e6c65f74b;hpb=55e6e7ba37a30570f5a31e2d78c22dfa7b61a36f;p=pspp diff --git a/src/language/stats/npar.c b/src/language/stats/npar.c index 7dd94f7813..eada5d1649 100644 --- a/src/language/stats/npar.c +++ b/src/language/stats/npar.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. -*-c-*- - Copyright (C) 2006, 2008, 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 2006, 2008, 2009, 2010, 2011, 2016 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,44 +16,48 @@ #include -#include -#include "npar-summary.h" +#include "language/stats/npar.h" #include #include -#include "xalloc.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include "data/case.h" +#include "data/casegrouper.h" +#include "data/casereader.h" +#include "data/dataset.h" +#include "data/dictionary.h" +#include "data/settings.h" +#include "data/variable.h" +#include "language/command.h" +#include "language/lexer/lexer.h" +#include "language/lexer/value-parser.h" +#include "language/lexer/variable-parser.h" +#include "language/stats/binomial.h" +#include "language/stats/chisquare.h" +#include "language/stats/ks-one-sample.h" +#include "language/stats/cochran.h" +#include "language/stats/friedman.h" +#include "language/stats/jonckheere-terpstra.h" +#include "language/stats/kruskal-wallis.h" +#include "language/stats/mann-whitney.h" +#include "language/stats/mcnemar.h" +#include "language/stats/median.h" +#include "language/stats/npar-summary.h" +#include "language/stats/runs.h" +#include "language/stats/sign.h" +#include "language/stats/wilcoxon.h" +#include "libpspp/array.h" +#include "libpspp/assertion.h" +#include "libpspp/cast.h" +#include "libpspp/hash-functions.h" +#include "libpspp/hmapx.h" +#include "libpspp/message.h" +#include "libpspp/pool.h" +#include "libpspp/str.h" +#include "libpspp/taint.h" +#include "math/moments.h" + +#include "gl/xalloc.h" #include "gettext.h" #define _(msgid) gettext (msgid) @@ -82,6 +86,7 @@ struct cmd_npar_tests int chisquare; int cochran; int binomial; + int ks_one_sample; int wilcoxon; int sign; int runs; @@ -89,6 +94,9 @@ struct cmd_npar_tests int kendall; int kruskal_wallis; int mann_whitney; + int mcnemar; + int median; + int jonckheere_terpstra; int missing; int method; int statistics; @@ -124,6 +132,7 @@ struct npar_specs /* 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_ks_one_sample (struct lexer *, struct dataset *, struct npar_specs *); static int npar_runs (struct lexer *, struct dataset *, struct npar_specs *); static int npar_friedman (struct lexer *, struct dataset *, struct npar_specs *); static int npar_kendall (struct lexer *, struct dataset *, struct npar_specs *); @@ -131,34 +140,45 @@ static int npar_cochran (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_kruskal_wallis (struct lexer *, struct dataset *, struct npar_specs *); +static int npar_jonckheere_terpstra (struct lexer *, struct dataset *, struct npar_specs *); static int npar_mann_whitney (struct lexer *, struct dataset *, struct npar_specs *); +static int npar_mcnemar (struct lexer *, struct dataset *, struct npar_specs *); +static int npar_median (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 ); + 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->binomial = 0; npt->chisquare = 0; npt->cochran = 0; + npt->binomial = 0; + npt->ks_one_sample = 0; + npt->wilcoxon = 0; + npt->sign = 0; + npt->runs = 0; npt->friedman = 0; + npt->kendall = 0; npt->kruskal_wallis = 0; npt->mann_whitney = 0; - npt->runs = 0; - npt->sign = 0; - npt->wilcoxon = 0; - npt->missing = 0; + npt->mcnemar = 0; + npt->median = 0; + npt->jonckheere_terpstra = 0; + npt->miss = MISS_ANALYSIS; + npt->missing = 0; npt->method = 0; npt->statistics = 0; + memset (npt->a_statistics, 0, sizeof npt->a_statistics); for (;;) { - if (lex_match_hyphenated_word (lexer, "COCHRAN")) + if (lex_match_id (lexer, "COCHRAN")) { npt->cochran++; switch (npar_cochran (lexer, ds, nps)) @@ -174,7 +194,7 @@ parse_npar_tests (struct lexer *lexer, struct dataset *ds, struct cmd_npar_tests NOT_REACHED (); } } - else if (lex_match_hyphenated_word (lexer, "FRIEDMAN")) + else if (lex_match_id (lexer, "FRIEDMAN")) { npt->friedman++; switch (npar_friedman (lexer, ds, nps)) @@ -190,7 +210,7 @@ parse_npar_tests (struct lexer *lexer, struct dataset *ds, struct cmd_npar_tests NOT_REACHED (); } } - else if (lex_match_hyphenated_word (lexer, "KENDALL")) + else if (lex_match_id (lexer, "KENDALL")) { npt->kendall++; switch (npar_kendall (lexer, ds, nps)) @@ -206,7 +226,7 @@ parse_npar_tests (struct lexer *lexer, struct dataset *ds, struct cmd_npar_tests NOT_REACHED (); } } - else if (lex_match_hyphenated_word (lexer, "RUNS")) + else if (lex_match_id (lexer, "RUNS")) { npt->runs++; switch (npar_runs (lexer, ds, nps)) @@ -222,7 +242,7 @@ parse_npar_tests (struct lexer *lexer, struct dataset *ds, struct cmd_npar_tests NOT_REACHED (); } } - else if (lex_match_hyphenated_word (lexer, "CHISQUARE")) + else if (lex_match_id (lexer, "CHISQUARE")) { lex_match (lexer, T_EQUALS); npt->chisquare++; @@ -235,11 +255,13 @@ parse_npar_tests (struct lexer *lexer, struct dataset *ds, struct cmd_npar_tests case 2: lex_error (lexer, NULL); goto lossage; + case 3: + continue; default: NOT_REACHED (); } } - else if (lex_match_hyphenated_word (lexer, "BINOMIAL")) + else if (lex_match_id (lexer, "BINOMIAL")) { lex_match (lexer, T_EQUALS); npt->binomial++; @@ -256,8 +278,44 @@ parse_npar_tests (struct lexer *lexer, struct dataset *ds, struct cmd_npar_tests NOT_REACHED (); } } - else if (lex_match_hyphenated_word (lexer, "K-W") || - lex_match_hyphenated_word (lexer, "KRUSKAL-WALLIS")) + else if (lex_match_phrase (lexer, "K-S") || + lex_match_phrase (lexer, "KOLMOGOROV-SMIRNOV")) + { + lex_match (lexer, T_EQUALS); + npt->ks_one_sample++; + switch (npar_ks_one_sample (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_phrase (lexer, "J-T") || + lex_match_phrase (lexer, "JONCKHEERE-TERPSTRA")) + { + lex_match (lexer, T_EQUALS); + npt->jonckheere_terpstra++; + switch (npar_jonckheere_terpstra (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_phrase (lexer, "K-W") || + lex_match_phrase (lexer, "KRUSKAL-WALLIS")) { lex_match (lexer, T_EQUALS); npt->kruskal_wallis++; @@ -274,8 +332,25 @@ parse_npar_tests (struct lexer *lexer, struct dataset *ds, struct cmd_npar_tests NOT_REACHED (); } } - else if (lex_match_hyphenated_word (lexer, "M-W") || - lex_match_hyphenated_word (lexer, "MANN-WHITNEY")) + else if (lex_match_phrase (lexer, "MCNEMAR")) + { + lex_match (lexer, T_EQUALS); + npt->mcnemar++; + switch (npar_mcnemar (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_phrase (lexer, "M-W") || + lex_match_phrase (lexer, "MANN-WHITNEY")) { lex_match (lexer, T_EQUALS); npt->mann_whitney++; @@ -291,8 +366,25 @@ parse_npar_tests (struct lexer *lexer, struct dataset *ds, struct cmd_npar_tests default: NOT_REACHED (); } + } + else if (lex_match_phrase (lexer, "MEDIAN")) + { + npt->median++; + + switch (npar_median (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")) + else if (lex_match_id (lexer, "WILCOXON")) { lex_match (lexer, T_EQUALS); npt->wilcoxon++; @@ -309,7 +401,7 @@ parse_npar_tests (struct lexer *lexer, struct dataset *ds, struct cmd_npar_tests NOT_REACHED (); } } - else if (lex_match_hyphenated_word (lexer, "SIGN")) + else if (lex_match_id (lexer, "SIGN")) { lex_match (lexer, T_EQUALS); npt->sign++; @@ -326,24 +418,24 @@ parse_npar_tests (struct lexer *lexer, struct dataset *ds, struct cmd_npar_tests NOT_REACHED (); } } - else if (lex_match_hyphenated_word (lexer, "MISSING")) + else if (lex_match_id (lexer, "MISSING")) { lex_match (lexer, T_EQUALS); npt->missing++; if (npt->missing > 1) { - msg (SE, _("The %s subcommand may be given only once."), "MISSING"); + lex_sbc_only_once ("MISSING"); goto lossage; } while (lex_token (lexer) != T_SLASH && lex_token (lexer) != T_ENDCMD) { - if (lex_match_hyphenated_word (lexer, "ANALYSIS")) + if (lex_match_id (lexer, "ANALYSIS")) npt->miss = MISS_ANALYSIS; - else if (lex_match_hyphenated_word (lexer, "LISTWISE")) + else if (lex_match_id (lexer, "LISTWISE")) npt->miss = MISS_LISTWISE; - else if (lex_match_hyphenated_word (lexer, "INCLUDE")) + else if (lex_match_id (lexer, "INCLUDE")) nps->filter = MV_SYSTEM; - else if (lex_match_hyphenated_word (lexer, "EXCLUDE")) + else if (lex_match_id (lexer, "EXCLUDE")) nps->filter = MV_ANY; else { @@ -353,13 +445,13 @@ parse_npar_tests (struct lexer *lexer, struct dataset *ds, struct cmd_npar_tests lex_match (lexer, T_COMMA); } } - else if (lex_match_hyphenated_word (lexer, "METHOD")) + else if (lex_match_id (lexer, "METHOD")) { lex_match (lexer, T_EQUALS); npt->method++; if (npt->method > 1) { - msg (SE, _("The %s subcommand may be given only once."), "METHOD"); + lex_sbc_only_once ("METHOD"); goto lossage; } switch (npar_method (lexer, nps)) @@ -375,15 +467,15 @@ parse_npar_tests (struct lexer *lexer, struct dataset *ds, struct cmd_npar_tests NOT_REACHED (); } } - else if (lex_match_hyphenated_word (lexer, "STATISTICS")) + else if (lex_match_id (lexer, "STATISTICS")) { lex_match (lexer, T_EQUALS); npt->statistics++; while (lex_token (lexer) != T_SLASH && lex_token (lexer) != T_ENDCMD) { - if (lex_match_hyphenated_word (lexer, "DESCRIPTIVES")) + if (lex_match_id (lexer, "DESCRIPTIVES")) npt->a_statistics[NPAR_ST_DESCRIPTIVES] = 1; - else if (lex_match_hyphenated_word (lexer, "QUARTILES")) + else if (lex_match_id (lexer, "QUARTILES")) npt->a_statistics[NPAR_ST_QUARTILES] = 1; else if (lex_match (lexer, T_ALL)) npt->a_statistics[NPAR_ST_ALL] = 1; @@ -395,7 +487,7 @@ parse_npar_tests (struct lexer *lexer, struct dataset *ds, struct cmd_npar_tests lex_match (lexer, T_COMMA); } } - else if ( settings_get_syntax () != COMPATIBLE && lex_match_id (lexer, "ALGORITHM")) + else if (settings_get_syntax () != COMPATIBLE && lex_match_id (lexer, "ALGORITHM")) { lex_match (lexer, T_EQUALS); if (lex_match_id (lexer, "COMPATIBLE")) @@ -406,7 +498,6 @@ parse_npar_tests (struct lexer *lexer, struct dataset *ds, struct cmd_npar_tests if (!lex_match (lexer, T_SLASH)) break; } - if (lex_token (lexer) != T_ENDCMD) { lex_error (lexer, _("expecting end of command")); @@ -437,18 +528,18 @@ npar_execute (struct casereader *input, int t; struct descriptives *summary_descriptives = NULL; - for ( t = 0 ; t < specs->n_tests; ++t ) + for (t = 0 ; t < specs->n_tests; ++t) { const struct npar_test *test = specs->test[t]; - if ( NULL == test->execute ) + if (NULL == test->execute) { - msg (SW, _("NPAR subcommand not currently implemented.")); + msg (SW, _("%s subcommand not currently implemented."), "NPAR"); continue; } test->execute (ds, casereader_clone (input), specs->filter, test, specs->exact, specs->timer); } - if ( specs->descriptives ) + if (specs->descriptives && specs->n_vars > 0) { summary_descriptives = xnmalloc (sizeof (*summary_descriptives), specs->n_vars); @@ -460,9 +551,10 @@ npar_execute (struct casereader *input, specs->filter); } - if ( (specs->descriptives || specs->quartiles) - && !taint_has_tainted_successor (casereader_get_taint (input)) ) - do_summary_box (summary_descriptives, specs->vv, specs->n_vars ); + if ((specs->descriptives || specs->quartiles) + && !taint_has_tainted_successor (casereader_get_taint (input))) + do_summary_box (summary_descriptives, specs->vv, specs->n_vars, + dict_get_weight_format (dataset_dict (ds))); free (summary_descriptives); casereader_destroy (input); @@ -485,13 +577,13 @@ cmd_npar_tests (struct lexer *lexer, struct dataset *ds) npar_specs.n_vars = -1; npar_specs.vv = NULL; - if ( ! parse_npar_tests (lexer, ds, &cmd, &npar_specs) ) + if (! parse_npar_tests (lexer, ds, &cmd, &npar_specs)) { pool_destroy (npar_specs.pool); return CMD_FAILURE; } - for (i = 0; i < npar_specs.n_tests; ++i ) + for (i = 0; i < npar_specs.n_tests; ++i) { const struct npar_test *test = npar_specs.test[i]; test->insert_variables (test, &var_map); @@ -510,18 +602,18 @@ cmd_npar_tests (struct lexer *lexer, struct dataset *ds) } } - sort (npar_specs.vv, npar_specs.n_vars, sizeof (*npar_specs.vv), + sort (npar_specs.vv, npar_specs.n_vars, sizeof (*npar_specs.vv), compare_var_ptrs_by_name, NULL); - if ( cmd.statistics ) + if (cmd.statistics) { int i; - for ( i = 0 ; i < NPAR_ST_count; ++i ) + for (i = 0 ; i < NPAR_ST_count; ++i) { - if ( cmd.a_statistics[i] ) + if (cmd.a_statistics[i]) { - switch ( i ) + switch (i) { case NPAR_ST_DESCRIPTIVES: npar_specs.descriptives = true; @@ -541,7 +633,7 @@ cmd_npar_tests (struct lexer *lexer, struct dataset *ds) } input = proc_open (ds); - if ( cmd.miss == MISS_LISTWISE ) + if (cmd.miss == MISS_LISTWISE) { input = casereader_create_filter_missing (input, npar_specs.vv, @@ -574,9 +666,9 @@ npar_runs (struct lexer *lexer, struct dataset *ds, nt->execute = runs_execute; nt->insert_variables = one_sample_insert_variables; - if ( lex_force_match (lexer, T_LPAREN) ) + if (lex_force_match (lexer, T_LPAREN)) { - if ( lex_match_id (lexer, "MEAN")) + if (lex_match_id (lexer, "MEAN")) { rt->cp_mode = CP_MEAN; } @@ -596,12 +688,16 @@ npar_runs (struct lexer *lexer, struct dataset *ds, } else { - lex_error (lexer, _("Expecting MEAN, MEDIAN, MODE or number")); + lex_error (lexer, _("Expecting %s, %s, %s or a number."), "MEAN", "MEDIAN", "MODE"); return 0; } - - lex_force_match (lexer, T_RPAREN); - lex_force_match (lexer, T_EQUALS); + + if (! lex_force_match (lexer, T_RPAREN)) + return 2; + + if (! lex_force_match (lexer, T_EQUALS)) + return 2; + if (!parse_variables_const_pool (lexer, specs->pool, dataset_dict (ds), &tp->vars, &tp->n_vars, PV_NO_SCRATCH | PV_NO_DUPLICATE | PV_NUMERIC)) @@ -624,7 +720,7 @@ static int npar_friedman (struct lexer *lexer, struct dataset *ds, struct npar_specs *specs) { - struct friedman_test *ft = pool_alloc (specs->pool, sizeof (*ft)); + struct friedman_test *ft = pool_alloc (specs->pool, sizeof (*ft)); struct one_sample_test *ost = &ft->parent; struct npar_test *nt = &ost->parent; @@ -655,7 +751,7 @@ static int npar_kendall (struct lexer *lexer, struct dataset *ds, struct npar_specs *specs) { - struct friedman_test *kt = pool_alloc (specs->pool, sizeof (*kt)); + struct friedman_test *kt = pool_alloc (specs->pool, sizeof (*kt)); struct one_sample_test *ost = &kt->parent; struct npar_test *nt = &ost->parent; @@ -687,7 +783,7 @@ static int npar_cochran (struct lexer *lexer, struct dataset *ds, struct npar_specs *specs) { - struct one_sample_test *ft = pool_alloc (specs->pool, sizeof (*ft)); + struct one_sample_test *ft = pool_alloc (specs->pool, sizeof (*ft)); struct npar_test *nt = &ft->parent; nt->execute = cochran_execute; @@ -720,7 +816,7 @@ npar_chisquare (struct lexer *lexer, struct dataset *ds, struct chisquare_test *cstp = pool_alloc (specs->pool, sizeof (*cstp)); struct one_sample_test *tp = &cstp->parent; struct npar_test *nt = &tp->parent; - + int retval = 1; nt->execute = chisquare_execute; nt->insert_variables = one_sample_insert_variables; @@ -734,16 +830,16 @@ npar_chisquare (struct lexer *lexer, struct dataset *ds, cstp->ranged = false; - if ( lex_match (lexer, T_LPAREN)) + if (lex_match (lexer, T_LPAREN)) { cstp->ranged = true; - if ( ! lex_force_num (lexer)) return 0; - cstp->lo = lex_integer (lexer); + if (! lex_force_num (lexer)) return 0; + cstp->lo = lex_number (lexer); lex_get (lexer); - lex_force_match (lexer, T_COMMA); - if (! lex_force_num (lexer) ) return 0; - cstp->hi = lex_integer (lexer); - if ( cstp->lo >= cstp->hi ) + if (! lex_force_match (lexer, T_COMMA)) return 0; + if (! lex_force_num (lexer)) return 0; + cstp->hi = lex_number (lexer); + if (cstp->lo >= cstp->hi) { msg (ME, _("The specified value of HI (%d) is " @@ -757,48 +853,45 @@ npar_chisquare (struct lexer *lexer, struct dataset *ds, cstp->n_expected = 0; cstp->expected = NULL; - if ( lex_match (lexer, T_SLASH) ) + if (lex_match_phrase (lexer, "/EXPECTED")) { - if ( lex_match_id (lexer, "EXPECTED") ) - { - lex_force_match (lexer, T_EQUALS); - if ( ! lex_match_id (lexer, "EQUAL") ) - { - double f; - int n; - while ( lex_is_number (lexer) ) - { - int i; - n = 1; - f = lex_number (lexer); - lex_get (lexer); - if ( lex_match (lexer, T_ASTERISK)) - { - n = f; - f = lex_number (lexer); - lex_get (lexer); - } - lex_match (lexer, T_COMMA); - - cstp->n_expected += n; - cstp->expected = pool_realloc (specs->pool, - cstp->expected, - sizeof (double) * - cstp->n_expected); - for ( i = cstp->n_expected - n ; - i < cstp->n_expected; - ++i ) - cstp->expected[i] = f; + if (! lex_force_match (lexer, T_EQUALS)) return 0; + if (! lex_match_id (lexer, "EQUAL")) + { + double f; + int n; + while (lex_is_number (lexer)) + { + int i; + n = 1; + f = lex_number (lexer); + lex_get (lexer); + if (lex_match (lexer, T_ASTERISK)) + { + n = f; + if (!lex_force_num (lexer)) + return 0; + f = lex_number (lexer); + lex_get (lexer); + } + lex_match (lexer, T_COMMA); - } - } - } - else - lex_put_back (lexer, T_SLASH); + cstp->n_expected += n; + cstp->expected = pool_realloc (specs->pool, + cstp->expected, + sizeof (double) * + cstp->n_expected); + for (i = cstp->n_expected - n ; + i < cstp->n_expected; + ++i) + cstp->expected[i] = f; + + } + } } - if ( cstp->ranged && cstp->n_expected > 0 && - cstp->n_expected != cstp->hi - cstp->lo + 1 ) + 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 " @@ -815,7 +908,7 @@ npar_chisquare (struct lexer *lexer, struct dataset *ds, specs->test[specs->n_tests - 1] = nt; - return 1; + return retval; } @@ -826,6 +919,7 @@ npar_binomial (struct lexer *lexer, struct dataset *ds, struct binomial_test *btp = pool_alloc (specs->pool, sizeof (*btp)); struct one_sample_test *tp = &btp->parent; struct npar_test *nt = &tp->parent; + bool equals = false; nt->execute = binomial_execute; nt->insert_variables = one_sample_insert_variables; @@ -834,50 +928,139 @@ npar_binomial (struct lexer *lexer, struct dataset *ds, btp->p = 0.5; - if ( lex_match (lexer, T_LPAREN) ) + if (lex_match (lexer, T_LPAREN)) { - if ( lex_force_num (lexer) ) + equals = false; + if (lex_force_num (lexer)) { btp->p = lex_number (lexer); lex_get (lexer); - lex_force_match (lexer, T_RPAREN); + if (!lex_force_match (lexer, T_RPAREN)) + return 0; } else return 0; } else - /* Kludge: q2c swallows the '=' so put it back here */ - lex_put_back (lexer, T_EQUALS); + equals = true; + + if (!equals) + if (!lex_force_match (lexer, T_EQUALS)) + return 0; + + { + 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, T_LPAREN)) + { + if (! lex_force_num (lexer)) + return 2; + btp->category1 = lex_number (lexer); + lex_get (lexer); + if (lex_match (lexer, T_COMMA)) + { + if (! lex_force_num (lexer)) return 2; + btp->category2 = lex_number (lexer); + lex_get (lexer); + } + else + { + btp->cutpoint = btp->category1; + } + + if (! lex_force_match (lexer, T_RPAREN)) + return 0; + } + } + else + { + return 2; + } + } + + 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; +} + + + +static void +ks_one_sample_parse_params (struct lexer *lexer, struct ks_one_sample_test *kst, int params) +{ + assert (params == 1 || params == 2); - if (lex_match (lexer, T_EQUALS) ) + if (lex_is_number (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) ) + kst->p[0] = lex_number (lexer); + + lex_get (lexer); + if (params == 2) { - if (lex_match (lexer, T_LPAREN)) + lex_match (lexer, T_COMMA); + if (lex_force_num (lexer)) { - lex_force_num (lexer); - btp->category1 = lex_number (lexer); - lex_get (lexer); - if ( lex_match (lexer, T_COMMA)) - { - if ( ! lex_force_num (lexer) ) return 2; - btp->category2 = lex_number (lexer); - lex_get (lexer); - } - else - { - btp->cutpoint = btp->category1; - } - - lex_force_match (lexer, T_RPAREN); + kst->p[1] = lex_number (lexer); + lex_get (lexer); } } - else - return 2; + } +} + +static int +npar_ks_one_sample (struct lexer *lexer, struct dataset *ds, struct npar_specs *specs) +{ + struct ks_one_sample_test *kst = pool_alloc (specs->pool, sizeof (*kst)); + struct one_sample_test *tp = &kst->parent; + struct npar_test *nt = &tp->parent; + + nt->execute = ks_one_sample_execute; + nt->insert_variables = one_sample_insert_variables; + kst->p[0] = kst->p[1] = SYSMIS; + + if (! lex_force_match (lexer, T_LPAREN)) + return 2; + + if (lex_match_id (lexer, "NORMAL")) + { + kst->dist = KS_NORMAL; + ks_one_sample_parse_params (lexer, kst, 2); } + else if (lex_match_id (lexer, "POISSON")) + { + kst->dist = KS_POISSON; + ks_one_sample_parse_params (lexer, kst, 1); + } + else if (lex_match_id (lexer, "UNIFORM")) + { + kst->dist = KS_UNIFORM; + ks_one_sample_parse_params (lexer, kst, 2); + } + else if (lex_match_id (lexer, "EXPONENTIAL")) + { + kst->dist = KS_EXPONENTIAL; + ks_one_sample_parse_params (lexer, kst, 1); + } + else + return 2; + + if (! lex_force_match (lexer, T_RPAREN)) + return 2; + + lex_match (lexer, T_EQUALS); + + if (! parse_variables_const_pool (lexer, specs->pool, dataset_dict (ds), + &tp->vars, &tp->n_vars, + PV_NUMERIC | PV_NO_SCRATCH | PV_NO_DUPLICATE)) + return 2; specs->n_tests++; specs->test = pool_realloc (specs->pool, @@ -890,20 +1073,11 @@ npar_binomial (struct lexer *lexer, struct dataset *ds, } -static bool -parse_two_sample_related_test (struct lexer *lexer, - const struct dictionary *dict, - struct two_sample_test *test_parameters, - struct pool *pool - ); - - static bool parse_two_sample_related_test (struct lexer *lexer, const struct dictionary *dict, struct two_sample_test *test_parameters, - struct pool *pool - ) + struct pool *pool) { int n = 0; bool paired = false; @@ -919,15 +1093,15 @@ parse_two_sample_related_test (struct lexer *lexer, if (!parse_variables_const_pool (lexer, pool, dict, &vlist1, &n_vlist1, - PV_NUMERIC | PV_NO_SCRATCH | PV_NO_DUPLICATE) ) + PV_NUMERIC | PV_NO_SCRATCH | PV_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, + if (!parse_variables_const_pool (lexer, pool, dict, &vlist2, &n_vlist2, - PV_NUMERIC | PV_NO_SCRATCH | PV_NO_DUPLICATE) ) + PV_NUMERIC | PV_NO_SCRATCH | PV_DUPLICATE)) return false; paired = (lex_match (lexer, T_LPAREN) && @@ -935,14 +1109,17 @@ parse_two_sample_related_test (struct lexer *lexer, } - if ( with ) + if (with) { if (paired) { - if ( n_vlist1 != n_vlist2) - msg (SE, _("PAIRED was specified but the number of variables " + if (n_vlist1 != n_vlist2) + { + msg (SE, _("PAIRED was specified but the number of variables " "preceding WITH (%zu) did not match the number " "following (%zu)."), n_vlist1, n_vlist2); + return false; + } test_parameters->n_pairs = n_vlist1 ; } @@ -957,30 +1134,30 @@ parse_two_sample_related_test (struct lexer *lexer, } test_parameters->pairs = - pool_alloc (pool, sizeof ( variable_pair) * test_parameters->n_pairs); + pool_alloc (pool, sizeof (variable_pair) * test_parameters->n_pairs); - if ( with ) + if (with) { if (paired) { int i; assert (n_vlist1 == n_vlist2); - for ( i = 0 ; i < n_vlist1; ++i ) + for (i = 0 ; i < n_vlist1; ++i) { - test_parameters->pairs[n][1] = vlist1[i]; - test_parameters->pairs[n][0] = vlist2[i]; + test_parameters->pairs[n][0] = vlist1[i]; + test_parameters->pairs[n][1] = vlist2[i]; n++; } } else { int i,j; - for ( i = 0 ; i < n_vlist1; ++i ) + for (i = 0 ; i < n_vlist1; ++i) { - for ( j = 0 ; j < n_vlist2; ++j ) + for (j = 0 ; j < n_vlist2; ++j) { - test_parameters->pairs[n][1] = vlist1[i]; - test_parameters->pairs[n][0] = vlist2[j]; + test_parameters->pairs[n][0] = vlist1[i]; + test_parameters->pairs[n][1] = vlist2[j]; n++; } } @@ -989,19 +1166,19 @@ parse_two_sample_related_test (struct lexer *lexer, else { int i,j; - for ( i = 0 ; i < n_vlist1 - 1; ++i ) + for (i = 0 ; i < n_vlist1 - 1; ++i) { - for ( j = i + 1 ; j < n_vlist1; ++j ) + for (j = i + 1 ; j < n_vlist1; ++j) { - assert ( n < test_parameters->n_pairs); - test_parameters->pairs[n][1] = vlist1[i]; - test_parameters->pairs[n][0] = vlist1[j]; + assert (n < test_parameters->n_pairs); + test_parameters->pairs[n][0] = vlist1[i]; + test_parameters->pairs[n][1] = vlist1[j]; n++; } } } - assert ( n == test_parameters->n_pairs); + assert (n == test_parameters->n_pairs); return true; } @@ -1012,24 +1189,26 @@ parse_n_sample_related_test (struct lexer *lexer, const struct dictionary *dict, struct n_sample_test *nst, struct pool *pool - ) + ) { if (!parse_variables_const_pool (lexer, pool, dict, &nst->vars, &nst->n_vars, - PV_NUMERIC | PV_NO_SCRATCH | PV_NO_DUPLICATE) ) + PV_NUMERIC | PV_NO_SCRATCH | PV_NO_DUPLICATE)) return false; - if ( ! lex_force_match (lexer, T_BY)) + if (! lex_force_match (lexer, T_BY)) return false; nst->indep_var = parse_variable_const (lexer, dict); + if (!nst->indep_var) + return false; - if ( ! lex_force_match (lexer, T_LPAREN)) + if (! lex_force_match (lexer, T_LPAREN)) return false; value_init (&nst->val1, var_get_width (nst->indep_var)); - if ( ! parse_value (lexer, &nst->val1, var_get_width (nst->indep_var))) + if (! parse_value (lexer, &nst->val1, nst->indep_var)) { value_destroy (&nst->val1, var_get_width (nst->indep_var)); return false; @@ -1038,13 +1217,13 @@ parse_n_sample_related_test (struct lexer *lexer, lex_match (lexer, T_COMMA); value_init (&nst->val2, var_get_width (nst->indep_var)); - if ( ! parse_value (lexer, &nst->val2, var_get_width (nst->indep_var))) + if (! parse_value (lexer, &nst->val2, nst->indep_var)) { value_destroy (&nst->val2, var_get_width (nst->indep_var)); return false; } - if ( ! lex_force_match (lexer, T_RPAREN)) + if (! lex_force_match (lexer, T_RPAREN)) return false; return true; @@ -1053,16 +1232,14 @@ parse_n_sample_related_test (struct lexer *lexer, static int npar_wilcoxon (struct lexer *lexer, struct dataset *ds, - struct npar_specs *specs ) + struct npar_specs *specs) { - - 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), - tp, specs->pool) ) + tp, specs->pool)) return 0; specs->n_tests++; @@ -1078,7 +1255,7 @@ npar_wilcoxon (struct lexer *lexer, static int npar_mann_whitney (struct lexer *lexer, struct dataset *ds, - struct npar_specs *specs ) + struct npar_specs *specs) { struct n_sample_test *tp = pool_alloc (specs->pool, sizeof (*tp)); struct npar_test *nt = &tp->parent; @@ -1087,7 +1264,45 @@ npar_mann_whitney (struct lexer *lexer, nt->execute = mann_whitney_execute; if (!parse_n_sample_related_test (lexer, dataset_dict (ds), - 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); + specs->test[specs->n_tests - 1] = nt; + + return 1; +} + + +static int +npar_median (struct lexer *lexer, + struct dataset *ds, + struct npar_specs *specs) +{ + struct median_test *mt = pool_alloc (specs->pool, sizeof (*mt)); + struct n_sample_test *tp = &mt->parent; + struct npar_test *nt = &tp->parent; + + mt->median = SYSMIS; + + if (lex_match (lexer, T_LPAREN) && lex_force_num (lexer)) + { + mt->median = lex_number (lexer); + lex_get (lexer); + if (! lex_force_match (lexer, T_RPAREN)) + return 0; + } + + lex_match (lexer, T_EQUALS); + + nt->insert_variables = n_sample_insert_variables; + nt->execute = median_execute; + + if (!parse_n_sample_related_test (lexer, dataset_dict (ds), + tp, specs->pool)) return 0; specs->n_tests++; @@ -1110,7 +1325,55 @@ npar_sign (struct lexer *lexer, struct dataset *ds, nt->execute = sign_execute; if (!parse_two_sample_related_test (lexer, dataset_dict (ds), - 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); + specs->test[specs->n_tests - 1] = nt; + + return 1; +} + + +static int +npar_mcnemar (struct lexer *lexer, struct dataset *ds, + struct npar_specs *specs) +{ + struct two_sample_test *tp = pool_alloc (specs->pool, sizeof (*tp)); + struct npar_test *nt = &tp->parent; + + nt->execute = mcnemar_execute; + + 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); + specs->test[specs->n_tests - 1] = nt; + + return 1; +} + + +static int +npar_jonckheere_terpstra (struct lexer *lexer, struct dataset *ds, + struct npar_specs *specs) +{ + struct n_sample_test *tp = pool_alloc (specs->pool, sizeof (*tp)); + struct npar_test *nt = &tp->parent; + + nt->insert_variables = n_sample_insert_variables; + + nt->execute = jonckheere_terpstra_execute; + + if (!parse_n_sample_related_test (lexer, dataset_dict (ds), + tp, specs->pool)) return 0; specs->n_tests++; @@ -1134,7 +1397,7 @@ npar_kruskal_wallis (struct lexer *lexer, struct dataset *ds, nt->execute = kruskal_wallis_execute; if (!parse_n_sample_related_test (lexer, dataset_dict (ds), - tp, specs->pool) ) + tp, specs->pool)) return 0; specs->n_tests++; @@ -1152,10 +1415,10 @@ insert_variable_into_map (struct hmapx *var_map, const struct variable *var) size_t hash = hash_pointer (var, 0); struct hmapx_node *node; const struct variable *v = NULL; - + HMAPX_FOR_EACH_WITH_HASH (v, node, hash, var_map) { - if ( v == var) + if (v == var) return ; } @@ -1170,7 +1433,7 @@ one_sample_insert_variables (const struct npar_test *test, int i; const struct one_sample_test *ost = UP_CAST (test, const struct one_sample_test, parent); - for ( i = 0 ; i < ost->n_vars ; ++i ) + for (i = 0 ; i < ost->n_vars ; ++i) insert_variable_into_map (var_map, ost->vars[i]); } @@ -1182,7 +1445,7 @@ two_sample_insert_variables (const struct npar_test *test, int i; const struct two_sample_test *tst = UP_CAST (test, const struct two_sample_test, parent); - for ( i = 0 ; i < tst->n_pairs ; ++i ) + for (i = 0 ; i < tst->n_pairs ; ++i) { variable_pair *pair = &tst->pairs[i]; @@ -1191,14 +1454,14 @@ two_sample_insert_variables (const struct npar_test *test, } } -static void +static void n_sample_insert_variables (const struct npar_test *test, struct hmapx *var_map) { int i; const struct n_sample_test *tst = UP_CAST (test, const struct n_sample_test, parent); - for ( i = 0 ; i < tst->n_vars ; ++i ) + for (i = 0 ; i < tst->n_vars ; ++i) insert_variable_into_map (var_map, tst->vars[i]); insert_variable_into_map (var_map, tst->indep_var); @@ -1208,7 +1471,7 @@ n_sample_insert_variables (const struct npar_test *test, static int npar_method (struct lexer *lexer, struct npar_specs *specs) { - if ( lex_match_id (lexer, "EXACT") ) + if (lex_match_id (lexer, "EXACT")) { specs->exact = true; specs->timer = 0.0; @@ -1216,14 +1479,15 @@ npar_method (struct lexer *lexer, struct npar_specs *specs) { specs->timer = 5.0; - if ( lex_match (lexer, T_LPAREN)) + if (lex_match (lexer, T_LPAREN)) { - if ( lex_force_num (lexer) ) + if (lex_force_num (lexer)) { specs->timer = lex_number (lexer); lex_get (lexer); } - lex_force_match (lexer, T_RPAREN); + if (lex_force_match (lexer, T_RPAREN)) + return 0; } } }