/* 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 java.lang.reflect.InvocationTargetException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.measure.unit.SI;
import javax.measure.unit.Unit;
import org.jscience.mathematics.number.Complex;
import org.jscience.physics.amount.Amount;
/**
*
* @author brenda
*/
/* class to implement complex numbers using Amount and Complex objects.
* Maybe it would be better to subclass Amount, but will postpone that
* decision */
public class ComplexAmount {
/* Store values as amount x complex,
* where amount is normalized to ONE.
* NOTE: real component can be NEGATIVE! so must still combine real and amount */
private Unit cUnit;
private Complex cComplex;
private static Double zeroTol=1E-15;
/* Private constructor. Mirroring Amount class */
private ComplexAmount ComplexAmount (){
ComplexAmount retval = new ComplexAmount();
cUnit = Unit.ONE;
cComplex=Complex.valueOf(0.0, 0.0);
return retval;
}
public static ComplexAmount valueOf(Complex a, Unit b){
ComplexAmount retval=new ComplexAmount();
retval.cUnit= b;
retval.cComplex=a;
return retval;
}
public static ComplexAmount valueOf(Amount d){
/* Amount is positive, Complex is unit vector */
ComplexAmount retval=new ComplexAmount();
retval.cUnit=d.getUnit();
retval.cComplex=Complex.valueOf(d.doubleValue(d.getUnit()), 0.0);
return retval;
}
public static ComplexAmount valueOf(Double d, Unit u){
/* Amount is positive, Complex is unit vector */
ComplexAmount retval=new ComplexAmount();
retval.cUnit = u;
retval.cComplex=Complex.valueOf(d, 0.0);
return retval;
}
public static ComplexAmount valueOf(String s){
/* Amount is positive, Complex is unit vector */
ComplexAmount retval=new ComplexAmount();
Amount amount = Amount.valueOf(s);
retval.cUnit = amount.getUnit();
retval.cComplex=Complex.valueOf(amount.doubleValue(amount.getUnit()),0);
return retval;
}
public ComplexAmount to(Unit u){
ComplexAmount retval = this;
retval.cUnit = u.getStandardUnit();
retval.cComplex = this.cComplex.times(Amount.valueOf(1.0,this.cUnit).doubleValue(u.getStandardUnit()));
return retval;
}
public Complex getComplex(){
return this.cComplex;
}
// return unit object for this ComplexAmount
public Unit getUnit(){
return this.cUnit;
}
public ComplexAmount real (){
return this.getReal();
}
public ComplexAmount imaginary (){
return this.getImaginary();
}
public Double getReal(Unit u){
return this.cComplex.getReal()
* Amount.valueOf(1.0, this.cUnit).doubleValue(u);
}
public ComplexAmount getReal(){
ComplexAmount retval = this.clone();
retval.cComplex = Complex.valueOf(this.cComplex.getReal(),0);
return retval;
}
public Double getImaginary(Unit u){
return this.cComplex.getImaginary()
* Amount.valueOf(1.0, this.cUnit).doubleValue(u);
}
public ComplexAmount getImaginary(){
ComplexAmount retval = this.clone();
retval.cComplex = Complex.valueOf(this.cComplex.getImaginary(),0);
return retval;
}
public ComplexAmount conjugate(){
return ComplexAmount.valueOf(this.cComplex.conjugate(),this.cUnit);
}
public ComplexAmount argument(){
return ComplexAmount.valueOf(
Math.atan2(this.getImaginary(this.cUnit).doubleValue(),
this.getReal(this.cUnit).doubleValue()),
javax.measure.unit.SI.RADIAN);
}
public ComplexAmount signum(){
return this.divide(this.abs());
}
public ComplexAmount plus (ComplexAmount ca) {
/* Convert amount to same units */
ComplexAmount retval=this.clone();
if (! this.cUnit.isCompatible(ca.cUnit)){
String thisUnit = this.cUnit.toString();
String caUnit = ca.cUnit.toString();
if (thisUnit.equals("")){
thisUnit = "dimensionless";
}
if (caUnit.equals("")){
caUnit="dimensionless";
}
throw new java.lang.IllegalArgumentException("Incompatible units: ["+thisUnit+"] and ["+caUnit+"]");
}
retval.cComplex = retval.cComplex.plus(ca.cComplex.times(Amount.valueOf(1,ca.cUnit).doubleValue(this.cUnit)));
return retval;
}
/* If CompleAmount doesn't have a plus operator valid for the object, then
* see if object has plus operator valid for ComplexAmount */
public Object plus(Object o) throws Exception {
/* see if o has a method "plus" which takes argument of type ComplexAmount */
Object retval;
try{
java.lang.reflect.Method m = o.getClass().getMethod("plus", ComplexAmount.class);
retval = m.invoke(o, this);
}
catch(Exception e){
throw new Exception("Cannot add these two operands");
}
return retval;
}
public ComplexAmount opposite(){
ComplexAmount retVal=this.clone();
retVal.cComplex=retVal.cComplex.opposite();
return retVal;
}
public ComplexAmount clone(){
ComplexAmount retval = new ComplexAmount();
retval.cUnit = this.cUnit;
retval.cComplex= this.cComplex;
return retval;
}
public ComplexAmount inverse(){
ComplexAmount retVal;
retVal = this.clone();
retVal.cUnit = retVal.cUnit.inverse();
retVal.cComplex = retVal.cComplex.inverse();
return retVal;
}
public ComplexAmount minus(ComplexAmount ca) {
ComplexAmount retVal=this.clone();
retVal = retVal.plus(ca.opposite());
return retVal;
}
/* If CompleAmount doesn't have a minus operator valid for the object, then
* see if object has plus operator valid for ComplexAmount */
public Object minus(Object o) throws Exception {
/* see if o has a method "plus" which takes argument of type ComplexAmount */
Object retval;
try{
java.lang.reflect.Method opposite = o.getClass().getMethod("opposite");
java.lang.reflect.Method plus = o.getClass().getMethod("plus", ComplexAmount.class);
retval = plus.invoke(opposite.invoke(o), this);
}
catch(Exception e){
throw new Exception("Subtraction operator not valid for these operands");
}
return retval;
}
public ComplexAmount times(ComplexAmount ca){
/* Multiply amount and complex separately, then normalize */
ComplexAmount retVal=this.clone();
retVal.cUnit = retVal.cUnit.times(ca.cUnit);
retVal.cComplex = retVal.cComplex.times(ca.cComplex);
return retVal;
}
public ComplexAmount multiply_vec(ComplexAmount b){
return this.multiply(b);
}
public Matrix multiply_vec(Matrix b) throws Exception{
return b.multiply(this);
}
public ComplexAmount multiply (Boolean b){
if (b){
return this;
}
else{
return ComplexAmount.valueOf(Amount.ZERO);
}
}
public ComplexAmount multiply(ComplexAmount ca){
return this.times(ca);
}
public Object multiply(Object o) throws Exception{
/* see if o has a method "multiply" which takes argument of type ComplexAmount */
Object retval;
try{
java.lang.reflect.Method m = o.getClass().getMethod("multiply", ComplexAmount.class);
retval = m.invoke(o, this);
}
catch(Exception e){
throw new Exception("Cannot multiply these two operands");
}
return retval;
}
public ComplexAmount divide (ComplexAmount ca){
ComplexAmount retVal=this.clone();
retVal.cUnit = this.cUnit.divide(ca.cUnit);
retVal.cComplex = this.cComplex.divide(ca.cComplex);
return retVal;
}
public ComplexAmount div_vec(ComplexAmount b) throws Exception{
return this.div(b);
}
public Matrix div_vec(Matrix b) throws Exception{
return b.forEachElement("div", this,true);
}
public ComplexAmount div(ComplexAmount ca){
return divide(ca);
}
public Object div(Object o) throws Throwable{
// try multiplying by inverse //
Object retval=null;
try{
java.lang.reflect.Method m = o.getClass().getMethod("inverse");
Object arg = m.invoke(o);
retval = this.multiply(arg);
}
catch (InvocationTargetException e){
throw e.getTargetException();
}
catch(Exception e){
throw new Exception("Cannot divide these two operands");
}
return retval;
}
public ComplexAmount sqrt_vec(){
return this.sqrt();
}
public ComplexAmount sqrt(){
ComplexAmount retVal=this.clone();
retVal.cUnit = this.cUnit.root(2);
retVal.cComplex = this.cComplex.sqrt();
return retVal;
}
public ComplexAmount nroot(ComplexAmount a){
return this.power(a.inverse());
}
public Matrix nroot(Matrix a) throws Exception{
return a.forEachElement("inverse").forEachElement("pow",this,true);
}
public Matrix nroot_vec(Matrix a) throws Exception {
return a.forEachElement("inverse").forEachElement("pow",this,true);
}
public ComplexAmount nroot_vec(ComplexAmount a) throws Exception{
return this.pow(a.inverse());
}
public ComplexAmount power_vec(ComplexAmount b) throws Exception{
return this.power(b);
}
public Matrix power_vec(Matrix b) throws Exception{
return b.forEachElement("power",this,true);
}
public ComplexAmount power(ComplexAmount x) {
return this.pow(x);
}
/* This method needs cleaned up, since it was converted from the old
* ComplexAmount format */
public ComplexAmount pow(ComplexAmount b){
Object bo=null;
/* Amount or ComplexAmount - illegal argument */
/* Double or Complex - won't work with Amount ao */
/* Integer - OK*/
/* if it has units, then illegal argument */
boolean bIsUnitless = b.cUnit.isCompatible(Unit.ONE);
if (! bIsUnitless){
throw new IllegalArgumentException(
"Exponent must be dimensionless");
}
boolean aIsUnitless =this.cUnit.isCompatible(Unit.ONE);
boolean aIsReal = Math.abs(this.cComplex.getImaginary())< zeroTol;
boolean aIsZero = aIsReal & Math.abs(this.cComplex.getReal())<=zeroTol;
boolean bIsReal = Math.abs(b.cComplex.getImaginary())< zeroTol;
Double bdouble = b.cComplex.getReal();
Double bround = Math.rint(bdouble);
boolean bIsZero = Math.abs(bdouble)<=zeroTol;
boolean bMagIsInteger = false;
boolean bInvIsInteger = false;
Integer bInv = 0;
if (bIsReal){
/* it's not complex, but real component can be negative! */
/* is magnitude an integer? */
if (bIsZero){
bMagIsInteger = true;
}
else{
bMagIsInteger = (Math.abs((bdouble - bround) / bdouble) < zeroTol);
/* See if the inverse is an integer, in which case we take a root. */
Double x = 1.0/bdouble;
Double bInvRnd = Math.rint(x);
bInvIsInteger = (Math.abs( ( x - bInvRnd) / x) < zeroTol);
bInv = Long.valueOf(Math.round(x)).intValue();
}
if (bIsZero){
bo = Integer.valueOf(0);
}
else if ( bIsReal && bMagIsInteger ) {
/* real and an integer */
bo = Long.valueOf(Math.round(bround)).intValue();
}
}
else{
/* Complex or double exponent */
bo = b.cComplex;
}
/* calculate the expoonent */
Integer bi;
Unit thisUnit;
Complex thisComplex;
if (bIsReal && bMagIsInteger){
/* If this.cComplex.getImaginary==0 then it must remain zero, since
exponent is whole nmber. Otherwise, we get small neg imaginary value
which results in sqrt((-2)^2)=-2 which is technically correct but
unexpected. */
boolean zeroimag = false;
if (this.cComplex.getImaginary()==0){
zeroimag = true;
}
bi = (Integer)bo;
thisUnit = this.getUnit().pow(bi);
thisComplex = this.cComplex.pow(bi.doubleValue());
//thisComplex = Complex.valueOf(Math.pow(this.cComplex.getReal(),bi),0);
if (zeroimag){
thisComplex = Complex.valueOf(thisComplex.getReal(),0);
}
return ComplexAmount.valueOf(thisComplex, thisUnit);
}
else if (bIsReal && bInvIsInteger){
/* If the inverse is an integer then we can take a root */
thisUnit = this.getUnit().root(bInv);
thisComplex = this.cComplex.pow(1/bInv.doubleValue());
return ComplexAmount.valueOf(thisComplex,thisUnit);
}
else if (aIsUnitless){
Logger.getLogger("com.CompPad").log(Level.FINE, bo + " " + this.cComplex);
/* Must be complex or double */
Complex a;
Complex bb;
a = this.cComplex;
bb = b.cComplex;
return ComplexAmount.valueOf(
a.pow(bb),
Unit.ONE);
}
else if ( ! aIsUnitless && bIsReal && ! bMagIsInteger && ! bInvIsInteger ){
throw new IllegalArgumentException("Exponent of dimensional quantity must be either integer or 1/integer.");
}
else{
throw new IllegalArgumentException("\"pow\" not supported for these operands");
}
/* If pow is 1/n where n is an integer, then attempt to take root of dimensional quantity */
}
public Matrix power(Matrix b) throws Exception {
return b.forEachElement("pow", this, true);
}
public ComplexAmount log(){
if ( this.cUnit.equals(Unit.ONE)){
/* Natural Logarithm. Must be dimensionless */
ComplexAmount retval=new ComplexAmount();
retval.cComplex=this.cComplex.log();
retval.cUnit = Unit.ONE;
return retval;
}
else{
throw new IllegalArgumentException("Exponent cannot have immaginary component");
}
}
public ComplexAmount log10(){
ComplexAmount log10 = ComplexAmount.valueOf(10., Unit.ONE).log();
return log().divide(log10);
}
public ComplexAmount log2(){
ComplexAmount log2 = ComplexAmount.valueOf(2., Unit.ONE).log();
return log().divide(log2);
}
@Override
public String toString(){
Logger.getLogger("com.CompPad").log(Level.FINE,"ComplexAmount.tostring");
Logger.getLogger("com.CompPad").log(Level.FINE,this.cComplex.toString() + " " + this.cUnit.toString());
if (Math.abs(cComplex.getImaginary())>zeroTol){
return this.cComplex.toString() + this.cUnit.toString()+" ";
}
else{
return Double.toString(this.cComplex.getReal()) + " " + this.cUnit.toString();
}
}
public ComplexAmount sin(){
/* Must have angle units eg compatible with radians */
/* Mathematically, it can be complex, but not yet supported */
ComplexAmount retval=new ComplexAmount();
if (Math.abs(this.cComplex.getImaginary())<zeroTol){
if (this.cUnit.isCompatible(javax.measure.unit.SI.RADIAN)){
retval.cComplex=
Complex.ONE.times(Math.sin(this.cComplex.getReal()
* Amount.valueOf(1.0, this.cUnit).doubleValue(SI.RADIAN)));
retval.cUnit=Unit.ONE;
return retval;
}
else{
throw new IllegalArgumentException("Units of argument to function \"sin\" must be compatible with \"RADIAN\"");
}
}
else{
/* Complex Argument */
retval.cComplex = this.cComplex.times(Complex.I).exp()
.minus(this.cComplex.times(Complex.I).opposite().exp())
.divide(Complex.I.times(Complex.valueOf(2,0)));
retval.cUnit = Unit.ONE;
return retval;
}
}
public ComplexAmount cos(){
/* Must have angle units eg compatible with radians */
/* Mathematically, it can be complex, but not yet supported */
ComplexAmount retval=new ComplexAmount();
if (Math.abs(this.cComplex.getImaginary())<zeroTol){
if (this.cUnit.isCompatible(javax.measure.unit.SI.RADIAN)){
retval.cComplex =
Complex.ONE.times(Math.cos(this.cComplex.getReal()
* Amount.valueOf(1.0, this.cUnit).doubleValue(SI.RADIAN)));
retval.cUnit=Unit.ONE;
return retval;
}
else{
throw new IllegalArgumentException("Units of argument to function \"cos\" must be compatible with \"RADIAN\"");
}
}
else{
/* Complex Argument */
retval.cComplex = this.cComplex.times(Complex.I).exp()
.plus(this.cComplex.times(Complex.I).opposite().exp())
.divide(Complex.valueOf(2,0));
retval.cUnit = Unit.ONE;
return retval;
}
}
public ComplexAmount tan(){
/* Must have angle units eg compatible with radians */
/* Mathematically, it can be complex, but not yet supported */
ComplexAmount retval=new ComplexAmount();
if (Math.abs(this.cComplex.getImaginary())<zeroTol){
if (this.cUnit.isCompatible(javax.measure.unit.SI.RADIAN)){
retval.cComplex =
Complex.ONE.times(Math.tan(this.cComplex.getReal()
* Amount.valueOf(1.0, this.cUnit).doubleValue(SI.RADIAN)));
retval.cUnit=Unit.ONE;
return retval;
}
else{
throw new IllegalArgumentException("Units of argument to function \"tan\" must be compatible with \"RADIAN\"");
}
}
else{
/* Complex argument */
return this.sin().divide(this.cos());
}
}
public ComplexAmount cot(){
return tan().inverse();
}
public ComplexAmount sec(){
return cos().inverse();
}
public ComplexAmount csc(){
return sin().inverse();
}
public ComplexAmount sin2(){
return sin().pow(ComplexAmount.valueOf(2.0,Unit.ONE));
}
public ComplexAmount cos2(){
return cos().pow(ComplexAmount.valueOf(2.0,Unit.ONE));
}
public ComplexAmount tan2(){
return tan().pow(ComplexAmount.valueOf(2.0,Unit.ONE));
}
public ComplexAmount sec2(){
return sec().pow(ComplexAmount.valueOf(2.0,Unit.ONE));
}
public ComplexAmount csc2(){
return csc().pow(ComplexAmount.valueOf(2.0,Unit.ONE));
}
public ComplexAmount cot2(){
return cot().pow(ComplexAmount.valueOf(2.0,Unit.ONE));
}
public ComplexAmount asin(){
/* Arguments must be dimensionless */
/* return value should have angular units */
ComplexAmount retval=new ComplexAmount();
if (Math.abs(this.cComplex.getImaginary())<zeroTol){
if (this.cUnit.isCompatible(Unit.ONE)){
retval.cUnit = Unit.ONE;
retval.cComplex = Complex.valueOf(
Math.asin(this.getReal(Unit.ONE)) , 0.0);
return retval;
}
else{
throw new IllegalArgumentException("Argument to function \"asin\" must be unitless");
}
}
else{
/* Complex arguments - use log form */
retval.cComplex = this.cComplex.times(Complex.I)
.plus( (Complex.ONE.minus(this.cComplex.pow(2))).sqrt())
.log().times(Complex.I.opposite());
retval.cUnit = Unit.ONE;
return retval;
}
}
public ComplexAmount acos(){
/* Arguments must be dimensionless */
/* return value should have angular units */
ComplexAmount retval=new ComplexAmount();
if (Math.abs(this.cComplex.getImaginary())<zeroTol){
if (this.cUnit.isCompatible(Unit.ONE)){
retval.cUnit = Unit.ONE;
retval.cComplex = Complex.valueOf(
Math.acos(this.getReal(Unit.ONE)) , 0.0);
return retval;
}
else{
throw new IllegalArgumentException("Argument to function \"acos\" must be unitless");
}
}
else{
/* Complex arguments - use log form */
retval.cComplex = this.cComplex
.plus( this.cComplex.pow(2).minus(Complex.ONE).sqrt())
.log().times(Complex.I.opposite());
retval.cUnit = Unit.ONE;
return retval;
}
}
public ComplexAmount atan(){
/* Arguments must be dimensionless */
/* return value should have angular units */
ComplexAmount retval=new ComplexAmount();
if (Math.abs(this.cComplex.getImaginary())<zeroTol){
if (this.cUnit.isCompatible(Unit.ONE)){
retval.cUnit = Unit.ONE;
retval.cComplex = Complex.valueOf(
Math.atan(this.getReal(Unit.ONE)) , 0.0);
return retval;
}
else{
throw new IllegalArgumentException("Argument to function \"atan\" must be unitless");
}
}
else{
/* Complex arguments - use log form */
retval.cComplex = Complex.ONE.minus(Complex.I.times(this.cComplex))
.divide(Complex.ONE.plus(Complex.I.times(this.cComplex)))
.log().times(Complex.I.divide(Complex.valueOf(2,0)));
retval.cUnit = Unit.ONE;
return retval;
}
}
public ComplexAmount acot(){
return inverse().atan();
}
public ComplexAmount asec(){
return inverse().cos();
}
public ComplexAmount acsc(){
return inverse().sin();
}
public ComplexAmount abs(){
/* Complex component is always a unit vector, so return
* amount as magnitude */
return ComplexAmount.valueOf(this.cComplex.magnitude(), this.cUnit);
/* cComplex is already normalized. cAmount is magnitude */
}
public Boolean isReal(){
if (this.cComplex.magnitude()==0.0){
return true;
}
else if (Math.abs(this.cComplex.getImaginary() / (this.cComplex.magnitude()) ) < zeroTol){
return true;
}
else{
return false;
}
}
public Boolean isInteger(){
if (this.isReal() & this.getUnit().isCompatible(Unit.ONE)){
Double x = Math.abs(this.getReal(Unit.ONE));
if (x<=zeroTol){
/* Then it's zero */
return true;
}
else if ( (x - Math.floor(x) ) / x <= zeroTol){
return true;
}
else{
return false;
}
}
else{
return false;
}
}
public boolean equals(ComplexAmount a){
/* complex and amount components are equal */
/* I think this needs updated to allow for equivalent units! */
return a.cComplex.minus(
this.cComplex.times(
Amount.valueOf(1.0,this.cUnit).doubleValue(a.cUnit))).magnitude()
< zeroTol;
}
public boolean neq(ComplexAmount b){
return !this.equals(b);
}
public boolean gt(ComplexAmount a){
/* convert a to this units */
/* Will throw error if units don't match */
return this.cComplex.isGreaterThan(
a.cComplex.times(
Amount.valueOf(1.0,a.cUnit).doubleValue(this.cUnit)));
}
public boolean gte(ComplexAmount b){
return (this.gt(b) || this.equals(b));
}
public int compareTo(ComplexAmount b){
int retval = 0;
if (this.gt(b)){
retval = 1;
}
else if (this.lt(b)){
retval = -1;
}
else{
retval = 0;
}
return retval;
}
public boolean lt(ComplexAmount a){
/* convert a to this units */
return this.cComplex.isLessThan(
a.cComplex.times(
Amount.valueOf(1.0,a.cUnit).doubleValue(this.cUnit)));
}
public boolean lte(ComplexAmount b){
return (this.lt(b) || this.equals(b));
}
public ComplexAmount round(ComplexAmount u){
if (u == null){
throw new java.lang.IllegalArgumentException("round: too few arguments");
}
if (u.getComplex().equals(Complex.ZERO)){
throw new java.lang.IllegalArgumentException("round: invalid arguments");
}
ComplexAmount x1 = this.divide(u);
Double x1r = ((Float) ((Long) Math.round(x1.getReal(Unit.ONE))).floatValue()).doubleValue();
Double x1i = ((Float) ((Long) Math.round(x1.getImaginary(Unit.ONE))).floatValue()).doubleValue();
ComplexAmount retval = ComplexAmount.valueOf(
Complex.valueOf(x1r,x1i),Unit.ONE);
return retval.times(u);
}
public Matrix round(Matrix U) throws Exception{
return U.forEachElement("round",this,true);
}
public ComplexAmount ceil(ComplexAmount u){
if (u == null){
throw new java.lang.IllegalArgumentException("ceil: too few arguments");
}
if (u.getComplex().equals(Complex.ZERO)){
throw new java.lang.IllegalArgumentException("ceil: invalid arguments");
}
ComplexAmount x1 = this.divide(u);
Double x1r = Math.ceil(x1.getReal(Unit.ONE));
Double x1i = Math.ceil(x1.getImaginary(Unit.ONE));
ComplexAmount retval = ComplexAmount.valueOf(
Complex.valueOf(x1r,x1i),Unit.ONE);
return retval.times(u);
}
public Matrix ceil(Matrix U) throws Exception{
return U.forEachElement("ceil",this,true);
}
public ComplexAmount floor(ComplexAmount u){
if (u == null){
throw new java.lang.IllegalArgumentException("floor: too few arguments");
}
if (u.getComplex().equals(Complex.ZERO)){
throw new java.lang.IllegalArgumentException("floor: invalid arguments");
}
ComplexAmount x1 = this.divide(u);
Double x1r = Math.floor(x1.getReal(Unit.ONE));
Double x1i = Math.floor(x1.getImaginary(Unit.ONE));
ComplexAmount retval = ComplexAmount.valueOf(
Complex.valueOf(x1r,x1i),Unit.ONE);
return retval.times(u);
}
public Matrix floor(Matrix U) throws Exception{
return U.forEachElement("floor",this,true);
}
}