type Dimensions = {
m->Number
n->Number
==(_:DimType)->Boolean
asString->String}
type MathMatrix = {
dimensions->Dimensions
setValue(_:Number)atRow(_:Number)column(_:Number)->Void
atRow(_:Number)column(_:Number)->Number
add(_:MathMatrix)->MathMatrix
sub(_:MathMatrix)->MathMatrix
scalarMult(_:Number)->MathMatrix
getRow(_:Number)->Dynamic
getCol(_:Number)->Dynamic
matrixMult(_:MathMatrix)->MathMatrix
transpose->MathMatrix
asString->String}
class MatrixDimensions.new(r:Number, c:Number){
def m:Number is public, readable = r
def n:Number is public, readable = c
method ==(other:Dimensions)->Boolean is public{
(m == other.m) && (n == other.n)}
method asString->String is public{"{m}x{n}"}
}
//constructs matrix with r rows, c columns, and all entries set to 0
method withRows(r:Number)columns(c:Number)->MathMatrix{Matrix.new(r, c)}
class Matrix.new(numRows:Number, numCols:Number){
//array containing rows of matrix
var index is readable := PrimitiveArray.new(numRows)
def dimensions:Dimensions is public, readable :=
MatrixDimensions.new(numRows, numCols)
//create rows, all values start off set to 0
for(0..(numRows - 1)) do {i->
var thisRow := PrimitiveArray.new(numCols)
index[i] := thisRow
for(0..(numCols - 1)) do {j->
thisRow[j] := 0}
}
// sets entry at row i, column j to val
method setValue(val:Number)atRow(i:Number)column(j:Number)->Void is public{
if((i < 1)||(j < 1)||(i > dimensions.m)||(j > dimensions.n)) then{
print "Invalid index {i}, {j}"}
else{
var theRow := index[i - 1]
theRow[j - 1] := val}
}
// returns entry at row i, column j, or 0 if dimensions are invalid
method atRow(i:Number)column(j:Number)->Number is public{
if((i < 1)||(j < 1)||(i > dimensions.m)||(j > dimensions.n)) then{
print "Invalid index; returning 0"
0}
else{
var theRow := index[i - 1]
theRow[j - 1]}
}
// returns sum of this matrix to other, or
// other if the dimensions are not the same
method add(other:MathMatrix)->MathMatrix is public{
if(!(dimensions == other.dimensions)) then {
print "Invalid dimensions; can't add. Returning argument."
return other}
else{
var result := Matrix.new(dimensions.m, dimensions.n)
for(1..dimensions.m) do{i->
for(1..dimensions.n) do {j->
result.setValue(atRow(i)column(j) + other.atRow(i)column(j))
atRow(i)column(j)}
}
return result}
}
// returns difference of this matrix and other, or
// other if the dimensions are not the same
method sub(other:MathMatrix)->MathMatrix is public{
if(!(dimensions == other.dimensions)) then {
print "Invalid dimensions; can't subtract. Returning argument."
return other}
else{
var result := Matrix.new(dimensions.m, dimensions.n)
for(1..dimensions.m) do{i->
for(1..dimensions.n) do {j->
result.setValue(atRow(i)column(j) - other.atRow(i)column(j))
atRow(i)column(j)}
}
return result}
}
//returns result of multiplying this matrix by the scalar lambda
method scalarMult(lambda:Number)->MathMatrix is public{
var result := Matrix.new(dimensions.m, dimensions.n)
for(1..dimensions.m) do{i->
for(1..dimensions.n) do {j->
result.setValue(lambda * atRow(i)column(j))atRow(i)column(j)}
}
return result
}
// returns the ith row of the matrix as an array, or an empty array
// if i is not a valid row entry
method getRow(i:Number)->Dynamic is public{
if((i < 1) || (i > dimensions.m)) then{
print "Invalid row index. Returning [empty]."
return PrimitiveArray.new(1)}
else{return index[i-1]}
}
// returns jth column of the matrix as an array, or an empty array
// if j is not a valid column entry
method getCol(j:Number)->Dynamic is public{
if((j < 1) || (j > dimensions.n)) then{
print "Invalid col index. Returning [empty]."
return PrimitiveArray.new(1)}
else{
var result := PrimitiveArray.new(dimensions.m)
for(0..(dimensions.m - 1)) do{row->
var thisRow := index[row]
result[row] := thisRow[j-1]}
return result
}
}
// returns the product of this matrix and other, or other if the
// dimensions are incorrect for matrix multiplication (# columns
// of this should equal # rows of other)
method matrixMult(other:MathMatrix)->MathMatrix is public{
if(dimensions.n != other.dimensions.m) then{
print "Invalid dimensions; can't multiply. Returning argument."
return other}
else{
var result:MathMatrix :=
Matrix.new(dimensions.m, other.dimensions.n)
for(1..dimensions.m) do {i->
var rowVector := getRow(i)
for(1..other.dimensions.n) do{j->
var colVector := other.getCol(j)
var sum := 0
for(0..(rowVector.size - 1)) do {k->
sum := sum + rowVector[k] * colVector[k]}
result.setValue(sum)atRow(i)column(j)}
}
return result}
}
// returns the transpose of this matrix
method transpose->MathMatrix is public{
var result:MathMatrix := Matrix.new(dimensions.n, dimensions.m)
for(1..dimensions.n) do{i->
for(1..dimensions.m) do{j->
result.setValue(atRow(j)column(i))atRow(i)column(j)}
}
return result}
// returns string representation of this matrix
method asString->String is public{
var s:String := "{dimensions} matrix:\n"
for(0..(index.size - 1)) do {i->
var thisRow := index[i]
for(0..(thisRow.size - 1)) do {j->
s := s ++ thisRow[j] ++ " "}
s := s ++ "\n"}
return s}
}