File indexing completed on 2021-12-21 14:36:20

0001 /*
0002     SPDX-FileCopyrightText: 2001-2013 Evan Teran <evan.teran@gmail.com>
0003     SPDX-FileCopyrightText: 1996-2000 Bernd Johannes Wuebben <wuebben@kde.org>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #pragma once
0009 
0010 #include "knumber.h"
0011 #include "stats.h"
0012 #include <QStack>
0013 
0014 class CalcEngine
0015 {
0016 public:
0017     // operations that can be stored in calculation stack
0018     enum Operation {
0019         FUNC_EQUAL,
0020         FUNC_PERCENT,
0021         FUNC_BRACKET,
0022         FUNC_OR,
0023         FUNC_XOR,
0024         FUNC_AND,
0025         FUNC_LSH,
0026         FUNC_RSH,
0027         FUNC_ADD,
0028         FUNC_SUBTRACT,
0029         FUNC_MULTIPLY,
0030         FUNC_DIVIDE,
0031         FUNC_MOD,
0032         FUNC_INTDIV,
0033         FUNC_BINOM,
0034         FUNC_POWER,
0035         FUNC_PWR_ROOT
0036     };
0037 
0038     enum Repeat { REPEAT_ALLOW, REPEAT_PREVENT };
0039 
0040     CalcEngine();
0041 
0042     KNumber lastOutput(bool &error) const;
0043 
0044     void enterOperation(const KNumber &num, Operation func, Repeat allow_repeat = REPEAT_ALLOW);
0045 
0046     void ArcCosDeg(const KNumber &input);
0047     void ArcCosRad(const KNumber &input);
0048     void ArcCosGrad(const KNumber &input);
0049     void ArcSinDeg(const KNumber &input);
0050     void ArcSinRad(const KNumber &input);
0051     void ArcSinGrad(const KNumber &input);
0052     void ArcTangensDeg(const KNumber &input);
0053     void ArcTangensRad(const KNumber &input);
0054     void ArcTangensGrad(const KNumber &input);
0055     void AreaCosHyp(const KNumber &input);
0056     void AreaSinHyp(const KNumber &input);
0057     void AreaTangensHyp(const KNumber &input);
0058     void Complement(const KNumber &input);
0059     void CosDeg(const KNumber &input);
0060     void CosRad(const KNumber &input);
0061     void CosGrad(const KNumber &input);
0062     void CosHyp(const KNumber &input);
0063     void Cube(const KNumber &input);
0064     void CubeRoot(const KNumber &input);
0065     void Exp(const KNumber &input);
0066     void Exp10(const KNumber &input);
0067     void Factorial(const KNumber &input);
0068     void Gamma(const KNumber &input);
0069     void InvertSign(const KNumber &input);
0070     void Ln(const KNumber &input);
0071     void Log10(const KNumber &input);
0072     void ParenClose(KNumber input);
0073     void ParenOpen(const KNumber &input);
0074     void Reciprocal(const KNumber &input);
0075     void SinDeg(const KNumber &input);
0076     void SinGrad(const KNumber &input);
0077     void SinRad(const KNumber &input);
0078     void SinHyp(const KNumber &input);
0079     void Square(const KNumber &input);
0080     void SquareRoot(const KNumber &input);
0081     void StatClearAll(const KNumber &input);
0082     void StatCount(const KNumber &input);
0083     void StatDataNew(const KNumber &input);
0084     void StatDataDel(const KNumber &input);
0085     void StatMean(const KNumber &input);
0086     void StatMedian(const KNumber &input);
0087     void StatStdDeviation(const KNumber &input);
0088     void StatStdSample(const KNumber &input);
0089     void StatSum(const KNumber &input);
0090     void StatSumSquares(const KNumber &input);
0091     void TangensDeg(const KNumber &input);
0092     void TangensRad(const KNumber &input);
0093     void TangensGrad(const KNumber &input);
0094     void TangensHyp(const KNumber &input);
0095 
0096     void Reset();
0097     void setOnlyUpdateOperation(bool update);
0098     bool getOnlyUpdateOperation() const;
0099 
0100 private:
0101     KStats stats;
0102 
0103     struct Node {
0104         KNumber number;
0105         Operation operation;
0106     };
0107 
0108     // Stack holds all operations and numbers that have not yet been
0109     // processed, e.g. user types "2+3*", the calculation can not be
0110     // executed, because "*" has a higher precedence than "+", so we
0111     // need to wait for the next number.
0112     //
0113     // In the stack this would be stored as ((2,+),(3,*),...)
0114     //
0115     // "enterOperation": If the introduced Operation has lower priority
0116     // than the preceding operations in the stack, then we can start to
0117     // evaluate the stack (with "evalStack"). Otherwise we append the new
0118     // Operation and number to the stack.
0119     //
0120     // E.g. "2*3+" evaluates to "6+", but "2+3*" can not be evaluated
0121     // yet.
0122     //
0123     // We also take care of brackets, by writing a marker "FUNC_BRACKET"
0124     // into the stack, each time the user opens one.  When a bracket is
0125     // closed, everything in the stack is evaluated until the first
0126     // marker "FUNC_BRACKET" found.
0127     QStack<Node> stack_;
0128 
0129     KNumber last_number_;
0130 
0131     Operation last_operation_;
0132     KNumber last_repeat_number_;
0133     bool only_update_operation_;
0134 
0135     bool percent_mode_;
0136     bool repeat_mode_;
0137 
0138     bool evalStack();
0139 
0140     KNumber evalOperation(const KNumber &arg1, Operation operation, const KNumber &arg2);
0141 };
0142