factor/library/math/matrices.factor

147 lines
4.0 KiB
Factor
Raw Normal View History

2005-04-13 20:44:06 -04:00
! Copyright (C) 2005 Slava Pestov.
! See http://factor.sf.net/license.txt for BSD license.
IN: matrices
2005-05-03 04:40:13 -04:00
USING: errors generic kernel lists math namespaces sequences
vectors ;
2005-04-13 20:44:06 -04:00
2005-05-03 04:40:13 -04:00
: n*v ( n vec -- vec )
#! Multiply a vector by a scalar.
[ * ] seq-map-with ;
2005-04-13 20:44:06 -04:00
! Vector operations
2005-05-03 04:40:13 -04:00
: v+ ( v v -- v ) [ + ] seq-2map ;
: v- ( v v -- v ) [ - ] seq-2map ;
: v* ( v v -- v ) [ * ] seq-2map ;
2005-04-13 20:44:06 -04:00
! Later, this will fixed when seq-2each works properly
2005-05-03 04:40:13 -04:00
! : v. ( v v -- x ) 0 swap [ * + ] seq-2each ;
2005-04-13 20:44:06 -04:00
: +/ ( seq -- n ) 0 swap [ + ] seq-each ;
2005-05-03 04:40:13 -04:00
: v. ( v v -- x ) v* +/ ;
2005-04-13 20:44:06 -04:00
2005-04-30 02:01:04 -04:00
! Matrices
2005-05-03 04:40:13 -04:00
! The major dimension is the number of elements per row.
TUPLE: matrix rows cols sequence ;
: >matrix<
[ matrix-rows ] keep
[ matrix-cols ] keep
matrix-sequence ;
2005-04-13 20:44:06 -04:00
M: matrix clone ( matrix -- matrix )
clone-tuple
dup matrix-sequence clone over set-matrix-sequence ;
: matrix@ ( row col matrix -- n ) matrix-rows * + ;
: matrix-get ( row col matrix -- elt )
[ matrix@ ] keep matrix-sequence nth ;
: matrix-set ( elt row col matrix -- )
[ matrix@ ] keep matrix-sequence set-nth ;
: <zero-matrix> ( rows cols -- matrix )
2dup * zero-vector <matrix> ;
2005-04-30 02:01:04 -04:00
: <row-vector> ( vector -- matrix )
#! Turn a vector into a matrix of one row.
[ 1 swap length ] keep <matrix> ;
: <col-vector> ( vector -- matrix )
#! Turn a vector into a matrix of one column.
[ length 1 ] keep <matrix> ;
2005-04-13 20:44:06 -04:00
: 2repeat ( i j quot -- | quot: i j -- i j )
rot [
rot [ [ rot dup slip -rot ] repeat ] keep -rot
] repeat 2drop ; inline
SYMBOL: matrix-maker
: make-matrix ( rows cols quot -- matrix )
[
matrix-maker set
2dup <zero-matrix> matrix set
[
[
2005-05-03 04:40:13 -04:00
[ matrix-maker get call ] 2keep
matrix get matrix-set
2005-04-13 20:44:06 -04:00
] 2keep
] 2repeat
matrix get
] with-scope ;
: <identity-matrix> ( n -- matrix )
#! Make a nxn identity matrix.
dup [ = 1 0 ? ] make-matrix ;
: transpose ( matrix -- matrix )
dup matrix-cols over matrix-rows [
pick matrix-get
] make-matrix nip ;
! Sequence of elements in a row of a matrix.
TUPLE: row index matrix ;
: >row< dup row-index swap row-matrix ;
M: row length row-matrix matrix-cols ;
2005-04-30 02:01:04 -04:00
M: row nth ( n row -- ) >row< swapd matrix-get ;
M: row thaw >vector ;
2005-04-13 20:44:06 -04:00
! Sequence of elements in a column of a matrix.
TUPLE: col index matrix ;
: >col< dup col-index swap col-matrix ;
M: col length col-matrix matrix-rows ;
2005-05-03 04:40:13 -04:00
M: col nth ( n column -- ) >col< matrix-get ;
2005-04-30 02:01:04 -04:00
M: col thaw >vector ;
2005-04-13 20:44:06 -04:00
2005-05-03 04:40:13 -04:00
: +check ( matrix matrix -- )
2005-04-13 20:44:06 -04:00
#! Check if the two matrices have dimensions compatible
#! for being added or subtracted.
over matrix-rows over matrix-rows = >r
2005-05-03 04:40:13 -04:00
swap matrix-cols swap matrix-cols = r> and [
"Matrix dimensions do not equal" throw
2005-04-13 20:44:06 -04:00
] unless ;
2005-05-03 04:40:13 -04:00
: element-wise ( m m -- v v )
2dup +check >r >matrix< r> matrix-sequence ;
2005-04-13 20:44:06 -04:00
2005-05-03 04:40:13 -04:00
! Matrix operations
: m+ ( m m -- m ) element-wise v+ <matrix> ;
: m- ( m m -- m ) element-wise v- <matrix> ;
2005-04-13 20:44:06 -04:00
2005-05-03 04:40:13 -04:00
: m* ( m m -- m )
#! Multiply two matrices element-wise. This is NOT matrix
#! multiplication in the usual mathematical sense. For that,
#! see the m. word.
element-wise v* <matrix> ;
2005-04-13 20:44:06 -04:00
2005-05-03 04:40:13 -04:00
: *check ( matrix matrix -- )
swap matrix-cols swap matrix-rows = [
2005-04-14 19:37:13 -04:00
"Matrix dimensions inappropriate for composition" throw
2005-04-13 20:44:06 -04:00
] unless ;
: *dimensions ( m m -- rows cols )
swap matrix-rows swap matrix-cols ;
2005-05-03 04:40:13 -04:00
: m. ( m1 m2 -- m )
#! Composition of two matrices.
2dup *check 2dup *dimensions [
( m1 m2 row col -- m1 m2 )
2005-04-13 20:44:06 -04:00
>r >r 2dup r> rot <row> r> rot <col> v.
] make-matrix 2nip ;
2005-05-03 04:40:13 -04:00
: n*m ( n m -- m )
#! Multiply a matrix by a scalar.
>matrix< >r rot r> n*v <matrix> ;
2005-04-13 20:44:06 -04:00
2005-05-03 04:40:13 -04:00
: m.v ( m v -- v )
#! Multiply a matrix by a column vector.
<col-vector> m. matrix-sequence ;
2005-04-13 20:44:06 -04:00
2005-05-03 04:40:13 -04:00
: v.m ( v m -- v )
#! Multiply a row vector by a matrix.
>r <row-vector> r> m. matrix-sequence ;
2005-04-13 20:44:06 -04:00
: row-list ( matrix -- list )
#! A list of lists, where each sublist is a row of the
#! matrix.
2005-05-03 04:40:13 -04:00
dup matrix-rows [ swap <row> >list ] project-with ;