diff --git a/src/CalcManager/CEngine/Rational.cpp b/src/CalcManager/CEngine/Rational.cpp index 20bf990..22a972a 100644 --- a/src/CalcManager/CEngine/Rational.cpp +++ b/src/CalcManager/CEngine/Rational.cpp @@ -2,7 +2,6 @@ #include "pch.h" #include "Header Files/Rational.h" -#include "Header Files/scimath.h" using namespace std; @@ -50,12 +49,12 @@ namespace CalcEngine destroyrat(pr); } - Rational::Rational(uint64_t ui, int32_t precision) + Rational::Rational(uint64_t ui) { uint32_t hi = HIDWORD(ui); uint32_t lo = LODWORD(ui); - Rational temp = Rational{ hi }.Lsh(32, precision).Or(lo, precision); + Rational temp = (Rational{ hi } << 32) | lo; m_p = Number{ temp.P() }; m_q = Number{ temp.Q() }; @@ -86,19 +85,19 @@ namespace CalcEngine return m_q; } - Rational Rational::Negate() const + Rational Rational::operator-() const { - return Rational{ Number{ -1 * m_p.Sign(), m_p.Exp(), m_p.Mantissa() }, m_q}; + return Rational{ Number{ -1 * m_p.Sign(), m_p.Exp(), m_p.Mantissa() }, m_q }; } - Rational Rational::Add(Rational const& rhs, int32_t precision) const + Rational& Rational::operator+=(Rational const& rhs) { PRAT lhsRat = this->ToPRAT(); PRAT rhsRat = rhs.ToPRAT(); try { - addrat(&lhsRat, rhsRat, precision); + addrat(&lhsRat, rhsRat, RATIONAL_PRECISION); destroyrat(rhsRat); } catch (DWORD error) @@ -108,20 +107,20 @@ namespace CalcEngine throw(error); } - Rational result = Rational{ lhsRat }; + *this = Rational{ lhsRat }; destroyrat(lhsRat); - return result; + return *this; } - Rational Rational::Sub(Rational const& rhs, int32_t precision) const + Rational& Rational::operator-=(Rational const& rhs) { PRAT lhsRat = this->ToPRAT(); PRAT rhsRat = rhs.ToPRAT(); try { - subrat(&lhsRat, rhsRat, precision); + subrat(&lhsRat, rhsRat, RATIONAL_PRECISION); destroyrat(rhsRat); } catch (DWORD error) @@ -131,20 +130,20 @@ namespace CalcEngine throw(error); } - Rational result = Rational{ lhsRat }; + *this = Rational{ lhsRat }; destroyrat(lhsRat); - return result; + return *this; } - Rational Rational::Mul(Rational const& rhs, int32_t precision) const + Rational& Rational::operator*=(Rational const& rhs) { PRAT lhsRat = this->ToPRAT(); PRAT rhsRat = rhs.ToPRAT(); try { - mulrat(&lhsRat, rhsRat, precision); + mulrat(&lhsRat, rhsRat, RATIONAL_PRECISION); destroyrat(rhsRat); } catch (DWORD error) @@ -154,20 +153,20 @@ namespace CalcEngine throw(error); } - Rational result = Rational{ lhsRat }; + *this = Rational{ lhsRat }; destroyrat(lhsRat); - return result; + return *this; } - Rational Rational::Div(Rational const& rhs, int32_t precision) const + Rational& Rational::operator/=(Rational const& rhs) { PRAT lhsRat = this->ToPRAT(); PRAT rhsRat = rhs.ToPRAT(); try { - divrat(&lhsRat, rhsRat, precision); + divrat(&lhsRat, rhsRat, RATIONAL_PRECISION); destroyrat(rhsRat); } catch (DWORD error) @@ -177,13 +176,13 @@ namespace CalcEngine throw(error); } - Rational result = Rational{ lhsRat }; + *this = Rational{ lhsRat }; destroyrat(lhsRat); - return result; + return *this; } - Rational Rational::Mod(Rational const& rhs) const + Rational& Rational::operator%=(Rational const& rhs) { PRAT lhsRat = this->ToPRAT(); PRAT rhsRat = rhs.ToPRAT(); @@ -200,20 +199,20 @@ namespace CalcEngine throw(error); } - Rational result = Rational{ lhsRat }; + *this = Rational{ lhsRat }; destroyrat(lhsRat); - return result; + return *this; } - Rational Rational::Lsh(Rational const& rhs, int32_t precision) const + Rational& Rational::operator<<=(Rational const& rhs) { PRAT lhsRat = this->ToPRAT(); PRAT rhsRat = rhs.ToPRAT(); try { - lshrat(&lhsRat, rhsRat, RATIONAL_BASE, precision); + lshrat(&lhsRat, rhsRat, RATIONAL_BASE, RATIONAL_PRECISION); destroyrat(rhsRat); } catch (DWORD error) @@ -223,20 +222,20 @@ namespace CalcEngine throw(error); } - Rational result = Rational{ lhsRat }; + *this = Rational{ lhsRat }; destroyrat(lhsRat); - return result; + return *this; } - Rational Rational::Rsh(Rational const& rhs, int32_t precision) const + Rational& Rational::operator>>=(Rational const& rhs) { PRAT lhsRat = this->ToPRAT(); PRAT rhsRat = rhs.ToPRAT(); try { - rshrat(&lhsRat, rhsRat, RATIONAL_BASE, precision); + rshrat(&lhsRat, rhsRat, RATIONAL_BASE, RATIONAL_PRECISION); destroyrat(rhsRat); } catch (DWORD error) @@ -246,25 +245,20 @@ namespace CalcEngine throw(error); } - Rational result = Rational{ lhsRat }; + *this = Rational{ lhsRat }; destroyrat(lhsRat); - return result; + return *this; } - Rational Rational::Not(Rational const& chopNum, int32_t precision) const - { - return this->Xor(chopNum, precision); - } - - Rational Rational::And(Rational const& rhs, int32_t precision) const + Rational& Rational::operator&=(Rational const& rhs) { PRAT lhsRat = this->ToPRAT(); PRAT rhsRat = rhs.ToPRAT(); try { - andrat(&lhsRat, rhsRat, RATIONAL_BASE, precision); + andrat(&lhsRat, rhsRat, RATIONAL_BASE, RATIONAL_PRECISION); destroyrat(rhsRat); } catch (DWORD error) @@ -274,19 +268,19 @@ namespace CalcEngine throw(error); } - Rational result = Rational{ lhsRat }; + *this = Rational{ lhsRat }; destroyrat(lhsRat); - return result; + return *this; } - Rational Rational::Or(Rational const& rhs, int32_t precision) const + Rational& Rational::operator|=(Rational const& rhs) { PRAT lhsRat = this->ToPRAT(); PRAT rhsRat = rhs.ToPRAT(); try { - orrat(&lhsRat, rhsRat, RATIONAL_BASE, precision); + orrat(&lhsRat, rhsRat, RATIONAL_BASE, RATIONAL_PRECISION); destroyrat(rhsRat); } catch (DWORD error) @@ -296,19 +290,19 @@ namespace CalcEngine throw(error); } - Rational result = Rational{ lhsRat }; + *this = Rational{ lhsRat }; destroyrat(lhsRat); - return result; + return *this; } - Rational Rational::Xor(Rational const& rhs, int32_t precision) const + Rational& Rational::operator^=(Rational const& rhs) { PRAT lhsRat = this->ToPRAT(); PRAT rhsRat = rhs.ToPRAT(); try { - xorrat(&lhsRat, rhsRat, RATIONAL_BASE, precision); + xorrat(&lhsRat, rhsRat, RATIONAL_BASE, RATIONAL_PRECISION); destroyrat(rhsRat); } catch (DWORD error) @@ -318,107 +312,136 @@ namespace CalcEngine throw(error); } - Rational result = Rational{ lhsRat }; + *this = Rational{ lhsRat }; destroyrat(lhsRat); - return result; + return *this; } - bool Rational::IsZero() const + Rational operator+(Rational lhs, Rational const& rhs) { - return this->P().IsZero(); + lhs += rhs; + return lhs; } - bool Rational::IsLess(Rational const& r, int32_t precision) const + Rational operator-(Rational lhs, Rational const& rhs) { - PRAT thisRat = this->ToPRAT(); - PRAT rRat = r.ToPRAT(); + lhs -= rhs; + return lhs; + } + + Rational operator*(Rational lhs, Rational const& rhs) + { + lhs *= rhs; + return lhs; + } + + Rational operator/(Rational lhs, Rational const& rhs) + { + lhs /= rhs; + return lhs; + } + + Rational operator%(Rational lhs, Rational const& rhs) + { + lhs %= rhs; + return lhs; + } + + Rational operator<<(Rational lhs, Rational const& rhs) + { + lhs <<= rhs; + return lhs; + } + + Rational operator>>(Rational lhs, Rational const& rhs) + { + lhs >>= rhs; + return lhs; + } + + Rational operator&(Rational lhs, Rational const& rhs) + { + lhs &= rhs; + return lhs; + } + + Rational operator|(Rational lhs, Rational const& rhs) + { + lhs |= rhs; + return lhs; + } + + Rational operator^(Rational lhs, Rational const& rhs) + { + lhs ^= rhs; + return lhs; + } + + bool operator==(Rational const& lhs, Rational const& rhs) + { + PRAT lhsRat = lhs.ToPRAT(); + PRAT rhsRat = rhs.ToPRAT(); bool result = false; try { - result = rat_lt(thisRat, rRat, precision); + result = rat_equ(lhsRat, rhsRat, RATIONAL_PRECISION); } catch (DWORD error) { - destroyrat(thisRat); - destroyrat(rRat); + destroyrat(lhsRat); + destroyrat(rhsRat); throw(error); } - destroyrat(thisRat); - destroyrat(rRat); + destroyrat(lhsRat); + destroyrat(rhsRat); return result; } - bool Rational::IsLessEq(Rational const& r, int32_t precision) const + bool operator!=(Rational const& lhs, Rational const& rhs) { - PRAT thisRat = this->ToPRAT(); - PRAT rRat = r.ToPRAT(); + return !(lhs == rhs); + } + + bool operator<(Rational const& lhs, Rational const& rhs) + { + PRAT lhsRat = lhs.ToPRAT(); + PRAT rhsRat = rhs.ToPRAT(); bool result = false; try { - result = rat_le(thisRat, rRat, precision); + result = rat_lt(lhsRat, rhsRat, RATIONAL_PRECISION); } catch (DWORD error) { - destroyrat(thisRat); - destroyrat(rRat); + destroyrat(lhsRat); + destroyrat(rhsRat); throw(error); } - destroyrat(thisRat); - destroyrat(rRat); + destroyrat(lhsRat); + destroyrat(rhsRat); return result; } - bool Rational::IsGreaterEq(Rational const& r, int32_t precision) const + bool operator>(Rational const& lhs, Rational const& rhs) { - PRAT thisRat = this->ToPRAT(); - PRAT rRat = r.ToPRAT(); - - bool result = false; - try - { - result = rat_ge(thisRat, rRat, precision); - } - catch (DWORD error) - { - destroyrat(thisRat); - destroyrat(rRat); - throw(error); - } - - destroyrat(thisRat); - destroyrat(rRat); - - return result; + return rhs < lhs; } - bool Rational::IsEq(Rational const& r, int32_t precision) const + bool operator<=(Rational const& lhs, Rational const& rhs) { - PRAT thisRat = this->ToPRAT(); - PRAT rRat = r.ToPRAT(); + return !(lhs > rhs); + } - bool result = false; - try - { - result = rat_equ(thisRat, rRat, precision); - } - catch (DWORD error) - { - destroyrat(thisRat); - destroyrat(rRat); - throw(error); - } - - destroyrat(thisRat); - destroyrat(rRat); - - return result; + bool operator>=(Rational const& lhs, Rational const& rhs) + { + return !(lhs < rhs); } wstring Rational::ToString(uint32_t radix, NUMOBJ_FMT fmt, int32_t precision) const @@ -441,13 +464,13 @@ namespace CalcEngine return result; } - uint64_t Rational::ToUInt64_t(int32_t precision) const + uint64_t Rational::ToUInt64_t() const { PRAT rat = this->ToPRAT(); uint64_t result; try { - result = rattoUlonglong(rat, RATIONAL_BASE, precision); + result = rattoUlonglong(rat, RATIONAL_BASE, RATIONAL_PRECISION); } catch (DWORD error) { diff --git a/src/CalcManager/CEngine/calc.cpp b/src/CalcManager/CEngine/calc.cpp index e0f7b0e..eca94ef 100644 --- a/src/CalcManager/CEngine/calc.cpp +++ b/src/CalcManager/CEngine/calc.cpp @@ -95,7 +95,7 @@ CCalcEngine::CCalcEngine(bool fPrecedence, bool fIntegerMode, CalculationManager m_dwWordBitWidth = DwWordBitWidthFromeNumWidth(m_numwidth); - m_maxTrigonometricNum = RationalMath::Pow(10, 100, m_precision); + m_maxTrigonometricNum = RationalMath::Pow(10, 100); SetRadixTypeAndNumWidth(DEC_RADIX, m_numwidth); SettingsChanged(); @@ -117,8 +117,8 @@ void CCalcEngine::InitChopNumbers() assert(m_chopNumbers.size() == m_maxDecimalValueStrings.size()); for (size_t i = 0; i < m_chopNumbers.size(); i++) { - auto maxVal = m_chopNumbers[i].Div(2, m_precision); - maxVal = RationalMath::Integer(maxVal, m_precision); + auto maxVal = m_chopNumbers[i] / 2; + maxVal = RationalMath::Integer(maxVal); m_maxDecimalValueStrings[i] = maxVal.ToString(10, FMT_FLOAT, m_precision); } diff --git a/src/CalcManager/CEngine/scicomm.cpp b/src/CalcManager/CEngine/scicomm.cpp index 71ea956..72cfe41 100644 --- a/src/CalcManager/CEngine/scicomm.cpp +++ b/src/CalcManager/CEngine/scicomm.cpp @@ -318,6 +318,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam) { if (IsCurrentTooBigForTrig()) { + m_currentVal = 0; DisplayError(CALC_E_DOMAIN); return; } @@ -382,7 +383,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam) CheckAndAddLastBinOpToHistory(false); } - m_lastVal = Rational{}; + m_lastVal = 0; m_bChangeOp = false; m_precedenceOpCount = m_nTempCom = m_nLastCom = m_nOpCode = m_openParenCount = 0; @@ -563,12 +564,12 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam) m_nPrecOp[m_precedenceOpCount++] = 0; } - m_lastVal = Rational{}; + m_lastVal = 0; if (IsBinOpCode(m_nLastCom)) { // We want 1 + ( to start as 1 + (0. Any number you type replaces 0. But if it is 1 + 3 (, it is // treated as 1 + (3 - m_currentVal = Rational{}; + m_currentVal = 0; } m_nTempCom = 0; m_nOpCode = 0; @@ -691,7 +692,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam) m_HistoryCollector.AddOpndToHistory(m_numberString, m_currentVal); } - m_currentVal = m_currentVal.Negate(); + m_currentVal = -(m_currentVal); DisplayNum(); m_HistoryCollector.AddUnaryOpToHistory(IDC_SIGN, m_bInv, m_angletype); @@ -708,7 +709,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam) else { // Recall immediate memory value. - m_currentVal = Rational{ *m_memoryValue }; + m_currentVal = *m_memoryValue; } CheckAndAddLastBinOpToHistory(); DisplayNum(); @@ -718,7 +719,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam) { /* MPLUS adds m_currentVal to immediate memory and kills the "mem" */ /* indicator if the result is zero. */ - Rational result = m_memoryValue->Add(m_currentVal, m_precision); + Rational result = *m_memoryValue + m_currentVal; m_memoryValue = make_unique(TruncateNumForIntMath(result)); // Memory should follow the current int mode break; @@ -727,14 +728,14 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam) { /* MMINUS subtracts m_currentVal to immediate memory and kills the "mem" */ /* indicator if the result is zero. */ - Rational result = m_memoryValue->Sub(m_currentVal, m_precision); + Rational result = *m_memoryValue - m_currentVal; m_memoryValue = make_unique(TruncateNumForIntMath(result)); break; } case IDC_STORE: case IDC_MCLEAR: - m_memoryValue = make_unique(wParam == IDC_STORE ? TruncateNumForIntMath(m_currentVal) : Rational{}); + m_memoryValue = make_unique(wParam == IDC_STORE ? TruncateNumForIntMath(m_currentVal) : 0); break; case IDC_PI: @@ -1002,13 +1003,7 @@ int CCalcEngine::IdcSetAngleTypeDecMode(int idc) bool CCalcEngine::IsCurrentTooBigForTrig() { - if (m_currentVal.IsGreaterEq(m_maxTrigonometricNum, m_precision)) - { - m_currentVal = Rational{}; - return true; - } - - return false; + return m_currentVal >= m_maxTrigonometricNum; } int CCalcEngine::GetCurrentRadix() @@ -1048,14 +1043,12 @@ wstring CCalcEngine::GetStringForDisplay(Rational const& rat, uint32_t radix) try { - uint64_t w64Bits = tempRat.ToUInt64_t(m_precision); + uint64_t w64Bits = tempRat.ToUInt64_t(); bool fMsb = ((w64Bits >> (m_dwWordBitWidth - 1)) & 1); if ((radix == 10) && fMsb) { // If high bit is set, then get the decimal number in negative 2's compl form. - tempRat = tempRat.Not(m_chopNumbers[m_numwidth], m_precision); - tempRat = tempRat.Add(1, m_precision); - tempRat = tempRat.Negate(); + tempRat = -((tempRat ^ m_chopNumbers[m_numwidth]) + 1); } result = tempRat.ToString(radix, m_nFE, m_precision); diff --git a/src/CalcManager/CEngine/scidisp.cpp b/src/CalcManager/CEngine/scidisp.cpp index 669fcdb..2d0e8f3 100644 --- a/src/CalcManager/CEngine/scidisp.cpp +++ b/src/CalcManager/CEngine/scidisp.cpp @@ -57,19 +57,18 @@ CalcEngine::Rational CCalcEngine::TruncateNumForIntMath(CalcEngine::Rational con } // Truncate to an integer. Do not round here. - auto result = RationalMath::Integer(rat, m_precision); + auto result = RationalMath::Integer(rat); // Can be converting a dec negative number to Hex/Oct/Bin rep. Use 2's complement form // Check the range. - if (result.IsLess(0, m_precision)) + if (result < 0) { // if negative make positive by doing a twos complement - result = result.Negate(); - result = result.Sub(1, m_precision); - result = result.Not(m_chopNumbers[m_numwidth], m_precision); + result = -(result) - 1; + result ^= m_chopNumbers[m_numwidth]; } - result = result.And(m_chopNumbers[m_numwidth], m_precision); + result &= m_chopNumbers[m_numwidth]; return result; } @@ -84,7 +83,7 @@ void CCalcEngine::DisplayNum(void) // called. // if (m_bRecord || - !gldPrevious.value.IsEq(m_currentVal, m_precision) || + gldPrevious.value != m_currentVal || gldPrevious.precision != m_precision || gldPrevious.radix != m_radix || gldPrevious.nFE != (int)m_nFE || diff --git a/src/CalcManager/CEngine/scifunc.cpp b/src/CalcManager/CEngine/scifunc.cpp index d3eb62f..eb513ea 100644 --- a/src/CalcManager/CEngine/scifunc.cpp +++ b/src/CalcManager/CEngine/scifunc.cpp @@ -32,20 +32,18 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r switch (op) { case IDC_CHOP: - result = m_bInv ? Frac(rat, m_precision) : Integer(rat, m_precision); + result = m_bInv ? Frac(rat) : Integer(rat); break; /* Return complement. */ case IDC_COM: if (m_radix == 10 && !m_fIntegerMode) { - result = RationalMath::Integer(rat, m_precision); - result = result.Add(1, m_precision); - result = result.Negate(); + result = -(RationalMath::Integer(rat) + 1); } else { - result = rat.Xor(m_chopNumbers[m_numwidth], m_precision); + result = rat ^ m_chopNumbers[m_numwidth]; } break; @@ -53,14 +51,14 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r case IDC_ROL: if (m_fIntegerMode) { - result = Integer(rat, m_precision); + result = Integer(rat); - uint64_t w64Bits = result.ToUInt64_t(m_precision); + uint64_t w64Bits = result.ToUInt64_t(); uint64_t msb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1; w64Bits <<= 1; // LShift by 1 w64Bits |= msb; // Set the prev Msb as the current Lsb - result = Rational{ w64Bits, m_precision }; + result = w64Bits; } break; @@ -68,14 +66,14 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r case IDC_ROR: if (m_fIntegerMode) { - result = Integer(rat, m_precision); + result = Integer(rat); - uint64_t w64Bits = result.ToUInt64_t(m_precision); + uint64_t w64Bits = result.ToUInt64_t(); uint64_t lsb = ((w64Bits & 0x01) == 1) ? 1 : 0; w64Bits >>= 1; //RShift by 1 w64Bits |= (lsb << (m_dwWordBitWidth - 1)); - result = Rational{ w64Bits, m_precision }; + result = w64Bits; } break; @@ -85,12 +83,11 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r // Otherwise, we evaluate it as "X [op] (X * Y%)" if (m_nOpCode == IDC_MUL || m_nOpCode == IDC_DIV) { - result = rat.Div(100, m_precision); + result = rat / 100; } else { - result = m_lastVal.Div(100, m_precision); - result = rat.Mul(result, m_precision); + result = rat * (m_lastVal / 100); } break; } @@ -98,76 +95,76 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r case IDC_SIN: /* Sine; normal and arc */ if (!m_fIntegerMode) { - result = m_bInv ? ASin(rat, m_angletype, m_precision) : Sin(rat, m_angletype, m_precision); + result = m_bInv ? ASin(rat, m_angletype) : Sin(rat, m_angletype); } break; case IDC_SINH: /* Sine- hyperbolic and archyperbolic */ if (!m_fIntegerMode) { - result = m_bInv ? ASinh(rat, m_precision) : Sinh(rat, m_precision); + result = m_bInv ? ASinh(rat) : Sinh(rat); } break; case IDC_COS: /* Cosine, follows convention of sine function. */ if (!m_fIntegerMode) { - result = m_bInv ? ACos(rat, m_angletype, m_precision) : Cos(rat, m_angletype, m_precision); + result = m_bInv ? ACos(rat, m_angletype) : Cos(rat, m_angletype); } break; case IDC_COSH: /* Cosine hyperbolic, follows convention of sine h function. */ if (!m_fIntegerMode) { - result = m_bInv ? ACosh(rat, m_precision) : Cosh(rat, m_precision); + result = m_bInv ? ACosh(rat) : Cosh(rat); } break; case IDC_TAN: /* Same as sine and cosine. */ if (!m_fIntegerMode) { - result = m_bInv ? ATan(rat, m_angletype, m_precision) : Tan(rat, m_angletype, m_precision); + result = m_bInv ? ATan(rat, m_angletype) : Tan(rat, m_angletype); } break; case IDC_TANH: /* Same as sine h and cosine h. */ if (!m_fIntegerMode) { - result = m_bInv ? ATanh(rat, m_precision) : Tanh(rat, m_precision); + result = m_bInv ? ATanh(rat) : Tanh(rat); } break; case IDC_REC: /* Reciprocal. */ - result = Invert(rat, m_precision); + result = Invert(rat); break; case IDC_SQR: /* Square */ - result = Pow(rat, 2, m_precision); + result = Pow(rat, 2); break; case IDC_SQRT: /* Square Root */ - result = Root(rat, 2, m_precision); + result = Root(rat, 2); break; case IDC_CUBEROOT: case IDC_CUB: /* Cubing and cube root functions. */ - result = IDC_CUBEROOT == op ? Root(rat, 3, m_precision) : Pow(rat, 3, m_precision); + result = IDC_CUBEROOT == op ? Root(rat, 3) : Pow(rat, 3); break; case IDC_LOG: /* Functions for common log. */ - result = Log10(rat, m_precision); + result = Log10(rat); break; case IDC_POW10: - result = Pow(10, rat, m_precision); + result = Pow(10, rat); break; case IDC_LN: /* Functions for natural log. */ - result = m_bInv ? Exp(rat, m_precision) : Log(rat, m_precision); + result = m_bInv ? Exp(rat) : Log(rat); break; case IDC_FAC: /* Calculate factorial. Inverse is ineffective. */ - result = Fact(rat, m_precision); + result = Fact(rat); break; case IDC_DEGREES: @@ -180,31 +177,28 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r { if (!m_fIntegerMode) { - Rational shftRat{ m_bInv ? 100 : 60 }; + auto shftRat{ m_bInv ? 100 : 60 }; - Rational degreeRat = Integer(rat, m_precision); + Rational degreeRat = Integer(rat); - Rational minuteRat = rat.Sub(degreeRat, m_precision); - minuteRat = minuteRat.Mul(shftRat, m_precision); + Rational minuteRat = (rat - degreeRat) * shftRat; Rational secondRat = minuteRat; - minuteRat = Integer(minuteRat, m_precision); + minuteRat = Integer(minuteRat); - secondRat = secondRat.Sub(minuteRat, m_precision); - secondRat = secondRat.Mul(shftRat, m_precision); + secondRat = (secondRat - minuteRat) * shftRat; // // degreeRat == degrees, minuteRat == minutes, secondRat == seconds // - shftRat = Rational{ m_bInv ? 60 : 100 }; - secondRat = secondRat.Div(shftRat, m_precision); + shftRat = m_bInv ? 60 : 100; + secondRat /= shftRat; - minuteRat = minuteRat.Add(secondRat, m_precision); - minuteRat = minuteRat.Div(shftRat, m_precision); + minuteRat = (minuteRat + secondRat) / shftRat; - result = degreeRat.Add(minuteRat, m_precision); + result = degreeRat + minuteRat; } break; } diff --git a/src/CalcManager/CEngine/scimath.cpp b/src/CalcManager/CEngine/scimath.cpp index 15908f6..5062323 100644 --- a/src/CalcManager/CEngine/scimath.cpp +++ b/src/CalcManager/CEngine/scimath.cpp @@ -2,18 +2,17 @@ // Licensed under the MIT License. #include "pch.h" -#include "Header Files/CalcEngine.h" -#include "Ratpack/ratpak.h" +#include "Header Files/scimath.h" using namespace std; using namespace CalcEngine; -Rational RationalMath::Frac(Rational const& rat, int32_t precision) +Rational RationalMath::Frac(Rational const& rat) { PRAT prat = rat.ToPRAT(); try { - fracrat(&prat, RATIONAL_BASE, precision); + fracrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION); } catch (DWORD error) { @@ -27,12 +26,12 @@ Rational RationalMath::Frac(Rational const& rat, int32_t precision) return result; } -Rational RationalMath::Integer(Rational const& rat, int32_t precision) +Rational RationalMath::Integer(Rational const& rat) { PRAT prat = rat.ToPRAT(); try { - intrat(&prat, RATIONAL_BASE, precision); + intrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION); } catch (DWORD error) { @@ -46,14 +45,14 @@ Rational RationalMath::Integer(Rational const& rat, int32_t precision) return result; } -Rational RationalMath::Pow(Rational const& base, Rational const& pow, int32_t precision) +Rational RationalMath::Pow(Rational const& base, Rational const& pow) { PRAT baseRat = base.ToPRAT(); PRAT powRat = pow.ToPRAT(); try { - powrat(&baseRat, powRat, RATIONAL_BASE, precision); + powrat(&baseRat, powRat, RATIONAL_BASE, RATIONAL_PRECISION); destroyrat(powRat); } catch (DWORD error) @@ -69,18 +68,18 @@ Rational RationalMath::Pow(Rational const& base, Rational const& pow, int32_t pr return result; } -Rational RationalMath::Root(Rational const& base, Rational const& root, int32_t precision) +Rational RationalMath::Root(Rational const& base, Rational const& root) { - return Pow(base, Invert(root, precision), precision); + return Pow(base, Invert(root)); } -Rational RationalMath::Fact(Rational const& rat, int32_t precision) +Rational RationalMath::Fact(Rational const& rat) { PRAT prat = rat.ToPRAT(); try { - factrat(&prat, RATIONAL_BASE, precision); + factrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION); } catch (DWORD error) { @@ -94,13 +93,13 @@ Rational RationalMath::Fact(Rational const& rat, int32_t precision) return result; } -Rational RationalMath::Exp(Rational const& rat, int32_t precision) +Rational RationalMath::Exp(Rational const& rat) { PRAT prat = rat.ToPRAT(); try { - exprat(&prat, RATIONAL_BASE, precision); + exprat(&prat, RATIONAL_BASE, RATIONAL_PRECISION); } catch (DWORD error) { @@ -114,13 +113,13 @@ Rational RationalMath::Exp(Rational const& rat, int32_t precision) return result; } -Rational RationalMath::Log(Rational const& rat, int32_t precision) +Rational RationalMath::Log(Rational const& rat) { PRAT prat = rat.ToPRAT(); try { - lograt(&prat, precision); + lograt(&prat, RATIONAL_PRECISION); } catch (DWORD error) { @@ -134,14 +133,14 @@ Rational RationalMath::Log(Rational const& rat, int32_t precision) return result; } -Rational RationalMath::Log10(Rational const& rat, int32_t precision) +Rational RationalMath::Log10(Rational const& rat) { - return Log(rat, precision).Div(Rational{ ln_ten }, precision); + return Log(rat) / Rational{ ln_ten }; } -Rational RationalMath::Invert(Rational const& rat, int32_t precision) +Rational RationalMath::Invert(Rational const& rat) { - return Rational{ 1 }.Div(rat, precision); + return 1 / rat; } Rational RationalMath::Abs(Rational const& rat) @@ -149,13 +148,13 @@ Rational RationalMath::Abs(Rational const& rat) return Rational{ Number{ 1, rat.P().Exp(), rat.P().Mantissa() }, Number{ 1, rat.Q().Exp(), rat.Q().Mantissa() } }; } -Rational RationalMath::Sin(Rational const& rat, ANGLE_TYPE angletype, int32_t precision) +Rational RationalMath::Sin(Rational const& rat, ANGLE_TYPE angletype) { PRAT prat = rat.ToPRAT(); try { - sinanglerat(&prat, angletype, RATIONAL_BASE, precision); + sinanglerat(&prat, angletype, RATIONAL_BASE, RATIONAL_PRECISION); } catch (DWORD error) { @@ -169,13 +168,13 @@ Rational RationalMath::Sin(Rational const& rat, ANGLE_TYPE angletype, int32_t pr return result; } -Rational RationalMath::Cos(Rational const& rat, ANGLE_TYPE angletype, int32_t precision) +Rational RationalMath::Cos(Rational const& rat, ANGLE_TYPE angletype) { PRAT prat = rat.ToPRAT(); try { - cosanglerat(&prat, angletype, RATIONAL_BASE, precision); + cosanglerat(&prat, angletype, RATIONAL_BASE, RATIONAL_PRECISION); } catch (DWORD error) { @@ -189,13 +188,13 @@ Rational RationalMath::Cos(Rational const& rat, ANGLE_TYPE angletype, int32_t pr return result; } -Rational RationalMath::Tan(Rational const& rat, ANGLE_TYPE angletype, int32_t precision) +Rational RationalMath::Tan(Rational const& rat, ANGLE_TYPE angletype) { PRAT prat = rat.ToPRAT(); try { - tananglerat(&prat, angletype, RATIONAL_BASE, precision); + tananglerat(&prat, angletype, RATIONAL_BASE, RATIONAL_PRECISION); } catch (DWORD error) { @@ -209,13 +208,13 @@ Rational RationalMath::Tan(Rational const& rat, ANGLE_TYPE angletype, int32_t pr return result; } -Rational RationalMath::ASin(Rational const& rat, ANGLE_TYPE angletype, int32_t precision) +Rational RationalMath::ASin(Rational const& rat, ANGLE_TYPE angletype) { PRAT prat = rat.ToPRAT(); try { - asinanglerat(&prat, angletype, RATIONAL_BASE, precision); + asinanglerat(&prat, angletype, RATIONAL_BASE, RATIONAL_PRECISION); } catch (DWORD error) { @@ -229,13 +228,13 @@ Rational RationalMath::ASin(Rational const& rat, ANGLE_TYPE angletype, int32_t p return result; } -Rational RationalMath::ACos(Rational const& rat, ANGLE_TYPE angletype, int32_t precision) +Rational RationalMath::ACos(Rational const& rat, ANGLE_TYPE angletype) { PRAT prat = rat.ToPRAT(); try { - acosanglerat(&prat, angletype, RATIONAL_BASE, precision); + acosanglerat(&prat, angletype, RATIONAL_BASE, RATIONAL_PRECISION); } catch (DWORD error) { @@ -249,13 +248,13 @@ Rational RationalMath::ACos(Rational const& rat, ANGLE_TYPE angletype, int32_t p return result; } -Rational RationalMath::ATan(Rational const& rat, ANGLE_TYPE angletype, int32_t precision) +Rational RationalMath::ATan(Rational const& rat, ANGLE_TYPE angletype) { PRAT prat = rat.ToPRAT(); try { - atananglerat(&prat, angletype, RATIONAL_BASE, precision); + atananglerat(&prat, angletype, RATIONAL_BASE, RATIONAL_PRECISION); } catch (DWORD error) { @@ -269,13 +268,13 @@ Rational RationalMath::ATan(Rational const& rat, ANGLE_TYPE angletype, int32_t p return result; } -Rational RationalMath::Sinh(Rational const& rat, int32_t precision) +Rational RationalMath::Sinh(Rational const& rat) { PRAT prat = rat.ToPRAT(); try { - sinhrat(&prat, RATIONAL_BASE, precision); + sinhrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION); } catch (DWORD error) { @@ -289,13 +288,13 @@ Rational RationalMath::Sinh(Rational const& rat, int32_t precision) return result; } -Rational RationalMath::Cosh(Rational const& rat, int32_t precision) +Rational RationalMath::Cosh(Rational const& rat) { PRAT prat = rat.ToPRAT(); try { - coshrat(&prat, RATIONAL_BASE, precision); + coshrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION); } catch (DWORD error) { @@ -309,13 +308,13 @@ Rational RationalMath::Cosh(Rational const& rat, int32_t precision) return result; } -Rational RationalMath::Tanh(Rational const& rat, int32_t precision) +Rational RationalMath::Tanh(Rational const& rat) { PRAT prat = rat.ToPRAT(); try { - tanhrat(&prat, RATIONAL_BASE, precision); + tanhrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION); } catch (DWORD error) { @@ -329,13 +328,13 @@ Rational RationalMath::Tanh(Rational const& rat, int32_t precision) return result; } -Rational RationalMath::ASinh(Rational const& rat, int32_t precision) +Rational RationalMath::ASinh(Rational const& rat) { PRAT prat = rat.ToPRAT(); try { - asinhrat(&prat, RATIONAL_BASE, precision); + asinhrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION); } catch (DWORD error) { @@ -349,13 +348,13 @@ Rational RationalMath::ASinh(Rational const& rat, int32_t precision) return result; } -Rational RationalMath::ACosh(Rational const& rat, int32_t precision) +Rational RationalMath::ACosh(Rational const& rat) { PRAT prat = rat.ToPRAT(); try { - acoshrat(&prat, RATIONAL_BASE, precision); + acoshrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION); } catch (DWORD error) { @@ -369,13 +368,13 @@ Rational RationalMath::ACosh(Rational const& rat, int32_t precision) return result; } -Rational RationalMath::ATanh(Rational const& rat, int32_t precision) +Rational RationalMath::ATanh(Rational const& rat) { PRAT prat = rat.ToPRAT(); try { - atanhrat(&prat, precision); + atanhrat(&prat, RATIONAL_PRECISION); } catch (DWORD error) { diff --git a/src/CalcManager/CEngine/scioper.cpp b/src/CalcManager/CEngine/scioper.cpp index 59dbb57..06fe345 100644 --- a/src/CalcManager/CEngine/scioper.cpp +++ b/src/CalcManager/CEngine/scioper.cpp @@ -11,69 +11,68 @@ using namespace CalcEngine::RationalMath; CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rational const& lhs, CalcEngine::Rational const& rhs) { // Remove any variance in how 0 could be represented in rat e.g. -0, 0/n, etc. - auto result = (!lhs.IsZero() ? lhs : Rational{}); + auto result = (lhs != 0 ? lhs : 0); try { switch (operation) { case IDC_AND: - result = result.And(rhs, m_precision); + result &= rhs; break; case IDC_OR: - result = result.Or(rhs, m_precision); + result |= rhs; break; case IDC_XOR: - result = result.Xor(rhs, m_precision); + result ^= rhs; break; case IDC_RSHF: { - if (m_fIntegerMode && result.IsGreaterEq(Rational{ m_dwWordBitWidth }, m_precision)) // Lsh/Rsh >= than current word size is always 0 + if (m_fIntegerMode && result >= m_dwWordBitWidth) // Lsh/Rsh >= than current word size is always 0 { throw CALC_E_NORESULT; } - uint64_t w64Bits = rhs.ToUInt64_t(m_precision); + uint64_t w64Bits = rhs.ToUInt64_t(); bool fMsb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1; Rational holdVal = result; - result = rhs.Rsh(holdVal, m_precision); + result = rhs >> holdVal; if (fMsb) { - result = Integer(result, m_precision); + result = Integer(result); - auto tempRat = m_chopNumbers[m_numwidth].Rsh(holdVal, m_precision); - tempRat = Integer(tempRat, m_precision); + auto tempRat = m_chopNumbers[m_numwidth] >> holdVal; + tempRat = Integer(tempRat); - tempRat = tempRat.Xor(m_chopNumbers[m_numwidth], m_precision); - result = result.Or(tempRat, m_precision); + result |= tempRat ^ m_chopNumbers[m_numwidth]; } break; } case IDC_LSHF: - if (m_fIntegerMode && result.IsGreaterEq(Rational{ m_dwWordBitWidth }, m_precision)) // Lsh/Rsh >= than current word size is always 0 + if (m_fIntegerMode && result >= m_dwWordBitWidth) // Lsh/Rsh >= than current word size is always 0 { throw CALC_E_NORESULT; } - result = rhs.Lsh(result, m_precision); + result = rhs << result; break; case IDC_ADD: - result = result.Add(rhs, m_precision); + result += rhs; break; case IDC_SUB: - result = rhs.Sub(result, m_precision); + result = rhs - result; break; case IDC_MUL: - result = result.Mul(rhs, m_precision); + result *= rhs; break; case IDC_DIV: @@ -85,24 +84,22 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa if (m_fIntegerMode) { - uint64_t w64Bits = rhs.ToUInt64_t(m_precision); + uint64_t w64Bits = rhs.ToUInt64_t(); bool fMsb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1; if (fMsb) { - result = rhs.Not(m_chopNumbers[m_numwidth], m_precision); - result = result.Add(1, m_precision); + result = (rhs ^ m_chopNumbers[m_numwidth]) + 1; iNumeratorSign = -1; } - w64Bits = temp.ToUInt64_t(m_precision); + w64Bits = temp.ToUInt64_t(); fMsb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1; if (fMsb) { - temp = temp.Not(m_chopNumbers[m_numwidth], m_precision); - temp = temp.Add(1, m_precision); + temp = (temp ^ m_chopNumbers[m_numwidth]) + 1; iDenominatorSign = -1; } @@ -111,28 +108,28 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa if (operation == IDC_DIV) { iFinalSign = iNumeratorSign * iDenominatorSign; - result = result.Div(temp, m_precision); + result /= temp; } else { iFinalSign = iNumeratorSign; - result = result.Mod(temp); + result %= temp; } if (m_fIntegerMode && iFinalSign == -1) { - result = Integer(result, m_precision).Negate(); + result = -(Integer(result)); } break; } case IDC_PWR: // Calculates rhs to the result(th) power. - result = Pow(rhs, result, m_precision); + result = Pow(rhs, result); break; case IDC_ROOT: // Calculates rhs to the result(th) root. - result = Root(rhs, result, m_precision); + result = Root(rhs, result); break; } } diff --git a/src/CalcManager/CEngine/sciset.cpp b/src/CalcManager/CEngine/sciset.cpp index 716bba1..1ae1dbc 100644 --- a/src/CalcManager/CEngine/sciset.cpp +++ b/src/CalcManager/CEngine/sciset.cpp @@ -18,16 +18,15 @@ void CCalcEngine::SetRadixTypeAndNumWidth(RADIX_TYPE radixtype, NUM_WIDTH numwid // back to 1111,1111,1000,0001 when in Word mode. if (m_fIntegerMode) { - uint64_t w64Bits = m_currentVal.ToUInt64_t(m_precision); + uint64_t w64Bits = m_currentVal.ToUInt64_t(); bool fMsb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1; // make sure you use the old width if (fMsb) { // If high bit is set, then get the decimal number in -ve 2'scompl form. - auto tempResult = m_currentVal.Not(m_chopNumbers[m_numwidth], m_precision); - tempResult = tempResult.Add(1, m_precision); + auto tempResult = m_currentVal ^ m_chopNumbers[m_numwidth]; - m_currentVal = tempResult.Negate(); + m_currentVal = -(tempResult + 1); } } @@ -85,16 +84,13 @@ bool CCalcEngine::TryToggleBit(CalcEngine::Rational& rat, DWORD wbitno) return false; // ignore error cant happen } - Rational result = Integer(rat, m_precision); - if (result.IsZero()) - { - // This is the same work around happenning in SciCalcFunctions. Ought to move to intrat function itself. - // Basic bug is there which doesn't treat 0/ n as 0, or -0 as 0 etc. - result = Rational{}; - } + Rational result = Integer(rat); - auto pow = Pow(2, static_cast(wbitno), m_precision); - rat = result.Xor(pow, m_precision); + // Remove any variance in how 0 could be represented in rat e.g. -0, 0/n, etc. + result = (result != 0 ? result : 0); + + // XOR the result with 2^wbitno power + rat = result ^ Pow(2, static_cast(wbitno)); return true; } diff --git a/src/CalcManager/Header Files/CalcEngine.h b/src/CalcManager/Header Files/CalcEngine.h index 78bac31..626f395 100644 --- a/src/CalcManager/Header Files/CalcEngine.h +++ b/src/CalcManager/Header Files/CalcEngine.h @@ -14,7 +14,6 @@ * \****************************************************************************/ -#include "scimath.h" #include "CCommand.h" #include "EngineStrings.h" #include "../Command.h" @@ -24,6 +23,7 @@ #include "History.h" // for History Collector #include "CalcInput.h" #include "ICalcDisplay.h" +#include "scimath.h" #include "Rational.h" // The following are NOT real exports of CalcEngine, but for forward declarations diff --git a/src/CalcManager/Header Files/Rational.h b/src/CalcManager/Header Files/Rational.h index aea8ce4..7b73585 100644 --- a/src/CalcManager/Header Files/Rational.h +++ b/src/CalcManager/Header Files/Rational.h @@ -10,6 +10,9 @@ namespace CalcEngine // RatPack calculations currently support up to Base64. inline constexpr uint32_t RATIONAL_BASE = 10; + // Default Precision to use for Rational calculations + inline constexpr int32_t RATIONAL_PRECISION = 128; + class Rational { public: @@ -18,7 +21,7 @@ namespace CalcEngine Rational(Number const& p, Number const& q) noexcept; Rational(int32_t i); Rational(uint32_t ui); - Rational(uint64_t ui, int32_t precision); + Rational(uint64_t ui); explicit Rational(PRAT prat) noexcept; PRAT ToPRAT() const; @@ -26,29 +29,42 @@ namespace CalcEngine Number const& P() const; Number const& Q() const; - Rational Negate() const; - Rational Add(Rational const& rhs, int32_t precision) const; - Rational Sub(Rational const& rhs, int32_t precision) const; - Rational Mul(Rational const& rhs, int32_t precision) const; - Rational Div(Rational const& rhs, int32_t precision) const; - Rational Mod(Rational const& rhs) const; + Rational operator-() const; + Rational& operator+=(Rational const& rhs); + Rational& operator-=(Rational const& rhs); + Rational& operator*=(Rational const& rhs); + Rational& operator/=(Rational const& rhs); + Rational& operator%=(Rational const& rhs); - Rational Lsh(Rational const& r, int32_t precision) const; - Rational Rsh(Rational const& r, int32_t precision) const; + Rational& operator<<=(Rational const& rhs); + Rational& operator>>=(Rational const& rhs); - Rational Not(Rational const& chopNum, int32_t precision) const; - Rational And(Rational const& r, int32_t precision) const; - Rational Or(Rational const& r, int32_t precision) const; - Rational Xor(Rational const& r, int32_t precision) const; + Rational& operator&=(Rational const& rhs); + Rational& operator|=(Rational const& rhs); + Rational& operator^=(Rational const& rhs); - bool IsZero() const; - bool IsLess(Rational const& r, int32_t precision) const; - bool IsLessEq(Rational const& r, int32_t precision) const; - bool IsGreaterEq(Rational const& r, int32_t precision) const; - bool IsEq(Rational const& r, int32_t precision) const; + friend Rational operator+(Rational lhs, Rational const& rhs); + friend Rational operator-(Rational lhs, Rational const& rhs); + friend Rational operator*(Rational lhs, Rational const& rhs); + friend Rational operator/(Rational lhs, Rational const& rhs); + friend Rational operator%(Rational lhs, Rational const& rhs); + + friend Rational operator<<(Rational lhs, Rational const& rhs); + friend Rational operator>>(Rational lhs, Rational const& rhs); + + friend Rational operator&(Rational lhs, Rational const& rhs); + friend Rational operator|(Rational lhs, Rational const& rhs); + friend Rational operator^(Rational lhs, Rational const& rhs); + + friend bool operator==(Rational const& lhs, Rational const& rhs); + friend bool operator!=(Rational const& lhs, Rational const& rhs); + friend bool operator<(Rational const& lhs, Rational const& rhs); + friend bool operator>(Rational const& lhs, Rational const& rhs); + friend bool operator<=(Rational const& lhs, Rational const& rhs); + friend bool operator>=(Rational const& lhs, Rational const& rhs); std::wstring ToString(uint32_t radix, NUMOBJ_FMT format, int32_t precision) const; - uint64_t ToUInt64_t(int32_t precision) const; + uint64_t ToUInt64_t() const; private: Number m_p; diff --git a/src/CalcManager/Header Files/scimath.h b/src/CalcManager/Header Files/scimath.h index e3726eb..06be9e8 100644 --- a/src/CalcManager/Header Files/scimath.h +++ b/src/CalcManager/Header Files/scimath.h @@ -5,31 +5,31 @@ namespace CalcEngine::RationalMath { - Rational Frac(Rational const& rat, int32_t precision); - Rational Integer(Rational const& rat, int32_t precision); + Rational Frac(Rational const& rat); + Rational Integer(Rational const& rat); - Rational Pow(Rational const& base, Rational const& pow, int32_t precision); - Rational Root(Rational const& base, Rational const& root, int32_t precision); - Rational Fact(Rational const& rat, int32_t precision); + Rational Pow(Rational const& base, Rational const& pow); + Rational Root(Rational const& base, Rational const& root); + Rational Fact(Rational const& rat); - Rational Exp(Rational const& rat, int32_t precision); - Rational Log(Rational const& rat, int32_t precision); - Rational Log10(Rational const& rat, int32_t precision); + Rational Exp(Rational const& rat); + Rational Log(Rational const& rat); + Rational Log10(Rational const& rat); - Rational Invert(Rational const& rat, int32_t precision); + Rational Invert(Rational const& rat); Rational Abs(Rational const& rat); - Rational Sin(Rational const& rat, ANGLE_TYPE angletype, int32_t precision); - Rational Cos(Rational const& rat, ANGLE_TYPE angletype, int32_t precision); - Rational Tan(Rational const& rat, ANGLE_TYPE angletype, int32_t precision); - Rational ASin(Rational const& rat, ANGLE_TYPE angletype, int32_t precision); - Rational ACos(Rational const& rat, ANGLE_TYPE angletype, int32_t precision); - Rational ATan(Rational const& rat, ANGLE_TYPE angletype, int32_t precision); + Rational Sin(Rational const& rat, ANGLE_TYPE angletype); + Rational Cos(Rational const& rat, ANGLE_TYPE angletype); + Rational Tan(Rational const& rat, ANGLE_TYPE angletype); + Rational ASin(Rational const& rat, ANGLE_TYPE angletype); + Rational ACos(Rational const& rat, ANGLE_TYPE angletype); + Rational ATan(Rational const& rat, ANGLE_TYPE angletype); - Rational Sinh(Rational const& rat, int32_t precision); - Rational Cosh(Rational const& rat, int32_t precision); - Rational Tanh(Rational const& rat, int32_t precision); - Rational ASinh(Rational const& rat, int32_t precision); - Rational ACosh(Rational const& rat, int32_t precision); - Rational ATanh(Rational const& rat, int32_t precision); + Rational Sinh(Rational const& rat); + Rational Cosh(Rational const& rat); + Rational Tanh(Rational const& rat); + Rational ASinh(Rational const& rat); + Rational ACosh(Rational const& rat); + Rational ATanh(Rational const& rat); } diff --git a/src/CalcManager/Ratpack/conv.cpp b/src/CalcManager/Ratpack/conv.cpp index 57ec5bb..05d118f 100644 --- a/src/CalcManager/Ratpack/conv.cpp +++ b/src/CalcManager/Ratpack/conv.cpp @@ -1259,20 +1259,7 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_ //----------------------------------------------------------------------------- wstring RatToString(_Inout_ PRAT& prat, int format, uint32_t radix, int32_t precision) { - // Convert p and q of rational form from internal base to requested base. - // Scale by largest power of BASEX possible. - long scaleby = min(prat->pp->exp, prat->pq->exp); - scaleby = max(scaleby, 0); - - prat->pp->exp -= scaleby; - prat->pq->exp -= scaleby; - - PNUMBER p = nRadixxtonum(prat->pp, radix, precision); - PNUMBER q = nRadixxtonum(prat->pq, radix, precision); - - // finally take the time hit to actually divide. - divnum(&p, q, radix, precision); - destroynum(q); + PNUMBER p = RatToNumber(prat, radix, precision); wstring result = NumberToString(p, format, radix, precision); destroynum(p); @@ -1280,6 +1267,40 @@ wstring RatToString(_Inout_ PRAT& prat, int format, uint32_t radix, int32_t prec return result; } +PNUMBER RatToNumber(_In_ PRAT prat, uint32_t radix, int32_t precision) +{ + PRAT temprat = nullptr; + DUPRAT(temprat, prat); + // Convert p and q of rational form from internal base to requested base. + // Scale by largest power of BASEX possible. + long scaleby = min(temprat->pp->exp, temprat->pq->exp); + scaleby = max(scaleby, 0); + + temprat->pp->exp -= scaleby; + temprat->pq->exp -= scaleby; + + PNUMBER p = nRadixxtonum(temprat->pp, radix, precision); + PNUMBER q = nRadixxtonum(temprat->pq, radix, precision); + + destroyrat(temprat); + + // finally take the time hit to actually divide. + divnum(&p, q, radix, precision); + destroynum(q); + + return p; +} + +// Converts a PRAT to a PNUMBER and back to a PRAT, flattening/simplifying the rational in the process +void flatrat(_Inout_ PRAT& prat, uint32_t radix, int32_t precision) +{ + PNUMBER pnum = RatToNumber(prat, radix, precision); + + destroyrat(prat); + prat = numtorat(pnum, radix); + destroynum(pnum); +} + //----------------------------------------------------------------------------- // // FUNCTION: gcd diff --git a/src/CalcManager/Ratpack/rat.cpp b/src/CalcManager/Ratpack/rat.cpp index ee294dc..efc448d 100644 --- a/src/CalcManager/Ratpack/rat.cpp +++ b/src/CalcManager/Ratpack/rat.cpp @@ -73,16 +73,11 @@ void gcdrat( PRAT *pa, uint32_t radix, int32_t precision) void fracrat( PRAT *pa , uint32_t radix, int32_t precision) { - // Only do the intrat operation if number is nonzero. + // Only do the flatrat operation if number is nonzero. // and only if the bottom part is not one. if ( !zernum( (*pa)->pp ) && !equnum( (*pa)->pq, num_one ) ) { - wstring ratStr = RatToString(*pa, FMT_FLOAT, radix, precision); - PNUMBER pnum = StringToNumber(ratStr, radix, precision); - - destroyrat( *pa ); - *pa = numtorat( pnum, radix); - destroynum( pnum ); + flatrat(*pa, radix, precision); } remnum( &((*pa)->pp), (*pa)->pq, BASEX ); diff --git a/src/CalcManager/Ratpack/ratpak.h b/src/CalcManager/Ratpack/ratpak.h index ee376b8..f5a508e 100644 --- a/src/CalcManager/Ratpack/ratpak.h +++ b/src/CalcManager/Ratpack/ratpak.h @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. +// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. #pragma once @@ -316,6 +316,10 @@ extern std::wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t r // returns a text representation of a PRAT extern std::wstring RatToString(_Inout_ PRAT& prat, int format, uint32_t radix, int32_t precision); +// converts a PRAT into a PNUMBER +extern PNUMBER RatToNumber(_In_ PRAT prat, uint32_t radix, int32_t precision); +// flattens a PRAT by converting it to a PNUMBER and back to a PRAT +extern void flatrat(_Inout_ PRAT& prat, uint32_t radix, int32_t precision); extern long numtolong(_In_ PNUMBER pnum, uint32_t radix ); extern long rattolong(_In_ PRAT prat, uint32_t radix, int32_t precision); diff --git a/src/CalcManager/Ratpack/support.cpp b/src/CalcManager/Ratpack/support.cpp index 81e17ec..65c2b4c 100644 --- a/src/CalcManager/Ratpack/support.cpp +++ b/src/CalcManager/Ratpack/support.cpp @@ -291,19 +291,18 @@ void intrat( PRAT *px, uint32_t radix, int32_t precision) // and only if the bottom part is not one. if ( !zernum( (*px)->pp ) && !equnum( (*px)->pq, num_one ) ) { - wstring ratStr = RatToString(*px, FMT_FLOAT, radix, precision); - PNUMBER pnum = StringToNumber(ratStr, radix, precision); - - destroyrat( *px ); - *px = numtorat( pnum, radix); - destroynum( pnum ); + flatrat(*px, radix, precision); + // Subtract the fractional part of the rational PRAT pret = nullptr; DUPRAT(pret,*px); modrat( &pret, rat_one ); - + subrat( px, pret, precision); destroyrat( pret ); + + // Simplify the value if possible to resolve rounding errors + flatrat(*px, radix, precision); } }