1 /* PSPP - a program for statistical analysis.
2 Copyright (C) 2021 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 #include <gsl/gsl_blas.h>
20 #include <gsl/gsl_cdf.h>
21 #include <gsl/gsl_eigen.h>
22 #include <gsl/gsl_linalg.h>
23 #include <gsl/gsl_matrix.h>
24 #include <gsl/gsl_permutation.h>
25 #include <gsl/gsl_randist.h>
26 #include <gsl/gsl_vector.h>
31 #include "data/any-reader.h"
32 #include "data/any-writer.h"
33 #include "data/casereader.h"
34 #include "data/casewriter.h"
35 #include "data/data-in.h"
36 #include "data/data-out.h"
37 #include "data/dataset.h"
38 #include "data/dictionary.h"
39 #include "data/file-handle-def.h"
40 #include "language/command.h"
41 #include "language/data-io/data-reader.h"
42 #include "language/data-io/data-writer.h"
43 #include "language/data-io/file-handle.h"
44 #include "language/lexer/format-parser.h"
45 #include "language/lexer/lexer.h"
46 #include "language/lexer/variable-parser.h"
47 #include "libpspp/array.h"
48 #include "libpspp/assertion.h"
49 #include "libpspp/compiler.h"
50 #include "libpspp/hmap.h"
51 #include "libpspp/i18n.h"
52 #include "libpspp/misc.h"
53 #include "libpspp/str.h"
54 #include "libpspp/string-array.h"
55 #include "libpspp/stringi-set.h"
56 #include "libpspp/u8-line.h"
57 #include "math/distributions.h"
58 #include "math/random.h"
59 #include "output/driver.h"
60 #include "output/output-item.h"
61 #include "output/pivot-table.h"
63 #include "gl/c-ctype.h"
64 #include "gl/c-strcase.h"
65 #include "gl/ftoastr.h"
66 #include "gl/minmax.h"
70 #define _(msgid) gettext (msgid)
71 #define N_(msgid) (msgid)
75 struct hmap_node hmap_node;
83 struct file_handle *outfile;
84 struct string_array variables;
85 struct string_array fnames;
86 struct string_array snames;
89 /* Collects and owns factors and splits. The individual msave_command
90 structs point to these but do not own them. */
91 struct matrix_expr **factors;
92 size_t n_factors, allocated_factors;
93 struct matrix_expr **splits;
94 size_t n_splits, allocated_splits;
96 /* Execution state. */
97 struct dictionary *dict;
98 struct casewriter *writer;
103 struct file_handle *file;
104 struct dfm_reader *reader;
110 struct file_handle *file;
111 struct dfm_writer *writer;
113 struct u8_line *held;
118 struct file_handle *file;
119 struct dataset *dataset;
121 /* Parameters from parsing the first SAVE command for 'file'. */
122 struct string_array variables;
123 struct matrix_expr *names;
124 struct stringi_set strings;
126 /* Results from the first (only) attempt to open this save_file. */
128 struct casewriter *writer;
129 struct dictionary *dict;
134 struct dataset *dataset;
135 struct session *session;
139 struct msave_common *common;
141 struct file_handle *prev_read_file;
142 struct read_file **read_files;
145 struct file_handle *prev_write_file;
146 struct write_file **write_files;
147 size_t n_write_files;
149 struct file_handle *prev_save_file;
150 struct save_file **save_files;
154 static struct matrix_var *
155 matrix_var_lookup (struct matrix_state *s, struct substring name)
157 struct matrix_var *var;
159 HMAP_FOR_EACH_WITH_HASH (var, struct matrix_var, hmap_node,
160 utf8_hash_case_substring (name, 0), &s->vars)
161 if (!utf8_sscasecmp (ss_cstr (var->name), name))
167 static struct matrix_var *
168 matrix_var_create (struct matrix_state *s, struct substring name)
170 struct matrix_var *var = xmalloc (sizeof *var);
171 *var = (struct matrix_var) { .name = ss_xstrdup (name) };
172 hmap_insert (&s->vars, &var->hmap_node, utf8_hash_case_substring (name, 0));
177 matrix_var_set (struct matrix_var *var, gsl_matrix *value)
179 gsl_matrix_free (var->value);
183 #define MATRIX_FUNCTIONS \
184 F(ABS, "ABS", m_m_e, NULL) \
185 F(ALL, "ALL", d_m, NULL) \
186 F(ANY, "ANY", d_m, NULL) \
187 F(ARSIN, "ARSIN", m_m_e, "a[-1,1]") \
188 F(ARTAN, "ARTAN", m_m_e, NULL) \
189 F(BLOCK, "BLOCK", m_any, NULL) \
190 F(CHOL, "CHOL", m_m, NULL) \
191 F(CMIN, "CMIN", m_m, NULL) \
192 F(CMAX, "CMAX", m_m, NULL) \
193 F(COS, "COS", m_m_e, NULL) \
194 F(CSSQ, "CSSQ", m_m, NULL) \
195 F(CSUM, "CSUM", m_m, NULL) \
196 F(DESIGN, "DESIGN", m_m, NULL) \
197 F(DET, "DET", d_m, NULL) \
198 F(DIAG, "DIAG", m_m, NULL) \
199 F(EVAL, "EVAL", m_m, NULL) \
200 F(EXP, "EXP", m_m_e, NULL) \
201 F(GINV, "GINV", m_m, NULL) \
202 F(GRADE, "GRADE", m_m, NULL) \
203 F(GSCH, "GSCH", m_m, NULL) \
204 F(IDENT, "IDENT", IDENT, NULL) \
205 F(INV, "INV", m_m, NULL) \
206 F(KRONEKER, "KRONEKER", m_mm, NULL) \
207 F(LG10, "LG10", m_m_e, "a>0") \
208 F(LN, "LN", m_m_e, "a>0") \
209 F(MAGIC, "MAGIC", m_d, NULL) \
210 F(MAKE, "MAKE", m_ddd, NULL) \
211 F(MDIAG, "MDIAG", m_v, NULL) \
212 F(MMAX, "MMAX", d_m, NULL) \
213 F(MMIN, "MMIN", d_m, NULL) \
214 F(MOD, "MOD", m_md, NULL) \
215 F(MSSQ, "MSSQ", d_m, NULL) \
216 F(MSUM, "MSUM", d_m, NULL) \
217 F(NCOL, "NCOL", d_m, NULL) \
218 F(NROW, "NROW", d_m, NULL) \
219 F(RANK, "RANK", d_m, NULL) \
220 F(RESHAPE, "RESHAPE", m_mdd, NULL) \
221 F(RMAX, "RMAX", m_m, NULL) \
222 F(RMIN, "RMIN", m_m, NULL) \
223 F(RND, "RND", m_m_e, NULL) \
224 F(RNKORDER, "RNKORDER", m_m, NULL) \
225 F(RSSQ, "RSSQ", m_m, NULL) \
226 F(RSUM, "RSUM", m_m, NULL) \
227 F(SIN, "SIN", m_m_e, NULL) \
228 F(SOLVE, "SOLVE", m_mm, NULL) \
229 F(SQRT, "SQRT", m_m, NULL) \
230 F(SSCP, "SSCP", m_m, NULL) \
231 F(SVAL, "SVAL", m_m, NULL) \
232 F(SWEEP, "SWEEP", m_md, NULL) \
233 F(T, "T", m_m, NULL) \
234 F(TRACE, "TRACE", d_m, NULL) \
235 F(TRANSPOS, "TRANSPOS", m_m, NULL) \
236 F(TRUNC, "TRUNC", m_m_e, NULL) \
237 F(UNIFORM, "UNIFORM", m_dd, NULL) \
238 F(PDF_BETA, "PDF.BETA", m_mdd_e, "a[0,1] b>0 c>0") \
239 F(CDF_BETA, "CDF.BETA", m_mdd_e, "a[0,1] b>0 c>0") \
240 F(IDF_BETA, "IDF.BETA", m_mdd_e, "a[0,1] b>0 c>0") \
241 F(RV_BETA, "RV.BETA", d_dd, "a>0 b>0") \
242 F(NCDF_BETA, "NCDF.BETA", m_mddd_e, "a>=0 b>0 c>0 d>0") \
243 F(NPDF_BETA, "NCDF.BETA", m_mddd_e, "a>=0 b>0 c>0 d>0") \
244 /* XXX CDF.BVNOR */ \
245 F(PDF_BVNOR, "PDF.BVNOR", m_mdd_e, "c[-1,1]") \
246 F(CDF_CAUCHY, "CDF.CAUCHY", m_mdd_e, "c>0") \
247 F(IDF_CAUCHY, "IDF.CAUCHY", m_mdd_e, "a(0,1) c>0") \
248 F(PDF_CAUCHY, "PDF.CAUCHY", m_mdd_e, "c>0") \
249 F(RV_CAUCHY, "RV.CAUCHY", d_dd, "b>0") \
250 F(CDF_CHISQ, "CDF.CHISQ", m_md_e, "a>=0 b>0") \
251 F(IDF_CHISQ, "IDF.CHISQ", m_md_e, "a[0,1) b>0") \
252 F(PDF_CHISQ, "PDF.CHISQ", m_md_e, "a>=0 b>0") \
253 F(RV_CHISQ, "RV.CHISQ", d_d, "a>0") \
254 F(SIG_CHISQ, "SIG.CHISQ", m_md_e, "a>=0 b>0") \
255 F(CDF_EXP, "CDF.EXP", m_md_e, "a>=0 b>=0") \
256 F(IDF_EXP, "IDF.EXP", m_md_e, "a[0,1) b>0") \
257 F(PDF_EXP, "PDF.EXP", m_md_e, "a>=0 b>0") \
258 F(RV_EXP, "RV.EXP", d_d, "a>0") \
259 F(PDF_XPOWER, "PDF.XPOWER", m_mdd_e, "b>0 c>=0") \
260 F(RV_XPOWER, "RV.XPOWER", d_dd, "a>0 c>=0")
262 struct matrix_function_properties
265 const char *constraints;
276 (a > 0 && a < 1, b > 0)
277 (a >= 0 && a < 1, b > 0)
278 (a >= 0 && a <= 1, b > 0)
279 (a == 0 || a == 1, b >= 0 && b <= 1)
280 (a >= 0 && a < 1, b > 0, c > 0)
281 (a >= 0 && a <= 1, b > 0, c > 0)
282 (a >= 0 && a < 1, b >= 1, c >= 1)
283 (a >= 0 && a <= 1, b, c)
284 (a > 0 && a < 1, b, c > 0)
285 (a >= 0 && a <= 1, b <= c, c)
286 (a > 0 && a == floor (a),
287 (a >= 0 && a == floor (a) && a <= b,
288 (a >= 0 && a == floor (a) && a <= d,
289 (a >= 0 && a == floor (a), b > 0)
290 (a > 0 && a == floor (a), b >= 0 && b <= 1)
295 (a > 0, b > 0, c > 0)
296 (a >= 0, b > 0, c > 0)
297 (a >= 0, b > 0, c > 0, d > 0)
298 (a >= 0, b > 0, c > 0, d >= 0)
299 (a > 0, b >= 1, c >= 1)
300 (a >= 1 && a == floor (a), b >= 0 && b <= 1)
301 (a >= 1, b > 0 && b <= 1)
302 (a >= 1, b == floor (b), c > 0 && c <= 1)
306 (a, b > 0 && b <= 2, c >= -1 && c <= 1)
307 (a, b > 0 && b == floor (c), c >= 0 && c <= 1)
312 (a >= b, b > 0, c > 0)
315 (a, b, c >= -1 && c <= 1)
317 (a == floor (a), b > 0 && b <= 1)
318 b > 0 && b == floor (b),
319 b > 0 && b == floor (b) && b <= a,
321 c > 0 && c == floor (c) && c <= a)
322 c > 0 && c == floor (c) && c <= b,
323 d > 0 && d == floor (d) && d <= b)
326 enum { d_d_MIN_ARGS = 1, d_d_MAX_ARGS = 1 };
327 enum { d_dd_MIN_ARGS = 2, d_dd_MAX_ARGS = 2 };
328 enum { m_d_MIN_ARGS = 1, m_d_MAX_ARGS = 1 };
329 enum { m_dd_MIN_ARGS = 2, m_dd_MAX_ARGS = 2 };
330 enum { m_ddd_MIN_ARGS = 3, m_ddd_MAX_ARGS = 3 };
331 enum { m_m_MIN_ARGS = 1, m_m_MAX_ARGS = 1 };
332 enum { m_m_e_MIN_ARGS = 1, m_m_e_MAX_ARGS = 1 };
333 enum { m_md_MIN_ARGS = 2, m_md_MAX_ARGS = 2 };
334 enum { m_md_e_MIN_ARGS = 2, m_md_e_MAX_ARGS = 2 };
335 enum { m_mdd_MIN_ARGS = 3, m_mdd_MAX_ARGS = 3 };
336 enum { m_mdd_e_MIN_ARGS = 3, m_mdd_e_MAX_ARGS = 3 };
337 enum { m_mddd_e_MIN_ARGS = 4, m_mddd_e_MAX_ARGS = 4 };
338 enum { m_mm_MIN_ARGS = 2, m_mm_MAX_ARGS = 2 };
339 enum { m_v_MIN_ARGS = 1, m_v_MAX_ARGS = 1 };
340 enum { d_m_MIN_ARGS = 1, d_m_MAX_ARGS = 1 };
341 enum { m_any_MIN_ARGS = 1, m_any_MAX_ARGS = INT_MAX };
342 enum { IDENT_MIN_ARGS = 1, IDENT_MAX_ARGS = 2 };
344 typedef double matrix_proto_d_d (double);
345 typedef double matrix_proto_d_dd (double, double);
346 typedef gsl_matrix *matrix_proto_m_d (double);
347 typedef gsl_matrix *matrix_proto_m_dd (double, double);
348 typedef gsl_matrix *matrix_proto_m_ddd (double, double, double);
349 typedef gsl_matrix *matrix_proto_m_m (gsl_matrix *);
350 typedef double matrix_proto_m_m_e (double);
351 typedef gsl_matrix *matrix_proto_m_md (gsl_matrix *, double);
352 typedef double matrix_proto_m_md_e (double, double);
353 typedef gsl_matrix *matrix_proto_m_mdd (gsl_matrix *, double, double);
354 typedef double matrix_proto_m_mdd_e (double, double, double);
355 typedef double matrix_proto_m_mddd_e (double, double, double, double);
356 typedef gsl_matrix *matrix_proto_m_mm (gsl_matrix *, gsl_matrix *);
357 typedef gsl_matrix *matrix_proto_m_v (gsl_vector *);
358 typedef double matrix_proto_d_m (gsl_matrix *);
359 typedef gsl_matrix *matrix_proto_m_any (gsl_matrix *[], size_t n);
360 typedef gsl_matrix *matrix_proto_IDENT (double, double);
362 #define F(ENUM, STRING, PROTO, CONSTRAINTS) \
363 static matrix_proto_##PROTO matrix_eval_##ENUM;
367 /* Matrix expressions. */
374 #define F(ENUM, STRING, PROTO, CONSTRAINTS) MOP_F_##ENUM,
378 /* Elementwise and scalar arithmetic. */
379 MOP_NEGATE, /* unary - */
380 MOP_ADD_ELEMS, /* + */
381 MOP_SUB_ELEMS, /* - */
382 MOP_MUL_ELEMS, /* &* */
383 MOP_DIV_ELEMS, /* / and &/ */
384 MOP_EXP_ELEMS, /* &** */
386 MOP_SEQ_BY, /* a:b:c */
388 /* Matrix arithmetic. */
390 MOP_EXP_MAT, /* ** */
407 MOP_PASTE_HORZ, /* a, b, c, ... */
408 MOP_PASTE_VERT, /* a; b; c; ... */
412 MOP_VEC_INDEX, /* x(y) */
413 MOP_VEC_ALL, /* x(:) */
414 MOP_MAT_INDEX, /* x(y,z) */
415 MOP_ROW_INDEX, /* x(y,:) */
416 MOP_COL_INDEX, /* x(:,z) */
423 MOP_EOF, /* EOF('file') */
431 struct matrix_expr **subs;
436 struct matrix_var *variable;
437 struct read_file *eof;
442 matrix_expr_destroy (struct matrix_expr *e)
449 #define F(ENUM, STRING, PROTO, CONSTRAINTS) case MOP_F_##ENUM:
480 for (size_t i = 0; i < e->n_subs; i++)
481 matrix_expr_destroy (e->subs[i]);
493 static struct matrix_expr *
494 matrix_expr_create_subs (enum matrix_op op, struct matrix_expr **subs,
497 struct matrix_expr *e = xmalloc (sizeof *e);
498 *e = (struct matrix_expr) {
500 .subs = xmemdup (subs, n_subs * sizeof *subs),
506 static struct matrix_expr *
507 matrix_expr_create_0 (enum matrix_op op)
509 struct matrix_expr *sub;
510 return matrix_expr_create_subs (op, &sub, 0);
513 static struct matrix_expr *
514 matrix_expr_create_1 (enum matrix_op op, struct matrix_expr *sub)
516 return matrix_expr_create_subs (op, &sub, 1);
519 static struct matrix_expr *
520 matrix_expr_create_2 (enum matrix_op op,
521 struct matrix_expr *sub0, struct matrix_expr *sub1)
523 struct matrix_expr *subs[] = { sub0, sub1 };
524 return matrix_expr_create_subs (op, subs, sizeof subs / sizeof *subs);
527 static struct matrix_expr *
528 matrix_expr_create_3 (enum matrix_op op, struct matrix_expr *sub0,
529 struct matrix_expr *sub1, struct matrix_expr *sub2)
531 struct matrix_expr *subs[] = { sub0, sub1, sub2 };
532 return matrix_expr_create_subs (op, subs, sizeof subs / sizeof *subs);
535 static struct matrix_expr *
536 matrix_expr_create_number (double number)
538 struct matrix_expr *e = xmalloc (sizeof *e);
539 *e = (struct matrix_expr) { .op = MOP_NUMBER, .number = number };
543 static struct matrix_expr *matrix_parse_or_xor (struct matrix_state *);
545 static struct matrix_expr *
546 matrix_parse_curly_comma (struct matrix_state *s)
548 struct matrix_expr *lhs = matrix_parse_or_xor (s);
552 while (lex_match (s->lexer, T_COMMA))
554 struct matrix_expr *rhs = matrix_parse_or_xor (s);
557 matrix_expr_destroy (lhs);
560 lhs = matrix_expr_create_2 (MOP_PASTE_HORZ, lhs, rhs);
565 static struct matrix_expr *
566 matrix_parse_curly_semi (struct matrix_state *s)
568 if (lex_token (s->lexer) == T_RCURLY)
569 return matrix_expr_create_0 (MOP_EMPTY);
571 struct matrix_expr *lhs = matrix_parse_curly_comma (s);
575 while (lex_match (s->lexer, T_SEMICOLON))
577 struct matrix_expr *rhs = matrix_parse_curly_comma (s);
580 matrix_expr_destroy (lhs);
583 lhs = matrix_expr_create_2 (MOP_PASTE_VERT, lhs, rhs);
588 #define MATRIX_FOR_ALL_ELEMENTS(D, Y, X, M) \
589 for (size_t Y = 0; Y < (M)->size1; Y++) \
590 for (size_t X = 0; X < (M)->size2; X++) \
591 for (double *D = gsl_matrix_ptr ((M), Y, X); D; D = NULL)
594 is_vector (const gsl_matrix *m)
596 return m->size1 <= 1 || m->size2 <= 1;
600 to_vector (gsl_matrix *m)
602 return (m->size1 == 1
603 ? gsl_matrix_row (m, 0).vector
604 : gsl_matrix_column (m, 0).vector);
609 matrix_eval_ABS (double d)
615 matrix_eval_ALL (gsl_matrix *m)
617 MATRIX_FOR_ALL_ELEMENTS (d, y, x, m)
624 matrix_eval_ANY (gsl_matrix *m)
626 MATRIX_FOR_ALL_ELEMENTS (d, y, x, m)
633 matrix_eval_ARSIN (double d)
639 matrix_eval_ARTAN (double d)
645 matrix_eval_BLOCK (gsl_matrix *m[], size_t n)
649 for (size_t i = 0; i < n; i++)
654 gsl_matrix *block = gsl_matrix_calloc (r, c);
656 for (size_t i = 0; i < n; i++)
658 for (size_t y = 0; y < m[i]->size1; y++)
659 for (size_t x = 0; x < m[i]->size2; x++)
660 gsl_matrix_set (block, r + y, c + x, gsl_matrix_get (m[i], y, x));
668 matrix_eval_CHOL (gsl_matrix *m)
670 if (!gsl_linalg_cholesky_decomp1 (m))
672 for (size_t y = 0; y < m->size1; y++)
673 for (size_t x = y + 1; x < m->size2; x++)
674 gsl_matrix_set (m, y, x, gsl_matrix_get (m, x, y));
676 for (size_t y = 0; y < m->size1; y++)
677 for (size_t x = 0; x < y; x++)
678 gsl_matrix_set (m, y, x, 0);
683 msg (SE, _("Input to CHOL function is not positive-definite."));
689 matrix_eval_col_extremum (gsl_matrix *m, bool min)
694 return gsl_matrix_alloc (1, 0);
696 gsl_matrix *cext = gsl_matrix_alloc (1, m->size2);
697 for (size_t x = 0; x < m->size2; x++)
699 double ext = gsl_matrix_get (m, 0, x);
700 for (size_t y = 1; y < m->size1; y++)
702 double value = gsl_matrix_get (m, y, x);
703 if (min ? value < ext : value > ext)
706 gsl_matrix_set (cext, 0, x, ext);
712 matrix_eval_CMAX (gsl_matrix *m)
714 return matrix_eval_col_extremum (m, false);
718 matrix_eval_CMIN (gsl_matrix *m)
720 return matrix_eval_col_extremum (m, true);
724 matrix_eval_COS (double d)
730 matrix_eval_col_sum (gsl_matrix *m, bool square)
735 return gsl_matrix_alloc (1, 0);
737 gsl_matrix *result = gsl_matrix_alloc (1, m->size2);
738 for (size_t x = 0; x < m->size2; x++)
741 for (size_t y = 0; y < m->size1; y++)
743 double d = gsl_matrix_get (m, y, x);
744 sum += square ? pow2 (d) : d;
746 gsl_matrix_set (result, 0, x, sum);
752 matrix_eval_CSSQ (gsl_matrix *m)
754 return matrix_eval_col_sum (m, true);
758 matrix_eval_CSUM (gsl_matrix *m)
760 return matrix_eval_col_sum (m, false);
764 compare_double_3way (const void *a_, const void *b_)
766 const double *a = a_;
767 const double *b = b_;
768 return *a < *b ? -1 : *a > *b;
772 matrix_eval_DESIGN (gsl_matrix *m)
774 double *tmp = xmalloc (m->size1 * m->size2 * sizeof *tmp);
775 gsl_matrix m2 = gsl_matrix_view_array (tmp, m->size2, m->size1).matrix;
776 gsl_matrix_transpose_memcpy (&m2, m);
778 for (size_t y = 0; y < m2.size1; y++)
779 qsort (tmp + y * m2.size2, m2.size2, sizeof *tmp, compare_double_3way);
781 size_t *n = xcalloc (m2.size1, sizeof *n);
783 for (size_t i = 0; i < m2.size1; i++)
785 double *row = tmp + m2.size2 * i;
786 for (size_t j = 0; j < m2.size2; )
789 for (k = j + 1; k < m2.size2; k++)
790 if (row[j] != row[k])
792 row[n[i]++] = row[j];
797 msg (MW, _("Column %zu in DESIGN argument has constant value."), i + 1);
802 gsl_matrix *result = gsl_matrix_alloc (m->size1, n_total);
804 for (size_t i = 0; i < m->size2; i++)
809 const double *unique = tmp + m2.size2 * i;
810 for (size_t j = 0; j < n[i]; j++, x++)
812 double value = unique[j];
813 for (size_t y = 0; y < m->size1; y++)
814 gsl_matrix_set (result, y, x, gsl_matrix_get (m, y, i) == value);
825 matrix_eval_DET (gsl_matrix *m)
827 gsl_permutation *p = gsl_permutation_alloc (m->size1);
829 gsl_linalg_LU_decomp (m, p, &signum);
830 gsl_permutation_free (p);
831 return gsl_linalg_LU_det (m, signum);
835 matrix_eval_DIAG (gsl_matrix *m)
837 gsl_matrix *diag = gsl_matrix_alloc (MIN (m->size1, m->size2), 1);
838 for (size_t i = 0; i < diag->size1; i++)
839 gsl_matrix_set (diag, i, 0, gsl_matrix_get (m, i, i));
844 is_symmetric (const gsl_matrix *m)
846 if (m->size1 != m->size2)
849 for (size_t y = 0; y < m->size1; y++)
850 for (size_t x = 0; x < y; x++)
851 if (gsl_matrix_get (m, y, x) != gsl_matrix_get (m, x, y))
858 compare_double_desc (const void *a_, const void *b_)
860 const double *a = a_;
861 const double *b = b_;
862 return *a > *b ? -1 : *a < *b;
866 matrix_eval_EVAL (gsl_matrix *m)
868 if (!is_symmetric (m))
870 msg (SE, _("Argument of EVAL must be symmetric."));
874 gsl_eigen_symm_workspace *w = gsl_eigen_symm_alloc (m->size1);
875 gsl_matrix *eval = gsl_matrix_alloc (m->size1, 1);
876 gsl_vector v_eval = to_vector (eval);
877 gsl_eigen_symm (m, &v_eval, w);
878 gsl_eigen_symm_free (w);
880 assert (v_eval.stride == 1);
881 qsort (v_eval.data, v_eval.size, sizeof *v_eval.data, compare_double_desc);
887 matrix_eval_EXP (double d)
892 /* From https://gist.github.com/turingbirds/5e99656e08dbe1324c99, where it was
895 Charl Linssen <charl@itfromb.it>
899 matrix_eval_GINV (gsl_matrix *A)
904 gsl_matrix *tmp_mat = NULL;
907 /* libgsl SVD can only handle the case m <= n, so transpose matrix. */
908 tmp_mat = gsl_matrix_alloc (m, n);
909 gsl_matrix_transpose_memcpy (tmp_mat, A);
917 gsl_matrix *V = gsl_matrix_alloc (m, m);
918 gsl_vector *u = gsl_vector_alloc (m);
920 gsl_vector *tmp_vec = gsl_vector_alloc (m);
921 gsl_linalg_SV_decomp (A, V, u, tmp_vec);
922 gsl_vector_free (tmp_vec);
925 gsl_matrix *Sigma_pinv = gsl_matrix_alloc (m, n);
926 gsl_matrix_set_zero (Sigma_pinv);
927 double cutoff = 1e-15 * gsl_vector_max (u);
929 for (size_t i = 0; i < m; ++i)
931 double x = gsl_vector_get (u, i);
932 gsl_matrix_set (Sigma_pinv, i, i, x > cutoff ? 1.0 / x : 0);
935 /* libgsl SVD yields "thin" SVD - pad to full matrix by adding zeros */
936 gsl_matrix *U = gsl_matrix_calloc (n, n);
937 for (size_t i = 0; i < n; i++)
938 for (size_t j = 0; j < m; j++)
939 gsl_matrix_set (U, i, j, gsl_matrix_get (A, i, j));
941 /* two dot products to obtain pseudoinverse */
942 gsl_matrix *tmp_mat2 = gsl_matrix_alloc (m, n);
943 gsl_blas_dgemm (CblasNoTrans, CblasNoTrans, 1., V, Sigma_pinv, 0., tmp_mat2);
948 A_pinv = gsl_matrix_alloc (n, m);
949 gsl_blas_dgemm (CblasNoTrans, CblasTrans, 1., U, tmp_mat2, 0., A_pinv);
953 A_pinv = gsl_matrix_alloc (m, n);
954 gsl_blas_dgemm (CblasNoTrans, CblasTrans, 1., tmp_mat2, U, 0., A_pinv);
957 gsl_matrix_free (tmp_mat);
958 gsl_matrix_free (tmp_mat2);
960 gsl_matrix_free (Sigma_pinv);
974 grade_compare_3way (const void *a_, const void *b_)
976 const struct grade *a = a_;
977 const struct grade *b = b_;
979 return (a->value < b->value ? -1
980 : a->value > b->value ? 1
988 matrix_eval_GRADE (gsl_matrix *m)
990 size_t n = m->size1 * m->size2;
991 struct grade *grades = xmalloc (n * sizeof *grades);
994 MATRIX_FOR_ALL_ELEMENTS (d, y, x, m)
995 grades[i++] = (struct grade) { .y = y, .x = x, .value = *d };
996 qsort (grades, n, sizeof *grades, grade_compare_3way);
998 for (size_t i = 0; i < n; i++)
999 gsl_matrix_set (m, grades[i].y, grades[i].x, i + 1);
1007 dot (gsl_vector *a, gsl_vector *b)
1009 double result = 0.0;
1010 for (size_t i = 0; i < a->size; i++)
1011 result += gsl_vector_get (a, i) * gsl_vector_get (b, i);
1016 norm2 (gsl_vector *v)
1018 double result = 0.0;
1019 for (size_t i = 0; i < v->size; i++)
1020 result += pow2 (gsl_vector_get (v, i));
1025 norm (gsl_vector *v)
1027 return sqrt (norm2 (v));
1031 matrix_eval_GSCH (gsl_matrix *v)
1033 if (v->size2 < v->size1)
1035 msg (SE, _("GSCH requires its argument to have at least as many columns "
1036 "as rows, but it has dimensions %zu×%zu."),
1037 v->size1, v->size2);
1040 if (!v->size1 || !v->size2)
1043 gsl_matrix *u = gsl_matrix_calloc (v->size1, v->size2);
1045 for (size_t vx = 0; vx < v->size2; vx++)
1047 gsl_vector u_i = gsl_matrix_column (u, ux).vector;
1048 gsl_vector v_i = gsl_matrix_column (v, vx).vector;
1050 gsl_vector_memcpy (&u_i, &v_i);
1051 for (size_t j = 0; j < ux; j++)
1053 gsl_vector u_j = gsl_matrix_column (u, j).vector;
1054 double scale = dot (&u_j, &u_i) / norm2 (&u_j);
1055 for (size_t k = 0; k < u_i.size; k++)
1056 gsl_vector_set (&u_i, k, (gsl_vector_get (&u_i, k)
1057 - scale * gsl_vector_get (&u_j, k)));
1060 double len = norm (&u_i);
1063 gsl_vector_scale (&u_i, 1.0 / len);
1064 if (++ux >= v->size1)
1071 msg (SE, _("%zu×%zu argument to GSCH contains only "
1072 "%zu linearly independent columns."),
1073 v->size1, v->size2, ux);
1074 gsl_matrix_free (u);
1078 u->size2 = v->size1;
1083 matrix_eval_IDENT (double s1, double s2)
1085 if (s1 < 0 || s1 > SIZE_MAX || s2 < 0 || s2 > SIZE_MAX)
1087 msg (SE, _("Arguments to IDENT must be non-negative integers."));
1091 gsl_matrix *m = gsl_matrix_alloc (s1, s2);
1092 MATRIX_FOR_ALL_ELEMENTS (d, y, x, m)
1098 invert_matrix (gsl_matrix *x)
1100 gsl_permutation *p = gsl_permutation_alloc (x->size1);
1102 gsl_linalg_LU_decomp (x, p, &signum);
1103 gsl_linalg_LU_invx (x, p);
1104 gsl_permutation_free (p);
1108 matrix_eval_INV (gsl_matrix *m)
1115 matrix_eval_KRONEKER (gsl_matrix *a, gsl_matrix *b)
1117 gsl_matrix *k = gsl_matrix_alloc (a->size1 * b->size1,
1118 a->size2 * b->size2);
1120 for (size_t ar = 0; ar < a->size1; ar++)
1121 for (size_t br = 0; br < b->size1; br++, y++)
1124 for (size_t ac = 0; ac < a->size2; ac++)
1125 for (size_t bc = 0; bc < b->size2; bc++, x++)
1127 double av = gsl_matrix_get (a, ar, ac);
1128 double bv = gsl_matrix_get (b, br, bc);
1129 gsl_matrix_set (k, y, x, av * bv);
1136 matrix_eval_LG10 (double d)
1142 matrix_eval_LN (double d)
1148 matrix_eval_MAGIC_odd (gsl_matrix *m, size_t n)
1150 /* Siamese method: https://en.wikipedia.org/wiki/Siamese_method. */
1153 for (size_t i = 1; i <= n * n; i++)
1155 gsl_matrix_set (m, y, x, i);
1157 size_t y1 = !y ? n - 1 : y - 1;
1158 size_t x1 = x + 1 >= n ? 0 : x + 1;
1159 if (gsl_matrix_get (m, y1, x1) == 0)
1165 y = y + 1 >= n ? 0 : y + 1;
1170 magic_exchange (gsl_matrix *m, size_t y1, size_t x1, size_t y2, size_t x2)
1172 double a = gsl_matrix_get (m, y1, x1);
1173 double b = gsl_matrix_get (m, y2, x2);
1174 gsl_matrix_set (m, y1, x1, b);
1175 gsl_matrix_set (m, y2, x2, a);
1179 matrix_eval_MAGIC_doubly_even (gsl_matrix *m, size_t n)
1183 /* A. Umar, "On the Construction of Even Order Magic Squares",
1184 https://arxiv.org/ftp/arxiv/papers/1202/1202.0948.pdf. */
1186 for (size_t i = 1; i <= n * n / 2; i++)
1188 gsl_matrix_set (m, y, x, i);
1198 for (size_t i = n * n; i > n * n / 2; i--)
1200 gsl_matrix_set (m, y, x, i);
1208 for (size_t y = 0; y < n; y++)
1209 for (size_t x = 0; x < n / 2; x++)
1211 unsigned int d = gsl_matrix_get (m, y, x);
1212 if (d % 2 != (y < n / 2))
1213 magic_exchange (m, y, x, y, n - x - 1);
1218 size_t x1 = n / 2 - 1;
1220 magic_exchange (m, y1, x1, y2, x1);
1221 magic_exchange (m, y1, x2, y2, x2);
1225 matrix_eval_MAGIC_singly_even (gsl_matrix *m, size_t n)
1227 /* A. Umar, "On the Construction of Even Order Magic Squares",
1228 https://arxiv.org/ftp/arxiv/papers/1202/1202.0948.pdf. */
1232 for (size_t i = 1; ; i++)
1234 gsl_matrix_set (m, y, x, i);
1235 if (++y == n / 2 - 1)
1247 for (size_t i = n * n; ; i--)
1249 gsl_matrix_set (m, y, x, i);
1250 if (++y == n / 2 - 1)
1259 for (size_t y = 0; y < n; y++)
1260 if (y != n / 2 - 1 && y != n / 2)
1261 for (size_t x = 0; x < n / 2; x++)
1263 unsigned int d = gsl_matrix_get (m, y, x);
1264 if (d % 2 != (y < n / 2))
1265 magic_exchange (m, y, x, y, n - x - 1);
1268 size_t a0 = (n * n - 2 * n) / 2 + 1;
1269 for (size_t i = 0; i < n / 2; i++)
1272 gsl_matrix_set (m, n / 2, i, a);
1273 gsl_matrix_set (m, n / 2 - 1, i, (n * n + 1) - a);
1275 for (size_t i = 0; i < n / 2; i++)
1277 size_t a = a0 + i + n / 2;
1278 gsl_matrix_set (m, n / 2 - 1, n - i - 1, a);
1279 gsl_matrix_set (m, n / 2, n - i - 1, (n * n + 1) - a);
1281 for (size_t x = 1; x < n / 2; x += 2)
1282 magic_exchange (m, n / 2, x, n / 2 - 1, x);
1283 for (size_t x = n / 2 + 2; x <= n - 3; x += 2)
1284 magic_exchange (m, n / 2, x, n / 2 - 1, x);
1285 size_t x1 = n / 2 - 2;
1286 size_t x2 = n / 2 + 1;
1287 size_t y1 = n / 2 - 2;
1288 size_t y2 = n / 2 + 1;
1289 magic_exchange (m, y1, x1, y2, x1);
1290 magic_exchange (m, y1, x2, y2, x2);
1294 matrix_eval_MAGIC (double n_)
1296 if (n_ < 3 || n_ >= sqrt (SIZE_MAX))
1298 msg (SE, _("MAGIC argument must be an integer 3 or greater."));
1303 gsl_matrix *m = gsl_matrix_calloc (n, n);
1305 matrix_eval_MAGIC_odd (m, n);
1307 matrix_eval_MAGIC_singly_even (m, n);
1309 matrix_eval_MAGIC_doubly_even (m, n);
1314 matrix_eval_MAKE (double r, double c, double value)
1316 if (r < 0 || r >= SIZE_MAX || c < 0 || c >= SIZE_MAX)
1318 msg (SE, _("Size arguments to MAKE must be integers."));
1322 gsl_matrix *m = gsl_matrix_alloc (r, c);
1323 MATRIX_FOR_ALL_ELEMENTS (d, y, x, m)
1329 matrix_eval_MDIAG (gsl_vector *v)
1331 gsl_matrix *m = gsl_matrix_calloc (v->size, v->size);
1332 gsl_vector diagonal = gsl_matrix_diagonal (m).vector;
1333 gsl_vector_memcpy (&diagonal, v);
1338 matrix_eval_MMAX (gsl_matrix *m)
1340 return gsl_matrix_max (m);
1344 matrix_eval_MMIN (gsl_matrix *m)
1346 return gsl_matrix_min (m);
1350 matrix_eval_MOD (gsl_matrix *m, double divisor)
1354 msg (SE, _("Divisor argument to MOD function must be nonzero."));
1358 MATRIX_FOR_ALL_ELEMENTS (d, y, x, m)
1359 *d = fmod (*d, divisor);
1364 matrix_eval_MSSQ (gsl_matrix *m)
1367 MATRIX_FOR_ALL_ELEMENTS (d, y, x, m)
1373 matrix_eval_MSUM (gsl_matrix *m)
1376 MATRIX_FOR_ALL_ELEMENTS (d, y, x, m)
1382 matrix_eval_NCOL (gsl_matrix *m)
1388 matrix_eval_NROW (gsl_matrix *m)
1394 matrix_eval_RANK (gsl_matrix *m)
1396 gsl_vector *tau = gsl_vector_alloc (MIN (m->size1, m->size2));
1397 gsl_linalg_QR_decomp (m, tau);
1398 gsl_vector_free (tau);
1400 return gsl_linalg_QRPT_rank (m, -1);
1404 matrix_eval_RESHAPE (gsl_matrix *m, double r_, double c_)
1406 if (r_ < 0 || r_ >= SIZE_MAX || c_ < 0 || c_ >= SIZE_MAX)
1408 msg (SE, _("Arguments 2 and 3 to RESHAPE must be integers."));
1413 if (size_overflow_p (xtimes (r, xmax (c, 1))) || c * r != m->size1 * m->size2)
1415 msg (SE, _("Product of RESHAPE arguments 2 and 3 differ from "
1416 "product of matrix dimensions."));
1420 gsl_matrix *dst = gsl_matrix_alloc (r, c);
1423 MATRIX_FOR_ALL_ELEMENTS (d, y2, x2, m)
1425 gsl_matrix_set (dst, y1, x1, *d);
1436 matrix_eval_row_extremum (gsl_matrix *m, bool min)
1441 return gsl_matrix_alloc (0, 1);
1443 gsl_matrix *rext = gsl_matrix_alloc (m->size1, 1);
1444 for (size_t y = 0; y < m->size1; y++)
1446 double ext = gsl_matrix_get (m, y, 0);
1447 for (size_t x = 1; x < m->size2; x++)
1449 double value = gsl_matrix_get (m, y, x);
1450 if (min ? value < ext : value > ext)
1453 gsl_matrix_set (rext, y, 0, ext);
1459 matrix_eval_RMAX (gsl_matrix *m)
1461 return matrix_eval_row_extremum (m, false);
1465 matrix_eval_RMIN (gsl_matrix *m)
1467 return matrix_eval_row_extremum (m, true);
1471 matrix_eval_RND (double d)
1483 rank_compare_3way (const void *a_, const void *b_)
1485 const struct rank *a = a_;
1486 const struct rank *b = b_;
1488 return a->value < b->value ? -1 : a->value > b->value;
1492 matrix_eval_RNKORDER (gsl_matrix *m)
1494 size_t n = m->size1 * m->size2;
1495 struct rank *ranks = xmalloc (n * sizeof *ranks);
1497 MATRIX_FOR_ALL_ELEMENTS (d, y, x, m)
1498 ranks[i++] = (struct rank) { .y = y, .x = x, .value = *d };
1499 qsort (ranks, n, sizeof *ranks, rank_compare_3way);
1501 for (size_t i = 0; i < n; )
1504 for (j = i + 1; j < n; j++)
1505 if (ranks[i].value != ranks[j].value)
1508 double rank = (i + j + 1.0) / 2.0;
1509 for (size_t k = i; k < j; k++)
1510 gsl_matrix_set (m, ranks[k].y, ranks[k].x, rank);
1521 matrix_eval_row_sum (gsl_matrix *m, bool square)
1526 return gsl_matrix_alloc (0, 1);
1528 gsl_matrix *result = gsl_matrix_alloc (m->size1, 1);
1529 for (size_t y = 0; y < m->size1; y++)
1532 for (size_t x = 0; x < m->size2; x++)
1534 double d = gsl_matrix_get (m, y, x);
1535 sum += square ? pow2 (d) : d;
1537 gsl_matrix_set (result, y, 0, sum);
1543 matrix_eval_RSSQ (gsl_matrix *m)
1545 return matrix_eval_row_sum (m, true);
1549 matrix_eval_RSUM (gsl_matrix *m)
1551 return matrix_eval_row_sum (m, false);
1555 matrix_eval_SIN (double d)
1561 matrix_eval_SOLVE (gsl_matrix *m1, gsl_matrix *m2)
1563 if (m1->size1 != m2->size1)
1565 msg (SE, _("SOLVE requires its arguments to have the same number of "
1566 "rows, but the first argument has dimensions %zu×%zu and "
1567 "the second %zu×%zu."),
1568 m1->size1, m1->size2,
1569 m2->size1, m2->size2);
1573 gsl_matrix *x = gsl_matrix_alloc (m2->size1, m2->size2);
1574 gsl_permutation *p = gsl_permutation_alloc (m1->size1);
1576 gsl_linalg_LU_decomp (m1, p, &signum);
1577 for (size_t i = 0; i < m2->size2; i++)
1579 gsl_vector bi = gsl_matrix_column (m2, i).vector;
1580 gsl_vector xi = gsl_matrix_column (x, i).vector;
1581 gsl_linalg_LU_solve (m1, p, &bi, &xi);
1583 gsl_permutation_free (p);
1588 matrix_eval_SQRT (gsl_matrix *m)
1590 MATRIX_FOR_ALL_ELEMENTS (d, y, x, m)
1594 msg (SE, _("Argument to SQRT must be nonnegative."));
1603 matrix_eval_SSCP (gsl_matrix *m)
1605 gsl_matrix *sscp = gsl_matrix_alloc (m->size2, m->size2);
1606 gsl_blas_dgemm (CblasTrans, CblasNoTrans, 1.0, m, m, 0.0, sscp);
1611 matrix_eval_SVAL (gsl_matrix *m)
1613 gsl_matrix *tmp_mat = NULL;
1614 if (m->size2 > m->size1)
1616 tmp_mat = gsl_matrix_alloc (m->size2, m->size1);
1617 gsl_matrix_transpose_memcpy (tmp_mat, m);
1622 gsl_matrix *V = gsl_matrix_alloc (m->size2, m->size2);
1623 gsl_vector *S = gsl_vector_alloc (m->size2);
1624 gsl_vector *work = gsl_vector_alloc (m->size2);
1625 gsl_linalg_SV_decomp (m, V, S, work);
1627 gsl_matrix *vals = gsl_matrix_alloc (m->size2, 1);
1628 for (size_t i = 0; i < m->size2; i++)
1629 gsl_matrix_set (vals, i, 0, gsl_vector_get (S, i));
1631 gsl_matrix_free (V);
1632 gsl_vector_free (S);
1633 gsl_vector_free (work);
1634 gsl_matrix_free (tmp_mat);
1640 matrix_eval_SWEEP (gsl_matrix *m, double d)
1642 if (d < 1 || d > SIZE_MAX)
1644 msg (SE, _("Scalar argument to SWEEP must be integer."));
1648 if (k >= MIN (m->size1, m->size2))
1650 msg (SE, _("Scalar argument to SWEEP must be integer less than or "
1651 "equal to the smaller of the matrix argument's rows and "
1656 double m_kk = gsl_matrix_get (m, k, k);
1657 if (fabs (m_kk) > 1e-19)
1659 gsl_matrix *a = gsl_matrix_alloc (m->size1, m->size2);
1660 MATRIX_FOR_ALL_ELEMENTS (a_ij, i, j, a)
1662 double m_ij = gsl_matrix_get (m, i, j);
1663 double m_ik = gsl_matrix_get (m, i, k);
1664 double m_kj = gsl_matrix_get (m, k, j);
1665 *a_ij = (i != k && j != k ? m_ij * m_kk - m_ik * m_kj
1674 for (size_t i = 0; i < m->size1; i++)
1676 gsl_matrix_set (m, i, k, 0);
1677 gsl_matrix_set (m, k, i, 0);
1684 matrix_eval_TRACE (gsl_matrix *m)
1687 size_t n = MIN (m->size1, m->size2);
1688 for (size_t i = 0; i < n; i++)
1689 sum += gsl_matrix_get (m, i, i);
1694 matrix_eval_T (gsl_matrix *m)
1696 return matrix_eval_TRANSPOS (m);
1700 matrix_eval_TRANSPOS (gsl_matrix *m)
1702 if (m->size1 == m->size2)
1704 gsl_matrix_transpose (m);
1709 gsl_matrix *t = gsl_matrix_alloc (m->size2, m->size1);
1710 gsl_matrix_transpose_memcpy (t, m);
1716 matrix_eval_TRUNC (double d)
1722 matrix_eval_UNIFORM (double r_, double c_)
1724 if (r_ < 0 || r_ >= SIZE_MAX || c_ < 0 || c_ >= SIZE_MAX)
1726 msg (SE, _("Arguments to UNIFORM must be integers."));
1731 if (size_overflow_p (xtimes (r, xmax (c, 1))))
1733 msg (SE, _("Product of arguments to UNIFORM exceeds memory size."));
1737 gsl_matrix *m = gsl_matrix_alloc (r, c);
1738 MATRIX_FOR_ALL_ELEMENTS (d, y, x, m)
1739 *d = gsl_ran_flat (get_rng (), 0, 1);
1744 matrix_eval_PDF_BETA (double x, double a, double b)
1746 return gsl_ran_beta_pdf (x, a, b);
1750 matrix_eval_CDF_BETA (double x, double a, double b)
1752 return gsl_cdf_beta_P (x, a, b);
1756 matrix_eval_IDF_BETA (double P, double a, double b)
1758 return gsl_cdf_beta_Pinv (P, a, b);
1762 matrix_eval_RV_BETA (double a, double b)
1764 return gsl_ran_beta (get_rng (), a, b);
1768 matrix_eval_NCDF_BETA (double x, double a, double b, double lambda)
1770 return ncdf_beta (x, a, b, lambda);
1774 matrix_eval_NPDF_BETA (double x, double a, double b, double lambda)
1776 return npdf_beta (x, a, b, lambda);
1780 matrix_eval_PDF_BVNOR (double x0, double x1, double r)
1782 return gsl_ran_bivariate_gaussian_pdf (x0, x1, 1, 1, r);
1786 matrix_eval_CDF_CAUCHY (double x, double a, double b)
1788 return gsl_cdf_cauchy_P ((x - a) / b, 1);
1792 matrix_eval_IDF_CAUCHY (double P, double a, double b)
1794 return a + b * gsl_cdf_cauchy_Pinv (P, 1);
1798 matrix_eval_PDF_CAUCHY (double x, double a, double b)
1800 return gsl_ran_cauchy_pdf ((x - a) / b, 1) / b;
1804 matrix_eval_RV_CAUCHY (double a, double b)
1806 return a + b * gsl_ran_cauchy (get_rng (), 1);
1810 matrix_eval_CDF_CHISQ (double x, double df)
1812 return gsl_cdf_chisq_P (x, df);
1816 matrix_eval_IDF_CHISQ (double P, double df)
1818 return gsl_cdf_chisq_Pinv (P, df);
1822 matrix_eval_PDF_CHISQ (double x, double df)
1824 return gsl_ran_chisq_pdf (x, df);
1828 matrix_eval_RV_CHISQ (double df)
1830 return gsl_ran_chisq (get_rng (), df);
1834 matrix_eval_SIG_CHISQ (double x, double df)
1836 return gsl_cdf_chisq_Q (x, df);
1840 matrix_eval_CDF_EXP (double x, double a)
1842 return gsl_cdf_exponential_P (x, 1. / a);
1846 matrix_eval_IDF_EXP (double P, double a)
1848 return gsl_cdf_exponential_Pinv (P, 1. / a);
1852 matrix_eval_PDF_EXP (double x, double a)
1854 return gsl_ran_exponential_pdf (x, 1. / a);
1858 matrix_eval_RV_EXP (double a)
1860 return gsl_ran_exponential (get_rng (), 1. / a);
1864 matrix_eval_PDF_XPOWER (double x, double a, double b)
1866 return gsl_ran_exppow_pdf (x, a, b);
1870 matrix_eval_RV_XPOWER (double a, double b)
1872 return gsl_ran_exppow (get_rng (), a, b);
1875 struct matrix_function
1879 size_t min_args, max_args;
1882 static struct matrix_expr *matrix_parse_expr (struct matrix_state *);
1885 word_matches (const char **test, const char **name)
1887 size_t test_len = strcspn (*test, ".");
1888 size_t name_len = strcspn (*name, ".");
1889 if (test_len == name_len)
1891 if (buf_compare_case (*test, *name, test_len))
1894 else if (test_len < 3 || test_len > name_len)
1898 if (buf_compare_case (*test, *name, test_len))
1904 if (**test != **name)
1915 /* Returns 0 if TOKEN and FUNC do not match,
1916 1 if TOKEN is an acceptable abbreviation for FUNC,
1917 2 if TOKEN equals FUNC. */
1919 compare_function_names (const char *token_, const char *func_)
1921 const char *token = token_;
1922 const char *func = func_;
1923 while (*token || *func)
1924 if (!word_matches (&token, &func))
1926 return !c_strcasecmp (token_, func_) ? 2 : 1;
1929 static const struct matrix_function *
1930 matrix_parse_function_name (const char *token)
1932 static const struct matrix_function functions[] =
1934 #define F(ENUM, STRING, PROTO, CONSTRAINTS) \
1935 { STRING, MOP_F_##ENUM, PROTO##_MIN_ARGS, PROTO##_MAX_ARGS },
1939 enum { N_FUNCTIONS = sizeof functions / sizeof *functions };
1941 for (size_t i = 0; i < N_FUNCTIONS; i++)
1943 if (compare_function_names (token, functions[i].name) > 0)
1944 return &functions[i];
1949 static struct read_file *
1950 read_file_create (struct matrix_state *s, struct file_handle *fh)
1952 for (size_t i = 0; i < s->n_read_files; i++)
1954 struct read_file *rf = s->read_files[i];
1962 struct read_file *rf = xmalloc (sizeof *rf);
1963 *rf = (struct read_file) { .file = fh };
1965 s->read_files = xrealloc (s->read_files,
1966 (s->n_read_files + 1) * sizeof *s->read_files);
1967 s->read_files[s->n_read_files++] = rf;
1971 static struct dfm_reader *
1972 read_file_open (struct read_file *rf)
1975 rf->reader = dfm_open_reader (rf->file, NULL, rf->encoding);
1980 read_file_destroy (struct read_file *rf)
1984 fh_unref (rf->file);
1985 dfm_close_reader (rf->reader);
1986 free (rf->encoding);
1991 static struct write_file *
1992 write_file_create (struct matrix_state *s, struct file_handle *fh)
1994 for (size_t i = 0; i < s->n_write_files; i++)
1996 struct write_file *wf = s->write_files[i];
2004 struct write_file *wf = xmalloc (sizeof *wf);
2005 *wf = (struct write_file) { .file = fh };
2007 s->write_files = xrealloc (s->write_files,
2008 (s->n_write_files + 1) * sizeof *s->write_files);
2009 s->write_files[s->n_write_files++] = wf;
2013 static struct dfm_writer *
2014 write_file_open (struct write_file *wf)
2017 wf->writer = dfm_open_writer (wf->file, wf->encoding);
2022 write_file_destroy (struct write_file *wf)
2028 dfm_put_record_utf8 (wf->writer, wf->held->s.ss.string,
2029 wf->held->s.ss.length);
2030 u8_line_destroy (wf->held);
2034 fh_unref (wf->file);
2035 dfm_close_writer (wf->writer);
2036 free (wf->encoding);
2042 matrix_parse_function (struct matrix_state *s, const char *token,
2043 struct matrix_expr **exprp)
2046 if (lex_next_token (s->lexer, 1) != T_LPAREN)
2049 if (lex_match_id (s->lexer, "EOF"))
2052 struct file_handle *fh = fh_parse (s->lexer, FH_REF_FILE, s->session);
2056 if (!lex_force_match (s->lexer, T_RPAREN))
2062 struct read_file *rf = read_file_create (s, fh);
2064 struct matrix_expr *e = xmalloc (sizeof *e);
2065 *e = (struct matrix_expr) { .op = MOP_EOF, .eof = rf };
2070 const struct matrix_function *f = matrix_parse_function_name (token);
2074 lex_get_n (s->lexer, 2);
2076 struct matrix_expr *e = xmalloc (sizeof *e);
2077 *e = (struct matrix_expr) { .op = f->op, .subs = NULL };
2079 size_t allocated_subs = 0;
2082 struct matrix_expr *sub = matrix_parse_expr (s);
2086 if (e->n_subs >= allocated_subs)
2087 e->subs = x2nrealloc (e->subs, &allocated_subs, sizeof *e->subs);
2088 e->subs[e->n_subs++] = sub;
2090 while (lex_match (s->lexer, T_COMMA));
2091 if (!lex_force_match (s->lexer, T_RPAREN))
2098 matrix_expr_destroy (e);
2102 static struct matrix_expr *
2103 matrix_parse_primary (struct matrix_state *s)
2105 if (lex_is_number (s->lexer))
2107 double number = lex_number (s->lexer);
2109 return matrix_expr_create_number (number);
2111 else if (lex_is_string (s->lexer))
2113 char string[sizeof (double)];
2114 buf_copy_str_rpad (string, sizeof string, lex_tokcstr (s->lexer), ' ');
2118 memcpy (&number, string, sizeof number);
2119 return matrix_expr_create_number (number);
2121 else if (lex_match (s->lexer, T_LPAREN))
2123 struct matrix_expr *e = matrix_parse_or_xor (s);
2124 if (!e || !lex_force_match (s->lexer, T_RPAREN))
2126 matrix_expr_destroy (e);
2131 else if (lex_match (s->lexer, T_LCURLY))
2133 struct matrix_expr *e = matrix_parse_curly_semi (s);
2134 if (!e || !lex_force_match (s->lexer, T_RCURLY))
2136 matrix_expr_destroy (e);
2141 else if (lex_token (s->lexer) == T_ID)
2143 struct matrix_expr *retval;
2144 if (matrix_parse_function (s, lex_tokcstr (s->lexer), &retval))
2147 struct matrix_var *var = matrix_var_lookup (s, lex_tokss (s->lexer));
2150 lex_error (s->lexer, _("Unknown variable %s."),
2151 lex_tokcstr (s->lexer));
2156 struct matrix_expr *e = xmalloc (sizeof *e);
2157 *e = (struct matrix_expr) { .op = MOP_VARIABLE, .variable = var };
2160 else if (lex_token (s->lexer) == T_ALL)
2162 struct matrix_expr *retval;
2163 if (matrix_parse_function (s, "ALL", &retval))
2167 lex_error (s->lexer, NULL);
2171 static struct matrix_expr *matrix_parse_postfix (struct matrix_state *);
2174 matrix_parse_index_expr (struct matrix_state *s, struct matrix_expr **indexp)
2176 if (lex_match (s->lexer, T_COLON))
2183 *indexp = matrix_parse_expr (s);
2184 return *indexp != NULL;
2188 static struct matrix_expr *
2189 matrix_parse_postfix (struct matrix_state *s)
2191 struct matrix_expr *lhs = matrix_parse_primary (s);
2192 if (!lhs || !lex_match (s->lexer, T_LPAREN))
2195 struct matrix_expr *i0;
2196 if (!matrix_parse_index_expr (s, &i0))
2198 matrix_expr_destroy (lhs);
2201 if (lex_match (s->lexer, T_RPAREN))
2203 ? matrix_expr_create_2 (MOP_VEC_INDEX, lhs, i0)
2204 : matrix_expr_create_1 (MOP_VEC_ALL, lhs));
2205 else if (lex_match (s->lexer, T_COMMA))
2207 struct matrix_expr *i1;
2208 if (!matrix_parse_index_expr (s, &i1)
2209 || !lex_force_match (s->lexer, T_RPAREN))
2211 matrix_expr_destroy (lhs);
2212 matrix_expr_destroy (i0);
2213 matrix_expr_destroy (i1);
2216 return (i0 && i1 ? matrix_expr_create_3 (MOP_MAT_INDEX, lhs, i0, i1)
2217 : i0 ? matrix_expr_create_2 (MOP_ROW_INDEX, lhs, i0)
2218 : i1 ? matrix_expr_create_2 (MOP_COL_INDEX, lhs, i1)
2223 lex_error_expecting (s->lexer, "`)'", "`,'");
2228 static struct matrix_expr *
2229 matrix_parse_unary (struct matrix_state *s)
2231 if (lex_match (s->lexer, T_DASH))
2233 struct matrix_expr *lhs = matrix_parse_unary (s);
2234 return lhs ? matrix_expr_create_1 (MOP_NEGATE, lhs) : NULL;
2236 else if (lex_match (s->lexer, T_PLUS))
2237 return matrix_parse_unary (s);
2239 return matrix_parse_postfix (s);
2242 static struct matrix_expr *
2243 matrix_parse_seq (struct matrix_state *s)
2245 struct matrix_expr *start = matrix_parse_unary (s);
2246 if (!start || !lex_match (s->lexer, T_COLON))
2249 struct matrix_expr *end = matrix_parse_unary (s);
2252 matrix_expr_destroy (start);
2256 if (lex_match (s->lexer, T_COLON))
2258 struct matrix_expr *increment = matrix_parse_unary (s);
2261 matrix_expr_destroy (start);
2262 matrix_expr_destroy (end);
2265 return matrix_expr_create_3 (MOP_SEQ_BY, start, end, increment);
2268 return matrix_expr_create_2 (MOP_SEQ, start, end);
2271 static struct matrix_expr *
2272 matrix_parse_exp (struct matrix_state *s)
2274 struct matrix_expr *lhs = matrix_parse_seq (s);
2281 if (lex_match (s->lexer, T_EXP))
2283 else if (lex_match_phrase (s->lexer, "&**"))
2288 struct matrix_expr *rhs = matrix_parse_seq (s);
2291 matrix_expr_destroy (lhs);
2294 lhs = matrix_expr_create_2 (op, lhs, rhs);
2298 static struct matrix_expr *
2299 matrix_parse_mul_div (struct matrix_state *s)
2301 struct matrix_expr *lhs = matrix_parse_exp (s);
2308 if (lex_match (s->lexer, T_ASTERISK))
2310 else if (lex_match (s->lexer, T_SLASH))
2312 else if (lex_match_phrase (s->lexer, "&*"))
2314 else if (lex_match_phrase (s->lexer, "&/"))
2319 struct matrix_expr *rhs = matrix_parse_exp (s);
2322 matrix_expr_destroy (lhs);
2325 lhs = matrix_expr_create_2 (op, lhs, rhs);
2329 static struct matrix_expr *
2330 matrix_parse_add_sub (struct matrix_state *s)
2332 struct matrix_expr *lhs = matrix_parse_mul_div (s);
2339 if (lex_match (s->lexer, T_PLUS))
2341 else if (lex_match (s->lexer, T_DASH))
2343 else if (lex_token (s->lexer) == T_NEG_NUM)
2348 struct matrix_expr *rhs = matrix_parse_mul_div (s);
2351 matrix_expr_destroy (lhs);
2354 lhs = matrix_expr_create_2 (op, lhs, rhs);
2358 static struct matrix_expr *
2359 matrix_parse_relational (struct matrix_state *s)
2361 struct matrix_expr *lhs = matrix_parse_add_sub (s);
2368 if (lex_match (s->lexer, T_GT))
2370 else if (lex_match (s->lexer, T_GE))
2372 else if (lex_match (s->lexer, T_LT))
2374 else if (lex_match (s->lexer, T_LE))
2376 else if (lex_match (s->lexer, T_EQUALS) || lex_match (s->lexer, T_EQ))
2378 else if (lex_match (s->lexer, T_NE))
2383 struct matrix_expr *rhs = matrix_parse_add_sub (s);
2386 matrix_expr_destroy (lhs);
2389 lhs = matrix_expr_create_2 (op, lhs, rhs);
2393 static struct matrix_expr *
2394 matrix_parse_not (struct matrix_state *s)
2396 if (lex_match (s->lexer, T_NOT))
2398 struct matrix_expr *lhs = matrix_parse_not (s);
2399 return lhs ? matrix_expr_create_1 (MOP_NOT, lhs) : NULL;
2402 return matrix_parse_relational (s);
2405 static struct matrix_expr *
2406 matrix_parse_and (struct matrix_state *s)
2408 struct matrix_expr *lhs = matrix_parse_not (s);
2412 while (lex_match (s->lexer, T_AND))
2414 struct matrix_expr *rhs = matrix_parse_not (s);
2417 matrix_expr_destroy (lhs);
2420 lhs = matrix_expr_create_2 (MOP_AND, lhs, rhs);
2425 static struct matrix_expr *
2426 matrix_parse_or_xor (struct matrix_state *s)
2428 struct matrix_expr *lhs = matrix_parse_and (s);
2435 if (lex_match (s->lexer, T_OR))
2437 else if (lex_match_id (s->lexer, "XOR"))
2442 struct matrix_expr *rhs = matrix_parse_and (s);
2445 matrix_expr_destroy (lhs);
2448 lhs = matrix_expr_create_2 (op, lhs, rhs);
2452 static struct matrix_expr *
2453 matrix_parse_expr (struct matrix_state *s)
2455 return matrix_parse_or_xor (s);
2458 /* Expression evaluation. */
2461 matrix_op_eval (enum matrix_op op, double a, double b)
2465 case MOP_ADD_ELEMS: return a + b;
2466 case MOP_SUB_ELEMS: return a - b;
2467 case MOP_MUL_ELEMS: return a * b;
2468 case MOP_DIV_ELEMS: return a / b;
2469 case MOP_EXP_ELEMS: return pow (a, b);
2470 case MOP_GT: return a > b;
2471 case MOP_GE: return a >= b;
2472 case MOP_LT: return a < b;
2473 case MOP_LE: return a <= b;
2474 case MOP_EQ: return a == b;
2475 case MOP_NE: return a != b;
2476 case MOP_AND: return (a > 0) && (b > 0);
2477 case MOP_OR: return (a > 0) || (b > 0);
2478 case MOP_XOR: return (a > 0) != (b > 0);
2480 #define F(ENUM, STRING, PROTO, CONSTRAINTS) case MOP_F_##ENUM:
2489 case MOP_PASTE_HORZ:
2490 case MOP_PASTE_VERT:
2506 matrix_op_name (enum matrix_op op)
2510 case MOP_ADD_ELEMS: return "+";
2511 case MOP_SUB_ELEMS: return "-";
2512 case MOP_MUL_ELEMS: return "&*";
2513 case MOP_DIV_ELEMS: return "&/";
2514 case MOP_EXP_ELEMS: return "&**";
2515 case MOP_GT: return ">";
2516 case MOP_GE: return ">=";
2517 case MOP_LT: return "<";
2518 case MOP_LE: return "<=";
2519 case MOP_EQ: return "=";
2520 case MOP_NE: return "<>";
2521 case MOP_AND: return "AND";
2522 case MOP_OR: return "OR";
2523 case MOP_XOR: return "XOR";
2525 #define F(ENUM, STRING, PROTO, CONSTRAINTS) case MOP_F_##ENUM:
2534 case MOP_PASTE_HORZ:
2535 case MOP_PASTE_VERT:
2551 is_scalar (const gsl_matrix *m)
2553 return m->size1 == 1 && m->size2 == 1;
2557 to_scalar (const gsl_matrix *m)
2559 assert (is_scalar (m));
2560 return gsl_matrix_get (m, 0, 0);
2564 matrix_expr_evaluate_elementwise (enum matrix_op op,
2565 gsl_matrix *a, gsl_matrix *b)
2569 double be = to_scalar (b);
2570 for (size_t r = 0; r < a->size1; r++)
2571 for (size_t c = 0; c < a->size2; c++)
2573 double *ae = gsl_matrix_ptr (a, r, c);
2574 *ae = matrix_op_eval (op, *ae, be);
2578 else if (is_scalar (a))
2580 double ae = to_scalar (a);
2581 for (size_t r = 0; r < b->size1; r++)
2582 for (size_t c = 0; c < b->size2; c++)
2584 double *be = gsl_matrix_ptr (b, r, c);
2585 *be = matrix_op_eval (op, ae, *be);
2589 else if (a->size1 == b->size1 && a->size2 == b->size2)
2591 for (size_t r = 0; r < a->size1; r++)
2592 for (size_t c = 0; c < a->size2; c++)
2594 double *ae = gsl_matrix_ptr (a, r, c);
2595 double be = gsl_matrix_get (b, r, c);
2596 *ae = matrix_op_eval (op, *ae, be);
2602 msg (SE, _("Operands to %s must have the same dimensions or one "
2603 "must be a scalar, not %zu×%zu and %zu×%zu matrices."),
2604 matrix_op_name (op), a->size1, a->size2, b->size1, b->size2);
2610 matrix_expr_evaluate_mul_mat (gsl_matrix *a, gsl_matrix *b)
2612 if (is_scalar (a) || is_scalar (b))
2613 return matrix_expr_evaluate_elementwise (MOP_MUL_ELEMS, a, b);
2615 if (a->size2 != b->size1)
2617 msg (SE, _("Matrices with dimensions %zu×%zu and %zu×%zu are "
2618 "not conformable for multiplication."),
2619 a->size1, a->size2, b->size1, b->size2);
2623 gsl_matrix *c = gsl_matrix_alloc (a->size1, b->size2);
2624 gsl_blas_dgemm (CblasNoTrans, CblasNoTrans, 1.0, a, b, 0.0, c);
2629 swap_matrix (gsl_matrix **a, gsl_matrix **b)
2631 gsl_matrix *tmp = *a;
2637 mul_matrix (gsl_matrix **z, const gsl_matrix *x, const gsl_matrix *y,
2640 gsl_blas_dgemm (CblasNoTrans, CblasNoTrans, 1.0, x, y, 0.0, *tmp);
2641 swap_matrix (z, tmp);
2645 square_matrix (gsl_matrix **x, gsl_matrix **tmp)
2647 mul_matrix (x, *x, *x, tmp);
2651 matrix_expr_evaluate_exp_mat (gsl_matrix *x_, gsl_matrix *b)
2654 if (x->size1 != x->size2)
2656 msg (SE, _("Matrix exponentation with ** requires a square matrix on "
2657 "the left-hand size, not one with dimensions %zu×%zu."),
2658 x->size1, x->size2);
2663 msg (SE, _("Matrix exponentiation with ** requires a scalar on the "
2664 "right-hand side, not a matrix with dimensions %zu×%zu."),
2665 b->size1, b->size2);
2668 double bf = to_scalar (b);
2669 if (bf != floor (bf) || bf <= LONG_MIN || bf > LONG_MAX)
2671 msg (SE, _("Exponent %.1f in matrix multiplication is non-integer "
2672 "or outside the valid range."), bf);
2677 gsl_matrix *y_ = gsl_matrix_alloc (x->size1, x->size2);
2679 gsl_matrix_set_identity (y);
2683 gsl_matrix *t_ = gsl_matrix_alloc (x->size1, x->size2);
2685 for (unsigned long int n = labs (bl); n > 1; n /= 2)
2688 mul_matrix (&y, x, y, &t);
2689 square_matrix (&x, &t);
2692 square_matrix (&x, &t);
2694 mul_matrix (&y, x, y, &t);
2698 /* Garbage collection.
2700 There are three matrices: 'x_', 'y_', and 't_', and 'x', 'y', and 't' are
2701 a permutation of them. We are returning one of them; that one must not be
2702 destroyed. We must not destroy 'x_' because the caller owns it. */
2704 gsl_matrix_free (y_);
2706 gsl_matrix_free (t_);
2712 matrix_expr_evaluate_seq (gsl_matrix *start_, gsl_matrix *end_,
2715 if (!is_scalar (start_) || !is_scalar (end_) || (by_ && !is_scalar (by_)))
2717 msg (SE, _("All operands of : operator must be scalars."));
2721 long int start = to_scalar (start_);
2722 long int end = to_scalar (end_);
2723 long int by = by_ ? to_scalar (by_) : 1;
2727 msg (SE, _("The increment operand to : must be nonzero."));
2731 long int n = (end >= start && by > 0 ? (end - start + by) / by
2732 : end <= start && by < 0 ? (start - end - by) / -by
2734 gsl_matrix *m = gsl_matrix_alloc (1, n);
2735 for (long int i = 0; i < n; i++)
2736 gsl_matrix_set (m, 0, i, start + i * by);
2741 matrix_expr_evaluate_not (gsl_matrix *a)
2743 for (size_t r = 0; r < a->size1; r++)
2744 for (size_t c = 0; c < a->size2; c++)
2746 double *ae = gsl_matrix_ptr (a, r, c);
2753 matrix_expr_evaluate_paste_horz (gsl_matrix *a, gsl_matrix *b)
2755 if (a->size1 != b->size1)
2757 if (!a->size1 || !a->size2)
2759 else if (!b->size1 || !b->size2)
2762 msg (SE, _("All columns in a matrix must have the same number of rows, "
2763 "but this tries to paste matrices with %zu and %zu rows."),
2764 a->size1, b->size1);
2768 gsl_matrix *c = gsl_matrix_alloc (a->size1, a->size2 + b->size2);
2769 for (size_t y = 0; y < a->size1; y++)
2771 for (size_t x = 0; x < a->size2; x++)
2772 gsl_matrix_set (c, y, x, gsl_matrix_get (a, y, x));
2773 for (size_t x = 0; x < b->size2; x++)
2774 gsl_matrix_set (c, y, x + a->size2, gsl_matrix_get (b, y, x));
2780 matrix_expr_evaluate_paste_vert (gsl_matrix *a, gsl_matrix *b)
2782 if (a->size2 != b->size2)
2784 if (!a->size1 || !a->size2)
2786 else if (!b->size1 || !b->size2)
2789 msg (SE, _("All rows in a matrix must have the same number of columns, "
2790 "but this tries to stack matrices with %zu and %zu columns."),
2791 a->size2, b->size2);
2795 gsl_matrix *c = gsl_matrix_alloc (a->size1 + b->size1, a->size2);
2796 for (size_t x = 0; x < a->size2; x++)
2798 for (size_t y = 0; y < a->size1; y++)
2799 gsl_matrix_set (c, y, x, gsl_matrix_get (a, y, x));
2800 for (size_t y = 0; y < b->size1; y++)
2801 gsl_matrix_set (c, y + a->size1, x, gsl_matrix_get (b, y, x));
2807 matrix_to_vector (gsl_matrix *m)
2810 gsl_vector v = to_vector (m);
2811 assert (v.block == m->block || !v.block);
2815 gsl_matrix_free (m);
2816 return xmemdup (&v, sizeof v);
2830 #define INDEX_VECTOR_INIT (struct index_vector) { .n = 0 }
2833 matrix_normalize_index_vector (const gsl_matrix *m, size_t size,
2834 enum index_type index_type, size_t other_size,
2835 struct index_vector *iv)
2844 msg (SE, _("Vector index must be scalar or vector, not a "
2846 m->size1, m->size2);
2850 msg (SE, _("Matrix row index must be scalar or vector, not a "
2852 m->size1, m->size2);
2856 msg (SE, _("Matrix column index must be scalar or vector, not a "
2858 m->size1, m->size2);
2864 gsl_vector v = to_vector (CONST_CAST (gsl_matrix *, m));
2865 *iv = (struct index_vector) {
2866 .indexes = xnmalloc (v.size, sizeof *iv->indexes),
2869 for (size_t i = 0; i < v.size; i++)
2871 double index = gsl_vector_get (&v, i);
2872 if (index < 1 || index >= size + 1)
2877 msg (SE, _("Index %g is out of range for vector "
2878 "with %zu elements."), index, size);
2882 msg (SE, _("%g is not a valid row index for "
2883 "a %zu×%zu matrix."),
2884 index, size, other_size);
2888 msg (SE, _("%g is not a valid column index for "
2889 "a %zu×%zu matrix."),
2890 index, other_size, size);
2897 iv->indexes[i] = index - 1;
2903 *iv = (struct index_vector) {
2904 .indexes = xnmalloc (size, sizeof *iv->indexes),
2907 for (size_t i = 0; i < size; i++)
2914 matrix_expr_evaluate_vec_all (gsl_matrix *sm)
2916 if (!is_vector (sm))
2918 msg (SE, _("Vector index operator may not be applied to "
2919 "a %zu×%zu matrix."),
2920 sm->size1, sm->size2);
2928 matrix_expr_evaluate_vec_index (gsl_matrix *sm, gsl_matrix *im)
2930 if (!matrix_expr_evaluate_vec_all (sm))
2933 gsl_vector sv = to_vector (sm);
2934 struct index_vector iv;
2935 if (!matrix_normalize_index_vector (im, sv.size, IV_VECTOR, 0, &iv))
2938 gsl_matrix *dm = gsl_matrix_alloc (sm->size1 == 1 ? 1 : iv.n,
2939 sm->size1 == 1 ? iv.n : 1);
2940 gsl_vector dv = to_vector (dm);
2941 for (size_t dx = 0; dx < iv.n; dx++)
2943 size_t sx = iv.indexes[dx];
2944 gsl_vector_set (&dv, dx, gsl_vector_get (&sv, sx));
2952 matrix_expr_evaluate_mat_index (gsl_matrix *sm, gsl_matrix *im0,
2955 struct index_vector iv0;
2956 if (!matrix_normalize_index_vector (im0, sm->size1, IV_ROW, sm->size2, &iv0))
2959 struct index_vector iv1;
2960 if (!matrix_normalize_index_vector (im1, sm->size2, IV_COLUMN, sm->size1,
2967 gsl_matrix *dm = gsl_matrix_alloc (iv0.n, iv1.n);
2968 for (size_t dy = 0; dy < iv0.n; dy++)
2970 size_t sy = iv0.indexes[dy];
2972 for (size_t dx = 0; dx < iv1.n; dx++)
2974 size_t sx = iv1.indexes[dx];
2975 gsl_matrix_set (dm, dy, dx, gsl_matrix_get (sm, sy, sx));
2983 #define F(ENUM, STRING, PROTO, CONSTRAINTS) \
2984 static gsl_matrix *matrix_expr_evaluate_##PROTO ( \
2985 const struct matrix_function_properties *, gsl_matrix *[], size_t, \
2986 matrix_proto_##PROTO *);
2991 check_scalar_arg (const char *name, gsl_matrix *subs[], size_t index)
2993 if (!is_scalar (subs[index]))
2995 msg (SE, _("Function %s argument %zu must be a scalar, "
2996 "not a %zu×%zu matrix."),
2997 name, index + 1, subs[index]->size1, subs[index]->size2);
3004 check_vector_arg (const char *name, gsl_matrix *subs[], size_t index)
3006 if (!is_vector (subs[index]))
3008 msg (SE, _("Function %s argument %zu must be a vector, "
3009 "not a %zu×%zu matrix."),
3010 name, index + 1, subs[index]->size1, subs[index]->size2);
3017 to_scalar_args (const char *name, gsl_matrix *subs[], size_t n_subs, double d[])
3019 for (size_t i = 0; i < n_subs; i++)
3021 if (!check_scalar_arg (name, subs, i))
3023 d[i] = to_scalar (subs[i]);
3029 parse_constraint_value (const char **constraintsp)
3032 long retval = strtol (*constraintsp, &tail, 10);
3033 *constraintsp = tail;
3038 check_constraints (const struct matrix_function_properties *props,
3039 gsl_matrix *args[], size_t n_args)
3041 const char *constraints = props->constraints;
3045 size_t arg_index = SIZE_MAX;
3046 while (*constraints)
3048 if (*constraints >= 'a' && *constraints <= 'd')
3050 arg_index = *constraints++ - 'a';
3051 assert (arg_index < n_args);
3053 else if (*constraints == '[' || *constraints == '(')
3055 assert (arg_index < n_args);
3056 bool open_lower = *constraints++ == '(';
3057 int minimum = parse_constraint_value (&constraints);
3058 assert (*constraints == ',');
3060 int maximum = parse_constraint_value (&constraints);
3061 assert (*constraints == ']' || *constraints == ')');
3062 bool open_upper = *constraints++ == ')';
3064 MATRIX_FOR_ALL_ELEMENTS (d, y, x, args[arg_index])
3065 if ((open_lower ? *d <= minimum : *d < minimum)
3066 || (open_upper ? *d >= maximum : *d > maximum))
3068 if (!is_scalar (args[arg_index]))
3069 msg (ME, _("Row %zu, column %zu of argument %zu to matrix "
3070 "function %s has value %g, which is outside "
3071 "the valid range %c%d,%d%c."),
3072 y + 1, x + 1, arg_index + 1, props->name, *d,
3073 open_lower ? '(' : '[',
3075 open_upper ? ')' : ']');
3077 msg (ME, _("Argument %zu to matrix function %s has value %g, "
3078 "which is outside the valid range %c%d,%d%c."),
3079 arg_index + 1, props->name, *d,
3080 open_lower ? '(' : '[',
3082 open_upper ? ')' : ']');
3086 else if (*constraints == '>' || *constraints == '<')
3088 bool greater = *constraints++ == '>';
3090 if (*constraints == '=')
3097 int comparand = parse_constraint_value (&constraints);
3099 assert (arg_index < n_args);
3100 MATRIX_FOR_ALL_ELEMENTS (d, y, x, args[arg_index])
3102 ? (equal ? !(*d >= comparand) : !(*d > comparand))
3103 : (equal ? !(*d <= comparand) : !(*d < comparand)))
3105 struct string s = DS_EMPTY_INITIALIZER;
3106 if (!is_scalar (args[arg_index]))
3107 ds_put_format (&s, _("Row %zu, column %zu of argument %zu "
3108 "to matrix function %s has "
3109 "invalid value %g."),
3110 y + 1, x + 1, arg_index + 1, props->name, *d);
3112 ds_put_format (&s, _("Argument %zu to matrix function %s "
3113 "has invalid value %g."),
3114 arg_index + 1, props->name, *d);
3116 ds_put_cstr (&s, " ");
3117 if (greater && equal)
3118 ds_put_format (&s, _("This argument must be greater than or "
3119 "equal to %d."), comparand);
3120 else if (greater && !equal)
3121 ds_put_format (&s, _("This argument must be greater than %d."),
3124 ds_put_format (&s, _("This argument must be less than or "
3125 "equal to %d."), comparand);
3127 ds_put_format (&s, _("This argument must be less than %d."),
3129 msg (ME, ds_cstr (&s));
3136 assert (*constraints == ' ');
3144 matrix_expr_evaluate_d_d (const struct matrix_function_properties *props,
3145 gsl_matrix *subs[], size_t n_subs,
3146 matrix_proto_d_d *f)
3148 assert (n_subs == 1);
3151 if (!to_scalar_args (props->name, subs, n_subs, &d))
3154 if (!check_constraints (props, subs, n_subs))
3157 gsl_matrix *m = gsl_matrix_alloc (1, 1);
3158 gsl_matrix_set (m, 0, 0, f (d));
3163 matrix_expr_evaluate_d_dd (const struct matrix_function_properties *props,
3164 gsl_matrix *subs[], size_t n_subs,
3165 matrix_proto_d_dd *f)
3167 assert (n_subs == 2);
3170 if (!to_scalar_args (props->name, subs, n_subs, d))
3173 if (!check_constraints (props, subs, n_subs))
3176 gsl_matrix *m = gsl_matrix_alloc (1, 1);
3177 gsl_matrix_set (m, 0, 0, f (d[0], d[1]));
3182 matrix_expr_evaluate_m_d (const struct matrix_function_properties *props,
3183 gsl_matrix *subs[], size_t n_subs,
3184 matrix_proto_m_d *f)
3186 assert (n_subs == 1);
3189 return to_scalar_args (props->name, subs, n_subs, &d) ? f (d) : NULL;
3193 matrix_expr_evaluate_m_dd (const struct matrix_function_properties *props,
3194 gsl_matrix *subs[], size_t n_subs,
3195 matrix_proto_m_dd *f)
3197 assert (n_subs == 2);
3200 return to_scalar_args (props->name, subs, n_subs, d) ? f(d[0], d[1]) : NULL;
3204 matrix_expr_evaluate_m_ddd (const struct matrix_function_properties *props,
3205 gsl_matrix *subs[], size_t n_subs,
3206 matrix_proto_m_ddd *f)
3208 assert (n_subs == 3);
3211 return to_scalar_args (props->name, subs, n_subs, d) ? f(d[0], d[1], d[2]) : NULL;
3215 matrix_expr_evaluate_m_m (const struct matrix_function_properties *props UNUSED,
3216 gsl_matrix *subs[], size_t n_subs,
3217 matrix_proto_m_m *f)
3219 assert (n_subs == 1);
3224 matrix_expr_evaluate_m_m_e (const struct matrix_function_properties *props,
3225 gsl_matrix *subs[], size_t n_subs,
3226 matrix_proto_m_m_e *f)
3228 assert (n_subs == 1);
3230 if (!check_constraints (props, subs, n_subs))
3233 MATRIX_FOR_ALL_ELEMENTS (a, y, x, subs[0])
3239 matrix_expr_evaluate_m_md (const struct matrix_function_properties *props UNUSED,
3240 gsl_matrix *subs[], size_t n_subs,
3241 matrix_proto_m_md *f)
3243 assert (n_subs == 2);
3244 if (!check_scalar_arg (props->name, subs, 1))
3246 return f (subs[0], to_scalar (subs[1]));
3250 matrix_expr_evaluate_m_md_e (const struct matrix_function_properties *props,
3251 gsl_matrix *subs[], size_t n_subs,
3252 matrix_proto_m_md_e *f)
3254 assert (n_subs == 2);
3255 if (!check_scalar_arg (props->name, subs, 1))
3258 if (!check_constraints (props, subs, n_subs))
3261 double b = to_scalar (subs[1]);
3262 MATRIX_FOR_ALL_ELEMENTS (a, y, x, subs[0])
3268 matrix_expr_evaluate_m_mdd (const struct matrix_function_properties *props UNUSED,
3269 gsl_matrix *subs[], size_t n_subs,
3270 matrix_proto_m_mdd *f)
3272 assert (n_subs == 3);
3273 if (!check_scalar_arg (props->name, subs, 1) || !check_scalar_arg (props->name, subs, 2))
3275 return f (subs[0], to_scalar (subs[1]), to_scalar (subs[2]));
3279 matrix_expr_evaluate_m_mdd_e (const struct matrix_function_properties *props,
3280 gsl_matrix *subs[], size_t n_subs,
3281 matrix_proto_m_mdd_e *f)
3283 assert (n_subs == 3);
3284 if (!check_scalar_arg (props->name, subs, 1) || !check_scalar_arg (props->name, subs, 2))
3287 if (!check_constraints (props, subs, n_subs))
3290 double b = to_scalar (subs[1]);
3291 double c = to_scalar (subs[2]);
3292 MATRIX_FOR_ALL_ELEMENTS (a, y, x, subs[0])
3298 matrix_expr_evaluate_m_mddd_e (const struct matrix_function_properties *props,
3299 gsl_matrix *subs[], size_t n_subs,
3300 matrix_proto_m_mddd_e *f)
3302 assert (n_subs == 4);
3303 for (size_t i = 1; i < 4; i++)
3304 if (!check_scalar_arg (props->name, subs, i))
3307 if (!check_constraints (props, subs, n_subs))
3310 double b = to_scalar (subs[1]);
3311 double c = to_scalar (subs[2]);
3312 double d = to_scalar (subs[3]);
3313 MATRIX_FOR_ALL_ELEMENTS (a, y, x, subs[0])
3314 *a = f (*a, b, c, d);
3319 matrix_expr_evaluate_m_mm (const struct matrix_function_properties *props UNUSED,
3320 gsl_matrix *subs[], size_t n_subs,
3321 matrix_proto_m_mm *f)
3323 assert (n_subs == 2);
3324 return f (subs[0], subs[1]);
3328 matrix_expr_evaluate_m_v (const struct matrix_function_properties *props,
3329 gsl_matrix *subs[], size_t n_subs,
3330 matrix_proto_m_v *f)
3332 assert (n_subs == 1);
3333 if (!check_vector_arg (props->name, subs, 0))
3335 gsl_vector v = to_vector (subs[0]);
3340 matrix_expr_evaluate_d_m (const struct matrix_function_properties *props UNUSED,
3341 gsl_matrix *subs[], size_t n_subs,
3342 matrix_proto_d_m *f)
3344 assert (n_subs == 1);
3346 gsl_matrix *m = gsl_matrix_alloc (1, 1);
3347 gsl_matrix_set (m, 0, 0, f (subs[0]));
3352 matrix_expr_evaluate_m_any (const struct matrix_function_properties *props UNUSED,
3353 gsl_matrix *subs[], size_t n_subs,
3354 matrix_proto_m_any *f)
3356 return f (subs, n_subs);
3360 matrix_expr_evaluate_IDENT (const struct matrix_function_properties *props,
3361 gsl_matrix *subs[], size_t n_subs,
3362 matrix_proto_IDENT *f)
3364 assert (n_subs <= 2);
3367 if (!to_scalar_args (props->name, subs, n_subs, d))
3370 return f (d[0], d[n_subs - 1]);
3374 matrix_expr_evaluate (const struct matrix_expr *e)
3376 if (e->op == MOP_NUMBER)
3378 gsl_matrix *m = gsl_matrix_alloc (1, 1);
3379 gsl_matrix_set (m, 0, 0, e->number);
3382 else if (e->op == MOP_VARIABLE)
3384 const gsl_matrix *src = e->variable->value;
3387 msg (SE, _("Uninitialized variable %s used in expression."),
3392 gsl_matrix *dst = gsl_matrix_alloc (src->size1, src->size2);
3393 gsl_matrix_memcpy (dst, src);
3396 else if (e->op == MOP_EOF)
3398 struct dfm_reader *reader = read_file_open (e->eof);
3399 gsl_matrix *m = gsl_matrix_alloc (1, 1);
3400 gsl_matrix_set (m, 0, 0, !reader || dfm_eof (reader));
3404 enum { N_LOCAL = 3 };
3405 gsl_matrix *local_subs[N_LOCAL];
3406 gsl_matrix **subs = (e->n_subs < N_LOCAL
3408 : xmalloc (e->n_subs * sizeof *subs));
3410 for (size_t i = 0; i < e->n_subs; i++)
3412 subs[i] = matrix_expr_evaluate (e->subs[i]);
3415 for (size_t j = 0; j < i; j++)
3416 gsl_matrix_free (subs[j]);
3417 if (subs != local_subs)
3423 gsl_matrix *result = NULL;
3426 #define F(ENUM, STRING, PROTO, CONSTRAINTS) \
3427 case MOP_F_##ENUM: \
3429 static const struct matrix_function_properties props = { \
3431 .constraints = CONSTRAINTS, \
3433 result = matrix_expr_evaluate_##PROTO (&props, subs, e->n_subs, \
3434 matrix_eval_##ENUM); \
3441 gsl_matrix_scale (subs[0], -1.0);
3459 result = matrix_expr_evaluate_elementwise (e->op, subs[0], subs[1]);
3463 result = matrix_expr_evaluate_not (subs[0]);
3467 result = matrix_expr_evaluate_seq (subs[0], subs[1], NULL);
3471 result = matrix_expr_evaluate_seq (subs[0], subs[1], subs[2]);
3475 result = matrix_expr_evaluate_mul_mat (subs[0], subs[1]);
3479 result = matrix_expr_evaluate_exp_mat (subs[0], subs[1]);
3482 case MOP_PASTE_HORZ:
3483 result = matrix_expr_evaluate_paste_horz (subs[0], subs[1]);
3486 case MOP_PASTE_VERT:
3487 result = matrix_expr_evaluate_paste_vert (subs[0], subs[1]);
3491 result = gsl_matrix_alloc (0, 0);
3495 result = matrix_expr_evaluate_vec_index (subs[0], subs[1]);
3499 result = matrix_expr_evaluate_vec_all (subs[0]);
3503 result = matrix_expr_evaluate_mat_index (subs[0], subs[1], subs[2]);
3507 result = matrix_expr_evaluate_mat_index (subs[0], subs[1], NULL);
3511 result = matrix_expr_evaluate_mat_index (subs[0], NULL, subs[1]);
3520 for (size_t i = 0; i < e->n_subs; i++)
3521 if (subs[i] != result)
3522 gsl_matrix_free (subs[i]);
3523 if (subs != local_subs)
3529 matrix_expr_evaluate_scalar (const struct matrix_expr *e, const char *context,
3532 gsl_matrix *m = matrix_expr_evaluate (e);
3538 msg (SE, _("Expression for %s must evaluate to scalar, "
3539 "not a %zu×%zu matrix."),
3540 context, m->size1, m->size2);
3541 gsl_matrix_free (m);
3546 gsl_matrix_free (m);
3551 matrix_expr_evaluate_integer (const struct matrix_expr *e, const char *context,
3555 if (!matrix_expr_evaluate_scalar (e, context, &d))
3559 if (d < LONG_MIN || d > LONG_MAX)
3561 msg (SE, _("Expression for %s is outside the integer range."), context);
3568 struct matrix_lvalue
3570 struct matrix_var *var;
3571 struct matrix_expr *indexes[2];
3576 matrix_lvalue_destroy (struct matrix_lvalue *lvalue)
3580 for (size_t i = 0; i < lvalue->n_indexes; i++)
3581 matrix_expr_destroy (lvalue->indexes[i]);
3586 static struct matrix_lvalue *
3587 matrix_lvalue_parse (struct matrix_state *s)
3589 struct matrix_lvalue *lvalue = xzalloc (sizeof *lvalue);
3590 if (!lex_force_id (s->lexer))
3592 lvalue->var = matrix_var_lookup (s, lex_tokss (s->lexer));
3593 if (lex_next_token (s->lexer, 1) == T_LPAREN)
3597 msg (SE, _("Undefined variable %s."), lex_tokcstr (s->lexer));
3602 lex_get_n (s->lexer, 2);
3604 if (!matrix_parse_index_expr (s, &lvalue->indexes[0]))
3606 lvalue->n_indexes++;
3608 if (lex_match (s->lexer, T_COMMA))
3610 if (!matrix_parse_index_expr (s, &lvalue->indexes[1]))
3612 lvalue->n_indexes++;
3614 if (!lex_force_match (s->lexer, T_RPAREN))
3620 lvalue->var = matrix_var_create (s, lex_tokss (s->lexer));
3626 matrix_lvalue_destroy (lvalue);
3631 matrix_lvalue_evaluate_vector (struct matrix_expr *e, size_t size,
3632 enum index_type index_type, size_t other_size,
3633 struct index_vector *iv)
3638 m = matrix_expr_evaluate (e);
3645 bool ok = matrix_normalize_index_vector (m, size, index_type,
3647 gsl_matrix_free (m);
3652 matrix_lvalue_assign_vector (struct matrix_lvalue *lvalue,
3653 struct index_vector *iv, gsl_matrix *sm)
3655 gsl_vector dv = to_vector (lvalue->var->value);
3657 /* Convert source matrix 'sm' to source vector 'sv'. */
3658 if (!is_vector (sm))
3660 msg (SE, _("Can't assign %zu×%zu matrix to subvector."),
3661 sm->size1, sm->size2);
3664 gsl_vector sv = to_vector (sm);
3665 if (iv->n != sv.size)
3667 msg (SE, _("Can't assign %zu-element vector "
3668 "to %zu-element subvector."), sv.size, iv->n);
3672 /* Assign elements. */
3673 for (size_t x = 0; x < iv->n; x++)
3674 gsl_vector_set (&dv, iv->indexes[x], gsl_vector_get (&sv, x));
3679 matrix_lvalue_assign_matrix (struct matrix_lvalue *lvalue,
3680 struct index_vector *iv0,
3681 struct index_vector *iv1, gsl_matrix *sm)
3683 gsl_matrix *dm = lvalue->var->value;
3685 /* Convert source matrix 'sm' to source vector 'sv'. */
3686 if (iv0->n != sm->size1)
3688 msg (SE, _("Row index vector for assignment to %s has %zu elements "
3689 "but source matrix has %zu rows."),
3690 lvalue->var->name, iv0->n, sm->size1);
3693 if (iv1->n != sm->size2)
3695 msg (SE, _("Column index vector for assignment to %s has %zu elements "
3696 "but source matrix has %zu columns."),
3697 lvalue->var->name, iv1->n, sm->size2);
3701 /* Assign elements. */
3702 for (size_t y = 0; y < iv0->n; y++)
3704 size_t f0 = iv0->indexes[y];
3705 for (size_t x = 0; x < iv1->n; x++)
3707 size_t f1 = iv1->indexes[x];
3708 gsl_matrix_set (dm, f0, f1, gsl_matrix_get (sm, y, x));
3714 /* Takes ownership of M. */
3716 matrix_lvalue_assign (struct matrix_lvalue *lvalue,
3717 struct index_vector *iv0, struct index_vector *iv1,
3720 if (!lvalue->n_indexes)
3722 gsl_matrix_free (lvalue->var->value);
3723 lvalue->var->value = sm;
3728 bool ok = (lvalue->n_indexes == 1
3729 ? matrix_lvalue_assign_vector (lvalue, iv0, sm)
3730 : matrix_lvalue_assign_matrix (lvalue, iv0, iv1, sm));
3731 free (iv0->indexes);
3732 free (iv1->indexes);
3733 gsl_matrix_free (sm);
3739 matrix_lvalue_evaluate (struct matrix_lvalue *lvalue,
3740 struct index_vector *iv0,
3741 struct index_vector *iv1)
3743 *iv0 = INDEX_VECTOR_INIT;
3744 *iv1 = INDEX_VECTOR_INIT;
3745 if (!lvalue->n_indexes)
3748 /* Validate destination matrix exists and has the right shape. */
3749 gsl_matrix *dm = lvalue->var->value;
3752 msg (SE, _("Undefined variable %s."), lvalue->var->name);
3755 else if (dm->size1 == 0 || dm->size2 == 0)
3757 msg (SE, _("Cannot index %zu×%zu matrix."),
3758 dm->size1, dm->size2);
3761 else if (lvalue->n_indexes == 1)
3763 if (!is_vector (dm))
3765 msg (SE, _("Can't use vector indexing on %zu×%zu matrix %s."),
3766 dm->size1, dm->size2, lvalue->var->name);
3769 return matrix_lvalue_evaluate_vector (lvalue->indexes[0],
3770 MAX (dm->size1, dm->size2),
3775 assert (lvalue->n_indexes == 2);
3776 if (!matrix_lvalue_evaluate_vector (lvalue->indexes[0], dm->size1,
3777 IV_ROW, dm->size2, iv0))
3780 if (!matrix_lvalue_evaluate_vector (lvalue->indexes[1], dm->size2,
3781 IV_COLUMN, dm->size1, iv1))
3783 free (iv0->indexes);
3790 /* Takes ownership of M. */
3792 matrix_lvalue_evaluate_and_assign (struct matrix_lvalue *lvalue, gsl_matrix *sm)
3794 struct index_vector iv0, iv1;
3795 if (!matrix_lvalue_evaluate (lvalue, &iv0, &iv1))
3797 gsl_matrix_free (sm);
3801 return matrix_lvalue_assign (lvalue, &iv0, &iv1, sm);
3805 /* Matrix command. */
3809 struct matrix_cmd **commands;
3813 static void matrix_cmds_uninit (struct matrix_cmds *);
3817 enum matrix_cmd_type
3840 struct compute_command
3842 struct matrix_lvalue *lvalue;
3843 struct matrix_expr *rvalue;
3847 struct print_command
3849 struct matrix_expr *expression;
3850 bool use_default_format;
3851 struct fmt_spec format;
3853 int space; /* -1 means NEWPAGE. */
3857 struct string_array literals; /* CLABELS/RLABELS. */
3858 struct matrix_expr *expr; /* CNAMES/RNAMES. */
3864 struct do_if_command
3868 struct matrix_expr *condition;
3869 struct matrix_cmds commands;
3879 struct matrix_var *var;
3880 struct matrix_expr *start;
3881 struct matrix_expr *end;
3882 struct matrix_expr *increment;
3884 /* Loop conditions. */
3885 struct matrix_expr *top_condition;
3886 struct matrix_expr *bottom_condition;
3889 struct matrix_cmds commands;
3893 struct display_command
3895 struct matrix_state *state;
3899 struct release_command
3901 struct matrix_var **vars;
3908 struct matrix_expr *expression;
3909 struct save_file *sf;
3915 struct read_file *rf;
3916 struct matrix_lvalue *dst;
3917 struct matrix_expr *size;
3919 enum fmt_type format;
3926 struct write_command
3928 struct write_file *wf;
3929 struct matrix_expr *expression;
3932 /* If this is nonnull, WRITE uses this format.
3934 If this is NULL, WRITE uses free-field format with as many
3935 digits of precision as needed. */
3936 struct fmt_spec *format;
3945 struct matrix_lvalue *dst;
3946 struct dataset *dataset;
3947 struct file_handle *file;
3949 struct var_syntax *vars;
3951 struct matrix_var *names;
3953 /* Treatment of missing values. */
3958 MGET_ERROR, /* Flag error on command. */
3959 MGET_ACCEPT, /* Accept without change, user-missing only. */
3960 MGET_OMIT, /* Drop this case. */
3961 MGET_RECODE /* Recode to 'substitute'. */
3964 double substitute; /* MGET_RECODE only. */
3970 struct msave_command
3972 struct msave_common *common;
3973 struct matrix_expr *expr;
3974 const char *rowtype;
3975 const struct matrix_expr *factors;
3976 const struct matrix_expr *splits;
3982 struct matrix_state *state;
3983 struct file_handle *file;
3985 struct stringi_set rowtypes;
3989 struct eigen_command
3991 struct matrix_expr *expr;
3992 struct matrix_var *evec;
3993 struct matrix_var *eval;
3997 struct setdiag_command
3999 struct matrix_var *dst;
4000 struct matrix_expr *expr;
4006 struct matrix_expr *expr;
4007 struct matrix_var *u;
4008 struct matrix_var *s;
4009 struct matrix_var *v;
4015 static struct matrix_cmd *matrix_parse_command (struct matrix_state *);
4016 static bool matrix_cmd_execute (struct matrix_cmd *);
4017 static void matrix_cmd_destroy (struct matrix_cmd *);
4020 static struct matrix_cmd *
4021 matrix_parse_compute (struct matrix_state *s)
4023 struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
4024 *cmd = (struct matrix_cmd) {
4025 .type = MCMD_COMPUTE,
4026 .compute = { .lvalue = NULL },
4029 struct compute_command *compute = &cmd->compute;
4030 compute->lvalue = matrix_lvalue_parse (s);
4031 if (!compute->lvalue)
4034 if (!lex_force_match (s->lexer, T_EQUALS))
4037 compute->rvalue = matrix_parse_expr (s);
4038 if (!compute->rvalue)
4044 matrix_cmd_destroy (cmd);
4049 matrix_cmd_execute_compute (struct compute_command *compute)
4051 gsl_matrix *value = matrix_expr_evaluate (compute->rvalue);
4055 matrix_lvalue_evaluate_and_assign (compute->lvalue, value);
4059 print_labels_destroy (struct print_labels *labels)
4063 string_array_destroy (&labels->literals);
4064 matrix_expr_destroy (labels->expr);
4070 parse_literal_print_labels (struct matrix_state *s,
4071 struct print_labels **labelsp)
4073 lex_match (s->lexer, T_EQUALS);
4074 print_labels_destroy (*labelsp);
4075 *labelsp = xzalloc (sizeof **labelsp);
4076 while (lex_token (s->lexer) != T_SLASH
4077 && lex_token (s->lexer) != T_ENDCMD
4078 && lex_token (s->lexer) != T_STOP)
4080 struct string label = DS_EMPTY_INITIALIZER;
4081 while (lex_token (s->lexer) != T_COMMA
4082 && lex_token (s->lexer) != T_SLASH
4083 && lex_token (s->lexer) != T_ENDCMD
4084 && lex_token (s->lexer) != T_STOP)
4086 if (!ds_is_empty (&label))
4087 ds_put_byte (&label, ' ');
4089 if (lex_token (s->lexer) == T_STRING)
4090 ds_put_cstr (&label, lex_tokcstr (s->lexer));
4093 char *rep = lex_next_representation (s->lexer, 0, 0);
4094 ds_put_cstr (&label, rep);
4099 string_array_append_nocopy (&(*labelsp)->literals,
4100 ds_steal_cstr (&label));
4102 if (!lex_match (s->lexer, T_COMMA))
4108 parse_expr_print_labels (struct matrix_state *s, struct print_labels **labelsp)
4110 lex_match (s->lexer, T_EQUALS);
4111 struct matrix_expr *e = matrix_parse_exp (s);
4115 print_labels_destroy (*labelsp);
4116 *labelsp = xzalloc (sizeof **labelsp);
4117 (*labelsp)->expr = e;
4121 static struct matrix_cmd *
4122 matrix_parse_print (struct matrix_state *s)
4124 struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
4125 *cmd = (struct matrix_cmd) {
4128 .use_default_format = true,
4132 if (lex_token (s->lexer) != T_SLASH && lex_token (s->lexer) != T_ENDCMD)
4135 for (size_t i = 0; ; i++)
4137 enum token_type t = lex_next_token (s->lexer, i);
4138 if (t == T_LPAREN || t == T_LBRACK || t == T_LCURLY)
4140 else if ((t == T_RPAREN || t == T_RBRACK || t == T_RCURLY) && depth)
4142 else if ((t == T_SLASH && !depth) || t == T_ENDCMD || t == T_STOP)
4145 cmd->print.title = lex_next_representation (s->lexer, 0, i - 1);
4150 cmd->print.expression = matrix_parse_exp (s);
4151 if (!cmd->print.expression)
4155 while (lex_match (s->lexer, T_SLASH))
4157 if (lex_match_id (s->lexer, "FORMAT"))
4159 lex_match (s->lexer, T_EQUALS);
4160 if (!parse_format_specifier (s->lexer, &cmd->print.format))
4162 cmd->print.use_default_format = false;
4164 else if (lex_match_id (s->lexer, "TITLE"))
4166 lex_match (s->lexer, T_EQUALS);
4167 if (!lex_force_string (s->lexer))
4169 free (cmd->print.title);
4170 cmd->print.title = ss_xstrdup (lex_tokss (s->lexer));
4173 else if (lex_match_id (s->lexer, "SPACE"))
4175 lex_match (s->lexer, T_EQUALS);
4176 if (lex_match_id (s->lexer, "NEWPAGE"))
4177 cmd->print.space = -1;
4178 else if (lex_force_int_range (s->lexer, "SPACE", 1, INT_MAX))
4180 cmd->print.space = lex_integer (s->lexer);
4186 else if (lex_match_id (s->lexer, "RLABELS"))
4187 parse_literal_print_labels (s, &cmd->print.rlabels);
4188 else if (lex_match_id (s->lexer, "CLABELS"))
4189 parse_literal_print_labels (s, &cmd->print.clabels);
4190 else if (lex_match_id (s->lexer, "RNAMES"))
4192 if (!parse_expr_print_labels (s, &cmd->print.rlabels))
4195 else if (lex_match_id (s->lexer, "CNAMES"))
4197 if (!parse_expr_print_labels (s, &cmd->print.clabels))
4202 lex_error_expecting (s->lexer, "FORMAT", "TITLE", "SPACE",
4203 "RLABELS", "CLABELS", "RNAMES", "CNAMES");
4211 matrix_cmd_destroy (cmd);
4216 matrix_is_integer (const gsl_matrix *m)
4218 for (size_t y = 0; y < m->size1; y++)
4219 for (size_t x = 0; x < m->size2; x++)
4221 double d = gsl_matrix_get (m, y, x);
4229 matrix_max_magnitude (const gsl_matrix *m)
4232 for (size_t y = 0; y < m->size1; y++)
4233 for (size_t x = 0; x < m->size2; x++)
4235 double d = fabs (gsl_matrix_get (m, y, x));
4243 format_fits (struct fmt_spec format, double x)
4245 char *s = data_out (&(union value) { .f = x }, NULL,
4246 &format, settings_get_fmt_settings ());
4247 bool fits = *s != '*' && !strchr (s, 'E');
4252 static struct fmt_spec
4253 default_format (const gsl_matrix *m, int *log_scale)
4257 double max = matrix_max_magnitude (m);
4259 if (matrix_is_integer (m))
4260 for (int w = 1; w <= 12; w++)
4262 struct fmt_spec format = { .type = FMT_F, .w = w };
4263 if (format_fits (format, -max))
4267 if (max >= 1e9 || max <= 1e-4)
4270 snprintf (s, sizeof s, "%.1e", max);
4272 const char *e = strchr (s, 'e');
4274 *log_scale = atoi (e + 1);
4277 return (struct fmt_spec) { .type = FMT_F, .w = 13, .d = 10 };
4281 trimmed_string (double d)
4283 struct substring s = ss_buffer ((char *) &d, sizeof d);
4284 ss_rtrim (&s, ss_cstr (" "));
4285 return ss_xstrdup (s);
4288 static struct string_array *
4289 print_labels_get (const struct print_labels *labels, size_t n,
4290 const char *prefix, bool truncate)
4295 struct string_array *out = xzalloc (sizeof *out);
4296 if (labels->literals.n)
4297 string_array_clone (out, &labels->literals);
4298 else if (labels->expr)
4300 gsl_matrix *m = matrix_expr_evaluate (labels->expr);
4301 if (m && is_vector (m))
4303 gsl_vector v = to_vector (m);
4304 for (size_t i = 0; i < v.size; i++)
4305 string_array_append_nocopy (out, trimmed_string (
4306 gsl_vector_get (&v, i)));
4308 gsl_matrix_free (m);
4314 string_array_append_nocopy (out, xasprintf ("%s%zu", prefix,
4317 string_array_append (out, "");
4320 string_array_delete (out, out->n - 1);
4323 for (size_t i = 0; i < out->n; i++)
4325 char *s = out->strings[i];
4326 s[strnlen (s, 8)] = '\0';
4333 matrix_cmd_print_space (int space)
4336 output_item_submit (page_break_item_create ());
4337 for (int i = 0; i < space; i++)
4338 output_log ("%s", "");
4342 matrix_cmd_print_text (const struct print_command *print, const gsl_matrix *m,
4343 struct fmt_spec format, int log_scale)
4345 matrix_cmd_print_space (print->space);
4347 output_log ("%s", print->title);
4349 output_log (" 10 ** %d X", log_scale);
4351 struct string_array *clabels = print_labels_get (print->clabels,
4352 m->size2, "col", true);
4353 if (clabels && format.w < 8)
4355 struct string_array *rlabels = print_labels_get (print->rlabels,
4356 m->size1, "row", true);
4360 struct string line = DS_EMPTY_INITIALIZER;
4362 ds_put_byte_multiple (&line, ' ', 8);
4363 for (size_t x = 0; x < m->size2; x++)
4364 ds_put_format (&line, " %*s", format.w, clabels->strings[x]);
4365 output_log_nocopy (ds_steal_cstr (&line));
4368 double scale = pow (10.0, log_scale);
4369 bool numeric = fmt_is_numeric (format.type);
4370 for (size_t y = 0; y < m->size1; y++)
4372 struct string line = DS_EMPTY_INITIALIZER;
4374 ds_put_format (&line, "%-8s", rlabels->strings[y]);
4376 for (size_t x = 0; x < m->size2; x++)
4378 double f = gsl_matrix_get (m, y, x);
4380 ? data_out (&(union value) { .f = f / scale}, NULL,
4381 &format, settings_get_fmt_settings ())
4382 : trimmed_string (f));
4383 ds_put_format (&line, " %s", s);
4386 output_log_nocopy (ds_steal_cstr (&line));
4389 string_array_destroy (rlabels);
4391 string_array_destroy (clabels);
4396 create_print_dimension (struct pivot_table *table, enum pivot_axis_type axis,
4397 const struct print_labels *print_labels, size_t n,
4398 const char *name, const char *prefix)
4400 struct string_array *labels = print_labels_get (print_labels, n, prefix,
4402 struct pivot_dimension *d = pivot_dimension_create (table, axis, name);
4403 for (size_t i = 0; i < n; i++)
4404 pivot_category_create_leaf (
4406 ? pivot_value_new_user_text (labels->strings[i], SIZE_MAX)
4407 : pivot_value_new_integer (i + 1)));
4409 d->hide_all_labels = true;
4410 string_array_destroy (labels);
4415 matrix_cmd_print_tables (const struct print_command *print, const gsl_matrix *m,
4416 struct fmt_spec format, int log_scale)
4418 struct pivot_table *table = pivot_table_create__ (
4419 pivot_value_new_user_text (print->title ? print->title : "", SIZE_MAX),
4422 create_print_dimension (table, PIVOT_AXIS_ROW, print->rlabels, m->size1,
4424 create_print_dimension (table, PIVOT_AXIS_COLUMN, print->clabels, m->size2,
4425 N_("Columns"), "col");
4427 struct pivot_footnote *footnote = NULL;
4430 char *s = xasprintf ("× 10**%d", log_scale);
4431 footnote = pivot_table_create_footnote (
4432 table, pivot_value_new_user_text_nocopy (s));
4435 double scale = pow (10.0, log_scale);
4436 bool numeric = fmt_is_numeric (format.type);
4437 for (size_t y = 0; y < m->size1; y++)
4438 for (size_t x = 0; x < m->size2; x++)
4440 double f = gsl_matrix_get (m, y, x);
4441 struct pivot_value *v;
4444 v = pivot_value_new_number (f / scale);
4445 v->numeric.format = format;
4448 v = pivot_value_new_user_text_nocopy (trimmed_string (f));
4450 pivot_value_add_footnote (v, footnote);
4451 pivot_table_put2 (table, y, x, v);
4454 pivot_table_submit (table);
4458 matrix_cmd_execute_print (const struct print_command *print)
4460 if (print->expression)
4462 gsl_matrix *m = matrix_expr_evaluate (print->expression);
4467 struct fmt_spec format = (print->use_default_format
4468 ? default_format (m, &log_scale)
4471 if (settings_get_mdisplay () == SETTINGS_MDISPLAY_TEXT)
4472 matrix_cmd_print_text (print, m, format, log_scale);
4474 matrix_cmd_print_tables (print, m, format, log_scale);
4476 gsl_matrix_free (m);
4480 matrix_cmd_print_space (print->space);
4482 output_log ("%s", print->title);
4489 matrix_parse_commands (struct matrix_state *s, struct matrix_cmds *c,
4490 const char *command_name,
4491 const char *stop1, const char *stop2)
4493 lex_end_of_command (s->lexer);
4494 lex_discard_rest_of_command (s->lexer);
4496 size_t allocated = 0;
4499 while (lex_token (s->lexer) == T_ENDCMD)
4502 if (lex_at_phrase (s->lexer, stop1)
4503 || (stop2 && lex_at_phrase (s->lexer, stop2)))
4506 if (lex_at_phrase (s->lexer, "END MATRIX"))
4508 msg (SE, _("Premature END MATRIX within %s."), command_name);
4512 struct matrix_cmd *cmd = matrix_parse_command (s);
4516 if (c->n >= allocated)
4517 c->commands = x2nrealloc (c->commands, &allocated, sizeof *c->commands);
4518 c->commands[c->n++] = cmd;
4523 matrix_parse_do_if_clause (struct matrix_state *s,
4524 struct do_if_command *ifc,
4525 bool parse_condition,
4526 size_t *allocated_clauses)
4528 if (ifc->n_clauses >= *allocated_clauses)
4529 ifc->clauses = x2nrealloc (ifc->clauses, allocated_clauses,
4530 sizeof *ifc->clauses);
4531 struct do_if_clause *c = &ifc->clauses[ifc->n_clauses++];
4532 *c = (struct do_if_clause) { .condition = NULL };
4534 if (parse_condition)
4536 c->condition = matrix_parse_expr (s);
4541 return matrix_parse_commands (s, &c->commands, "DO IF", "ELSE", "END IF");
4544 static struct matrix_cmd *
4545 matrix_parse_do_if (struct matrix_state *s)
4547 struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
4548 *cmd = (struct matrix_cmd) {
4550 .do_if = { .n_clauses = 0 }
4553 size_t allocated_clauses = 0;
4556 if (!matrix_parse_do_if_clause (s, &cmd->do_if, true, &allocated_clauses))
4559 while (lex_match_phrase (s->lexer, "ELSE IF"));
4561 if (lex_match_id (s->lexer, "ELSE")
4562 && !matrix_parse_do_if_clause (s, &cmd->do_if, false, &allocated_clauses))
4565 if (!lex_match_phrase (s->lexer, "END IF"))
4570 matrix_cmd_destroy (cmd);
4575 matrix_cmd_execute_do_if (struct do_if_command *cmd)
4577 for (size_t i = 0; i < cmd->n_clauses; i++)
4579 struct do_if_clause *c = &cmd->clauses[i];
4583 if (!matrix_expr_evaluate_scalar (c->condition,
4584 i ? "ELSE IF" : "DO IF",
4589 for (size_t j = 0; j < c->commands.n; j++)
4590 if (!matrix_cmd_execute (c->commands.commands[j]))
4597 static struct matrix_cmd *
4598 matrix_parse_loop (struct matrix_state *s)
4600 struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
4601 *cmd = (struct matrix_cmd) { .type = MCMD_LOOP, .loop = { .var = NULL } };
4603 struct loop_command *loop = &cmd->loop;
4604 if (lex_token (s->lexer) == T_ID && lex_next_token (s->lexer, 1) == T_EQUALS)
4606 struct substring name = lex_tokss (s->lexer);
4607 loop->var = matrix_var_lookup (s, name);
4609 loop->var = matrix_var_create (s, name);
4614 loop->start = matrix_parse_expr (s);
4615 if (!loop->start || !lex_force_match (s->lexer, T_TO))
4618 loop->end = matrix_parse_expr (s);
4622 if (lex_match (s->lexer, T_BY))
4624 loop->increment = matrix_parse_expr (s);
4625 if (!loop->increment)
4630 if (lex_match_id (s->lexer, "IF"))
4632 loop->top_condition = matrix_parse_expr (s);
4633 if (!loop->top_condition)
4637 bool was_in_loop = s->in_loop;
4639 bool ok = matrix_parse_commands (s, &loop->commands, "LOOP",
4641 s->in_loop = was_in_loop;
4645 if (!lex_match_phrase (s->lexer, "END LOOP"))
4648 if (lex_match_id (s->lexer, "IF"))
4650 loop->bottom_condition = matrix_parse_expr (s);
4651 if (!loop->bottom_condition)
4658 matrix_cmd_destroy (cmd);
4663 matrix_cmd_execute_loop (struct loop_command *cmd)
4667 long int increment = 1;
4670 if (!matrix_expr_evaluate_integer (cmd->start, "LOOP", &value)
4671 || !matrix_expr_evaluate_integer (cmd->end, "TO", &end)
4673 && !matrix_expr_evaluate_integer (cmd->increment, "BY",
4677 if (increment > 0 ? value > end
4678 : increment < 0 ? value < end
4683 int mxloops = settings_get_mxloops ();
4684 for (int i = 0; i < mxloops; i++)
4689 && (cmd->var->value->size1 != 1 || cmd->var->value->size2 != 1))
4691 gsl_matrix_free (cmd->var->value);
4692 cmd->var->value = NULL;
4694 if (!cmd->var->value)
4695 cmd->var->value = gsl_matrix_alloc (1, 1);
4697 gsl_matrix_set (cmd->var->value, 0, 0, value);
4700 if (cmd->top_condition)
4703 if (!matrix_expr_evaluate_scalar (cmd->top_condition, "LOOP IF",
4708 for (size_t j = 0; j < cmd->commands.n; j++)
4709 if (!matrix_cmd_execute (cmd->commands.commands[j]))
4712 if (cmd->bottom_condition)
4715 if (!matrix_expr_evaluate_scalar (cmd->bottom_condition,
4716 "END LOOP IF", &d) || d > 0)
4723 if (increment > 0 ? value > end : value < end)
4729 static struct matrix_cmd *
4730 matrix_parse_break (struct matrix_state *s)
4734 msg (SE, _("BREAK not inside LOOP."));
4738 struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
4739 *cmd = (struct matrix_cmd) { .type = MCMD_BREAK };
4743 static struct matrix_cmd *
4744 matrix_parse_display (struct matrix_state *s)
4746 while (lex_token (s->lexer) != T_ENDCMD)
4748 if (!lex_match_id (s->lexer, "DICTIONARY")
4749 && !lex_match_id (s->lexer, "STATUS"))
4751 lex_error_expecting (s->lexer, "DICTIONARY", "STATUS");
4756 struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
4757 *cmd = (struct matrix_cmd) { .type = MCMD_DISPLAY, .display = { s } };
4762 compare_matrix_var_pointers (const void *a_, const void *b_)
4764 const struct matrix_var *const *ap = a_;
4765 const struct matrix_var *const *bp = b_;
4766 const struct matrix_var *a = *ap;
4767 const struct matrix_var *b = *bp;
4768 return strcmp (a->name, b->name);
4772 matrix_cmd_execute_display (struct display_command *cmd)
4774 const struct matrix_state *s = cmd->state;
4776 struct pivot_table *table = pivot_table_create (N_("Matrix Variables"));
4777 struct pivot_dimension *attr_dimension
4778 = pivot_dimension_create (table, PIVOT_AXIS_COLUMN, N_("Attribute"));
4779 pivot_category_create_group (attr_dimension->root, N_("Dimension"),
4780 N_("Rows"), N_("Columns"));
4781 pivot_category_create_leaves (attr_dimension->root, N_("Size (kB)"));
4783 const struct matrix_var **vars = xmalloc (hmap_count (&s->vars) * sizeof *vars);
4786 const struct matrix_var *var;
4787 HMAP_FOR_EACH (var, struct matrix_var, hmap_node, &s->vars)
4789 vars[n_vars++] = var;
4790 qsort (vars, n_vars, sizeof *vars, compare_matrix_var_pointers);
4792 struct pivot_dimension *rows = pivot_dimension_create (
4793 table, PIVOT_AXIS_ROW, N_("Variable"));
4794 for (size_t i = 0; i < n_vars; i++)
4796 const struct matrix_var *var = vars[i];
4797 pivot_category_create_leaf (
4798 rows->root, pivot_value_new_user_text (var->name, SIZE_MAX));
4800 size_t r = var->value->size1;
4801 size_t c = var->value->size2;
4802 double values[] = { r, c, r * c * sizeof (double) / 1024 };
4803 for (size_t j = 0; j < sizeof values / sizeof *values; j++)
4804 pivot_table_put2 (table, j, i, pivot_value_new_integer (values[j]));
4807 pivot_table_submit (table);
4810 static struct matrix_cmd *
4811 matrix_parse_release (struct matrix_state *s)
4813 struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
4814 *cmd = (struct matrix_cmd) { .type = MCMD_RELEASE };
4816 size_t allocated_vars = 0;
4817 while (lex_token (s->lexer) == T_ID)
4819 struct matrix_var *var = matrix_var_lookup (s, lex_tokss (s->lexer));
4822 if (cmd->release.n_vars >= allocated_vars)
4823 cmd->release.vars = x2nrealloc (cmd->release.vars, &allocated_vars,
4824 sizeof *cmd->release.vars);
4825 cmd->release.vars[cmd->release.n_vars++] = var;
4828 lex_error (s->lexer, _("Variable name expected."));
4831 if (!lex_match (s->lexer, T_COMMA))
4839 matrix_cmd_execute_release (struct release_command *cmd)
4841 for (size_t i = 0; i < cmd->n_vars; i++)
4843 struct matrix_var *var = cmd->vars[i];
4844 gsl_matrix_free (var->value);
4849 static struct save_file *
4850 save_file_create (struct matrix_state *s, struct file_handle *fh,
4851 struct string_array *variables,
4852 struct matrix_expr *names,
4853 struct stringi_set *strings)
4855 for (size_t i = 0; i < s->n_save_files; i++)
4857 struct save_file *sf = s->save_files[i];
4858 if (fh_equal (sf->file, fh))
4862 string_array_destroy (variables);
4863 matrix_expr_destroy (names);
4864 stringi_set_destroy (strings);
4870 struct save_file *sf = xmalloc (sizeof *sf);
4871 *sf = (struct save_file) {
4873 .dataset = s->dataset,
4874 .variables = *variables,
4876 .strings = STRINGI_SET_INITIALIZER (sf->strings),
4879 stringi_set_swap (&sf->strings, strings);
4880 stringi_set_destroy (strings);
4882 s->save_files = xrealloc (s->save_files,
4883 (s->n_save_files + 1) * sizeof *s->save_files);
4884 s->save_files[s->n_save_files++] = sf;
4888 static struct casewriter *
4889 save_file_open (struct save_file *sf, gsl_matrix *m)
4891 if (sf->writer || sf->error)
4895 size_t n_variables = caseproto_get_n_widths (
4896 casewriter_get_proto (sf->writer));
4897 if (m->size2 != n_variables)
4899 msg (ME, _("The first SAVE to %s within this matrix program "
4900 "had %zu columns, so a %zu×%zu matrix cannot be "
4902 sf->file == fh_inline_file () ? "*" : fh_get_name (sf->file),
4903 n_variables, m->size1, m->size2);
4911 struct dictionary *dict = dict_create (get_default_encoding ());
4913 /* Fill 'names' with user-specified names if there were any, either from
4914 sf->variables or sf->names. */
4915 struct string_array names = { .n = 0 };
4916 if (sf->variables.n)
4917 string_array_clone (&names, &sf->variables);
4920 gsl_matrix *nm = matrix_expr_evaluate (sf->names);
4921 if (nm && is_vector (nm))
4923 gsl_vector nv = to_vector (nm);
4924 for (size_t i = 0; i < nv.size; i++)
4926 char *name = trimmed_string (gsl_vector_get (&nv, i));
4927 if (dict_id_is_valid (dict, name, true))
4928 string_array_append_nocopy (&names, name);
4933 gsl_matrix_free (nm);
4936 struct stringi_set strings;
4937 stringi_set_clone (&strings, &sf->strings);
4939 for (size_t i = 0; dict_get_var_cnt (dict) < m->size2; i++)
4944 name = names.strings[i];
4947 snprintf (tmp_name, sizeof tmp_name, "COL%zu", i + 1);
4951 int width = stringi_set_delete (&strings, name) ? 8 : 0;
4952 struct variable *var = dict_create_var (dict, name, width);
4955 msg (ME, _("Duplicate variable name %s in SAVE statement."),
4961 if (!stringi_set_is_empty (&strings))
4963 size_t count = stringi_set_count (&strings);
4964 const char *example = stringi_set_node_get_string (
4965 stringi_set_first (&strings));
4968 msg (ME, _("The SAVE command STRINGS subcommand specifies an unknown "
4969 "variable %s."), example);
4971 msg (ME, ngettext ("The SAVE command STRINGS subcommand specifies %zu "
4972 "unknown variable: %s.",
4973 "The SAVE command STRINGS subcommand specifies %zu "
4974 "unknown variables, including %s.",
4979 stringi_set_destroy (&strings);
4980 string_array_destroy (&names);
4989 if (sf->file == fh_inline_file ())
4990 sf->writer = autopaging_writer_create (dict_get_proto (dict));
4992 sf->writer = any_writer_open (sf->file, dict);
5004 save_file_destroy (struct save_file *sf)
5008 if (sf->file == fh_inline_file () && sf->writer && sf->dict)
5010 dataset_set_dict (sf->dataset, sf->dict);
5011 dataset_set_source (sf->dataset, casewriter_make_reader (sf->writer));
5015 casewriter_destroy (sf->writer);
5016 dict_unref (sf->dict);
5018 fh_unref (sf->file);
5019 string_array_destroy (&sf->variables);
5020 matrix_expr_destroy (sf->names);
5021 stringi_set_destroy (&sf->strings);
5026 static struct matrix_cmd *
5027 matrix_parse_save (struct matrix_state *s)
5029 struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
5030 *cmd = (struct matrix_cmd) {
5032 .save = { .expression = NULL },
5035 struct file_handle *fh = NULL;
5036 struct save_command *save = &cmd->save;
5038 struct string_array variables = STRING_ARRAY_INITIALIZER;
5039 struct matrix_expr *names = NULL;
5040 struct stringi_set strings = STRINGI_SET_INITIALIZER (strings);
5042 save->expression = matrix_parse_exp (s);
5043 if (!save->expression)
5046 while (lex_match (s->lexer, T_SLASH))
5048 if (lex_match_id (s->lexer, "OUTFILE"))
5050 lex_match (s->lexer, T_EQUALS);
5053 fh = (lex_match (s->lexer, T_ASTERISK)
5055 : fh_parse (s->lexer, FH_REF_FILE, s->session));
5059 else if (lex_match_id (s->lexer, "VARIABLES"))
5061 lex_match (s->lexer, T_EQUALS);
5065 struct dictionary *d = dict_create (get_default_encoding ());
5066 bool ok = parse_DATA_LIST_vars (s->lexer, d, &names, &n,
5067 PV_NO_SCRATCH | PV_NO_DUPLICATE);
5072 string_array_clear (&variables);
5073 variables = (struct string_array) {
5079 else if (lex_match_id (s->lexer, "NAMES"))
5081 lex_match (s->lexer, T_EQUALS);
5082 matrix_expr_destroy (names);
5083 names = matrix_parse_exp (s);
5087 else if (lex_match_id (s->lexer, "STRINGS"))
5089 lex_match (s->lexer, T_EQUALS);
5090 while (lex_token (s->lexer) == T_ID)
5092 stringi_set_insert (&strings, lex_tokcstr (s->lexer));
5094 if (!lex_match (s->lexer, T_COMMA))
5100 lex_error_expecting (s->lexer, "OUTFILE", "VARIABLES", "NAMES",
5108 if (s->prev_save_file)
5109 fh = fh_ref (s->prev_save_file);
5112 lex_sbc_missing ("OUTFILE");
5116 fh_unref (s->prev_save_file);
5117 s->prev_save_file = fh_ref (fh);
5119 if (variables.n && names)
5121 msg (SW, _("VARIABLES and NAMES both specified; ignoring NAMES."));
5122 matrix_expr_destroy (names);
5126 save->sf = save_file_create (s, fh, &variables, names, &strings);
5130 string_array_destroy (&variables);
5131 matrix_expr_destroy (names);
5132 stringi_set_destroy (&strings);
5134 matrix_cmd_destroy (cmd);
5139 matrix_cmd_execute_save (const struct save_command *save)
5141 gsl_matrix *m = matrix_expr_evaluate (save->expression);
5145 struct casewriter *writer = save_file_open (save->sf, m);
5148 gsl_matrix_free (m);
5152 const struct caseproto *proto = casewriter_get_proto (writer);
5153 for (size_t y = 0; y < m->size1; y++)
5155 struct ccase *c = case_create (proto);
5156 for (size_t x = 0; x < m->size2; x++)
5158 double d = gsl_matrix_get (m, y, x);
5159 int width = caseproto_get_width (proto, x);
5160 union value *value = case_data_rw_idx (c, x);
5164 memcpy (value->s, &d, width);
5166 casewriter_write (writer, c);
5168 gsl_matrix_free (m);
5171 static struct matrix_cmd *
5172 matrix_parse_read (struct matrix_state *s)
5174 struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
5175 *cmd = (struct matrix_cmd) {
5177 .read = { .format = FMT_F },
5180 struct file_handle *fh = NULL;
5181 char *encoding = NULL;
5182 struct read_command *read = &cmd->read;
5183 read->dst = matrix_lvalue_parse (s);
5188 int repetitions = 0;
5189 int record_width = 0;
5190 bool seen_format = false;
5191 while (lex_match (s->lexer, T_SLASH))
5193 if (lex_match_id (s->lexer, "FILE"))
5195 lex_match (s->lexer, T_EQUALS);
5198 fh = fh_parse (s->lexer, FH_REF_FILE, NULL);
5202 else if (lex_match_id (s->lexer, "ENCODING"))
5204 lex_match (s->lexer, T_EQUALS);
5205 if (!lex_force_string (s->lexer))
5209 encoding = ss_xstrdup (lex_tokss (s->lexer));
5213 else if (lex_match_id (s->lexer, "FIELD"))
5215 lex_match (s->lexer, T_EQUALS);
5217 if (!lex_force_int_range (s->lexer, "FIELD", 1, INT_MAX))
5219 read->c1 = lex_integer (s->lexer);
5221 if (!lex_force_match (s->lexer, T_TO)
5222 || !lex_force_int_range (s->lexer, "TO", read->c1, INT_MAX))
5224 read->c2 = lex_integer (s->lexer) + 1;
5227 record_width = read->c2 - read->c1;
5228 if (lex_match (s->lexer, T_BY))
5230 if (!lex_force_int_range (s->lexer, "BY", 1,
5231 read->c2 - read->c1))
5233 by = lex_integer (s->lexer);
5236 if (record_width % by)
5238 msg (SE, _("BY %d does not evenly divide record width %d."),
5246 else if (lex_match_id (s->lexer, "SIZE"))
5248 lex_match (s->lexer, T_EQUALS);
5249 matrix_expr_destroy (read->size);
5250 read->size = matrix_parse_exp (s);
5254 else if (lex_match_id (s->lexer, "MODE"))
5256 lex_match (s->lexer, T_EQUALS);
5257 if (lex_match_id (s->lexer, "RECTANGULAR"))
5258 read->symmetric = false;
5259 else if (lex_match_id (s->lexer, "SYMMETRIC"))
5260 read->symmetric = true;
5263 lex_error_expecting (s->lexer, "RECTANGULAR", "SYMMETRIC");
5267 else if (lex_match_id (s->lexer, "REREAD"))
5268 read->reread = true;
5269 else if (lex_match_id (s->lexer, "FORMAT"))
5273 lex_sbc_only_once ("FORMAT");
5278 lex_match (s->lexer, T_EQUALS);
5280 if (lex_token (s->lexer) != T_STRING && !lex_force_id (s->lexer))
5283 const char *p = lex_tokcstr (s->lexer);
5284 if (c_isdigit (p[0]))
5286 repetitions = atoi (p);
5287 p += strspn (p, "0123456789");
5288 if (!fmt_from_name (p, &read->format))
5290 lex_error (s->lexer, _("Unknown format %s."), p);
5295 else if (fmt_from_name (p, &read->format))
5299 struct fmt_spec format;
5300 if (!parse_format_specifier (s->lexer, &format))
5302 read->format = format.type;
5308 lex_error_expecting (s->lexer, "FILE", "FIELD", "MODE",
5309 "REREAD", "FORMAT");
5316 lex_sbc_missing ("FIELD");
5320 if (!read->dst->n_indexes && !read->size)
5322 msg (SE, _("SIZE is required for reading data into a full matrix "
5323 "(as opposed to a submatrix)."));
5329 if (s->prev_read_file)
5330 fh = fh_ref (s->prev_read_file);
5333 lex_sbc_missing ("FILE");
5337 fh_unref (s->prev_read_file);
5338 s->prev_read_file = fh_ref (fh);
5340 read->rf = read_file_create (s, fh);
5344 free (read->rf->encoding);
5345 read->rf->encoding = encoding;
5349 /* Field width may be specified in multiple ways:
5352 2. The format on FORMAT.
5353 3. The repetition factor on FORMAT.
5355 (2) and (3) are mutually exclusive.
5357 If more than one of these is present, they must agree. If none of them is
5358 present, then free-field format is used.
5360 if (repetitions > record_width)
5362 msg (SE, _("%d repetitions cannot fit in record width %d."),
5363 repetitions, record_width);
5366 int w = (repetitions ? record_width / repetitions
5372 msg (SE, _("FORMAT specifies %d repetitions with record width %d, "
5373 "which implies field width %d, "
5374 "but BY specifies field width %d."),
5375 repetitions, record_width, w, by);
5377 msg (SE, _("FORMAT specifies field width %d but BY specifies %d."),
5386 matrix_cmd_destroy (cmd);
5392 parse_error (const struct dfm_reader *reader, enum fmt_type format,
5393 struct substring data, size_t y, size_t x,
5394 int first_column, int last_column, char *error)
5396 int line_number = dfm_get_line_number (reader);
5397 struct msg_location *location = xmalloc (sizeof *location);
5398 *location = (struct msg_location) {
5399 .file_name = xstrdup (dfm_get_file_name (reader)),
5400 .first_line = line_number,
5401 .last_line = line_number + 1,
5402 .first_column = first_column,
5403 .last_column = last_column,
5405 struct msg *m = xmalloc (sizeof *m);
5407 .category = MSG_C_DATA,
5408 .severity = MSG_S_WARNING,
5409 .location = location,
5410 .text = xasprintf (_("Error reading \"%.*s\" as format %s "
5411 "for matrix row %zu, column %zu: %s"),
5412 (int) data.length, data.string, fmt_name (format),
5413 y + 1, x + 1, error),
5421 matrix_read_set_field (struct read_command *read, struct dfm_reader *reader,
5422 gsl_matrix *m, struct substring p, size_t y, size_t x,
5423 const char *line_start)
5425 const char *input_encoding = dfm_reader_get_encoding (reader);
5428 if (fmt_is_numeric (read->format))
5431 error = data_in (p, input_encoding, read->format,
5432 settings_get_fmt_settings (), &v, 0, NULL);
5433 if (!error && v.f == SYSMIS)
5434 error = xstrdup (_("Matrix data may not contain missing value."));
5439 uint8_t s[sizeof (double)];
5440 union value v = { .s = s };
5441 error = data_in (p, input_encoding, read->format,
5442 settings_get_fmt_settings (), &v, sizeof s, "UTF-8");
5443 memcpy (&f, s, sizeof f);
5448 int c1 = utf8_count_columns (line_start, p.string - line_start) + 1;
5449 int c2 = c1 + ss_utf8_count_columns (p) - 1;
5450 parse_error (reader, read->format, p, y, x, c1, c2, error);
5454 gsl_matrix_set (m, y, x, f);
5455 if (read->symmetric && x != y)
5456 gsl_matrix_set (m, x, y, f);
5461 matrix_read_line (struct read_command *read, struct dfm_reader *reader,
5462 struct substring *line, const char **startp)
5464 if (dfm_eof (reader))
5466 msg (SE, _("Unexpected end of file reading matrix data."));
5469 dfm_expand_tabs (reader);
5470 struct substring record = dfm_get_record (reader);
5471 /* XXX need to recode record into UTF-8 */
5472 *startp = record.string;
5473 *line = ss_utf8_columns (record, read->c1 - 1, read->c2 - read->c1);
5478 matrix_read (struct read_command *read, struct dfm_reader *reader,
5481 for (size_t y = 0; y < m->size1; y++)
5483 size_t nx = read->symmetric ? y + 1 : m->size2;
5485 struct substring line = ss_empty ();
5486 const char *line_start = line.string;
5487 for (size_t x = 0; x < nx; x++)
5494 ss_ltrim (&line, ss_cstr (" ,"));
5495 if (!ss_is_empty (line))
5497 if (!matrix_read_line (read, reader, &line, &line_start))
5499 dfm_forward_record (reader);
5502 ss_get_bytes (&line, ss_cspan (line, ss_cstr (" ,")), &p);
5506 if (!matrix_read_line (read, reader, &line, &line_start))
5508 size_t fields_per_line = (read->c2 - read->c1) / read->w;
5509 int f = x % fields_per_line;
5510 if (f == fields_per_line - 1)
5511 dfm_forward_record (reader);
5513 p = ss_substr (line, read->w * f, read->w);
5516 matrix_read_set_field (read, reader, m, p, y, x, line_start);
5520 dfm_forward_record (reader);
5523 ss_ltrim (&line, ss_cstr (" ,"));
5524 if (!ss_is_empty (line))
5527 msg (SW, _("Trailing garbage on line \"%.*s\""),
5528 (int) line.length, line.string);
5535 matrix_cmd_execute_read (struct read_command *read)
5537 struct index_vector iv0, iv1;
5538 if (!matrix_lvalue_evaluate (read->dst, &iv0, &iv1))
5541 size_t size[2] = { SIZE_MAX, SIZE_MAX };
5544 gsl_matrix *m = matrix_expr_evaluate (read->size);
5550 msg (SE, _("SIZE must evaluate to a scalar or a 2-element vector, "
5551 "not a %zu×%zu matrix."), m->size1, m->size2);
5552 gsl_matrix_free (m);
5558 gsl_vector v = to_vector (m);
5562 d[0] = gsl_vector_get (&v, 0);
5565 else if (v.size == 2)
5567 d[0] = gsl_vector_get (&v, 0);
5568 d[1] = gsl_vector_get (&v, 1);
5572 msg (SE, _("SIZE must evaluate to a scalar or a 2-element vector, "
5573 "not a %zu×%zu matrix."),
5574 m->size1, m->size2),
5575 gsl_matrix_free (m);
5580 gsl_matrix_free (m);
5582 if (d[0] < 0 || d[0] > SIZE_MAX || d[1] < 0 || d[1] > SIZE_MAX)
5584 msg (SE, _("Matrix dimensions %g×%g specified on SIZE "
5585 "are outside valid range."),
5596 if (read->dst->n_indexes)
5598 size_t submatrix_size[2];
5599 if (read->dst->n_indexes == 2)
5601 submatrix_size[0] = iv0.n;
5602 submatrix_size[1] = iv1.n;
5604 else if (read->dst->var->value->size1 == 1)
5606 submatrix_size[0] = 1;
5607 submatrix_size[1] = iv0.n;
5611 submatrix_size[0] = iv0.n;
5612 submatrix_size[1] = 1;
5617 if (size[0] != submatrix_size[0] || size[1] != submatrix_size[1])
5619 msg (SE, _("Matrix dimensions %zu×%zu specified on SIZE "
5620 "differ from submatrix dimensions %zu×%zu."),
5622 submatrix_size[0], submatrix_size[1]);
5630 size[0] = submatrix_size[0];
5631 size[1] = submatrix_size[1];
5635 struct dfm_reader *reader = read_file_open (read->rf);
5637 dfm_reread_record (reader, 1);
5639 if (read->symmetric && size[0] != size[1])
5641 msg (SE, _("Cannot read non-square %zu×%zu matrix "
5642 "using READ with MODE=SYMMETRIC."),
5648 gsl_matrix *tmp = gsl_matrix_calloc (size[0], size[1]);
5649 matrix_read (read, reader, tmp);
5650 matrix_lvalue_assign (read->dst, &iv0, &iv1, tmp);
5653 static struct matrix_cmd *
5654 matrix_parse_write (struct matrix_state *s)
5656 struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
5657 *cmd = (struct matrix_cmd) {
5661 struct file_handle *fh = NULL;
5662 char *encoding = NULL;
5663 struct write_command *write = &cmd->write;
5664 write->expression = matrix_parse_exp (s);
5665 if (!write->expression)
5669 int repetitions = 0;
5670 int record_width = 0;
5671 enum fmt_type format = FMT_F;
5672 bool has_format = false;
5673 while (lex_match (s->lexer, T_SLASH))
5675 if (lex_match_id (s->lexer, "OUTFILE"))
5677 lex_match (s->lexer, T_EQUALS);
5680 fh = fh_parse (s->lexer, FH_REF_FILE, NULL);
5684 else if (lex_match_id (s->lexer, "ENCODING"))
5686 lex_match (s->lexer, T_EQUALS);
5687 if (!lex_force_string (s->lexer))
5691 encoding = ss_xstrdup (lex_tokss (s->lexer));
5695 else if (lex_match_id (s->lexer, "FIELD"))
5697 lex_match (s->lexer, T_EQUALS);
5699 if (!lex_force_int_range (s->lexer, "FIELD", 1, INT_MAX))
5701 write->c1 = lex_integer (s->lexer);
5703 if (!lex_force_match (s->lexer, T_TO)
5704 || !lex_force_int_range (s->lexer, "TO", write->c1, INT_MAX))
5706 write->c2 = lex_integer (s->lexer) + 1;
5709 record_width = write->c2 - write->c1;
5710 if (lex_match (s->lexer, T_BY))
5712 if (!lex_force_int_range (s->lexer, "BY", 1,
5713 write->c2 - write->c1))
5715 by = lex_integer (s->lexer);
5718 if (record_width % by)
5720 msg (SE, _("BY %d does not evenly divide record width %d."),
5728 else if (lex_match_id (s->lexer, "MODE"))
5730 lex_match (s->lexer, T_EQUALS);
5731 if (lex_match_id (s->lexer, "RECTANGULAR"))
5732 write->triangular = false;
5733 else if (lex_match_id (s->lexer, "TRIANGULAR"))
5734 write->triangular = true;
5737 lex_error_expecting (s->lexer, "RECTANGULAR", "TRIANGULAR");
5741 else if (lex_match_id (s->lexer, "HOLD"))
5743 else if (lex_match_id (s->lexer, "FORMAT"))
5745 if (has_format || write->format)
5747 lex_sbc_only_once ("FORMAT");
5751 lex_match (s->lexer, T_EQUALS);
5753 if (lex_token (s->lexer) != T_STRING && !lex_force_id (s->lexer))
5756 const char *p = lex_tokcstr (s->lexer);
5757 if (c_isdigit (p[0]))
5759 repetitions = atoi (p);
5760 p += strspn (p, "0123456789");
5761 if (!fmt_from_name (p, &format))
5763 lex_error (s->lexer, _("Unknown format %s."), p);
5769 else if (fmt_from_name (p, &format))
5776 struct fmt_spec spec;
5777 if (!parse_format_specifier (s->lexer, &spec))
5779 write->format = xmemdup (&spec, sizeof spec);
5784 lex_error_expecting (s->lexer, "OUTFILE", "FIELD", "MODE",
5792 lex_sbc_missing ("FIELD");
5798 if (s->prev_write_file)
5799 fh = fh_ref (s->prev_write_file);
5802 lex_sbc_missing ("OUTFILE");
5806 fh_unref (s->prev_write_file);
5807 s->prev_write_file = fh_ref (fh);
5809 write->wf = write_file_create (s, fh);
5813 free (write->wf->encoding);
5814 write->wf->encoding = encoding;
5818 /* Field width may be specified in multiple ways:
5821 2. The format on FORMAT.
5822 3. The repetition factor on FORMAT.
5824 (2) and (3) are mutually exclusive.
5826 If more than one of these is present, they must agree. If none of them is
5827 present, then free-field format is used.
5829 if (repetitions > record_width)
5831 msg (SE, _("%d repetitions cannot fit in record width %d."),
5832 repetitions, record_width);
5835 int w = (repetitions ? record_width / repetitions
5836 : write->format ? write->format->w
5841 msg (SE, _("FORMAT specifies %d repetitions with record width %d, "
5842 "which implies field width %d, "
5843 "but BY specifies field width %d."),
5844 repetitions, record_width, w, by);
5846 msg (SE, _("FORMAT specifies field width %d but BY specifies %d."),
5850 if (w && !write->format)
5852 write->format = xmalloc (sizeof *write->format);
5853 *write->format = (struct fmt_spec) { .type = format, .w = w };
5855 if (!fmt_check_output (write->format))
5859 if (write->format && fmt_var_width (write->format) > sizeof (double))
5861 char s[FMT_STRING_LEN_MAX + 1];
5862 fmt_to_string (write->format, s);
5863 msg (SE, _("Format %s is too wide for %zu-byte matrix eleemnts."),
5864 s, sizeof (double));
5872 matrix_cmd_destroy (cmd);
5877 matrix_cmd_execute_write (struct write_command *write)
5879 gsl_matrix *m = matrix_expr_evaluate (write->expression);
5883 if (write->triangular && m->size1 != m->size2)
5885 msg (SE, _("WRITE with MODE=TRIANGULAR requires a square matrix but "
5886 "the matrix to be written has dimensions %zu×%zu."),
5887 m->size1, m->size2);
5888 gsl_matrix_free (m);
5892 struct dfm_writer *writer = write_file_open (write->wf);
5893 if (!writer || !m->size1)
5895 gsl_matrix_free (m);
5899 const struct fmt_settings *settings = settings_get_fmt_settings ();
5900 struct u8_line *line = write->wf->held;
5901 for (size_t y = 0; y < m->size1; y++)
5905 line = xmalloc (sizeof *line);
5906 u8_line_init (line);
5908 size_t nx = write->triangular ? y + 1 : m->size2;
5910 for (size_t x = 0; x < nx; x++)
5913 double f = gsl_matrix_get (m, y, x);
5917 if (fmt_is_numeric (write->format->type))
5920 v.s = (uint8_t *) &f;
5921 s = data_out (&v, NULL, write->format, settings);
5925 s = xmalloc (DBL_BUFSIZE_BOUND);
5926 if (c_dtoastr (s, DBL_BUFSIZE_BOUND, FTOASTR_UPPER_E, 0, f)
5927 >= DBL_BUFSIZE_BOUND)
5930 size_t len = strlen (s);
5931 int width = u8_width (CHAR_CAST (const uint8_t *, s), len, UTF8);
5932 if (width + x0 > write->c2)
5934 dfm_put_record_utf8 (writer, line->s.ss.string,
5936 u8_line_clear (line);
5939 u8_line_put (line, x0, x0 + width, s, len);
5942 x0 += write->format ? write->format->w : width + 1;
5945 if (y + 1 >= m->size1 && write->hold)
5947 dfm_put_record_utf8 (writer, line->s.ss.string, line->s.ss.length);
5948 u8_line_clear (line);
5952 u8_line_destroy (line);
5956 write->wf->held = line;
5958 gsl_matrix_free (m);
5961 static struct matrix_cmd *
5962 matrix_parse_get (struct matrix_state *s)
5964 struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
5965 *cmd = (struct matrix_cmd) {
5968 .dataset = s->dataset,
5969 .user = { .treatment = MGET_ERROR },
5970 .system = { .treatment = MGET_ERROR },
5974 struct get_command *get = &cmd->get;
5975 get->dst = matrix_lvalue_parse (s);
5979 while (lex_match (s->lexer, T_SLASH))
5981 if (lex_match_id (s->lexer, "FILE"))
5983 lex_match (s->lexer, T_EQUALS);
5985 fh_unref (get->file);
5986 if (lex_match (s->lexer, T_ASTERISK))
5990 get->file = fh_parse (s->lexer, FH_REF_FILE, s->session);
5995 else if (lex_match_id (s->lexer, "ENCODING"))
5997 lex_match (s->lexer, T_EQUALS);
5998 if (!lex_force_string (s->lexer))
6001 free (get->encoding);
6002 get->encoding = ss_xstrdup (lex_tokss (s->lexer));
6006 else if (lex_match_id (s->lexer, "VARIABLES"))
6008 lex_match (s->lexer, T_EQUALS);
6012 lex_sbc_only_once ("VARIABLES");
6016 if (!var_syntax_parse (s->lexer, &get->vars, &get->n_vars))
6019 else if (lex_match_id (s->lexer, "NAMES"))
6021 lex_match (s->lexer, T_EQUALS);
6022 if (!lex_force_id (s->lexer))
6025 struct substring name = lex_tokss (s->lexer);
6026 get->names = matrix_var_lookup (s, name);
6028 get->names = matrix_var_create (s, name);
6031 else if (lex_match_id (s->lexer, "MISSING"))
6033 lex_match (s->lexer, T_EQUALS);
6034 if (lex_match_id (s->lexer, "ACCEPT"))
6035 get->user.treatment = MGET_ACCEPT;
6036 else if (lex_match_id (s->lexer, "OMIT"))
6037 get->user.treatment = MGET_OMIT;
6038 else if (lex_is_number (s->lexer))
6040 get->user.treatment = MGET_RECODE;
6041 get->user.substitute = lex_number (s->lexer);
6046 lex_error (s->lexer, NULL);
6050 else if (lex_match_id (s->lexer, "SYSMIS"))
6052 lex_match (s->lexer, T_EQUALS);
6053 if (lex_match_id (s->lexer, "OMIT"))
6054 get->system.treatment = MGET_OMIT;
6055 else if (lex_is_number (s->lexer))
6057 get->system.treatment = MGET_RECODE;
6058 get->system.substitute = lex_number (s->lexer);
6063 lex_error (s->lexer, NULL);
6069 lex_error_expecting (s->lexer, "FILE", "VARIABLES", "NAMES",
6070 "MISSING", "SYSMIS");
6075 if (get->user.treatment != MGET_ACCEPT)
6076 get->system.treatment = MGET_ERROR;
6081 matrix_cmd_destroy (cmd);
6086 matrix_cmd_execute_get__ (struct get_command *get, struct casereader *reader,
6087 const struct dictionary *dict)
6089 struct variable **vars;
6094 if (!var_syntax_evaluate (get->vars, get->n_vars, dict,
6095 &vars, &n_vars, PV_NUMERIC))
6100 n_vars = dict_get_var_cnt (dict);
6101 vars = xnmalloc (n_vars, sizeof *vars);
6102 for (size_t i = 0; i < n_vars; i++)
6104 struct variable *var = dict_get_var (dict, i);
6105 if (!var_is_numeric (var))
6107 msg (SE, _("GET: Variable %s is not numeric."),
6108 var_get_name (var));
6118 gsl_matrix *names = gsl_matrix_alloc (n_vars, 1);
6119 for (size_t i = 0; i < n_vars; i++)
6121 char s[sizeof (double)];
6123 buf_copy_str_rpad (s, sizeof s, var_get_name (vars[i]), ' ');
6124 memcpy (&f, s, sizeof f);
6125 gsl_matrix_set (names, i, 0, f);
6128 gsl_matrix_free (get->names->value);
6129 get->names->value = names;
6133 gsl_matrix *m = gsl_matrix_alloc (4, n_vars);
6134 long long int casenum = 1;
6136 for (struct ccase *c = casereader_read (reader); c;
6137 c = casereader_read (reader), casenum++)
6139 if (n_rows >= m->size1)
6141 gsl_matrix *p = gsl_matrix_alloc (m->size1 * 2, n_vars);
6142 for (size_t y = 0; y < n_rows; y++)
6143 for (size_t x = 0; x < n_vars; x++)
6144 gsl_matrix_set (p, y, x, gsl_matrix_get (m, y, x));
6145 gsl_matrix_free (m);
6150 for (size_t x = 0; x < n_vars; x++)
6152 const struct variable *var = vars[x];
6153 double d = case_num (c, var);
6156 if (get->system.treatment == MGET_RECODE)
6157 d = get->system.substitute;
6158 else if (get->system.treatment == MGET_OMIT)
6162 msg (SE, _("GET: Variable %s in case %lld "
6163 "is system-missing."),
6164 var_get_name (var), casenum);
6168 else if (var_is_num_missing (var, d, MV_USER))
6170 if (get->user.treatment == MGET_RECODE)
6171 d = get->user.substitute;
6172 else if (get->user.treatment == MGET_OMIT)
6174 else if (get->user.treatment != MGET_ACCEPT)
6176 msg (SE, _("GET: Variable %s in case %lld has user-missing "
6178 var_get_name (var), casenum, d);
6182 gsl_matrix_set (m, n_rows, x, d);
6193 matrix_lvalue_evaluate_and_assign (get->dst, m);
6196 gsl_matrix_free (m);
6201 matrix_open_casereader (const char *command_name,
6202 struct file_handle *file, const char *encoding,
6203 struct dataset *dataset,
6204 struct casereader **readerp, struct dictionary **dictp)
6208 *readerp = any_reader_open_and_decode (file, encoding, dictp, NULL);
6209 return *readerp != NULL;
6213 if (dict_get_var_cnt (dataset_dict (dataset)) == 0)
6215 msg (ME, _("The %s command cannot read an empty active file."),
6219 *readerp = proc_open (dataset);
6220 *dictp = dict_ref (dataset_dict (dataset));
6226 matrix_close_casereader (struct file_handle *file, struct dataset *dataset,
6227 struct casereader *reader, struct dictionary *dict)
6230 casereader_destroy (reader);
6232 proc_commit (dataset);
6236 matrix_cmd_execute_get (struct get_command *get)
6238 struct casereader *r;
6239 struct dictionary *d;
6240 if (matrix_open_casereader ("GET", get->file, get->encoding, get->dataset,
6243 matrix_cmd_execute_get__ (get, r, d);
6244 matrix_close_casereader (get->file, get->dataset, r, d);
6249 match_rowtype (struct lexer *lexer)
6251 static const char *rowtypes[] = {
6252 "COV", "CORR", "MEAN", "STDDEV", "N", "COUNT"
6254 size_t n_rowtypes = sizeof rowtypes / sizeof *rowtypes;
6256 for (size_t i = 0; i < n_rowtypes; i++)
6257 if (lex_match_id (lexer, rowtypes[i]))
6260 lex_error_expecting_array (lexer, rowtypes, n_rowtypes);
6265 parse_var_names (struct lexer *lexer, struct string_array *sa)
6267 lex_match (lexer, T_EQUALS);
6269 string_array_clear (sa);
6271 struct dictionary *dict = dict_create (get_default_encoding ());
6274 bool ok = parse_DATA_LIST_vars (lexer, dict, &names, &n_names,
6275 PV_NO_DUPLICATE | PV_NO_SCRATCH);
6280 for (size_t i = 0; i < n_names; i++)
6281 if (ss_equals_case (ss_cstr (names[i]), ss_cstr ("ROWTYPE_"))
6282 || ss_equals_case (ss_cstr (names[i]), ss_cstr ("VARNAME_")))
6284 msg (SE, _("Variable name %s is reserved."), names[i]);
6285 for (size_t j = 0; j < n_names; j++)
6291 string_array_clear (sa);
6292 sa->strings = names;
6293 sa->n = sa->allocated = n_names;
6299 msave_common_destroy (struct msave_common *common)
6303 fh_unref (common->outfile);
6304 string_array_destroy (&common->variables);
6305 string_array_destroy (&common->fnames);
6306 string_array_destroy (&common->snames);
6308 for (size_t i = 0; i < common->n_factors; i++)
6309 matrix_expr_destroy (common->factors[i]);
6310 free (common->factors);
6312 for (size_t i = 0; i < common->n_splits; i++)
6313 matrix_expr_destroy (common->splits[i]);
6314 free (common->splits);
6316 dict_unref (common->dict);
6317 casewriter_destroy (common->writer);
6324 compare_variables (const char *keyword,
6325 const struct string_array *new,
6326 const struct string_array *old)
6332 msg (SE, _("%s may only be specified on MSAVE if it was specified "
6333 "on the first MSAVE within MATRIX."), keyword);
6336 else if (!string_array_equal_case (old, new))
6338 msg (SE, _("%s must specify the same variables each time within "
6339 "a given MATRIX."), keyword);
6346 static struct matrix_cmd *
6347 matrix_parse_msave (struct matrix_state *s)
6349 struct msave_common *common = xmalloc (sizeof *common);
6350 *common = (struct msave_common) { .outfile = NULL };
6352 struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
6353 *cmd = (struct matrix_cmd) { .type = MCMD_MSAVE, .msave = { .expr = NULL } };
6355 struct matrix_expr *splits = NULL;
6356 struct matrix_expr *factors = NULL;
6358 struct msave_command *msave = &cmd->msave;
6359 msave->expr = matrix_parse_exp (s);
6363 while (lex_match (s->lexer, T_SLASH))
6365 if (lex_match_id (s->lexer, "TYPE"))
6367 lex_match (s->lexer, T_EQUALS);
6369 msave->rowtype = match_rowtype (s->lexer);
6370 if (!msave->rowtype)
6373 else if (lex_match_id (s->lexer, "OUTFILE"))
6375 lex_match (s->lexer, T_EQUALS);
6377 fh_unref (common->outfile);
6378 common->outfile = fh_parse (s->lexer, FH_REF_FILE, NULL);
6379 if (!common->outfile)
6382 else if (lex_match_id (s->lexer, "VARIABLES"))
6384 if (!parse_var_names (s->lexer, &common->variables))
6387 else if (lex_match_id (s->lexer, "FNAMES"))
6389 if (!parse_var_names (s->lexer, &common->fnames))
6392 else if (lex_match_id (s->lexer, "SNAMES"))
6394 if (!parse_var_names (s->lexer, &common->snames))
6397 else if (lex_match_id (s->lexer, "SPLIT"))
6399 lex_match (s->lexer, T_EQUALS);
6401 matrix_expr_destroy (splits);
6402 splits = matrix_parse_exp (s);
6406 else if (lex_match_id (s->lexer, "FACTOR"))
6408 lex_match (s->lexer, T_EQUALS);
6410 matrix_expr_destroy (factors);
6411 factors = matrix_parse_exp (s);
6417 lex_error_expecting (s->lexer, "TYPE", "OUTFILE", "VARIABLES",
6418 "FNAMES", "SNAMES", "SPLIT", "FACTOR");
6422 if (!msave->rowtype)
6424 lex_sbc_missing ("TYPE");
6430 if (common->fnames.n && !factors)
6432 msg (SE, _("FNAMES requires FACTOR."));
6435 if (common->snames.n && !splits)
6437 msg (SE, _("SNAMES requires SPLIT."));
6440 if (!common->outfile)
6442 lex_sbc_missing ("OUTFILE");
6449 if (common->outfile)
6451 if (!fh_equal (common->outfile, s->common->outfile))
6453 msg (SE, _("OUTFILE must name the same file on each MSAVE "
6454 "within a single MATRIX command."));
6458 if (!compare_variables ("VARIABLES",
6459 &common->variables, &s->common->variables)
6460 || !compare_variables ("FNAMES", &common->fnames, &s->common->fnames)
6461 || !compare_variables ("SNAMES", &common->snames, &s->common->snames))
6463 msave_common_destroy (common);
6465 msave->common = s->common;
6467 struct msave_common *c = s->common;
6470 if (c->n_factors >= c->allocated_factors)
6471 c->factors = x2nrealloc (c->factors, &c->allocated_factors,
6472 sizeof *c->factors);
6473 c->factors[c->n_factors++] = factors;
6475 if (c->n_factors > 0)
6476 msave->factors = c->factors[c->n_factors - 1];
6480 if (c->n_splits >= c->allocated_splits)
6481 c->splits = x2nrealloc (c->splits, &c->allocated_splits,
6483 c->splits[c->n_splits++] = splits;
6485 if (c->n_splits > 0)
6486 msave->splits = c->splits[c->n_splits - 1];
6491 matrix_expr_destroy (splits);
6492 matrix_expr_destroy (factors);
6493 msave_common_destroy (common);
6494 matrix_cmd_destroy (cmd);
6499 matrix_expr_evaluate_vector (const struct matrix_expr *e, const char *name)
6501 gsl_matrix *m = matrix_expr_evaluate (e);
6507 msg (SE, _("%s expression must evaluate to vector, "
6508 "not a %zu×%zu matrix."),
6509 name, m->size1, m->size2);
6510 gsl_matrix_free (m);
6514 return matrix_to_vector (m);
6518 msave_add_vars (struct dictionary *d, const struct string_array *vars)
6520 for (size_t i = 0; i < vars->n; i++)
6521 if (!dict_create_var (d, vars->strings[i], 0))
6522 return vars->strings[i];
6526 static struct dictionary *
6527 msave_create_dict (const struct msave_common *common)
6529 struct dictionary *dict = dict_create (get_default_encoding ());
6531 const char *dup_split = msave_add_vars (dict, &common->snames);
6534 /* Should not be possible because the parser ensures that the names are
6539 dict_create_var_assert (dict, "ROWTYPE_", 8);
6541 const char *dup_factor = msave_add_vars (dict, &common->fnames);
6544 msg (SE, _("Duplicate or invalid FACTOR variable name %s."), dup_factor);
6548 dict_create_var_assert (dict, "VARNAME_", 8);
6550 const char *dup_var = msave_add_vars (dict, &common->variables);
6553 msg (SE, _("Duplicate or invalid variable name %s."), dup_var);
6565 matrix_cmd_execute_msave (struct msave_command *msave)
6567 struct msave_common *common = msave->common;
6568 gsl_matrix *m = NULL;
6569 gsl_vector *factors = NULL;
6570 gsl_vector *splits = NULL;
6572 m = matrix_expr_evaluate (msave->expr);
6576 if (!common->variables.n)
6577 for (size_t i = 0; i < m->size2; i++)
6578 string_array_append_nocopy (&common->variables,
6579 xasprintf ("COL%zu", i + 1));
6580 else if (m->size2 != common->variables.n)
6583 _("Matrix on MSAVE has %zu columns but there are %zu variables."),
6584 m->size2, common->variables.n);
6590 factors = matrix_expr_evaluate_vector (msave->factors, "FACTOR");
6594 if (!common->fnames.n)
6595 for (size_t i = 0; i < factors->size; i++)
6596 string_array_append_nocopy (&common->fnames,
6597 xasprintf ("FAC%zu", i + 1));
6598 else if (factors->size != common->fnames.n)
6600 msg (SE, _("There are %zu factor variables, "
6601 "but %zu factor values were supplied."),
6602 common->fnames.n, factors->size);
6609 splits = matrix_expr_evaluate_vector (msave->splits, "SPLIT");
6613 if (!common->snames.n)
6614 for (size_t i = 0; i < splits->size; i++)
6615 string_array_append_nocopy (&common->snames,
6616 xasprintf ("SPL%zu", i + 1));
6617 else if (splits->size != common->snames.n)
6619 msg (SE, _("There are %zu split variables, "
6620 "but %zu split values were supplied."),
6621 common->snames.n, splits->size);
6626 if (!common->writer)
6628 struct dictionary *dict = msave_create_dict (common);
6632 common->writer = any_writer_open (common->outfile, dict);
6633 if (!common->writer)
6639 common->dict = dict;
6642 bool matrix = (!strcmp (msave->rowtype, "COV")
6643 || !strcmp (msave->rowtype, "CORR"));
6644 for (size_t y = 0; y < m->size1; y++)
6646 struct ccase *c = case_create (dict_get_proto (common->dict));
6649 /* Split variables */
6651 for (size_t i = 0; i < splits->size; i++)
6652 case_data_rw_idx (c, idx++)->f = gsl_vector_get (splits, i);
6655 buf_copy_str_rpad (CHAR_CAST (char *, case_data_rw_idx (c, idx++)->s), 8,
6656 msave->rowtype, ' ');
6660 for (size_t i = 0; i < factors->size; i++)
6661 *case_num_rw_idx (c, idx++) = gsl_vector_get (factors, i);
6664 const char *varname_ = (matrix && y < common->variables.n
6665 ? common->variables.strings[y]
6667 buf_copy_str_rpad (CHAR_CAST (char *, case_data_rw_idx (c, idx++)->s), 8,
6670 /* Continuous variables. */
6671 for (size_t x = 0; x < m->size2; x++)
6672 case_data_rw_idx (c, idx++)->f = gsl_matrix_get (m, y, x);
6673 casewriter_write (common->writer, c);
6677 gsl_matrix_free (m);
6678 gsl_vector_free (factors);
6679 gsl_vector_free (splits);
6682 static struct matrix_cmd *
6683 matrix_parse_mget (struct matrix_state *s)
6685 struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
6686 *cmd = (struct matrix_cmd) {
6690 .rowtypes = STRINGI_SET_INITIALIZER (cmd->mget.rowtypes),
6694 struct mget_command *mget = &cmd->mget;
6696 lex_match (s->lexer, T_SLASH);
6697 while (lex_token (s->lexer) != T_ENDCMD)
6699 if (lex_match_id (s->lexer, "FILE"))
6701 lex_match (s->lexer, T_EQUALS);
6703 fh_unref (mget->file);
6704 mget->file = fh_parse (s->lexer, FH_REF_FILE, s->session);
6708 else if (lex_match_id (s->lexer, "ENCODING"))
6710 lex_match (s->lexer, T_EQUALS);
6711 if (!lex_force_string (s->lexer))
6714 free (mget->encoding);
6715 mget->encoding = ss_xstrdup (lex_tokss (s->lexer));
6719 else if (lex_match_id (s->lexer, "TYPE"))
6721 lex_match (s->lexer, T_EQUALS);
6722 while (lex_token (s->lexer) != T_SLASH
6723 && lex_token (s->lexer) != T_ENDCMD)
6725 const char *rowtype = match_rowtype (s->lexer);
6729 stringi_set_insert (&mget->rowtypes, rowtype);
6734 lex_error_expecting (s->lexer, "FILE", "TYPE");
6737 lex_match (s->lexer, T_SLASH);
6742 matrix_cmd_destroy (cmd);
6746 static const struct variable *
6747 get_a8_var (const struct dictionary *d, const char *name)
6749 const struct variable *v = dict_lookup_var (d, name);
6752 msg (SE, _("Matrix data file lacks %s variable."), name);
6755 if (var_get_width (v) != 8)
6757 msg (SE, _("%s variable in matrix data file must be "
6758 "8-byte string, but it has width %d."),
6759 name, var_get_width (v));
6766 var_changed (const struct ccase *ca, const struct ccase *cb,
6767 const struct variable *var)
6770 ? !value_equal (case_data (ca, var), case_data (cb, var),
6771 var_get_width (var))
6776 vars_changed (const struct ccase *ca, const struct ccase *cb,
6777 const struct dictionary *d,
6778 size_t first_var, size_t n_vars)
6780 for (size_t i = 0; i < n_vars; i++)
6782 const struct variable *v = dict_get_var (d, first_var + i);
6783 if (var_changed (ca, cb, v))
6790 vars_all_missing (const struct ccase *c, const struct dictionary *d,
6791 size_t first_var, size_t n_vars)
6793 for (size_t i = 0; i < n_vars; i++)
6794 if (case_num (c, dict_get_var (d, first_var + i)) != SYSMIS)
6800 matrix_mget_commit_var (struct ccase **rows, size_t n_rows,
6801 const struct dictionary *d,
6802 const struct variable *rowtype_var,
6803 const struct stringi_set *accepted_rowtypes,
6804 struct matrix_state *s,
6805 size_t ss, size_t sn, size_t si,
6806 size_t fs, size_t fn, size_t fi,
6807 size_t cs, size_t cn,
6808 struct pivot_table *pt,
6809 struct pivot_dimension *var_dimension)
6814 /* Is this a matrix for pooled data, either where there are no factor
6815 variables or the factor variables are missing? */
6816 bool pooled = !fn || vars_all_missing (rows[0], d, fs, fn);
6818 struct substring rowtype = case_ss (rows[0], rowtype_var);
6819 ss_rtrim (&rowtype, ss_cstr (" "));
6820 if (!stringi_set_is_empty (accepted_rowtypes)
6821 && !stringi_set_contains_len (accepted_rowtypes,
6822 rowtype.string, rowtype.length))
6825 const char *prefix = (ss_equals_case (rowtype, ss_cstr ("COV")) ? "CV"
6826 : ss_equals_case (rowtype, ss_cstr ("CORR")) ? "CR"
6827 : ss_equals_case (rowtype, ss_cstr ("MEAN")) ? "MN"
6828 : ss_equals_case (rowtype, ss_cstr ("STDDEV")) ? "SD"
6829 : ss_equals_case (rowtype, ss_cstr ("N")) ? "NC"
6830 : ss_equals_case (rowtype, ss_cstr ("COUNT")) ? "CN"
6834 msg (SE, _("Matrix data file contains unknown ROWTYPE_ \"%.*s\"."),
6835 (int) rowtype.length, rowtype.string);
6839 struct string name = DS_EMPTY_INITIALIZER;
6840 ds_put_cstr (&name, prefix);
6842 ds_put_format (&name, "F%zu", fi);
6844 ds_put_format (&name, "S%zu", si);
6846 struct matrix_var *mv = matrix_var_lookup (s, ds_ss (&name));
6848 mv = matrix_var_create (s, ds_ss (&name));
6851 msg (SW, _("Matrix data file contains variable with existing name %s."),
6853 goto exit_free_name;
6856 gsl_matrix *m = gsl_matrix_alloc (n_rows, cn);
6857 size_t n_missing = 0;
6858 for (size_t y = 0; y < n_rows; y++)
6860 for (size_t x = 0; x < cn; x++)
6862 struct variable *var = dict_get_var (d, cs + x);
6863 double value = case_num (rows[y], var);
6864 if (var_is_num_missing (var, value, MV_ANY))
6869 gsl_matrix_set (m, y, x, value);
6873 int var_index = pivot_category_create_leaf (
6874 var_dimension->root, pivot_value_new_user_text (ds_cstr (&name), SIZE_MAX));
6875 double values[] = { n_rows, cn };
6876 for (size_t j = 0; j < sn; j++)
6878 struct variable *var = dict_get_var (d, ss + j);
6879 const union value *value = case_data (rows[0], var);
6880 pivot_table_put2 (pt, j, var_index,
6881 pivot_value_new_var_value (var, value));
6883 for (size_t j = 0; j < fn; j++)
6885 struct variable *var = dict_get_var (d, fs + j);
6886 const union value sysmis = { .f = SYSMIS };
6887 const union value *value = pooled ? &sysmis : case_data (rows[0], var);
6888 pivot_table_put2 (pt, j + sn, var_index,
6889 pivot_value_new_var_value (var, value));
6891 for (size_t j = 0; j < sizeof values / sizeof *values; j++)
6892 pivot_table_put2 (pt, j + sn + fn, var_index,
6893 pivot_value_new_integer (values[j]));
6896 msg (SE, ngettext ("Matrix data file variable %s contains a missing "
6897 "value, which was treated as zero.",
6898 "Matrix data file variable %s contains %zu missing "
6899 "values, which were treated as zero.", n_missing),
6900 ds_cstr (&name), n_missing);
6907 for (size_t y = 0; y < n_rows; y++)
6908 case_unref (rows[y]);
6912 matrix_cmd_execute_mget__ (struct mget_command *mget,
6913 struct casereader *r, const struct dictionary *d)
6915 const struct variable *rowtype_ = get_a8_var (d, "ROWTYPE_");
6916 const struct variable *varname_ = get_a8_var (d, "VARNAME_");
6917 if (!rowtype_ || !varname_)
6920 if (var_get_dict_index (rowtype_) >= var_get_dict_index (varname_))
6922 msg (SE, _("ROWTYPE_ must precede VARNAME_ in matrix data file."));
6925 if (var_get_dict_index (varname_) + 1 >= dict_get_var_cnt (d))
6927 msg (SE, _("Matrix data file contains no continuous variables."));
6931 for (size_t i = 0; i < dict_get_var_cnt (d); i++)
6933 const struct variable *v = dict_get_var (d, i);
6934 if (v != rowtype_ && v != varname_ && var_get_width (v) != 0)
6937 _("Matrix data file contains unexpected string variable %s."),
6943 /* SPLIT variables. */
6945 size_t sn = var_get_dict_index (rowtype_);
6946 struct ccase *sc = NULL;
6949 /* FACTOR variables. */
6950 size_t fs = var_get_dict_index (rowtype_) + 1;
6951 size_t fn = var_get_dict_index (varname_) - var_get_dict_index (rowtype_) - 1;
6952 struct ccase *fc = NULL;
6955 /* Continuous variables. */
6956 size_t cs = var_get_dict_index (varname_) + 1;
6957 size_t cn = dict_get_var_cnt (d) - cs;
6958 struct ccase *cc = NULL;
6961 struct pivot_table *pt = pivot_table_create (
6962 N_("Matrix Variables Created by MGET"));
6963 struct pivot_dimension *attr_dimension = pivot_dimension_create (
6964 pt, PIVOT_AXIS_COLUMN, N_("Attribute"));
6965 struct pivot_dimension *var_dimension = pivot_dimension_create (
6966 pt, PIVOT_AXIS_ROW, N_("Variable"));
6969 struct pivot_category *splits = pivot_category_create_group (
6970 attr_dimension->root, N_("Split Values"));
6971 for (size_t i = 0; i < sn; i++)
6972 pivot_category_create_leaf (splits, pivot_value_new_variable (
6973 dict_get_var (d, ss + i)));
6977 struct pivot_category *factors = pivot_category_create_group (
6978 attr_dimension->root, N_("Factors"));
6979 for (size_t i = 0; i < fn; i++)
6980 pivot_category_create_leaf (factors, pivot_value_new_variable (
6981 dict_get_var (d, fs + i)));
6983 pivot_category_create_group (attr_dimension->root, N_("Dimensions"),
6984 N_("Rows"), N_("Columns"));
6987 struct ccase **rows = NULL;
6988 size_t allocated_rows = 0;
6992 while ((c = casereader_read (r)) != NULL)
6994 bool row_has_factors = fn && !vars_all_missing (c, d, fs, fn);
7004 = (sn && (!sc || vars_changed (sc, c, d, ss, sn)) ? SPLITS_CHANGED
7005 : fn && (!fc || vars_changed (fc, c, d, fs, fn)) ? FACTORS_CHANGED
7006 : !cc || var_changed (cc, c, rowtype_) ? ROWTYPE_CHANGED
7009 if (change != NOTHING_CHANGED)
7011 matrix_mget_commit_var (rows, n_rows, d,
7012 rowtype_, &mget->rowtypes,
7023 if (n_rows >= allocated_rows)
7024 rows = x2nrealloc (rows, &allocated_rows, sizeof *rows);
7027 if (change == SPLITS_CHANGED)
7033 /* Reset the factor number, if there are factors. */
7037 if (row_has_factors)
7043 else if (change == FACTORS_CHANGED)
7045 if (row_has_factors)
7051 matrix_mget_commit_var (rows, n_rows, d,
7052 rowtype_, &mget->rowtypes,
7064 if (var_dimension->n_leaves)
7065 pivot_table_submit (pt);
7067 pivot_table_unref (pt);
7071 matrix_cmd_execute_mget (struct mget_command *mget)
7073 struct casereader *r;
7074 struct dictionary *d;
7075 if (matrix_open_casereader ("MGET", mget->file, mget->encoding,
7076 mget->state->dataset, &r, &d))
7078 matrix_cmd_execute_mget__ (mget, r, d);
7079 matrix_close_casereader (mget->file, mget->state->dataset, r, d);
7084 matrix_parse_dst_var (struct matrix_state *s, struct matrix_var **varp)
7086 if (!lex_force_id (s->lexer))
7089 *varp = matrix_var_lookup (s, lex_tokss (s->lexer));
7091 *varp = matrix_var_create (s, lex_tokss (s->lexer));
7096 static struct matrix_cmd *
7097 matrix_parse_eigen (struct matrix_state *s)
7099 struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
7100 *cmd = (struct matrix_cmd) {
7102 .eigen = { .expr = NULL }
7105 struct eigen_command *eigen = &cmd->eigen;
7106 if (!lex_force_match (s->lexer, T_LPAREN))
7108 eigen->expr = matrix_parse_expr (s);
7110 || !lex_force_match (s->lexer, T_COMMA)
7111 || !matrix_parse_dst_var (s, &eigen->evec)
7112 || !lex_force_match (s->lexer, T_COMMA)
7113 || !matrix_parse_dst_var (s, &eigen->eval)
7114 || !lex_force_match (s->lexer, T_RPAREN))
7120 matrix_cmd_destroy (cmd);
7125 matrix_cmd_execute_eigen (struct eigen_command *eigen)
7127 gsl_matrix *A = matrix_expr_evaluate (eigen->expr);
7130 if (!is_symmetric (A))
7132 msg (SE, _("Argument of EIGEN must be symmetric."));
7133 gsl_matrix_free (A);
7137 gsl_eigen_symmv_workspace *w = gsl_eigen_symmv_alloc (A->size1);
7138 gsl_matrix *eval = gsl_matrix_alloc (A->size1, 1);
7139 gsl_vector v_eval = to_vector (eval);
7140 gsl_matrix *evec = gsl_matrix_alloc (A->size1, A->size2);
7141 gsl_eigen_symmv (A, &v_eval, evec, w);
7142 gsl_eigen_symmv_free (w);
7144 gsl_eigen_symmv_sort (&v_eval, evec, GSL_EIGEN_SORT_VAL_DESC);
7146 gsl_matrix_free (A);
7148 gsl_matrix_free (eigen->eval->value);
7149 eigen->eval->value = eval;
7151 gsl_matrix_free (eigen->evec->value);
7152 eigen->evec->value = evec;
7155 static struct matrix_cmd *
7156 matrix_parse_setdiag (struct matrix_state *s)
7158 struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
7159 *cmd = (struct matrix_cmd) {
7160 .type = MCMD_SETDIAG,
7161 .setdiag = { .dst = NULL }
7164 struct setdiag_command *setdiag = &cmd->setdiag;
7165 if (!lex_force_match (s->lexer, T_LPAREN) || !lex_force_id (s->lexer))
7168 setdiag->dst = matrix_var_lookup (s, lex_tokss (s->lexer));
7171 lex_error (s->lexer, _("Unknown variable %s."), lex_tokcstr (s->lexer));
7176 if (!lex_force_match (s->lexer, T_COMMA))
7179 setdiag->expr = matrix_parse_expr (s);
7183 if (!lex_force_match (s->lexer, T_RPAREN))
7189 matrix_cmd_destroy (cmd);
7194 matrix_cmd_execute_setdiag (struct setdiag_command *setdiag)
7196 gsl_matrix *dst = setdiag->dst->value;
7199 msg (SE, _("SETDIAG destination matrix %s is uninitialized."),
7200 setdiag->dst->name);
7204 gsl_matrix *src = matrix_expr_evaluate (setdiag->expr);
7208 size_t n = MIN (dst->size1, dst->size2);
7209 if (is_scalar (src))
7211 double d = to_scalar (src);
7212 for (size_t i = 0; i < n; i++)
7213 gsl_matrix_set (dst, i, i, d);
7215 else if (is_vector (src))
7217 gsl_vector v = to_vector (src);
7218 for (size_t i = 0; i < n && i < v.size; i++)
7219 gsl_matrix_set (dst, i, i, gsl_vector_get (&v, i));
7222 msg (SE, _("SETDIAG argument 2 must be a scalar or a vector, "
7223 "not a %zu×%zu matrix."),
7224 src->size1, src->size2);
7225 gsl_matrix_free (src);
7228 static struct matrix_cmd *
7229 matrix_parse_svd (struct matrix_state *s)
7231 struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
7232 *cmd = (struct matrix_cmd) {
7234 .svd = { .expr = NULL }
7237 struct svd_command *svd = &cmd->svd;
7238 if (!lex_force_match (s->lexer, T_LPAREN))
7240 svd->expr = matrix_parse_expr (s);
7242 || !lex_force_match (s->lexer, T_COMMA)
7243 || !matrix_parse_dst_var (s, &svd->u)
7244 || !lex_force_match (s->lexer, T_COMMA)
7245 || !matrix_parse_dst_var (s, &svd->s)
7246 || !lex_force_match (s->lexer, T_COMMA)
7247 || !matrix_parse_dst_var (s, &svd->v)
7248 || !lex_force_match (s->lexer, T_RPAREN))
7254 matrix_cmd_destroy (cmd);
7259 matrix_cmd_execute_svd (struct svd_command *svd)
7261 gsl_matrix *m = matrix_expr_evaluate (svd->expr);
7265 if (m->size1 >= m->size2)
7268 gsl_matrix *V = gsl_matrix_alloc (A->size2, A->size2);
7269 gsl_matrix *S = gsl_matrix_calloc (A->size2, A->size2);
7270 gsl_vector Sv = gsl_matrix_diagonal (S).vector;
7271 gsl_vector *work = gsl_vector_alloc (A->size2);
7272 gsl_linalg_SV_decomp (A, V, &Sv, work);
7273 gsl_vector_free (work);
7275 matrix_var_set (svd->u, A);
7276 matrix_var_set (svd->s, S);
7277 matrix_var_set (svd->v, V);
7281 gsl_matrix *At = gsl_matrix_alloc (m->size2, m->size1);
7282 gsl_matrix_transpose_memcpy (At, m);
7283 gsl_matrix_free (m);
7285 gsl_matrix *Vt = gsl_matrix_alloc (At->size2, At->size2);
7286 gsl_matrix *St = gsl_matrix_calloc (At->size2, At->size2);
7287 gsl_vector Stv = gsl_matrix_diagonal (St).vector;
7288 gsl_vector *work = gsl_vector_alloc (At->size2);
7289 gsl_linalg_SV_decomp (At, Vt, &Stv, work);
7290 gsl_vector_free (work);
7292 matrix_var_set (svd->v, At);
7293 matrix_var_set (svd->s, St);
7294 matrix_var_set (svd->u, Vt);
7299 matrix_cmd_execute (struct matrix_cmd *cmd)
7304 matrix_cmd_execute_compute (&cmd->compute);
7308 matrix_cmd_execute_print (&cmd->print);
7312 return matrix_cmd_execute_do_if (&cmd->do_if);
7315 matrix_cmd_execute_loop (&cmd->loop);
7322 matrix_cmd_execute_display (&cmd->display);
7326 matrix_cmd_execute_release (&cmd->release);
7330 matrix_cmd_execute_save (&cmd->save);
7334 matrix_cmd_execute_read (&cmd->read);
7338 matrix_cmd_execute_write (&cmd->write);
7342 matrix_cmd_execute_get (&cmd->get);
7346 matrix_cmd_execute_msave (&cmd->msave);
7350 matrix_cmd_execute_mget (&cmd->mget);
7354 matrix_cmd_execute_eigen (&cmd->eigen);
7358 matrix_cmd_execute_setdiag (&cmd->setdiag);
7362 matrix_cmd_execute_svd (&cmd->svd);
7370 matrix_cmds_uninit (struct matrix_cmds *cmds)
7372 for (size_t i = 0; i < cmds->n; i++)
7373 matrix_cmd_destroy (cmds->commands[i]);
7374 free (cmds->commands);
7378 matrix_cmd_destroy (struct matrix_cmd *cmd)
7386 matrix_lvalue_destroy (cmd->compute.lvalue);
7387 matrix_expr_destroy (cmd->compute.rvalue);
7391 matrix_expr_destroy (cmd->print.expression);
7392 free (cmd->print.title);
7393 print_labels_destroy (cmd->print.rlabels);
7394 print_labels_destroy (cmd->print.clabels);
7398 for (size_t i = 0; i < cmd->do_if.n_clauses; i++)
7400 matrix_expr_destroy (cmd->do_if.clauses[i].condition);
7401 matrix_cmds_uninit (&cmd->do_if.clauses[i].commands);
7403 free (cmd->do_if.clauses);
7407 matrix_expr_destroy (cmd->loop.start);
7408 matrix_expr_destroy (cmd->loop.end);
7409 matrix_expr_destroy (cmd->loop.increment);
7410 matrix_expr_destroy (cmd->loop.top_condition);
7411 matrix_expr_destroy (cmd->loop.bottom_condition);
7412 matrix_cmds_uninit (&cmd->loop.commands);
7422 free (cmd->release.vars);
7426 matrix_expr_destroy (cmd->save.expression);
7430 matrix_lvalue_destroy (cmd->read.dst);
7431 matrix_expr_destroy (cmd->read.size);
7435 matrix_expr_destroy (cmd->write.expression);
7436 free (cmd->write.format);
7440 matrix_lvalue_destroy (cmd->get.dst);
7441 fh_unref (cmd->get.file);
7442 free (cmd->get.encoding);
7443 var_syntax_destroy (cmd->get.vars, cmd->get.n_vars);
7447 matrix_expr_destroy (cmd->msave.expr);
7451 fh_unref (cmd->mget.file);
7452 stringi_set_destroy (&cmd->mget.rowtypes);
7456 matrix_expr_destroy (cmd->eigen.expr);
7460 matrix_expr_destroy (cmd->setdiag.expr);
7464 matrix_expr_destroy (cmd->svd.expr);
7470 struct matrix_command_name
7473 struct matrix_cmd *(*parse) (struct matrix_state *);
7476 static const struct matrix_command_name *
7477 matrix_parse_command_name (struct lexer *lexer)
7479 static const struct matrix_command_name commands[] = {
7480 { "COMPUTE", matrix_parse_compute },
7481 { "CALL EIGEN", matrix_parse_eigen },
7482 { "CALL SETDIAG", matrix_parse_setdiag },
7483 { "CALL SVD", matrix_parse_svd },
7484 { "PRINT", matrix_parse_print },
7485 { "DO IF", matrix_parse_do_if },
7486 { "LOOP", matrix_parse_loop },
7487 { "BREAK", matrix_parse_break },
7488 { "READ", matrix_parse_read },
7489 { "WRITE", matrix_parse_write },
7490 { "GET", matrix_parse_get },
7491 { "SAVE", matrix_parse_save },
7492 { "MGET", matrix_parse_mget },
7493 { "MSAVE", matrix_parse_msave },
7494 { "DISPLAY", matrix_parse_display },
7495 { "RELEASE", matrix_parse_release },
7497 static size_t n = sizeof commands / sizeof *commands;
7499 for (const struct matrix_command_name *c = commands; c < &commands[n]; c++)
7500 if (lex_match_phrase (lexer, c->name))
7505 static struct matrix_cmd *
7506 matrix_parse_command (struct matrix_state *s)
7508 size_t nesting_level = SIZE_MAX;
7510 struct matrix_cmd *c = NULL;
7511 const struct matrix_command_name *cmd = matrix_parse_command_name (s->lexer);
7513 lex_error (s->lexer, _("Unknown matrix command."));
7514 else if (!cmd->parse)
7515 lex_error (s->lexer, _("Matrix command %s is not yet implemented."),
7519 nesting_level = output_open_group (
7520 group_item_create_nocopy (utf8_to_title (cmd->name),
7521 utf8_to_title (cmd->name)));
7526 lex_end_of_command (s->lexer);
7527 lex_discard_rest_of_command (s->lexer);
7528 if (nesting_level != SIZE_MAX)
7529 output_close_groups (nesting_level);
7535 cmd_matrix (struct lexer *lexer, struct dataset *ds)
7537 if (!lex_force_match (lexer, T_ENDCMD))
7540 struct matrix_state state = {
7542 .session = dataset_session (ds),
7544 .vars = HMAP_INITIALIZER (state.vars),
7549 while (lex_match (lexer, T_ENDCMD))
7551 if (lex_token (lexer) == T_STOP)
7553 msg (SE, _("Unexpected end of input expecting matrix command."));
7557 if (lex_match_phrase (lexer, "END MATRIX"))
7560 struct matrix_cmd *c = matrix_parse_command (&state);
7563 matrix_cmd_execute (c);
7564 matrix_cmd_destroy (c);
7568 struct matrix_var *var, *next;
7569 HMAP_FOR_EACH_SAFE (var, next, struct matrix_var, hmap_node, &state.vars)
7572 gsl_matrix_free (var->value);
7573 hmap_delete (&state.vars, &var->hmap_node);
7576 hmap_destroy (&state.vars);
7577 msave_common_destroy (state.common);
7578 fh_unref (state.prev_read_file);
7579 for (size_t i = 0; i < state.n_read_files; i++)
7580 read_file_destroy (state.read_files[i]);
7581 free (state.read_files);
7582 fh_unref (state.prev_write_file);
7583 for (size_t i = 0; i < state.n_write_files; i++)
7584 write_file_destroy (state.write_files[i]);
7585 free (state.write_files);
7586 fh_unref (state.prev_save_file);
7587 for (size_t i = 0; i < state.n_save_files; i++)
7588 save_file_destroy (state.save_files[i]);
7589 free (state.save_files);