YAP 7.1.0
matrix.c
1/*************************************************************************
2 * *
3 * YAP Prolog *
4 * *
5 * Yap Prolog was developed at NCCUP - Universidade do Porto *
6 * *
7 * Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
8 * *
9 **************************************************************************
10 * *
11 * File: matrix.c * Last rev:
12 ** mods: * comments: numerical arrays *
13 * *
14 *************************************************************************/
15
16#include "YapConfig.h"
17#include "YapInterface.h"
18#include <math.h>
19#if defined(__MINGW32__) || _MSC_VER
20#include <windows.h>
21#endif
22
23#if HAVE_STRING_H
24#include <string.h>
25#endif
26
27/* maximal number of dimensions, 1024 should be enough */
28#define MAX_DIMS 1024
29
30/*
31 A matrix is something of the form
32
33 TYPE = {int,double}
34 BASE = integer
35 #DIMS = an int
36 DIM1
37 ...
38 DIMn
39 DATA in C format.
40
41 floating point matrixes may need to be aligned, so we always have an
42 extra element at the end.
43*/
44
45typedef enum { INT_MATRIX, FLOAT_MATRIX } mat_data_type;
46
47typedef enum {
48 MAT_TYPE = 0,
49 MAT_BASE = 1,
50 MAT_NDIMS = 2,
51 MAT_SIZE = 3,
52 MAT_ALIGN = 4,
53 MAT_DIMS = 5,
54} mat_type;
55
56typedef enum {
57 MAT_PLUS = 0,
58 MAT_SUB = 1,
59 MAT_TIMES = 2,
60 MAT_DIV = 3,
61 MAT_IDIV = 4,
62 MAT_ZDIV = 5,
63 MAT_LOG = 6,
64 MAT_EXP = 7
65} op_type;
66
68typedef struct m {
69 int type;
70 //> 'i' integers,
71 //> 'f' floating-point
72 //> 'b' boolean
73 //> 't' term
74 bool c_ord;
75 union {
76 double *data;
77 intptr_t *ls;
78 bool *bools;
79 struct DB_TERM **dbterms;
80 YAP_Term *terms;
81 };
82 intptr_t ndims;
83 intptr_t sz;
84 intptr_t *dims, base;
85} M;
86
87static YAP_Functor MFunctorM, MFunctorFloats;
88static YAP_Term MTermTrue, MTermFalse, MTermFail;
89static YAP_Atom MAtomC;
90
91static YAP_Int *matrix_long_data(intptr_t *mat, intptr_t ndims) {
92 return (YAP_Int *)(mat + (MAT_DIMS + ndims));
93}
94
95static double *matrix_double_data(intptr_t *mat, intptr_t ndims) {
96 return (double *)(mat + (MAT_DIMS + ndims));
97}
98
99static intptr_t matrix_get_offset(intptr_t *mat, intptr_t *indx) {
100 intptr_t i, pos = mat[MAT_SIZE], off = 0;
101
102 /* find where we are */
103 for (i = 0; i < mat[MAT_NDIMS]; i++) {
104 int v;
105 pos /= mat[MAT_DIMS + i];
106 v = indx[i] - mat[MAT_BASE];
107 if (v >= mat[MAT_DIMS + i]) {
108 return off;
109 }
110 off += pos * v;
111 }
112 return off;
113}
114
115static void matrix_get_index(intptr_t *mat, intptr_t offset, intptr_t *indx) {
116 intptr_t i, pos = mat[MAT_SIZE];
117
118 /* find where we are */
119 for (i = 0; i < mat[MAT_NDIMS]; i++) {
120 pos /= mat[MAT_DIMS + i];
121 indx[i] = offset / pos;
122 offset = offset % pos;
123 }
124}
125
126static size_t GET_OFFSET(YAP_Term t, M *mat, intptr_t *poffset) {
127 intptr_t i, off = 0, pos = mat->sz;
128 if (YAP_IsIntTerm(t)) {
129 *poffset = YAP_IntOfTerm(t);
130 return true;
131 }
132 /* find where we are */
133 for (i = 0; i < mat->ndims; i++) {
134 size_t v;
135 if (!YAP_IsPairTerm(t))
136 YAP_Error(TYPE_ERROR, t, NULL);
137 v = YAP_IntOfTerm(YAP_HeadOfTerm(t)) - mat->base;
138 pos /= mat->dims[i];
139 off += pos * v;
140 t = YAP_TailOfTerm(t);
141 }
142 *poffset = off;
143 return true;
144}
145
146
147static YAP_Bool GET_INDEX(M *mat, intptr_t off, YAP_Term *tf) {
148 intptr_t i, pos = mat->sz;
149 YAP_Term t;
150 /* find where we are */
151 *tf = 0;
152 /* find where we are */
153 for (i = 0; i < mat->ndims; i++) {
154 t = YAP_MkNewPairTerm();
155 if (*tf==0)
156 *tf = t;
157 pos /= mat->dims[i];
158 YAP_Unify(YAP_HeadOfTerm(t),YAP_MkIntTerm(off/pos));
159 off = off % pos;
160 *tf = YAP_TailOfTerm(t);
161 };
162 return YAP_Unify(t,YAP_ARG3);
163}
164
165static void matrix_next_index(intptr_t *dims, intptr_t ndims, intptr_t *indx) {
166 intptr_t i;
167
168 /* find where we are */
169 for (i = ndims; i > 0;) {
170 i--;
171 indx[i]++;
172 if (indx[i] != dims[i])
173 return;
174 indx[i] = 0;
175 }
176}
177
178static int GET_MATRIX(YAP_Term inp, M *o) {
179 intptr_t *mat;
180 o->base = 0;
181 // source: stack
182 //
183 if ((mat = YAP_BlobOfTerm(inp))) {
184 o->type = mat[MAT_TYPE] == FLOAT_MATRIX ? 'f' : 'i';
185 o->c_ord = true;
186 o->sz = mat[MAT_SIZE];
187 o->ndims = mat[MAT_NDIMS];
188 o->data = (double *)(mat + (MAT_DIMS + o->ndims));
189 o->dims = mat + MAT_DIMS;
190 return true;
191 } else if (YAP_IsAtomTerm(inp)) {
192 if ((o->data = YAP_FetchArray(inp, &o->sz, &o->type))) {
193 // old-style arrays
194 if (o->sz > 0) {
195 o->ndims = 1;
196 o->dims = &o->sz;
197 o->c_ord = true;
198 return true;
199 }
200 }
201 }else if (YAP_IsApplTerm(inp)) {
202 YAP_Functor f = YAP_FunctorOfTerm(inp);
203 const char *name=YAP_AtomName(YAP_NameOfFunctor(f));
204 int c =name[0];
205
206 if (c== '$')
207 {
208 YAP_Term bases = YAP_IntOfTerm(YAP_ArgOfTerm(4,inp));
209 o->sz = YAP_IntOfTerm(YAP_ArgOfTerm(3,inp));
210 if (YAP_IsIntTerm(bases))
211 o->base = YAP_IntOfTerm(bases);
212 else
213 o->base = YAP_IntOfTerm(YAP_HeadOfTerm(bases));
214 o->c_ord = o->base == 0;
215 o->ndims = YAP_IntOfTerm(YAP_ArgOfTerm(2,inp));
216 o->dims = malloc(o->ndims*sizeof(intptr_t));
217 YAP_Term l = YAP_ArgOfTerm(1,inp);
218 intptr_t *d = o->dims;
219 while(YAP_IsPairTerm(l)) {
220 *d++ = YAP_IntOfTerm(YAP_HeadOfTerm(l));
221 l = YAP_TailOfTerm(l);
222 }
223 o->terms=YAP_ArgsOfTerm(YAP_ArgOfTerm(inp,5))+1;
224 } else
225 {
226
227 o->sz = YAP_IntOfTerm(YAP_ArgOfTerm(2, inp));
228 o->c_ord = true;
229 o->ndims = 1;
230 o->dims = &o->sz;
231 o->type = c;
232 o->data = (double *)YAP_IntOfTerm(YAP_ArgOfTerm(1, inp));
233 return true;
234 }
235 }
236 return false;
237}
238
239static bool IS_MATRIX(YAP_Term inp) {
240 intptr_t *mat;
241 if ((mat = YAP_BlobOfTerm(inp))) {
242 return
243 mat[MAT_TYPE] == FLOAT_MATRIX ||
244 mat[MAT_TYPE] == INT_MATRIX;
245 } else if (YAP_IsAtomTerm(inp)) {
246 intptr_t size;
247 int type;
248 if (YAP_FetchArray(inp, &size, &type)) {
249 return true;
250 }
251 return false;
252 }else {
253 YAP_Functor f = YAP_FunctorOfTerm(inp);
254 return
255 f == MFunctorM ||
256 f == MFunctorFloats;
257 }
258 return false;
259}
260
261static YAP_Bool is_matrix(void) {
262 return IS_MATRIX(YAP_ARG1);
263}
264
265
266static YAP_Term new_int_matrix(intptr_t ndims, intptr_t dims[],
267 YAP_Int data[]) {
268 intptr_t sz;
269 intptr_t i, nelems = 1;
270 YAP_Term blob;
271 intptr_t *mat;
272 YAP_Int *bdata;
273 int idims[MAX_DIMS];
274
275 /* in case we don't have enough room and need to shift the stack, we can't
276 really afford to keep a pointer to the global */
277 for (i = 0; i < ndims; i++) {
278 idims[i] = dims[i];
279 nelems *= dims[i];
280 }
281 sz = ((MAT_DIMS + 1) * sizeof(int) + ndims * sizeof(int) +
282 nelems * sizeof(YAP_Int)) /
283 sizeof(YAP_CELL);
284
285 blob = YAP_MkBlobTerm(sz);
286 if (blob == YAP_TermNil()) {
287 return blob;
288 }
289 mat = (intptr_t *)YAP_BlobOfTerm(blob);
290 mat[MAT_TYPE] = INT_MATRIX;
291 mat[MAT_BASE] = 0;
292 mat[MAT_NDIMS] = ndims;
293 mat[MAT_SIZE] = nelems;
294 for (i = 0; i < ndims; i++) {
295 mat[MAT_DIMS + i] = idims[i];
296 }
297 bdata = matrix_long_data(mat, ndims);
298 if (data)
299 memmove((void *)bdata, (void *)data, sizeof(double) * nelems);
300 return blob;
301}
302
303static YAP_Term new_float_matrix(intptr_t ndims, intptr_t dims[],
304 double data[]) {
305 intptr_t sz;
306 intptr_t i, nelems = 1;
307 YAP_Term blob;
308 intptr_t *mat;
309 double *bdata;
310 int idims[MAX_DIMS];
311
312 /* in case we don't have enough room and need to shift the stack, we can't
313 really afford to keep a pointer to the global */
314 for (i = 0; i < ndims; i++) {
315 idims[i] = dims[i];
316 nelems *= dims[i];
317 }
318 sz = ((MAT_DIMS + 1) * sizeof(int) + ndims * sizeof(int) +
319 (nelems + 1) * sizeof(double) + (sizeof(YAP_CELL) - 1)) /
320 sizeof(YAP_CELL);
321 blob = YAP_MkBlobTerm(sz);
322 if (blob == YAP_TermNil())
323 return blob;
324 mat = YAP_BlobOfTerm(blob);
325 mat[MAT_TYPE] = FLOAT_MATRIX;
326 mat[MAT_BASE] = 0;
327 mat[MAT_NDIMS] = ndims;
328 mat[MAT_SIZE] = nelems;
329 for (i = 0; i < ndims; i++) {
330 mat[MAT_DIMS + i] = idims[i];
331 }
332 bdata = matrix_double_data(mat, ndims);
333 if (data)
334 memmove((void *)bdata, (void *)data, sizeof(double) * nelems);
335 return blob;
336}
337
338static YAP_Bool scan_dims(intptr_t ndims, YAP_Term tl,
339 intptr_t dims[MAX_DIMS]) {
340 int i;
341
342 for (i = 0; i < ndims; i++) {
343 YAP_Term th;
344 int d;
345
346 if (!YAP_IsPairTerm(tl)) {
347 return FALSE;
348 }
349 th = YAP_HeadOfTerm(tl);
350 if (!YAP_IsIntTerm(th)) {
351 /* ERROR */
352 return FALSE;
353 }
354 d = YAP_IntOfTerm(th);
355 if (d < 0) {
356 /* ERROR */
357 return FALSE;
358 }
359 dims[i] = d;
360 tl = YAP_TailOfTerm(tl);
361 }
362 if (tl != YAP_TermNil()) {
363 /* ERROR */
364 return FALSE;
365 }
366 return TRUE;
367}
368
369static YAP_Bool cp_int_matrix(YAP_Term tl, YAP_Term matrix) {
370 intptr_t *mat = (intptr_t *)YAP_BlobOfTerm(matrix);
371 int i, nelems = mat[MAT_SIZE];
372 YAP_Int *j = matrix_long_data(mat, mat[MAT_NDIMS]);
373
374 for (i = 0; i < nelems; i++) {
375 YAP_Term th;
376 int d;
377
378 if (!YAP_IsPairTerm(tl)) {
379 return FALSE;
380 }
381 th = YAP_HeadOfTerm(tl);
382 if (!YAP_IsIntTerm(th)) {
383 /* ERROR */
384 return FALSE;
385 }
386 d = YAP_IntOfTerm(th);
387 j[i] = d;
388 tl = YAP_TailOfTerm(tl);
389 }
390 if (tl != YAP_TermNil()) {
391 /* ERROR */
392 return FALSE;
393 }
394 return TRUE;
395}
396
397static YAP_Bool cp_float_matrix(YAP_Term tl, YAP_Term matrix) {
398 intptr_t *mat = (intptr_t *)YAP_BlobOfTerm(matrix);
399 intptr_t i, nelems = mat[MAT_SIZE];
400 double *j = matrix_double_data(mat, mat[MAT_NDIMS]);
401
402 for (i = 0; i < nelems; i++) {
403 YAP_Term th;
404 double d;
405
406 if (!YAP_IsPairTerm(tl)) {
407 return FALSE;
408 }
409 th = YAP_HeadOfTerm(tl);
410 if (YAP_IsIntTerm(th)) {
411 d = YAP_IntOfTerm(th);
412 } else if (!YAP_IsFloatTerm(th)) {
413 /* ERROR */
414 return FALSE;
415 } else {
416 d = YAP_FloatOfTerm(th);
417 }
418 j[i] = d;
419 tl = YAP_TailOfTerm(tl);
420 }
421 if (tl != YAP_TermNil()) {
422 /* ERROR */
423 return FALSE;
424 }
425 return TRUE;
426}
427
428static YAP_Bool set_int_matrix(YAP_Term matrix, YAP_Int set) {
429 intptr_t *mat = (intptr_t *)YAP_BlobOfTerm(matrix);
430 int i, nelems = mat[MAT_SIZE];
431 YAP_Int *j = matrix_long_data(mat, mat[MAT_NDIMS]);
432
433 for (i = 0; i < nelems; i++) {
434 j[i] = set;
435 }
436 return TRUE;
437}
438
439static YAP_Bool set_float_matrix(YAP_Term matrix, double set) {
440 intptr_t *mat = (intptr_t *)YAP_BlobOfTerm(matrix);
441 int i, nelems = mat[MAT_SIZE];
442 double *j = matrix_double_data(mat, mat[MAT_NDIMS]);
443
444 for (i = 0; i < nelems; i++) {
445 j[i] = set;
446 }
447 return TRUE;
448}
449
450static YAP_Bool new_ints_matrix(void) {
451 intptr_t ndims = YAP_IntOfTerm(YAP_ARG1);
452 YAP_Term tl = YAP_ARG2, out;
453 intptr_t dims[MAX_DIMS];
454 YAP_Term data;
455
456 if (!scan_dims(ndims, tl, dims))
457 return FALSE;
458 out = new_int_matrix(ndims, dims, NULL);
459 if (out == YAP_TermNil())
460 return FALSE;
461 data = YAP_ARG3;
462 if (!YAP_IsVarTerm(data) && !cp_int_matrix(data, out))
463 return FALSE;
464 return YAP_Unify(YAP_ARG4, out);
465}
466
467static YAP_Bool new_ints_matrix_set(void) {
468 intptr_t ndims = YAP_IntOfTerm(YAP_ARG1);
469 YAP_Term tl = YAP_ARG2, out, tset = YAP_ARG3;
470 intptr_t dims[MAX_DIMS];
471 YAP_Int set;
472
473 if (!YAP_IsIntTerm(tset)) {
474 return FALSE;
475 }
476 set = YAP_IntOfTerm(tset);
477 if (!scan_dims(ndims, tl, dims))
478 return FALSE;
479 size_t sz = 1, i;
480 for (i = 0; i < ndims; i++)
481 sz *= dims[i];
482 if (YAP_RequiresExtraStack(sz * sizeof(YAP_CELL))<0)
483 return false;
484 out = new_int_matrix(ndims, dims, NULL);
485 return set_int_matrix(out, set) && YAP_Unify(YAP_ARG4, out);
486}
487
488static YAP_Bool new_floats_matrix(void) {
489 intptr_t ndims = YAP_IntOfTerm(YAP_ARG1);
490 YAP_Term tl = YAP_ARG2, out, data = YAP_ARG3;
491 intptr_t dims[MAX_DIMS];
492 if (!scan_dims(ndims, tl, dims))
493 return FALSE;
494 out = new_float_matrix(ndims, dims, NULL);
495 if (out == YAP_TermNil())
496 return FALSE;
497 if (!YAP_IsVarTerm(data) && !cp_float_matrix(data, out))
498 return FALSE;
499 return YAP_Unify(YAP_ARG4, out);
500}
501
502 static YAP_Bool new_floats_matrix_set(void) {
503 intptr_t ndims = YAP_IntOfTerm(YAP_ARG1);
504 YAP_Term tl = YAP_ARG2, out, tset = YAP_ARG3;
505 intptr_t dims[MAX_DIMS];
506 double set;
507
508 if (!YAP_IsFloatTerm(tset)) {
509 return FALSE;
510 }
511 set = YAP_FloatOfTerm(tset);
512 if (!scan_dims(ndims, tl, dims))
513 return FALSE;
514 out = new_float_matrix(ndims, dims, NULL);
515 if (!set_float_matrix(out, set))
516 return FALSE;
517 return YAP_Unify(YAP_ARG4, out);
518}
519
520static YAP_Term mk_int_list(intptr_t nelems, intptr_t *data) {
521 YAP_Term tn = YAP_TermNil();
522 YAP_Term tf = tn;
523 int i = 0;
524
525 for (i = nelems - 1; i >= 0; i--) {
526 tf = YAP_MkPairTerm(YAP_MkIntTerm(data[i]), tf);
527 if (tf == tn) {
528 /* error */
529 return tn;
530 }
531 }
532 return tf;
533}
534
535static YAP_Term mk_int_list2(intptr_t nelems, int base, intptr_t *data) {
536 YAP_Term tn = YAP_TermNil();
537 YAP_Term tf = tn;
538 int i = 0;
539
540 for (i = nelems - 1; i >= 0; i--) {
541 tf = YAP_MkPairTerm(YAP_MkIntTerm(data[i] + base), tf);
542 if (tf == tn) {
543 /* error */
544 return tn;
545 }
546 }
547 return tf;
548}
549
550static YAP_Term mk_rep_int_list(intptr_t nelems, int data) {
551 YAP_Term tn = YAP_TermNil();
552 YAP_Term tf = tn;
553 int i = 0;
554
555 for (i = nelems - 1; i >= 0; i--) {
556 tf = YAP_MkPairTerm(YAP_MkIntTerm(data), tf);
557 if (tf == tn) {
558 /* error */
559 return tn;
560 }
561 }
562 return tf;
563}
564
565static void matrix_float_set(intptr_t *mat, intptr_t *indx, double nval) {
566 intptr_t off = 0;
567
568 off = matrix_get_offset(mat, indx);
569 (matrix_double_data(mat, mat[MAT_NDIMS]))[off] = nval;
570}
571
572static void matrix_long_set(intptr_t *mat, intptr_t *indx, YAP_Int nval) {
573 intptr_t off = matrix_get_offset(mat, indx);
574 (matrix_long_data(mat, mat[MAT_NDIMS]))[off] = nval;
575}
576
577
578static YAP_Bool matrix_get_one(void) {
579 M mat;
580 YAP_Term tf;
581 intptr_t offset;
582 if (GET_MATRIX(YAP_ARG1, &mat)>=0 && GET_OFFSET(YAP_ARG2, &mat, &offset)) {
583 switch (mat.type) {
584 case 'f':
585 tf = YAP_MkFloatTerm(mat.data[offset]);
586 return YAP_Unify(YAP_ARG3, tf);
587 case 'i':
588 tf = YAP_MkIntTerm(mat.ls[offset]);
589 return YAP_Unify(YAP_ARG3, tf);
590 return true;
591 case 'b':
592 return YAP_Unify(YAP_ARG3, (mat.bools[offset] ? MTermTrue : MTermFalse));
593 ;
594 case 't':
595 return YAP_Unify(YAP_ARG3, mat.terms[offset]);
596 default:
597 return false;
598 }
599 }
600 return false;
601}
602
603//> M[off] <== int|float
604static YAP_Bool matrix_set_one(void) {
605 M mat;
606 intptr_t offset;
607 if (GET_MATRIX(YAP_ARG1, &mat)<0 || !(GET_OFFSET(YAP_ARG2, &mat, &offset))) {
608 /* Error */
609 return false;
610 }
611 switch (mat.type) {
612 case 'f':
613 if (YAP_IsIntTerm(YAP_ARG3)) {
614 mat.data[offset] = YAP_IntOfTerm(YAP_ARG3);
615 } else if (YAP_IsFloatTerm(YAP_ARG3)) {
616 mat.data[offset] = YAP_FloatOfTerm(YAP_ARG3);
617 }
618 return true;
619 case 'i':
620 if (YAP_IsIntTerm(YAP_ARG3))
621 mat.ls[offset] = YAP_IntOfTerm(YAP_ARG3);
622 else if (YAP_IsFloatTerm(YAP_ARG3))
623 mat.ls[offset] = YAP_FloatOfTerm(YAP_ARG3);
624 return true;
625 case 'b':
626 if (YAP_ARG3 == MTermTrue || YAP_ARG3 == YAP_MkIntTerm(1)) {
627 mat.bools[offset] = true;
628 return true;
629 } else if (YAP_ARG3 == MTermFalse || YAP_ARG3 == YAP_MkIntTerm(0)) {
630 mat.bools[offset] = false;
631 return true;
632 } else {
633 return false;
634 }
635 case 't':
636 mat.terms[offset] = YAP_ARG3;
637 return true;
638 default:
639 return false;
640 }
641}
642
643static YAP_Term flist(YAP_Term t, double *f) {
644 YAP_Term hd = YAP_HeadOfTerm(t);
645 if (YAP_IsIntTerm(hd)) {
646 *f = YAP_IntOfTerm(hd);
647 } else if (YAP_IsFloatTerm(hd)) {
648 *f = YAP_FloatOfTerm(hd);
649 } else {
650 return 0;
651 }
652 return YAP_TailOfTerm(t);
653}
654
655static YAP_Term ilist(YAP_Term t, YAP_Int *f) {
656 YAP_Term hd = YAP_HeadOfTerm(t);
657 if (YAP_IsIntTerm(hd)) {
658 *f = YAP_IntOfTerm(hd);
659 } else if (YAP_IsFloatTerm(hd)) {
660 *f = YAP_FloatOfTerm(hd);
661 } else {
662 return 0;
663 }
664 return YAP_TailOfTerm(t);
665}
666
667static YAP_Term blist(YAP_Term t, YAP_Bool *f) {
668 YAP_Term hd = YAP_HeadOfTerm(t);
669 if (hd == MTermTrue || hd == YAP_MkIntTerm(1)) {
670 *f = true;
671 } else if (hd == MTermFalse || hd == YAP_MkIntTerm(0)) {
672 *f = false;
673 }else {
674 return 0;
675 }
676 return YAP_TailOfTerm(t);
677}
678
679//> M[off] <== int|float
680static YAP_Bool matrix_set_all(void) {
681 M mat;
682 intptr_t offset, sz ;
683 if (GET_MATRIX(YAP_ARG1, &mat)<0) {
684 /* Error */
685 return false;
686 }
687 sz = mat.sz;
688 switch (mat.type) {
689 case 'f': {
690 double d;
691 if (YAP_IsIntTerm(YAP_ARG2)) {
692 d = YAP_IntOfTerm(YAP_ARG2);
693 } else if (YAP_IsFloatTerm(YAP_ARG2)) {
694 d = YAP_FloatOfTerm(YAP_ARG2);
695 } else {
696 YAP_Term t = YAP_ARG2;
697 for (offset = 0; offset < sz; offset++)
698 t = flist(t, mat.data + offset);
699 return true;
700 }
701 for (offset = 0; offset < sz; offset++)
702 mat.data[offset] = d;
703 return true;
704 }
705 case 'b': {
706 YAP_Bool d;
707 if (YAP_ARG2 == MTermTrue || YAP_ARG2 == YAP_MkIntTerm(1)) {
708 d = true;
709 return true;
710 } else if (YAP_ARG2 == MTermFalse || YAP_ARG2 == YAP_MkIntTerm(0)) {
711 d = false;
712 }else {
713 YAP_Term t = YAP_ARG2;
714 for (offset = 0; offset < sz; offset++)
715 t = blist(t, mat.bools+offset);
716 return true;
717 }
718 for (offset = 0; offset < sz; offset++)
719 mat.bools[offset] = d;
720 return true;
721 }
722 case 'i':
723 {
724 YAP_Int d;
725 if (YAP_IsIntTerm(YAP_ARG2)) {
726 d = YAP_IntOfTerm(YAP_ARG2);
727 } else if (YAP_IsFloatTerm(YAP_ARG2)) {
728 d = YAP_FloatOfTerm(YAP_ARG2 );
729 } else {
730 YAP_Term t = YAP_ARG2;
731 for (offset = 0; offset < sz; offset++)
732 t = ilist(t, mat.ls+offset);
733 return true;
734 }
735 for (offset = 0; offset < sz; offset++)
736 mat.ls[offset] = d;
737 return true;
738 }
739 case 't': {
740 YAP_Term d = YAP_ARG2;
741 for (offset = 0; offset < sz; offset++)
742 mat.terms[offset] = d;
743 return true;
744 }
745 default:
746 return false;
747 }
748}
749
750//> M <== [int|float]
751static YAP_Bool matrix_add_to_all(void) {
752 M mat;
753 intptr_t offset, sz;
754 if (GET_MATRIX(YAP_ARG1, &mat)<0) {
755 /* Error */
756 return false;
757 }
758 sz = mat.sz;
759 switch (mat.type) {
760 case 'f': {
761 YAP_Float f;
762 if (YAP_IsIntTerm(YAP_ARG3)) {
763 f = YAP_IntOfTerm(YAP_ARG3);
764 } else if (YAP_IsFloatTerm(YAP_ARG3)) {
765 f = YAP_FloatOfTerm(YAP_ARG3);
766 } else {
767 return false;
768 }
769 for (offset = 0; offset < sz; offset++) {
770 mat.data[offset] += f;
771 }
772 }
773 return true;
774 case 'i': {
775 YAP_Int i;
776 if (YAP_IsIntTerm(YAP_ARG3)) {
777 i = YAP_IntOfTerm(YAP_ARG3);
778 } else if (YAP_IsFloatTerm(YAP_ARG3)) {
779 i = YAP_FloatOfTerm(YAP_ARG3);
780 } else {
781 return false;
782 }
783 for (offset = 0; offset < sz; offset++) {
784 mat.ls[offset] += i;
785
786 }
787 return true;
788 }
789 case 'b':
790 return false;
791 case 't':
792 return false;
793
794 default:
795 return false;
796 }
797}
798
799//> M[off] <== int|float
800static YAP_Bool matrix_inc(void) {
801 M mat;
802 intptr_t offset;
803 if (GET_MATRIX(YAP_ARG1, &mat)<0 || !(GET_OFFSET(YAP_ARG2, &mat, &offset))) {
804 /* Error */
805 return false;
806 }
807 switch (mat.type) {
808 case 'f':
809 mat.data[offset] += 1.0;
810 return true;
811 case 'i':
812 mat.ls[offset] += 1;
813 return true;
814 case 'b':
815 case 't':
816 default:
817 return false;
818 }
819}
820
821//> M[off] <== int|float
822static YAP_Bool matrix_inc3(void) {
823 M mat;
824 intptr_t offset;
825 if (GET_MATRIX(YAP_ARG1, &mat)<0 || !(GET_OFFSET(YAP_ARG2, &mat, &offset))) {
826 /* Error */
827 return false;
828 }
829 switch (mat.type) {
830 case 'f':
831 mat.data[offset] += 1.0;
832 return YAP_Unify(YAP_MkFloatTerm(mat.data[offset]), YAP_ARG3);
833 case 'i':
834 mat.ls[offset] += 1;
835 return YAP_Unify(YAP_MkIntTerm(mat.data[offset]), YAP_ARG3);
836 case 'b':
837 case 't':
838 default:
839 return false;
840 }
841}
842
843static YAP_Bool matrix_dec(void) {
844 M mat;
845 intptr_t offset;
846 if (GET_MATRIX(YAP_ARG1, &mat)<0 || !(GET_OFFSET(YAP_ARG2, &mat, &offset))) {
847 /* Error */
848 return false;
849 }
850 switch (mat.type) {
851 case 'f':
852 mat.data[offset] -= 1.0;
853 return true;
854 case 'i':
855 mat.ls[offset] -= 1;
856 return true;
857 case 'b':
858 case 't':
859 default:
860 return false;
861 }
862}
863
864//> M[off] <== int|float
865static YAP_Bool matrix_dec3(void) {
866 M mat;
867 intptr_t offset;
868 if (GET_MATRIX(YAP_ARG1, &mat)<0 || !(GET_OFFSET(YAP_ARG2, &mat, &offset))) {
869 /* Error */
870 return false;
871 }
872 switch (mat.type) {
873 case 'f':
874 mat.data[offset] -= 1.0;
875 return YAP_Unify(YAP_MkFloatTerm(mat.data[offset]), YAP_ARG3);
876 case 'i':
877 mat.ls[offset] -= 1;
878 return YAP_Unify(YAP_MkIntTerm(mat.ls[offset]), YAP_ARG3);
879 case 'b':
880 case 't':
881 default:
882 return false;
883 }
884}
885
886
887static YAP_Bool matrix_min(void) {
888 M mat;
889 if (GET_MATRIX(YAP_ARG1, &mat)<0) {
890 /* Error */
891 return false;
892 }
893 switch (mat.type) {
894 case 'f': {
895 intptr_t i, sz = mat.sz;
896 double max = mat.data[0];
897 for (i = 1; i < sz; i++) {
898 if (mat.data[i] < max) {
899 max = mat.data[i];
900 }
901 }
902 return YAP_Unify(YAP_MkFloatTerm(max), YAP_ARG2);
903 }
904 case 'i': {
905 intptr_t i, sz = mat.sz;
906 YAP_Int max = mat.ls[0];
907 for (i = 1; i < sz; i++) {
908 if (mat.ls[i] < max) {
909 max = mat.ls[i];
910 }
911 }
912 return YAP_Unify(YAP_MkIntTerm(max), YAP_ARG2);
913 }
914 case 'b':
915 case 't':
916 default:
917 return false;
918 }
919}
920
921
922static YAP_Bool matrix_minarg(void) {
923 M mat;
924 if (GET_MATRIX(YAP_ARG1, &mat)<0) {
925 /* Error */
926 return false;
927 }
928 intptr_t i, off = 0, sz = mat.sz;
929 switch (mat.type) {
930 case 'f': {
931 double max = mat.data[0];
932 for (i = 1; i < sz; i++) {
933 if (mat.data[i] < max) {
934 max = mat.data[i];
935 off = i;
936 }
937 }
938 }
939 case 'i': {
940 YAP_Int max = mat.ls[0];
941 for (i = 1; i < sz; i++) {
942 if (mat.ls[i] < max) {
943 max = mat.ls[i];
944 off = i;
945 }
946 }
947 }
948 case 'b':
949 case 't':
950 default:
951 return false;
952 }
953 YAP_Term t = 0, tf = YAP_ARG3;
954 if (GET_INDEX(&mat, off, &t) &&
955 YAP_Unify(tf,t))
956 return true;
957 return false;
958 }
959
960
961static YAP_Bool matrix_max(void) {
962 M mat;
963 if (GET_MATRIX(YAP_ARG1, &mat)<0) {
964 /* Error */
965 return false;
966 }
967 switch (mat.type) {
968 case 'f': {
969 intptr_t i, sz = mat.sz;
970 double max = mat.data[0];
971 for (i = 1; i < sz; i++) {
972 if (mat.data[i] > max) {
973 max = mat.data[i];
974 }
975 }
976 return YAP_Unify(YAP_MkFloatTerm(max), YAP_ARG2);
977 }
978 case 'i': {
979 intptr_t i, sz = mat.sz;
980 YAP_Int max = mat.ls[0];
981 for (i = 1; i < sz; i++) {
982 if (mat.ls[i] > max) {
983 max = mat.ls[i];
984 }
985 }
986 return YAP_Unify(YAP_MkIntTerm(max), YAP_ARG2);
987 }
988 case 'b':
989 case 't':
990 default:
991 return false;
992 }
993}
994
995
996static YAP_Bool matrix_maxarg(void) {
997 M mat;
998 if (GET_MATRIX(YAP_ARG1, &mat)<0) {
999 /* Error */
1000 return false;
1001 }
1002 intptr_t i, off = 0, sz = mat.sz;
1003 switch (mat.type) {
1004 case 'f': {
1005 double max = mat.data[0];
1006 for (i = 1; i < sz; i++) {
1007 if (mat.data[i] > max) {
1008 max = mat.data[i];
1009 off = i;
1010 }
1011 }
1012 return YAP_Unify(YAP_MkIntTerm(off), YAP_ARG2);
1013 }
1014 case 'i': {
1015 YAP_Int max = mat.ls[0];
1016 for (i = 1; i < sz; i++) {
1017 if (mat.ls[i] > max) {
1018 max = mat.ls[i];
1019 off = i;
1020 }
1021 }
1022 return YAP_Unify(YAP_MkIntTerm(off), YAP_ARG2);
1023 }
1024 case 'b':
1025 case 't':
1026 default:
1027 return false;
1028 }
1029}
1030
1031
1032static YAP_Bool matrix_dims(void) {
1033 M *mat, m0;
1034 YAP_Term tf;
1035 mat = &m0;
1036
1037 int rc = GET_MATRIX(YAP_ARG1, mat);
1038 if (rc<0) {
1039 /* Error */
1040 return FALSE;
1041 }
1042 tf = mk_int_list(mat->ndims, mat->dims);
1043 return YAP_Unify(YAP_ARG2, tf);
1044}
1045
1046
1055static YAP_Bool matrix_to_list(void) {
1056 M mat;
1057
1058 int rc = GET_MATRIX(YAP_ARG1, &mat);
1059 if (rc<0) {
1060 /* Error */
1061 return false;
1062 }
1063 YAP_Term t = YAP_TermNil();
1064switch (mat.type)
1065 {
1066 case 'i':
1067 {
1068 if (YAP_RequiresExtraStack(mat.sz*5+4096) < 0)
1069 return false;
1070 int i=mat.sz;
1071 while (i) {
1072 i--;
1073 t = YAP_MkPairTerm(YAP_MkIntTerm(mat.ls[i]),t);
1074 }
1075 }
1076 break;
1077 case 'f':
1078 {
1079 if (YAP_RequiresExtraStack(mat.sz*5+4096) < 0)
1080 return false;
1081 int i=mat.sz;
1082 while (i) {
1083 i--;
1084 t = YAP_MkPairTerm(YAP_MkFloatTerm(mat.ls[i]),t);
1085 }
1086 }
1087 break;
1088 case 'b':
1089 {
1090 if (YAP_RequiresExtraStack(mat.sz*2+4096) < 0)
1091 return false;
1092 int i=mat.sz;
1093 while (i) {
1094 i--;
1095 t = YAP_MkPairTerm((mat.bools[i] ? MTermTrue : MTermFalse),t);
1096 }
1097 }
1098 break;
1099 case 't':
1100 {
1101 if (YAP_RequiresExtraStack(mat.sz*2+4096) < 0)
1102 return false;
1103 int i=mat.sz;
1104 while (i) {
1105 i--;
1106 t = YAP_MkPairTerm(mat.terms[i],t);
1107 }
1108 }
1109 break;
1110 default:
1111 return false;
1112 }
1113 return YAP_Unify(YAP_ARG2, t);
1114}
1115
1116static YAP_Bool matrix_set_base(void) {
1117 intptr_t *mat;
1118
1119 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
1120 if (!mat) {
1121 /* Error */
1122 return FALSE;
1123 }
1124 mat[MAT_BASE] = YAP_IntOfTerm(YAP_ARG2);
1125 return TRUE;
1126}
1127
1128static YAP_Bool matrix_dims3(void) {
1129 intptr_t *mat;
1130 YAP_Term tf, tof;
1131
1132 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
1133 if (!mat) {
1134 /* Error */
1135 return FALSE;
1136 }
1137 tf = mk_int_list(mat[MAT_NDIMS], mat + MAT_DIMS);
1138 tof = mk_rep_int_list(mat[MAT_NDIMS], mat[MAT_BASE]);
1139 return YAP_Unify(YAP_ARG2, tf) && YAP_Unify(YAP_ARG3, tof);
1140}
1141
1150static YAP_Bool matrix_size(void) {
1151 intptr_t *mat;
1152
1153 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
1154 if (!mat) {
1155 /* Error */
1156 return FALSE;
1157 }
1158 return YAP_Unify(YAP_ARG2, YAP_MkIntTerm(mat[MAT_SIZE]));
1159}
1160
1161static YAP_Bool matrix_ndims(void) {
1162 intptr_t *mat;
1163
1164 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
1165 if (!mat) {
1166 /* Error */
1167 return FALSE;
1168 }
1169 return YAP_Unify(YAP_ARG2, YAP_MkIntTerm(mat[MAT_NDIMS]));
1170}
1171
1172static YAP_Bool matrix_type(void) {
1173 intptr_t *mat;
1174 YAP_Term tf;
1175
1176 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
1177 if (!mat) {
1178 /* not an error, it may be called on a term matrix */
1179 return FALSE;
1180 }
1181 if (mat[MAT_TYPE] == INT_MATRIX) {
1182 tf = YAP_MkIntTerm(0);
1183 } else {
1184 tf = YAP_MkIntTerm(1);
1185 }
1186 return YAP_Unify(YAP_ARG2, tf);
1187}
1188
1189static YAP_Bool matrix_arg_to_offset(void) {
1190 M mat;
1191 intptr_t off;
1192 if (GET_MATRIX(YAP_ARG1, &mat)<0)
1193 return false;
1194 if (!GET_OFFSET(YAP_ARG2, &mat, &off))
1195 return false;
1196 return YAP_Unify(YAP_ARG3, YAP_MkIntTerm(off));
1197}
1198
1199static YAP_Bool matrix_offset_to_arg(void) {
1200 intptr_t indx[MAX_DIMS];
1201 M mat;
1202 YAP_Term off;
1203 if (GET_MATRIX(YAP_ARG1, &mat)<0)
1204 return false;
1205 if (!GET_INDEX(&mat, YAP_ARG2, &off))
1206 return false;
1207 return YAP_Unify(YAP_ARG3, YAP_MkIntTerm(off));
1208 YAP_Term tf = mk_int_list2(mat.ndims, mat.base, indx);
1209 return YAP_Unify(YAP_ARG3, tf);
1210}
1211
1212
1213static YAP_Bool matrix_log_all(void) {
1214 intptr_t *mat;
1215
1216 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
1217 if (!mat) {
1218 /* Error */
1219 return FALSE;
1220 }
1221 if (mat[MAT_TYPE] == INT_MATRIX) {
1222 return FALSE;
1223 } else {
1224 double *data = matrix_double_data(mat, mat[MAT_NDIMS]);
1225 intptr_t i;
1226
1227 for (i = 0; i < mat[MAT_SIZE]; i++) {
1228 data[i] = log(data[i]);
1229 }
1230 }
1231 return TRUE;
1232}
1233
1234static YAP_Bool matrix_log_all2(void) {
1235 intptr_t *mat;
1236
1237 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
1238 if (!mat) {
1239 /* Error */
1240 return FALSE;
1241 }
1242 if (mat[MAT_TYPE] == INT_MATRIX) {
1243 YAP_Term out;
1244 YAP_Int *data = matrix_long_data(mat, mat[MAT_NDIMS]);
1245 double *ndata;
1246 intptr_t i;
1247 intptr_t *nmat;
1248
1249 if (!YAP_IsVarTerm(YAP_ARG2)) {
1250 out = YAP_ARG2;
1251 } else {
1252 out = new_float_matrix(mat[MAT_NDIMS], mat + MAT_DIMS, NULL);
1253 if (out == YAP_TermNil())
1254 return FALSE;
1255 }
1256 nmat = (intptr_t *)YAP_BlobOfTerm(out);
1257 ndata = matrix_double_data(nmat, mat[MAT_NDIMS]);
1258 for (i = 0; i < mat[MAT_SIZE]; i++) {
1259 ndata[i] = log((double)data[i]);
1260 }
1261 if (YAP_IsVarTerm(YAP_ARG2)) {
1262 return YAP_Unify(YAP_ARG2, out);
1263 }
1264 } else {
1265 YAP_Term out;
1266 double *data = matrix_double_data(mat, mat[MAT_NDIMS]), *ndata;
1267 intptr_t i;
1268 intptr_t *nmat;
1269
1270 if (!YAP_IsVarTerm(YAP_ARG2)) {
1271 out = YAP_ARG2;
1272 } else {
1273 out = new_float_matrix(mat[MAT_NDIMS], mat + MAT_DIMS, NULL);
1274 if (out == YAP_TermNil())
1275 return FALSE;
1276 }
1277 nmat = (intptr_t *)YAP_BlobOfTerm(out);
1278 ndata = matrix_double_data(nmat, mat[MAT_NDIMS]);
1279 for (i = 0; i < mat[MAT_SIZE]; i++) {
1280 ndata[i] = log(data[i]);
1281 }
1282 if (YAP_IsVarTerm(YAP_ARG2)) {
1283 return YAP_Unify(YAP_ARG2, out);
1284 }
1285 }
1286 return TRUE;
1287}
1288
1289static YAP_Bool matrix_exp_all(void) {
1290 intptr_t *mat;
1291
1292 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
1293 if (!mat) {
1294 /* Error */
1295 return FALSE;
1296 }
1297 if (mat[MAT_TYPE] == INT_MATRIX) {
1298 return FALSE;
1299 } else {
1300 double *data = matrix_double_data(mat, mat[MAT_NDIMS]);
1301 intptr_t i;
1302
1303 for (i = 0; i < mat[MAT_SIZE]; i++) {
1304 data[i] = exp(data[i]);
1305 }
1306 }
1307 return TRUE;
1308}
1309
1310static YAP_Bool matrix_exp2_all(void) {
1311 intptr_t *mat;
1312
1313 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
1314 if (!mat) {
1315 /* Error */
1316 return FALSE;
1317 }
1318 if (mat[MAT_TYPE] == INT_MATRIX) {
1319 return FALSE;
1320 } else {
1321 double *data = matrix_double_data(mat, mat[MAT_NDIMS]);
1322 intptr_t i;
1323 double max = data[0];
1324
1325 for (i = 1; i < mat[MAT_SIZE]; i++) {
1326 if (data[i] > max)
1327 max = data[i];
1328 }
1329
1330 for (i = 0; i < mat[MAT_SIZE]; i++) {
1331 data[i] = exp(data[i] - max);
1332 }
1333 }
1334 return TRUE;
1335}
1336
1337static YAP_Bool matrix_exp_all2(void) {
1338 intptr_t *mat;
1339
1340 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
1341 if (!mat) {
1342 /* Error */
1343 return FALSE;
1344 }
1345 if (mat[MAT_TYPE] == INT_MATRIX) {
1346 YAP_Term out;
1347 YAP_Int *data = matrix_long_data(mat, mat[MAT_NDIMS]);
1348 double *ndata;
1349 intptr_t i;
1350 intptr_t *nmat;
1351
1352 if (!YAP_IsVarTerm(YAP_ARG2)) {
1353 out = YAP_ARG2;
1354 } else {
1355 out = new_float_matrix(mat[MAT_NDIMS], mat + MAT_DIMS, NULL);
1356 if (out == YAP_TermNil())
1357 return FALSE;
1358 }
1359 nmat = (intptr_t *)YAP_BlobOfTerm(out);
1360 ndata = matrix_double_data(nmat, mat[MAT_NDIMS]);
1361 for (i = 0; i < mat[MAT_SIZE]; i++) {
1362 ndata[i] = exp((double)data[i]);
1363 }
1364 if (YAP_IsVarTerm(YAP_ARG2)) {
1365 return YAP_Unify(YAP_ARG2, out);
1366 }
1367 } else {
1368 YAP_Term out;
1369 double *data = matrix_double_data(mat, mat[MAT_NDIMS]), *ndata;
1370 intptr_t i;
1371 intptr_t *nmat;
1372
1373 if (!YAP_IsVarTerm(YAP_ARG2)) {
1374 out = YAP_ARG2;
1375 } else {
1376 out = new_float_matrix(mat[MAT_NDIMS], mat + MAT_DIMS, NULL);
1377 if (out == YAP_TermNil())
1378 return FALSE;
1379 }
1380 nmat = (intptr_t *)YAP_BlobOfTerm(out);
1381 ndata = matrix_double_data(nmat, mat[MAT_NDIMS]);
1382 for (i = 0; i < mat[MAT_SIZE]; i++) {
1383 ndata[i] = exp(data[i]);
1384 }
1385 if (YAP_IsVarTerm(YAP_ARG2)) {
1386 return YAP_Unify(YAP_ARG2, out);
1387 }
1388 }
1389 return TRUE;
1390}
1391
1400static YAP_Bool matrix_sum(void) {
1401 M mat;
1402 YAP_Term tf;
1403 int i;
1404 if (GET_MATRIX(YAP_ARG1, &mat)>=0) {
1405 if (mat.type == 'i') {
1406 YAP_Int sum = 0;
1407
1408 for (i = 0; i < mat.sz; i++) {
1409 sum += mat.ls[i];
1410 }
1411 tf = YAP_MkIntTerm(sum);
1412 } else {
1413 double *data = mat.data;
1414 intptr_t i;
1415 double sum = 0.0;
1416 // function KahanSum(input)
1417 double c = 0.0; // A running compensation for lost low-order bits.
1418 for (i = 0; i < mat.sz; i++) {
1419 double y = data[i] - c; // So far, so good: c is zero.
1420 double t =
1421 sum +
1422 y; // Alas, sum is big, y small, so low-order digits of y are lost.
1423 c = (t - sum) - y; // (t - sum) cancels the high-order part of y;
1424 // subtracting y recovers negative (low part of y)
1425 sum = t; // Algebraically, c should always be zero. Beware
1426 // overly-aggressive optimizing compilers!
1427 }
1428 tf = YAP_MkFloatTerm(sum);
1429 }
1430 }
1431 return YAP_Unify(YAP_ARG2, tf);
1432}
1433
1434static void add_int_lines(int total, intptr_t nlines, YAP_Int *mat0,
1435 YAP_Int *matf) {
1436 intptr_t ncols = total / nlines, i;
1437 for (i = 0; i < ncols; i++) {
1438 YAP_Int sum = 0;
1439 int j;
1440
1441 for (j = i; j < total; j += ncols) {
1442 sum += mat0[j];
1443 }
1444 matf[i] = sum;
1445 }
1446}
1447
1448static void add_double_lines(int total, intptr_t nlines, double *mat0,
1449 double *matf) {
1450 intptr_t ncols = total / nlines, i;
1451 for (i = 0; i < ncols; i++) {
1452 double sum = 0;
1453 int j;
1454
1455 for (j = i; j < total; j += ncols) {
1456 sum += mat0[j];
1457 }
1458 matf[i] = sum;
1459 }
1460}
1461
1462static YAP_Bool matrix_agg_lines(void) {
1463 intptr_t *mat;
1464 YAP_Term tf;
1465 YAP_Term top = YAP_ARG2;
1466 op_type op;
1467
1468 if (!YAP_IsIntTerm(top)) {
1469 return FALSE;
1470 }
1471 op = YAP_IntOfTerm(top);
1472 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
1473 if (!mat) {
1474 /* Error */
1475 return FALSE;
1476 }
1477 /* create a new array without first dimension */
1478 if (mat[MAT_TYPE] == INT_MATRIX) {
1479 YAP_Int *data, *ndata;
1480 intptr_t dims = mat[MAT_NDIMS];
1481 intptr_t *nmat;
1482
1483 tf = new_int_matrix(dims - 1, mat + (MAT_DIMS + 1), NULL);
1484 if (tf == YAP_TermNil())
1485 return FALSE;
1486 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
1487 nmat = (intptr_t *)YAP_BlobOfTerm(tf);
1488 data = matrix_long_data(mat, dims);
1489 ndata = matrix_long_data(nmat, dims - 1);
1490 if (op == MAT_PLUS) {
1491 add_int_lines(mat[MAT_SIZE], mat[MAT_DIMS], data, ndata);
1492 } else
1493 return FALSE;
1494 } else {
1495 double *data, *ndata;
1496 intptr_t dims = mat[MAT_NDIMS];
1497 intptr_t *nmat;
1498
1499 tf = new_float_matrix(dims - 1, mat + (MAT_DIMS + 1), NULL);
1500 nmat = (intptr_t *)YAP_BlobOfTerm(tf);
1501 if (tf == YAP_TermNil())
1502 return FALSE;
1503 data = matrix_double_data(mat, dims);
1504 ndata = matrix_double_data(nmat, dims - 1);
1505 if (op == MAT_PLUS) {
1506 add_double_lines(mat[MAT_SIZE], mat[MAT_DIMS], data, ndata);
1507 } else
1508 return FALSE;
1509 }
1510 return YAP_Unify(YAP_ARG3, tf);
1511}
1512
1513static void add_int_cols(int total, intptr_t nlines, YAP_Int *mat0,
1514 YAP_Int *matf) {
1515 intptr_t ncols = total / nlines, i, j = 0;
1516 for (i = 0; i < nlines; i++) {
1517 YAP_Int sum = 0;
1518 int max = (i + 1) * ncols;
1519
1520 for (; j < max; j++) {
1521 sum += mat0[j];
1522 }
1523 matf[i] = sum;
1524 }
1525}
1526
1527static void add_double_cols(int total, intptr_t nlines, double *mat0,
1528 double *matf) {
1529 intptr_t ncols = total / nlines, i, j = 0;
1530 for (i = 0; i < nlines; i++) {
1531 double sum = 0;
1532 int max = (i + 1) * ncols;
1533
1534 for (; j < max; j++) {
1535 sum += mat0[j];
1536 }
1537 matf[i] = sum;
1538 }
1539}
1540
1541static YAP_Bool matrix_agg_cols(void) {
1542 intptr_t *mat;
1543 YAP_Term tf;
1544 YAP_Term top = YAP_ARG2;
1545 op_type op;
1546
1547 if (!YAP_IsIntTerm(top)) {
1548 return FALSE;
1549 }
1550 op = YAP_IntOfTerm(top);
1551 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
1552 if (!mat) {
1553 /* Error */
1554 return FALSE;
1555 }
1556 /* create a new array without first dimension */
1557 if (mat[MAT_TYPE] == INT_MATRIX) {
1558 YAP_Int *data, *ndata;
1559 intptr_t dims = mat[MAT_NDIMS];
1560 intptr_t *nmat;
1561
1562 tf = new_int_matrix(1, mat + MAT_DIMS, NULL);
1563 if (tf == YAP_TermNil())
1564 return FALSE;
1565 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
1566 nmat = (intptr_t *)YAP_BlobOfTerm(tf);
1567 data = matrix_long_data(mat, dims);
1568 ndata = matrix_long_data(nmat, 1);
1569 if (op == MAT_PLUS) {
1570 add_int_cols(mat[MAT_SIZE], mat[MAT_DIMS], data, ndata);
1571 } else
1572 return FALSE;
1573 } else {
1574 double *data, *ndata;
1575 intptr_t dims = mat[MAT_NDIMS];
1576 intptr_t *nmat;
1577
1578 tf = new_float_matrix(1, mat + MAT_DIMS, NULL);
1579 if (tf == YAP_TermNil())
1580 return FALSE;
1581 nmat = (intptr_t *)YAP_BlobOfTerm(tf);
1582 data = matrix_double_data(mat, dims);
1583 ndata = matrix_double_data(nmat, 1);
1584 if (op == MAT_PLUS) {
1585 add_double_cols(mat[MAT_SIZE], mat[MAT_DIMS], data, ndata);
1586 } else
1587 return FALSE;
1588 }
1589 return YAP_Unify(YAP_ARG3, tf);
1590}
1591
1592static void div_int_by_lines(int total, intptr_t nlines, YAP_Int *mat1,
1593 YAP_Int *mat2, double *ndata) {
1594 intptr_t ncols = total / nlines, i;
1595 for (i = 0; i < total; i++) {
1596 ndata[i] = ((double)mat1[i]) / mat2[i % ncols];
1597 }
1598}
1599
1600static void div_int_by_dlines(int total, intptr_t nlines, YAP_Int *mat1,
1601 double *mat2, double *ndata) {
1602 intptr_t ncols = total / nlines, i;
1603 for (i = 0; i < total; i++) {
1604 ndata[i] = mat1[i] / mat2[i % ncols];
1605 }
1606}
1607
1608static void div_float_long_by_lines(int total, intptr_t nlines, double *mat1,
1609 YAP_Int *mat2, double *ndata) {
1610 intptr_t ncols = total / nlines, i;
1611 for (i = 0; i < total; i++) {
1612 ndata[i] = mat1[i] / mat2[i % ncols];
1613 }
1614}
1615
1616static void div_float_by_lines(int total, intptr_t nlines, double *mat1,
1617 double *mat2, double *ndata) {
1618 intptr_t ncols = total / nlines, i;
1619 for (i = 0; i < total; i++) {
1620 ndata[i] = mat1[i] / mat2[i % ncols];
1621 }
1622}
1623
1624static YAP_Bool matrix_op_to_lines(void) {
1625 intptr_t *mat1, *mat2;
1626 YAP_Term top = YAP_ARG3;
1627 op_type op;
1628 YAP_Term tf;
1629
1630 if (!YAP_IsIntTerm(top)) {
1631 return FALSE;
1632 }
1633 op = YAP_IntOfTerm(top);
1634 mat1 = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
1635 if (!mat1) {
1636 /* Error */
1637 return FALSE;
1638 }
1639 mat2 = (intptr_t *)YAP_BlobOfTerm(YAP_ARG2);
1640 if (!mat2) {
1641 /* Error */
1642 return FALSE;
1643 }
1644 /* create a new array without first dimension */
1645 if (mat1[MAT_TYPE] == INT_MATRIX) {
1646 YAP_Int *data1;
1647 intptr_t dims = mat1[MAT_NDIMS];
1648 intptr_t *nmat;
1649 data1 = matrix_long_data(mat1, dims);
1650
1651 if (mat2[MAT_TYPE] == INT_MATRIX) {
1652 YAP_Int *data2 = matrix_long_data(mat2, dims - 1);
1653 if (op == MAT_DIV) {
1654 double *ndata;
1655
1656 tf = new_float_matrix(dims, mat1 + MAT_DIMS, NULL);
1657 if (tf == YAP_TermNil())
1658 return FALSE;
1659 nmat = YAP_BlobOfTerm(tf);
1660 ndata = matrix_double_data(nmat, dims);
1661 div_int_by_lines(mat1[MAT_SIZE], mat1[MAT_DIMS], data1, data2, ndata);
1662 } else {
1663 return FALSE;
1664 }
1665 } else if (mat2[MAT_TYPE] == FLOAT_MATRIX) {
1666 double *data2 = matrix_double_data(mat2, dims - 1);
1667 if (op == MAT_DIV) {
1668 double *ndata;
1669
1670 tf = new_float_matrix(dims, mat1 + MAT_DIMS, NULL);
1671 if (tf == YAP_TermNil())
1672 return FALSE;
1673 nmat = YAP_BlobOfTerm(tf);
1674 ndata = matrix_double_data(nmat, dims);
1675 div_int_by_dlines(mat1[MAT_SIZE], mat1[MAT_DIMS], data1, data2, ndata);
1676 } else {
1677 return FALSE;
1678 }
1679 } else {
1680 return FALSE;
1681 }
1682 } else {
1683 double *data1, *ndata;
1684 intptr_t dims = mat1[MAT_NDIMS];
1685 intptr_t *nmat;
1686
1687 data1 = matrix_double_data(mat1, dims);
1688 tf = new_float_matrix(dims, mat1 + MAT_DIMS, NULL);
1689 nmat = YAP_BlobOfTerm(tf);
1690 if (tf == YAP_TermNil())
1691 return FALSE;
1692 ndata = matrix_double_data(nmat, dims);
1693 if (mat2[MAT_TYPE] == INT_MATRIX) {
1694 YAP_Int *data2 = matrix_long_data(mat2, dims - 1);
1695 if (op == MAT_DIV) {
1696 div_float_long_by_lines(mat1[MAT_SIZE], mat1[MAT_DIMS], data1, data2,
1697 ndata);
1698 } else {
1699 return FALSE;
1700 }
1701 } else if (mat2[MAT_TYPE] == FLOAT_MATRIX) {
1702 double *data2 = matrix_double_data(mat2, dims - 1);
1703 if (op == MAT_DIV) {
1704 div_float_by_lines(mat1[MAT_SIZE], mat1[MAT_DIMS], data1, data2, ndata);
1705 } else {
1706 return FALSE;
1707 }
1708 } else {
1709 return FALSE;
1710 }
1711 }
1712 return YAP_Unify(YAP_ARG4, tf);
1713}
1714
1715static void matrix_long_add_data(YAP_Int *nmat, int siz, YAP_Int mat1[],
1716 YAP_Int mat2[]) {
1717 intptr_t i;
1718
1719 for (i = 0; i < siz; i++) {
1720 nmat[i] = mat1[i] + mat2[i];
1721 }
1722}
1723
1724static void matrix_long_double_add_data(double *nmat, int siz, YAP_Int mat1[],
1725 double mat2[]) {
1726 intptr_t i;
1727
1728 for (i = 0; i < siz; i++) {
1729 nmat[i] = mat1[i] + mat2[i];
1730 }
1731}
1732
1733static void matrix_double_add_data(double *nmat, int siz, double mat1[],
1734 double mat2[]) {
1735 intptr_t i;
1736
1737 for (i = 0; i < siz; i++) {
1738 nmat[i] = mat1[i] + mat2[i];
1739 }
1740}
1741
1742static void matrix_long_sub_data(YAP_Int *nmat, int siz, YAP_Int mat1[],
1743 YAP_Int mat2[]) {
1744 intptr_t i;
1745
1746 for (i = 0; i < siz; i++) {
1747 nmat[i] = mat1[i] - mat2[i];
1748 }
1749}
1750
1751static void matrix_long_double_sub_data(double *nmat, int siz, YAP_Int mat1[],
1752 double mat2[]) {
1753 intptr_t i;
1754
1755 for (i = 0; i < siz; i++) {
1756 nmat[i] = mat1[i] - mat2[i];
1757 }
1758}
1759
1760static void matrix_long_double_rsub_data(double *nmat, int siz, double mat1[],
1761 YAP_Int mat2[]) {
1762 intptr_t i;
1763
1764 for (i = 0; i < siz; i++) {
1765 nmat[i] = mat2[i] - mat1[i];
1766 }
1767}
1768
1769static void matrix_double_sub_data(double *nmat, int siz, double mat1[],
1770 double mat2[]) {
1771 intptr_t i;
1772
1773 for (i = 0; i < siz; i++) {
1774 nmat[i] = mat1[i] - mat2[i];
1775 }
1776}
1777
1778static void matrix_long_mult_data(YAP_Int *nmat, int siz, YAP_Int mat1[],
1779 YAP_Int mat2[]) {
1780 intptr_t i;
1781
1782 for (i = 0; i < siz; i++) {
1783 nmat[i] = mat1[i] * mat2[i];
1784 }
1785}
1786
1787static void matrix_long_double_mult_data(double *nmat, int siz, YAP_Int mat1[],
1788 double mat2[]) {
1789 intptr_t i;
1790
1791 for (i = 0; i < siz; i++) {
1792 nmat[i] = mat1[i] * mat2[i];
1793 }
1794}
1795
1796static void matrix_double_mult_data(double *nmat, int siz, double mat1[],
1797 double mat2[]) {
1798 intptr_t i;
1799
1800 for (i = 0; i < siz; i++) {
1801 nmat[i] = mat1[i] * mat2[i];
1802 }
1803}
1804
1805static void matrix_long_div_data(YAP_Int *nmat, int siz, YAP_Int mat1[],
1806 YAP_Int mat2[]) {
1807 intptr_t i;
1808
1809 for (i = 0; i < siz; i++) {
1810 nmat[i] = mat1[i] / mat2[i];
1811 }
1812}
1813
1814static void matrix_long_double_div_data(double *nmat, int siz, YAP_Int mat1[],
1815 double mat2[]) {
1816 intptr_t i;
1817
1818 for (i = 0; i < siz; i++) {
1819 nmat[i] = mat1[i] / mat2[i];
1820 }
1821}
1822
1823static void matrix_long_double_div2_data(double *nmat, int siz, double mat1[],
1824 YAP_Int mat2[]) {
1825 intptr_t i;
1826
1827 for (i = 0; i < siz; i++) {
1828 nmat[i] = mat1[i] / mat2[i];
1829 }
1830}
1831
1832static void matrix_double_div_data(double *nmat, int siz, double mat1[],
1833 double mat2[]) {
1834 intptr_t i;
1835
1836 for (i = 0; i < siz; i++) {
1837 nmat[i] = mat1[i] / mat2[i];
1838 }
1839}
1840
1841static void matrix_long_zdiv_data(YAP_Int *nmat, int siz, YAP_Int mat1[],
1842 YAP_Int mat2[]) {
1843 intptr_t i;
1844
1845 for (i = 0; i < siz; i++) {
1846 if (mat1[i] == 0)
1847 nmat[i] = 0;
1848 else
1849 nmat[i] = mat1[i] / mat2[i];
1850 }
1851}
1852
1853static void matrix_long_double_zdiv_data(double *nmat, int siz, YAP_Int mat1[],
1854 double mat2[]) {
1855 intptr_t i;
1856
1857 for (i = 0; i < siz; i++) {
1858 if (mat1[i] == 0)
1859 nmat[i] = 0;
1860 else
1861 nmat[i] = mat1[i] / mat2[i];
1862 }
1863}
1864
1865static void matrix_long_double_zdiv2_data(double *nmat, int siz, double mat1[],
1866 YAP_Int mat2[]) {
1867 intptr_t i;
1868
1869 for (i = 0; i < siz; i++) {
1870 if (mat1[i] == 0.0)
1871 nmat[i] = 0;
1872 else
1873 nmat[i] = mat1[i] / mat2[i];
1874 }
1875}
1876
1877static void matrix_double_zdiv_data(double *nmat, int siz, double mat1[],
1878 double mat2[]) {
1879 intptr_t i;
1880
1881 for (i = 0; i < siz; i++) {
1882 if (mat1[i] == 0.0) {
1883 nmat[i] = 0.0;
1884 } else {
1885 nmat[i] = mat1[i] / mat2[i];
1886 }
1887 }
1888}
1889
1890static YAP_Bool matrix_op(void) {
1891 M mat1, mat2, nmat;
1892 YAP_Term top = YAP_ARG3;
1893 op_type op;
1894 YAP_Term tf = YAP_ARG4;
1895 int create = true;
1896 if (!YAP_IsIntTerm(top)) {
1897 return FALSE;
1898 }
1899 op = YAP_IntOfTerm(top);
1900 if (GET_MATRIX(YAP_ARG1, &mat1)<0 ||
1901 GET_MATRIX(YAP_ARG2, &mat2)<0) {
1902 return false;
1903}
1904 if (tf == YAP_ARG1 || tf == YAP_ARG2) {
1905 create = false;
1906 }
1907 int mem= 0;
1908 if (create && (mem = YAP_RequiresExtraStack(mat1.sz*2+4096)) > 0) {
1909 GET_MATRIX(YAP_ARG1, &mat1);
1910 GET_MATRIX(YAP_ARG2, &mat2);
1911 } else if (mem<0) {
1912 return false;
1913 }
1914 if (create) {
1915 if (mat1.type == 'i' && mat2.type == 'i') {
1916 tf = new_int_matrix(mat1.ndims, mat1.dims, NULL);
1917 } else {
1918 tf = new_float_matrix(mat1.ndims, mat1.dims, NULL);
1919 }
1920 if (tf == YAP_TermNil()) {
1921 return FALSE;
1922 }
1923 }else {
1924 tf=YAP_ARG1;
1925 }
1926 GET_MATRIX(tf, &nmat);
1927 if (mat1.type == 'i') {
1928
1929 if (mat2.type == 'i') {
1930 switch (op) {
1931 case MAT_PLUS:
1932 matrix_long_add_data(nmat.ls, mat1.sz, mat1.ls, mat2.ls);
1933 break;
1934 case MAT_SUB:
1935 matrix_long_sub_data(nmat.ls, mat1.sz, mat1.ls, mat2.ls);
1936 break;
1937 case MAT_TIMES:
1938 matrix_long_mult_data(nmat.ls, mat1.sz, mat1.ls, mat2.ls);
1939 break;
1940 case MAT_DIV:
1941 matrix_long_div_data(nmat.ls, mat1.sz, mat1.ls, mat2.ls);
1942 break;
1943 case MAT_ZDIV:
1944 matrix_long_zdiv_data(nmat.ls, mat1.sz, mat1.ls, mat2.ls);
1945 break;
1946 default:
1947 return FALSE;
1948 }
1949 } else if (mat2.type == 'f') {
1950 switch (op) {
1951 case MAT_PLUS:
1952 matrix_long_double_add_data(nmat.data, nmat.sz, mat1.ls, mat2.data);
1953 break;
1954 case MAT_SUB:
1955 matrix_long_double_sub_data(nmat.data, nmat.sz, mat1.ls, mat2.data);
1956 break;
1957 case MAT_TIMES:
1958 matrix_long_double_mult_data(nmat.data, nmat.sz, mat1.ls, mat2.data);
1959 break;
1960 case MAT_DIV:
1961 matrix_long_double_div_data(nmat.data, nmat.sz, mat1.ls, mat2.data);
1962 break;
1963 case MAT_ZDIV:
1964 matrix_long_zdiv_data(nmat.ls, mat1.sz, mat1.ls, mat2.ls);
1965 break;
1966 default:
1967 return FALSE;
1968 }
1969 } else {
1970 return FALSE;
1971 }
1972 } else {
1973 if (mat2.type == 'i') {
1974 switch (op) {
1975 case MAT_PLUS:
1976 matrix_long_double_add_data(nmat.data, nmat.sz, mat2.ls, mat1.data);
1977 break;
1978 case MAT_SUB:
1979 matrix_long_double_rsub_data(nmat.data, nmat.sz, mat1.data, mat2.ls);
1980 break;
1981 case MAT_TIMES:
1982 matrix_long_double_mult_data(nmat.data, nmat.sz, mat2.ls, mat1.data );
1983 break;
1984 case MAT_DIV:
1985 matrix_long_double_div2_data(nmat.data, nmat.sz, mat1.data, mat2.ls);
1986 break;
1987 case MAT_ZDIV:
1988 matrix_long_double_zdiv_data(nmat.data, nmat.sz, mat2.ls, mat1.data);
1989 break;
1990 default:
1991 return FALSE;
1992 }
1993 } else if (mat2.type == 'f') {
1994 switch (op) {
1995 case MAT_PLUS:
1996 matrix_double_add_data(nmat.data, nmat.sz, mat1.data, mat2.data);
1997 break;
1998 case MAT_SUB:
1999 matrix_double_sub_data(nmat.data, nmat.sz, mat1.data, mat2.data);
2000 break;
2001 case MAT_TIMES:
2002 matrix_double_mult_data(nmat.data, nmat.sz, mat1.data, mat2.data);
2003 break;
2004 case MAT_DIV:
2005 matrix_double_div_data(nmat.data, nmat.sz, mat1.data, mat2.data);
2006 break;
2007 case MAT_ZDIV:
2008 matrix_double_zdiv_data(nmat.data, nmat.sz, mat1.data, mat2.data);
2009 break;
2010 default:
2011 return FALSE;
2012 }
2013 } else {
2014 return FALSE;
2015 }
2016 }
2017
2018 return YAP_Unify(YAP_ARG4, tf);
2019 }
2020
2021static void add_int_by_cols(int total, intptr_t nlines, YAP_Int *mat1,
2022 YAP_Int *mat2, YAP_Int *ndata) {
2023 intptr_t i, ncols = total / nlines;
2024 for (i = 0; i < total; i++) {
2025 ndata[i] = mat1[i] + mat2[i / ncols];
2026 }
2027}
2028
2029static void add_int_by_dcols(int total, intptr_t nlines, YAP_Int *mat1,
2030 double *mat2, double *ndata) {
2031 intptr_t i, ncols = total / nlines;
2032 for (i = 0; i < total; i++) {
2033 ndata[i] = mat1[i] + mat2[i / ncols];
2034 }
2035}
2036
2037static void add_double_by_cols(int total, intptr_t nlines, double *mat1,
2038 double *mat2, double *ndata) {
2039 intptr_t i;
2040 intptr_t ncols = total / nlines;
2041
2042 for (i = 0; i < total; i++) {
2043 ndata[i] = mat1[i] + mat2[i / ncols];
2044 }
2045}
2046
2047static YAP_Bool matrix_op_to_cols(void) {
2048 intptr_t *mat1, *mat2;
2049 YAP_Term top = YAP_ARG3;
2050 op_type op;
2051 YAP_Term tf;
2052
2053 if (!YAP_IsIntTerm(top)) {
2054 return FALSE;
2055 }
2056 op = YAP_IntOfTerm(top);
2057 mat1 = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
2058 if (!mat1) {
2059 /* Error */
2060 return FALSE;
2061 }
2062 mat2 = (intptr_t *)YAP_BlobOfTerm(YAP_ARG2);
2063 if (!mat2) {
2064 /* Error */
2065 return FALSE;
2066 }
2067 if (mat1[MAT_TYPE] == INT_MATRIX) {
2068 YAP_Int *data1;
2069 intptr_t dims = mat1[MAT_NDIMS];
2070 intptr_t *nmat;
2071 data1 = matrix_long_data(mat1, dims);
2072
2073 if (mat2[MAT_TYPE] == INT_MATRIX) {
2074 YAP_Int *data2 = matrix_long_data(mat2, 1);
2075 if (op == MAT_PLUS) {
2076 YAP_Int *ndata;
2077
2078 tf = new_int_matrix(dims, mat1 + MAT_DIMS, NULL);
2079 if (tf == YAP_TermNil())
2080 return FALSE;
2081 nmat = YAP_BlobOfTerm(tf);
2082 ndata = matrix_long_data(nmat, dims);
2083 add_int_by_cols(mat1[MAT_SIZE], mat1[MAT_DIMS], data1, data2, ndata);
2084 } else {
2085 return FALSE;
2086 }
2087 } else if (mat2[MAT_TYPE] == FLOAT_MATRIX) {
2088 double *data2 = matrix_double_data(mat2, 1);
2089 if (op == MAT_PLUS) {
2090 double *ndata;
2091
2092 tf = new_float_matrix(dims, mat1 + MAT_DIMS, NULL);
2093 if (tf == YAP_TermNil())
2094 return FALSE;
2095 nmat = YAP_BlobOfTerm(tf);
2096 ndata = matrix_double_data(nmat, dims);
2097 add_int_by_dcols(mat1[MAT_SIZE], mat1[MAT_DIMS], data1, data2, ndata);
2098 } else {
2099 return FALSE;
2100 }
2101 } else {
2102 return FALSE;
2103 }
2104 } else {
2105 double *data1, *data2, *ndata;
2106 intptr_t dims = mat1[MAT_NDIMS];
2107 intptr_t *nmat;
2108
2109 if (mat2[MAT_TYPE] != FLOAT_MATRIX)
2110 return FALSE;
2111 tf = new_float_matrix(dims, mat1 + MAT_DIMS, NULL);
2112 if (tf == YAP_TermNil())
2113 return FALSE;
2114 nmat = YAP_BlobOfTerm(tf);
2115 data1 = matrix_double_data(mat1, dims);
2116 data2 = matrix_double_data(mat2, 1);
2117 ndata = matrix_double_data(nmat, dims);
2118 if (op == MAT_PLUS) {
2119 add_double_by_cols(mat1[MAT_SIZE], mat1[MAT_DIMS], data1, data2, ndata);
2120 } else
2121 return FALSE;
2122 }
2123 return YAP_Unify(YAP_ARG4, tf);
2124}
2125
2126static YAP_Bool matrix_op_to_all(void) {
2127 intptr_t *mat;
2128 YAP_Term tf = 0;
2129 YAP_Term top = YAP_ARG2;
2130 op_type op;
2131 int create = FALSE;
2132
2133 if (!YAP_IsIntTerm(top)) {
2134 return FALSE;
2135 }
2136 op = YAP_IntOfTerm(top);
2137 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
2138 if (!mat) {
2139 /* Error */
2140 return FALSE;
2141 }
2142 if (YAP_IsVarTerm(YAP_ARG4)) {
2143 create = TRUE;
2144 }
2145 /* create a new array with same dimensions */
2146 if (mat[MAT_TYPE] == INT_MATRIX) {
2147 YAP_Int *data;
2148 intptr_t dims = mat[MAT_NDIMS];
2149 intptr_t *nmat;
2150 YAP_Term tnum = YAP_ARG3;
2151
2152 if (YAP_IsIntTerm(tnum)) {
2153 YAP_Int num;
2154 YAP_Int *ndata;
2155
2156 num = YAP_IntOfTerm(tnum);
2157 data = matrix_long_data(mat, dims);
2158 if (create) {
2159 tf = new_int_matrix(dims, mat + (MAT_DIMS), NULL);
2160 if (tf == YAP_TermNil())
2161 return FALSE;
2162 nmat = (intptr_t *)YAP_BlobOfTerm(tf);
2163 ndata = matrix_long_data(nmat, dims);
2164 } else {
2165 nmat = mat;
2166 ndata = data;
2167 }
2168 if (op == MAT_PLUS) {
2169 intptr_t i;
2170
2171 for (i = 0; i < mat[MAT_SIZE]; i++) {
2172 ndata[i] = data[i] + num;
2173 }
2174 } else if (op == MAT_TIMES) {
2175 intptr_t i;
2176
2177 for (i = 0; i < mat[MAT_SIZE]; i++) {
2178 ndata[i] = data[i] * num;
2179 }
2180 } else {
2181 return FALSE;
2182 }
2183 } else if (YAP_IsFloatTerm(tnum)) {
2184 double num;
2185 double *ndata;
2186
2187 num = YAP_FloatOfTerm(tnum);
2188 if (create) {
2189 tf = new_float_matrix(dims, mat + (MAT_DIMS), NULL);
2190 if (tf == YAP_TermNil())
2191 return FALSE;
2192 nmat = (intptr_t *)YAP_BlobOfTerm(tf);
2193 ndata = matrix_double_data(nmat, dims);
2194 } else {
2195 return FALSE;
2196 }
2197 data = matrix_long_data(mat, dims);
2198 if (op == MAT_PLUS) {
2199 intptr_t i;
2200
2201 for (i = 0; i < mat[MAT_SIZE]; i++) {
2202 ndata[i] = data[i] + num;
2203 }
2204 } else if (op == MAT_SUB) {
2205 intptr_t i;
2206
2207 for (i = 0; i < mat[MAT_SIZE]; i++) {
2208 ndata[i] = num - data[i];
2209 }
2210 } else if (op == MAT_TIMES) {
2211 intptr_t i;
2212
2213 for (i = 0; i < mat[MAT_SIZE]; i++) {
2214 ndata[i] = data[i] * num;
2215 }
2216 } else if (op == MAT_DIV) {
2217 intptr_t i;
2218
2219 for (i = 0; i < mat[MAT_SIZE]; i++) {
2220 ndata[i] = data[i] / num;
2221 }
2222 }
2223 } else {
2224 return FALSE;
2225 }
2226 } else {
2227 double *data, *ndata;
2228 intptr_t dims = mat[MAT_NDIMS];
2229 intptr_t *nmat;
2230 YAP_Term tnum = YAP_ARG3;
2231 double num;
2232
2233 if (YAP_IsFloatTerm(tnum)) {
2234 num = YAP_FloatOfTerm(tnum);
2235 } else if (!YAP_IntOfTerm(tnum)) {
2236 return FALSE;
2237 } else {
2238 if (!create)
2239 return FALSE;
2240 num = (double)YAP_IntOfTerm(tnum);
2241 }
2242 data = matrix_double_data(mat, dims);
2243 if (create) {
2244 tf = new_float_matrix(dims, mat + (MAT_DIMS), NULL);
2245 if (tf == YAP_TermNil())
2246 return FALSE;
2247 nmat = (intptr_t *)YAP_BlobOfTerm(tf);
2248 ndata = matrix_double_data(nmat, dims);
2249 } else {
2250 nmat = mat;
2251 ndata = data;
2252 }
2253 switch (op) {
2254 case MAT_PLUS: {
2255 intptr_t i;
2256
2257 for (i = 0; i < mat[MAT_SIZE]; i++) {
2258 ndata[i] = data[i] + num;
2259 }
2260 } break;
2261 case MAT_SUB: {
2262 intptr_t i;
2263
2264 for (i = 0; i < mat[MAT_SIZE]; i++) {
2265 ndata[i] = num - data[i];
2266 }
2267 } break;
2268 case MAT_TIMES: {
2269 intptr_t i;
2270
2271 for (i = 0; i < mat[MAT_SIZE]; i++) {
2272 ndata[i] = data[i] * num;
2273 }
2274 } break;
2275 case MAT_DIV: {
2276 intptr_t i;
2277
2278 for (i = 0; i < mat[MAT_SIZE]; i++) {
2279 ndata[i] = data[i] / num;
2280 }
2281 } break;
2282 default:
2283 return FALSE;
2284 }
2285 }
2286 if (create)
2287 return YAP_Unify(YAP_ARG4, tf);
2288 return YAP_Unify(YAP_ARG4, YAP_ARG1);
2289}
2290
2291/* given a matrix M and a set of dims, build a new reordered matrix to follow
2292 the new order
2293*/
2294static YAP_Bool matrix_transpose(void) {
2295 intptr_t ndims, i, *dims, *dimsn;
2296 intptr_t conv[MAX_DIMS], indx[MAX_DIMS], nindx[MAX_DIMS];
2297 YAP_Term tconv, tf;
2298 intptr_t *mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1), *nmat;
2299 if (!mat) {
2300 /* Error */
2301 return FALSE;
2302 }
2303 ndims = mat[MAT_NDIMS];
2304 if (mat[MAT_TYPE] == INT_MATRIX) {
2305 /* create a new matrix with the same size */
2306 tf = new_int_matrix(ndims, mat + MAT_DIMS, NULL);
2307 if (tf == YAP_TermNil())
2308 return FALSE;
2309 } else {
2310 /* create a new matrix with the same size */
2311 tf = new_float_matrix(ndims, mat + MAT_DIMS, NULL);
2312 if (tf == YAP_TermNil())
2313 return FALSE;
2314 }
2315 /* just in case there was an overflow */
2316 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
2317 nmat = (intptr_t *)YAP_BlobOfTerm(tf);
2318 dims = mat + MAT_DIMS;
2319 dimsn = nmat + MAT_DIMS;
2320 /* we now have our target matrix, let us grab our conversion matrix */
2321 tconv = YAP_ARG2;
2322 for (i = 0; i < ndims; i++) {
2323 YAP_Term th;
2324 YAP_Int j;
2325
2326 if (!YAP_IsPairTerm(tconv))
2327 return FALSE;
2328 th = YAP_HeadOfTerm(tconv);
2329 if (!YAP_IsIntTerm(th))
2330 return FALSE;
2331 conv[i] = j = YAP_IntOfTerm(th);
2332 dimsn[i] = dims[j];
2333 tconv = YAP_TailOfTerm(tconv);
2334 }
2335 /*
2336 we now got all the dimensions set up, so what we need to do
2337 next is to copy the elements to the new matrix.
2338 */
2339 if (mat[MAT_TYPE] == INT_MATRIX) {
2340 YAP_Int *data = matrix_long_data(mat, ndims);
2341 /* create a new matrix with the same size */
2342 for (i = 0; i < mat[MAT_SIZE]; i++) {
2343 YAP_Int x = data[i];
2344 int j;
2345 /*
2346 not very efficient, we could try to take advantage of the fact
2347 that we usually only change an index at a time
2348 */
2349 matrix_get_index(mat, i, indx);
2350 for (j = 0; j < ndims; j++) {
2351 nindx[j] = indx[conv[j]];
2352 }
2353 matrix_long_set(nmat, nindx, x);
2354 }
2355 } else {
2356 double *data = matrix_double_data(mat, ndims);
2357 /* create a new matrix with the same size */
2358 for (i = 0; i < mat[MAT_SIZE]; i++) {
2359 double x = data[i];
2360 long j;
2361
2362 matrix_get_index(mat, i, indx);
2363 for (j = 0; j < ndims; j++)
2364 nindx[j] = indx[conv[j]];
2365 matrix_float_set(nmat, nindx, x);
2366 }
2367 }
2368 return YAP_Unify(YAP_ARG3, tf);
2369}
2370
2371/* given a matrix M and a set of dims, fold one of the dimensions of the
2372 matrix on one of the elements
2373*/
2374static YAP_Bool matrix_select(void) {
2375 intptr_t ndims, i, j, newdims, prdim, leftarg, *dims, indx[MAX_DIMS];
2376 intptr_t nindx[MAX_DIMS];
2377 YAP_Term tpdim, tdimarg, tf;
2378 intptr_t *mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1), *nmat;
2379 if (!mat) {
2380 /* Error */
2381 return FALSE;
2382 }
2383 /* we now have our target matrix, let us grab our conversion arguments */
2384 tpdim = YAP_ARG2;
2385 ndims = mat[MAT_NDIMS];
2386 dims = mat + MAT_DIMS;
2387 if (!YAP_IsIntTerm(tpdim)) {
2388 return FALSE;
2389 }
2390 prdim = YAP_IntOfTerm(tpdim);
2391 tdimarg = YAP_ARG3;
2392 if (!YAP_IsIntTerm(tdimarg)) {
2393 return FALSE;
2394 }
2395 leftarg = YAP_IntOfTerm(tdimarg);
2396 for (i = 0, j = 0; i < ndims; i++) {
2397 if (i != prdim) {
2398 nindx[j] = dims[i];
2399 j++;
2400 }
2401 }
2402 newdims = ndims - 1;
2403 if (mat[MAT_TYPE] == INT_MATRIX) {
2404 YAP_Int *data, *ndata;
2405
2406 /* create a new matrix with the same size */
2407 tf = new_int_matrix(newdims, nindx, NULL);
2408 if (tf == YAP_TermNil())
2409 return FALSE;
2410 /* in case the matrix moved */
2411 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
2412 nmat = (intptr_t *)YAP_BlobOfTerm(tf);
2413 data = matrix_long_data(mat, ndims);
2414 ndata = matrix_long_data(nmat, newdims);
2415 /* create a new matrix with smaller size */
2416 for (i = 0; i < nmat[MAT_SIZE]; i++) {
2417 int j, k;
2418 /*
2419 not very efficient, we could try to take advantage of the fact
2420 that we usually only change an index at a time
2421 */
2422 matrix_get_index(nmat, i, indx);
2423 for (j = 0, k = 0; j < newdims; j++, k++) {
2424 if (j == prdim) {
2425 nindx[k] = leftarg;
2426 k++;
2427 }
2428 nindx[k] = indx[j];
2429 }
2430 if (k == prdim) {
2431 nindx[k] = leftarg;
2432 }
2433 ndata[i] = data[matrix_get_offset(mat, nindx)];
2434 }
2435 } else {
2436 double *data, *ndata;
2437
2438 /* create a new matrix with the same size */
2439 tf = new_float_matrix(newdims, nindx, NULL);
2440 if (tf == YAP_TermNil())
2441 return FALSE;
2442 /* in case the matrix moved */
2443 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
2444 nmat = (intptr_t *)YAP_BlobOfTerm(tf);
2445 data = matrix_double_data(mat, ndims);
2446 ndata = matrix_double_data(nmat, newdims);
2447 /* create a new matrix with the same size */
2448 for (i = 0; i < nmat[MAT_SIZE]; i++) {
2449 int j, k;
2450 /*
2451 not very efficient, we could try to take advantage of the fact
2452 that we usually only change an index at a time
2453 */
2454 matrix_get_index(nmat, i, indx);
2455 for (j = 0, k = 0; j < newdims; j++, k++) {
2456 if (j == prdim) {
2457 nindx[k] = leftarg;
2458 k++;
2459 }
2460 nindx[k] = indx[j];
2461 }
2462 if (k == prdim) {
2463 nindx[k] = leftarg;
2464 }
2465 ndata[i] = data[matrix_get_offset(mat, nindx)];
2466 }
2467 }
2468 return YAP_Unify(YAP_ARG4, tf);
2469}
2470
2471/* given a matrix M and a set of N-1 dims, get the first dimension
2472 */
2473static YAP_Bool matrix_column(void) {
2474 intptr_t size, i, ndims, newdims[1];
2475 intptr_t indx[MAX_DIMS];
2476 intptr_t *mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1), *nmat;
2477 YAP_Term tconv, tf;
2478
2479 if (!mat) {
2480 /* Error */
2481 return FALSE;
2482 }
2483 ndims = mat[MAT_NDIMS];
2484 /* we now have our target matrix, let us grab our conversion arguments */
2485 tconv = YAP_ARG2;
2486 for (i = 1; i < ndims; i++) {
2487 YAP_Term th;
2488
2489 if (!YAP_IsPairTerm(tconv))
2490 return FALSE;
2491 th = YAP_HeadOfTerm(tconv);
2492 if (!YAP_IsIntTerm(th))
2493 return FALSE;
2494 indx[i] = YAP_IntOfTerm(th);
2495 tconv = YAP_TailOfTerm(tconv);
2496 }
2497 if (tconv != YAP_TermNil())
2498 return FALSE;
2499 newdims[0] = size = mat[MAT_DIMS];
2500 if (mat[MAT_TYPE] == INT_MATRIX) {
2501 YAP_Int *data, *ndata;
2502
2503 /* create a new matrix with the same size */
2504 tf = new_int_matrix(1, newdims, NULL);
2505 if (tf == YAP_TermNil())
2506 return FALSE;
2507 /* in case the matrix moved */
2508 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
2509 nmat = (intptr_t *)YAP_BlobOfTerm(tf);
2510 data = matrix_long_data(mat, ndims);
2511 ndata = matrix_long_data(nmat, 1);
2512 /* create a new matrix with smaller size */
2513 for (i = 0; i < size; i++) {
2514 indx[0] = i;
2515 ndata[i] = data[matrix_get_offset(mat, indx)];
2516 }
2517 } else {
2518 double *data, *ndata;
2519
2520 /* create a new matrix with the same size */
2521 tf = new_float_matrix(1, newdims, NULL);
2522 if (tf == YAP_TermNil())
2523 return FALSE;
2524 /* in case the matrix moved */
2525 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
2526 nmat = (intptr_t *)YAP_BlobOfTerm(tf);
2527 data = matrix_double_data(mat, ndims);
2528 ndata = matrix_double_data(nmat, 1);
2529 /* create a new matrix with smaller size */
2530 for (i = 0; i < size; i++) {
2531 indx[0] = i;
2532 ndata[i] = data[matrix_get_offset(mat, indx)];
2533 }
2534 }
2535 return YAP_Unify(YAP_ARG3, tf);
2536}
2537
2538/* given a matrix M and a set of dims, sum out one of the dimensions
2539 */
2540static YAP_Bool matrix_sum_out(void) {
2541 intptr_t ndims, i, j, newdims, prdim;
2542 intptr_t indx[MAX_DIMS], nindx[MAX_DIMS];
2543 YAP_Term tpdim, tf;
2544 intptr_t *mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1), *nmat;
2545 if (!mat) {
2546 /* Error */
2547 return FALSE;
2548 }
2549 /* we now have our target matrix, let us grab our conversion arguments */
2550 tpdim = YAP_ARG2;
2551 ndims = mat[MAT_NDIMS];
2552 if (!YAP_IsIntTerm(tpdim)) {
2553 return FALSE;
2554 }
2555 prdim = YAP_IntOfTerm(tpdim);
2556 newdims = ndims - 1;
2557 for (i = 0, j = 0; i < ndims; i++) {
2558 if (i != prdim) {
2559 nindx[j] = (mat + MAT_DIMS)[i];
2560 j++;
2561 }
2562 }
2563 if (mat[MAT_TYPE] == INT_MATRIX) {
2564 YAP_Int *data, *ndata;
2565
2566 /* create a new matrix with the same size */
2567 tf = new_int_matrix(newdims, nindx, NULL);
2568 if (tf == YAP_TermNil())
2569 return FALSE;
2570 /* in case the matrix moved */
2571 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
2572 nmat = (intptr_t *)YAP_BlobOfTerm(tf);
2573 data = matrix_long_data(mat, ndims);
2574 ndata = matrix_long_data(nmat, newdims);
2575 /* create a new matrix with smaller size */
2576 for (i = 0; i < nmat[MAT_SIZE]; i++)
2577 ndata[i] = 0;
2578 for (i = 0; i < mat[MAT_SIZE]; i++) {
2579 int j, k;
2580 /*
2581 not very efficient, we could try to take advantage of the fact
2582 that we usually only change an index at a time
2583 */
2584 matrix_get_index(mat, i, indx);
2585 for (j = 0, k = 0; j < ndims; j++) {
2586 if (j != prdim) {
2587 nindx[k++] = indx[j];
2588 }
2589 }
2590 ndata[matrix_get_offset(nmat, nindx)] += data[i];
2591 }
2592 } else {
2593 double *data, *ndata;
2594
2595 /* create a new matrix with the same size */
2596 tf = new_float_matrix(newdims, nindx, NULL);
2597 if (tf == YAP_TermNil())
2598 return FALSE;
2599 /* in case the matrix moved */
2600 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
2601 nmat = (intptr_t *)YAP_BlobOfTerm(tf);
2602 data = matrix_double_data(mat, ndims);
2603 ndata = matrix_double_data(nmat, newdims);
2604 /* create a new matrix with smaller size */
2605 for (i = 0; i < nmat[MAT_SIZE]; i++)
2606 ndata[i] = 0.0;
2607 for (i = 0; i < mat[MAT_SIZE]; i++) {
2608 int j, k;
2609 /*
2610 not very efficient, we could try to take advantage of the fact
2611 that we usually only change an index at a time
2612 */
2613 matrix_get_index(mat, i, indx);
2614 for (j = 0, k = 0; j < ndims; j++) {
2615 if (j != prdim) {
2616 nindx[k++] = indx[j];
2617 }
2618 }
2619 ndata[matrix_get_offset(nmat, nindx)] += data[i];
2620 }
2621 }
2622 return YAP_Unify(YAP_ARG3, tf);
2623}
2624
2625/* given a matrix M and a set of dims, sum out one of the dimensions
2626 */
2627static YAP_Bool matrix_sum_out_several(void) {
2628 intptr_t ndims, i, *dims, newdims;
2629 intptr_t indx[MAX_DIMS], nindx[MAX_DIMS], conv[MAX_DIMS];
2630 YAP_Term tf, tconv;
2631 intptr_t *mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1), *nmat;
2632 if (!mat) {
2633 /* Error */
2634 return FALSE;
2635 }
2636 ndims = mat[MAT_NDIMS];
2637 dims = mat + MAT_DIMS;
2638 /* we now have our target matrix, let us grab our conversion arguments */
2639 tconv = YAP_ARG2;
2640 for (i = 0, newdims = 0; i < ndims; i++) {
2641 YAP_Term th;
2642
2643 if (!YAP_IsPairTerm(tconv))
2644 return FALSE;
2645 th = YAP_HeadOfTerm(tconv);
2646 if (!YAP_IsIntTerm(th))
2647 return FALSE;
2648 conv[i] = YAP_IntOfTerm(th);
2649 if (!conv[i]) {
2650 nindx[newdims++] = dims[i];
2651 }
2652 tconv = YAP_TailOfTerm(tconv);
2653 }
2654 if (mat[MAT_TYPE] == INT_MATRIX) {
2655 YAP_Int *data, *ndata;
2656
2657 /* create a new matrix with the same size */
2658 tf = new_int_matrix(newdims, nindx, NULL);
2659 if (tf == YAP_TermNil())
2660 return FALSE;
2661 /* in case the matrix moved */
2662 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
2663 nmat = (intptr_t *)YAP_BlobOfTerm(tf);
2664 data = matrix_long_data(mat, ndims);
2665 ndata = matrix_long_data(nmat, newdims);
2666 /* create a new matrix with smaller size */
2667 for (i = 0; i < nmat[MAT_SIZE]; i++)
2668 ndata[i] = 0;
2669 for (i = 0; i < mat[MAT_SIZE]; i++) {
2670 int j, k;
2671 /*
2672 not very efficient, we could try to take advantage of the fact
2673 that we usually only change an index at a time
2674 */
2675 matrix_get_index(mat, i, indx);
2676 for (j = 0, k = 0; j < ndims; j++) {
2677 if (!conv[j]) {
2678 nindx[k++] = indx[j];
2679 }
2680 }
2681 ndata[matrix_get_offset(nmat, nindx)] =
2682 log(exp(ndata[matrix_get_offset(nmat, nindx)]) + exp(data[i]));
2683 }
2684 } else {
2685 double *data, *ndata;
2686
2687 /* create a new matrix with the same size */
2688 tf = new_float_matrix(newdims, nindx, NULL);
2689 if (tf == YAP_TermNil())
2690 return FALSE;
2691 /* in case the matrix moved */
2692 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
2693 nmat = (intptr_t *)YAP_BlobOfTerm(tf);
2694 data = matrix_double_data(mat, ndims);
2695 ndata = matrix_double_data(nmat, newdims);
2696 /* create a new matrix with smaller size */
2697 for (i = 0; i < nmat[MAT_SIZE]; i++)
2698 ndata[i] = 0.0;
2699 for (i = 0; i < mat[MAT_SIZE]; i++) {
2700 int j, k;
2701 /*
2702 not very efficient, we could try to take advantage of the fact
2703 that we usually only change an index at a time
2704 */
2705 matrix_get_index(mat, i, indx);
2706 for (j = 0, k = 0; j < ndims; j++) {
2707 if (!conv[j]) {
2708 nindx[k++] = indx[j];
2709 }
2710 }
2711 ndata[matrix_get_offset(nmat, nindx)] =
2712 log(exp(ndata[matrix_get_offset(nmat, nindx)]) + exp(data[i]));
2713 }
2714 }
2715 return YAP_Unify(YAP_ARG3, tf);
2716}
2717
2718/* given a matrix M and a set of dims, sum out one of the dimensions
2719 */
2720static YAP_Bool matrix_sum_out_logs(void) {
2721 intptr_t ndims, i, j, *dims, newdims, prdim;
2722 intptr_t nindx[MAX_DIMS];
2723 YAP_Term tpdim, tf;
2724 intptr_t *mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1), *nmat;
2725 if (!mat) {
2726 /* Error */
2727 return FALSE;
2728 }
2729 /* we now have our target matrix, let us grab our conversion arguments */
2730 tpdim = YAP_ARG2;
2731 ndims = mat[MAT_NDIMS];
2732 dims = mat + MAT_DIMS;
2733 if (!YAP_IsIntTerm(tpdim)) {
2734 return FALSE;
2735 }
2736 prdim = YAP_IntOfTerm(tpdim);
2737 newdims = ndims - 1;
2738 for (i = 0, j = 0; i < ndims; i++) {
2739 if (i != prdim) {
2740 nindx[j] = dims[i];
2741 j++;
2742 }
2743 }
2744 if (mat[MAT_TYPE] == INT_MATRIX) {
2745 YAP_Int *data, *ndata;
2746 int d = 1, j = 0, dd = 1;
2747
2748 /* create a new matrix with the same size */
2749 tf = new_int_matrix(newdims, nindx, NULL);
2750 if (tf == YAP_TermNil())
2751 return FALSE;
2752 /* in case the matrix moved */
2753 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
2754 nmat = (intptr_t *)YAP_BlobOfTerm(tf);
2755 data = matrix_long_data(mat, ndims);
2756 ndata = matrix_long_data(nmat, newdims);
2757 while (j < prdim) {
2758 d = d * dims[j];
2759 j++;
2760 }
2761 dd = d * dims[prdim];
2762 for (i = 0; i < nmat[MAT_SIZE]; i++) {
2763 int j = i % d + (i / dd) * d;
2764 ndata[j] = exp(data[i]);
2765 }
2766 for (; i < mat[MAT_SIZE]; i++) {
2767 int j = i % d + (i / dd) * d;
2768 ndata[j] += exp(data[i]);
2769 }
2770 for (i = 0; i < nmat[MAT_SIZE]; i++) {
2771 ndata[i] = log(ndata[i]);
2772 }
2773 } else {
2774 double *data, *ndata;
2775 int d = 1, j = 0, dd = 1;
2776
2777 /* create a new matrix with the same size */
2778 tf = new_float_matrix(newdims, nindx, NULL);
2779 if (tf == YAP_TermNil())
2780 return FALSE;
2781 /* in case the matrix moved */
2782 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
2783 nmat = (intptr_t *)YAP_BlobOfTerm(tf);
2784 data = matrix_double_data(mat, ndims);
2785 ndata = matrix_double_data(nmat, newdims);
2786
2787 j = ndims - 1;
2788 while (j > prdim) {
2789 d = d * dims[j];
2790 j--;
2791 }
2792 dd = d * dims[prdim];
2793 memset(ndata, 0, sizeof(double) * nmat[MAT_SIZE]);
2794 for (i = 0; i < mat[MAT_SIZE]; i++) {
2795 YAP_Int k = i % d + (i / dd) * d;
2796 ndata[k] += exp(data[i]);
2797 }
2798 for (i = 0; i < nmat[MAT_SIZE]; i++) {
2799 ndata[i] = log(ndata[i]);
2800 }
2801 }
2802 return YAP_Unify(YAP_ARG3, tf);
2803}
2804
2805/* given a matrix M and a set of dims, sum out one of the dimensions
2806 */
2807static YAP_Bool matrix_sum_out_logs_several(void) {
2808 intptr_t ndims, i, *dims, newdims;
2809 intptr_t indx[MAX_DIMS], nindx[MAX_DIMS], conv[MAX_DIMS];
2810 YAP_Term tf, tconv;
2811 intptr_t *mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1), *nmat;
2812
2813 if (!mat) {
2814 /* Error */
2815 return FALSE;
2816 }
2817 ndims = mat[MAT_NDIMS];
2818 dims = mat + MAT_DIMS;
2819 /* we now have our target matrix, let us grab our conversion arguments */
2820 tconv = YAP_ARG2;
2821 for (i = 0, newdims = 0; i < ndims; i++) {
2822 YAP_Term th;
2823
2824 if (!YAP_IsPairTerm(tconv))
2825 return FALSE;
2826 th = YAP_HeadOfTerm(tconv);
2827 if (!YAP_IsIntTerm(th))
2828 return FALSE;
2829 conv[i] = YAP_IntOfTerm(th);
2830 if (!conv[i]) {
2831 nindx[newdims++] = dims[i];
2832 }
2833 tconv = YAP_TailOfTerm(tconv);
2834 }
2835 if (mat[MAT_TYPE] == INT_MATRIX) {
2836 YAP_Int *data, *ndata;
2837
2838 /* create a new matrix with the same size */
2839 tf = new_int_matrix(newdims, nindx, NULL);
2840 if (tf == YAP_TermNil())
2841 return FALSE;
2842 /* in case the matrix moved */
2843 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
2844 nmat = (intptr_t *)YAP_BlobOfTerm(tf);
2845 data = matrix_long_data(mat, ndims);
2846 ndata = matrix_long_data(nmat, newdims);
2847 /* create a new matrix with smaller size */
2848 for (i = 0; i < nmat[MAT_SIZE]; i++)
2849 ndata[i] = 0;
2850 for (i = 0; i < mat[MAT_SIZE]; i++) {
2851 int j, k;
2852 /*
2853 not very efficient, we could try to take advantage of the fact
2854 that we usually only change an index at a time
2855 */
2856 matrix_get_index(mat, i, indx);
2857 for (j = 0, k = 0; j < ndims; j++) {
2858 if (!conv[j]) {
2859 nindx[k++] = indx[j];
2860 }
2861 }
2862 ndata[matrix_get_offset(nmat, nindx)] += exp(data[i]);
2863 }
2864 } else {
2865 double *data, *ndata;
2866
2867 /* create a new matrix with the same size */
2868 tf = new_float_matrix(newdims, nindx, NULL);
2869 if (tf == YAP_TermNil())
2870 return FALSE;
2871 /* in case the matrix moved */
2872 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
2873 nmat = (intptr_t *)YAP_BlobOfTerm(tf);
2874 data = matrix_double_data(mat, ndims);
2875 ndata = matrix_double_data(nmat, newdims);
2876 /* create a new matrix with smaller size */
2877 for (i = 0; i < nmat[MAT_SIZE]; i++)
2878 ndata[i] = 0.0;
2879 for (i = 0; i < mat[MAT_SIZE]; i++) {
2880 int j, k;
2881 /*
2882 not very efficient, we could try to take advantage of the fact
2883 that we usually only change an index at a time
2884 */
2885 matrix_get_index(mat, i, indx);
2886 for (j = 0, k = 0; j < ndims; j++) {
2887 if (!conv[j]) {
2888 nindx[k++] = indx[j];
2889 }
2890 }
2891 ndata[matrix_get_offset(nmat, nindx)] += exp(data[i]);
2892 }
2893 for (i = 0; i < nmat[MAT_SIZE]; i++) {
2894 ndata[i] = log(ndata[i]);
2895 }
2896 }
2897 return YAP_Unify(YAP_ARG3, tf);
2898}
2899
2900/* given a matrix M and a set of dims, build a matrix to follow
2901 the new order
2902*/
2903static YAP_Bool matrix_expand(void) {
2904 intptr_t ndims, i, *dims, newdims = 0, olddims = 0;
2905 intptr_t new[MAX_DIMS], indx[MAX_DIMS], nindx[MAX_DIMS];
2906 YAP_Term tconv, tf;
2907 intptr_t *mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1), *nmat;
2908 if (!mat) {
2909 /* Error */
2910 return FALSE;
2911 }
2912 /* we now have our target matrix, let us grab our conversion matrix */
2913 tconv = YAP_ARG2;
2914 ndims = mat[MAT_NDIMS];
2915 dims = mat + MAT_DIMS;
2916 for (i = 0; i < MAX_DIMS; i++) {
2917 YAP_Term th;
2918 YAP_Int j;
2919
2920 if (!YAP_IsPairTerm(tconv)) {
2921 if (tconv != YAP_TermNil())
2922 return FALSE;
2923 break;
2924 }
2925 th = YAP_HeadOfTerm(tconv);
2926 if (!YAP_IsIntTerm(th))
2927 return FALSE;
2928 newdims++;
2929 j = YAP_IntOfTerm(th);
2930 if (j == 0) {
2931 new[i] = 0;
2932 nindx[i] = dims[olddims];
2933 olddims++;
2934 } else {
2935 new[i] = 1;
2936 nindx[i] = j;
2937 }
2938 tconv = YAP_TailOfTerm(tconv);
2939 }
2940 if (olddims != ndims)
2941 return FALSE;
2942 if (mat[MAT_TYPE] == INT_MATRIX) {
2943 YAP_Int *data, *ndata;
2944
2945 /* create a new matrix with the same size */
2946 tf = new_int_matrix(newdims, nindx, NULL);
2947 if (tf == YAP_TermNil())
2948 return FALSE;
2949 /* in case the matrix moved */
2950 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
2951 nmat = (intptr_t *)YAP_BlobOfTerm(tf);
2952 data = matrix_long_data(mat, ndims);
2953 ndata = matrix_long_data(nmat, newdims);
2954 /* create a new matrix with the same size */
2955 for (i = 0; i < nmat[MAT_SIZE]; i++) {
2956 int j, k = 0;
2957 /*
2958 not very efficient, we could try to take advantage of the fact
2959 that we usually only change an index at a time
2960 */
2961 matrix_get_index(nmat, i, indx);
2962 for (j = 0; j < newdims; j++) {
2963 if (!new[j])
2964 nindx[k++] = indx[j];
2965 }
2966 ndata[i] = data[matrix_get_offset(mat, nindx)];
2967 }
2968 } else {
2969 double *data, *ndata;
2970
2971 /* create a new matrix with the same size */
2972 tf = new_float_matrix(newdims, nindx, NULL);
2973 if (tf == YAP_TermNil())
2974 return FALSE;
2975 /* in case the matrix moved */
2976 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
2977 nmat = (intptr_t *)YAP_BlobOfTerm(tf);
2978 data = matrix_double_data(mat, ndims);
2979 ndata = matrix_double_data(nmat, newdims);
2980 /* create a new matrix with the same size */
2981 for (i = 0; i < newdims; i++)
2982 indx[i] = 0;
2983 for (i = 0; i < nmat[MAT_SIZE]; i++) {
2984 int j, k = 0;
2985 /*
2986 not very efficient, we could try to take advantage of the fact
2987 that we usually only change an index at a time
2988 */
2989 for (j = 0; j < newdims; j++) {
2990 if (!new[j])
2991 nindx[k++] = indx[j];
2992 }
2993 ndata[i] = data[matrix_get_offset(mat, nindx)];
2994 matrix_next_index(nmat + MAT_DIMS, newdims, indx);
2995 }
2996 }
2997 return YAP_Unify(YAP_ARG3, tf);
2998}
2999
3000/* given a matrix M and a set of dims, build contract a matrix to follow
3001 the new order
3002*/
3003static YAP_Bool matrix_set_all_that_disagree(void) {
3004 intptr_t ndims, i, *dims;
3005 intptr_t indx[MAX_DIMS];
3006 YAP_Term tf;
3007 intptr_t *mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1), *nmat;
3008 int dim = YAP_IntOfTerm(YAP_ARG2);
3009 int pos = YAP_IntOfTerm(YAP_ARG3);
3010
3011 if (!mat) {
3012 /* Error */
3013 return FALSE;
3014 }
3015 ndims = mat[MAT_NDIMS];
3016 dims = mat + MAT_DIMS;
3017 if (mat[MAT_TYPE] == INT_MATRIX) {
3018 YAP_Int *data, *ndata, val;
3019
3020 /* create a new matrix with the same size */
3021 tf = new_int_matrix(ndims, dims, NULL);
3022 if (tf == YAP_TermNil())
3023 return FALSE;
3024 /* in case the matrix moved */
3025 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
3026 nmat = (intptr_t *)YAP_BlobOfTerm(tf);
3027 data = matrix_long_data(mat, ndims);
3028 ndata = matrix_long_data(nmat, ndims);
3029 if (!YAP_IsIntTerm(YAP_ARG4))
3030 return FALSE;
3031 val = YAP_IntOfTerm(YAP_ARG4);
3032 /* create a new matrix with the same size */
3033 for (i = 0; i < nmat[MAT_SIZE]; i++) {
3034
3035 /*
3036 not very efficient, we could try to take advantage of the fact
3037 that we usually only change an index at a time
3038 */
3039 matrix_get_index(mat, i, indx);
3040 if (indx[dim] != pos)
3041 ndata[i] = val;
3042 else
3043 ndata[i] = data[i];
3044 }
3045 } else {
3046 double *data, *ndata, val;
3047
3048 /* create a new matrix with the same size */
3049 tf = new_float_matrix(ndims, dims, NULL);
3050 if (tf == YAP_TermNil())
3051 return FALSE;
3052 /* in case the matrix moved */
3053 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
3054 nmat = (intptr_t *)YAP_BlobOfTerm(tf);
3055 data = matrix_double_data(mat, ndims);
3056 ndata = matrix_double_data(nmat, ndims);
3057 if (YAP_IsFloatTerm(YAP_ARG4))
3058 val = YAP_FloatOfTerm(YAP_ARG4);
3059 else if (YAP_IsIntTerm(YAP_ARG4))
3060 val = YAP_IntOfTerm(YAP_ARG4);
3061 else
3062 return FALSE;
3063 /* create a new matrix with the same size */
3064 for (i = 0; i < nmat[MAT_SIZE]; i++) {
3065
3066 /*
3067 not very efficient, we could try to take advantage of the fact
3068 that we usually only change an index at a time
3069 */
3070 matrix_get_index(mat, i, indx);
3071 if (indx[dim] != pos)
3072 ndata[i] = val;
3073 else
3074 ndata[i] = data[i];
3075 }
3076 }
3077 return YAP_Unify(YAP_ARG5, tf);
3078}
3079
3080static YAP_Bool matrix_m(void) {
3081 intptr_t ndims, i, size;
3082 YAP_Term tm, *tp;
3083 intptr_t *mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
3084
3085 if (!mat) {
3086 return YAP_Unify(YAP_ARG1, YAP_ARG2);
3087 }
3088 ndims = mat[MAT_NDIMS];
3089 size = mat[MAT_SIZE];
3090 tm = YAP_MkNewApplTerm(MFunctorM, 5);
3091 tp = YAP_ArgsOfTerm(tm);
3092 tp[0] = mk_int_list(ndims, mat + MAT_DIMS);
3093 tp[1] = YAP_MkIntTerm(ndims);
3094 tp[2] = YAP_MkIntTerm(size);
3095 tp[3] = mk_rep_int_list(ndims, mat[MAT_BASE]);
3096 tp[4] = YAP_MkNewApplTerm(YAP_MkFunctor(MAtomC, size), size);
3097 tp = YAP_ArgsOfTerm(tp[3]);
3098 if (mat[MAT_TYPE] == INT_MATRIX) {
3099 YAP_Int *data;
3100
3101 /* in case the matrix moved */
3102 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
3103 data = matrix_long_data(mat, ndims);
3104 for (i = 0; i < mat[MAT_SIZE]; i++) {
3105 tp[i] = YAP_MkIntTerm(data[i]);
3106 }
3107 } else {
3108 double *data;
3109
3110 /* in case the matrix moved */
3111 mat = (intptr_t *)YAP_BlobOfTerm(YAP_ARG1);
3112 data = matrix_double_data(mat, ndims);
3113 for (i = 0; i < mat[MAT_SIZE]; i++) {
3114 tp[i] = YAP_MkFloatTerm(data[i]);
3115 }
3116 }
3117 return YAP_Unify(YAP_ARG2, tm);
3118}
3119
3120
3121X_API void init_matrix(void);
3122
3123X_API void init_matrix(void) {
3124 // useful constants
3125 MAtomC = YAP_LookupAtom("c");
3126 MFunctorM = YAP_MkFunctor(YAP_LookupAtom("$matrix"), 5);
3127 MFunctorFloats = YAP_MkFunctor(YAP_LookupAtom("floats"), 2);
3128 MTermTrue = YAP_MkAtomTerm(YAP_LookupAtom("true"));
3129 MTermFail = YAP_MkAtomTerm(YAP_LookupAtom("fail"));
3130 MTermFalse = YAP_MkAtomTerm(YAP_LookupAtom("false"));
3131
3132 // new matrix
3133 YAP_UserCPredicate("new_ints_matrix", new_ints_matrix, 4);
3134 YAP_UserCPredicate("new_ints_matrix_set", new_ints_matrix_set, 4);
3135 YAP_UserCPredicate("new_floats_matrix", new_floats_matrix, 4);
3136 YAP_UserCPredicate("new_floats_matrix_set", new_floats_matrix_set, 4);
3137
3138 // matrix op constant
3139 YAP_UserCPredicate("matrix_set_one", matrix_set_one, 3);
3140 YAP_UserCPredicate("matrix_set_all", matrix_set_all, 2);
3141 YAP_UserCPredicate("matrix_get_one", matrix_get_one, 3);
3142 //YAP_UserCPredicate("matrix_get_all", matrix_get_all, 3);
3143 YAP_UserCPredicate("matrix_add_to_all" , matrix_add_to_all, 2);
3144 YAP_UserCPredicate("matrix_inc", matrix_inc, 2);
3145 YAP_UserCPredicate("matrix_dec", matrix_dec, 2);
3146 YAP_UserCPredicate("matrix_inc", matrix_inc3, 3);
3147 YAP_UserCPredicate("matrix_dec", matrix_dec3, 3);
3148 // matrix aggregates
3149 YAP_UserCPredicate("matrix_max", matrix_max, 2);
3150 YAP_UserCPredicate("matrix_maxarg", matrix_maxarg, 2);
3151 YAP_UserCPredicate("matrix_min", matrix_min, 2);
3152 YAP_UserCPredicate("matrix_minarg", matrix_minarg, 2);
3153 YAP_UserCPredicate("matrix_to_list", matrix_to_list, 2);
3154 YAP_UserCPredicate("matrix_set_base", matrix_set_base, 2);
3155 YAP_UserCPredicate("matrix_dims", matrix_dims, 2);
3156 YAP_UserCPredicate("matrix_dims", matrix_dims3, 3);
3157 YAP_UserCPredicate("matrix_ndims", matrix_ndims, 2);
3158 YAP_UserCPredicate("matrix_size", matrix_size, 2);
3159 YAP_UserCPredicate("matrix_type_as_number", matrix_type, 2);
3160 YAP_UserCPredicate("matrix_arg_to_offset", matrix_arg_to_offset, 3);
3161 YAP_UserCPredicate("matrix_offset_to_arg", matrix_offset_to_arg, 3);
3162 YAP_UserCPredicate("matrix_sum", matrix_sum, 2);
3163 YAP_UserCPredicate("matrix_shuffle", matrix_transpose, 3);
3164 YAP_UserCPredicate("matrix_expand", matrix_expand, 3);
3165 YAP_UserCPredicate("matrix_select", matrix_select, 4);
3166 YAP_UserCPredicate("matrix_column", matrix_column, 3);
3167 YAP_UserCPredicate("matrix_to_logs", matrix_log_all, 1);
3168 YAP_UserCPredicate("matrix_to_exps", matrix_exp_all, 1);
3169 YAP_UserCPredicate("matrix_to_exps2", matrix_exp2_all, 1);
3170 YAP_UserCPredicate("matrix_to_logs", matrix_log_all2, 2);
3171 YAP_UserCPredicate("matrix_to_exps", matrix_exp_all2, 2);
3172 YAP_UserCPredicate("matrix_sum_out", matrix_sum_out, 3);
3173 YAP_UserCPredicate("matrix_sum_out_several", matrix_sum_out_several, 3);
3174 YAP_UserCPredicate("matrix_sum_logs_out", matrix_sum_out_logs, 3);
3175 YAP_UserCPredicate("matrix_sum_logs_out_several", matrix_sum_out_logs_several,
3176 3);
3177 YAP_UserCPredicate("matrix_set_all_that_disagree",
3178 matrix_set_all_that_disagree, 5);
3179 YAP_UserCPredicate("do_matrix_op", matrix_op, 4);
3180 YAP_UserCPredicate("do_matrix_agg_lines", matrix_agg_lines, 3);
3181 YAP_UserCPredicate("do_matrix_agg_cols", matrix_agg_cols, 3);
3182 YAP_UserCPredicate("do_matrix_op_to_all", matrix_op_to_all, 4);
3183 YAP_UserCPredicate("do_matrix_op_to_lines", matrix_op_to_lines, 4);
3184 YAP_UserCPredicate("do_matrix_op_to_cols", matrix_op_to_cols, 4);
3185 YAP_UserCPredicate("matrix_m", matrix_m, 2);
3186 YAP_UserCPredicate("is_matrix", is_matrix, 1);
3187}
3188
3189#ifdef _WIN32
3190
3191int WINAPI win_matrixs(HANDLE, DWORD, LPVOID);
3192
3193int WINAPI win_matrixs(HANDLE hinst, DWORD reason, LPVOID reserved) {
3194 switch (reason) {
3195 case DLL_PROCESS_ATTACH:
3196 break;
3197 case DLL_PROCESS_DETACH:
3198 break;
3199 case DLL_THREAD_ATTACH:
3200 break;
3201 case DLL_THREAD_DETACH:
3202 break;
3203 }
3204 return 1;
3205}
3206#endif
Definition: Yatom.h:689
A matrix.
Definition: matrix.c:68