package org.matheclipse.core.reflection.system;
import static org.matheclipse.core.expression.F.Arg;
import static org.matheclipse.core.expression.F.C1D2;
import static org.matheclipse.core.expression.F.C2;
import static org.matheclipse.core.expression.F.CN1;
import static org.matheclipse.core.expression.F.Cos;
import static org.matheclipse.core.expression.F.E;
import static org.matheclipse.core.expression.F.Im;
import static org.matheclipse.core.expression.F.Log;
import static org.matheclipse.core.expression.F.Plus;
import static org.matheclipse.core.expression.F.Power;
import static org.matheclipse.core.expression.F.Sin;
import static org.matheclipse.core.expression.F.Times;
import org.matheclipse.core.eval.exception.Validate;
import org.matheclipse.core.eval.interfaces.AbstractFunctionEvaluator;
import org.matheclipse.core.eval.interfaces.IFunctionEvaluator;
import org.matheclipse.core.expression.F;
import org.matheclipse.core.generic.Functors;
import org.matheclipse.core.interfaces.IAST;
import org.matheclipse.core.interfaces.IComplex;
import org.matheclipse.core.interfaces.IComplexNum;
import org.matheclipse.core.interfaces.IExpr;
import org.matheclipse.core.interfaces.INumber;
import org.matheclipse.core.interfaces.ISymbol;
/**
* Get the imaginary part of an expression
*
* See: Imaginary part
*/
public class Im implements IFunctionEvaluator {
public Im() {
}
public IExpr evaluate(final IAST ast) {
Validate.checkSize(ast, 2);
IExpr arg1 = ast.arg1();
if (arg1.isSignedNumber()) {
return F.C0;
}
if (arg1.isComplex()) {
return ((IComplex) arg1).getIm();
}
if (arg1 instanceof IComplexNum) {
return F.num(((IComplexNum) arg1).getImaginaryPart());
}
if (AbstractFunctionEvaluator.isNegativeExpression(arg1)) {
return Times(CN1, Im(Times(CN1, arg1)));
}
if (arg1.isTimes()) {
if (arg1.getAt(1).isSignedNumber()) {
IAST temp = ((IAST) arg1).clone();
temp.remove(1);
return F.Times(arg1.getAt(1), F.Im(temp));
}
if (arg1.getAt(1).equals(F.CI)) {
// Im(I*temp) -> Re(temp)
IAST temp = ((IAST) arg1).clone();
temp.remove(1);
return F.Re(temp);
}
}
if (arg1.isPlus()) {
return ((IAST) arg1).map(Functors.replace1st(F.Im(F.Null)));
}
if (arg1.isPower()) {
IAST astPower = (IAST) arg1;
if (astPower.arg1().isRealFunction()) {
// test for x^(a+I*b)
IExpr x = astPower.arg1();
if (astPower.get(2).isNumber()) {
// (x^2)^(a/2)*E^(-b*Arg[x])*Sin[a*Arg[x]+1/2*b*Log[x^2]]
IExpr a = ((INumber) astPower.get(2)).getRe();
IExpr b = ((INumber) astPower.get(2)).getIm();
return imPowerComplex(x, a, b);
}
if (astPower.get(2).isNumericFunction()) {
// (x^2)^(a/2)*E^(-b*Arg[x])*Sin[a*Arg[x]+1/2*b*Log[x^2]]
IExpr a = F.eval(F.Re(astPower.get(2)));
IExpr b = F.eval(F.Im(astPower.get(2)));
return imPowerComplex(x, a, b);
}
}
}
return null;
}
/**
* Evaluate Im(x^(a+I*b))
*
* @param x
* @param a
* the real part of the exponent
* @param b
* the imaginary part of the exponent
* @return
*/
private IExpr imPowerComplex(IExpr x, IExpr a, IExpr b) {
if (x.equals(F.E)) {
// Im(E^(a+I*b)) -> E^a*Sin[b]
return Times(Power(F.E, a), Sin(b));
}
return Times(Times(Power(Power(x, C2), Times(C1D2, a)), Power(E, Times(Times(CN1, b), Arg(x)))),
Sin(Plus(Times(a, Arg(x)), Times(Times(C1D2, b), Log(Power(x, C2))))));
}
public IExpr numericEval(final IAST ast) {
return evaluate(ast);
}
public void setUp(final ISymbol symbol) {
symbol.setAttributes(ISymbol.LISTABLE);
}
}
Ads help maintain this website.