summaryrefslogtreecommitdiffstats
path: root/kcalc/kcalc_core.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kcalc/kcalc_core.cpp')
-rw-r--r--kcalc/kcalc_core.cpp1004
1 files changed, 1004 insertions, 0 deletions
diff --git a/kcalc/kcalc_core.cpp b/kcalc/kcalc_core.cpp
new file mode 100644
index 0000000..4270895
--- /dev/null
+++ b/kcalc/kcalc_core.cpp
@@ -0,0 +1,1004 @@
+/*
+ kCalculator, a scientific calculator for the X window system using the
+ Qt widget libraries, available at no cost at http://www.troll.no
+
+ The stack engine contained in this file was take from
+ Martin Bartlett's xfrmcalc
+
+ portions: Copyright (C) 2003-2006 Klaus Niederkrueger
+
+ portions: Copyright (C) 1996 Bernd Johannes Wuebben
+ wuebben@math.cornell.edu
+
+ portions: Copyright (C) 1995 Martin Bartlett
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+*/
+
+
+#if defined(_ISOC99_SOURCE)
+ #include <cassert>
+ #include <cstdio>
+ #include <climits>
+ #include <csignal>
+ #include <cerrno>
+ #include <cstring>
+ using namespace std;
+#else
+ #include <limits.h>
+ #include <stdio.h>
+ #include <assert.h>
+ #include <signal.h>
+ #include <errno.h>
+ #include <string.h>
+#endif
+
+#include <config.h>
+#include "kcalc_core.h"
+#include <stdlib.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include "kcalctype.h"
+
+#ifndef HAVE_FUNC_ISINF
+ #ifdef HAVE_IEEEFP_H
+ #include <ieeefp.h>
+ #else
+ #include <math.h>
+ #endif
+
+#undef isinf
+int isinf(double x)
+{
+#ifdef _HPUX_SOURCE
+return !isfinite(x) && x == x;
+#else
+return !finite(x) && x==x;
+#endif
+}
+
+#endif
+
+
+static void fpe_handler(int fpe_parm)
+{
+ UNUSED(fpe_parm);
+ // display_error = true;
+ //tmp_number = 0L;
+}
+
+
+static bool _error;
+
+static KNumber ExecOr(const KNumber & left_op, const KNumber & right_op)
+{
+ return (left_op | right_op);
+}
+
+static KNumber ExecXor(const KNumber & left_op, const KNumber & right_op)
+{
+ return (left_op | right_op) - (left_op & right_op);
+}
+
+static KNumber ExecAnd(const KNumber & left_op, const KNumber & right_op)
+{
+ return (left_op & right_op);
+}
+
+static KNumber ExecLsh(const KNumber & left_op, const KNumber & right_op)
+{
+ return left_op << right_op;
+}
+
+static KNumber ExecRsh(const KNumber & left_op, const KNumber & right_op)
+{
+ return left_op >> right_op;
+}
+
+static KNumber ExecAdd(const KNumber & left_op, const KNumber & right_op)
+{
+ return left_op + right_op;
+}
+
+static KNumber ExecSubtract(const KNumber & left_op, const KNumber & right_op)
+{
+ return left_op - right_op;
+}
+
+static KNumber ExecMultiply(const KNumber & left_op, const KNumber & right_op)
+{
+ return left_op * right_op;
+}
+
+static KNumber ExecDivide(const KNumber & left_op, const KNumber & right_op)
+{
+ return left_op / right_op;
+}
+
+static KNumber ExecMod(const KNumber & left_op, const KNumber & right_op)
+{
+ return left_op % right_op;
+}
+
+static KNumber ExecIntDiv(const KNumber & left_op, const KNumber & right_op)
+{
+ return (left_op / right_op).integerPart();
+}
+
+bool isoddint(const KNumber & input)
+{
+ if (input.type() != KNumber::IntegerType) return false;
+ // Routine to check if KNumber is an Odd integer
+ return ( (input / KNumber(2)).type() == KNumber::IntegerType);
+}
+
+static KNumber ExecPower(const KNumber & left_op, const KNumber & right_op)
+{
+ return left_op.power(right_op);
+}
+
+static KNumber ExecPwrRoot(const KNumber & left_op, const KNumber & right_op)
+{
+ return left_op.power(KNumber::One / right_op);
+}
+
+static KNumber ExecAddP(const KNumber & left_op, const KNumber & right_op)
+{
+ return left_op * (KNumber::One + right_op/KNumber(100));
+}
+
+static KNumber ExecSubP(const KNumber & left_op, const KNumber & right_op)
+{
+ return left_op * (KNumber::One - right_op/KNumber(100));
+}
+
+static KNumber ExecMultiplyP(const KNumber & left_op, const KNumber & right_op)
+{
+ return left_op * right_op / KNumber(100);
+}
+
+static KNumber ExecDivideP(const KNumber & left_op, const KNumber & right_op)
+{
+ return left_op * KNumber(100) / right_op;
+}
+
+
+// build precedence list
+const struct operator_data CalcEngine::Operator[] = {
+ { 0, NULL, NULL}, // FUNC_EQUAL
+ { 0, NULL, NULL}, // FUNC_PERCENT
+ { 0, NULL, NULL}, // FUNC_BRACKET
+ { 1, ExecOr, NULL}, // FUNC_OR
+ { 2, ExecXor, NULL}, // FUNC_XOR
+ { 3, ExecAnd, NULL}, // FUNC_AND
+ { 4, ExecLsh, NULL}, // FUNC_LSH
+ { 4, ExecRsh, NULL}, // FUNC_RSH
+ { 5, ExecAdd, ExecAddP}, // FUNC_ADD
+ { 5, ExecSubtract, ExecSubP}, // FUNC_SUBTRACT
+ { 6, ExecMultiply, ExecMultiplyP}, // FUNC_MULTIPLY
+ { 6, ExecDivide, ExecDivideP}, // FUNC_DIVIDE
+ { 6, ExecMod, NULL}, // FUNC_MOD
+ { 6, ExecIntDiv, NULL}, // FUNC_INTDIV
+ { 7, ExecPower, NULL}, // FUNC_POWER
+ { 7, ExecPwrRoot, NULL} // FUNC_PWR_ROOT
+};
+
+
+CalcEngine::CalcEngine()
+ : _percent_mode(false)
+{
+ //
+ // Basic initialization involves initializing the calcultion
+ // stack, and setting up the floating point excetion signal
+ // handler to trap the errors that the code can/has not been
+ // written to trap.
+ //
+
+ struct sigaction fpe_trap;
+
+ sigemptyset(&fpe_trap.sa_mask);
+ fpe_trap.sa_handler = &fpe_handler;
+#ifdef SA_RESTART
+ fpe_trap.sa_flags = SA_RESTART;
+#endif
+ sigaction(SIGFPE, &fpe_trap, NULL);
+
+ _last_number = KNumber::Zero;
+ _error = false;
+}
+
+KNumber CalcEngine::lastOutput(bool &error) const
+{
+ error = _error;
+ return _last_number;
+}
+
+void CalcEngine::ArcCosDeg(KNumber input)
+{
+ if (input.type() == KNumber::SpecialType ||
+ input < -KNumber::One || input > KNumber::One) {
+ _last_number = KNumber("nan");
+ return;
+ }
+
+ if (input.type() == KNumber::IntegerType) {
+ if (input == KNumber::One) {
+ _last_number = KNumber::Zero;
+ return;
+ }
+ if (input == - KNumber::One) {
+ _last_number = KNumber(180);
+ return;
+ }
+ if (input == KNumber::Zero) {
+ _last_number = KNumber(90);
+ return;
+ }
+ }
+ CALCAMNT tmp_num = static_cast<double>(input);
+ _last_number = Rad2Deg(KNumber(double(ACOS(tmp_num))));
+}
+
+void CalcEngine::ArcCosRad(KNumber input)
+{
+ if (input.type() == KNumber::SpecialType ||
+ input < -KNumber::One || input > KNumber::One) {
+ _last_number = KNumber("nan");
+ return;
+ }
+ CALCAMNT tmp_num = static_cast<double>(input);
+ _last_number = KNumber(double(ACOS(tmp_num)));
+}
+
+void CalcEngine::ArcCosGrad(KNumber input)
+{
+ if (input.type() == KNumber::SpecialType ||
+ input < -KNumber::One || input > KNumber::One) {
+ _last_number = KNumber("nan");
+ return;
+ }
+ if (input.type() == KNumber::IntegerType) {
+ if (input == KNumber::One) {
+ _last_number = KNumber::Zero;
+ return;
+ }
+ if (input == - KNumber::One) {
+ _last_number = KNumber(200);
+ return;
+ }
+ if (input == KNumber::Zero) {
+ _last_number = KNumber(100);
+ return;
+ }
+ }
+ CALCAMNT tmp_num = static_cast<double>(input);
+ _last_number = Rad2Gra(KNumber(double(ACOS(tmp_num))));
+}
+
+void CalcEngine::ArcSinDeg(KNumber input)
+{
+ if (input.type() == KNumber::SpecialType ||
+ input < -KNumber::One || input > KNumber::One) {
+ _last_number = KNumber("nan");
+ return;
+ }
+ if (input.type() == KNumber::IntegerType) {
+ if (input == KNumber::One) {
+ _last_number = KNumber(90);
+ return;
+ }
+ if (input == - KNumber::One) {
+ _last_number = KNumber(-90);
+ return;
+ }
+ if (input == KNumber::Zero) {
+ _last_number = KNumber(0);
+ return;
+ }
+ }
+ CALCAMNT tmp_num = static_cast<double>(input);
+ _last_number = Rad2Deg(KNumber(double(ASIN(tmp_num))));
+}
+
+void CalcEngine::ArcSinRad(KNumber input)
+{
+ if (input.type() == KNumber::SpecialType ||
+ input < -KNumber::One || input > KNumber::One) {
+ _last_number = KNumber("nan");
+ return;
+ }
+ CALCAMNT tmp_num = static_cast<double>(input);
+ _last_number = KNumber(double(ASIN(tmp_num)));
+}
+
+void CalcEngine::ArcSinGrad(KNumber input)
+{
+ if (input.type() == KNumber::SpecialType ||
+ input < -KNumber::One || input > KNumber::One) {
+ _last_number = KNumber("nan");
+ return;
+ }
+ if (input.type() == KNumber::IntegerType) {
+ if (input == KNumber::One) {
+ _last_number = KNumber(100);
+ return;
+ }
+ if (input == - KNumber::One) {
+ _last_number = KNumber(-100);
+ return;
+ }
+ if (input == KNumber::Zero) {
+ _last_number = KNumber(0);
+ return;
+ }
+ }
+ CALCAMNT tmp_num = static_cast<double>(input);
+ _last_number = Rad2Gra(KNumber(double(ASIN(tmp_num))));
+}
+
+void CalcEngine::ArcTangensDeg(KNumber input)
+{
+ if (input.type() == KNumber::SpecialType) {
+ if (input == KNumber("nan")) _last_number = KNumber("nan");
+ if (input == KNumber("inf")) _last_number = KNumber(90);
+ if (input == KNumber("-inf")) _last_number = KNumber(-90);
+ return;
+ }
+
+ CALCAMNT tmp_num = static_cast<double>(input);
+ _last_number = Rad2Deg(KNumber(double(ATAN(tmp_num))));
+}
+
+void CalcEngine::ArcTangensRad(KNumber input)
+{
+ if (input.type() == KNumber::SpecialType) {
+ if (input == KNumber("nan")) _last_number = KNumber("nan");
+ if (input == KNumber("inf"))
+ _last_number = KNumber::Pi/KNumber(2);
+ if (input == KNumber("-inf"))
+ _last_number = -KNumber::Pi/KNumber(2);
+ return;
+ }
+
+ CALCAMNT tmp_num = static_cast<double>(input);
+ _last_number = KNumber(double(ATAN(tmp_num)));
+}
+
+void CalcEngine::ArcTangensGrad(KNumber input)
+{
+ if (input.type() == KNumber::SpecialType) {
+ if (input == KNumber("nan")) _last_number = KNumber("nan");
+ if (input == KNumber("inf")) _last_number = KNumber(100);
+ if (input == KNumber("-inf")) _last_number = KNumber(-100);
+ return;
+ }
+
+ CALCAMNT tmp_num = static_cast<double>(input);
+ _last_number = Rad2Gra(KNumber(double(ATAN(tmp_num))));
+}
+
+void CalcEngine::AreaCosHyp(KNumber input)
+{
+ if (input.type() == KNumber::SpecialType) {
+ if (input == KNumber("nan")) _last_number = KNumber("nan");
+ if (input == KNumber("inf")) _last_number = KNumber("inf");
+ if (input == KNumber("-inf")) _last_number = KNumber("nan");
+ return;
+ }
+
+ if (input < KNumber::One) {
+ _last_number = KNumber("nan");
+ return;
+ }
+ if (input == KNumber::One) {
+ _last_number = KNumber::Zero;
+ return;
+ }
+ CALCAMNT tmp_num = static_cast<double>(input);
+ _last_number = KNumber(double(ACOSH(tmp_num)));
+}
+
+void CalcEngine::AreaSinHyp(KNumber input)
+{
+ if (input.type() == KNumber::SpecialType) {
+ if (input == KNumber("nan")) _last_number = KNumber("nan");
+ if (input == KNumber("inf")) _last_number = KNumber("inf");
+ if (input == KNumber("-inf")) _last_number = KNumber("-inf");
+ return;
+ }
+
+ if (input == KNumber::Zero) {
+ _last_number = KNumber::Zero;
+ return;
+ }
+ CALCAMNT tmp_num = static_cast<double>(input);
+ _last_number = KNumber(double(ASINH(tmp_num)));
+}
+
+void CalcEngine::AreaTangensHyp(KNumber input)
+{
+ if (input.type() == KNumber::SpecialType) {
+ _last_number = KNumber("nan");
+ return;
+ }
+
+ if (input < -KNumber::One || input > KNumber::One) {
+ _last_number = KNumber("nan");
+ return;
+ }
+ if (input == KNumber::One) {
+ _last_number = KNumber("inf");
+ return;
+ }
+ if (input == - KNumber::One) {
+ _last_number = KNumber("-inf");
+ return;
+ }
+ CALCAMNT tmp_num = static_cast<double>(input);
+ _last_number = KNumber(double(ATANH(tmp_num)));
+}
+
+void CalcEngine::Complement(KNumber input)
+{
+ if (input.type() != KNumber::IntegerType)
+ {
+ _last_number = KNumber("nan");
+ return;
+ }
+ _last_number = - input - KNumber::One;
+}
+
+
+
+// move a number into the interval [0,360) by adding multiples of 360
+static KNumber const moveIntoDegInterval(KNumber const &num)
+{
+ KNumber tmp_num = num - (num/KNumber(360)).integerPart() * KNumber(360);
+ if(tmp_num < KNumber::Zero)
+ return tmp_num + KNumber(360);
+ return tmp_num;
+}
+
+// move a number into the interval [0,400) by adding multiples of 400
+static KNumber const moveIntoGradInterval(KNumber const &num)
+{
+ KNumber tmp_num = num - (num/KNumber(400)).integerPart() * KNumber(400);
+ if(tmp_num < KNumber::Zero)
+ return tmp_num + KNumber(400);
+ return tmp_num;
+}
+
+
+void CalcEngine::CosDeg(KNumber input)
+{
+ if (input.type() == KNumber::SpecialType) {
+ _last_number = KNumber("nan");
+ return;
+ }
+ KNumber trunc_input = moveIntoDegInterval(input);
+ if (trunc_input.type() == KNumber::IntegerType) {
+ KNumber mult = trunc_input/KNumber(90);
+ if (mult.type() == KNumber::IntegerType) {
+ if (mult == KNumber::Zero)
+ _last_number = 1;
+ else if (mult == KNumber(1))
+ _last_number = 0;
+ else if (mult == KNumber(2))
+ _last_number = -1;
+ else if (mult == KNumber(3))
+ _last_number = 0;
+ else qDebug("Something wrong in CalcEngine::CosDeg\n");
+ return;
+ }
+ }
+ trunc_input = Deg2Rad(trunc_input);
+
+ CALCAMNT tmp_num = static_cast<double>(trunc_input);
+ _last_number = KNumber(double(COS(tmp_num)));
+}
+
+void CalcEngine::CosRad(KNumber input)
+{
+ if (input.type() == KNumber::SpecialType) {
+ _last_number = KNumber("nan");
+ return;
+ }
+ CALCAMNT tmp_num = static_cast<double>(input);
+ _last_number = KNumber(double(COS(tmp_num)));
+}
+
+void CalcEngine::CosGrad(KNumber input)
+{
+ if (input.type() == KNumber::SpecialType) {
+ _last_number = KNumber("nan");
+ return;
+ }
+ KNumber trunc_input = moveIntoGradInterval(input);
+ if (trunc_input.type() == KNumber::IntegerType) {
+ KNumber mult = trunc_input/KNumber(100);
+ if (mult.type() == KNumber::IntegerType) {
+ if (mult == KNumber::Zero)
+ _last_number = 1;
+ else if (mult == KNumber(1))
+ _last_number = 0;
+ else if (mult == KNumber(2))
+ _last_number = -1;
+ else if (mult == KNumber(3))
+ _last_number = 0;
+ else qDebug("Something wrong in CalcEngine::CosGrad\n");
+ return;
+ }
+ }
+ trunc_input = Gra2Rad(trunc_input);
+
+ CALCAMNT tmp_num = static_cast<double>(trunc_input);
+ _last_number = KNumber(double(COS(tmp_num)));
+}
+
+void CalcEngine::CosHyp(KNumber input)
+{
+ if (input.type() == KNumber::SpecialType) {
+ if (input == KNumber("nan")) _last_number = KNumber("nan");
+ if (input == KNumber("inf")) _last_number = KNumber("inf");
+ if (input == KNumber("-inf")) _last_number = KNumber("inf");
+ return;
+ }
+
+ CALCAMNT tmp_num = static_cast<double>(input);
+ _last_number = KNumber(double(COSH(tmp_num)));
+}
+
+void CalcEngine::Cube(KNumber input)
+{
+ _last_number = input*input*input;
+}
+
+void CalcEngine::CubeRoot(KNumber input)
+{
+ _last_number = input.cbrt();
+}
+
+void CalcEngine::Exp(KNumber input)
+{
+ if (input.type() == KNumber::SpecialType) {
+ if (input == KNumber("nan")) _last_number = KNumber("nan");
+ if (input == KNumber("inf")) _last_number = KNumber("inf");
+ if (input == KNumber("-inf")) _last_number = KNumber::Zero;
+ return;
+ }
+ CALCAMNT tmp_num = static_cast<double>(input);
+ _last_number = KNumber(double(EXP(tmp_num)));
+}
+
+void CalcEngine::Exp10(KNumber input)
+{
+ if (input.type() == KNumber::SpecialType) {
+ if (input == KNumber("nan")) _last_number = KNumber("nan");
+ if (input == KNumber("inf")) _last_number = KNumber("inf");
+ if (input == KNumber("-inf")) _last_number = KNumber::Zero;
+ return;
+ }
+ _last_number = KNumber(10).power(input);
+}
+
+
+static KNumber _factorial(KNumber input)
+{
+ KNumber tmp_amount = input;
+
+ // don't do recursive factorial,
+ // because large numbers lead to
+ // stack overflows
+ while (tmp_amount > KNumber::One)
+ {
+ tmp_amount -= KNumber::One;
+
+ input = tmp_amount * input;
+
+ }
+
+ if (tmp_amount < KNumber::One)
+ return KNumber::One;
+ return input;
+}
+
+
+void CalcEngine::Factorial(KNumber input)
+{
+ if (input == KNumber("inf")) return;
+ if (input < KNumber::Zero || input.type() == KNumber::SpecialType)
+ {
+ _error = true;
+ _last_number = KNumber("nan");
+ return;
+ }
+ KNumber tmp_amount = input.integerPart();
+
+ _last_number = _factorial(tmp_amount);
+}
+
+void CalcEngine::InvertSign(KNumber input)
+{
+ _last_number = -input;
+}
+
+void CalcEngine::Ln(KNumber input)
+{
+ if (input.type() == KNumber::SpecialType) {
+ if (input == KNumber("nan")) _last_number = KNumber("nan");
+ if (input == KNumber("inf")) _last_number = KNumber("inf");
+ if (input == KNumber("-inf")) _last_number = KNumber("nan");
+ return;
+ }
+ if (input < KNumber::Zero)
+ _last_number = KNumber("nan");
+ else if (input == KNumber::Zero)
+ _last_number = KNumber("-inf");
+ else if (input == KNumber::One)
+ _last_number = 0;
+ else {
+ CALCAMNT tmp_num = static_cast<double>(input);
+ _last_number = KNumber(double(LN(tmp_num)));
+ }
+}
+
+void CalcEngine::Log10(KNumber input)
+{
+ if (input.type() == KNumber::SpecialType) {
+ if (input == KNumber("nan")) _last_number = KNumber("nan");
+ if (input == KNumber("inf")) _last_number = KNumber("inf");
+ if (input == KNumber("-inf")) _last_number = KNumber("nan");
+ return;
+ }
+ if (input < KNumber::Zero)
+ _last_number = KNumber("nan");
+ else if (input == KNumber::Zero)
+ _last_number = KNumber("-inf");
+ else if (input == KNumber::One)
+ _last_number = 0;
+ else {
+ CALCAMNT tmp_num = static_cast<double>(input);
+ _last_number = KNumber(double(LOG_TEN(tmp_num)));
+ }
+}
+
+void CalcEngine::ParenClose(KNumber input)
+{
+ // evaluate stack until corresponding opening bracket
+ while (!_stack.isEmpty())
+ {
+ _node tmp_node = _stack.pop();
+ if (tmp_node.operation == FUNC_BRACKET)
+ break;
+ input = evalOperation(tmp_node.number, tmp_node.operation,
+ input);
+ }
+ _last_number = input;
+ return;
+}
+
+void CalcEngine::ParenOpen(KNumber input)
+{
+ enterOperation(input, FUNC_BRACKET);
+}
+
+void CalcEngine::Reciprocal(KNumber input)
+{
+ _last_number = KNumber::One/input;
+}
+
+
+void CalcEngine::SinDeg(KNumber input)
+{
+ if (input.type() == KNumber::SpecialType) {
+ _last_number = KNumber("nan");
+ return;
+ }
+
+ KNumber trunc_input = moveIntoDegInterval(input);
+ if (trunc_input.type() == KNumber::IntegerType) {
+ KNumber mult = trunc_input/KNumber(90);
+ if (mult.type() == KNumber::IntegerType) {
+ if (mult == KNumber::Zero)
+ _last_number = 0;
+ else if (mult == KNumber(1))
+ _last_number = 1;
+ else if (mult == KNumber(2))
+ _last_number = 0;
+ else if (mult == KNumber(3))
+ _last_number = -1;
+ else qDebug("Something wrong in CalcEngine::SinDeg\n");
+ return;
+ }
+ }
+ trunc_input = Deg2Rad(trunc_input);
+
+ CALCAMNT tmp_num = static_cast<double>(trunc_input);
+ _last_number = KNumber(double(SIN(tmp_num)));
+}
+
+void CalcEngine::SinRad(KNumber input)
+{
+ if (input.type() == KNumber::SpecialType) {
+ _last_number = KNumber("nan");
+ return;
+ }
+
+ CALCAMNT tmp_num = static_cast<double>(input);
+ _last_number = KNumber(double(SIN(tmp_num)));
+}
+
+void CalcEngine::SinGrad(KNumber input)
+{
+ if (input.type() == KNumber::SpecialType) {
+ _last_number = KNumber("nan");
+ return;
+ }
+
+ KNumber trunc_input = moveIntoGradInterval(input);
+ if (trunc_input.type() == KNumber::IntegerType) {
+ KNumber mult = trunc_input/KNumber(100);
+ if (mult.type() == KNumber::IntegerType) {
+ if (mult == KNumber::Zero)
+ _last_number = 0;
+ else if (mult == KNumber(1))
+ _last_number = 1;
+ else if (mult == KNumber(2))
+ _last_number = 0;
+ else if (mult == KNumber(3))
+ _last_number = -1;
+ else qDebug("Something wrong in CalcEngine::SinGrad\n");
+ return;
+ }
+ }
+
+ trunc_input = Gra2Rad(trunc_input);
+
+ CALCAMNT tmp_num = static_cast<double>(trunc_input);
+ _last_number = KNumber(double(SIN(tmp_num)));
+}
+
+void CalcEngine::SinHyp(KNumber input)
+{
+ if (input.type() == KNumber::SpecialType) {
+ if (input == KNumber("nan")) _last_number = KNumber("nan");
+ if (input == KNumber("inf")) _last_number = KNumber("inf");
+ if (input == KNumber("-inf")) _last_number = KNumber("-inf");
+ return;
+ }
+
+ CALCAMNT tmp_num = static_cast<double>(input);
+ _last_number = KNumber(double(SINH(tmp_num)));
+}
+
+void CalcEngine::Square(KNumber input)
+{
+ _last_number = input*input;
+}
+
+void CalcEngine::SquareRoot(KNumber input)
+{
+ _last_number = input.sqrt();
+}
+
+void CalcEngine::StatClearAll(KNumber input)
+{
+ UNUSED(input);
+ stats.clearAll();
+}
+
+void CalcEngine::StatCount(KNumber input)
+{
+ UNUSED(input);
+ _last_number = KNumber(stats.count());
+}
+
+void CalcEngine::StatDataNew(KNumber input)
+{
+ stats.enterData(input);
+ _last_number = KNumber(stats.count());
+}
+
+void CalcEngine::StatDataDel(KNumber input)
+{
+ UNUSED(input);
+ stats.clearLast();
+ _last_number = KNumber::Zero;
+}
+
+void CalcEngine::StatMean(KNumber input)
+{
+ UNUSED(input);
+ _last_number = stats.mean();
+
+ _error = stats.error();
+}
+
+void CalcEngine::StatMedian(KNumber input)
+{
+ UNUSED(input);
+ _last_number = stats.median();
+
+ _error = stats.error();
+}
+
+void CalcEngine::StatStdDeviation(KNumber input)
+{
+ UNUSED(input);
+ _last_number = stats.std();
+
+ _error = stats.error();
+}
+
+void CalcEngine::StatStdSample(KNumber input)
+{
+ UNUSED(input);
+ _last_number = stats.sample_std();
+
+ _error = stats.error();
+}
+
+void CalcEngine::StatSum(KNumber input)
+{
+ UNUSED(input);
+ _last_number = stats.sum();
+}
+
+void CalcEngine::StatSumSquares(KNumber input)
+{
+ UNUSED(input);
+ _last_number = stats.sum_of_squares();
+
+ _error = stats.error();
+}
+
+void CalcEngine::TangensDeg(KNumber input)
+{
+ if (input.type() == KNumber::SpecialType) {
+ _last_number = KNumber("nan");
+ return;
+ }
+
+ SinDeg(input);
+ KNumber arg1 = _last_number;
+ CosDeg(input);
+ KNumber arg2 = _last_number;
+ _last_number = arg1 / arg2;
+}
+
+void CalcEngine::TangensRad(KNumber input)
+{
+ if (input.type() == KNumber::SpecialType) {
+ _last_number = KNumber("nan");
+ return;
+ }
+
+ SinRad(input);
+ KNumber arg1 = _last_number;
+ CosRad(input);
+ KNumber arg2 = _last_number;
+ _last_number = arg1 / arg2;
+}
+
+void CalcEngine::TangensGrad(KNumber input)
+{
+ if (input.type() == KNumber::SpecialType) {
+ _last_number = KNumber("nan");
+ return;
+ }
+
+ SinGrad(input);
+ KNumber arg1 = _last_number;
+ CosGrad(input);
+ KNumber arg2 = _last_number;
+ _last_number = arg1 / arg2;
+}
+
+void CalcEngine::TangensHyp(KNumber input)
+{
+ if (input.type() == KNumber::SpecialType) {
+ if (input == KNumber("nan")) _last_number = KNumber("nan");
+ if (input == KNumber("inf")) _last_number = KNumber::One;
+ if (input == KNumber("-inf")) _last_number = KNumber::MinusOne;
+ return;
+ }
+
+ CALCAMNT tmp_num = static_cast<double>(input);
+ _last_number = KNumber(double(TANH(tmp_num)));
+}
+
+KNumber CalcEngine::evalOperation(KNumber arg1, Operation operation,
+ KNumber arg2)
+{
+ if (!_percent_mode || Operator[operation].prcnt_ptr == NULL)
+ {
+ return (Operator[operation].arith_ptr)(arg1, arg2);
+ } else {
+ _percent_mode = false;
+ return (Operator[operation].prcnt_ptr)(arg1, arg2);
+ }
+}
+
+void CalcEngine::enterOperation(KNumber number, Operation func)
+{
+ _node tmp_node;
+
+ if (func == FUNC_BRACKET)
+ {
+ tmp_node.number = 0;
+ tmp_node.operation = FUNC_BRACKET;
+
+ _stack.push(tmp_node);
+
+ return;
+ }
+
+ if (func == FUNC_PERCENT)
+ {
+ _percent_mode = true;
+ }
+
+ tmp_node.number = number;
+ tmp_node.operation = func;
+
+ _stack.push(tmp_node);
+
+ evalStack();
+}
+
+bool CalcEngine::evalStack(void)
+{
+ // this should never happen
+ if (_stack.isEmpty()) KMessageBox::error(0L, i18n("Stack processing error - empty stack"));
+
+ _node tmp_node = _stack.pop();
+
+ while (! _stack.isEmpty())
+ {
+ _node tmp_node2 = _stack.pop();
+ if (Operator[tmp_node.operation].precedence <=
+ Operator[tmp_node2.operation].precedence)
+ {
+ if (tmp_node2.operation == FUNC_BRACKET) continue;
+ KNumber tmp_result =
+ evalOperation(tmp_node2.number, tmp_node2.operation,
+ tmp_node.number);
+ tmp_node.number = tmp_result;
+ }
+ else
+ {
+ _stack.push(tmp_node2);
+ break;
+ }
+
+ }
+
+ if(tmp_node.operation != FUNC_EQUAL && tmp_node.operation != FUNC_PERCENT)
+ _stack.push(tmp_node);
+
+ _last_number = tmp_node.number;
+ return true;
+}
+
+void CalcEngine::Reset()
+{
+ _error = false;
+ _last_number = KNumber::Zero;
+
+ _stack.clear();
+}
+
+