diff --git a/res/layout/calc_division_button.xml b/res/layout/calc_division_button.xml
index cb6dc93b..bbdcad71 100644
--- a/res/layout/calc_division_button.xml
+++ b/res/layout/calc_division_button.xml
@@ -8,8 +8,10 @@
\ No newline at end of file
diff --git a/res/layout/calc_functions_button.xml b/res/layout/calc_functions_button.xml
index 18ddaa8b..1c2846bd 100644
--- a/res/layout/calc_functions_button.xml
+++ b/res/layout/calc_functions_button.xml
@@ -7,6 +7,7 @@
-->
\ No newline at end of file
diff --git a/res/layout/calc_subtraction_button.xml b/res/layout/calc_subtraction_button.xml
index d27a828b..e30899d2 100644
--- a/res/layout/calc_subtraction_button.xml
+++ b/res/layout/calc_subtraction_button.xml
@@ -8,7 +8,7 @@
Результат не допустим!
Операторы
+ Возвращает остаток от деления \'x\' на \'y\'.
+ Суммирует функции \'f(i)\', пробегая по переменной \'i\' от \'from\' до \'to\'.
+ Возвращает произведение функций \'f(i)\', пробегая по переменной \'i\' от \'from\' до \'to\'.
+ Возвращает производную порядка \'order\' функции \'f(x)\' по переменной \'x\' и вычисляет её в точке \'x_point\'.
+ Возвращает интеграл функции \'f(x)\' по переменно \'x\'.
+ Интегрирует функцию \'f(x)\' по переменной \'x\' от \'a\' до \'b\'.
+
diff --git a/res/values/strings.xml b/res/values/strings.xml
index a741d9cf..302eee32 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -140,12 +140,20 @@
Not-equals function - gives 1 if two arguments are not equals, 0 otherwise.
Lesser function - gives 1 if first argument is less than second, 0 otherwise.
Greater function - gives 1 if first argument is greater than second, 0 otherwise.
- Converts degrees into radians: d - degrees, m - minutes (default = 0), s - seconds (default = 0)
- Converts degrees from DMS notation to decimal notation: d - degrees, m - minutes (default = 0), s - seconds (default = 0)
+ Converts degrees into radians: d - degrees, m - minutes (default = 0), s - seconds (default = 0).
+ Converts degrees from DMS notation to decimal notation: d - degrees, m - minutes (default = 0), s - seconds (default = 0).
Converts radians into degrees.
Unable to create empty constant!
Current result is not valid!
Operators
+ Modulo operation finds the remainder of division of \'x\' by \'y\'.
+ Sums functions \'f(i)\', iterating through \'i\' from \'from\' to \'to\'.
+ Gives product of functions \'f(i)\', iterating through \'i\' from \'from\' to \'to\'.
+ Gives derivative of order \'order\' of functions \'f(x)\' by \'x\' variable and calculates at point \'x_point\'.
+ Gives integral of function \'f(x)\' by \'x\' variable.
+ Integrates function \'f(x)\' by \'x\' variable from \'a\' to \'b\'.
+
+
diff --git a/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java b/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java
index 330cb048..760129f7 100644
--- a/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java
+++ b/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java
@@ -96,6 +96,18 @@ public class CalculatorActivity extends Activity implements FontSizeAdjuster, Sh
final OnDragListener historyOnDragListener = new OnDragListenerVibrator(newOnDragListener(new HistoryDragProcessor(this.calculatorModel), dragPreferences), vibrator, preferences);
((DragButton) findViewById(R.id.historyButton)).setOnDragListener(historyOnDragListener);
+ ((DragButton) findViewById(R.id.subtractionButton)).setOnDragListener(new OnDragListenerVibrator(newOnDragListener(new SimpleOnDragListener.DragProcessor() {
+ @Override
+ public boolean processDragEvent(@NotNull DragDirection dragDirection, @NotNull DragButton dragButton, @NotNull Point2d startPoint2d, @NotNull MotionEvent motionEvent) {
+ if (dragDirection == DragDirection.down) {
+ operatorsButtonClickHandler(dragButton);
+ return true;
+ }
+ return false;
+ }
+ }, dragPreferences), vibrator, preferences));
+
+
final OnDragListener toPositionOnDragListener = new OnDragListenerVibrator(new SimpleOnDragListener(new CursorDragProcessor(calculatorModel), dragPreferences), vibrator, preferences);
((DragButton) findViewById(R.id.rightButton)).setOnDragListener(toPositionOnDragListener);
((DragButton) findViewById(R.id.leftButton)).setOnDragListener(toPositionOnDragListener);
diff --git a/src/main/java/org/solovyev/android/calculator/CalculatorModel.java b/src/main/java/org/solovyev/android/calculator/CalculatorModel.java
index 76c68d9d..50091873 100644
--- a/src/main/java/org/solovyev/android/calculator/CalculatorModel.java
+++ b/src/main/java/org/solovyev/android/calculator/CalculatorModel.java
@@ -269,6 +269,9 @@ public enum CalculatorModel implements CursorControl, HistoryControl extends AndroidMathRegistryImpl {
+
+ @NotNull
+ private static final Map substitutes = new HashMap();
+ static {
+ substitutes.put("√", "sqrt");
+ }
+
+ @NotNull
+ private static final String FUNCTION_DESCRIPTION_PREFIX = "c_fun_description_";
+
+ public AndroidFunctionsMathRegistry(@NotNull MathRegistry functionsRegistry) {
+ super(functionsRegistry, FUNCTION_DESCRIPTION_PREFIX);
+ }
+
+ @NotNull
+ @Override
+ protected Map getSubstitutes() {
+ return substitutes;
+ }
+}
diff --git a/src/main/java/org/solovyev/android/calculator/model/AndroidMathRegistryImpl.java b/src/main/java/org/solovyev/android/calculator/model/AndroidMathRegistryImpl.java
index 5a362fc3..3c68ece4 100644
--- a/src/main/java/org/solovyev/android/calculator/model/AndroidMathRegistryImpl.java
+++ b/src/main/java/org/solovyev/android/calculator/model/AndroidMathRegistryImpl.java
@@ -7,7 +7,6 @@
package org.solovyev.android.calculator.model;
import android.content.Context;
-import jscl.math.function.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.solovyev.android.calculator.R;
@@ -24,32 +23,40 @@ import java.util.Map;
* Date: 10/30/11
* Time: 1:03 AM
*/
-public class AndroidMathRegistryImpl implements AndroidMathRegistry {
-
- @NotNull
- private static final String FUNCTION_DESCRIPTION_PREFIX = "c_fun_description_";
+public abstract class AndroidMathRegistryImpl implements AndroidMathRegistry {
@NotNull
private final MathRegistry functionsRegistry;
- public AndroidMathRegistryImpl(@NotNull MathRegistry functionsRegistry) {
+ @NotNull
+ private final String prefix;
+
+ protected AndroidMathRegistryImpl(@NotNull MathRegistry functionsRegistry, @NotNull String prefix) {
this.functionsRegistry = functionsRegistry;
+ this.prefix = prefix;
}
+ @NotNull
+ protected abstract Map getSubstitutes();
+
@Nullable
@Override
- public String getDescription(@NotNull Context context, @NotNull String functionName) {
+ public String getDescription(@NotNull Context context, @NotNull String name) {
final String result;
final Map stringsCache = RClassUtils.getCache(R.string.class);
final Integer stringId;
- if (!functionName.equals("√")) {
- stringId = stringsCache.get(FUNCTION_DESCRIPTION_PREFIX + functionName);
+
+ final Map substitutes = getSubstitutes();
+ final String substitute = substitutes.get(name);
+ if (substitute == null) {
+ stringId = stringsCache.get(prefix + name);
} else {
// todo serso: think
- stringId = stringsCache.get(FUNCTION_DESCRIPTION_PREFIX + "sqrt");
+ stringId = stringsCache.get(prefix + substitute);
}
+
if (stringId != null) {
result = context.getString(stringId);
} else {
diff --git a/src/main/java/org/solovyev/android/calculator/model/AndroidOperatorsMathRegistry.java b/src/main/java/org/solovyev/android/calculator/model/AndroidOperatorsMathRegistry.java
new file mode 100644
index 00000000..7de0bfc3
--- /dev/null
+++ b/src/main/java/org/solovyev/android/calculator/model/AndroidOperatorsMathRegistry.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2009-2011. Created by serso aka se.solovyev.
+ * For more information, please, contact se.solovyev@gmail.com
+ * or visit http://se.solovyev.org
+ */
+
+package org.solovyev.android.calculator.model;
+
+import org.jetbrains.annotations.NotNull;
+import org.solovyev.common.math.MathEntity;
+import org.solovyev.common.math.MathRegistry;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * User: serso
+ * Date: 11/17/11
+ * Time: 11:29 PM
+ */
+public class AndroidOperatorsMathRegistry extends AndroidMathRegistryImpl {
+
+ @NotNull
+ private static final Map substitutes = new HashMap();
+ static {
+ substitutes.put("Σ", "sum");
+ substitutes.put("∏", "product");
+ substitutes.put("∂", "derivative");
+ substitutes.put("∫ab", "integral_ab");
+ substitutes.put("∫", "integral");
+ substitutes.put("Σ", "sum");
+ }
+
+ @NotNull
+ private static final String OPERATOR_DESCRIPTION_PREFIX = "c_op_description_";
+
+ protected AndroidOperatorsMathRegistry(@NotNull MathRegistry functionsRegistry) {
+ super(functionsRegistry, OPERATOR_DESCRIPTION_PREFIX);
+ }
+
+ @NotNull
+ @Override
+ protected Map getSubstitutes() {
+ return substitutes;
+ }
+}
diff --git a/src/main/java/org/solovyev/android/calculator/model/CalculatorEngine.java b/src/main/java/org/solovyev/android/calculator/model/CalculatorEngine.java
index 625e18ee..4047e4c6 100644
--- a/src/main/java/org/solovyev/android/calculator/model/CalculatorEngine.java
+++ b/src/main/java/org/solovyev/android/calculator/model/CalculatorEngine.java
@@ -13,24 +13,18 @@ import jscl.math.operator.Operator;
import jscl.text.ParseInterruptedException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.solovyev.android.calculator.R;
import org.solovyev.android.calculator.jscl.JsclOperation;
import org.solovyev.android.msg.AndroidMessage;
import org.solovyev.common.NumberMapper;
import org.solovyev.common.math.MathRegistry;
import org.solovyev.common.msg.MessageRegistry;
-import org.solovyev.common.msg.MessageType;
-import org.solovyev.common.utils.CollectionsUtils;
-import org.solovyev.common.utils.Formatter;
import org.solovyev.common.utils.MutableObject;
import org.solovyev.common.utils.StringUtils;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
-import java.util.HashSet;
import java.util.Locale;
-import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -70,18 +64,16 @@ public enum CalculatorEngine {
private final AndroidVarsRegistry varsRegister = new AndroidVarsRegistryImpl(engine.getConstantsRegistry());
@NotNull
- private final AndroidMathRegistry functionsRegistry = new AndroidMathRegistryImpl(engine.getFunctionsRegistry());
+ private final AndroidMathRegistry functionsRegistry = new AndroidFunctionsMathRegistry(engine.getFunctionsRegistry());
@NotNull
- private final AndroidMathRegistry operatorsRegistry = new AndroidMathRegistryImpl(engine.getOperatorsRegistry());
+ private final AndroidMathRegistry operatorsRegistry = new AndroidOperatorsMathRegistry(engine.getOperatorsRegistry());
private final MathRegistry postfixFunctionsRegistry = engine.getPostfixFunctionsRegistry();
- @NotNull
- private final static Set tooLongExecutionCache = new HashSet();
-
@NotNull
private DecimalFormatSymbols decimalGroupSymbols = new DecimalFormatSymbols(Locale.getDefault());
+
{
decimalGroupSymbols.setDecimalSeparator('.');
decimalGroupSymbols.setGroupingSeparator(GROUPING_SEPARATOR_DEFAULT.charAt(0));
@@ -106,7 +98,7 @@ public enum CalculatorEngine {
final DecimalFormat df = new DecimalFormat();
df.setDecimalFormatSymbols(decimalGroupSymbols);
df.setGroupingUsed(useGroupingSeparator);
- if (round ) {
+ if (round) {
if (isRoundResult()) {
df.setMaximumFractionDigits(instance.getPrecision());
return df.format(new BigDecimal(value).setScale(instance.getPrecision(), BigDecimal.ROUND_HALF_UP).doubleValue());
@@ -178,75 +170,70 @@ public enum CalculatorEngine {
final JsclOperation finalOperation = operation;
final String result;
- if (!tooLongExecutionCache.contains(jsclExpression)) {
- final MutableObject calculationResult = new MutableObject(null);
- final MutableObject exception = new MutableObject(null);
- final MutableObject calculationThread = new MutableObject(null);
+ final MutableObject calculationResult = new MutableObject(null);
+ final MutableObject exception = new MutableObject(null);
+ final MutableObject calculationThread = new MutableObject(null);
- final CountDownLatch latch = new CountDownLatch(1);
+ 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);
- calculationResult.setObject(finalOperation.evaluate(jsclExpression));
- } catch (ArithmeticException e) {
- //System.out.println(e.getMessage());
- exception.setObject(new ParseException(e.getMessage(), e));
- } catch (jscl.text.ParseException e) {
- //System.out.println(e.getMessage());
- exception.setObject(new ParseException(e.getMessage(), 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();
- }
+ 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);
+ calculationResult.setObject(finalOperation.evaluate(jsclExpression));
+ } catch (ArithmeticException e) {
+ //System.out.println(e.getMessage());
+ exception.setObject(new ParseException(e.getMessage(), e));
+ } catch (jscl.text.ParseException e) {
+ //System.out.println(e.getMessage());
+ exception.setObject(new ParseException(e.getMessage(), 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();
+ }
+ }).start();
- try {
- //Log.d(CalculatorEngine.class.getName(), "Main thread is waiting: " + Thread.currentThread().getName());
- latch.await(timeout, TimeUnit.MILLISECONDS);
- //Log.d(CalculatorEngine.class.getName(), "Main thread got up: " + Thread.currentThread().getName());
+ try {
+ //Log.d(CalculatorEngine.class.getName(), "Main thread is waiting: " + Thread.currentThread().getName());
+ latch.await(timeout, TimeUnit.MILLISECONDS);
+ //Log.d(CalculatorEngine.class.getName(), "Main thread got up: " + Thread.currentThread().getName());
- final ParseException evalErrorLocal = exception.getObject();
- final Object calculationResultLocal = calculationResult.getObject();
- final Thread calculationThreadLocal = calculationThread.getObject();
+ final ParseException evalErrorLocal = exception.getObject();
+ final Object calculationResultLocal = calculationResult.getObject();
+ final Thread calculationThreadLocal = calculationThread.getObject();
- if (calculationThreadLocal != null) {
- // todo serso: interrupt doesn't stop the thread but it MUST be killed
- threadKiller.killThread(calculationThreadLocal);
- //calculationThreadLocal.stop();
- }
-
- if ( evalErrorLocal != null ) {
- if ( finalOperation == JsclOperation.numeric && preparedExpression.isExistsUndefinedVar() ) {
- return evaluate(JsclOperation.simplify, expression, mr);
- }
- throw evalErrorLocal;
- }
-
- if ( calculationResultLocal == null ) {
- tooLongExecutionCache.add(jsclExpression);
- throw new ParseException("Too long calculation for: " + jsclExpression);
- }
-
- } catch (InterruptedException e) {
- throw new ParseException(e);
+ if (calculationThreadLocal != null) {
+ // todo serso: interrupt doesn't stop the thread but it MUST be killed
+ threadKiller.killThread(calculationThreadLocal);
+ //calculationThreadLocal.stop();
}
- result = String.valueOf(calculationResult.getObject()).trim();
- } else {
- throw new ParseException("Too long calculation for: " + jsclExpression);
+ if (evalErrorLocal != null) {
+ if (finalOperation == JsclOperation.numeric && preparedExpression.isExistsUndefinedVar()) {
+ return evaluate(JsclOperation.simplify, expression, mr);
+ }
+ throw evalErrorLocal;
+ }
+
+ if (calculationResultLocal == null) {
+ throw new ParseException("Too long calculation for: " + jsclExpression);
+ }
+
+ } catch (InterruptedException e) {
+ throw new ParseException(e);
}
+ result = String.valueOf(calculationResult.getObject()).trim();
+
return new Result(operation.getFromProcessor().process(result), operation);
}
}
@@ -330,6 +317,7 @@ public enum CalculatorEngine {
void setTimeout(int timeout) {
this.timeout = timeout;
}
+
// for tests only
void setThreadKiller(@NotNull ThreadKiller threadKiller) {
this.threadKiller = threadKiller;