package org.matheclipse.core.reflection.system;
import static org.matheclipse.core.expression.F.*;
import org.apache.commons.math3.fraction.BigFraction;
import org.matheclipse.core.eval.interfaces.AbstractTrigArg1;
import org.matheclipse.core.eval.interfaces.INumeric;
import org.matheclipse.core.eval.interfaces.ISignedNumberConstant;
import org.matheclipse.core.expression.ComplexNum;
import org.matheclipse.core.expression.F;
import org.matheclipse.core.expression.Num;
import org.matheclipse.core.interfaces.IComplex;
import org.matheclipse.core.interfaces.IComplexNum;
import org.matheclipse.core.interfaces.IEvaluator;
import org.matheclipse.core.interfaces.IExpr;
import org.matheclipse.core.interfaces.ISignedNumber;
import org.matheclipse.core.interfaces.ISymbol;
import org.matheclipse.parser.client.SyntaxError;
/**
*
* See Wikipedia - Argument (complex_analysis)
*
*/
public class Arg extends AbstractTrigArg1 implements INumeric {
public Arg() {
}
@Override
public IExpr evaluateArg1(final IExpr arg1) {
if (arg1.isSignedNumber()) {
final ISignedNumber in = (ISignedNumber) arg1;
if (in.isNegative()) {
return F.Pi;
} else if (!in.equals(F.C0)) {
return F.C0;
}
} else if (arg1.isComplexNumeric()) {
final IComplexNum ic = (IComplexNum) arg1;
// ic == ( x + I * y )
return num(Math.atan2(ic.getImaginaryPart(), ic.getRealPart()));
} else if (arg1.isComplex()) {
final IComplex ic = (IComplex) arg1;
// ic == ( x + I * y )
BigFraction x = ic.getRealPart();
BigFraction y = ic.getImaginaryPart();
int xi = x.compareTo(BigFraction.ZERO);
int yi = y.compareTo(BigFraction.ZERO);
if (xi < 0) {
// x < 0
if (yi < 0) {
// y < 0
// -Pi + ArcTan(y/x)
return Plus(Times(CN1, Pi), ArcTan(Divide(F.fraction(y), F.fraction(x))));
} else {
// y >= 0
// Pi + ArcTan(y/x)
return Plus(Pi, ArcTan(Divide(F.fraction(y), F.fraction(x))));
}
}
if (xi > 0) {
// ArcTan(y/x)
return ArcTan(Divide(F.fraction(y), F.fraction(x)));
}
if (yi < 0) {
// y < 0
// -Pi/2 + ArcTan(x/y)
return Plus(Times(CN1D2, Pi), ArcTan(Divide(F.fraction(x), F.fraction(y))));
} else {
if (yi > 0) {
// y > 0
// Pi/2 + ArcTan(x/y)
return Plus(Times(C1D2, Pi), ArcTan(Divide(F.fraction(x), F.fraction(y))));
}
}
}
if (arg1.isConstant()) {
ISymbol sym = (ISymbol) arg1;
IEvaluator eval = sym.getEvaluator();
if (eval instanceof ISignedNumberConstant) {
double val = ((ISignedNumberConstant) eval).evalReal();
if (val < 0.0) {
return F.Pi;
} else if (val > 0.0) {
return F.C0;
}
}
}
return null;
}
@Override
public IExpr numericEvalD1(final Num arg1) {
final double d = arg1.getRealPart();
if (d < 0) {
return F.num(Math.PI);
} else if (d > 0) {
return F.CD0;
}
return null;
}
/**
* Evaluate this function for one double complex argument
*
* @param arg1
* a double complex number
*
* @return
*/
public IExpr numericEvalDC1(final ComplexNum arg1) {
return num(Math.atan2(arg1.getImaginaryPart(), arg1.getRealPart()));
}
public double evalReal(final double[] stack, final int top, final int size) {
if (size != 1) {
throw new UnsupportedOperationException();
}
if (stack[top] < 0) {
return Math.PI;
} else if (stack[top] > 0) {
return 0;
}
throw new UnsupportedOperationException();
}
@Override
public void setUp(final ISymbol symbol) throws SyntaxError {
symbol.setAttributes(ISymbol.LISTABLE | ISymbol.NUMERICFUNCTION);
super.setUp(symbol);
}
}
Ads help maintain this website.