abs_mat.sa


Generated by gen_html_sa_files from ICSI. Contact gomes@icsi.berkeley.edu for details
 
---------------------------> Sather 1.1 source file <--------------------------
-- Author: Matt Kennel <mbk@inls.ucsd.edu>
-- modified, integrated by gomes@icsi.berkeley.edu
-- Copyright (C) 1995, Oak Ridge National Laboratory
-- $Id: abs_mat.sa,v 1.2 1996/07/18 01:00:39 davids Exp $
--
-- COPYRIGHT NOTICE: This code is provided WITHOUT ANY WARRANTY
-- and is subject to the terms of the SATHER LIBRARY GENERAL PUBLIC
-- LICENSE contained in the file: sather/doc/license.txt of the
-- Sather distribution. The license is also available from ICSI,
-- 1947 Center St., Suite 600, Berkeley CA 94704, USA. 
--


abstract class $MAT{ET<$NFE{ET},VT<$VEC{ET,VT},MT<$MAT{ET,VT,MT}}

abstract class $MAT{ET<$NFE{ET},VT<$VEC{ET,VT},MT<$MAT{ET,VT,MT}} -- -- The specification of a general Basic matrix. -- -- "ET" is the *element_type* which must be a $NFE, a.k.a. numerical -- field element. -- -- "VT" is its associated vector type, needed to -- define matrix-vector operations. -- -- "MT" ought to be the same matrix type as the concrete implementations -- that subtype from this type. -- -- This appears to be somewhat odd, but it serves to give a concrete type -- so as to allow proper covariance in arguments. Just as a matrix/ -- vector multiplication method needs to have a specific vector type -- to go along with the matrix type, matrix/matrix operations like -- multiplication need to be defined to accept arguments of the same -- matrix type as "self". For example, a concrete matrix class -- implementaion MAT_DC (double complex dense matrix) would need to -- define "plus(arg:MAT_DC)", allowing one to add a MATDC to another, -- but not allowing one to add a MAT_DC to a MAT_UT_F (upper triangular). -- The subtyping clause of MAT_DC would then read like -- -- class MAT_DC < $MAT{CPXD,VEC_DC,MAT_DC} is ... -- -- In this way, this $MAT{ET,VT,MT} class is less useful for -- allowing run-time substitutability of many implementations than -- as a precise specification of responsibilities of its subtypes. -- -- However, both Basic and Fancy concrete matrices may subtype -- from $MAT{*,*,*}. -- -- If proven to be useful, more general $MAT{} abstract types above -- this one that -- do not have covarying features (and thus be useful for run-time -- polymorphism) may be written in the future. -- -- Routine naming convention. -- ========================== -- The idea is that reading the routine name in order ought to generate -- the actual meaning of the operation. -- -- A := B{^T} OP {s*}C{^T} -- -- (brackets denote optional operation.) -- -- For A,B,C: if B=self, write nothing. If a matrix argument then write -- "arg". If transpose is desired append "arg" with "_trans", or just -- add "trans" if self. If an argument is a vector type then use -- "vec" instead of "arg". -- -- For OP, write "plus" for addition, "minus" for subtraction and -- "times" for multiplication. -- -- If "self" is modified, overall routine name should have "inplace_" in -- front. -- -- If there's a scalar multiplication, insert "scaled_" before the second -- argument. -- -- If the routine modifies data in some reference argument, -- then "into" denotes the argument that will be changed. -- -- -- -- -- Example: A := B^T - C. -- B /= self, so "arg". Transposed argument. "arg_trans". -- operation is subtraction. "arg_trans_minus". -- another argument, so "arg_trans_minus_arg(arg1,arg2:MT)" -- is the signature. -- -- Example: B := B + s*C^T -- Modifies self. "inplace_". B is self so nothing. -- "inplace_". operation is addition. "inplace_plus". -- scalar multiplication. "inplace_plus_scaled". -- matrix argument, transposed. -- "inplace_plus_scaled_arg_trans(s:ET,arg:MT)" -- is the routine signature. is -- -- COMMON OPERATIONS. -- nr:INT; -- number of rows. nc:INT; -- number of columns. size: INT; -- Total number of elements (nr*nc) size1:INT; -- First dimension (nr) size2:INT; -- Second dimension (nc) is_same_shape(arg:MT):BOOL; -- true if arg has the same dimensions as self. is_same_shape_trans(arg:MT):BOOL; -- true if arg^T has the same dimensions as self. fits(arg:MT):BOOL; -- is the total number of elements in 'arg' the same as that in self? is_eq(arg:MT):BOOL; -- equal to create(nr,nc:INT):MT; -- -- result := "new matrix, 'nr' x 'nc'" -- -- Example: m ::= #MAT_D(10,4); create(arg:MT):MT; -- -- result := "matrix, same size as 'arg', -- data initialized to *zero*." -- -- Example: m2 ::= #MAT_D(m); str:STR; -- -- A string representation of self. Creates return value. -- copy:MT; -- -- result := copy of self. Creates new return value. -- -- Example: m2 ::= m.copy; contents(arg:MT); -- -- "array portion of self" := "array portion of arg" -- -- Example: m2.contents(m); -- With syntax extension, m2.contents := m; Synonym for -- "inplace_contents". inplace_contents(arg:MT); -- -- "array portion of self" := "array portion of arg" -- -- Example: m2.inplace_contents(m); inplace_contents_from_function(function:ROUT{INT,INT}:ET); -- -- "array portion of self"(i,j) = function(i,j) all i,j -- -- Example: -- fun ::= #ROUT( MY_CLASS::hilbert_elements(_:INT,_:INT) ) -- m:MAT; m.inplace_contents_from_function(fun) ident:MT; -- -- result "new matrix same size as self " := "identity matrix" -- -- Example: m2 ::= m.id; -- This is the identity under multiplication, of course. inplace_ident; -- -- "array portion of self" := "identity matrix" -- -- Example: m.inplace_ident; trans:MT; -- -- result (created) := "transpose of self" -- -- Example: mt ::= m.trans; inplace_trans; -- -- "array portion of self " := "transpose of self " -- -- Example: m.inplace_trans; inplace_arg_trans(arg:MT); -- -- "array portion of self" := "transpose of arg" -- -- Example: m2:MAT_D; m.inplace_arg_trans(m2); -- times_elt(s:ET):MT; -- -- result (created) := self * s; -- -- Example: m2 ::= m * 0.40d0; -- Sugar for "mat * scalar", synonym for 'scaled_by'. scaled_by(s:ET):MT; -- -- result (created) := self * s; -- -- Example: m2 ::= m * 0.40d0; -- inplace_scaled_by(s:ET); -- -- self := self * s; -- -- Example: m.inplace_scaled_by(4.0d0); inplace_elements(s:ET); -- -- self := s "for all elements" -- Example: m.inplace_elements(0.0) -- clear matrix. -- -- ELEMENT ACCESS -- aget(i,j:INT):ET; -- -- result := self[i,j]; -- -- Example: m:MAT_D; s:FLTD := m[1,2]; aset(i,j:INT,s:ET); -- -- self[i,j] := s; -- -- Example: m:MAT_D; m[1,2] := 3.0d0; -- -- BASIC MATRIX/MATRIX ADDITIVE OPERATIONS. -- plus(arg:MT):MT; -- -- result (created) := self + arg. -- -- Example: a,b,c:MAT_D; c := a + b; -- Sugar for "a + b", synonym for "plus_arg". plus_arg(arg:MT):MT; -- -- result (created) := self + arg. -- -- Example: a,b,c:MAT_D; c := a + b; minus(arg:MT):MT; -- -- result (created) := self + arg. -- -- Example: a,b,c:MAT_D; c := a - b; -- Sugar for "a - b", synonym for "minus_arg". minus_arg(arg:MT):MT; -- -- result (created) := self - arg. -- -- Example: a,b,c:MAT_D; c := a - b; inplace_plus_arg(arg:MT); -- -- self := self + arg. -- -- Example: a,b:MAT_D; a.inplace_plus_arg(b); inplace_minus_arg(arg:MT); -- -- self := self - arg. -- -- Example: a,b:MAT_D; a.inplace_minus_arg(b); plus_arg_trans(arg:MT):MT; -- -- result (created) := self + arg^T; -- -- Example: a,b,c:MAT_D; c := a.plus_arg_trans(b); minus_arg_trans(arg:MT):MT; -- -- result (created) := self - arg^T; -- -- Example: a,b,c:MAT_D; c := a.plus_arg_trans(b); inplace_plus_arg_trans(arg:MT); -- -- self := self + arg^T; -- -- Example: a,b,c:MAT_D; c := a.plus_arg_trans(b); inplace_minus_arg_trans(arg:MT); -- -- result (created) := self - arg^T; -- -- Example: a,b,c:MAT_D; c := a.plus_arg_trans(b); inplace_arg_plus_arg(arg1,arg2:MT); -- -- self := arg1 + arg2 -- -- Example: a,b,c:MAT_D; c.inplace_arg_plus_arg(a,b); inplace_arg_minus_arg(arg1,arg2:MT); -- -- self := arg1 - arg2 -- -- Example: a,b,c:MAT_D; c.inplace_arg_minus_arg(a,b); inplace_arg_plus_arg_trans(arg1,arg2:MT); -- -- self := arg1 + arg2^T; -- -- Example: a,b,c:MAT_D; c.inplace_arg_plus_arg_trans(a,b); -- Requires: self/=arg2. inplace_arg_minus_arg_trans(arg1,arg2:MT); -- -- self := arg1 - arg2^T; -- -- Example: a,b,c:MAT_D; c.inplace_arg_minus_arg_trans(a,b); -- Requires: self/=arg2. inplace_arg_trans_plus_arg_trans(arg1,arg2:MT); -- -- self := arg1^T + arg2^T; -- -- Example: a,b,c:MAT_D; c.inplace_arg_trans_plus_arg_trans(a,b); -- Requires: self /= arg1, self/=arg2. inplace_arg_trans_minus_arg_trans(arg1,arg2:MT); -- -- self := arg1^T - arg2^T; -- -- Example: a,b,c:MAT_D; c.inplace_arg_trans_minus_arg_trans(a,b); -- Requires: self /= arg1, self/=arg2. -- -- Note what is missing: -- -- "inplace_arg_trans_plus_arg" is not needed given commutative matrix -- elements, it is equivalent to "inplace_arg_plus_arg_trans" switching -- the order of the arguments. -- -- "inplace_trans_plus_arg" (i.e. self := self^T + arg) cannot really -- be implemented more efficiently than self := self^T, self := self+arg; -- Correct me if I'm wrong. -- -- MATRIX ADDITIVE OPERATIONS WITH SCALAR MULTIPLICATION -- plus_scaled_arg(s:ET,arg:MT):MT; -- -- result := self + s*arg; -- -- Example: a,b,c:MAT_D; c := a.plus_scaled_arg(3.0d0,b); inplace_plus_scaled_arg(s:ET,arg:MT); -- -- self := self + s*arg; -- -- Example: a,b:MAT_D; a.inplace_plus_scaled_arg(3.0d0,b); plus_scaled_arg_trans(s:ET,arg:MT):MT; -- -- result := self + s*arg^T; -- -- Example: a,b,c:MAT_D; c := a.plus_scaled_arg_trans(3.0d0,b); inplace_plus_scaled_arg_trans(s:ET,arg:MT); -- -- self := self + s*arg^T; -- -- Example: a,b:MAT_D; a.inplace_plus_scaled_arg_trans(3.0d0,b); -- triplets inplace_arg_plus_scaled_arg(arg1:MT,s:ET,arg2:MT); -- -- self := arg1 + s*arg2; -- -- Example: a,b,c:MAT_D; c.inplace_arg_plus_scaled_arg(a,3.1415d0,b); inplace_arg_plus_scaled_arg_trans(arg1:MT,s:ET,arg2:MT); -- -- self := arg1 + s*arg2^T; -- -- Example: a,b,c:MAT_D; -- c.inplace_arg_plus_scaled_arg_trans(a,3.1415d0,b); -- -- MULTIPLICATIVE OPERATIONS -- times(arg:MT):MT; -- -- result := self * arg. -- -- Example: c ::= a * b; -- Sugar for "a * b" trans_times_arg(arg:MT):SAME; -- -- result := self^T * arg -- -- Example: c ::= a.trans_times_arg(b); times_arg_trans(arg:MT):SAME; -- -- result := self * arg^T -- -- Example: c ::= a.times_arg_trans(b); trans_times_arg_trans(arg:MT):SAME; -- -- result := self^T * arg^T; -- -- Example: c ::= a.trans_times_arg_trans(b); -- in place versions inplace_arg_times_arg(arg1,arg2:MT); -- -- self := arg1 * arg2. -- -- Example: c ::= #MATD(a); c.inplace_arg_times_arg(a,b); inplace_arg_trans_times_arg(arg1,arg2:MT); -- -- self := arg1^T * arg2; -- -- Example: c ::= #MATD(a); c.inplace_arg_trans_times_arg(a,b); inplace_arg_times_arg_trans(arg1,arg2:MT); -- -- self := arg1 * arg2^T; -- -- Example: c ::= #MATD(a); c.inplace_arg_times_arg_trans(a,b); inplace_arg_trans_times_arg_trans(arg1,arg2:MT); -- -- self := arg1^T * arg2^T; -- -- Example: c ::= #MATD(a); c.inplace_arg_trans_times_arg_trans(a,b); -- Multiplicative operations with embedded scalar multiplication -- are not needed; the scalar can be distributed out of the multiplication, -- and "inplace_scaled_by(s)" used on the result. It may be faster however, -- to provide them. I'd like input on this issue. -- -- MATRIX/VECTOR MULTIPLICATION. -- times_vec(arg:VT):VT; -- -- result := self * arg; -- -- Example: a:MAT_D; b:VEC_D; c:VEC_D:= a * b; -- Sugar for "a * b" trans_times_vec(arg:VT):VT; -- -- result := self^T * arg. -- -- Example: a:MAT_D; b:VEC_D; c:VEC_D:= a.trans_times_vec(b); times_vec_into_vec(arg:VT,dest:VT); -- -- dest := self * arg; -- -- Example: a:MAT_D; b,c:VEC_D; a.times_vec_into_vec(b,c); trans_times_vec_into_vec(arg:VT,dest:VT); -- -- dest := self^T * arg; -- -- Example: a:MAT_D; b,c:VEC_D; a.trans_times_vec_into_vec(b,c); times_scaled_vec_into_vec(s:ET,arg:VT,dest:VT); -- -- dest := self * s*arg; -- -- Example: a:MAT_D; b,c:VEC_D; a.times_scaled_vec_into_vec(-1.0, -- b,c); trans_times_scaled_vec_into_vec(s:ET,arg:VT,dest:VT); -- -- dest := self^T * s*arg; -- -- Example: a:MAT_D; b,c:VEC_D; a.trans_times_scaled_vec_ -- into_vec(-2.0,b,c); -- -- OTHER MATRIX/VECTOR ROUTINES -- inplace_plus_scaled_vec_times_vec(s:ET,v1,v2:VT); -- -- self := self + s*v1*v2^T -- (Add scaled outer product of v1 and v2 to self. A BLAS operation) -- -- Example: covariance_mat:MAT_D; datum:VEC_D; -- covariance_mat.inplace_plus_scaled_vec_times_vec(1.0/n.fltd, -- datum,datum); -- -- MATRIX/VECTOR MANIPULATION -- create_col_matrix(arg:VT):SAME; -- -- Create a "column" matrix, an N by 1 matrix with -- elements of arg, and N the size of arg. -- -- Example: v:VEC_D; m ::= MAT_D::create_col(v); create_row_matrix(arg:VT):SAME; -- -- Create a "row" matrix, a 1 by N matrix with -- elements of arg, and N the size of arg. -- -- Example: v:VEC_D; m ::= MAT_D::create_(row); col(i:INT):VT; -- -- result := the i'th column of self into a vector. -- -- Example: v ::= m.col(4); row(i:INT):VT; -- -- result := "ith row of self as a vector" -- -- Example: v ::= m.row(4); col(i:INT,v:VT); -- -- Set the i'th col of self to v -- -- Example: m.col(4,v); row(i:INT,v:VT); -- -- Set the i'th row of self to v. -- -- Example: v:VEC_D; m.row(4,v); -- With proposed syntax extension: m.row(4) := v; inplace_scaled_col(s:ET,i:INT); -- -- Scale the i'th column of self by "s". -- -- Example: v:MAT_D; m.scale_col(4,3.1415d0); inplace_scaled_row(s:ET,i:INT); -- -- Scale the i'th row of self by "s". -- -- Example: v:MAT_D; m.scale_row(4,3.1415d0); inplace_col_plus_scaled_vec(i:INT,s:ET,v:VT); -- -- Add "s*v" to ith column of self. -- -- Example: m:MAT_D; v:VEC_D; m.inplace_col_plus_scaled_vec(4,2.0,v); inplace_row(i: INT, v:VT); -- -- Set ith row of self to "v" -- -- Example: v:VEC; m.inplace_row_scaled(v); inplace_row_plus_scaled_vec(i:INT,s:ET,v:VT); -- -- Add "s*v" to ith row of self. -- -- Example: m:MAT_D; v:VEC_D; -- m.inplace_row_plus_scaled_vec(4,2.0,v); inplace_swapped_col(i:INT,v:VT); -- -- swap "i"'th column of self with "v". -- -- Example: m:MAT_D; v:VEC_D; m.swap_column(4,v); inplace_swapped_row(i:INT,v:VT); -- -- swap "i"'th row of self with "v". -- -- Example: m:MAT_D; v:VEC_D; m.swap_row(4,v); -- -- MISC MATRIX MANIPULATION -- submatrix(lr,ur:INT, lc,uc:INT):SAME; -- -- Result a subsection of self[lr..ur,lc..uc] in a -- newly created return value. -- -- Example: m:MAT_D; m2 ::= m.submatrix(0,9,0,1); -- m2 is 10 x 2 inplace_submatrix_to_arg(lr,ur:INT, lc,uc:INT,arg:MT); -- -- Set a subsection of self[lr..ur,lc..uc] to the argument. -- -- Example: m:MAT_D; m2.submatrix(0,9,0,1,m); -- Or with syntax extension, m2.submatrix(0,9,0,1) := m; inplace_swapped(arg:MT); -- -- Swap contents of self with same sized "arg". -- -- Example: m2.swap(m1); -- -- ITERS -- {somebody suggest some good ones please} -- ind1!:INT; -- Yield each value of the first index in order. The rows ind2!:INT; -- Yield each value of the second index in order. The columns diag_elt!:ET; -- Yield values along the diagonal (square in smaller dimension) inplace_diag_elt!(val:ET); -- Set values along the diagonal (square in smaller dimension) inds!:TUP{INT,INT}; -- Yield tuples of the indices of self in same order as storage. elt!: ET; -- Yield all elements in storage order, usually column-major for -- new BLAS compatible matrices. inplace_elt!(val:ET); -- Set elements in storage order elt1!(once i1:INT):ET; -- Yield elements by varying index 2 and holding index 1 at `i1'. -- The elements of a row "i1" -- this is the same as row_elt! elt2!(once i2:INT):ET; -- Yield elements by varying index 1 and holding index 2 at `i2'. -- The elements of a "column" i2 -- this is the same as col_elt! row_elt!(once row:INT):ET; -- Yield elements by varying index 2 and holding index 1 at `row'. -- The elements of a row "row" col_elt!(once col:INT):ET; -- Yield elements by varying index 1 and holding index 2 at `col'. -- The elements of a "column" col end; -- type $MAT{ET,VT,MT}