import io
import math_matrix
type MathMatrix = {
dimensions->Dimensions
setValue(_:Number)atRow(_:Number)column(_:Number)->Void
atRow(_:Number)columns(_:Number)->Number
add(_:MathMatrix)->MathMatrix
sub(_:MathMatrix)->MathMatrix
scalarMult(_:Number)->MathMatrix
getRow(_:Number)->Dynamic
getCol(_:Number)->Dynamic
matrixMult(_:MathMatrix)->MathMatrix
transpose->MathMatrix
asString->String}
var ostream := io.output
var istream := io.input
def default:MathMatrix = math_matrix.withRows 1 columns 1
var matrixA:MathMatrix := default
var matrixB:MathMatrix := default
var matrixC:MathMatrix := default
//returns line entered into standard input
method getLine->String{
var line:String := ""
var nxt := istream.next
while{nxt != "\n"} do {
line := line ++ nxt
nxt := istream.next}
return line}
//returns true if string only contains digits
method checkString(entry:String)->Boolean{
var entIter := entry.iter
while{entIter.havemore} do {
var nxt := entIter.next
if((nxt.ord < 48) || (nxt.ord > 57)) then{return false}
}
true}
//returns matrix selected by user
method getMatrix(chosen:String)->MathMatrix{
if(chosen == "A") then{matrixA}
else{if(chosen == "B") then{matrixB}
else{if(chosen == "C") then{matrixC}
else{
ostream.write("Invalid entry; must be A B or C: ")
getMatrix(getLine)}}}
}
//asks user to input desired numbers of rows and columns, creates
//empty matrix with those dimensions, and has user input values for
//each entry
//if user inputs invalid entry for dimensions or values, returns
//default 1x1 matrix
method makeMatrix->MathMatrix{
ostream.write("Enter number of rows: \n")
var entered:String := getLine
var rows:Number := 0
if(checkString(entered)) then{rows := entered.asNumber}
else{
ostream.write("Invalid entry\n")
return default}
ostream.write("Enter number of columns: \n")
entered := getLine
var cols:Number := 0
if(checkString(entered)) then{cols := entered.asNumber}
else{
ostream.write("Invalid entry\n")
return default}
var myMatrix:MathMatrix := if((cols > 0) && (rows > 0)) then{
math_matrix.withRows(rows)columns(cols)}
else{
ostream.write("Invalid dimensions\n")
default}
for(1..rows) do {i->
ostream.write("Row {i} :\n")
for(1..cols) do {j->
ostream.write("{i}, {j} = ")
entered := getLine
if(checkString(entered)) then{
myMatrix.setValue(entered.asNumber)atRow(i)column(j)}
else{myMatrix.setValue 0 atRow(i)column(j)}
}
}
return myMatrix}
//allows user to set dimensions and entries of selected matrix
method edit->Void{
ostream.write("Available matrices: A B C\n")
var choose := getLine
if(choose == "A") then{matrixA := makeMatrix}
else{if(choose == "B") then{matrixB := makeMatrix}
else{if(choose == "C") then{matrixC := makeMatrix}
else{ostream.write("Invalid entry\n")}}}}
//allows user to view selected matrix
method get->Void{
ostream.write("Available matrices: A B C\n")
var choose := getLine
ostream.write("{getMatrix(choose)}\n")}
//allows user to perform basic math on matrices and displays result
//does not currently allow operations on more than two matrices
method math->Void{
ostream.write("Available methods: + - * t\n")
var c := getLine
if(c == "*") then{
ostream.write("Enter s for scalar, m for matrix\n")
c := getLine
if(c == "s") then{ // scalar multiplication
ostream.write("First argument, expecting number: ")
c := getLine
var lambda:Number := 0
if(checkString(c)) then{lambda := c.asNumber}
else{
ostream.write("Invalid entry\n")
return None}
ostream.write("Second argument (A B C): ")
c := getLine
store(getMatrix(c).scalarMult(lambda))}
else{if(c == "m") then{ // matrix multiplication
ostream.write("First argument (A B C): ")
c := getLine
var first:MathMatrix := getMatrix(c)
ostream.write("Second argument (A B C): ")
c := getLine
var second:MathMatrix := getMatrix(c)
if(first.dimensions.n != second.dimensions.m) then {
ostream.write("Invalid dimensions\n")}
else{store(first.matrixMult(second))}}}}
else{if((c == "+") || (c == "-")) then{ //addition and subtraction
var op:String := c
ostream.write("First argument (A B C): ")
c := getLine
var first:MathMatrix := getMatrix(c)
ostream.write("Second argument (A B C): ")
c := getLine
var second:MathMatrix := getMatrix(c)
if(first.dimensions == second.dimensions) then{
if(op == "+") then {store(first.add(second))}
else{store(first.sub(second))}}
else{ostream.write("Invalid dimensions\n")}}
else{if(c == "t") then { //transpose
ostream.write("Argument (A B C): ")
store(getMatrix(getLine).transpose)}
else{ostream.write("Invalid method\n")}}}}
//allows user to store result of computation in slot A, B, or C
method store(result)->Void{
ostream.write("{result}\n")
ostream.write("Store result? y/n\n")
var c:String := getLine
if(c == "y") then {
ostream.write("Available matrices: A B C\n")
c := getLine
if(c == "A") then {matrixA := result}
else{if(c == "B") then{matrixB := result}
else{if(c == "C") then{matrixC := result}
else{ostream.write("Invalid entry\n")}}}
}
}
ostream.write("Options: get math edit quit\n")
//reads user input and executes until user inputs "quit"
var command:String := getLine
while{command != "quit"} do {
if(command == "edit") then{edit}
else{if(command == "get") then{get}
else{if(command == "math") then{math}
else{ostream.write("Invalid entry\n")}}}
ostream.write("Options: get math edit quit\n")
command := getLine}