/* Copyright 2011 Toby D. Rule
This file is part of CompPad, an OpenOffice extension to provide live
mathematical and engineering calculations within a Writer document.
CompPad is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
CompPad is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with CompPad. If not, see <http://www.gnu.org/licenses/>.
*/
package com.CompPad.model;
import com.CompPad.model.operators.Operator;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jscience.mathematics.number.Complex;
import org.jscience.physics.amount.Amount;
import javax.measure.unit.Unit;
import org.jscience.mathematics.vector.ComplexMatrix;
/**
*
* @author trule
*/
public class Matrix {
/* Elements handled as linked lists. Each element will be handled individually
to keep things simple, for now. */
private int m;
private int n;
private ArrayList<ArrayList> rows = new ArrayList<ArrayList>();
private Unit unit;
private ComplexMatrix matrix;
private Matrix(){
}
public static Matrix valueOf(Object o){
/* Create a matrix with one element, o */
Matrix A = new Matrix();
A.m=1;
A.n=1;
A.rows.add(new ArrayList());
A.rows.get(0).add(o);
return A;
}
/* Build an empty matrix */
public Matrix(Integer nrows, Integer ncols){
m = nrows;
n = ncols;
for (int i = 0; i < nrows; i++){
this.rows.add(new ArrayList());
for (int j = 0; j < ncols; j++){
rows.get(rows.size()-1).add(null);
}
}
}
public Matrix copy(){
Matrix A = new Matrix();
A.m=this.m;
A.n=this.n;
for (ArrayList row:this.rows){
ArrayList newRow = new ArrayList();
for (Object o:row){
newRow.add(o);
}
A.rows.add(newRow);
}
return A;
}
Matrix addColumn(Object o){
Matrix A = this.copy();
if (A.m==1){
A.rows.get(0).add(o);
A.n+=1;
Logger.getLogger("com.CompPad").log(Level.FINE,A.toString());
return A;
}
else{
return A.addColumn(Matrix.valueOf(o));
}
}
Matrix addColumn(Matrix Barg){
ArrayList x;
Matrix A = this.copy();
Matrix B = Barg.copy();
Integer mm = Math.max(A.m, B.m);
/* Fill in with null values */
if (mm > A.m){
for (int i = A.m; i<mm; ++i){
x = new ArrayList();
for (int j = 0; j < A.n; ++j){
x.add(null);
}
A.rows.add(x);
}
}
else if (mm > B.m){
for (int i = B.m; i<mm; ++i){
x = new ArrayList();
for (int j = 0; j < B.n; ++j){
x.add(null);
}
B.rows.add(x);
}
}
for (int i = 0; i < mm; ++i){
A.rows.get(i).addAll(B.rows.get(i));
}
A.m = mm;
A.n=A.n+B.n;
return A;
}
// Matrix addColumn(Matrix B){
//
// Matrix A = this.copy();
// if (A.m==B.m){
// for (int i = 0; i < A.m; ++i){
// A.rows.get(i).addAll(B.rows.get(i));
// }
// A.n=A.n+B.n;
// return A;
// }
// else{
// throw (new UnsupportedOperationException(
// "addcolumn for rows(A) <> rows(B) not supported."));
// }
// }
// Matrix addColumn(Matrix B){
Matrix addRow(Matrix v){
if (v.m==1){
if (this.n==v.n){
Matrix A = this.copy();
/* Make sure we're actually adding a copy of this row and not
a reference to the ArrayList! */
A.rows.add(v.rows.get(0));
A.m+=1;
return A;
}
else{
throw(new IllegalArgumentException("ncolumns does not match"));
}
}
else{
Matrix A = this.copy();
for (ArrayList row :v.rows){
A.rows.add(row);
A.m+=1;
}
return A;
// throw(new UnsupportedOperationException("addRow(Matrix v) not supported where v.m>1"));
}
}
public int nrows(){
return m;
}
public int ncolumns(){
return n;
}
public Object get(int i, int j){
if (i>=this.m||j >= this.n){
throw new IllegalArgumentException("Cannot access index ["
+i+","+j+"] of matrix of size {"+this.m+"x"+this.n+"}");
}
return rows.get(i).get(j);
}
public Object get(int i){
/* Return element i of a 1-vector */
if (this.m==1){
return rows.get(0).get(i);
}
else if (this.n == 1){
return rows.get(i).get(0);
}
else {
throw new IllegalArgumentException("m>1 and n>1 so subscript must be vector");
}
}
public Object get(Matrix B){
/* Return slices of A. Row slices specified by first column of B. Column slices
* specified by second columm of B.
* If b.nrows()>1 then return matrix
* If slice is a single element (b.nrows()=1), then
return that element, not a 1x1 matrix */
Matrix A = this.copy();
if(B.ncolumns() == 1){
if (A.m==1){
B = Matrix.valueOf(ComplexAmount.valueOf(0.0, Unit.ONE)).addColumn(B);
}
else if (A.n == 1){
B = B.addColumn(ComplexAmount.valueOf(0.0, Unit.ONE));
}
else{
throw new IllegalArgumentException("Two subscripts required");
}
}
ArrayList row = new ArrayList();
Matrix retval = new Matrix();
int ix;
int jx;
retval.m = 0;
for (int i1 = 0; i1 < B.nrows(); ++i1){
if(B.rows.get(i1).get(0) != null){
retval.m++;
retval.n = 0;
for (int i2=0; i2< B.nrows(); ++i2){
if (B.rows.get(i2).get(1) != null ){
ix = ( (ComplexAmount) B.rows.get(i1).get(0)).getReal(Unit.ONE).intValue();
jx = ( (ComplexAmount) B.rows.get(i2).get(1)).getReal(Unit.ONE).intValue();
if (ix >= m){
throw new IllegalArgumentException("Cannot access row "+(ix+1)+ " of matrix with "+m+" rows");
}
if (jx >= n){
throw new IllegalArgumentException("Cannot access column "+(jx+1)+ " of matrix with "+n+" rows");
}
row.add(A.rows.get(ix).get(jx));
retval.n++;
}
}
retval.rows.add(row);
row = new ArrayList();
}
}
return retval;
}
public void set(int i, int j, Object o){
rows.get(i).set(j, o);
}
public Matrix plus(Matrix A){
/* Check that they are same size */
int thisIsMatrix=1;
int AIsMatrix=1;
if (this.m!=A.m){
throw new IllegalArgumentException("Size mismatch");
}
if (this.n==1){
thisIsMatrix=0;
}
if (A.n==1){
AIsMatrix=0;
}
if (thisIsMatrix==1 & AIsMatrix==1 & this.n!=A.n){
throw new IllegalArgumentException("Size mismatch");
}
Matrix retval = new Matrix();
retval.m = A.m;
retval.n=Math.max(this.n,A.n);
ArrayList newRow;
ArrayList thisRow;
ArrayList ARow;
Object thisObj;
Object AObj;
for (int i=0; i<retval.m; ++i){
newRow = new ArrayList();
thisRow = this.rows.get(i);
ARow = A.rows.get(i);
for (int j = 0; j < retval.n; ++j){
thisObj = thisRow.get(j*thisIsMatrix);
AObj = ARow.get(j*AIsMatrix);
if (ComplexAmount.class.isInstance(thisObj)&ComplexAmount.class.isInstance(AObj)){
newRow.add(((ComplexAmount)thisObj).plus((ComplexAmount)AObj));
}
else{
throw new IllegalArgumentException("Elements must be ComplexAmount");
}
}
retval.rows.add(newRow);
}
return retval;
}
public Matrix plus(ComplexAmount x){
Matrix A = new Matrix();
A.m=this.m;
A.n=this.n;
for (ArrayList row:this.rows){
ArrayList newRow = new ArrayList();
for (Object o:row){
if (ComplexAmount.class.isInstance(o)){
newRow.add(x.plus((ComplexAmount)o));
}
else{
throw new IllegalArgumentException("Array Elements must be ComplexAmount");
}
}
A.rows.add(newRow);
}
return A;
}
public Matrix minus(ComplexAmount x){
return this.plus(x.opposite());
}
public Matrix minus(Matrix A){
return this.plus(A.times(ComplexAmount.valueOf(-1.0,Unit.ONE)));
}
public Matrix multiply(ComplexAmount x){
return times(x);
}
public Matrix multiply(Matrix x){
return times(x);
}
public Matrix multiply_vec(ComplexAmount b){
return this.multiply(b);
}
public Matrix multiply_vec(Matrix b) throws Exception{
return this.forEachElement("multiply", b);
}
public Object multiply(Object o) throws Exception{
/* see if o has a method "multiply" which takes argument of type Matrix -
This assumes that the operand order can be switched, which isn't always
the case with multiply, but the main application of this method is
to allow for elementwise operations, which are */
Object retval;
try{
java.lang.reflect.Method z = o.getClass().getMethod("multiply", Matrix.class);
retval = z.invoke(o, this);
}
catch(Exception e){
throw new Exception("Cannot multiply these two operands");
}
return retval;
}
public Matrix opposite(){
return this.times(ComplexAmount.valueOf(-1.0,Unit.ONE));
}
public Matrix times(ComplexAmount x){
Matrix A = new Matrix();
A.m=this.m;
A.n=this.n;
for (ArrayList row:this.rows){
ArrayList newRow = new ArrayList();
for (Object o:row){
if (ComplexAmount.class.isInstance(o)){
newRow.add(x.times((ComplexAmount)o));
}
else{
throw new IllegalArgumentException("Array Elements must be ComplexAmount");
}
}
A.rows.add(newRow);
}
return A;
}
/* formulate matrix */
private void doMatrix(){
Complex x[][] = new Complex[m][n];
/* This naively assumes that the first element is ComplexAmount, and has
* the same units as all the other elements */
this.unit = ((ComplexAmount)rows.get(0).get(0)).getUnit();
for (int i=0; i<m; ++i){
for (int j=0; j<n; ++j){
x[i][j] = ((ComplexAmount)rows.get(i).get(j)).getComplex();
}
}
this.matrix = ComplexMatrix.valueOf(x);
}
public Matrix times(Matrix A){
if (this.n != A.m){
throw new org.jscience.mathematics.vector.DimensionException(
"Cannot multiply matrices with dimensions "
+this.m+"x"+this.n+" and "+A.m+"x"+A.n);
}
this.doMatrix();
A.doMatrix();
Matrix retval = new Matrix();
retval.matrix = this.matrix.times(A.matrix);
retval.unit= this.unit.times(A.unit);
/* Now convert back to rows format because for now I'm not
* going to try to manage two data types */
retval.doRows();
return retval;
}
public Matrix div_vec(ComplexAmount b) throws Exception{
return this.div(b);
}
public Matrix div_vec(Matrix b) throws Exception{
return this.forEachElement("div", b);
}
public Matrix div(ComplexAmount b) throws Exception{
return this.forEachElement("div", b,null);
}
public Matrix div(Matrix A){
throw new IllegalArgumentException("Pseudoinverse not yet supported");
}
public Object div(Object o) throws Exception{
/* If we can't do this.div(o) then see if o has a method "inverseAndMultiplyBy"
and multiply by the inverse */
Object retval;
java.lang.reflect.Method f;
try{
f = o.getClass().getMethod("inverseAndMultiplyBy",Matrix.class);
}
catch(Exception e){
throw new Exception("Cannot divide Matrix by arg2");
}
retval = f.invoke(o,this);
return retval;
}
public Matrix divElements(Matrix A){
throw new UnsupportedOperationException("Not yet implemented");
}
public Matrix timesElements(Matrix A){
throw new UnsupportedOperationException("Not yet implemented");
}
public Matrix power_vec(ComplexAmount b) throws Exception{
return this.forEachElement("power", b, null);
}
public Matrix power_vec(Matrix b) throws Exception{
return this.forEachElement("power",b);
}
public Matrix power(ComplexAmount a){
if (this.m!=this.n){
throw new org.jscience.mathematics.vector.DimensionException(
"Cannot take exponent of non-square matrix");
}
Matrix retval = this.copy();
if (a.getUnit().isCompatible(Unit.ONE)){
if (a.isReal() & a.isInteger()){
Integer exp = (int) a.getReal(Unit.ONE).longValue();
retval.doMatrix();
retval.unit = retval.unit.pow(exp);
retval.matrix= (ComplexMatrix) retval.matrix.pow(exp);
retval.doRows();
return retval;
}
else{
throw new IllegalArgumentException(" non-integer exponents of matrices are not yet supported ");
}
}
else{
/* exponent not dimensionless */
throw new IllegalArgumentException("Exponent must be dimensionless");
}
}
public Matrix sqrt_vec() throws Exception{
return this.forEachElement("sqrt");
}
public Matrix sqrt(){
throw(new UnsupportedOperationException(
"JScience does not support sqrt for matrices"));
}
public Matrix nroot_vec(Matrix a) throws Exception {
return this.forEachElement("pow",a.forEachElement("inverse"));
}
public Matrix nroot_vec(ComplexAmount a) throws Exception{
return this.forEachElement("pow",a.inverse(), false);
}
@Override
public String toString(){
return rows.toString();
}
public Matrix inverse(){
this.doMatrix();
Matrix retval = new Matrix();
retval.matrix = this.matrix.inverse();
retval.unit= this.unit.inverse();
/* Now convert back to rows format because for now I'm not
* going to try to manage two data types */
retval.doRows();
return retval;
}
private void doRows(){
/* Convert ComplexMatrix data to rows format */
this.m = this.matrix.getNumberOfRows();
this.n = this.matrix.getNumberOfColumns();
this.rows=new ArrayList();
for (int i=0; i<this.m; ++i){
ArrayList newRow = new ArrayList();
for (int j=0; j<this.n; ++j){
newRow.add(ComplexAmount.valueOf(this.matrix.get(i, j), this.unit));
}
this.rows.add(newRow);
}
}
public Matrix transpose(){
Matrix retval = new Matrix();
retval.m = this.n;
retval.n = this.m;
retval.rows = new ArrayList();
for (int i=0; i<retval.m; ++i){
ArrayList newRow = new ArrayList();
for (int j=0; j<retval.n; ++j){
newRow.add(this.get(j, i));
}
retval.rows.add(newRow);
}
return retval;
}
public ComplexAmount max(){
ComplexAmount ca;
ComplexAmount retval=null;
for (ArrayList row:this.rows){
for (Object o:row){
/* Assume it's a complexAmount */
ca = (ComplexAmount)o;
if (retval==null){
retval=ca;
}
else if (ca.gt(retval)){
retval=ca;
}
}
}
return retval.clone();
}
public ComplexAmount min(){
ComplexAmount ca;
ComplexAmount retval=null;
for (ArrayList row:this.rows){
for (Object o:row){
/* Assume it's a complexAmount */
ca = (ComplexAmount)o;
if (retval==null){
retval=ca;
}
else if (ca.lt(retval)){
retval=ca;
}
}
}
return retval.clone();
}
public ComplexAmount sum(){
ComplexAmount ca;
ComplexAmount retval=null;
for (ArrayList row:this.rows){
for (Object o:row){
/* Assume it's a complexAmount */
ca = (ComplexAmount)o;
if (retval==null){
retval=ca.clone();
}
else{
retval=retval.plus(ca);
}
}
}
return retval;
}
public ComplexAmount prod(){
ComplexAmount ca;
ComplexAmount retval=null;
for (ArrayList row:this.rows){
for (Object o:row){
/* Assume it's a complexAmount */
ca = (ComplexAmount)o;
if (retval==null){
retval=ca.clone();
}
else{
retval=retval.times(ca);
}
}
}
return retval;
}
public Matrix equals(Matrix B) throws Exception {
return this.forEachElement("equals",B);
}
public Matrix neq(Matrix B) throws Exception{
return this.forEachElement("equals",B ).not();
}
public Matrix not() throws Exception{
return this.forEachElement("equals",false,false);
}
public Matrix gt(Matrix B) throws Exception{
return this.forEachElement("gt", B);
}
public Matrix lt(Matrix B) throws Exception{
return this.forEachElement("lt",B);
}
public Matrix gte(Matrix B) throws Exception{
return this.forEachElement("gte", B);
}
public Matrix lte(Matrix B) throws Exception{
return this.forEachElement("lte",B);
}
public Matrix subscript(Matrix b){ return (Matrix) get(b);}
public Object subscript(ComplexAmount b){
return get(b.getReal(Unit.ONE).intValue());
}
public Matrix log() throws Exception{return forEachElement("log");}
public Matrix log10() throws Exception{return forEachElement("log10");}
public Matrix log2() throws Exception{return forEachElement("log2");}
public Matrix sin() throws Exception{return forEachElement("sin");}
public Matrix cos() throws Exception{return forEachElement("cos");}
public Matrix tan() throws Exception{return forEachElement("tan");}
public Matrix csc() throws Exception{return forEachElement("csc");}
public Matrix sec() throws Exception{return forEachElement("sec");}
public Matrix cot() throws Exception{return forEachElement("cot");}
public Matrix sin2() throws Exception{return forEachElement("sin2");}
public Matrix cos2() throws Exception{return forEachElement("cos2");}
public Matrix tan2() throws Exception{return forEachElement("tan2");}
public Matrix csc2() throws Exception{return forEachElement("csc2");}
public Matrix sec2() throws Exception{return forEachElement("sec2");}
public Matrix cot2() throws Exception{return forEachElement("cot2");}
public Matrix asin() throws Exception{return forEachElement("asin");}
public Matrix acos() throws Exception{return forEachElement("acos");}
public Matrix atan() throws Exception{return forEachElement("atan");}
public Matrix acsc() throws Exception{return forEachElement("acsc");}
public Matrix asec() throws Exception{return forEachElement("asec");}
public Matrix acot() throws Exception{ return forEachElement("acot"); }
public Matrix round(ComplexAmount u) throws Exception{
return this.forEachElement("round",u,false);
}
public Matrix round(Matrix U) throws Exception{
return this.forEachElement("round",U);
}
public Matrix floor(ComplexAmount u) throws Exception{
return this.forEachElement("floor",u,false);
}
public Matrix floor(Matrix U) throws Exception{
return this.forEachElement("floor",U);
}
public Matrix ceil(ComplexAmount u) throws Exception{
return this.forEachElement("ceil",u,false);
}
public Matrix ceil(Matrix U) throws Exception{
return this.forEachElement("ceil",U);
}
public static Object rand(ComplexAmount cn, ComplexAmount cm){
int m;
int n;
Object retval = null;
if (cn.isInteger() & cm.isInteger()
& cn.getUnit().isCompatible(Unit.ONE)
& cm.getUnit().isCompatible(Unit.ONE)){
m = Operators.round(ComplexAmount.valueOf(Amount.ONE),cm).getReal(Unit.ONE).intValue();
n = Operators.round(ComplexAmount.valueOf(Amount.ONE),cn).getReal(Unit.ONE).intValue();
}
else{
throw (new IllegalArgumentException("arguments must be integer"));
}
if (m == 0 & n == 0){
retval = ComplexAmount.valueOf(Complex.valueOf(Math.random(), 0) , Unit.ONE);
}
else{
for (int i=0; i< m; ++i){
Matrix row = Matrix.valueOf(ComplexAmount.valueOf(Complex.valueOf(Math.random(),0),Unit.ONE));
for (int j=1; j<n; ++j){
row = row.addColumn(ComplexAmount.valueOf(Complex.valueOf(Math.random(),0),Unit.ONE));
}
if (i == 0){
retval = row;
}
else{
retval = ((Matrix)retval).addRow(row);
}
}
}
return retval;
}
public static Object zeros(ComplexAmount cn, ComplexAmount cm){
int m;
int n;
Object retval = null;
if (cn.isInteger() & cm.isInteger()
& cn.getUnit().isCompatible(Unit.ONE)
& cm.getUnit().isCompatible(Unit.ONE)){
m = Operators.round(ComplexAmount.valueOf(Amount.ONE),cm).getReal(Unit.ONE).intValue();
n = Operators.round(ComplexAmount.valueOf(Amount.ONE),cn).getReal(Unit.ONE).intValue();
}
else{
throw (new IllegalArgumentException("arguments must be integer"));
}
if (m == 0 & n == 0){
retval = ComplexAmount.valueOf(Amount.ZERO);
}
else{
for (int i=0; i< m; ++i){
Matrix row = Matrix.valueOf(ComplexAmount.valueOf(Amount.ZERO));
for (int j=1; j<n; ++j){
row = row.addColumn(ComplexAmount.valueOf(Amount.ZERO));
}
if (i == 0){
retval = row;
}
else{
retval = ((Matrix)retval).addRow(row);
}
}
}
return retval;
}
public Matrix real() throws java.lang.Exception{
return this.forEachElement(Operators.class,
Operators.class.getMethod("real", ComplexAmount.class));
}
public Matrix imaginary() throws java.lang.Exception{
return this.forEachElement(Operators.class,
Operators.class.getMethod("imaginary",ComplexAmount.class));
}
public Matrix argument () throws java.lang.Exception{
return this.forEachElement(Operators.class,
Operators.class.getMethod("argument", ComplexAmount.class));
}
public Matrix signum () throws java.lang.Exception{
return this.forEachElement(Operators.class,
Operators.class.getMethod("signum", ComplexAmount.class));
}
public Matrix conjugate () throws java.lang.Exception{
return this.forEachElement(Operators.class,
Operators.class.getMethod("argument", ComplexAmount.class));
}
public static Object ones(ComplexAmount cn, ComplexAmount cm){
int m;
int n;
Object retval = null;
if (cn.isInteger() & cm.isInteger()
& cn.getUnit().isCompatible(Unit.ONE)
& cm.getUnit().isCompatible(Unit.ONE)){
m = Operators.round(ComplexAmount.valueOf(Amount.ONE),cm).getReal(Unit.ONE).intValue();
n = Operators.round(ComplexAmount.valueOf(Amount.ONE),cn).getReal(Unit.ONE).intValue();
}
else{
throw (new IllegalArgumentException("arguments must be integer"));
}
if (m == 0 & n == 0){
retval = ComplexAmount.valueOf(Amount.ONE);
}
else{
for (int i=0; i< m; ++i){
Matrix row = Matrix.valueOf(ComplexAmount.valueOf(Amount.ONE));
for (int j=1; j<n; ++j){
row = row.addColumn(ComplexAmount.valueOf(Amount.ONE));
}
if (i == 0){
retval = row;
}
else{
retval = ((Matrix)retval).addRow(row);
}
}
}
return retval;
}
public ComplexAmount getNumberOfRows(){
return ComplexAmount.valueOf(Double.valueOf(Integer.toString(this.m)), Unit.ONE);
}
public ComplexAmount getNumberOfColumns(){
return ComplexAmount.valueOf(Double.valueOf(Integer.toString(this.n)), Unit.ONE);
}
public Matrix forEachElement(Object ob, Method method)
throws java.lang.Exception {
Matrix A = new Matrix();
A.m=this.m;
A.n=this.n;
for (ArrayList row:this.rows){
ArrayList newRow = new ArrayList();
for (Object o:row){
// if (ComplexAmount.class.isInstance(o)){
newRow.add(method.invoke(ob, o));
// }
// else{
// throw new IllegalArgumentException("Array Elements must be ComplexAmount");
// }
}
A.rows.add(newRow);
}
return A;
}
/* Call the specified method for each element of the matrix */
public Matrix forEachElement(Object ob, Method method , Object arg, Boolean reverse)
throws java.lang.Exception {
Matrix A = new Matrix();
A.m=this.m;
A.n=this.n;
for (ArrayList row:this.rows){
ArrayList newRow = new ArrayList();
for (Object o:row){
// if (ComplexAmount.class.isInstance(o)){
if (reverse){
newRow.add(method.invoke(ob, arg, o));
}
else{
newRow.add(method.invoke(ob, o, arg));
}
// }
// else{
// throw new IllegalArgumentException("Array Elements must be ComplexAmount");
// }
}
A.rows.add(newRow);
}
return A;
}
public Matrix forEachElement(String smethod, ComplexAmount arg, Boolean reverse)
throws java.lang.Exception {
/* Applies Operator op to each element of the array */
if (reverse==null){reverse = false;}
Method method = ComplexAmount.class.getMethod(smethod, arg.getClass());
Matrix A = new Matrix();
A.m=this.m;
A.n=this.n;
for (ArrayList row:this.rows){
ArrayList newRow = new ArrayList();
for (Object o:row){
/* Right now we're assuming o is a complex amount */
if (ComplexAmount.class.isInstance(o)){
if (reverse == false){
newRow.add(method.invoke(o, arg));
}
else{
/* Reverse order of operations for each element */
newRow.add(method.invoke(arg, o));
}
}
else{
throw new IllegalArgumentException("Array Elements must be ComplexAmount");
}
}
A.rows.add(newRow);
}
return A;
}
public Matrix forEachElement(String smethod, Boolean arg, Boolean reverse)
throws java.lang.Exception {
/* Applies Operator op to each element of the array */
if (reverse==null){reverse = false;}
Method method = Boolean.class.getMethod(smethod, Object.class);
Matrix A = new Matrix();
A.m=this.m;
A.n=this.n;
for (ArrayList row:this.rows){
ArrayList newRow = new ArrayList();
for (Object o:row){
/* Right now we're assuming o is a complex amount */
if (Boolean.class.isInstance(o)){
if (reverse == false){
newRow.add(method.invoke(o, arg));
}
else{
/* Reverse order of operations for each element */
newRow.add(method.invoke(arg, o));
}
}
else{
throw new IllegalArgumentException("Array Elements must be Boolean");
}
}
A.rows.add(newRow);
}
return A;
}
public Matrix forEachElement(String smethod, Matrix arg)
throws java.lang.Exception {
/* Applies Operator op to each element of the array */
/* We're assuming the elements have ComplexAmount members */
int thisIsMatrix=1;
int argIsMatrix=1;
if (this.m!=arg.m){
throw new IllegalArgumentException("Size mismatch");
}
if (this.n==1){
thisIsMatrix=0;
}
if (arg.n==1){
argIsMatrix=0;
}
if (thisIsMatrix==1 & argIsMatrix==1 & this.n!=arg.n){
throw new IllegalArgumentException("Size mismatch");
}
Matrix A = new Matrix();
A.m=this.m;
A.n=Math.max(this.n,arg.n);
Object argObj;
Object thisObj;
ArrayList newRow;
for (int i=0; i<A.m; ++i){
newRow = new ArrayList();
for (int j = 0 ; j < A.n; ++j){
thisObj = this.get(i,j*thisIsMatrix);
argObj = arg.get(i, j*argIsMatrix);
/* Right now we're assuming o is a complex amount */
if (ComplexAmount.class.isInstance(thisObj) && ComplexAmount.class.isInstance(argObj)){
Method method = ComplexAmount.class.getMethod(smethod, ComplexAmount.class);
newRow.add( method.invoke((ComplexAmount)thisObj, (ComplexAmount) argObj ));
}
else if (Boolean.class.isInstance(thisObj) && Boolean.class.isInstance(argObj)){
Method method = Boolean.class.getMethod(smethod, Object.class);
newRow.add(method.invoke((Boolean) thisObj,(Boolean)argObj));
}
else{
throw new IllegalArgumentException("Elements with type "+thisObj.getClass().toString() +
", "+ argObj.getClass().toString() + "not supported for "+smethod);
}
}
A.rows.add(newRow);
}
return A;
}
public Matrix forEachElement(Object ob, Method method, Matrix arg)
throws java.lang.Exception {
/* Applies Operator op to each element of the array */
/* We're assuming the elements have ComplexAmount members */
int thisIsMatrix=1;
int argIsMatrix=1;
if (this.m!=arg.m){
throw new IllegalArgumentException("Size mismatch");
}
if (this.n==1){
thisIsMatrix=0;
}
if (arg.n==1){
argIsMatrix=0;
}
if (thisIsMatrix==1 & argIsMatrix==1 & this.n!=arg.n){
throw new IllegalArgumentException("Size mismatch");
}
// Method method = ComplexAmount.class.getMethod(smethod, ComplexAmount.class);
Matrix A = new Matrix();
A.m=this.m;
A.n=Math.max(this.n,arg.n);
Object argObj;
Object thisObj;
ArrayList newRow;
for (int i=0; i<A.m; ++i){
newRow = new ArrayList();
for (int j = 0 ; j < A.n; ++j){
thisObj = this.get(i,j*thisIsMatrix);
argObj = arg.get(i, j*argIsMatrix);
/* Right now we're assuming o is a complex amount */
// if (ComplexAmount.class.isInstance(thisObj) & ComplexAmount.class.isInstance(argObj)){
newRow.add( method.invoke(ob, thisObj, argObj ));
// }
// else{
// throw new IllegalArgumentException("Array Elements must be ComplexAmount");
// }
}
A.rows.add(newRow);
}
return A;
}
public Matrix forEachElement(String smethod)
throws java.lang.Exception {
/* Applies Operator op to each element of the array */
Method method = ComplexAmount.class.getMethod(smethod);
Matrix A = new Matrix();
A.m=this.m;
A.n=this.n;
for (ArrayList row:this.rows){
ArrayList newRow = new ArrayList();
for (Object o:row){
/* Right now we're assuming o is a complex amount */
if (ComplexAmount.class.isInstance(o)){
newRow.add(method.invoke(o));
}
else{
throw new IllegalArgumentException("Array Elements must be ComplexAmount");
}
}
A.rows.add(newRow);
}
return A;
}
public Matrix forEachElement(Operator op, ComplexAmount arg)
throws java.lang.Exception {
/* Applies Operator op to each element of the array */
Matrix A = new Matrix();
A.m=this.m;
A.n=this.n;
for (ArrayList row:this.rows){
ArrayList newRow = new ArrayList();
for (Object o:row){
/* Right now we're assuming o is a complex amount */
newRow.add(op.call(arg));
}
A.rows.add(newRow);
}
return A;
}
}