single-torrix-gsl.c
1 //! @file single-torrix-gsl.c
2 //! @author J. Marcel van der Veer
3
4 //! @section Copyright
5 //!
6 //! This file is part of Algol68G - an Algol 68 compiler-interpreter.
7 //! Copyright 2001-2025 J. Marcel van der Veer [algol68g@xs4all.nl].
8
9 //! @section License
10 //!
11 //! This program is free software; you can redistribute it and/or modify it
12 //! under the terms of the GNU General Public License as published by the
13 //! Free Software Foundation; either version 3 of the License, or
14 //! (at your option) any later version.
15 //!
16 //! This program is distributed in the hope that it will be useful, but
17 //! WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 //! or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 //! more details. You should have received a copy of the GNU General Public
20 //! License along with this program. If not, see [http://www.gnu.org/licenses/].
21
22 //! @section Synopsis
23 //!
24 //! REAL GSL vector and matrix routines.
25
26 #include "a68g.h"
27 #include "a68g-torrix.h"
28
29 #if defined (HAVE_GSL)
30
31 //! @brief Set permutation vector element - function fails in gsl.
32
33 void gsl_permutation_set (const gsl_permutation * p, const size_t i, const size_t j)
34 {
35 DATA (p)[i] = j;
36 }
37
38 //! @brief Map GSL error handler onto a68g error handler.
39
40 void torrix_error_handler (const char *reason, const char *file, int line, int gsl_errno)
41 {
42 if (line != 0) {
43 ASSERT (a68g_bufprt (A68G (edit_line), SNPRINTF_SIZE, "%s in line %d of file %s", reason, line, file) >= 0);
44 } else {
45 ASSERT (a68g_bufprt (A68G (edit_line), SNPRINTF_SIZE, "%s", reason) >= 0);
46 }
47 diagnostic (A68G_RUNTIME_ERROR, A68G (f_entry), ERROR_TORRIX, A68G (edit_line), gsl_strerror (gsl_errno));
48 exit_genie (A68G (f_entry), A68G_RUNTIME_ERROR);
49 }
50
51 //! @brief Pop [] INT on the stack as gsl_permutation.
52
53 gsl_permutation *pop_permutation (NODE_T * p, BOOL_T get)
54 {
55 A68G_REF desc; A68G_ARRAY *arr; A68G_TUPLE *tup;
56 POP_REF (p, &desc);
57 CHECK_REF (p, desc, M_ROW_INT);
58 GET_DESCRIPTOR (arr, tup, &desc);
59 size_t len = ROW_SIZE (tup);
60 gsl_permutation *v = gsl_permutation_calloc ((size_t) len);
61 if (get && len > 0) {
62 BYTE_T *base = DEREF (BYTE_T, &ARRAY (arr));
63 int idx = VECTOR_OFFSET (arr, tup);
64 int inc = SPAN (tup) * ELEM_SIZE (arr);
65 for (int k = 0; k < len; k++, idx += inc) {
66 A68G_INT *x = (A68G_INT *) (base + idx);
67 CHECK_INIT (p, INITIALISED (x), M_INT);
68 gsl_permutation_set (v, (size_t) k, (size_t) VALUE (x));
69 }
70 }
71 return v;
72 }
73
74 //! @brief Push gsl_permutation on the stack as [] INT.
75
76 void push_permutation (NODE_T * p, gsl_permutation * v)
77 {
78 size_t len = SIZE (v);
79 A68G_REF desc, row; A68G_ARRAY arr; A68G_TUPLE tup;
80 NEW_ROW_1D (desc, row, arr, tup, M_ROW_INT, M_INT, len);
81 BYTE_T *base = DEREF (BYTE_T, &ARRAY (&arr));
82 int idx = VECTOR_OFFSET (&arr, &tup);
83 int inc = SPAN (&tup) * ELEM_SIZE (&arr);
84 for (size_t k = 0; k < len; k++, idx += inc) {
85 A68G_INT *x = (A68G_INT *) (base + idx);
86 STATUS (x) = INIT_MASK;
87 VALUE (x) = (INT_T) gsl_permutation_get (v, k);
88 }
89 PUSH_REF (p, desc);
90 }
91
92 //! @brief Pop [] REAL on the stack as gsl_vector.
93
94 gsl_vector *pop_vector (NODE_T * p, BOOL_T get)
95 {
96 A68G_REF desc; A68G_ARRAY *arr; A68G_TUPLE *tup;
97 POP_REF (p, &desc);
98 CHECK_REF (p, desc, M_ROW_REAL);
99 GET_DESCRIPTOR (arr, tup, &desc);
100 size_t len = ROW_SIZE (tup);
101 gsl_vector *v = gsl_vector_calloc ((size_t) len);
102 if (get && len > 0) {
103 BYTE_T *base = DEREF (BYTE_T, &ARRAY (arr));
104 int idx = VECTOR_OFFSET (arr, tup);
105 int inc = SPAN (tup) * ELEM_SIZE (arr);
106 for (int k = 0; k < len; k++, idx += inc) {
107 A68G_REAL *x = (A68G_REAL *) (base + idx);
108 CHECK_INIT (p, INITIALISED (x), M_REAL);
109 gsl_vector_set (v, (size_t) k, VALUE (x));
110 }
111 }
112 return v;
113 }
114
115 //! @brief Push gsl_vector on the stack as [] REAL.
116
117 void push_vector (NODE_T * p, gsl_vector * v)
118 {
119 PUSH_REF (p, vector_to_row (p, v));
120 }
121
122 //! @brief Pop [, ] REAL on the stack as gsl_matrix.
123
124 gsl_matrix *pop_matrix (NODE_T * p, BOOL_T get)
125 {
126 A68G_REF desc; A68G_ARRAY *arr; A68G_TUPLE *tup1, *tup2;
127 POP_REF (p, &desc);
128 CHECK_REF (p, desc, M_ROW_ROW_REAL);
129 GET_DESCRIPTOR (arr, tup1, &desc);
130 tup2 = &(tup1[1]);
131 size_t len1 = ROW_SIZE (tup1), len2 = ROW_SIZE (tup2);
132 gsl_matrix *a = gsl_matrix_calloc ((size_t) len1, (size_t) len2);
133 if (get && (len1 * len2 > 0)) {
134 BYTE_T *base = DEREF (BYTE_T, &ARRAY (arr));
135 int idx1 = MATRIX_OFFSET (arr, tup1, tup2);
136 int inc1 = SPAN (tup1) * ELEM_SIZE (arr), inc2 = SPAN (tup2) * ELEM_SIZE (arr);
137 for (int k1 = 0; k1 < len1; k1++, idx1 += inc1) {
138 for (int k2 = 0, idx2 = idx1; k2 < len2; k2++, idx2 += inc2) {
139 A68G_REAL *x = (A68G_REAL *) (base + idx2);
140 CHECK_INIT (p, INITIALISED (x), M_REAL);
141 gsl_matrix_set (a, (size_t) k1, (size_t) k2, VALUE (x));
142 }
143 }
144 }
145 return a;
146 }
147
148 //! @brief Push gsl_matrix on the stack as [, ] REAL.
149
150 void push_matrix (NODE_T * p, gsl_matrix * a)
151 {
152 PUSH_REF (p, matrix_to_row (p, a));
153 }
154
155 //! @brief Pop [] COMPLEX on the stack as gsl_vector_complex.
156
157 gsl_vector_complex *pop_vector_complex (NODE_T * p, BOOL_T get)
158 {
159 A68G_REF desc; A68G_ARRAY *arr; A68G_TUPLE *tup;
160 POP_REF (p, &desc);
161 CHECK_REF (p, desc, M_ROW_COMPLEX);
162 GET_DESCRIPTOR (arr, tup, &desc);
163 size_t len = ROW_SIZE (tup);
164 gsl_vector_complex *v = gsl_vector_complex_calloc ((size_t) len);
165 if (get && len > 0) {
166 BYTE_T *base = DEREF (BYTE_T, &ARRAY (arr));
167 int idx = VECTOR_OFFSET (arr, tup);
168 int inc = SPAN (tup) * ELEM_SIZE (arr);
169 for (int k = 0; k < len; k++, idx += inc) {
170 A68G_REAL *re = (A68G_REAL *) (base + idx);
171 A68G_REAL *im = (A68G_REAL *) (base + idx + SIZE (M_REAL));
172 gsl_complex z;
173 CHECK_INIT (p, INITIALISED (re), M_COMPLEX);
174 CHECK_INIT (p, INITIALISED (im), M_COMPLEX);
175 GSL_SET_COMPLEX (&z, VALUE (re), VALUE (im));
176 gsl_vector_complex_set (v, (size_t) k, z);
177 }
178 }
179 return v;
180 }
181
182 //! @brief Push gsl_vector_complex on the stack as [] COMPLEX.
183
184 void push_vector_complex (NODE_T * p, gsl_vector_complex * v)
185 {
186 size_t len = SIZE (v);
187 A68G_REF desc, row; A68G_ARRAY arr; A68G_TUPLE tup;
188 NEW_ROW_1D (desc, row, arr, tup, M_ROW_COMPLEX, M_COMPLEX, len);
189 BYTE_T *base = DEREF (BYTE_T, &ARRAY (&arr));
190 int idx = VECTOR_OFFSET (&arr, &tup);
191 int inc = SPAN (&tup) * ELEM_SIZE (&arr);
192 for (int k = 0; k < len; k++, idx += inc) {
193 A68G_REAL *re = (A68G_REAL *) (base + idx);
194 A68G_REAL *im = (A68G_REAL *) (base + idx + SIZE (M_REAL));
195 gsl_complex z = gsl_vector_complex_get (v, (size_t) k);
196 STATUS (re) = INIT_MASK;
197 VALUE (re) = GSL_REAL (z);
198 STATUS (im) = INIT_MASK;
199 VALUE (im) = GSL_IMAG (z);
200 CHECK_COMPLEX (p, VALUE (re), VALUE (im));
201 }
202 PUSH_REF (p, desc);
203 }
204
205 //! @brief Pop [, ] COMPLEX on the stack as gsl_matrix_complex.
206
207 gsl_matrix_complex *pop_matrix_complex (NODE_T * p, BOOL_T get)
208 {
209 A68G_REF desc; A68G_ARRAY *arr; A68G_TUPLE *tup1, *tup2;
210 POP_REF (p, &desc);
211 CHECK_REF (p, desc, M_ROW_ROW_COMPLEX);
212 GET_DESCRIPTOR (arr, tup1, &desc);
213 tup2 = &(tup1[1]);
214 size_t len1 = ROW_SIZE (tup1), len2 = ROW_SIZE (tup2);
215 gsl_matrix_complex *a = gsl_matrix_complex_calloc ((size_t) len1, (size_t) len2);
216 if (get && (len1 * len2 > 0)) {
217 BYTE_T *base = DEREF (BYTE_T, &ARRAY (arr));
218 int idx1 = MATRIX_OFFSET (arr, tup1, tup2);
219 int inc1 = SPAN (tup1) * ELEM_SIZE (arr), inc2 = SPAN (tup2) * ELEM_SIZE (arr);
220 for (int k1 = 0; k1 < len1; k1++, idx1 += inc1) {
221 for (int k2 = 0, idx2 = idx1; k2 < len2; k2++, idx2 += inc2) {
222 A68G_REAL *re = (A68G_REAL *) (base + idx2);
223 A68G_REAL *im = (A68G_REAL *) (base + idx2 + SIZE (M_REAL));
224 CHECK_INIT (p, INITIALISED (re), M_COMPLEX);
225 CHECK_INIT (p, INITIALISED (im), M_COMPLEX);
226 gsl_complex z;
227 GSL_SET_COMPLEX (&z, VALUE (re), VALUE (im));
228 gsl_matrix_complex_set (a, (size_t) k1, (size_t) k2, z);
229 }
230 }
231 }
232 return a;
233 }
234
235 //! @brief Push gsl_matrix_complex on the stack as [, ] COMPLEX.
236
237 void push_matrix_complex (NODE_T * p, gsl_matrix_complex * a)
238 {
239 size_t len1 = SIZE1 (a), len2 = SIZE2 (a);
240 A68G_REF desc, row; A68G_ARRAY arr; A68G_TUPLE tup1, tup2;
241 desc = heap_generator (p, M_ROW_ROW_COMPLEX, DESCRIPTOR_SIZE (2));
242 row = heap_generator_3 (p, M_ROW_ROW_COMPLEX, len1, len2, 2 * SIZE (M_REAL));
243 DIM (&arr) = 2;
244 MOID (&arr) = M_COMPLEX;
245 ELEM_SIZE (&arr) = 2 * SIZE (M_REAL);
246 SLICE_OFFSET (&arr) = FIELD_OFFSET (&arr) = 0;
247 ARRAY (&arr) = row;
248 LWB (&tup1) = 1; UPB (&tup1) = len1; SPAN (&tup1) = 1;
249 SHIFT (&tup1) = LWB (&tup1); K (&tup1) = 0;
250 LWB (&tup2) = 1; UPB (&tup2) = len2; SPAN (&tup2) = ROW_SIZE (&tup1);
251 SHIFT (&tup2) = LWB (&tup2) * SPAN (&tup2); K (&tup2) = 0;
252 PUT_DESCRIPTOR2 (arr, tup1, tup2, &desc);
253 BYTE_T *base = DEREF (BYTE_T, &ARRAY (&arr));
254 int idx1 = MATRIX_OFFSET (&arr, &tup1, &tup2);
255 int inc1 = SPAN (&tup1) * ELEM_SIZE (&arr), inc2 = SPAN (&tup2) * ELEM_SIZE (&arr);
256 for (int k1 = 0; k1 < len1; k1++, idx1 += inc1) {
257 for (int k2 = 0, idx2 = idx1; k2 < len2; k2++, idx2 += inc2) {
258 A68G_REAL *re = (A68G_REAL *) (base + idx2);
259 A68G_REAL *im = (A68G_REAL *) (base + idx2 + SIZE (M_REAL));
260 gsl_complex z = gsl_matrix_complex_get (a, (size_t) k1, (size_t) k2);
261 STATUS (re) = INIT_MASK;
262 VALUE (re) = GSL_REAL (z);
263 STATUS (im) = INIT_MASK;
264 VALUE (im) = GSL_IMAG (z);
265 CHECK_COMPLEX (p, VALUE (re), VALUE (im));
266 }
267 }
268 PUSH_REF (p, desc);
269 }
270
271 //! @brief Generically perform operation and assign result (+:=, -:=, ...) .
272
273 void op_ab_torrix (NODE_T * p, MOID_T * m, MOID_T * n, GPROC * op)
274 {
275 ADDR_T parm_size = SIZE (m) + SIZE (n);
276 A68G_REF dst, src, *save = (A68G_REF *) STACK_OFFSET (-parm_size);
277 dst = *save;
278 CHECK_REF (p, dst, m);
279 *save = *DEREF (A68G_ROW, &dst);
280 STATUS (&src) = (STATUS_MASK_T) (INIT_MASK | IN_STACK_MASK);
281 OFFSET (&src) = A68G_SP - parm_size;
282 (*op) (p);
283 if (IS_REF (m)) {
284 genie_store (p, SUB (m), &dst, &src);
285 } else {
286 ABEND (A68G_TRUE, ERROR_INTERNAL_CONSISTENCY, NO_TEXT);
287 }
288 *save = dst;
289 }
290
291 //! @brief PROC vector echo = ([] REAL) [] REAL
292
293 void genie_vector_echo (NODE_T * p)
294 {
295 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
296 gsl_vector *u = pop_vector (p, A68G_TRUE);
297 push_vector (p, u);
298 gsl_vector_free (u);
299 (void) gsl_set_error_handler (save_handler);
300 }
301
302 //! @brief PROC matrix echo = ([, ] REAL) [, ] REAL
303
304 void genie_matrix_echo (NODE_T * p)
305 {
306 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
307 gsl_matrix *a = pop_matrix (p, A68G_TRUE);
308 push_matrix (p, a);
309 gsl_matrix_free (a);
310 (void) gsl_set_error_handler (save_handler);
311 }
312
313 //! @brief PROC complex vector echo = ([] COMPLEX) [] COMPLEX
314
315 void genie_vector_complex_echo (NODE_T * p)
316 {
317 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
318 gsl_vector_complex *u = pop_vector_complex (p, A68G_TRUE);
319 push_vector_complex (p, u);
320 gsl_vector_complex_free (u);
321 (void) gsl_set_error_handler (save_handler);
322 }
323
324 //! @brief PROC complex matrix echo = ([, ] COMPLEX) [, ] COMPLEX
325
326 void genie_matrix_complex_echo (NODE_T * p)
327 {
328 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
329 gsl_matrix_complex *a = pop_matrix_complex (p, A68G_TRUE);
330 push_matrix_complex (p, a);
331 gsl_matrix_complex_free (a);
332 (void) gsl_set_error_handler (save_handler);
333 }
334
335 //! @brief OP ROW = ([] REAL) [, ] REAL
336
337 void genie_vector_row (NODE_T * p)
338 {
339 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
340 gsl_vector *u = pop_vector (p, A68G_TRUE);
341 gsl_matrix *v = gsl_matrix_calloc (1, SIZE (u));
342 ASSERT_GSL (gsl_matrix_set_row (v, 0, u));
343 push_matrix (p, v);
344 gsl_vector_free (u);
345 gsl_matrix_free (v);
346 (void) gsl_set_error_handler (save_handler);
347 }
348
349 //! @brief OP COL = ([] REAL) [, ] REAL
350
351 void genie_vector_col (NODE_T * p)
352 {
353 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
354 gsl_vector *u = pop_vector (p, A68G_TRUE);
355 gsl_matrix *v = gsl_matrix_calloc (SIZE (u), 1);
356 ASSERT_GSL (gsl_matrix_set_col (v, 0, u));
357 push_matrix (p, v);
358 gsl_vector_free (u);
359 gsl_matrix_free (v);
360 (void) gsl_set_error_handler (save_handler);
361 }
362
363 //! @brief OP - = ([] REAL) [] REAL
364
365 void genie_vector_minus (NODE_T * p)
366 {
367 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
368 gsl_vector *u = pop_vector (p, A68G_TRUE);
369 ASSERT_GSL (gsl_vector_scale (u, -1));
370 push_vector (p, u);
371 gsl_vector_free (u);
372 (void) gsl_set_error_handler (save_handler);
373 }
374
375 //! @brief OP - = ([, ] REAL) [, ] REAL
376
377 void genie_matrix_minus (NODE_T * p)
378 {
379 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
380 gsl_matrix * a = pop_matrix (p, A68G_TRUE);
381 ASSERT_GSL (gsl_matrix_scale (a, -1));
382 push_matrix (p, a);
383 gsl_matrix_free (a);
384 (void) gsl_set_error_handler (save_handler);
385 }
386
387 //! @brief OP T = ([, ] REAL) [, ] REAL
388
389 void genie_matrix_transpose (NODE_T * p)
390 {
391 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
392 gsl_matrix *a = pop_matrix (p, A68G_TRUE);
393 gsl_matrix *t = gsl_matrix_calloc (SIZE2(a), SIZE1(a));
394 ASSERT_GSL (gsl_matrix_transpose_memcpy (t, a));
395 push_matrix (p, t);
396 gsl_matrix_free (a);
397 gsl_matrix_free (t);
398 (void) gsl_set_error_handler (save_handler);
399 }
400
401 //! @brief OP T = ([, ] COMPLEX) [, ] COMPLEX
402
403 void genie_matrix_complex_transpose (NODE_T * p)
404 {
405 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
406 gsl_matrix_complex *a = pop_matrix_complex (p, A68G_TRUE);
407 gsl_matrix_complex *t = gsl_matrix_complex_calloc (SIZE2(a), SIZE1(a));
408 ASSERT_GSL ( gsl_matrix_complex_transpose_memcpy (t, a));
409 push_matrix_complex (p, a);
410 gsl_matrix_complex_free (a);
411 gsl_matrix_complex_free (t);
412 (void) gsl_set_error_handler (save_handler);
413 }
414
415 //! @brief OP INV = ([, ] REAL) [, ] REAL
416
417 void genie_matrix_inv (NODE_T * p)
418 {
419 // Avoid direct use of the inverse whenever possible; linear solver functions
420 // can obtain the same result more efficiently and reliably.
421 // Consult any introductory textbook on numerical linear algebra for details.
422 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
423 gsl_matrix *u = pop_matrix (p, A68G_TRUE);
424 unt M = SIZE1 (u), N =SIZE2 (u);
425 MATH_RTE (p, M != N, M_ROW_ROW_REAL, "matrix is not square");
426 gsl_matrix *inv = NO_REAL_MATRIX;
427 compute_pseudo_inverse (p, &inv, u, 0); // Pseudo inverse equals inverse for a square matrix.
428 push_matrix (p, inv);
429 gsl_matrix_free (inv);
430 gsl_matrix_free (u);
431 (void) gsl_set_error_handler (save_handler);
432 }
433
434 //! @brief OP INV = ([, ] COMPLEX) [, ] COMPLEX
435
436 void genie_matrix_complex_inv (NODE_T * p)
437 {
438 // Avoid direct use of the inverse whenever possible; linear solver functions
439 // can obtain the same result more efficiently and reliably.
440 // Consult any introductory textbook on numerical linear algebra for details.
441 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
442 gsl_matrix_complex *u = pop_matrix_complex (p, A68G_TRUE);
443 unt M = SIZE1 (u), N =SIZE2 (u);
444 MATH_RTE (p, M != N, M_ROW_ROW_COMPLEX, "matrix is not square");
445 gsl_permutation *q = gsl_permutation_calloc (SIZE1 (u));
446 int sign;
447 ASSERT_GSL (gsl_linalg_complex_LU_decomp (u, q, &sign));
448 gsl_matrix_complex *inv = gsl_matrix_complex_calloc (SIZE1 (u), SIZE2 (u));
449 ASSERT_GSL (gsl_linalg_complex_LU_invert (u, q, inv));
450 push_matrix_complex (p, inv);
451 gsl_matrix_complex_free (inv);
452 gsl_matrix_complex_free (u);
453 gsl_permutation_free (q);
454 (void) gsl_set_error_handler (save_handler);
455 }
456
457 //! @brief OP DET = ([, ] REAL) REAL
458
459 void genie_matrix_det (NODE_T * p)
460 {
461 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
462 gsl_matrix *u = pop_matrix (p, A68G_TRUE);
463 gsl_permutation *q = gsl_permutation_calloc (SIZE1 (u));
464 int sign, rc = gsl_linalg_LU_decomp (u, q, &sign);
465 if (rc != GSL_SUCCESS) {
466 PUSH_VALUE (p, 0, A68G_REAL);
467 } else {
468 REAL_T det = gsl_linalg_LU_det (u, sign);
469 if (a68g_isnan_real (det)) {
470 PUSH_VALUE (p, 0, A68G_REAL);
471 } else {
472 PUSH_VALUE (p, det, A68G_REAL);
473 }
474 }
475 gsl_matrix_free (u);
476 gsl_permutation_free (q);
477 (void) gsl_set_error_handler (save_handler);
478 }
479
480 //! @brief OP DET = ([, ] COMPLEX) COMPLEX
481
482 void genie_matrix_complex_det (NODE_T * p)
483 {
484 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
485 gsl_matrix_complex *u = pop_matrix_complex (p, A68G_TRUE);
486 gsl_permutation *q = gsl_permutation_calloc (SIZE1 (u));
487 int sign, rc = gsl_linalg_complex_LU_decomp (u, q, &sign);
488 if (rc != GSL_SUCCESS) {
489 PUSH_COMPLEX_VALUE (p, 0, 0);
490 } else {
491 gsl_complex det = gsl_linalg_complex_LU_det (u, sign);
492 REAL_T re_det = GSL_REAL (det), im_det = GSL_IMAG (det);
493 if (a68g_isnan_real (re_det) || a68g_isnan_real (im_det)) {
494 PUSH_COMPLEX_VALUE (p, 0, 0);
495 } else {
496 PUSH_COMPLEX_VALUE (p, re_det, im_det);
497 }
498 }
499 gsl_matrix_complex_free (u);
500 gsl_permutation_free (q);
501 (void) gsl_set_error_handler (save_handler);
502 }
503
504 //! @brief OP TRACE = ([, ] REAL) REAL
505
506 void genie_matrix_trace (NODE_T * p)
507 {
508 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
509 gsl_matrix *a = pop_matrix (p, A68G_TRUE);
510 size_t len1 = SIZE1 (a), len2 = SIZE2 (a);
511 if (len1 != len2) {
512 torrix_error_handler ("cannot calculate trace", __FILE__, __LINE__, GSL_ENOTSQR);
513 }
514 REAL_T sum = 0.0;
515 for (int k = 0; k < len1; k++) {
516 sum += gsl_matrix_get (a, (size_t) k, (size_t) k);
517 }
518 PUSH_VALUE (p, sum, A68G_REAL);
519 gsl_matrix_free (a);
520 (void) gsl_set_error_handler (save_handler);
521 }
522
523 //! @brief OP TRACE = ([, ] COMPLEX) COMPLEX
524
525 void genie_matrix_complex_trace (NODE_T * p)
526 {
527 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
528 gsl_matrix_complex *a = pop_matrix_complex (p, A68G_TRUE);
529 size_t len1 = SIZE1 (a), len2 = SIZE2 (a);
530 if (len1 != len2) {
531 torrix_error_handler ("cannot calculate trace", __FILE__, __LINE__, GSL_ENOTSQR);
532 }
533 gsl_complex sum;
534 GSL_SET_COMPLEX (&sum, 0.0, 0.0);
535 for (int k = 0; k < len1; k++) {
536 sum = gsl_complex_add (sum, gsl_matrix_complex_get (a, (size_t) k, (size_t) k));
537 }
538 PUSH_COMPLEX_VALUE (p, GSL_REAL (sum), GSL_IMAG (sum));
539 gsl_matrix_complex_free (a);
540 (void) gsl_set_error_handler (save_handler);
541 }
542
543 //! @brief OP - = ([] COMPLEX) [] COMPLEX
544
545 void genie_vector_complex_minus (NODE_T * p)
546 {
547 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
548 gsl_vector_complex *u = pop_vector_complex (p, A68G_TRUE);
549 gsl_blas_zdscal (-1, u);
550 push_vector_complex (p, u);
551 gsl_vector_complex_free (u);
552 (void) gsl_set_error_handler (save_handler);
553 }
554
555 //! @brief OP - = ([, ] COMPLEX) [, ] COMPLEX
556
557 void genie_matrix_complex_minus (NODE_T * p)
558 {
559 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
560 gsl_complex one;
561 GSL_SET_COMPLEX (&one, -1.0, 0.0);
562 gsl_matrix_complex *a = pop_matrix_complex (p, A68G_TRUE);
563 ASSERT_GSL (gsl_matrix_complex_scale (a, one));
564 push_matrix_complex (p, a);
565 gsl_matrix_complex_free (a);
566 (void) gsl_set_error_handler (save_handler);
567 }
568
569 //! @brief OP + = ([] REAL, [] REAL) [] REAL
570
571 void genie_vector_add (NODE_T * p)
572 {
573 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
574 gsl_vector *v = pop_vector (p, A68G_TRUE);
575 gsl_vector *u = pop_vector (p, A68G_TRUE);
576 ASSERT_GSL (gsl_vector_add (u, v));
577 push_vector (p, u);
578 gsl_vector_free (u);
579 gsl_vector_free (v);
580 (void) gsl_set_error_handler (save_handler);
581 }
582
583 //! @brief OP - = ([] REAL, [] REAL) [] REAL
584
585 void genie_vector_sub (NODE_T * p)
586 {
587 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
588 gsl_vector *v = pop_vector (p, A68G_TRUE);
589 gsl_vector *u = pop_vector (p, A68G_TRUE);
590 ASSERT_GSL (gsl_vector_sub (u, v));
591 push_vector (p, u);
592 gsl_vector_free (u);
593 gsl_vector_free (v);
594 (void) gsl_set_error_handler (save_handler);
595 }
596
597 //! @brief OP = = ([] REAL, [] REAL) BOOL
598
599 void genie_vector_eq (NODE_T * p)
600 {
601 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
602 gsl_vector *v = pop_vector (p, A68G_TRUE);
603 gsl_vector *u = pop_vector (p, A68G_TRUE);
604 ASSERT_GSL (gsl_vector_sub (u, v));
605 PUSH_VALUE (p, (BOOL_T) (gsl_vector_isnull (u) ? A68G_TRUE : A68G_FALSE), A68G_BOOL);
606 gsl_vector_free (u);
607 gsl_vector_free (v);
608 (void) gsl_set_error_handler (save_handler);
609 }
610
611 //! @brief OP /= = ([] REAL, [] REAL) BOOL
612
613 void genie_vector_ne (NODE_T * p)
614 {
615 genie_vector_eq (p);
616 genie_not_bool (p);
617 }
618
619 //! @brief OP +:= = (REF [] REAL, [] REAL) REF [] REAL
620
621 void genie_vector_plusab (NODE_T * p)
622 {
623 op_ab_torrix (p, M_REF_ROW_REAL, M_ROW_REAL, genie_vector_add);
624 }
625
626 //! @brief OP -:= = (REF [] REAL, [] REAL) REF [] REAL
627
628 void genie_vector_minusab (NODE_T * p)
629 {
630 op_ab_torrix (p, M_REF_ROW_REAL, M_ROW_REAL, genie_vector_sub);
631 }
632
633 //! @brief OP + = ([, ] REAL, [, ] REAL) [, ] REAL
634
635 void genie_matrix_add (NODE_T * p)
636 {
637 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
638 gsl_matrix *v = pop_matrix (p, A68G_TRUE);
639 gsl_matrix *u = pop_matrix (p, A68G_TRUE);
640 ASSERT_GSL (gsl_matrix_add (u, v));
641 push_matrix (p, u);
642 gsl_matrix_free (u);
643 gsl_matrix_free (v);
644 (void) gsl_set_error_handler (save_handler);
645 }
646
647 //! @brief OP - = ([, ] REAL, [, ] REAL) [, ] REAL
648
649 void genie_matrix_sub (NODE_T * p)
650 {
651 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
652 gsl_matrix *v = pop_matrix (p, A68G_TRUE);
653 gsl_matrix *u = pop_matrix (p, A68G_TRUE);
654 ASSERT_GSL (gsl_matrix_sub (u, v));
655 push_matrix (p, u);
656 gsl_matrix_free (u);
657 gsl_matrix_free (v);
658 (void) gsl_set_error_handler (save_handler);
659 }
660
661 //! @brief OP = = ([, ] REAL, [, ] REAL) [, ] BOOL
662
663 void genie_matrix_eq (NODE_T * p)
664 {
665 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
666 gsl_matrix *v = pop_matrix (p, A68G_TRUE);
667 gsl_matrix *u = pop_matrix (p, A68G_TRUE);
668 ASSERT_GSL (gsl_matrix_sub (u, v));
669 PUSH_VALUE (p, (BOOL_T) (gsl_matrix_isnull (u) ? A68G_TRUE : A68G_FALSE), A68G_BOOL);
670 gsl_matrix_free (u);
671 gsl_matrix_free (v);
672 (void) gsl_set_error_handler (save_handler);
673 }
674
675 //! @brief OP /= = ([, ] REAL, [, ] REAL) [, ] BOOL
676
677 void genie_matrix_ne (NODE_T * p)
678 {
679 genie_matrix_eq (p);
680 genie_not_bool (p);
681 }
682
683 //! @brief OP +:= = (REF [, ] REAL, [, ] REAL) [, ] REAL
684
685 void genie_matrix_plusab (NODE_T * p)
686 {
687 op_ab_torrix (p, M_REF_ROW_ROW_REAL, M_ROW_ROW_REAL, genie_matrix_add);
688 }
689
690 //! @brief OP -:= = (REF [, ] REAL, [, ] REAL) [, ] REAL
691
692 void genie_matrix_minusab (NODE_T * p)
693 {
694 op_ab_torrix (p, M_REF_ROW_ROW_REAL, M_ROW_ROW_REAL, genie_matrix_sub);
695 }
696
697 //! @brief OP + = ([] COMPLEX, [] COMPLEX) [] COMPLEX
698
699 void genie_vector_complex_add (NODE_T * p)
700 {
701 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
702 gsl_complex one;
703 GSL_SET_COMPLEX (&one, 1.0, 0.0);
704 gsl_vector_complex *v = pop_vector_complex (p, A68G_TRUE);
705 gsl_vector_complex *u = pop_vector_complex (p, A68G_TRUE);
706 ASSERT_GSL (gsl_blas_zaxpy (one, u, v));
707 push_vector_complex (p, v);
708 gsl_vector_complex_free (u);
709 gsl_vector_complex_free (v);
710 (void) gsl_set_error_handler (save_handler);
711 }
712
713 //! @brief OP - = ([] COMPLEX, [] COMPLEX) [] COMPLEX
714
715 void genie_vector_complex_sub (NODE_T * p)
716 {
717 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
718 gsl_complex one;
719 GSL_SET_COMPLEX (&one, -1.0, 0.0);
720 gsl_vector_complex *v = pop_vector_complex (p, A68G_TRUE);
721 gsl_vector_complex *u = pop_vector_complex (p, A68G_TRUE);
722 ASSERT_GSL (gsl_blas_zaxpy (one, v, u));
723 push_vector_complex (p, u);
724 gsl_vector_complex_free (u);
725 gsl_vector_complex_free (v);
726 (void) gsl_set_error_handler (save_handler);
727 }
728
729 //! @brief OP = = ([] COMPLEX, [] COMPLEX) BOOL
730
731 void genie_vector_complex_eq (NODE_T * p)
732 {
733 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
734 gsl_complex one;
735 GSL_SET_COMPLEX (&one, -1.0, 0.0);
736 gsl_vector_complex *v = pop_vector_complex (p, A68G_TRUE);
737 gsl_vector_complex *u = pop_vector_complex (p, A68G_TRUE);
738 ASSERT_GSL (gsl_blas_zaxpy (one, v, u));
739 PUSH_VALUE (p, (BOOL_T) (gsl_vector_complex_isnull (u) ? A68G_TRUE : A68G_FALSE), A68G_BOOL);
740 gsl_vector_complex_free (u);
741 gsl_vector_complex_free (v);
742 (void) gsl_set_error_handler (save_handler);
743 }
744
745 //! @brief OP /= = ([] COMPLEX, [] COMPLEX) BOOL
746
747 void genie_vector_complex_ne (NODE_T * p)
748 {
749 genie_vector_complex_eq (p);
750 genie_not_bool (p);
751 }
752
753 //! @brief OP +:= = (REF [] COMPLEX, [] COMPLEX) [] COMPLEX
754
755 void genie_vector_complex_plusab (NODE_T * p)
756 {
757 op_ab_torrix (p, M_REF_ROW_COMPLEX, M_ROW_COMPLEX, genie_vector_complex_add);
758 }
759
760 //! @brief OP -:= = (REF [] COMPLEX, [] COMPLEX) [] COMPLEX
761
762 void genie_vector_complex_minusab (NODE_T * p)
763 {
764 op_ab_torrix (p, M_REF_ROW_COMPLEX, M_ROW_COMPLEX, genie_vector_complex_sub);
765 }
766
767 //! @brief OP + = ([, ] COMPLEX, [, ] COMPLEX) [, ] COMPLEX
768
769 void genie_matrix_complex_add (NODE_T * p)
770 {
771 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
772 gsl_matrix_complex *v = pop_matrix_complex (p, A68G_TRUE);
773 gsl_matrix_complex *u = pop_matrix_complex (p, A68G_TRUE);
774 ASSERT_GSL (gsl_matrix_complex_add (u, v));
775 push_matrix_complex (p, u);
776 gsl_matrix_complex_free (u);
777 gsl_matrix_complex_free (v);
778 (void) gsl_set_error_handler (save_handler);
779 }
780
781 //! @brief OP - = ([, ] COMPLEX, [, ] COMPLEX) [, ] COMPLEX
782
783 void genie_matrix_complex_sub (NODE_T * p)
784 {
785 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
786 gsl_matrix_complex *v = pop_matrix_complex (p, A68G_TRUE);
787 gsl_matrix_complex *u = pop_matrix_complex (p, A68G_TRUE);
788 ASSERT_GSL (gsl_matrix_complex_sub (u, v));
789 push_matrix_complex (p, u);
790 gsl_matrix_complex_free (u);
791 gsl_matrix_complex_free (v);
792 (void) gsl_set_error_handler (save_handler);
793 }
794
795 //! @brief OP = = ([, ] COMPLEX, [, ] COMPLEX) BOOL
796
797 void genie_matrix_complex_eq (NODE_T * p)
798 {
799 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
800 gsl_matrix_complex *v = pop_matrix_complex (p, A68G_TRUE);
801 gsl_matrix_complex *u = pop_matrix_complex (p, A68G_TRUE);
802 ASSERT_GSL (gsl_matrix_complex_sub (u, v));
803 PUSH_VALUE (p, (BOOL_T) (gsl_matrix_complex_isnull (u) ? A68G_TRUE : A68G_FALSE), A68G_BOOL);
804 gsl_matrix_complex_free (u);
805 gsl_matrix_complex_free (v);
806 (void) gsl_set_error_handler (save_handler);
807 }
808
809 //! @brief OP /= = ([, ] COMPLEX, [, ] COMPLEX) BOOL
810
811 void genie_matrix_complex_ne (NODE_T * p)
812 {
813 genie_matrix_complex_eq (p);
814 genie_not_bool (p);
815 }
816
817 //! @brief OP +:= = (REF [, ] COMPLEX, [, ] COMPLEX) [, ] COMPLEX
818
819 void genie_matrix_complex_plusab (NODE_T * p)
820 {
821 op_ab_torrix (p, M_REF_ROW_ROW_COMPLEX, M_ROW_ROW_COMPLEX, genie_matrix_complex_add);
822 }
823
824 //! @brief OP -:= = (REF [, ] COMPLEX, [, ] COMPLEX) [, ] COMPLEX
825
826 void genie_matrix_complex_minusab (NODE_T * p)
827 {
828 op_ab_torrix (p, M_REF_ROW_ROW_COMPLEX, M_ROW_ROW_COMPLEX, genie_matrix_complex_sub);
829 }
830
831 //! @brief OP * = ([] REAL, REAL) [] REAL
832
833 void genie_vector_scale_real (NODE_T * p)
834 {
835 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
836 A68G_REAL v;
837 POP_OBJECT (p, &v, A68G_REAL);
838 gsl_vector *u = pop_vector (p, A68G_TRUE);
839 ASSERT_GSL (gsl_vector_scale (u, VALUE (&v)));
840 push_vector (p, u);
841 gsl_vector_free (u);
842 (void) gsl_set_error_handler (save_handler);
843 }
844
845 //! @brief OP * = (REAL, [] REAL) [] REAL
846
847 void genie_real_scale_vector (NODE_T * p)
848 {
849 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
850 gsl_vector *u = pop_vector (p, A68G_TRUE);
851 A68G_REAL v;
852 POP_OBJECT (p, &v, A68G_REAL);
853 ASSERT_GSL (gsl_vector_scale (u, VALUE (&v)));
854 push_vector (p, u);
855 gsl_vector_free (u);
856 (void) gsl_set_error_handler (save_handler);
857 }
858
859 //! @brief OP * = ([, ] REAL, REAL) [, ] REAL
860
861 void genie_matrix_scale_real (NODE_T * p)
862 {
863 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
864 A68G_REAL v;
865 POP_OBJECT (p, &v, A68G_REAL);
866 gsl_matrix *u = pop_matrix (p, A68G_TRUE);
867 ASSERT_GSL (gsl_matrix_scale (u, VALUE (&v)));
868 push_matrix (p, u);
869 gsl_matrix_free (u);
870 (void) gsl_set_error_handler (save_handler);
871 }
872
873 //! @brief OP * = (REAL, [, ] REAL) [, ] REAL
874
875 void genie_real_scale_matrix (NODE_T * p)
876 {
877 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
878 gsl_matrix *u = pop_matrix (p, A68G_TRUE);
879 A68G_REAL v;
880 POP_OBJECT (p, &v, A68G_REAL);
881 ASSERT_GSL (gsl_matrix_scale (u, VALUE (&v)));
882 push_matrix (p, u);
883 gsl_matrix_free (u);
884 (void) gsl_set_error_handler (save_handler);
885 }
886
887 //! @brief OP * = ([] COMPLEX, COMPLEX) [] COMPLEX
888
889 void genie_vector_complex_scale_complex (NODE_T * p)
890 {
891 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
892 A68G_REAL re, im; gsl_complex v;
893 POP_OBJECT (p, &im, A68G_REAL);
894 POP_OBJECT (p, &re, A68G_REAL);
895 GSL_SET_COMPLEX (&v, VALUE (&re), VALUE (&im));
896 gsl_vector_complex *u = pop_vector_complex (p, A68G_TRUE);
897 gsl_blas_zscal (v, u);
898 push_vector_complex (p, u);
899 gsl_vector_complex_free (u);
900 (void) gsl_set_error_handler (save_handler);
901 }
902
903 //! @brief OP * = (COMPLEX, [] COMPLEX) [] COMPLEX
904
905 void genie_complex_scale_vector_complex (NODE_T * p)
906 {
907 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
908 gsl_vector_complex *u = pop_vector_complex (p, A68G_TRUE);
909 A68G_REAL re, im; gsl_complex v;
910 POP_OBJECT (p, &im, A68G_REAL);
911 POP_OBJECT (p, &re, A68G_REAL);
912 GSL_SET_COMPLEX (&v, VALUE (&re), VALUE (&im));
913 gsl_blas_zscal (v, u);
914 push_vector_complex (p, u);
915 gsl_vector_complex_free (u);
916 (void) gsl_set_error_handler (save_handler);
917 }
918
919 //! @brief OP * = ([, ] COMPLEX, COMPLEX) [, ] COMPLEX
920
921 void genie_matrix_complex_scale_complex (NODE_T * p)
922 {
923 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
924 A68G_REAL re, im; gsl_complex v;
925 POP_OBJECT (p, &im, A68G_REAL);
926 POP_OBJECT (p, &re, A68G_REAL);
927 GSL_SET_COMPLEX (&v, VALUE (&re), VALUE (&im));
928 gsl_matrix_complex *u = pop_matrix_complex (p, A68G_TRUE);
929 ASSERT_GSL (gsl_matrix_complex_scale (u, v));
930 push_matrix_complex (p, u);
931 gsl_matrix_complex_free (u);
932 (void) gsl_set_error_handler (save_handler);
933 }
934
935 //! @brief OP * = (COMPLEX, [, ] COMPLEX) [, ] COMPLEX
936
937 void genie_complex_scale_matrix_complex (NODE_T * p)
938 {
939 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
940 gsl_matrix_complex *u = pop_matrix_complex (p, A68G_TRUE);
941 A68G_REAL re, im; gsl_complex v;
942 POP_OBJECT (p, &im, A68G_REAL);
943 POP_OBJECT (p, &re, A68G_REAL);
944 GSL_SET_COMPLEX (&v, VALUE (&re), VALUE (&im));
945 ASSERT_GSL (gsl_matrix_complex_scale (u, v));
946 push_matrix_complex (p, u);
947 gsl_matrix_complex_free (u);
948 (void) gsl_set_error_handler (save_handler);
949 }
950
951 //! @brief OP *:= (REF [] REAL, REAL) REF [] REAL
952
953 void genie_vector_scale_real_ab (NODE_T * p)
954 {
955 op_ab_torrix (p, M_REF_ROW_REAL, M_REAL, genie_vector_scale_real);
956 }
957
958 //! @brief OP *:= (REF [, ] REAL, REAL) REF [, ] REAL
959
960 void genie_matrix_scale_real_ab (NODE_T * p)
961 {
962 op_ab_torrix (p, M_REF_ROW_ROW_REAL, M_REAL, genie_matrix_scale_real);
963 }
964
965 //! @brief OP *:= (REF [] COMPLEX, COMPLEX) REF [] COMPLEX
966
967 void genie_vector_complex_scale_complex_ab (NODE_T * p)
968 {
969 op_ab_torrix (p, M_REF_ROW_COMPLEX, M_COMPLEX, genie_vector_complex_scale_complex);
970 }
971
972 //! @brief OP *:= (REF [, ] COMPLEX, COMPLEX) REF [, ] COMPLEX
973
974 void genie_matrix_complex_scale_complex_ab (NODE_T * p)
975 {
976 op_ab_torrix (p, M_REF_ROW_ROW_COMPLEX, M_COMPLEX, genie_matrix_complex_scale_complex);
977 }
978
979 //! @brief OP / = ([] REAL, REAL) [] REAL
980
981 void genie_vector_div_real (NODE_T * p)
982 {
983 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
984 A68G_REAL v;
985 POP_OBJECT (p, &v, A68G_REAL);
986 if (VALUE (&v) == 0.0) {
987 diagnostic (A68G_RUNTIME_ERROR, p, ERROR_DIVISION_BY_ZERO, M_ROW_REAL);
988 exit_genie (p, A68G_RUNTIME_ERROR);
989 }
990 gsl_vector *u = pop_vector (p, A68G_TRUE);
991 ASSERT_GSL (gsl_vector_scale (u, 1.0 / VALUE (&v)));
992 push_vector (p, u);
993 gsl_vector_free (u);
994 (void) gsl_set_error_handler (save_handler);
995 }
996
997 //! @brief OP / = ([, ] REAL, REAL) [, ] REAL
998
999 void genie_matrix_div_real (NODE_T * p)
1000 {
1001 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1002 A68G_REAL v;
1003 POP_OBJECT (p, &v, A68G_REAL);
1004 if (VALUE (&v) == 0.0) {
1005 diagnostic (A68G_RUNTIME_ERROR, p, ERROR_DIVISION_BY_ZERO, M_ROW_ROW_REAL);
1006 exit_genie (p, A68G_RUNTIME_ERROR);
1007 }
1008 gsl_matrix *u = pop_matrix (p, A68G_TRUE);
1009 ASSERT_GSL (gsl_matrix_scale (u, 1.0 / VALUE (&v)));
1010 push_matrix (p, u);
1011 gsl_matrix_free (u);
1012 (void) gsl_set_error_handler (save_handler);
1013 }
1014
1015 //! @brief OP / = ([] COMPLEX, COMPLEX) [] COMPLEX
1016
1017 void genie_vector_complex_div_complex (NODE_T * p)
1018 {
1019 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1020 A68G_REAL re, im; gsl_complex v;
1021 POP_OBJECT (p, &im, A68G_REAL);
1022 POP_OBJECT (p, &re, A68G_REAL);
1023 if (VALUE (&re) == 0.0 && VALUE (&im) == 0.0) {
1024 diagnostic (A68G_RUNTIME_ERROR, p, ERROR_DIVISION_BY_ZERO, M_ROW_COMPLEX);
1025 exit_genie (p, A68G_RUNTIME_ERROR);
1026 }
1027 GSL_SET_COMPLEX (&v, VALUE (&re), VALUE (&im));
1028 v = gsl_complex_inverse (v);
1029 gsl_vector_complex *u = pop_vector_complex (p, A68G_TRUE);
1030 gsl_blas_zscal (v, u);
1031 push_vector_complex (p, u);
1032 gsl_vector_complex_free (u);
1033 (void) gsl_set_error_handler (save_handler);
1034 }
1035
1036 //! @brief OP / = ([, ] COMPLEX, COMPLEX) [, ] COMPLEX
1037
1038 void genie_matrix_complex_div_complex (NODE_T * p)
1039 {
1040 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1041 A68G_REAL re, im; gsl_complex v;
1042 POP_OBJECT (p, &im, A68G_REAL);
1043 POP_OBJECT (p, &re, A68G_REAL);
1044 if (VALUE (&re) == 0.0 && VALUE (&im) == 0.0) {
1045 diagnostic (A68G_RUNTIME_ERROR, p, ERROR_DIVISION_BY_ZERO, M_ROW_ROW_COMPLEX);
1046 exit_genie (p, A68G_RUNTIME_ERROR);
1047 }
1048 GSL_SET_COMPLEX (&v, VALUE (&re), VALUE (&im));
1049 v = gsl_complex_inverse (v);
1050 gsl_matrix_complex *u = pop_matrix_complex (p, A68G_TRUE);
1051 ASSERT_GSL (gsl_matrix_complex_scale (u, v));
1052 push_matrix_complex (p, u);
1053 gsl_matrix_complex_free (u);
1054 (void) gsl_set_error_handler (save_handler);
1055 }
1056
1057 //! @brief OP /:= (REF [] REAL, REAL) REF [] REAL
1058
1059 void genie_vector_div_real_ab (NODE_T * p)
1060 {
1061 op_ab_torrix (p, M_REF_ROW_REAL, M_REAL, genie_vector_div_real);
1062 }
1063
1064 //! @brief OP /:= (REF [, ] REAL, REAL) REF [, ] REAL
1065
1066 void genie_matrix_div_real_ab (NODE_T * p)
1067 {
1068 op_ab_torrix (p, M_REF_ROW_ROW_REAL, M_REAL, genie_matrix_div_real);
1069 }
1070
1071 //! @brief OP /:= (REF [] COMPLEX, COMPLEX) REF [] COMPLEX
1072
1073 void genie_vector_complex_div_complex_ab (NODE_T * p)
1074 {
1075 op_ab_torrix (p, M_REF_ROW_COMPLEX, M_COMPLEX, genie_vector_complex_div_complex);
1076 }
1077
1078 //! @brief OP /:= (REF [, ] COMPLEX, COMPLEX) REF [, ] COMPLEX
1079
1080 void genie_matrix_complex_div_complex_ab (NODE_T * p)
1081 {
1082 op_ab_torrix (p, M_REF_ROW_ROW_COMPLEX, M_COMPLEX, genie_matrix_complex_div_complex);
1083 }
1084
1085 //! @brief OP * = ([] REAL, [] REAL) REAL
1086
1087 void genie_vector_dot (NODE_T * p)
1088 {
1089 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1090 gsl_vector *v = pop_vector (p, A68G_TRUE);
1091 gsl_vector *u = pop_vector (p, A68G_TRUE);
1092 REAL_T w;
1093 ASSERT_GSL (gsl_blas_ddot (u, v, &w));
1094 PUSH_VALUE (p, w, A68G_REAL);
1095 gsl_vector_free (u);
1096 gsl_vector_free (v);
1097 (void) gsl_set_error_handler (save_handler);
1098 }
1099
1100 //! @brief OP * = ([] COMPLEX, [] COMPLEX) COMPLEX
1101
1102 void genie_vector_complex_dot (NODE_T * p)
1103 {
1104 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1105 gsl_vector_complex *v = pop_vector_complex (p, A68G_TRUE);
1106 gsl_vector_complex *u = pop_vector_complex (p, A68G_TRUE);
1107 gsl_complex w;
1108 ASSERT_GSL (gsl_blas_zdotc (u, v, &w));
1109 PUSH_COMPLEX_VALUE (p, GSL_REAL (w), GSL_IMAG (w));
1110 gsl_vector_complex_free (u);
1111 gsl_vector_complex_free (v);
1112 (void) gsl_set_error_handler (save_handler);
1113 }
1114
1115 //! @brief OP NORM = ([] REAL) REAL
1116
1117 void genie_vector_norm (NODE_T * p)
1118 {
1119 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1120 gsl_vector *u = pop_vector (p, A68G_TRUE);
1121 PUSH_VALUE (p, gsl_blas_dnrm2 (u), A68G_REAL);
1122 gsl_vector_free (u);
1123 (void) gsl_set_error_handler (save_handler);
1124 }
1125
1126 //! @brief OP NORM = ([] COMPLEX) COMPLEX
1127
1128 void genie_vector_complex_norm (NODE_T * p)
1129 {
1130 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1131 gsl_vector_complex *u = pop_vector_complex (p, A68G_TRUE);
1132 PUSH_VALUE (p, gsl_blas_dznrm2 (u), A68G_REAL);
1133 gsl_vector_complex_free (u);
1134 (void) gsl_set_error_handler (save_handler);
1135 }
1136
1137 //! @brief OP DYAD = ([] REAL, [] REAL) [, ] REAL
1138
1139 void genie_vector_dyad (NODE_T * p)
1140 {
1141 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1142 gsl_vector *v = pop_vector (p, A68G_TRUE);
1143 gsl_vector *u = pop_vector (p, A68G_TRUE);
1144 size_t len1 = SIZE (u), len2 = SIZE (v);
1145 gsl_matrix *w = gsl_matrix_calloc ((size_t) len1, (size_t) len2);
1146 for (int j = 0; j < len1; j++) {
1147 REAL_T uj = gsl_vector_get (u, (size_t) j);
1148 for (int k = 0; k < len2; k++) {
1149 REAL_T vk = gsl_vector_get (v, (size_t) k);
1150 gsl_matrix_set (w, (size_t) j, (size_t) k, uj * vk);
1151 }
1152 }
1153 push_matrix (p, w);
1154 gsl_vector_free (u);
1155 gsl_vector_free (v);
1156 gsl_matrix_free (w);
1157 (void) gsl_set_error_handler (save_handler);
1158 }
1159
1160 //! @brief OP DYAD = ([] COMPLEX, [] COMPLEX) [, ] COMPLEX
1161
1162 void genie_vector_complex_dyad (NODE_T * p)
1163 {
1164 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1165 gsl_vector_complex *v = pop_vector_complex (p, A68G_TRUE);
1166 gsl_vector_complex *u = pop_vector_complex (p, A68G_TRUE);
1167 size_t len1 = SIZE (u), len2 = SIZE (v);
1168 gsl_matrix_complex *w = gsl_matrix_complex_calloc ((size_t) len1, (size_t) len2);
1169 for (int j = 0; j < len1; j++) {
1170 gsl_complex uj = gsl_vector_complex_get (u, (size_t) j);
1171 for (int k = 0; k < len2; k++) {
1172 gsl_complex vk = gsl_vector_complex_get (u, (size_t) k);
1173 gsl_matrix_complex_set (w, (size_t) j, (size_t) k, gsl_complex_mul (uj, vk));
1174 }
1175 }
1176 push_matrix_complex (p, w);
1177 gsl_vector_complex_free (u);
1178 gsl_vector_complex_free (v);
1179 gsl_matrix_complex_free (w);
1180 (void) gsl_set_error_handler (save_handler);
1181 }
1182
1183 //! @brief OP * = ([, ] REAL, [] REAL) [] REAL
1184
1185 void genie_matrix_times_vector (NODE_T * p)
1186 {
1187 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1188 gsl_vector *u = pop_vector (p, A68G_TRUE);
1189 gsl_matrix *w = pop_matrix (p, A68G_TRUE);
1190 size_t len = SIZE (u);
1191 gsl_vector *v = gsl_vector_calloc ((size_t) len);
1192 gsl_vector_set_zero (v);
1193 ASSERT_GSL (gsl_blas_dgemv (CblasNoTrans, 1.0, w, u, 0.0, v));
1194 push_vector (p, v);
1195 gsl_vector_free (u);
1196 gsl_vector_free (v);
1197 gsl_matrix_free (w);
1198 (void) gsl_set_error_handler (save_handler);
1199 }
1200
1201 //! @brief OP * = ([] REAL, [, ] REAL) [] REAL
1202
1203 void genie_vector_times_matrix (NODE_T * p)
1204 {
1205 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1206 gsl_matrix *w = pop_matrix (p, A68G_TRUE);
1207 ASSERT_GSL (gsl_matrix_transpose (w));
1208 gsl_vector *u = pop_vector (p, A68G_TRUE);
1209 size_t len = SIZE (u);
1210 gsl_vector *v = gsl_vector_calloc ((size_t) len);
1211 gsl_vector_set_zero (v);
1212 ASSERT_GSL (gsl_blas_dgemv (CblasNoTrans, 1.0, w, u, 0.0, v));
1213 push_vector (p, v);
1214 gsl_vector_free (u);
1215 gsl_vector_free (v);
1216 gsl_matrix_free (w);
1217 (void) gsl_set_error_handler (save_handler);
1218 }
1219
1220 //! @brief OP * = ([, ] REAL, [, ] REAL) [, ] REAL
1221
1222 void genie_matrix_times_matrix (NODE_T * p)
1223 {
1224 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1225 gsl_matrix *v = pop_matrix (p, A68G_TRUE);
1226 gsl_matrix *u = pop_matrix (p, A68G_TRUE);
1227 size_t len2 = SIZE2 (v), len1 = SIZE1 (u);
1228 gsl_matrix *w = gsl_matrix_calloc ((size_t) len1, (size_t) len2);
1229 ASSERT_GSL (gsl_blas_dgemm (CblasNoTrans, CblasNoTrans, 1.0, u, v, 0.0, w));
1230 push_matrix (p, w);
1231 gsl_matrix_free (u);
1232 gsl_matrix_free (v);
1233 gsl_matrix_free (w);
1234 (void) gsl_set_error_handler (save_handler);
1235 }
1236
1237 //! @brief OP * = ([, ] COMPLEX, [] COMPLEX) [] COMPLEX
1238
1239 void genie_matrix_complex_times_vector (NODE_T * p)
1240 {
1241 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1242 gsl_complex zero, one;
1243 GSL_SET_COMPLEX (&zero, 0.0, 0.0);
1244 GSL_SET_COMPLEX (&one, 1.0, 0.0);
1245 gsl_vector_complex *u = pop_vector_complex (p, A68G_TRUE);
1246 gsl_matrix_complex *w = pop_matrix_complex (p, A68G_TRUE);
1247 size_t len = SIZE (u);
1248 gsl_vector_complex *v = gsl_vector_complex_calloc ((size_t) len);
1249 ASSERT_GSL (gsl_blas_zgemv (CblasNoTrans, one, w, u, zero, v));
1250 push_vector_complex (p, v);
1251 gsl_vector_complex_free (u);
1252 gsl_vector_complex_free (v);
1253 gsl_matrix_complex_free (w);
1254 (void) gsl_set_error_handler (save_handler);
1255 }
1256
1257 //! @brief OP * = ([] COMPLEX, [, ] COMPLEX) [] COMPLEX
1258
1259 void genie_vector_complex_times_matrix (NODE_T * p)
1260 {
1261 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1262 gsl_complex zero, one;
1263 GSL_SET_COMPLEX (&zero, 0.0, 0.0);
1264 GSL_SET_COMPLEX (&one, 1.0, 0.0);
1265 gsl_matrix_complex *w = pop_matrix_complex (p, A68G_TRUE);
1266 ASSERT_GSL (gsl_matrix_complex_transpose (w));
1267 gsl_vector_complex *u = pop_vector_complex (p, A68G_TRUE);
1268 size_t len = SIZE (u);
1269 gsl_vector_complex *v = gsl_vector_complex_calloc ((size_t) len);
1270 ASSERT_GSL (gsl_blas_zgemv (CblasNoTrans, one, w, u, zero, v));
1271 push_vector_complex (p, v);
1272 gsl_vector_complex_free (u);
1273 gsl_vector_complex_free (v);
1274 gsl_matrix_complex_free (w);
1275 (void) gsl_set_error_handler (save_handler);
1276 }
1277
1278 //! @brief OP * = ([, ] COMPLEX, [, ] COMPLEX) [, ] COMPLEX
1279
1280 void genie_matrix_complex_times_matrix (NODE_T * p)
1281 {
1282 gsl_error_handler_t *save_handler = gsl_set_error_handler (torrix_error_handler);
1283 gsl_complex zero, one;
1284 GSL_SET_COMPLEX (&zero, 0.0, 0.0);
1285 GSL_SET_COMPLEX (&one, 1.0, 0.0);
1286 gsl_matrix_complex *v = pop_matrix_complex (p, A68G_TRUE);
1287 gsl_matrix_complex *u = pop_matrix_complex (p, A68G_TRUE);
1288 size_t len1 = SIZE2 (v), len2 = SIZE1 (u);
1289 gsl_matrix_complex *w = gsl_matrix_complex_calloc ((size_t) len1, (size_t) len2);
1290 ASSERT_GSL (gsl_blas_zgemm (CblasNoTrans, CblasNoTrans, one, u, v, zero, w));
1291 gsl_matrix_complex_free (u);
1292 gsl_matrix_complex_free (v);
1293 push_matrix_complex (p, w);
1294 gsl_matrix_complex_free (w);
1295 (void) gsl_set_error_handler (save_handler);
1296 }
1297
1298 #endif
|
© 2002-2025 J.M. van der Veer (jmvdveer@xs4all.nl)
|