package org.solovyev.android.calculator.plot;
import android.text.TextUtils;
import jscl.math.Expression;
import jscl.math.Generic;
import jscl.math.JsclInteger;
import jscl.math.NumericWrapper;
import jscl.math.function.CustomFunction;
import jscl.math.numeric.Complex;
import jscl.math.numeric.Numeric;
import jscl.math.numeric.Real;
import org.solovyev.android.plotter.Function;
import javax.annotation.Nonnull;
public class ExpressionFunction extends Function {
@Nonnull
public final jscl.math.function.Function function;
public final int arity;
private final Generic[] parameters;
public ExpressionFunction(@Nonnull jscl.math.function.Function function) {
super(makeFunctionName(function));
this.function = function;
this.arity = function.getMaxParameters();
this.parameters = new Generic[this.arity];
}
@Nonnull
private static String makeFunctionName(@Nonnull jscl.math.function.Function function) {
String name = function.getName();
if (TextUtils.isEmpty(name)) {
if (function instanceof CustomFunction) {
name = ((CustomFunction) function).getContent();
} else {
name = function.toString();
}
if (name.length() > 10) {
name = name.substring(0, 10) + "…";
}
}
return name;
}
@Override
public int getArity() {
return arity;
}
@Override
public float evaluate() {
try {
return unwrap(function.numeric());
} catch (RuntimeException e) {
return Float.NaN;
}
}
@Override
public float evaluate(float x) {
try {
parameters[0] = Expression.valueOf((double) x);
function.setParameters(parameters);
return unwrap(function.numeric());
} catch (RuntimeException e) {
return Float.NaN;
}
}
@Override
public float evaluate(float x, float y) {
try {
parameters[0] = Expression.valueOf((double) x);
parameters[1] = Expression.valueOf((double) y);
function.setParameters(parameters);
return unwrap(function.numeric());
} catch (RuntimeException e) {
return Float.NaN;
}
}
public float unwrap(Generic numeric) {
if (numeric instanceof JsclInteger) {
return ((JsclInteger) numeric).intValue();
}
if (numeric instanceof NumericWrapper) {
return unwrap(((NumericWrapper) numeric).content());
}
return Float.NaN;
}
public float unwrap(Numeric content) {
if (content instanceof Real) {
return (float) content.doubleValue();
}
if (content instanceof Complex) {
final Complex complex = (Complex) content;
final double imag = complex.imaginaryPart();
final double real = complex.realPart();
if (real == 0f && imag != 0f) {
return Float.NaN;
}
return (float) real;
}
return Float.NaN;
}
}