summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorHans Boehm <hboehm@google.com>2015-06-02 22:13:43 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2015-06-02 22:13:43 +0000
commit694406b52e3bafa9da4396de836e6214e3a9d799 (patch)
treef5b35ef4905d0799c0806d8f298e67446696b54a /src
parent7531cd7dadfcb9c7df658fb2193c42b65ea0e21f (diff)
parent4db31b490443e4454d98a5ae2bc44b87149accfe (diff)
downloadandroid_packages_apps_ExactCalculator-694406b52e3bafa9da4396de836e6214e3a9d799.tar.gz
android_packages_apps_ExactCalculator-694406b52e3bafa9da4396de836e6214e3a9d799.tar.bz2
android_packages_apps_ExactCalculator-694406b52e3bafa9da4396de836e6214e3a9d799.zip
Merge "Implement percent and new inverse functions" into mnc-dev
Diffstat (limited to 'src')
-rw-r--r--src/com/android/calculator2/BoundedRational.java19
-rw-r--r--src/com/android/calculator2/Calculator.java10
-rw-r--r--src/com/android/calculator2/CalculatorExpr.java56
-rw-r--r--src/com/android/calculator2/Evaluator.java24
-rw-r--r--src/com/android/calculator2/KeyMaps.java7
5 files changed, 91 insertions, 25 deletions
diff --git a/src/com/android/calculator2/BoundedRational.java b/src/com/android/calculator2/BoundedRational.java
index ee2ee92..a6dd6d9 100644
--- a/src/com/android/calculator2/BoundedRational.java
+++ b/src/com/android/calculator2/BoundedRational.java
@@ -229,6 +229,14 @@ public class BoundedRational {
return null;
}
+ private static BoundedRational map0to1(BoundedRational r) {
+ if (r == null) return null;
+ if (r.mNum.equals(BigInteger.ZERO)) {
+ return ONE;
+ }
+ return null;
+ }
+
private static BoundedRational map1to0(BoundedRational r) {
if (r == null) return null;
if (r.mNum.equals(r.mDen)) {
@@ -345,12 +353,7 @@ public class BoundedRational {
}
public static BoundedRational cos(BoundedRational r) {
- // Maps 0 to 1, null otherwise
- if (r == null) return null;
- if (r.mNum.equals(BigInteger.ZERO)) {
- return ONE;
- }
- return null;
+ return map0to1(r);
}
public static BoundedRational degreeCos(BoundedRational r) {
@@ -403,6 +406,10 @@ public class BoundedRational {
return map1to0(r);
}
+ public static BoundedRational exp(BoundedRational r) {
+ return map0to1(r);
+ }
+
// Return the base 10 log of n, if n is a power of 10, -1 otherwise.
// n must be positive.
private static long b10Log(BigInteger n) {
diff --git a/src/com/android/calculator2/Calculator.java b/src/com/android/calculator2/Calculator.java
index 0970174..b2cf477 100644
--- a/src/com/android/calculator2/Calculator.java
+++ b/src/com/android/calculator2/Calculator.java
@@ -227,12 +227,18 @@ public class Calculator extends Activity
mInvertibleButtons = new View[] {
findViewById(R.id.fun_sin),
findViewById(R.id.fun_cos),
- findViewById(R.id.fun_tan)
+ findViewById(R.id.fun_tan),
+ findViewById(R.id.fun_ln),
+ findViewById(R.id.fun_log),
+ findViewById(R.id.op_sqrt)
};
mInverseButtons = new View[] {
findViewById(R.id.fun_arcsin),
findViewById(R.id.fun_arccos),
- findViewById(R.id.fun_arctan)
+ findViewById(R.id.fun_arctan),
+ findViewById(R.id.fun_exp),
+ findViewById(R.id.fun_10pow),
+ findViewById(R.id.op_sqr)
};
mEvaluator = new Evaluator(this, mResultText);
diff --git a/src/com/android/calculator2/CalculatorExpr.java b/src/com/android/calculator2/CalculatorExpr.java
index e5be4b9..6771b52 100644
--- a/src/com/android/calculator2/CalculatorExpr.java
+++ b/src/com/android/calculator2/CalculatorExpr.java
@@ -582,7 +582,7 @@ class CalculatorExpr {
case R.id.const_pi:
return new EvalRet(i+1, CR.PI, null);
case R.id.const_e:
- return new EvalRet(i+1, CR.valueOf(1).exp(), null);
+ return new EvalRet(i+1, REAL_E, null);
case R.id.op_sqrt:
// Seems to have highest precedence.
// Does not add implicit paren.
@@ -635,6 +635,12 @@ class CalculatorExpr {
ratVal = BoundedRational.ln(argVal.mRatVal);
if (ratVal != null) break;
return new EvalRet(argVal.mPos, argVal.mVal.ln(), null);
+ case R.id.fun_exp:
+ argVal = evalExpr(i+1, ec);
+ if (isOperator(argVal.mPos, R.id.rparen, ec)) argVal.mPos++;
+ ratVal = BoundedRational.exp(argVal.mRatVal);
+ if (ratVal != null) break;
+ return new EvalRet(argVal.mPos, argVal.mVal.exp(), null);
case R.id.fun_log:
argVal = evalExpr(i+1, ec);
if (isOperator(argVal.mPos, R.id.rparen, ec)) argVal.mPos++;
@@ -702,35 +708,59 @@ class CalculatorExpr {
// Test for integer-ness to 100 bits past binary point.
private static final BigInteger MASK =
BigInteger.ONE.shiftLeft(-TEST_PREC).subtract(BigInteger.ONE);
+ private static final CR REAL_E = CR.valueOf(1).exp();
+ private static final CR REAL_ONE_HUNDREDTH = CR.valueOf(100).inverse();
+ private static final BoundedRational RATIONAL_ONE_HUNDREDTH =
+ new BoundedRational(1,100);
private static boolean isApprInt(CR x) {
BigInteger appr = x.get_appr(TEST_PREC);
return appr.and(MASK).signum() == 0;
}
- private EvalRet evalFactorial(int i, EvalContext ec) throws SyntaxException {
+ private EvalRet evalSuffix(int i, EvalContext ec) throws SyntaxException {
EvalRet tmp = evalUnary(i, ec);
int cpos = tmp.mPos;
CR cval = tmp.mVal;
BoundedRational ratVal = tmp.mRatVal;
- while (isOperator(cpos, R.id.op_fact, ec)) {
- if (ratVal == null) {
- // Assume it was an integer, but we
- // didn't figure it out.
- // KitKat may have used the Gamma function.
- if (!isApprInt(cval)) {
- throw new ArithmeticException("factorial(non-integer)");
+ boolean isFact;
+ boolean isSquared = false;
+ while ((isFact = isOperator(cpos, R.id.op_fact, ec)) ||
+ (isSquared = isOperator(cpos, R.id.op_sqr, ec)) ||
+ isOperator(cpos, R.id.op_pct, ec)) {
+ if (isFact) {
+ if (ratVal == null) {
+ // Assume it was an integer, but we
+ // didn't figure it out.
+ // KitKat may have used the Gamma function.
+ if (!isApprInt(cval)) {
+ throw new ArithmeticException("factorial(non-integer)");
+ }
+ ratVal = new BoundedRational(cval.BigIntegerValue());
+ }
+ ratVal = BoundedRational.fact(ratVal);
+ cval = ratVal.CRValue();
+ } else if (isSquared) {
+ ratVal = BoundedRational.multiply(ratVal, ratVal);
+ if (ratVal == null) {
+ cval = cval.multiply(cval);
+ } else {
+ cval = ratVal.CRValue();
+ }
+ } else /* percent */ {
+ ratVal = BoundedRational.multiply(ratVal, RATIONAL_ONE_HUNDREDTH);
+ if (ratVal == null) {
+ cval = cval.multiply(REAL_ONE_HUNDREDTH);
+ } else {
+ cval = ratVal.CRValue();
}
- ratVal = new BoundedRational(cval.BigIntegerValue());
}
- ratVal = BoundedRational.fact(ratVal);
++cpos;
}
- if (ratVal != null) cval = ratVal.CRValue();
return new EvalRet(cpos, cval, ratVal);
}
private EvalRet evalFactor(int i, EvalContext ec) throws SyntaxException {
- final EvalRet result1 = evalFactorial(i, ec);
+ final EvalRet result1 = evalSuffix(i, ec);
int cpos = result1.mPos; // current position
CR cval = result1.mVal; // value so far
BoundedRational ratVal = result1.mRatVal; // int value so far
diff --git a/src/com/android/calculator2/Evaluator.java b/src/com/android/calculator2/Evaluator.java
index 4ddaf15..9b9e830 100644
--- a/src/com/android/calculator2/Evaluator.java
+++ b/src/com/android/calculator2/Evaluator.java
@@ -776,10 +776,15 @@ class Evaluator {
// syntax issues, and the expression is unchanged.
// Return true otherwise.
boolean append(int id) {
- mChangedValue = (KeyMaps.digVal(id) != KeyMaps.NOT_DIGIT
- || KeyMaps.isSuffix(id)
- || id == R.id.const_pi || id == R.id.const_e);
- return mExpr.add(id);
+ if (id == R.id.fun_10pow) {
+ add10pow(); // Handled as macro expansion.
+ return true;
+ } else {
+ mChangedValue = (KeyMaps.digVal(id) != KeyMaps.NOT_DIGIT
+ || KeyMaps.isSuffix(id)
+ || id == R.id.const_pi || id == R.id.const_e);
+ return mExpr.add(id);
+ }
}
void delete() {
@@ -865,6 +870,17 @@ class Evaluator {
mExpr.append(mSaved);
}
+ // Add the power of 10 operator to the expression. This is treated
+ // essentially as a macro expansion.
+ private void add10pow() {
+ CalculatorExpr ten = new CalculatorExpr();
+ ten.add(R.id.digit_1);
+ ten.add(R.id.digit_0);
+ mChangedValue = true; // For consistency. Reevaluation is probably not useful.
+ mExpr.append(ten);
+ mExpr.add(R.id.op_pow);
+ }
+
// Retrieve the main expression being edited.
// It is the callee's reponsibility to call cancelAll to cancel
// ongoing concurrent computations before modifying the result.
diff --git a/src/com/android/calculator2/KeyMaps.java b/src/com/android/calculator2/KeyMaps.java
index e3b84e7..5385424 100644
--- a/src/com/android/calculator2/KeyMaps.java
+++ b/src/com/android/calculator2/KeyMaps.java
@@ -67,6 +67,9 @@ public class KeyMaps {
return context.getString(R.string.fun_ln) + context.getString(R.string.lparen);
case R.id.fun_log:
return context.getString(R.string.fun_log) + context.getString(R.string.lparen);
+ case R.id.fun_exp:
+ // Button label doesn't work.
+ return context.getString(R.string.exponential) + context.getString(R.string.lparen);
case R.id.lparen:
return context.getString(R.string.lparen);
case R.id.rparen:
@@ -79,6 +82,9 @@ public class KeyMaps {
return context.getString(R.string.op_div);
case R.id.op_add:
return context.getString(R.string.op_add);
+ case R.id.op_sqr:
+ // Button label doesn't work.
+ return context.getString(R.string.squared);
case R.id.op_sub:
return context.getString(R.string.op_sub);
case R.id.dec_point:
@@ -132,6 +138,7 @@ public class KeyMaps {
switch (id) {
case R.id.op_fact:
case R.id.op_pct:
+ case R.id.op_sqr:
return true;
default:
return false;