[pure-lang-svn] SF.net SVN: pure-lang:[836] pure/trunk
Status: Beta
Brought to you by:
agraef
From: <ag...@us...> - 2008-09-23 10:32:03
|
Revision: 836 http://pure-lang.svn.sourceforge.net/pure-lang/?rev=836&view=rev Author: agraef Date: 2008-09-23 10:31:58 +0000 (Tue, 23 Sep 2008) Log Message: ----------- Moved the matrix operations from primitives.pure to their own module. Modified Paths: -------------- pure/trunk/ChangeLog pure/trunk/lib/prelude.pure pure/trunk/lib/primitives.pure Added Paths: ----------- pure/trunk/lib/matrices.pure Modified: pure/trunk/ChangeLog =================================================================== --- pure/trunk/ChangeLog 2008-09-23 09:15:34 UTC (rev 835) +++ pure/trunk/ChangeLog 2008-09-23 10:31:58 UTC (rev 836) @@ -1,5 +1,8 @@ 2008-09-23 Albert Graef <Dr....@t-...> + * lib/matrices.pure: Moved the matrix operations from + primitives.pure to their own module. + * lib/primitives.pure: Added a bunch of new matrix operations. In particular, list operations like filter and map now work on matrices, too. Added: pure/trunk/lib/matrices.pure =================================================================== --- pure/trunk/lib/matrices.pure (rev 0) +++ pure/trunk/lib/matrices.pure 2008-09-23 10:31:58 UTC (rev 836) @@ -0,0 +1,339 @@ + +/* Basic matrix functions. */ + +/* Copyright (c) 2008 by Albert Graef <Dr....@t-...>. + + This file is part of the Pure programming language and system. + + Pure is free software: you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation, either version 3 of the License, or (at your option) any later + version. + + Pure is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + details. + + You should have received a copy of the GNU General Public License along + with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Additional matrix predicates. The numeric matrix types will only be + available if the interpreter was built with support for the GNU Scientific + Library (GSL). This is the case iff the global gsl_version variable is + predefined by the interpreter. */ + +extern int matrix_type(expr* x); + +dmatrixp x = case x of _::matrix = matrix_type x==1; _ = 0 end; +cmatrixp x = case x of _::matrix = matrix_type x==2; _ = 0 end; +imatrixp x = case x of _::matrix = matrix_type x==3; _ = 0 end; + +/* The nmatrixp predicate checks for any kind of numeric (double, complex or + int) matrix, smatrix for symbolic matrices. */ + +nmatrixp x = case x of _::matrix = matrix_type x>=1; _ = 0 end; +smatrixp x = case x of _::matrix = matrix_type x==0; _ = 0 end; + +/* Pure represents row and column vectors as matrices with 1 row or column, + respectively. The following predicates allow you to check for these special + kinds of matrices. */ + +vectorp x = matrixp x && (n==1 || m==1 when n::int,m::int = dim x end); +rowvectorp x = matrixp x && dim x!0==1; +colvectorp x = matrixp x && dim x!1==1; + +/* Size of a matrix (#x) and its dimensions (dim x=n,m where n is the number + of rows, m the number of columns). Note that Pure supports empty matrices, + thus the total size may well be zero, meaning that either the number of + rows or the number of columns is zero, or both. The null predicate checks + for empty matrices. */ + +private matrix_size matrix_dim; +extern int matrix_size(expr *x), expr* matrix_dim(expr *x); + +#x::matrix = matrix_size x; +dim x::matrix = matrix_dim x; +null x::matrix = #x==0; + +/* The stride of a matrix denotes the real row size of the underlying C array, + see the description of the 'pack' function below for further details. + There's little use for this value in Pure, but it may be needed when + interfacing to C. */ + +private matrix_stride; +extern int matrix_stride(expr *x); + +stride x::matrix = matrix_stride x; + +/* Indexing. Note that in difference to Octave and MATLAB, all indices are + zero-based, and you *must* use Pure's indexing operator '!' to retrieve an + element. You can either get an element by specifying its row-major index in + the range 0..#x-1, or with a two-dimensional subscript of the form of a + pair (i,j), where i denotes the row and j the column index. Both operations + take only constant time, and an 'out_of_bounds' exception is thrown if an + index falls outside the valid range. */ + +private matrix_elem_at matrix_elem_at2; +extern expr* matrix_elem_at(expr* x, int i); +extern expr* matrix_elem_at2(expr* x, int i, int j); + +x::matrix!i::int = matrix_elem_at x i if i>=0 && i<#x; + = throw out_of_bounds otherwise; + +x::matrix!(i::int,j::int) + = matrix_elem_at2 x i j + if (i>=0 && i<n && j>=0 && j<m + when n::int,m::int = dim x end); + = throw out_of_bounds otherwise; + +/* Matrix slices (x!!ns). As with simple indexing, elements can addressed + using either singleton (row-major) indices or index pair (row,column). The + former is specified as a list of int values, the latter as a pair of lists + of int values. As with list slicing, index ranges may be non-contiguous + and/or non-monotonous. However, the case of contiguous and monotonous + ranges is optimized by making good use of the 'submat' operation below. */ + +x::matrix!!(ns,ms) = case ns,ms of + ns@(n:_),ms@(m:_) = submat x (n,m) (#ns,#ms) + if cont ns && cont ms; + _ = colcatmap (mth (rowcatmap (nth x) ns)) ms; + end with + cont [n] = 1; + cont (n::int:ns@(m::int:_)) = cont ns if m==n+1; + cont _ = 0 otherwise; + nth x n = catch (cst {}) (row x n); + mth x m = catch (cst {}) (col x m); + end; +x::matrix!!ns = if packed x then rowvector x!!([0],ns) + else colcatmap (nth x) ns with + nth x n = catch (cst {}) {x!n}; + end; + +/* Extract rows and columns from a matrix. */ + +private matrix_slice; +extern expr* matrix_slice(expr* x, int i1, int j1, int i2, int j2); + +row x::matrix i::int = if i>=0 && i<n then matrix_slice x i 0 i (m-1) + else throw out_of_bounds + when n::int,m::int = dim x end; + +col x::matrix j::int = if j>=0 && j<m then matrix_slice x 0 j (n-1) j + else throw out_of_bounds + when n::int,m::int = dim x end; + +rows x::matrix = map (row x) (0..n-1) when n::int,_ = dim x end; + +cols x::matrix = map (col x) (0..m-1) when _,m::int = dim x end; + +/* Convert a matrix to a list and vice versa. list x converts a matrix x to a + flat list of its elements, while list2 converts it to a list of lists. + Conversely, matrix xs converts a list of lists or matrices specifying the + rows of the matrix to the corresponding matrix; otherwise, the result is a + row vector. NOTE: The matrix function may throw a 'bad_matrix_value x' in + case of dimension mismatch, where x denotes the offending submatrix. */ + +list x::matrix = [x!i|i=0..#x-1]; +list2 x::matrix = [[x!(i,j)|j=0..m-1]|i=0..n-1] + when n::int,m::int = dim x end; + +matrix [] = {}; +matrix xs@(x:_) = rowcatmap colcat xs if all listp xs; + = rowcat xs if any matrixp xs; + = colcat xs otherwise; + +/* Extract (sub-,super-) diagonals from a matrix. Sub- and super-diagonals for + k=0 return the main diagonal. Indices for sub- and super-diagonals can also + be negative, in which case the corresponding super- or sub-diagonal is + returned instead. In each case the result is a row vector. */ + +private matrix_diag matrix_subdiag matrix_supdiag; +extern expr* matrix_diag(expr* x) = diag; +extern expr* matrix_subdiag(expr* x, int k) = subdiag; +extern expr* matrix_supdiag(expr* x, int k) = supdiag; + +/* Extract a submatrix of a given size at a given offset. The result shares + the underlying storage with the input matrix (i.e., matrix elements are + *not* copied) and so this is a comparatively cheap operation. */ + +submat x::matrix (i::int,j::int) (n::int,m::int) + = matrix_slice x i j (i+n-1) (j+m-1); + +/* Change the dimensions of a matrix without changing its size. The total + number of elements must match that of the input matrix. Reuses the + underlying storage of the input matrix if possible. */ + +private matrix_redim; +extern expr* matrix_redim(expr* x, int n, int m); + +redim x::matrix (n::int,m::int) + = matrix_redim x n m if n>=0 && m>=0 && n*m==#x; + +/* You can also redim a matrix to a given row size. In this case the row size + must be positive and divide the total size of the matrix, */ + +redim x::matrix m::int = redim x (#x div m,m) if m>0 && #x mod m==0; + +/* Convenience functions for converting a matrix to a row or column vector. */ + +rowvector x::matrix = redim x (#x); +colvector x::matrix = redim x 1; + +/* Construct matrices from lists of rows and columns. These take either + scalars or submatrices as inputs; corresponding dimensions must match. + rowcat combines submatrices vertically, like {x;y}; colcat combines them + horizontally, like {x,y}. NOTE: Like the built-in matrix constructs, these + operations may throw a 'bad_matrix_value x' in case of dimension mismatch, + where x denotes the offending submatrix. */ + +extern expr* matrix_rows(expr *x) = rowcat; +extern expr* matrix_columns(expr *x) = colcat; + +/* Combinations of rowcat/colcat and map. */ + +rowcatmap f [] = {}; +rowcatmap f xs@(_:_) = rowcat (map f xs); + +colcatmap f [] = {}; +colcatmap f xs@(_:_) = colcat (map f xs); + +/* Transpose a matrix. */ + +private matrix_transpose; +extern expr* matrix_transpose(expr *x); + +x::matrix' = matrix_transpose x; + +/* Reverse a matrix. 'rowrev' reverses the rows, 'colrev' the columns, + 'reverse' both dimensions. */ + +rowrev x::matrix = rowcat (reverse (rows x)); +colrev x::matrix = colcat (reverse (cols x)); +reverse x::matrix = rowrev (colrev x); + +/* catmap et al on matrices. This allows list and matrix comprehensions to + draw values from matrices as well as from lists, treating the matrix as a + flat list of its elements. */ + +catmap f x::matrix = catmap f (list x); +rowcatmap f x::matrix = rowcat (map f (list x)); +colcatmap f x::matrix = colcat (map f (list x)); + +/* Implementations of the other customary list operations, so that these can + be used on matrices, too. These operations treat the matrix essentially as + if it was a flat list of its elements. Aggregate results are then converted + back to matrices with the appropriate dimensions. (This depends on the + particular operation; functions like map and zip keep the dimensions of the + input matrix intact, while other functions like filter, take or scanl + always return a flat row vector. Also note that the zip-style operations + require that the row sizes of all arguments match.) */ + +cycle x::matrix = cycle (list x); +cyclen n::int x::matrix = cyclen n (list x) if not null x; + +all p x::matrix = all p (list x); +any p x::matrix = any p (list x); +do f x::matrix = do f (list x); +drop k::int x::matrix = x!!(k..#x-1); +dropwhile p x::matrix = colcat (dropwhile p (list x)); +filter p x::matrix = colcat (filter p (list x)); +foldl f a x::matrix = foldl f a (list x); +foldl1 f x::matrix = foldl1 f (list x); +foldr f a x::matrix = foldr f a (list x); +foldr1 f x::matrix = foldr1 f (list x); +head x::matrix = x!0 if not null x; +init x::matrix = x!!(0..#x-2) if not null x; +last x::matrix = x!(#x-1) if not null x; +map f x::matrix = flip redim (dim x) $ colcat (map f (list x)); +scanl f a x::matrix = colcat (scanl f a (list x)); +scanl1 f x::matrix = colcat (scanl1 f (list x)); +scanr f a x::matrix = colcat (scanr f a (list x)); +scanr1 f x::matrix = colcat (scanr1 f (list x)); +take k::int x::matrix = x!!(0..k-1); +takewhile p x::matrix = colcat (takewhile p (list x)); +tail x::matrix = x!!(1..#x-1) if not null x; + +zip x::matrix y::matrix = flip redim (dim x!1) $ + colcat (zip (list x) (list y)) + if dim x!1==dim y!1; +zip3 x::matrix y::matrix z::matrix + = flip redim (dim x!1) $ + colcat (zip3 (list x) (list y) (list z)) + if dim x!1==dim y!1 && dim x!1==dim z!1; +zipwith f x::matrix y::matrix + = flip redim (dim x!1) $ + colcat (zipwith f (list x) (list y)) + if dim x!1==dim y!1; +zipwith3 f x::matrix y::matrix z::matrix + = flip redim (dim x!1) $ + colcat (zipwith3 f (list x) (list y) (list z)) + if dim x!1==dim y!1 && dim x!1==dim z!1; +dowith f x::matrix y::matrix + = dowith f (list x) (list y) + if dim x!1==dim y!1; +dowith3 f x::matrix y::matrix z::matrix + = dowith3 f (list x) (list y) (list z) + if dim x!1==dim y!1 && dim x!1==dim z!1; + +unzip x::matrix = flip redim (dim x) (colcat u), + flip redim (dim x) (colcat v) + when u,v = unzip (list x) end; +unzip3 x::matrix = flip redim (dim x) (colcat u), + flip redim (dim x) (colcat v), + flip redim (dim x) (colcat w) + when u,v,w = unzip3 (list x) end; + +/* Matrix conversions. These convert between different types of numeric + matrices. You can also extract the real and imaginary parts of a (complex) + matrix. */ + +private matrix_double matrix_complex matrix_int; +extern expr* matrix_double(expr *x), expr* matrix_complex(expr *x), + expr* matrix_int(expr *x); + +dmatrix x::matrix = matrix_double x if imatrixp x || dmatrixp x; +imatrix x::matrix = matrix_int x if imatrixp x || dmatrixp x; +cmatrix x::matrix = matrix_complex x if nmatrixp x; + +private matrix_re matrix_im; +extern expr* matrix_re(expr *x), expr* matrix_im(expr *x); + +re x::matrix = matrix_re x if nmatrixp x; +im x::matrix = matrix_im x if nmatrixp x; + +/* 'Pack' a matrix. This creates a copy of the matrix which has the data in + contiguous storage. If possible, it also frees up extra memory if the + matrix was created as a slice from a bigger matrix. The 'packed' predicate + can be used to verify whether a matrix is already packed. */ + +pack x::matrix = colcat [x,{}]; +packed x::matrix = stride x==dim x!1; + +/* Convert a matrix to a pointer. This returns a pointer to the underlying C + array, which allows you to change the data in-place by shelling out to C + functions, so beware. You also need to be careful when passing such a + pointer to C functions if the underlying data is non-contiguous; when in + doubt use the 'pack' function from above to place the data in contiguous + storage first. */ + +pointer x::matrix = pure_pointerval x; + +/* Matrix comparisons. */ + +x::matrix == y::matrix = x === y + if nmatrixp x && matrix_type x == matrix_type y; +// mixed numeric cases + = cmatrix x === y if nmatrixp x && cmatrixp y; + = x === cmatrix y if cmatrixp x && nmatrixp y; + = dmatrix x === y if imatrixp x && dmatrixp y; + = x === dmatrix y if dmatrixp x && imatrixp y; +// comparisons with symbolic matrices + = 0 if dim x != dim y; + = compare 0 with + compare i::int = 1 if i>=n; + = 0 if x!i != y!i; + = compare (i+1); + end when n::int = #x end; + +x::matrix != y::matrix = not x == y; Modified: pure/trunk/lib/prelude.pure =================================================================== --- pure/trunk/lib/prelude.pure 2008-09-23 09:15:34 UTC (rev 835) +++ pure/trunk/lib/prelude.pure 2008-09-23 10:31:58 UTC (rev 836) @@ -74,7 +74,7 @@ Note that the math and system modules are *not* included here, so you have to do that yourself if your program requires any of those operations. */ -using primitives, strings; +using primitives, matrices, strings; /* Basic combinators. */ Modified: pure/trunk/lib/primitives.pure =================================================================== --- pure/trunk/lib/primitives.pure 2008-09-23 09:15:34 UTC (rev 835) +++ pure/trunk/lib/primitives.pure 2008-09-23 10:31:58 UTC (rev 836) @@ -41,33 +41,8 @@ doublep x = case x of _::double = 1; _ = 0 end; stringp x = case x of _::string = 1; _ = 0 end; pointerp x = case x of _::pointer = 1; _ = 0 end; - -/* Matrix predicates. The numeric matrix types will only be available if the - interpreter was built with support for the GNU Scientific Library (GSL). - This is the case iff the global gsl_version variable is predefined by the - interpreter. */ - -extern int matrix_type(expr* x); - matrixp x = case x of _::matrix = 1; _ = 0 end; -dmatrixp x = case x of _::matrix = matrix_type x==1; _ = 0 end; -cmatrixp x = case x of _::matrix = matrix_type x==2; _ = 0 end; -imatrixp x = case x of _::matrix = matrix_type x==3; _ = 0 end; -/* The nmatrixp predicate checks for any kind of numeric (double, complex or - int) matrix, smatrix for symbolic matrices. */ - -nmatrixp x = case x of _::matrix = matrix_type x>=1; _ = 0 end; -smatrixp x = case x of _::matrix = matrix_type x==0; _ = 0 end; - -/* Pure represents row and column vectors as matrices with 1 row or column, - respectively. The following predicates allow you to check for these special - kinds of matrices. */ - -vectorp x = matrixp x && (n==1 || m==1 when n::int,m::int = dim x end); -rowvectorp x = matrixp x && dim x!0==1; -colvectorp x = matrixp x && dim x!1==1; - /* Predicates to check for function objects, global (unbound) variables, function applications, proper lists, list nodes and tuples. */ @@ -117,8 +92,7 @@ pointer x::int | pointer x::bigint | pointer x::double | -pointer x::string | -pointer x::matrix = pure_pointerval x; +pointer x::string = pure_pointerval x; /* Convert signed (8/16/32/64) bit integers to the corresponding unsigned quantities. These functions behave as if the value was "cast" to the @@ -410,266 +384,6 @@ x::pointer==y::pointer = bigint x == bigint y; x::pointer!=y::pointer = bigint x != bigint y; -/* Basic matrix operations: size, dimensions and indexing. */ - -private matrix_size matrix_dim matrix_stride; -extern int matrix_size(expr *x), int matrix_stride(expr *x); -extern expr* matrix_dim(expr *x); - -null x::matrix = #x==0; -#x::matrix = matrix_size x; -dim x::matrix = matrix_dim x; -stride x::matrix = matrix_stride x; - -private matrix_elem_at matrix_elem_at2; -extern expr* matrix_elem_at(expr* x, int i); -extern expr* matrix_elem_at2(expr* x, int i, int j); - -x::matrix!i::int = matrix_elem_at x i if i>=0 && i<#x; - = throw out_of_bounds otherwise; - -x::matrix!(i::int,j::int) - = matrix_elem_at2 x i j - if (i>=0 && i<n && j>=0 && j<m - when n::int,m::int = dim x end); - = throw out_of_bounds otherwise; - -/* Matrix slices. */ - -x::matrix!!(ns,ms) = case ns,ms of - // optimize the case of contiguous slices - ns@(n:_),ms@(m:_) = submat x (n,m) (#ns,#ms) - if cont ns && cont ms; - _ = colcatmap (mth (rowcatmap (nth x) ns)) ms; - end with - cont [n] = 1; - cont (n::int:ns@(m::int:_)) = cont ns if m==n+1; - cont _ = 0 otherwise; - nth x n = catch (cst {}) (row x n); - mth x m = catch (cst {}) (col x m); - end; -x::matrix!!ns = if packed x then rowvector x!!([0],ns) - else colcatmap (nth x) ns with - nth x n = catch (cst {}) {x!n}; - end; - -/* Extract rows and columns from a matrix. */ - -private matrix_slice; -extern expr* matrix_slice(expr* x, int i1, int j1, int i2, int j2); - -row x::matrix i::int = if i>=0 && i<n then matrix_slice x i 0 i (m-1) - else throw out_of_bounds - when n::int,m::int = dim x end; - -col x::matrix j::int = if j>=0 && j<m then matrix_slice x 0 j (n-1) j - else throw out_of_bounds - when n::int,m::int = dim x end; - -rows x::matrix = map (row x) (0..n-1) when n::int,_ = dim x end; - -cols x::matrix = map (col x) (0..m-1) when _,m::int = dim x end; - -/* Convert a matrix to a list and vice versa. list x converts a matrix x to a - flat list of its elements, while list2 converts it to a list of lists. - Conversely, matrix xs converts a list of lists or matrices specifying the - rows of the matrix to the corresponding matrix; otherwise, the result is a - row vector. NOTE: The matrix function may throw a 'bad_matrix_value x' in - case of dimension mismatch, where x denotes the offending submatrix. */ - -list x::matrix = [x!i|i=0..#x-1]; -list2 x::matrix = [[x!(i,j)|j=0..m-1]|i=0..n-1] - when n::int,m::int = dim x end; - -matrix [] = {}; -matrix xs@(x:_) = rowcatmap colcat xs if all listp xs; - = rowcat xs if any matrixp xs; - = colcat xs otherwise; - -/* Extract (sub-,super-) diagonals from a matrix. Sub- and super-diagonals for - k=0 return the main diagonal. Indices for sub- and super-diagonals can also - be negative, in which case the corresponding super- or sub-diagonal is - returned instead. In each case the result is a row vector. */ - -private matrix_diag matrix_subdiag matrix_supdiag; -extern expr* matrix_diag(expr* x) = diag; -extern expr* matrix_subdiag(expr* x, int k) = subdiag; -extern expr* matrix_supdiag(expr* x, int k) = supdiag; - -/* Extract a submatrix of a given size at a given offset. The result shares - the underlying storage with the input matrix (i.e., matrix elements are - *not* copied) and so this is a comparatively cheap operation. */ - -submat x::matrix (i::int,j::int) (n::int,m::int) - = matrix_slice x i j (i+n-1) (j+m-1); - -/* Change the dimensions of a matrix without changing its size. The total - number of elements must match that of the input matrix. Reuses the - underlying storage of the input matrix if possible. */ - -private matrix_redim; -extern expr* matrix_redim(expr* x, int n, int m); - -redim x::matrix (n::int,m::int) - = matrix_redim x n m if n>=0 && m>=0 && n*m==#x; - -/* You can also redim a matrix to a given positive row size. In this case the - row size must divide the total size of the matrix, */ - -redim x::matrix m::int = redim x (#x div m,m) if m>0 && #x mod m==0; - -/* Convenience functions for converting a matrix to a row or column vector. */ - -rowvector x::matrix = redim x (#x); -colvector x::matrix = redim x 1; - -/* Construct matrices from lists of rows and columns. These take either - scalars or submatrices as inputs; corresponding dimensions must match. - rowcat combines submatrices vertically, like {x;y}; colcat combines them - horizontally, like {x,y}. NOTE: Like the built-in matrix constructs, these - operations may throw a 'bad_matrix_value x' in case of dimension mismatch, - where x denotes the offending submatrix. */ - -extern expr* matrix_rows(expr *x) = rowcat; -extern expr* matrix_columns(expr *x) = colcat; - -/* Combinations of rowcat/colcat and map. */ - -rowcatmap f [] = {}; -rowcatmap f xs@(_:_) = rowcat (map f xs); - -colcatmap f [] = {}; -colcatmap f xs@(_:_) = colcat (map f xs); - -/* 'Pack' a matrix. This creates a copy of the matrix which has the data in - contiguous storage. If possible, it also frees up extra memory if the - matrix was created as a slice from a bigger matrix. The 'packed' predicate - can be used to verify whether a matrix is already packed. */ - -pack x::matrix = colcat [x,{}]; -packed x::matrix = stride x==dim x!1; - -/* Transpose a matrix. */ - -private matrix_transpose; -extern expr* matrix_transpose(expr *x); - -x::matrix' = matrix_transpose x; - -/* Reverse a matrix. rowrev reverses the rows, colrev the columns, reverse - both dimensions. */ - -rowrev x::matrix = rowcat (reverse (rows x)); -colrev x::matrix = colcat (reverse (cols x)); -reverse x::matrix = rowrev (colrev x); - -/* catmap et al on matrices. This allows list and matrix comprehensions to - draw values from matrices just as well as from lists, treating the matrix - as a flat list of its elements. */ - -catmap f x::matrix = catmap f (list x); -rowcatmap f x::matrix = rowcat (map f (list x)); -colcatmap f x::matrix = colcat (map f (list x)); - -/* Implementations of the other customary list operations, so that these can - be used on matrices, too. These operations treat the matrix essentially as - if it was a flat list of its elements. Aggregate results are then converted - back to matrices with the appropriate dimensions. (This depends on the - operation; operations like map and zip keep the dimensions of the input - matrix intact, while other functions like filter, take or scanl always - return a flat row vector. Also note that the zip-style operations require - that the row sizes of all arguments match.) */ - -cycle x::matrix = cycle (list x); -cyclen n::int x::matrix = cyclen n (list x) if not null x; - -all p x::matrix = all p (list x); -any p x::matrix = any p (list x); -do f x::matrix = do f (list x); -drop k::int x::matrix = x!!(k..#x-1); -dropwhile p x::matrix = colcat (dropwhile p (list x)); -filter p x::matrix = colcat (filter p (list x)); -foldl f a x::matrix = foldl f a (list x); -foldl1 f x::matrix = foldl1 f (list x); -foldr f a x::matrix = foldr f a (list x); -foldr1 f x::matrix = foldr1 f (list x); -head x::matrix = x!0 if not null x; -init x::matrix = x!!(0..#x-2) if not null x; -last x::matrix = x!(#x-1) if not null x; -map f x::matrix = flip redim (dim x) $ colcat (map f (list x)); -scanl f a x::matrix = colcat (scanl f a (list x)); -scanl1 f x::matrix = colcat (scanl1 f (list x)); -scanr f a x::matrix = colcat (scanr f a (list x)); -scanr1 f x::matrix = colcat (scanr1 f (list x)); -take k::int x::matrix = x!!(0..k-1); -takewhile p x::matrix = colcat (takewhile p (list x)); -tail x::matrix = x!!(1..#x-1) if not null x; - -zip x::matrix y::matrix = flip redim (dim x!1) $ - colcat (zip (list x) (list y)) - if dim x!1==dim y!1; -zip3 x::matrix y::matrix z::matrix - = flip redim (dim x!1) $ - colcat (zip3 (list x) (list y) (list z)) - if dim x!1==dim y!1 && dim x!1==dim z!1; -zipwith f x::matrix y::matrix - = flip redim (dim x!1) $ - colcat (zipwith f (list x) (list y)) - if dim x!1==dim y!1; -zipwith3 f x::matrix y::matrix z::matrix - = flip redim (dim x!1) $ - colcat (zipwith3 f (list x) (list y) (list z)) - if dim x!1==dim y!1 && dim x!1==dim z!1; -dowith f x::matrix y::matrix - = dowith f (list x) (list y) - if dim x!1==dim y!1; -dowith3 f x::matrix y::matrix z::matrix - = dowith3 f (list x) (list y) (list z) - if dim x!1==dim y!1 && dim x!1==dim z!1; - -unzip x::matrix = flip redim (dim x) (colcat u), - flip redim (dim x) (colcat v) - when u,v = unzip (list x) end; -unzip3 x::matrix = flip redim (dim x) (colcat u), - flip redim (dim x) (colcat v), - flip redim (dim x) (colcat w) - when u,v,w = unzip3 (list x) end; - -/* Matrix conversions. */ - -private matrix_double matrix_complex matrix_int; -extern expr* matrix_double(expr *x), expr* matrix_complex(expr *x), - expr* matrix_int(expr *x); - -dmatrix x::matrix = matrix_double x if imatrixp x || dmatrixp x; -imatrix x::matrix = matrix_int x if imatrixp x || dmatrixp x; -cmatrix x::matrix = matrix_complex x if nmatrixp x; - -private matrix_re matrix_im; -extern expr* matrix_re(expr *x), expr* matrix_im(expr *x); - -re x::matrix = matrix_re x if nmatrixp x; -im x::matrix = matrix_im x if nmatrixp x; - -/* Matrix comparisons. */ - -x::matrix == y::matrix = x === y - if nmatrixp x && matrix_type x == matrix_type y; -// mixed numeric cases - = cmatrix x === y if nmatrixp x && cmatrixp y; - = x === cmatrix y if cmatrixp x && nmatrixp y; - = dmatrix x === y if imatrixp x && dmatrixp y; - = x === dmatrix y if dmatrixp x && imatrixp y; -// comparisons with symbolic matrices - = 0 if dim x != dim y; - = compare 0 with - compare i::int = 1 if i>=n; - = 0 if x!i != y!i; - = compare (i+1); - end when n::int = #x end; - -x::matrix != y::matrix = not x == y; - /* IEEE floating point infinities and NaNs. Place these after the definitions of the built-in operators so that the double arithmetic works. */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |