diff --git a/app/src/main/java/org/solovyev/android/calculator/functions/BaseFunctionFragment.java b/app/src/main/java/org/solovyev/android/calculator/functions/BaseFunctionFragment.java index 5c23a2e0..3c63e710 100644 --- a/app/src/main/java/org/solovyev/android/calculator/functions/BaseFunctionFragment.java +++ b/app/src/main/java/org/solovyev/android/calculator/functions/BaseFunctionFragment.java @@ -22,8 +22,6 @@ package org.solovyev.android.calculator.functions; -import static org.solovyev.android.calculator.functions.CppFunction.NO_ID; - import android.annotation.SuppressLint; import android.content.Context; import android.content.DialogInterface; @@ -59,9 +57,6 @@ import org.solovyev.android.calculator.keyboard.FloatingKeyboardWindow; import org.solovyev.android.calculator.view.EditTextCompat; import org.solovyev.common.math.MathRegistry; -import butterknife.Bind; -import butterknife.ButterKnife; - import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; @@ -72,6 +67,11 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.inject.Inject; +import butterknife.Bind; +import butterknife.ButterKnife; + +import static org.solovyev.android.calculator.functions.CppFunction.NO_ID; + public abstract class BaseFunctionFragment extends BaseDialogFragment implements View.OnClickListener, View.OnFocusChangeListener, View.OnKeyListener { protected static final String ARG_FUNCTION = "function"; @@ -274,12 +274,6 @@ public abstract class BaseFunctionFragment extends BaseDialogFragment implements } protected boolean validateName() { - final String name = nameView.getText().toString(); - if (!Engine.isValidName(name)) { - setError(nameLabel, getString(R.string.function_name_is_not_valid)); - return false; - } - clearError(nameLabel); return true; } diff --git a/app/src/main/java/org/solovyev/android/calculator/functions/EditFunctionFragment.java b/app/src/main/java/org/solovyev/android/calculator/functions/EditFunctionFragment.java index 38dca236..9f1ae9fe 100644 --- a/app/src/main/java/org/solovyev/android/calculator/functions/EditFunctionFragment.java +++ b/app/src/main/java/org/solovyev/android/calculator/functions/EditFunctionFragment.java @@ -12,14 +12,15 @@ import android.support.v7.app.AlertDialog; import org.solovyev.android.Activities; import org.solovyev.android.Check; import org.solovyev.android.calculator.App; +import org.solovyev.android.calculator.Engine; import org.solovyev.android.calculator.R; import org.solovyev.android.calculator.entities.EntityRemovalDialog; -import jscl.math.function.Function; - import javax.annotation.Nonnull; import javax.annotation.Nullable; +import jscl.math.function.Function; + public class EditFunctionFragment extends BaseFunctionFragment { public EditFunctionFragment() { @@ -103,10 +104,11 @@ public class EditFunctionFragment extends BaseFunctionFragment { @Override protected boolean validateName() { - if (!super.validateName()) { + final String name = nameView.getText().toString(); + if (!Engine.isValidName(name)) { + setError(nameLabel, getString(R.string.function_name_is_not_valid)); return false; } - final String name = nameView.getText().toString(); final Function existingFunction = functionsRegistry.get(name); if (existingFunction != null) { if (!existingFunction.isIdDefined()) { diff --git a/app/src/main/java/org/solovyev/android/calculator/plot/ExpressionFunction.java b/app/src/main/java/org/solovyev/android/calculator/plot/ExpressionFunction.java index c1f6ca0c..e4c12a2e 100644 --- a/app/src/main/java/org/solovyev/android/calculator/plot/ExpressionFunction.java +++ b/app/src/main/java/org/solovyev/android/calculator/plot/ExpressionFunction.java @@ -1,46 +1,46 @@ package org.solovyev.android.calculator.plot; +import android.text.TextUtils; + import org.solovyev.android.plotter.Function; -import jscl.math.Expression; +import javax.annotation.Nonnull; + import jscl.math.Generic; import jscl.math.JsclInteger; import jscl.math.NumericWrapper; -import jscl.math.function.Constant; +import jscl.math.function.CustomFunction; import jscl.math.numeric.Complex; import jscl.math.numeric.Numeric; import jscl.math.numeric.Real; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - public class ExpressionFunction extends Function { - private static final Complex NaN = Complex.valueOf(Double.NaN, 0d); - @Nonnull public final jscl.math.function.Function function; - public final Constant xVariable; - public final Constant yVariable; public final boolean imaginary; public final int arity; + private final Generic[] parameters; - public ExpressionFunction(@Nonnull jscl.math.function.Function function, @Nullable Constant x, - @Nullable Constant y, boolean imaginary) { - super(imaginary ? "Im(" + function.toString() + ")" : function.toString()); + public ExpressionFunction(@Nonnull jscl.math.function.Function function, + boolean imaginary) { + super(makeFunctionName(function, imaginary)); this.function = function; - this.xVariable = x; - this.yVariable = y; this.imaginary = imaginary; - this.arity = countArity(x, y); + this.arity = function.getMaxParameters(); + this.parameters = new Generic[this.arity]; } - private static int countArity(@Nullable Constant x, @Nullable Constant y) { - if (x != null && y != null) { - return 2; - } else if (x == null && y == null) { - return 0; + @Nonnull + private static String makeFunctionName(@Nonnull jscl.math.function.Function function, boolean imaginary) { + String name = function.getName(); + if (TextUtils.isEmpty(name)) { + if (function instanceof CustomFunction) { + name = ((CustomFunction) function).getContent(); + } else { + name = function.toString(); + } } - return 1; + return imaginary ? "Im(" + name + ")" : name; } @Override @@ -50,81 +50,53 @@ public class ExpressionFunction extends Function { @Override public float evaluate() { - final Complex value = calculate(function); - if (imaginary) { - return (float) value.imaginaryPart(); + try { + return unwrap(function.numeric()); + } catch (RuntimeException e) { + return Float.NaN; } - return (float) value.realPart(); } @Override public float evaluate(float x) { - final Complex value = calculate(function, xVariable, x); - if (imaginary) { - return (float) value.imaginaryPart(); + try { + parameters[0] = new NumericWrapper(Real.valueOf(x)); + function.setParameters(parameters); + return unwrap(function.numeric()); + } catch (RuntimeException e) { + return Float.NaN; } - return (float) value.realPart(); } @Override public float evaluate(float x, float y) { - final Complex value = calculate(function, xVariable, x, yVariable, y); - if (imaginary) { - return (float) value.imaginaryPart(); - } - return (float) value.realPart(); - } - - @Nonnull - public static Complex calculate(jscl.math.function.Function function, Constant xVar, - float x, Constant yVar, float y) { - try { - Generic tmp = function.substitute(xVar, Expression.valueOf((double) x)); - tmp = tmp.substitute(yVar, Expression.valueOf((double) y)); - return unwrap(tmp.numeric()); - } catch (RuntimeException e) { - return NaN; - } - } - - @Nonnull - public static Complex calculate(jscl.math.function.Function function, Constant xVar, - float x) { - try { - return unwrap(function.substitute(xVar, Expression.valueOf((double) x)).numeric()); - } catch (RuntimeException e) { - return NaN; - } - } - - @Nonnull - public static Complex calculate(jscl.math.function.Function function) { try { + parameters[0] = new NumericWrapper(Real.valueOf(x)); + parameters[1] = new NumericWrapper(Real.valueOf(y)); + function.setParameters(parameters); return unwrap(function.numeric()); } catch (RuntimeException e) { - return NaN; + return Float.NaN; } } - @Nonnull - public static Complex unwrap(Generic numeric) { + public float unwrap(Generic numeric) { if (numeric instanceof JsclInteger) { - return Complex.valueOf(((JsclInteger) numeric).intValue(), 0d); - } else if (numeric instanceof NumericWrapper) { - return unwrap(((NumericWrapper) numeric).content()); - } else { - return NaN; + return ((JsclInteger) numeric).intValue(); } + if (numeric instanceof NumericWrapper) { + return unwrap(((NumericWrapper) numeric).content()); + } + return Float.NaN; } - @Nonnull - public static Complex unwrap(Numeric content) { + public float unwrap(Numeric content) { if (content instanceof Real) { - return Complex.valueOf(((Real) content).doubleValue(), 0d); - } else if (content instanceof Complex) { - return ((Complex) content); - } else { - throw new ArithmeticException(); + return (float) ((Real) content).doubleValue(); } + if (content instanceof Complex) { + return (float) (imaginary ? ((Complex) content).imaginaryPart() : ((Complex) content).realPart()); + } + return Float.NaN; } } diff --git a/app/src/main/java/org/solovyev/android/calculator/plot/PlotEditFunctionFragment.java b/app/src/main/java/org/solovyev/android/calculator/plot/PlotEditFunctionFragment.java index 964deaf1..66984f86 100644 --- a/app/src/main/java/org/solovyev/android/calculator/plot/PlotEditFunctionFragment.java +++ b/app/src/main/java/org/solovyev/android/calculator/plot/PlotEditFunctionFragment.java @@ -10,8 +10,6 @@ import android.view.View; import android.widget.SeekBar; import android.widget.TextView; -import com.google.common.base.Strings; - import org.solovyev.android.calculator.App; import org.solovyev.android.calculator.AppComponent; import org.solovyev.android.calculator.R; @@ -23,18 +21,18 @@ import org.solovyev.android.plotter.PlotIconView; import org.solovyev.android.plotter.Plotter; import org.solovyev.android.plotter.meshes.MeshSpec; -import butterknife.Bind; -import jscl.math.function.Constant; -import jscl.math.function.CustomFunction; -import uz.shift.colorpicker.LineColorPicker; -import uz.shift.colorpicker.OnColorChangedListener; - import java.util.ArrayList; import java.util.List; import javax.annotation.Nonnull; import javax.inject.Inject; +import butterknife.Bind; +import jscl.math.function.Constant; +import jscl.math.function.CustomFunction; +import uz.shift.colorpicker.LineColorPicker; +import uz.shift.colorpicker.OnColorChangedListener; + public class PlotEditFunctionFragment extends BaseFunctionFragment implements SeekBar.OnSeekBarChangeListener { @Inject @@ -67,22 +65,14 @@ public class PlotEditFunctionFragment extends BaseFunctionFragment final PlotEditFunctionFragment fragment = new PlotEditFunctionFragment(); if (pf != null && pf.function instanceof ExpressionFunction) { final Bundle args = new Bundle(); - final String name = - pf.function.hasName() ? Strings.nullToEmpty(pf.function.getName()) : ""; - final List parameters = new ArrayList<>(); final ExpressionFunction ef = (ExpressionFunction) pf.function; - if (ef.xVariable != null) { - parameters.add(ef.xVariable.getName()); - } - if (ef.yVariable != null) { - parameters.add(ef.yVariable.getName()); - } + final List parameters = new ArrayList<>(((CustomFunction) ef.function).getParameterNames()); args.putParcelable(ARG_FUNCTION, CppFunction - .builder(name, - ((CustomFunction) ef.function).getContent()) - .withParameters(parameters) - .withId(pf.function.getId()) - .build()); + .builder(ef.function.getName(), + ((CustomFunction) ef.function).getContent()) + .withParameters(parameters) + .withId(pf.function.getId()) + .build()); fragment.setArguments(args); } return fragment; @@ -168,7 +158,7 @@ public class PlotEditFunctionFragment extends BaseFunctionFragment final Constant x = parameters.size() > 0 ? new Constant(parameters.get(0)) : null; final Constant y = parameters.size() > 1 ? new Constant(parameters.get(1)) : null; final ExpressionFunction expressionFunction = - new ExpressionFunction(function.toJsclBuilder().create(), x, y, false); + new ExpressionFunction(function.toJsclBuilder().create(), false); final PlotFunction plotFunction = PlotFunction.create(expressionFunction, applyMeshSpec()); final int id = function.getId(); diff --git a/jscl/src/main/java/jscl/math/NumericWrapper.java b/jscl/src/main/java/jscl/math/NumericWrapper.java index f0be0556..09ed7ab4 100644 --- a/jscl/src/main/java/jscl/math/NumericWrapper.java +++ b/jscl/src/main/java/jscl/math/NumericWrapper.java @@ -1,5 +1,11 @@ package jscl.math; +import java.math.BigInteger; +import java.util.Collections; +import java.util.Set; + +import javax.annotation.Nonnull; + import jscl.JsclMathEngine; import jscl.math.function.Constant; import jscl.math.function.Constants; @@ -11,12 +17,6 @@ import jscl.math.numeric.Real; import jscl.math.numeric.Vector; import jscl.mathml.MathML; -import java.math.BigInteger; -import java.util.Collections; -import java.util.Set; - -import javax.annotation.Nonnull; - public final class NumericWrapper extends Generic implements INumeric { @Nonnull @@ -185,7 +185,7 @@ public final class NumericWrapper extends Generic implements INumeric