5214ee3d8be73b5b1c088cbe64ea659cb770cf18
[pspp] / src / language / stats / matrix.c
1 /* PSPP - a program for statistical analysis.
2    Copyright (C) 2021 Free Software Foundation, Inc.
3
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.
8
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.
13
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/>. */
16
17 #include <config.h>
18
19 #include <gsl/gsl_blas.h>
20 #include <gsl/gsl_eigen.h>
21 #include <gsl/gsl_linalg.h>
22 #include <gsl/gsl_matrix.h>
23 #include <gsl/gsl_permutation.h>
24 #include <gsl/gsl_randist.h>
25 #include <gsl/gsl_vector.h>
26 #include <limits.h>
27 #include <math.h>
28 #include <uniwidth.h>
29
30 #include "data/any-reader.h"
31 #include "data/any-writer.h"
32 #include "data/casereader.h"
33 #include "data/casewriter.h"
34 #include "data/data-in.h"
35 #include "data/data-out.h"
36 #include "data/dataset.h"
37 #include "data/dictionary.h"
38 #include "data/file-handle-def.h"
39 #include "language/command.h"
40 #include "language/data-io/data-reader.h"
41 #include "language/data-io/data-writer.h"
42 #include "language/data-io/file-handle.h"
43 #include "language/lexer/format-parser.h"
44 #include "language/lexer/lexer.h"
45 #include "language/lexer/variable-parser.h"
46 #include "libpspp/array.h"
47 #include "libpspp/assertion.h"
48 #include "libpspp/compiler.h"
49 #include "libpspp/hmap.h"
50 #include "libpspp/i18n.h"
51 #include "libpspp/misc.h"
52 #include "libpspp/str.h"
53 #include "libpspp/string-array.h"
54 #include "libpspp/stringi-set.h"
55 #include "libpspp/u8-line.h"
56 #include "math/random.h"
57 #include "output/driver.h"
58 #include "output/output-item.h"
59 #include "output/pivot-table.h"
60
61 #include "gl/c-ctype.h"
62 #include "gl/ftoastr.h"
63 #include "gl/minmax.h"
64 #include "gl/xsize.h"
65
66 #include "gettext.h"
67 #define _(msgid) gettext (msgid)
68 #define N_(msgid) (msgid)
69
70 struct matrix_var
71   {
72     struct hmap_node hmap_node;
73     char *name;
74     gsl_matrix *value;
75   };
76
77 struct msave_common
78   {
79     /* Configuration. */
80     struct file_handle *outfile;
81     struct string_array variables;
82     struct string_array fnames;
83     struct string_array snames;
84     bool has_factors;
85     bool has_splits;
86     size_t n_varnames;
87
88     /* Execution state. */
89     struct dictionary *dict;
90     struct casewriter *writer;
91   };
92
93 struct read_file
94   {
95     struct file_handle *file;
96     struct dfm_reader *reader;
97     char *encoding;
98   };
99
100 struct write_file
101   {
102     struct file_handle *file;
103     struct dfm_writer *writer;
104     char *encoding;
105     struct u8_line *held;
106   };
107
108 struct matrix_state
109   {
110     struct dataset *dataset;
111     struct session *session;
112     struct lexer *lexer;
113     struct hmap vars;
114     bool in_loop;
115     struct file_handle *prev_save_outfile;
116     struct msave_common *common;
117
118     struct file_handle *prev_read_file;
119     struct read_file **read_files;
120     size_t n_read_files;
121
122     struct file_handle *prev_write_file;
123     struct write_file **write_files;
124     size_t n_write_files;
125   };
126
127 static struct matrix_var *
128 matrix_var_lookup (struct matrix_state *s, struct substring name)
129 {
130   struct matrix_var *var;
131
132   HMAP_FOR_EACH_WITH_HASH (var, struct matrix_var, hmap_node,
133                            utf8_hash_case_substring (name, 0), &s->vars)
134     if (!utf8_sscasecmp (ss_cstr (var->name), name))
135       return var;
136
137   return NULL;
138 }
139
140 static struct matrix_var *
141 matrix_var_create (struct matrix_state *s, struct substring name)
142 {
143   struct matrix_var *var = xmalloc (sizeof *var);
144   *var = (struct matrix_var) { .name = ss_xstrdup (name) };
145   hmap_insert (&s->vars, &var->hmap_node, utf8_hash_case_substring (name, 0));
146   return var;
147 }
148
149 static void
150 matrix_var_set (struct matrix_var *var, gsl_matrix *value)
151 {
152   gsl_matrix_free (var->value);
153   var->value = value;
154 }
155 \f
156 #define MATRIX_FUNCTIONS \
157     F(ABS, m_m) \
158     F(ALL, d_m) \
159     F(ANY, d_m) \
160     F(ARSIN, m_m) \
161     F(ARTAN, m_m) \
162     F(BLOCK, m_any) \
163     F(CHOL, m_m) \
164     F(CMIN, m_m) \
165     F(CMAX, m_m) \
166     F(COS, m_m) \
167     F(CSSQ, m_m) \
168     F(CSUM, m_m) \
169     F(DESIGN, m_m) \
170     F(DET, d_m) \
171     F(DIAG, m_m) \
172     F(EVAL, m_m) \
173     F(EXP, m_m) \
174     F(GINV, m_m) \
175     F(GRADE, m_m) \
176     F(GSCH, m_m) \
177     F(IDENT, IDENT) \
178     F(INV, m_m) \
179     F(KRONEKER, m_mm) \
180     F(LG10, m_m) \
181     F(LN, m_m) \
182     F(MAGIC, m_d) \
183     F(MAKE, m_ddd) \
184     F(MDIAG, m_v) \
185     F(MMAX, d_m) \
186     F(MMIN, d_m) \
187     F(MOD, m_md) \
188     F(MSSQ, d_m) \
189     F(MSUM, d_m) \
190     F(NCOL, d_m) \
191     F(NROW, d_m) \
192     F(RANK, d_m) \
193     F(RESHAPE, m_mdd) \
194     F(RMAX, m_m) \
195     F(RMIN, m_m) \
196     F(RND, m_m) \
197     F(RNKORDER, m_m) \
198     F(RSSQ, m_m) \
199     F(RSUM, m_m) \
200     F(SIN, m_m) \
201     F(SOLVE, m_mm) \
202     F(SQRT, m_m) \
203     F(SSCP, m_m) \
204     F(SVAL, m_m) \
205     F(SWEEP, m_md) \
206     F(T, m_m) \
207     F(TRACE, d_m) \
208     F(TRANSPOS, m_m) \
209     F(TRUNC, m_m) \
210     F(UNIFORM, m_dd)
211
212 enum { m_d_MIN_ARGS = 1, m_d_MAX_ARGS = 1 };
213 enum { m_dd_MIN_ARGS = 2, m_dd_MAX_ARGS = 2 };
214 enum { m_ddd_MIN_ARGS = 3, m_ddd_MAX_ARGS = 3 };
215 enum { m_m_MIN_ARGS = 1, m_m_MAX_ARGS = 1 };
216 enum { m_md_MIN_ARGS = 2, m_md_MAX_ARGS = 2 };
217 enum { m_mdd_MIN_ARGS = 3, m_mdd_MAX_ARGS = 3 };
218 enum { m_mm_MIN_ARGS = 2, m_mm_MAX_ARGS = 2 };
219 enum { m_v_MIN_ARGS = 1, m_v_MAX_ARGS = 1 };
220 enum { d_m_MIN_ARGS = 1, d_m_MAX_ARGS = 1 };
221 enum { m_any_MIN_ARGS = 1, m_any_MAX_ARGS = INT_MAX };
222 enum { IDENT_MIN_ARGS = 1, IDENT_MAX_ARGS = 2 };
223
224 typedef gsl_matrix *matrix_proto_m_d (double);
225 typedef gsl_matrix *matrix_proto_m_dd (double, double);
226 typedef gsl_matrix *matrix_proto_m_ddd (double, double, double);
227 typedef gsl_matrix *matrix_proto_m_m (gsl_matrix *);
228 typedef gsl_matrix *matrix_proto_m_md (gsl_matrix *, double);
229 typedef gsl_matrix *matrix_proto_m_mdd (gsl_matrix *, double, double);
230 typedef gsl_matrix *matrix_proto_m_mm (gsl_matrix *, gsl_matrix *);
231 typedef gsl_matrix *matrix_proto_m_v (gsl_vector *);
232 typedef double matrix_proto_d_m (gsl_matrix *);
233 typedef gsl_matrix *matrix_proto_m_any (gsl_matrix *[], size_t n);
234 typedef gsl_matrix *matrix_proto_IDENT (double, double);
235
236 #define F(NAME, PROTOTYPE) static matrix_proto_##PROTOTYPE matrix_eval_##NAME;
237 MATRIX_FUNCTIONS
238 #undef F
239 \f
240 /* Matrix expressions. */
241
242 struct matrix_expr
243   {
244     enum matrix_op
245       {
246         /* Functions. */
247 #define F(NAME, PROTOTYPE) MOP_F_##NAME,
248         MATRIX_FUNCTIONS
249 #undef F
250
251         /* Elementwise and scalar arithmetic. */
252         MOP_NEGATE,             /* unary - */
253         MOP_ADD_ELEMS,          /* + */
254         MOP_SUB_ELEMS,          /* - */
255         MOP_MUL_ELEMS,          /* &* */
256         MOP_DIV_ELEMS,          /* / and &/ */
257         MOP_EXP_ELEMS,          /* &** */
258         MOP_SEQ,                /* a:b */
259         MOP_SEQ_BY,             /* a:b:c */
260
261         /* Matrix arithmetic. */
262         MOP_MUL_MAT,            /* * */
263         MOP_EXP_MAT,            /* ** */
264
265         /* Relational. */
266         MOP_GT,                 /* > */
267         MOP_GE,                 /* >= */
268         MOP_LT,                 /* < */
269         MOP_LE,                 /* <= */
270         MOP_EQ,                 /* = */
271         MOP_NE,                 /* <> */
272
273         /* Logical. */
274         MOP_NOT,                /* NOT */
275         MOP_AND,                /* AND */
276         MOP_OR,                 /* OR */
277         MOP_XOR,                /* XOR */
278
279         /* {}. */
280         MOP_PASTE_HORZ,         /* a, b, c, ... */
281         MOP_PASTE_VERT,         /* a; b; c; ... */
282         MOP_EMPTY,              /* {} */
283
284         /* Sub-matrices. */
285         MOP_VEC_INDEX,          /* x(y) */
286         MOP_VEC_ALL,            /* x(:) */
287         MOP_MAT_INDEX,          /* x(y,z) */
288         MOP_ROW_INDEX,          /* x(y,:) */
289         MOP_COL_INDEX,          /* x(:,z) */
290
291         /* Literals. */
292         MOP_NUMBER,
293         MOP_VARIABLE,
294
295         /* Oddball stuff. */
296         MOP_EOF,                /* EOF('file') */
297       }
298     op;
299
300     union
301       {
302         struct
303           {
304             struct matrix_expr **subs;
305             size_t n_subs;
306           };
307
308         double number;
309         struct matrix_var *variable;
310         struct read_file *eof;
311       };
312   };
313
314 static void
315 matrix_expr_destroy (struct matrix_expr *e)
316 {
317   if (!e)
318     return;
319
320   switch (e->op)
321     {
322 #define F(NAME, PROTOTYPE) case MOP_F_##NAME:
323 MATRIX_FUNCTIONS
324 #undef F
325     case MOP_NEGATE:
326     case MOP_ADD_ELEMS:
327     case MOP_SUB_ELEMS:
328     case MOP_MUL_ELEMS:
329     case MOP_DIV_ELEMS:
330     case MOP_EXP_ELEMS:
331     case MOP_SEQ:
332     case MOP_SEQ_BY:
333     case MOP_MUL_MAT:
334     case MOP_EXP_MAT:
335     case MOP_GT:
336     case MOP_GE:
337     case MOP_LT:
338     case MOP_LE:
339     case MOP_EQ:
340     case MOP_NE:
341     case MOP_NOT:
342     case MOP_AND:
343     case MOP_OR:
344     case MOP_XOR:
345     case MOP_EMPTY:
346     case MOP_PASTE_HORZ:
347     case MOP_PASTE_VERT:
348     case MOP_VEC_INDEX:
349     case MOP_VEC_ALL:
350     case MOP_MAT_INDEX:
351     case MOP_ROW_INDEX:
352     case MOP_COL_INDEX:
353       for (size_t i = 0; i < e->n_subs; i++)
354         matrix_expr_destroy (e->subs[i]);
355       free (e->subs);
356       break;
357
358     case MOP_NUMBER:
359     case MOP_VARIABLE:
360     case MOP_EOF:
361       break;
362     }
363   free (e);
364 }
365
366 static struct matrix_expr *
367 matrix_expr_create_subs (enum matrix_op op, struct matrix_expr **subs,
368                          size_t n_subs)
369 {
370   struct matrix_expr *e = xmalloc (sizeof *e);
371   *e = (struct matrix_expr) {
372     .op = op,
373     .subs = xmemdup (subs, n_subs * sizeof *subs),
374     .n_subs = n_subs
375   };
376   return e;
377 }
378
379 static struct matrix_expr *
380 matrix_expr_create_0 (enum matrix_op op)
381 {
382   struct matrix_expr *sub;
383   return matrix_expr_create_subs (op, &sub, 0);
384 }
385
386 static struct matrix_expr *
387 matrix_expr_create_1 (enum matrix_op op, struct matrix_expr *sub)
388 {
389   return matrix_expr_create_subs (op, &sub, 1);
390 }
391
392 static struct matrix_expr *
393 matrix_expr_create_2 (enum matrix_op op,
394                       struct matrix_expr *sub0, struct matrix_expr *sub1)
395 {
396   struct matrix_expr *subs[] = { sub0, sub1 };
397   return matrix_expr_create_subs (op, subs, sizeof subs / sizeof *subs);
398 }
399
400 static struct matrix_expr *
401 matrix_expr_create_3 (enum matrix_op op, struct matrix_expr *sub0,
402                       struct matrix_expr *sub1, struct matrix_expr *sub2)
403 {
404   struct matrix_expr *subs[] = { sub0, sub1, sub2 };
405   return matrix_expr_create_subs (op, subs, sizeof subs / sizeof *subs);
406 }
407
408 static struct matrix_expr *
409 matrix_expr_create_number (double number)
410 {
411   struct matrix_expr *e = xmalloc (sizeof *e);
412   *e = (struct matrix_expr) { .op = MOP_NUMBER, .number = number };
413   return e;
414 }
415
416 static struct matrix_expr *matrix_parse_or_xor (struct matrix_state *);
417
418 static struct matrix_expr *
419 matrix_parse_curly_comma (struct matrix_state *s)
420 {
421   struct matrix_expr *lhs = matrix_parse_or_xor (s);
422   if (!lhs)
423     return NULL;
424
425   while (lex_match (s->lexer, T_COMMA))
426     {
427       struct matrix_expr *rhs = matrix_parse_or_xor (s);
428       if (!rhs)
429         {
430           matrix_expr_destroy (lhs);
431           return NULL;
432         }
433       lhs = matrix_expr_create_2 (MOP_PASTE_HORZ, lhs, rhs);
434     }
435   return lhs;
436 }
437
438 static struct matrix_expr *
439 matrix_parse_curly_semi (struct matrix_state *s)
440 {
441   if (lex_token (s->lexer) == T_RCURLY)
442     return matrix_expr_create_0 (MOP_EMPTY);
443
444   struct matrix_expr *lhs = matrix_parse_curly_comma (s);
445   if (!lhs)
446     return NULL;
447
448   while (lex_match (s->lexer, T_SEMICOLON))
449     {
450       struct matrix_expr *rhs = matrix_parse_curly_comma (s);
451       if (!rhs)
452         {
453           matrix_expr_destroy (lhs);
454           return NULL;
455         }
456       lhs = matrix_expr_create_2 (MOP_PASTE_VERT, lhs, rhs);
457     }
458   return lhs;
459 }
460
461 #define MATRIX_FOR_ALL_ELEMENTS(D, Y, X, M)                     \
462   for (size_t Y = 0; Y < (M)->size1; Y++)                       \
463     for (size_t X = 0; X < (M)->size2; X++)                     \
464       for (double *D = gsl_matrix_ptr ((M), Y, X); D; D = NULL)
465
466 static bool
467 is_vector (const gsl_matrix *m)
468 {
469   return m->size1 <= 1 || m->size2 <= 1;
470 }
471
472 static gsl_vector
473 to_vector (gsl_matrix *m)
474 {
475   return (m->size1 == 1
476           ? gsl_matrix_row (m, 0).vector
477           : gsl_matrix_column (m, 0).vector);
478 }
479
480
481 static gsl_matrix *
482 matrix_eval_ABS (gsl_matrix *m)
483 {
484   MATRIX_FOR_ALL_ELEMENTS (d, y, x, m)
485     *d = fabs (*d);
486   return m;
487 }
488
489 static double
490 matrix_eval_ALL (gsl_matrix *m)
491 {
492   MATRIX_FOR_ALL_ELEMENTS (d, y, x, m)
493     if (*d == 0.0)
494       return 0.0;
495   return 1.0;
496 }
497
498 static double
499 matrix_eval_ANY (gsl_matrix *m)
500 {
501   MATRIX_FOR_ALL_ELEMENTS (d, y, x, m)
502     if (*d != 0.0)
503       return !.0;
504   return 0.0;
505 }
506
507 static gsl_matrix *
508 matrix_eval_ARSIN (gsl_matrix *m)
509 {
510   MATRIX_FOR_ALL_ELEMENTS (d, y, x, m)
511     *d = asin (*d);
512   return m;
513 }
514
515 static gsl_matrix *
516 matrix_eval_ARTAN (gsl_matrix *m)
517 {
518   MATRIX_FOR_ALL_ELEMENTS (d, y, x, m)
519     *d = atan (*d);
520   return m;
521 }
522
523 static gsl_matrix *
524 matrix_eval_BLOCK (gsl_matrix *m[], size_t n)
525 {
526   size_t r = 0;
527   size_t c = 0;
528   for (size_t i = 0; i < n; i++)
529     {
530       r += m[i]->size1;
531       c += m[i]->size2;
532     }
533   gsl_matrix *block = gsl_matrix_calloc (r, c);
534   r = c = 0;
535   for (size_t i = 0; i < n; i++)
536     {
537       for (size_t y = 0; y < m[i]->size1; y++)
538         for (size_t x = 0; x < m[i]->size2; x++)
539           gsl_matrix_set (block, r + y, c + x, gsl_matrix_get (m[i], y, x));
540       r += m[i]->size1;
541       c += m[i]->size2;
542     }
543   return block;
544 }
545
546 static gsl_matrix *
547 matrix_eval_CHOL (gsl_matrix *m)
548 {
549   if (!gsl_linalg_cholesky_decomp1 (m))
550     {
551       for (size_t y = 0; y < m->size1; y++)
552         for (size_t x = y + 1; x < m->size2; x++)
553           gsl_matrix_set (m, y, x, gsl_matrix_get (m, x, y));
554
555       for (size_t y = 0; y < m->size1; y++)
556         for (size_t x = 0; x < y; x++)
557           gsl_matrix_set (m, y, x, 0);
558       return m;
559     }
560   else
561     {
562       msg (SE, _("Input to CHOL function is not positive-definite."));
563       return NULL;
564     }
565 }
566
567 static gsl_matrix *
568 matrix_eval_col_extremum (gsl_matrix *m, bool min)
569 {
570   if (m->size1 <= 1)
571     return m;
572   else if (!m->size2)
573     return gsl_matrix_alloc (1, 0);
574
575   gsl_matrix *cext = gsl_matrix_alloc (1, m->size2);
576   for (size_t x = 0; x < m->size2; x++)
577     {
578       double ext = gsl_matrix_get (m, 0, x);
579       for (size_t y = 1; y < m->size1; y++)
580         {
581           double value = gsl_matrix_get (m, y, x);
582           if (min ? value < ext : value > ext)
583             ext = value;
584         }
585       gsl_matrix_set (cext, 0, x, ext);
586     }
587   return cext;
588 }
589
590 static gsl_matrix *
591 matrix_eval_CMAX (gsl_matrix *m)
592 {
593   return matrix_eval_col_extremum (m, false);
594 }
595
596 static gsl_matrix *
597 matrix_eval_CMIN (gsl_matrix *m)
598 {
599   return matrix_eval_col_extremum (m, true);
600 }
601
602 static gsl_matrix *
603 matrix_eval_COS (gsl_matrix *m)
604 {
605   MATRIX_FOR_ALL_ELEMENTS (d, y, x, m)
606     *d = cos (*d);
607   return m;
608 }
609
610 static gsl_matrix *
611 matrix_eval_col_sum (gsl_matrix *m, bool square)
612 {
613   if (m->size1 == 0)
614     return m;
615   else if (!m->size2)
616     return gsl_matrix_alloc (1, 0);
617
618   gsl_matrix *result = gsl_matrix_alloc (1, m->size2);
619   for (size_t x = 0; x < m->size2; x++)
620     {
621       double sum = 0;
622       for (size_t y = 0; y < m->size1; y++)
623         {
624           double d = gsl_matrix_get (m, y, x);
625           sum += square ? pow2 (d) : d;
626         }
627       gsl_matrix_set (result, 0, x, sum);
628     }
629   return result;
630 }
631
632 static gsl_matrix *
633 matrix_eval_CSSQ (gsl_matrix *m)
634 {
635   return matrix_eval_col_sum (m, true);
636 }
637
638 static gsl_matrix *
639 matrix_eval_CSUM (gsl_matrix *m)
640 {
641   return matrix_eval_col_sum (m, false);
642 }
643
644 static int
645 compare_double_3way (const void *a_, const void *b_)
646 {
647   const double *a = a_;
648   const double *b = b_;
649   return *a < *b ? -1 : *a > *b;
650 }
651
652 static gsl_matrix *
653 matrix_eval_DESIGN (gsl_matrix *m)
654 {
655   double *tmp = xmalloc (m->size1 * m->size2 * sizeof *tmp);
656   gsl_matrix m2 = gsl_matrix_view_array (tmp, m->size2, m->size1).matrix;
657   gsl_matrix_transpose_memcpy (&m2, m);
658
659   for (size_t y = 0; y < m2.size1; y++)
660     qsort (tmp + y * m2.size2, m2.size2, sizeof *tmp, compare_double_3way);
661
662   size_t *n = xcalloc (m2.size1, sizeof *n);
663   size_t n_total = 0;
664   for (size_t i = 0; i < m2.size1; i++)
665     {
666       double *row = tmp + m2.size2 * i;
667       for (size_t j = 0; j < m2.size2; )
668         {
669           size_t k;
670           for (k = j + 1; k < m2.size2; k++)
671             if (row[j] != row[k])
672               break;
673           row[n[i]++] = row[j];
674           j = k;
675         }
676
677       if (n[i] <= 1)
678         msg (MW, _("Column %zu in DESIGN argument has constant value."), i + 1);
679       else
680         n_total += n[i];
681     }
682
683   gsl_matrix *result = gsl_matrix_alloc (m->size1, n_total);
684   size_t x = 0;
685   for (size_t i = 0; i < m->size2; i++)
686     {
687       if (n[i] <= 1)
688         continue;
689
690       const double *unique = tmp + m2.size2 * i;
691       for (size_t j = 0; j < n[i]; j++, x++)
692         {
693           double value = unique[j];
694           for (size_t y = 0; y < m->size1; y++)
695             gsl_matrix_set (result, y, x, gsl_matrix_get (m, y, i) == value);
696         }
697     }
698
699   free (n);
700   free (tmp);
701
702   return result;
703 }
704
705 static double
706 matrix_eval_DET (gsl_matrix *m)
707 {
708   gsl_permutation *p = gsl_permutation_alloc (m->size1);
709   int signum;
710   gsl_linalg_LU_decomp (m, p, &signum);
711   gsl_permutation_free (p);
712   return gsl_linalg_LU_det (m, signum);
713 }
714
715 static gsl_matrix *
716 matrix_eval_DIAG (gsl_matrix *m)
717 {
718   gsl_matrix *diag = gsl_matrix_alloc (MIN (m->size1, m->size2), 1);
719   for (size_t i = 0; i < diag->size1; i++)
720     gsl_matrix_set (diag, i, 0, gsl_matrix_get (m, i, i));
721   return diag;
722 }
723
724 static bool
725 is_symmetric (const gsl_matrix *m)
726 {
727   if (m->size1 != m->size2)
728     return false;
729
730   for (size_t y = 0; y < m->size1; y++)
731     for (size_t x = 0; x < y; x++)
732       if (gsl_matrix_get (m, y, x) != gsl_matrix_get (m, x, y))
733         return false;
734
735   return true;
736 }
737
738 static int
739 compare_double_desc (const void *a_, const void *b_)
740 {
741   const double *a = a_;
742   const double *b = b_;
743   return *a > *b ? -1 : *a < *b;
744 }
745
746 static gsl_matrix *
747 matrix_eval_EVAL (gsl_matrix *m)
748 {
749   if (!is_symmetric (m))
750     {
751       msg (SE, _("Argument of EVAL must be symmetric."));
752       return NULL;
753     }
754
755   gsl_eigen_symm_workspace *w = gsl_eigen_symm_alloc (m->size1);
756   gsl_matrix *eval = gsl_matrix_alloc (m->size1, 1);
757   gsl_vector v_eval = to_vector (eval);
758   gsl_eigen_symm (m, &v_eval, w);
759   gsl_eigen_symm_free (w);
760
761   assert (v_eval.stride == 1);
762   qsort (v_eval.data, v_eval.size, sizeof *v_eval.data, compare_double_desc);
763
764   return eval;
765 }
766
767 static gsl_matrix *
768 matrix_eval_EXP (gsl_matrix *m)
769 {
770   MATRIX_FOR_ALL_ELEMENTS (d, y, x, m)
771     *d = exp (*d);
772   return m;
773 }
774
775 /* From https://gist.github.com/turingbirds/5e99656e08dbe1324c99, where it was
776    marked as:
777
778    Charl Linssen <charl@itfromb.it>
779    Feb 2016
780    PUBLIC DOMAIN */
781 static gsl_matrix *
782 matrix_eval_GINV (gsl_matrix *A)
783 {
784   size_t n = A->size1;
785   size_t m = A->size2;
786   bool swap = m > n;
787   gsl_matrix *tmp_mat = NULL;
788   if (swap)
789     {
790       /* libgsl SVD can only handle the case m <= n, so transpose matrix. */
791       tmp_mat = gsl_matrix_alloc (m, n);
792       gsl_matrix_transpose_memcpy (tmp_mat, A);
793       A = tmp_mat;
794       size_t i = m;
795       m = n;
796       n = i;
797     }
798
799   /* Do SVD. */
800   gsl_matrix *V = gsl_matrix_alloc (m, m);
801   gsl_vector *u = gsl_vector_alloc (m);
802
803   gsl_vector *tmp_vec = gsl_vector_alloc (m);
804   gsl_linalg_SV_decomp (A, V, u, tmp_vec);
805   gsl_vector_free (tmp_vec);
806
807   /* Compute Σ⁻¹. */
808   gsl_matrix *Sigma_pinv = gsl_matrix_alloc (m, n);
809   gsl_matrix_set_zero (Sigma_pinv);
810   double cutoff = 1e-15 * gsl_vector_max (u);
811
812   for (size_t i = 0; i < m; ++i)
813     {
814       double x = gsl_vector_get (u, i);
815       gsl_matrix_set (Sigma_pinv, i, i, x > cutoff ? 1.0 / x : 0);
816     }
817
818   /* libgsl SVD yields "thin" SVD - pad to full matrix by adding zeros */
819   gsl_matrix *U = gsl_matrix_calloc (n, n);
820   for (size_t i = 0; i < n; i++)
821     for (size_t j = 0; j < m; j++)
822       gsl_matrix_set (U, i, j, gsl_matrix_get (A, i, j));
823
824   /* two dot products to obtain pseudoinverse */
825   gsl_matrix *tmp_mat2 = gsl_matrix_alloc (m, n);
826   gsl_blas_dgemm (CblasNoTrans, CblasNoTrans, 1., V, Sigma_pinv, 0., tmp_mat2);
827
828   gsl_matrix *A_pinv;
829   if (swap)
830     {
831       A_pinv = gsl_matrix_alloc (n, m);
832       gsl_blas_dgemm (CblasNoTrans, CblasTrans, 1., U, tmp_mat2, 0., A_pinv);
833     }
834   else
835     {
836       A_pinv = gsl_matrix_alloc (m, n);
837       gsl_blas_dgemm (CblasNoTrans, CblasTrans, 1., tmp_mat2, U, 0., A_pinv);
838     }
839
840   gsl_matrix_free (tmp_mat);
841   gsl_matrix_free (tmp_mat2);
842   gsl_matrix_free (U);
843   gsl_matrix_free (Sigma_pinv);
844   gsl_vector_free (u);
845   gsl_matrix_free (V);
846
847   return A_pinv;
848 }
849
850 struct grade
851   {
852     size_t y, x;
853     double value;
854   };
855
856 static int
857 grade_compare_3way (const void *a_, const void *b_)
858 {
859   const struct grade *a = a_;
860   const struct grade *b = b_;
861
862   return (a->value < b->value ? -1
863           : a->value > b->value ? 1
864           : a->y < b->y ? -1
865           : a->y > b->y ? 1
866           : a->x < b->x ? -1
867           : a->x > b->x);
868 }
869
870 static gsl_matrix *
871 matrix_eval_GRADE (gsl_matrix *m)
872 {
873   size_t n = m->size1 * m->size2;
874   struct grade *grades = xmalloc (n * sizeof *grades);
875
876   size_t i = 0;
877   MATRIX_FOR_ALL_ELEMENTS (d, y, x, m)
878     grades[i++] = (struct grade) { .y = y, .x = x, .value = *d };
879   qsort (grades, n, sizeof *grades, grade_compare_3way);
880
881   for (size_t i = 0; i < n; i++)
882     gsl_matrix_set (m, grades[i].y, grades[i].x, i + 1);
883
884   free (grades);
885
886   return m;
887 }
888
889 static double
890 dot (gsl_vector *a, gsl_vector *b)
891 {
892   double result = 0.0;
893   for (size_t i = 0; i < a->size; i++)
894     result += gsl_vector_get (a, i) * gsl_vector_get (b, i);
895   return result;
896 }
897
898 static double
899 norm2 (gsl_vector *v)
900 {
901   double result = 0.0;
902   for (size_t i = 0; i < v->size; i++)
903     result += pow2 (gsl_vector_get (v, i));
904   return result;
905 }
906
907 static double
908 norm (gsl_vector *v)
909 {
910   return sqrt (norm2 (v));
911 }
912
913 static gsl_matrix *
914 matrix_eval_GSCH (gsl_matrix *v)
915 {
916   if (v->size2 < v->size1)
917     {
918       msg (SE, _("GSCH requires its argument to have at least as many columns "
919                  "as rows, but it has dimensions %zu×%zu."),
920            v->size1, v->size2);
921       return NULL;
922     }
923   if (!v->size1 || !v->size2)
924     return v;
925
926   gsl_matrix *u = gsl_matrix_calloc (v->size1, v->size2);
927   size_t ux = 0;
928   for (size_t vx = 0; vx < v->size2; vx++)
929     {
930       gsl_vector u_i = gsl_matrix_column (u, ux).vector;
931       gsl_vector v_i = gsl_matrix_column (v, vx).vector;
932
933       gsl_vector_memcpy (&u_i, &v_i);
934       for (size_t j = 0; j < ux; j++)
935         {
936           gsl_vector u_j = gsl_matrix_column (u, j).vector;
937           double scale = dot (&u_j, &u_i) / norm2 (&u_j);
938           for (size_t k = 0; k < u_i.size; k++)
939             gsl_vector_set (&u_i, k, (gsl_vector_get (&u_i, k)
940                                       - scale * gsl_vector_get (&u_j, k)));
941         }
942
943       double len = norm (&u_i);
944       if (len > 1e-15)
945         {
946           gsl_vector_scale (&u_i, 1.0 / len);
947           if (++ux >= v->size1)
948             break;
949         }
950     }
951
952   if (ux < v->size1)
953     {
954       msg (SE, _("%zu×%zu argument to GSCH contains only "
955                  "%zu linearly independent columns."),
956            v->size1, v->size2, ux);
957       gsl_matrix_free (u);
958       return NULL;
959     }
960
961   u->size2 = v->size1;
962   return u;
963 }
964
965 static gsl_matrix *
966 matrix_eval_IDENT (double s1, double s2)
967 {
968   if (s1 < 0 || s1 > SIZE_MAX || s2 < 0 || s2 > SIZE_MAX)
969     {
970       msg (SE, _("Arguments to IDENT must be non-negative integers."));
971       return NULL;
972     }
973
974   gsl_matrix *m = gsl_matrix_alloc (s1, s2);
975   MATRIX_FOR_ALL_ELEMENTS (d, y, x, m)
976     *d = x == y;
977   return m;
978 }
979
980 static void
981 invert_matrix (gsl_matrix *x)
982 {
983   gsl_permutation *p = gsl_permutation_alloc (x->size1);
984   int signum;
985   gsl_linalg_LU_decomp (x, p, &signum);
986   gsl_linalg_LU_invx (x, p);
987   gsl_permutation_free (p);
988 }
989
990 static gsl_matrix *
991 matrix_eval_INV (gsl_matrix *m)
992 {
993   invert_matrix (m);
994   return m;
995 }
996
997 static gsl_matrix *
998 matrix_eval_KRONEKER (gsl_matrix *a, gsl_matrix *b)
999 {
1000   gsl_matrix *k = gsl_matrix_alloc (a->size1 * b->size1,
1001                                     a->size2 * b->size2);
1002   size_t y = 0;
1003   for (size_t ar = 0; ar < a->size1; ar++)
1004     for (size_t br = 0; br < b->size1; br++, y++)
1005       {
1006         size_t x = 0;
1007         for (size_t ac = 0; ac < a->size2; ac++)
1008           for (size_t bc = 0; bc < b->size2; bc++, x++)
1009             {
1010               double av = gsl_matrix_get (a, ar, ac);
1011               double bv = gsl_matrix_get (b, br, bc);
1012               gsl_matrix_set (k, y, x, av * bv);
1013             }
1014       }
1015   return k;
1016 }
1017
1018 static gsl_matrix *
1019 matrix_eval_LG10 (gsl_matrix *m)
1020 {
1021   MATRIX_FOR_ALL_ELEMENTS (d, y, x, m)
1022     *d = log10 (*d);
1023   return m;
1024 }
1025
1026 static gsl_matrix *
1027 matrix_eval_LN (gsl_matrix *m)
1028 {
1029   MATRIX_FOR_ALL_ELEMENTS (d, y, x, m)
1030     *d = log (*d);
1031   return m;
1032 }
1033
1034 static void
1035 matrix_eval_MAGIC_odd (gsl_matrix *m, size_t n)
1036 {
1037   /* Siamese method: https://en.wikipedia.org/wiki/Siamese_method. */
1038   size_t y = 0;
1039   size_t x = n / 2;
1040   for (size_t i = 1; i <= n * n; i++)
1041     {
1042       gsl_matrix_set (m, y, x, i);
1043
1044       size_t y1 = !y ? n - 1 : y - 1;
1045       size_t x1 = x + 1 >= n ? 0 : x + 1;
1046       if (gsl_matrix_get (m, y1, x1) == 0)
1047         {
1048           y = y1;
1049           x = x1;
1050         }
1051       else
1052         y = y + 1 >= n ? 0 : y + 1;
1053     }
1054 }
1055
1056 static void
1057 magic_exchange (gsl_matrix *m, size_t y1, size_t x1, size_t y2, size_t x2)
1058 {
1059   double a = gsl_matrix_get (m, y1, x1);
1060   double b = gsl_matrix_get (m, y2, x2);
1061   gsl_matrix_set (m, y1, x1, b);
1062   gsl_matrix_set (m, y2, x2, a);
1063 }
1064
1065 static void
1066 matrix_eval_MAGIC_doubly_even (gsl_matrix *m, size_t n)
1067 {
1068   size_t x, y;
1069
1070   /* A. Umar, "On the Construction of Even Order Magic Squares",
1071      https://arxiv.org/ftp/arxiv/papers/1202/1202.0948.pdf. */
1072   x = y = 0;
1073   for (size_t i = 1; i <= n * n / 2; i++)
1074     {
1075       gsl_matrix_set (m, y, x, i);
1076       if (++y >= n)
1077         {
1078           y = 0;
1079           x++;
1080         }
1081     }
1082
1083   x = n - 1;
1084   y = 0;
1085   for (size_t i = n * n; i > n * n / 2; i--)
1086     {
1087       gsl_matrix_set (m, y, x, i);
1088       if (++y >= n)
1089         {
1090           y = 0;
1091           x--;
1092         }
1093     }
1094
1095   for (size_t y = 0; y < n; y++)
1096     for (size_t x = 0; x < n / 2; x++)
1097       {
1098         unsigned int d = gsl_matrix_get (m, y, x);
1099         if (d % 2 != (y < n / 2))
1100           magic_exchange (m, y, x, y, n - x - 1);
1101       }
1102
1103   size_t y1 = n / 2;
1104   size_t y2 = n - 1;
1105   size_t x1 = n / 2 - 1;
1106   size_t x2 = n / 2;
1107   magic_exchange (m, y1, x1, y2, x1);
1108   magic_exchange (m, y1, x2, y2, x2);
1109 }
1110
1111 static void
1112 matrix_eval_MAGIC_singly_even (gsl_matrix *m, size_t n)
1113 {
1114   /* A. Umar, "On the Construction of Even Order Magic Squares",
1115      https://arxiv.org/ftp/arxiv/papers/1202/1202.0948.pdf. */
1116   size_t x, y;
1117
1118   x = y = 0;
1119   for (size_t i = 1; ; i++)
1120     {
1121       gsl_matrix_set (m, y, x, i);
1122       if (++y == n / 2 - 1)
1123         y += 2;
1124       else if (y >= n)
1125         {
1126           y = 0;
1127           if (++x >= n / 2)
1128             break;
1129         }
1130     }
1131
1132   x = n - 1;
1133   y = 0;
1134   for (size_t i = n * n; ; i--)
1135     {
1136       gsl_matrix_set (m, y, x, i);
1137       if (++y == n / 2 - 1)
1138         y += 2;
1139       else if (y >= n)
1140         {
1141           y = 0;
1142           if (--x < n / 2)
1143             break;
1144         }
1145     }
1146   for (size_t y = 0; y < n; y++)
1147     if (y != n / 2 - 1 && y != n / 2)
1148       for (size_t x = 0; x < n / 2; x++)
1149         {
1150           unsigned int d = gsl_matrix_get (m, y, x);
1151           if (d % 2 != (y < n / 2))
1152             magic_exchange (m, y, x, y, n - x - 1);
1153         }
1154
1155   size_t a0 = (n * n - 2 * n) / 2 + 1;
1156   for (size_t i = 0; i < n / 2; i++)
1157     {
1158       size_t a = a0 + i;
1159       gsl_matrix_set (m, n / 2, i, a);
1160       gsl_matrix_set (m, n / 2 - 1, i, (n * n + 1) - a);
1161     }
1162   for (size_t i = 0; i < n / 2; i++)
1163     {
1164       size_t a = a0 + i + n / 2;
1165       gsl_matrix_set (m, n / 2 - 1, n - i - 1, a);
1166       gsl_matrix_set (m, n / 2, n - i - 1, (n * n + 1) - a);
1167     }
1168   for (size_t x = 1; x < n / 2; x += 2)
1169     magic_exchange (m, n / 2, x, n / 2 - 1, x);
1170   for (size_t x = n / 2 + 2; x <= n - 3; x += 2)
1171     magic_exchange (m, n / 2, x, n / 2 - 1, x);
1172   size_t x1 = n / 2 - 2;
1173   size_t x2 = n / 2 + 1;
1174   size_t y1 = n / 2 - 2;
1175   size_t y2 = n / 2 + 1;
1176   magic_exchange (m, y1, x1, y2, x1);
1177   magic_exchange (m, y1, x2, y2, x2);
1178 }
1179
1180 static gsl_matrix *
1181 matrix_eval_MAGIC (double n_)
1182 {
1183   if (n_ < 3 || n_ >= sqrt (SIZE_MAX))
1184     {
1185       msg (SE, _("MAGIC argument must be an integer 3 or greater."));
1186       return NULL;
1187     }
1188   size_t n = n_;
1189
1190   gsl_matrix *m = gsl_matrix_calloc (n, n);
1191   if (n % 2)
1192     matrix_eval_MAGIC_odd (m, n);
1193   else if (n % 4)
1194     matrix_eval_MAGIC_singly_even (m, n);
1195   else
1196     matrix_eval_MAGIC_doubly_even (m, n);
1197   return m;
1198 }
1199
1200 static gsl_matrix *
1201 matrix_eval_MAKE (double r, double c, double value)
1202 {
1203   if (r < 0 || r >= SIZE_MAX || c < 0 || c >= SIZE_MAX)
1204     {
1205       msg (SE, _("Size arguments to MAKE must be integers."));
1206       return NULL;
1207     }
1208
1209   gsl_matrix *m = gsl_matrix_alloc (r, c);
1210   MATRIX_FOR_ALL_ELEMENTS (d, y, x, m)
1211     *d = value;
1212   return m;
1213 }
1214
1215 static gsl_matrix *
1216 matrix_eval_MDIAG (gsl_vector *v)
1217 {
1218   gsl_matrix *m = gsl_matrix_calloc (v->size, v->size);
1219   gsl_vector diagonal = gsl_matrix_diagonal (m).vector;
1220   gsl_vector_memcpy (&diagonal, v);
1221   return m;
1222 }
1223
1224 static double
1225 matrix_eval_MMAX (gsl_matrix *m)
1226 {
1227   return gsl_matrix_max (m);
1228 }
1229
1230 static double
1231 matrix_eval_MMIN (gsl_matrix *m)
1232 {
1233   return gsl_matrix_min (m);
1234 }
1235
1236 static gsl_matrix *
1237 matrix_eval_MOD (gsl_matrix *m, double divisor)
1238 {
1239   if (divisor == 0.0)
1240     {
1241       msg (SE, _("Divisor argument to MOD function must be nonzero."));
1242       return NULL;
1243     }
1244
1245   MATRIX_FOR_ALL_ELEMENTS (d, y, x, m)
1246     *d = fmod (*d, divisor);
1247   return m;
1248 }
1249
1250 static double
1251 matrix_eval_MSSQ (gsl_matrix *m)
1252 {
1253   double mssq = 0.0;
1254   MATRIX_FOR_ALL_ELEMENTS (d, y, x, m)
1255     mssq += *d * *d;
1256   return mssq;
1257 }
1258
1259 static double
1260 matrix_eval_MSUM (gsl_matrix *m)
1261 {
1262   double msum = 0.0;
1263   MATRIX_FOR_ALL_ELEMENTS (d, y, x, m)
1264     msum += *d;
1265   return msum;
1266 }
1267
1268 static double
1269 matrix_eval_NCOL (gsl_matrix *m)
1270 {
1271   return m->size2;
1272 }
1273
1274 static double
1275 matrix_eval_NROW (gsl_matrix *m)
1276 {
1277   return m->size1;
1278 }
1279
1280 static double
1281 matrix_eval_RANK (gsl_matrix *m)
1282 {
1283   gsl_vector *tau = gsl_vector_alloc (MIN (m->size1, m->size2));
1284   gsl_linalg_QR_decomp (m, tau);
1285   gsl_vector_free (tau);
1286
1287   return gsl_linalg_QRPT_rank (m, -1);
1288 }
1289
1290 static gsl_matrix *
1291 matrix_eval_RESHAPE (gsl_matrix *m, double r_, double c_)
1292 {
1293   if (r_ < 0 || r_ >= SIZE_MAX || c_ < 0 || c_ >= SIZE_MAX)
1294     {
1295       msg (SE, _("Arguments 2 and 3 to RESHAPE must be integers."));
1296       return NULL;
1297     }
1298   size_t r = r_;
1299   size_t c = c_;
1300   if (size_overflow_p (xtimes (r, xmax (c, 1))) || c * r != m->size1 * m->size2)
1301     {
1302       msg (SE, _("Product of RESHAPE arguments 2 and 3 differ from "
1303                  "product of matrix dimensions."));
1304       return NULL;
1305     }
1306
1307   gsl_matrix *dst = gsl_matrix_alloc (r, c);
1308   size_t y1 = 0;
1309   size_t x1 = 0;
1310   MATRIX_FOR_ALL_ELEMENTS (d, y2, x2, m)
1311     {
1312       gsl_matrix_set (dst, y1, x1, *d);
1313       if (++x1 >= c)
1314         {
1315           x1 = 0;
1316           y1++;
1317         }
1318     }
1319   return dst;
1320 }
1321
1322 static gsl_matrix *
1323 matrix_eval_row_extremum (gsl_matrix *m, bool min)
1324 {
1325   if (m->size2 <= 1)
1326     return m;
1327   else if (!m->size1)
1328     return gsl_matrix_alloc (0, 1);
1329
1330   gsl_matrix *rext = gsl_matrix_alloc (m->size1, 1);
1331   for (size_t y = 0; y < m->size1; y++)
1332     {
1333       double ext = gsl_matrix_get (m, y, 0);
1334       for (size_t x = 1; x < m->size2; x++)
1335         {
1336           double value = gsl_matrix_get (m, y, x);
1337           if (min ? value < ext : value > ext)
1338             ext = value;
1339         }
1340       gsl_matrix_set (rext, y, 0, ext);
1341     }
1342   return rext;
1343 }
1344
1345 static gsl_matrix *
1346 matrix_eval_RMAX (gsl_matrix *m)
1347 {
1348   return matrix_eval_row_extremum (m, false);
1349 }
1350
1351 static gsl_matrix *
1352 matrix_eval_RMIN (gsl_matrix *m)
1353 {
1354   return matrix_eval_row_extremum (m, true);
1355 }
1356
1357 static gsl_matrix *
1358 matrix_eval_RND (gsl_matrix *m)
1359 {
1360   MATRIX_FOR_ALL_ELEMENTS (d, y, x, m)
1361     *d = rint (*d);
1362   return m;
1363 }
1364
1365 struct rank
1366   {
1367     size_t y, x;
1368     double value;
1369   };
1370
1371 static int
1372 rank_compare_3way (const void *a_, const void *b_)
1373 {
1374   const struct rank *a = a_;
1375   const struct rank *b = b_;
1376
1377   return a->value < b->value ? -1 : a->value > b->value;
1378 }
1379
1380 static gsl_matrix *
1381 matrix_eval_RNKORDER (gsl_matrix *m)
1382 {
1383   size_t n = m->size1 * m->size2;
1384   struct rank *ranks = xmalloc (n * sizeof *ranks);
1385   size_t i = 0;
1386   MATRIX_FOR_ALL_ELEMENTS (d, y, x, m)
1387     ranks[i++] = (struct rank) { .y = y, .x = x, .value = *d };
1388   qsort (ranks, n, sizeof *ranks, rank_compare_3way);
1389
1390   for (size_t i = 0; i < n; )
1391     {
1392       size_t j;
1393       for (j = i + 1; j < n; j++)
1394         if (ranks[i].value != ranks[j].value)
1395           break;
1396
1397       double rank = (i + j + 1.0) / 2.0;
1398       for (size_t k = i; k < j; k++)
1399         gsl_matrix_set (m, ranks[k].y, ranks[k].x, rank);
1400
1401       i = j;
1402     }
1403
1404   free (ranks);
1405
1406   return m;
1407 }
1408
1409 static gsl_matrix *
1410 matrix_eval_row_sum (gsl_matrix *m, bool square)
1411 {
1412   if (m->size1 == 0)
1413     return m;
1414   else if (!m->size1)
1415     return gsl_matrix_alloc (0, 1);
1416
1417   gsl_matrix *result = gsl_matrix_alloc (m->size1, 1);
1418   for (size_t y = 0; y < m->size1; y++)
1419     {
1420       double sum = 0;
1421       for (size_t x = 0; x < m->size2; x++)
1422         {
1423           double d = gsl_matrix_get (m, y, x);
1424           sum += square ? pow2 (d) : d;
1425         }
1426       gsl_matrix_set (result, y, 0, sum);
1427     }
1428   return result;
1429 }
1430
1431 static gsl_matrix *
1432 matrix_eval_RSSQ (gsl_matrix *m)
1433 {
1434   return matrix_eval_row_sum (m, true);
1435 }
1436
1437 static gsl_matrix *
1438 matrix_eval_RSUM (gsl_matrix *m)
1439 {
1440   return matrix_eval_row_sum (m, false);
1441 }
1442
1443 static gsl_matrix *
1444 matrix_eval_SIN (gsl_matrix *m)
1445 {
1446   MATRIX_FOR_ALL_ELEMENTS (d, y, x, m)
1447     *d = sin (*d);
1448   return m;
1449 }
1450
1451 static gsl_matrix *
1452 matrix_eval_SOLVE (gsl_matrix *m1, gsl_matrix *m2)
1453 {
1454   if (m1->size1 != m2->size1)
1455     {
1456       msg (SE, _("SOLVE requires its arguments to have the same number of "
1457                  "rows, but the first argument has dimensions %zu×%zu and "
1458                  "the second %zu×%zu."),
1459            m1->size1, m1->size2,
1460            m2->size1, m2->size2);
1461       return NULL;
1462     }
1463
1464   gsl_matrix *x = gsl_matrix_alloc (m2->size1, m2->size2);
1465   gsl_permutation *p = gsl_permutation_alloc (m1->size1);
1466   int signum;
1467   gsl_linalg_LU_decomp (m1, p, &signum);
1468   for (size_t i = 0; i < m2->size2; i++)
1469     {
1470       gsl_vector bi = gsl_matrix_column (m2, i).vector;
1471       gsl_vector xi = gsl_matrix_column (x, i).vector;
1472       gsl_linalg_LU_solve (m1, p, &bi, &xi);
1473     }
1474   gsl_permutation_free (p);
1475   return x;
1476 }
1477
1478 static gsl_matrix *
1479 matrix_eval_SQRT (gsl_matrix *m)
1480 {
1481   MATRIX_FOR_ALL_ELEMENTS (d, y, x, m)
1482     {
1483       if (*d < 0)
1484         {
1485           msg (SE, _("Argument to SQRT must be nonnegative."));
1486           return NULL;
1487         }
1488       *d = sqrt (*d);
1489     }
1490   return m;
1491 }
1492
1493 static gsl_matrix *
1494 matrix_eval_SSCP (gsl_matrix *m)
1495 {
1496   gsl_matrix *sscp = gsl_matrix_alloc (m->size2, m->size2);
1497   gsl_blas_dgemm (CblasTrans, CblasNoTrans, 1.0, m, m, 0.0, sscp);
1498   return sscp;
1499 }
1500
1501 static gsl_matrix *
1502 matrix_eval_SVAL (gsl_matrix *m)
1503 {
1504   gsl_matrix *tmp_mat = NULL;
1505   if (m->size2 > m->size1)
1506     {
1507       tmp_mat = gsl_matrix_alloc (m->size2, m->size1);
1508       gsl_matrix_transpose_memcpy (tmp_mat, m);
1509       m = tmp_mat;
1510     }
1511
1512   /* Do SVD. */
1513   gsl_matrix *V = gsl_matrix_alloc (m->size2, m->size2);
1514   gsl_vector *S = gsl_vector_alloc (m->size2);
1515   gsl_vector *work = gsl_vector_alloc (m->size2);
1516   gsl_linalg_SV_decomp (m, V, S, work);
1517
1518   gsl_matrix *vals = gsl_matrix_alloc (m->size2, 1);
1519   for (size_t i = 0; i < m->size2; i++)
1520     gsl_matrix_set (vals, i, 0, gsl_vector_get (S, i));
1521
1522   gsl_matrix_free (V);
1523   gsl_vector_free (S);
1524   gsl_vector_free (work);
1525   gsl_matrix_free (tmp_mat);
1526
1527   return vals;
1528 }
1529
1530 static gsl_matrix *
1531 matrix_eval_SWEEP (gsl_matrix *m, double d)
1532 {
1533   if (d < 1 || d > SIZE_MAX)
1534     {
1535       msg (SE, _("Scalar argument to SWEEP must be integer."));
1536       return NULL;
1537     }
1538   size_t k = d - 1;
1539   if (k >= MIN (m->size1, m->size2))
1540     {
1541       msg (SE, _("Scalar argument to SWEEP must be integer less than or "
1542                  "equal to the smaller of the matrix argument's rows and "
1543                  "columns."));
1544       return NULL;
1545     }
1546
1547   double m_kk = gsl_matrix_get (m, k, k);
1548   if (fabs (m_kk) > 1e-19)
1549     {
1550       gsl_matrix *a = gsl_matrix_alloc (m->size1, m->size2);
1551       MATRIX_FOR_ALL_ELEMENTS (a_ij, i, j, a)
1552         {
1553           double m_ij = gsl_matrix_get (m, i, j);
1554           double m_ik = gsl_matrix_get (m, i, k);
1555           double m_kj = gsl_matrix_get (m, k, j);
1556           *a_ij = (i != k && j != k ? m_ij * m_kk - m_ik * m_kj
1557                    : i != k ? -m_ik
1558                    : j != k ? m_kj
1559                    : 1.0) / m_kk;
1560         }
1561       return a;
1562     }
1563   else
1564     {
1565       for (size_t i = 0; i < m->size1; i++)
1566         {
1567           gsl_matrix_set (m, i, k, 0);
1568           gsl_matrix_set (m, k, i, 0);
1569         }
1570       return m;
1571     }
1572 }
1573
1574 static double
1575 matrix_eval_TRACE (gsl_matrix *m)
1576 {
1577   double sum = 0;
1578   size_t n = MIN (m->size1, m->size2);
1579   for (size_t i = 0; i < n; i++)
1580     sum += gsl_matrix_get (m, i, i);
1581   return sum;
1582 }
1583
1584 static gsl_matrix *
1585 matrix_eval_T (gsl_matrix *m)
1586 {
1587   return matrix_eval_TRANSPOS (m);
1588 }
1589
1590 static gsl_matrix *
1591 matrix_eval_TRANSPOS (gsl_matrix *m)
1592 {
1593   if (m->size1 == m->size2)
1594     {
1595       gsl_matrix_transpose (m);
1596       return m;
1597     }
1598   else
1599     {
1600       gsl_matrix *t = gsl_matrix_alloc (m->size2, m->size1);
1601       gsl_matrix_transpose_memcpy (t, m);
1602       return t;
1603     }
1604 }
1605
1606 static gsl_matrix *
1607 matrix_eval_TRUNC (gsl_matrix *m)
1608 {
1609   MATRIX_FOR_ALL_ELEMENTS (d, y, x, m)
1610     *d = trunc (*d);
1611   return m;
1612 }
1613
1614 static gsl_matrix *
1615 matrix_eval_UNIFORM (double r_, double c_)
1616 {
1617   if (r_ < 0 || r_ >= SIZE_MAX || c_ < 0 || c_ >= SIZE_MAX)
1618     {
1619       msg (SE, _("Arguments to UNIFORM must be integers."));
1620       return NULL;
1621     }
1622   size_t r = r_;
1623   size_t c = c_;
1624   if (size_overflow_p (xtimes (r, xmax (c, 1))))
1625     {
1626       msg (SE, _("Product of arguments to UNIFORM exceeds memory size."));
1627       return NULL;
1628     }
1629
1630   gsl_matrix *m = gsl_matrix_alloc (r, c);
1631   MATRIX_FOR_ALL_ELEMENTS (d, y, x, m)
1632     *d = gsl_ran_flat (get_rng (), 0, 1);
1633   return m;
1634 }
1635
1636 struct matrix_function
1637   {
1638     const char *name;
1639     enum matrix_op op;
1640     size_t min_args, max_args;
1641   };
1642
1643 static struct matrix_expr *matrix_parse_expr (struct matrix_state *);
1644
1645 static const struct matrix_function *
1646 matrix_parse_function_name (const char *token)
1647 {
1648   static const struct matrix_function functions[] =
1649     {
1650 #define F(NAME, PROTO) { #NAME, MOP_F_##NAME, PROTO##_MIN_ARGS, PROTO##_MAX_ARGS },
1651       MATRIX_FUNCTIONS
1652 #undef F
1653     };
1654   enum { N_FUNCTIONS = sizeof functions / sizeof *functions };
1655
1656   for (size_t i = 0; i < N_FUNCTIONS; i++)
1657     {
1658       if (lex_id_match_n (ss_cstr (functions[i].name), ss_cstr (token), 3))
1659         return &functions[i];
1660     }
1661   return NULL;
1662 }
1663
1664 static struct read_file *
1665 read_file_create (struct matrix_state *s, struct file_handle *fh)
1666 {
1667   for (size_t i = 0; i < s->n_read_files; i++)
1668     {
1669       struct read_file *rf = s->read_files[i];
1670       if (rf->file == fh)
1671         {
1672           fh_unref (fh);
1673           return rf;
1674         }
1675     }
1676
1677   struct read_file *rf = xmalloc (sizeof *rf);
1678   *rf = (struct read_file) { .file = fh };
1679
1680   s->read_files = xrealloc (s->read_files,
1681                             (s->n_read_files + 1) * sizeof *s->read_files);
1682   s->read_files[s->n_read_files++] = rf;
1683   return rf;
1684 }
1685
1686 static struct dfm_reader *
1687 read_file_open (struct read_file *rf)
1688 {
1689   if (!rf->reader)
1690     rf->reader = dfm_open_reader (rf->file, NULL, rf->encoding);
1691   return rf->reader;
1692 }
1693
1694 static void
1695 read_file_destroy (struct read_file *rf)
1696 {
1697   if (rf)
1698     {
1699       fh_unref (rf->file);
1700       dfm_close_reader (rf->reader);
1701       free (rf->encoding);
1702       free (rf);
1703     }
1704 }
1705
1706 static struct write_file *
1707 write_file_create (struct matrix_state *s, struct file_handle *fh)
1708 {
1709   for (size_t i = 0; i < s->n_write_files; i++)
1710     {
1711       struct write_file *wf = s->write_files[i];
1712       if (wf->file == fh)
1713         {
1714           fh_unref (fh);
1715           return wf;
1716         }
1717     }
1718
1719   struct write_file *wf = xmalloc (sizeof *wf);
1720   *wf = (struct write_file) { .file = fh };
1721
1722   s->write_files = xrealloc (s->write_files,
1723                              (s->n_write_files + 1) * sizeof *s->write_files);
1724   s->write_files[s->n_write_files++] = wf;
1725   return wf;
1726 }
1727
1728 static struct dfm_writer *
1729 write_file_open (struct write_file *wf)
1730 {
1731   if (!wf->writer)
1732     wf->writer = dfm_open_writer (wf->file, wf->encoding);
1733   return wf->writer;
1734 }
1735
1736 static void
1737 write_file_destroy (struct write_file *wf)
1738 {
1739   if (wf)
1740     {
1741       if (wf->held)
1742         {
1743           dfm_put_record_utf8 (wf->writer, wf->held->s.ss.string,
1744                                wf->held->s.ss.length);
1745           u8_line_destroy (wf->held);
1746           free (wf->held);
1747         }
1748
1749       fh_unref (wf->file);
1750       dfm_close_writer (wf->writer);
1751       free (wf->encoding);
1752       free (wf);
1753     }
1754 }
1755
1756 static bool
1757 matrix_parse_function (struct matrix_state *s, const char *token,
1758                        struct matrix_expr **exprp)
1759 {
1760   *exprp = NULL;
1761   if (lex_next_token (s->lexer, 1) != T_LPAREN)
1762     return false;
1763
1764   if (lex_match_id (s->lexer, "EOF"))
1765     {
1766       lex_get (s->lexer);
1767       struct file_handle *fh = fh_parse (s->lexer, FH_REF_FILE, s->session);
1768       if (!fh)
1769         return true;
1770
1771       if (!lex_force_match (s->lexer, T_RPAREN))
1772         {
1773           fh_unref (fh);
1774           return true;
1775         }
1776
1777       struct read_file *rf = read_file_create (s, fh);
1778
1779       struct matrix_expr *e = xmalloc (sizeof *e);
1780       *e = (struct matrix_expr) { .op = MOP_EOF, .eof = rf };
1781       *exprp = e;
1782       return true;
1783     }
1784
1785   const struct matrix_function *f = matrix_parse_function_name (token);
1786   if (!f)
1787     return false;
1788
1789   lex_get_n (s->lexer, 2);
1790
1791   struct matrix_expr *e = xmalloc (sizeof *e);
1792   *e = (struct matrix_expr) { .op = f->op, .subs = NULL };
1793
1794   size_t allocated_subs = 0;
1795   do
1796     {
1797       struct matrix_expr *sub = matrix_parse_expr (s);
1798       if (!sub)
1799         goto error;
1800
1801       if (e->n_subs >= allocated_subs)
1802         e->subs = x2nrealloc (e->subs, &allocated_subs, sizeof *e->subs);
1803       e->subs[e->n_subs++] = sub;
1804     }
1805   while (lex_match (s->lexer, T_COMMA));
1806   if (!lex_force_match (s->lexer, T_RPAREN))
1807     goto error;
1808
1809   *exprp = e;
1810   return true;
1811
1812 error:
1813   matrix_expr_destroy (e);
1814   return true;
1815 }
1816
1817 static struct matrix_expr *
1818 matrix_parse_primary (struct matrix_state *s)
1819 {
1820   if (lex_is_number (s->lexer))
1821     {
1822       double number = lex_number (s->lexer);
1823       lex_get (s->lexer);
1824       return matrix_expr_create_number (number);
1825     }
1826   else if (lex_is_string (s->lexer))
1827     {
1828       char string[sizeof (double)];
1829       buf_copy_str_rpad (string, sizeof string, lex_tokcstr (s->lexer), ' ');
1830       lex_get (s->lexer);
1831
1832       double number;
1833       memcpy (&number, string, sizeof number);
1834       return matrix_expr_create_number (number);
1835     }
1836   else if (lex_match (s->lexer, T_LPAREN))
1837     {
1838       struct matrix_expr *e = matrix_parse_or_xor (s);
1839       if (!e || !lex_force_match (s->lexer, T_RPAREN))
1840         {
1841           matrix_expr_destroy (e);
1842           return NULL;
1843         }
1844       return e;
1845     }
1846   else if (lex_match (s->lexer, T_LCURLY))
1847     {
1848       struct matrix_expr *e = matrix_parse_curly_semi (s);
1849       if (!e || !lex_force_match (s->lexer, T_RCURLY))
1850         {
1851           matrix_expr_destroy (e);
1852           return NULL;
1853         }
1854       return e;
1855     }
1856   else if (lex_token (s->lexer) == T_ID)
1857     {
1858       struct matrix_expr *retval;
1859       if (matrix_parse_function (s, lex_tokcstr (s->lexer), &retval))
1860         return retval;
1861
1862       struct matrix_var *var = matrix_var_lookup (s, lex_tokss (s->lexer));
1863       if (!var)
1864         {
1865           lex_error (s->lexer, _("Unknown variable %s."),
1866                      lex_tokcstr (s->lexer));
1867           return NULL;
1868         }
1869       lex_get (s->lexer);
1870
1871       struct matrix_expr *e = xmalloc (sizeof *e);
1872       *e = (struct matrix_expr) { .op = MOP_VARIABLE, .variable = var };
1873       return e;
1874     }
1875   else if (lex_token (s->lexer) == T_ALL)
1876     {
1877       struct matrix_expr *retval;
1878       if (matrix_parse_function (s, "ALL", &retval))
1879         return retval;
1880     }
1881
1882   lex_error (s->lexer, NULL);
1883   return NULL;
1884 }
1885
1886 static struct matrix_expr *matrix_parse_postfix (struct matrix_state *);
1887
1888 static bool
1889 matrix_parse_index_expr (struct matrix_state *s, struct matrix_expr **indexp)
1890 {
1891   if (lex_match (s->lexer, T_COLON))
1892     {
1893       *indexp = NULL;
1894       return true;
1895     }
1896   else
1897     {
1898       *indexp = matrix_parse_expr (s);
1899       return *indexp != NULL;
1900     }
1901 }
1902
1903 static struct matrix_expr *
1904 matrix_parse_postfix (struct matrix_state *s)
1905 {
1906   struct matrix_expr *lhs = matrix_parse_primary (s);
1907   if (!lhs || !lex_match (s->lexer, T_LPAREN))
1908     return lhs;
1909
1910   struct matrix_expr *i0;
1911   if (!matrix_parse_index_expr (s, &i0))
1912     {
1913       matrix_expr_destroy (lhs);
1914       return NULL;
1915     }
1916   if (lex_match (s->lexer, T_RPAREN))
1917     return (i0
1918             ? matrix_expr_create_2 (MOP_VEC_INDEX, lhs, i0)
1919             : matrix_expr_create_1 (MOP_VEC_ALL, lhs));
1920   else if (lex_match (s->lexer, T_COMMA))
1921     {
1922       struct matrix_expr *i1;
1923       if (!matrix_parse_index_expr (s, &i1)
1924           || !lex_force_match (s->lexer, T_RPAREN))
1925         {
1926           matrix_expr_destroy (lhs);
1927           matrix_expr_destroy (i0);
1928           matrix_expr_destroy (i1);
1929           return NULL;
1930         }
1931       return (i0 && i1 ? matrix_expr_create_3 (MOP_MAT_INDEX, lhs, i0, i1)
1932               : i0 ? matrix_expr_create_2 (MOP_ROW_INDEX, lhs, i0)
1933               : i1 ? matrix_expr_create_2 (MOP_COL_INDEX, lhs, i1)
1934               : lhs);
1935     }
1936   else
1937     {
1938       lex_error_expecting (s->lexer, "`)'", "`,'");
1939       return NULL;
1940     }
1941 }
1942
1943 static struct matrix_expr *
1944 matrix_parse_unary (struct matrix_state *s)
1945 {
1946   if (lex_match (s->lexer, T_DASH))
1947     {
1948       struct matrix_expr *lhs = matrix_parse_unary (s);
1949       return lhs ? matrix_expr_create_1 (MOP_NEGATE, lhs) : NULL;
1950     }
1951   else if (lex_match (s->lexer, T_PLUS))
1952     return matrix_parse_unary (s);
1953   else
1954     return matrix_parse_postfix (s);
1955 }
1956
1957 static struct matrix_expr *
1958 matrix_parse_seq (struct matrix_state *s)
1959 {
1960   struct matrix_expr *start = matrix_parse_unary (s);
1961   if (!start || !lex_match (s->lexer, T_COLON))
1962     return start;
1963
1964   struct matrix_expr *end = matrix_parse_unary (s);
1965   if (!end)
1966     {
1967       matrix_expr_destroy (start);
1968       return NULL;
1969     }
1970
1971   if (lex_match (s->lexer, T_COLON))
1972     {
1973       struct matrix_expr *increment = matrix_parse_unary (s);
1974       if (!increment)
1975         {
1976           matrix_expr_destroy (start);
1977           matrix_expr_destroy (end);
1978           return NULL;
1979         }
1980       return matrix_expr_create_3 (MOP_SEQ_BY, start, end, increment);
1981     }
1982   else
1983     return matrix_expr_create_2 (MOP_SEQ, start, end);
1984 }
1985
1986 static struct matrix_expr *
1987 matrix_parse_exp (struct matrix_state *s)
1988 {
1989   struct matrix_expr *lhs = matrix_parse_seq (s);
1990   if (!lhs)
1991     return NULL;
1992
1993   for (;;)
1994     {
1995       enum matrix_op op;
1996       if (lex_match (s->lexer, T_EXP))
1997         op = MOP_EXP_MAT;
1998       else if (lex_match_phrase (s->lexer, "&**"))
1999         op = MOP_EXP_ELEMS;
2000       else
2001         return lhs;
2002
2003       struct matrix_expr *rhs = matrix_parse_seq (s);
2004       if (!rhs)
2005         {
2006           matrix_expr_destroy (lhs);
2007           return NULL;
2008         }
2009       lhs = matrix_expr_create_2 (op, lhs, rhs);
2010     }
2011 }
2012
2013 static struct matrix_expr *
2014 matrix_parse_mul_div (struct matrix_state *s)
2015 {
2016   struct matrix_expr *lhs = matrix_parse_exp (s);
2017   if (!lhs)
2018     return NULL;
2019
2020   for (;;)
2021     {
2022       enum matrix_op op;
2023       if (lex_match (s->lexer, T_ASTERISK))
2024         op = MOP_MUL_MAT;
2025       else if (lex_match (s->lexer, T_SLASH))
2026         op = MOP_DIV_ELEMS;
2027       else if (lex_match_phrase (s->lexer, "&*"))
2028         op = MOP_MUL_ELEMS;
2029       else if (lex_match_phrase (s->lexer, "&/"))
2030         op = MOP_DIV_ELEMS;
2031       else
2032         return lhs;
2033
2034       struct matrix_expr *rhs = matrix_parse_exp (s);
2035       if (!rhs)
2036         {
2037           matrix_expr_destroy (lhs);
2038           return NULL;
2039         }
2040       lhs = matrix_expr_create_2 (op, lhs, rhs);
2041     }
2042 }
2043
2044 static struct matrix_expr *
2045 matrix_parse_add_sub (struct matrix_state *s)
2046 {
2047   struct matrix_expr *lhs = matrix_parse_mul_div (s);
2048   if (!lhs)
2049     return NULL;
2050
2051   for (;;)
2052     {
2053       enum matrix_op op;
2054       if (lex_match (s->lexer, T_PLUS))
2055         op = MOP_ADD_ELEMS;
2056       else if (lex_match (s->lexer, T_DASH))
2057         op = MOP_SUB_ELEMS;
2058       else if (lex_token (s->lexer) == T_NEG_NUM)
2059         op = MOP_ADD_ELEMS;
2060       else
2061         return lhs;
2062
2063       struct matrix_expr *rhs = matrix_parse_mul_div (s);
2064       if (!rhs)
2065         {
2066           matrix_expr_destroy (lhs);
2067           return NULL;
2068         }
2069       lhs = matrix_expr_create_2 (op, lhs, rhs);
2070     }
2071 }
2072
2073 static struct matrix_expr *
2074 matrix_parse_relational (struct matrix_state *s)
2075 {
2076   struct matrix_expr *lhs = matrix_parse_add_sub (s);
2077   if (!lhs)
2078     return NULL;
2079
2080   for (;;)
2081     {
2082       enum matrix_op op;
2083       if (lex_match (s->lexer, T_GT))
2084         op = MOP_GT;
2085       else if (lex_match (s->lexer, T_GE))
2086         op = MOP_GE;
2087       else if (lex_match (s->lexer, T_LT))
2088         op = MOP_LT;
2089       else if (lex_match (s->lexer, T_LE))
2090         op = MOP_LE;
2091       else if (lex_match (s->lexer, T_EQUALS) || lex_match (s->lexer, T_EQ))
2092         op = MOP_EQ;
2093       else if (lex_match (s->lexer, T_NE))
2094         op = MOP_NE;
2095       else
2096         return lhs;
2097
2098       struct matrix_expr *rhs = matrix_parse_add_sub (s);
2099       if (!rhs)
2100         {
2101           matrix_expr_destroy (lhs);
2102           return NULL;
2103         }
2104       lhs = matrix_expr_create_2 (op, lhs, rhs);
2105     }
2106 }
2107
2108 static struct matrix_expr *
2109 matrix_parse_not (struct matrix_state *s)
2110 {
2111   if (lex_match (s->lexer, T_NOT))
2112     {
2113       struct matrix_expr *lhs = matrix_parse_not (s);
2114       return lhs ? matrix_expr_create_1 (MOP_NOT, lhs) : NULL;
2115     }
2116   else
2117     return matrix_parse_relational (s);
2118 }
2119
2120 static struct matrix_expr *
2121 matrix_parse_and (struct matrix_state *s)
2122 {
2123   struct matrix_expr *lhs = matrix_parse_not (s);
2124   if (!lhs)
2125     return NULL;
2126
2127   while (lex_match (s->lexer, T_AND))
2128     {
2129       struct matrix_expr *rhs = matrix_parse_not (s);
2130       if (!rhs)
2131         {
2132           matrix_expr_destroy (lhs);
2133           return NULL;
2134         }
2135       lhs = matrix_expr_create_2 (MOP_AND, lhs, rhs);
2136     }
2137   return lhs;
2138 }
2139
2140 static struct matrix_expr *
2141 matrix_parse_or_xor (struct matrix_state *s)
2142 {
2143   struct matrix_expr *lhs = matrix_parse_and (s);
2144   if (!lhs)
2145     return NULL;
2146
2147   for (;;)
2148     {
2149       enum matrix_op op;
2150       if (lex_match (s->lexer, T_OR))
2151         op = MOP_OR;
2152       else if (lex_match_id (s->lexer, "XOR"))
2153         op = MOP_XOR;
2154       else
2155         return lhs;
2156
2157       struct matrix_expr *rhs = matrix_parse_and (s);
2158       if (!rhs)
2159         {
2160           matrix_expr_destroy (lhs);
2161           return NULL;
2162         }
2163       lhs = matrix_expr_create_2 (op, lhs, rhs);
2164     }
2165 }
2166
2167 static struct matrix_expr *
2168 matrix_parse_expr (struct matrix_state *s)
2169 {
2170   return matrix_parse_or_xor (s);
2171 }
2172 \f
2173 /* Expression evaluation. */
2174
2175 static double
2176 matrix_op_eval (enum matrix_op op, double a, double b)
2177 {
2178   switch (op)
2179     {
2180     case MOP_ADD_ELEMS: return a + b;
2181     case MOP_SUB_ELEMS: return a - b;
2182     case MOP_MUL_ELEMS: return a * b;
2183     case MOP_DIV_ELEMS: return a / b;
2184     case MOP_EXP_ELEMS: return pow (a, b);
2185     case MOP_GT: return a > b;
2186     case MOP_GE: return a >= b;
2187     case MOP_LT: return a < b;
2188     case MOP_LE: return a <= b;
2189     case MOP_EQ: return a == b;
2190     case MOP_NE: return a != b;
2191     case MOP_AND: return (a > 0) && (b > 0);
2192     case MOP_OR: return (a > 0) || (b > 0);
2193     case MOP_XOR: return (a > 0) != (b > 0);
2194
2195 #define F(NAME, PROTOTYPE) case MOP_F_##NAME:
2196       MATRIX_FUNCTIONS
2197 #undef F
2198     case MOP_NEGATE:
2199     case MOP_SEQ:
2200     case MOP_SEQ_BY:
2201     case MOP_MUL_MAT:
2202     case MOP_EXP_MAT:
2203     case MOP_NOT:
2204     case MOP_PASTE_HORZ:
2205     case MOP_PASTE_VERT:
2206     case MOP_EMPTY:
2207     case MOP_VEC_INDEX:
2208     case MOP_VEC_ALL:
2209     case MOP_MAT_INDEX:
2210     case MOP_ROW_INDEX:
2211     case MOP_COL_INDEX:
2212     case MOP_NUMBER:
2213     case MOP_VARIABLE:
2214     case MOP_EOF:
2215       NOT_REACHED ();
2216     }
2217   NOT_REACHED ();
2218 }
2219
2220 static const char *
2221 matrix_op_name (enum matrix_op op)
2222 {
2223   switch (op)
2224     {
2225     case MOP_ADD_ELEMS: return "+";
2226     case MOP_SUB_ELEMS: return "-";
2227     case MOP_MUL_ELEMS: return "&*";
2228     case MOP_DIV_ELEMS: return "&/";
2229     case MOP_EXP_ELEMS: return "&**";
2230     case MOP_GT: return ">";
2231     case MOP_GE: return ">=";
2232     case MOP_LT: return "<";
2233     case MOP_LE: return "<=";
2234     case MOP_EQ: return "=";
2235     case MOP_NE: return "<>";
2236     case MOP_AND: return "AND";
2237     case MOP_OR: return "OR";
2238     case MOP_XOR: return "XOR";
2239
2240 #define F(NAME, PROTOTYPE) case MOP_F_##NAME:
2241       MATRIX_FUNCTIONS
2242 #undef F
2243     case MOP_NEGATE:
2244     case MOP_SEQ:
2245     case MOP_SEQ_BY:
2246     case MOP_MUL_MAT:
2247     case MOP_EXP_MAT:
2248     case MOP_NOT:
2249     case MOP_PASTE_HORZ:
2250     case MOP_PASTE_VERT:
2251     case MOP_EMPTY:
2252     case MOP_VEC_INDEX:
2253     case MOP_VEC_ALL:
2254     case MOP_MAT_INDEX:
2255     case MOP_ROW_INDEX:
2256     case MOP_COL_INDEX:
2257     case MOP_NUMBER:
2258     case MOP_VARIABLE:
2259     case MOP_EOF:
2260       NOT_REACHED ();
2261     }
2262   NOT_REACHED ();
2263 }
2264
2265 static bool
2266 is_scalar (const gsl_matrix *m)
2267 {
2268   return m->size1 == 1 && m->size2 == 1;
2269 }
2270
2271 static double
2272 to_scalar (const gsl_matrix *m)
2273 {
2274   assert (is_scalar (m));
2275   return gsl_matrix_get (m, 0, 0);
2276 }
2277
2278 static gsl_matrix *
2279 matrix_expr_evaluate_elementwise (enum matrix_op op,
2280                                   gsl_matrix *a, gsl_matrix *b)
2281 {
2282   if (is_scalar (b))
2283     {
2284       double be = to_scalar (b);
2285       for (size_t r = 0; r < a->size1; r++)
2286         for (size_t c = 0; c < a->size2; c++)
2287           {
2288             double *ae = gsl_matrix_ptr (a, r, c);
2289             *ae = matrix_op_eval (op, *ae, be);
2290           }
2291       return a;
2292     }
2293   else if (is_scalar (a))
2294     {
2295       double ae = to_scalar (a);
2296       for (size_t r = 0; r < b->size1; r++)
2297         for (size_t c = 0; c < b->size2; c++)
2298           {
2299             double *be = gsl_matrix_ptr (b, r, c);
2300             *be = matrix_op_eval (op, ae, *be);
2301           }
2302       return b;
2303     }
2304   else if (a->size1 == b->size1 && a->size2 == b->size2)
2305     {
2306       for (size_t r = 0; r < a->size1; r++)
2307         for (size_t c = 0; c < a->size2; c++)
2308           {
2309             double *ae = gsl_matrix_ptr (a, r, c);
2310             double be = gsl_matrix_get (b, r, c);
2311             *ae = matrix_op_eval (op, *ae, be);
2312           }
2313       return a;
2314     }
2315   else
2316     {
2317       msg (SE, _("Operands to %s must have the same dimensions or one "
2318                  "must be a scalar, not %zu×%zu and %zu×%zu matrices."),
2319            matrix_op_name (op), a->size1, a->size2, b->size1, b->size2);
2320       return NULL;
2321     }
2322 }
2323
2324 static gsl_matrix *
2325 matrix_expr_evaluate_mul_mat (gsl_matrix *a, gsl_matrix *b)
2326 {
2327   if (is_scalar (a) || is_scalar (b))
2328     return matrix_expr_evaluate_elementwise (MOP_MUL_ELEMS, a, b);
2329
2330   if (a->size2 != b->size1)
2331     {
2332       msg (SE, _("Matrices with dimensions %zu×%zu and %zu×%zu are "
2333                  "not conformable for multiplication."),
2334            a->size1, a->size2, b->size1, b->size2);
2335       return NULL;
2336     }
2337
2338   gsl_matrix *c = gsl_matrix_alloc (a->size1, b->size2);
2339   gsl_blas_dgemm (CblasNoTrans, CblasNoTrans, 1.0, a, b, 0.0, c);
2340   return c;
2341 }
2342
2343 static void
2344 swap_matrix (gsl_matrix **a, gsl_matrix **b)
2345 {
2346   gsl_matrix *tmp = *a;
2347   *a = *b;
2348   *b = tmp;
2349 }
2350
2351 static void
2352 mul_matrix (gsl_matrix **z, const gsl_matrix *x, const gsl_matrix *y,
2353             gsl_matrix **tmp)
2354 {
2355   gsl_blas_dgemm (CblasNoTrans, CblasNoTrans, 1.0, x, y, 0.0, *tmp);
2356   swap_matrix (z, tmp);
2357 }
2358
2359 static void
2360 square_matrix (gsl_matrix **x, gsl_matrix **tmp)
2361 {
2362   mul_matrix (x, *x, *x, tmp);
2363 }
2364
2365 static gsl_matrix *
2366 matrix_expr_evaluate_exp_mat (gsl_matrix *x_, gsl_matrix *b)
2367 {
2368   gsl_matrix *x = x_;
2369   if (x->size1 != x->size2)
2370     {
2371       msg (SE, _("Matrix exponentation with ** requires a square matrix on "
2372                  "the left-hand size, not one with dimensions %zu×%zu."),
2373            x->size1, x->size2);
2374       return NULL;
2375     }
2376   if (!is_scalar (b))
2377     {
2378       msg (SE, _("Matrix exponentiation with ** requires a scalar on the "
2379                  "right-hand side, not a matrix with dimensions %zu×%zu."),
2380            b->size1, b->size2);
2381       return NULL;
2382     }
2383   double bf = to_scalar (b);
2384   if (bf != floor (bf) || bf <= LONG_MIN || bf > LONG_MAX)
2385     {
2386       msg (SE, _("Exponent %.1f in matrix multiplication is non-integer "
2387                  "or outside the valid range."), bf);
2388       return NULL;
2389     }
2390   long int bl = bf;
2391
2392   gsl_matrix *y_ = gsl_matrix_alloc (x->size1, x->size2);
2393   gsl_matrix *y = y_;
2394   gsl_matrix_set_identity (y);
2395   if (bl == 0)
2396     return y;
2397
2398   gsl_matrix *t_ = gsl_matrix_alloc (x->size1, x->size2);
2399   gsl_matrix *t = t_;
2400   for (unsigned long int n = labs (bl); n > 1; n /= 2)
2401     if (n & 1)
2402       {
2403         mul_matrix (&y, x, y, &t);
2404         square_matrix (&x, &t);
2405       }
2406     else
2407       square_matrix (&x, &t);
2408
2409   mul_matrix (&y, x, y, &t);
2410   if (bf < 0)
2411     invert_matrix (y);
2412
2413   /* Garbage collection.
2414
2415      There are three matrices: 'x_', 'y_', and 't_', and 'x', 'y', and 't' are
2416      a permutation of them.  We are returning one of them; that one must not be
2417      destroyed.  We must not destroy 'x_' because the caller owns it. */
2418   if (y != y_)
2419     gsl_matrix_free (y_);
2420   if (y != t_)
2421     gsl_matrix_free (t_);
2422
2423   return y;
2424 }
2425
2426 static gsl_matrix *
2427 matrix_expr_evaluate_seq (gsl_matrix *start_, gsl_matrix *end_,
2428                           gsl_matrix *by_)
2429 {
2430   if (!is_scalar (start_) || !is_scalar (end_) || (by_ && !is_scalar (by_)))
2431     {
2432       msg (SE, _("All operands of : operator must be scalars."));
2433       return NULL;
2434     }
2435
2436   long int start = to_scalar (start_);
2437   long int end = to_scalar (end_);
2438   long int by = by_ ? to_scalar (by_) : 1;
2439
2440   if (!by)
2441     {
2442       msg (SE, _("The increment operand to : must be nonzero."));
2443       return NULL;
2444     }
2445
2446   long int n = (end >= start && by > 0 ? (end - start + by) / by
2447                 : end <= start && by < 0 ? (start - end - by) / -by
2448                 : 0);
2449   gsl_matrix *m = gsl_matrix_alloc (1, n);
2450   for (long int i = 0; i < n; i++)
2451     gsl_matrix_set (m, 0, i, start + i * by);
2452   return m;
2453 }
2454
2455 static gsl_matrix *
2456 matrix_expr_evaluate_not (gsl_matrix *a)
2457 {
2458   for (size_t r = 0; r < a->size1; r++)
2459     for (size_t c = 0; c < a->size2; c++)
2460       {
2461         double *ae = gsl_matrix_ptr (a, r, c);
2462         *ae = !(*ae > 0);
2463       }
2464   return a;
2465 }
2466
2467 static gsl_matrix *
2468 matrix_expr_evaluate_paste_horz (gsl_matrix *a, gsl_matrix *b)
2469 {
2470   if (a->size1 != b->size1)
2471     {
2472       if (!a->size1 || !a->size2)
2473         return b;
2474       else if (!b->size1 || !b->size2)
2475         return a;
2476
2477       msg (SE, _("All columns in a matrix must have the same number of rows, "
2478                  "but this tries to paste matrices with %zu and %zu rows."),
2479            a->size1, b->size1);
2480       return NULL;
2481     }
2482
2483   gsl_matrix *c = gsl_matrix_alloc (a->size1, a->size2 + b->size2);
2484   for (size_t y = 0; y < a->size1; y++)
2485     {
2486       for (size_t x = 0; x < a->size2; x++)
2487         gsl_matrix_set (c, y, x, gsl_matrix_get (a, y, x));
2488       for (size_t x = 0; x < b->size2; x++)
2489         gsl_matrix_set (c, y, x + a->size2, gsl_matrix_get (b, y, x));
2490     }
2491   return c;
2492 }
2493
2494 static gsl_matrix *
2495 matrix_expr_evaluate_paste_vert (gsl_matrix *a, gsl_matrix *b)
2496 {
2497   if (a->size2 != b->size2)
2498     {
2499       if (!a->size1 || !a->size2)
2500         return b;
2501       else if (!b->size1 || !b->size2)
2502         return a;
2503
2504       msg (SE, _("All rows in a matrix must have the same number of columns, "
2505                  "but this tries to stack matrices with %zu and %zu columns."),
2506            a->size2, b->size2);
2507       return NULL;
2508     }
2509
2510   gsl_matrix *c = gsl_matrix_alloc (a->size1 + b->size1, a->size2);
2511   for (size_t x = 0; x < a->size2; x++)
2512     {
2513       for (size_t y = 0; y < a->size1; y++)
2514         gsl_matrix_set (c, y, x, gsl_matrix_get (a, y, x));
2515       for (size_t y = 0; y < b->size1; y++)
2516         gsl_matrix_set (c, y + a->size1, x, gsl_matrix_get (b, y, x));
2517     }
2518   return c;
2519 }
2520
2521 static gsl_vector *
2522 matrix_to_vector (gsl_matrix *m)
2523 {
2524   assert (m->owner);
2525   gsl_vector v = to_vector (m);
2526   assert (v.block == m->block || !v.block);
2527   assert (!v.owner);
2528   v.owner = 1;
2529   m->owner = 0;
2530   return xmemdup (&v, sizeof v);
2531 }
2532
2533 enum index_type {
2534   IV_ROW,
2535   IV_COLUMN,
2536   IV_VECTOR
2537 };
2538
2539 struct index_vector
2540   {
2541     size_t *indexes;
2542     size_t n;
2543   };
2544 #define INDEX_VECTOR_INIT (struct index_vector) { .n = 0 }
2545
2546 static bool
2547 matrix_normalize_index_vector (const gsl_matrix *m, size_t size,
2548                                enum index_type index_type, size_t other_size,
2549                                struct index_vector *iv)
2550 {
2551   if (m)
2552     {
2553       if (!is_vector (m))
2554         {
2555           switch (index_type)
2556             {
2557             case IV_VECTOR:
2558               msg (SE, _("Vector index must be scalar or vector, not a "
2559                          "%zu×%zu matrix."),
2560                    m->size1, m->size2);
2561               break;
2562
2563             case IV_ROW:
2564               msg (SE, _("Matrix row index must be scalar or vector, not a "
2565                          "%zu×%zu matrix."),
2566                    m->size1, m->size2);
2567               break;
2568
2569             case IV_COLUMN:
2570               msg (SE, _("Matrix column index must be scalar or vector, not a "
2571                          "%zu×%zu matrix."),
2572                    m->size1, m->size2);
2573               break;
2574             }
2575           return false;
2576         }
2577
2578       gsl_vector v = to_vector (CONST_CAST (gsl_matrix *, m));
2579       *iv = (struct index_vector) {
2580         .indexes = xnmalloc (v.size, sizeof *iv->indexes),
2581         .n = v.size,
2582       };
2583       for (size_t i = 0; i < v.size; i++)
2584         {
2585           double index = gsl_vector_get (&v, i);
2586           if (index < 1 || index >= size + 1)
2587             {
2588               switch (index_type)
2589                 {
2590                 case IV_VECTOR:
2591                   msg (SE, _("Index %g is out of range for vector "
2592                              "with %zu elements."), index, size);
2593                   break;
2594
2595                 case IV_ROW:
2596                   msg (SE, _("%g is not a valid row index for "
2597                              "a %zu×%zu matrix."),
2598                        index, size, other_size);
2599                   break;
2600
2601                 case IV_COLUMN:
2602                   msg (SE, _("%g is not a valid column index for "
2603                              "a %zu×%zu matrix."),
2604                        index, other_size, size);
2605                   break;
2606                 }
2607
2608               free (iv->indexes);
2609               return false;
2610             }
2611           iv->indexes[i] = index - 1;
2612         }
2613       return true;
2614     }
2615   else
2616     {
2617       *iv = (struct index_vector) {
2618         .indexes = xnmalloc (size, sizeof *iv->indexes),
2619         .n = size,
2620       };
2621       for (size_t i = 0; i < size; i++)
2622         iv->indexes[i] = i;
2623       return true;
2624     }
2625 }
2626
2627 static gsl_matrix *
2628 matrix_expr_evaluate_vec_all (gsl_matrix *sm)
2629 {
2630   if (!is_vector (sm))
2631     {
2632       msg (SE, _("Vector index operator may not be applied to "
2633                  "a %zu×%zu matrix."),
2634            sm->size1, sm->size2);
2635       return NULL;
2636     }
2637
2638   return sm;
2639 }
2640
2641 static gsl_matrix *
2642 matrix_expr_evaluate_vec_index (gsl_matrix *sm, gsl_matrix *im)
2643 {
2644   if (!matrix_expr_evaluate_vec_all (sm))
2645     return NULL;
2646
2647   gsl_vector sv = to_vector (sm);
2648   struct index_vector iv;
2649   if (!matrix_normalize_index_vector (im, sv.size, IV_VECTOR, 0, &iv))
2650     return NULL;
2651
2652   gsl_matrix *dm = gsl_matrix_alloc (sm->size1 == 1 ? 1 : iv.n,
2653                                      sm->size1 == 1 ? iv.n : 1);
2654   gsl_vector dv = to_vector (dm);
2655   for (size_t dx = 0; dx < iv.n; dx++)
2656     {
2657       size_t sx = iv.indexes[dx];
2658       gsl_vector_set (&dv, dx, gsl_vector_get (&sv, sx));
2659     }
2660   free (iv.indexes);
2661
2662   return dm;
2663 }
2664
2665 static gsl_matrix *
2666 matrix_expr_evaluate_mat_index (gsl_matrix *sm, gsl_matrix *im0,
2667                                 gsl_matrix *im1)
2668 {
2669   struct index_vector iv0;
2670   if (!matrix_normalize_index_vector (im0, sm->size1, IV_ROW, sm->size2, &iv0))
2671     return NULL;
2672
2673   struct index_vector iv1;
2674   if (!matrix_normalize_index_vector (im1, sm->size2, IV_COLUMN, sm->size1,
2675                                       &iv1))
2676     {
2677       free (iv0.indexes);
2678       return NULL;
2679     }
2680
2681   gsl_matrix *dm = gsl_matrix_alloc (iv0.n, iv1.n);
2682   for (size_t dy = 0; dy < iv0.n; dy++)
2683     {
2684       size_t sy = iv0.indexes[dy];
2685
2686       for (size_t dx = 0; dx < iv1.n; dx++)
2687         {
2688           size_t sx = iv1.indexes[dx];
2689           gsl_matrix_set (dm, dy, dx, gsl_matrix_get (sm, sy, sx));
2690         }
2691     }
2692   free (iv0.indexes);
2693   free (iv1.indexes);
2694   return dm;
2695 }
2696
2697 #define F(NAME, PROTOTYPE)                              \
2698   static gsl_matrix *matrix_expr_evaluate_##PROTOTYPE ( \
2699     const char *name, gsl_matrix *[], size_t,           \
2700     matrix_proto_##PROTOTYPE *);
2701 MATRIX_FUNCTIONS
2702 #undef F
2703
2704 static bool
2705 check_scalar_arg (const char *name, gsl_matrix *subs[], size_t index)
2706 {
2707   if (!is_scalar (subs[index]))
2708     {
2709       msg (SE, _("Function %s argument %zu must be a scalar, "
2710                  "not a %zu×%zu matrix."),
2711            name, index + 1, subs[index]->size1, subs[index]->size2);
2712       return false;
2713     }
2714   return true;
2715 }
2716
2717 static bool
2718 check_vector_arg (const char *name, gsl_matrix *subs[], size_t index)
2719 {
2720   if (!is_vector (subs[index]))
2721     {
2722       msg (SE, _("Function %s argument %zu must be a vector, "
2723                  "not a %zu×%zu matrix."),
2724            name, index + 1, subs[index]->size1, subs[index]->size2);
2725       return false;
2726     }
2727   return true;
2728 }
2729
2730 static bool
2731 to_scalar_args (const char *name, gsl_matrix *subs[], size_t n_subs, double d[])
2732 {
2733   for (size_t i = 0; i < n_subs; i++)
2734     {
2735       if (!check_scalar_arg (name, subs, i))
2736         return false;
2737       d[i] = to_scalar (subs[i]);
2738     }
2739   return true;
2740 }
2741
2742 static gsl_matrix *
2743 matrix_expr_evaluate_m_d (const char *name,
2744                           gsl_matrix *subs[], size_t n_subs,
2745                           matrix_proto_m_d *f)
2746 {
2747   assert (n_subs == 1);
2748
2749   double d;
2750   return to_scalar_args (name, subs, n_subs, &d) ? f(d) : NULL;
2751 }
2752
2753 static gsl_matrix *
2754 matrix_expr_evaluate_m_dd (const char *name,
2755                            gsl_matrix *subs[], size_t n_subs,
2756                            matrix_proto_m_dd *f)
2757 {
2758   assert (n_subs == 2);
2759
2760   double d[2];
2761   return to_scalar_args (name, subs, n_subs, d) ? f(d[0], d[1]) : NULL;
2762 }
2763
2764 static gsl_matrix *
2765 matrix_expr_evaluate_m_ddd (const char *name,
2766                            gsl_matrix *subs[], size_t n_subs,
2767                            matrix_proto_m_ddd *f)
2768 {
2769   assert (n_subs == 3);
2770
2771   double d[3];
2772   return to_scalar_args (name, subs, n_subs, d) ? f(d[0], d[1], d[2]) : NULL;
2773 }
2774
2775 static gsl_matrix *
2776 matrix_expr_evaluate_m_m (const char *name UNUSED,
2777                           gsl_matrix *subs[], size_t n_subs,
2778                           matrix_proto_m_m *f)
2779 {
2780   assert (n_subs == 1);
2781   return f (subs[0]);
2782 }
2783
2784 static gsl_matrix *
2785 matrix_expr_evaluate_m_md (const char *name UNUSED,
2786                            gsl_matrix *subs[], size_t n_subs,
2787                            matrix_proto_m_md *f)
2788 {
2789   assert (n_subs == 2);
2790   if (!check_scalar_arg (name, subs, 1))
2791     return NULL;
2792   return f (subs[0], to_scalar (subs[1]));
2793 }
2794
2795 static gsl_matrix *
2796 matrix_expr_evaluate_m_mdd (const char *name UNUSED,
2797                             gsl_matrix *subs[], size_t n_subs,
2798                             matrix_proto_m_mdd *f)
2799 {
2800   assert (n_subs == 3);
2801   if (!check_scalar_arg (name, subs, 1) || !check_scalar_arg (name, subs, 2))
2802     return NULL;
2803   return f (subs[0], to_scalar (subs[1]), to_scalar (subs[2]));
2804 }
2805
2806 static gsl_matrix *
2807 matrix_expr_evaluate_m_mm (const char *name UNUSED,
2808                            gsl_matrix *subs[], size_t n_subs,
2809                            matrix_proto_m_mm *f)
2810 {
2811   assert (n_subs == 2);
2812   return f (subs[0], subs[1]);
2813 }
2814
2815 static gsl_matrix *
2816 matrix_expr_evaluate_m_v (const char *name,
2817                           gsl_matrix *subs[], size_t n_subs,
2818                           matrix_proto_m_v *f)
2819 {
2820   assert (n_subs == 1);
2821   if (!check_vector_arg (name, subs, 0))
2822     return NULL;
2823   gsl_vector v = to_vector (subs[0]);
2824   return f (&v);
2825 }
2826
2827 static gsl_matrix *
2828 matrix_expr_evaluate_d_m (const char *name UNUSED,
2829                           gsl_matrix *subs[], size_t n_subs,
2830                           matrix_proto_d_m *f)
2831 {
2832   assert (n_subs == 1);
2833
2834   gsl_matrix *m = gsl_matrix_alloc (1, 1);
2835   gsl_matrix_set (m, 0, 0, f (subs[0]));
2836   return m;
2837 }
2838
2839 static gsl_matrix *
2840 matrix_expr_evaluate_m_any (const char *name UNUSED,
2841                           gsl_matrix *subs[], size_t n_subs,
2842                           matrix_proto_m_any *f)
2843 {
2844   return f (subs, n_subs);
2845 }
2846
2847 static gsl_matrix *
2848 matrix_expr_evaluate_IDENT (const char *name,
2849                             gsl_matrix *subs[], size_t n_subs,
2850                             matrix_proto_IDENT *f)
2851 {
2852   assert (n_subs <= 2);
2853
2854   double d[2];
2855   if (!to_scalar_args (name, subs, n_subs, d))
2856     return NULL;
2857
2858   return f (d[0], d[n_subs - 1]);
2859 }
2860
2861 static gsl_matrix *
2862 matrix_expr_evaluate (const struct matrix_expr *e)
2863 {
2864   if (e->op == MOP_NUMBER)
2865     {
2866       gsl_matrix *m = gsl_matrix_alloc (1, 1);
2867       gsl_matrix_set (m, 0, 0, e->number);
2868       return m;
2869     }
2870   else if (e->op == MOP_VARIABLE)
2871     {
2872       const gsl_matrix *src = e->variable->value;
2873       if (!src)
2874         {
2875           msg (SE, _("Uninitialized variable %s used in expression."),
2876                e->variable->name);
2877           return NULL;
2878         }
2879
2880       gsl_matrix *dst = gsl_matrix_alloc (src->size1, src->size2);
2881       gsl_matrix_memcpy (dst, src);
2882       return dst;
2883     }
2884   else if (e->op == MOP_EOF)
2885     {
2886       struct dfm_reader *reader = read_file_open (e->eof);
2887       gsl_matrix *m = gsl_matrix_alloc (1, 1);
2888       gsl_matrix_set (m, 0, 0, !reader || dfm_eof (reader));
2889       return m;
2890     }
2891
2892   enum { N_LOCAL = 3 };
2893   gsl_matrix *local_subs[N_LOCAL];
2894   gsl_matrix **subs = (e->n_subs < N_LOCAL
2895                        ? local_subs
2896                        : xmalloc (e->n_subs * sizeof *subs));
2897
2898   for (size_t i = 0; i < e->n_subs; i++)
2899     {
2900       subs[i] = matrix_expr_evaluate (e->subs[i]);
2901       if (!subs[i])
2902         {
2903           for (size_t j = 0; j < i; j++)
2904             gsl_matrix_free (subs[j]);
2905           if (subs != local_subs)
2906             free (subs);
2907           return NULL;
2908         }
2909     }
2910
2911   gsl_matrix *result = NULL;
2912   switch (e->op)
2913     {
2914 #define F(NAME, PROTOTYPE)                                              \
2915       case MOP_F_##NAME:                                                \
2916         result = matrix_expr_evaluate_##PROTOTYPE (#NAME,               \
2917                                                    subs, e->n_subs,     \
2918                                                    matrix_eval_##NAME); \
2919       break;
2920       MATRIX_FUNCTIONS
2921 #undef F
2922
2923     case MOP_NEGATE:
2924       gsl_matrix_scale (subs[0], -1.0);
2925       result = subs[0];
2926       break;
2927
2928     case MOP_ADD_ELEMS:
2929     case MOP_SUB_ELEMS:
2930     case MOP_MUL_ELEMS:
2931     case MOP_DIV_ELEMS:
2932     case MOP_EXP_ELEMS:
2933     case MOP_GT:
2934     case MOP_GE:
2935     case MOP_LT:
2936     case MOP_LE:
2937     case MOP_EQ:
2938     case MOP_NE:
2939     case MOP_AND:
2940     case MOP_OR:
2941     case MOP_XOR:
2942       result = matrix_expr_evaluate_elementwise (e->op, subs[0], subs[1]);
2943       break;
2944
2945     case MOP_NOT:
2946       result = matrix_expr_evaluate_not (subs[0]);
2947       break;
2948
2949     case MOP_SEQ:
2950       result = matrix_expr_evaluate_seq (subs[0], subs[1], NULL);
2951       break;
2952
2953     case MOP_SEQ_BY:
2954       result = matrix_expr_evaluate_seq (subs[0], subs[1], subs[2]);
2955       break;
2956
2957     case MOP_MUL_MAT:
2958       result = matrix_expr_evaluate_mul_mat (subs[0], subs[1]);
2959       break;
2960
2961     case MOP_EXP_MAT:
2962       result = matrix_expr_evaluate_exp_mat (subs[0], subs[1]);
2963       break;
2964
2965     case MOP_PASTE_HORZ:
2966       result = matrix_expr_evaluate_paste_horz (subs[0], subs[1]);
2967       break;
2968
2969     case MOP_PASTE_VERT:
2970       result = matrix_expr_evaluate_paste_vert (subs[0], subs[1]);
2971       break;
2972
2973     case MOP_EMPTY:
2974       result = gsl_matrix_alloc (0, 0);
2975       break;
2976
2977     case MOP_VEC_INDEX:
2978       result = matrix_expr_evaluate_vec_index (subs[0], subs[1]);
2979       break;
2980
2981     case MOP_VEC_ALL:
2982       result = matrix_expr_evaluate_vec_all (subs[0]);
2983       break;
2984
2985     case MOP_MAT_INDEX:
2986       result = matrix_expr_evaluate_mat_index (subs[0], subs[1], subs[2]);
2987       break;
2988
2989     case MOP_ROW_INDEX:
2990       result = matrix_expr_evaluate_mat_index (subs[0], subs[1], NULL);
2991       break;
2992
2993     case MOP_COL_INDEX:
2994       result = matrix_expr_evaluate_mat_index (subs[0], NULL, subs[1]);
2995       break;
2996
2997     case MOP_NUMBER:
2998     case MOP_VARIABLE:
2999     case MOP_EOF:
3000       NOT_REACHED ();
3001     }
3002
3003   for (size_t i = 0; i < e->n_subs; i++)
3004     if (subs[i] != result)
3005       gsl_matrix_free (subs[i]);
3006   if (subs != local_subs)
3007     free (subs);
3008   return result;
3009 }
3010
3011 static bool
3012 matrix_expr_evaluate_scalar (const struct matrix_expr *e, const char *context,
3013                              double *d)
3014 {
3015   gsl_matrix *m = matrix_expr_evaluate (e);
3016   if (!m)
3017     return false;
3018
3019   if (!is_scalar (m))
3020     {
3021       msg (SE, _("Expression for %s must evaluate to scalar, "
3022                  "not a %zu×%zu matrix."),
3023            context, m->size1, m->size2);
3024       gsl_matrix_free (m);
3025       return false;
3026     }
3027
3028   *d = to_scalar (m);
3029   gsl_matrix_free (m);
3030   return true;
3031 }
3032
3033 static bool
3034 matrix_expr_evaluate_integer (const struct matrix_expr *e, const char *context,
3035                               long int *integer)
3036 {
3037   double d;
3038   if (!matrix_expr_evaluate_scalar (e, context, &d))
3039     return false;
3040
3041   d = trunc (d);
3042   if (d < LONG_MIN || d > LONG_MAX)
3043     {
3044       msg (SE, _("Expression for %s is outside the integer range."), context);
3045       return false;
3046     }
3047   *integer = d;
3048   return true;
3049 }
3050 \f
3051 struct matrix_lvalue
3052   {
3053     struct matrix_var *var;
3054     struct matrix_expr *indexes[2];
3055     size_t n_indexes;
3056   };
3057
3058 static void
3059 matrix_lvalue_destroy (struct matrix_lvalue *lvalue)
3060 {
3061   if (lvalue)
3062     {
3063       for (size_t i = 0; i < lvalue->n_indexes; i++)
3064         matrix_expr_destroy (lvalue->indexes[i]);
3065       free (lvalue);
3066     }
3067 }
3068
3069 static struct matrix_lvalue *
3070 matrix_lvalue_parse (struct matrix_state *s)
3071 {
3072   struct matrix_lvalue *lvalue = xzalloc (sizeof *lvalue);
3073   if (!lex_force_id (s->lexer))
3074     goto error;
3075   lvalue->var = matrix_var_lookup (s, lex_tokss (s->lexer));
3076   if (lex_next_token (s->lexer, 1) == T_LPAREN)
3077     {
3078       if (!lvalue->var)
3079         {
3080           msg (SE, _("Undefined variable %s."), lex_tokcstr (s->lexer));
3081           free (lvalue);
3082           return NULL;
3083         }
3084
3085       lex_get_n (s->lexer, 2);
3086
3087       if (!matrix_parse_index_expr (s, &lvalue->indexes[0]))
3088         goto error;
3089       lvalue->n_indexes++;
3090
3091       if (lex_match (s->lexer, T_COMMA))
3092         {
3093           if (!matrix_parse_index_expr (s, &lvalue->indexes[1]))
3094             goto error;
3095           lvalue->n_indexes++;
3096         }
3097       if (!lex_force_match (s->lexer, T_RPAREN))
3098         goto error;
3099     }
3100   else
3101     {
3102       if (!lvalue->var)
3103         lvalue->var = matrix_var_create (s, lex_tokss (s->lexer));
3104       lex_get (s->lexer);
3105     }
3106   return lvalue;
3107
3108 error:
3109   matrix_lvalue_destroy (lvalue);
3110   return NULL;
3111 }
3112
3113 static bool
3114 matrix_lvalue_evaluate_vector (struct matrix_expr *e, size_t size,
3115                                enum index_type index_type, size_t other_size,
3116                                struct index_vector *iv)
3117 {
3118   gsl_matrix *m;
3119   if (e)
3120     {
3121       m = matrix_expr_evaluate (e);
3122       if (!m)
3123         return false;
3124     }
3125   else
3126     m = NULL;
3127
3128   bool ok = matrix_normalize_index_vector (m, size, index_type,
3129                                            other_size, iv);
3130   gsl_matrix_free (m);
3131   return ok;
3132 }
3133
3134 static bool
3135 matrix_lvalue_assign_vector (struct matrix_lvalue *lvalue,
3136                              struct index_vector *iv, gsl_matrix *sm)
3137 {
3138   gsl_vector dv = to_vector (lvalue->var->value);
3139
3140   /* Convert source matrix 'sm' to source vector 'sv'. */
3141   if (!is_vector (sm))
3142     {
3143       msg (SE, _("Can't assign %zu×%zu matrix to subvector."),
3144            sm->size1, sm->size2);
3145       return false;
3146     }
3147   gsl_vector sv = to_vector (sm);
3148   if (iv->n != sv.size)
3149     {
3150       msg (SE, _("Can't assign %zu-element vector "
3151                  "to %zu-element subvector."), sv.size, iv->n);
3152       return false;
3153     }
3154
3155   /* Assign elements. */
3156   for (size_t x = 0; x < iv->n; x++)
3157     gsl_vector_set (&dv, iv->indexes[x], gsl_vector_get (&sv, x));
3158   return true;
3159 }
3160
3161 static bool
3162 matrix_lvalue_assign_matrix (struct matrix_lvalue *lvalue,
3163                              struct index_vector *iv0,
3164                              struct index_vector *iv1, gsl_matrix *sm)
3165 {
3166   gsl_matrix *dm = lvalue->var->value;
3167
3168   /* Convert source matrix 'sm' to source vector 'sv'. */
3169   if (iv0->n != sm->size1)
3170     {
3171       msg (SE, _("Row index vector for assignment to %s has %zu elements "
3172                  "but source matrix has %zu rows."),
3173            lvalue->var->name, iv0->n, sm->size1);
3174       return false;
3175     }
3176   if (iv1->n != sm->size2)
3177     {
3178       msg (SE, _("Column index vector for assignment to %s has %zu elements "
3179                  "but source matrix has %zu columns."),
3180            lvalue->var->name, iv1->n, sm->size2);
3181       return false;
3182     }
3183
3184   /* Assign elements. */
3185   for (size_t y = 0; y < iv0->n; y++)
3186     {
3187       size_t f0 = iv0->indexes[y];
3188       for (size_t x = 0; x < iv1->n; x++)
3189         {
3190           size_t f1 = iv1->indexes[x];
3191           gsl_matrix_set (dm, f0, f1, gsl_matrix_get (sm, y, x));
3192         }
3193     }
3194   return true;
3195 }
3196
3197 /* Takes ownership of M. */
3198 static bool
3199 matrix_lvalue_assign (struct matrix_lvalue *lvalue,
3200                       struct index_vector *iv0, struct index_vector *iv1,
3201                       gsl_matrix *sm)
3202 {
3203   if (!lvalue->n_indexes)
3204     {
3205       gsl_matrix_free (lvalue->var->value);
3206       lvalue->var->value = sm;
3207       return true;
3208     }
3209   else
3210     {
3211       bool ok = (lvalue->n_indexes == 1
3212                  ? matrix_lvalue_assign_vector (lvalue, iv0, sm)
3213                  : matrix_lvalue_assign_matrix (lvalue, iv0, iv1, sm));
3214       free (iv0->indexes);
3215       free (iv1->indexes);
3216       gsl_matrix_free (sm);
3217       return ok;
3218     }
3219 }
3220
3221 static bool
3222 matrix_lvalue_evaluate (struct matrix_lvalue *lvalue,
3223                         struct index_vector *iv0,
3224                         struct index_vector *iv1)
3225 {
3226   *iv0 = INDEX_VECTOR_INIT;
3227   *iv1 = INDEX_VECTOR_INIT;
3228   if (!lvalue->n_indexes)
3229     return true;
3230
3231   /* Validate destination matrix exists and has the right shape. */
3232   gsl_matrix *dm = lvalue->var->value;
3233   if (!dm)
3234     {
3235       msg (SE, _("Undefined variable %s."), lvalue->var->name);
3236       return false;
3237     }
3238   else if (dm->size1 == 0 || dm->size2 == 0)
3239     {
3240       msg (SE, _("Cannot index %zu×%zu matrix."),
3241            dm->size1, dm->size2);
3242       return false;
3243     }
3244   else if (lvalue->n_indexes == 1)
3245     {
3246       if (!is_vector (dm))
3247         {
3248           msg (SE, _("Can't use vector indexing on %zu×%zu matrix %s."),
3249                dm->size1, dm->size2, lvalue->var->name);
3250           return false;
3251         }
3252       return matrix_lvalue_evaluate_vector (lvalue->indexes[0],
3253                                             MAX (dm->size1, dm->size2),
3254                                             IV_VECTOR, 0, iv0);
3255     }
3256   else
3257     {
3258       assert (lvalue->n_indexes == 2);
3259       if (!matrix_lvalue_evaluate_vector (lvalue->indexes[0], dm->size1,
3260                                           IV_ROW, dm->size2, iv0))
3261         return false;
3262
3263       if (!matrix_lvalue_evaluate_vector (lvalue->indexes[1], dm->size2,
3264                                           IV_COLUMN, dm->size1, iv1))
3265         {
3266           free (iv0->indexes);
3267           return false;
3268         }
3269       return true;
3270     }
3271 }
3272
3273 /* Takes ownership of M. */
3274 static bool
3275 matrix_lvalue_evaluate_and_assign (struct matrix_lvalue *lvalue, gsl_matrix *sm)
3276 {
3277   struct index_vector iv0, iv1;
3278   if (!matrix_lvalue_evaluate (lvalue, &iv0, &iv1))
3279     {
3280       gsl_matrix_free (sm);
3281       return false;
3282     }
3283
3284   return matrix_lvalue_assign (lvalue, &iv0, &iv1, sm);
3285 }
3286
3287 \f
3288 /* Matrix command. */
3289
3290 struct matrix_cmds
3291   {
3292     struct matrix_cmd **commands;
3293     size_t n;
3294   };
3295
3296 static void matrix_cmds_uninit (struct matrix_cmds *);
3297
3298 struct matrix_cmd
3299   {
3300     enum matrix_cmd_type
3301       {
3302         MCMD_COMPUTE,
3303         MCMD_PRINT,
3304         MCMD_DO_IF,
3305         MCMD_LOOP,
3306         MCMD_BREAK,
3307         MCMD_DISPLAY,
3308         MCMD_RELEASE,
3309         MCMD_SAVE,
3310         MCMD_READ,
3311         MCMD_WRITE,
3312         MCMD_GET,
3313         MCMD_MSAVE,
3314         MCMD_MGET,
3315         MCMD_EIGEN,
3316         MCMD_SETDIAG,
3317         MCMD_SVD,
3318       }
3319     type;
3320
3321     union
3322       {
3323         struct compute_command
3324           {
3325             struct matrix_lvalue *lvalue;
3326             struct matrix_expr *rvalue;
3327           }
3328         compute;
3329
3330         struct print_command
3331           {
3332             struct matrix_expr *expression;
3333             bool use_default_format;
3334             struct fmt_spec format;
3335             char *title;
3336             int space;          /* -1 means NEWPAGE. */
3337
3338             struct print_labels
3339               {
3340                 struct string_array literals; /* CLABELS/RLABELS. */
3341                 struct matrix_expr *expr;     /* CNAMES/RNAMES. */
3342               }
3343             *rlabels, *clabels;
3344           }
3345         print;
3346
3347         struct do_if_command
3348           {
3349             struct do_if_clause
3350               {
3351                 struct matrix_expr *condition;
3352                 struct matrix_cmds commands;
3353               }
3354             *clauses;
3355             size_t n_clauses;
3356           }
3357         do_if;
3358
3359         struct loop_command
3360           {
3361             /* Index. */
3362             struct matrix_var *var;
3363             struct matrix_expr *start;
3364             struct matrix_expr *end;
3365             struct matrix_expr *increment;
3366
3367             /* Loop conditions. */
3368             struct matrix_expr *top_condition;
3369             struct matrix_expr *bottom_condition;
3370
3371             /* Commands. */
3372             struct matrix_cmds commands;
3373           }
3374         loop;
3375
3376         struct display_command
3377           {
3378             struct matrix_state *state;
3379             bool dictionary;
3380             bool status;
3381           }
3382         display;
3383
3384         struct release_command
3385           {
3386             struct matrix_var **vars;
3387             size_t n_vars;
3388           }
3389         release;
3390
3391         struct save_command
3392           {
3393             struct matrix_expr *expression;
3394             struct file_handle *outfile;
3395             struct string_array *variables;
3396             struct matrix_expr *names;
3397             struct stringi_set strings;
3398           }
3399         save;
3400
3401         struct read_command
3402           {
3403             struct read_file *rf;
3404             struct matrix_lvalue *dst;
3405             struct matrix_expr *size;
3406             int c1, c2;
3407             enum fmt_type format;
3408             int w;
3409             //int d;
3410             bool symmetric;
3411             bool reread;
3412           }
3413         read;
3414
3415         struct write_command
3416           {
3417             struct write_file *wf;
3418             struct matrix_expr *expression;
3419             int c1, c2;
3420
3421             /* If this is nonnull, WRITE uses this format.
3422
3423                If this is NULL, WRITE uses free-field format with as many
3424                digits of precision as needed. */
3425             struct fmt_spec *format;
3426
3427             bool triangular;
3428             bool hold;
3429           }
3430         write;
3431
3432         struct get_command
3433           {
3434             struct matrix_lvalue *dst;
3435             struct dataset *dataset;
3436             struct file_handle *file;
3437             char *encoding;
3438             struct var_syntax *vars;
3439             size_t n_vars;
3440             struct matrix_var *names;
3441
3442             /* Treatment of missing values. */
3443             struct
3444               {
3445                 enum
3446                   {
3447                     MGET_ERROR,  /* Flag error on command. */
3448                     MGET_ACCEPT, /* Accept without change, user-missing only. */
3449                     MGET_OMIT,   /* Drop this case. */
3450                     MGET_RECODE  /* Recode to 'substitute'. */
3451                   }
3452                 treatment;
3453                 double substitute; /* MGET_RECODE only. */
3454               }
3455             user, system;
3456           }
3457         get;
3458
3459         struct msave_command
3460           {
3461             struct msave_common *common;
3462             char *varname_;
3463             struct matrix_expr *expr;
3464             const char *rowtype;
3465             struct matrix_expr *factors;
3466             struct matrix_expr *splits;
3467           }
3468          msave;
3469
3470         struct mget_command
3471           {
3472             struct matrix_state *state;
3473             struct file_handle *file;
3474             struct stringi_set rowtypes;
3475           }
3476         mget;
3477
3478         struct eigen_command
3479           {
3480             struct matrix_expr *expr;
3481             struct matrix_var *evec;
3482             struct matrix_var *eval;
3483           }
3484         eigen;
3485
3486         struct setdiag_command
3487           {
3488             struct matrix_var *dst;
3489             struct matrix_expr *expr;
3490           }
3491         setdiag;
3492
3493         struct svd_command
3494           {
3495             struct matrix_expr *expr;
3496             struct matrix_var *u;
3497             struct matrix_var *s;
3498             struct matrix_var *v;
3499           }
3500         svd;
3501       };
3502   };
3503
3504 static struct matrix_cmd *matrix_parse_command (struct matrix_state *);
3505 static bool matrix_cmd_execute (struct matrix_cmd *);
3506 static void matrix_cmd_destroy (struct matrix_cmd *);
3507
3508 \f
3509 static struct matrix_cmd *
3510 matrix_parse_compute (struct matrix_state *s)
3511 {
3512   struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
3513   *cmd = (struct matrix_cmd) {
3514     .type = MCMD_COMPUTE,
3515     .compute = { .lvalue = NULL },
3516   };
3517
3518   struct compute_command *compute = &cmd->compute;
3519   compute->lvalue = matrix_lvalue_parse (s);
3520   if (!compute->lvalue)
3521     goto error;
3522
3523   if (!lex_force_match (s->lexer, T_EQUALS))
3524     goto error;
3525
3526   compute->rvalue = matrix_parse_expr (s);
3527   if (!compute->rvalue)
3528     goto error;
3529
3530   return cmd;
3531
3532 error:
3533   matrix_cmd_destroy (cmd);
3534   return NULL;
3535 }
3536
3537 static void
3538 matrix_cmd_execute_compute (struct compute_command *compute)
3539 {
3540   gsl_matrix *value = matrix_expr_evaluate (compute->rvalue);
3541   if (!value)
3542     return;
3543
3544   matrix_lvalue_evaluate_and_assign (compute->lvalue, value);
3545 }
3546 \f
3547 static void
3548 print_labels_destroy (struct print_labels *labels)
3549 {
3550   if (labels)
3551     {
3552       string_array_destroy (&labels->literals);
3553       matrix_expr_destroy (labels->expr);
3554       free (labels);
3555     }
3556 }
3557
3558 static void
3559 parse_literal_print_labels (struct matrix_state *s,
3560                             struct print_labels **labelsp)
3561 {
3562   lex_match (s->lexer, T_EQUALS);
3563   print_labels_destroy (*labelsp);
3564   *labelsp = xzalloc (sizeof **labelsp);
3565   while (lex_token (s->lexer) != T_SLASH
3566          && lex_token (s->lexer) != T_ENDCMD
3567          && lex_token (s->lexer) != T_STOP)
3568     {
3569       struct string label = DS_EMPTY_INITIALIZER;
3570       while (lex_token (s->lexer) != T_COMMA
3571              && lex_token (s->lexer) != T_SLASH
3572              && lex_token (s->lexer) != T_ENDCMD
3573              && lex_token (s->lexer) != T_STOP)
3574         {
3575           if (!ds_is_empty (&label))
3576             ds_put_byte (&label, ' ');
3577
3578           if (lex_token (s->lexer) == T_STRING)
3579             ds_put_cstr (&label, lex_tokcstr (s->lexer));
3580           else
3581             {
3582               char *rep = lex_next_representation (s->lexer, 0, 0);
3583               ds_put_cstr (&label, rep);
3584               free (rep);
3585             }
3586           lex_get (s->lexer);
3587         }
3588       string_array_append_nocopy (&(*labelsp)->literals,
3589                                   ds_steal_cstr (&label));
3590
3591       if (!lex_match (s->lexer, T_COMMA))
3592         break;
3593     }
3594 }
3595
3596 static bool
3597 parse_expr_print_labels (struct matrix_state *s, struct print_labels **labelsp)
3598 {
3599   lex_match (s->lexer, T_EQUALS);
3600   struct matrix_expr *e = matrix_parse_exp (s);
3601   if (!e)
3602     return false;
3603
3604   print_labels_destroy (*labelsp);
3605   *labelsp = xzalloc (sizeof **labelsp);
3606   (*labelsp)->expr = e;
3607   return true;
3608 }
3609
3610 static struct matrix_cmd *
3611 matrix_parse_print (struct matrix_state *s)
3612 {
3613   struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
3614   *cmd = (struct matrix_cmd) {
3615     .type = MCMD_PRINT,
3616     .print = {
3617       .use_default_format = true,
3618     }
3619   };
3620
3621   if (lex_token (s->lexer) != T_SLASH && lex_token (s->lexer) != T_ENDCMD)
3622     {
3623       size_t depth = 0;
3624       for (size_t i = 0; ; i++)
3625         {
3626           enum token_type t = lex_next_token (s->lexer, i);
3627           if (t == T_LPAREN || t == T_LBRACK || t == T_LCURLY)
3628             depth++;
3629           else if ((t == T_RPAREN || t == T_RBRACK || t == T_RCURLY) && depth)
3630             depth--;
3631           else if ((t == T_SLASH && !depth) || t == T_ENDCMD || t == T_STOP)
3632             {
3633               if (i > 0)
3634                 cmd->print.title = lex_next_representation (s->lexer, 0, i - 1);
3635               break;
3636             }
3637         }
3638
3639       cmd->print.expression = matrix_parse_exp (s);
3640       if (!cmd->print.expression)
3641         goto error;
3642     }
3643
3644   while (lex_match (s->lexer, T_SLASH))
3645     {
3646       if (lex_match_id (s->lexer, "FORMAT"))
3647         {
3648           lex_match (s->lexer, T_EQUALS);
3649           if (!parse_format_specifier (s->lexer, &cmd->print.format))
3650             goto error;
3651           cmd->print.use_default_format = false;
3652         }
3653       else if (lex_match_id (s->lexer, "TITLE"))
3654         {
3655           lex_match (s->lexer, T_EQUALS);
3656           if (!lex_force_string (s->lexer))
3657             goto error;
3658           free (cmd->print.title);
3659           cmd->print.title = ss_xstrdup (lex_tokss (s->lexer));
3660           lex_get (s->lexer);
3661         }
3662       else if (lex_match_id (s->lexer, "SPACE"))
3663         {
3664           lex_match (s->lexer, T_EQUALS);
3665           if (lex_match_id (s->lexer, "NEWPAGE"))
3666             cmd->print.space = -1;
3667           else if (lex_force_int_range (s->lexer, "SPACE", 1, INT_MAX))
3668             {
3669               cmd->print.space = lex_integer (s->lexer);
3670               lex_get (s->lexer);
3671             }
3672           else
3673             goto error;
3674         }
3675       else if (lex_match_id (s->lexer, "RLABELS"))
3676         parse_literal_print_labels (s, &cmd->print.rlabels);
3677       else if (lex_match_id (s->lexer, "CLABELS"))
3678         parse_literal_print_labels (s, &cmd->print.clabels);
3679       else if (lex_match_id (s->lexer, "RNAMES"))
3680         {
3681           if (!parse_expr_print_labels (s, &cmd->print.rlabels))
3682             goto error;
3683         }
3684       else if (lex_match_id (s->lexer, "CNAMES"))
3685         {
3686           if (!parse_expr_print_labels (s, &cmd->print.clabels))
3687             goto error;
3688         }
3689       else
3690         {
3691           lex_error_expecting (s->lexer, "FORMAT", "TITLE", "SPACE",
3692                                "RLABELS", "CLABELS", "RNAMES", "CNAMES");
3693           goto error;
3694         }
3695
3696     }
3697   return cmd;
3698
3699 error:
3700   matrix_cmd_destroy (cmd);
3701   return NULL;
3702 }
3703
3704 static bool
3705 matrix_is_integer (const gsl_matrix *m)
3706 {
3707   for (size_t y = 0; y < m->size1; y++)
3708     for (size_t x = 0; x < m->size2; x++)
3709       {
3710         double d = gsl_matrix_get (m, y, x);
3711         if (d != floor (d))
3712           return false;
3713       }
3714   return true;
3715 }
3716
3717 static double
3718 matrix_max_magnitude (const gsl_matrix *m)
3719 {
3720   double max = 0.0;
3721   for (size_t y = 0; y < m->size1; y++)
3722     for (size_t x = 0; x < m->size2; x++)
3723       {
3724         double d = fabs (gsl_matrix_get (m, y, x));
3725         if (d > max)
3726           max = d;
3727       }
3728   return max;
3729 }
3730
3731 static bool
3732 format_fits (struct fmt_spec format, double x)
3733 {
3734   char *s = data_out (&(union value) { .f = x }, NULL,
3735                       &format, settings_get_fmt_settings ());
3736   bool fits = *s != '*' && !strchr (s, 'E');
3737   free (s);
3738   return fits;
3739 }
3740
3741 static struct fmt_spec
3742 default_format (const gsl_matrix *m, int *log_scale)
3743 {
3744   *log_scale = 0;
3745
3746   double max = matrix_max_magnitude (m);
3747
3748   if (matrix_is_integer (m))
3749     for (int w = 1; w <= 12; w++)
3750       {
3751         struct fmt_spec format = { .type = FMT_F, .w = w };
3752         if (format_fits (format, -max))
3753           return format;
3754       }
3755
3756   if (max >= 1e9 || max <= 1e-4)
3757     {
3758       char s[64];
3759       snprintf (s, sizeof s, "%.1e", max);
3760
3761       const char *e = strchr (s, 'e');
3762       if (e)
3763         *log_scale = atoi (e + 1);
3764     }
3765
3766   return (struct fmt_spec) { .type = FMT_F, .w = 13, .d = 10 };
3767 }
3768
3769 static char *
3770 trimmed_string (double d)
3771 {
3772   struct substring s = ss_buffer ((char *) &d, sizeof d);
3773   ss_rtrim (&s, ss_cstr (" "));
3774   return ss_xstrdup (s);
3775 }
3776
3777 static struct string_array *
3778 print_labels_get (const struct print_labels *labels, size_t n,
3779                   const char *prefix, bool truncate)
3780 {
3781   if (!labels)
3782     return NULL;
3783
3784   struct string_array *out = xzalloc (sizeof *out);
3785   if (labels->literals.n)
3786     string_array_clone (out, &labels->literals);
3787   else if (labels->expr)
3788     {
3789       gsl_matrix *m = matrix_expr_evaluate (labels->expr);
3790       if (m && is_vector (m))
3791         {
3792           gsl_vector v = to_vector (m);
3793           for (size_t i = 0; i < v.size; i++)
3794             string_array_append_nocopy (out, trimmed_string (
3795                                           gsl_vector_get (&v, i)));
3796         }
3797       gsl_matrix_free (m);
3798     }
3799
3800   while (out->n < n)
3801     {
3802       if (labels->expr)
3803         string_array_append_nocopy (out, xasprintf ("%s%zu", prefix,
3804                                                     out->n + 1));
3805       else
3806         string_array_append (out, "");
3807     }
3808   while (out->n > n)
3809     string_array_delete (out, out->n - 1);
3810
3811   if (truncate)
3812     for (size_t i = 0; i < out->n; i++)
3813       {
3814         char *s = out->strings[i];
3815         s[strnlen (s, 8)] = '\0';
3816       }
3817
3818   return out;
3819 }
3820
3821 static void
3822 matrix_cmd_print_space (int space)
3823 {
3824   if (space < 0)
3825     output_item_submit (page_break_item_create ());
3826   for (int i = 0; i < space; i++)
3827     output_log ("%s", "");
3828 }
3829
3830 static void
3831 matrix_cmd_print_text (const struct print_command *print, const gsl_matrix *m,
3832                        struct fmt_spec format, int log_scale)
3833 {
3834   matrix_cmd_print_space (print->space);
3835   if (print->title)
3836     output_log ("%s", print->title);
3837   if (log_scale != 0)
3838     output_log ("  10 ** %d   X", log_scale);
3839
3840   struct string_array *clabels = print_labels_get (print->clabels,
3841                                                    m->size2, "col", true);
3842   if (clabels && format.w < 8)
3843     format.w = 8;
3844   struct string_array *rlabels = print_labels_get (print->rlabels,
3845                                                    m->size1, "row", true);
3846
3847   if (clabels)
3848     {
3849       struct string line = DS_EMPTY_INITIALIZER;
3850       if (rlabels)
3851         ds_put_byte_multiple (&line, ' ', 8);
3852       for (size_t x = 0; x < m->size2; x++)
3853         ds_put_format (&line, " %*s", format.w, clabels->strings[x]);
3854       output_log_nocopy (ds_steal_cstr (&line));
3855     }
3856
3857   double scale = pow (10.0, log_scale);
3858   bool numeric = fmt_is_numeric (format.type);
3859   for (size_t y = 0; y < m->size1; y++)
3860     {
3861       struct string line = DS_EMPTY_INITIALIZER;
3862       if (rlabels)
3863         ds_put_format (&line, "%-8s", rlabels->strings[y]);
3864
3865       for (size_t x = 0; x < m->size2; x++)
3866         {
3867           double f = gsl_matrix_get (m, y, x);
3868           char *s = (numeric
3869                      ? data_out (&(union value) { .f = f / scale}, NULL,
3870                                  &format, settings_get_fmt_settings ())
3871                      : trimmed_string (f));
3872           ds_put_format (&line, " %s", s);
3873           free (s);
3874         }
3875       output_log_nocopy (ds_steal_cstr (&line));
3876     }
3877
3878   string_array_destroy (rlabels);
3879   free (rlabels);
3880   string_array_destroy (clabels);
3881   free (clabels);
3882 }
3883
3884 static void
3885 create_print_dimension (struct pivot_table *table, enum pivot_axis_type axis,
3886                         const struct print_labels *print_labels, size_t n,
3887                         const char *name, const char *prefix)
3888 {
3889   struct string_array *labels = print_labels_get (print_labels, n, prefix,
3890                                                   false);
3891   struct pivot_dimension *d = pivot_dimension_create (table, axis, name);
3892   for (size_t i = 0; i < n; i++)
3893     pivot_category_create_leaf (
3894       d->root, (labels
3895                 ? pivot_value_new_user_text (labels->strings[i], SIZE_MAX)
3896                 : pivot_value_new_integer (i + 1)));
3897   if (!labels)
3898     d->hide_all_labels = true;
3899   string_array_destroy (labels);
3900   free (labels);
3901 }
3902
3903 static void
3904 matrix_cmd_print_tables (const struct print_command *print, const gsl_matrix *m,
3905                          struct fmt_spec format, int log_scale)
3906 {
3907   struct pivot_table *table = pivot_table_create__ (
3908     pivot_value_new_user_text (print->title ? print->title : "", SIZE_MAX),
3909     "Matrix Print");
3910
3911   create_print_dimension (table, PIVOT_AXIS_ROW, print->rlabels, m->size1,
3912                           N_("Rows"), "row");
3913   create_print_dimension (table, PIVOT_AXIS_COLUMN, print->clabels, m->size2,
3914                           N_("Columns"), "col");
3915
3916   struct pivot_footnote *footnote = NULL;
3917   if (log_scale != 0)
3918     {
3919       char *s = xasprintf ("× 10**%d", log_scale);
3920       footnote = pivot_table_create_footnote (
3921         table, pivot_value_new_user_text_nocopy (s));
3922     }
3923
3924   double scale = pow (10.0, log_scale);
3925   bool numeric = fmt_is_numeric (format.type);
3926   for (size_t y = 0; y < m->size1; y++)
3927     for (size_t x = 0; x < m->size2; x++)
3928       {
3929         double f = gsl_matrix_get (m, y, x);
3930         struct pivot_value *v;
3931         if (numeric)
3932           {
3933             v = pivot_value_new_number (f / scale);
3934             v->numeric.format = format;
3935           }
3936         else
3937           v = pivot_value_new_user_text_nocopy (trimmed_string (f));
3938         if (footnote)
3939           pivot_value_add_footnote (v, footnote);
3940         pivot_table_put2 (table, y, x, v);
3941       }
3942
3943   pivot_table_submit (table);
3944 }
3945
3946 static void
3947 matrix_cmd_execute_print (const struct print_command *print)
3948 {
3949   if (print->expression)
3950     {
3951       gsl_matrix *m = matrix_expr_evaluate (print->expression);
3952       if (!m)
3953         return;
3954
3955       int log_scale = 0;
3956       struct fmt_spec format = (print->use_default_format
3957                                 ? default_format (m, &log_scale)
3958                                 : print->format);
3959
3960       if (settings_get_mdisplay () == SETTINGS_MDISPLAY_TEXT)
3961         matrix_cmd_print_text (print, m, format, log_scale);
3962       else
3963         matrix_cmd_print_tables (print, m, format, log_scale);
3964
3965       gsl_matrix_free (m);
3966     }
3967   else
3968     {
3969       matrix_cmd_print_space (print->space);
3970       if (print->title)
3971         output_log ("%s", print->title);
3972     }
3973 }
3974 \f
3975 /* DO IF. */
3976
3977 static bool
3978 matrix_parse_commands (struct matrix_state *s, struct matrix_cmds *c,
3979                        const char *command_name,
3980                        const char *stop1, const char *stop2)
3981 {
3982   lex_end_of_command (s->lexer);
3983   lex_discard_rest_of_command (s->lexer);
3984
3985   size_t allocated = 0;
3986   for (;;)
3987     {
3988       while (lex_token (s->lexer) == T_ENDCMD)
3989         lex_get (s->lexer);
3990
3991       if (lex_at_phrase (s->lexer, stop1)
3992           || (stop2 && lex_at_phrase (s->lexer, stop2)))
3993         return true;
3994
3995       if (lex_at_phrase (s->lexer, "END MATRIX"))
3996         {
3997           msg (SE, _("Premature END MATRIX within %s."), command_name);
3998           return false;
3999         }
4000
4001       struct matrix_cmd *cmd = matrix_parse_command (s);
4002       if (!cmd)
4003         return false;
4004
4005       if (c->n >= allocated)
4006         c->commands = x2nrealloc (c->commands, &allocated, sizeof *c->commands);
4007       c->commands[c->n++] = cmd;
4008     }
4009 }
4010
4011 static bool
4012 matrix_parse_do_if_clause (struct matrix_state *s,
4013                            struct do_if_command *ifc,
4014                            bool parse_condition,
4015                            size_t *allocated_clauses)
4016 {
4017   if (ifc->n_clauses >= *allocated_clauses)
4018     ifc->clauses = x2nrealloc (ifc->clauses, allocated_clauses,
4019                                sizeof *ifc->clauses);
4020   struct do_if_clause *c = &ifc->clauses[ifc->n_clauses++];
4021   *c = (struct do_if_clause) { .condition = NULL };
4022
4023   if (parse_condition)
4024     {
4025       c->condition = matrix_parse_expr (s);
4026       if (!c->condition)
4027         return false;
4028     }
4029
4030   return matrix_parse_commands (s, &c->commands, "DO IF", "ELSE", "END IF");
4031 }
4032
4033 static struct matrix_cmd *
4034 matrix_parse_do_if (struct matrix_state *s)
4035 {
4036   struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
4037   *cmd = (struct matrix_cmd) {
4038     .type = MCMD_DO_IF,
4039     .do_if = { .n_clauses = 0 }
4040   };
4041
4042   size_t allocated_clauses = 0;
4043   do
4044     {
4045       if (!matrix_parse_do_if_clause (s, &cmd->do_if, true, &allocated_clauses))
4046         goto error;
4047     }
4048   while (lex_match_phrase (s->lexer, "ELSE IF"));
4049
4050   if (lex_match_id (s->lexer, "ELSE")
4051       && !matrix_parse_do_if_clause (s, &cmd->do_if, false, &allocated_clauses))
4052     goto error;
4053
4054   if (!lex_match_phrase (s->lexer, "END IF"))
4055     NOT_REACHED ();
4056   return cmd;
4057
4058 error:
4059   matrix_cmd_destroy (cmd);
4060   return NULL;
4061 }
4062
4063 static bool
4064 matrix_cmd_execute_do_if (struct do_if_command *cmd)
4065 {
4066   for (size_t i = 0; i < cmd->n_clauses; i++)
4067     {
4068       struct do_if_clause *c = &cmd->clauses[i];
4069       if (c->condition)
4070         {
4071           double d;
4072           if (!matrix_expr_evaluate_scalar (c->condition,
4073                                             i ? "ELSE IF" : "DO IF",
4074                                             &d) || d <= 0)
4075             continue;
4076         }
4077
4078       for (size_t j = 0; j < c->commands.n; j++)
4079         if (!matrix_cmd_execute (c->commands.commands[j]))
4080           return false;
4081       return true;
4082     }
4083   return true;
4084 }
4085 \f
4086 static struct matrix_cmd *
4087 matrix_parse_loop (struct matrix_state *s)
4088 {
4089   struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
4090   *cmd = (struct matrix_cmd) { .type = MCMD_LOOP, .loop = { .var = NULL } };
4091
4092   struct loop_command *loop = &cmd->loop;
4093   if (lex_token (s->lexer) == T_ID && lex_next_token (s->lexer, 1) == T_EQUALS)
4094     {
4095       struct substring name = lex_tokss (s->lexer);
4096       loop->var = matrix_var_lookup (s, name);
4097       if (!loop->var)
4098         loop->var = matrix_var_create (s, name);
4099
4100       lex_get (s->lexer);
4101       lex_get (s->lexer);
4102
4103       loop->start = matrix_parse_expr (s);
4104       if (!loop->start || !lex_force_match (s->lexer, T_TO))
4105         goto error;
4106
4107       loop->end = matrix_parse_expr (s);
4108       if (!loop->end)
4109         goto error;
4110
4111       if (lex_match (s->lexer, T_BY))
4112         {
4113           loop->increment = matrix_parse_expr (s);
4114           if (!loop->increment)
4115             goto error;
4116         }
4117     }
4118
4119   if (lex_match_id (s->lexer, "IF"))
4120     {
4121       loop->top_condition = matrix_parse_expr (s);
4122       if (!loop->top_condition)
4123         goto error;
4124     }
4125
4126   bool was_in_loop = s->in_loop;
4127   s->in_loop = true;
4128   bool ok = matrix_parse_commands (s, &loop->commands, "LOOP",
4129                                    "END LOOP", NULL);
4130   s->in_loop = was_in_loop;
4131   if (!ok)
4132     goto error;
4133
4134   if (!lex_match_phrase (s->lexer, "END LOOP"))
4135     NOT_REACHED ();
4136
4137   if (lex_match_id (s->lexer, "IF"))
4138     {
4139       loop->bottom_condition = matrix_parse_expr (s);
4140       if (!loop->bottom_condition)
4141         goto error;
4142     }
4143
4144   return cmd;
4145
4146 error:
4147   matrix_cmd_destroy (cmd);
4148   return NULL;
4149 }
4150
4151 static void
4152 matrix_cmd_execute_loop (struct loop_command *cmd)
4153 {
4154   long int value = 0;
4155   long int end = 0;
4156   long int increment = 1;
4157   if (cmd->var)
4158     {
4159       if (!matrix_expr_evaluate_integer (cmd->start, "LOOP", &value)
4160           || !matrix_expr_evaluate_integer (cmd->end, "TO", &end)
4161           || (cmd->increment
4162               && !matrix_expr_evaluate_integer (cmd->increment, "BY",
4163                                                 &increment)))
4164         return;
4165
4166       if (increment > 0 ? value > end
4167           : increment < 0 ? value < end
4168           : true)
4169         return;
4170     }
4171
4172   int mxloops = settings_get_mxloops ();
4173   for (int i = 0; i < mxloops; i++)
4174     {
4175       if (cmd->var)
4176         {
4177           if (cmd->var->value
4178               && (cmd->var->value->size1 != 1 || cmd->var->value->size2 != 1))
4179             {
4180               gsl_matrix_free (cmd->var->value);
4181               cmd->var->value = NULL;
4182             }
4183           if (!cmd->var->value)
4184             cmd->var->value = gsl_matrix_alloc (1, 1);
4185
4186           gsl_matrix_set (cmd->var->value, 0, 0, value);
4187         }
4188
4189       if (cmd->top_condition)
4190         {
4191           double d;
4192           if (!matrix_expr_evaluate_scalar (cmd->top_condition, "LOOP IF",
4193                                             &d) || d <= 0)
4194             return;
4195         }
4196
4197       for (size_t j = 0; j < cmd->commands.n; j++)
4198         if (!matrix_cmd_execute (cmd->commands.commands[j]))
4199           return;
4200
4201       if (cmd->bottom_condition)
4202         {
4203           double d;
4204           if (!matrix_expr_evaluate_scalar (cmd->bottom_condition,
4205                                             "END LOOP IF", &d) || d > 0)
4206             return;
4207         }
4208
4209       if (cmd->var)
4210         {
4211           value += increment;
4212           if (increment > 0 ? value > end : value < end)
4213             return;
4214         }
4215     }
4216 }
4217 \f
4218 static struct matrix_cmd *
4219 matrix_parse_break (struct matrix_state *s)
4220 {
4221   if (!s->in_loop)
4222     {
4223       msg (SE, _("BREAK not inside LOOP."));
4224       return NULL;
4225     }
4226
4227   struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
4228   *cmd = (struct matrix_cmd) { .type = MCMD_BREAK };
4229   return cmd;
4230 }
4231 \f
4232 static struct matrix_cmd *
4233 matrix_parse_display (struct matrix_state *s)
4234 {
4235   bool dictionary = false;
4236   bool status = false;
4237   while (lex_token (s->lexer) == T_ID)
4238     {
4239       if (lex_match_id (s->lexer, "DICTIONARY"))
4240         dictionary = true;
4241       else if (lex_match_id (s->lexer, "STATUS"))
4242         status = true;
4243       else
4244         {
4245           lex_error_expecting (s->lexer, "DICTIONARY", "STATUS");
4246           return NULL;
4247         }
4248     }
4249   if (!dictionary && !status)
4250     dictionary = status = true;
4251
4252   struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
4253   *cmd = (struct matrix_cmd) {
4254     .type = MCMD_DISPLAY,
4255     .display = {
4256       .state = s,
4257       .dictionary = dictionary,
4258       .status = status,
4259     }
4260   };
4261   return cmd;
4262 }
4263
4264 static int
4265 compare_matrix_var_pointers (const void *a_, const void *b_)
4266 {
4267   const struct matrix_var *const *ap = a_;
4268   const struct matrix_var *const *bp = b_;
4269   const struct matrix_var *a = *ap;
4270   const struct matrix_var *b = *bp;
4271   return strcmp (a->name, b->name);
4272 }
4273
4274 static void
4275 matrix_cmd_execute_display (struct display_command *cmd)
4276 {
4277   const struct matrix_state *s = cmd->state;
4278
4279   struct pivot_table *table = pivot_table_create (N_("Matrix Variables"));
4280   pivot_dimension_create (
4281     table, PIVOT_AXIS_COLUMN, N_("Property"),
4282     N_("Rows"), N_("Columns"), N_("Size (kB)"));
4283
4284   const struct matrix_var **vars = xmalloc (hmap_count (&s->vars) * sizeof *vars);
4285   size_t n_vars = 0;
4286
4287   const struct matrix_var *var;
4288   HMAP_FOR_EACH (var, struct matrix_var, hmap_node, &s->vars)
4289     if (var->value)
4290       vars[n_vars++] = var;
4291   qsort (vars, n_vars, sizeof *vars, compare_matrix_var_pointers);
4292
4293   struct pivot_dimension *rows = pivot_dimension_create (
4294     table, PIVOT_AXIS_ROW, N_("Variable"));
4295   for (size_t i = 0; i < n_vars; i++)
4296     {
4297       const struct matrix_var *var = vars[i];
4298       pivot_category_create_leaf (
4299         rows->root, pivot_value_new_user_text (var->name, SIZE_MAX));
4300
4301       size_t r = var->value->size1;
4302       size_t c = var->value->size2;
4303       double values[] = { r, c, r * c * sizeof (double) / 1024 };
4304       for (size_t j = 0; j < sizeof values / sizeof *values; j++)
4305         pivot_table_put2 (table, j, i, pivot_value_new_integer (values[j]));
4306     }
4307   pivot_table_submit (table);
4308 }
4309 \f
4310 static struct matrix_cmd *
4311 matrix_parse_release (struct matrix_state *s)
4312 {
4313   struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
4314   *cmd = (struct matrix_cmd) { .type = MCMD_RELEASE };
4315
4316   size_t allocated_vars = 0;
4317   while (lex_token (s->lexer) == T_ID)
4318     {
4319       struct matrix_var *var = matrix_var_lookup (s, lex_tokss (s->lexer));
4320       if (var)
4321         {
4322           if (cmd->release.n_vars >= allocated_vars)
4323             cmd->release.vars = x2nrealloc (cmd->release.vars, &allocated_vars,
4324                                             sizeof *cmd->release.vars);
4325           cmd->release.vars[cmd->release.n_vars++] = var;
4326         }
4327       else
4328         lex_error (s->lexer, _("Variable name expected."));
4329       lex_get (s->lexer);
4330
4331       if (!lex_match (s->lexer, T_COMMA))
4332         break;
4333     }
4334
4335   return cmd;
4336 }
4337
4338 static void
4339 matrix_cmd_execute_release (struct release_command *cmd)
4340 {
4341   for (size_t i = 0; i < cmd->n_vars; i++)
4342     {
4343       struct matrix_var *var = cmd->vars[i];
4344       gsl_matrix_free (var->value);
4345       var->value = NULL;
4346     }
4347 }
4348 \f
4349 static struct matrix_cmd *
4350 matrix_parse_save (struct matrix_state *s)
4351 {
4352   struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
4353   *cmd = (struct matrix_cmd) {
4354     .type = MCMD_SAVE,
4355     .save = {
4356       .strings = STRINGI_SET_INITIALIZER (cmd->save.strings)
4357     }
4358   };
4359
4360   struct save_command *save = &cmd->save;
4361   save->expression = matrix_parse_exp (s);
4362   if (!save->expression)
4363     goto error;
4364
4365   while (lex_match (s->lexer, T_SLASH))
4366     {
4367       if (lex_match_id (s->lexer, "OUTFILE"))
4368         {
4369           lex_match (s->lexer, T_EQUALS);
4370
4371           fh_unref (save->outfile);
4372           save->outfile = (lex_match (s->lexer, T_ASTERISK)
4373                            ? fh_inline_file ()
4374                            : fh_parse (s->lexer, FH_REF_FILE, s->session));
4375           if (!save->outfile)
4376             goto error;
4377         }
4378       else if (lex_match_id (s->lexer, "VARIABLES"))
4379         {
4380           lex_match (s->lexer, T_EQUALS);
4381
4382           char **names;
4383           size_t n;
4384           struct dictionary *d = dict_create (get_default_encoding ());
4385           bool ok = parse_DATA_LIST_vars (s->lexer, d, &names, &n,
4386                                           PV_NO_SCRATCH | PV_NO_DUPLICATE);
4387           dict_unref (d);
4388           if (!ok)
4389             goto error;
4390
4391           string_array_destroy (save->variables);
4392           if (!save->variables)
4393             save->variables = xmalloc (sizeof *save->variables);
4394           *save->variables = (struct string_array) {
4395             .strings = names,
4396             .n = n,
4397             .allocated = n,
4398           };
4399         }
4400       else if (lex_match_id (s->lexer, "NAMES"))
4401         {
4402           lex_match (s->lexer, T_EQUALS);
4403           matrix_expr_destroy (save->names);
4404           save->names = matrix_parse_exp (s);
4405           if (!save->names)
4406             goto error;
4407         }
4408       else if (lex_match_id (s->lexer, "STRINGS"))
4409         {
4410           lex_match (s->lexer, T_EQUALS);
4411           while (lex_token (s->lexer) == T_ID)
4412             {
4413               stringi_set_insert (&save->strings, lex_tokcstr (s->lexer));
4414               lex_get (s->lexer);
4415               if (!lex_match (s->lexer, T_COMMA))
4416                 break;
4417             }
4418         }
4419       else
4420         {
4421           lex_error_expecting (s->lexer, "OUTFILE", "VARIABLES", "NAMES",
4422                                "STRINGS");
4423           goto error;
4424         }
4425     }
4426
4427   if (!save->outfile)
4428     {
4429       if (s->prev_save_outfile)
4430         save->outfile = fh_ref (s->prev_save_outfile);
4431       else
4432         {
4433           lex_sbc_missing ("OUTFILE");
4434           goto error;
4435         }
4436     }
4437   fh_unref (s->prev_save_outfile);
4438   s->prev_save_outfile = fh_ref (save->outfile);
4439
4440   if (save->variables && save->names)
4441     {
4442       msg (SW, _("VARIABLES and NAMES both specified; ignoring NAMES."));
4443       matrix_expr_destroy (save->names);
4444       save->names = NULL;
4445     }
4446
4447   return cmd;
4448
4449 error:
4450   matrix_cmd_destroy (cmd);
4451   return NULL;
4452 }
4453
4454 static void
4455 matrix_cmd_execute_save (const struct save_command *save)
4456 {
4457   assert (save->outfile != fh_inline_file ()); /* XXX not yet implemented */
4458
4459   gsl_matrix *m = matrix_expr_evaluate (save->expression);
4460   if (!m)
4461     return;
4462
4463   bool ok = true;
4464   struct dictionary *dict = dict_create (get_default_encoding ());
4465   struct string_array names = { .n = 0 };
4466   if (save->variables)
4467     string_array_clone (&names, save->variables);
4468   else if (save->names)
4469     {
4470       gsl_matrix *nm = matrix_expr_evaluate (save->names);
4471       if (nm && is_vector (nm))
4472         {
4473           gsl_vector nv = to_vector (nm);
4474           for (size_t i = 0; i < nv.size; i++)
4475             {
4476               char *name = trimmed_string (gsl_vector_get (&nv, i));
4477               if (dict_id_is_valid (dict, name, true))
4478                 string_array_append_nocopy (&names, name);
4479               else
4480                 ok = false;
4481             }
4482         }
4483     }
4484
4485   struct stringi_set strings;
4486   stringi_set_clone (&strings, &save->strings);
4487
4488   for (size_t i = 0; dict_get_var_cnt (dict) < m->size2; i++)
4489     {
4490       char tmp_name[64];
4491       const char *name;
4492       if (i < names.n)
4493         name = names.strings[i];
4494       else
4495         {
4496           snprintf (tmp_name, sizeof tmp_name, "COL%zu", i + 1);
4497           name = tmp_name;
4498         }
4499
4500       int width = stringi_set_delete (&strings, name) ? 8 : 0;
4501       struct variable *var = dict_create_var (dict, name, width);
4502       if (!var)
4503         {
4504           msg (SE, _("Duplicate variable name %s in SAVE statement."),
4505                name);
4506           ok = false;
4507         }
4508     }
4509
4510   if (!stringi_set_is_empty (&strings))
4511     {
4512       const char *example = stringi_set_node_get_string (
4513         stringi_set_first (&strings));
4514       msg (SE, ngettext ("STRINGS specified a variable %s, but no variable "
4515                          "with that name was found on SAVE.",
4516                          "STRINGS specified %2$zu variables, including %1$s, "
4517                          "whose names were not found on SAVE.",
4518                          stringi_set_count (&strings)),
4519            example, stringi_set_count (&strings));
4520       ok = false;
4521     }
4522   stringi_set_destroy (&strings);
4523   string_array_destroy (&names);
4524
4525   if (!ok)
4526     {
4527       gsl_matrix_free (m);
4528       dict_unref (dict);
4529       return;
4530     }
4531
4532   struct casewriter *writer = any_writer_open (save->outfile, dict);
4533   if (!writer)
4534     {
4535       gsl_matrix_free (m);
4536       dict_unref (dict);
4537       return;
4538     }
4539
4540   const struct caseproto *proto = dict_get_proto (dict);
4541   for (size_t y = 0; y < m->size1; y++)
4542     {
4543       struct ccase *c = case_create (proto);
4544       for (size_t x = 0; x < m->size2; x++)
4545         {
4546           double d = gsl_matrix_get (m, y, x);
4547           int width = caseproto_get_width (proto, x);
4548           union value *value = case_data_rw_idx (c, x);
4549           if (width == 0)
4550             value->f = d;
4551           else
4552             memcpy (value->s, &d, width);
4553         }
4554       casewriter_write (writer, c);
4555     }
4556   casewriter_destroy (writer);
4557
4558   gsl_matrix_free (m);
4559   dict_unref (dict);
4560 }
4561 \f
4562 static struct matrix_cmd *
4563 matrix_parse_read (struct matrix_state *s)
4564 {
4565   struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
4566   *cmd = (struct matrix_cmd) {
4567     .type = MCMD_READ,
4568     .read = { .format = FMT_F },
4569   };
4570
4571   struct file_handle *fh = NULL;
4572   char *encoding = NULL;
4573   struct read_command *read = &cmd->read;
4574   read->dst = matrix_lvalue_parse (s);
4575   if (!read->dst)
4576     goto error;
4577
4578   int by = 0;
4579   int repetitions = 0;
4580   int record_width = 0;
4581   bool seen_format = false;
4582   while (lex_match (s->lexer, T_SLASH))
4583     {
4584       if (lex_match_id (s->lexer, "FILE"))
4585         {
4586           lex_match (s->lexer, T_EQUALS);
4587
4588           fh_unref (fh);
4589           fh = fh_parse (s->lexer, FH_REF_FILE, NULL);
4590           if (!fh)
4591             goto error;
4592         }
4593       else if (lex_match_id (s->lexer, "ENCODING"))
4594         {
4595           lex_match (s->lexer, T_EQUALS);
4596           if (!lex_force_string (s->lexer))
4597             goto error;
4598
4599           free (encoding);
4600           encoding = ss_xstrdup (lex_tokss (s->lexer));
4601
4602           lex_get (s->lexer);
4603         }
4604       else if (lex_match_id (s->lexer, "FIELD"))
4605         {
4606           lex_match (s->lexer, T_EQUALS);
4607
4608           if (!lex_force_int_range (s->lexer, "FIELD", 1, INT_MAX))
4609             goto error;
4610           read->c1 = lex_integer (s->lexer);
4611           lex_get (s->lexer);
4612           if (!lex_force_match (s->lexer, T_TO)
4613               || !lex_force_int_range (s->lexer, "TO", read->c1, INT_MAX))
4614             goto error;
4615           read->c2 = lex_integer (s->lexer) + 1;
4616           lex_get (s->lexer);
4617
4618           record_width = read->c2 - read->c1;
4619           if (lex_match (s->lexer, T_BY))
4620             {
4621               if (!lex_force_int_range (s->lexer, "BY", 1,
4622                                         read->c2 - read->c1))
4623                 goto error;
4624               by = lex_integer (s->lexer);
4625               lex_get (s->lexer);
4626
4627               if (record_width % by)
4628                 {
4629                   msg (SE, _("BY %d does not evenly divide record width %d."),
4630                        by, record_width);
4631                   goto error;
4632                 }
4633             }
4634           else
4635             by = 0;
4636         }
4637       else if (lex_match_id (s->lexer, "SIZE"))
4638         {
4639           lex_match (s->lexer, T_EQUALS);
4640           matrix_expr_destroy (read->size);
4641           read->size = matrix_parse_exp (s);
4642           if (!read->size)
4643             goto error;
4644         }
4645       else if (lex_match_id (s->lexer, "MODE"))
4646         {
4647           lex_match (s->lexer, T_EQUALS);
4648           if (lex_match_id (s->lexer, "RECTANGULAR"))
4649             read->symmetric = false;
4650           else if (lex_match_id (s->lexer, "SYMMETRIC"))
4651             read->symmetric = true;
4652           else
4653             {
4654               lex_error_expecting (s->lexer, "RECTANGULAR", "SYMMETRIC");
4655               goto error;
4656             }
4657         }
4658       else if (lex_match_id (s->lexer, "REREAD"))
4659         read->reread = true;
4660       else if (lex_match_id (s->lexer, "FORMAT"))
4661         {
4662           if (seen_format)
4663             {
4664               lex_sbc_only_once ("FORMAT");
4665               goto error;
4666             }
4667           seen_format = true;
4668
4669           lex_match (s->lexer, T_EQUALS);
4670
4671           if (lex_token (s->lexer) != T_STRING && !lex_force_id (s->lexer))
4672             goto error;
4673
4674           const char *p = lex_tokcstr (s->lexer);
4675           if (c_isdigit (p[0]))
4676             {
4677               repetitions = atoi (p);
4678               p += strspn (p, "0123456789");
4679               if (!fmt_from_name (p, &read->format))
4680                 {
4681                   lex_error (s->lexer, _("Unknown format %s."), p);
4682                   goto error;
4683                 }
4684               lex_get (s->lexer);
4685             }
4686           else if (fmt_from_name (p, &read->format))
4687             lex_get (s->lexer);
4688           else
4689             {
4690               struct fmt_spec format;
4691               if (!parse_format_specifier (s->lexer, &format))
4692                 goto error;
4693               read->format = format.type;
4694               read->w = format.w;
4695             }
4696         }
4697       else
4698         {
4699           lex_error_expecting (s->lexer, "FILE", "FIELD", "MODE",
4700                                "REREAD", "FORMAT");
4701           goto error;
4702         }
4703     }
4704
4705   if (!read->c1)
4706     {
4707       lex_sbc_missing ("FIELD");
4708       goto error;
4709     }
4710
4711   if (!read->dst->n_indexes && !read->size)
4712     {
4713       msg (SE, _("SIZE is required for reading data into a full matrix "
4714                  "(as opposed to a submatrix)."));
4715       goto error;
4716     }
4717
4718   if (!fh)
4719     {
4720       if (s->prev_read_file)
4721         fh = fh_ref (s->prev_read_file);
4722       else
4723         {
4724           lex_sbc_missing ("FILE");
4725           goto error;
4726         }
4727     }
4728   fh_unref (s->prev_read_file);
4729   s->prev_read_file = fh_ref (fh);
4730
4731   read->rf = read_file_create (s, fh);
4732   fh = NULL;
4733   if (encoding)
4734     {
4735       free (read->rf->encoding);
4736       read->rf->encoding = encoding;
4737       encoding = NULL;
4738     }
4739
4740   /* Field width may be specified in multiple ways:
4741
4742      1. BY on FIELD.
4743      2. The format on FORMAT.
4744      3. The repetition factor on FORMAT.
4745
4746      (2) and (3) are mutually exclusive.
4747
4748      If more than one of these is present, they must agree.  If none of them is
4749      present, then free-field format is used.
4750    */
4751   if (repetitions > record_width)
4752     {
4753       msg (SE, _("%d repetitions cannot fit in record width %d."),
4754            repetitions, record_width);
4755       goto error;
4756     }
4757   int w = (repetitions ? record_width / repetitions
4758            : read->w ? read->w
4759            : by);
4760   if (by && w != by)
4761     {
4762       if (repetitions)
4763         msg (SE, _("FORMAT specifies %d repetitions with record width %d, "
4764                    "which implies field width %d, "
4765                    "but BY specifies field width %d."),
4766              repetitions, record_width, w, by);
4767       else
4768         msg (SE, _("FORMAT specifies field width %d but BY specifies %d."),
4769              w, by);
4770       goto error;
4771     }
4772   read->w = w;
4773   return cmd;
4774
4775 error:
4776   fh_unref (fh);
4777   matrix_cmd_destroy (cmd);
4778   free (encoding);
4779   return NULL;
4780 }
4781
4782 static void
4783 parse_error (const struct dfm_reader *reader, enum fmt_type format,
4784              struct substring data, size_t y, size_t x,
4785              int first_column, int last_column, char *error)
4786 {
4787   int line_number = dfm_get_line_number (reader);
4788   struct msg_location *location = xmalloc (sizeof *location);
4789   *location = (struct msg_location) {
4790     .file_name = xstrdup (dfm_get_file_name (reader)),
4791     .first_line = line_number,
4792     .last_line = line_number + 1,
4793     .first_column = first_column,
4794     .last_column = last_column,
4795   };
4796   struct msg *m = xmalloc (sizeof *m);
4797   *m = (struct msg) {
4798     .category = MSG_C_DATA,
4799     .severity = MSG_S_WARNING,
4800     .location = location,
4801     .text = xasprintf (_("Error reading \"%.*s\" as format %s "
4802                          "for matrix row %zu, column %zu: %s"),
4803                        (int) data.length, data.string, fmt_name (format),
4804                        y + 1, x + 1, error),
4805   };
4806   msg_emit (m);
4807
4808   free (error);
4809 }
4810
4811 static void
4812 matrix_read_set_field (struct read_command *read, struct dfm_reader *reader,
4813                        gsl_matrix *m, struct substring p, size_t y, size_t x,
4814                        const char *line_start)
4815 {
4816   const char *input_encoding = dfm_reader_get_encoding (reader);
4817   char *error;
4818   double f;
4819   if (fmt_is_numeric (read->format))
4820     {
4821       union value v;
4822       error = data_in (p, input_encoding, read->format,
4823                        settings_get_fmt_settings (), &v, 0, NULL);
4824       if (!error && v.f == SYSMIS)
4825         error = xstrdup (_("Matrix data may not contain missing value."));
4826       f = v.f;
4827     }
4828     else
4829       {
4830         uint8_t s[sizeof (double)];
4831         union value v = { .s = s };
4832         error = data_in (p, input_encoding, read->format,
4833                          settings_get_fmt_settings (), &v, sizeof s, "UTF-8");
4834         memcpy (&f, s, sizeof f);
4835       }
4836
4837   if (error)
4838     {
4839       int c1 = utf8_count_columns (line_start, p.string - line_start) + 1;
4840       int c2 = c1 + ss_utf8_count_columns (p) - 1;
4841       parse_error (reader, read->format, p, y, x, c1, c2, error);
4842     }
4843   else
4844     {
4845       gsl_matrix_set (m, y, x, f);
4846       if (read->symmetric && x != y)
4847         gsl_matrix_set (m, x, y, f);
4848     }
4849 }
4850
4851 static bool
4852 matrix_read_line (struct read_command *read, struct dfm_reader *reader,
4853                   struct substring *line, const char **startp)
4854 {
4855   if (dfm_eof (reader))
4856     {
4857       msg (SE, _("Unexpected end of file reading matrix data."));
4858       return false;
4859     }
4860   dfm_expand_tabs (reader);
4861   struct substring record = dfm_get_record (reader);
4862   /* XXX need to recode record into UTF-8 */
4863   *startp = record.string;
4864   *line = ss_utf8_columns (record, read->c1 - 1, read->c2 - read->c1);
4865   return true;
4866 }
4867
4868 static void
4869 matrix_read (struct read_command *read, struct dfm_reader *reader,
4870              gsl_matrix *m)
4871 {
4872   for (size_t y = 0; y < m->size1; y++)
4873     {
4874       size_t nx = read->symmetric ? y + 1 : m->size2;
4875
4876       struct substring line = ss_empty ();
4877       const char *line_start = line.string;
4878       for (size_t x = 0; x < nx; x++)
4879         {
4880           struct substring p;
4881           if (!read->w)
4882             {
4883               for (;;)
4884                 {
4885                   ss_ltrim (&line, ss_cstr (" ,"));
4886                   if (!ss_is_empty (line))
4887                     break;
4888                   if (!matrix_read_line (read, reader, &line, &line_start))
4889                     return;
4890                   dfm_forward_record (reader);
4891                 }
4892
4893               ss_get_bytes (&line, ss_cspan (line, ss_cstr (" ,")), &p);
4894             }
4895           else
4896             {
4897               if (!matrix_read_line (read, reader, &line, &line_start))
4898                 return;
4899               size_t fields_per_line = (read->c2 - read->c1) / read->w;
4900               int f = x % fields_per_line;
4901               if (f == fields_per_line - 1)
4902                 dfm_forward_record (reader);
4903
4904               p = ss_substr (line, read->w * f, read->w);
4905             }
4906
4907           matrix_read_set_field (read, reader, m, p, y, x, line_start);
4908         }
4909
4910       if (read->w)
4911         dfm_forward_record (reader);
4912       else
4913         {
4914           ss_ltrim (&line, ss_cstr (" ,"));
4915           if (!ss_is_empty (line))
4916             {
4917               /* XXX */
4918               msg (SW, _("Trailing garbage on line \"%.*s\""),
4919                    (int) line.length, line.string);
4920             }
4921         }
4922     }
4923 }
4924
4925 static void
4926 matrix_cmd_execute_read (struct read_command *read)
4927 {
4928   struct index_vector iv0, iv1;
4929   if (!matrix_lvalue_evaluate (read->dst, &iv0, &iv1))
4930     return;
4931
4932   size_t size[2] = { SIZE_MAX, SIZE_MAX };
4933   if (read->size)
4934     {
4935       gsl_matrix *m = matrix_expr_evaluate (read->size);
4936       if (!m)
4937         return;
4938
4939       if (!is_vector (m))
4940         {
4941           msg (SE, _("SIZE must evaluate to a scalar or a 2-element vector, "
4942                      "not a %zu×%zu matrix."), m->size1, m->size2);
4943           gsl_matrix_free (m);
4944           free (iv0.indexes);
4945           free (iv1.indexes);
4946           return;
4947         }
4948
4949       gsl_vector v = to_vector (m);
4950       double d[2];
4951       if (v.size == 1)
4952         {
4953           d[0] = gsl_vector_get (&v, 0);
4954           d[1] = 1;
4955         }
4956       else if (v.size == 2)
4957         {
4958           d[0] = gsl_vector_get (&v, 0);
4959           d[1] = gsl_vector_get (&v, 1);
4960         }
4961       else
4962         {
4963           msg (SE, _("SIZE must evaluate to a scalar or a 2-element vector, "
4964                      "not a %zu×%zu matrix."),
4965                m->size1, m->size2),
4966           gsl_matrix_free (m);
4967           free (iv0.indexes);
4968           free (iv1.indexes);
4969           return;
4970         }
4971       gsl_matrix_free (m);
4972
4973       if (d[0] < 0 || d[0] > SIZE_MAX || d[1] < 0 || d[1] > SIZE_MAX)
4974         {
4975           msg (SE, _("Matrix dimensions %g×%g specified on SIZE "
4976                      "are outside valid range."),
4977                d[0], d[1]);
4978           free (iv0.indexes);
4979           free (iv1.indexes);
4980           return;
4981         }
4982
4983       size[0] = d[0];
4984       size[1] = d[1];
4985     }
4986
4987   if (read->dst->n_indexes)
4988     {
4989       size_t submatrix_size[2];
4990       if (read->dst->n_indexes == 2)
4991         {
4992           submatrix_size[0] = iv0.n;
4993           submatrix_size[1] = iv1.n;
4994         }
4995       else if (read->dst->var->value->size1 == 1)
4996         {
4997           submatrix_size[0] = 1;
4998           submatrix_size[1] = iv0.n;
4999         }
5000       else
5001         {
5002           submatrix_size[0] = iv0.n;
5003           submatrix_size[1] = 1;
5004         }
5005
5006       if (read->size)
5007         {
5008           if (size[0] != submatrix_size[0] || size[1] != submatrix_size[1])
5009             {
5010               msg (SE, _("Matrix dimensions %zu×%zu specified on SIZE "
5011                          "differ from submatrix dimensions %zu×%zu."),
5012                    size[0], size[1],
5013                    submatrix_size[0], submatrix_size[1]);
5014               free (iv0.indexes);
5015               free (iv1.indexes);
5016               return;
5017             }
5018         }
5019       else
5020         {
5021           size[0] = submatrix_size[0];
5022           size[1] = submatrix_size[1];
5023         }
5024     }
5025
5026   struct dfm_reader *reader = read_file_open (read->rf);
5027   if (read->reread)
5028     dfm_reread_record (reader, 1);
5029
5030   if (read->symmetric && size[0] != size[1])
5031     {
5032       msg (SE, _("Cannot read non-square %zu×%zu matrix "
5033                  "using READ with MODE=SYMMETRIC."),
5034            size[0], size[1]);
5035       free (iv0.indexes);
5036       free (iv1.indexes);
5037       return;
5038     }
5039   gsl_matrix *tmp = gsl_matrix_calloc (size[0], size[1]);
5040   matrix_read (read, reader, tmp);
5041   matrix_lvalue_assign (read->dst, &iv0, &iv1, tmp);
5042 }
5043 \f
5044 static struct matrix_cmd *
5045 matrix_parse_write (struct matrix_state *s)
5046 {
5047   struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
5048   *cmd = (struct matrix_cmd) {
5049     .type = MCMD_WRITE,
5050   };
5051
5052   struct file_handle *fh = NULL;
5053   char *encoding = NULL;
5054   struct write_command *write = &cmd->write;
5055   write->expression = matrix_parse_exp (s);
5056   if (!write->expression)
5057     goto error;
5058
5059   int by = 0;
5060   int repetitions = 0;
5061   int record_width = 0;
5062   enum fmt_type format = FMT_F;
5063   bool has_format = false;
5064   while (lex_match (s->lexer, T_SLASH))
5065     {
5066       if (lex_match_id (s->lexer, "OUTFILE"))
5067         {
5068           lex_match (s->lexer, T_EQUALS);
5069
5070           fh_unref (fh);
5071           fh = fh_parse (s->lexer, FH_REF_FILE, NULL);
5072           if (!fh)
5073             goto error;
5074         }
5075       else if (lex_match_id (s->lexer, "ENCODING"))
5076         {
5077           lex_match (s->lexer, T_EQUALS);
5078           if (!lex_force_string (s->lexer))
5079             goto error;
5080
5081           free (encoding);
5082           encoding = ss_xstrdup (lex_tokss (s->lexer));
5083
5084           lex_get (s->lexer);
5085         }
5086       else if (lex_match_id (s->lexer, "FIELD"))
5087         {
5088           lex_match (s->lexer, T_EQUALS);
5089
5090           if (!lex_force_int_range (s->lexer, "FIELD", 1, INT_MAX))
5091             goto error;
5092           write->c1 = lex_integer (s->lexer);
5093           lex_get (s->lexer);
5094           if (!lex_force_match (s->lexer, T_TO)
5095               || !lex_force_int_range (s->lexer, "TO", write->c1, INT_MAX))
5096             goto error;
5097           write->c2 = lex_integer (s->lexer) + 1;
5098           lex_get (s->lexer);
5099
5100           record_width = write->c2 - write->c1;
5101           if (lex_match (s->lexer, T_BY))
5102             {
5103               if (!lex_force_int_range (s->lexer, "BY", 1,
5104                                         write->c2 - write->c1))
5105                 goto error;
5106               by = lex_integer (s->lexer);
5107               lex_get (s->lexer);
5108
5109               if (record_width % by)
5110                 {
5111                   msg (SE, _("BY %d does not evenly divide record width %d."),
5112                        by, record_width);
5113                   goto error;
5114                 }
5115             }
5116           else
5117             by = 0;
5118         }
5119       else if (lex_match_id (s->lexer, "MODE"))
5120         {
5121           lex_match (s->lexer, T_EQUALS);
5122           if (lex_match_id (s->lexer, "RECTANGULAR"))
5123             write->triangular = false;
5124           else if (lex_match_id (s->lexer, "TRIANGULAR"))
5125             write->triangular = true;
5126           else
5127             {
5128               lex_error_expecting (s->lexer, "RECTANGULAR", "TRIANGULAR");
5129               goto error;
5130             }
5131         }
5132       else if (lex_match_id (s->lexer, "HOLD"))
5133         write->hold = true;
5134       else if (lex_match_id (s->lexer, "FORMAT"))
5135         {
5136           if (has_format || write->format)
5137             {
5138               lex_sbc_only_once ("FORMAT");
5139               goto error;
5140             }
5141
5142           lex_match (s->lexer, T_EQUALS);
5143
5144           if (lex_token (s->lexer) != T_STRING && !lex_force_id (s->lexer))
5145             goto error;
5146
5147           const char *p = lex_tokcstr (s->lexer);
5148           if (c_isdigit (p[0]))
5149             {
5150               repetitions = atoi (p);
5151               p += strspn (p, "0123456789");
5152               if (!fmt_from_name (p, &format))
5153                 {
5154                   lex_error (s->lexer, _("Unknown format %s."), p);
5155                   goto error;
5156                 }
5157               has_format = true;
5158               lex_get (s->lexer);
5159             }
5160           else if (fmt_from_name (p, &format))
5161             {
5162               has_format = true;
5163               lex_get (s->lexer);
5164             }
5165           else
5166             {
5167               struct fmt_spec spec;
5168               if (!parse_format_specifier (s->lexer, &spec))
5169                 goto error;
5170               write->format = xmemdup (&spec, sizeof spec);
5171             }
5172         }
5173       else
5174         {
5175           lex_error_expecting (s->lexer, "OUTFILE", "FIELD", "MODE",
5176                                "HOLD", "FORMAT");
5177           goto error;
5178         }
5179     }
5180
5181   if (!write->c1)
5182     {
5183       lex_sbc_missing ("FIELD");
5184       goto error;
5185     }
5186
5187   if (!fh)
5188     {
5189       if (s->prev_write_file)
5190         fh = fh_ref (s->prev_write_file);
5191       else
5192         {
5193           lex_sbc_missing ("OUTFILE");
5194           goto error;
5195         }
5196     }
5197   fh_unref (s->prev_write_file);
5198   s->prev_write_file = fh_ref (fh);
5199
5200   write->wf = write_file_create (s, fh);
5201   fh = NULL;
5202   if (encoding)
5203     {
5204       free (write->wf->encoding);
5205       write->wf->encoding = encoding;
5206       encoding = NULL;
5207     }
5208
5209   /* Field width may be specified in multiple ways:
5210
5211      1. BY on FIELD.
5212      2. The format on FORMAT.
5213      3. The repetition factor on FORMAT.
5214
5215      (2) and (3) are mutually exclusive.
5216
5217      If more than one of these is present, they must agree.  If none of them is
5218      present, then free-field format is used.
5219    */
5220   if (repetitions > record_width)
5221     {
5222       msg (SE, _("%d repetitions cannot fit in record width %d."),
5223            repetitions, record_width);
5224       goto error;
5225     }
5226   int w = (repetitions ? record_width / repetitions
5227            : write->format ? write->format->w
5228            : by);
5229   if (by && w != by)
5230     {
5231       if (repetitions)
5232         msg (SE, _("FORMAT specifies %d repetitions with record width %d, "
5233                    "which implies field width %d, "
5234                    "but BY specifies field width %d."),
5235              repetitions, record_width, w, by);
5236       else
5237         msg (SE, _("FORMAT specifies field width %d but BY specifies %d."),
5238              w, by);
5239       goto error;
5240     }
5241   if (w && !write->format)
5242     {
5243       write->format = xmalloc (sizeof *write->format);
5244       *write->format = (struct fmt_spec) { .type = format, .w = w };
5245
5246       if (!fmt_check_output (write->format))
5247         goto error;
5248     };
5249
5250   if (write->format && fmt_var_width (write->format) > sizeof (double))
5251     {
5252       char s[FMT_STRING_LEN_MAX + 1];
5253       fmt_to_string (write->format, s);
5254       msg (SE, _("Format %s is too wide for %zu-byte matrix eleemnts."),
5255            s, sizeof (double));
5256       goto error;
5257     }
5258
5259   return cmd;
5260
5261 error:
5262   fh_unref (fh);
5263   matrix_cmd_destroy (cmd);
5264   return NULL;
5265 }
5266
5267 static void
5268 matrix_cmd_execute_write (struct write_command *write)
5269 {
5270   gsl_matrix *m = matrix_expr_evaluate (write->expression);
5271   if (!m)
5272     return;
5273
5274   if (write->triangular && m->size1 != m->size2)
5275     {
5276       msg (SE, _("WRITE with MODE=TRIANGULAR requires a square matrix but "
5277                  "the matrix to be written has dimensions %zu×%zu."),
5278            m->size1, m->size2);
5279       gsl_matrix_free (m);
5280       return;
5281     }
5282
5283   struct dfm_writer *writer = write_file_open (write->wf);
5284   if (!writer || !m->size1)
5285     {
5286       gsl_matrix_free (m);
5287       return;
5288     }
5289
5290   const struct fmt_settings *settings = settings_get_fmt_settings ();
5291   struct u8_line *line = write->wf->held;
5292   for (size_t y = 0; y < m->size1; y++)
5293     {
5294       if (!line)
5295         {
5296           line = xmalloc (sizeof *line);
5297           u8_line_init (line);
5298         }
5299       size_t nx = write->triangular ? y + 1 : m->size2;
5300       int x0 = write->c1;
5301       for (size_t x = 0; x < nx; x++)
5302         {
5303           char *s;
5304           double f = gsl_matrix_get (m, y, x);
5305           if (write->format)
5306             {
5307               union value v;
5308               if (fmt_is_numeric (write->format->type))
5309                 v.f = f;
5310               else
5311                 v.s = (uint8_t *) &f;
5312               s = data_out (&v, NULL, write->format, settings);
5313             }
5314           else
5315             {
5316               s = xmalloc (DBL_BUFSIZE_BOUND);
5317               if (c_dtoastr (s, DBL_BUFSIZE_BOUND, FTOASTR_UPPER_E, 0, f)
5318                   >= DBL_BUFSIZE_BOUND)
5319                 abort ();
5320             }
5321           size_t len = strlen (s);
5322           int width = u8_width (CHAR_CAST (const uint8_t *, s), len, UTF8);
5323           if (width + x0 > write->c2)
5324             {
5325               dfm_put_record_utf8 (writer, line->s.ss.string,
5326                                    line->s.ss.length);
5327               u8_line_clear (line);
5328               x0 = write->c1;
5329             }
5330           u8_line_put (line, x0, x0 + width, s, len);
5331           free (s);
5332
5333           x0 += write->format ? write->format->w : width + 1;
5334         }
5335
5336       if (y + 1 >= m->size1 && write->hold)
5337         break;
5338       dfm_put_record_utf8 (writer, line->s.ss.string, line->s.ss.length);
5339       u8_line_clear (line);
5340     }
5341   if (!write->hold)
5342     {
5343       u8_line_destroy (line);
5344       free (line);
5345       line = NULL;
5346     }
5347   write->wf->held = line;
5348
5349   gsl_matrix_free (m);
5350 }
5351 \f
5352 static struct matrix_cmd *
5353 matrix_parse_get (struct matrix_state *s)
5354 {
5355   struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
5356   *cmd = (struct matrix_cmd) {
5357     .type = MCMD_GET,
5358     .get = {
5359       .dataset = s->dataset,
5360       .user = { .treatment = MGET_ERROR },
5361       .system = { .treatment = MGET_ERROR },
5362     }
5363   };
5364
5365   struct get_command *get = &cmd->get;
5366   get->dst = matrix_lvalue_parse (s);
5367   if (!get->dst)
5368     goto error;
5369
5370   while (lex_match (s->lexer, T_SLASH))
5371     {
5372       if (lex_match_id (s->lexer, "FILE"))
5373         {
5374           lex_match (s->lexer, T_EQUALS);
5375
5376           fh_unref (get->file);
5377           if (lex_match (s->lexer, T_ASTERISK))
5378             get->file = NULL;
5379           else
5380             {
5381               get->file = fh_parse (s->lexer, FH_REF_FILE, s->session);
5382               if (!get->file)
5383                 goto error;
5384             }
5385         }
5386       else if (lex_match_id (s->lexer, "ENCODING"))
5387         {
5388           lex_match (s->lexer, T_EQUALS);
5389           if (!lex_force_string (s->lexer))
5390             goto error;
5391
5392           free (get->encoding);
5393           get->encoding = ss_xstrdup (lex_tokss (s->lexer));
5394
5395           lex_get (s->lexer);
5396         }
5397       else if (lex_match_id (s->lexer, "VARIABLES"))
5398         {
5399           lex_match (s->lexer, T_EQUALS);
5400
5401           if (get->n_vars)
5402             {
5403               lex_sbc_only_once ("VARIABLES");
5404               goto error;
5405             }
5406
5407           if (!var_syntax_parse (s->lexer, &get->vars, &get->n_vars))
5408             goto error;
5409         }
5410       else if (lex_match_id (s->lexer, "NAMES"))
5411         {
5412           lex_match (s->lexer, T_EQUALS);
5413           if (!lex_force_id (s->lexer))
5414             goto error;
5415
5416           struct substring name = lex_tokss (s->lexer);
5417           get->names = matrix_var_lookup (s, name);
5418           if (!get->names)
5419             get->names = matrix_var_create (s, name);
5420           lex_get (s->lexer);
5421         }
5422       else if (lex_match_id (s->lexer, "MISSING"))
5423         {
5424           lex_match (s->lexer, T_EQUALS);
5425           if (lex_match_id (s->lexer, "ACCEPT"))
5426             get->user.treatment = MGET_ACCEPT;
5427           else if (lex_match_id (s->lexer, "OMIT"))
5428             get->user.treatment = MGET_OMIT;
5429           else if (lex_is_number (s->lexer))
5430             {
5431               get->user.treatment = MGET_RECODE;
5432               get->user.substitute = lex_number (s->lexer);
5433               lex_get (s->lexer);
5434             }
5435           else
5436             {
5437               lex_error (s->lexer, NULL);
5438               goto error;
5439             }
5440         }
5441       else if (lex_match_id (s->lexer, "SYSMIS"))
5442         {
5443           lex_match (s->lexer, T_EQUALS);
5444           if (lex_match_id (s->lexer, "OMIT"))
5445             get->system.treatment = MGET_OMIT;
5446           else if (lex_is_number (s->lexer))
5447             {
5448               get->system.treatment = MGET_RECODE;
5449               get->system.substitute = lex_number (s->lexer);
5450               lex_get (s->lexer);
5451             }
5452           else
5453             {
5454               lex_error (s->lexer, NULL);
5455               goto error;
5456             }
5457         }
5458       else
5459         {
5460           lex_error_expecting (s->lexer, "FILE", "VARIABLES", "NAMES",
5461                                "MISSING", "SYSMIS");
5462           goto error;
5463         }
5464     }
5465
5466   if (get->user.treatment != MGET_ACCEPT)
5467     get->system.treatment = MGET_ERROR;
5468
5469   return cmd;
5470
5471 error:
5472   matrix_cmd_destroy (cmd);
5473   return NULL;
5474 }
5475
5476 static void
5477 matrix_cmd_execute_get__ (struct get_command *get,
5478                           const struct dictionary *dict,
5479                           struct casereader *reader)
5480 {
5481   struct variable **vars;
5482   size_t n_vars = 0;
5483
5484   if (get->n_vars)
5485     {
5486       if (!var_syntax_evaluate (get->vars, get->n_vars, dict,
5487                                 &vars, &n_vars, PV_NUMERIC))
5488         return;
5489     }
5490   else
5491     {
5492       n_vars = dict_get_var_cnt (dict);
5493       vars = xnmalloc (n_vars, sizeof *vars);
5494       for (size_t i = 0; i < n_vars; i++)
5495         {
5496           struct variable *var = dict_get_var (dict, i);
5497           if (!var_is_numeric (var))
5498             {
5499               msg (SE, _("GET: Variable %s is not numeric."),
5500                    var_get_name (var));
5501               free (vars);
5502               return;
5503             }
5504           vars[i] = var;
5505         }
5506     }
5507
5508   if (get->names)
5509     {
5510       gsl_matrix *names = gsl_matrix_alloc (n_vars, 1);
5511       for (size_t i = 0; i < n_vars; i++)
5512         {
5513           char s[sizeof (double)];
5514           double f;
5515           buf_copy_str_rpad (s, sizeof s, var_get_name (vars[i]), ' ');
5516           memcpy (&f, s, sizeof f);
5517           gsl_matrix_set (names, i, 0, f);
5518         }
5519
5520       gsl_matrix_free (get->names->value);
5521       get->names->value = names;
5522     }
5523
5524   size_t n_rows = 0;
5525   gsl_matrix *m = gsl_matrix_alloc (4, n_vars);
5526   long long int casenum = 1;
5527   bool error = false;
5528   for (struct ccase *c = casereader_read (reader); c;
5529        c = casereader_read (reader), casenum++)
5530     {
5531       if (n_rows >= m->size1)
5532         {
5533           gsl_matrix *p = gsl_matrix_alloc (m->size1 * 2, n_vars);
5534           for (size_t y = 0; y < n_rows; y++)
5535             for (size_t x = 0; x < n_vars; x++)
5536               gsl_matrix_set (p, y, x, gsl_matrix_get (m, y, x));
5537           gsl_matrix_free (m);
5538           m = p;
5539         }
5540
5541       bool keep = true;
5542       for (size_t x = 0; x < n_vars; x++)
5543         {
5544           const struct variable *var = vars[x];
5545           double d = case_num (c, var);
5546           if (d == SYSMIS)
5547             {
5548               if (get->system.treatment == MGET_RECODE)
5549                 d = get->system.substitute;
5550               else if (get->system.treatment == MGET_OMIT)
5551                 keep = false;
5552               else
5553                 {
5554                   msg (SE, _("GET: Variable %s in case %lld "
5555                              "is system-missing."),
5556                        var_get_name (var), casenum);
5557                   error = true;
5558                 }
5559             }
5560           else if (var_is_num_missing (var, d, MV_USER))
5561             {
5562               if (get->user.treatment == MGET_RECODE)
5563                 d = get->user.substitute;
5564               else if (get->user.treatment == MGET_OMIT)
5565                 keep = false;
5566               else if (get->user.treatment != MGET_ACCEPT)
5567                 {
5568                   msg (SE, _("GET: Variable %s in case %lld has user-missing "
5569                              "value %g."),
5570                        var_get_name (var), casenum, d);
5571                   error = true;
5572                 }
5573             }
5574           gsl_matrix_set (m, n_rows, x, d);
5575         }
5576       case_unref (c);
5577       if (error)
5578         break;
5579       if (keep)
5580         n_rows++;
5581     }
5582   if (!error)
5583     {
5584       m->size1 = n_rows;
5585       matrix_lvalue_evaluate_and_assign (get->dst, m);
5586     }
5587   else
5588     gsl_matrix_free (m);
5589   free (vars);
5590 }
5591
5592 static void
5593 matrix_cmd_execute_get (struct get_command *get)
5594 {
5595   struct dictionary *dict;
5596   struct casereader *reader;
5597   if (get->file)
5598     {
5599        reader = any_reader_open_and_decode (get->file, get->encoding,
5600                                             &dict, NULL);
5601        if (!reader)
5602          return;
5603     }
5604   else
5605     {
5606       if (dict_get_var_cnt (dataset_dict (get->dataset)) == 0)
5607         {
5608           msg (ME, _("GET cannot read empty active file."));
5609           return;
5610         }
5611       reader = proc_open (get->dataset);
5612       dict = dict_ref (dataset_dict (get->dataset));
5613     }
5614
5615   matrix_cmd_execute_get__ (get, dict, reader);
5616
5617   dict_unref (dict);
5618   casereader_destroy (reader);
5619   if (!get->file)
5620     proc_commit (get->dataset);
5621 }
5622 \f
5623 static const char *
5624 match_rowtype (struct lexer *lexer)
5625 {
5626   static const char *rowtypes[] = {
5627     "COV", "CORR", "MEAN", "STDDEV", "N", "COUNT"
5628   };
5629   size_t n_rowtypes = sizeof rowtypes / sizeof *rowtypes;
5630
5631   for (size_t i = 0; i < n_rowtypes; i++)
5632     if (lex_match_id (lexer, rowtypes[i]))
5633       return rowtypes[i];
5634
5635   lex_error_expecting_array (lexer, rowtypes, n_rowtypes);
5636   return NULL;
5637 }
5638
5639 static bool
5640 parse_var_names (struct lexer *lexer, struct string_array *sa)
5641 {
5642   lex_match (lexer, T_EQUALS);
5643
5644   string_array_clear (sa);
5645
5646   struct dictionary *dict = dict_create (get_default_encoding ());
5647   dict_create_var_assert (dict, "ROWTYPE_", 8);
5648   dict_create_var_assert (dict, "VARNAME_", 8);
5649   char **names;
5650   size_t n_names;
5651   bool ok = parse_DATA_LIST_vars (lexer, dict, &names, &n_names,
5652                                   PV_NO_DUPLICATE | PV_NO_SCRATCH);
5653   dict_unref (dict);
5654
5655   if (ok)
5656     {
5657       string_array_clear (sa);
5658       sa->strings = names;
5659       sa->n = sa->allocated = n_names;
5660     }
5661   return ok;
5662 }
5663
5664 static void
5665 msave_common_uninit (struct msave_common *common)
5666 {
5667   if (common)
5668     {
5669       fh_unref (common->outfile);
5670       string_array_destroy (&common->variables);
5671       string_array_destroy (&common->fnames);
5672       string_array_destroy (&common->snames);
5673     }
5674 }
5675
5676 static bool
5677 compare_variables (const char *keyword,
5678                    const struct string_array *new,
5679                    const struct string_array *old)
5680 {
5681   if (new->n)
5682     {
5683       if (!old->n)
5684         {
5685           msg (SE, _("%s may only be specified on MSAVE if it was specified "
5686                      "on the first MSAVE within MATRIX."), keyword);
5687           return false;
5688         }
5689       else if (!string_array_equal_case (old, new))
5690         {
5691           msg (SE, _("%s must specify the same variables each time within "
5692                      "a given MATRIX."), keyword);
5693           return false;
5694         }
5695     }
5696   return true;
5697 }
5698
5699 static struct matrix_cmd *
5700 matrix_parse_msave (struct matrix_state *s)
5701 {
5702   struct msave_common common = { .outfile = NULL };
5703   struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
5704   *cmd = (struct matrix_cmd) { .type = MCMD_MSAVE, .msave = { .expr = NULL } };
5705
5706   struct msave_command *msave = &cmd->msave;
5707   if (lex_token (s->lexer) == T_ID)
5708     msave->varname_ = ss_xstrdup (lex_tokss (s->lexer));
5709   msave->expr = matrix_parse_exp (s);
5710   if (!msave->expr)
5711     return NULL;
5712
5713   while (lex_match (s->lexer, T_SLASH))
5714     {
5715       if (lex_match_id (s->lexer, "TYPE"))
5716         {
5717           lex_match (s->lexer, T_EQUALS);
5718
5719           msave->rowtype = match_rowtype (s->lexer);
5720           if (!msave->rowtype)
5721             goto error;
5722         }
5723       else if (lex_match_id (s->lexer, "OUTFILE"))
5724         {
5725           lex_match (s->lexer, T_EQUALS);
5726
5727           fh_unref (common.outfile);
5728           common.outfile = fh_parse (s->lexer, FH_REF_FILE, NULL);
5729           if (!common.outfile)
5730             goto error;
5731         }
5732       else if (lex_match_id (s->lexer, "VARIABLES"))
5733         {
5734           if (!parse_var_names (s->lexer, &common.variables))
5735             goto error;
5736         }
5737       else if (lex_match_id (s->lexer, "FNAMES"))
5738         {
5739           if (!parse_var_names (s->lexer, &common.fnames))
5740             goto error;
5741         }
5742       else if (lex_match_id (s->lexer, "SNAMES"))
5743         {
5744           if (!parse_var_names (s->lexer, &common.snames))
5745             goto error;
5746         }
5747       else if (lex_match_id (s->lexer, "SPLIT"))
5748         {
5749           lex_match (s->lexer, T_EQUALS);
5750
5751           matrix_expr_destroy (msave->splits);
5752           msave->splits = matrix_parse_exp (s);
5753           if (!msave->splits)
5754             goto error;
5755         }
5756       else if (lex_match_id (s->lexer, "FACTOR"))
5757         {
5758           lex_match (s->lexer, T_EQUALS);
5759
5760           matrix_expr_destroy (msave->factors);
5761           msave->factors = matrix_parse_exp (s);
5762           if (!msave->factors)
5763             goto error;
5764         }
5765       else
5766         {
5767           lex_error_expecting (s->lexer, "TYPE", "OUTFILE", "VARIABLES",
5768                                "FNAMES", "SNAMES", "SPLIT", "FACTOR");
5769           goto error;
5770         }
5771     }
5772   if (!msave->rowtype)
5773     {
5774       lex_sbc_missing ("TYPE");
5775       goto error;
5776     }
5777   common.has_splits = msave->splits || common.snames.n;
5778   common.has_factors = msave->factors || common.fnames.n;
5779
5780   struct msave_common *c = s->common ? s->common : &common;
5781   if (c->fnames.n && !msave->factors)
5782     {
5783       msg (SE, _("FNAMES requires FACTOR."));
5784       goto error;
5785     }
5786   if (c->snames.n && !msave->splits)
5787     {
5788       msg (SE, _("SNAMES requires SPLIT."));
5789       goto error;
5790     }
5791   if (c->has_factors && !common.has_factors)
5792     {
5793       msg (SE, _("%s is required because it was present on the first "
5794                  "MSAVE in this MATRIX command."), "FACTOR");
5795       goto error;
5796     }
5797   if (c->has_splits && !common.has_splits)
5798     {
5799       msg (SE, _("%s is required because it was present on the first "
5800                  "MSAVE in this MATRIX command."), "SPLIT");
5801       goto error;
5802     }
5803
5804   if (!s->common)
5805     {
5806       if (!common.outfile)
5807         {
5808           lex_sbc_missing ("OUTFILE");
5809           goto error;
5810         }
5811       s->common = xmemdup (&common, sizeof common);
5812     }
5813   else
5814     {
5815       if (common.outfile)
5816         {
5817           bool same = common.outfile == s->common->outfile;
5818           fh_unref (common.outfile);
5819           if (!same)
5820             {
5821               msg (SE, _("OUTFILE must name the same file on each MSAVE "
5822                          "within a single MATRIX command."));
5823               goto error;
5824             }
5825         }
5826       if (!compare_variables ("VARIABLES",
5827                               &common.variables, &s->common->variables)
5828           || !compare_variables ("FNAMES", &common.fnames, &s->common->fnames)
5829           || !compare_variables ("SNAMES", &common.snames, &s->common->snames))
5830         goto error;
5831       msave_common_uninit (&common);
5832     }
5833   msave->common = s->common;
5834   if (!msave->varname_)
5835     msave->varname_ = xasprintf ("MAT%zu", ++s->common->n_varnames);
5836   return cmd;
5837
5838 error:
5839   msave_common_uninit (&common);
5840   matrix_cmd_destroy (cmd);
5841   return NULL;
5842 }
5843
5844 static gsl_vector *
5845 matrix_expr_evaluate_vector (struct matrix_expr *e, const char *name)
5846 {
5847   gsl_matrix *m = matrix_expr_evaluate (e);
5848   if (!m)
5849     return NULL;
5850
5851   if (!is_vector (m))
5852     {
5853       msg (SE, _("%s expression must evaluate to vector, "
5854                  "not a %zu×%zu matrix."),
5855            name, m->size1, m->size2);
5856       gsl_matrix_free (m);
5857       return NULL;
5858     }
5859
5860   return matrix_to_vector (m);
5861 }
5862
5863 static const char *
5864 msave_add_vars (struct dictionary *d, const struct string_array *vars)
5865 {
5866   for (size_t i = 0; i < vars->n; i++)
5867     if (!dict_create_var (d, vars->strings[i], 0))
5868       return vars->strings[i];
5869   return NULL;
5870 }
5871
5872 static struct dictionary *
5873 msave_create_dict (const struct msave_common *common)
5874 {
5875   struct dictionary *dict = dict_create (get_default_encoding ());
5876
5877   const char *dup_split = msave_add_vars (dict, &common->snames);
5878   if (dup_split)
5879     {
5880       msg (SE, _("Duplicate SPLIT variable name %s."), dup_split);
5881       goto error;
5882     }
5883
5884   dict_create_var_assert (dict, "ROWTYPE_", 8);
5885
5886   const char *dup_factor = msave_add_vars (dict, &common->fnames);
5887   if (dup_factor)
5888     {
5889       msg (SE, _("Duplicate or invalid FACTOR variable name %s."), dup_factor);
5890       goto error;
5891     }
5892
5893   dict_create_var_assert (dict, "VARNAME_", 8);
5894
5895   const char *dup_var = msave_add_vars (dict, &common->variables);
5896   if (dup_var)
5897     {
5898       msg (SE, _("Duplicate or invalid variable name %s."), dup_var);
5899       goto error;
5900     }
5901
5902   return dict;
5903
5904 error:
5905   dict_unref (dict);
5906   return NULL;
5907 }
5908
5909 static void
5910 matrix_cmd_execute_msave (struct msave_command *msave)
5911 {
5912   struct msave_common *common = msave->common;
5913   gsl_matrix *m = NULL;
5914   gsl_vector *factors = NULL;
5915   gsl_vector *splits = NULL;
5916
5917   m = matrix_expr_evaluate (msave->expr);
5918   if (!m)
5919     goto error;
5920
5921   if (!common->variables.n)
5922     for (size_t i = 0; i < m->size2; i++)
5923       string_array_append_nocopy (&common->variables,
5924                                   xasprintf ("COL%zu", i + 1));
5925
5926   if (m->size2 != common->variables.n)
5927     {
5928       msg (SE, _("Matrix on MSAVE has %zu columns instead of required %zu."),
5929            m->size2, common->variables.n);
5930       goto error;
5931     }
5932
5933   if (msave->factors)
5934     {
5935       factors = matrix_expr_evaluate_vector (msave->factors, "FACTOR");
5936       if (!factors)
5937         goto error;
5938
5939       if (!common->fnames.n)
5940         for (size_t i = 0; i < factors->size; i++)
5941           string_array_append_nocopy (&common->fnames,
5942                                       xasprintf ("FAC%zu", i + 1));
5943
5944       if (factors->size != common->fnames.n)
5945         {
5946           msg (SE, _("There are %zu factor variables, "
5947                      "but %zu split values were supplied."),
5948                common->fnames.n, factors->size);
5949           goto error;
5950         }
5951     }
5952
5953   if (msave->splits)
5954     {
5955       splits = matrix_expr_evaluate_vector (msave->splits, "SPLIT");
5956       if (!splits)
5957         goto error;
5958
5959       if (!common->fnames.n)
5960         for (size_t i = 0; i < splits->size; i++)
5961           string_array_append_nocopy (&common->fnames,
5962                                       xasprintf ("SPL%zu", i + 1));
5963
5964       if (splits->size != common->fnames.n)
5965         {
5966           msg (SE, _("There are %zu split variables, "
5967                      "but %zu split values were supplied."),
5968                common->fnames.n, splits->size);
5969           goto error;
5970         }
5971     }
5972
5973   if (!common->writer)
5974     {
5975       struct dictionary *dict = msave_create_dict (common);
5976       if (!dict)
5977         goto error;
5978
5979       common->writer = any_writer_open (common->outfile, dict);
5980       if (!common->writer)
5981         {
5982           dict_unref (dict);
5983           goto error;
5984         }
5985
5986       common->dict = dict;
5987     }
5988
5989   for (size_t y = 0; y < m->size1; y++)
5990     {
5991       struct ccase *c = case_create (dict_get_proto (common->dict));
5992       size_t idx = 0;
5993
5994       /* Split variables */
5995       if (splits)
5996         for (size_t i = 0; i < splits->size; i++)
5997           case_data_rw_idx (c, idx++)->f = gsl_vector_get (splits, i);
5998
5999       /* ROWTYPE_. */
6000       buf_copy_str_rpad (CHAR_CAST (char *, case_data_rw_idx (c, idx++)->s), 8,
6001                          msave->rowtype, ' ');
6002
6003       /* Factors. */
6004       if (factors)
6005         for (size_t i = 0; i < factors->size; i++)
6006           *case_num_rw_idx (c, idx++) = gsl_vector_get (factors, i);
6007
6008       /* VARNAME_. */
6009       buf_copy_str_rpad (CHAR_CAST (char *, case_data_rw_idx (c, idx++)->s), 8,
6010                          msave->varname_, ' ');
6011
6012       /* Continuous variables. */
6013       for (size_t x = 0; x < m->size2; x++)
6014         case_data_rw_idx (c, idx++)->f = gsl_matrix_get (m, y, x);
6015       casewriter_write (common->writer, c);
6016     }
6017
6018 error:
6019   gsl_matrix_free (m);
6020   gsl_vector_free (factors);
6021   gsl_vector_free (splits);
6022 }
6023 \f
6024 static struct matrix_cmd *
6025 matrix_parse_mget (struct matrix_state *s)
6026 {
6027   struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
6028   *cmd = (struct matrix_cmd) { .type = MCMD_MGET, .mget = { .state = s } };
6029
6030   struct mget_command *mget = &cmd->mget;
6031
6032   for (;;)
6033     {
6034       if (lex_match_id (s->lexer, "FILE"))
6035         {
6036           lex_match (s->lexer, T_EQUALS);
6037
6038           fh_unref (mget->file);
6039           mget->file = fh_parse (s->lexer, FH_REF_FILE, s->session);
6040           if (!mget->file)
6041             goto error;
6042         }
6043       else if (lex_match_id (s->lexer, "TYPE"))
6044         {
6045           lex_match (s->lexer, T_EQUALS);
6046           while (lex_token (s->lexer) != T_SLASH
6047                  && lex_token (s->lexer) != T_ENDCMD)
6048             {
6049               const char *rowtype = match_rowtype (s->lexer);
6050               if (!rowtype)
6051                 goto error;
6052
6053               stringi_set_insert (&mget->rowtypes, rowtype);
6054             }
6055         }
6056       else
6057         {
6058           lex_error_expecting (s->lexer, "FILE", "TYPE");
6059           goto error;
6060         }
6061       if (lex_token (s->lexer) == T_ENDCMD)
6062         break;
6063
6064       if (!lex_force_match (s->lexer, T_SLASH))
6065         goto error;
6066     }
6067   return cmd;
6068
6069 error:
6070   matrix_cmd_destroy (cmd);
6071   return NULL;
6072 }
6073
6074 static const struct variable *
6075 get_a8_var (const struct dictionary *d, const char *name)
6076 {
6077   const struct variable *v = dict_lookup_var (d, name);
6078   if (!v)
6079     {
6080       msg (SE, _("Matrix data file lacks %s variable."), name);
6081       return NULL;
6082     }
6083   if (var_get_width (v) != 8)
6084     {
6085       msg (SE, _("%s variable in matrix data file must be "
6086                  "8-byte string, but it has width %d."),
6087            name, var_get_width (v));
6088       return NULL;
6089     }
6090   return v;
6091 }
6092
6093 static bool
6094 is_rowtype (const union value *v, const char *rowtype)
6095 {
6096   struct substring vs = ss_buffer (CHAR_CAST (char *, v->s), 8);
6097   ss_rtrim (&vs, ss_cstr (" "));
6098   return ss_equals_case (vs, ss_cstr (rowtype));
6099 }
6100
6101 static void
6102 matrix_mget_commit_var (struct ccase **rows, size_t n_rows,
6103                         const struct dictionary *d,
6104                         const struct variable *rowtype_var,
6105                         struct matrix_state *s, size_t si, size_t fi,
6106                         size_t cs, size_t cn)
6107 {
6108   if (!n_rows)
6109     return;
6110
6111   const union value *rowtype_ = case_data (rows[0], rowtype_var);
6112   const char *name_prefix = (is_rowtype (rowtype_, "COV") ? "CV"
6113                              : is_rowtype (rowtype_, "CORR") ? "CR"
6114                              : is_rowtype (rowtype_, "MEAN") ? "MN"
6115                              : is_rowtype (rowtype_, "STDDEV") ? "SD"
6116                              : is_rowtype (rowtype_, "N") ? "NC"
6117                              : "CN");
6118
6119   struct string name = DS_EMPTY_INITIALIZER;
6120   ds_put_cstr (&name, name_prefix);
6121   if (fi > 0)
6122     ds_put_format (&name, "F%zu", fi);
6123   if (si > 0)
6124     ds_put_format (&name, "S%zu", si);
6125
6126   struct matrix_var *mv = matrix_var_lookup (s, ds_ss (&name));
6127   if (!mv)
6128     mv = matrix_var_create (s, ds_ss (&name));
6129   else if (mv->value)
6130     {
6131       msg (SW, _("Matrix data file contains variable with existing name %s."),
6132            ds_cstr (&name));
6133       goto exit;
6134     }
6135
6136   gsl_matrix *m = gsl_matrix_alloc (n_rows, cn);
6137   size_t n_missing = 0;
6138   for (size_t y = 0; y < n_rows; y++)
6139     {
6140       for (size_t x = 0; x < cn; x++)
6141         {
6142           struct variable *var = dict_get_var (d, cs + x);
6143           double value = case_num (rows[y], var);
6144           if (var_is_num_missing (var, value, MV_ANY))
6145             {
6146               n_missing++;
6147               value = 0.0;
6148             }
6149           gsl_matrix_set (m, y, x, value);
6150         }
6151     }
6152
6153   if (n_missing)
6154     msg (SE, ngettext ("Matrix data file variable %s contains a missing "
6155                        "value, which was treated as zero.",
6156                        "Matrix data file variable %s contains %zu missing "
6157                        "values, which were treated as zero.", n_missing),
6158          ds_cstr (&name), n_missing);
6159   mv->value = m;
6160
6161 exit:
6162   ds_destroy (&name);
6163   for (size_t y = 0; y < n_rows; y++)
6164     case_unref (rows[y]);
6165 }
6166
6167 static bool
6168 var_changed (const struct ccase *ca, const struct ccase *cb,
6169              const struct variable *var)
6170 {
6171   return !value_equal (case_data (ca, var), case_data (cb, var),
6172                        var_get_width (var));
6173 }
6174
6175 static bool
6176 vars_changed (const struct ccase *ca, const struct ccase *cb,
6177               const struct dictionary *d,
6178               size_t first_var, size_t n_vars)
6179 {
6180   for (size_t i = 0; i < n_vars; i++)
6181     {
6182       const struct variable *v = dict_get_var (d, first_var + i);
6183       if (var_changed (ca, cb, v))
6184         return true;
6185     }
6186   return false;
6187 }
6188
6189 static void
6190 matrix_cmd_execute_mget (struct mget_command *mget)
6191 {
6192   struct dictionary *d;
6193   struct casereader *r = any_reader_open_and_decode (mget->file, "UTF-8",
6194                                                      &d, NULL);
6195   if (!r)
6196     return;
6197
6198   const struct variable *rowtype_ = get_a8_var (d, "ROWTYPE_");
6199   const struct variable *varname_ = get_a8_var (d, "VARNAME_");
6200   if (!rowtype_ || !varname_)
6201     goto exit;
6202
6203   if (var_get_dict_index (rowtype_) >= var_get_dict_index (varname_))
6204     {
6205       msg (SE, _("ROWTYPE_ must precede VARNAME_ in matrix data file."));
6206       goto exit;
6207     }
6208   if (var_get_dict_index (varname_) + 1 >= dict_get_var_cnt (d))
6209     {
6210       msg (SE, _("Matrix data file contains no continuous variables."));
6211       goto exit;
6212     }
6213
6214   for (size_t i = 0; i < dict_get_var_cnt (d); i++)
6215     {
6216       const struct variable *v = dict_get_var (d, i);
6217       if (v != rowtype_ && v != varname_ && var_get_width (v) != 0)
6218         {
6219           msg (SE,
6220                _("Matrix data file contains unexpected string variable %s."),
6221                var_get_name (v));
6222           goto exit;
6223         }
6224     }
6225
6226   /* SPLIT variables. */
6227   size_t ss = 0;
6228   size_t sn = var_get_dict_index (rowtype_);
6229   struct ccase *sc = NULL;
6230   size_t si = 0;
6231
6232   /* FACTOR variables. */
6233   size_t fs = var_get_dict_index (rowtype_) + 1;
6234   size_t fn = var_get_dict_index (varname_) - var_get_dict_index (rowtype_) - 1;
6235   struct ccase *fc = NULL;
6236   size_t fi = 0;
6237
6238   /* Continuous variables. */
6239   size_t cs = var_get_dict_index (varname_) + 1;
6240   size_t cn = dict_get_var_cnt (d) - cs;
6241   struct ccase *cc = NULL;
6242
6243   /* Matrix. */
6244   struct ccase **rows = NULL;
6245   size_t allocated_rows = 0;
6246   size_t n_rows = 0;
6247
6248   struct ccase *c;
6249   while ((c = casereader_read (r)) != NULL)
6250     {
6251       bool sd = vars_changed (sc, c, d, ss, sn);
6252       bool fd = sd || vars_changed (fc, c, d, fs, fn);
6253       bool md = fd || !cc || var_changed (cc, c, rowtype_) || var_changed (cc, c, varname_);
6254       if (sd)
6255         {
6256           si++;
6257           case_unref (sc);
6258           sc = case_ref (c);
6259         }
6260       if (fd)
6261         {
6262           fi++;
6263           case_unref (fc);
6264           fc = case_ref (c);
6265         }
6266       if (md)
6267         {
6268           matrix_mget_commit_var (rows, n_rows, d, rowtype_,
6269                                   mget->state, si, fi, cs, cn);
6270           n_rows = 0;
6271           case_unref (cc);
6272           cc = case_ref (c);
6273         }
6274
6275       if (n_rows >= allocated_rows)
6276         rows = x2nrealloc (rows, &allocated_rows, sizeof *rows);
6277       rows[n_rows++] = c;
6278     }
6279   matrix_mget_commit_var (rows, n_rows, d, rowtype_,
6280                           mget->state, si, fi, cs, cn);
6281   free (rows);
6282
6283 exit:
6284   casereader_destroy (r);
6285 }
6286 \f
6287 static bool
6288 matrix_parse_dst_var (struct matrix_state *s, struct matrix_var **varp)
6289 {
6290   if (!lex_force_id (s->lexer))
6291     return false;
6292
6293   *varp = matrix_var_lookup (s, lex_tokss (s->lexer));
6294   if (!*varp)
6295     *varp = matrix_var_create (s, lex_tokss (s->lexer));
6296   lex_get (s->lexer);
6297   return true;
6298 }
6299
6300 static struct matrix_cmd *
6301 matrix_parse_eigen (struct matrix_state *s)
6302 {
6303   struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
6304   *cmd = (struct matrix_cmd) {
6305     .type = MCMD_EIGEN,
6306     .eigen = { .expr = NULL }
6307   };
6308
6309   struct eigen_command *eigen = &cmd->eigen;
6310   if (!lex_force_match (s->lexer, T_LPAREN))
6311     goto error;
6312   eigen->expr = matrix_parse_expr (s);
6313   if (!eigen->expr
6314       || !lex_force_match (s->lexer, T_COMMA)
6315       || !matrix_parse_dst_var (s, &eigen->evec)
6316       || !lex_force_match (s->lexer, T_COMMA)
6317       || !matrix_parse_dst_var (s, &eigen->eval)
6318       || !lex_force_match (s->lexer, T_RPAREN))
6319     goto error;
6320
6321   return cmd;
6322
6323 error:
6324   matrix_cmd_destroy (cmd);
6325   return NULL;
6326 }
6327
6328 static void
6329 matrix_cmd_execute_eigen (struct eigen_command *eigen)
6330 {
6331   gsl_matrix *A = matrix_expr_evaluate (eigen->expr);
6332   if (!A)
6333     return;
6334   if (!is_symmetric (A))
6335     {
6336       msg (SE, _("Argument of EIGEN must be symmetric."));
6337       gsl_matrix_free (A);
6338       return;
6339     }
6340
6341   gsl_eigen_symmv_workspace *w = gsl_eigen_symmv_alloc (A->size1);
6342   gsl_matrix *eval = gsl_matrix_alloc (A->size1, 1);
6343   gsl_vector v_eval = to_vector (eval);
6344   gsl_matrix *evec = gsl_matrix_alloc (A->size1, A->size2);
6345   gsl_eigen_symmv (A, &v_eval, evec, w);
6346   gsl_eigen_symmv_free (w);
6347
6348   gsl_eigen_symmv_sort (&v_eval, evec, GSL_EIGEN_SORT_VAL_DESC);
6349
6350   gsl_matrix_free (A);
6351
6352   gsl_matrix_free (eigen->eval->value);
6353   eigen->eval->value = eval;
6354
6355   gsl_matrix_free (eigen->evec->value);
6356   eigen->evec->value = evec;
6357 }
6358 \f
6359 static struct matrix_cmd *
6360 matrix_parse_setdiag (struct matrix_state *s)
6361 {
6362   struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
6363   *cmd = (struct matrix_cmd) {
6364     .type = MCMD_SETDIAG,
6365     .setdiag = { .dst = NULL }
6366   };
6367
6368   struct setdiag_command *setdiag = &cmd->setdiag;
6369   if (!lex_force_match (s->lexer, T_LPAREN) || !lex_force_id (s->lexer))
6370     goto error;
6371
6372   setdiag->dst = matrix_var_lookup (s, lex_tokss (s->lexer));
6373   if (!setdiag->dst)
6374     {
6375       lex_error (s->lexer, _("Unknown variable %s."), lex_tokcstr (s->lexer));
6376       goto error;
6377     }
6378   lex_get (s->lexer);
6379
6380   if (!lex_force_match (s->lexer, T_COMMA))
6381     goto error;
6382
6383   setdiag->expr = matrix_parse_expr (s);
6384   if (!setdiag->expr)
6385     goto error;
6386
6387   if (!lex_force_match (s->lexer, T_RPAREN))
6388     goto error;
6389
6390   return cmd;
6391
6392 error:
6393   matrix_cmd_destroy (cmd);
6394   return NULL;
6395 }
6396
6397 static void
6398 matrix_cmd_execute_setdiag (struct setdiag_command *setdiag)
6399 {
6400   gsl_matrix *dst = setdiag->dst->value;
6401   if (!dst)
6402     {
6403       msg (SE, _("SETDIAG destination matrix %s is uninitialized."),
6404            setdiag->dst->name);
6405       return;
6406     }
6407
6408   gsl_matrix *src = matrix_expr_evaluate (setdiag->expr);
6409   if (!src)
6410     return;
6411
6412   size_t n = MIN (dst->size1, dst->size2);
6413   if (is_scalar (src))
6414     {
6415       double d = to_scalar (src);
6416       for (size_t i = 0; i < n; i++)
6417         gsl_matrix_set (dst, i, i, d);
6418     }
6419   else if (is_vector (src))
6420     {
6421       gsl_vector v = to_vector (src);
6422       for (size_t i = 0; i < n && i < v.size; i++)
6423         gsl_matrix_set (dst, i, i, gsl_vector_get (&v, i));
6424     }
6425   else
6426     msg (SE, _("SETDIAG argument 2 must be a scalar or a vector, "
6427                "not a %zu×%zu matrix."),
6428          src->size1, src->size2);
6429   gsl_matrix_free (src);
6430 }
6431 \f
6432 static struct matrix_cmd *
6433 matrix_parse_svd (struct matrix_state *s)
6434 {
6435   struct matrix_cmd *cmd = xmalloc (sizeof *cmd);
6436   *cmd = (struct matrix_cmd) {
6437     .type = MCMD_SVD,
6438     .svd = { .expr = NULL }
6439   };
6440
6441   struct svd_command *svd = &cmd->svd;
6442   if (!lex_force_match (s->lexer, T_LPAREN))
6443     goto error;
6444   svd->expr = matrix_parse_expr (s);
6445   if (!svd->expr
6446       || !lex_force_match (s->lexer, T_COMMA)
6447       || !matrix_parse_dst_var (s, &svd->u)
6448       || !lex_force_match (s->lexer, T_COMMA)
6449       || !matrix_parse_dst_var (s, &svd->s)
6450       || !lex_force_match (s->lexer, T_COMMA)
6451       || !matrix_parse_dst_var (s, &svd->v)
6452       || !lex_force_match (s->lexer, T_RPAREN))
6453     goto error;
6454
6455   return cmd;
6456
6457 error:
6458   matrix_cmd_destroy (cmd);
6459   return NULL;
6460 }
6461
6462 static void
6463 matrix_cmd_execute_svd (struct svd_command *svd)
6464 {
6465   gsl_matrix *m = matrix_expr_evaluate (svd->expr);
6466   if (!m)
6467     return;
6468
6469   if (m->size1 >= m->size2)
6470     {
6471       gsl_matrix *A = m;
6472       gsl_matrix *V = gsl_matrix_alloc (A->size2, A->size2);
6473       gsl_matrix *S = gsl_matrix_calloc (A->size2, A->size2);
6474       gsl_vector Sv = gsl_matrix_diagonal (S).vector;
6475       gsl_vector *work = gsl_vector_alloc (A->size2);
6476       gsl_linalg_SV_decomp (A, V, &Sv, work);
6477       gsl_vector_free (work);
6478
6479       matrix_var_set (svd->u, A);
6480       matrix_var_set (svd->s, S);
6481       matrix_var_set (svd->v, V);
6482     }
6483   else
6484     {
6485       gsl_matrix *At = gsl_matrix_alloc (m->size2, m->size1);
6486       gsl_matrix_transpose_memcpy (At, m);
6487       gsl_matrix_free (m);
6488
6489       gsl_matrix *Vt = gsl_matrix_alloc (At->size2, At->size2);
6490       gsl_matrix *St = gsl_matrix_calloc (At->size2, At->size2);
6491       gsl_vector Stv = gsl_matrix_diagonal (St).vector;
6492       gsl_vector *work = gsl_vector_alloc (At->size2);
6493       gsl_linalg_SV_decomp (At, Vt, &Stv, work);
6494       gsl_vector_free (work);
6495
6496       matrix_var_set (svd->v, At);
6497       matrix_var_set (svd->s, St);
6498       matrix_var_set (svd->u, Vt);
6499     }
6500 }
6501 \f
6502 static bool
6503 matrix_cmd_execute (struct matrix_cmd *cmd)
6504 {
6505   switch (cmd->type)
6506     {
6507     case MCMD_COMPUTE:
6508       matrix_cmd_execute_compute (&cmd->compute);
6509       break;
6510
6511     case MCMD_PRINT:
6512       matrix_cmd_execute_print (&cmd->print);
6513       break;
6514
6515     case MCMD_DO_IF:
6516       return matrix_cmd_execute_do_if (&cmd->do_if);
6517
6518     case MCMD_LOOP:
6519       matrix_cmd_execute_loop (&cmd->loop);
6520       break;
6521
6522     case MCMD_BREAK:
6523       return false;
6524
6525     case MCMD_DISPLAY:
6526       matrix_cmd_execute_display (&cmd->display);
6527       break;
6528
6529     case MCMD_RELEASE:
6530       matrix_cmd_execute_release (&cmd->release);
6531       break;
6532
6533     case MCMD_SAVE:
6534       matrix_cmd_execute_save (&cmd->save);
6535       break;
6536
6537     case MCMD_READ:
6538       matrix_cmd_execute_read (&cmd->read);
6539       break;
6540
6541     case MCMD_WRITE:
6542       matrix_cmd_execute_write (&cmd->write);
6543       break;
6544
6545     case MCMD_GET:
6546       matrix_cmd_execute_get (&cmd->get);
6547       break;
6548
6549     case MCMD_MSAVE:
6550       matrix_cmd_execute_msave (&cmd->msave);
6551       break;
6552
6553     case MCMD_MGET:
6554       matrix_cmd_execute_mget (&cmd->mget);
6555       break;
6556
6557     case MCMD_EIGEN:
6558       matrix_cmd_execute_eigen (&cmd->eigen);
6559       break;
6560
6561     case MCMD_SETDIAG:
6562       matrix_cmd_execute_setdiag (&cmd->setdiag);
6563       break;
6564
6565     case MCMD_SVD:
6566       matrix_cmd_execute_svd (&cmd->svd);
6567       break;
6568     }
6569
6570   return true;
6571 }
6572
6573 static void
6574 matrix_cmds_uninit (struct matrix_cmds *cmds)
6575 {
6576   for (size_t i = 0; i < cmds->n; i++)
6577     matrix_cmd_destroy (cmds->commands[i]);
6578   free (cmds->commands);
6579 }
6580
6581 static void
6582 matrix_cmd_destroy (struct matrix_cmd *cmd)
6583 {
6584   if (!cmd)
6585     return;
6586
6587   switch (cmd->type)
6588     {
6589     case MCMD_COMPUTE:
6590       matrix_lvalue_destroy (cmd->compute.lvalue);
6591       matrix_expr_destroy (cmd->compute.rvalue);
6592       break;
6593
6594     case MCMD_PRINT:
6595       matrix_expr_destroy (cmd->print.expression);
6596       free (cmd->print.title);
6597       print_labels_destroy (cmd->print.rlabels);
6598       print_labels_destroy (cmd->print.clabels);
6599       break;
6600
6601     case MCMD_DO_IF:
6602       for (size_t i = 0; i < cmd->do_if.n_clauses; i++)
6603         {
6604           matrix_expr_destroy (cmd->do_if.clauses[i].condition);
6605           matrix_cmds_uninit (&cmd->do_if.clauses[i].commands);
6606         }
6607       free (cmd->do_if.clauses);
6608       break;
6609
6610     case MCMD_LOOP:
6611       matrix_expr_destroy (cmd->loop.start);
6612       matrix_expr_destroy (cmd->loop.end);
6613       matrix_expr_destroy (cmd->loop.increment);
6614       matrix_expr_destroy (cmd->loop.top_condition);
6615       matrix_expr_destroy (cmd->loop.bottom_condition);
6616       matrix_cmds_uninit (&cmd->loop.commands);
6617       break;
6618
6619     case MCMD_BREAK:
6620       break;
6621
6622     case MCMD_DISPLAY:
6623       break;
6624
6625     case MCMD_RELEASE:
6626       free (cmd->release.vars);
6627       break;
6628
6629     case MCMD_SAVE:
6630       matrix_expr_destroy (cmd->save.expression);
6631       fh_unref (cmd->save.outfile);
6632       string_array_destroy (cmd->save.variables);
6633       matrix_expr_destroy (cmd->save.names);
6634       stringi_set_destroy (&cmd->save.strings);
6635       break;
6636
6637     case MCMD_READ:
6638       matrix_lvalue_destroy (cmd->read.dst);
6639       matrix_expr_destroy (cmd->read.size);
6640       break;
6641
6642     case MCMD_WRITE:
6643       matrix_expr_destroy (cmd->write.expression);
6644       free (cmd->write.format);
6645       break;
6646
6647     case MCMD_GET:
6648       matrix_lvalue_destroy (cmd->get.dst);
6649       fh_unref (cmd->get.file);
6650       free (cmd->get.encoding);
6651       var_syntax_destroy (cmd->get.vars, cmd->get.n_vars);
6652       break;
6653
6654     case MCMD_MSAVE:
6655       free (cmd->msave.varname_);
6656       matrix_expr_destroy (cmd->msave.expr);
6657       matrix_expr_destroy (cmd->msave.factors);
6658       matrix_expr_destroy (cmd->msave.splits);
6659       break;
6660
6661     case MCMD_MGET:
6662       fh_unref (cmd->mget.file);
6663       stringi_set_destroy (&cmd->mget.rowtypes);
6664       break;
6665
6666     case MCMD_EIGEN:
6667       matrix_expr_destroy (cmd->eigen.expr);
6668       break;
6669
6670     case MCMD_SETDIAG:
6671       matrix_expr_destroy (cmd->setdiag.expr);
6672       break;
6673
6674     case MCMD_SVD:
6675       matrix_expr_destroy (cmd->svd.expr);
6676       break;
6677     }
6678   free (cmd);
6679 }
6680
6681 struct matrix_command_name
6682   {
6683     const char *name;
6684     struct matrix_cmd *(*parse) (struct matrix_state *);
6685   };
6686
6687 static const struct matrix_command_name *
6688 matrix_parse_command_name (struct lexer *lexer)
6689 {
6690   static const struct matrix_command_name commands[] = {
6691     { "COMPUTE", matrix_parse_compute },
6692     { "CALL EIGEN", matrix_parse_eigen },
6693     { "CALL SETDIAG", matrix_parse_setdiag },
6694     { "CALL SVD", matrix_parse_svd },
6695     { "PRINT", matrix_parse_print },
6696     { "DO IF", matrix_parse_do_if },
6697     { "LOOP", matrix_parse_loop },
6698     { "BREAK", matrix_parse_break },
6699     { "READ", matrix_parse_read },
6700     { "WRITE", matrix_parse_write },
6701     { "GET", matrix_parse_get },
6702     { "SAVE", matrix_parse_save },
6703     { "MGET", matrix_parse_mget },
6704     { "MSAVE", matrix_parse_msave },
6705     { "DISPLAY", matrix_parse_display },
6706     { "RELEASE", matrix_parse_release },
6707   };
6708   static size_t n = sizeof commands / sizeof *commands;
6709
6710   for (const struct matrix_command_name *c = commands; c < &commands[n]; c++)
6711     if (lex_match_phrase (lexer, c->name))
6712       return c;
6713   return NULL;
6714 }
6715
6716 static struct matrix_cmd *
6717 matrix_parse_command (struct matrix_state *s)
6718 {
6719   size_t nesting_level = SIZE_MAX;
6720
6721   struct matrix_cmd *c = NULL;
6722   const struct matrix_command_name *cmd = matrix_parse_command_name (s->lexer);
6723   if (!cmd)
6724     lex_error (s->lexer, _("Unknown matrix command."));
6725   else if (!cmd->parse)
6726     lex_error (s->lexer, _("Matrix command %s is not yet implemented."),
6727                cmd->name);
6728   else
6729     {
6730       nesting_level = output_open_group (
6731         group_item_create_nocopy (utf8_to_title (cmd->name),
6732                                   utf8_to_title (cmd->name)));
6733       c = cmd->parse (s);
6734     }
6735
6736   if (c)
6737     lex_end_of_command (s->lexer);
6738   lex_discard_rest_of_command (s->lexer);
6739   if (nesting_level != SIZE_MAX)
6740     output_close_groups (nesting_level);
6741
6742   return c;
6743 }
6744
6745 int
6746 cmd_matrix (struct lexer *lexer, struct dataset *ds)
6747 {
6748   if (!lex_force_match (lexer, T_ENDCMD))
6749     return CMD_FAILURE;
6750
6751   struct matrix_state state = {
6752     .dataset = ds,
6753     .session = dataset_session (ds),
6754     .lexer = lexer,
6755     .vars = HMAP_INITIALIZER (state.vars),
6756   };
6757
6758   for (;;)
6759     {
6760       while (lex_match (lexer, T_ENDCMD))
6761         continue;
6762       if (lex_token (lexer) == T_STOP)
6763         {
6764           msg (SE, _("Unexpected end of input expecting matrix command."));
6765           break;
6766         }
6767
6768       if (lex_match_phrase (lexer, "END MATRIX"))
6769         break;
6770
6771       struct matrix_cmd *c = matrix_parse_command (&state);
6772       if (c)
6773         {
6774           matrix_cmd_execute (c);
6775           matrix_cmd_destroy (c);
6776         }
6777     }
6778
6779   struct matrix_var *var, *next;
6780   HMAP_FOR_EACH_SAFE (var, next, struct matrix_var, hmap_node, &state.vars)
6781     {
6782       free (var->name);
6783       gsl_matrix_free (var->value);
6784       hmap_delete (&state.vars, &var->hmap_node);
6785       free (var);
6786     }
6787   hmap_destroy (&state.vars);
6788   fh_unref (state.prev_save_outfile);
6789   if (state.common)
6790     {
6791       dict_unref (state.common->dict);
6792       casewriter_destroy (state.common->writer);
6793       free (state.common);
6794     }
6795   fh_unref (state.prev_read_file);
6796   for (size_t i = 0; i < state.n_read_files; i++)
6797     read_file_destroy (state.read_files[i]);
6798   free (state.read_files);
6799   fh_unref (state.prev_write_file);
6800   for (size_t i = 0; i < state.n_write_files; i++)
6801     write_file_destroy (state.write_files[i]);
6802   free (state.write_files);
6803
6804   return CMD_SUCCESS;
6805 }