New architecture
This commit is contained in:
parent
233c685a49
commit
f03c2496a6
@ -1,85 +1,84 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||||
* For more information, please, contact se.solovyev@gmail.com
|
* For more information, please, contact se.solovyev@gmail.com
|
||||||
* or visit http://se.solovyev.org
|
* or visit http://se.solovyev.org
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.solovyev.android.calculator;
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
import jscl.MathEngine;
|
import jscl.NumeralBase;
|
||||||
import jscl.NumeralBase;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.solovyev.android.calculator.math.MathType;
|
||||||
import org.solovyev.android.calculator.math.MathType;
|
import org.solovyev.common.text.StringUtils;
|
||||||
import org.solovyev.common.text.StringUtils;
|
|
||||||
|
/**
|
||||||
/**
|
* User: serso
|
||||||
* User: serso
|
* Date: 12/15/11
|
||||||
* Date: 12/15/11
|
* Time: 9:01 PM
|
||||||
* Time: 9:01 PM
|
*/
|
||||||
*/
|
public abstract class AbstractNumberBuilder {
|
||||||
public abstract class AbstractNumberBuilder {
|
|
||||||
|
@NotNull
|
||||||
@NotNull
|
protected final CalculatorEngine engine;
|
||||||
protected final MathEngine engine;
|
|
||||||
|
@Nullable
|
||||||
@Nullable
|
protected StringBuilder numberBuilder = null;
|
||||||
protected StringBuilder numberBuilder = null;
|
|
||||||
|
@Nullable
|
||||||
@Nullable
|
protected NumeralBase nb;
|
||||||
protected NumeralBase nb;
|
|
||||||
|
protected AbstractNumberBuilder(@NotNull CalculatorEngine engine) {
|
||||||
protected AbstractNumberBuilder(@NotNull MathEngine engine) {
|
this.engine = engine;
|
||||||
this.engine = engine;
|
this.nb = engine.getNumeralBase();
|
||||||
this.nb = engine.getNumeralBase();
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
/**
|
* Method determines if we can continue to process current number
|
||||||
* Method determines if we can continue to process current number
|
*
|
||||||
*
|
* @param mathTypeResult current math type result
|
||||||
* @param mathTypeResult current math type result
|
* @return true if we can continue of processing of current number, if false - new number should be constructed
|
||||||
* @return true if we can continue of processing of current number, if false - new number should be constructed
|
*/
|
||||||
*/
|
protected boolean canContinue(@NotNull MathType.Result mathTypeResult) {
|
||||||
protected boolean canContinue(@NotNull MathType.Result mathTypeResult) {
|
boolean result = mathTypeResult.getMathType().getGroupType() == MathType.MathGroupType.number &&
|
||||||
boolean result = mathTypeResult.getMathType().getGroupType() == MathType.MathGroupType.number &&
|
!spaceBefore(mathTypeResult) &&
|
||||||
!spaceBefore(mathTypeResult) &&
|
numeralBaseCheck(mathTypeResult) &&
|
||||||
numeralBaseCheck(mathTypeResult) &&
|
numeralBaseInTheStart(mathTypeResult.getMathType()) || isSignAfterE(mathTypeResult);
|
||||||
numeralBaseInTheStart(mathTypeResult.getMathType()) || isSignAfterE(mathTypeResult);
|
return result;
|
||||||
return result;
|
}
|
||||||
}
|
|
||||||
|
private boolean spaceBefore(@NotNull MathType.Result mathTypeResult) {
|
||||||
private boolean spaceBefore(@NotNull MathType.Result mathTypeResult) {
|
return numberBuilder == null && StringUtils.isEmpty(mathTypeResult.getMatch().trim());
|
||||||
return numberBuilder == null && StringUtils.isEmpty(mathTypeResult.getMatch().trim());
|
}
|
||||||
}
|
|
||||||
|
private boolean numeralBaseInTheStart(@NotNull MathType mathType) {
|
||||||
private boolean numeralBaseInTheStart(@NotNull MathType mathType) {
|
return mathType != MathType.numeral_base || numberBuilder == null;
|
||||||
return mathType != MathType.numeral_base || numberBuilder == null;
|
}
|
||||||
}
|
|
||||||
|
private boolean numeralBaseCheck(@NotNull MathType.Result mathType) {
|
||||||
private boolean numeralBaseCheck(@NotNull MathType.Result mathType) {
|
return mathType.getMathType() != MathType.digit || getNumeralBase().getAcceptableCharacters().contains(mathType.getMatch().charAt(0));
|
||||||
return mathType.getMathType() != MathType.digit || getNumeralBase().getAcceptableCharacters().contains(mathType.getMatch().charAt(0));
|
}
|
||||||
}
|
|
||||||
|
private boolean isSignAfterE(@NotNull MathType.Result mathTypeResult) {
|
||||||
private boolean isSignAfterE(@NotNull MathType.Result mathTypeResult) {
|
if (!isHexMode()) {
|
||||||
if (!isHexMode()) {
|
if ("-".equals(mathTypeResult.getMatch()) || "+".equals(mathTypeResult.getMatch())) {
|
||||||
if ("-".equals(mathTypeResult.getMatch()) || "+".equals(mathTypeResult.getMatch())) {
|
final StringBuilder localNb = numberBuilder;
|
||||||
final StringBuilder localNb = numberBuilder;
|
if (localNb != null && localNb.length() > 0) {
|
||||||
if (localNb != null && localNb.length() > 0) {
|
if (localNb.charAt(localNb.length() - 1) == MathType.POWER_10) {
|
||||||
if (localNb.charAt(localNb.length() - 1) == MathType.POWER_10) {
|
return true;
|
||||||
return true;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
public boolean isHexMode() {
|
||||||
public boolean isHexMode() {
|
return nb == NumeralBase.hex || (nb == null && engine.getNumeralBase() == NumeralBase.hex);
|
||||||
return nb == NumeralBase.hex || (nb == null && engine.getNumeralBase() == NumeralBase.hex);
|
}
|
||||||
}
|
|
||||||
|
@NotNull
|
||||||
@NotNull
|
protected NumeralBase getNumeralBase() {
|
||||||
protected NumeralBase getNumeralBase() {
|
return nb == null ? engine.getNumeralBase() : nb;
|
||||||
return nb == null ? engine.getNumeralBase() : nb;
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@ -15,6 +15,16 @@ import org.solovyev.common.history.HistoryControl;
|
|||||||
*/
|
*/
|
||||||
public interface Calculator extends CalculatorEventContainer, HistoryControl<CalculatorHistoryState> {
|
public interface Calculator extends CalculatorEventContainer, HistoryControl<CalculatorHistoryState> {
|
||||||
|
|
||||||
|
void init();
|
||||||
|
|
||||||
|
/*
|
||||||
|
**********************************************************************
|
||||||
|
*
|
||||||
|
* CALCULATIONS
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
void evaluate();
|
void evaluate();
|
||||||
|
|
||||||
void simplify();
|
void simplify();
|
||||||
@ -31,11 +41,16 @@ public interface Calculator extends CalculatorEventContainer, HistoryControl<Cal
|
|||||||
@NotNull
|
@NotNull
|
||||||
CalculatorEventDataId convert(@NotNull Generic generic, @NotNull NumeralBase to);
|
CalculatorEventDataId convert(@NotNull Generic generic, @NotNull NumeralBase to);
|
||||||
|
|
||||||
|
/*
|
||||||
|
**********************************************************************
|
||||||
|
*
|
||||||
|
* EVENTS
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
CalculatorEventDataId fireCalculatorEvent(@NotNull CalculatorEventType calculatorEventType, @Nullable Object data);
|
CalculatorEventDataId fireCalculatorEvent(@NotNull CalculatorEventType calculatorEventType, @Nullable Object data);
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
CalculatorEventDataId fireCalculatorEvent(@NotNull CalculatorEventType calculatorEventType, @Nullable Object data, @NotNull Long sequenceId);
|
CalculatorEventDataId fireCalculatorEvent(@NotNull CalculatorEventType calculatorEventType, @Nullable Object data, @NotNull Long sequenceId);
|
||||||
|
|
||||||
void init();
|
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
package org.solovyev.android.calculator;
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import jscl.AngleUnit;
|
||||||
import jscl.MathEngine;
|
import jscl.MathEngine;
|
||||||
|
import jscl.NumeralBase;
|
||||||
import jscl.math.function.Function;
|
import jscl.math.function.Function;
|
||||||
import jscl.math.function.IConstant;
|
import jscl.math.function.IConstant;
|
||||||
import jscl.math.operator.Operator;
|
import jscl.math.operator.Operator;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.text.DecimalFormatSymbols;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: Solovyev_S
|
* User: Solovyev_S
|
||||||
* Date: 20.09.12
|
* Date: 20.09.12
|
||||||
@ -13,8 +17,27 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
*/
|
*/
|
||||||
public interface CalculatorEngine {
|
public interface CalculatorEngine {
|
||||||
|
|
||||||
@NotNull
|
/*
|
||||||
String getMultiplicationSign();
|
**********************************************************************
|
||||||
|
*
|
||||||
|
* INIT
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
void init();
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
void softReset();
|
||||||
|
|
||||||
|
/*
|
||||||
|
**********************************************************************
|
||||||
|
*
|
||||||
|
* REGISTRIES
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
CalculatorMathRegistry<IConstant> getVarsRegistry();
|
CalculatorMathRegistry<IConstant> getVarsRegistry();
|
||||||
@ -29,11 +52,46 @@ public interface CalculatorEngine {
|
|||||||
CalculatorMathRegistry<Operator> getPostfixFunctionsRegistry();
|
CalculatorMathRegistry<Operator> getPostfixFunctionsRegistry();
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
MathEngine getEngine();
|
CalculatorMathEngine getMathEngine();
|
||||||
|
|
||||||
void init();
|
@Deprecated
|
||||||
|
@NotNull
|
||||||
|
MathEngine getMathEngine0();
|
||||||
|
|
||||||
void reset();
|
/*
|
||||||
|
**********************************************************************
|
||||||
|
*
|
||||||
|
* PREFERENCES
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
void softReset();
|
@NotNull
|
||||||
|
String getMultiplicationSign();
|
||||||
|
|
||||||
|
void setUseGroupingSeparator(boolean useGroupingSeparator);
|
||||||
|
|
||||||
|
void setGroupingSeparator(char groupingSeparator);
|
||||||
|
|
||||||
|
void setPrecision(@NotNull Integer precision);
|
||||||
|
|
||||||
|
void setRoundResult(@NotNull Boolean round);
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
AngleUnit getAngleUnits();
|
||||||
|
|
||||||
|
void setAngleUnits(@NotNull AngleUnit angleUnits);
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
NumeralBase getNumeralBase();
|
||||||
|
|
||||||
|
void setNumeralBase(@NotNull NumeralBase numeralBase);
|
||||||
|
|
||||||
|
void setMultiplicationSign(@NotNull String multiplicationSign);
|
||||||
|
|
||||||
|
void setScienceNotation(@NotNull Boolean scienceNotation);
|
||||||
|
|
||||||
|
void setTimeout(@NotNull Integer timeout);
|
||||||
|
|
||||||
|
void setDecimalGroupSymbols(@NotNull DecimalFormatSymbols decimalGroupSymbols);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,320 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import jscl.AngleUnit;
|
||||||
|
import jscl.JsclMathEngine;
|
||||||
|
import jscl.MathEngine;
|
||||||
|
import jscl.NumeralBase;
|
||||||
|
import jscl.math.Generic;
|
||||||
|
import jscl.math.function.Function;
|
||||||
|
import jscl.math.function.IConstant;
|
||||||
|
import jscl.math.operator.Operator;
|
||||||
|
import jscl.text.ParseException;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.text.DecimalFormatSymbols;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 9/23/12
|
||||||
|
* Time: 5:34 PM
|
||||||
|
*/
|
||||||
|
public class CalculatorEngineImpl implements CalculatorEngine {
|
||||||
|
|
||||||
|
/*
|
||||||
|
**********************************************************************
|
||||||
|
*
|
||||||
|
* CONSTANTS
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
private static final String MULTIPLICATION_SIGN_DEFAULT = "×";
|
||||||
|
|
||||||
|
private static final String MAX_CALCULATION_TIME_DEFAULT = "5";
|
||||||
|
|
||||||
|
/*
|
||||||
|
**********************************************************************
|
||||||
|
*
|
||||||
|
* ENGINE/REGISTRIES
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
private final MathEngine engine;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final CalculatorMathEngine mathEngine;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final CalculatorMathRegistry<IConstant> varsRegistry;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final CalculatorMathRegistry<Function> functionsRegistry;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final CalculatorMathRegistry<Operator> operatorsRegistry;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final CalculatorMathRegistry<Operator> postfixFunctionsRegistry;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final Object lock;
|
||||||
|
|
||||||
|
/*
|
||||||
|
**********************************************************************
|
||||||
|
*
|
||||||
|
* PREFERENCES
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
private int timeout = Integer.valueOf(MAX_CALCULATION_TIME_DEFAULT);
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private String multiplicationSign = MULTIPLICATION_SIGN_DEFAULT;
|
||||||
|
|
||||||
|
public CalculatorEngineImpl(@NotNull JsclMathEngine engine,
|
||||||
|
@NotNull CalculatorMathRegistry<IConstant> varsRegistry,
|
||||||
|
@NotNull CalculatorMathRegistry<Function> functionsRegistry,
|
||||||
|
@NotNull CalculatorMathRegistry<Operator> operatorsRegistry,
|
||||||
|
@NotNull CalculatorMathRegistry<Operator> postfixFunctionsRegistry,
|
||||||
|
@Nullable Object lock) {
|
||||||
|
|
||||||
|
this.engine = engine;
|
||||||
|
this.mathEngine = new JsclCalculatorMathEngine(engine);
|
||||||
|
|
||||||
|
this.engine.setRoundResult(true);
|
||||||
|
this.engine.setUseGroupingSeparator(true);
|
||||||
|
|
||||||
|
this.varsRegistry = varsRegistry;
|
||||||
|
this.functionsRegistry = functionsRegistry;
|
||||||
|
this.operatorsRegistry = operatorsRegistry;
|
||||||
|
this.postfixFunctionsRegistry = postfixFunctionsRegistry;
|
||||||
|
this.lock = lock == null ? new Object() : lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
**********************************************************************
|
||||||
|
*
|
||||||
|
* REGISTRIES
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public CalculatorMathRegistry<IConstant> getVarsRegistry() {
|
||||||
|
return this.varsRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public CalculatorMathRegistry<Function> getFunctionsRegistry() {
|
||||||
|
return this.functionsRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public CalculatorMathRegistry<Operator> getOperatorsRegistry() {
|
||||||
|
return this.operatorsRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public CalculatorMathRegistry<Operator> getPostfixFunctionsRegistry() {
|
||||||
|
return this.postfixFunctionsRegistry;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public CalculatorMathEngine getMathEngine() {
|
||||||
|
return this.mathEngine;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public MathEngine getMathEngine0() {
|
||||||
|
return this.engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
**********************************************************************
|
||||||
|
*
|
||||||
|
* INIT
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init() {
|
||||||
|
synchronized (lock) {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reset() {
|
||||||
|
synchronized (lock) {
|
||||||
|
varsRegistry.load();
|
||||||
|
functionsRegistry.load();
|
||||||
|
operatorsRegistry.load();
|
||||||
|
postfixFunctionsRegistry.load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void softReset() {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
**********************************************************************
|
||||||
|
*
|
||||||
|
* PREFERENCES
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public String getMultiplicationSign() {
|
||||||
|
return this.multiplicationSign;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUseGroupingSeparator(boolean useGroupingSeparator) {
|
||||||
|
synchronized (lock) {
|
||||||
|
this.engine.setUseGroupingSeparator(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setGroupingSeparator(char groupingSeparator) {
|
||||||
|
synchronized (lock) {
|
||||||
|
this.engine.setGroupingSeparator(groupingSeparator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPrecision(@NotNull Integer precision) {
|
||||||
|
synchronized (lock) {
|
||||||
|
this.engine.setPrecision(precision);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRoundResult(@NotNull Boolean round) {
|
||||||
|
synchronized (lock) {
|
||||||
|
this.engine.setRoundResult(round);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public AngleUnit getAngleUnits() {
|
||||||
|
synchronized (lock) {
|
||||||
|
return this.engine.getAngleUnits();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAngleUnits(@NotNull AngleUnit angleUnits) {
|
||||||
|
synchronized (lock) {
|
||||||
|
this.engine.setAngleUnits(angleUnits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public NumeralBase getNumeralBase() {
|
||||||
|
synchronized (lock) {
|
||||||
|
return this.engine.getNumeralBase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setNumeralBase(@NotNull NumeralBase numeralBase) {
|
||||||
|
synchronized (lock) {
|
||||||
|
this.engine.setNumeralBase(numeralBase);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMultiplicationSign(@NotNull String multiplicationSign) {
|
||||||
|
this.multiplicationSign = multiplicationSign;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setScienceNotation(@NotNull Boolean scienceNotation) {
|
||||||
|
synchronized (lock) {
|
||||||
|
this.engine.setScienceNotation(scienceNotation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTimeout(@NotNull Integer timeout) {
|
||||||
|
this.timeout = timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setDecimalGroupSymbols(@NotNull DecimalFormatSymbols decimalGroupSymbols) {
|
||||||
|
synchronized (lock) {
|
||||||
|
this.engine.setDecimalGroupSymbols(decimalGroupSymbols);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
**********************************************************************
|
||||||
|
*
|
||||||
|
* STATIC CLASSES
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
private static final class JsclCalculatorMathEngine implements CalculatorMathEngine {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final MathEngine mathEngine;
|
||||||
|
|
||||||
|
private JsclCalculatorMathEngine(@NotNull MathEngine mathEngine) {
|
||||||
|
this.mathEngine = mathEngine;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public String evaluate(@NotNull String expression) throws ParseException {
|
||||||
|
return this.mathEngine.evaluate(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public String simplify(@NotNull String expression) throws ParseException {
|
||||||
|
return this.mathEngine.simplify(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public String elementary(@NotNull String expression) throws ParseException {
|
||||||
|
return this.mathEngine.elementary(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Generic evaluateGeneric(@NotNull String expression) throws ParseException {
|
||||||
|
return this.mathEngine.evaluateGeneric(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Generic simplifyGeneric(@NotNull String expression) throws ParseException {
|
||||||
|
return this.mathEngine.simplifyGeneric(expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Generic elementaryGeneric(@NotNull String expression) throws ParseException {
|
||||||
|
return this.mathEngine.elementaryGeneric(expression);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -149,7 +149,7 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
|
|||||||
|
|
||||||
fireCalculatorEvent(newConversionEventData(sequenceId), CalculatorEventType.conversion_started, null);
|
fireCalculatorEvent(newConversionEventData(sequenceId), CalculatorEventType.conversion_started, null);
|
||||||
|
|
||||||
final NumeralBase from = CalculatorLocatorImpl.getInstance().getEngine().getEngine().getNumeralBase();
|
final NumeralBase from = CalculatorLocatorImpl.getInstance().getEngine().getNumeralBase();
|
||||||
|
|
||||||
if (from != to) {
|
if (from != to) {
|
||||||
String fromString = generic.toString();
|
String fromString = generic.toString();
|
||||||
@ -236,7 +236,7 @@ public class CalculatorImpl implements Calculator, CalculatorEventListener {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
final Generic result = operation.evaluateGeneric(jsclExpression);
|
final Generic result = operation.evaluateGeneric(jsclExpression, CalculatorLocatorImpl.getInstance().getEngine().getMathEngine());
|
||||||
|
|
||||||
// NOTE: toString() method must be called here as ArithmeticOperationException may occur in it (just to avoid later check!)
|
// NOTE: toString() method must be called here as ArithmeticOperationException may occur in it (just to avoid later check!)
|
||||||
result.toString();
|
result.toString();
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import jscl.math.Generic;
|
||||||
|
import jscl.text.ParseException;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 9/23/12
|
||||||
|
* Time: 6:05 PM
|
||||||
|
*/
|
||||||
|
public interface CalculatorMathEngine {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
String evaluate(@NotNull String expression) throws ParseException;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
String simplify(@NotNull String expression) throws ParseException;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
String elementary(@NotNull String expression) throws ParseException;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
Generic evaluateGeneric(@NotNull String expression) throws ParseException;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
Generic simplifyGeneric(@NotNull String expression) throws ParseException;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
Generic elementaryGeneric(@NotNull String expression) throws ParseException;
|
||||||
|
}
|
@ -1,55 +1,54 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||||
* For more information, please, contact se.solovyev@gmail.com
|
* For more information, please, contact se.solovyev@gmail.com
|
||||||
* or visit http://se.solovyev.org
|
* or visit http://se.solovyev.org
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.solovyev.android.calculator;
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
import jscl.MathEngine;
|
import jscl.NumeralBase;
|
||||||
import jscl.NumeralBase;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.solovyev.android.calculator.math.MathType;
|
||||||
import org.solovyev.android.calculator.math.MathType;
|
|
||||||
|
/**
|
||||||
/**
|
* User: serso
|
||||||
* User: serso
|
* Date: 12/15/11
|
||||||
* Date: 12/15/11
|
* Time: 8:33 PM
|
||||||
* Time: 8:33 PM
|
*/
|
||||||
*/
|
|
||||||
|
public class LiteNumberBuilder extends AbstractNumberBuilder {
|
||||||
public class LiteNumberBuilder extends AbstractNumberBuilder {
|
|
||||||
|
public LiteNumberBuilder(@NotNull CalculatorEngine engine) {
|
||||||
public LiteNumberBuilder(@NotNull MathEngine engine) {
|
super(engine);
|
||||||
super(engine);
|
this.nb = engine.getNumeralBase();
|
||||||
this.nb = engine.getNumeralBase();
|
}
|
||||||
}
|
|
||||||
|
public void process(@NotNull MathType.Result mathTypeResult) {
|
||||||
public void process(@NotNull MathType.Result mathTypeResult) {
|
if (canContinue(mathTypeResult)) {
|
||||||
if (canContinue(mathTypeResult)) {
|
// let's continue building number
|
||||||
// let's continue building number
|
if (numberBuilder == null) {
|
||||||
if (numberBuilder == null) {
|
// if new number => create new builder
|
||||||
// if new number => create new builder
|
numberBuilder = new StringBuilder();
|
||||||
numberBuilder = new StringBuilder();
|
}
|
||||||
}
|
|
||||||
|
if (mathTypeResult.getMathType() != MathType.numeral_base) {
|
||||||
if (mathTypeResult.getMathType() != MathType.numeral_base) {
|
// just add matching string
|
||||||
// just add matching string
|
numberBuilder.append(mathTypeResult.getMatch());
|
||||||
numberBuilder.append(mathTypeResult.getMatch());
|
} else {
|
||||||
} else {
|
// set explicitly numeral base (do not include it into number)
|
||||||
// set explicitly numeral base (do not include it into number)
|
nb = NumeralBase.getByPrefix(mathTypeResult.getMatch());
|
||||||
nb = NumeralBase.getByPrefix(mathTypeResult.getMatch());
|
}
|
||||||
}
|
|
||||||
|
} else {
|
||||||
} else {
|
// process current number (and go to the next one)
|
||||||
// process current number (and go to the next one)
|
if (numberBuilder != null) {
|
||||||
if (numberBuilder != null) {
|
numberBuilder = null;
|
||||||
numberBuilder = null;
|
|
||||||
|
// must set default numeral base (exit numeral base mode)
|
||||||
// must set default numeral base (exit numeral base mode)
|
nb = engine.getNumeralBase();
|
||||||
nb = engine.getNumeralBase();
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -1,203 +1,202 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
* Copyright (c) 2009-2011. Created by serso aka se.solovyev.
|
||||||
* For more information, please, contact se.solovyev@gmail.com
|
* For more information, please, contact se.solovyev@gmail.com
|
||||||
* or visit http://se.solovyev.org
|
* or visit http://se.solovyev.org
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.solovyev.android.calculator;
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
import jscl.MathContext;
|
import jscl.MathContext;
|
||||||
import jscl.MathEngine;
|
import jscl.MathEngine;
|
||||||
import jscl.NumeralBase;
|
import jscl.NumeralBase;
|
||||||
import jscl.math.numeric.Real;
|
import jscl.math.numeric.Real;
|
||||||
import jscl.text.*;
|
import jscl.text.*;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.solovyev.android.calculator.AbstractNumberBuilder;
|
import org.solovyev.android.calculator.math.MathType;
|
||||||
import org.solovyev.android.calculator.math.MathType;
|
import org.solovyev.common.MutableObject;
|
||||||
import org.solovyev.common.MutableObject;
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.ArrayList;
|
import java.util.List;
|
||||||
import java.util.List;
|
|
||||||
|
/**
|
||||||
/**
|
* User: serso
|
||||||
* User: serso
|
* Date: 10/23/11
|
||||||
* Date: 10/23/11
|
* Time: 2:57 PM
|
||||||
* Time: 2:57 PM
|
*/
|
||||||
*/
|
public class NumberBuilder extends AbstractNumberBuilder {
|
||||||
public class NumberBuilder extends AbstractNumberBuilder {
|
|
||||||
|
public NumberBuilder(@NotNull CalculatorEngine engine) {
|
||||||
public NumberBuilder(@NotNull MathEngine engine) {
|
super(engine);
|
||||||
super(engine);
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
/**
|
* Method replaces number in text according to some rules (e.g. formatting)
|
||||||
* Method replaces number in text according to some rules (e.g. formatting)
|
*
|
||||||
*
|
* @param text text where number can be replaced
|
||||||
* @param text text where number can be replaced
|
* @param mathTypeResult math type result of current token
|
||||||
* @param mathTypeResult math type result of current token
|
* @param offset offset between new number length and old number length (newNumberLength - oldNumberLength)
|
||||||
* @param offset offset between new number length and old number length (newNumberLength - oldNumberLength)
|
*
|
||||||
*
|
*
|
||||||
*
|
* @return new math type result (as one can be changed due to substituting of number with constant)
|
||||||
* @return new math type result (as one can be changed due to substituting of number with constant)
|
*/
|
||||||
*/
|
@NotNull
|
||||||
@NotNull
|
public MathType.Result process(@NotNull StringBuilder text, @NotNull MathType.Result mathTypeResult, @Nullable MutableObject<Integer> offset) {
|
||||||
public MathType.Result process(@NotNull StringBuilder text, @NotNull MathType.Result mathTypeResult, @Nullable MutableObject<Integer> offset) {
|
final MathType.Result possibleResult;
|
||||||
final MathType.Result possibleResult;
|
if (canContinue(mathTypeResult)) {
|
||||||
if (canContinue(mathTypeResult)) {
|
// let's continue building number
|
||||||
// let's continue building number
|
if (numberBuilder == null) {
|
||||||
if (numberBuilder == null) {
|
// if new number => create new builder
|
||||||
// if new number => create new builder
|
numberBuilder = new StringBuilder();
|
||||||
numberBuilder = new StringBuilder();
|
}
|
||||||
}
|
|
||||||
|
if (mathTypeResult.getMathType() != MathType.numeral_base) {
|
||||||
if (mathTypeResult.getMathType() != MathType.numeral_base) {
|
// just add matching string
|
||||||
// just add matching string
|
numberBuilder.append(mathTypeResult.getMatch());
|
||||||
numberBuilder.append(mathTypeResult.getMatch());
|
} else {
|
||||||
} else {
|
// set explicitly numeral base (do not include it into number)
|
||||||
// set explicitly numeral base (do not include it into number)
|
nb = NumeralBase.getByPrefix(mathTypeResult.getMatch());
|
||||||
nb = NumeralBase.getByPrefix(mathTypeResult.getMatch());
|
}
|
||||||
}
|
|
||||||
|
possibleResult = null;
|
||||||
possibleResult = null;
|
} else {
|
||||||
} else {
|
// process current number (and go to the next one)
|
||||||
// process current number (and go to the next one)
|
possibleResult = processNumber(text, offset);
|
||||||
possibleResult = processNumber(text, offset);
|
}
|
||||||
}
|
|
||||||
|
return possibleResult == null ? mathTypeResult : possibleResult;
|
||||||
return possibleResult == null ? mathTypeResult : possibleResult;
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
/**
|
* Method replaces number in text according to some rules (e.g. formatting)
|
||||||
* Method replaces number in text according to some rules (e.g. formatting)
|
*
|
||||||
*
|
* @param text text where number can be replaced
|
||||||
* @param text text where number can be replaced
|
* @param offset offset between new number length and old number length (newNumberLength - oldNumberLength)
|
||||||
* @param offset offset between new number length and old number length (newNumberLength - oldNumberLength)
|
*
|
||||||
*
|
* @return new math type result (as one can be changed due to substituting of number with constant)
|
||||||
* @return new math type result (as one can be changed due to substituting of number with constant)
|
*/
|
||||||
*/
|
@Nullable
|
||||||
@Nullable
|
public MathType.Result processNumber(@NotNull StringBuilder text, @Nullable MutableObject<Integer> offset) {
|
||||||
public MathType.Result processNumber(@NotNull StringBuilder text, @Nullable MutableObject<Integer> offset) {
|
// total number of trimmed chars
|
||||||
// total number of trimmed chars
|
int trimmedChars = 0;
|
||||||
int trimmedChars = 0;
|
|
||||||
|
String number = null;
|
||||||
String number = null;
|
|
||||||
|
// toXml numeral base (as later it might be replaced)
|
||||||
// toXml numeral base (as later it might be replaced)
|
final NumeralBase localNb = getNumeralBase();
|
||||||
final NumeralBase localNb = getNumeralBase();
|
|
||||||
|
if (numberBuilder != null) {
|
||||||
if (numberBuilder != null) {
|
try {
|
||||||
try {
|
number = numberBuilder.toString();
|
||||||
number = numberBuilder.toString();
|
|
||||||
|
// let's get rid of unnecessary characters (grouping separators, + after E)
|
||||||
// let's get rid of unnecessary characters (grouping separators, + after E)
|
final List<String> tokens = new ArrayList<String>();
|
||||||
final List<String> tokens = new ArrayList<String>();
|
tokens.addAll(MathType.grouping_separator.getTokens());
|
||||||
tokens.addAll(MathType.grouping_separator.getTokens());
|
// + after E can be omitted: 10+E = 10E (NOTE: - cannot be omitted )
|
||||||
// + after E can be omitted: 10+E = 10E (NOTE: - cannot be omitted )
|
tokens.add("+");
|
||||||
tokens.add("+");
|
for (String groupingSeparator : tokens) {
|
||||||
for (String groupingSeparator : tokens) {
|
final String trimmedNumber = number.replace(groupingSeparator, "");
|
||||||
final String trimmedNumber = number.replace(groupingSeparator, "");
|
trimmedChars += number.length() - trimmedNumber.length();
|
||||||
trimmedChars += number.length() - trimmedNumber.length();
|
number = trimmedNumber;
|
||||||
number = trimmedNumber;
|
}
|
||||||
}
|
|
||||||
|
// check if number still valid
|
||||||
// check if number still valid
|
toDouble(number, getNumeralBase(), engine.getMathEngine0());
|
||||||
toDouble(number, getNumeralBase(), engine);
|
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
} catch (NumberFormatException e) {
|
// number is not valid => stop
|
||||||
// number is not valid => stop
|
number = null;
|
||||||
number = null;
|
}
|
||||||
}
|
|
||||||
|
numberBuilder = null;
|
||||||
numberBuilder = null;
|
|
||||||
|
// must set default numeral base (exit numeral base mode)
|
||||||
// must set default numeral base (exit numeral base mode)
|
nb = engine.getNumeralBase();
|
||||||
nb = engine.getNumeralBase();
|
}
|
||||||
}
|
|
||||||
|
return replaceNumberInText(text, number, trimmedChars, offset, localNb, engine.getMathEngine0());
|
||||||
return replaceNumberInText(text, number, trimmedChars, offset, localNb, engine);
|
}
|
||||||
}
|
|
||||||
|
@Nullable
|
||||||
@Nullable
|
private static MathType.Result replaceNumberInText(@NotNull StringBuilder text,
|
||||||
private static MathType.Result replaceNumberInText(@NotNull StringBuilder text,
|
@Nullable String number,
|
||||||
@Nullable String number,
|
int trimmedChars,
|
||||||
int trimmedChars,
|
@Nullable MutableObject<Integer> offset,
|
||||||
@Nullable MutableObject<Integer> offset,
|
@NotNull NumeralBase nb,
|
||||||
@NotNull NumeralBase nb,
|
@NotNull final MathEngine engine) {
|
||||||
@NotNull final MathEngine engine) {
|
MathType.Result result = null;
|
||||||
MathType.Result result = null;
|
|
||||||
|
if (number != null) {
|
||||||
if (number != null) {
|
// in any case remove old number from text
|
||||||
// in any case remove old number from text
|
final int oldNumberLength = number.length() + trimmedChars;
|
||||||
final int oldNumberLength = number.length() + trimmedChars;
|
text.delete(text.length() - oldNumberLength, text.length());
|
||||||
text.delete(text.length() - oldNumberLength, text.length());
|
|
||||||
|
final String newNumber = formatNumber(number, nb, engine);
|
||||||
final String newNumber = formatNumber(number, nb, engine);
|
if (offset != null) {
|
||||||
if (offset != null) {
|
// register offset between old number and new number
|
||||||
// register offset between old number and new number
|
offset.setObject(newNumber.length() - oldNumberLength);
|
||||||
offset.setObject(newNumber.length() - oldNumberLength);
|
}
|
||||||
}
|
text.append(newNumber);
|
||||||
text.append(newNumber);
|
}
|
||||||
}
|
|
||||||
|
return result;
|
||||||
return result;
|
}
|
||||||
}
|
|
||||||
|
@NotNull
|
||||||
@NotNull
|
private static String formatNumber(@NotNull String number, @NotNull NumeralBase nb, @NotNull MathEngine engine) {
|
||||||
private static String formatNumber(@NotNull String number, @NotNull NumeralBase nb, @NotNull MathEngine engine) {
|
String result;
|
||||||
String result;
|
|
||||||
|
int indexOfDot = number.indexOf('.');
|
||||||
int indexOfDot = number.indexOf('.');
|
|
||||||
|
if (indexOfDot < 0) {
|
||||||
if (indexOfDot < 0) {
|
int indexOfE;
|
||||||
int indexOfE;
|
if (nb == NumeralBase.hex) {
|
||||||
if (nb == NumeralBase.hex) {
|
indexOfE = -1;
|
||||||
indexOfE = -1;
|
} else {
|
||||||
} else {
|
indexOfE = number.indexOf(MathType.POWER_10);
|
||||||
indexOfE = number.indexOf(MathType.POWER_10);
|
}
|
||||||
}
|
if (indexOfE < 0) {
|
||||||
if (indexOfE < 0) {
|
result = engine.addGroupingSeparators(nb, number);
|
||||||
result = engine.addGroupingSeparators(nb, number);
|
} else {
|
||||||
} else {
|
final String partBeforeE;
|
||||||
final String partBeforeE;
|
if (indexOfE != 0) {
|
||||||
if (indexOfE != 0) {
|
partBeforeE = engine.addGroupingSeparators(nb, number.substring(0, indexOfE));
|
||||||
partBeforeE = engine.addGroupingSeparators(nb, number.substring(0, indexOfE));
|
} else {
|
||||||
} else {
|
partBeforeE = "";
|
||||||
partBeforeE = "";
|
}
|
||||||
}
|
result = partBeforeE + number.substring(indexOfE);
|
||||||
result = partBeforeE + number.substring(indexOfE);
|
}
|
||||||
}
|
} else {
|
||||||
} else {
|
final String integerPart;
|
||||||
final String integerPart;
|
if (indexOfDot != 0) {
|
||||||
if (indexOfDot != 0) {
|
integerPart = engine.addGroupingSeparators(nb, number.substring(0, indexOfDot));
|
||||||
integerPart = engine.addGroupingSeparators(nb, number.substring(0, indexOfDot));
|
} else {
|
||||||
} else {
|
integerPart = "";
|
||||||
integerPart = "";
|
}
|
||||||
}
|
result = integerPart + number.substring(indexOfDot);
|
||||||
result = integerPart + number.substring(indexOfDot);
|
}
|
||||||
}
|
|
||||||
|
return result;
|
||||||
return result;
|
}
|
||||||
}
|
|
||||||
|
@NotNull
|
||||||
@NotNull
|
private static Double toDouble(@NotNull String s, @NotNull NumeralBase nb, @NotNull final MathContext mc) throws NumberFormatException {
|
||||||
private static Double toDouble(@NotNull String s, @NotNull NumeralBase nb, @NotNull final MathContext mc) throws NumberFormatException {
|
final NumeralBase defaultNb = mc.getNumeralBase();
|
||||||
final NumeralBase defaultNb = mc.getNumeralBase();
|
try {
|
||||||
try {
|
mc.setNumeralBase(nb);
|
||||||
mc.setNumeralBase(nb);
|
|
||||||
|
try {
|
||||||
try {
|
return JsclIntegerParser.parser.parse(Parser.Parameters.newInstance(s, new MutableInt(0), mc), null).content().doubleValue();
|
||||||
return JsclIntegerParser.parser.parse(Parser.Parameters.newInstance(s, new MutableInt(0), mc), null).content().doubleValue();
|
} catch (ParseException e) {
|
||||||
} catch (ParseException e) {
|
try {
|
||||||
try {
|
return ((Real) DoubleParser.parser.parse(Parser.Parameters.newInstance(s, new MutableInt(0), mc), null).content()).doubleValue();
|
||||||
return ((Real) DoubleParser.parser.parse(Parser.Parameters.newInstance(s, new MutableInt(0), mc), null).content()).doubleValue();
|
} catch (ParseException e1) {
|
||||||
} catch (ParseException e1) {
|
throw new NumberFormatException();
|
||||||
throw new NumberFormatException();
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
} finally {
|
||||||
} finally {
|
mc.setNumeralBase(defaultNb);
|
||||||
mc.setNumeralBase(defaultNb);
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@ -52,7 +52,7 @@ public class ToJsclTextProcessor implements TextProcessor<PreparedExpression, St
|
|||||||
MathType.Result mathTypeResult = null;
|
MathType.Result mathTypeResult = null;
|
||||||
MathType.Result mathTypeBefore;
|
MathType.Result mathTypeBefore;
|
||||||
|
|
||||||
final LiteNumberBuilder nb = new LiteNumberBuilder(CalculatorLocatorImpl.getInstance().getEngine().getEngine());
|
final LiteNumberBuilder nb = new LiteNumberBuilder(CalculatorLocatorImpl.getInstance().getEngine());
|
||||||
for (int i = 0; i < s.length(); i++) {
|
for (int i = 0; i < s.length(); i++) {
|
||||||
if (s.charAt(i) == ' ') continue;
|
if (s.charAt(i) == ' ') continue;
|
||||||
startsWithFinder.setI(i);
|
startsWithFinder.setI(i);
|
||||||
|
@ -9,7 +9,7 @@ package org.solovyev.android.calculator.jscl;
|
|||||||
import jscl.math.Generic;
|
import jscl.math.Generic;
|
||||||
import jscl.text.ParseException;
|
import jscl.text.ParseException;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.solovyev.android.calculator.CalculatorLocatorImpl;
|
import org.solovyev.android.calculator.CalculatorMathEngine;
|
||||||
import org.solovyev.android.calculator.text.DummyTextProcessor;
|
import org.solovyev.android.calculator.text.DummyTextProcessor;
|
||||||
import org.solovyev.android.calculator.text.FromJsclSimplifyTextProcessor;
|
import org.solovyev.android.calculator.text.FromJsclSimplifyTextProcessor;
|
||||||
import org.solovyev.android.calculator.text.TextProcessor;
|
import org.solovyev.android.calculator.text.TextProcessor;
|
||||||
@ -39,28 +39,28 @@ public enum JsclOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public final String evaluate(@NotNull String expression) throws ParseException {
|
public final String evaluate(@NotNull String expression, @NotNull CalculatorMathEngine engine) throws ParseException {
|
||||||
switch (this) {
|
switch (this) {
|
||||||
case simplify:
|
case simplify:
|
||||||
return CalculatorLocatorImpl.getInstance().getEngine().getEngine().simplify(expression);
|
return engine.simplify(expression);
|
||||||
case elementary:
|
case elementary:
|
||||||
return CalculatorLocatorImpl.getInstance().getEngine().getEngine().elementary(expression);
|
return engine.elementary(expression);
|
||||||
case numeric:
|
case numeric:
|
||||||
return CalculatorLocatorImpl.getInstance().getEngine().getEngine().evaluate(expression);
|
return engine.evaluate(expression);
|
||||||
default:
|
default:
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public final Generic evaluateGeneric(@NotNull String expression) throws ParseException {
|
public final Generic evaluateGeneric(@NotNull String expression, @NotNull CalculatorMathEngine engine) throws ParseException {
|
||||||
switch (this) {
|
switch (this) {
|
||||||
case simplify:
|
case simplify:
|
||||||
return CalculatorLocatorImpl.getInstance().getEngine().getEngine().simplifyGeneric(expression);
|
return engine.simplifyGeneric(expression);
|
||||||
case elementary:
|
case elementary:
|
||||||
return CalculatorLocatorImpl.getInstance().getEngine().getEngine().elementaryGeneric(expression);
|
return engine.elementaryGeneric(expression);
|
||||||
case numeric:
|
case numeric:
|
||||||
return CalculatorLocatorImpl.getInstance().getEngine().getEngine().evaluateGeneric(expression);
|
return engine.evaluateGeneric(expression);
|
||||||
default:
|
default:
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
@ -15,4 +15,4 @@
|
|||||||
a:layout_width="fill_parent"
|
a:layout_width="fill_parent"
|
||||||
a:layout_height="fill_parent"
|
a:layout_height="fill_parent"
|
||||||
style="?controlButtonStyle"
|
style="?controlButtonStyle"
|
||||||
a:onClick="numericButtonClickHandler"/>
|
a:onClick="equalsButtonClickHandler"/>
|
@ -37,7 +37,7 @@ public class AndroidCalculator implements Calculator {
|
|||||||
/*
|
/*
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
*
|
*
|
||||||
* DELETED TO CALCULATOR
|
* DELEGATED TO CALCULATOR
|
||||||
*
|
*
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
*/
|
*/
|
||||||
|
@ -32,7 +32,7 @@ public class AndroidCalculatorDisplayView extends AutoResizeTextView implements
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final static TextProcessor<TextHighlighter.Result, String> textHighlighter = new TextHighlighter(Color.WHITE, false, CalculatorLocatorImpl.getInstance().getEngine().getEngine());
|
private final static TextProcessor<TextHighlighter.Result, String> textHighlighter = new TextHighlighter(Color.WHITE, false);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
**********************************************************************
|
**********************************************************************
|
||||||
|
@ -31,7 +31,7 @@ public class AndroidCalculatorEditorView extends EditText implements SharedPrefe
|
|||||||
private boolean highlightText = true;
|
private boolean highlightText = true;
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final static TextProcessor<TextHighlighter.Result, String> textHighlighter = new TextHighlighter(Color.WHITE, true, CalculatorLocatorImpl.getInstance().getEngine().getEngine());
|
private final static TextProcessor<TextHighlighter.Result, String> textHighlighter = new TextHighlighter(Color.WHITE, true);
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private volatile CalculatorEditorViewState viewState = CalculatorEditorViewStateImpl.newDefaultInstance();
|
private volatile CalculatorEditorViewState viewState = CalculatorEditorViewStateImpl.newDefaultInstance();
|
||||||
|
@ -531,7 +531,7 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({"UnusedDeclaration"})
|
@SuppressWarnings({"UnusedDeclaration"})
|
||||||
public void numericButtonClickHandler(@NotNull View v) {
|
public void equalsButtonClickHandler(@NotNull View v) {
|
||||||
getCalculator().evaluate();
|
getCalculator().evaluate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -655,8 +655,6 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
|
|||||||
if (!theme.equals(newTheme) || !layout.equals(newLayout)) {
|
if (!theme.equals(newTheme) || !layout.equals(newLayout)) {
|
||||||
AndroidUtils.restartActivity(this);
|
AndroidUtils.restartActivity(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
getCalculator().evaluate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -674,13 +672,6 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
|
|||||||
dpclRegister.announce().onDragPreferencesChange(SimpleOnDragListener.getPreferences(preferences, this));
|
dpclRegister.announce().onDragPreferencesChange(SimpleOnDragListener.getPreferences(preferences, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AndroidCalculatorEngine.Preferences.getPreferenceKeys().contains(key)) {
|
|
||||||
CalculatorLocatorImpl.getInstance().getEngine().softReset();
|
|
||||||
|
|
||||||
// reevaluate in order to update values (in case of preferences changed from the main window, like numeral bases and angle units)
|
|
||||||
this.getCalculator().evaluate();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( CalculatorPreferences.Gui.usePrevAsBack.getKey().equals(key) ) {
|
if ( CalculatorPreferences.Gui.usePrevAsBack.getKey().equals(key) ) {
|
||||||
useBackAsPrev = CalculatorPreferences.Gui.usePrevAsBack.getPreference(preferences);
|
useBackAsPrev = CalculatorPreferences.Gui.usePrevAsBack.getPreference(preferences);
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ enum ConversionMenuItem implements AMenuItem<CalculatorDisplayViewState> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
|
public void onClick(@NotNull CalculatorDisplayViewState data, @NotNull Context context) {
|
||||||
final NumeralBase fromNumeralBase = CalculatorLocatorImpl.getInstance().getEngine().getEngine().getNumeralBase();
|
final NumeralBase fromNumeralBase = CalculatorLocatorImpl.getInstance().getEngine().getNumeralBase();
|
||||||
|
|
||||||
final Generic lastResult = data.getResult();
|
final Generic lastResult = data.getResult();
|
||||||
|
|
||||||
|
@ -160,7 +160,7 @@ public class FunctionEditorSaver implements DialogInterface.OnClickListener{
|
|||||||
if (!StringUtils.isEmpty(name)) {
|
if (!StringUtils.isEmpty(name)) {
|
||||||
try {
|
try {
|
||||||
assert name != null;
|
assert name != null;
|
||||||
Identifier.parser.parse(Parser.Parameters.newInstance(name, new MutableInt(0), CalculatorLocatorImpl.getInstance().getEngine().getEngine()), null);
|
Identifier.parser.parse(Parser.Parameters.newInstance(name, new MutableInt(0), CalculatorLocatorImpl.getInstance().getEngine().getMathEngine0()), null);
|
||||||
result = true;
|
result = true;
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
// not valid name;
|
// not valid name;
|
||||||
|
@ -157,7 +157,7 @@ class VarEditorSaver<T extends MathEntity> implements DialogInterface.OnClickLis
|
|||||||
if (!StringUtils.isEmpty(name)) {
|
if (!StringUtils.isEmpty(name)) {
|
||||||
try {
|
try {
|
||||||
assert name != null;
|
assert name != null;
|
||||||
Identifier.parser.parse(Parser.Parameters.newInstance(name, new MutableInt(0), CalculatorLocatorImpl.getInstance().getEngine().getEngine()), null);
|
Identifier.parser.parse(Parser.Parameters.newInstance(name, new MutableInt(0), CalculatorLocatorImpl.getInstance().getEngine().getMathEngine0()), null);
|
||||||
result = true;
|
result = true;
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
// not valid name;
|
// not valid name;
|
||||||
|
@ -9,24 +9,21 @@ import android.app.Application;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import jscl.*;
|
import jscl.AngleUnit;
|
||||||
import jscl.math.Generic;
|
import jscl.JsclMathEngine;
|
||||||
|
import jscl.MathEngine;
|
||||||
|
import jscl.NumeralBase;
|
||||||
import jscl.math.function.Function;
|
import jscl.math.function.Function;
|
||||||
import jscl.math.function.IConstant;
|
import jscl.math.function.IConstant;
|
||||||
import jscl.math.operator.Operator;
|
import jscl.math.operator.Operator;
|
||||||
import jscl.text.ParseInterruptedException;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.solovyev.android.calculator.CalculatorEngine;
|
||||||
import org.solovyev.android.calculator.*;
|
import org.solovyev.android.calculator.CalculatorEngineImpl;
|
||||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
import org.solovyev.android.calculator.CalculatorMathEngine;
|
||||||
import org.solovyev.android.calculator.text.TextProcessor;
|
import org.solovyev.android.calculator.CalculatorMathRegistry;
|
||||||
import org.solovyev.android.msg.AndroidMessage;
|
|
||||||
import org.solovyev.android.prefs.BooleanPreference;
|
import org.solovyev.android.prefs.BooleanPreference;
|
||||||
import org.solovyev.android.prefs.Preference;
|
import org.solovyev.android.prefs.Preference;
|
||||||
import org.solovyev.android.prefs.StringPreference;
|
import org.solovyev.android.prefs.StringPreference;
|
||||||
import org.solovyev.common.MutableObject;
|
|
||||||
import org.solovyev.common.msg.MessageRegistry;
|
|
||||||
import org.solovyev.common.msg.MessageType;
|
|
||||||
import org.solovyev.common.text.EnumMapper;
|
import org.solovyev.common.text.EnumMapper;
|
||||||
import org.solovyev.common.text.NumberMapper;
|
import org.solovyev.common.text.NumberMapper;
|
||||||
import org.solovyev.common.text.StringUtils;
|
import org.solovyev.common.text.StringUtils;
|
||||||
@ -35,8 +32,6 @@ import java.text.DecimalFormatSymbols;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
@ -46,270 +41,199 @@ import java.util.concurrent.TimeUnit;
|
|||||||
|
|
||||||
public class AndroidCalculatorEngine implements CalculatorEngine {
|
public class AndroidCalculatorEngine implements CalculatorEngine {
|
||||||
|
|
||||||
private static final String GROUPING_SEPARATOR_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_calc_grouping_separator";
|
private static final String GROUPING_SEPARATOR_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_calc_grouping_separator";
|
||||||
|
|
||||||
private static final String MULTIPLICATION_SIGN_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_calc_multiplication_sign";
|
private static final String MULTIPLICATION_SIGN_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_calc_multiplication_sign";
|
||||||
private static final String MULTIPLICATION_SIGN_DEFAULT = "×";
|
private static final String MULTIPLICATION_SIGN_DEFAULT = "×";
|
||||||
|
|
||||||
private static final String MAX_CALCULATION_TIME_P_KEY = "calculation.max_calculation_time";
|
private static final String MAX_CALCULATION_TIME_P_KEY = "calculation.max_calculation_time";
|
||||||
private static final String MAX_CALCULATION_TIME_DEFAULT = "5";
|
private static final String MAX_CALCULATION_TIME_DEFAULT = "5";
|
||||||
|
|
||||||
private static final String SCIENCE_NOTATION_P_KEY = "calculation.output.science_notation";
|
private static final String SCIENCE_NOTATION_P_KEY = "calculation.output.science_notation";
|
||||||
private static final boolean SCIENCE_NOTATION_DEFAULT = false;
|
private static final boolean SCIENCE_NOTATION_DEFAULT = false;
|
||||||
|
|
||||||
private static final String ROUND_RESULT_P_KEY = "org.solovyev.android.calculator.CalculatorModel_round_result";
|
private static final String ROUND_RESULT_P_KEY = "org.solovyev.android.calculator.CalculatorModel_round_result";
|
||||||
private static final boolean ROUND_RESULT_DEFAULT = true;
|
private static final boolean ROUND_RESULT_DEFAULT = true;
|
||||||
|
|
||||||
private static final String RESULT_PRECISION_P_KEY = "org.solovyev.android.calculator.CalculatorModel_result_precision";
|
private static final String RESULT_PRECISION_P_KEY = "org.solovyev.android.calculator.CalculatorModel_result_precision";
|
||||||
private static final String RESULT_PRECISION_DEFAULT = "5";
|
private static final String RESULT_PRECISION_DEFAULT = "5";
|
||||||
|
|
||||||
private static final String NUMERAL_BASES_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_numeral_bases";
|
private static final String NUMERAL_BASES_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_numeral_bases";
|
||||||
private static final String NUMERAL_BASES_DEFAULT = "dec";
|
private static final String NUMERAL_BASES_DEFAULT = "dec";
|
||||||
|
|
||||||
private static final String ANGLE_UNITS_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_angle_units";
|
private static final String ANGLE_UNITS_P_KEY = "org.solovyev.android.calculator.CalculatorActivity_angle_units";
|
||||||
private static final String ANGLE_UNITS_DEFAULT = "deg";
|
private static final String ANGLE_UNITS_DEFAULT = "deg";
|
||||||
|
|
||||||
public static class Preferences {
|
public static class Preferences {
|
||||||
public static final Preference<String> groupingSeparator = StringPreference.newInstance(GROUPING_SEPARATOR_P_KEY, JsclMathEngine.GROUPING_SEPARATOR_DEFAULT);
|
public static final Preference<String> groupingSeparator = StringPreference.newInstance(GROUPING_SEPARATOR_P_KEY, JsclMathEngine.GROUPING_SEPARATOR_DEFAULT);
|
||||||
public static final Preference<String> multiplicationSign = StringPreference.newInstance(MULTIPLICATION_SIGN_P_KEY, MULTIPLICATION_SIGN_DEFAULT);
|
public static final Preference<String> multiplicationSign = StringPreference.newInstance(MULTIPLICATION_SIGN_P_KEY, MULTIPLICATION_SIGN_DEFAULT);
|
||||||
public static final Preference<Integer> precision = StringPreference.newInstance(RESULT_PRECISION_P_KEY, RESULT_PRECISION_DEFAULT, new NumberMapper<Integer>(Integer.class));
|
public static final Preference<Integer> precision = StringPreference.newInstance(RESULT_PRECISION_P_KEY, RESULT_PRECISION_DEFAULT, new NumberMapper<Integer>(Integer.class));
|
||||||
public static final Preference<Boolean> roundResult = new BooleanPreference(ROUND_RESULT_P_KEY, ROUND_RESULT_DEFAULT);
|
public static final Preference<Boolean> roundResult = new BooleanPreference(ROUND_RESULT_P_KEY, ROUND_RESULT_DEFAULT);
|
||||||
public static final Preference<NumeralBase> numeralBase = StringPreference.newInstance(NUMERAL_BASES_P_KEY, NUMERAL_BASES_DEFAULT, EnumMapper.newInstance(NumeralBase.class));
|
public static final Preference<NumeralBase> numeralBase = StringPreference.newInstance(NUMERAL_BASES_P_KEY, NUMERAL_BASES_DEFAULT, EnumMapper.newInstance(NumeralBase.class));
|
||||||
public static final Preference<AngleUnit> angleUnit = StringPreference.newInstance(ANGLE_UNITS_P_KEY, ANGLE_UNITS_DEFAULT, EnumMapper.newInstance(AngleUnit.class));
|
public static final Preference<AngleUnit> angleUnit = StringPreference.newInstance(ANGLE_UNITS_P_KEY, ANGLE_UNITS_DEFAULT, EnumMapper.newInstance(AngleUnit.class));
|
||||||
public static final Preference<Boolean> scienceNotation = new BooleanPreference(SCIENCE_NOTATION_P_KEY, SCIENCE_NOTATION_DEFAULT);
|
public static final Preference<Boolean> scienceNotation = new BooleanPreference(SCIENCE_NOTATION_P_KEY, SCIENCE_NOTATION_DEFAULT);
|
||||||
public static final Preference<Integer> maxCalculationTime = StringPreference.newInstance(MAX_CALCULATION_TIME_P_KEY, MAX_CALCULATION_TIME_DEFAULT, new NumberMapper<Integer>(Integer.class));
|
public static final Preference<Integer> maxCalculationTime = StringPreference.newInstance(MAX_CALCULATION_TIME_P_KEY, MAX_CALCULATION_TIME_DEFAULT, new NumberMapper<Integer>(Integer.class));
|
||||||
|
|
||||||
private static final List<String> preferenceKeys = new ArrayList<String>();
|
private static final List<String> preferenceKeys = new ArrayList<String>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
preferenceKeys.add(groupingSeparator.getKey());
|
preferenceKeys.add(groupingSeparator.getKey());
|
||||||
preferenceKeys.add(multiplicationSign.getKey());
|
preferenceKeys.add(multiplicationSign.getKey());
|
||||||
preferenceKeys.add(precision.getKey());
|
preferenceKeys.add(precision.getKey());
|
||||||
preferenceKeys.add(roundResult.getKey());
|
preferenceKeys.add(roundResult.getKey());
|
||||||
preferenceKeys.add(numeralBase.getKey());
|
preferenceKeys.add(numeralBase.getKey());
|
||||||
preferenceKeys.add(angleUnit.getKey());
|
preferenceKeys.add(angleUnit.getKey());
|
||||||
preferenceKeys.add(scienceNotation.getKey());
|
preferenceKeys.add(scienceNotation.getKey());
|
||||||
preferenceKeys.add(maxCalculationTime.getKey());
|
preferenceKeys.add(maxCalculationTime.getKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static List<String> getPreferenceKeys() {
|
public static List<String> getPreferenceKeys() {
|
||||||
return Collections.unmodifiableList(preferenceKeys);
|
return Collections.unmodifiableList(preferenceKeys);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private final Object lock = new Object();
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private MathEngine engine = JsclMathEngine.instance;
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public final TextProcessor<PreparedExpression, String> preprocessor = ToJsclTextProcessor.getInstance();
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private final CalculatorMathRegistry<IConstant> varsRegistry;
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private final CalculatorMathRegistry<Function> functionsRegistry;
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private final CalculatorMathRegistry<Operator> operatorsRegistry;
|
|
||||||
|
|
||||||
private final CalculatorMathRegistry<Operator> postfixFunctionsRegistry;
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private ThreadKiller threadKiller = new AndroidThreadKiller();
|
|
||||||
|
|
||||||
// calculation thread timeout in seconds, after timeout thread would be interrupted
|
|
||||||
private int timeout = Integer.valueOf(MAX_CALCULATION_TIME_DEFAULT);
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private String multiplicationSign = MULTIPLICATION_SIGN_DEFAULT;
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private final Context context;
|
private final Context context;
|
||||||
|
|
||||||
public AndroidCalculatorEngine(@NotNull Application application) {
|
@NotNull
|
||||||
|
private final CalculatorEngine calculatorEngine;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final Object lock;
|
||||||
|
|
||||||
|
public AndroidCalculatorEngine(@NotNull Application application) {
|
||||||
this.context = application;
|
this.context = application;
|
||||||
|
this.lock = new Object();
|
||||||
|
|
||||||
this.engine.setRoundResult(true);
|
final JsclMathEngine engine = JsclMathEngine.instance;
|
||||||
this.engine.setUseGroupingSeparator(true);
|
this.calculatorEngine = new CalculatorEngineImpl(engine,
|
||||||
|
new AndroidVarsRegistryImpl(engine.getConstantsRegistry(), application),
|
||||||
this.varsRegistry = new AndroidVarsRegistryImpl(engine.getConstantsRegistry(), application);
|
new AndroidFunctionsMathRegistry(engine.getFunctionsRegistry(), application),
|
||||||
this.functionsRegistry = new AndroidFunctionsMathRegistry(engine.getFunctionsRegistry(), application);
|
new AndroidOperatorsMathRegistry(engine.getOperatorsRegistry(), application),
|
||||||
this.operatorsRegistry = new AndroidOperatorsMathRegistry(engine.getOperatorsRegistry(), application);
|
new AndroidPostfixFunctionsRegistry(engine.getPostfixFunctionsRegistry(), application),
|
||||||
this.postfixFunctionsRegistry = new AndroidPostfixFunctionsRegistry(engine.getPostfixFunctionsRegistry(), application);
|
this.lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NotNull
|
@NotNull
|
||||||
public String getMultiplicationSign() {
|
public CalculatorMathRegistry<IConstant> getVarsRegistry() {
|
||||||
return multiplicationSign;
|
return calculatorEngine.getVarsRegistry();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMultiplicationSign(@NotNull String multiplicationSign) {
|
@Override
|
||||||
this.multiplicationSign = multiplicationSign;
|
@NotNull
|
||||||
}
|
public CalculatorMathRegistry<Function> getFunctionsRegistry() {
|
||||||
|
return calculatorEngine.getFunctionsRegistry();
|
||||||
|
}
|
||||||
|
|
||||||
public CalculatorOutput evaluate(@NotNull JsclOperation operation,
|
@Override
|
||||||
@NotNull String expression) throws CalculatorParseException, CalculatorEvalException {
|
@NotNull
|
||||||
return evaluate(operation, expression, null);
|
public CalculatorMathRegistry<Operator> getOperatorsRegistry() {
|
||||||
}
|
return calculatorEngine.getOperatorsRegistry();
|
||||||
|
}
|
||||||
|
|
||||||
public CalculatorOutput evaluate(@NotNull final JsclOperation operation,
|
@Override
|
||||||
@NotNull String expression,
|
@NotNull
|
||||||
@Nullable MessageRegistry mr) throws CalculatorParseException, CalculatorEvalException {
|
public CalculatorMathRegistry<Operator> getPostfixFunctionsRegistry() {
|
||||||
synchronized (lock) {
|
return calculatorEngine.getPostfixFunctionsRegistry();
|
||||||
final StringBuilder sb = new StringBuilder();
|
}
|
||||||
|
|
||||||
final PreparedExpression preparedExpression = preprocessor.process(expression);
|
@Override
|
||||||
sb.append(preparedExpression);
|
@NotNull
|
||||||
|
public CalculatorMathEngine getMathEngine() {
|
||||||
|
return calculatorEngine.getMathEngine();
|
||||||
|
}
|
||||||
|
|
||||||
//Log.d(CalculatorEngine.class.getName(), "Preprocessed expression: " + preparedExpression);
|
@NotNull
|
||||||
/*if (operation == JsclOperation.numeric && preparedExpression.isExistsUndefinedVar()) {
|
@Override
|
||||||
operation = JsclOperation.simplify;
|
public MathEngine getMathEngine0() {
|
||||||
|
return calculatorEngine.getMathEngine0();
|
||||||
|
}
|
||||||
|
|
||||||
if (mr != null) {
|
@NotNull
|
||||||
final String undefinedVars = CollectionsUtils.formatValue(preparedExpression.getUndefinedVars(), ", ", new Formatter<Var>() {
|
@Override
|
||||||
@Override
|
public NumeralBase getNumeralBase() {
|
||||||
public String formatValue(@Nullable Var var) throws IllegalArgumentException {
|
return calculatorEngine.getNumeralBase();
|
||||||
return var != null ? var.getName() : "";
|
}
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
mr.addMessage(new AndroidMessage(R.string.c_simplify_instead_of_numeric, MessageType.info, undefinedVars));
|
@Override
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
final String jsclExpression = sb.toString();
|
|
||||||
|
|
||||||
final MutableObject<Generic> calculationResult = new MutableObject<Generic>(null);
|
|
||||||
final MutableObject<CalculatorParseException> parseException = new MutableObject<CalculatorParseException>(null);
|
|
||||||
final MutableObject<CalculatorEvalException> evalException = new MutableObject<CalculatorEvalException>(null);
|
|
||||||
final MutableObject<Thread> calculationThread = new MutableObject<Thread>(null);
|
|
||||||
|
|
||||||
final CountDownLatch latch = new CountDownLatch(1);
|
|
||||||
|
|
||||||
new Thread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
final Thread thread = Thread.currentThread();
|
|
||||||
try {
|
|
||||||
//Log.d(CalculatorEngine.class.getName(), "Calculation thread started work: " + thread.getName());
|
|
||||||
//System.out.println(jsclExpression);
|
|
||||||
calculationThread.setObject(thread);
|
|
||||||
final Generic genericResult = operation.evaluateGeneric(jsclExpression);
|
|
||||||
|
|
||||||
// NOTE: toString() method must be called here as ArithmeticOperationException may occur in it (just to avoid later check!)
|
|
||||||
genericResult.toString();
|
|
||||||
|
|
||||||
calculationResult.setObject(genericResult);
|
|
||||||
} catch (AbstractJsclArithmeticException e) {
|
|
||||||
evalException.setObject(new CalculatorEvalException(e, e, jsclExpression));
|
|
||||||
} catch (ArithmeticException e) {
|
|
||||||
//System.out.println(e.getMessage());
|
|
||||||
final AndroidMessage androidMessage = new AndroidMessage(R.string.msg_1, MessageType.error, CalculatorApplication.getInstance(), e.getMessage());
|
|
||||||
parseException.setObject(new CalculatorParseException(jsclExpression, androidMessage));
|
|
||||||
} catch (StackOverflowError e) {
|
|
||||||
//System.out.println(StringUtils.fromStackTrace(e.getStackTrace()));
|
|
||||||
final AndroidMessage androidMessage = new AndroidMessage(R.string.msg_2, MessageType.error, CalculatorApplication.getInstance());
|
|
||||||
parseException.setObject(new CalculatorParseException(jsclExpression, androidMessage));
|
|
||||||
} catch (jscl.text.ParseException e) {
|
|
||||||
//System.out.println(e.getMessage());
|
|
||||||
parseException.setObject(new CalculatorParseException(e));
|
|
||||||
} catch (ParseInterruptedException e) {
|
|
||||||
//System.out.println(e.getMessage());
|
|
||||||
// do nothing - we ourselves interrupt the calculations
|
|
||||||
} finally {
|
|
||||||
//Log.d(CalculatorEngine.class.getName(), "Calculation thread ended work: " + thread.getName());
|
|
||||||
calculationThread.setObject(null);
|
|
||||||
latch.countDown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).start();
|
|
||||||
|
|
||||||
try {
|
|
||||||
//Log.d(CalculatorEngine.class.getName(), "Main thread is waiting: " + Thread.currentThread().getName());
|
|
||||||
latch.await(timeout, TimeUnit.SECONDS);
|
|
||||||
//Log.d(CalculatorEngine.class.getName(), "Main thread got up: " + Thread.currentThread().getName());
|
|
||||||
|
|
||||||
final CalculatorParseException parseExceptionObject = parseException.getObject();
|
|
||||||
final CalculatorEvalException evalExceptionObject = evalException.getObject();
|
|
||||||
final Object calculationResultLocal = calculationResult.getObject();
|
|
||||||
final Thread calculationThreadLocal = calculationThread.getObject();
|
|
||||||
|
|
||||||
if (calculationThreadLocal != null) {
|
|
||||||
if (threadKiller != null) {
|
|
||||||
threadKiller.killThread(calculationThreadLocal);
|
|
||||||
}
|
|
||||||
//calculationThreadLocal.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parseExceptionObject != null || evalExceptionObject != null) {
|
|
||||||
if (operation == JsclOperation.numeric &&
|
|
||||||
(preparedExpression.isExistsUndefinedVar() || (evalExceptionObject != null && evalExceptionObject.getCause() instanceof NumeralBaseException))) {
|
|
||||||
return evaluate(JsclOperation.simplify, expression, mr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parseExceptionObject != null) {
|
|
||||||
throw parseExceptionObject;
|
|
||||||
} else {
|
|
||||||
throw evalExceptionObject;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (calculationResultLocal == null) {
|
|
||||||
final AndroidMessage androidMessage = new AndroidMessage(R.string.msg_3, MessageType.error, CalculatorApplication.getInstance());
|
|
||||||
throw new CalculatorParseException(jsclExpression, androidMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
final AndroidMessage androidMessage = new AndroidMessage(R.string.msg_4, MessageType.error, CalculatorApplication.getInstance());
|
|
||||||
throw new CalculatorParseException(jsclExpression, androidMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
final Generic genericResult = calculationResult.getObject();
|
|
||||||
|
|
||||||
return new CalculatorOutputImpl(operation.getFromProcessor().process(genericResult), operation, genericResult);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPrecision(int precision) {
|
|
||||||
this.getEngine().setPrecision(precision);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRoundResult(boolean roundResult) {
|
|
||||||
this.getEngine().setRoundResult(roundResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init() {
|
public void init() {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
reset();
|
calculatorEngine.init();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reset() {
|
public void reset() {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
|
|
||||||
softReset(preferences);
|
softReset(preferences);
|
||||||
|
|
||||||
varsRegistry.load();
|
calculatorEngine.reset();
|
||||||
functionsRegistry.load();
|
}
|
||||||
operatorsRegistry.load();
|
}
|
||||||
postfixFunctionsRegistry.load();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void softReset() {
|
public void softReset() {
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
softReset(PreferenceManager.getDefaultSharedPreferences(context));
|
softReset(PreferenceManager.getDefaultSharedPreferences(context));
|
||||||
}
|
|
||||||
}
|
calculatorEngine.softReset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUseGroupingSeparator(boolean useGroupingSeparator) {
|
||||||
|
calculatorEngine.setUseGroupingSeparator(useGroupingSeparator);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setGroupingSeparator(char groupingSeparator) {
|
||||||
|
calculatorEngine.setGroupingSeparator(groupingSeparator);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPrecision(@NotNull Integer precision) {
|
||||||
|
calculatorEngine.setPrecision(precision);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRoundResult(@NotNull Boolean round) {
|
||||||
|
calculatorEngine.setRoundResult(round);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public AngleUnit getAngleUnits() {
|
||||||
|
return calculatorEngine.getAngleUnits();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAngleUnits(@NotNull AngleUnit angleUnits) {
|
||||||
|
calculatorEngine.setAngleUnits(angleUnits);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setNumeralBase(@NotNull NumeralBase numeralBase) {
|
||||||
|
calculatorEngine.setNumeralBase(numeralBase);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMultiplicationSign(@NotNull String multiplicationSign) {
|
||||||
|
calculatorEngine.setMultiplicationSign(multiplicationSign);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setScienceNotation(@NotNull Boolean scienceNotation) {
|
||||||
|
calculatorEngine.setScienceNotation(scienceNotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTimeout(@NotNull Integer timeout) {
|
||||||
|
calculatorEngine.setTimeout(timeout);
|
||||||
|
}
|
||||||
|
|
||||||
private void softReset(@NotNull SharedPreferences preferences) {
|
private void softReset(@NotNull SharedPreferences preferences) {
|
||||||
this.setPrecision(Preferences.precision.getPreference(preferences));
|
this.setPrecision(Preferences.precision.getPreference(preferences));
|
||||||
@ -322,100 +246,32 @@ public class AndroidCalculatorEngine implements CalculatorEngine {
|
|||||||
|
|
||||||
final String groupingSeparator = Preferences.groupingSeparator.getPreference(preferences);
|
final String groupingSeparator = Preferences.groupingSeparator.getPreference(preferences);
|
||||||
if (StringUtils.isEmpty(groupingSeparator)) {
|
if (StringUtils.isEmpty(groupingSeparator)) {
|
||||||
this.getEngine().setUseGroupingSeparator(false);
|
this.setUseGroupingSeparator(false);
|
||||||
} else {
|
} else {
|
||||||
this.getEngine().setUseGroupingSeparator(true);
|
this.setUseGroupingSeparator(true);
|
||||||
this.getEngine().setGroupingSeparator(groupingSeparator.charAt(0));
|
setGroupingSeparator(groupingSeparator.charAt(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public NumeralBase getNumeralBaseFromPrefs(@NotNull SharedPreferences preferences) {
|
||||||
|
return Preferences.numeralBase.getPreference(preferences);
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public NumeralBase getNumeralBaseFromPrefs(@NotNull SharedPreferences preferences) {
|
public AngleUnit getAngleUnitsFromPrefs(@NotNull SharedPreferences preferences) {
|
||||||
return Preferences.numeralBase.getPreference(preferences);
|
return Preferences.angleUnit.getPreference(preferences);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
//for tests only
|
||||||
public AngleUnit getAngleUnitsFromPrefs(@NotNull SharedPreferences preferences) {
|
public void setDecimalGroupSymbols(@NotNull DecimalFormatSymbols decimalGroupSymbols) {
|
||||||
return Preferences.angleUnit.getPreference(preferences);
|
this.calculatorEngine.setDecimalGroupSymbols(decimalGroupSymbols);
|
||||||
}
|
}
|
||||||
|
|
||||||
//for tests only
|
@Override
|
||||||
void setDecimalGroupSymbols(@NotNull DecimalFormatSymbols decimalGroupSymbols) {
|
|
||||||
synchronized (lock) {
|
|
||||||
this.getEngine().setDecimalGroupSymbols(decimalGroupSymbols);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public CalculatorMathRegistry<IConstant> getVarsRegistry() {
|
public String getMultiplicationSign() {
|
||||||
return varsRegistry;
|
return calculatorEngine.getMultiplicationSign();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
@NotNull
|
|
||||||
public CalculatorMathRegistry<Function> getFunctionsRegistry() {
|
|
||||||
return functionsRegistry;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@NotNull
|
|
||||||
public CalculatorMathRegistry<Operator> getOperatorsRegistry() {
|
|
||||||
return operatorsRegistry;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@NotNull
|
|
||||||
public CalculatorMathRegistry<Operator> getPostfixFunctionsRegistry() {
|
|
||||||
return postfixFunctionsRegistry;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@NotNull
|
|
||||||
public MathEngine getEngine() {
|
|
||||||
return engine;
|
|
||||||
}
|
|
||||||
|
|
||||||
// package protected for tests
|
|
||||||
void setTimeout(int timeout) {
|
|
||||||
this.timeout = timeout;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAngleUnits(@NotNull AngleUnit angleUnits) {
|
|
||||||
getEngine().setAngleUnits(angleUnits);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setScienceNotation(boolean scienceNotation) {
|
|
||||||
getEngine().setScienceNotation(scienceNotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setNumeralBase(@NotNull NumeralBase numeralBase) {
|
|
||||||
getEngine().setNumeralBase(numeralBase);
|
|
||||||
}
|
|
||||||
|
|
||||||
// for tests only
|
|
||||||
void setThreadKiller(@Nullable ThreadKiller threadKiller) {
|
|
||||||
this.threadKiller = threadKiller;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static interface ThreadKiller {
|
|
||||||
void killThread(@NotNull Thread thread);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class AndroidThreadKiller implements ThreadKiller {
|
|
||||||
@Override
|
|
||||||
public void killThread(@NotNull Thread thread) {
|
|
||||||
thread.setPriority(Thread.MIN_PRIORITY);
|
|
||||||
thread.interrupt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ThreadKillerImpl implements ThreadKiller {
|
|
||||||
@Override
|
|
||||||
public void killThread(@NotNull Thread thread) {
|
|
||||||
thread.setPriority(Thread.MIN_PRIORITY);
|
|
||||||
thread.stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ public class AngleUnitsButton extends DirectionDragButton {
|
|||||||
super.initDirectionTextPaint(basePaint, directionTextData, resources);
|
super.initDirectionTextPaint(basePaint, directionTextData, resources);
|
||||||
|
|
||||||
final TextPaint directionTextPaint = directionTextData.getPaint();
|
final TextPaint directionTextPaint = directionTextData.getPaint();
|
||||||
if (CalculatorLocatorImpl.getInstance().getEngine().getEngine().getAngleUnits().name().equals(directionTextData.getText())) {
|
if (CalculatorLocatorImpl.getInstance().getEngine().getAngleUnits().name().equals(directionTextData.getText())) {
|
||||||
directionTextPaint.setColor(resources.getColor(R.color.selected_angle_unit_text_color));
|
directionTextPaint.setColor(resources.getColor(R.color.selected_angle_unit_text_color));
|
||||||
} else {
|
} else {
|
||||||
directionTextPaint.setColor(resources.getColor(R.color.default_text_color));
|
directionTextPaint.setColor(resources.getColor(R.color.default_text_color));
|
||||||
|
@ -37,12 +37,12 @@ public class NumeralBaseConverterDialog {
|
|||||||
String value = initialFromValue;
|
String value = initialFromValue;
|
||||||
try {
|
try {
|
||||||
value = ToJsclTextProcessor.getInstance().process(value).getExpression();
|
value = ToJsclTextProcessor.getInstance().process(value).getExpression();
|
||||||
b.setFromValue(UnitImpl.newInstance(value, AndroidNumeralBase.valueOf(CalculatorLocatorImpl.getInstance().getEngine().getEngine().getNumeralBase())));
|
b.setFromValue(UnitImpl.newInstance(value, AndroidNumeralBase.valueOf(CalculatorLocatorImpl.getInstance().getEngine().getNumeralBase())));
|
||||||
} catch (CalculatorParseException e) {
|
} catch (CalculatorParseException e) {
|
||||||
b.setFromValue(UnitImpl.newInstance(value, AndroidNumeralBase.valueOf(CalculatorLocatorImpl.getInstance().getEngine().getEngine().getNumeralBase())));
|
b.setFromValue(UnitImpl.newInstance(value, AndroidNumeralBase.valueOf(CalculatorLocatorImpl.getInstance().getEngine().getNumeralBase())));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
b.setFromValue(UnitImpl.newInstance("", AndroidNumeralBase.valueOf(CalculatorLocatorImpl.getInstance().getEngine().getEngine().getNumeralBase())));
|
b.setFromValue(UnitImpl.newInstance("", AndroidNumeralBase.valueOf(CalculatorLocatorImpl.getInstance().getEngine().getNumeralBase())));
|
||||||
}
|
}
|
||||||
|
|
||||||
b.setConverter(AndroidNumeralBase.getConverter());
|
b.setConverter(AndroidNumeralBase.getConverter());
|
||||||
@ -63,7 +63,7 @@ public class NumeralBaseConverterDialog {
|
|||||||
public void onClick(@NotNull Unit<String> fromUnits, @NotNull Unit<String> toUnits) {
|
public void onClick(@NotNull Unit<String> fromUnits, @NotNull Unit<String> toUnits) {
|
||||||
String toUnitsValue = toUnits.getValue();
|
String toUnitsValue = toUnits.getValue();
|
||||||
|
|
||||||
if (!toUnits.getUnitType().equals(AndroidNumeralBase.valueOf(CalculatorLocatorImpl.getInstance().getEngine().getEngine().getNumeralBase()))) {
|
if (!toUnits.getUnitType().equals(AndroidNumeralBase.valueOf(CalculatorLocatorImpl.getInstance().getEngine().getNumeralBase()))) {
|
||||||
toUnitsValue = ((AndroidNumeralBase) toUnits.getUnitType()).getNumeralBase().getJsclPrefix() + toUnitsValue;
|
toUnitsValue = ((AndroidNumeralBase) toUnits.getUnitType()).getNumeralBase().getJsclPrefix() + toUnitsValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ public class NumeralBasesButton extends DirectionDragButton {
|
|||||||
super.initDirectionTextPaint(basePaint, directionTextData, resources);
|
super.initDirectionTextPaint(basePaint, directionTextData, resources);
|
||||||
|
|
||||||
final TextPaint directionTextPaint = directionTextData.getPaint();
|
final TextPaint directionTextPaint = directionTextData.getPaint();
|
||||||
if (CalculatorLocatorImpl.getInstance().getEngine().getEngine().getNumeralBase().name().equals(directionTextData.getText())) {
|
if (CalculatorLocatorImpl.getInstance().getEngine().getNumeralBase().name().equals(directionTextData.getText())) {
|
||||||
directionTextPaint.setColor(resources.getColor(R.color.selected_angle_unit_text_color));
|
directionTextPaint.setColor(resources.getColor(R.color.selected_angle_unit_text_color));
|
||||||
} else {
|
} else {
|
||||||
directionTextPaint.setColor(resources.getColor(R.color.default_text_color));
|
directionTextPaint.setColor(resources.getColor(R.color.default_text_color));
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
package org.solovyev.android.calculator.view;
|
package org.solovyev.android.calculator.view;
|
||||||
|
|
||||||
import jscl.MathContext;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.solovyev.android.calculator.*;
|
import org.solovyev.android.calculator.*;
|
||||||
@ -30,9 +29,6 @@ public class TextHighlighter implements TextProcessor<TextHighlighter.Result, St
|
|||||||
nbFontAttributes.put("color", "#008000");
|
nbFontAttributes.put("color", "#008000");
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public final MathContext mathContext;
|
|
||||||
|
|
||||||
public static class Result implements CharSequence {
|
public static class Result implements CharSequence {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@ -76,10 +72,9 @@ public class TextHighlighter implements TextProcessor<TextHighlighter.Result, St
|
|||||||
private final int colorBlue;
|
private final int colorBlue;
|
||||||
private final boolean formatNumber;
|
private final boolean formatNumber;
|
||||||
|
|
||||||
public TextHighlighter(int baseColor, boolean formatNumber, @NotNull MathContext mathContext) {
|
public TextHighlighter(int baseColor, boolean formatNumber) {
|
||||||
this.color = baseColor;
|
this.color = baseColor;
|
||||||
this.formatNumber = formatNumber;
|
this.formatNumber = formatNumber;
|
||||||
this.mathContext = mathContext;
|
|
||||||
//this.colorRed = Color.red(baseColor);
|
//this.colorRed = Color.red(baseColor);
|
||||||
this.colorRed = (baseColor >> 16) & 0xFF;
|
this.colorRed = (baseColor >> 16) & 0xFF;
|
||||||
//this.colorGreen = Color.green(baseColor);
|
//this.colorGreen = Color.green(baseColor);
|
||||||
@ -102,9 +97,9 @@ public class TextHighlighter implements TextProcessor<TextHighlighter.Result, St
|
|||||||
|
|
||||||
final AbstractNumberBuilder numberBuilder;
|
final AbstractNumberBuilder numberBuilder;
|
||||||
if (!formatNumber) {
|
if (!formatNumber) {
|
||||||
numberBuilder = new LiteNumberBuilder(CalculatorLocatorImpl.getInstance().getEngine().getEngine());
|
numberBuilder = new LiteNumberBuilder(CalculatorLocatorImpl.getInstance().getEngine());
|
||||||
} else {
|
} else {
|
||||||
numberBuilder = new NumberBuilder(CalculatorLocatorImpl.getInstance().getEngine().getEngine());
|
numberBuilder = new NumberBuilder(CalculatorLocatorImpl.getInstance().getEngine());
|
||||||
}
|
}
|
||||||
for (int i = 0; i < text.length(); i++) {
|
for (int i = 0; i < text.length(); i++) {
|
||||||
MathType.Result mathType = MathType.getType(text, i, numberBuilder.isHexMode());
|
MathType.Result mathType = MathType.getType(text, i, numberBuilder.isHexMode());
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
package org.solovyev.android.calculator;
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
import jscl.JsclMathEngine;
|
|
||||||
import jscl.MathEngine;
|
import jscl.MathEngine;
|
||||||
import jscl.NumeralBase;
|
import jscl.NumeralBase;
|
||||||
import junit.framework.Assert;
|
import junit.framework.Assert;
|
||||||
@ -26,7 +25,7 @@ public class TextHighlighterTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testProcess() throws Exception {
|
public void testProcess() throws Exception {
|
||||||
TextProcessor<?, String> textHighlighter = new TextHighlighter(0, false, JsclMathEngine.instance);
|
TextProcessor<?, String> textHighlighter = new TextHighlighter(0, false);
|
||||||
|
|
||||||
final Random random = new Random(new Date().getTime());
|
final Random random = new Random(new Date().getTime());
|
||||||
for (int i = 0; i < 1000; i++) {
|
for (int i = 0; i < 1000; i++) {
|
||||||
@ -46,7 +45,7 @@ public class TextHighlighterTest {
|
|||||||
Assert.assertEquals(")", textHighlighter.process(")").toString());
|
Assert.assertEquals(")", textHighlighter.process(")").toString());
|
||||||
Assert.assertEquals(")()(", textHighlighter.process(")()(").toString());
|
Assert.assertEquals(")()(", textHighlighter.process(")()(").toString());
|
||||||
|
|
||||||
textHighlighter = new TextHighlighter(0, true, JsclMathEngine.instance);
|
textHighlighter = new TextHighlighter(0, true);
|
||||||
Assert.assertEquals("1 000 000", textHighlighter.process("1000000").toString());
|
Assert.assertEquals("1 000 000", textHighlighter.process("1000000").toString());
|
||||||
Assert.assertEquals("1 000 000", textHighlighter.process("1000000").toString());
|
Assert.assertEquals("1 000 000", textHighlighter.process("1000000").toString());
|
||||||
Assert.assertEquals("0.1E3", textHighlighter.process("0.1E3").toString());
|
Assert.assertEquals("0.1E3", textHighlighter.process("0.1E3").toString());
|
||||||
@ -65,7 +64,7 @@ public class TextHighlighterTest {
|
|||||||
Assert.assertEquals("-1 000 000E3", textHighlighter.process("-1000000E3").toString());
|
Assert.assertEquals("-1 000 000E3", textHighlighter.process("-1000000E3").toString());
|
||||||
Assert.assertEquals("-1 000 000E-3", textHighlighter.process("-1000000E-3").toString());
|
Assert.assertEquals("-1 000 000E-3", textHighlighter.process("-1000000E-3").toString());
|
||||||
Assert.assertEquals("-1 000 000E-30000", textHighlighter.process("-1000000E-30000").toString());
|
Assert.assertEquals("-1 000 000E-30000", textHighlighter.process("-1000000E-30000").toString());
|
||||||
textHighlighter = new TextHighlighter(0, false, JsclMathEngine.instance);
|
textHighlighter = new TextHighlighter(0, false);
|
||||||
|
|
||||||
textHighlighter.process("cannot calculate 3^10^10 !!!\n" +
|
textHighlighter.process("cannot calculate 3^10^10 !!!\n" +
|
||||||
" unable to enter 0. FIXED\n" +
|
" unable to enter 0. FIXED\n" +
|
||||||
@ -92,7 +91,7 @@ public class TextHighlighterTest {
|
|||||||
Assert.assertEquals("<b>0x:</b>FF33233FFE", textHighlighter.process("0x:FF33233FFE").toString());
|
Assert.assertEquals("<b>0x:</b>FF33233FFE", textHighlighter.process("0x:FF33233FFE").toString());
|
||||||
Assert.assertEquals("<b>0x:</b>FF33 233 FFE", textHighlighter.process("0x:FF33 233 FFE").toString());
|
Assert.assertEquals("<b>0x:</b>FF33 233 FFE", textHighlighter.process("0x:FF33 233 FFE").toString());
|
||||||
|
|
||||||
final MathEngine me = CalculatorLocatorImpl.getInstance().getEngine().getEngine();
|
final MathEngine me = CalculatorLocatorImpl.getInstance().getEngine().getMathEngine0();
|
||||||
try {
|
try {
|
||||||
me.setNumeralBase(NumeralBase.hex);
|
me.setNumeralBase(NumeralBase.hex);
|
||||||
Assert.assertEquals("E", textHighlighter.process("E").toString());
|
Assert.assertEquals("E", textHighlighter.process("E").toString());
|
||||||
|
@ -5,25 +5,8 @@
|
|||||||
|
|
||||||
package org.solovyev.android.calculator.model;
|
package org.solovyev.android.calculator.model;
|
||||||
|
|
||||||
import jscl.AngleUnit;
|
|
||||||
import jscl.JsclMathEngine;
|
|
||||||
import jscl.NumeralBase;
|
|
||||||
import jscl.math.Expression;
|
|
||||||
import jscl.math.Generic;
|
|
||||||
import jscl.math.function.Constant;
|
|
||||||
import jscl.math.function.CustomFunction;
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
|
||||||
import org.solovyev.android.calculator.CalculatorEvalException;
|
|
||||||
import org.solovyev.android.calculator.CalculatorLocatorImpl;
|
import org.solovyev.android.calculator.CalculatorLocatorImpl;
|
||||||
import org.solovyev.android.calculator.CalculatorParseException;
|
|
||||||
import org.solovyev.android.calculator.jscl.JsclOperation;
|
|
||||||
|
|
||||||
import java.text.DecimalFormatSymbols;
|
|
||||||
import java.util.Locale;
|
|
||||||
|
|
||||||
import static junit.framework.Assert.fail;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User: serso
|
* User: serso
|
||||||
@ -37,9 +20,8 @@ public class AndroidCalculatorEngineTest {
|
|||||||
public static void setUp() throws Exception {
|
public static void setUp() throws Exception {
|
||||||
CalculatorLocatorImpl.getInstance().getEngine().init();
|
CalculatorLocatorImpl.getInstance().getEngine().init();
|
||||||
((AndroidCalculatorEngine) CalculatorLocatorImpl.getInstance().getEngine()).setPrecision(3);
|
((AndroidCalculatorEngine) CalculatorLocatorImpl.getInstance().getEngine()).setPrecision(3);
|
||||||
((AndroidCalculatorEngine) CalculatorLocatorImpl.getInstance().getEngine()).setThreadKiller(new AndroidCalculatorEngine.ThreadKillerImpl());
|
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
@Test
|
@Test
|
||||||
public void testDegrees() throws Exception {
|
public void testDegrees() throws Exception {
|
||||||
final AndroidCalculatorEngine cm = (AndroidCalculatorEngine) CalculatorLocatorImpl.getInstance().getEngine();
|
final AndroidCalculatorEngine cm = (AndroidCalculatorEngine) CalculatorLocatorImpl.getInstance().getEngine();
|
||||||
@ -95,7 +77,7 @@ public class AndroidCalculatorEngineTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*final long start = System.currentTimeMillis();
|
*//*final long start = System.currentTimeMillis();
|
||||||
try {
|
try {
|
||||||
cm.evaluate(JsclOperation.numeric, "3^10^10^10");
|
cm.evaluate(JsclOperation.numeric, "3^10^10^10");
|
||||||
Assert.fail();
|
Assert.fail();
|
||||||
@ -106,7 +88,7 @@ public class AndroidCalculatorEngineTest {
|
|||||||
} else {
|
} else {
|
||||||
Assert.fail();
|
Assert.fail();
|
||||||
}
|
}
|
||||||
}*/
|
}*//*
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +139,7 @@ public class AndroidCalculatorEngineTest {
|
|||||||
Assert.assertEquals("-2+2.5i", cm.evaluate(JsclOperation.numeric, "-2+2.5i").getStringResult());
|
Assert.assertEquals("-2+2.5i", cm.evaluate(JsclOperation.numeric, "-2+2.5i").getStringResult());
|
||||||
Assert.assertEquals("-2+2.1i", cm.evaluate(JsclOperation.numeric, "-2+2.1i").getStringResult());
|
Assert.assertEquals("-2+2.1i", cm.evaluate(JsclOperation.numeric, "-2+2.1i").getStringResult());
|
||||||
Assert.assertEquals("-0.1-0.2i", cm.evaluate(JsclOperation.numeric, "(1-i)/(2+6i)").getStringResult());
|
Assert.assertEquals("-0.1-0.2i", cm.evaluate(JsclOperation.numeric, "(1-i)/(2+6i)").getStringResult());
|
||||||
|
|
||||||
junit.framework.Assert.assertEquals("24", cm.evaluate(JsclOperation.numeric, "4!").getStringResult());
|
junit.framework.Assert.assertEquals("24", cm.evaluate(JsclOperation.numeric, "4!").getStringResult());
|
||||||
junit.framework.Assert.assertEquals("24", cm.evaluate(JsclOperation.numeric, "(2+2)!").getStringResult());
|
junit.framework.Assert.assertEquals("24", cm.evaluate(JsclOperation.numeric, "(2+2)!").getStringResult());
|
||||||
junit.framework.Assert.assertEquals("120", cm.evaluate(JsclOperation.numeric, "(2+2+1)!").getStringResult());
|
junit.framework.Assert.assertEquals("120", cm.evaluate(JsclOperation.numeric, "(2+2+1)!").getStringResult());
|
||||||
@ -230,7 +212,7 @@ public class AndroidCalculatorEngineTest {
|
|||||||
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((0))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))").getStringResult());
|
Assert.assertEquals("0", cm.evaluate(JsclOperation.numeric, "((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((0))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))").getStringResult());
|
||||||
|
|
||||||
|
|
||||||
/* Assert.assertEquals("0.524", cm.evaluate(JsclOperation.numeric, "30°").getResult());
|
*//* Assert.assertEquals("0.524", cm.evaluate(JsclOperation.numeric, "30°").getResult());
|
||||||
Assert.assertEquals("0.524", cm.evaluate(JsclOperation.numeric, "(10+20)°").getResult());
|
Assert.assertEquals("0.524", cm.evaluate(JsclOperation.numeric, "(10+20)°").getResult());
|
||||||
Assert.assertEquals("1.047", cm.evaluate(JsclOperation.numeric, "(10+20)°*2").getResult());
|
Assert.assertEquals("1.047", cm.evaluate(JsclOperation.numeric, "(10+20)°*2").getResult());
|
||||||
try {
|
try {
|
||||||
@ -240,14 +222,14 @@ public class AndroidCalculatorEngineTest {
|
|||||||
if ( !e.getMessage().equals("Power operation after postfix function is currently unsupported!") ) {
|
if ( !e.getMessage().equals("Power operation after postfix function is currently unsupported!") ) {
|
||||||
junit.framework.Assert.fail();
|
junit.framework.Assert.fail();
|
||||||
}
|
}
|
||||||
}*/
|
}*//*
|
||||||
|
|
||||||
/* try {
|
*//* try {
|
||||||
cm.setTimeout(5000);
|
cm.setTimeout(5000);
|
||||||
Assert.assertEquals("2", cm.evaluate(JsclOperation.numeric, "2!").getResult());
|
Assert.assertEquals("2", cm.evaluate(JsclOperation.numeric, "2!").getResult());
|
||||||
} finally {
|
} finally {
|
||||||
cm.setTimeout(3000);
|
cm.setTimeout(3000);
|
||||||
}*/
|
}*//*
|
||||||
|
|
||||||
CalculatorLocatorImpl.getInstance().getEngine().getVarsRegistry().add(new Var.Builder("t", (String) null));
|
CalculatorLocatorImpl.getInstance().getEngine().getVarsRegistry().add(new Var.Builder("t", (String) null));
|
||||||
Assert.assertEquals("2t", cm.evaluate(JsclOperation.simplify, "∂(t^2,t)").getStringResult());
|
Assert.assertEquals("2t", cm.evaluate(JsclOperation.simplify, "∂(t^2,t)").getStringResult());
|
||||||
@ -442,5 +424,5 @@ public class AndroidCalculatorEngineTest {
|
|||||||
Assert.assertEquals("1/(bln(a))", cm.evaluate(JsclOperation.simplify, "∂(log(a, b), b)").getStringResult());
|
Assert.assertEquals("1/(bln(a))", cm.evaluate(JsclOperation.simplify, "∂(log(a, b), b)").getStringResult());
|
||||||
Assert.assertEquals("-ln(b)/(aln(a)^2)", cm.evaluate(JsclOperation.simplify, "∂(log(a, b), a)").getStringResult());
|
Assert.assertEquals("-ln(b)/(aln(a)^2)", cm.evaluate(JsclOperation.simplify, "∂(log(a, b), a)").getStringResult());
|
||||||
|
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,6 @@ public class NumeralBaseTest {
|
|||||||
public static void setUp() throws Exception {
|
public static void setUp() throws Exception {
|
||||||
CalculatorLocatorImpl.getInstance().getEngine().init();
|
CalculatorLocatorImpl.getInstance().getEngine().init();
|
||||||
((AndroidCalculatorEngine) CalculatorLocatorImpl.getInstance().getEngine()).setPrecision(3);
|
((AndroidCalculatorEngine) CalculatorLocatorImpl.getInstance().getEngine()).setPrecision(3);
|
||||||
((AndroidCalculatorEngine) CalculatorLocatorImpl.getInstance().getEngine()).setThreadKiller(new AndroidCalculatorEngine.ThreadKillerImpl());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -100,11 +99,11 @@ public class NumeralBaseTest {
|
|||||||
final String bin = "0b:" + line[2].toUpperCase();
|
final String bin = "0b:" + line[2].toUpperCase();
|
||||||
|
|
||||||
final String decExpression = converter.convert(dec);
|
final String decExpression = converter.convert(dec);
|
||||||
final String decResult = CalculatorLocatorImpl.getInstance().getEngine().getEngine().evaluate(decExpression);
|
final String decResult = CalculatorLocatorImpl.getInstance().getEngine().getMathEngine().evaluate(decExpression);
|
||||||
final String hexExpression = converter.convert(hex);
|
final String hexExpression = converter.convert(hex);
|
||||||
final String hexResult = CalculatorLocatorImpl.getInstance().getEngine().getEngine().evaluate(hexExpression);
|
final String hexResult = CalculatorLocatorImpl.getInstance().getEngine().getMathEngine().evaluate(hexExpression);
|
||||||
final String binExpression = converter.convert(bin);
|
final String binExpression = converter.convert(bin);
|
||||||
final String binResult = CalculatorLocatorImpl.getInstance().getEngine().getEngine().evaluate(binExpression);
|
final String binResult = CalculatorLocatorImpl.getInstance().getEngine().getMathEngine().evaluate(binExpression);
|
||||||
|
|
||||||
Assert.assertEquals("dec-hex: " + decExpression + " : " + hexExpression, decResult, hexResult);
|
Assert.assertEquals("dec-hex: " + decExpression + " : " + hexExpression, decResult, hexResult);
|
||||||
Assert.assertEquals("dec-bin: " + decExpression + " : " + binExpression, decResult, binResult);
|
Assert.assertEquals("dec-bin: " + decExpression + " : " + binExpression, decResult, binResult);
|
||||||
|
@ -68,10 +68,10 @@ public class ToJsclTextProcessorTest {
|
|||||||
Assert.assertEquals( "EE", preprocessor.process("EE").toString());
|
Assert.assertEquals( "EE", preprocessor.process("EE").toString());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
CalculatorLocatorImpl.getInstance().getEngine().getEngine().setNumeralBase(NumeralBase.hex);
|
CalculatorLocatorImpl.getInstance().getEngine().setNumeralBase(NumeralBase.hex);
|
||||||
Assert.assertEquals( "22F*exp(F)", preprocessor.process("22Fexp(F)").toString());
|
Assert.assertEquals( "22F*exp(F)", preprocessor.process("22Fexp(F)").toString());
|
||||||
} finally {
|
} finally {
|
||||||
CalculatorLocatorImpl.getInstance().getEngine().getEngine().setNumeralBase(NumeralBase.dec);
|
CalculatorLocatorImpl.getInstance().getEngine().setNumeralBase(NumeralBase.dec);
|
||||||
}
|
}
|
||||||
Assert.assertEquals( "0x:ABCDEF", preprocessor.process("0x:ABCDEF").toString());
|
Assert.assertEquals( "0x:ABCDEF", preprocessor.process("0x:ABCDEF").toString());
|
||||||
Assert.assertEquals( "0x:ABCDEF", preprocessor.process("0x:A BC DEF").toString());
|
Assert.assertEquals( "0x:ABCDEF", preprocessor.process("0x:A BC DEF").toString());
|
||||||
|
Loading…
Reference in New Issue
Block a user