summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichele Bini <michele.bini@gmail.com>2022-06-10 20:59:11 (GMT)
committerMichele Bini <michele.bini@gmail.com>2022-06-11 01:09:51 (GMT)
commitd0a184a9e5dfd56a447f93c6e23715adb0738d0e (patch)
tree50c7711980a16ea880d63f6ece990e8cbd193601
parentf022fef811e5a7809d566308dc321624dcdd989d (diff)
simplify code, reduce duplication
-rw-r--r--src/displayapp/screens/Calculator.cpp103
1 files changed, 37 insertions, 66 deletions
diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp
index 42688a3..dd23059 100644
--- a/src/displayapp/screens/Calculator.cpp
+++ b/src/displayapp/screens/Calculator.cpp
@@ -7,7 +7,6 @@
using namespace Pinetime::Applications::Screens;
-// Anonymous Namespace for all the structs
namespace {
template <typename X, uint8_t max_stack_len> struct Stack {
// Basic stack data type without dynamic allocations
@@ -21,58 +20,40 @@ namespace {
inline X& push() { return data[stack_len++]; }
inline void push(X x) { X& datum{ push() }; datum = x; }
};
- struct Node {
- // if op == 0, the node represents a double value, otherwise it's an operator
- char op;
- double val;
- };
- template <uint8_t max_stack_len> struct CalcStack : public Stack<Node, max_stack_len> {
- typedef Stack<Node, max_stack_len> Super;
- inline Node& push() { return Super::push(); }
+ template <uint8_t max_stack_len> struct CalcStack : public Stack<double, max_stack_len> {
+ typedef Stack<double, max_stack_len> Super;
inline void pushValue(double value) {
- Super::data[Super::stack_len].op = 0;
- Super::data[Super::stack_len].val = value;
- Super::stack_len++;
+ Super::push(value);
}
- void pushOperator(char op) {
- Node* node0 = Super::data + Super::stack_len;
- node0->op = op;
- if (Super::stack_len > 1) {
- // Evaluate subexpressions as soon as it's possible
- // Inf and NaN take care of error handling in case of non-finite results
- Node* node1 = node0 - 1;
- if (node1->op == 0) {
- Node* node2 = node1 - 1;
- auto val2 = node2->val;
- auto val1 = node1->val;
- if (node2->op == 0) {
- switch (op) {
- case '^':
- val2 = pow(val2, val1);
- break;
- case 'x':
- val2 *= val1;
- break;
- case '/':
- val2 /= val1;
- break;
- case '+':
- val2 += val1;
- break;
- case '-':
- val2 -= val1;
- break;
- default:
- goto done;
- }
- }
- node2->val = val2;
- Super::stack_len--;
- return;
- }
+ bool pushOperator(char op) {
+ if (Super::size() < 2) return false;
+ double* node0 = Super::data + Super::stack_len;
+ // Call this only when stack_len >= 2
+ // Evaluate subexpressions as soon as possible
+ // Inf and NaN take care of error handling in case of non-finite results
+ auto& val2 { node0[-2] };
+ auto val1 = node0[-1];
+ switch (op) {
+ case '^':
+ val2 = pow(val2, val1);
+ break;
+ case 'x':
+ val2 *= val1;
+ break;
+ case '/':
+ val2 /= val1;
+ break;
+ case '+':
+ val2 += val1;
+ break;
+ case '-':
+ val2 -= val1;
+ break;
+ default:
+ return false;
}
- done:
- Super::stack_len++;
+ Super::stack_len--;
+ return true;
}
};
@@ -190,8 +171,7 @@ bool Calculator::Eval() {
}
if (isdigit(input.top())) {
- if (!parseFloat(input, output.push().val, sign)) return false;
- output.top().op = 0;
+ if (!parseFloat(input, output.push(), sign)) return false;
sign = +1;
expectingNumber = false;
continue;
@@ -226,8 +206,7 @@ bool Calculator::Eval() {
// or (the operator at the top of the operator stack has equal precedence and the token is left associative))
|| (getPrecedence(operators.top()) == getPrecedence(next) && leftAssociative(next)))) {
// need two elements on the output stack to add a binary operator
- if (output.size() < 2) return false;
- output.pushOperator(operators.top());
+ if (!output.pushOperator(operators.top())) return false;
operators.pop();
}
operators.push(next);
@@ -253,8 +232,7 @@ bool Calculator::Eval() {
case ')':
while (operators.top() != '(') {
// need two elements on the output stack to add a binary operator
- if (output.size() < 2) return false;
- output.pushOperator(operators.top());
+ if (!output.pushOperator(operators.top())) return false;
operators.pop();
if (operators.empty()) return false;
}
@@ -263,18 +241,11 @@ bool Calculator::Eval() {
}
}
while (!operators.empty()) {
- char op = operators.pop();
- if ((op == ')' || op == '(')
- ||
- // need two elements on the output stack to add a binary operator
- (output.size() < 2))
- {
- return false;
- }
- output.pushOperator(op);
+ output.pushOperator(operators.pop());
}
// perform the calculation
- resultFloat = output.top().val;
+ // assert(output.size() == 1);
+ resultFloat = output.data[0]; // this is the same as output.top() when output.size() == 1, but may reduce binary size
// make sure that the absolute value of the integral part of result fits in a 32 bit unsigned integer
sign = (resultFloat < 0);
if (sign) {