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} }