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}