From: Ben Pfaff Date: Thu, 11 May 2023 02:29:56 +0000 (-0700) Subject: MATRIX DATA: Make N subcommand work properly without ROWTYPE_. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=427a66b4601c3f38180d6b0980336625b7fb7671;p=pspp MATRIX DATA: Make N subcommand work properly without ROWTYPE_. I found this bug myself while experimenting. --- diff --git a/src/language/commands/matrix-data.c b/src/language/commands/matrix-data.c index 8c8c45bc88..365caf6fd3 100644 --- a/src/language/commands/matrix-data.c +++ b/src/language/commands/matrix-data.c @@ -546,6 +546,35 @@ matrix_sched_init (const struct matrix_format *mf, enum rowtype rt, gsl_matrix_set (m, y, x, y == x ? diagonal : SYSMIS); } +static struct ccase * +matrix_sched_output_create_case (const struct matrix_format *mf, + enum rowtype rt, const struct variable *var, + const double *d, int split_num, + struct casewriter *w) +{ + struct ccase *c = case_create (casewriter_get_proto (w)); + for (size_t i = 0; mf->input_vars[i] != mf->cvars[0]; i++) + if (mf->input_vars[i] != mf->rowtype) + *case_num_rw (c, mf->input_vars[i]) = d[i]; + if (mf->n_svars && !mf->svar_indexes) + *case_num_rw (c, mf->svars[0]) = split_num; + set_string (c, mf->rowtype, rowtype_name (rt)); + const char *varname = var ? var_get_name (var) : ""; + set_string (c, mf->varname, ss_cstr (varname)); + return c; +} + +static void +matrix_sched_output_n (const struct matrix_format *mf, double n, + const double *d, int split_num, struct casewriter *w) +{ + struct ccase *c = matrix_sched_output_create_case (mf, C_N, NULL, d, + split_num, w); + for (int x = 0; x < mf->n_cvars; x++) + *case_num_rw (c, mf->cvars[x]) = n; + casewriter_write (w, c); +} + static void matrix_sched_output (const struct matrix_format *mf, enum rowtype rt, gsl_matrix *m, const double *d, int split_num, @@ -556,37 +585,21 @@ matrix_sched_output (const struct matrix_format *mf, enum rowtype rt, if (rt == C_N_SCALAR) { - for (size_t x = 1; x < mf->n_cvars; x++) - gsl_matrix_set (m, 0, x, gsl_matrix_get (m, 0, 0)); - rt = C_N; + matrix_sched_output_n (mf, gsl_matrix_get (m, 0, 0), d, split_num, w); + return; } for (int y = 0; y < ms->nr; y++) { - struct ccase *c = case_create (casewriter_get_proto (w)); - for (size_t i = 0; mf->input_vars[i] != mf->cvars[0]; i++) - if (mf->input_vars[i] != mf->rowtype) - *case_num_rw (c, mf->input_vars[i]) = d[i]; - if (mf->n_svars && !mf->svar_indexes) - *case_num_rw (c, mf->svars[0]) = split_num; - set_string (c, mf->rowtype, rowtype_name (rt)); - const char *varname = n_dims == 2 ? var_get_name (mf->cvars[y]) : ""; - set_string (c, mf->varname, ss_cstr (varname)); + const struct variable *var = n_dims == 2 ? mf->cvars[y] : NULL; + struct ccase *c = matrix_sched_output_create_case (mf, rt, var, d, + split_num, w); for (int x = 0; x < mf->n_cvars; x++) *case_num_rw (c, mf->cvars[x]) = gsl_matrix_get (m, y, x); casewriter_write (w, c); } } -static void -matrix_sched_output_n (const struct matrix_format *mf, double n, - gsl_matrix *m, const double *d, int split_num, - struct casewriter *w) -{ - gsl_matrix_set (m, 0, 0, n); - matrix_sched_output (mf, C_N_SCALAR, m, d, split_num, w); -} - static void check_eol (const struct matrix_format *mf, struct substring *p, struct dfm_reader *r) @@ -635,7 +648,7 @@ parse_data_with_rowtype (const struct matrix_format *mf, record. */ if (mf->n >= 0 && (!prev || !equal_split_columns (mf, prev, d))) { - matrix_sched_output_n (mf, mf->n, m, d, 0, w); + matrix_sched_output_n (mf, mf->n, d, 0, w); if (!prev) prev = xnmalloc (mf->n_input_vars, sizeof *prev); @@ -729,7 +742,7 @@ static void parse_matrix_without_rowtype (const struct matrix_format *mf, struct substring *p, struct dfm_reader *r, gsl_matrix *m, enum rowtype rowtype, bool pooled, - int split_num, struct casewriter *w) + int split_num, bool *first, struct casewriter *w) { int n_dims = rowtype_dimensions (rowtype); const struct matrix_sched *ms = &mf->ms[n_dims]; @@ -778,6 +791,14 @@ parse_matrix_without_rowtype (const struct matrix_format *mf, check_eol (mf, p, r); } + /* If there's an N subcommand, and this is a new split, then output an N + record. */ + if (mf->n >= 0 && *first) + { + *first = false; + matrix_sched_output_n (mf, mf->n, d, 0, w); + } + matrix_sched_output (mf, rowtype, m, d, split_num, w); exit: free (d); @@ -796,6 +817,7 @@ parse_data_without_rowtype (const struct matrix_format *mf, int split_num = 1; do { + bool first = true; for (size_t i = 0; i < mf->n_contents; ) { size_t j = i; @@ -809,11 +831,11 @@ parse_data_without_rowtype (const struct matrix_format *mf, for (size_t h = i; h <= j; h++) parse_matrix_without_rowtype (mf, &p, r, m, mf->contents[h].rowtype, false, - split_num, w); + split_num, &first, w); } else parse_matrix_without_rowtype (mf, &p, r, m, mf->contents[i].rowtype, - true, split_num, w); + true, split_num, &first, w); i = j + 1; } diff --git a/tests/language/commands/matrix-data.at b/tests/language/commands/matrix-data.at index 1e8e3f84bf..8f56e25303 100644 --- a/tests/language/commands/matrix-data.at +++ b/tests/language/commands/matrix-data.at @@ -921,6 +921,45 @@ CORR,var08,.17,.29,-.05,.20,.27,.20,.04,1.00 ]) AT_CLEANUP +dnl Keep this test in sync with Example 6 in doc/matrices.texi. +AT_SETUP([MATRIX DATA - LOWER DIAGONAL with N and without ROWTYPE_]) +AT_DATA([matrix-data.sps], [dnl +MATRIX DATA + VARIABLES=var01 TO var08 + /CONTENTS=MEAN SD CORR + /N 92. +BEGIN DATA. +24.3 5.4 69.7 20.1 13.4 2.7 27.9 3.7 + 5.7 1.5 23.5 5.8 2.8 4.5 5.4 1.5 +1.00 + .18 1.00 +-.22 -.17 1.00 + .36 .31 -.14 1.00 + .27 .16 -.12 .22 1.00 + .33 .15 -.17 .24 .21 1.00 + .50 .29 -.20 .32 .12 .38 1.00 + .17 .29 -.05 .20 .27 .20 .04 1.00 +END DATA. +FORMATS var01 TO var08(F5.2). +LIST. +]) +AT_CHECK([pspp matrix-data.sps -O format=csv], [0], [dnl +Table: Data List +ROWTYPE_,VARNAME_,var01,var02,var03,var04,var05,var06,var07,var08 +N,,92.00,92.00,92.00,92.00,92.00,92.00,92.00,92.00 +MEAN,,24.30,5.40,69.70,20.10,13.40,2.70,27.90,3.70 +STDDEV,,5.70,1.50,23.50,5.80,2.80,4.50,5.40,1.50 +CORR,var01,1.00,.18,-.22,.36,.27,.33,.50,.17 +CORR,var02,.18,1.00,-.17,.31,.16,.15,.29,.29 +CORR,var03,-.22,-.17,1.00,-.14,-.12,-.17,-.20,-.05 +CORR,var04,.36,.31,-.14,1.00,.22,.24,.32,.20 +CORR,var05,.27,.16,-.12,.22,1.00,.21,.12,.27 +CORR,var06,.33,.15,-.17,.24,.21,1.00,.38,.20 +CORR,var07,.50,.29,-.20,.32,.12,.38,1.00,.04 +CORR,var08,.17,.29,-.05,.20,.27,.20,.04,1.00 +]) +AT_CLEANUP + AT_SETUP([MATRIX DATA - extraneous data without ROWTYPE_]) AT_DATA([matrix-data.sps], [dnl MATRIX DATA @@ -1019,6 +1058,63 @@ s1,ROWTYPE_,VARNAME_,var01,var02,var03,var04 ]) AT_CLEANUP +dnl Keep this test in sync with Example 7 in doc/matrices.texi. +AT_SETUP([MATRIX DATA - Split variables with explicit values with N and without ROWTYPE_]) +AT_DATA([matrix-data.sps], [dnl +MATRIX DATA + VARIABLES=s1 var01 TO var04 + /SPLIT=s1 + /FORMAT=FULL + /CONTENTS=MEAN SD CORR + /N=99. +BEGIN DATA. +0 34 35 36 37 +0 22 11 55 66 +0 1 .9 .8 .7 +0 .9 1 .6 .5 +0 .8 .6 1 .4 +0 .7 .5 .4 1 +1 44 45 34 39 +1 23 15 51 46 +1 1 .2 .3 .4 +1 .2 1 .5 .6 +1 .3 .5 1 .7 +1 .4 .6 .7 1 +END DATA. +FORMATS var01 TO var04(F5.2). +LIST. +]) +AT_CHECK([pspp matrix-data.sps -O format=csv], [0], [dnl +Table: Split Values +Variable,Value +s1,0 + +Table: Data List +s1,ROWTYPE_,VARNAME_,var01,var02,var03,var04 +0,N,,99.00,99.00,99.00,99.00 +0,MEAN,,34.00,35.00,36.00,37.00 +0,STDDEV,,22.00,11.00,55.00,66.00 +0,CORR,var01,1.00,.90,.80,.70 +0,CORR,var02,.90,1.00,.60,.50 +0,CORR,var03,.80,.60,1.00,.40 +0,CORR,var04,.70,.50,.40,1.00 + +Table: Split Values +Variable,Value +s1,1 + +Table: Data List +s1,ROWTYPE_,VARNAME_,var01,var02,var03,var04 +1,N,,99.00,99.00,99.00,99.00 +1,MEAN,,44.00,45.00,34.00,39.00 +1,STDDEV,,23.00,15.00,51.00,46.00 +1,CORR,var01,1.00,.20,.30,.40 +1,CORR,var02,.20,1.00,.50,.60 +1,CORR,var03,.30,.50,1.00,.70 +1,CORR,var04,.40,.60,.70,1.00 +]) +AT_CLEANUP + dnl Keep this test in sync with Example 8 in doc/matrices.texi. AT_SETUP([MATRIX DATA - Split variable with sequential values without ROWTYPE_]) AT_DATA([matrix-data.sps], [dnl