YAP 7.1.0
matrix.yap
Go to the documentation of this file.
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-2006 *
8* *
9**************************************************************************
10* *
11* File: matrix.yap *
12* Last rev: *
13* mods: *
14* comments: Have some fun with blobs *
15* *
16*************************************************************************/
17/**
18 * @file matrix.yap
19 * @author VITOR SANTOS COSTA <vsc@VITORs-MBP.lan>
20 * @date Tue Nov 17 22:53:40 2015
21 *
22 * @brief Vector, Array and Matrix library
23 *
24 *
25*/
26
27
28:- module( matrix,
29 [(<==)/2, op(800, xfx, <==),
30 (+=)/2, op(800, xfx, +=),
31 (-=)/2, op(800, xfx, -=),
32 op(950,fy,:=),
33 op(950,yfx,:=),
34% op(950,fx,<-),
35% op(950,yfx,<-),
36 op(700, xfx, in),
37 op(700, xfx, within),
38 op(700, xfx, ins),
39 op(450, xfx, '..'), % should bind more tightly than \/
40 op(790, fx, matrix),
41 op(790, fx, array),
42 op(780, xfx, of),
43 is_matrix/1,
47 matrix_dims/2,
48 matrix_ndims/2,
52 matrix_to_lists/2,
54 matrix_set/2,
55 matrix_set/3,
56 matrix_set_all/2,
57 matrix_add/3,
58 matrix_inc/2,
60 matrix_mult/2,
61 matrix_inc/3,
65 matrix_max/2,
66 matrix_maxarg/2,
67 matrix_min/2,
68 matrix_minarg/2,
70 matrix_sum_out/3,
71 matrix_sum_out_several/3,
72 matrix_sum_logs_out/3,
73 matrix_sum_logs_out_several/3,
74 matrix_add_to_all/2,
77 matrix_to_logs/1,
78 matrix_to_exps/1,
79 matrix_to_exps2/1,
80 matrix_to_logs/2,
81 matrix_to_exps/2,
88 matrix_set_all_that_disagree/5,
89 matrix_expand/3,
92 matrix_get/2,
93 matrix_set/2,
94 foreach/2,
95 foreach/4,
96 op(50, yf, []),
97 op(50, yf, '()'),
98 op(100, xfy, '.'),
99 op(100, fy, '.')
100 ]).
101
102
103:- load_foreign_files([matrix], [], init_matrix).
104
105:- multifile rhs_opaque/1, array_extension/2.
106
107/** @defgroup matrix Matrix Library
108@ingroup YAPLibrary
109@{
110
111This package provides a fast implementation of multi-dimensional
112matrices of integers and floats. In contrast to dynamic arrays, these
113matrices are multi-dimensional and compact. In contrast to static
114arrays. these arrays are allocated in the stack, and disppear in
115backtracking. Matrices are available by loading the library
116`library(matrix)`. They are multimensional objects of type:
117
118 + <tt>terms</tt>: Prolog terms
119
120+ <tt>ints</tt>: bounded integers, represented as an opaque term. The
121maximum integer depends on hardware, but should be obtained from the
122natural size of the machine.
123
124+ <tt>floats</tt>: floating-point numbers, represented as an opaque term.
125
126
127The matrix library also supports a B-Prolog/ECliPSe inspired `foreach`iterator to iterate over
128elements of a matrix:
129
130+ Copy a vector, element by element.
131
132```
133 foreach(I in 0..N1, X[I] <== Y[I])
134```
135
136+ The lower-triangular matrix _Z_ is the difference between the
137lower-triangular and upper-triangular parts of _X_.
138
139```
140 foreach([I in 0..N1, J in I..N1], Z[I,J] <== X[I,J] - X[I,J])
141```
142
143+ Add all elements of a matrix by using _Sum␇_ as an accumulator.
144
145```
146 foreach([I in 0..N1, J in 0..N1], plus(X[I,J]), 0, Sum)
147```
148
149 Notice that the library does not support all known matrix operations. Please
150contact the YAP maintainers if you require extra functionality.
151
152
153
154
155*/
156
157
158/*
159 A matrix is an object with integer or floating point numbers. A
160 matrix may have a number of dimensions. These data structures
161 implement a number of routine manipulation procedures.
162
163 '$matrix'(Type,D1,D2,...,Dn,data(......))
164
165 Type = int, float
166
167 Operations:
168
169typedef enum {
170 MAT_SUM=0,
171 MAT_SUB=1,
172 MAT_TIMES=2,
173 MAT_DIV=3,
174 MAT_IDIV=4,
175 MAT_ZDIV=5
176} op_type;
177
178 */
179
180/** @pred matrix_agg_cols(+ _Matrix_,+Operator,+ _Aggregate_)
181
182
183
184If _Matrix_ is a n-dimensional matrix, unify _Aggregate_ with
185the one dimensional matrix where each element is obtained by adding all
186Matrix elements with same first index. Currently, only addition is supported.
187
188
189*/
190/** @pred matrix_agg_lines(+ _Matrix_,+Operator,+ _Aggregate_)s
191
192
193
194If _Matrix_ is a n-dimensional matrix, unify _Aggregate_ with
195the n-1 dimensional matrix where each element is obtained by adding all
196_Matrix_ elements with same last n-1 index. Currently, only addition is supported.
197
198
199*/
200/** @pred matrix_arg_to_offset(+ _Matrix_,+ _Position_,- _Offset_)
201
202
203
204Given matrix _Matrix_ return what is the numerical _Offset_ of
205the element at _Position_.
206
207
208*/
209/** @pred matrix_column(+ _Matrix_,+ _Column_,- _NewMatrix)_
210
211
212
213Select from _Matrix_ the column matching _Column_ as new matrix _NewMatrix_. _Column_ must have one less dimension than the original matrix.
214
215
216
217 */
218/** @pred matrix_dec(+ _Matrix_,+ _Position_)
219
220
221
222Decrement the element of _Matrix_ at position _Position_.
223
224
225*/
226/** @pred matrix_dec(+ _Matrix_,+ _Position_,- _Element_)
227
228
229Decrement the element of _Matrix_ at position _Position_ and
230unify with _Element_.
231
232
233*/
234/** @pred matrix_new(+ _Type_,+ _Dims_,+ _List_,- _Matrix_)
235
236
237Create a new matrix _Matrix_ of type _Type_, which may be one of
238`ints` or `floats`, with dimensions _Dims_, and
239initialized from list _List_.
240
241
242*/
243matrix_new(ints,Dims,Source,O) :-
244 new_matrix_ints(Dims,Source,O).
245matrix_new(floats,Dims,Source,O) :-
246 new_matrix_floats(Dims,Source,O).
247/** @pred matrix_new(+ _Type_,+ _Dims_,- _Matrix_)
248
249
250
251Create a new matrix _Matrix_ of type _Type_, which may be one of
252`ints` or `floats`, and with a list of dimensions _Dims_.
253The matrix will be initialized to zeros.
254
255```
256?- matrix_new(ints,[2,3],Matrix).
257
258Matrix = {..}
259```
260Notice that currently YAP will always write a matrix of numbers as `{..}`.
261
262
263*/
264matrix_new(ints,Dims,O) :-
265 new_matrix_ints_set(Dims,0,O).
266matrix_new(floats,Dims,O) :-
267 new_matrix_floats(Dims,0,O).
268/** @pred matrix_new_set(? _Dims_,+ _OldMatrix_,+ _Value_,- _NewMatrix_)
269
270
271
272Create a new matrix _NewMatrix_ of type _Type_, with dimensions
273 _Dims_. The elements of _NewMatrix_ are set to _Value_.
274
275
276*/
277matrix_new_set(ints,Dims,C.O) :-
278 new_matrix_ints_set(Dims,C,O).
279matrix_new_set(floats,Dims,C,O) :-
280 new_matrix_floats(Dims,C,O).
281/** @pred matrix_offset_to_arg(+ _Matrix_,- _Offset_,+ _Position_)
282
283
284
285Given a position _Position _ for matrix _Matrix_ return the
286corresponding numerical _Offset_ from the beginning of the matrix.
287
288
289*/
290/** @pred matrix_op(+ _Matrix1_,+ _Matrix2_,+ _Op_,- _Result_)
291
292
293
294 _Result_ is the result of applying _Op_ to matrix _Matrix1_
295and _Matrix2_. Currently, only addition (`+`) is supported.
296
297
298*/
299/** @pred matrix_op_to_all(+ _Matrix1_,+ _Op_,+ _Operand_,- _Result_)
300
301
302
303 _Result_ is the result of applying _Op_ to all elements of
304 _Matrix1_, with _Operand_ as the second argument. Currently,
305only addition (`+`), multiplication (`\*`), and division
306(`/`) are supported.
307
308
309*/
310/** @pred matrix_op_to_cols(+ _Matrix1_,+ _Cols_,+ _Op_,- _Result_)
311
312
313
314 _Result_ is the result of applying _Op_ to all elements of
315 _Matrix1_, with the corresponding element in _Cols_ as the
316second argument. Currently, only addition (`+`) is
317supported. Notice that _Cols_ will have n-1 dimensions.
318
319
320*/
321/** @pred matrix_op_to_lines(+ _Matrix1_,+ _Lines_,+ _Op_,- _Result_)
322
323
324
325 _Result_ is the result of applying _Op_ to all elements of
326 _Matrix1_, with the corresponding element in _Lines_ as the
327second argument. Currently, only division (`/`) is supported.
328
329
330*/
331/** @pred matrix_select(+ _Matrix_,+ _Dimension_,+ _Index_,- _New_)
332
333
334
335Select from _Matrix_ the elements who have _Index_ at
336 _Dimension_.
337
338
339*/
340/** @pred matrix_shuffle(+ _Matrix_,+ _NewOrder_,- _Shuffle_)
341
342
343
344Shuffle the dimensions of matrix _Matrix_ according to
345 _NewOrder_. The list _NewOrder_ must have all the dimensions of
346 _Matrix_, starting from 0.
347
348
349*/
350/** @pred matrix_transpose(+ _Matrix_,- _Transpose_)
351
352
353
354Transpose matrix _Matrix_ to _Transpose_. Equivalent to:
355
356```
357matrix_transpose(Matrix,Transpose) :-
358 matrix_shuffle(Matrix,[1,0],Transpose).
359```
360
361
362*/
363/** @pred matrix_type(+ _Matrix_,- _Type_)
364
365
366
367Unify _NElems_ with the type of the elements in _Matrix_.
368
369
370*/
371
372
373
374:- load_foreign_files([matrix], [], init_matrix).
375
376:- multifile rhs_opaque/1, array_extension/2.
377
378
379:- meta_predicate foreach(+,0), foreach(+,2, +, -).
380:- reexport(library(maplist)).
381:- use_module(library(mapargs)).
382:- use_module(library(lists)).
383
384%term_expansion((M[I] := P), [(eval(M.[I],V) :- is_matrix(M), matrix:matrix_get(M,[I],V))]) :-
385% !.
386%
387%term_expansion((M.Op() := P), (eval(M.Op(),V) :- is_matrix(M), matrix:op(M,Op,V))] :-
388%
389% abstract_mat(M) :- is_matrix(M), !.
390
391%% @pred LHS ==> RHS
392%%
393%% Matrix operation
394%%
395%% 1 Initialization:
396
397%% - One can use use old array routines (check static_array/3) for
398%% offline arrays/
399%%
400%% 1. `Atom <== [1000,1001,1002]`
401%% 1. `Atom <== matrix[1000] of int`
402%% 2. `Atom <== matrix[333] of 0`
403%%
404%% The opaque family of routines allocates on stack:
405%% 1. `Var <== [[1000],[1001],[1002]]`
406%% 1. `Var <== matrix[1000] of term`
407%% 2. `Var <== matrix[333,2] of 3.1415`
408%%
409%% YAP also supports foreign matrices, as
410/** @pred ?_LHS_ <== ?_RHS_ is semidet
411
412
413General matrix assignment operation. It evaluates the right-hand side
414 according to the
415left-hand side and to the matrix:
416
417+ if _LHS_ is part of an integer or floating-point matrix,
418perform non-backtrackable assignment.
419+ other unify left-hand side and right-hand size.
420
421Matrix elements can be accessed through the `matrix_get/2` predicate
422or through an <tt>R</tt>-inspired access notation (that uses the ciao
423style extension to `[]`). Examples include:
424
425
426 + Access the second row, third column of matrix <tt>X</tt>. Indices start from
427`0`,
428```
429 _E_ <== _X_[2,3]
430```
431
432+ Access all the second row, the output is a list ofe elements.
433```
434 _L_ <== _X_[2,_]
435```
436
437+ Access all the second, thrd and fourth rows, the output is a list of elements.
438```
439 _L_ <== _X_[2..4,_]
440```
441
442+ Access all the fifth, sixth and eight rows, the output is a list of elements.
443```
444 _L_ <== _X_[2..4+3,_]
445```
446
447The right-hand side supports the following operators:
448
449+ `[]/2`
450
451 written as _M_[ _Offset_]: obtain an element or list of elements
452of matrix _M_ at offset _Offset_.
453
454+ `../2`
455
456 _I_.. _J_ generates a list with all integers from _I_ to
457 _J_, included.
458
459+ `+/2`
460
461 add two numbers, add two matrices element-by-element, or add a number to
462all elements of a matrix or list.
463
464+ `-/2 `
465
466 subtract two numbers, subtract two matrices or lists element-by-element, or subtract a number from
467all elements of a matrix or list
468
469+ `* /2`
470
471 multiply two numbers, multiply two matrices or lists
472 element-by-element, or multiply a number from all elements of a
473 matrix or list
474
475 + `log/1`
476
477 natural logarithm of a number, matrix or list
478
479+ `exp/1 `
480
481 natural exponentiation of a number, matrix or list
482
483
484+ _X_ <== array[ _Dim1_,..., _Dimn_] of _Objects_
485 The of/2 operator can be used to create a new array of
486 _Objects_. The objects supported are:
487
488 + `Unbound Variable`
489 create an array of free variables
490 + `ints`
491 create an array of integers
492 + `floats`
493 create an array of floating-point numbers
494 + `_I_: _J_`
495 create an array with integers from _I_ to _J_
496 + `[..]`
497 create an array from the values in a list
498
499The dimensions can be given as an integer, and the matrix will be
500indexed `C`-style from `0..( _Max_-1)`, or can be given
501as an interval ` _Base_.. _Limit_`. In the latter case,
502matrices of integers and of floating-point numbers should have the same
503 _Base_ on every dimension.
504
505*/
506( LHS <== RHS ) :-
507 kindofm(RHS),
508 (atom(LHS) -> V= LHS ; atom),
509 new(RHS,V),
510 new,
511 V = LHS.
512( LHS <== RHS ) :-
513 eval(RHS,V),
514 matrix_set(LHS,V),
515 matrix_set.
516
517( LHS += RHS ) :-
518 eval(RHS,V),
519 eval(LHS+V, V2),
520 matrix_set(LHS,V2),
521 matrix_set.
522
523( LHS -= RHS ) :-
524 eval(RHS,V),
525 eval(LHS-V, V2),
526 matrix_set(LHS,V2),
527 matrix_set.
528
529
530kindofm(matrix(_)) :- kindofm.
531
532
533eval(M[I],Exp) :- eval, matrix_get(M,[I],Exp).
534
535
536eval(Matrix.dims(), V) :- eval,
537 matrix_dims(Matrix, V). /**> list with matrix dimensions */
538
539
540 eval(Matrix.sum(), V) :- eval,matrix_sum(Matrix, V). /**> list with matrix dimensions */
541
542eval(Matrix.nrow(), V) :- eval,matrix_nrow(Matrix, V). /**> number of rows in bi-dimensional matrix */
543
544eval(Matrix.ncol(), V) :- eval,matrix_ncol(Matrix, V). /**> number of columns in bi-dimensional matrix */
545
546eval(Matrix.length(), V) :- eval,matrix_size(Matrix, V). /**> size of a matrix*/
547
548eval(Matrix.size(), V) :- eval,matrix_size(Matrix, V). /**> size of a matrix*/
549
550eval(Matrix.max(), V) :- eval,matrix_max(Matrix, V). /**> maximum element of a numeric matrix*/
551
552eval(Matrix.maxarg(), V) :- eval, matrix_maxarg(Matrix, V). /** argument of maximum element of a numeric matrix*/
553
554eval(Matrix.min(), V) :- eval, matrix_min(Matrix, V). /** minimum element of a numeric matrix*/
555
556eval(Matrix.minarg(), V) :- eval, matrix_minarg(Matrix, V). /**> argument of minimum element of a numeric matrix*/
557
558eval(Matrix.list(), V) :- eval, matrix_to_list(Matrix, V). /**> represent matrix as a list*/
559
560eval(Matrix.lists(), V) :- eval, matrix_to_lists(Matrix, V). /**> represent matrix as a list of lists */
561
562eval(A+B, C) :- eval,
563 matrix_op(A, B, +, C). /**> sq */
564
565eval(A-B, C) :- eval,
566 matrix_op(A, B, -, C). /**> subtract lists */
567
568eval(A*B, C) :- eval,
569 matrix_op(A, B, *, C). /**> represent matrix as a list of lists */
570
571eval(A/B, C) :- eval,
572 matrix_op(A, B, /, C). /**> represent matrix as a list of lists */
573
574eval(Cs,Exp) :- catch(Exp is Cs,_,fail), catch.
575
576
577/**
578+ `matrix/1`
579
580 create a vector from a list
581
582+ `matrix/2`
583
584 create a matrix from a list. Options are:
585 + dim=
586 a list of dimensions
587
588 + type=
589 integers, floating-point or terms
590
591 + base=
592 a list of base offsets per dimension (all must be the same for arrays of
593integers and floating-points
594
595+ `matrix/3`
596
597 create matrix giving two options
598
599*/
600
601
602new(matrix L, Target) :-
603 is_list(L),
604 is_list,
605 subl(L,Dim),
606 mk_data(L, (dim=Dim), Info),
607 new(matrix( {Info} ), Target).
608new(matrix {Info}, Target) :-
609 new,
610 storage({Info}, Target).
611new(mat( Stuff ), Target) :-
612 new,
613 new(matrix Stuff, Target).
614new(matrix {Info}[Dims], Target) :-
615 new,
616 new(matrix {dim=Dims,Info}, Target).
617new(matrix[Dims] of ints, Target) :-
618 new,
619 mk_data(0, ( dim=[Dims], type = i, exists=a), Info),
620 new(matrix( {Info} ), Target).
621new(matrix[Dims] of C, Target) :-
622 integer(C),
623 integer,
624 mk_data(C,(dim=[Dims], type = i, exists=b), Info),
625 new(matrix( {Info} ), Target).
626new(matrix[Dims] of C, Target) :-
627 float(C),
628 float,
629 mk_data(C,(dim=[Dims], type = f, exists=b), Info),
630 new(matrix( {Info} ), Target).
631
632%%
633%% extract info from data
634%%
635mk_data(int, Info,NInfo) :-
636 mk_data,
637 ( find(type = _, Info) -> NInfo = Info ; NInfo = (type=i, Info) ).
638mk_data(integer, Info,NInfo) :-
639 mk_data,
640 ( find(type = _, Info) -> NInfo = Info ; NInfo = (type=i, Info) ).
641mk_data(ints, Info,NInfo) :-
642 mk_data,
643 ( find(type = _, Info) -> NInfo = Info ; NInfo = (type=i, Info) ).
644mk_data(integers, Info,NInfo) :-
645 mk_data,
646 ( find(type = _, Info) -> NInfo = Info ; NInfo = (type=i, Info) ).
647mk_data(float, Info,NInfo) :-
648 mk_data,
649 ( find(type = _, Info) -> NInfo = Info ; NInfo = (type=f, Info) ).
650mk_data(double, Info,NInfo) :-
651 mk_data,
652 ( find(type = _, Info) -> NInfo = Info ; NInfo = (type=f, Info) ).
653mk_data(floats, Info,NInfo) :-
654 mk_data,
655 ( find(type = _, Info) -> NInfo = Info ; NInfo = (type=f, Info) ).
656mk_data(doubles, Info,NInfo) :-
657 mk_data,
658 ( find(type = _, Info) -> NInfo = Info ; NInfo = (type=f, Info) ).
659mk_data(C,Info, NInfo) :-
660 number(C),
661 number,
662 ( find(type = _, Info) -> NInfo = MInfo ;
663 lub(C,T), MInfo = (type=T, Info) ),
664 ( find(data = _, Info) -> NInfo = MInfo ;
665 find(fill = _, Info) -> NInfo = MInfo ;
666 NInfo = (fill=C, MInfo) ).
667mk_data(L,Info, NInfo) :-
668 is_list(L),
669 is_list,
670 ( find(type = _, Info) -> NInfo = MInfo ;
671 lub(L,T), MInfo = (type=T, Info) ),
672 ( find(data = _, Info) -> NInfo = MInfo ;
673 find(fill = _, Info) -> NInfo = MInfo ;
674 flatten(L,Flat),
675 NInfo = (data=Flat, MInfo) ).
676
677dims(Info,_,Info) :-
678 find(dim=_,Info),
679 find.
680dims(Info, Data, (dim=Dims,Info)) :-
681 is_list(Data),
682 subl(Data,Dims).
683
684subl([H|L],[N|NL]) :-
685 subl,
686 length([H|L],N),
687 subl(H,NL).
688subl(_,[]).
689
690find(Key=Val,{Key=Val,_}) :-
691 find.
692find(Key=Val,{_,Dict}) :-
693 find,
694 find(Key=Val, {Dict}).
695 find(Key=Val,{Key=Val}).
696
697
698find_with_default(Key,Dict,Val) :-
699 find(Key=Val, Dict),
700 find.
701find_with_default(Key,_Dict,Val) :-
702 default(Key,Val).
703
704default(dim,[]).
705default(type,t).
706default(data,[]).
707default(filler,[]).
708
709lub([], b).
710lub([H|L], Lub) :-
711 lub(H, Lub1),
712 lub(L, Lub2),
713 lub,
714 lub_op(Lub1, Lub2, Lub).
715lub(H, L) :-
716 l(H,L).
717
718lub_op(b, T, T):- lub_op.
719lub_op(T, b, T):- lub_op.
720lub_op(i, T, T):- lub_op.
721lub_op(T, i, T):- lub_op.
722lub_op(f, T, T):- lub_op.
723lub_op(T, f, T):- lub_op.
724lub_op(t, t, t):- lub_op.
725
726l(true, b).
727l(false, b).
728l(i, i).
729l(f, f).
730l(I, i) :- integer(I).
731l(F, f) :- float(F).
732l(_, t).
733
734%%> Static Array of ints with: data source, constant initializer, default
735storage(Info, Mat) :-
736 (atom(Mat)->Loc=atom;Loc = atom),
737 spec(Info,Type,Loc,Data,Filler,Dims),
738 schedule(Type,Loc,Data,Filler,Dims,Mat).
739
740spec(Info,Type,_Loc,Data,Filler,Dims) :-
741 find_with_default(type, Info, Type),
742 (
743 find(data=Data, Info)
744 ->
745 find
746 ;
747 Data = [],
748 find_with_default(filler, Info, Filler)
749 ),
750 find_with_default(dim, Info, Dims).
751
752schedule(i,static_array,[H|L],_,[Sz], Mat) :-
753 static_array(Mat,Sz,int),
754 static_array,
755 matrix_set(Mat,[H|L]).
756schedule(i,static_array,_,0,[Sz], Mat) :-
757 static_array(Mat,Sz,int),
758 static_array.
759schedule(i,static_array,_,C,[Sz], Mat) :-
760 static_array(Mat,Sz,int),
761 update_whole_array(Mat,C).
762
763
764%%> OPaque matrix of ints with: data source, constant initializer, default
765schedule(i,_,Data,_,Dims,Mat) :-
766 Data = [_|_],
767 length(Dims,NDims),
768 new_ints_matrix(NDims,Dims,Data,Mat).
769schedule(i,_,_,0,Dims,Mat) :-
770 length(Dims,NDims),
771 new_ints_matrix(NDims,Dims,[],Mat).
772schedule(i,_,_,C,Dims,Mat) :-
773 number(C),
774 number,
775 length(Dims,NDims),
776 new_ints_matrix_set(NDims,Dims,C,Mat).
777%%> OPaque matrix of float
778schedule(f,_,Data,_,Dims,Mat) :-
779 Data = [_|_],
780 length(Dims,NDims),
781 new_ints_matrix(NDims,Dims,Data,Mat).
782schedule(f,_,_,0,Dims,Mat) :-
783 length(Dims,NDims),
784 new_ints_matrix(NDims,Dims,[],Mat).
785schedule(f,_,_,C,Dims,Mat) :-
786 number(C),
787 number,
788 length(Dims,NDims),
789 new_ints_matrix_set(NDims,Dims,C,Mat).
790storage(_,_,_,[H|Dims], '$matrix'([H|Dims], NDims, Size, Offsets, Matrix) ) :-
791 length([H|Dims],NDims),
792 multiply(Dims,H,Size),
793 functor(Matrix,matrix,Size),
794 Offsets=0.
795
796zip(A-B0,A,B0,B1) :- B1 is B0+1.
797
798multiply([],P,P).
799multiply([X|Xs],P0,P) :-
800 Pi is X*P0,
801 myltiply(Xs,Pi,P).
802
803
804foreach( Domain, Goal) :-
805 strip_module(Goal, M, Locals^NG), strip_module,
806 term_variables(Domain+Locals, LocalVarsL),
807 LocalVars =.. [vs|LocalVarsL],
808 iterate( Domain, [], LocalVars, M:NG, [], [] ),
809 iterate:reset_variables( LocalVars ).
810foreach( Domain, Goal ) :-
811 strip_module(Goal, M, NG),
812 term_variables(Domain, LocalVarsL),
813 LocalVars =.. [vs|LocalVarsL],
814 iterate( Domain, [], LocalVars, M:NG, [], [] ),
815 iterate:reset_variables( LocalVars ).
816
817foreach( Domain, Goal, Inp, Out) :-
818 strip_module(Goal, M, Locals^NG), strip_module,
819 term_variables(Domain+Locals, LocalVarsL),
820 LocalVars =.. [vs|LocalVarsL],
821 iterate( Domain, [], LocalVars, M:NG, [], [], Inp, Out).
822foreach( Domain, Goal, Inp, Out ) :-
823 strip_module(Goal, M, NG),
824 term_variables(Domain, LocalVarsL),
825 LocalVars =.. [vs|LocalVarsL],
826 iterate( Domain, [], LocalVars, M:NG, [], [], Inp, Out ).
827
828iterate( [], [], LocalVars, Goal, Vs, Bs ) :-
829 iterate:freshen_variables(LocalVars),
830 Vs = Bs,
831 MG freshen_variables Goal,
832 once( MG ),
833 once:reset_variables(LocalVars).
834iterate( [], [H|Cont], LocalVars, Goal, Vs, Bs ) :-
835 iterate(H, Cont, LocalVars, Goal, Vs, Bs ).
836iterate( [H|L], [], LocalVars, Goal, Vs, Bs ) :- iterate,
837 iterate(H, L, LocalVars, Goal, Vs, Bs ).
838iterate( [H|L], Cont, LocalVars, Goal, Vs, Bs ) :- iterate,
839 append(L, Cont, LCont),
840 iterate(H, LCont, LocalVars, Goal, Vs, Bs ).
841iterate( [] ins _A .. _B, [H|L], LocalVars, Goal, Vs, Bs ) :- iterate,
842 iterate(H, L, LocalVars, Goal, Vs, Bs ).
843iterate( [] ins _A .. _B, [], LocalVars, Goal, Vs, Bs ) :- iterate,
844 iterate([], [], LocalVars, Goal, Vs, Bs ).
845iterate( [V|Ps] ins A..B, Cont, LocalVars, Goal, Vs, Bs ) :-
846 eval(A, Vs, Bs, NA),
847 eval(B, Vs, Bs, NB),
848 ( NA > NB -> true ;
849 A1 is NA+1,
850 iterate( Ps ins NA..NB, Cont, LocalVars, Goal, [V|Vs], [NA|Bs] ),
851 iterate( [V|Ps] ins A1..NB, Cont, LocalVars, Goal, Vs, Bs )
852 ).
853iterate( V in A..B, Cont, LocalVars, Goal, Vs, Bs) :-
854 var(V),
855 eval(A, Vs, Bs, NA),
856 eval(B, Vs, Bs, NB),
857 ( NA > NB -> true ;
858 A1 is NA+1,
859 (Cont = [H|L] ->
860 iterate( H, L, LocalVars, Goal, [V|Vs], [NA|Bs] )
861 ;
862 iterate( [], [], LocalVars, Goal, [V|Vs], [NA|Bs] )
863 ),
864 iterate( V in A1..NB, Cont, LocalVars, Goal, Vs, Bs )
865 ).
866
867iterate( [], [], LocalVars, Goal, Vs, Bs, Inp, Out ) :-
868 iterate:freshen_variables(LocalVars),
869 Vs = Bs,
870 MG freshen_variables Goal,
871 once( call(MG, Inp, Out) ),
872 once:reset_variables(LocalVars).
873iterate( [], [H|Cont], LocalVars, Goal, Vs, Bs, Inp, Out ) :-
874 iterate(H, Cont, LocalVars, Goal, Vs, Bs, Inp, Out ).
875iterate( [H|L], [], LocalVars, Goal, Vs, Bs, Inp, Out ) :- iterate,
876 iterate(H, L, LocalVars, Goal, Vs, Bs, Inp, Out ).
877iterate( [H|L], Cont, LocalVars, Goal, Vs, Bs, Inp, Out ) :- iterate,
878 append(L, Cont, LCont),
879 iterate(H, LCont, LocalVars, Goal, Vs, Bs, Inp, Out ).
880iterate( [] ins _A .. _B, [], LocalVars, Goal, Vs, Bs, Inp, Out ) :- iterate,
881 iterate([], [], LocalVars, Goal, Vs, Bs, Inp, Out ).
882iterate( [] ins _A .. _B, [H|L], LocalVars, Goal, Vs, Bs, Inp, Out ) :- iterate,
883 iterate(H, L, LocalVars, Goal, Vs, Bs, Inp, Out ).
884iterate( [V|Ps] ins A..B, Cont, LocalVars, Goal, Vs, Bs, Inp, Out ) :-
885 eval(A, Vs, Bs, NA),
886 eval(B, Vs, Bs, NB),
887 ( NA > NB -> Inp = Out ;
888 A1 is NA+1,
889 iterate( Ps ins A..B, Cont, LocalVars, Goal, [V|Vs], [NA|Bs], Inp, Mid ),
890 iterate( [V|Ps] ins A1..NB, Cont, LocalVars, Goal, Vs, Bs, Mid, Out )
891 ).
892iterate( V in A..B, Cont, LocalVars, Goal, Vs, Bs, Inp, Out) :-
893 var(V),
894 eval(A, Vs, Bs, NA),
895 eval(B, Vs, Bs, NB),
896 ( NA > NB -> Inp = Out ;
897 A1 is NA+1,
898 (Cont = [H|L] ->
899 iterate( H, L, LocalVars, Goal, [V|Vs], [NA|Bs], Inp, Mid )
900 ;
901 iterate( [], [], LocalVars, Goal, [V|Vs], [NA|Bs], Inp, Mid )
902 ),
903 iterate( V in A1..NB, Cont, LocalVars, Goal, Vs, Bs, Mid, Out )
904 ).
905
906
907eval(I, _Vs, _Bs, I) :- integer(I), integer.
908eval(I, Vs, Bs, NI) :-
909 copy_term(I+Vs, IA+Bs),
910 NI copy_term IA.
911
912matrix_seq(A, B, Dims, M) :-
913 ints(A, B, L),
914 matrix_new(ints, Dims, L, M).
915
916ints(A,B,O) :-
917 ( A > B -> O = [] ; O = [A|L], A1 is A+1, ints(A1,B,L) ).
918
919 /**
920 */
921% base case
922
923matrix_set(V, VF) :-
924 var(V),
925 var,
926 V = VF.
927matrix_set(M,V) :-
928 is_matrix(M),
929 is_matrix,
930 matrix_set_all(M,V).
931matrix_set(M[Args], Val) :-
932 matrix_set,
933 matrix_set(M,[Args],Val).
934
935matrix_set(M, Args, Val) :-
936 maplist(integer, Args),
937 maplist,
938 matrix_set_one(M,Args,Val).
939matrix_set(M, Args, Val) :-
940 dims( M, Dims, Bases),
941 maplist( index(Range), Args, Dims, Bases, NArgs),
942 (
943 var(Range)
944 ->
945 var ( M, Args, Val )
946 ;
947 matrix_set_range( M, NArgs, Val )
948 ).
949
950
951%c
952% ranges of arguments
953%
954index(Range, V, M, Base, Indx) :- var(V), var,
955 Max is (M-1)+Base,
956 index(Range, Base..Max, M, Base, Indx).
957index(Range, '*', M, Base, Indx) :- index,
958 Max is (M-1)+Base,
959 index(Range, Base..Max, M, Base, Indx).
960index(Range, Exp, M, _Base, Indx) :- index,
961 index(Exp, M, Indx0),
962 ( integer(Indx0) -> Indx = Indx0 ;
963 Indx0 = [Indx] -> ;
964 Indx0 = Indx, Range = ).
965
966index(I, _M, I ) :- integer(I), integer.
967index(I..J, _M, [I|O] ) :- index,
968 I1 is I, J1 is J,
969 once( foldl(inc, O, I1, J1) ).
970index(I:J, _M, [I|O] ) :- index,
971 I1 is I, J1 is J,
972 once( foldl(inc, O, I1, J1) ).
973index(I+J, M, O ) :- index,
974 index(I, M, I1),
975 index(J, M, J1),
976 add_index(I1, J1, O).
977index(I-J, M, O ) :- index,
978 index(I, M, I1),
979 index(J, M, J1),
980 sub_index(I1, J1, O).
981index(I*J, M, O ) :- index,
982 index(I, M, I1),
983 index(J, M, J1),
984 O is I1*J1.
985index(I rem J, M, O ) :- index,
986 index(I, M, I1),
987 index(J, M, J1),
988 O is I1 rem J1.
989index(I, M, NI ) :-
990 maplist(indx(M), I, NI).
991
992indx(M, I, NI) :- index(I, M, NI).
993
994add_index(I1, J1, O) :-
995 integer(I1),
996 integer(J1),
997 O is I1+J1.
998add_index(I1, J1, O) :-
999 integer(I1), integer,
1000 maplist(plus(I1), J1, O).
1001add_index(I1, J1, O) :-
1002 integer(J1), integer,
1003 maplist(plus(J1), I1, O).
1004add_index(I1, J1, O) :-
1005 ord_union(I1, J1, O).
1006
1007sub_index(I1, J1, O) :-
1008 integer(I1),
1009 integer(J1), integer,
1010 O is I1-J1.
1011sub_index(I1, J1, O) :-
1012 integer(I1), integer,
1013 maplist(rminus(I1), J1, O).
1014sub_index(I1, J1, O) :-
1015 integer(J1), integer,
1016 maplist(minus(J1), I1, O).
1017sub_index(I1, J1, O) :-
1018 ord_subtract(I1, J1, O).
1019
1020minus(X, Y, Z) :- Z is X-Y.
1021
1022rminus(X, Y, Z) :- Z is Y-X.
1023
1024times(X, Y, Z) :- Z is Y*X.
1025
1026div(X, Y, Z) :- Z is X/Y.
1027
1028rdiv(X, Y, Z) :- Z is Y/X.
1029
1030zdiv(X, Y, Z) :- (X == 0 -> Z = 0 ; X == 0.0 -> Z = 0.0 ; Z is X / Y ).
1031
1032mplus(I1, I2, V) :-
1033 (matrix(I1) ->
1034 ( number(I2) -> matrix_op_to_all(I1, +, I2, V) ;
1035 matrix(I2) -> matrix_op(I1, I2, +, V) ;
1036 V is I1+I2 ) ;
1037 is_list(I1) ->
1038 ( number(I2) -> maplist(plus(I2), I1, V) ;
1039 is_list(I2) -> maplist(plus, I1, I2, V) ;
1040 V is I1+I2 ) ;
1041 V is I1 +I2
1042 ).
1043
1044msub(I1, I2, V) :-
1045 (matrix(I1) ->
1046 ( number(I2) -> matrix_op_to_all(I1, -, I2, V) ;
1047 matrix(I2) -> matrix_op(I1, I2, -, V) ;
1048 V is I1-I2 ) ;
1049 is_list(I1) ->
1050 ( number(I2) -> maplist(minus(I2), I1, V) ;
1051 is_list(I2) -> maplist(minus, I1, I2, V) ;
1052 V is I1-I2 ) ;
1053 V is I1-I2
1054 ).
1055
1056
1057
1058mtimes(I1, I2, V) :-
1059 (matrix(I1) ->
1060 ( number(I2) -> matrix_op_to_all(I1, *, I2, V) ;
1061 matrix(I2) -> matrix_op(I1, I2, *, V) ;
1062 V is I1*I2 ) ;
1063 is_list(I1) ->
1064 ( number(I2) -> maplist(times(I2), I1, V) ;
1065 is_list(I2) -> maplist(times, I1, I2, V) ;
1066 V is I1*I2 ) ;
1067 V is I1*I2
1068 ).
1069
1070mfdiv(I1, I2, V) :-
1071 (matrix(I1) ->
1072 ( number(I2) -> matrix_op_to_all(I1, /, I2, V) ;
1073 matrix(I2) -> matrix_op(I1, I2, /, V) ;
1074 V is I1/I2 ) ;
1075 is_list(I1) ->
1076 ( number(I2) -> maplist(div(I2), I1, V) ;
1077 is_list(I2) -> maplist(div, I1, I2, V) ;
1078 V is I1/I2 ) ;
1079 V is I1/I2
1080 ).
1081
1082
1083mneg(I1, V) :-
1084 (matrix(I1) ->
1085 matrix_op_to_all(I1, *, -1, V) ;
1086 is_list(I1) ->
1087 maplist(mult(-1), V) ;
1088 V is -I1
1089 ).
1090
1091%
1092% three types of matrix: integers, floats and general terms.
1093%
1094
1095
1096matrix_to_lists( Mat, ToList) :-
1097 matrix_dims( Mat, [D|Dims] ),
1098 D1 is D-1,
1099 foreach( I in 0..D1, matrix_slicer( Dims, Mat, [I|L]-L), ToList, [] ).
1100
1101matrix_slicer( [_], M, Pos-[_], [O|L0], L0) :- matrix_slicer,
1102 O matrix_slicer '[]'(Pos,M).
1103matrix_slicer( [D|Dims], M, Pos-[I|L], [O|L0], L0) :-
1104 D1 is D-1,
1105 foreach( I in 0..D1 , L^matrix_slicer( Dims, M, Pos-L), O, [] ).
1106
1107/** @pred matrix_get(+ _Matrix_,+ _Position_,- _Elem_)
1108
1109Unify _Elem_ with the element of _Matrix_ at position
1110 _Position_, or with a list of elements i if Pod is a range.
1111
1112
1113*/
1114matrix_get( Mat, Pos, El) :-
1115 maplist(integer,Pos),
1116 maplist,
1117 matrix_get_one(Mat, Pos, El).
1118matrix_get( Mat, Pos, El) :-
1119 matrix_get_range( Mat, Pos, El).
1120
1121matrix_get_range( Mat, Pos, Els) :-
1122 slice(Pos, Keys),
1123 maplist( matrix_get_one(Mat), Keys, Els).
1124
1125slice([], [[]]).
1126slice([[H|T]|Extra], Els) :- slice,
1127 slice(Extra, Els0),
1128 foldl(add_index_prefix( Els0 ), [H|T], Els, [] ).
1129slice([H|Extra], Els) :- slice,
1130 slice(Extra, Els0),
1131 add_index_prefix( Els0 , H, Els, [] ).
1132
1133add_index_prefix( [] , _H ) --> [].
1134add_index_prefix( [L|Els0] , H ) --> [[H|L]],
1135 add_index_prefix( Els0 , H ).
1136
1137
1138
1139matrix_type(Matrix,Type) :-
1140 ( matrix_type_as_number(Matrix, 0) -> Type = matrix_type_as_number ;
1141 opaque( Matrix ) -> Type = opaque ;
1142 Type = opaque ).
1143
1144matrix_base(Matrix, Bases) :-
1145 dims(Matrix, Bases).
1146
1147
1148matrix_agg_lines(M1,+,NM) :-
1149 do_matrix_agg_lines(M1,0,NM).
1150/* other operations: *, logprod */
1151
1152matrix_agg_cols(M1,+,NM) :-
1153 do_matrix_agg_cols(M1,0,NM).
1154/* other operations: *, logprod */
1155
1156matrix_op(M1,M2,+,NM) :-
1157 ( opaque(M1), opaque(M2) ->
1158 do_matrix_op(M1,M2,0,NM) ;
1159 matrix_m(M1, '$matrix'(A,B,D,E,C1)),
1160 matrix_m(M2, '$matrix'(A,B,D,E,C2)),
1161 mapargs(plus, C1, C2, C),
1162 NM = '$matrix'(A,B,D,E,C) ).
1163matrix_op(M1,M2,-,NM) :-
1164 ( opaque(M1), opaque(M2) ->
1165 do_matrix_op(M1,M2,1,NM) ;
1166 matrix_m(M1, '$matrix'(A,B,D,E,C1)),
1167 matrix_m(M2, '$matrix'(A,B,D,E,C2)),
1168 mapargs(minus, C1, C2, C),
1169 NM = '$matrix'(A,B,D,E,C) ).
1170matrix_op(M1,M2,*,NM) :-
1171 ( opaque(M1), opaque(M2) ->
1172 do_matrix_op(M1,M2,2,NM) ;
1173 matrix_m(M1, '$matrix'(A,B,D,E,C1)),
1174 matrix_m(M2, '$matrix'(A,B,D,E,C2)),
1175 mapargs(times, C1, C2, C),
1176 NM = '$matrix'(A,B,D,E,C) ).
1177matrix_op(M1,M2,/,NM) :-
1178 ( opaque(M1), opaque(M2) ->
1179 do_matrix_op(M1,M2,5,NM) ;
1180 matrix_m(M1, '$matrix'(A,B,D,E,C1)),
1181 matrix_m(M2, '$matrix'(A,B,D,E,C2)),
1182 mapargs(div, C1, C2, C),
1183 NM = '$matrix'(A,B,D,E,C)
1184 ).
1185
1186
1187matrix_op_to_all(M1,+,Num,NM) :-
1188 ( opaque(M1) ->
1189 do_matrix_op_to_all(M1,0,Num,NM)
1190 ; M1 == NM, M1 = floats(Ad,Sz) ->
1191 address_op_to_all(Ad,Sz,0,Num)
1192 ;
1193 M1 = '$matrix'(A,B,D,E,C),
1194 mapargs(plus(Num), C, NC),
1195 NM = '$matrix'(A,B,D,E,NC)
1196 ).
1197matrix_op_to_all(M1,-,Num,NM) :-
1198 ( opaque(M1) ->
1199 do_matrix_op_to_all(M1,1,Num,NM)
1200 ; M1 == NM, M1 = floats(Ad,Sz) ->
1201 address_op_to_all(Ad,Sz,1,Num)
1202 ;
1203 M1 = '$matrix'(A,B,D,E,C),
1204 mapargs(minus(Num), C, NC),
1205 NM = '$matrix'(A,B,D,E,NC)
1206 ).
1207matrix_op_to_all(M1,*,Num,NM) :-
1208 ( opaque(M1) ->
1209 do_matrix_op_to_all(M1,2,Num,NM)
1210 ; M1 == NM, M1 = floats(Ad,Sz) ->
1211 address_op_to_all(Ad,Sz,2,Num)
1212 ;
1213 M1 = '$matrix'(A,B,D,E,C),
1214 mapargs(times(Num), C, NC),
1215 NM = '$matrix'(A,B,D,E,NC)
1216 ).
1217matrix_op_to_all(M1,/,Num,NM) :-
1218 % can only use floats.
1219 FNum is float(Num),
1220 ( opaque(M1) ->
1221 do_matrix_op_to_all(M1,3,FNum,NM)
1222 ; M1 == NM, M1 = floats(Ad,Sz) ->
1223 address_op_to_all(Ad,Sz,3,Num)
1224 ;
1225 M1 = '$matrix'(A,B,D,E,C),
1226 mapargs(div(Num), C, NC),
1227 NM = '$matrix'(A,B,D,E,NC)
1228 ).
1229
1230/* other operations: *, logprod */
1231
1232matrix_op_to_lines(M1,M2,/,NM) :-
1233 do_matrix_op_to_lines(M1,M2,3,NM).
1234/* other operations: *, logprod */
1235
1236matrix_op_to_cols(M1,M2,+,NM) :-
1237 do_matrix_op_to_cols(M1,M2,0,NM).
1238/* other operations: *, logprod */
1239
1240
1241matrix_transpose(M1,M2) :-
1242 matrix_shuffle(M1,[1,0],M2).
1243
1244size(N0, N1, N2) :-
1245 N2 is N0*N1.
1246
1247% use 1 to get access to matrix
1248m_get('$matrix'(Dims, _, Sz, Bases, M), Indx, V) :-
1249 foldl2(indx, Indx, Dims, Bases, Sz, _, 1, Offset),
1250 arg(Offset, M, V).
1251
1252
1253indx( I, Dim, Base, BlkSz, NBlkSz, I0, IF) :-
1254 NBlkSz is BlkSz div Dim ,
1255 IF is (I-Base)*NBlkSz + I0.
1256
1257offset( I, Dim, BlkSz, NBlkSz, Base, I0, IF) :-
1258 NBlkSz is BlkSz div Dim,
1259 I is I0 div NBlkSz + Base,
1260 IF is I0 rem NBlkSz.
1261
1262inc(I1, I, I1) :-
1263 I1 is I+1.
1264/**
1265 */
1266% base case
1267
1268
1269
1270/** @} */
1271
1272
catch( : Goal,+ Exception,+ Action)
is_list( ?_List_ )
matrix_size(+ Matrix,- NElems)
matrix_sum(+ Matrix,+ Sum)
matrix_to_list(+ Matrix,- Elems)
static_array(+ Name, + Size, + Type)
load_foreign_files( Files, Libs, InitRoutine)
reexport(+F)
use_module( +Files )
copy_term(? TI,- TF)
once( 0:G)
term_variables(? Term, - Variables)
arg(+ N,+ T, A)
atom( T)
float( T)
functor( T, F, N)
integer( T)
number( T)
var( T)
append(? List1,? List2,? List3)
flatten(+ List, ? FlattenedList)
length(? L,? S)
foldl2(: Pred, + List, ? List1, ? List2, ? X0, ? X, ? Y0, ? Y)
maplist( 2:Pred, + List1,+ List2)
maplist(3:Pred,+ List1,+ List2,+ List4)
maplist(: Pred, ? L1, ? L2, ? L3, ? L4)
matrix_agg_cols(+ Matrix,+Operator,+ Aggregate)
matrix_agg_lines(+ Matrix,+Operator,+ Aggregate)
matrix_arg_to_offset(+ Matrix,+ Position,- Offset)
matrix_column(+ Matrix,+ Column,- NewMatrix)
matrix_dec(+ Matrix,+ Position)
matrix_dec(+ Matrix,+ Position,- Element)
matrix_get(+ Matrix,+ Position,- Elem)
matrix_new(+ Type,+ Dims,- Matrix)
matrix_new(+ Type,+ Dims,+ List,- Matrix)
matrix_new_set(? Dims,+ OldMatrix,+ Value,- NewMatrix)
matrix_offset_to_arg(+ Matrix,- Offset,+ Position)
matrix_op(+ Matrix1,+ Matrix2,+ Op,- Result)
matrix_op_to_all(+ Matrix1,+ Op,+ Operand,- Result)
matrix_op_to_cols(+ Matrix1,+ Cols,+ Op,- Result)
matrix_op_to_lines(+ Matrix1,+ Lines,+ Op,- Result)
matrix_select(+ Matrix,+ Dimension,+ Index,- New)
matrix_shuffle(+ Matrix,+ NewOrder,- Shuffle)
matrix_transpose(+ Matrix,- Transpose)
matrix_type(+ Matrix,- Type)
ord_subtract(+ Set1, + Set2, ? Difference)
ord_union(+ Set1, + Set2, ? Union)