1 /**
2 @file gsl.c
3 @author J. Marcel van der Veer.
4 @brief Vector, matrix and FFT support through GSL.
5
6 @section Copyright
7
8 This file is part of Algol68G - an Algol 68 interpreter.
9 Copyright 2001-2016 J. Marcel van der Veer <algol68g@xs4all.nl>.
10
11 @section Description
12
13 This program is free software; you can redistribute it and/or modify it under
14 the terms of the GNU General Public License as published by the Free Software
15 Foundation; either version 3 of the License, or (at your option) any later
16 version.
17
18 This program is distributed in the hope that it will be useful, but WITHOUT ANY
19 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
20 PARTICULAR PURPOSE. See the GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License along with
23 this program. If not, see <http://www.gnu.org/licenses/>.
24 **/
25
26 #include "a68g.h"
27
28 #if defined HAVE_GNU_GSL
29
30 static NODE_T *error_node = NO_NODE;
31
32 #define VECTOR_OFFSET(a, t)\
33 ((LWB (t) * SPAN (t) - SHIFT (t) + SLICE_OFFSET (a)) * ELEM_SIZE (a) + FIELD_OFFSET (a))
34
35 #define MATRIX_OFFSET(a, t1, t2)\
36 ((LWB (t1) * SPAN (t1) - SHIFT (t1) + LWB (t2) * SPAN (t2) - SHIFT (t2) + SLICE_OFFSET (a)) * ELEM_SIZE (a) + FIELD_OFFSET (a))
37
38 /**
39 @brief Set permutation vector element - function fails in gsl.
40 @param p Permutation vector.
41 @param i Element iindex.
42 @param j Element value.
43 **/
44
45 void
gsl_permutation_set(const gsl_permutation * p,const size_t i,const size_t j)46 gsl_permutation_set (const gsl_permutation * p, const size_t i, const size_t j)
47 {
48 DATA (p)[i] = j;
49 }
50
51 /**
52 @brief Map GSL error handler onto a68g error handler.
53 @param reason Error text.
54 @param file Gsl file where error occured.
55 @param line Line in above file.
56 @param gsl_errno Gsl error number.
57 **/
58
59 void
torrix_error_handler(const char * reason,const char * file,int line,int gsl_errno)60 torrix_error_handler (const char *reason, const char *file, int line, int gsl_errno)
61 {
62 if (line != 0) {
63 ASSERT (snprintf (edit_line, SNPRINTF_SIZE, "%s in line %d of file %s", reason, line, file) >= 0);
64 } else {
65 ASSERT (snprintf (edit_line, SNPRINTF_SIZE, "%s", reason) >= 0);
66 }
67 diagnostic_node (A68_RUNTIME_ERROR, error_node, ERROR_TORRIX, edit_line, gsl_strerror (gsl_errno));
68 exit_genie (error_node, A68_RUNTIME_ERROR);
69 }
70
71 /**
72 @brief Detect math errors, mainly in BLAS functions.
73 @param rc Return code from function.
74 **/
75
76 static void
torrix_test_error(int rc)77 torrix_test_error (int rc)
78 {
79 if (rc != 0) {
80 torrix_error_handler ("math error", "", 0, rc);
81 }
82 }
83
84 /**
85 @brief Pop [] INT on the stack as gsl_permutation.
86 @param p Node in syntax tree.
87 @param get Whether to get elements from row in the stack.
88 @return Gsl_permutation_complex.
89 **/
90
91 static gsl_permutation *
pop_permutation(NODE_T * p,BOOL_T get)92 pop_permutation (NODE_T * p, BOOL_T get)
93 {
94 A68_REF desc;
95 A68_ARRAY *arr;
96 A68_TUPLE *tup;
97 int len, inc, iindex, k;
98 BYTE_T *base;
99 gsl_permutation *v;
100 /* Pop arguments */
101 POP_REF (p, &desc);
102 CHECK_REF (p, desc, MODE (ROW_INT));
103 GET_DESCRIPTOR (arr, tup, &desc);
104 len = ROW_SIZE (tup);
105 v = gsl_permutation_alloc ((size_t) len);
106 if (get && len > 0) {
107 base = DEREF (BYTE_T, &ARRAY (arr));
108 iindex = VECTOR_OFFSET (arr, tup);
109 inc = SPAN (tup) * ELEM_SIZE (arr);
110 for (k = 0; k < len; k++, iindex += inc) {
111 A68_INT *x = (A68_INT *) (base + iindex);
112 CHECK_INIT (p, INITIALISED (x), MODE (INT));
113 gsl_permutation_set (v, (size_t) k, (size_t) VALUE (x));
114 }
115 }
116 return (v);
117 }
118
119 /**
120 @brief Push gsl_permutation on the stack as [] INT.
121 @param p Node in syntax tree.
122 @param v Permutation.
123 **/
124
125 static void
push_permutation(NODE_T * p,gsl_permutation * v)126 push_permutation (NODE_T * p, gsl_permutation * v)
127 {
128 A68_REF desc, row;
129 A68_ARRAY arr;
130 A68_TUPLE tup;
131 int len, inc, iindex, k;
132 BYTE_T *base;
133 len = (int) (SIZE (v));
134 desc = heap_generator (p, MODE (ROW_INT), SIZE_AL (A68_ARRAY) + SIZE_AL (A68_TUPLE));
135 row = heap_generator (p, MODE (ROW_INT), len * SIZE (MODE (INT)));
136 DIM (&arr) = 1;
137 MOID (&arr) = MODE (INT);
138 ELEM_SIZE (&arr) = SIZE (MODE (INT));
139 SLICE_OFFSET (&arr) = FIELD_OFFSET (&arr) = 0;
140 ARRAY (&arr) = row;
141 LWB (&tup) = 1;
142 UPB (&tup) = len;
143 SPAN (&tup) = 1;
144 SHIFT (&tup) = LWB (&tup);
145 K (&tup) = 0;
146 PUT_DESCRIPTOR (arr, tup, &desc);
147 base = DEREF (BYTE_T, &ARRAY (&arr));
148 iindex = VECTOR_OFFSET (&arr, &tup);
149 inc = SPAN (&tup) * ELEM_SIZE (&arr);
150 for (k = 0; k < len; k++, iindex += inc) {
151 A68_INT *x = (A68_INT *) (base + iindex);
152 STATUS (x) = INIT_MASK;
153 VALUE (x) = (int) gsl_permutation_get (v, (size_t) k);
154 }
155 PUSH_REF (p, desc);
156 }
157
158 /**
159 @brief Pop [] REAL on the stack as gsl_vector.
160 @param p Node in syntax tree.
161 @param get Whether to get elements from row in the stack.
162 @return Gsl_vector_complex.
163 **/
164
165 static gsl_vector *
pop_vector(NODE_T * p,BOOL_T get)166 pop_vector (NODE_T * p, BOOL_T get)
167 {
168 A68_REF desc;
169 A68_ARRAY *arr;
170 A68_TUPLE *tup;
171 int len, inc, iindex, k;
172 BYTE_T *base;
173 gsl_vector *v;
174 /* Pop arguments */
175 POP_REF (p, &desc);
176 CHECK_REF (p, desc, MODE (ROW_REAL));
177 GET_DESCRIPTOR (arr, tup, &desc);
178 len = ROW_SIZE (tup);
179 v = gsl_vector_alloc ((size_t) len);
180 if (get && len > 0) {
181 base = DEREF (BYTE_T, &ARRAY (arr));
182 iindex = VECTOR_OFFSET (arr, tup);
183 inc = SPAN (tup) * ELEM_SIZE (arr);
184 for (k = 0; k < len; k++, iindex += inc) {
185 A68_REAL *x = (A68_REAL *) (base + iindex);
186 CHECK_INIT (p, INITIALISED (x), MODE (REAL));
187 gsl_vector_set (v, (size_t) k, VALUE (x));
188 }
189 }
190 return (v);
191 }
192
193 /**
194 @brief Push gsl_vector on the stack as [] REAL.
195 @param p Node in syntax tree.
196 @param v Vector.
197 **/
198
199 static void
push_vector(NODE_T * p,gsl_vector * v)200 push_vector (NODE_T * p, gsl_vector * v)
201 {
202 A68_REF desc, row;
203 A68_ARRAY arr;
204 A68_TUPLE tup;
205 int len, inc, iindex, k;
206 BYTE_T *base;
207 len = (int) (SIZE (v));
208 desc = heap_generator (p, MODE (ROW_REAL), SIZE_AL (A68_ARRAY) + SIZE_AL (A68_TUPLE));
209 row = heap_generator (p, MODE (ROW_REAL), len * SIZE (MODE (REAL)));
210 DIM (&arr) = 1;
211 MOID (&arr) = MODE (REAL);
212 ELEM_SIZE (&arr) = SIZE (MODE (REAL));
213 SLICE_OFFSET (&arr) = FIELD_OFFSET (&arr) = 0;
214 ARRAY (&arr) = row;
215 LWB (&tup) = 1;
216 UPB (&tup) = len;
217 SPAN (&tup) = 1;
218 SHIFT (&tup) = LWB (&tup);
219 K (&tup) = 0;
220 PUT_DESCRIPTOR (arr, tup, &desc);
221 base = DEREF (BYTE_T, &ARRAY (&arr));
222 iindex = VECTOR_OFFSET (&arr, &tup);
223 inc = SPAN (&tup) * ELEM_SIZE (&arr);
224 for (k = 0; k < len; k++, iindex += inc) {
225 A68_REAL *x = (A68_REAL *) (base + iindex);
226 STATUS (x) = INIT_MASK;
227 VALUE (x) = gsl_vector_get (v, (size_t) k);
228 CHECK_REAL_REPRESENTATION (p, VALUE (x));
229 }
230 PUSH_REF (p, desc);
231 }
232
233 /**
234 @brief Pop [,] REAL on the stack as gsl_matrix.
235 @param p Node in syntax tree.
236 @param get Whether to get elements from row in the stack.
237 @return Gsl_matrix.
238 **/
239
240 static gsl_matrix *
pop_matrix(NODE_T * p,BOOL_T get)241 pop_matrix (NODE_T * p, BOOL_T get)
242 {
243 A68_REF desc;
244 A68_ARRAY *arr;
245 A68_TUPLE *tup1, *tup2;
246 int len1, len2, inc1, inc2, iindex1, iindex2, k1, k2;
247 BYTE_T *base;
248 gsl_matrix *a;
249 /* Pop arguments */
250 POP_REF (p, &desc);
251 CHECK_REF (p, desc, MODE (ROWROW_REAL));
252 GET_DESCRIPTOR (arr, tup1, &desc);
253 tup2 = &(tup1[1]);
254 len1 = ROW_SIZE (tup1);
255 len2 = ROW_SIZE (tup2);
256 a = gsl_matrix_alloc ((size_t) len1, (size_t) len2);
257 if (get && (len1 * len2 > 0)) {
258 base = DEREF (BYTE_T, &ARRAY (arr));
259 iindex1 = MATRIX_OFFSET (arr, tup1, tup2);
260 inc1 = SPAN (tup1) * ELEM_SIZE (arr);
261 inc2 = SPAN (tup2) * ELEM_SIZE (arr);
262 for (k1 = 0; k1 < len1; k1++, iindex1 += inc1) {
263 for (k2 = 0, iindex2 = iindex1; k2 < len2; k2++, iindex2 += inc2) {
264 A68_REAL *x = (A68_REAL *) (base + iindex2);
265 CHECK_INIT (p, INITIALISED (x), MODE (REAL));
266 gsl_matrix_set (a, (size_t) k1, (size_t) k2, VALUE (x));
267 }
268 }
269 }
270 return (a);
271 }
272
273 /**
274 @brief Push gsl_matrix on the stack as [,] REAL.
275 @param p Node in syntax tree.
276 @param a Matrix.
277 **/
278
279 static void
push_matrix(NODE_T * p,gsl_matrix * a)280 push_matrix (NODE_T * p, gsl_matrix * a)
281 {
282 A68_REF desc, row;
283 A68_ARRAY arr;
284 A68_TUPLE tup1, tup2;
285 int len1, len2, inc1, inc2, iindex1, iindex2, k1, k2;
286 BYTE_T *base;
287 len1 = (int) (SIZE1 (a));
288 len2 = (int) (SIZE2 (a));
289 desc = heap_generator (p, MODE (ROWROW_REAL), SIZE_AL (A68_ARRAY) + 2 * SIZE_AL (A68_TUPLE));
290 row = heap_generator (p, MODE (ROWROW_REAL), len1 * len2 * SIZE (MODE (REAL)));
291 DIM (&arr) = 2;
292 MOID (&arr) = MODE (REAL);
293 ELEM_SIZE (&arr) = SIZE (MODE (REAL));
294 SLICE_OFFSET (&arr) = FIELD_OFFSET (&arr) = 0;
295 ARRAY (&arr) = row;
296 LWB (&tup1) = 1;
297 UPB (&tup1) = len1;
298 SPAN (&tup1) = 1;
299 SHIFT (&tup1) = LWB (&tup1);
300 K (&tup1) = 0;
301 LWB (&tup2) = 1;
302 UPB (&tup2) = len2;
303 SPAN (&tup2) = ROW_SIZE (&tup1);
304 SHIFT (&tup2) = LWB (&tup2) * SPAN (&tup2);
305 K (&tup2) = 0;
306 PUT_DESCRIPTOR2 (arr, tup1, tup2, &desc);
307 base = DEREF (BYTE_T, &ARRAY (&arr));
308 iindex1 = MATRIX_OFFSET (&arr, &tup1, &tup2);
309 inc1 = SPAN (&tup1) * ELEM_SIZE (&arr);
310 inc2 = SPAN (&tup2) * ELEM_SIZE (&arr);
311 for (k1 = 0; k1 < len1; k1++, iindex1 += inc1) {
312 for (k2 = 0, iindex2 = iindex1; k2 < len2; k2++, iindex2 += inc2) {
313 A68_REAL *x = (A68_REAL *) (base + iindex2);
314 STATUS (x) = INIT_MASK;
315 VALUE (x) = gsl_matrix_get (a, (size_t) k1, (size_t) k2);
316 CHECK_REAL_REPRESENTATION (p, VALUE (x));
317 }
318 }
319 PUSH_REF (p, desc);
320 }
321
322 /**
323 @brief Pop [] COMPLEX on the stack as gsl_vector_complex.
324 @param p Node in syntax tree.
325 @param get Whether to get elements from row in the stack.
326 @return Gsl_vector_complex.
327 **/
328
329 static gsl_vector_complex *
pop_vector_complex(NODE_T * p,BOOL_T get)330 pop_vector_complex (NODE_T * p, BOOL_T get)
331 {
332 A68_REF desc;
333 A68_ARRAY *arr;
334 A68_TUPLE *tup;
335 int len, inc, iindex, k;
336 BYTE_T *base;
337 gsl_vector_complex *v;
338 /* Pop arguments */
339 POP_REF (p, &desc);
340 CHECK_REF (p, desc, MODE (ROW_COMPLEX));
341 GET_DESCRIPTOR (arr, tup, &desc);
342 len = ROW_SIZE (tup);
343 v = gsl_vector_complex_alloc ((size_t) len);
344 if (get && len > 0) {
345 base = DEREF (BYTE_T, &ARRAY (arr));
346 iindex = VECTOR_OFFSET (arr, tup);
347 inc = SPAN (tup) * ELEM_SIZE (arr);
348 for (k = 0; k < len; k++, iindex += inc) {
349 A68_REAL *re = (A68_REAL *) (base + iindex);
350 A68_REAL *im = (A68_REAL *) (base + iindex + SIZE (MODE (REAL)));
351 gsl_complex z;
352 CHECK_INIT (p, INITIALISED (re), MODE (COMPLEX));
353 CHECK_INIT (p, INITIALISED (im), MODE (COMPLEX));
354 GSL_SET_COMPLEX (&z, VALUE (re), VALUE (im));
355 gsl_vector_complex_set (v, (size_t) k, z);
356 }
357 }
358 return (v);
359 }
360
361 /**
362 @brief Push gsl_vector_complex on the stack as [] COMPLEX.
363 @param p Node in syntax tree.
364 @param v Vector.
365 **/
366
367 static void
push_vector_complex(NODE_T * p,gsl_vector_complex * v)368 push_vector_complex (NODE_T * p, gsl_vector_complex * v)
369 {
370 A68_REF desc, row;
371 A68_ARRAY arr;
372 A68_TUPLE tup;
373 int len, inc, iindex, k;
374 BYTE_T *base;
375 len = (int) (SIZE (v));
376 desc = heap_generator (p, MODE (ROW_COMPLEX), SIZE_AL (A68_ARRAY) + SIZE_AL (A68_TUPLE));
377 row = heap_generator (p, MODE (ROW_COMPLEX), len * 2 * SIZE (MODE (REAL)));
378 DIM (&arr) = 1;
379 MOID (&arr) = MODE (COMPLEX);
380 ELEM_SIZE (&arr) = 2 * SIZE (MODE (REAL));
381 SLICE_OFFSET (&arr) = FIELD_OFFSET (&arr) = 0;
382 ARRAY (&arr) = row;
383 LWB (&tup) = 1;
384 UPB (&tup) = len;
385 SPAN (&tup) = 1;
386 SHIFT (&tup) = LWB (&tup);
387 K (&tup) = 0;
388 PUT_DESCRIPTOR (arr, tup, &desc);
389 base = DEREF (BYTE_T, &ARRAY (&arr));
390 iindex = VECTOR_OFFSET (&arr, &tup);
391 inc = SPAN (&tup) * ELEM_SIZE (&arr);
392 for (k = 0; k < len; k++, iindex += inc) {
393 A68_REAL *re = (A68_REAL *) (base + iindex);
394 A68_REAL *im = (A68_REAL *) (base + iindex + SIZE (MODE (REAL)));
395 gsl_complex z = gsl_vector_complex_get (v, (size_t) k);
396 STATUS (re) = INIT_MASK;
397 VALUE (re) = GSL_REAL (z);
398 STATUS (im) = INIT_MASK;
399 VALUE (im) = GSL_IMAG (z);
400 CHECK_COMPLEX_REPRESENTATION (p, VALUE (re), VALUE (im));
401 }
402 PUSH_REF (p, desc);
403 }
404
405 /**
406 @brief Pop [,] COMPLEX on the stack as gsl_matrix_complex.
407 @param p Node in syntax tree.
408 @param get Whether to get elements from row in the stack.
409 @return Gsl_matrix_complex.
410 **/
411
412 static gsl_matrix_complex *
pop_matrix_complex(NODE_T * p,BOOL_T get)413 pop_matrix_complex (NODE_T * p, BOOL_T get)
414 {
415 A68_REF desc;
416 A68_ARRAY *arr;
417 A68_TUPLE *tup1, *tup2;
418 int len1, len2;
419 gsl_matrix_complex *a;
420 /* Pop arguments */
421 POP_REF (p, &desc);
422 CHECK_REF (p, desc, MODE (ROWROW_COMPLEX));
423 GET_DESCRIPTOR (arr, tup1, &desc);
424 tup2 = &(tup1[1]);
425 len1 = ROW_SIZE (tup1);
426 len2 = ROW_SIZE (tup2);
427 a = gsl_matrix_complex_alloc ((size_t) len1, (size_t) len2);
428 if (get && (len1 * len2 > 0)) {
429 BYTE_T *base = DEREF (BYTE_T, &ARRAY (arr));
430 int iindex1 = MATRIX_OFFSET (arr, tup1, tup2);
431 int inc1 = SPAN (tup1) * ELEM_SIZE (arr), inc2 = SPAN (tup2) * ELEM_SIZE (arr), k1;
432 for (k1 = 0; k1 < len1; k1++, iindex1 += inc1) {
433 int iindex2, k2;
434 for (k2 = 0, iindex2 = iindex1; k2 < len2; k2++, iindex2 += inc2) {
435 A68_REAL *re = (A68_REAL *) (base + iindex2);
436 A68_REAL *im = (A68_REAL *) (base + iindex2 + SIZE (MODE (REAL)));
437 gsl_complex z;
438 CHECK_INIT (p, INITIALISED (re), MODE (COMPLEX));
439 CHECK_INIT (p, INITIALISED (im), MODE (COMPLEX));
440 GSL_SET_COMPLEX (&z, VALUE (re), VALUE (im));
441 gsl_matrix_complex_set (a, (size_t) k1, (size_t) k2, z);
442 }
443 }
444 }
445 return (a);
446 }
447
448 /**
449 @brief Push gsl_matrix_complex on the stack as [,] COMPLEX.
450 @param p Node in syntax tree.
451 @param a Matrix.
452 **/
453
454 static void
push_matrix_complex(NODE_T * p,gsl_matrix_complex * a)455 push_matrix_complex (NODE_T * p, gsl_matrix_complex * a)
456 {
457 A68_REF desc, row;
458 A68_ARRAY arr;
459 A68_TUPLE tup1, tup2;
460 int len1, len2, inc1, inc2, iindex1, iindex2, k1, k2;
461 BYTE_T *base;
462 len1 = (int) (SIZE1 (a));
463 len2 = (int) (SIZE2 (a));
464 desc = heap_generator (p, MODE (ROWROW_COMPLEX), SIZE_AL (A68_ARRAY) + 2 * SIZE_AL (A68_TUPLE));
465 row = heap_generator (p, MODE (ROWROW_COMPLEX), len1 * len2 * 2 * SIZE (MODE (REAL)));
466 DIM (&arr) = 2;
467 MOID (&arr) = MODE (COMPLEX);
468 ELEM_SIZE (&arr) = 2 * SIZE (MODE (REAL));
469 SLICE_OFFSET (&arr) = FIELD_OFFSET (&arr) = 0;
470 ARRAY (&arr) = row;
471 LWB (&tup1) = 1;
472 UPB (&tup1) = len1;
473 SPAN (&tup1) = 1;
474 SHIFT (&tup1) = LWB (&tup1);
475 K (&tup1) = 0;
476 LWB (&tup2) = 1;
477 UPB (&tup2) = len2;
478 SPAN (&tup2) = ROW_SIZE (&tup1);
479 SHIFT (&tup2) = LWB (&tup2) * SPAN (&tup2);
480 K (&tup2) = 0;
481 PUT_DESCRIPTOR2 (arr, tup1, tup2, &desc);
482 base = DEREF (BYTE_T, &ARRAY (&arr));
483 iindex1 = MATRIX_OFFSET (&arr, &tup1, &tup2);
484 inc1 = SPAN (&tup1) * ELEM_SIZE (&arr);
485 inc2 = SPAN (&tup2) * ELEM_SIZE (&arr);
486 for (k1 = 0; k1 < len1; k1++, iindex1 += inc1) {
487 for (k2 = 0, iindex2 = iindex1; k2 < len2; k2++, iindex2 += inc2) {
488 A68_REAL *re = (A68_REAL *) (base + iindex2);
489 A68_REAL *im = (A68_REAL *) (base + iindex2 + SIZE (MODE (REAL)));
490 gsl_complex z = gsl_matrix_complex_get (a, (size_t) k1, (size_t) k2);
491 STATUS (re) = INIT_MASK;
492 VALUE (re) = GSL_REAL (z);
493 STATUS (im) = INIT_MASK;
494 VALUE (im) = GSL_IMAG (z);
495 CHECK_COMPLEX_REPRESENTATION (p, VALUE (re), VALUE (im));
496 }
497 }
498 PUSH_REF (p, desc);
499 }
500
501 /**
502 @brief Generically perform operation and assign result (+:=, -:=, ...) .
503 @param p Node in syntax tree.
504 @param m Mode of REF [...] M.
505 @param n Mode of right operand M.
506 @param op Operation to be performed.
507 **/
508
509 static void
op_ab(NODE_T * p,MOID_T * m,MOID_T * n,GPROC * op)510 op_ab (NODE_T * p, MOID_T * m, MOID_T * n, GPROC * op)
511 {
512 ADDR_T parm_size = SIZE (m) + SIZE (n);
513 A68_REF dst, src, *save = (A68_REF *) STACK_OFFSET (-parm_size);
514 error_node = p;
515 dst = *save;
516 CHECK_REF (p, dst, m);
517 *save = *DEREF (A68_ROW, &dst);
518 STATUS (&src) = (STATUS_MASK) (INIT_MASK | IN_STACK_MASK);
519 OFFSET (&src) = stack_pointer - parm_size;
520 (*op) (p);
521 genie_store (p, n, &dst, &src);
522 *save = dst;
523 }
524
525 /**
526 @brief PROC vector echo = ([] REAL) [] REAL
527 @param p Node in syntax tree.
528 **/
529
530 void
genie_vector_echo(NODE_T * p)531 genie_vector_echo (NODE_T * p)
532 {
533 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
534 gsl_vector *u;
535 error_node = p;
536 u = pop_vector (p, A68_TRUE);
537 push_vector (p, u);
538 gsl_vector_free (u);
539 (void) gsl_set_error_handler (save_handler);
540 }
541
542 /**
543 @brief PROC matrix echo = ([,] REAL) [,] REAL
544 @param p Node in syntax tree.
545 **/
546
547 void
genie_matrix_echo(NODE_T * p)548 genie_matrix_echo (NODE_T * p)
549 {
550 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
551 gsl_matrix *a;
552 error_node = p;
553 a = pop_matrix (p, A68_TRUE);
554 push_matrix (p, a);
555 gsl_matrix_free (a);
556 (void) gsl_set_error_handler (save_handler);
557 }
558
559 /**
560 @brief PROC complex vector echo = ([] COMPLEX) [] COMPLEX
561 @param p Node in syntax tree.
562 **/
563
564 void
genie_vector_complex_echo(NODE_T * p)565 genie_vector_complex_echo (NODE_T * p)
566 {
567 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
568 gsl_vector_complex *u;
569 error_node = p;
570 u = pop_vector_complex (p, A68_TRUE);
571 push_vector_complex (p, u);
572 gsl_vector_complex_free (u);
573 (void) gsl_set_error_handler (save_handler);
574 }
575
576 /**
577 @brief PROC complex matrix echo = ([,] COMPLEX) [,] COMPLEX
578 @param p Node in syntax tree.
579 **/
580
581 void
genie_matrix_complex_echo(NODE_T * p)582 genie_matrix_complex_echo (NODE_T * p)
583 {
584 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
585 gsl_matrix_complex *a;
586 error_node = p;
587 a = pop_matrix_complex (p, A68_TRUE);
588 push_matrix_complex (p, a);
589 gsl_matrix_complex_free (a);
590 (void) gsl_set_error_handler (save_handler);
591 }
592
593 /**
594 @brief OP - = ([] REAL) [] REAL
595 @param p Node in syntax tree.
596 **/
597
598 void
genie_vector_minus(NODE_T * p)599 genie_vector_minus (NODE_T * p)
600 {
601 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
602 gsl_vector *u;
603 int rc;
604 error_node = p;
605 u = pop_vector (p, A68_TRUE);
606 rc = gsl_vector_scale (u, -1);
607 torrix_test_error (rc);
608 push_vector (p, u);
609 gsl_vector_free (u);
610 (void) gsl_set_error_handler (save_handler);
611 }
612
613 /**
614 @brief OP - = ([,] REAL) [,] REAL
615 @param p Node in syntax tree.
616 **/
617
618 void
genie_matrix_minus(NODE_T * p)619 genie_matrix_minus (NODE_T * p)
620 {
621 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
622 gsl_matrix *a;
623 int rc;
624 error_node = p;
625 a = pop_matrix (p, A68_TRUE);
626 rc = gsl_matrix_scale (a, -1);
627 torrix_test_error (rc);
628 push_matrix (p, a);
629 gsl_matrix_free (a);
630 (void) gsl_set_error_handler (save_handler);
631 }
632
633 /**
634 @brief OP T = ([,] REAL) [,] REAL
635 @param p Node in syntax tree.
636 **/
637
638 void
genie_matrix_transpose(NODE_T * p)639 genie_matrix_transpose (NODE_T * p)
640 {
641 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
642 gsl_matrix *a;
643 int rc;
644 error_node = p;
645 a = pop_matrix (p, A68_TRUE);
646 rc = gsl_matrix_transpose (a);
647 torrix_test_error (rc);
648 push_matrix (p, a);
649 gsl_matrix_free (a);
650 (void) gsl_set_error_handler (save_handler);
651 }
652
653 /**
654 @brief OP T = ([,] COMPLEX) [,] COMPLEX
655 @param p Node in syntax tree.
656 **/
657
658 void
genie_matrix_complex_transpose(NODE_T * p)659 genie_matrix_complex_transpose (NODE_T * p)
660 {
661 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
662 gsl_matrix_complex *a;
663 int rc;
664 error_node = p;
665 a = pop_matrix_complex (p, A68_TRUE);
666 rc = gsl_matrix_complex_transpose (a);
667 torrix_test_error (rc);
668 push_matrix_complex (p, a);
669 gsl_matrix_complex_free (a);
670 (void) gsl_set_error_handler (save_handler);
671 }
672
673 /**
674 @brief OP INV = ([,] REAL) [,] REAL
675 @param p Node in syntax tree.
676 **/
677
678 void
genie_matrix_inv(NODE_T * p)679 genie_matrix_inv (NODE_T * p)
680 {
681 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
682 gsl_permutation *q;
683 gsl_matrix *u, *inv;
684 int rc, signum;
685 error_node = p;
686 u = pop_matrix (p, A68_TRUE);
687 q = gsl_permutation_alloc (SIZE1 (u));
688 rc = gsl_linalg_LU_decomp (u, q, &signum);
689 torrix_test_error (rc);
690 inv = gsl_matrix_alloc (SIZE1 (u), SIZE2 (u));
691 rc = gsl_linalg_LU_invert (u, q, inv);
692 torrix_test_error (rc);
693 push_matrix (p, inv);
694 gsl_matrix_free (inv);
695 gsl_matrix_free (u);
696 gsl_permutation_free (q);
697 (void) gsl_set_error_handler (save_handler);
698 }
699
700 /**
701 @brief OP INV = ([,] COMPLEX) [,] COMPLEX
702 @param p Node in syntax tree.
703 **/
704
705 void
genie_matrix_complex_inv(NODE_T * p)706 genie_matrix_complex_inv (NODE_T * p)
707 {
708 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
709 gsl_permutation *q;
710 gsl_matrix_complex *u, *inv;
711 int rc, signum;
712 error_node = p;
713 u = pop_matrix_complex (p, A68_TRUE);
714 q = gsl_permutation_alloc (SIZE1 (u));
715 rc = gsl_linalg_complex_LU_decomp (u, q, &signum);
716 torrix_test_error (rc);
717 inv = gsl_matrix_complex_alloc (SIZE1 (u), SIZE2 (u));
718 rc = gsl_linalg_complex_LU_invert (u, q, inv);
719 torrix_test_error (rc);
720 push_matrix_complex (p, inv);
721 gsl_matrix_complex_free (inv);
722 gsl_matrix_complex_free (u);
723 gsl_permutation_free (q);
724 (void) gsl_set_error_handler (save_handler);
725 }
726
727 /**
728 @brief OP DET = ([,] REAL) REAL
729 @param p Node in syntax tree.
730 **/
731
732 void
genie_matrix_det(NODE_T * p)733 genie_matrix_det (NODE_T * p)
734 {
735 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
736 gsl_permutation *q;
737 gsl_matrix *u;
738 int rc, signum;
739 error_node = p;
740 u = pop_matrix (p, A68_TRUE);
741 q = gsl_permutation_alloc (SIZE1 (u));
742 rc = gsl_linalg_LU_decomp (u, q, &signum);
743 torrix_test_error (rc);
744 PUSH_PRIMITIVE (p, gsl_linalg_LU_det (u, signum), A68_REAL);
745 gsl_matrix_free (u);
746 gsl_permutation_free (q);
747 (void) gsl_set_error_handler (save_handler);
748 }
749
750 /**
751 @brief OP DET = ([,] COMPLEX) COMPLEX
752 @param p Node in syntax tree.
753 **/
754
755 void
genie_matrix_complex_det(NODE_T * p)756 genie_matrix_complex_det (NODE_T * p)
757 {
758 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
759 gsl_permutation *q;
760 gsl_matrix_complex *u;
761 int rc, signum;
762 gsl_complex det;
763 error_node = p;
764 u = pop_matrix_complex (p, A68_TRUE);
765 q = gsl_permutation_alloc (SIZE1 (u));
766 rc = gsl_linalg_complex_LU_decomp (u, q, &signum);
767 torrix_test_error (rc);
768 det = gsl_linalg_complex_LU_det (u, signum);
769 PUSH_PRIMITIVE (p, GSL_REAL (det), A68_REAL);
770 PUSH_PRIMITIVE (p, GSL_IMAG (det), A68_REAL);
771 gsl_matrix_complex_free (u);
772 gsl_permutation_free (q);
773 (void) gsl_set_error_handler (save_handler);
774 }
775
776 /**
777 @brief OP TRACE = ([,] REAL) REAL
778 @param p Node in syntax tree.
779 **/
780
781 void
genie_matrix_trace(NODE_T * p)782 genie_matrix_trace (NODE_T * p)
783 {
784 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
785 gsl_matrix *a;
786 double sum;
787 int len1, len2, k;
788 error_node = p;
789 a = pop_matrix (p, A68_TRUE);
790 len1 = (int) (SIZE1 (a));
791 len2 = (int) (SIZE2 (a));
792 if (len1 != len2) {
793 torrix_error_handler ("cannot calculate trace", __FILE__, __LINE__, GSL_ENOTSQR);
794 }
795 sum = 0.0;
796 for (k = 0; k < len1; k++) {
797 sum += gsl_matrix_get (a, (size_t) k, (size_t) k);
798 }
799 PUSH_PRIMITIVE (p, sum, A68_REAL);
800 gsl_matrix_free (a);
801 (void) gsl_set_error_handler (save_handler);
802 }
803
804 /**
805 @brief OP TRACE = ([,] COMPLEX) COMPLEX
806 @param p Node in syntax tree.
807 **/
808
809 void
genie_matrix_complex_trace(NODE_T * p)810 genie_matrix_complex_trace (NODE_T * p)
811 {
812 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
813 gsl_matrix_complex *a;
814 gsl_complex sum;
815 int len1, len2, k;
816 error_node = p;
817 a = pop_matrix_complex (p, A68_TRUE);
818 len1 = (int) (SIZE1 (a));
819 len2 = (int) (SIZE2 (a));
820 if (len1 != len2) {
821 torrix_error_handler ("cannot calculate trace", __FILE__, __LINE__, GSL_ENOTSQR);
822 }
823 GSL_SET_COMPLEX (&sum, 0.0, 0.0);
824 for (k = 0; k < len1; k++) {
825 sum = gsl_complex_add (sum, gsl_matrix_complex_get (a, (size_t) k, (size_t) k));
826 }
827 PUSH_PRIMITIVE (p, GSL_REAL (sum), A68_REAL);
828 PUSH_PRIMITIVE (p, GSL_IMAG (sum), A68_REAL);
829 gsl_matrix_complex_free (a);
830 (void) gsl_set_error_handler (save_handler);
831 }
832
833 /**
834 @brief OP - = ([] COMPLEX) [] COMPLEX
835 @param p Node in syntax tree.
836 **/
837
838 void
genie_vector_complex_minus(NODE_T * p)839 genie_vector_complex_minus (NODE_T * p)
840 {
841 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
842 gsl_vector_complex *u;
843 error_node = p;
844 u = pop_vector_complex (p, A68_TRUE);
845 gsl_blas_zdscal (-1, u);
846 push_vector_complex (p, u);
847 gsl_vector_complex_free (u);
848 (void) gsl_set_error_handler (save_handler);
849 }
850
851 /**
852 @brief OP - = ([,] COMPLEX) [,] COMPLEX
853 @param p Node in syntax tree.
854 **/
855
856 void
genie_matrix_complex_minus(NODE_T * p)857 genie_matrix_complex_minus (NODE_T * p)
858 {
859 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
860 gsl_matrix_complex *a;
861 gsl_complex one;
862 int rc;
863 error_node = p;
864 GSL_SET_COMPLEX (&one, -1.0, 0.0);
865 a = pop_matrix_complex (p, A68_TRUE);
866 rc = gsl_matrix_complex_scale (a, one);
867 torrix_test_error (rc);
868 push_matrix_complex (p, a);
869 gsl_matrix_complex_free (a);
870 (void) gsl_set_error_handler (save_handler);
871 }
872
873 /**
874 @brief OP + = ([] REAL, [] REAL) [] REAL
875 @param p Node in syntax tree.
876 **/
877
878 void
genie_vector_add(NODE_T * p)879 genie_vector_add (NODE_T * p)
880 {
881 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
882 gsl_vector *u, *v;
883 int rc;
884 error_node = p;
885 v = pop_vector (p, A68_TRUE);
886 u = pop_vector (p, A68_TRUE);
887 rc = gsl_vector_add (u, v);
888 torrix_test_error (rc);
889 push_vector (p, u);
890 gsl_vector_free (u);
891 gsl_vector_free (v);
892 (void) gsl_set_error_handler (save_handler);
893 }
894
895 /**
896 @brief OP - = ([] REAL, [] REAL) [] REAL
897 @param p Node in syntax tree.
898 **/
899
900 void
genie_vector_sub(NODE_T * p)901 genie_vector_sub (NODE_T * p)
902 {
903 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
904 gsl_vector *u, *v;
905 int rc;
906 error_node = p;
907 v = pop_vector (p, A68_TRUE);
908 u = pop_vector (p, A68_TRUE);
909 rc = gsl_vector_sub (u, v);
910 torrix_test_error (rc);
911 push_vector (p, u);
912 gsl_vector_free (u);
913 gsl_vector_free (v);
914 (void) gsl_set_error_handler (save_handler);
915 }
916
917 /**
918 @brief OP = = ([] REAL, [] REAL) BOOL
919 @param p Node in syntax tree.
920 **/
921
922 void
genie_vector_eq(NODE_T * p)923 genie_vector_eq (NODE_T * p)
924 {
925 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
926 gsl_vector *u, *v;
927 int rc;
928 error_node = p;
929 v = pop_vector (p, A68_TRUE);
930 u = pop_vector (p, A68_TRUE);
931 rc = gsl_vector_sub (u, v);
932 torrix_test_error (rc);
933 PUSH_PRIMITIVE (p, (BOOL_T) (gsl_vector_isnull (u) ? A68_TRUE : A68_FALSE), A68_BOOL);
934 gsl_vector_free (u);
935 gsl_vector_free (v);
936 (void) gsl_set_error_handler (save_handler);
937 }
938
939 /**
940 @brief OP /= = ([] REAL, [] REAL) BOOL
941 @param p Node in syntax tree.
942 **/
943
944 void
genie_vector_ne(NODE_T * p)945 genie_vector_ne (NODE_T * p)
946 {
947 genie_vector_eq (p);
948 genie_not_bool (p);
949 }
950
951 /**
952 @brief OP +:= = (REF [] REAL, [] REAL) REF [] REAL
953 @param p Node in syntax tree.
954 **/
955
956 void
genie_vector_plusab(NODE_T * p)957 genie_vector_plusab (NODE_T * p)
958 {
959 op_ab (p, MODE (REF_ROW_REAL), MODE (ROW_REAL), genie_vector_add);
960 }
961
962 /**
963 @brief OP -:= = (REF [] REAL, [] REAL) REF [] REAL
964 @param p Node in syntax tree.
965 **/
966
967 void
genie_vector_minusab(NODE_T * p)968 genie_vector_minusab (NODE_T * p)
969 {
970 op_ab (p, MODE (REF_ROW_REAL), MODE (ROW_REAL), genie_vector_sub);
971 }
972
973 /**
974 @brief OP + = ([, ] REAL, [, ] REAL) [, ] REAL
975 @param p Node in syntax tree.
976 **/
977
978 void
genie_matrix_add(NODE_T * p)979 genie_matrix_add (NODE_T * p)
980 {
981 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
982 gsl_matrix *u, *v;
983 int rc;
984 error_node = p;
985 v = pop_matrix (p, A68_TRUE);
986 u = pop_matrix (p, A68_TRUE);
987 rc = gsl_matrix_add (u, v);
988 torrix_test_error (rc);
989 push_matrix (p, u);
990 gsl_matrix_free (u);
991 gsl_matrix_free (v);
992 (void) gsl_set_error_handler (save_handler);
993 }
994
995 /**
996 @brief OP - = ([, ] REAL, [, ] REAL) [, ] REAL
997 @param p Node in syntax tree.
998 **/
999
1000 void
genie_matrix_sub(NODE_T * p)1001 genie_matrix_sub (NODE_T * p)
1002 {
1003 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1004 gsl_matrix *u, *v;
1005 int rc;
1006 error_node = p;
1007 v = pop_matrix (p, A68_TRUE);
1008 u = pop_matrix (p, A68_TRUE);
1009 rc = gsl_matrix_sub (u, v);
1010 torrix_test_error (rc);
1011 push_matrix (p, u);
1012 gsl_matrix_free (u);
1013 gsl_matrix_free (v);
1014 (void) gsl_set_error_handler (save_handler);
1015 }
1016
1017 /**
1018 @brief OP = = ([, ] REAL, [, ] REAL) [, ] BOOL
1019 @param p Node in syntax tree.
1020 **/
1021
1022 void
genie_matrix_eq(NODE_T * p)1023 genie_matrix_eq (NODE_T * p)
1024 {
1025 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1026 gsl_matrix *u, *v;
1027 int rc;
1028 error_node = p;
1029 v = pop_matrix (p, A68_TRUE);
1030 u = pop_matrix (p, A68_TRUE);
1031 rc = gsl_matrix_sub (u, v);
1032 torrix_test_error (rc);
1033 PUSH_PRIMITIVE (p, (BOOL_T) (gsl_matrix_isnull (u) ? A68_TRUE : A68_FALSE), A68_BOOL);
1034 gsl_matrix_free (u);
1035 gsl_matrix_free (v);
1036 (void) gsl_set_error_handler (save_handler);
1037 }
1038
1039 /**
1040 @brief OP /= = ([, ] REAL, [, ] REAL) [, ] BOOL
1041 @param p Node in syntax tree.
1042 **/
1043
1044 void
genie_matrix_ne(NODE_T * p)1045 genie_matrix_ne (NODE_T * p)
1046 {
1047 genie_matrix_eq (p);
1048 genie_not_bool (p);
1049 }
1050
1051 /**
1052 @brief OP +:= = (REF [, ] REAL, [, ] REAL) [, ] REAL
1053 @param p Node in syntax tree.
1054 **/
1055
1056 void
genie_matrix_plusab(NODE_T * p)1057 genie_matrix_plusab (NODE_T * p)
1058 {
1059 op_ab (p, MODE (REF_ROWROW_REAL), MODE (ROWROW_REAL), genie_matrix_add);
1060 }
1061
1062 /**
1063 @brief OP -:= = (REF [, ] REAL, [, ] REAL) [, ] REAL
1064 @param p Node in syntax tree.
1065 **/
1066
1067 void
genie_matrix_minusab(NODE_T * p)1068 genie_matrix_minusab (NODE_T * p)
1069 {
1070 op_ab (p, MODE (REF_ROWROW_REAL), MODE (ROWROW_REAL), genie_matrix_sub);
1071 }
1072
1073 /**
1074 @brief OP + = ([] COMPLEX, [] COMPLEX) [] COMPLEX
1075 @param p Node in syntax tree.
1076 **/
1077
1078 void
genie_vector_complex_add(NODE_T * p)1079 genie_vector_complex_add (NODE_T * p)
1080 {
1081 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1082 gsl_vector_complex *u, *v;
1083 gsl_complex one;
1084 int rc;
1085 error_node = p;
1086 GSL_SET_COMPLEX (&one, 1.0, 0.0);
1087 v = pop_vector_complex (p, A68_TRUE);
1088 u = pop_vector_complex (p, A68_TRUE);
1089 rc = gsl_blas_zaxpy (one, u, v);
1090 torrix_test_error (rc);
1091 push_vector_complex (p, v);
1092 gsl_vector_complex_free (u);
1093 gsl_vector_complex_free (v);
1094 (void) gsl_set_error_handler (save_handler);
1095 }
1096
1097 /**
1098 @brief OP - = ([] COMPLEX, [] COMPLEX) [] COMPLEX
1099 @param p Node in syntax tree.
1100 **/
1101
1102 void
genie_vector_complex_sub(NODE_T * p)1103 genie_vector_complex_sub (NODE_T * p)
1104 {
1105 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1106 gsl_vector_complex *u, *v;
1107 gsl_complex one;
1108 int rc;
1109 error_node = p;
1110 GSL_SET_COMPLEX (&one, -1.0, 0.0);
1111 v = pop_vector_complex (p, A68_TRUE);
1112 u = pop_vector_complex (p, A68_TRUE);
1113 rc = gsl_blas_zaxpy (one, v, u);
1114 torrix_test_error (rc);
1115 push_vector_complex (p, u);
1116 gsl_vector_complex_free (u);
1117 gsl_vector_complex_free (v);
1118 (void) gsl_set_error_handler (save_handler);
1119 }
1120
1121 /**
1122 @brief OP = = ([] COMPLEX, [] COMPLEX) BOOL
1123 @param p Node in syntax tree.
1124 **/
1125
1126 void
genie_vector_complex_eq(NODE_T * p)1127 genie_vector_complex_eq (NODE_T * p)
1128 {
1129 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1130 gsl_vector_complex *u, *v;
1131 gsl_complex one;
1132 int rc;
1133 error_node = p;
1134 GSL_SET_COMPLEX (&one, -1.0, 0.0);
1135 v = pop_vector_complex (p, A68_TRUE);
1136 u = pop_vector_complex (p, A68_TRUE);
1137 rc = gsl_blas_zaxpy (one, v, u);
1138 torrix_test_error (rc);
1139 PUSH_PRIMITIVE (p, (BOOL_T) (gsl_vector_complex_isnull (u) ? A68_TRUE : A68_FALSE), A68_BOOL);
1140 gsl_vector_complex_free (u);
1141 gsl_vector_complex_free (v);
1142 (void) gsl_set_error_handler (save_handler);
1143 }
1144
1145 /**
1146 @brief OP /= = ([] COMPLEX, [] COMPLEX) BOOL
1147 @param p Node in syntax tree.
1148 **/
1149
1150 void
genie_vector_complex_ne(NODE_T * p)1151 genie_vector_complex_ne (NODE_T * p)
1152 {
1153 genie_vector_complex_eq (p);
1154 genie_not_bool (p);
1155 }
1156
1157 /**
1158 @brief OP +:= = (REF [] COMPLEX, [] COMPLEX) [] COMPLEX
1159 @param p Node in syntax tree.
1160 **/
1161
1162 void
genie_vector_complex_plusab(NODE_T * p)1163 genie_vector_complex_plusab (NODE_T * p)
1164 {
1165 op_ab (p, MODE (REF_ROW_COMPLEX), MODE (ROW_COMPLEX), genie_vector_complex_add);
1166 }
1167
1168 /**
1169 @brief OP -:= = (REF [] COMPLEX, [] COMPLEX) [] COMPLEX
1170 @param p Node in syntax tree.
1171 **/
1172
1173 void
genie_vector_complex_minusab(NODE_T * p)1174 genie_vector_complex_minusab (NODE_T * p)
1175 {
1176 op_ab (p, MODE (REF_ROW_COMPLEX), MODE (ROW_COMPLEX), genie_vector_complex_sub);
1177 }
1178
1179 /**
1180 @brief OP + = ([, ] COMPLEX, [, ] COMPLEX) [, ] COMPLEX
1181 @param p Node in syntax tree.
1182 **/
1183
1184 void
genie_matrix_complex_add(NODE_T * p)1185 genie_matrix_complex_add (NODE_T * p)
1186 {
1187 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1188 gsl_matrix_complex *u, *v;
1189 int rc;
1190 error_node = p;
1191 v = pop_matrix_complex (p, A68_TRUE);
1192 u = pop_matrix_complex (p, A68_TRUE);
1193 rc = gsl_matrix_complex_add (u, v);
1194 torrix_test_error (rc);
1195 push_matrix_complex (p, u);
1196 gsl_matrix_complex_free (u);
1197 gsl_matrix_complex_free (v);
1198 (void) gsl_set_error_handler (save_handler);
1199 }
1200
1201 /**
1202 @brief OP - = ([, ] COMPLEX, [, ] COMPLEX) [, ] COMPLEX
1203 @param p Node in syntax tree.
1204 **/
1205
1206 void
genie_matrix_complex_sub(NODE_T * p)1207 genie_matrix_complex_sub (NODE_T * p)
1208 {
1209 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1210 gsl_matrix_complex *u, *v;
1211 int rc;
1212 error_node = p;
1213 v = pop_matrix_complex (p, A68_TRUE);
1214 u = pop_matrix_complex (p, A68_TRUE);
1215 rc = gsl_matrix_complex_sub (u, v);
1216 torrix_test_error (rc);
1217 push_matrix_complex (p, u);
1218 gsl_matrix_complex_free (u);
1219 gsl_matrix_complex_free (v);
1220 (void) gsl_set_error_handler (save_handler);
1221 }
1222
1223 /**
1224 @brief OP = = ([, ] COMPLEX, [, ] COMPLEX) BOOL
1225 @param p Node in syntax tree.
1226 **/
1227
1228 void
genie_matrix_complex_eq(NODE_T * p)1229 genie_matrix_complex_eq (NODE_T * p)
1230 {
1231 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1232 gsl_matrix_complex *u, *v;
1233 int rc;
1234 error_node = p;
1235 v = pop_matrix_complex (p, A68_TRUE);
1236 u = pop_matrix_complex (p, A68_TRUE);
1237 rc = gsl_matrix_complex_sub (u, v);
1238 torrix_test_error (rc);
1239 PUSH_PRIMITIVE (p, (BOOL_T) (gsl_matrix_complex_isnull (u) ? A68_TRUE : A68_FALSE), A68_BOOL);
1240 gsl_matrix_complex_free (u);
1241 gsl_matrix_complex_free (v);
1242 (void) gsl_set_error_handler (save_handler);
1243 }
1244
1245 /**
1246 @brief OP /= = ([, ] COMPLEX, [, ] COMPLEX) BOOL
1247 @param p Node in syntax tree.
1248 **/
1249
1250 void
genie_matrix_complex_ne(NODE_T * p)1251 genie_matrix_complex_ne (NODE_T * p)
1252 {
1253 genie_matrix_complex_eq (p);
1254 genie_not_bool (p);
1255 }
1256
1257 /**
1258 @brief OP +:= = (REF [, ] COMPLEX, [, ] COMPLEX) [, ] COMPLEX
1259 @param p Node in syntax tree.
1260 **/
1261
1262 void
genie_matrix_complex_plusab(NODE_T * p)1263 genie_matrix_complex_plusab (NODE_T * p)
1264 {
1265 op_ab (p, MODE (REF_ROWROW_COMPLEX), MODE (ROWROW_COMPLEX), genie_matrix_complex_add);
1266 }
1267
1268 /**
1269 @brief OP -:= = (REF [, ] COMPLEX, [, ] COMPLEX) [, ] COMPLEX
1270 @param p Node in syntax tree.
1271 **/
1272
1273 void
genie_matrix_complex_minusab(NODE_T * p)1274 genie_matrix_complex_minusab (NODE_T * p)
1275 {
1276 op_ab (p, MODE (REF_ROWROW_COMPLEX), MODE (ROWROW_COMPLEX), genie_matrix_complex_sub);
1277 }
1278
1279 /**
1280 @brief OP * = ([] REAL, REAL) [] REAL
1281 @param p Node in syntax tree.
1282 **/
1283
1284 void
genie_vector_scale_real(NODE_T * p)1285 genie_vector_scale_real (NODE_T * p)
1286 {
1287 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1288 gsl_vector *u;
1289 A68_REAL v;
1290 int rc;
1291 error_node = p;
1292 POP_OBJECT (p, &v, A68_REAL);
1293 u = pop_vector (p, A68_TRUE);
1294 rc = gsl_vector_scale (u, VALUE (&v));
1295 torrix_test_error (rc);
1296 push_vector (p, u);
1297 gsl_vector_free (u);
1298 (void) gsl_set_error_handler (save_handler);
1299 }
1300
1301 /**
1302 @brief OP * = (REAL, [] REAL) [] REAL
1303 @param p Node in syntax tree.
1304 **/
1305
1306 void
genie_real_scale_vector(NODE_T * p)1307 genie_real_scale_vector (NODE_T * p)
1308 {
1309 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1310 gsl_vector *u;
1311 A68_REAL v;
1312 int rc;
1313 error_node = p;
1314 u = pop_vector (p, A68_TRUE);
1315 POP_OBJECT (p, &v, A68_REAL);
1316 rc = gsl_vector_scale (u, VALUE (&v));
1317 torrix_test_error (rc);
1318 push_vector (p, u);
1319 gsl_vector_free (u);
1320 (void) gsl_set_error_handler (save_handler);
1321 }
1322
1323 /**
1324 @brief OP * = ([, ] REAL, REAL) [, ] REAL
1325 @param p Node in syntax tree.
1326 **/
1327
1328 void
genie_matrix_scale_real(NODE_T * p)1329 genie_matrix_scale_real (NODE_T * p)
1330 {
1331 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1332 gsl_matrix *u;
1333 A68_REAL v;
1334 int rc;
1335 error_node = p;
1336 POP_OBJECT (p, &v, A68_REAL);
1337 u = pop_matrix (p, A68_TRUE);
1338 rc = gsl_matrix_scale (u, VALUE (&v));
1339 torrix_test_error (rc);
1340 push_matrix (p, u);
1341 gsl_matrix_free (u);
1342 (void) gsl_set_error_handler (save_handler);
1343 }
1344
1345 /**
1346 @brief OP * = (REAL, [, ] REAL) [, ] REAL
1347 @param p Node in syntax tree.
1348 **/
1349
1350 void
genie_real_scale_matrix(NODE_T * p)1351 genie_real_scale_matrix (NODE_T * p)
1352 {
1353 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1354 gsl_matrix *u;
1355 A68_REAL v;
1356 int rc;
1357 error_node = p;
1358 u = pop_matrix (p, A68_TRUE);
1359 POP_OBJECT (p, &v, A68_REAL);
1360 rc = gsl_matrix_scale (u, VALUE (&v));
1361 torrix_test_error (rc);
1362 push_matrix (p, u);
1363 gsl_matrix_free (u);
1364 (void) gsl_set_error_handler (save_handler);
1365 }
1366
1367 /**
1368 @brief OP * = ([] COMPLEX, COMPLEX) [] COMPLEX
1369 @param p Node in syntax tree.
1370 **/
1371
1372 void
genie_vector_complex_scale_complex(NODE_T * p)1373 genie_vector_complex_scale_complex (NODE_T * p)
1374 {
1375 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1376 gsl_vector_complex *u;
1377 A68_REAL re, im;
1378 gsl_complex v;
1379 error_node = p;
1380 POP_OBJECT (p, &im, A68_REAL);
1381 POP_OBJECT (p, &re, A68_REAL);
1382 GSL_SET_COMPLEX (&v, VALUE (&re), VALUE (&im));
1383 u = pop_vector_complex (p, A68_TRUE);
1384 gsl_blas_zscal (v, u);
1385 push_vector_complex (p, u);
1386 gsl_vector_complex_free (u);
1387 (void) gsl_set_error_handler (save_handler);
1388 }
1389
1390 /**
1391 @brief OP * = (COMPLEX, [] COMPLEX) [] COMPLEX
1392 @param p Node in syntax tree.
1393 **/
1394
1395 void
genie_complex_scale_vector_complex(NODE_T * p)1396 genie_complex_scale_vector_complex (NODE_T * p)
1397 {
1398 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1399 gsl_vector_complex *u;
1400 A68_REAL re, im;
1401 gsl_complex v;
1402 error_node = p;
1403 u = pop_vector_complex (p, A68_TRUE);
1404 POP_OBJECT (p, &im, A68_REAL);
1405 POP_OBJECT (p, &re, A68_REAL);
1406 GSL_SET_COMPLEX (&v, VALUE (&re), VALUE (&im));
1407 gsl_blas_zscal (v, u);
1408 push_vector_complex (p, u);
1409 gsl_vector_complex_free (u);
1410 (void) gsl_set_error_handler (save_handler);
1411 }
1412
1413 /**
1414 @brief OP * = ([, ] COMPLEX, COMPLEX) [, ] COMPLEX
1415 @param p Node in syntax tree.
1416 **/
1417
1418 void
genie_matrix_complex_scale_complex(NODE_T * p)1419 genie_matrix_complex_scale_complex (NODE_T * p)
1420 {
1421 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1422 gsl_matrix_complex *u;
1423 A68_REAL re, im;
1424 gsl_complex v;
1425 int rc;
1426 error_node = p;
1427 POP_OBJECT (p, &im, A68_REAL);
1428 POP_OBJECT (p, &re, A68_REAL);
1429 GSL_SET_COMPLEX (&v, VALUE (&re), VALUE (&im));
1430 u = pop_matrix_complex (p, A68_TRUE);
1431 rc = gsl_matrix_complex_scale (u, v);
1432 torrix_test_error (rc);
1433 push_matrix_complex (p, u);
1434 gsl_matrix_complex_free (u);
1435 (void) gsl_set_error_handler (save_handler);
1436 }
1437
1438 /**
1439 @brief OP * = (COMPLEX, [, ] COMPLEX) [, ] COMPLEX
1440 @param p Node in syntax tree.
1441 **/
1442
1443 void
genie_complex_scale_matrix_complex(NODE_T * p)1444 genie_complex_scale_matrix_complex (NODE_T * p)
1445 {
1446 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1447 gsl_matrix_complex *u;
1448 A68_REAL re, im;
1449 gsl_complex v;
1450 int rc;
1451 error_node = p;
1452 u = pop_matrix_complex (p, A68_TRUE);
1453 POP_OBJECT (p, &im, A68_REAL);
1454 POP_OBJECT (p, &re, A68_REAL);
1455 GSL_SET_COMPLEX (&v, VALUE (&re), VALUE (&im));
1456 rc = gsl_matrix_complex_scale (u, v);
1457 torrix_test_error (rc);
1458 push_matrix_complex (p, u);
1459 gsl_matrix_complex_free (u);
1460 (void) gsl_set_error_handler (save_handler);
1461 }
1462
1463 /**
1464 @brief OP *:= (REF [] REAL, REAL) REF [] REAL
1465 @param p Node in syntax tree.
1466 **/
1467
1468 void
genie_vector_scale_real_ab(NODE_T * p)1469 genie_vector_scale_real_ab (NODE_T * p)
1470 {
1471 op_ab (p, MODE (REF_ROW_REAL), MODE (REAL), genie_vector_scale_real);
1472 }
1473
1474 /**
1475 @brief OP *:= (REF [, ] REAL, REAL) REF [, ] REAL
1476 @param p Node in syntax tree.
1477 **/
1478
1479 void
genie_matrix_scale_real_ab(NODE_T * p)1480 genie_matrix_scale_real_ab (NODE_T * p)
1481 {
1482 op_ab (p, MODE (REF_ROWROW_REAL), MODE (REAL), genie_matrix_scale_real);
1483 }
1484
1485 /**
1486 @brief OP *:= (REF [] COMPLEX, COMPLEX) REF [] COMPLEX
1487 @param p Node in syntax tree.
1488 **/
1489
1490 void
genie_vector_complex_scale_complex_ab(NODE_T * p)1491 genie_vector_complex_scale_complex_ab (NODE_T * p)
1492 {
1493 op_ab (p, MODE (REF_ROW_COMPLEX), MODE (COMPLEX), genie_vector_complex_scale_complex);
1494 }
1495
1496 /**
1497 @brief OP *:= (REF [, ] COMPLEX, COMPLEX) REF [, ] COMPLEX
1498 @param p Node in syntax tree.
1499 **/
1500
1501 void
genie_matrix_complex_scale_complex_ab(NODE_T * p)1502 genie_matrix_complex_scale_complex_ab (NODE_T * p)
1503 {
1504 op_ab (p, MODE (REF_ROWROW_COMPLEX), MODE (COMPLEX), genie_matrix_complex_scale_complex);
1505 }
1506
1507 /**
1508 @brief OP / = ([] REAL, REAL) [] REAL
1509 @param p Node in syntax tree.
1510 **/
1511
1512 void
genie_vector_div_real(NODE_T * p)1513 genie_vector_div_real (NODE_T * p)
1514 {
1515 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1516 gsl_vector *u;
1517 A68_REAL v;
1518 int rc;
1519 error_node = p;
1520 POP_OBJECT (p, &v, A68_REAL);
1521 if (VALUE (&v) == 0.0) {
1522 diagnostic_node (A68_RUNTIME_ERROR, p, ERROR_DIVISION_BY_ZERO, MODE (ROW_REAL));
1523 exit_genie (p, A68_RUNTIME_ERROR);
1524 }
1525 u = pop_vector (p, A68_TRUE);
1526 rc = gsl_vector_scale (u, 1.0 / VALUE (&v));
1527 torrix_test_error (rc);
1528 push_vector (p, u);
1529 gsl_vector_free (u);
1530 (void) gsl_set_error_handler (save_handler);
1531 }
1532
1533 /**
1534 @brief OP / = ([, ] REAL, REAL) [, ] REAL
1535 @param p Node in syntax tree.
1536 **/
1537
1538 void
genie_matrix_div_real(NODE_T * p)1539 genie_matrix_div_real (NODE_T * p)
1540 {
1541 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1542 gsl_matrix *u;
1543 A68_REAL v;
1544 int rc;
1545 error_node = p;
1546 POP_OBJECT (p, &v, A68_REAL);
1547 if (VALUE (&v) == 0.0) {
1548 diagnostic_node (A68_RUNTIME_ERROR, p, ERROR_DIVISION_BY_ZERO, MODE (ROWROW_REAL));
1549 exit_genie (p, A68_RUNTIME_ERROR);
1550 }
1551 u = pop_matrix (p, A68_TRUE);
1552 rc = gsl_matrix_scale (u, 1.0 / VALUE (&v));
1553 torrix_test_error (rc);
1554 push_matrix (p, u);
1555 gsl_matrix_free (u);
1556 (void) gsl_set_error_handler (save_handler);
1557 }
1558
1559 /**
1560 @brief OP / = ([] COMPLEX, COMPLEX) [] COMPLEX
1561 @param p Node in syntax tree.
1562 **/
1563
1564 void
genie_vector_complex_div_complex(NODE_T * p)1565 genie_vector_complex_div_complex (NODE_T * p)
1566 {
1567 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1568 gsl_vector_complex *u;
1569 A68_REAL re, im;
1570 gsl_complex v;
1571 error_node = p;
1572 POP_OBJECT (p, &im, A68_REAL);
1573 POP_OBJECT (p, &re, A68_REAL);
1574 if (VALUE (&re) == 0.0 && VALUE (&im) == 0.0) {
1575 diagnostic_node (A68_RUNTIME_ERROR, p, ERROR_DIVISION_BY_ZERO, MODE (ROW_COMPLEX));
1576 exit_genie (p, A68_RUNTIME_ERROR);
1577 }
1578 GSL_SET_COMPLEX (&v, VALUE (&re), VALUE (&im));
1579 u = pop_vector_complex (p, A68_TRUE);
1580 v = gsl_complex_inverse (v);
1581 gsl_blas_zscal (v, u);
1582 push_vector_complex (p, u);
1583 gsl_vector_complex_free (u);
1584 (void) gsl_set_error_handler (save_handler);
1585 }
1586
1587 /**
1588 @brief OP / = ([, ] COMPLEX, COMPLEX) [, ] COMPLEX
1589 @param p Node in syntax tree.
1590 **/
1591
1592 void
genie_matrix_complex_div_complex(NODE_T * p)1593 genie_matrix_complex_div_complex (NODE_T * p)
1594 {
1595 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1596 gsl_matrix_complex *u;
1597 A68_REAL re, im;
1598 gsl_complex v;
1599 int rc;
1600 error_node = p;
1601 POP_OBJECT (p, &im, A68_REAL);
1602 POP_OBJECT (p, &re, A68_REAL);
1603 if (VALUE (&re) == 0.0 && VALUE (&im) == 0.0) {
1604 diagnostic_node (A68_RUNTIME_ERROR, p, ERROR_DIVISION_BY_ZERO, MODE (ROWROW_COMPLEX));
1605 exit_genie (p, A68_RUNTIME_ERROR);
1606 }
1607 GSL_SET_COMPLEX (&v, VALUE (&re), VALUE (&im));
1608 v = gsl_complex_inverse (v);
1609 u = pop_matrix_complex (p, A68_TRUE);
1610 rc = gsl_matrix_complex_scale (u, v);
1611 torrix_test_error (rc);
1612 push_matrix_complex (p, u);
1613 gsl_matrix_complex_free (u);
1614 (void) gsl_set_error_handler (save_handler);
1615 }
1616
1617 /**
1618 @brief OP /:= (REF [] REAL, REAL) REF [] REAL
1619 @param p Node in syntax tree.
1620 **/
1621
1622 void
genie_vector_div_real_ab(NODE_T * p)1623 genie_vector_div_real_ab (NODE_T * p)
1624 {
1625 op_ab (p, MODE (REF_ROW_REAL), MODE (REAL), genie_vector_div_real);
1626 }
1627
1628 /**
1629 @brief OP /:= (REF [, ] REAL, REAL) REF [, ] REAL
1630 @param p Node in syntax tree.
1631 **/
1632
1633 void
genie_matrix_div_real_ab(NODE_T * p)1634 genie_matrix_div_real_ab (NODE_T * p)
1635 {
1636 op_ab (p, MODE (REF_ROWROW_REAL), MODE (REAL), genie_matrix_div_real);
1637 }
1638
1639 /**
1640 @brief OP /:= (REF [] COMPLEX, COMPLEX) REF [] COMPLEX
1641 @param p Node in syntax tree.
1642 **/
1643
1644 void
genie_vector_complex_div_complex_ab(NODE_T * p)1645 genie_vector_complex_div_complex_ab (NODE_T * p)
1646 {
1647 op_ab (p, MODE (REF_ROW_COMPLEX), MODE (COMPLEX), genie_vector_complex_div_complex);
1648 }
1649
1650 /**
1651 @brief OP /:= (REF [, ] COMPLEX, COMPLEX) REF [, ] COMPLEX
1652 @param p Node in syntax tree.
1653 **/
1654
1655 void
genie_matrix_complex_div_complex_ab(NODE_T * p)1656 genie_matrix_complex_div_complex_ab (NODE_T * p)
1657 {
1658 op_ab (p, MODE (REF_ROWROW_COMPLEX), MODE (COMPLEX), genie_matrix_complex_div_complex);
1659 }
1660
1661 /**
1662 @brief OP * = ([] REAL, [] REAL) REAL
1663 @param p Node in syntax tree.
1664 **/
1665
1666 void
genie_vector_dot(NODE_T * p)1667 genie_vector_dot (NODE_T * p)
1668 {
1669 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1670 gsl_vector *u, *v;
1671 double w;
1672 int rc;
1673 error_node = p;
1674 v = pop_vector (p, A68_TRUE);
1675 u = pop_vector (p, A68_TRUE);
1676 rc = gsl_blas_ddot (u, v, &w);
1677 torrix_test_error (rc);
1678 PUSH_PRIMITIVE (p, w, A68_REAL);
1679 gsl_vector_free (u);
1680 gsl_vector_free (v);
1681 (void) gsl_set_error_handler (save_handler);
1682 }
1683
1684 /**
1685 @brief OP * = ([] COMPLEX, [] COMPLEX) COMPLEX
1686 @param p Node in syntax tree.
1687 **/
1688
1689 void
genie_vector_complex_dot(NODE_T * p)1690 genie_vector_complex_dot (NODE_T * p)
1691 {
1692 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1693 gsl_vector_complex *u, *v;
1694 gsl_complex w;
1695 int rc;
1696 error_node = p;
1697 v = pop_vector_complex (p, A68_TRUE);
1698 u = pop_vector_complex (p, A68_TRUE);
1699 rc = gsl_blas_zdotc (u, v, &w);
1700 torrix_test_error (rc);
1701 PUSH_PRIMITIVE (p, GSL_REAL (w), A68_REAL);
1702 PUSH_PRIMITIVE (p, GSL_IMAG (w), A68_REAL);
1703 gsl_vector_complex_free (u);
1704 gsl_vector_complex_free (v);
1705 (void) gsl_set_error_handler (save_handler);
1706 }
1707
1708 /**
1709 @brief OP NORM = ([] REAL) REAL
1710 @param p Node in syntax tree.
1711 **/
1712
1713 void
genie_vector_norm(NODE_T * p)1714 genie_vector_norm (NODE_T * p)
1715 {
1716 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1717 gsl_vector *u;
1718 error_node = p;
1719 u = pop_vector (p, A68_TRUE);
1720 PUSH_PRIMITIVE (p, gsl_blas_dnrm2 (u), A68_REAL);
1721 gsl_vector_free (u);
1722 (void) gsl_set_error_handler (save_handler);
1723 }
1724
1725 /**
1726 @brief OP NORM = ([] COMPLEX) COMPLEX
1727 @param p Node in syntax tree.
1728 **/
1729
1730 void
genie_vector_complex_norm(NODE_T * p)1731 genie_vector_complex_norm (NODE_T * p)
1732 {
1733 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1734 gsl_vector_complex *u;
1735 error_node = p;
1736 u = pop_vector_complex (p, A68_TRUE);
1737 PUSH_PRIMITIVE (p, gsl_blas_dznrm2 (u), A68_REAL);
1738 gsl_vector_complex_free (u);
1739 (void) gsl_set_error_handler (save_handler);
1740 }
1741
1742 /**
1743 @brief OP DYAD = ([] REAL, [] REAL) [, ] REAL
1744 @param p Node in syntax tree.
1745 **/
1746
1747 void
genie_vector_dyad(NODE_T * p)1748 genie_vector_dyad (NODE_T * p)
1749 {
1750 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1751 gsl_vector *u, *v;
1752 gsl_matrix *w;
1753 int len1, len2, j, k;
1754 error_node = p;
1755 v = pop_vector (p, A68_TRUE);
1756 u = pop_vector (p, A68_TRUE);
1757 len1 = (int) (SIZE (u));
1758 len2 = (int) (SIZE (v));
1759 w = gsl_matrix_alloc ((size_t) len1, (size_t) len2);
1760 for (j = 0; j < len1; j++) {
1761 double uj = gsl_vector_get (u, (size_t) j);
1762 for (k = 0; k < len2; k++) {
1763 double vk = gsl_vector_get (v, (size_t) k);
1764 gsl_matrix_set (w, (size_t) j, (size_t) k, uj * vk);
1765 }
1766 }
1767 push_matrix (p, w);
1768 gsl_vector_free (u);
1769 gsl_vector_free (v);
1770 gsl_matrix_free (w);
1771 (void) gsl_set_error_handler (save_handler);
1772 }
1773
1774 /**
1775 @brief OP DYAD = ([] COMPLEX, [] COMPLEX) [, ] COMPLEX
1776 @param p Node in syntax tree.
1777 **/
1778
1779 void
genie_vector_complex_dyad(NODE_T * p)1780 genie_vector_complex_dyad (NODE_T * p)
1781 {
1782 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1783 gsl_vector_complex *u, *v;
1784 gsl_matrix_complex *w;
1785 int len1, len2, j, k;
1786 error_node = p;
1787 v = pop_vector_complex (p, A68_TRUE);
1788 u = pop_vector_complex (p, A68_TRUE);
1789 len1 = (int) (SIZE (u));
1790 len2 = (int) (SIZE (v));
1791 w = gsl_matrix_complex_alloc ((size_t) len1, (size_t) len2);
1792 for (j = 0; j < len1; j++) {
1793 gsl_complex uj = gsl_vector_complex_get (u, (size_t) j);
1794 for (k = 0; k < len2; k++) {
1795 gsl_complex vk = gsl_vector_complex_get (u, (size_t) k);
1796 gsl_matrix_complex_set (w, (size_t) j, (size_t) k, gsl_complex_mul (uj, vk));
1797 }
1798 }
1799 push_matrix_complex (p, w);
1800 gsl_vector_complex_free (u);
1801 gsl_vector_complex_free (v);
1802 gsl_matrix_complex_free (w);
1803 (void) gsl_set_error_handler (save_handler);
1804 }
1805
1806 /**
1807 @brief OP * = ([, ] REAL, [] REAL) [] REAL
1808 @param p Node in syntax tree.
1809 **/
1810
1811 void
genie_matrix_times_vector(NODE_T * p)1812 genie_matrix_times_vector (NODE_T * p)
1813 {
1814 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1815 int len;
1816 int rc;
1817 gsl_vector *u, *v;
1818 gsl_matrix *w;
1819 error_node = p;
1820 u = pop_vector (p, A68_TRUE);
1821 w = pop_matrix (p, A68_TRUE);
1822 len = (int) (SIZE (u));
1823 v = gsl_vector_alloc ((size_t) len);
1824 gsl_vector_set_zero (v);
1825 rc = gsl_blas_dgemv (CblasNoTrans, 1.0, w, u, 0.0, v);
1826 torrix_test_error (rc);
1827 push_vector (p, v);
1828 gsl_vector_free (u);
1829 gsl_vector_free (v);
1830 gsl_matrix_free (w);
1831 (void) gsl_set_error_handler (save_handler);
1832 }
1833
1834 /**
1835 @brief OP * = ([] REAL, [, ] REAL) [] REAL
1836 @param p Node in syntax tree.
1837 **/
1838
1839 void
genie_vector_times_matrix(NODE_T * p)1840 genie_vector_times_matrix (NODE_T * p)
1841 {
1842 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1843 int len;
1844 int rc;
1845 gsl_vector *u, *v;
1846 gsl_matrix *w;
1847 error_node = p;
1848 w = pop_matrix (p, A68_TRUE);
1849 rc = gsl_matrix_transpose (w);
1850 torrix_test_error (rc);
1851 u = pop_vector (p, A68_TRUE);
1852 len = (int) (SIZE (u));
1853 v = gsl_vector_alloc ((size_t) len);
1854 gsl_vector_set_zero (v);
1855 rc = gsl_blas_dgemv (CblasNoTrans, 1.0, w, u, 0.0, v);
1856 torrix_test_error (rc);
1857 push_vector (p, v);
1858 gsl_vector_free (u);
1859 gsl_vector_free (v);
1860 gsl_matrix_free (w);
1861 (void) gsl_set_error_handler (save_handler);
1862 }
1863
1864 /**
1865 @brief OP * = ([, ] REAL, [, ] REAL) [, ] REAL
1866 @param p Node in syntax tree.
1867 **/
1868
1869 void
genie_matrix_times_matrix(NODE_T * p)1870 genie_matrix_times_matrix (NODE_T * p)
1871 {
1872 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1873 int len1, len2;
1874 int rc;
1875 gsl_matrix *u, *v, *w;
1876 error_node = p;
1877 v = pop_matrix (p, A68_TRUE);
1878 u = pop_matrix (p, A68_TRUE);
1879 len2 = (int) (SIZE2 (v));
1880 len1 = (int) (SIZE1 (u));
1881 w = gsl_matrix_alloc ((size_t) len1, (size_t) len2);
1882 gsl_matrix_set_zero (w);
1883 rc = gsl_blas_dgemm (CblasNoTrans, CblasNoTrans, 1.0, u, v, 0.0, w);
1884 torrix_test_error (rc);
1885 push_matrix (p, w);
1886 gsl_matrix_free (u);
1887 gsl_matrix_free (v);
1888 gsl_matrix_free (w);
1889 (void) gsl_set_error_handler (save_handler);
1890 }
1891
1892 /**
1893 @brief OP * = ([, ] COMPLEX, [] COMPLEX) [] COMPLEX
1894 @param p Node in syntax tree.
1895 **/
1896
1897 void
genie_matrix_complex_times_vector(NODE_T * p)1898 genie_matrix_complex_times_vector (NODE_T * p)
1899 {
1900 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1901 int len, rc;
1902 gsl_vector_complex *u, *v;
1903 gsl_matrix_complex *w;
1904 gsl_complex zero, one;
1905 error_node = p;
1906 GSL_SET_COMPLEX (&zero, 0.0, 0.0);
1907 GSL_SET_COMPLEX (&one, 1.0, 0.0);
1908 u = pop_vector_complex (p, A68_TRUE);
1909 w = pop_matrix_complex (p, A68_TRUE);
1910 len = (int) (SIZE (u));
1911 v = gsl_vector_complex_alloc ((size_t) len);
1912 gsl_vector_complex_set_zero (v);
1913 rc = gsl_blas_zgemv (CblasNoTrans, one, w, u, zero, v);
1914 torrix_test_error (rc);
1915 push_vector_complex (p, v);
1916 gsl_vector_complex_free (u);
1917 gsl_vector_complex_free (v);
1918 gsl_matrix_complex_free (w);
1919 (void) gsl_set_error_handler (save_handler);
1920 }
1921
1922 /**
1923 @brief OP * = ([] COMPLEX, [, ] COMPLEX) [] COMPLEX
1924 @param p Node in syntax tree.
1925 **/
1926
1927 void
genie_vector_complex_times_matrix(NODE_T * p)1928 genie_vector_complex_times_matrix (NODE_T * p)
1929 {
1930 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1931 int len, rc;
1932 gsl_vector_complex *u, *v;
1933 gsl_matrix_complex *w;
1934 gsl_complex zero, one;
1935 error_node = p;
1936 GSL_SET_COMPLEX (&zero, 0.0, 0.0);
1937 GSL_SET_COMPLEX (&one, 1.0, 0.0);
1938 w = pop_matrix_complex (p, A68_TRUE);
1939 rc = gsl_matrix_complex_transpose (w);
1940 torrix_test_error (rc);
1941 u = pop_vector_complex (p, A68_TRUE);
1942 len = (int) (SIZE (u));
1943 v = gsl_vector_complex_alloc ((size_t) len);
1944 gsl_vector_complex_set_zero (v);
1945 rc = gsl_blas_zgemv (CblasNoTrans, one, w, u, zero, v);
1946 torrix_test_error (rc);
1947 push_vector_complex (p, v);
1948 gsl_vector_complex_free (u);
1949 gsl_vector_complex_free (v);
1950 gsl_matrix_complex_free (w);
1951 (void) gsl_set_error_handler (save_handler);
1952 }
1953
1954 /**
1955 @brief OP * = ([, ] COMPLEX, [, ] COMPLEX) [, ] COMPLEX
1956 @param p Node in syntax tree.
1957 **/
1958
1959 void
genie_matrix_complex_times_matrix(NODE_T * p)1960 genie_matrix_complex_times_matrix (NODE_T * p)
1961 {
1962 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1963 int len1, len2, rc;
1964 gsl_matrix_complex *u, *v, *w;
1965 gsl_complex zero, one;
1966 error_node = p;
1967 GSL_SET_COMPLEX (&zero, 0.0, 0.0);
1968 GSL_SET_COMPLEX (&one, 1.0, 0.0);
1969 v = pop_matrix_complex (p, A68_TRUE);
1970 u = pop_matrix_complex (p, A68_TRUE);
1971 len1 = (int) (SIZE2 (v));
1972 len2 = (int) (SIZE1 (u));
1973 w = gsl_matrix_complex_alloc ((size_t) len1, (size_t) len2);
1974 gsl_matrix_complex_set_zero (w);
1975 rc = gsl_blas_zgemm (CblasNoTrans, CblasNoTrans, one, u, v, zero, w);
1976 torrix_test_error (rc);
1977 push_matrix_complex (p, w);
1978 gsl_matrix_complex_free (u);
1979 gsl_matrix_complex_free (v);
1980 gsl_matrix_complex_free (w);
1981 (void) gsl_set_error_handler (save_handler);
1982 }
1983
1984 /**
1985 @brief PROC lu decomp = ([, ] REAL, REF [] INT, REF INT) [, ] REAL
1986 @param p Node in syntax tree.
1987 **/
1988
1989 void
genie_matrix_lu(NODE_T * p)1990 genie_matrix_lu (NODE_T * p)
1991 {
1992 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1993 A68_REF ref_signum, ref_q;
1994 gsl_permutation *q;
1995 gsl_matrix *u;
1996 int rc;
1997 A68_INT signum;
1998 error_node = p;
1999 POP_REF (p, &ref_signum);
2000 CHECK_REF (p, ref_signum, MODE (REF_INT));
2001 POP_REF (p, &ref_q);
2002 CHECK_REF (p, ref_q, MODE (REF_ROW_INT));
2003 PUSH_REF (p, *DEREF (A68_ROW, &ref_q));
2004 q = pop_permutation (p, A68_FALSE);
2005 u = pop_matrix (p, A68_TRUE);
2006 rc = gsl_linalg_LU_decomp (u, q, &(VALUE (&signum)));
2007 torrix_test_error (rc);
2008 STATUS (&signum) = INIT_MASK;
2009 *DEREF (A68_INT, &ref_signum) = signum;
2010 push_permutation (p, q);
2011 POP_REF (p, DEREF (A68_ROW, &ref_q));
2012 push_matrix (p, u);
2013 gsl_matrix_free (u);
2014 gsl_permutation_free (q);
2015 (void) gsl_set_error_handler (save_handler);
2016 }
2017
2018 /**
2019 @brief PROC lu det = ([, ] REAL, INT) REAL
2020 @param p Node in syntax tree.
2021 **/
2022
2023 void
genie_matrix_lu_det(NODE_T * p)2024 genie_matrix_lu_det (NODE_T * p)
2025 {
2026 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
2027 gsl_matrix *lu;
2028 A68_INT signum;
2029 error_node = p;
2030 POP_OBJECT (p, &signum, A68_INT);
2031 lu = pop_matrix (p, A68_TRUE);
2032 PUSH_PRIMITIVE (p, gsl_linalg_LU_det (lu, VALUE (&signum)), A68_REAL);
2033 gsl_matrix_free (lu);
2034 (void) gsl_set_error_handler (save_handler);
2035 }
2036
2037 /**
2038 @brief PROC lu inv = ([, ] REAL, [] INT) [, ] REAL
2039 @param p Node in syntax tree.
2040 **/
2041
2042 void
genie_matrix_lu_inv(NODE_T * p)2043 genie_matrix_lu_inv (NODE_T * p)
2044 {
2045 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
2046 gsl_permutation *q;
2047 gsl_matrix *lu, *inv;
2048 int rc;
2049 error_node = p;
2050 q = pop_permutation (p, A68_TRUE);
2051 lu = pop_matrix (p, A68_TRUE);
2052 inv = gsl_matrix_alloc (SIZE1 (lu), SIZE2 (lu));
2053 rc = gsl_linalg_LU_invert (lu, q, inv);
2054 torrix_test_error (rc);
2055 push_matrix (p, inv);
2056 gsl_matrix_free (lu);
2057 gsl_matrix_free (inv);
2058 gsl_permutation_free (q);
2059 (void) gsl_set_error_handler (save_handler);
2060 }
2061
2062 /**
2063 @brief PROC lu solve ([, ] REAL, [, ] REAL, [] INT, [] REAL) [] REAL
2064 @param p Node in syntax tree.
2065 **/
2066
2067 void
genie_matrix_lu_solve(NODE_T * p)2068 genie_matrix_lu_solve (NODE_T * p)
2069 {
2070 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
2071 gsl_permutation *q;
2072 gsl_matrix *a, *lu;
2073 gsl_vector *b, *x, *r;
2074 int rc;
2075 error_node = p;
2076 b = pop_vector (p, A68_TRUE);
2077 q = pop_permutation (p, A68_TRUE);
2078 lu = pop_matrix (p, A68_TRUE);
2079 a = pop_matrix (p, A68_TRUE);
2080 x = gsl_vector_alloc (SIZE (b));
2081 r = gsl_vector_alloc (SIZE (b));
2082 rc = gsl_linalg_LU_solve (lu, q, b, x);
2083 torrix_test_error (rc);
2084 rc = gsl_linalg_LU_refine (a, lu, q, b, x, r);
2085 torrix_test_error (rc);
2086 push_vector (p, x);
2087 gsl_matrix_free (a);
2088 gsl_matrix_free (lu);
2089 gsl_vector_free (b);
2090 gsl_vector_free (r);
2091 gsl_vector_free (x);
2092 gsl_permutation_free (q);
2093 (void) gsl_set_error_handler (save_handler);
2094 }
2095
2096 /**
2097 @brief PROC complex lu decomp = ([, ] COMPLEX, REF [] INT, REF INT) [, ] COMPLEX
2098 @param p Node in syntax tree.
2099 **/
2100
2101 void
genie_matrix_complex_lu(NODE_T * p)2102 genie_matrix_complex_lu (NODE_T * p)
2103 {
2104 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
2105 A68_REF ref_signum, ref_q;
2106 gsl_permutation *q;
2107 gsl_matrix_complex *u;
2108 int rc;
2109 A68_INT signum;
2110 error_node = p;
2111 POP_REF (p, &ref_signum);
2112 CHECK_REF (p, ref_signum, MODE (REF_INT));
2113 POP_REF (p, &ref_q);
2114 CHECK_REF (p, ref_q, MODE (REF_ROW_INT));
2115 PUSH_REF (p, *DEREF (A68_ROW, &ref_q));
2116 q = pop_permutation (p, A68_FALSE);
2117 u = pop_matrix_complex (p, A68_TRUE);
2118 rc = gsl_linalg_complex_LU_decomp (u, q, &(VALUE (&signum)));
2119 torrix_test_error (rc);
2120 STATUS (&signum) = INIT_MASK;
2121 *DEREF (A68_INT, &ref_signum) = signum;
2122 push_permutation (p, q);
2123 POP_REF (p, DEREF (A68_ROW, &ref_q));
2124 push_matrix_complex (p, u);
2125 gsl_matrix_complex_free (u);
2126 gsl_permutation_free (q);
2127 (void) gsl_set_error_handler (save_handler);
2128 }
2129
2130 /**
2131 @brief PROC complex lu det = ([, ] COMPLEX, INT) COMPLEX
2132 @param p Node in syntax tree.
2133 **/
2134
2135 void
genie_matrix_complex_lu_det(NODE_T * p)2136 genie_matrix_complex_lu_det (NODE_T * p)
2137 {
2138 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
2139 gsl_matrix_complex *lu;
2140 A68_INT signum;
2141 gsl_complex det;
2142 error_node = p;
2143 POP_OBJECT (p, &signum, A68_INT);
2144 lu = pop_matrix_complex (p, A68_TRUE);
2145 det = gsl_linalg_complex_LU_det (lu, VALUE (&signum));
2146 PUSH_PRIMITIVE (p, GSL_REAL (det), A68_REAL);
2147 PUSH_PRIMITIVE (p, GSL_IMAG (det), A68_REAL);
2148 gsl_matrix_complex_free (lu);
2149 (void) gsl_set_error_handler (save_handler);
2150 }
2151
2152 /**
2153 @brief PROC complex lu inv = ([, ] COMPLEX, [] INT) [, ] COMPLEX
2154 @param p Node in syntax tree.
2155 **/
2156
2157 void
genie_matrix_complex_lu_inv(NODE_T * p)2158 genie_matrix_complex_lu_inv (NODE_T * p)
2159 {
2160 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
2161 gsl_permutation *q;
2162 gsl_matrix_complex *lu, *inv;
2163 int rc;
2164 error_node = p;
2165 q = pop_permutation (p, A68_TRUE);
2166 lu = pop_matrix_complex (p, A68_TRUE);
2167 inv = gsl_matrix_complex_alloc (SIZE1 (lu), SIZE2 (lu));
2168 rc = gsl_linalg_complex_LU_invert (lu, q, inv);
2169 torrix_test_error (rc);
2170 push_matrix_complex (p, inv);
2171 gsl_matrix_complex_free (lu);
2172 gsl_matrix_complex_free (inv);
2173 gsl_permutation_free (q);
2174 (void) gsl_set_error_handler (save_handler);
2175 }
2176
2177 /**
2178 @brief PROC complex lu solve ([, ] COMPLEX, [, ] COMPLEX, [] INT, [] COMPLEX) [] COMPLEX
2179 @param p Node in syntax tree.
2180 **/
2181
2182 void
genie_matrix_complex_lu_solve(NODE_T * p)2183 genie_matrix_complex_lu_solve (NODE_T * p)
2184 {
2185 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
2186 gsl_permutation *q;
2187 gsl_matrix_complex *a, *lu;
2188 gsl_vector_complex *b, *x, *r;
2189 int rc;
2190 error_node = p;
2191 b = pop_vector_complex (p, A68_TRUE);
2192 q = pop_permutation (p, A68_TRUE);
2193 lu = pop_matrix_complex (p, A68_TRUE);
2194 a = pop_matrix_complex (p, A68_TRUE);
2195 x = gsl_vector_complex_alloc (SIZE (b));
2196 r = gsl_vector_complex_alloc (SIZE (b));
2197 rc = gsl_linalg_complex_LU_solve (lu, q, b, x);
2198 torrix_test_error (rc);
2199 rc = gsl_linalg_complex_LU_refine (a, lu, q, b, x, r);
2200 torrix_test_error (rc);
2201 push_vector_complex (p, x);
2202 gsl_matrix_complex_free (a);
2203 gsl_matrix_complex_free (lu);
2204 gsl_vector_complex_free (b);
2205 gsl_vector_complex_free (r);
2206 gsl_vector_complex_free (x);
2207 gsl_permutation_free (q);
2208 (void) gsl_set_error_handler (save_handler);
2209 }
2210
2211 /**
2212 @brief PROC svd decomp = ([, ] REAL, REF [, ] REAL, REF [] REAL) [, ] REAL
2213 @param p Node in syntax tree.
2214 **/
2215
2216 void
genie_matrix_svd(NODE_T * p)2217 genie_matrix_svd (NODE_T * p)
2218 {
2219 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
2220 gsl_matrix *a, *v;
2221 gsl_vector *s, *w;
2222 A68_REF ref_s, ref_v;
2223 int rc;
2224 error_node = p;
2225 POP_REF (p, &ref_s);
2226 CHECK_REF (p, ref_s, MODE (REF_ROW_REAL));
2227 PUSH_REF (p, *DEREF (A68_ROW, &ref_s));
2228 s = pop_vector (p, A68_FALSE);
2229 POP_REF (p, &ref_v);
2230 CHECK_REF (p, ref_v, MODE (REF_ROWROW_REAL));
2231 PUSH_REF (p, *DEREF (A68_ROW, &ref_v));
2232 v = pop_matrix (p, A68_FALSE);
2233 a = pop_matrix (p, A68_TRUE);
2234 w = gsl_vector_alloc (SIZE2 (v));
2235 rc = gsl_linalg_SV_decomp (a, v, s, w);
2236 torrix_test_error (rc);
2237 push_vector (p, s);
2238 POP_REF (p, DEREF (A68_ROW, &ref_s));
2239 push_matrix (p, v);
2240 POP_REF (p, DEREF (A68_ROW, &ref_v));
2241 push_matrix (p, a);
2242 gsl_matrix_free (a);
2243 gsl_matrix_free (v);
2244 gsl_vector_free (s);
2245 gsl_vector_free (w);
2246 (void) gsl_set_error_handler (save_handler);
2247 }
2248
2249 /**
2250 @brief PROC svd solve = ([, ] REAL, [, ] REAL, [] REAL, [] REAL) [] REAL
2251 @param p Node in syntax tree.
2252 **/
2253
2254 void
genie_matrix_svd_solve(NODE_T * p)2255 genie_matrix_svd_solve (NODE_T * p)
2256 {
2257 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
2258 gsl_matrix *u, *v;
2259 gsl_vector *s, *b, *x;
2260 int rc;
2261 error_node = p;
2262 b = pop_vector (p, A68_TRUE);
2263 s = pop_vector (p, A68_TRUE);
2264 v = pop_matrix (p, A68_TRUE);
2265 u = pop_matrix (p, A68_TRUE);
2266 x = gsl_vector_alloc (SIZE (b));
2267 rc = gsl_linalg_SV_solve (u, v, s, b, x);
2268 push_vector (p, x);
2269 gsl_vector_free (x);
2270 gsl_vector_free (b);
2271 gsl_vector_free (s);
2272 gsl_matrix_free (v);
2273 gsl_matrix_free (u);
2274 (void) rc;
2275 (void) gsl_set_error_handler (save_handler);
2276 }
2277
2278 /**
2279 @brief PROC qr decomp = ([, ] REAL, [] REAL) [, ] REAL
2280 @param p Node in syntax tree.
2281 **/
2282
2283 void
genie_matrix_qr(NODE_T * p)2284 genie_matrix_qr (NODE_T * p)
2285 {
2286 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
2287 gsl_matrix *a;
2288 gsl_vector *t;
2289 A68_REF ref_t;
2290 int rc;
2291 error_node = p;
2292 POP_REF (p, &ref_t);
2293 CHECK_REF (p, ref_t, MODE (REF_ROW_REAL));
2294 PUSH_REF (p, *DEREF (A68_ROW, &ref_t));
2295 t = pop_vector (p, A68_FALSE);
2296 a = pop_matrix (p, A68_TRUE);
2297 rc = gsl_linalg_QR_decomp (a, t);
2298 torrix_test_error (rc);
2299 push_vector (p, t);
2300 POP_REF (p, DEREF (A68_ROW, &ref_t));
2301 push_matrix (p, a);
2302 gsl_matrix_free (a);
2303 gsl_vector_free (t);
2304 (void) gsl_set_error_handler (save_handler);
2305 }
2306
2307 /**
2308 @brief PROC qr solve = ([, ] REAL, [] REAL, [] REAL) [] REAL
2309 @param p Node in syntax tree.
2310 **/
2311
2312 void
genie_matrix_qr_solve(NODE_T * p)2313 genie_matrix_qr_solve (NODE_T * p)
2314 {
2315 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
2316 gsl_matrix *q;
2317 gsl_vector *t, *b, *x;
2318 int rc;
2319 error_node = p;
2320 b = pop_vector (p, A68_TRUE);
2321 t = pop_vector (p, A68_TRUE);
2322 q = pop_matrix (p, A68_TRUE);
2323 x = gsl_vector_alloc (SIZE (b));
2324 rc = gsl_linalg_QR_solve (q, t, b, x);
2325 push_vector (p, x);
2326 gsl_vector_free (x);
2327 gsl_vector_free (b);
2328 gsl_vector_free (t);
2329 gsl_matrix_free (q);
2330 (void) rc;
2331 (void) gsl_set_error_handler (save_handler);
2332 }
2333
2334 /**
2335 @brief PROC qr ls solve = ([, ] REAL, [] REAL, [] REAL) [] REAL
2336 @param p Node in syntax tree.
2337 **/
2338
2339 void
genie_matrix_qr_ls_solve(NODE_T * p)2340 genie_matrix_qr_ls_solve (NODE_T * p)
2341 {
2342 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
2343 gsl_matrix *q;
2344 gsl_vector *t, *b, *x, *r;
2345 int rc;
2346 error_node = p;
2347 b = pop_vector (p, A68_TRUE);
2348 t = pop_vector (p, A68_TRUE);
2349 q = pop_matrix (p, A68_TRUE);
2350 r = gsl_vector_alloc (SIZE (b));
2351 x = gsl_vector_alloc (SIZE (b));
2352 rc = gsl_linalg_QR_lssolve (q, t, b, x, r);
2353 push_vector (p, x);
2354 gsl_vector_free (x);
2355 gsl_vector_free (r);
2356 gsl_vector_free (b);
2357 gsl_vector_free (t);
2358 gsl_matrix_free (q);
2359 (void) rc;
2360 (void) gsl_set_error_handler (save_handler);
2361 }
2362
2363 /**
2364 @brief PROC cholesky decomp = ([, ] REAL) [, ] REAL
2365 @param p Node in syntax tree.
2366 **/
2367
2368 void
genie_matrix_ch(NODE_T * p)2369 genie_matrix_ch (NODE_T * p)
2370 {
2371 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
2372 gsl_matrix *a;
2373 int rc;
2374 error_node = p;
2375 a = pop_matrix (p, A68_TRUE);
2376 rc = gsl_linalg_cholesky_decomp (a);
2377 torrix_test_error (rc);
2378 push_matrix (p, a);
2379 gsl_matrix_free (a);
2380 (void) gsl_set_error_handler (save_handler);
2381 }
2382
2383 /**
2384 @brief PROC cholesky solve = ([, ] REAL, [] REAL) [] REAL
2385 @param p Node in syntax tree.
2386 **/
2387
2388 void
genie_matrix_ch_solve(NODE_T * p)2389 genie_matrix_ch_solve (NODE_T * p)
2390 {
2391 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
2392 gsl_matrix *c;
2393 gsl_vector *b, *x;
2394 int rc;
2395 error_node = p;
2396 b = pop_vector (p, A68_TRUE);
2397 c = pop_matrix (p, A68_TRUE);
2398 x = gsl_vector_alloc (SIZE (b));
2399 rc = gsl_linalg_cholesky_solve (c, b, x);
2400 push_vector (p, x);
2401 gsl_vector_free (x);
2402 gsl_vector_free (b);
2403 gsl_matrix_free (c);
2404 (void) rc;
2405 (void) gsl_set_error_handler (save_handler);
2406 }
2407
2408 /**
2409 @brief Map GSL error handler onto a68g error handler.
2410 @param reason Error text.
2411 @param file Gsl file where error occured.
2412 @param line Line in above file.
2413 @param gsl_errno Gsl error number.
2414 **/
2415
2416 void
fft_error_handler(const char * reason,const char * file,int line,int gsl_errno)2417 fft_error_handler (const char *reason, const char *file, int line, int gsl_errno)
2418 {
2419 if (line != 0) {
2420 ASSERT (snprintf (edit_line, SNPRINTF_SIZE, "%s in line %d of file %s", reason, line, file) >= 0);
2421 } else {
2422 ASSERT (snprintf (edit_line, SNPRINTF_SIZE, "%s", reason) >= 0);
2423 }
2424 diagnostic_node (A68_RUNTIME_ERROR, error_node, ERROR_FFT, edit_line, gsl_strerror (gsl_errno));
2425 exit_genie (error_node, A68_RUNTIME_ERROR);
2426 }
2427
2428 /**
2429 @brief Detect math errors.
2430 @param rc Return code from function.
2431 **/
2432
2433 static void
fft_test_error(int rc)2434 fft_test_error (int rc)
2435 {
2436 if (rc != 0) {
2437 fft_error_handler ("math error", "", 0, rc);
2438 }
2439 }
2440
2441 /**
2442 @brief Pop [] REAL on the stack as complex double [].
2443 @param p Node in syntax tree.
2444 @param len Length of array.
2445 @return Double [].
2446 **/
2447
2448 static double *
pop_array_real(NODE_T * p,int * len)2449 pop_array_real (NODE_T * p, int *len)
2450 {
2451 A68_REF desc;
2452 A68_ARRAY *arr;
2453 A68_TUPLE *tup;
2454 int inc, iindex, k;
2455 BYTE_T *base;
2456 double *v;
2457 error_node = p;
2458 /* Pop arguments */
2459 POP_REF (p, &desc);
2460 CHECK_REF (p, desc, MODE (ROW_REAL));
2461 GET_DESCRIPTOR (arr, tup, &desc);
2462 *len = ROW_SIZE (tup);
2463 if ((*len) <= 0) {
2464 return (NO_REAL);
2465 }
2466 v = malloc (2 * (size_t) (*len) * sizeof (double));
2467 fft_test_error (v == NO_REAL ? GSL_ENOMEM : GSL_SUCCESS);
2468 base = DEREF (BYTE_T, &ARRAY (arr));
2469 iindex = VECTOR_OFFSET (arr, tup);
2470 inc = SPAN (tup) * ELEM_SIZE (arr);
2471 for (k = 0; k < (*len); k++, iindex += inc) {
2472 A68_REAL *x = (A68_REAL *) (base + iindex);
2473 CHECK_INIT (p, INITIALISED (x), MODE (REAL));
2474 v[2 * k] = VALUE (x);
2475 v[2 * k + 1] = 0.0;
2476 }
2477 return (v);
2478 }
2479
2480 /**
2481 @brief Push double [] on the stack as [] REAL.
2482 @param p Node in syntax tree.
2483 @param v First element.
2484 @param len Length of array.
2485 **/
2486
2487 static void
push_array_real(NODE_T * p,double * v,int len)2488 push_array_real (NODE_T * p, double *v, int len)
2489 {
2490 A68_REF desc, row;
2491 A68_ARRAY arr;
2492 A68_TUPLE tup;
2493 int inc, iindex, k;
2494 BYTE_T *base;
2495 error_node = p;
2496 desc = heap_generator (p, MODE (ROW_REAL), SIZE_AL (A68_ARRAY) + SIZE_AL (A68_TUPLE));
2497 row = heap_generator (p, MODE (ROW_REAL), len * SIZE (MODE (REAL)));
2498 DIM (&arr) = 1;
2499 MOID (&arr) = MODE (REAL);
2500 ELEM_SIZE (&arr) = SIZE (MODE (REAL));
2501 SLICE_OFFSET (&arr) = FIELD_OFFSET (&arr) = 0;
2502 ARRAY (&arr) = row;
2503 LWB (&tup) = 1;
2504 UPB (&tup) = len;
2505 SHIFT (&tup) = LWB (&tup);
2506 SPAN (&tup) = 1;
2507 K (&tup) = 0;
2508 PUT_DESCRIPTOR (arr, tup, &desc);
2509 base = DEREF (BYTE_T, &ARRAY (&arr));
2510 iindex = VECTOR_OFFSET (&arr, &tup);
2511 inc = SPAN (&tup) * ELEM_SIZE (&arr);
2512 for (k = 0; k < len; k++, iindex += inc) {
2513 A68_REAL *x = (A68_REAL *) (base + iindex);
2514 STATUS (x) = INIT_MASK;
2515 VALUE (x) = v[2 * k];
2516 CHECK_REAL_REPRESENTATION (p, VALUE (x));
2517 }
2518 PUSH_REF (p, desc);
2519 }
2520
2521 /**
2522 @brief Pop [] COMPLEX on the stack as double [].
2523 @param p Node in syntax tree.
2524 @param len Length or array.
2525 @return Double [].
2526 **/
2527
2528 static double *
pop_array_complex(NODE_T * p,int * len)2529 pop_array_complex (NODE_T * p, int *len)
2530 {
2531 A68_REF desc;
2532 A68_ARRAY *arr;
2533 A68_TUPLE *tup;
2534 int inc, iindex, k;
2535 BYTE_T *base;
2536 double *v;
2537 error_node = p;
2538 /* Pop arguments */
2539 POP_REF (p, &desc);
2540 CHECK_REF (p, desc, MODE (ROW_COMPLEX));
2541 GET_DESCRIPTOR (arr, tup, &desc);
2542 *len = ROW_SIZE (tup);
2543 if ((*len) <= 0) {
2544 return (NO_REAL);
2545 }
2546 v = malloc (2 * (size_t) (*len) * sizeof (double));
2547 fft_test_error (v == NO_REAL ? GSL_ENOMEM : GSL_SUCCESS);
2548 base = DEREF (BYTE_T, &ARRAY (arr));
2549 iindex = VECTOR_OFFSET (arr, tup);
2550 inc = SPAN (tup) * ELEM_SIZE (arr);
2551 for (k = 0; k < (*len); k++, iindex += inc) {
2552 A68_REAL *re = (A68_REAL *) (base + iindex);
2553 A68_REAL *im = (A68_REAL *) (base + iindex + SIZE (MODE (REAL)));
2554 CHECK_INIT (p, INITIALISED (re), MODE (COMPLEX));
2555 CHECK_INIT (p, INITIALISED (im), MODE (COMPLEX));
2556 v[2 * k] = VALUE (re);
2557 v[2 * k + 1] = VALUE (im);
2558 }
2559 return (v);
2560 }
2561
2562 /**
2563 @brief Push double [] on the stack as [] COMPLEX.
2564 @param p Node in syntax tree.
2565 @param v First element.
2566 @param len Length of array.
2567 **/
2568
2569 static void
push_array_complex(NODE_T * p,double * v,int len)2570 push_array_complex (NODE_T * p, double *v, int len)
2571 {
2572 A68_REF desc, row;
2573 A68_ARRAY arr;
2574 A68_TUPLE tup;
2575 int inc, iindex, k;
2576 BYTE_T *base;
2577 error_node = p;
2578 desc = heap_generator (p, MODE (ROW_COMPLEX), SIZE_AL (A68_ARRAY) + SIZE_AL (A68_TUPLE));
2579 row = heap_generator (p, MODE (ROW_COMPLEX), len * 2 * SIZE (MODE (REAL)));
2580 DIM (&arr) = 1;
2581 MOID (&arr) = MODE (COMPLEX);
2582 ELEM_SIZE (&arr) = 2 * SIZE (MODE (REAL));
2583 SLICE_OFFSET (&arr) = FIELD_OFFSET (&arr) = 0;
2584 ARRAY (&arr) = row;
2585 LWB (&tup) = 1;
2586 UPB (&tup) = len;
2587 SHIFT (&tup) = LWB (&tup);
2588 SPAN (&tup) = 1;
2589 K (&tup) = 0;
2590 PUT_DESCRIPTOR (arr, tup, &desc);
2591 base = DEREF (BYTE_T, &ARRAY (&arr));
2592 iindex = VECTOR_OFFSET (&arr, &tup);
2593 inc = SPAN (&tup) * ELEM_SIZE (&arr);
2594 for (k = 0; k < len; k++, iindex += inc) {
2595 A68_REAL *re = (A68_REAL *) (base + iindex);
2596 A68_REAL *im = (A68_REAL *) (base + iindex + SIZE (MODE (REAL)));
2597 STATUS (re) = INIT_MASK;
2598 VALUE (re) = v[2 * k];
2599 STATUS (im) = INIT_MASK;
2600 VALUE (im) = v[2 * k + 1];
2601 CHECK_COMPLEX_REPRESENTATION (p, VALUE (re), VALUE (im));
2602 }
2603 PUSH_REF (p, desc);
2604 }
2605
2606 /**
2607 @brief Push prime factorisation on the stack as [] INT.
2608 @param p Node in syntax tree.
2609 **/
2610
2611 void
genie_prime_factors(NODE_T * p)2612 genie_prime_factors (NODE_T * p)
2613 {
2614 gsl_error_handler_t *save_handler = gsl_set_error_handler (fft_error_handler);
2615 A68_INT n;
2616 A68_REF desc, row;
2617 A68_ARRAY arr;
2618 A68_TUPLE tup;
2619 int len, inc, iindex, k;
2620 BYTE_T *base;
2621 gsl_fft_complex_wavetable *wt;
2622 error_node = p;
2623 POP_OBJECT (p, &n, A68_INT);
2624 CHECK_INIT (p, INITIALISED (&n), MODE (INT));
2625 wt = gsl_fft_complex_wavetable_alloc ((size_t) (VALUE (&n)));
2626 len = (int) (NF (wt));
2627 desc = heap_generator (p, MODE (ROW_INT), SIZE_AL (A68_ARRAY) + SIZE_AL (A68_TUPLE));
2628 row = heap_generator (p, MODE (ROW_INT), len * SIZE (MODE (INT)));
2629 DIM (&arr) = 1;
2630 MOID (&arr) = MODE (INT);
2631 ELEM_SIZE (&arr) = SIZE (MODE (INT));
2632 SLICE_OFFSET (&arr) = FIELD_OFFSET (&arr) = 0;
2633 ARRAY (&arr) = row;
2634 LWB (&tup) = 1;
2635 UPB (&tup) = len;
2636 SHIFT (&tup) = LWB (&tup);
2637 SPAN (&tup) = 1;
2638 K (&tup) = 0;
2639 PUT_DESCRIPTOR (arr, tup, &desc);
2640 base = DEREF (BYTE_T, &ARRAY (&arr));
2641 iindex = VECTOR_OFFSET (&arr, &tup);
2642 inc = SPAN (&tup) * ELEM_SIZE (&arr);
2643 for (k = 0; k < len; k++, iindex += inc) {
2644 A68_INT *x = (A68_INT *) (base + iindex);
2645 STATUS (x) = INIT_MASK;
2646 VALUE (x) = (int) ((FACTOR (wt))[k]);
2647 }
2648 gsl_fft_complex_wavetable_free (wt);
2649 PUSH_REF (p, desc);
2650 (void) gsl_set_error_handler (save_handler);
2651 }
2652
2653 /**
2654 @brief PROC ([] COMPLEX) [] COMPLEX fft complex forward
2655 @param p Node in syntax tree.
2656 **/
2657
2658 void
genie_fft_complex_forward(NODE_T * p)2659 genie_fft_complex_forward (NODE_T * p)
2660 {
2661 gsl_error_handler_t *save_handler = gsl_set_error_handler (fft_error_handler);
2662 int len, rc;
2663 double *data;
2664 gsl_fft_complex_wavetable *wt;
2665 gsl_fft_complex_workspace *ws;
2666 error_node = p;
2667 data = pop_array_complex (p, &len);
2668 fft_test_error (len == 0 ? GSL_EDOM : GSL_SUCCESS);
2669 wt = gsl_fft_complex_wavetable_alloc ((size_t) len);
2670 ws = gsl_fft_complex_workspace_alloc ((size_t) len);
2671 rc = gsl_fft_complex_forward (data, 1, (size_t) len, wt, ws);
2672 fft_test_error (rc);
2673 push_array_complex (p, data, len);
2674 gsl_fft_complex_wavetable_free (wt);
2675 gsl_fft_complex_workspace_free (ws);
2676 if (data != NO_REAL) {
2677 free (data);
2678 }
2679 (void) gsl_set_error_handler (save_handler);
2680 }
2681
2682 /**
2683 @brief PROC ([] COMPLEX) [] COMPLEX fft complex backward
2684 @param p Node in syntax tree.
2685 **/
2686
2687 void
genie_fft_complex_backward(NODE_T * p)2688 genie_fft_complex_backward (NODE_T * p)
2689 {
2690 gsl_error_handler_t *save_handler = gsl_set_error_handler (fft_error_handler);
2691 int len, rc;
2692 double *data;
2693 gsl_fft_complex_wavetable *wt;
2694 gsl_fft_complex_workspace *ws;
2695 error_node = p;
2696 data = pop_array_complex (p, &len);
2697 fft_test_error (len == 0 ? GSL_EDOM : GSL_SUCCESS);
2698 wt = gsl_fft_complex_wavetable_alloc ((size_t) len);
2699 ws = gsl_fft_complex_workspace_alloc ((size_t) len);
2700 rc = gsl_fft_complex_backward (data, 1, (size_t) len, wt, ws);
2701 fft_test_error (rc);
2702 push_array_complex (p, data, len);
2703 gsl_fft_complex_wavetable_free (wt);
2704 gsl_fft_complex_workspace_free (ws);
2705 if (data != NO_REAL) {
2706 free (data);
2707 }
2708 (void) gsl_set_error_handler (save_handler);
2709 }
2710
2711 /**
2712 @brief PROC ([] COMPLEX) [] COMPLEX fft complex inverse
2713 @param p Node in syntax tree.
2714 **/
2715
2716 void
genie_fft_complex_inverse(NODE_T * p)2717 genie_fft_complex_inverse (NODE_T * p)
2718 {
2719 gsl_error_handler_t *save_handler = gsl_set_error_handler (fft_error_handler);
2720 int len, rc;
2721 double *data;
2722 gsl_fft_complex_wavetable *wt;
2723 gsl_fft_complex_workspace *ws;
2724 error_node = p;
2725 data = pop_array_complex (p, &len);
2726 fft_test_error (len == 0 ? GSL_EDOM : GSL_SUCCESS);
2727 wt = gsl_fft_complex_wavetable_alloc ((size_t) len);
2728 ws = gsl_fft_complex_workspace_alloc ((size_t) len);
2729 rc = gsl_fft_complex_inverse (data, 1, (size_t) len, wt, ws);
2730 fft_test_error (rc);
2731 push_array_complex (p, data, len);
2732 gsl_fft_complex_wavetable_free (wt);
2733 gsl_fft_complex_workspace_free (ws);
2734 if (data != NO_REAL) {
2735 free (data);
2736 }
2737 (void) gsl_set_error_handler (save_handler);
2738 }
2739
2740 /**
2741 @brief PROC ([] REAL) [] COMPLEX fft forward
2742 @param p Node in syntax tree.
2743 **/
2744
2745 void
genie_fft_forward(NODE_T * p)2746 genie_fft_forward (NODE_T * p)
2747 {
2748 gsl_error_handler_t *save_handler = gsl_set_error_handler (fft_error_handler);
2749 int len, rc;
2750 double *data;
2751 gsl_fft_complex_wavetable *wt;
2752 gsl_fft_complex_workspace *ws;
2753 error_node = p;
2754 data = pop_array_real (p, &len);
2755 fft_test_error (len == 0 ? GSL_EDOM : GSL_SUCCESS);
2756 wt = gsl_fft_complex_wavetable_alloc ((size_t) len);
2757 ws = gsl_fft_complex_workspace_alloc ((size_t) len);
2758 rc = gsl_fft_complex_forward (data, 1, (size_t) len, wt, ws);
2759 fft_test_error (rc);
2760 push_array_complex (p, data, len);
2761 gsl_fft_complex_wavetable_free (wt);
2762 gsl_fft_complex_workspace_free (ws);
2763 if (data != NO_REAL) {
2764 free (data);
2765 }
2766 (void) gsl_set_error_handler (save_handler);
2767 }
2768
2769 /**
2770 @brief PROC ([] COMPLEX) [] REAL fft backward
2771 @param p Node in syntax tree.
2772 **/
2773
2774 void
genie_fft_backward(NODE_T * p)2775 genie_fft_backward (NODE_T * p)
2776 {
2777 gsl_error_handler_t *save_handler = gsl_set_error_handler (fft_error_handler);
2778 int len, rc;
2779 double *data;
2780 gsl_fft_complex_wavetable *wt;
2781 gsl_fft_complex_workspace *ws;
2782 error_node = p;
2783 data = pop_array_complex (p, &len);
2784 fft_test_error (len == 0 ? GSL_EDOM : GSL_SUCCESS);
2785 wt = gsl_fft_complex_wavetable_alloc ((size_t) len);
2786 ws = gsl_fft_complex_workspace_alloc ((size_t) len);
2787 rc = gsl_fft_complex_backward (data, 1, (size_t) len, wt, ws);
2788 fft_test_error (rc);
2789 push_array_real (p, data, len);
2790 gsl_fft_complex_wavetable_free (wt);
2791 gsl_fft_complex_workspace_free (ws);
2792 if (data != NO_REAL) {
2793 free (data);
2794 }
2795 (void) gsl_set_error_handler (save_handler);
2796 }
2797
2798 /**
2799 @brief PROC ([] COMPLEX) [] REAL fft inverse
2800 @param p Node in syntax tree.
2801 **/
2802
2803 void
genie_fft_inverse(NODE_T * p)2804 genie_fft_inverse (NODE_T * p)
2805 {
2806 gsl_error_handler_t *save_handler = gsl_set_error_handler (fft_error_handler);
2807 int len, rc;
2808 double *data;
2809 gsl_fft_complex_wavetable *wt;
2810 gsl_fft_complex_workspace *ws;
2811 error_node = p;
2812 data = pop_array_complex (p, &len);
2813 fft_test_error (len == 0 ? GSL_EDOM : GSL_SUCCESS);
2814 wt = gsl_fft_complex_wavetable_alloc ((size_t) len);
2815 ws = gsl_fft_complex_workspace_alloc ((size_t) len);
2816 rc = gsl_fft_complex_inverse (data, 1, (size_t) len, wt, ws);
2817 fft_test_error (rc);
2818 push_array_real (p, data, len);
2819 gsl_fft_complex_wavetable_free (wt);
2820 gsl_fft_complex_workspace_free (ws);
2821 if (data != NO_REAL) {
2822 free (data);
2823 }
2824 (void) gsl_set_error_handler (save_handler);
2825 }
2826
2827 /**
2828 @brief Map GSL error handler onto a68g error handler.
2829 @param reason Error text.
2830 @param file Gsl file where error occured.
2831 @param line Line in above file.
2832 @param gsl_errno Gsl error number.
2833 **/
2834
2835 void
laplace_error_handler(const char * reason,const char * file,int line,int gsl_errno)2836 laplace_error_handler (const char *reason, const char *file, int line, int gsl_errno)
2837 {
2838 if (line != 0) {
2839 ASSERT (snprintf (edit_line, SNPRINTF_SIZE, "%s in line %d of file %s", reason, line, file) >= 0);
2840 } else {
2841 ASSERT (snprintf (edit_line, SNPRINTF_SIZE, "%s", reason) >= 0);
2842 }
2843 diagnostic_node (A68_RUNTIME_ERROR, error_node, ERROR_LAPLACE, edit_line, gsl_strerror (gsl_errno));
2844 exit_genie (error_node, A68_RUNTIME_ERROR);
2845 }
2846
2847 /**
2848 @brief Detect math errors.
2849 @param rc Return code from function.
2850 **/
2851
2852 static void
laplace_test_error(int rc)2853 laplace_test_error (int rc)
2854 {
2855 if (rc != 0) {
2856 laplace_error_handler ("math error", "", 0, rc);
2857 }
2858 }
2859
2860 /**
2861 @brief PROC (PROC (REAL) REAL, REAL, REF REAL) REAL laplace
2862 @param p Node in syntax tree.
2863 **/
2864
2865 #define LAPLACE_DIVISIONS 1024
2866
2867 typedef struct A68_LAPLACE A68_LAPLACE;
2868
2869 struct A68_LAPLACE
2870 {
2871 NODE_T *p;
2872 A68_PROCEDURE f;
2873 double s;
2874 };
2875
2876 /**
2877 @brief Evaluate function for Laplace transform.
2878 @param t Argument.
2879 @param z LAPLACE value.
2880 **/
2881
2882 double
laplace_f(double t,void * z)2883 laplace_f (double t, void *z)
2884 {
2885 A68_LAPLACE *l = (A68_LAPLACE *) z;
2886 ADDR_T pop_sp = stack_pointer, pop_fp = frame_pointer;
2887 MOID_T *u = MODE (PROC_REAL_REAL);
2888 A68_REAL *ft = (A68_REAL *) STACK_TOP;
2889 PUSH_PRIMITIVE (P (l), t, A68_REAL);
2890 genie_call_procedure (P (l), MOID (&(F (l))), u, u, &(F (l)), pop_sp, pop_fp);
2891 stack_pointer = pop_sp;
2892 return (VALUE (ft) * a68g_exp (-(S (l)) * t));
2893 }
2894
2895 /**
2896 @brief Calculate Laplace transform.
2897 @param p Node in syntax tree.
2898 **/
2899
2900 void
genie_laplace(NODE_T * p)2901 genie_laplace (NODE_T * p)
2902 {
2903 A68_REF ref_error;
2904 A68_REAL s, *error;
2905 A68_PROCEDURE f;
2906 A68_LAPLACE l;
2907 gsl_function g;
2908 gsl_integration_workspace *w;
2909 double result, estimated_error;
2910 int rc;
2911 gsl_error_handler_t *save_handler = gsl_set_error_handler (laplace_error_handler);
2912 POP_REF (p, &ref_error);
2913 CHECK_REF (p, ref_error, MODE (REF_REAL));
2914 error = (A68_REAL *) ADDRESS (&ref_error);
2915 POP_OBJECT (p, &s, A68_REAL);
2916 POP_PROCEDURE (p, &f);
2917 P (&l) = p;
2918 F (&l) = f;
2919 S (&l) = VALUE (&s);
2920 FUNCTION (&g) = &laplace_f;
2921 GSL_PARAMS (&g) = &l;
2922 w = gsl_integration_workspace_alloc (LAPLACE_DIVISIONS);
2923 if (VALUE (error) >= 0.0) {
2924 rc = gsl_integration_qagiu (&g, 0.0, VALUE (error), 0.0, LAPLACE_DIVISIONS, w, &result, &estimated_error);
2925 } else {
2926 rc = gsl_integration_qagiu (&g, 0.0, 0.0, -VALUE (error), LAPLACE_DIVISIONS, w, &result, &estimated_error);
2927 }
2928 laplace_test_error (rc);
2929 VALUE (error) = estimated_error;
2930 PUSH_PRIMITIVE (p, result, A68_REAL);
2931 gsl_integration_workspace_free (w);
2932 (void) gsl_set_error_handler (save_handler);
2933 }
2934
2935 #endif /* defined HAVE_GNU_GSL */
2936