summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichele Bini <michele.bini@gmail.com>2022-06-10 18:03:45 (GMT)
committerMichele Bini <michele.bini@gmail.com>2022-06-11 01:09:51 (GMT)
commit4e3a3b312c946bed572e4c1a05314ddd673c3389 (patch)
tree43db25d4db79e92288724f8d596a97438bfa7305
parente05cdb375c1cf44d8443a88aa18ab61990f93a32 (diff)
Clarify code a bit
-rw-r--r--src/displayapp/screens/Calculator.cpp37
1 files changed, 14 insertions, 23 deletions
diff --git a/src/displayapp/screens/Calculator.cpp b/src/displayapp/screens/Calculator.cpp
index c0a947d..c44f781 100644
--- a/src/displayapp/screens/Calculator.cpp
+++ b/src/displayapp/screens/Calculator.cpp
@@ -10,11 +10,8 @@ using namespace Pinetime::Applications::Screens;
// Anonymous Namespace for all the structs
namespace {
- struct Node {
- char op;
- double val;
- };
- template <typename X, uint8_t max_stack_len> struct StaticallyAllocatedStack {
+ template <typename X, uint8_t max_stack_len> struct Stack {
+ // Basic stack data type without dynamic allocations
X data[max_stack_len];
uint8_t stack_len = 0;
inline auto size() { return stack_len; }
@@ -25,8 +22,13 @@ namespace {
inline X& push() { return data[stack_len++]; }
inline void push(X x) { X& datum{ push() }; datum = x; }
};
- template <uint8_t max_stack_len> struct CalcStack : public StaticallyAllocatedStack<Node, max_stack_len> {
- typedef StaticallyAllocatedStack<Node, max_stack_len> Super;
+ 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(); }
inline void pushValue(double value) {
Super::data[Super::stack_len].op = 0;
@@ -37,6 +39,8 @@ namespace {
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;
@@ -73,7 +77,7 @@ namespace {
}
};
- template <typename I, typename F, typename S> bool parseFloat(I& i, F& f, S& s) {
+ template <typename Input, typename Float, typename Sign> bool parseFloat(Input& i, Float& f, Sign& s) {
f = 0;
int8_t dot_position = -1;
while (!i.empty()) {
@@ -171,12 +175,12 @@ Calculator::Calculator(DisplayApp* app, Controllers::MotorController& motorContr
}
void Calculator::Eval() {
- StaticallyAllocatedStack<char, 32> input;
+ Stack<char, 32> input;
for (int8_t i = position - 1; i >= 0; i--) {
input.push(text[i]);
}
CalcStack<16> output;
- StaticallyAllocatedStack<char, 32> operators;
+ Stack<char, 32> operators;
bool expectingNumber = true;
int8_t sign = +1;
double resultFloat;
@@ -284,18 +288,6 @@ void Calculator::Eval() {
}
// perform the calculation
resultFloat = output.top().val;
-#if 0
- // This only seems to work in the simulator
- if (!std::isfinite(resultFloat)) {
- goto eval_error;
- }
- position = 0;
- for (char s : std::to_string(resultFloat)) {
- text[position++] = s;
- }
- text[position] = 0;
-#else
- // position = snprintf(text, 20, "%.9g", resultFloat);
// make sure that the absolute value of the integral part of result fits in a 32 bit unsigned integer
sign = (resultFloat < 0);
if (sign) {
@@ -326,7 +318,6 @@ void Calculator::Eval() {
position--;
}
}
-#endif
return;
eval_error:
motorController.RunForDuration(10);