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