From: Ben Pfaff Date: Fri, 19 Nov 2021 03:37:23 +0000 (-0800) Subject: MSAVE tests X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4c60ca0d4871358b2f73a9353e0d2a8e86d91aa0;p=pspp MSAVE tests --- diff --git a/doc/matrices.texi b/doc/matrices.texi index 565cdbd257..65dbd94b62 100644 --- a/doc/matrices.texi +++ b/doc/matrices.texi @@ -2563,7 +2563,7 @@ warning and does not change the variable. [@t{/FNAMES}@t{=}@i{variable}@dots{}]@t{.} @end display -The @code{MSAVE} command evaluates the @i{expression} specifies just +The @code{MSAVE} command evaluates the @i{expression} specified just after the command name, and writes the resulting matrix to a matrix file (@pxref{Matrix Files}). diff --git a/src/language/stats/matrix.c b/src/language/stats/matrix.c index ed43412a32..f79a1f8a09 100644 --- a/src/language/stats/matrix.c +++ b/src/language/stats/matrix.c @@ -81,10 +81,15 @@ struct msave_common struct string_array variables; struct string_array fnames; struct string_array snames; - bool has_factors; - bool has_splits; size_t n_varnames; + /* Collects and owns factors and splits. The individual msave_command + structs point to these but do not own them. */ + struct matrix_expr **factors; + size_t n_factors, allocated_factors; + struct matrix_expr **splits; + size_t n_splits, allocated_splits; + /* Execution state. */ struct dictionary *dict; struct casewriter *writer; @@ -2546,6 +2551,7 @@ matrix_to_vector (gsl_matrix *m) assert (!v.owner); v.owner = 1; m->owner = 0; + gsl_matrix_free (m); return xmemdup (&v, sizeof v); } @@ -3474,11 +3480,10 @@ struct matrix_cmd struct msave_command { struct msave_common *common; - char *varname_; struct matrix_expr *expr; const char *rowtype; - struct matrix_expr *factors; - struct matrix_expr *splits; + const struct matrix_expr *factors; + const struct matrix_expr *splits; } msave; @@ -5788,8 +5793,6 @@ parse_var_names (struct lexer *lexer, struct string_array *sa) string_array_clear (sa); struct dictionary *dict = dict_create (get_default_encoding ()); - dict_create_var_assert (dict, "ROWTYPE_", 8); - dict_create_var_assert (dict, "VARNAME_", 8); char **names; size_t n_names; bool ok = parse_DATA_LIST_vars (lexer, dict, &names, &n_names, @@ -5798,6 +5801,17 @@ parse_var_names (struct lexer *lexer, struct string_array *sa) if (ok) { + for (size_t i = 0; i < n_names; i++) + if (ss_equals_case (ss_cstr (names[i]), ss_cstr ("ROWTYPE_")) + || ss_equals_case (ss_cstr (names[i]), ss_cstr ("VARNAME_"))) + { + msg (SE, _("Variable name %s is reserved."), names[i]); + for (size_t j = 0; j < n_names; j++) + free (names[i]); + free (names); + return false; + } + string_array_clear (sa); sa->strings = names; sa->n = sa->allocated = n_names; @@ -5806,7 +5820,7 @@ parse_var_names (struct lexer *lexer, struct string_array *sa) } static void -msave_common_uninit (struct msave_common *common) +msave_common_destroy (struct msave_common *common) { if (common) { @@ -5814,6 +5828,19 @@ msave_common_uninit (struct msave_common *common) string_array_destroy (&common->variables); string_array_destroy (&common->fnames); string_array_destroy (&common->snames); + + for (size_t i = 0; i < common->n_factors; i++) + matrix_expr_destroy (common->factors[i]); + free (common->factors); + + for (size_t i = 0; i < common->n_splits; i++) + matrix_expr_destroy (common->splits[i]); + free (common->splits); + + dict_unref (common->dict); + casewriter_destroy (common->writer); + + free (common); } } @@ -5843,16 +5870,19 @@ compare_variables (const char *keyword, static struct matrix_cmd * matrix_parse_msave (struct matrix_state *s) { - struct msave_common common = { .outfile = NULL }; + struct msave_common *common = xmalloc (sizeof *common); + *common = (struct msave_common) { .outfile = NULL }; + struct matrix_cmd *cmd = xmalloc (sizeof *cmd); *cmd = (struct matrix_cmd) { .type = MCMD_MSAVE, .msave = { .expr = NULL } }; + struct matrix_expr *splits = NULL; + struct matrix_expr *factors = NULL; + struct msave_command *msave = &cmd->msave; - if (lex_token (s->lexer) == T_ID) - msave->varname_ = ss_xstrdup (lex_tokss (s->lexer)); msave->expr = matrix_parse_exp (s); if (!msave->expr) - return NULL; + goto error; while (lex_match (s->lexer, T_SLASH)) { @@ -5868,42 +5898,42 @@ matrix_parse_msave (struct matrix_state *s) { lex_match (s->lexer, T_EQUALS); - fh_unref (common.outfile); - common.outfile = fh_parse (s->lexer, FH_REF_FILE, NULL); - if (!common.outfile) + fh_unref (common->outfile); + common->outfile = fh_parse (s->lexer, FH_REF_FILE, NULL); + if (!common->outfile) goto error; } else if (lex_match_id (s->lexer, "VARIABLES")) { - if (!parse_var_names (s->lexer, &common.variables)) + if (!parse_var_names (s->lexer, &common->variables)) goto error; } else if (lex_match_id (s->lexer, "FNAMES")) { - if (!parse_var_names (s->lexer, &common.fnames)) + if (!parse_var_names (s->lexer, &common->fnames)) goto error; } else if (lex_match_id (s->lexer, "SNAMES")) { - if (!parse_var_names (s->lexer, &common.snames)) + if (!parse_var_names (s->lexer, &common->snames)) goto error; } else if (lex_match_id (s->lexer, "SPLIT")) { lex_match (s->lexer, T_EQUALS); - matrix_expr_destroy (msave->splits); - msave->splits = matrix_parse_exp (s); - if (!msave->splits) + matrix_expr_destroy (splits); + splits = matrix_parse_exp (s); + if (!splits) goto error; } else if (lex_match_id (s->lexer, "FACTOR")) { lex_match (s->lexer, T_EQUALS); - matrix_expr_destroy (msave->factors); - msave->factors = matrix_parse_exp (s); - if (!msave->factors) + matrix_expr_destroy (factors); + factors = matrix_parse_exp (s); + if (!factors) goto error; } else @@ -5918,49 +5948,31 @@ matrix_parse_msave (struct matrix_state *s) lex_sbc_missing ("TYPE"); goto error; } - common.has_splits = msave->splits || common.snames.n; - common.has_factors = msave->factors || common.fnames.n; - - struct msave_common *c = s->common ? s->common : &common; - if (c->fnames.n && !msave->factors) - { - msg (SE, _("FNAMES requires FACTOR.")); - goto error; - } - if (c->snames.n && !msave->splits) - { - msg (SE, _("SNAMES requires SPLIT.")); - goto error; - } - if (c->has_factors && !common.has_factors) - { - msg (SE, _("%s is required because it was present on the first " - "MSAVE in this MATRIX command."), "FACTOR"); - goto error; - } - if (c->has_splits && !common.has_splits) - { - msg (SE, _("%s is required because it was present on the first " - "MSAVE in this MATRIX command."), "SPLIT"); - goto error; - } if (!s->common) { - if (!common.outfile) + if (common->fnames.n && !factors) + { + msg (SE, _("FNAMES requires FACTOR.")); + goto error; + } + if (common->snames.n && !splits) + { + msg (SE, _("SNAMES requires SPLIT.")); + goto error; + } + if (!common->outfile) { lex_sbc_missing ("OUTFILE"); goto error; } - s->common = xmemdup (&common, sizeof common); + s->common = common; } else { - if (common.outfile) + if (common->outfile) { - bool same = common.outfile == s->common->outfile; - fh_unref (common.outfile); - if (!same) + if (!fh_equal (common->outfile, s->common->outfile)) { msg (SE, _("OUTFILE must name the same file on each MSAVE " "within a single MATRIX command.")); @@ -5968,25 +5980,47 @@ matrix_parse_msave (struct matrix_state *s) } } if (!compare_variables ("VARIABLES", - &common.variables, &s->common->variables) - || !compare_variables ("FNAMES", &common.fnames, &s->common->fnames) - || !compare_variables ("SNAMES", &common.snames, &s->common->snames)) + &common->variables, &s->common->variables) + || !compare_variables ("FNAMES", &common->fnames, &s->common->fnames) + || !compare_variables ("SNAMES", &common->snames, &s->common->snames)) goto error; - msave_common_uninit (&common); + msave_common_destroy (common); } msave->common = s->common; - if (!msave->varname_) - msave->varname_ = xasprintf ("MAT%zu", ++s->common->n_varnames); + + struct msave_common *c = s->common; + if (factors) + { + if (c->n_factors >= c->allocated_factors) + c->factors = x2nrealloc (c->factors, &c->allocated_factors, + sizeof *c->factors); + c->factors[c->n_factors++] = factors; + } + if (c->n_factors > 0) + msave->factors = c->factors[c->n_factors - 1]; + + if (splits) + { + if (c->n_splits >= c->allocated_splits) + c->splits = x2nrealloc (c->splits, &c->allocated_splits, + sizeof *c->splits); + c->splits[c->n_splits++] = splits; + } + if (c->n_splits > 0) + msave->splits = c->splits[c->n_splits - 1]; + return cmd; error: - msave_common_uninit (&common); + matrix_expr_destroy (splits); + matrix_expr_destroy (factors); + msave_common_destroy (common); matrix_cmd_destroy (cmd); return NULL; } static gsl_vector * -matrix_expr_evaluate_vector (struct matrix_expr *e, const char *name) +matrix_expr_evaluate_vector (const struct matrix_expr *e, const char *name) { gsl_matrix *m = matrix_expr_evaluate (e); if (!m) @@ -6021,8 +6055,9 @@ msave_create_dict (const struct msave_common *common) const char *dup_split = msave_add_vars (dict, &common->snames); if (dup_split) { - msg (SE, _("Duplicate SPLIT variable name %s."), dup_split); - goto error; + /* Should not be possible because the parser ensures that the names are + unique. */ + NOT_REACHED (); } dict_create_var_assert (dict, "ROWTYPE_", 8); @@ -6066,10 +6101,10 @@ matrix_cmd_execute_msave (struct msave_command *msave) for (size_t i = 0; i < m->size2; i++) string_array_append_nocopy (&common->variables, xasprintf ("COL%zu", i + 1)); - - if (m->size2 != common->variables.n) + else if (m->size2 != common->variables.n) { - msg (SE, _("Matrix on MSAVE has %zu columns instead of required %zu."), + msg (SE, + _("Matrix on MSAVE has %zu columns but there are %zu variables."), m->size2, common->variables.n); goto error; } @@ -6084,11 +6119,10 @@ matrix_cmd_execute_msave (struct msave_command *msave) for (size_t i = 0; i < factors->size; i++) string_array_append_nocopy (&common->fnames, xasprintf ("FAC%zu", i + 1)); - - if (factors->size != common->fnames.n) + else if (factors->size != common->fnames.n) { msg (SE, _("There are %zu factor variables, " - "but %zu split values were supplied."), + "but %zu factor values were supplied."), common->fnames.n, factors->size); goto error; } @@ -6100,16 +6134,15 @@ matrix_cmd_execute_msave (struct msave_command *msave) if (!splits) goto error; - if (!common->fnames.n) + if (!common->snames.n) for (size_t i = 0; i < splits->size; i++) - string_array_append_nocopy (&common->fnames, + string_array_append_nocopy (&common->snames, xasprintf ("SPL%zu", i + 1)); - - if (splits->size != common->fnames.n) + else if (splits->size != common->snames.n) { msg (SE, _("There are %zu split variables, " "but %zu split values were supplied."), - common->fnames.n, splits->size); + common->snames.n, splits->size); goto error; } } @@ -6130,6 +6163,8 @@ matrix_cmd_execute_msave (struct msave_command *msave) common->dict = dict; } + bool matrix = (!strcmp (msave->rowtype, "COV") + || !strcmp (msave->rowtype, "CORR")); for (size_t y = 0; y < m->size1; y++) { struct ccase *c = case_create (dict_get_proto (common->dict)); @@ -6150,8 +6185,11 @@ matrix_cmd_execute_msave (struct msave_command *msave) *case_num_rw_idx (c, idx++) = gsl_vector_get (factors, i); /* VARNAME_. */ + const char *varname_ = (matrix && y < common->variables.n + ? common->variables.strings[y] + : ""); buf_copy_str_rpad (CHAR_CAST (char *, case_data_rw_idx (c, idx++)->s), 8, - msave->varname_, ' '); + varname_, ' '); /* Continuous variables. */ for (size_t x = 0; x < m->size2; x++) @@ -6930,10 +6968,7 @@ matrix_cmd_destroy (struct matrix_cmd *cmd) break; case MCMD_MSAVE: - free (cmd->msave.varname_); matrix_expr_destroy (cmd->msave.expr); - matrix_expr_destroy (cmd->msave.factors); - matrix_expr_destroy (cmd->msave.splits); break; case MCMD_MGET: @@ -7063,12 +7098,7 @@ cmd_matrix (struct lexer *lexer, struct dataset *ds) free (var); } hmap_destroy (&state.vars); - if (state.common) - { - dict_unref (state.common->dict); - casewriter_destroy (state.common->writer); - free (state.common); - } + msave_common_destroy (state.common); fh_unref (state.prev_read_file); for (size_t i = 0; i < state.n_read_files; i++) read_file_destroy (state.read_files[i]); diff --git a/tests/language/stats/matrix.at b/tests/language/stats/matrix.at index 4692518965..06b93749a5 100644 --- a/tests/language/stats/matrix.at +++ b/tests/language/stats/matrix.at @@ -3720,3 +3720,273 @@ ncs2 0 0 ]) AT_CLEANUP + +AT_SETUP([MATRIX - MSAVE]) +AT_DATA([matrix.sps], [dnl +MATRIX. +MSAVE {1, 2; 3, 4}/TYPE=CORR/VARIABLES=X,Y/OUTFILE='matrix.sav'. +MSAVE {5, 6; 7, 8; 9, 10}/TYPE=COV/VARIABLES=X,Y. +MSAVE {11, 12}/TYPE=MEAN. +MSAVE {13, 14}/TYPE=STDDEV. +MSAVE {15, 16}/TYPE=N. +MSAVE {17, 18}/TYPE=COUNT. +END MATRIX. +GET 'matrix.sav'. +LIST. +]) +AT_CHECK([pspp matrix.sps -O format=csv], [0], [dnl +Table: Data List +ROWTYPE_,VARNAME_,X,Y +CORR,X,1.00,2.00 +CORR,Y,3.00,4.00 +COV,X,5.00,6.00 +COV,Y,7.00,8.00 +COV,,9.00,10.00 +MEAN,,11.00,12.00 +STDDEV,,13.00,14.00 +N,,15.00,16.00 +COUNT,,17.00,18.00 +]) +AT_CLEANUP + +AT_SETUP([MATRIX - MSAVE with factor variables]) +AT_DATA([matrix.sps], [dnl +MATRIX. +MSAVE {1, 2; 3, 4}/TYPE=CORR/FACTOR={1,1}/FNAMES=X,Y/OUTFILE='matrix.sav'. +MSAVE {5, 6; 7, 8; 9, 10}/TYPE=COV. +MSAVE {11, 12}/TYPE=MEAN. +MSAVE {13, 14}/FACTOR={2,1}/TYPE=STDDEV. +MSAVE {15, 16}/TYPE=N. +MSAVE {17, 18}/FACTOR={1,2}/TYPE=COUNT. +END MATRIX. +GET 'matrix.sav'. +LIST. + +MATRIX. +MSAVE {1, 2; 3, 4}/TYPE=CORR/FACTOR={5,6,7,8}/OUTFILE='matrix2.sav'. +END MATRIX. +GET 'matrix2.sav'. +LIST. +]) +AT_CHECK([pspp matrix.sps -O format=csv], [0], [dnl +Table: Data List +ROWTYPE_,X,Y,VARNAME_,COL1,COL2 +CORR,1.00,1.00,COL1,1.00,2.00 +CORR,1.00,1.00,COL2,3.00,4.00 +COV,1.00,1.00,COL1,5.00,6.00 +COV,1.00,1.00,COL2,7.00,8.00 +COV,1.00,1.00,,9.00,10.00 +MEAN,1.00,1.00,,11.00,12.00 +STDDEV,2.00,1.00,,13.00,14.00 +N,2.00,1.00,,15.00,16.00 +COUNT,1.00,2.00,,17.00,18.00 + +Table: Data List +ROWTYPE_,FAC1,FAC2,FAC3,FAC4,VARNAME_,COL1,COL2 +CORR,5.00,6.00,7.00,8.00,COL1,1.00,2.00 +CORR,5.00,6.00,7.00,8.00,COL2,3.00,4.00 +]) +AT_CLEANUP + +AT_SETUP([MATRIX - MSAVE with split variables]) +AT_DATA([matrix.sps], [dnl +MATRIX. +MSAVE {1, 2; 3, 4}/TYPE=CORR/SPLIT={1,1}/SNAMES=X,Y/OUTFILE='matrix.sav'. +MSAVE {5, 6; 7, 8; 9, 10}/TYPE=COV. +MSAVE {11, 12}/TYPE=MEAN. +MSAVE {13, 14}/SPLIT={2,1}/TYPE=STDDEV. +MSAVE {15, 16}/TYPE=N. +MSAVE {17, 18}/SPLIT={1,2}/TYPE=COUNT. +END MATRIX. +GET 'matrix.sav'. +LIST. + +MATRIX. +MSAVE {1, 2; 3, 4}/TYPE=CORR/SPLIT={5,6,7,8}/OUTFILE='matrix2.sav'. +END MATRIX. +GET 'matrix2.sav'. +LIST. +]) +AT_CHECK([pspp matrix.sps -O format=csv], [0], [dnl +Table: Data List +X,Y,ROWTYPE_,VARNAME_,COL1,COL2 +1.00,1.00,CORR,COL1,1.00,2.00 +1.00,1.00,CORR,COL2,3.00,4.00 +1.00,1.00,COV,COL1,5.00,6.00 +1.00,1.00,COV,COL2,7.00,8.00 +1.00,1.00,COV,,9.00,10.00 +1.00,1.00,MEAN,,11.00,12.00 +2.00,1.00,STDDEV,,13.00,14.00 +2.00,1.00,N,,15.00,16.00 +1.00,2.00,COUNT,,17.00,18.00 + +Table: Data List +SPL1,SPL2,SPL3,SPL4,ROWTYPE_,VARNAME_,COL1,COL2 +5.00,6.00,7.00,8.00,CORR,COL1,1.00,2.00 +5.00,6.00,7.00,8.00,CORR,COL2,3.00,4.00 +]) +AT_CLEANUP + +AT_SETUP([MATRIX - MSAVE with factor and split variables]) +AT_DATA([matrix.sps], [dnl +MATRIX. +MSAVE {1, 2; 3, 4}/TYPE=CORR/SPLIT=1/FACTOR=1/OUTFILE='matrix.sav'. +MSAVE {5, 6; 7, 8; 9, 10}/TYPE=COV. +MSAVE {11, 12}/FACTOR=2/TYPE=MEAN. +MSAVE {13, 14}/FACTOR=1/SPLIT=2/TYPE=STDDEV. +MSAVE {15, 16}/TYPE=N. +MSAVE {17, 18}/FACTOR=2/TYPE=COUNT. +END MATRIX. +GET 'matrix.sav'. +LIST. +]) +AT_CHECK([pspp matrix.sps -O format=csv], [0], [dnl +Table: Data List +SPL1,ROWTYPE_,FAC1,VARNAME_,COL1,COL2 +1.00,CORR,1.00,COL1,1.00,2.00 +1.00,CORR,1.00,COL2,3.00,4.00 +1.00,COV,1.00,COL1,5.00,6.00 +1.00,COV,1.00,COL2,7.00,8.00 +1.00,COV,1.00,,9.00,10.00 +1.00,MEAN,2.00,,11.00,12.00 +2.00,STDDEV,1.00,,13.00,14.00 +2.00,N,1.00,,15.00,16.00 +2.00,COUNT,2.00,,17.00,18.00 +]) +AT_CLEANUP + +AT_SETUP([MATRIX - MSAVE - negative]) +AT_DATA([matrix.sps], [dnl +MATRIX. +MSAVE !. +MSAVE 1/TYPE=!. +MSAVE 1/OUTFILE=!. +MSAVE 1/VARIABLES=!. +MSAVE 1/FNAMES=!. +MSAVE 1/SNAMES=!. +MSAVE 1/SPLIT=!. +MSAVE 1/FACTOR=!. +MSAVE 1/!. +MSAVE 1. +MSAVE 1/TYPE=COV/FNAMES=x. +MSAVE 1/TYPE=COV/SNAMES=x. +MSAVE 1/TYPE=COV. + +MSAVE 1/TYPE=COV/OUTFILE='matrix.sav' + /FACTOR=1 /FNAMES=y + /SPLIT=2 /SNAMES=z + /VARIABLES=w. +MSAVE 1/TYPE=COV/OUTFILE='matrix2.sav'. +MSAVE 1/TYPE=COV/VARIABLES=x. +MSAVE 1/TYPE=COV/FNAMES=x. +MSAVE 1/TYPE=COV/SNAMES=x. +END MATRIX. + +MATRIX. +MSAVE 1/TYPE=COV/VARIABLES=x/OUTFILE='matrix3.sav'/FACTOR=1/SPLIT=2. +MSAVE {1,2}/TYPE=COV/VARIABLES=x/OUTFILE='matrix3.sav'/FACTOR=1/SPLIT=2. +MSAVE {1,2;3}/TYPE=COV. +MSAVE 0/TYPE=COV/FACTOR={1,2}. +MSAVE 0/TYPE=COV/FACTOR=1/SPLIT={1;2}. +END MATRIX. + +MATRIX. +MSAVE 1/TYPE=COV/OUTFILE='matrix4.sav'/SNAMES=x,x/SPLIT=1. +END MATRIX. + +MATRIX. +MSAVE 1/TYPE=COV/OUTFILE='matrix5.sav'/SNAMES=x/FNAMES=x/SPLIT=1/FACTOR=1. +END MATRIX. + +MATRIX. +MSAVE 1/TYPE=COV/OUTFILE='matrix6.sav'/VARIABLES=x/FNAMES=x/FACTOR=1. +END MATRIX. + +MATRIX. +MSAVE 1/TYPE=COV/OUTFILE='matrix6.sav'/VARIABLES=x/SNAMES=x/SPLIT=1. +END MATRIX. + +MATRIX. +MSAVE 1/TYPE=COV/OUTFILE='matrix7.sav'/SNAMES=VARNAME_. +MSAVE 1/TYPE=COV/OUTFILE='matrix7.sav'/SNAMES=ROWTYPE_. +MSAVE 1/TYPE=COV/OUTFILE='matrix7.sav'/FNAMES=VARNAME_. +MSAVE 1/TYPE=COV/OUTFILE='matrix7.sav'/FNAMES=ROWTYPE_. +MSAVE 1/TYPE=COV/OUTFILE='matrix7.sav'/VARIABLES=VARNAME_. +MSAVE 1/TYPE=COV/OUTFILE='matrix7.sav'/VARIABLES=ROWTYPE_. +END MATRIX. +]) +AT_CHECK([pspp matrix.sps], [1], [dnl +matrix.sps:2.7: error: MSAVE: Syntax error at `!'. + +matrix.sps:3.14: error: MSAVE: Syntax error at `!': expecting COV, CORR, MEAN, +STDDEV, N, or COUNT. + +matrix.sps:4.17: error: MSAVE: Syntax error at `!': expecting a file name or +handle name. + +matrix.sps:5.19: error: MSAVE: Syntax error at `!': expecting variable name. + +matrix.sps:6.16: error: MSAVE: Syntax error at `!': expecting variable name. + +matrix.sps:7.16: error: MSAVE: Syntax error at `!': expecting variable name. + +matrix.sps:8.15: error: MSAVE: Syntax error at `!'. + +matrix.sps:9.16: error: MSAVE: Syntax error at `!'. + +matrix.sps:10.9: error: MSAVE: Syntax error at `!': expecting TYPE, OUTFILE, +VARIABLES, FNAMES, SNAMES, SPLIT, or FACTOR. + +matrix.sps:11: error: MSAVE: Required subcommand TYPE was not specified. + +matrix.sps:12: error: MSAVE: FNAMES requires FACTOR. + +matrix.sps:13: error: MSAVE: SNAMES requires SPLIT. + +matrix.sps:14: error: MSAVE: Required subcommand OUTFILE was not specified. + +matrix.sps:20: error: MSAVE: OUTFILE must name the same file on each MSAVE +within a single MATRIX command. + +matrix.sps:21: error: MSAVE: VARIABLES must specify the same variables each +time within a given MATRIX. + +matrix.sps:22: error: MSAVE: FNAMES must specify the same variables each time +within a given MATRIX. + +matrix.sps:23: error: MSAVE: SNAMES must specify the same variables each time +within a given MATRIX. + +matrix.sps:28: error: MATRIX: Matrix on MSAVE has 2 columns but there are 1 +variables. + +matrix.sps:29: error: MATRIX: All rows in a matrix must have the same number of +columns, but this tries to stack matrices with 2 and 1 columns. + +matrix.sps:30: error: MATRIX: There are 1 factor variables, but 2 factor values +were supplied. + +matrix.sps:31: error: MATRIX: There are 1 split variables, but 2 split values +were supplied. + +matrix.sps:35: error: MSAVE: Variable x appears twice in variable list. + +matrix.sps:39: error: MATRIX: Duplicate or invalid FACTOR variable name x. + +matrix.sps:43: error: MATRIX: Duplicate or invalid variable name x. + +matrix.sps:47: error: MATRIX: Duplicate or invalid variable name x. + +matrix.sps:51: error: MSAVE: Variable name VARNAME_ is reserved. + +matrix.sps:52: error: MSAVE: Variable name ROWTYPE_ is reserved. + +matrix.sps:53: error: MSAVE: Variable name VARNAME_ is reserved. + +matrix.sps:54: error: MSAVE: Variable name ROWTYPE_ is reserved. + +matrix.sps:55: error: MSAVE: Variable name VARNAME_ is reserved. + +matrix.sps:56: error: MSAVE: Variable name ROWTYPE_ is reserved. +]) +AT_CLEANUP \ No newline at end of file