1 | /* |
2 | SPDX-FileCopyrightText: 2001-2013 Evan Teran <evan.teran@gmail.com> |
3 | SPDX-FileCopyrightText: 1996-2000 Bernd Johannes Wuebben <wuebben@kde.org> |
4 | |
5 | SPDX-License-Identifier: GPL-2.0-or-later |
6 | */ |
7 | |
8 | #pragma once |
9 | |
10 | #include "knumber.h" |
11 | #include "stats.h" |
12 | #include <QStack> |
13 | |
14 | class CalcEngine |
15 | { |
16 | public: |
17 | // operations that can be stored in calculation stack |
18 | enum Operation { |
19 | FUNC_EQUAL, |
20 | FUNC_PERCENT, |
21 | FUNC_BRACKET, |
22 | FUNC_OR, |
23 | FUNC_XOR, |
24 | FUNC_AND, |
25 | FUNC_LSH, |
26 | FUNC_RSH, |
27 | FUNC_ADD, |
28 | FUNC_SUBTRACT, |
29 | FUNC_MULTIPLY, |
30 | FUNC_DIVIDE, |
31 | FUNC_MOD, |
32 | FUNC_INTDIV, |
33 | FUNC_BINOM, |
34 | FUNC_POWER, |
35 | FUNC_PWR_ROOT |
36 | }; |
37 | |
38 | enum Repeat { REPEAT_ALLOW, REPEAT_PREVENT }; |
39 | |
40 | CalcEngine(); |
41 | |
42 | KNumber lastOutput(bool &error) const; |
43 | |
44 | void enterOperation(const KNumber &num, Operation func, Repeat allow_repeat = REPEAT_ALLOW); |
45 | |
46 | void ArcCosDeg(const KNumber &input); |
47 | void ArcCosRad(const KNumber &input); |
48 | void ArcCosGrad(const KNumber &input); |
49 | void ArcSinDeg(const KNumber &input); |
50 | void ArcSinRad(const KNumber &input); |
51 | void ArcSinGrad(const KNumber &input); |
52 | void ArcTangensDeg(const KNumber &input); |
53 | void ArcTangensRad(const KNumber &input); |
54 | void ArcTangensGrad(const KNumber &input); |
55 | void AreaCosHyp(const KNumber &input); |
56 | void AreaSinHyp(const KNumber &input); |
57 | void AreaTangensHyp(const KNumber &input); |
58 | void Complement(const KNumber &input); |
59 | void CosDeg(const KNumber &input); |
60 | void CosRad(const KNumber &input); |
61 | void CosGrad(const KNumber &input); |
62 | void CosHyp(const KNumber &input); |
63 | void Cube(const KNumber &input); |
64 | void CubeRoot(const KNumber &input); |
65 | void Exp(const KNumber &input); |
66 | void Exp10(const KNumber &input); |
67 | void Factorial(const KNumber &input); |
68 | void Gamma(const KNumber &input); |
69 | void InvertSign(const KNumber &input); |
70 | void Ln(const KNumber &input); |
71 | void Log10(const KNumber &input); |
72 | void ParenClose(KNumber input); |
73 | void ParenOpen(const KNumber &input); |
74 | void Reciprocal(const KNumber &input); |
75 | void SinDeg(const KNumber &input); |
76 | void SinGrad(const KNumber &input); |
77 | void SinRad(const KNumber &input); |
78 | void SinHyp(const KNumber &input); |
79 | void Square(const KNumber &input); |
80 | void SquareRoot(const KNumber &input); |
81 | void StatClearAll(const KNumber &input); |
82 | void StatCount(const KNumber &input); |
83 | void StatDataNew(const KNumber &input); |
84 | void StatDataDel(const KNumber &input); |
85 | void StatMean(const KNumber &input); |
86 | void StatMedian(const KNumber &input); |
87 | void StatStdDeviation(const KNumber &input); |
88 | void StatStdSample(const KNumber &input); |
89 | void StatSum(const KNumber &input); |
90 | void StatSumSquares(const KNumber &input); |
91 | void TangensDeg(const KNumber &input); |
92 | void TangensRad(const KNumber &input); |
93 | void TangensGrad(const KNumber &input); |
94 | void TangensHyp(const KNumber &input); |
95 | |
96 | void Reset(); |
97 | void setOnlyUpdateOperation(bool update); |
98 | bool getOnlyUpdateOperation() const; |
99 | |
100 | private: |
101 | KStats stats; |
102 | |
103 | struct Node { |
104 | KNumber number; |
105 | Operation operation; |
106 | }; |
107 | |
108 | // Stack holds all operations and numbers that have not yet been |
109 | // processed, e.g. user types "2+3*", the calculation can not be |
110 | // executed, because "*" has a higher precedence than "+", so we |
111 | // need to wait for the next number. |
112 | // |
113 | // In the stack this would be stored as ((2,+),(3,*),...) |
114 | // |
115 | // "enterOperation": If the introduced Operation has lower priority |
116 | // than the preceding operations in the stack, then we can start to |
117 | // evaluate the stack (with "evalStack"). Otherwise we append the new |
118 | // Operation and number to the stack. |
119 | // |
120 | // E.g. "2*3+" evaluates to "6+", but "2+3*" can not be evaluated |
121 | // yet. |
122 | // |
123 | // We also take care of brackets, by writing a marker "FUNC_BRACKET" |
124 | // into the stack, each time the user opens one. When a bracket is |
125 | // closed, everything in the stack is evaluated until the first |
126 | // marker "FUNC_BRACKET" found. |
127 | QStack<Node> stack_; |
128 | |
129 | KNumber last_number_; |
130 | |
131 | Operation last_operation_; |
132 | KNumber last_repeat_number_; |
133 | bool only_update_operation_; |
134 | |
135 | bool percent_mode_; |
136 | bool repeat_mode_; |
137 | |
138 | bool evalStack(); |
139 | |
140 | KNumber evalOperation(const KNumber &arg1, Operation operation, const KNumber &arg2); |
141 | }; |
142 | |
143 | |