Hi all, I have enhanved TwoDimensionalArray to include arithmetic for block matrices and have an operation array2 (similar to matrix for Matrix) for easy creation of two-dimensional array and would suggest to include this into the next version:
(1) -> )r array2-jg-test A11 := matrix [[2]] (1) [2] Type: Matrix(Integer) A12 := matrix [[1,2,3]] (2) [1 2 3] Type: Matrix(Integer) A21 := matrix [[1],[7]] +1+ (3) | | +7+ Type: Matrix(Integer) A22 := matrix [[-3,1,0],[5,5,3]] +- 3 1 0+ (4) | | + 5 5 3+ Type: Matrix(Integer) A := array2([[A11, A12],[A21, A22]])$ARRAY2(Matrix Integer) +[2] [1 2 3] + | | (5) |+1+ +- 3 1 0+| || | | || ++7+ + 5 5 3++ Type: TwoDimensionalArray(Matrix(Integer)) B11 := matrix [[2]] (6) [2] Type: Matrix(Integer) B21:= matrix [[2],[3], [1]] +2+ | | (7) |3| | | +1+ Type: Matrix(Integer) B := array2 [[B11],[B21]]$ARRAY2(Matrix Integer) +[2]+ | | |+2+| (8) || || ||3|| || || ++1++ Type: TwoDimensionalArray(Matrix(Integer)) A +[2] [1 2 3] + | | (9) |+1+ +- 3 1 0+| || | | || ++7+ + 5 5 3++ Type: TwoDimensionalArray(Matrix(Integer)) B +[2]+ | | |+2+| (10) || || ||3|| || || ++1++ Type: TwoDimensionalArray(Matrix(Integer)) A*B +[15] + | | (11) |+- 1+| || || ++42 ++ Type: TwoDimensionalArray(Matrix(Integer)) -- Mit freundlichen Grüßen Johannes Grabmeier Prof. Dr. Johannes Grabmeier Köckstraße 1, D-94469 Deggendorf Tel. +49-(0)-991-2979584, Tel. +49-(0)-151-681-70756 Tel. +49-(0)-991-3615-141 (d), Fax: +49-(0)-32224-192688 -- You received this message because you are subscribed to the Google Groups "FriCAS - computer algebra system" group. To unsubscribe from this group and stop receiving emails from it, send an email to fricas-devel+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/fricas-devel/2fa80ab2-6eb3-2a41-bb78-c397fdb08063%40grabmeier.net.
)abbrev category ARR2CAT TwoDimensionalArrayCategory ++ Two dimensional array categories and domains ++ Author: ++ Date Created: 27 October 1989 ++ updated J. Grabmeier November 2019: columnSums, rowSums ++ updated J. Grabmeier August 2019: array2, *, arrayMultiply ++ Keywords: array, data structure ++ Examples: ++ References: TwoDimensionalArrayCategory(R, Row, Col) : Category == Definition where ++ TwoDimensionalArrayCategory is a general array category which ++ allows different representations and indexing schemes. ++ Rows and columns may be extracted with rows returned as objects ++ of type Row and columns returned as objects of type Col. ++ The index of the 'first' row may be obtained by calling the ++ function 'minRowIndex'. The index of the 'first' column may ++ be obtained by calling the function 'minColIndex'. The index of ++ the first element of a 'Row' is the same as the index of the ++ first column in an array and vice versa. R : Type Row : IndexedAggregate(Integer, R) Col : IndexedAggregate(Integer, R) PI ==> PositiveInteger NNI ==> NonNegativeInteger LNNI ==> List(NNI) LI ==> List(Integer) SI ==> Segment(Integer) LSI ==> List(SI) Definition == Join(HomogeneousAggregate(R), _ shallowlyMutable, finiteAggregate) with if R has Comparable then Comparable --% Array creation new : (NonNegativeInteger, NonNegativeInteger, R) -> % ++ new(m, n, r) is an m-by-n array all of whose entries are r qnew : (NonNegativeInteger, NonNegativeInteger) -> % ++ qnew(m, n) is is an m-by-n uninitilized array fill! : (%, R) -> % ++ fill!(m, r) fills m with r's array2: List List R -> % ++ array2(lili) constructs a 2-dimensional array, the inner list being the rows. --% Size inquiries minRowIndex : % -> Integer ++ minRowIndex(m) returns the index of the 'first' row of the array m maxRowIndex : % -> Integer ++ maxRowIndex(m) returns the index of the 'last' row of the array m minColIndex : % -> Integer ++ minColIndex(m) returns the index of the 'first' column of the array m maxColIndex : % -> Integer ++ maxColIndex(m) returns the index of the 'last' column of the array m nrows : % -> NonNegativeInteger ++ nrows(m) returns the number of rows in the array m ncols : % -> NonNegativeInteger ++ ncols(m) returns the number of columns in the array m --% Part extractions elt : (%, Integer, Integer) -> R ++ elt(m, i, j) returns the element in the ith row and jth ++ column of the array m ++ error check to determine if indices are in proper ranges qelt : (%, Integer, Integer) -> R ++ qelt(m, i, j) returns the element in the ith row and jth ++ column of the array m ++ NO error check to determine if indices are in proper ranges elt : (%, Integer, Integer, R) -> R ++ elt(m, i, j, r) returns the element in the ith row and jth ++ column of the array m, if m has an ith row and a jth column, ++ and returns r otherwise row : (%, Integer) -> Row ++ row(m, i) returns the ith row of m ++ error check to determine if index is in proper ranges column : (%, Integer) -> Col ++ column(m, j) returns the jth column of m ++ error check to determine if index is in proper ranges parts : % -> List R ++ parts(m) returns a list of the elements of m in row major order listOfLists : % -> List List R ++ \spad{listOfLists(m)} returns the rows of the array m as a list ++ of lists. subMatrix : (%, Integer, Integer, Integer, Integer) -> % ++ \spad{subMatrix(x, i1, i2, j1, j2)} extracts the submatrix ++ \spad{[x(i, j)]} where the index i ranges from \spad{i1} to \spad{i2} ++ and the index j ranges from \spad{j1} to \spad{j2}. elt : (%, Integer, LI) -> % ++ \spad{elt(x, row, colList)} returns an 1-by-n array consisting ++ of elements of x, where \spad{n = # colList}. ++ If \spad{colList = [j<1>, j<2>, ..., j<n>]}, then the \spad{(k, l)}th ++ entry of \spad{elt(x, row, colList)} is \spad{x(row, j<l>)}. elt : (%, LI, Integer) -> % ++ \spad{elt(x, rowList, col)} returns an m-by-1 array consisting ++ of elements of x, where \spad{m = # rowList}. ++ If \spad{rowList = [i<1>, i<2>, ..., i<m>]}, then the \spad{(k, l)}th ++ entry of \spad{elt(x, rowList, col)} is \spad{x(i<k>, col)}. elt : (%, LI, LI) -> % ++ \spad{elt(x, rowList, colList)} returns an m-by-n array consisting ++ of elements of x, where \spad{m = # rowList} and \spad{n = # colList}. ++ If \spad{rowList = [i<1>, i<2>, ..., i<m>]} and \spad{colList = ++ [j<1>, j<2>, ..., j<n>]}, then the \spad{(k, l)}th entry of ++ \spad{elt(x, rowList, colList)} is \spad{x(i<k>, j<l>)}. elt : (%, SI, SI) -> % ++ \spad{elt(x, s1, s2)} is equivalent to ++ \spad{elt(x, expand(s1), expand(s2))} but should be more ++ convenient and more efficient. elt : (%, LI, SI) -> % ++ \spad{elt(x, rowList, s)} is equivalent to ++ \spad{elt(x, rowList, expand(s))} but should be more ++ convenient and more efficient. elt : (%, SI, LI) -> % ++ \spad{elt(x, s, colList)} is equivalent to ++ \spad{elt(x, expand(s), colList)} but should be more ++ convenient and more efficient. elt : (%, Integer, LSI) -> % ++ \spad{elt(x, row, ls2)} is equivalent to \spad{elt(x, row, l2)} ++ where l2 is obtained appending expansions of elements of ls2, ++ but should be more convenient and more efficient. elt : (%, LSI, Integer) -> % ++ \spad{elt(x, ls1, col)} is equivalent to \spad{elt(x, l1, col)} ++ where l1 is obtained appending expansions of elements of ls1, ++ but should be more convenient and more efficient. setelt! : (%, Integer, LSI, %) -> % ++ \spad{setelt!(x, row, ls2)} is equivalent to ++ \spad{setelt!(x, row, l2)} where l2 is obtained appending ++ expansions of elements of ls2, but should be more convenient ++ and more efficient. setelt! : (%, LSI, Integer, %) -> % ++ \spad{setelt!(x, ls1, col)} is equivalent to ++ \spad{setelt!(x, l1, col)} where l1 is obtained appending ++ expansions of elements of ls1, but should be more convenient ++ and more efficient. -- Works by coercing single integers to segments of integers -- elt : (%, LI, LSI) -> % -- elt : (%, LSI, LI) -> % elt : (%, SI, LSI) -> % ++ \spad{elt(x, s1, ls2)} is equivalent to \spad{elt(x, l1, l2)} ++ where li is obtained appending expansions of elements of lsi, ++ but should be more convenient and more efficient. elt : (%, LSI, SI) -> % ++ \spad{elt(x, ls1, s2)} is equivalent to \spad{elt(x, l1, l2)} ++ where li is obtained appending expansions of elements of lsi, ++ but should be more convenient and more efficient. elt : (%, LSI, LSI) -> % ++ \spad{elt(x, ls1, ls2)} is equivalent to \spad{elt(x, l1, l2)} ++ where li is obtained appending expansions of elements of lsi, ++ but should be more convenient and more efficient. rowSlice : % -> Segment(Integer) ++ \spad{rowSlice(m)} returns a segment s such that for ++ m the access m(s, j) gives the j-th column. colSlice : % -> Segment(Integer) ++ \spad{colSlice(m)} returns a segment s such that for ++ m the access m(i, s) gives the i-th row. --% Part assignments setelt! : (%, Integer, Integer, R) -> R ++ setelt!(m, i, j, r) sets the element in the ith row and jth ++ column of m to r ++ error check to determine if indices are in proper ranges qsetelt! : (%, Integer, Integer, R) -> R ++ qsetelt!(m, i, j, r) sets the element in the ith row and jth ++ column of m to r ++ NO error check to determine if indices are in proper ranges setRow! : (%, Integer, Row) -> % ++ setRow!(m, i, v) sets to ith row of m to v setColumn! : (%, Integer, Col) -> % ++ setColumn!(m, j, v) sets to jth column of m to v setelt! : (%, Integer, LI, %) -> % ++ \spad{setelt!(x, row, colList)} assigns to an 1-by-n selection ++ of the array, where \spad{n = # colList}. setelt! : (%, LI, Integer, %) -> % ++ \spad{setelt!(x, rowList, col)} assigns to an m-by-1 selection ++ of the array, where \spad{m = # rowList}. setelt! : (%, List Integer, List Integer, %) -> % ++ \spad{setelt!(x, rowList, colList, y)} destructively alters ++ the array x. If y is \spad{m}-by-\spad{n}, ++ \spad{rowList = [i<1>, i<2>, ..., i<m>]} ++ and \spad{colList = [j<1>, j<2>, ..., j<n>]}, then ++ \spad{x(i<k>, j<l>)} ++ is set to \spad{y(k, l)} for \spad{k = 1, ..., m} and ++ \spad{l = 1, ..., n}. setelt! : (%, SI, SI, %) -> % ++ \spad{setelt!(x, s1, s2)} is equivalent to ++ \spad{setelt!(x, expand(s1), expand(s2))} but should be more ++ convenient and more efficient. setelt! : (%, LI, SI, %) -> % ++ \spad{setelt!(x, l1, s2)} is equivalent to ++ \spad{setelt!(x, l1, expand(s2))} but should be more ++ convenient and more efficient. setelt! : (%, SI, LI, %) -> % ++ \spad{setelt!(x, s1, l2)} is equivalent to ++ \spad{setelt!(x, expand(s1), l2)} but should be more ++ convenient and more efficient. -- Works by coercing single integers to segments of integers -- setelt! : (%, LI, LSI, %) -> % -- setelt! : (%, LSI, LI, %) -> % setelt! : (%, SI, LSI, %) -> % ++ \spad{setelt!(x, s1, ls2)} is equivalent to \spad{setelt!(x, l1, l2)} ++ where li is obtained appending expansions of elements of lsi, ++ but should be more convenient and more efficient. setelt! : (%, LSI, SI, %) -> % ++ \spad{setelt!(x, ls1, s2)} is equivalent to \spad{setelt!(x, l1, l2)} ++ where li is obtained appending expansions of elements of lsi, ++ but should be more convenient and more efficient. setelt! : (%, LSI, LSI, %) -> % ++ \spad{setelt!(x, ls1, ls1)} is equivalent to ++ \spad{setelt!(x, l1, l2)} where li is obtained appending ++ expansions of elements of lsi, but should be more convenient ++ and more efficient. setsubMatrix! : (%, Integer, Integer, %) -> % ++ \spad{setsubMatrix(x, i1, j1, y)} destructively alters the ++ array x. Here \spad{x(i, j)} is set to \spad{y(i-i1+1, j-j1+1)} for ++ \spad{i = i1, ..., i1-1+nrows y} and \spad{j = j1, ..., j1-1+ncols y}. -- manipulations swapRows! : (%, Integer, Integer) -> % ++ \spad{swapRows!(m, i, j)} interchanges the \spad{i}th and \spad{j}th ++ rows of m. This destructively alters the array. swapColumns! : (%, Integer, Integer) -> % ++ \spad{swapColumns!(m, i, j)} interchanges the \spad{i}th and ++ \spad{j}th columns of m. This destructively alters the array. transpose : % -> % ++ \spad{transpose(m)} returns the transpose of the array m. squareTop : % -> % ++ \spad{squareTop(m)} returns an n-by-n array consisting of the first ++ n rows of the m-by-n array m. Error: if ++ \spad{m < n}. horizConcat : (%, %) -> % ++ \spad{horizConcat(x, y)} horizontally concatenates two arrays with ++ an equal number of rows. The entries of y appear to the right ++ of the entries of x. Error: if the arrays ++ do not have the same number of rows. horizConcat : (List %) -> % ++ \spad{horizConcat(l)} horizontally concatenates all members of l ++ Error: if the arrays do not have the same number of rows. vertConcat : (%, %) -> % ++ \spad{vertConcat(x, y)} vertically concatenates two arrays with an ++ equal number of columns. The entries of y appear below ++ of the entries of x. Error: if the arrays ++ do not have the same number of columns. vertConcat : (List %) -> % ++ \spad{vertConcat(l)} vertically concatenates all members of l ++ Error: if the arrays do not have the same number of columns. blockConcat : (List List %) -> % ++ \spad{blockConcat(ll)} concatenates arrays row and ++ column wise, building a array from blocks. The order ++ is row major as in \spad{matrix}. vertSplit : (%, PI) -> List % ++ \spad{vertSplit(a, n)} splits a into n arrays ++ of equal size row wise. ++ Error: if number of rows of a is not divisible by n. vertSplit : (%, LNNI) -> List % ++ \spad{vertSplit(a, [n1, ..., ni])} splits a into ++ arrays having n1, ..., ni rows. ++ Error: if number of rows of a is different than ++ n1+ ... + ni. horizSplit : (%, PI) -> List % ++ \spad{horizSplit(a, n)} splits a into n arrays ++ of equal size column wise. ++ Error: if number of columns of a is not divisible by n. horizSplit : (%, LNNI) -> List % ++ \spad{horizSplit(a, [n1, n2, ..., ni])} splits a into ++ arrays having n1, ..., ni columns. ++ Error: if number of columns of a is different than ++ n1 + ... + ni. blockSplit : (%, PI, PI) -> List List % ++ \spad{blockSplit(a, n, m)} splits a into n*m ++ subarrays of equal size row and column wise, dividing ++ a into blocks. ++ Error: if number of rows of a is not divisible by n ++ or number of columns of a is not divisible by m. blockSplit : (%, LNNI, LNNI) -> List List % ++ \spad{blockSplit(a, [n1,...,ni], [m1,...,mi])} splits a ++ into multiple subarraus row and column wise, such that ++ element at position k, l has nk rows and ml columns. ++ Error: if number of rows of a is different than ++ n1 + ... + ni or number of columns of a is different ++ than m1 + ... + mj -- Map and Zip map : (R -> R, %) -> % ++ map(f, a) returns \spad{b}, where \spad{b(i, j) = f(a(i, j))} for all \spad{i, j} map! : (R -> R, %) -> % ++ map!(f, a) assign \spad{a(i, j)} to \spad{f(a(i, j))} for all \spad{i, j} map : ((R, R) -> R, %, %) -> % ++ map(f, a, b) returns \spad{c}, where \spad{c(i, j) = f(a(i, j), b(i, j))} ++ for all \spad{i, j} map : ((R, R) -> R, %, %, R) -> % ++ map(f, a, b, r) returns \spad{c}, where \spad{c(i, j) = f(a(i, j), b(i, j))} when both ++ \spad{a(i, j)} and \spad{b(i, j)} exist; ++ else \spad{c(i, j) = f(r, b(i, j))} when \spad{a(i, j)} does not exist; ++ else \spad{c(i, j) = f(a(i, j), r)} when \spad{b(i, j)} does not exist; ++ otherwise \spad{c(i, j) = f(r, r)}. if R has AbelianSemiGroup then columnSums: % -> Row rowSums: % -> Col if R has "*": (R, R) -> R and R has "+": (R, R) -> R then "*": (%,%) -> % arrayMultiply: (%,%) -> % add minr ==> minRowIndex maxr ==> maxRowIndex minc ==> minColIndex maxc ==> maxColIndex mini ==> minIndex maxi ==> maxIndex --% Predicates import from Integer any?(f, m) == for i in minRowIndex(m)..maxRowIndex(m) repeat for j in minColIndex(m)..maxColIndex(m) repeat f(qelt(m, i, j)) => return true false every?(f, m) == for i in minRowIndex(m)..maxRowIndex(m) repeat for j in minColIndex(m)..maxColIndex(m) repeat not f(qelt(m, i, j)) => return false true size?(m, n) == nrows(m) * ncols(m) = n less?(m, n) == nrows(m) * ncols(m) < n more?(m, n) == nrows(m) * ncols(m) > n if R has Comparable then smaller?(m1, m2) == mri1 := minRowIndex(m1) mri2 := minRowIndex(m2) mri1 < mri2 => true mri2 < mri1 => false minr := mri1 mri1 := maxRowIndex(m1) mri2 := maxRowIndex(m2) mri1 < mri2 => true mri2 < mri1 => false maxr := mri1 mci1 := minColIndex(m1) mci2 := minColIndex(m2) mci1 < mci2 => true mci2 < mci1 => false minc := mci1 mci1 := maxColIndex(m1) mci2 := maxColIndex(m2) mci1 < mci2 => true mci2 < mci1 => false maxc := mci1 for i in minr..maxr repeat for j in minc..maxc repeat el1 := m1(i, j) el2 := m2(i, j) smaller?(el1, el2) => return true if not(el1 = el2) then return false false --% Size inquiries # m == nrows(m) * ncols(m) --% Part extractions elt(m, i, j, r) == i < minRowIndex(m) or i > maxRowIndex(m) => r j < minColIndex(m) or j > maxColIndex(m) => r qelt(m, i, j) count(f : R -> Boolean, m : %) == num : NonNegativeInteger := 0 for i in minRowIndex(m)..maxRowIndex(m) repeat for j in minColIndex(m)..maxColIndex(m) repeat if f(qelt(m, i, j)) then num := num + 1 num parts m == entryList : List R := [] for i in maxRowIndex(m)..minRowIndex(m) by -1 repeat for j in maxColIndex(m)..minColIndex(m) by -1 repeat entryList := concat(qelt(m, i, j), entryList) entryList listOfLists x == ll : List List R := [] for i in maxr(x)..minr(x) by -1 repeat l : List R := [] for j in maxc(x)..minc(x) by -1 repeat l := cons(qelt(x, i, j), l) ll := cons(l, ll) ll subMatrix(x, i1, i2, j1, j2) == (i2 + 1 < i1) => error "subMatrix: bad row indices" (j2 + 1 < j1) => error "subMatrix: bad column indices" rows := qcoerce(i2 - i1 + 1)@NonNegativeInteger cols := qcoerce(j2 - j1 + 1)@NonNegativeInteger y := qnew(rows, cols) rows = 0 or cols = 0 => y (i1 < minr(x)) or (i2 > maxr(x)) => error "subMatrix: index out of range" (j1 < minc(x)) or (j2 > maxc(x)) => error "subMatrix: index out of range" for i in minr(y)..maxr(y) for k in i1..i2 repeat for j in minc(y)..maxc(y) for l in j1..j2 repeat qsetelt!(y, i, j, qelt(x, k, l)) y elt(x : %, row : Integer, colList : LI) == (row < minr(x)) or (row > maxr(x)) => error "elt: index out of range" for ej in colList repeat (ej < minc(x)) or (ej > maxc(x)) => error "elt: index out of range" y := qnew(1, # colList) for ej in colList for j in minc(y)..maxc(y) repeat qsetelt!(y, 1, j, qelt(x, row, ej)) y elt(x : %, rowList : LI, col : Integer) == for ei in rowList repeat (ei < minr(x)) or (ei > maxr(x)) => error "elt: index out of range" (col < minc(x)) or (col > maxc(x)) => error "elt: index out of range" y := qnew(# rowList, 1) for ei in rowList for i in minr(y)..maxr(y) repeat qsetelt!(y, i, 1, qelt(x, ei, col)) y elt(x : %, rowList : List Integer, colList : List Integer) == for ei in rowList repeat (ei < minr(x)) or (ei > maxr(x)) => error "elt: index out of range" for ej in colList repeat (ej < minc(x)) or (ej > maxc(x)) => error "elt: index out of range" y := qnew(# rowList, # colList) for ei in rowList for i in minr(y)..maxr(y) repeat for ej in colList for j in minc(y)..maxc(y) repeat qsetelt!(y, i, j, qelt(x, ei, ej)) y check_seg(s : SI, lb : Integer, ub : Integer) : NonNegativeInteger == ii := incr(s) i1 := low(s) i2 := high(s) -- Empty segment: (ii > 0 and i2 + 1 < i1) or (ii < 0 and i1 + 1 < i2) => error "check_seg: bad indices" (i1 > i2 and ii > 0) or (i2 > i1 and ii < 0) => 0 -- Regular segment: 0 < ii => (i2 + 1 < i1) => error "check_seg: index out of range" cc := qcoerce(i2 - i1 + ii)@NonNegativeInteger cc < ii => cc i1 < lb or ub < i2 => error "check_seg: index out of range" ii = 1 => cc qcoerce(cc quo ii)@NonNegativeInteger ii < 0 => ii := -ii (i1 + 1 < i2) or i2 < lb or ub < i1 => error "check_seg: index out of range" cc := qcoerce(i1 - i2 + ii)@NonNegativeInteger cc < ii => cc i2 < lb or ub < i1 => error "check_seg: index out of range" ii = 1 => cc qcoerce(cc quo ii)@NonNegativeInteger error "chec_seg: zero increment" elt(x : %, rowList : LI, sc : SI) : % == lc := low(sc) uc := high(sc) ic := incr(sc) nr := # rowList nc := check_seg(sc, minc(x), maxc(x)) y := qnew(nr, nc) nr = 0 or nc = 0 => y for i in minr(y)..maxr(y) for k in rowList repeat for j in minc(y)..maxc(y) for l in lc..uc by ic repeat qsetelt!(y, i, j, qelt(x, k, l)) y elt(x : %, sr : SI, colList : LI) : % == lr := low(sr) ur := high(sr) ir := incr(sr) nr := check_seg(sr, minr(x), maxr(x)) nc := # colList y := qnew(nr, nc) nr = 0 or nc = 0 => y for i in minr(y)..maxr(y) for k in lr..ur by ir repeat for j in minc(y)..maxc(y) for l in colList repeat qsetelt!(y, i, j, qelt(x, k, l)) y elt(x : %, sr : SI, sc : SI) : % == lr := low(sr) ur := high(sr) lc := low(sc) uc := high(sc) ir := incr(sr) ic := incr(sc) ir = 1 and ic = 1 => subMatrix(x, lr, ur, lc, uc) nr := check_seg(sr, minr(x), maxr(x)) nc := check_seg(sc, minc(x), maxc(x)) y := qnew(nr, nc) nr = 0 or nc = 0 => y for i in minr(y)..maxr(y) for k in lr..ur by ir repeat for j in minc(y)..maxc(y) for l in lc..uc by ic repeat qsetelt!(y, i, j, qelt(x, k, l)) y check_segs(ls : LSI, lb : Integer, ub : Integer) : NonNegativeInteger == res : NonNegativeInteger := 0 for s in ls repeat res := res + check_seg(s, lb, ub) res elt(x : %, row : Integer, lsc : LSI) : % == nc := check_segs(lsc, minc(x), maxc(x)) y := qnew(1, nc) nc = 0 => y j := minc(y) for sc in lsc repeat for l in low(sc)..high(sc) by incr(sc) repeat qsetelt!(y, 1, j, qelt(x, row, l)) j := j + 1 y elt(x : %, lsr : LSI, col : Integer) : % == nr := check_segs(lsr, minr(x), maxr(x)) y := qnew(nr, 1) nr = 0 => y i := minr(y) for sr in lsr repeat for k in low(sr)..high(sr) by incr(sr) repeat qsetelt!(y, i, 1, qelt(x, k, col)) i := i + 1 y elt(x : %, sr : SI, lsc : LSI) : % == lr := low(sr) ur := high(sr) ir := incr(sr) nr := check_seg(sr, minr(x), maxr(x)) nc := check_segs(lsc, minc(x), maxc(x)) y := qnew(nr, nc) nr = 0 or nc = 0 => y j := minc(y) for sc in lsc repeat for l in low(sc)..high(sc) by incr(sc) repeat for i in minr(y)..maxr(y) for k in lr..ur by ir repeat qsetelt!(y, i, j, qelt(x, k, l)) j := j + 1 y elt(x : %, lsr : LSI, sc : SI) : % == lc := low(sc) uc := high(sc) ic := incr(sc) nr := check_segs(lsr, minr(x), maxr(x)) nc := check_seg(sc, minc(x), maxc(x)) y := qnew(nr, nc) nr = 0 or nc = 0 => y i := minr(y) for sr in lsr repeat for k in low(sr)..high(sr) by incr(sr) repeat for j in minc(y)..maxc(y) for l in lc..uc by ic repeat qsetelt!(y, i, j, qelt(x, k, l)) i := i + 1 y elt(x : %, lsr : LSI, lsc : LSI) : % == nr := check_segs(lsr, minr(x), maxr(x)) nc := check_segs(lsc, minc(x), maxc(x)) y := qnew(nr, nc) nr = 0 or nc = 0 => y i := minr(y) for sr in lsr repeat lr := low(sr) ur := high(sr) ir := incr(sr) for k in lr..ur by ir repeat j := minc(y) for sc in lsc repeat for l in low(sc)..high(sc) by incr(sc) repeat qsetelt!(y, i, j, qelt(x, k, l)) j := j + 1 i := i + 1 y rowSlice(x :%) : Segment(Integer) == minr(x)..maxr(x) colSlice(x :%) : Segment(Integer) == minc(x)..maxc(x) -- Setting parts setelt!(x : %, row : Integer, colList : LI, y : %) == (row < minr(x)) or (row > maxr(x)) => error "setelt!: index out of range" for ej in colList repeat (ej < minc(x)) or (ej > maxc(x)) => error "setelt!: index out of range" ((nrows y) ~= 1) or ((# colList) ~= (ncols y)) => error "setelt!: matrix has bad dimensions" rowiy := minr(y) for ej in colList for j in minc(y)..maxc(y) repeat qsetelt!(x, row, ej, qelt(y, rowiy, j)) y setelt!(x : %, rowList : LI, col : Integer, y : %) == for ei in rowList repeat (ei < minr(x)) or (ei > maxr(x)) => error "setelt!: index out of range" (col < minc(x)) or (col > maxc(x)) => error "setelt!: index out of range" ((# rowList) ~= (nrows y)) or ((ncols y) ~= 1) => error "setelt!: matrix has bad dimensions" coliy := minc(y) for ei in rowList for i in minr(y)..maxr(y) repeat qsetelt!(x, ei, col, qelt(y, i, coliy)) y setelt!(x : %, rowList : List Integer, colList : List Integer, y : %) == for ei in rowList repeat (ei < minr(x)) or (ei > maxr(x)) => error "setelt!: index out of range" for ej in colList repeat (ej < minc(x)) or (ej > maxc(x)) => error "setelt!: index out of range" ((# rowList) ~= (nrows y)) or ((# colList) ~= (ncols y)) => error "setelt!: matrix has bad dimensions" for ei in rowList for i in minr(y)..maxr(y) repeat for ej in colList for j in minc(y)..maxc(y) repeat qsetelt!(x, ei, ej, qelt(y, i, j)) y setelt!(x : %, sr : SI, sc : SI, y : %) == lr := low(sr) ur := high(sr) lc := low(sc) uc := high(sc) ir := incr(sr) ic := incr(sc) -- ir = 1 and ic = 1 => subMatrix(x, lr, ur, lc, uc) nr := check_seg(sr, minr(x), maxr(x)) nc := check_seg(sc, minc(x), maxc(x)) nrows(y) ~= nr or ncols(y) ~= nc => error "setelt!: matrix has bad dimensions" nr = 0 or nc = 0 => y for i in minr(y)..maxr(y) for k in lr..ur by ir repeat for j in minc(y)..maxc(y) for l in lc..uc by ic repeat qsetelt!(x, k, l, qelt(y, i, j)) y setelt!(x : %, rowList : LI, sc : SI, y : %) == lc := low(sc) uc := high(sc) ic := incr(sc) nr := # rowList nc := check_seg(sc, minc(x), maxc(x)) nrows(y) ~= nr or ncols(y) ~= nc => error "setelt!: matrix has bad dimensions" nr = 0 or nc = 0 => y for i in minr(y)..maxr(y) for k in rowList repeat for j in minc(y)..maxc(y) for l in lc..uc by ic repeat qsetelt!(x, k, l, qelt(y, i, j)) y setelt!(x : %, sr : SI, colList : LI, y : %) == lr := low(sr) ur := high(sr) ir := incr(sr) nr := check_seg(sr, minr(x), maxr(x)) nc := # colList nrows(y) ~= nr or ncols(y) ~= nc => error "setelt!: matrix has bad dimensions" nr = 0 or nc = 0 => y for i in minr(y)..maxr(y) for k in lr..ur by ir repeat for j in minc(y)..maxc(y) for l in colList repeat qsetelt!(x, k, l, qelt(y, i, j)) y setelt!(x : %, row : Integer, lsc : LSI, y : %) == nc := check_segs(lsc, minc(x), maxc(x)) nrows(y) ~= 1 or ncols(y) ~= nc => error "setelt!: matrix has bad dimensions" nc = 0 => y i := minr(y) j := minc(y) for sc in lsc repeat for l in low(sc)..high(sc) by incr(sc) repeat qsetelt!(x, row, l, qelt(y, i, j)) j := j + 1 y setelt!(x : %, lsr : LSI, col : Integer, y : %) == nr := check_segs(lsr, minr(x), maxr(x)) nrows(y) ~= nr or ncols(y) ~= 1 => error "setelt!: matrix has bad dimensions" nr = 0 => y i := minr(y) j := minc(y) for sr in lsr repeat for k in low(sr)..high(sr) by incr(sr) repeat qsetelt!(x, k, col, qelt(y, i, j)) i := i + 1 y setelt!(x : %, sr : SI, lsc : LSI, y : %) == lr := low(sr) ur := high(sr) ir := incr(sr) nr := check_seg(sr, minr(x), maxr(x)) nc := check_segs(lsc, minc(x), maxc(x)) nrows(y) ~= nr or ncols(y) ~= nc => error "setelt!: matrix has bad dimensions" nr = 0 or nc = 0 => y j := minc(y) for sc in lsc repeat for l in low(sc)..high(sc) by incr(sc) repeat for i in minr(y)..maxr(y) for k in lr..ur by ir repeat qsetelt!(x, k, l, qelt(y, i, j)) j := j + 1 y setelt!(x : %, lsr : LSI, sc : SI, y : %) == lc := low(sc) uc := high(sc) ic := incr(sc) nr := check_segs(lsr, minr(x), maxr(x)) nc := check_seg(sc, minc(x), maxc(x)) nrows(y) ~= nr or ncols(y) ~= nc => error "setelt!: matrix has bad dimensions" nr = 0 or nc = 0 => y i := minr(y) for sr in lsr repeat for k in low(sr)..high(sr) by incr(sr) repeat for j in minc(y)..maxc(y) for l in lc..uc by ic repeat qsetelt!(x, k, l, qelt(y, i, j)) i := i + 1 y setelt!(x : %, lsr : LSI, lsc : LSI, y : %) == nr := check_segs(lsr, minr(x), maxr(x)) nc := check_segs(lsc, minc(x), maxc(x)) nrows(y) ~= nr or ncols(y) ~= nc => error "setelt!: matrix has bad dimensions" nr = 0 or nc = 0 => y i := minr(y) for sr in lsr repeat lr := low(sr) ur := high(sr) ir := incr(sr) for k in lr..ur by ir repeat j := minc(y) for sc in lsc repeat for l in low(sc)..high(sc) by incr(sc) repeat qsetelt!(x, k, l, qelt(y, i, j)) j := j + 1 i := i + 1 y setsubMatrix!(x, i1, j1, y) == i2 := i1 + nrows(y) - 1 j2 := j1 + ncols(y) - 1 (i1 < minr(x)) or (i2 > maxr(x)) => error "setsubMatrix!: inserted matrix too big, " "use subMatrix to restrict it" (j1 < minc(x)) or (j2 > maxc(x)) => error "setsubMatrix!: inserted matrix too big, " "use subMatrix to restrict it" for i in minr(y)..maxr(y) for k in i1..i2 repeat for j in minc(y)..maxc(y) for l in j1..j2 repeat qsetelt!(x, k, l, qelt(y, i, j)) x -- Manipulations swapRows!(x, i1, i2) == (i1 < minr(x)) or (i1 > maxr(x)) or (i2 < minr(x)) or _ (i2 > maxr(x)) => error "swapRows!: index out of range" i1 = i2 => x for j in minc(x)..maxc(x) repeat r := qelt(x, i1, j) qsetelt!(x, i1, j, qelt(x, i2, j)) qsetelt!(x, i2, j, r) x swapColumns!(x, j1, j2) == (j1 < minc(x)) or (j1 > maxc(x)) or (j2 < minc(x)) or _ (j2 > maxc(x)) => error "swapColumns!: index out of range" j1 = j2 => x for i in minr(x)..maxr(x) repeat r := qelt(x, i, j1) qsetelt!(x, i, j1, qelt(x, i, j2)) qsetelt!(x, i, j2, r) x transpose(x : %) == ans := qnew(ncols x, nrows x) for i in minr(ans)..maxr(ans) repeat for j in minc(ans)..maxc(ans) repeat qsetelt!(ans, i, j, qelt(x, j, i)) ans squareTop x == nrows x < (cols := ncols x) => error "squareTop: number of columns exceeds number of rows" ans := qnew(cols, cols) for i in minr(x)..(minr(x) + cols - 1) repeat for j in minc(x)..maxc(x) repeat qsetelt!(ans, i, j, qelt(x, i, j)) ans horizConcat(x, y) == horizConcat([x, y]) horizConcat(la : List %) == empty?(la) => error "horizConcat: empty list" a1 := first(la) nr := nrows(a1) nc := ncols(a1) for a in rest(la) repeat nr ~= nrows(a) => error "horizConcat: array must have same number of rows" nc := nc + ncols(a) ans := qnew(nr, nc) for i in minr(a1)..maxr(a1) repeat l := minc(ans) for a in la repeat for j in minc(a)..maxc(a) repeat qsetelt!(ans, i, l, qelt(a, i, j)) l := l + 1 ans vertConcat(x, y) == vertConcat([x, y]) vertConcat(la : List %) == empty?(la) => error "vertConcat: empty list" a1 := first(la) nr := nrows(a1) nc := ncols(a1) for a in rest(la) repeat nc ~= ncols(a) => error "vertConcat: array must have same number of columns" nr := nr + nrows(a) ans := qnew(nr, nc) l := minr(ans) for a in la repeat for i in minr(a)..maxr(a) repeat for j in minc(a)..maxc(a) repeat qsetelt!(ans, l, j, qelt(a, i, j)) l := l + 1 ans blockConcat(LLA: List List %) : % == vertConcat([horizConcat(LA) for LA in LLA]) vertSplit(A : %, r : PI) : List % == dr := nrows(A) exquo r dr case "failed" => error "split does not result in an equal division" mir := minr A mic := minc A mac := maxc A [ subMatrix(A, mir+i*dr, mir+(i+1)*dr-1, mic, mac) for i in 0..(r-1) ] vertSplit(A : %, lr : LNNI) : List % == reduce("+", lr) ~= nrows(A) => error "split does not result in proper partition" l : List NNI := cons(1, scan(_+, lr, 1$NNI)$ListFunctions2(NNI, NNI)) mir := minr(A) -1 -- additional shift because l starts at 1 mic := minc A mac := maxc A [subMatrix(A, mir+l(i-1), mir+l(i)-1, mic, mac) for i in 2..#l] horizSplit(A : %, c : PI) : List % == dc := ncols(A) exquo c dc case "failed" => error "split does not result in an equal division" mir := minr A mar := maxr A mic := minc A [ subMatrix(A, mir, mar, mic+i*dc, mic+(i+1)*dc-1) for i in 0..(c-1) ] horizSplit(A : %, lc : LNNI) : List % == reduce("+", lc) ~= ncols(A) => error "split does not result in proper partition" l : List NNI := cons(1, scan(_+, lc, 1$NNI)$ListFunctions2(NNI, NNI)) mir := minr A mar := maxr A mic := minc(A) -1 -- additional shift because l starts at 1 [subMatrix(A, mir, mar, mic+l(i-1), mic+l(i)-1) for i in 2..#l] blockSplit(A : %, nr : PI, nc : PI) : List List % == -- The map version does not work with OpenAxiom. --map( (X:M):(List M) +-> horizSplit(X, nc), vertSplit(A, nr) )$ListFunctions2(M, List M) [ horizSplit(X, nc) for X in vertSplit(A, nr) ] blockSplit(A : %, lr : LNNI, lc : LNNI) : List List % == --map( (X:M):(List M) +-> horizSplit(X, lc), vertSplit(A, lr) )$ListFunctions2(M, List M) [horizSplit(X, lc) for X in vertSplit(A, lr)] --% Creation copy m == ans := qnew(nrows m, ncols m) for i in minRowIndex(m)..maxRowIndex(m) repeat for j in minColIndex(m)..maxColIndex(m) repeat qsetelt!(ans, i, j, qelt(m, i, j)) ans fill!(m, r) == for i in minRowIndex(m)..maxRowIndex(m) repeat for j in minColIndex(m)..maxColIndex(m) repeat qsetelt!(m, i, j, r) m map(f : R -> R, m : %) : % == ans := qnew(nrows m, ncols m) for i in minRowIndex(m)..maxRowIndex(m) repeat for j in minColIndex(m)..maxColIndex(m) repeat qsetelt!(ans, i, j, f(qelt(m, i, j))) ans map!(f, m) == for i in minRowIndex(m)..maxRowIndex(m) repeat for j in minColIndex(m)..maxColIndex(m) repeat qsetelt!(m, i, j, f(qelt(m, i, j))) m map(f, m, n) == (nrows(m) ~= nrows(n)) or (ncols(m) ~= ncols(n)) => error "map: arguments must have same dimensions" ans := qnew(nrows m, ncols m) for i in minRowIndex(m)..maxRowIndex(m) repeat for j in minColIndex(m)..maxColIndex(m) repeat qsetelt!(ans, i, j, f(qelt(m, i, j), qelt(n, i, j))) ans map(f, m, n, r) == -- FIXME: what if minRowIndex differ? maxRow := max(maxRowIndex m, maxRowIndex n) maxCol := max(maxColIndex m, maxColIndex n) ans := qnew(max(nrows m, nrows n), max(ncols m, ncols n)) for i in minRowIndex(m)..maxRow repeat for j in minColIndex(m)..maxCol repeat qsetelt!(ans, i, j, f(elt(m, i, j, r), elt(n, i, j, r))) ans setRow!(m, i, v) == i < minRowIndex(m) or i > maxRowIndex(m) => error "setRow!: index out of range" for j in minColIndex(m)..maxColIndex(m) _ for k in minIndex(v)..maxIndex(v) repeat qsetelt!(m, i, j, v.k) m setColumn!(m, j, v) == j < minColIndex(m) or j > maxColIndex(m) => error "setColumn!: index out of range" for i in minRowIndex(m)..maxRowIndex(m) _ for k in minIndex(v)..maxIndex(v) repeat qsetelt!(m, i, j, v.k) m if R has _= : (R, R) -> Boolean then m = n == eq?(m, n) => true (nrows(m) ~= nrows(n)) or (ncols(m) ~= ncols(n)) => false for i in minRowIndex(m)..maxRowIndex(m) repeat for j in minColIndex(m)..maxColIndex(m) repeat not (qelt(m, i, j) = qelt(n, i, j)) => return false true member?(r, m) == for i in minRowIndex(m)..maxRowIndex(m) repeat for j in minColIndex(m)..maxColIndex(m) repeat qelt(m, i, j) = r => return true false count(r : R, m : %) == count(x +-> x = r, m) if Row has shallowlyMutable and Row has LinearAggregate(R) then row(m, i) == i < minRowIndex(m) or i > maxRowIndex(m) => error "row: index out of range" (nc := ncols m) = 0 => empty() mci := minColIndex(m) v : Row := new(nc, qelt(m, i, mci)) for j in mci..maxColIndex(m) _ for k in minIndex(v)..maxIndex(v) repeat qsetelt!(v, k, qelt(m, i, j)) v if Col has shallowlyMutable and Col has LinearAggregate(R) then column(m, j) == j < minColIndex(m) or j > maxColIndex(m) => error "column: index out of range" (nr := nrows m) = 0 => empty() mri := minRowIndex(m) v : Col := new(nr, qelt(m, mri, j)) for i in mri..maxRowIndex(m) _ for k in minIndex(v)..maxIndex(v) repeat qsetelt!(v, k, qelt(m, i, j)) v if R has CoercibleTo(OutputForm) then coerce(m : %) == l : List List OutputForm l := [[qelt(m, i, j) :: OutputForm _ for j in minColIndex(m)..maxColIndex(m)] _ for i in minRowIndex(m)..maxRowIndex(m)] matrix l )abbrev domain IIARRAY2 InnerIndexedTwoDimensionalArray InnerIndexedTwoDimensionalArray(R, mnRow, mnCol, Row, Col) : _ Exports == Implementation where ++ This is an internal type which provides an implementation of ++ 2-dimensional arrays as PrimitiveArray's of PrimitiveArray's. R : Type mnRow, mnCol : Integer NNI ==> NonNegativeInteger Row : FiniteLinearAggregate R Col : FiniteLinearAggregate R Exports ==> TwoDimensionalArrayCategory(R, Row, Col) Implementation ==> add Qsize ==> MATRIX_SIZE$Lisp Qnew ==> MAKE_MATRIX$Lisp Qnew1 ==> MAKE_MATRIX1$Lisp Qnrows ==> ANROWS$Lisp Qncols ==> ANCOLS$Lisp Qelt2 ==> QAREF2O$Lisp Qsetelt2 ==> QSETAREF2O$Lisp --% Primitive array creation empty() == Qnew(0, 0) qnew(rows, cols) == Qnew(rows, cols) new(rows, cols, a) == Qnew1(rows, cols, a) array2(l: List List R): % == a2 := qnew(#l :: NNI, #first(l) :: NNI) for i in 1..#l for ll in l repeat for j in 1..#ll for r in ll repeat qsetelt!(a2, i, j, r) a2 --% Size inquiries minRowIndex m == mnRow minColIndex m == mnCol maxRowIndex m == nrows m + mnRow - 1 maxColIndex m == ncols m + mnCol - 1 nrows m == Qnrows(m) ncols m == Qncols(m) --% Part selection/assignment qelt(m, i, j) == Qelt2(m, i, j, mnRow, mnCol) elt(m : %, i : Integer, j : Integer) == i < minRowIndex(m) or i > maxRowIndex(m) => error "elt: index out of range" j < minColIndex(m) or j > maxColIndex(m) => error "elt: index out of range" qelt(m, i, j) qsetelt!(m, i, j, r) == Qsetelt2(m, i, j, r, mnRow, mnCol) setelt!(m : %, i : Integer, j : Integer, r : R) == i < minRowIndex(m) or i > maxRowIndex(m) => error "setelt!: index out of range" j < minColIndex(m) or j > maxColIndex(m) => error "setelt!: index out of range" qsetelt!(m, i, j, r) if R has SetCategory then latex(m : %) : String == s : String := "\left[ \begin{array}{" j : Integer for j in minColIndex(m)..maxColIndex(m) repeat s := concat(s,"c")$String s := concat(s,"} ")$String i : Integer for i in minRowIndex(m)..maxRowIndex(m) repeat for j in minColIndex(m)..maxColIndex(m) repeat s := concat(s, latex(qelt(m, i, j))$R)$String if j < maxColIndex(m) then s := concat(s, " & ")$String if i < maxRowIndex(m) then s := concat(s, " \\ ")$String concat(s, "\end{array} \right]")$String if R has "*": (R, R) -> R and R has "+": (R, R) -> R then arrayMultiply(x: %, y: %): % == (ncols x ~= nrows y) => error "can't multiply 2-dimensional arrays of incompatible dimensions" ans := qnew(nrows x, ncols y) for i in minRowIndex(x)..maxRowIndex(x) repeat for j in minColIndex(y)..maxColIndex(y) repeat li : List R := [qelt(x, i, l) * qelt(y, k, j) for l in minColIndex(x)..maxColIndex(x) for k in minRowIndex(y)..maxRowIndex(y) ] entry : R := reduce("+", li) qsetelt!(ans, i, j, entry) ans ((x: %) * (y: %)): % == arrayMultiply(x, y) if R has AbelianSemiGroup then columnSums(m: %): Row == lLm : List List R := listOfLists m cS : List R := [] for rw in lLm repeat cS := concat(cS, reduce(_+, rw) ) construct cS rowSums(m: %): Col == lLm : List List R := listOfLists transpose m cS : List R := [] for rw in lLm repeat cS := concat(cS, reduce(_+, rw) ) construct cS )abbrev domain IARRAY2 IndexedTwoDimensionalArray IndexedTwoDimensionalArray(R, mnRow, mnCol) : Exports == Implementation where ++ An IndexedTwoDimensionalArray is a 2-dimensional array where ++ the minimal row and column indices are parameters of the type. ++ Rows and columns are returned as IndexedOneDimensionalArray's with ++ minimal indices matching those of the IndexedTwoDimensionalArray. ++ The index of the 'first' row may be obtained by calling the ++ function 'minRowIndex'. The index of the 'first' column may ++ be obtained by calling the function 'minColIndex'. The index of ++ the first element of a 'Row' is the same as the index of the ++ first column in an array and vice versa. R : Type mnRow, mnCol : Integer Row ==> IndexedOneDimensionalArray(R, mnCol) Col ==> IndexedOneDimensionalArray(R, mnRow) Exports ==> TwoDimensionalArrayCategory(R, Row, Col) Implementation ==> InnerIndexedTwoDimensionalArray(R, mnRow, mnCol, Row, Col) )abbrev domain ARRAY2 TwoDimensionalArray TwoDimensionalArray(R) : Exports == Implementation where ++ A TwoDimensionalArray is a two dimensional array with ++ 1-based indexing for both rows and columns. R : Type Row ==> OneDimensionalArray R Col ==> OneDimensionalArray R Exports ==> TwoDimensionalArrayCategory(R, Row, Col) Implementation ==> InnerIndexedTwoDimensionalArray(R, 1, 1, Row, Col) add Qelt2 ==> QAREF2O$Lisp Qsetelt2 ==> QSETAREF2O$Lisp -- qelt and qsetelt! are logically unnecessary, but good for -- performance qelt(m, i, j) == Qelt2(m, i, j, 1@Integer, 1@Integer) qsetelt!(m, i, j, r) == Qsetelt2(m, i, j, r, 1@Integer, 1@Integer) --Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd. --All rights reserved. -- --Redistribution and use in source and binary forms, with or without --modification, are permitted provided that the following conditions are --met: -- -- - Redistributions of source code must retain the above copyright -- notice, this list of conditions and the following disclaimer. -- -- - Redistributions in binary form must reproduce the above copyright -- notice, this list of conditions and the following disclaimer in -- the documentation and/or other materials provided with the -- distribution. -- -- - Neither the name of The Numerical ALgorithms Group Ltd. nor the -- names of its contributors may be used to endorse or promote products -- derived from this software without specific prior written permission. -- --THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS --IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED --TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A --PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER --OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, --EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, --PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR --PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF --LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING --NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS --SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
A11 := matrix [[2]] A12 := matrix [[1,2,3]] A21 := matrix [[1],[7]] A22 := matrix [[-3,1,0],[5,5,3]] A := array2([[A11, A12],[A21, A22]])$ARRAY2(Matrix Integer) B11 := matrix [[2]] B21:= matrix [[2],[3], [1]] B := array2 [[B11],[B21]]$ARRAY2(Matrix Integer) A B A*B