CalcEngine: Convert NumObj* functions to use Rationals and move under CalcEngine::RationalMath namespace (#12)
* Converts NumObj* functions to use Rationals. Places new functions under CalcEngine::RationalMath namespace * Moves functions that correspond to an operator to the Rational class with intent to convert to operators in the future * Consolidates use of RatPack's NUMBER and RAT data types to Number/Rational classes and RationalMath namespace.
This commit is contained in:
parent
3e093155b1
commit
995f077127
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "Header Files/Rational.h"
|
#include "Header Files/Rational.h"
|
||||||
|
#include "Header Files/scimath.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
@ -29,6 +30,37 @@ namespace CalcEngine
|
|||||||
m_q{ q }
|
m_q{ q }
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
Rational::Rational(int32_t i)
|
||||||
|
{
|
||||||
|
PRAT pr = longtorat(static_cast<long>(i));
|
||||||
|
|
||||||
|
m_p = Number{ pr->pp };
|
||||||
|
m_q = Number{ pr->pq };
|
||||||
|
|
||||||
|
destroyrat(pr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational::Rational(uint32_t ui)
|
||||||
|
{
|
||||||
|
PRAT pr = Ulongtorat(static_cast<unsigned long>(ui));
|
||||||
|
|
||||||
|
m_p = Number{ pr->pp };
|
||||||
|
m_q = Number{ pr->pq };
|
||||||
|
|
||||||
|
destroyrat(pr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational::Rational(uint64_t ui, uint32_t radix, int32_t precision)
|
||||||
|
{
|
||||||
|
uint32_t hi = HIDWORD(ui);
|
||||||
|
uint32_t lo = LODWORD(ui);
|
||||||
|
|
||||||
|
Rational temp = Rational{ hi }.Lsh(32, radix, precision).Or(lo, radix, precision);
|
||||||
|
|
||||||
|
m_p = Number{ temp.P() };
|
||||||
|
m_q = Number{ temp.Q() };
|
||||||
|
}
|
||||||
|
|
||||||
Rational::Rational(PRAT prat) noexcept :
|
Rational::Rational(PRAT prat) noexcept :
|
||||||
m_p{ Number{prat->pp} },
|
m_p{ Number{prat->pp} },
|
||||||
m_q{ Number{prat->pq} }
|
m_q{ Number{prat->pq} }
|
||||||
@ -54,8 +86,390 @@ namespace CalcEngine
|
|||||||
return m_q;
|
return m_q;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rational Rational::Negate() const
|
||||||
|
{
|
||||||
|
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
|
||||||
|
{
|
||||||
|
PRAT lhsRat = this->ToPRAT();
|
||||||
|
PRAT rhsRat = rhs.ToPRAT();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
addrat(&lhsRat, rhsRat, precision);
|
||||||
|
destroyrat(rhsRat);
|
||||||
|
}
|
||||||
|
catch (DWORD error)
|
||||||
|
{
|
||||||
|
destroyrat(lhsRat);
|
||||||
|
destroyrat(rhsRat);
|
||||||
|
throw(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational result = Rational{ lhsRat };
|
||||||
|
destroyrat(lhsRat);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational Rational::Sub(Rational const& rhs, int32_t precision) const
|
||||||
|
{
|
||||||
|
PRAT lhsRat = this->ToPRAT();
|
||||||
|
PRAT rhsRat = rhs.ToPRAT();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
subrat(&lhsRat, rhsRat, precision);
|
||||||
|
destroyrat(rhsRat);
|
||||||
|
}
|
||||||
|
catch (DWORD error)
|
||||||
|
{
|
||||||
|
destroyrat(lhsRat);
|
||||||
|
destroyrat(rhsRat);
|
||||||
|
throw(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational result = Rational{ lhsRat };
|
||||||
|
destroyrat(lhsRat);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational Rational::Mul(Rational const& rhs, int32_t precision) const
|
||||||
|
{
|
||||||
|
PRAT lhsRat = this->ToPRAT();
|
||||||
|
PRAT rhsRat = rhs.ToPRAT();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
mulrat(&lhsRat, rhsRat, precision);
|
||||||
|
destroyrat(rhsRat);
|
||||||
|
}
|
||||||
|
catch (DWORD error)
|
||||||
|
{
|
||||||
|
destroyrat(lhsRat);
|
||||||
|
destroyrat(rhsRat);
|
||||||
|
throw(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational result = Rational{ lhsRat };
|
||||||
|
destroyrat(lhsRat);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational Rational::Div(Rational const& rhs, int32_t precision) const
|
||||||
|
{
|
||||||
|
PRAT lhsRat = this->ToPRAT();
|
||||||
|
PRAT rhsRat = rhs.ToPRAT();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
divrat(&lhsRat, rhsRat, precision);
|
||||||
|
destroyrat(rhsRat);
|
||||||
|
}
|
||||||
|
catch (DWORD error)
|
||||||
|
{
|
||||||
|
destroyrat(lhsRat);
|
||||||
|
destroyrat(rhsRat);
|
||||||
|
throw(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational result = Rational{ lhsRat };
|
||||||
|
destroyrat(lhsRat);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational Rational::Mod(Rational const& rhs) const
|
||||||
|
{
|
||||||
|
PRAT lhsRat = this->ToPRAT();
|
||||||
|
PRAT rhsRat = rhs.ToPRAT();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
modrat(&lhsRat, rhsRat);
|
||||||
|
destroyrat(rhsRat);
|
||||||
|
}
|
||||||
|
catch (DWORD error)
|
||||||
|
{
|
||||||
|
destroyrat(lhsRat);
|
||||||
|
destroyrat(rhsRat);
|
||||||
|
throw(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational result = Rational{ lhsRat };
|
||||||
|
destroyrat(lhsRat);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational Rational::Lsh(Rational const& rhs, uint32_t radix, int32_t precision) const
|
||||||
|
{
|
||||||
|
PRAT lhsRat = this->ToPRAT();
|
||||||
|
PRAT rhsRat = rhs.ToPRAT();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lshrat(&lhsRat, rhsRat, radix, precision);
|
||||||
|
destroyrat(rhsRat);
|
||||||
|
}
|
||||||
|
catch (DWORD error)
|
||||||
|
{
|
||||||
|
destroyrat(lhsRat);
|
||||||
|
destroyrat(rhsRat);
|
||||||
|
throw(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational result = Rational{ lhsRat };
|
||||||
|
destroyrat(lhsRat);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational Rational::Rsh(Rational const& rhs, uint32_t radix, int32_t precision) const
|
||||||
|
{
|
||||||
|
PRAT lhsRat = this->ToPRAT();
|
||||||
|
PRAT rhsRat = rhs.ToPRAT();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
rshrat(&lhsRat, rhsRat, radix, precision);
|
||||||
|
destroyrat(rhsRat);
|
||||||
|
}
|
||||||
|
catch (DWORD error)
|
||||||
|
{
|
||||||
|
destroyrat(lhsRat);
|
||||||
|
destroyrat(rhsRat);
|
||||||
|
throw(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational result = Rational{ lhsRat };
|
||||||
|
destroyrat(lhsRat);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational Rational::Not(bool isIntegerMode, Rational const& chopNum, uint32_t radix, int32_t precision) const
|
||||||
|
{
|
||||||
|
Rational result{};
|
||||||
|
|
||||||
|
if (radix == 10 && !isIntegerMode)
|
||||||
|
{
|
||||||
|
result = RationalMath::Integer(*this, radix, precision);
|
||||||
|
result = result.Add(1, precision);
|
||||||
|
result = result.Negate();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = this->Xor(chopNum, radix, precision);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational Rational::And(Rational const& rhs, uint32_t radix, int32_t precision) const
|
||||||
|
{
|
||||||
|
PRAT lhsRat = this->ToPRAT();
|
||||||
|
PRAT rhsRat = rhs.ToPRAT();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
andrat(&lhsRat, rhsRat, radix, precision);
|
||||||
|
destroyrat(rhsRat);
|
||||||
|
}
|
||||||
|
catch (DWORD error)
|
||||||
|
{
|
||||||
|
destroyrat(lhsRat);
|
||||||
|
destroyrat(rhsRat);
|
||||||
|
throw(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational result = Rational{ lhsRat };
|
||||||
|
destroyrat(lhsRat);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational Rational::Or(Rational const& rhs, uint32_t radix, int32_t precision) const
|
||||||
|
{
|
||||||
|
PRAT lhsRat = this->ToPRAT();
|
||||||
|
PRAT rhsRat = rhs.ToPRAT();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
orrat(&lhsRat, rhsRat, radix, precision);
|
||||||
|
destroyrat(rhsRat);
|
||||||
|
}
|
||||||
|
catch (DWORD error)
|
||||||
|
{
|
||||||
|
destroyrat(lhsRat);
|
||||||
|
destroyrat(rhsRat);
|
||||||
|
throw(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational result = Rational{ lhsRat };
|
||||||
|
destroyrat(lhsRat);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational Rational::Xor(Rational const& rhs, uint32_t radix, int32_t precision) const
|
||||||
|
{
|
||||||
|
PRAT lhsRat = this->ToPRAT();
|
||||||
|
PRAT rhsRat = rhs.ToPRAT();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
xorrat(&lhsRat, rhsRat, radix, precision);
|
||||||
|
destroyrat(rhsRat);
|
||||||
|
}
|
||||||
|
catch (DWORD error)
|
||||||
|
{
|
||||||
|
destroyrat(lhsRat);
|
||||||
|
destroyrat(rhsRat);
|
||||||
|
throw(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational result = Rational{ lhsRat };
|
||||||
|
destroyrat(lhsRat);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
bool Rational::IsZero() const
|
bool Rational::IsZero() const
|
||||||
{
|
{
|
||||||
return this->P().IsZero();
|
return this->P().IsZero();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Rational::IsLess(Rational const& r, int32_t precision) const
|
||||||
|
{
|
||||||
|
PRAT thisRat = this->ToPRAT();
|
||||||
|
PRAT rRat = r.ToPRAT();
|
||||||
|
|
||||||
|
bool result = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
result = rat_lt(thisRat, rRat, precision);
|
||||||
|
}
|
||||||
|
catch (DWORD error)
|
||||||
|
{
|
||||||
|
destroyrat(thisRat);
|
||||||
|
destroyrat(rRat);
|
||||||
|
throw(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
destroyrat(thisRat);
|
||||||
|
destroyrat(rRat);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Rational::IsLessEq(Rational const& r, int32_t precision) const
|
||||||
|
{
|
||||||
|
PRAT thisRat = this->ToPRAT();
|
||||||
|
PRAT rRat = r.ToPRAT();
|
||||||
|
|
||||||
|
bool result = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
result = rat_le(thisRat, rRat, precision);
|
||||||
|
}
|
||||||
|
catch (DWORD error)
|
||||||
|
{
|
||||||
|
destroyrat(thisRat);
|
||||||
|
destroyrat(rRat);
|
||||||
|
throw(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
destroyrat(thisRat);
|
||||||
|
destroyrat(rRat);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Rational::IsGreaterEq(Rational const& r, int32_t precision) const
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Rational::IsEq(Rational const& r, int32_t precision) const
|
||||||
|
{
|
||||||
|
PRAT thisRat = this->ToPRAT();
|
||||||
|
PRAT rRat = r.ToPRAT();
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
wstring Rational::ToString(uint32_t radix, NUMOBJ_FMT fmt, int32_t precision) const
|
||||||
|
{
|
||||||
|
PRAT rat = this->ToPRAT();
|
||||||
|
wstring result{};
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
result = RatToString(rat, fmt, radix, precision);
|
||||||
|
}
|
||||||
|
catch (DWORD error)
|
||||||
|
{
|
||||||
|
destroyrat(rat);
|
||||||
|
throw(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
destroyrat(rat);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t Rational::ToUInt64_t(uint32_t radix, int32_t precision) const
|
||||||
|
{
|
||||||
|
PRAT rat = this->ToPRAT();
|
||||||
|
uint64_t result;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
result = rattoUlonglong(rat, radix, precision);
|
||||||
|
}
|
||||||
|
catch (DWORD error)
|
||||||
|
{
|
||||||
|
destroyrat(rat);
|
||||||
|
throw(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
destroyrat(rat);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,29 +1,6 @@
|
|||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
/**************************************************************************\
|
|
||||||
*** SCICALC Scientific Calculator for Windows 3.00.12
|
|
||||||
*** (c)1989 Microsoft Corporation. All Rights Reserved.
|
|
||||||
***
|
|
||||||
*** scimain.c
|
|
||||||
***
|
|
||||||
*** Definitions of all globals, WinMain procedure
|
|
||||||
***
|
|
||||||
*** Last modification
|
|
||||||
*** Fri 22-Nov-1996
|
|
||||||
***
|
|
||||||
*** 22-Nov-1996
|
|
||||||
*** Converted Calc from floating point to infinite precision.
|
|
||||||
*** The new math engine is in ..\ratpak
|
|
||||||
***
|
|
||||||
***
|
|
||||||
*** 05-Jan-1990
|
|
||||||
*** Calc did not have a floating point exception signal handler. This
|
|
||||||
*** would cause CALC to be forced to exit on a FP exception as that's
|
|
||||||
*** the default.
|
|
||||||
*** The signal handler is defined in SCIFUNC.C, in WinMain we hook the
|
|
||||||
*** the signal.
|
|
||||||
\**************************************************************************/
|
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "Header Files/CalcEngine.h"
|
#include "Header Files/CalcEngine.h"
|
||||||
|
|
||||||
@ -46,9 +23,7 @@ static constexpr wstring_view DEFAULT_GRP_STR = L"3;0";
|
|||||||
static constexpr wstring_view DEFAULT_NUMBER_STR = L"0";
|
static constexpr wstring_view DEFAULT_NUMBER_STR = L"0";
|
||||||
|
|
||||||
// Read strings for keys, errors, trig types, etc.
|
// Read strings for keys, errors, trig types, etc.
|
||||||
// These will be copied from the resources to local memory. A larger
|
// These will be copied from the resources to local memory.
|
||||||
// than needed block is allocated first and then reallocated once we
|
|
||||||
// know how much is actually used.
|
|
||||||
|
|
||||||
array<wstring, CSTRINGSENGMAX> CCalcEngine::s_engineStrings;
|
array<wstring, CSTRINGSENGMAX> CCalcEngine::s_engineStrings;
|
||||||
|
|
||||||
@ -111,7 +86,7 @@ CCalcEngine::CCalcEngine(bool fPrecedence, bool fIntegerMode, CalculationManager
|
|||||||
m_numberString(DEFAULT_NUMBER_STR),
|
m_numberString(DEFAULT_NUMBER_STR),
|
||||||
m_nOp(),
|
m_nOp(),
|
||||||
m_nPrecOp(),
|
m_nPrecOp(),
|
||||||
m_memoryValue{make_unique<Rational>()},
|
m_memoryValue{ make_unique<Rational>() },
|
||||||
m_holdVal{},
|
m_holdVal{},
|
||||||
m_currentVal{},
|
m_currentVal{},
|
||||||
m_lastVal{}
|
m_lastVal{}
|
||||||
@ -120,12 +95,7 @@ CCalcEngine::CCalcEngine(bool fPrecedence, bool fIntegerMode, CalculationManager
|
|||||||
|
|
||||||
m_dwWordBitWidth = DwWordBitWidthFromeNumWidth(m_numwidth);
|
m_dwWordBitWidth = DwWordBitWidthFromeNumWidth(m_numwidth);
|
||||||
|
|
||||||
PRAT maxTrig = longtorat(10L);
|
m_maxTrigonometricNum = RationalMath::Pow(10, 100, m_radix, m_precision);
|
||||||
PRAT hundred = longtorat(100L);
|
|
||||||
powrat(&maxTrig, hundred, m_radix, m_precision);
|
|
||||||
m_maxTrigonometricNum = Rational{ maxTrig };
|
|
||||||
destroyrat(maxTrig);
|
|
||||||
destroyrat(hundred);
|
|
||||||
|
|
||||||
SetRadixTypeAndNumWidth(DEC_RADIX, m_numwidth);
|
SetRadixTypeAndNumWidth(DEC_RADIX, m_numwidth);
|
||||||
SettingsChanged();
|
SettingsChanged();
|
||||||
@ -147,14 +117,10 @@ void CCalcEngine::InitChopNumbers()
|
|||||||
assert(m_chopNumbers.size() == m_maxDecimalValueStrings.size());
|
assert(m_chopNumbers.size() == m_maxDecimalValueStrings.size());
|
||||||
for (size_t i = 0; i < m_chopNumbers.size(); i++)
|
for (size_t i = 0; i < m_chopNumbers.size(); i++)
|
||||||
{
|
{
|
||||||
PRAT hno = m_chopNumbers[i].ToPRAT();
|
auto maxVal = m_chopNumbers[i].Div(2, m_precision);
|
||||||
|
maxVal = RationalMath::Integer(maxVal, m_radix, m_precision);
|
||||||
|
|
||||||
divrat(&hno, rat_two, m_precision);
|
m_maxDecimalValueStrings[i] = maxVal.ToString(10, FMT_FLOAT, m_precision);
|
||||||
intrat(&hno, m_radix, m_precision);
|
|
||||||
|
|
||||||
m_maxDecimalValueStrings[i] = NumObjToString(hno, 10, FMT_FLOAT, m_precision);
|
|
||||||
|
|
||||||
NumObjDestroy(&hno);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,9 +32,9 @@ using namespace CalcEngine;
|
|||||||
// 0 is returned. Higher the number, higher the precendence of the operator.
|
// 0 is returned. Higher the number, higher the precendence of the operator.
|
||||||
INT NPrecedenceOfOp(int nopCode)
|
INT NPrecedenceOfOp(int nopCode)
|
||||||
{
|
{
|
||||||
static BYTE rgbPrec[]={ 0,0, IDC_OR,0, IDC_XOR,0, IDC_AND,1,
|
static BYTE rgbPrec[] = { 0,0, IDC_OR,0, IDC_XOR,0, IDC_AND,1,
|
||||||
IDC_ADD,2, IDC_SUB,2, IDC_RSHF,3, IDC_LSHF,3,
|
IDC_ADD,2, IDC_SUB,2, IDC_RSHF,3, IDC_LSHF,3,
|
||||||
IDC_MOD,3, IDC_DIV,3, IDC_MUL,3, IDC_PWR,4, IDC_ROOT, 4};
|
IDC_MOD,3, IDC_DIV,3, IDC_MUL,3, IDC_PWR,4, IDC_ROOT, 4 };
|
||||||
int iPrec;
|
int iPrec;
|
||||||
|
|
||||||
iPrec = 0;
|
iPrec = 0;
|
||||||
@ -46,7 +46,7 @@ INT NPrecedenceOfOp(int nopCode)
|
|||||||
{
|
{
|
||||||
iPrec = 0;
|
iPrec = 0;
|
||||||
}
|
}
|
||||||
return rgbPrec[iPrec+1];
|
return rgbPrec[iPrec + 1];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,13 +77,13 @@ void CCalcEngine::ClearTemporaryValues()
|
|||||||
m_input.Clear();
|
m_input.Clear();
|
||||||
m_bRecord = true;
|
m_bRecord = true;
|
||||||
CheckAndAddLastBinOpToHistory();
|
CheckAndAddLastBinOpToHistory();
|
||||||
DisplayNum ();
|
DisplayNum();
|
||||||
m_bError=false;
|
m_bError = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCalcEngine::ProcessCommand(WPARAM wParam)
|
void CCalcEngine::ProcessCommand(WPARAM wParam)
|
||||||
{
|
{
|
||||||
if(wParam == IDC_SET_RESULT)
|
if (wParam == IDC_SET_RESULT)
|
||||||
{
|
{
|
||||||
wParam = IDC_RECALL;
|
wParam = IDC_RECALL;
|
||||||
m_bSetCalcState = true;
|
m_bSetCalcState = true;
|
||||||
@ -104,13 +104,13 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
|||||||
|
|
||||||
if (!IsGuiSettingOpCode(wParam))
|
if (!IsGuiSettingOpCode(wParam))
|
||||||
{
|
{
|
||||||
m_nLastCom=m_nTempCom;
|
m_nLastCom = m_nTempCom;
|
||||||
m_nTempCom=(INT)wParam;
|
m_nTempCom = (INT)wParam;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_bError)
|
if (m_bError)
|
||||||
{
|
{
|
||||||
if(wParam == IDC_CLEAR)
|
if (wParam == IDC_CLEAR)
|
||||||
{
|
{
|
||||||
// handle "C" normally
|
// handle "C" normally
|
||||||
}
|
}
|
||||||
@ -129,12 +129,12 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
|||||||
// Toggle Record/Display mode if appropriate.
|
// Toggle Record/Display mode if appropriate.
|
||||||
if (m_bRecord)
|
if (m_bRecord)
|
||||||
{
|
{
|
||||||
if (IsOpInRange(wParam, IDC_AND, IDC_MMINUS) ||
|
if (IsOpInRange(wParam, IDC_AND, IDC_MMINUS) ||
|
||||||
IsOpInRange(wParam, IDC_OPENP, IDC_CLOSEP) ||
|
IsOpInRange(wParam, IDC_OPENP, IDC_CLOSEP) ||
|
||||||
IsOpInRange(wParam, IDM_HEX, IDM_BIN) ||
|
IsOpInRange(wParam, IDM_HEX, IDM_BIN) ||
|
||||||
IsOpInRange(wParam, IDM_QWORD, IDM_BYTE) ||
|
IsOpInRange(wParam, IDM_QWORD, IDM_BYTE) ||
|
||||||
IsOpInRange(wParam, IDM_DEG, IDM_GRAD) ||
|
IsOpInRange(wParam, IDM_DEG, IDM_GRAD) ||
|
||||||
IsOpInRange(wParam, IDC_BINEDITSTART, IDC_BINEDITSTART+63) ||
|
IsOpInRange(wParam, IDC_BINEDITSTART, IDC_BINEDITSTART + 63) ||
|
||||||
(IDC_INV == wParam) ||
|
(IDC_INV == wParam) ||
|
||||||
(IDC_SIGN == wParam && 10 != m_radix))
|
(IDC_SIGN == wParam && 10 != m_radix))
|
||||||
{
|
{
|
||||||
@ -145,7 +145,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ( IsDigitOpCode(wParam)|| wParam == IDC_PNT)
|
if (IsDigitOpCode(wParam) || wParam == IDC_PNT)
|
||||||
{
|
{
|
||||||
m_bRecord = true;
|
m_bRecord = true;
|
||||||
m_input.Clear();
|
m_input.Clear();
|
||||||
@ -156,7 +156,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
|||||||
// Interpret digit keys.
|
// Interpret digit keys.
|
||||||
if (IsDigitOpCode(wParam))
|
if (IsDigitOpCode(wParam))
|
||||||
{
|
{
|
||||||
unsigned int iValue = static_cast<unsigned int>(wParam-IDC_0);
|
unsigned int iValue = static_cast<unsigned int>(wParam - IDC_0);
|
||||||
|
|
||||||
// this is redundant, illegal keys are disabled
|
// this is redundant, illegal keys are disabled
|
||||||
if (iValue >= static_cast<unsigned int>(m_radix))
|
if (iValue >= static_cast<unsigned int>(m_radix))
|
||||||
@ -186,7 +186,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
|||||||
INT nPrev;
|
INT nPrev;
|
||||||
bool fPrecInvToHigher = false; // Is Precedence Invertion from lower to higher precedence happenning ??
|
bool fPrecInvToHigher = false; // Is Precedence Invertion from lower to higher precedence happenning ??
|
||||||
|
|
||||||
m_nOpCode =(INT)wParam;
|
m_nOpCode = (INT)wParam;
|
||||||
|
|
||||||
// Check to see if by changing this binop, a Precedence invertion is happenning.
|
// Check to see if by changing this binop, a Precedence invertion is happenning.
|
||||||
// Eg. 1 * 2 + and + is getting changed to ^. The previous precedence rules would have already computed
|
// Eg. 1 * 2 + and + is getting changed to ^. The previous precedence rules would have already computed
|
||||||
@ -221,9 +221,9 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
|||||||
/* Scientific mode. */
|
/* Scientific mode. */
|
||||||
if (m_bChangeOp)
|
if (m_bChangeOp)
|
||||||
{
|
{
|
||||||
DoPrecedenceCheckAgain:
|
DoPrecedenceCheckAgain:
|
||||||
|
|
||||||
nx = NPrecedenceOfOp((int) wParam);
|
nx = NPrecedenceOfOp((int)wParam);
|
||||||
ni = NPrecedenceOfOp(m_nOpCode);
|
ni = NPrecedenceOfOp(m_nOpCode);
|
||||||
|
|
||||||
if ((nx > ni) && m_fPrecedence)
|
if ((nx > ni) && m_fPrecedence)
|
||||||
@ -237,7 +237,7 @@ DoPrecedenceCheckAgain:
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_nPrecNum = MAXPRECDEPTH-1;
|
m_nPrecNum = MAXPRECDEPTH - 1;
|
||||||
HandleErrorCommand(wParam);
|
HandleErrorCommand(wParam);
|
||||||
}
|
}
|
||||||
m_nPrecNum++;
|
m_nPrecNum++;
|
||||||
@ -253,13 +253,13 @@ DoPrecedenceCheckAgain:
|
|||||||
|
|
||||||
if (!m_bError)
|
if (!m_bError)
|
||||||
{
|
{
|
||||||
DisplayNum ();
|
DisplayNum();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((m_nPrecNum !=0) && (m_nPrecOp[m_nPrecNum-1]))
|
if ((m_nPrecNum != 0) && (m_nPrecOp[m_nPrecNum - 1]))
|
||||||
{
|
{
|
||||||
m_nPrecNum--;
|
m_nPrecNum--;
|
||||||
m_nOpCode=m_nPrecOp[m_nPrecNum] ;
|
m_nOpCode = m_nPrecOp[m_nPrecNum];
|
||||||
|
|
||||||
m_lastVal = m_precedenceVals[m_nPrecNum];
|
m_lastVal = m_precedenceVals[m_nPrecNum];
|
||||||
|
|
||||||
@ -274,7 +274,7 @@ DoPrecedenceCheckAgain:
|
|||||||
m_HistoryCollector.EnclosePrecInvertionBrackets();
|
m_HistoryCollector.EnclosePrecInvertionBrackets();
|
||||||
}
|
}
|
||||||
m_HistoryCollector.PopLastOpndStart();
|
m_HistoryCollector.PopLastOpndStart();
|
||||||
goto DoPrecedenceCheckAgain ;
|
goto DoPrecedenceCheckAgain;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -283,7 +283,7 @@ DoPrecedenceCheckAgain:
|
|||||||
DisplayAnnounceBinaryOperator();
|
DisplayAnnounceBinaryOperator();
|
||||||
|
|
||||||
m_lastVal = m_currentVal;
|
m_lastVal = m_currentVal;
|
||||||
m_nOpCode=(INT)wParam;
|
m_nOpCode = (INT)wParam;
|
||||||
m_HistoryCollector.AddBinOpToHistory(m_nOpCode);
|
m_HistoryCollector.AddBinOpToHistory(m_nOpCode);
|
||||||
m_bNoPrevEqu = m_bChangeOp = true;
|
m_bNoPrevEqu = m_bChangeOp = true;
|
||||||
return;
|
return;
|
||||||
@ -304,7 +304,7 @@ DoPrecedenceCheckAgain:
|
|||||||
|
|
||||||
// we do not add percent sign to history or to two line display.
|
// we do not add percent sign to history or to two line display.
|
||||||
// instead, we add the result of applying %.
|
// instead, we add the result of applying %.
|
||||||
if(wParam != IDC_PERCENT)
|
if (wParam != IDC_PERCENT)
|
||||||
{
|
{
|
||||||
if (!m_HistoryCollector.FOpndAddedToHistory())
|
if (!m_HistoryCollector.FOpndAddedToHistory())
|
||||||
{
|
{
|
||||||
@ -329,9 +329,9 @@ DoPrecedenceCheckAgain:
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* Display the result, reset flags, and reset indicators. */
|
/* Display the result, reset flags, and reset indicators. */
|
||||||
DisplayNum ();
|
DisplayNum();
|
||||||
|
|
||||||
if(wParam == IDC_PERCENT)
|
if (wParam == IDC_PERCENT)
|
||||||
{
|
{
|
||||||
CheckAndAddLastBinOpToHistory();
|
CheckAndAddLastBinOpToHistory();
|
||||||
m_HistoryCollector.AddOpndToHistory(m_numberString, m_currentVal, true /* Add to primary and secondary display */);
|
m_HistoryCollector.AddOpndToHistory(m_numberString, m_currentVal, true /* Add to primary and secondary display */);
|
||||||
@ -343,8 +343,8 @@ DoPrecedenceCheckAgain:
|
|||||||
if (m_bInv &&
|
if (m_bInv &&
|
||||||
((wParam == IDC_CHOP) ||
|
((wParam == IDC_CHOP) ||
|
||||||
(wParam == IDC_SIN) || (wParam == IDC_COS) || (wParam == IDC_TAN) ||
|
(wParam == IDC_SIN) || (wParam == IDC_COS) || (wParam == IDC_TAN) ||
|
||||||
(wParam == IDC_LN) || (wParam == IDC_DMS) || (wParam == IDC_DEGREES) ||
|
(wParam == IDC_LN) || (wParam == IDC_DMS) || (wParam == IDC_DEGREES) ||
|
||||||
(wParam == IDC_SINH) || (wParam == IDC_COSH) || (wParam == IDC_TANH)))
|
(wParam == IDC_SINH) || (wParam == IDC_COSH) || (wParam == IDC_TANH)))
|
||||||
{
|
{
|
||||||
m_bInv = false;
|
m_bInv = false;
|
||||||
}
|
}
|
||||||
@ -353,7 +353,7 @@ DoPrecedenceCheckAgain:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Tiny binary edit windows clicked. Toggle that bit and update display
|
// Tiny binary edit windows clicked. Toggle that bit and update display
|
||||||
if (IsOpInRange(wParam, IDC_BINEDITSTART, IDC_BINEDITSTART+63))
|
if (IsOpInRange(wParam, IDC_BINEDITSTART, IDC_BINEDITSTART + 63))
|
||||||
{
|
{
|
||||||
// Same reasoning as for unary operators. We need to seed it previous number
|
// Same reasoning as for unary operators. We need to seed it previous number
|
||||||
if (m_nLastCom >= IDC_AND && m_nLastCom <= IDC_PWR)
|
if (m_nLastCom >= IDC_AND && m_nLastCom <= IDC_PWR)
|
||||||
@ -372,44 +372,44 @@ DoPrecedenceCheckAgain:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Now branch off to do other commands and functions. */
|
/* Now branch off to do other commands and functions. */
|
||||||
switch(wParam)
|
switch (wParam)
|
||||||
{
|
{
|
||||||
case IDC_CLEAR: /* Total clear. */
|
case IDC_CLEAR: /* Total clear. */
|
||||||
|
{
|
||||||
|
if (!m_bChangeOp)
|
||||||
{
|
{
|
||||||
if (!m_bChangeOp)
|
// A special goody we are doing to preserve the history, if all was done was serious of unary operations last
|
||||||
{
|
CheckAndAddLastBinOpToHistory(false);
|
||||||
// A special goody we are doing to preserve the history, if all was done was serious of unary operations last
|
|
||||||
CheckAndAddLastBinOpToHistory(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_lastVal = Rational{};
|
|
||||||
|
|
||||||
m_bChangeOp=false;
|
|
||||||
m_nPrecNum=m_nTempCom=m_nLastCom=m_nOpCode= m_openParenCount =0;
|
|
||||||
m_nPrevOpCode = 0;
|
|
||||||
m_bNoPrevEqu= true;
|
|
||||||
|
|
||||||
|
|
||||||
/* clear the parenthesis status box indicator, this will not be
|
|
||||||
cleared for CENTR */
|
|
||||||
if (nullptr != m_pCalcDisplay)
|
|
||||||
{
|
|
||||||
m_pCalcDisplay->SetParenDisplayText(L"");
|
|
||||||
m_pCalcDisplay->SetExpressionDisplay(make_shared<CalculatorVector<pair<wstring, int>>>(), make_shared<CalculatorVector<shared_ptr<IExpressionCommand>>>());
|
|
||||||
}
|
|
||||||
|
|
||||||
m_HistoryCollector.ClearHistoryLine(wstring());
|
|
||||||
ClearTemporaryValues();
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
m_lastVal = Rational{};
|
||||||
|
|
||||||
|
m_bChangeOp = false;
|
||||||
|
m_nPrecNum = m_nTempCom = m_nLastCom = m_nOpCode = m_openParenCount = 0;
|
||||||
|
m_nPrevOpCode = 0;
|
||||||
|
m_bNoPrevEqu = true;
|
||||||
|
|
||||||
|
|
||||||
|
/* clear the parenthesis status box indicator, this will not be
|
||||||
|
cleared for CENTR */
|
||||||
|
if (nullptr != m_pCalcDisplay)
|
||||||
|
{
|
||||||
|
m_pCalcDisplay->SetParenDisplayText(L"");
|
||||||
|
m_pCalcDisplay->SetExpressionDisplay(make_shared<CalculatorVector<pair<wstring, int>>>(), make_shared<CalculatorVector<shared_ptr<IExpressionCommand>>>());
|
||||||
|
}
|
||||||
|
|
||||||
|
m_HistoryCollector.ClearHistoryLine(wstring());
|
||||||
|
ClearTemporaryValues();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case IDC_CENTR: /* Clear only temporary values. */
|
case IDC_CENTR: /* Clear only temporary values. */
|
||||||
{
|
{
|
||||||
// Clear the INV & leave (=xx indicator active
|
// Clear the INV & leave (=xx indicator active
|
||||||
ClearTemporaryValues();
|
ClearTemporaryValues();
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_BACK:
|
case IDC_BACK:
|
||||||
// Divide number by the current radix and truncate.
|
// Divide number by the current radix and truncate.
|
||||||
@ -487,15 +487,15 @@ DoPrecedenceCheckAgain:
|
|||||||
/* Check for errors. If this wasn't done, DisplayNum */
|
/* Check for errors. If this wasn't done, DisplayNum */
|
||||||
/* would immediately overwrite any error message. */
|
/* would immediately overwrite any error message. */
|
||||||
if (!m_bError)
|
if (!m_bError)
|
||||||
DisplayNum ();
|
DisplayNum();
|
||||||
|
|
||||||
/* No longer the first EQU. */
|
/* No longer the first EQU. */
|
||||||
m_bNoPrevEqu= false;
|
m_bNoPrevEqu = false;
|
||||||
}
|
}
|
||||||
else if (!m_bError)
|
else if (!m_bError)
|
||||||
DisplayNum();
|
DisplayNum();
|
||||||
|
|
||||||
if (m_nPrecNum==0 || !m_fPrecedence)
|
if (m_nPrecNum == 0 || !m_fPrecedence)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
m_nOpCode = m_nPrecOp[--m_nPrecNum];
|
m_nOpCode = m_nPrecOp[--m_nPrecNum];
|
||||||
@ -510,7 +510,7 @@ DoPrecedenceCheckAgain:
|
|||||||
}
|
}
|
||||||
m_HistoryCollector.PopLastOpndStart();
|
m_HistoryCollector.PopLastOpndStart();
|
||||||
|
|
||||||
m_bNoPrevEqu= true;
|
m_bNoPrevEqu = true;
|
||||||
} while (m_nPrecNum >= 0);
|
} while (m_nPrecNum >= 0);
|
||||||
|
|
||||||
if (!m_bError)
|
if (!m_bError)
|
||||||
@ -523,17 +523,17 @@ DoPrecedenceCheckAgain:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_bChangeOp=false;
|
m_bChangeOp = false;
|
||||||
m_nPrevOpCode = 0;
|
m_nPrevOpCode = 0;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_OPENP:
|
case IDC_OPENP:
|
||||||
case IDC_CLOSEP:
|
case IDC_CLOSEP:
|
||||||
nx=0;
|
nx = 0;
|
||||||
if (wParam==IDC_OPENP)
|
if (wParam == IDC_OPENP)
|
||||||
{
|
{
|
||||||
nx=1;
|
nx = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// -IF- the Paren holding array is full and we try to add a paren
|
// -IF- the Paren holding array is full and we try to add a paren
|
||||||
@ -541,7 +541,7 @@ DoPrecedenceCheckAgain:
|
|||||||
// paren
|
// paren
|
||||||
// -OR- the the precidence holding array is full
|
// -OR- the the precidence holding array is full
|
||||||
if ((m_openParenCount >= MAXPRECDEPTH && nx) || (!m_openParenCount && !nx)
|
if ((m_openParenCount >= MAXPRECDEPTH && nx) || (!m_openParenCount && !nx)
|
||||||
|| ( (m_nPrecNum >= MAXPRECDEPTH && m_nPrecOp[m_nPrecNum-1]!=0) ) )
|
|| ((m_nPrecNum >= MAXPRECDEPTH && m_nPrecOp[m_nPrecNum - 1] != 0)))
|
||||||
{
|
{
|
||||||
HandleErrorCommand(wParam);
|
HandleErrorCommand(wParam);
|
||||||
break;
|
break;
|
||||||
@ -570,9 +570,9 @@ DoPrecedenceCheckAgain:
|
|||||||
// treated as 1 + (3
|
// treated as 1 + (3
|
||||||
m_currentVal = Rational{};
|
m_currentVal = Rational{};
|
||||||
}
|
}
|
||||||
m_nTempCom=0;
|
m_nTempCom = 0;
|
||||||
m_nOpCode=0;
|
m_nOpCode = 0;
|
||||||
m_bChangeOp= false; // a ( is like starting a fresh sub equation
|
m_bChangeOp = false; // a ( is like starting a fresh sub equation
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -649,7 +649,7 @@ DoPrecedenceCheckAgain:
|
|||||||
case IDM_DWORD:
|
case IDM_DWORD:
|
||||||
case IDM_WORD:
|
case IDM_WORD:
|
||||||
case IDM_BYTE:
|
case IDM_BYTE:
|
||||||
if ( m_bRecord )
|
if (m_bRecord)
|
||||||
{
|
{
|
||||||
m_currentVal = m_input.ToRational(m_radix, m_precision);
|
m_currentVal = m_input.ToRational(m_radix, m_precision);
|
||||||
m_bRecord = false;
|
m_bRecord = false;
|
||||||
@ -666,44 +666,41 @@ DoPrecedenceCheckAgain:
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_SIGN:
|
case IDC_SIGN:
|
||||||
|
{
|
||||||
|
if (m_bRecord)
|
||||||
{
|
{
|
||||||
if (m_bRecord)
|
if (m_input.TryToggleSign(m_fIntegerMode, m_maxDecimalValueStrings[m_numwidth]))
|
||||||
{
|
{
|
||||||
if (m_input.TryToggleSign(m_fIntegerMode, m_maxDecimalValueStrings[m_numwidth]))
|
DisplayNum();
|
||||||
{
|
|
||||||
DisplayNum();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
HandleErrorCommand(wParam);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// Doing +/- while in Record mode is not a unary operation
|
|
||||||
if (IsBinOpCode(m_nLastCom))
|
|
||||||
{
|
{
|
||||||
m_currentVal = m_lastVal;
|
HandleErrorCommand(wParam);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
if (!m_HistoryCollector.FOpndAddedToHistory())
|
|
||||||
{
|
|
||||||
m_HistoryCollector.AddOpndToHistory(m_numberString, m_currentVal);
|
|
||||||
}
|
|
||||||
|
|
||||||
PRAT curRat = m_currentVal.ToPRAT();
|
|
||||||
NumObjNegate(&curRat);
|
|
||||||
m_currentVal = Rational{ curRat };
|
|
||||||
destroyrat(curRat);
|
|
||||||
|
|
||||||
DisplayNum();
|
|
||||||
m_HistoryCollector.AddUnaryOpToHistory(IDC_SIGN, m_bInv, m_angletype);
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
// Doing +/- while in Record mode is not a unary operation
|
||||||
|
if (IsBinOpCode(m_nLastCom))
|
||||||
|
{
|
||||||
|
m_currentVal = m_lastVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_HistoryCollector.FOpndAddedToHistory())
|
||||||
|
{
|
||||||
|
m_HistoryCollector.AddOpndToHistory(m_numberString, m_currentVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_currentVal = m_currentVal.Negate();
|
||||||
|
|
||||||
|
DisplayNum();
|
||||||
|
m_HistoryCollector.AddUnaryOpToHistory(IDC_SIGN, m_bInv, m_angletype);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case IDC_RECALL:
|
case IDC_RECALL:
|
||||||
|
|
||||||
if(m_bSetCalcState)
|
if (m_bSetCalcState)
|
||||||
{
|
{
|
||||||
// Not a Memory recall. set the result
|
// Not a Memory recall. set the result
|
||||||
m_bSetCalcState = false;
|
m_bSetCalcState = false;
|
||||||
@ -714,31 +711,25 @@ DoPrecedenceCheckAgain:
|
|||||||
m_currentVal = Rational{ *m_memoryValue };
|
m_currentVal = Rational{ *m_memoryValue };
|
||||||
}
|
}
|
||||||
CheckAndAddLastBinOpToHistory();
|
CheckAndAddLastBinOpToHistory();
|
||||||
DisplayNum ();
|
DisplayNum();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_MPLUS:
|
case IDC_MPLUS:
|
||||||
{
|
{
|
||||||
/* MPLUS adds m_currentVal to immediate memory and kills the "mem" */
|
/* MPLUS adds m_currentVal to immediate memory and kills the "mem" */
|
||||||
/* indicator if the result is zero. */
|
/* indicator if the result is zero. */
|
||||||
PRAT memRat = m_memoryValue->ToPRAT();
|
Rational result = m_memoryValue->Add(m_currentVal, m_precision);
|
||||||
PRAT curRat = m_currentVal.ToPRAT();
|
m_memoryValue = make_unique<Rational>(TruncateNumForIntMath(result)); // Memory should follow the current int mode
|
||||||
addrat(&memRat, curRat, m_precision);
|
|
||||||
m_memoryValue = make_unique<Rational>(TruncateNumForIntMath(Rational{ memRat })); // Memory should follow the current int mode
|
|
||||||
destroyrat(curRat);
|
|
||||||
destroyrat(memRat);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IDC_MMINUS:
|
case IDC_MMINUS:
|
||||||
{
|
{
|
||||||
/* MMINUS subtracts m_currentVal to immediate memory and kills the "mem" */
|
/* MMINUS subtracts m_currentVal to immediate memory and kills the "mem" */
|
||||||
/* indicator if the result is zero. */
|
/* indicator if the result is zero. */
|
||||||
PRAT memRat = m_memoryValue->ToPRAT();
|
Rational result = m_memoryValue->Sub(m_currentVal, m_precision);
|
||||||
PRAT curRat = m_currentVal.ToPRAT();
|
m_memoryValue = make_unique<Rational>(TruncateNumForIntMath(result));
|
||||||
subrat(&memRat, curRat, m_precision);
|
|
||||||
m_memoryValue = make_unique<Rational>(TruncateNumForIntMath(Rational{ memRat }));
|
|
||||||
destroyrat(curRat);
|
|
||||||
destroyrat(memRat);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case IDC_STORE:
|
case IDC_STORE:
|
||||||
@ -784,7 +775,7 @@ DoPrecedenceCheckAgain:
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_INV:
|
case IDC_INV:
|
||||||
m_bInv=!m_bInv;
|
m_bInv = !m_bInv;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1011,18 +1002,13 @@ int CCalcEngine::IdcSetAngleTypeDecMode(int idc)
|
|||||||
|
|
||||||
bool CCalcEngine::IsCurrentTooBigForTrig()
|
bool CCalcEngine::IsCurrentTooBigForTrig()
|
||||||
{
|
{
|
||||||
bool result = false;
|
if (m_currentVal.IsGreaterEq(m_maxTrigonometricNum, m_precision))
|
||||||
PRAT maxTrigRat = m_maxTrigonometricNum.ToPRAT();
|
|
||||||
PRAT curRat = m_currentVal.ToPRAT();
|
|
||||||
if (NumObjIsGreaterEq(curRat, maxTrigRat, m_precision))
|
|
||||||
{
|
{
|
||||||
m_currentVal = Rational{};
|
m_currentVal = Rational{};
|
||||||
result = true;
|
return true;
|
||||||
}
|
}
|
||||||
destroyrat(curRat);
|
|
||||||
destroyrat(maxTrigRat);
|
|
||||||
|
|
||||||
return result;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CCalcEngine::GetCurrentRadix()
|
int CCalcEngine::GetCurrentRadix()
|
||||||
@ -1052,39 +1038,30 @@ wstring CCalcEngine::GetStringForDisplay(Rational const& rat, uint32_t radix)
|
|||||||
// Check for standard\scientific mode
|
// Check for standard\scientific mode
|
||||||
if (!m_fIntegerMode)
|
if (!m_fIntegerMode)
|
||||||
{
|
{
|
||||||
PRAT prat = rat.ToPRAT();
|
result = rat.ToString(radix, m_nFE, m_precision);
|
||||||
result = NumObjToString(prat, radix, m_nFE, m_precision);
|
|
||||||
destroyrat(prat);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Programmer mode
|
// Programmer mode
|
||||||
// Find most significant bit to determine if number is negative
|
// Find most significant bit to determine if number is negative
|
||||||
PRAT hnoNumCopy = TruncateNumForIntMath(rat).ToPRAT();
|
auto tempRat = TruncateNumForIntMath(rat);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ULONGLONG w64Bits = NumObjGetUlValue(hnoNumCopy, m_radix, m_precision);
|
uint64_t w64Bits = tempRat.ToUInt64_t(m_radix, m_precision);
|
||||||
bool fMsb = ((w64Bits >> (m_dwWordBitWidth - 1)) & 1);
|
bool fMsb = ((w64Bits >> (m_dwWordBitWidth - 1)) & 1);
|
||||||
if ((radix == 10) && fMsb)
|
if ((radix == 10) && fMsb)
|
||||||
{
|
{
|
||||||
// If high bit is set, then get the decimal number in -ve 2'scompl form.
|
// If high bit is set, then get the decimal number in negative 2's compl form.
|
||||||
PRAT chopRat = m_chopNumbers[m_numwidth].ToPRAT();
|
tempRat = tempRat.Not(true, m_chopNumbers[m_numwidth], m_radix, m_precision);
|
||||||
NumObjNot(&hnoNumCopy, true, chopRat, m_radix, m_precision);
|
tempRat = tempRat.Add(1, m_precision);
|
||||||
destroyrat(chopRat);
|
tempRat = tempRat.Negate();
|
||||||
addrat(&hnoNumCopy, rat_one, m_precision);
|
|
||||||
NumObjNegate(&hnoNumCopy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
result = NumObjToString(hnoNumCopy, radix, m_nFE, m_precision);
|
result = tempRat.ToString(radix, m_nFE, m_precision);
|
||||||
NumObjDestroy(&hnoNumCopy);
|
|
||||||
}
|
}
|
||||||
catch (DWORD)
|
catch (DWORD)
|
||||||
{
|
{
|
||||||
if (hnoNumCopy != nullptr)
|
|
||||||
{
|
|
||||||
NumObjDestroy(&hnoNumCopy);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ constexpr wstring_view c_decPostSepStr = L"]?(\\d*)(?:e[+-]?(\\d*))?$";
|
|||||||
// State of calc last time DisplayNum was called
|
// State of calc last time DisplayNum was called
|
||||||
//
|
//
|
||||||
typedef struct {
|
typedef struct {
|
||||||
PRAT hnoNum;
|
Rational value;
|
||||||
int32_t precision;
|
int32_t precision;
|
||||||
uint32_t radix;
|
uint32_t radix;
|
||||||
INT nFE;
|
INT nFE;
|
||||||
@ -46,7 +46,7 @@ typedef struct {
|
|||||||
bool bUseSep;
|
bool bUseSep;
|
||||||
} LASTDISP;
|
} LASTDISP;
|
||||||
|
|
||||||
LASTDISP gldPrevious = { nullptr, -1, 0, -1, (NUM_WIDTH)-1, false, false, false };
|
LASTDISP gldPrevious = { 0, -1, 0, -1, (NUM_WIDTH)-1, false, false, false };
|
||||||
|
|
||||||
// Truncates if too big, makes it a non negative - the number in rat. Doesn't do anything if not in INT mode
|
// Truncates if too big, makes it a non negative - the number in rat. Doesn't do anything if not in INT mode
|
||||||
CalcEngine::Rational CCalcEngine::TruncateNumForIntMath(CalcEngine::Rational const& rat)
|
CalcEngine::Rational CCalcEngine::TruncateNumForIntMath(CalcEngine::Rational const& rat)
|
||||||
@ -56,27 +56,20 @@ CalcEngine::Rational CCalcEngine::TruncateNumForIntMath(CalcEngine::Rational con
|
|||||||
return rat;
|
return rat;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRAT tempRat = rat.ToPRAT();
|
|
||||||
|
|
||||||
// Truncate to an integer. Do not round here.
|
// Truncate to an integer. Do not round here.
|
||||||
intrat(&tempRat, m_radix, m_precision);
|
auto result = RationalMath::Integer(rat, m_radix, m_precision);
|
||||||
|
|
||||||
PRAT chopRat = m_chopNumbers[m_numwidth].ToPRAT();
|
// Can be converting a dec negative number to Hex/Oct/Bin rep. Use 2's complement form
|
||||||
// Can be converting a dec -ve number to Hex/Oct/Bin rep. Use 2's completement form
|
|
||||||
// Check the range.
|
// Check the range.
|
||||||
if (NumObjIsLess(tempRat, rat_zero, m_precision))
|
if (result.IsLess(0, m_precision))
|
||||||
{
|
{
|
||||||
// if negative make positive by doing a twos complement
|
// if negative make positive by doing a twos complement
|
||||||
NumObjNegate(&tempRat);
|
result = result.Negate();
|
||||||
subrat(&tempRat, rat_one, m_precision);
|
result = result.Sub(1, m_precision);
|
||||||
NumObjNot(&tempRat, true, chopRat, m_radix, m_precision);
|
result = result.Not(true /* IntegerMode */, m_chopNumbers[m_numwidth], m_radix, m_precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
andrat(&tempRat, chopRat, m_radix, m_precision);
|
result = result.And(m_chopNumbers[m_numwidth], m_radix, m_precision);
|
||||||
destroyrat(chopRat);
|
|
||||||
|
|
||||||
Rational result{ tempRat };
|
|
||||||
destroyrat(tempRat);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -90,27 +83,24 @@ void CCalcEngine::DisplayNum(void)
|
|||||||
// something important has changed since the last time DisplayNum was
|
// something important has changed since the last time DisplayNum was
|
||||||
// called.
|
// called.
|
||||||
//
|
//
|
||||||
PRAT curRat = m_currentVal.ToPRAT();
|
if (m_bRecord ||
|
||||||
bool hasValChanged = !gldPrevious.hnoNum || !NumObjIsEq(gldPrevious.hnoNum, curRat, m_precision);
|
!gldPrevious.value.IsEq(m_currentVal, m_precision) ||
|
||||||
destroyrat(curRat);
|
gldPrevious.precision != m_precision ||
|
||||||
if ( m_bRecord || gldPrevious.hnoNum == nullptr ||
|
gldPrevious.radix != m_radix ||
|
||||||
hasValChanged ||
|
gldPrevious.nFE != (int)m_nFE ||
|
||||||
gldPrevious.precision != m_precision ||
|
gldPrevious.bUseSep != true ||
|
||||||
gldPrevious.radix != m_radix ||
|
gldPrevious.numwidth != m_numwidth ||
|
||||||
gldPrevious.nFE != (int)m_nFE ||
|
gldPrevious.fIntMath != m_fIntegerMode ||
|
||||||
gldPrevious.bUseSep != true ||
|
gldPrevious.bRecord != m_bRecord)
|
||||||
gldPrevious.numwidth != m_numwidth ||
|
|
||||||
gldPrevious.fIntMath != m_fIntegerMode ||
|
|
||||||
gldPrevious.bRecord != m_bRecord )
|
|
||||||
{
|
{
|
||||||
gldPrevious.precision = m_precision;
|
gldPrevious.precision = m_precision;
|
||||||
gldPrevious.radix = m_radix;
|
gldPrevious.radix = m_radix;
|
||||||
gldPrevious.nFE = (int)m_nFE;
|
gldPrevious.nFE = (int)m_nFE;
|
||||||
gldPrevious.numwidth = m_numwidth;
|
gldPrevious.numwidth = m_numwidth;
|
||||||
|
|
||||||
gldPrevious.fIntMath = m_fIntegerMode;
|
gldPrevious.fIntMath = m_fIntegerMode;
|
||||||
gldPrevious.bRecord = m_bRecord;
|
gldPrevious.bRecord = m_bRecord;
|
||||||
gldPrevious.bUseSep = true;
|
gldPrevious.bUseSep = true;
|
||||||
|
|
||||||
if (m_bRecord)
|
if (m_bRecord)
|
||||||
{
|
{
|
||||||
@ -128,10 +118,9 @@ void CCalcEngine::DisplayNum(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Displayed number can go thru transformation. So copy it after transformation
|
// Displayed number can go thru transformation. So copy it after transformation
|
||||||
destroyrat(gldPrevious.hnoNum);
|
gldPrevious.value = m_currentVal;
|
||||||
gldPrevious.hnoNum = m_currentVal.ToPRAT();
|
|
||||||
|
|
||||||
if((m_radix == 10) && IsNumberInvalid(m_numberString, MAX_EXPONENT, m_precision, m_radix))
|
if ((m_radix == 10) && IsNumberInvalid(m_numberString, MAX_EXPONENT, m_precision, m_radix))
|
||||||
{
|
{
|
||||||
DisplayError(CALC_E_OVERFLOW);
|
DisplayError(CALC_E_OVERFLOW);
|
||||||
}
|
}
|
||||||
@ -268,7 +257,7 @@ wstring CCalcEngine::GroupDigitsPerRadix(wstring_view numberString, uint32_t rad
|
|||||||
switch (radix)
|
switch (radix)
|
||||||
{
|
{
|
||||||
case 10:
|
case 10:
|
||||||
return GroupDigits(wstring{ m_groupSeparator }, m_decGrouping, numberString, (L'-' == numberString[0]));
|
return GroupDigits(wstring{ m_groupSeparator }, m_decGrouping, numberString, (L'-' == numberString[0]));
|
||||||
case 8:
|
case 8:
|
||||||
return GroupDigits(L" ", { 3, 0 }, numberString);
|
return GroupDigits(L" ", { 3, 0 }, numberString);
|
||||||
case 2:
|
case 2:
|
||||||
|
@ -21,273 +21,193 @@
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace CalcEngine;
|
using namespace CalcEngine;
|
||||||
|
using namespace CalcEngine::RationalMath;
|
||||||
|
|
||||||
/* Routines for more complex mathematical functions/error checking. */
|
/* Routines for more complex mathematical functions/error checking. */
|
||||||
CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& rat, DWORD op)
|
CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& rat, DWORD op)
|
||||||
{
|
{
|
||||||
PRAT tempRat = rat.ToPRAT();
|
Rational result{};
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
switch (op)
|
switch (op)
|
||||||
{
|
{
|
||||||
case IDC_CHOP:
|
case IDC_CHOP:
|
||||||
m_bInv ? fracrat(&tempRat , m_radix, m_precision) : intrat(&tempRat, m_radix, m_precision);
|
result = m_bInv ? Frac(rat, m_radix, m_precision) : Integer(rat, m_radix, m_precision);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Return complement. */
|
/* Return complement. */
|
||||||
case IDC_COM:
|
case IDC_COM:
|
||||||
{
|
result = rat.Not(m_fIntegerMode, m_chopNumbers[m_numwidth], m_radix, m_precision);
|
||||||
PRAT chopRat = m_chopNumbers[m_numwidth].ToPRAT();
|
break;
|
||||||
NumObjNot(&tempRat, m_fIntegerMode, chopRat, m_radix, m_precision);
|
|
||||||
destroyrat(chopRat);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rotate Left with hi bit wrapped over to lo bit
|
// Rotate Left with hi bit wrapped over to lo bit
|
||||||
case IDC_ROL:
|
case IDC_ROL:
|
||||||
if (m_fIntegerMode)
|
if (m_fIntegerMode)
|
||||||
{
|
{
|
||||||
intrat(&tempRat, m_radix, m_precision);
|
result = Integer(rat, m_radix, m_precision);
|
||||||
|
|
||||||
PRAT curRat = m_currentVal.ToPRAT();
|
uint64_t w64Bits = result.ToUInt64_t(m_radix, m_precision);
|
||||||
ULONGLONG w64Bits = NumObjGetUlValue(curRat, m_radix, m_precision);
|
uint64_t msb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1;
|
||||||
ULONGLONG msb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1;
|
w64Bits <<= 1; // LShift by 1
|
||||||
|
w64Bits |= msb; // Set the prev Msb as the current Lsb
|
||||||
|
|
||||||
w64Bits <<= 1; // LShift by 1
|
result = Rational{ w64Bits, m_radix, m_precision };
|
||||||
w64Bits |= msb; // Set the prev Msb as the current Lsb
|
}
|
||||||
NumObjSetUlonglongValue(&curRat, w64Bits, m_radix, m_precision);
|
break;
|
||||||
m_currentVal = Rational{ curRat };
|
|
||||||
destroyrat(curRat);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Rotate right with lo bit wrapped over to hi bit
|
// Rotate right with lo bit wrapped over to hi bit
|
||||||
case IDC_ROR:
|
case IDC_ROR:
|
||||||
if (m_fIntegerMode)
|
if (m_fIntegerMode)
|
||||||
{
|
|
||||||
intrat(&tempRat, m_radix, m_precision);
|
|
||||||
PRAT curRat = m_currentVal.ToPRAT();
|
|
||||||
ULONGLONG w64Bits = NumObjGetUlValue(curRat, m_radix, m_precision);
|
|
||||||
|
|
||||||
ULONGLONG lsb = ((w64Bits & 0x01) == 1) ? 1 : 0;
|
|
||||||
w64Bits >>= 1; //RShift by 1
|
|
||||||
w64Bits |= (lsb << (m_dwWordBitWidth - 1));
|
|
||||||
NumObjSetUlonglongValue(&curRat, w64Bits, m_radix, m_precision);
|
|
||||||
m_currentVal = Rational{ curRat };
|
|
||||||
destroyrat(curRat);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case IDC_PERCENT:
|
|
||||||
{
|
{
|
||||||
PRAT hno = nullptr;
|
result = Integer(rat, m_radix, m_precision);
|
||||||
PRAT hno100 = nullptr;
|
|
||||||
|
|
||||||
try
|
uint64_t w64Bits = result.ToUInt64_t(m_radix, m_precision);
|
||||||
{
|
uint64_t lsb = ((w64Bits & 0x01) == 1) ? 1 : 0;
|
||||||
// If the operator is multiply/divide, we evaluate this as "X [op] (Y%)"
|
w64Bits >>= 1; //RShift by 1
|
||||||
// Otherwise, we evaluate it as "X [op] (X * Y%)"
|
w64Bits |= (lsb << (m_dwWordBitWidth - 1));
|
||||||
if (m_nOpCode == IDC_MUL || m_nOpCode == IDC_DIV)
|
|
||||||
{
|
|
||||||
NumObjSetIntValue(&hno100, 100);
|
|
||||||
|
|
||||||
divrat(&tempRat, hno100, m_precision);
|
result = Rational{ w64Bits, m_radix, m_precision };
|
||||||
destroyrat(hno100);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
hno = m_lastVal.ToPRAT();
|
|
||||||
NumObjSetIntValue(&hno100, 100);
|
|
||||||
|
|
||||||
divrat(&hno, hno100, m_precision);
|
|
||||||
destroyrat(hno100);
|
|
||||||
|
|
||||||
mulrat(&tempRat, hno, m_precision);
|
|
||||||
destroyrat(hno);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch ( DWORD nErrCode )
|
|
||||||
{
|
|
||||||
destroyrat(hno);
|
|
||||||
destroyrat(hno100);
|
|
||||||
destroyrat(tempRat);
|
|
||||||
throw nErrCode;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case IDC_SIN: /* Sine; normal and arc */
|
case IDC_PERCENT:
|
||||||
if (!m_fIntegerMode)
|
{
|
||||||
{
|
// If the operator is multiply/divide, we evaluate this as "X [op] (Y%)"
|
||||||
m_bInv ? asinanglerat(&tempRat, m_angletype, m_radix, m_precision) : NumObjSin(&tempRat, m_angletype, m_radix, m_precision);
|
// Otherwise, we evaluate it as "X [op] (X * Y%)"
|
||||||
}
|
if (m_nOpCode == IDC_MUL || m_nOpCode == IDC_DIV)
|
||||||
break;
|
|
||||||
|
|
||||||
case IDC_SINH: /* Sine- hyperbolic and archyperbolic */
|
|
||||||
if (!m_fIntegerMode)
|
|
||||||
{
|
|
||||||
m_bInv ? asinhrat(&tempRat, m_radix, m_precision) : sinhrat(&tempRat, m_radix, m_precision);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case IDC_COS: /* Cosine, follows convention of sine function. */
|
|
||||||
if (!m_fIntegerMode)
|
|
||||||
{
|
|
||||||
m_bInv ? acosanglerat(&tempRat, m_angletype, m_radix, m_precision) : NumObjCos(&tempRat, m_angletype, m_radix, m_precision);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case IDC_COSH: /* Cosine hyperbolic, follows convention of sine h function. */
|
|
||||||
if (!m_fIntegerMode)
|
|
||||||
{
|
|
||||||
m_bInv ? acoshrat(&tempRat, m_radix, m_precision) : coshrat(&tempRat, m_radix, m_precision);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case IDC_TAN: /* Same as sine and cosine. */
|
|
||||||
if (!m_fIntegerMode)
|
|
||||||
{
|
|
||||||
m_bInv ? atananglerat(&tempRat, m_angletype, m_radix, m_precision) : NumObjTan(&tempRat, m_angletype, m_radix, m_precision);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case IDC_TANH: /* Same as sine h and cosine h. */
|
|
||||||
if (!m_fIntegerMode)
|
|
||||||
{
|
|
||||||
m_bInv ? atanhrat(&tempRat, m_precision) : tanhrat(&tempRat, m_radix, m_precision);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case IDC_REC: /* Reciprocal. */
|
|
||||||
NumObjInvert(&tempRat, m_precision);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case IDC_SQR: /* Square */
|
|
||||||
powrat(&tempRat, rat_two, m_radix, m_precision);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case IDC_SQRT: /* Sqrt only in Std mode */
|
|
||||||
rootrat(&tempRat, rat_two, m_radix, m_precision);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case IDC_CUBEROOT:
|
|
||||||
case IDC_CUB: /* Cubing and cube root functions. */
|
|
||||||
{
|
{
|
||||||
PRAT hno = nullptr;
|
result = rat.Div(100, m_precision);
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
NumObjAssign(&hno, rat_one);
|
|
||||||
addrat(&hno, rat_two, m_precision);
|
|
||||||
|
|
||||||
if (IDC_CUBEROOT == op)
|
|
||||||
{
|
|
||||||
rootrat(&tempRat, hno, m_radix, m_precision);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
powrat(&tempRat, hno, m_radix, m_precision);
|
|
||||||
}
|
|
||||||
|
|
||||||
destroyrat(hno);
|
|
||||||
}
|
|
||||||
catch (DWORD nErrCode)
|
|
||||||
{
|
|
||||||
destroyrat(hno);
|
|
||||||
destroyrat(tempRat);
|
|
||||||
throw nErrCode;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
case IDC_LOG: /* Functions for common log. */
|
|
||||||
log10rat(&tempRat, m_precision);
|
|
||||||
break;
|
|
||||||
case IDC_POW10:
|
|
||||||
NumObjAntiLog10(&tempRat, m_radix, m_precision);
|
|
||||||
break;
|
|
||||||
case IDC_LN: /* Functions for natural log. */
|
|
||||||
if (m_bInv)
|
|
||||||
{
|
|
||||||
exprat(&tempRat, m_radix, m_precision); // e^x.
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lograt(&tempRat, m_precision);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case IDC_FAC: /* Calculate factorial. Inverse is ineffective. */
|
|
||||||
factrat(&tempRat, m_radix, m_precision);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case IDC_DEGREES:
|
|
||||||
ProcessCommand(IDC_INV);
|
|
||||||
// This case falls through to IDC_DMS case because in the old Win32 Calc,
|
|
||||||
// the degrees functionality was achieved as 'Inv' of 'dms' operation,
|
|
||||||
// so setting the IDC_INV command first and then performing 'dms' operation as global variables m_bInv, m_bRecord
|
|
||||||
// are set properly through ProcessCommand(IDC_INV)
|
|
||||||
case IDC_DMS:
|
|
||||||
{
|
{
|
||||||
if (!m_fIntegerMode)
|
result = m_lastVal.Div(100, m_precision);
|
||||||
{
|
result = rat.Mul(result, m_precision);
|
||||||
PRAT hnoMin = nullptr;
|
|
||||||
PRAT hnoSec = nullptr;
|
|
||||||
PRAT hnoShft = nullptr;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
NumObjSetIntValue(&hnoShft, m_bInv ? 100 : 60);
|
|
||||||
|
|
||||||
NumObjAssign(&hnoMin, tempRat);
|
|
||||||
intrat(&tempRat, m_radix, m_precision);
|
|
||||||
|
|
||||||
subrat(&hnoMin, tempRat, m_precision);
|
|
||||||
mulrat(&hnoMin, hnoShft, m_precision);
|
|
||||||
NumObjAssign(&hnoSec, hnoMin );
|
|
||||||
intrat(&hnoMin, m_radix, m_precision);
|
|
||||||
|
|
||||||
subrat(&hnoSec, hnoMin, m_precision);
|
|
||||||
mulrat(&hnoSec, hnoShft, m_precision);
|
|
||||||
|
|
||||||
//
|
|
||||||
// tempRat == degrees, hnoMin == minutes, hnoSec == seconds
|
|
||||||
//
|
|
||||||
|
|
||||||
NumObjSetIntValue(&hnoShft, m_bInv ? 60 : 100);
|
|
||||||
divrat(&hnoSec, hnoShft, m_precision);
|
|
||||||
addrat(&hnoMin, hnoSec, m_precision);
|
|
||||||
|
|
||||||
divrat(&hnoMin, hnoShft, m_precision);
|
|
||||||
addrat(&tempRat, hnoMin, m_precision);
|
|
||||||
|
|
||||||
destroyrat(hnoShft);
|
|
||||||
destroyrat(hnoMin);
|
|
||||||
destroyrat(hnoSec);
|
|
||||||
}
|
|
||||||
catch (DWORD nErrCode)
|
|
||||||
{
|
|
||||||
destroyrat(hnoShft);
|
|
||||||
destroyrat(hnoMin);
|
|
||||||
destroyrat(hnoSec);
|
|
||||||
destroyrat(tempRat);
|
|
||||||
throw nErrCode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case IDC_SIN: /* Sine; normal and arc */
|
||||||
|
if (!m_fIntegerMode)
|
||||||
|
{
|
||||||
|
result = m_bInv ? ASin(rat, m_angletype, m_radix, m_precision) : Sin(rat, m_angletype, m_radix, m_precision);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IDC_SINH: /* Sine- hyperbolic and archyperbolic */
|
||||||
|
if (!m_fIntegerMode)
|
||||||
|
{
|
||||||
|
result = m_bInv ? ASinh(rat, m_radix, m_precision) : Sinh(rat, m_radix, m_precision);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IDC_COS: /* Cosine, follows convention of sine function. */
|
||||||
|
if (!m_fIntegerMode)
|
||||||
|
{
|
||||||
|
result = m_bInv ? ACos(rat, m_angletype, m_radix, m_precision) : Cos(rat, m_angletype, m_radix, m_precision);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IDC_COSH: /* Cosine hyperbolic, follows convention of sine h function. */
|
||||||
|
if (!m_fIntegerMode)
|
||||||
|
{
|
||||||
|
result = m_bInv ? ACosh(rat, m_radix, m_precision) : Cosh(rat, m_radix, m_precision);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IDC_TAN: /* Same as sine and cosine. */
|
||||||
|
if (!m_fIntegerMode)
|
||||||
|
{
|
||||||
|
result = m_bInv ? ATan(rat, m_angletype, m_radix, m_precision) : Tan(rat, m_angletype, m_radix, m_precision);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IDC_TANH: /* Same as sine h and cosine h. */
|
||||||
|
if (!m_fIntegerMode)
|
||||||
|
{
|
||||||
|
result = m_bInv ? ATanh(rat, m_precision) : Tanh(rat, m_radix, m_precision);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IDC_REC: /* Reciprocal. */
|
||||||
|
result = Invert(rat, m_precision);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IDC_SQR: /* Square */
|
||||||
|
result = Pow(rat, 2, m_radix, m_precision);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IDC_SQRT: /* Square Root */
|
||||||
|
result = Root(rat, 2, m_radix, m_precision);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IDC_CUBEROOT:
|
||||||
|
case IDC_CUB: /* Cubing and cube root functions. */
|
||||||
|
result = IDC_CUBEROOT == op ? Root(rat, 3, m_radix, m_precision) : Pow(rat, 3, m_radix, m_precision);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IDC_LOG: /* Functions for common log. */
|
||||||
|
result = Log10(rat, m_precision);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IDC_POW10:
|
||||||
|
result = Pow(10, rat, m_radix, m_precision);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IDC_LN: /* Functions for natural log. */
|
||||||
|
result = m_bInv ? Exp(rat, m_radix, m_precision) : Log(rat, m_precision);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IDC_FAC: /* Calculate factorial. Inverse is ineffective. */
|
||||||
|
result = Fact(rat, m_radix, m_precision);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IDC_DEGREES:
|
||||||
|
ProcessCommand(IDC_INV);
|
||||||
|
// This case falls through to IDC_DMS case because in the old Win32 Calc,
|
||||||
|
// the degrees functionality was achieved as 'Inv' of 'dms' operation,
|
||||||
|
// so setting the IDC_INV command first and then performing 'dms' operation as global variables m_bInv, m_bRecord
|
||||||
|
// are set properly through ProcessCommand(IDC_INV)
|
||||||
|
case IDC_DMS:
|
||||||
|
{
|
||||||
|
if (!m_fIntegerMode)
|
||||||
|
{
|
||||||
|
Rational shftRat{ m_bInv ? 100 : 60 };
|
||||||
|
|
||||||
|
Rational degreeRat = Integer(rat, m_radix, m_precision);
|
||||||
|
|
||||||
|
Rational minuteRat = rat.Sub(degreeRat, m_precision);
|
||||||
|
minuteRat = minuteRat.Mul(shftRat, m_precision);
|
||||||
|
|
||||||
|
Rational secondRat = minuteRat;
|
||||||
|
|
||||||
|
minuteRat = Integer(minuteRat, m_radix, m_precision);
|
||||||
|
|
||||||
|
secondRat = secondRat.Sub(minuteRat, m_precision);
|
||||||
|
secondRat = secondRat.Mul(shftRat, m_precision);
|
||||||
|
|
||||||
|
//
|
||||||
|
// degreeRat == degrees, minuteRat == minutes, secondRat == seconds
|
||||||
|
//
|
||||||
|
|
||||||
|
shftRat = Rational{ m_bInv ? 60 : 100 };
|
||||||
|
secondRat = secondRat.Div(shftRat, m_precision);
|
||||||
|
|
||||||
|
minuteRat = minuteRat.Add(secondRat, m_precision);
|
||||||
|
minuteRat = minuteRat.Div(shftRat, m_precision);
|
||||||
|
|
||||||
|
result = degreeRat.Add(minuteRat, m_precision);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
} // end switch( op )
|
} // end switch( op )
|
||||||
|
|
||||||
Rational result{ tempRat };
|
|
||||||
destroyrat(tempRat);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
catch(DWORD nErrCode)
|
catch (DWORD nErrCode)
|
||||||
{
|
{
|
||||||
DisplayError(nErrCode);
|
DisplayError(nErrCode);
|
||||||
destroyrat(tempRat);
|
result = rat;
|
||||||
return rat;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Routine to display error messages and set m_bError flag. Errors are */
|
/* Routine to display error messages and set m_bError flag. Errors are */
|
||||||
|
@ -3,204 +3,388 @@
|
|||||||
|
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "Header Files/CalcEngine.h"
|
#include "Header Files/CalcEngine.h"
|
||||||
|
#include "Ratpack/ratpak.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
using namespace CalcEngine;
|
||||||
|
|
||||||
/**************************************************************************\
|
Rational RationalMath::Frac(Rational const& rat, uint32_t radix, int32_t precision)
|
||||||
* *
|
|
||||||
* *
|
|
||||||
* *
|
|
||||||
* # # ##### *
|
|
||||||
* # # # # # *
|
|
||||||
* # # # # # # # *
|
|
||||||
* # ### ### # # *
|
|
||||||
* # # ### # # # ### # # ### ##### # ### ### ### *
|
|
||||||
* # ## # # # ## # # # # # # ## # # # *
|
|
||||||
* # # # # # # # # # ##### # # ##### # *
|
|
||||||
* # # # # # # # # # # # # # # ## *
|
|
||||||
* # # # # # # # # # ### # # ### ### ## *
|
|
||||||
* *
|
|
||||||
* *
|
|
||||||
* Infinte Precision Production Version *
|
|
||||||
* *
|
|
||||||
\**************************************************************************/
|
|
||||||
//
|
|
||||||
// RETAIL version of NUMOBJ math that uses Infinite Precision
|
|
||||||
//
|
|
||||||
// History
|
|
||||||
//
|
|
||||||
// 16-Nov-1996 Wrote it
|
|
||||||
// whenever-97 Rewrote it using improved ratpak model
|
|
||||||
//
|
|
||||||
|
|
||||||
/*****************************************************************\
|
|
||||||
*
|
|
||||||
* Generic Math Package support routines and variables
|
|
||||||
*
|
|
||||||
* History:
|
|
||||||
* 01-Dec-1996 Wrote them
|
|
||||||
* whenever-97 Rewrote them
|
|
||||||
*
|
|
||||||
\*****************************************************************/
|
|
||||||
|
|
||||||
/*****************************************************************\
|
|
||||||
*
|
|
||||||
* Unary functions
|
|
||||||
*
|
|
||||||
* History:
|
|
||||||
* 01-Dec-1996 Wrote them
|
|
||||||
* whenever-97 Rewrote them
|
|
||||||
*
|
|
||||||
\*****************************************************************/
|
|
||||||
|
|
||||||
void NumObjInvert(PRAT * phno, int32_t precision)
|
|
||||||
{
|
{
|
||||||
PRAT hno = nullptr;
|
PRAT prat = rat.ToPRAT();
|
||||||
|
try
|
||||||
NumObjAssign( &hno, rat_one);
|
|
||||||
divrat( &hno, *phno, precision);
|
|
||||||
NumObjAssign( phno, hno );
|
|
||||||
NumObjDestroy( &hno );
|
|
||||||
}
|
|
||||||
|
|
||||||
void NumObjNegate(PRAT *phno)
|
|
||||||
{
|
|
||||||
(*phno)->pp->sign = -(*phno)->pp->sign;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NumObjAbs(PRAT *phno)
|
|
||||||
{
|
|
||||||
(*phno)->pp->sign = 1;
|
|
||||||
(*phno)->pq->sign = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NumObjAntiLog10(PRAT *phno, uint32_t radix, int32_t precision)
|
|
||||||
{
|
|
||||||
PRAT hno = nullptr;
|
|
||||||
|
|
||||||
NumObjSetIntValue( &hno, 10 );
|
|
||||||
powrat( &hno, *phno, radix, precision);
|
|
||||||
NumObjAssign( phno, hno );
|
|
||||||
NumObjDestroy( &hno );
|
|
||||||
}
|
|
||||||
|
|
||||||
void NumObjNot(PRAT *phno, bool fIntegerMode, PRAT chopNum, uint32_t radix, int32_t precision)
|
|
||||||
{
|
|
||||||
if (radix == 10 && !fIntegerMode)
|
|
||||||
{
|
{
|
||||||
intrat( phno, radix, precision);
|
fracrat(&prat, radix, precision);
|
||||||
addrat( phno, rat_one, precision);
|
|
||||||
NumObjNegate( phno );
|
|
||||||
}
|
}
|
||||||
else
|
catch (DWORD error)
|
||||||
{
|
{
|
||||||
|
destroyrat(prat);
|
||||||
xorrat( phno, chopNum, radix, precision);
|
throw(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rational result{ prat };
|
||||||
|
destroyrat(prat);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NumObjSin(PRAT *phno, ANGLE_TYPE angletype, uint32_t radix, int32_t precision )
|
Rational RationalMath::Integer(Rational const& rat, uint32_t radix, int32_t precision)
|
||||||
{
|
{
|
||||||
sinanglerat(phno, angletype, radix, precision);
|
PRAT prat = rat.ToPRAT();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
intrat(&prat, radix, precision);
|
||||||
|
}
|
||||||
|
catch (DWORD error)
|
||||||
|
{
|
||||||
|
destroyrat(prat);
|
||||||
|
throw(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational result{ prat };
|
||||||
|
destroyrat(prat);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NumObjCos(PRAT *phno, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
|
Rational RationalMath::Pow(Rational const& base, Rational const& pow, uint32_t radix, int32_t precision)
|
||||||
{
|
{
|
||||||
cosanglerat(phno, angletype, radix, precision);
|
PRAT baseRat = base.ToPRAT();
|
||||||
|
PRAT powRat = pow.ToPRAT();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
powrat(&baseRat, powRat, radix, precision);
|
||||||
|
destroyrat(powRat);
|
||||||
|
}
|
||||||
|
catch (DWORD error)
|
||||||
|
{
|
||||||
|
destroyrat(baseRat);
|
||||||
|
destroyrat(powRat);
|
||||||
|
throw(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational result{ baseRat };
|
||||||
|
destroyrat(baseRat);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NumObjTan(PRAT *phno, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
|
Rational RationalMath::Root(Rational const& base, Rational const& root, uint32_t radix, int32_t precision)
|
||||||
{
|
{
|
||||||
tananglerat(phno, angletype, radix, precision);
|
return Pow(base, Invert(root, precision), radix, precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************\
|
Rational RationalMath::Fact(Rational const& rat, uint32_t radix, int32_t precision)
|
||||||
*
|
|
||||||
* Number format conversion routines
|
|
||||||
*
|
|
||||||
* History:
|
|
||||||
* 06-Dec-1996 wrote them
|
|
||||||
\******************************************************************/
|
|
||||||
void NumObjSetIntValue(PRAT *phnol, LONG i )
|
|
||||||
{
|
{
|
||||||
PRAT pr = nullptr;
|
PRAT prat = rat.ToPRAT();
|
||||||
|
|
||||||
pr = longtorat( i );
|
try
|
||||||
NumObjAssign( phnol, pr );
|
{
|
||||||
destroyrat(pr);
|
factrat(&prat, radix, precision);
|
||||||
|
}
|
||||||
|
catch (DWORD error)
|
||||||
|
{
|
||||||
|
destroyrat(prat);
|
||||||
|
throw(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational result{ prat };
|
||||||
|
destroyrat(prat);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NumObjSetIUlongValue(PRAT *phnol, ULONG ul )
|
Rational RationalMath::Exp(Rational const& rat, uint32_t radix, int32_t precision)
|
||||||
{
|
{
|
||||||
PRAT pr = nullptr;
|
PRAT prat = rat.ToPRAT();
|
||||||
|
|
||||||
pr = Ulongtorat( ul );
|
try
|
||||||
NumObjAssign( phnol, pr );
|
{
|
||||||
destroyrat(pr);
|
exprat(&prat, radix, precision);
|
||||||
|
}
|
||||||
|
catch (DWORD error)
|
||||||
|
{
|
||||||
|
destroyrat(prat);
|
||||||
|
throw(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational result{ prat };
|
||||||
|
destroyrat(prat);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Set with 64 bit number
|
Rational RationalMath::Log(Rational const& rat, int32_t precision)
|
||||||
void NumObjSetUlonglongValue(PRAT *phnol, ULONGLONG ul, uint32_t radix, int32_t precision)
|
|
||||||
{
|
{
|
||||||
ULONG hi, lo;
|
PRAT prat = rat.ToPRAT();
|
||||||
PRAT hno = nullptr;
|
|
||||||
|
|
||||||
hi = HIDWORD(ul);
|
try
|
||||||
lo = LODWORD(ul);
|
{
|
||||||
NumObjSetIUlongValue(phnol, hi);
|
lograt(&prat, precision);
|
||||||
NumObjSetIntValue(&hno, 32);
|
}
|
||||||
lshrat(phnol, hno, radix, precision);
|
catch (DWORD error)
|
||||||
NumObjSetIUlongValue(&hno, lo);
|
{
|
||||||
orrat(phnol, hno, radix, precision);
|
destroyrat(prat);
|
||||||
NumObjDestroy(&hno);
|
throw(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational result{ prat };
|
||||||
|
destroyrat(prat);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONGLONG NumObjGetUlValue( PRAT hnol, uint32_t radix, int32_t precision)
|
Rational RationalMath::Log10(Rational const& rat, int32_t precision)
|
||||||
{
|
{
|
||||||
return rattoUlonglong(hnol, radix, precision);
|
return Log(rat, precision).Div(10, precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
wstring NumObjToString(PRAT hnoNum, uint32_t radix, NUMOBJ_FMT fmt, int32_t precision)
|
Rational RationalMath::Invert(Rational const& rat, int32_t precision)
|
||||||
{
|
{
|
||||||
return RatToString(hnoNum, fmt, radix, precision);
|
return Rational{ 1 }.Div(rat, precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NumObjIsZero(PRAT hno)
|
Rational RationalMath::Abs(Rational const& rat)
|
||||||
{
|
{
|
||||||
return zerrat(hno);
|
return Rational{ Number{ 1, rat.P().Exp(), rat.P().Mantissa() }, Number{ 1, rat.Q().Exp(), rat.Q().Mantissa() } };
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NumObjIsLess(PRAT hno1, PRAT hno2, int32_t precision)
|
Rational RationalMath::Sin(Rational const& rat, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
|
||||||
{
|
{
|
||||||
return rat_lt(hno1, hno2, precision);
|
PRAT prat = rat.ToPRAT();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
sinanglerat(&prat, angletype, radix, precision);
|
||||||
|
}
|
||||||
|
catch (DWORD error)
|
||||||
|
{
|
||||||
|
destroyrat(prat);
|
||||||
|
throw(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational result{ prat };
|
||||||
|
destroyrat(prat);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NumObjIsLessEq(PRAT hno1, PRAT hno2, int32_t precision)
|
Rational RationalMath::Cos(Rational const& rat, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
|
||||||
{
|
{
|
||||||
return rat_le(hno1, hno2, precision);
|
PRAT prat = rat.ToPRAT();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
cosanglerat(&prat, angletype, radix, precision);
|
||||||
|
}
|
||||||
|
catch (DWORD error)
|
||||||
|
{
|
||||||
|
destroyrat(prat);
|
||||||
|
throw(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational result{ prat };
|
||||||
|
destroyrat(prat);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NumObjIsGreaterEq(PRAT hno1, PRAT hno2, int32_t precision)
|
Rational RationalMath::Tan(Rational const& rat, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
|
||||||
{
|
{
|
||||||
return rat_ge(hno1, hno2, precision);
|
PRAT prat = rat.ToPRAT();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
tananglerat(&prat, angletype, radix, precision);
|
||||||
|
}
|
||||||
|
catch (DWORD error)
|
||||||
|
{
|
||||||
|
destroyrat(prat);
|
||||||
|
throw(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational result{ prat };
|
||||||
|
destroyrat(prat);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NumObjIsEq(PRAT hno1, PRAT hno2, int32_t precision)
|
Rational RationalMath::ASin(Rational const& rat, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
|
||||||
{
|
{
|
||||||
return rat_equ(hno1, hno2, precision);
|
PRAT prat = rat.ToPRAT();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
asinanglerat(&prat, angletype, radix, precision);
|
||||||
|
}
|
||||||
|
catch (DWORD error)
|
||||||
|
{
|
||||||
|
destroyrat(prat);
|
||||||
|
throw(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational result{ prat };
|
||||||
|
destroyrat(prat);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NumObjAssign(PRAT *phnol, PRAT hnor)
|
Rational RationalMath::ACos(Rational const& rat, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
|
||||||
{
|
{
|
||||||
DUPRAT(*phnol, hnor);
|
PRAT prat = rat.ToPRAT();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
acosanglerat(&prat, angletype, radix, precision);
|
||||||
|
}
|
||||||
|
catch (DWORD error)
|
||||||
|
{
|
||||||
|
destroyrat(prat);
|
||||||
|
throw(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational result{ prat };
|
||||||
|
destroyrat(prat);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t NumObjGetExp(PRAT hno)
|
Rational RationalMath::ATan(Rational const& rat, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
|
||||||
{
|
{
|
||||||
return LOGRATRADIX(hno);
|
PRAT prat = rat.ToPRAT();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
atananglerat(&prat, angletype, radix, precision);
|
||||||
|
}
|
||||||
|
catch (DWORD error)
|
||||||
|
{
|
||||||
|
destroyrat(prat);
|
||||||
|
throw(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational result{ prat };
|
||||||
|
destroyrat(prat);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NumObjDestroy(PRAT *phno)
|
Rational RationalMath::Sinh(Rational const& rat, uint32_t radix, int32_t precision)
|
||||||
{
|
{
|
||||||
destroyrat(*phno);
|
PRAT prat = rat.ToPRAT();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
sinhrat(&prat, radix, precision);
|
||||||
|
}
|
||||||
|
catch (DWORD error)
|
||||||
|
{
|
||||||
|
destroyrat(prat);
|
||||||
|
throw(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational result{ prat };
|
||||||
|
destroyrat(prat);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational RationalMath::Cosh(Rational const& rat, uint32_t radix, int32_t precision)
|
||||||
|
{
|
||||||
|
PRAT prat = rat.ToPRAT();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
coshrat(&prat, radix, precision);
|
||||||
|
}
|
||||||
|
catch (DWORD error)
|
||||||
|
{
|
||||||
|
destroyrat(prat);
|
||||||
|
throw(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational result{ prat };
|
||||||
|
destroyrat(prat);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational RationalMath::Tanh(Rational const& rat, uint32_t radix, int32_t precision)
|
||||||
|
{
|
||||||
|
PRAT prat = rat.ToPRAT();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
tanhrat(&prat, radix, precision);
|
||||||
|
}
|
||||||
|
catch (DWORD error)
|
||||||
|
{
|
||||||
|
destroyrat(prat);
|
||||||
|
throw(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational result{ prat };
|
||||||
|
destroyrat(prat);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational RationalMath::ASinh(Rational const& rat, uint32_t radix, int32_t precision)
|
||||||
|
{
|
||||||
|
PRAT prat = rat.ToPRAT();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
asinhrat(&prat, radix, precision);
|
||||||
|
}
|
||||||
|
catch (DWORD error)
|
||||||
|
{
|
||||||
|
destroyrat(prat);
|
||||||
|
throw(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational result{ prat };
|
||||||
|
destroyrat(prat);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational RationalMath::ACosh(Rational const& rat, uint32_t radix, int32_t precision)
|
||||||
|
{
|
||||||
|
PRAT prat = rat.ToPRAT();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
acoshrat(&prat, radix, precision);
|
||||||
|
}
|
||||||
|
catch (DWORD error)
|
||||||
|
{
|
||||||
|
destroyrat(prat);
|
||||||
|
throw(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational result{ prat };
|
||||||
|
destroyrat(prat);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational RationalMath::ATanh(Rational const& rat, int32_t precision)
|
||||||
|
{
|
||||||
|
PRAT prat = rat.ToPRAT();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
atanhrat(&prat, precision);
|
||||||
|
}
|
||||||
|
catch (DWORD error)
|
||||||
|
{
|
||||||
|
destroyrat(prat);
|
||||||
|
throw(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
Rational result{ prat };
|
||||||
|
destroyrat(prat);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -5,181 +5,135 @@
|
|||||||
#include "Header Files/CalcEngine.h"
|
#include "Header Files/CalcEngine.h"
|
||||||
|
|
||||||
using namespace CalcEngine;
|
using namespace CalcEngine;
|
||||||
|
using namespace CalcEngine::RationalMath;
|
||||||
|
|
||||||
// Routines to perform standard operations &|^~<<>>+-/*% and pwr.
|
// Routines to perform standard operations &|^~<<>>+-/*% and pwr.
|
||||||
CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rational const& lhs, CalcEngine::Rational const& rhs)
|
CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rational const& lhs, CalcEngine::Rational const& rhs)
|
||||||
{
|
{
|
||||||
PRAT rhsRat = rhs.ToPRAT();
|
|
||||||
PRAT hno = nullptr;
|
|
||||||
|
|
||||||
// Remove any variance in how 0 could be represented in rat e.g. -0, 0/n, etc.
|
// Remove any variance in how 0 could be represented in rat e.g. -0, 0/n, etc.
|
||||||
PRAT resultRat = nullptr;
|
auto result = (!lhs.IsZero() ? lhs : Rational{});
|
||||||
if (lhs.IsZero())
|
|
||||||
{
|
|
||||||
NumObjAssign(&resultRat, rat_zero);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
resultRat = lhs.ToPRAT();
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
switch (operation)
|
switch (operation)
|
||||||
{
|
{
|
||||||
case IDC_AND:
|
case IDC_AND:
|
||||||
andrat(&resultRat, rhsRat, m_radix, m_precision);
|
result = result.And(rhs, m_radix, m_precision);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_OR:
|
case IDC_OR:
|
||||||
orrat(&resultRat, rhsRat, m_radix, m_precision);
|
result = result.Or(rhs, m_radix, m_precision);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_XOR:
|
case IDC_XOR:
|
||||||
xorrat(&resultRat, rhsRat, m_radix, m_precision);
|
result = result.Xor(rhs, m_radix, m_precision);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_RSHF:
|
case IDC_RSHF:
|
||||||
{
|
{
|
||||||
if (m_fIntegerMode)
|
if (m_fIntegerMode && result.IsGreaterEq(Rational{ m_dwWordBitWidth }, m_precision)) // Lsh/Rsh >= than current word size is always 0
|
||||||
{
|
{
|
||||||
NumObjSetIntValue(&hno, m_dwWordBitWidth);
|
throw CALC_E_NORESULT;
|
||||||
if (NumObjIsGreaterEq(resultRat, hno, m_precision)) // Lsh/Rsh >= than current word size is always 0
|
|
||||||
{
|
|
||||||
throw CALC_E_NORESULT;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NumObjAssign(&hno, resultRat);
|
uint64_t w64Bits = rhs.ToUInt64_t(m_radix, m_precision);
|
||||||
NumObjAssign(&resultRat, rhsRat);
|
|
||||||
|
|
||||||
uint64_t w64Bits = NumObjGetUlValue(resultRat, m_radix, m_precision);
|
|
||||||
bool fMsb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1;
|
bool fMsb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1;
|
||||||
|
|
||||||
rshrat(&resultRat, hno, m_radix, m_precision);
|
Rational holdVal = result;
|
||||||
|
result = rhs.Rsh(holdVal, m_radix, m_precision);
|
||||||
|
|
||||||
if (fMsb)
|
if (fMsb)
|
||||||
{
|
{
|
||||||
intrat(&resultRat, m_radix, m_precision);
|
result = Integer(result, m_radix, m_precision);
|
||||||
PRAT temp = m_chopNumbers[m_numwidth].ToPRAT();
|
|
||||||
PRAT chopRat = m_chopNumbers[m_numwidth].ToPRAT();
|
auto tempRat = m_chopNumbers[m_numwidth].Rsh(holdVal, m_radix, m_precision);
|
||||||
rshrat(&temp, hno, m_radix, m_precision);
|
tempRat = Integer(tempRat, m_radix, m_precision);
|
||||||
intrat(&temp, m_radix, m_precision);
|
|
||||||
xorrat(&temp, chopRat, m_radix, m_precision);
|
tempRat = tempRat.Xor(m_chopNumbers[m_numwidth], m_radix, m_precision);
|
||||||
orrat(&resultRat, temp, m_radix, m_precision);
|
result = result.Or(tempRat, m_radix, m_precision);
|
||||||
destroyrat(temp);
|
|
||||||
destroyrat(chopRat);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case IDC_LSHF:
|
case IDC_LSHF:
|
||||||
if (m_fIntegerMode)
|
if (m_fIntegerMode && result.IsGreaterEq(Rational{ m_dwWordBitWidth }, m_precision)) // Lsh/Rsh >= than current word size is always 0
|
||||||
{
|
{
|
||||||
NumObjSetIntValue(&hno, m_dwWordBitWidth);
|
throw CALC_E_NORESULT;
|
||||||
if (NumObjIsGreaterEq(resultRat, hno, m_precision))
|
|
||||||
{
|
|
||||||
throw CALC_E_NORESULT;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NumObjAssign(&hno, resultRat);
|
result = rhs.Lsh(result, m_radix, m_precision);
|
||||||
NumObjAssign(&resultRat, rhsRat);
|
|
||||||
|
|
||||||
lshrat(&resultRat, hno, m_radix, m_precision);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_ADD:
|
case IDC_ADD:
|
||||||
addrat(&resultRat, rhsRat, m_precision);
|
result = result.Add(rhs, m_precision);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_SUB:
|
case IDC_SUB:
|
||||||
// in order to do ( rhsRat - resultRat ) we actually do -(resultRat - rhsRat ) because it's quicker
|
result = rhs.Sub(result, m_precision);
|
||||||
subrat(&resultRat, rhsRat, m_precision);
|
|
||||||
NumObjNegate(&resultRat);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_MUL:
|
case IDC_MUL:
|
||||||
mulrat(&resultRat, rhsRat, m_precision);
|
result = result.Mul(rhs, m_precision);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IDC_DIV:
|
case IDC_DIV:
|
||||||
case IDC_MOD:
|
case IDC_MOD:
|
||||||
|
{
|
||||||
|
int iNumeratorSign = 1, iDenominatorSign = 1, iFinalSign = 1;
|
||||||
|
auto temp = result;
|
||||||
|
result = rhs;
|
||||||
|
|
||||||
|
if (m_fIntegerMode)
|
||||||
{
|
{
|
||||||
int iNumeratorSign = 1, iDenominatorSign = 1, iFinalSign = 1;
|
uint64_t w64Bits = rhs.ToUInt64_t(m_radix, m_precision);
|
||||||
// REVIEW: These lengthly number assignments can be replaced with some quick pointer swaps.
|
bool fMsb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1;
|
||||||
// the swaps cannot change the value of pratX unless we also modify the code that calls
|
|
||||||
// the DoOperation function.
|
|
||||||
NumObjAssign(&hno, resultRat);
|
|
||||||
NumObjAssign(&resultRat, rhsRat);
|
|
||||||
|
|
||||||
if(m_fIntegerMode)
|
if (fMsb)
|
||||||
{
|
{
|
||||||
uint64_t w64Bits = NumObjGetUlValue(resultRat, m_radix, m_precision);
|
result = rhs.Not(true /* IntegerMode */, m_chopNumbers[m_numwidth], m_radix, m_precision);
|
||||||
bool fMsb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1;
|
result = result.Add(1, m_precision);
|
||||||
|
|
||||||
if (fMsb)
|
iNumeratorSign = -1;
|
||||||
{
|
|
||||||
PRAT chopRat = m_chopNumbers[m_numwidth].ToPRAT();
|
|
||||||
NumObjNot(&resultRat, true, chopRat, m_radix, m_precision);
|
|
||||||
destroyrat(chopRat);
|
|
||||||
addrat(&resultRat, rat_one, m_precision);
|
|
||||||
|
|
||||||
iNumeratorSign = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
w64Bits = NumObjGetUlValue(hno, m_radix, m_precision);
|
|
||||||
fMsb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1;
|
|
||||||
|
|
||||||
if (fMsb)
|
|
||||||
{
|
|
||||||
PRAT chopRat = m_chopNumbers[m_numwidth].ToPRAT();
|
|
||||||
NumObjNot( &hno, true, chopRat, m_radix, m_precision);
|
|
||||||
destroyrat(chopRat);
|
|
||||||
addrat( &hno, rat_one, m_precision);
|
|
||||||
|
|
||||||
iDenominatorSign = -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (operation == IDC_DIV)
|
w64Bits = temp.ToUInt64_t(m_radix, m_precision);
|
||||||
{
|
fMsb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1;
|
||||||
iFinalSign = iNumeratorSign * iDenominatorSign;
|
|
||||||
divrat(&resultRat, hno, m_precision);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
iFinalSign = iNumeratorSign;
|
|
||||||
modrat(&resultRat, hno );
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_fIntegerMode && iFinalSign == -1)
|
if (fMsb)
|
||||||
{
|
{
|
||||||
intrat(&resultRat, m_radix, m_precision);
|
temp = temp.Not(true /* IntegerMode */, m_chopNumbers[m_numwidth], m_radix, m_precision);
|
||||||
NumObjNegate(&resultRat);
|
temp = temp.Add(1, m_precision);
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
iDenominatorSign = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case IDC_PWR: // Calculates rhsRat to the resultRat(th) power.
|
if (operation == IDC_DIV)
|
||||||
{
|
{
|
||||||
NumObjAssign(&hno, resultRat);
|
iFinalSign = iNumeratorSign * iDenominatorSign;
|
||||||
NumObjAssign(&resultRat, rhsRat);
|
result = result.Div(temp, m_precision);
|
||||||
|
|
||||||
powrat(&resultRat, hno , m_radix, m_precision);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case IDC_ROOT: // Calculates rhsRat to the resultRat(th) root.
|
else
|
||||||
{
|
{
|
||||||
NumObjAssign(&hno, resultRat);
|
iFinalSign = iNumeratorSign;
|
||||||
NumObjAssign(&resultRat, rhsRat);
|
result = result.Mod(temp);
|
||||||
|
|
||||||
rootrat(&resultRat, hno, m_radix, m_precision);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_fIntegerMode && iFinalSign == -1)
|
||||||
|
{
|
||||||
|
result = Integer(result, m_radix, m_precision).Negate();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case IDC_PWR: // Calculates rhs to the result(th) power.
|
||||||
|
result = Pow(rhs, result, m_radix, m_precision);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IDC_ROOT: // Calculates rhs to the result(th) root.
|
||||||
|
result = Root(rhs, result, m_radix, m_precision);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (DWORD dwErrCode)
|
catch (DWORD dwErrCode)
|
||||||
@ -187,15 +141,8 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa
|
|||||||
DisplayError(dwErrCode);
|
DisplayError(dwErrCode);
|
||||||
|
|
||||||
// On error, return the original value
|
// On error, return the original value
|
||||||
destroyrat(resultRat);
|
result = lhs;
|
||||||
resultRat = lhs.ToPRAT();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
destroyrat(hno);
|
|
||||||
destroyrat(rhsRat);
|
|
||||||
|
|
||||||
Rational result{ resultRat };
|
|
||||||
destroyrat(resultRat);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -1,29 +1,13 @@
|
|||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*** SCICALC Scientific Calculator for Windows 3.00.12 ***/
|
|
||||||
/*** (c)1989 Microsoft Corporation. All Rights Reserved. ***/
|
|
||||||
/*** ***/
|
|
||||||
/*** sciset.c ***/
|
|
||||||
/*** ***/
|
|
||||||
/*** Functions contained: ***/
|
|
||||||
/*** ***/
|
|
||||||
/*** Functions called: ***/
|
|
||||||
/*** none ***/
|
|
||||||
/*** ***/
|
|
||||||
/*** History: ***/
|
|
||||||
/*** 12-Dec-1996 Added SetMaxIntDigits ***/
|
|
||||||
/*** Whenever-97 Removed SetMaxIntDigits ***/
|
|
||||||
/*** ***/
|
|
||||||
/**************************************************************************/
|
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "Header Files/CalcEngine.h"
|
#include "Header Files/CalcEngine.h"
|
||||||
|
|
||||||
using namespace CalcEngine;
|
using namespace CalcEngine;
|
||||||
|
using namespace CalcEngine::RationalMath;
|
||||||
|
|
||||||
//
|
// To be called when either the radix or num width changes. You can use -1 in either of these values to mean
|
||||||
// To be called when either the radix or num width changes. You can use -1 in either of these values to mean
|
|
||||||
// dont change that.
|
// dont change that.
|
||||||
void CCalcEngine::SetRadixTypeAndNumWidth(RADIX_TYPE radixtype, NUM_WIDTH numwidth)
|
void CCalcEngine::SetRadixTypeAndNumWidth(RADIX_TYPE radixtype, NUM_WIDTH numwidth)
|
||||||
{
|
{
|
||||||
@ -34,22 +18,17 @@ void CCalcEngine::SetRadixTypeAndNumWidth(RADIX_TYPE radixtype, NUM_WIDTH numwid
|
|||||||
// back to 1111,1111,1000,0001 when in Word mode.
|
// back to 1111,1111,1000,0001 when in Word mode.
|
||||||
if (m_fIntegerMode)
|
if (m_fIntegerMode)
|
||||||
{
|
{
|
||||||
PRAT curRat = m_currentVal.ToPRAT();
|
uint64_t w64Bits = m_currentVal.ToUInt64_t(m_radix, m_precision);
|
||||||
ULONGLONG w64Bits = NumObjGetUlValue(curRat, m_radix, m_precision);
|
|
||||||
bool fMsb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1; // make sure you use the old width
|
bool fMsb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1; // make sure you use the old width
|
||||||
|
|
||||||
if (fMsb)
|
if (fMsb)
|
||||||
{
|
{
|
||||||
// If high bit is set, then get the decimal number in -ve 2'scompl form.
|
// If high bit is set, then get the decimal number in -ve 2'scompl form.
|
||||||
PRAT chopRat = m_chopNumbers[m_numwidth].ToPRAT();
|
auto tempResult = m_currentVal.Not(true /* IntegerMode */, m_chopNumbers[m_numwidth], m_radix, m_precision);
|
||||||
NumObjNot(&curRat, true, chopRat, m_radix, m_precision);
|
tempResult = tempResult.Add(1, m_precision);
|
||||||
destroyrat(chopRat);
|
|
||||||
addrat(&curRat, rat_one, m_precision);
|
|
||||||
NumObjNegate(&curRat);
|
|
||||||
m_currentVal = Rational{ curRat };
|
|
||||||
}
|
|
||||||
|
|
||||||
destroyrat(curRat);
|
m_currentVal = tempResult.Negate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (radixtype >= HEX_RADIX && radixtype <= BIN_RADIX)
|
if (radixtype >= HEX_RADIX && radixtype <= BIN_RADIX)
|
||||||
@ -84,9 +63,9 @@ LONG CCalcEngine::DwWordBitWidthFromeNumWidth(NUM_WIDTH /*numwidth*/)
|
|||||||
return wmax;
|
return wmax;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t CCalcEngine::NRadixFromRadixType( RADIX_TYPE radixtype)
|
uint32_t CCalcEngine::NRadixFromRadixType(RADIX_TYPE radixtype)
|
||||||
{
|
{
|
||||||
static constexpr uint32_t rgnRadish[4]={16, 10, 8, 2}; /* Number bases in the same order as radixtype */
|
static constexpr uint32_t rgnRadish[4] = { 16, 10, 8, 2 }; /* Number bases in the same order as radixtype */
|
||||||
uint32_t radix = 10;
|
uint32_t radix = 10;
|
||||||
|
|
||||||
// convert special bases into symbolic values
|
// convert special bases into symbolic values
|
||||||
@ -106,25 +85,16 @@ bool CCalcEngine::TryToggleBit(CalcEngine::Rational& rat, DWORD wbitno)
|
|||||||
return false; // ignore error cant happen
|
return false; // ignore error cant happen
|
||||||
}
|
}
|
||||||
|
|
||||||
PRAT hnumPow = nullptr;
|
Rational result = Integer(rat, m_radix, m_precision);
|
||||||
NumObjAssign(&hnumPow, rat_two);
|
if (result.IsZero())
|
||||||
PRAT hnum = longtorat(wbitno);
|
|
||||||
powrat(&hnumPow, hnum, m_radix, m_precision);
|
|
||||||
|
|
||||||
PRAT resultRat = rat.ToPRAT();
|
|
||||||
intrat(&resultRat, m_radix, m_precision);
|
|
||||||
if (NumObjIsZero(resultRat))
|
|
||||||
{
|
{
|
||||||
// This is the same work around happenning in SciCalcFunctions. Ought to move to intrat function itself.
|
// This is the same work around happenning in SciCalcFunctions. Ought to move to intrat function itself.
|
||||||
// Basic bug is there which doesn treat 0/ n as 0, or -0 as 0 etc.
|
// Basic bug is there which doesn't treat 0/ n as 0, or -0 as 0 etc.
|
||||||
NumObjAssign(&resultRat, rat_zero);
|
result = Rational{};
|
||||||
}
|
}
|
||||||
|
|
||||||
xorrat(&resultRat, hnumPow, m_radix, m_precision);
|
auto pow = Pow(2, static_cast<int32_t>(wbitno), m_radix, m_precision);
|
||||||
rat = Rational{ resultRat };
|
rat = result.Xor(pow, m_radix, m_precision);
|
||||||
destroyrat(resultRat);
|
|
||||||
NumObjDestroy(&hnumPow);
|
|
||||||
NumObjDestroy(&hnum);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -293,9 +293,7 @@ wstring COpndCommand::GetString(uint32_t radix, int32_t precision, wchar_t decim
|
|||||||
|
|
||||||
if (m_fInitialized)
|
if (m_fInitialized)
|
||||||
{
|
{
|
||||||
PRAT valRat = m_value.ToPRAT();
|
result = m_value.ToString(radix, eNUMOBJ_FMT::FMT_FLOAT, precision);
|
||||||
result = NumObjToString(valRat, radix, eNUMOBJ_FMT::FMT_FLOAT, precision);
|
|
||||||
destroyrat(valRat);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -12,6 +12,9 @@ namespace CalcEngine
|
|||||||
Rational() noexcept;
|
Rational() noexcept;
|
||||||
Rational(Number const& n) noexcept;
|
Rational(Number const& n) noexcept;
|
||||||
Rational(Number const& p, Number const& q) noexcept;
|
Rational(Number const& p, Number const& q) noexcept;
|
||||||
|
Rational(int32_t i);
|
||||||
|
Rational(uint32_t ui);
|
||||||
|
Rational(uint64_t ui, uint32_t radix, int32_t precision);
|
||||||
|
|
||||||
explicit Rational(PRAT prat) noexcept;
|
explicit Rational(PRAT prat) noexcept;
|
||||||
PRAT ToPRAT() const;
|
PRAT ToPRAT() const;
|
||||||
@ -19,7 +22,29 @@ namespace CalcEngine
|
|||||||
Number const& P() const;
|
Number const& P() const;
|
||||||
Number const& Q() 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 Lsh(Rational const& r, uint32_t radix, int32_t precision) const;
|
||||||
|
Rational Rsh(Rational const& r, uint32_t radix, int32_t precision) const;
|
||||||
|
|
||||||
|
Rational Not(bool isIntegerMode, Rational const& chopNum, uint32_t radix, int32_t precision) const;
|
||||||
|
Rational And(Rational const& r, uint32_t radix, int32_t precision) const;
|
||||||
|
Rational Or(Rational const& r, uint32_t radix, int32_t precision) const;
|
||||||
|
Rational Xor(Rational const& r, uint32_t radix, int32_t precision) const;
|
||||||
|
|
||||||
bool IsZero() const;
|
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;
|
||||||
|
|
||||||
|
std::wstring ToString(uint32_t radix, NUMOBJ_FMT format, int32_t precision) const;
|
||||||
|
uint64_t ToUInt64_t(uint32_t radix, int32_t precision) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Number m_p;
|
Number m_p;
|
||||||
|
@ -1,79 +1,35 @@
|
|||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
/**************************************************************************\
|
#include "Rational.h"
|
||||||
* *
|
|
||||||
* *
|
|
||||||
* *
|
|
||||||
* # # ##### *
|
|
||||||
* # # # # # *
|
|
||||||
* # # # # # # # *
|
|
||||||
* # ### ### # # *
|
|
||||||
* # # ### # # # ### # # ### ##### # ### ### ### *
|
|
||||||
* # ## # # # ## # # # # # # ## # # # *
|
|
||||||
* # # # # # # # # # ##### # # ##### # *
|
|
||||||
* # # # # # # # # # # # # # # ## *
|
|
||||||
* # # # # # # # # # ### # # ### ### ## *
|
|
||||||
* *
|
|
||||||
* *
|
|
||||||
* Infinte Precision Production Version *
|
|
||||||
* *
|
|
||||||
\**************************************************************************/
|
|
||||||
//
|
|
||||||
// RETAIL version of NUMOBJ math that uses Infinite Precision
|
|
||||||
//
|
|
||||||
#include "../Ratpack/ratpak.h"
|
|
||||||
|
|
||||||
//
|
namespace CalcEngine::RationalMath
|
||||||
// Unary functions
|
{
|
||||||
//
|
Rational Frac(Rational const& rat, uint32_t radix, int32_t precision);
|
||||||
void NumObjInvert(PRAT *phno, int32_t precision);
|
Rational Integer(Rational const& rat, uint32_t radix, int32_t precision);
|
||||||
void NumObjNegate(PRAT *phno);
|
|
||||||
void NumObjAbs(PRAT *phno);
|
|
||||||
|
|
||||||
void NumObjSin(PRAT *phno, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
|
Rational Pow(Rational const& base, Rational const& pow, uint32_t radix, int32_t precision);
|
||||||
void NumObjCos(PRAT *phno, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
|
Rational Root(Rational const& base, Rational const& root, uint32_t radix, int32_t precision);
|
||||||
void NumObjTan(PRAT *phno, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
|
Rational Fact(Rational const& rat, uint32_t radix, int32_t precision);
|
||||||
void NumObjAntiLog10(PRAT *phno, uint32_t radix, int32_t precision);
|
|
||||||
|
|
||||||
void NumObjNot(PRAT *phno, bool fIntegerMode, PRAT chopNum, uint32_t radix, int32_t precision);
|
Rational Exp(Rational const& rat, uint32_t radix, int32_t precision);
|
||||||
|
Rational Log(Rational const& rat, int32_t precision);
|
||||||
|
Rational Log10(Rational const& rat, int32_t precision);
|
||||||
|
|
||||||
//
|
Rational Invert(Rational const& rat, int32_t precision);
|
||||||
// Comparison functions
|
Rational Abs(Rational const& rat);
|
||||||
//
|
|
||||||
bool NumObjIsZero(PRAT hno);
|
|
||||||
bool NumObjIsLess(PRAT hno1, PRAT hno2, int32_t precision);
|
|
||||||
bool NumObjIsLessEq(PRAT hno1, PRAT hno2, int32_t precision);
|
|
||||||
bool NumObjIsGreaterEq(PRAT hno1, PRAT hno2, int32_t precision);
|
|
||||||
bool NumObjIsEq(PRAT hno1, PRAT hno2, int32_t precision);
|
|
||||||
|
|
||||||
//
|
Rational Sin(Rational const& rat, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
|
||||||
// Assignment operator. ('=' in C language)
|
Rational Cos(Rational const& rat, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
|
||||||
//
|
Rational Tan(Rational const& rat, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
|
||||||
void NumObjAssign(PRAT *phnol, PRAT hnor);
|
Rational ASin(Rational const& rat, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
|
||||||
|
Rational ACos(Rational const& rat, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
|
||||||
|
Rational ATan(Rational const& rat, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
|
||||||
|
|
||||||
//
|
Rational Sinh(Rational const& rat, uint32_t radix, int32_t precision);
|
||||||
// Data type conversion functions
|
Rational Cosh(Rational const& rat, uint32_t radix, int32_t precision);
|
||||||
//
|
Rational Tanh(Rational const& rat, uint32_t radix, int32_t precision);
|
||||||
void NumObjSetIntValue(PRAT *phnol, LONG i );
|
Rational ASinh(Rational const& rat, uint32_t radix, int32_t precision);
|
||||||
void NumObjSetUlonglongValue(PRAT *phnol, ULONGLONG ul, uint32_t radix, int32_t precision);
|
Rational ACosh(Rational const& rat, uint32_t radix, int32_t precision);
|
||||||
|
Rational ATanh(Rational const& rat, int32_t precision);
|
||||||
ULONGLONG NumObjGetUlValue( PRAT hnol, uint32_t radix, int32_t precision);
|
}
|
||||||
|
|
||||||
// Returns a string representation of hnoNum
|
|
||||||
std::wstring NumObjToString(PRAT hnoNum, uint32_t radix, NUMOBJ_FMT fmt, int32_t precision);
|
|
||||||
|
|
||||||
//
|
|
||||||
// NumObjGetExp
|
|
||||||
//
|
|
||||||
// returns an int that equals the exponent of the NumObj
|
|
||||||
//
|
|
||||||
int32_t NumObjGetExp(PRAT hno);
|
|
||||||
|
|
||||||
//
|
|
||||||
// NumObjDestroy( hno )
|
|
||||||
//
|
|
||||||
// call this when you nolonger need the NumObj. Failure to do so
|
|
||||||
// will result in memory leaks.
|
|
||||||
//
|
|
||||||
void NumObjDestroy(PRAT *phno);
|
|
Loading…
Reference in New Issue
Block a user