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 "Header Files/Rational.h"
|
||||
#include "Header Files/scimath.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -29,6 +30,37 @@ namespace CalcEngine
|
||||
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 :
|
||||
m_p{ Number{prat->pp} },
|
||||
m_q{ Number{prat->pq} }
|
||||
@ -54,8 +86,390 @@ namespace CalcEngine
|
||||
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
|
||||
{
|
||||
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.
|
||||
// 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 "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";
|
||||
|
||||
// Read strings for keys, errors, trig types, etc.
|
||||
// These will be copied from the resources to local memory. A larger
|
||||
// than needed block is allocated first and then reallocated once we
|
||||
// know how much is actually used.
|
||||
// These will be copied from the resources to local memory.
|
||||
|
||||
array<wstring, CSTRINGSENGMAX> CCalcEngine::s_engineStrings;
|
||||
|
||||
@ -111,7 +86,7 @@ CCalcEngine::CCalcEngine(bool fPrecedence, bool fIntegerMode, CalculationManager
|
||||
m_numberString(DEFAULT_NUMBER_STR),
|
||||
m_nOp(),
|
||||
m_nPrecOp(),
|
||||
m_memoryValue{make_unique<Rational>()},
|
||||
m_memoryValue{ make_unique<Rational>() },
|
||||
m_holdVal{},
|
||||
m_currentVal{},
|
||||
m_lastVal{}
|
||||
@ -120,12 +95,7 @@ CCalcEngine::CCalcEngine(bool fPrecedence, bool fIntegerMode, CalculationManager
|
||||
|
||||
m_dwWordBitWidth = DwWordBitWidthFromeNumWidth(m_numwidth);
|
||||
|
||||
PRAT maxTrig = longtorat(10L);
|
||||
PRAT hundred = longtorat(100L);
|
||||
powrat(&maxTrig, hundred, m_radix, m_precision);
|
||||
m_maxTrigonometricNum = Rational{ maxTrig };
|
||||
destroyrat(maxTrig);
|
||||
destroyrat(hundred);
|
||||
m_maxTrigonometricNum = RationalMath::Pow(10, 100, m_radix, m_precision);
|
||||
|
||||
SetRadixTypeAndNumWidth(DEC_RADIX, m_numwidth);
|
||||
SettingsChanged();
|
||||
@ -147,14 +117,10 @@ void CCalcEngine::InitChopNumbers()
|
||||
assert(m_chopNumbers.size() == m_maxDecimalValueStrings.size());
|
||||
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);
|
||||
intrat(&hno, m_radix, m_precision);
|
||||
|
||||
m_maxDecimalValueStrings[i] = NumObjToString(hno, 10, FMT_FLOAT, m_precision);
|
||||
|
||||
NumObjDestroy(&hno);
|
||||
m_maxDecimalValueStrings[i] = maxVal.ToString(10, FMT_FLOAT, m_precision);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,21 +32,21 @@ using namespace CalcEngine;
|
||||
// 0 is returned. Higher the number, higher the precendence of the operator.
|
||||
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_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;
|
||||
|
||||
iPrec = 0;
|
||||
while ((iPrec < ARRAYSIZE(rgbPrec)) && (nopCode != rgbPrec[iPrec]))
|
||||
{
|
||||
iPrec += 2;
|
||||
}
|
||||
}
|
||||
if (iPrec >= ARRAYSIZE(rgbPrec))
|
||||
{
|
||||
iPrec = 0;
|
||||
}
|
||||
return rgbPrec[iPrec+1];
|
||||
return rgbPrec[iPrec + 1];
|
||||
|
||||
}
|
||||
|
||||
@ -77,13 +77,13 @@ void CCalcEngine::ClearTemporaryValues()
|
||||
m_input.Clear();
|
||||
m_bRecord = true;
|
||||
CheckAndAddLastBinOpToHistory();
|
||||
DisplayNum ();
|
||||
m_bError=false;
|
||||
DisplayNum();
|
||||
m_bError = false;
|
||||
}
|
||||
|
||||
void CCalcEngine::ProcessCommand(WPARAM wParam)
|
||||
{
|
||||
if(wParam == IDC_SET_RESULT)
|
||||
if (wParam == IDC_SET_RESULT)
|
||||
{
|
||||
wParam = IDC_RECALL;
|
||||
m_bSetCalcState = true;
|
||||
@ -104,13 +104,13 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
||||
|
||||
if (!IsGuiSettingOpCode(wParam))
|
||||
{
|
||||
m_nLastCom=m_nTempCom;
|
||||
m_nTempCom=(INT)wParam;
|
||||
m_nLastCom = m_nTempCom;
|
||||
m_nTempCom = (INT)wParam;
|
||||
}
|
||||
|
||||
if (m_bError)
|
||||
{
|
||||
if(wParam == IDC_CLEAR)
|
||||
if (wParam == IDC_CLEAR)
|
||||
{
|
||||
// handle "C" normally
|
||||
}
|
||||
@ -129,23 +129,23 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
||||
// Toggle Record/Display mode if appropriate.
|
||||
if (m_bRecord)
|
||||
{
|
||||
if (IsOpInRange(wParam, IDC_AND, IDC_MMINUS) ||
|
||||
IsOpInRange(wParam, IDC_OPENP, IDC_CLOSEP) ||
|
||||
IsOpInRange(wParam, IDM_HEX, IDM_BIN) ||
|
||||
IsOpInRange(wParam, IDM_QWORD, IDM_BYTE) ||
|
||||
IsOpInRange(wParam, IDM_DEG, IDM_GRAD) ||
|
||||
IsOpInRange(wParam, IDC_BINEDITSTART, IDC_BINEDITSTART+63) ||
|
||||
(IDC_INV == wParam) ||
|
||||
if (IsOpInRange(wParam, IDC_AND, IDC_MMINUS) ||
|
||||
IsOpInRange(wParam, IDC_OPENP, IDC_CLOSEP) ||
|
||||
IsOpInRange(wParam, IDM_HEX, IDM_BIN) ||
|
||||
IsOpInRange(wParam, IDM_QWORD, IDM_BYTE) ||
|
||||
IsOpInRange(wParam, IDM_DEG, IDM_GRAD) ||
|
||||
IsOpInRange(wParam, IDC_BINEDITSTART, IDC_BINEDITSTART + 63) ||
|
||||
(IDC_INV == wParam) ||
|
||||
(IDC_SIGN == wParam && 10 != m_radix))
|
||||
{
|
||||
m_bRecord = false;
|
||||
m_currentVal = m_input.ToRational(m_radix, m_precision);
|
||||
DisplayNum(); // Causes 3.000 to shrink to 3. on first op.
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( IsDigitOpCode(wParam)|| wParam == IDC_PNT)
|
||||
if (IsDigitOpCode(wParam) || wParam == IDC_PNT)
|
||||
{
|
||||
m_bRecord = true;
|
||||
m_input.Clear();
|
||||
@ -156,7 +156,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
||||
// Interpret digit keys.
|
||||
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
|
||||
if (iValue >= static_cast<unsigned int>(m_radix))
|
||||
@ -179,14 +179,14 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
||||
|
||||
// BINARY OPERATORS:
|
||||
if (IsBinOpCode(wParam))
|
||||
{
|
||||
{
|
||||
/* Change the operation if last input was operation. */
|
||||
if (IsBinOpCode(m_nLastCom))
|
||||
{
|
||||
INT nPrev;
|
||||
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.
|
||||
// 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. */
|
||||
if (m_bChangeOp)
|
||||
{
|
||||
DoPrecedenceCheckAgain:
|
||||
DoPrecedenceCheckAgain:
|
||||
|
||||
nx = NPrecedenceOfOp((int) wParam);
|
||||
nx = NPrecedenceOfOp((int)wParam);
|
||||
ni = NPrecedenceOfOp(m_nOpCode);
|
||||
|
||||
if ((nx > ni) && m_fPrecedence)
|
||||
@ -237,7 +237,7 @@ DoPrecedenceCheckAgain:
|
||||
}
|
||||
else
|
||||
{
|
||||
m_nPrecNum = MAXPRECDEPTH-1;
|
||||
m_nPrecNum = MAXPRECDEPTH - 1;
|
||||
HandleErrorCommand(wParam);
|
||||
}
|
||||
m_nPrecNum++;
|
||||
@ -253,13 +253,13 @@ DoPrecedenceCheckAgain:
|
||||
|
||||
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_nOpCode=m_nPrecOp[m_nPrecNum] ;
|
||||
m_nOpCode = m_nPrecOp[m_nPrecNum];
|
||||
|
||||
m_lastVal = m_precedenceVals[m_nPrecNum];
|
||||
|
||||
@ -274,7 +274,7 @@ DoPrecedenceCheckAgain:
|
||||
m_HistoryCollector.EnclosePrecInvertionBrackets();
|
||||
}
|
||||
m_HistoryCollector.PopLastOpndStart();
|
||||
goto DoPrecedenceCheckAgain ;
|
||||
goto DoPrecedenceCheckAgain;
|
||||
}
|
||||
|
||||
}
|
||||
@ -283,7 +283,7 @@ DoPrecedenceCheckAgain:
|
||||
DisplayAnnounceBinaryOperator();
|
||||
|
||||
m_lastVal = m_currentVal;
|
||||
m_nOpCode=(INT)wParam;
|
||||
m_nOpCode = (INT)wParam;
|
||||
m_HistoryCollector.AddBinOpToHistory(m_nOpCode);
|
||||
m_bNoPrevEqu = m_bChangeOp = true;
|
||||
return;
|
||||
@ -292,7 +292,7 @@ DoPrecedenceCheckAgain:
|
||||
// UNARY OPERATORS:
|
||||
if (IsUnaryOpCode(wParam) || (wParam == IDC_DEGREES))
|
||||
{
|
||||
/* Functions are unary operations. */
|
||||
/* Functions are unary operations. */
|
||||
/* If the last thing done was an operator, m_currentVal was cleared. */
|
||||
/* In that case we better use the number before the operator */
|
||||
/* was entered, otherwise, things like 5+ 1/x give Divide By */
|
||||
@ -304,7 +304,7 @@ DoPrecedenceCheckAgain:
|
||||
|
||||
// we do not add percent sign to history or to two line display.
|
||||
// instead, we add the result of applying %.
|
||||
if(wParam != IDC_PERCENT)
|
||||
if (wParam != IDC_PERCENT)
|
||||
{
|
||||
if (!m_HistoryCollector.FOpndAddedToHistory())
|
||||
{
|
||||
@ -329,9 +329,9 @@ DoPrecedenceCheckAgain:
|
||||
return;
|
||||
|
||||
/* Display the result, reset flags, and reset indicators. */
|
||||
DisplayNum ();
|
||||
DisplayNum();
|
||||
|
||||
if(wParam == IDC_PERCENT)
|
||||
if (wParam == IDC_PERCENT)
|
||||
{
|
||||
CheckAndAddLastBinOpToHistory();
|
||||
m_HistoryCollector.AddOpndToHistory(m_numberString, m_currentVal, true /* Add to primary and secondary display */);
|
||||
@ -343,8 +343,8 @@ DoPrecedenceCheckAgain:
|
||||
if (m_bInv &&
|
||||
((wParam == IDC_CHOP) ||
|
||||
(wParam == IDC_SIN) || (wParam == IDC_COS) || (wParam == IDC_TAN) ||
|
||||
(wParam == IDC_LN) || (wParam == IDC_DMS) || (wParam == IDC_DEGREES) ||
|
||||
(wParam == IDC_SINH) || (wParam == IDC_COSH) || (wParam == IDC_TANH)))
|
||||
(wParam == IDC_LN) || (wParam == IDC_DMS) || (wParam == IDC_DEGREES) ||
|
||||
(wParam == IDC_SINH) || (wParam == IDC_COSH) || (wParam == IDC_TANH)))
|
||||
{
|
||||
m_bInv = false;
|
||||
}
|
||||
@ -353,7 +353,7 @@ DoPrecedenceCheckAgain:
|
||||
}
|
||||
|
||||
// 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
|
||||
if (m_nLastCom >= IDC_AND && m_nLastCom <= IDC_PWR)
|
||||
@ -372,46 +372,46 @@ DoPrecedenceCheckAgain:
|
||||
}
|
||||
|
||||
/* Now branch off to do other commands and functions. */
|
||||
switch(wParam)
|
||||
switch (wParam)
|
||||
{
|
||||
case IDC_CLEAR: /* Total clear. */
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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. */
|
||||
{
|
||||
if (!m_bChangeOp)
|
||||
{
|
||||
// Clear the INV & leave (=xx indicator active
|
||||
ClearTemporaryValues();
|
||||
}
|
||||
// A special goody we are doing to preserve the history, if all was done was serious of unary operations last
|
||||
CheckAndAddLastBinOpToHistory(false);
|
||||
}
|
||||
|
||||
break;
|
||||
m_lastVal = Rational{};
|
||||
|
||||
case IDC_BACK:
|
||||
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. */
|
||||
{
|
||||
// Clear the INV & leave (=xx indicator active
|
||||
ClearTemporaryValues();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case IDC_BACK:
|
||||
// Divide number by the current radix and truncate.
|
||||
// Only allow backspace if we're recording.
|
||||
if (m_bRecord)
|
||||
@ -427,7 +427,7 @@ DoPrecedenceCheckAgain:
|
||||
|
||||
/* EQU enables the user to press it multiple times after and */
|
||||
/* operation to enable repeats of the last operation. */
|
||||
case IDC_EQU:
|
||||
case IDC_EQU:
|
||||
while (m_openParenCount > 0)
|
||||
{
|
||||
// when m_bError is set and m_ParNum is non-zero it goes into infinite loop
|
||||
@ -487,15 +487,15 @@ DoPrecedenceCheckAgain:
|
||||
/* Check for errors. If this wasn't done, DisplayNum */
|
||||
/* would immediately overwrite any error message. */
|
||||
if (!m_bError)
|
||||
DisplayNum ();
|
||||
DisplayNum();
|
||||
|
||||
/* No longer the first EQU. */
|
||||
m_bNoPrevEqu= false;
|
||||
m_bNoPrevEqu = false;
|
||||
}
|
||||
else if (!m_bError)
|
||||
DisplayNum();
|
||||
|
||||
if (m_nPrecNum==0 || !m_fPrecedence)
|
||||
if (m_nPrecNum == 0 || !m_fPrecedence)
|
||||
break;
|
||||
|
||||
m_nOpCode = m_nPrecOp[--m_nPrecNum];
|
||||
@ -510,7 +510,7 @@ DoPrecedenceCheckAgain:
|
||||
}
|
||||
m_HistoryCollector.PopLastOpndStart();
|
||||
|
||||
m_bNoPrevEqu= true;
|
||||
m_bNoPrevEqu = true;
|
||||
} while (m_nPrecNum >= 0);
|
||||
|
||||
if (!m_bError)
|
||||
@ -523,17 +523,17 @@ DoPrecedenceCheckAgain:
|
||||
}
|
||||
}
|
||||
|
||||
m_bChangeOp=false;
|
||||
m_bChangeOp = false;
|
||||
m_nPrevOpCode = 0;
|
||||
|
||||
break;
|
||||
|
||||
case IDC_OPENP:
|
||||
case IDC_CLOSEP:
|
||||
nx=0;
|
||||
if (wParam==IDC_OPENP)
|
||||
nx = 0;
|
||||
if (wParam == IDC_OPENP)
|
||||
{
|
||||
nx=1;
|
||||
nx = 1;
|
||||
}
|
||||
|
||||
// -IF- the Paren holding array is full and we try to add a paren
|
||||
@ -541,7 +541,7 @@ DoPrecedenceCheckAgain:
|
||||
// paren
|
||||
// -OR- the the precidence holding array is full
|
||||
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);
|
||||
break;
|
||||
@ -570,9 +570,9 @@ DoPrecedenceCheckAgain:
|
||||
// treated as 1 + (3
|
||||
m_currentVal = Rational{};
|
||||
}
|
||||
m_nTempCom=0;
|
||||
m_nOpCode=0;
|
||||
m_bChangeOp= false; // a ( is like starting a fresh sub equation
|
||||
m_nTempCom = 0;
|
||||
m_nOpCode = 0;
|
||||
m_bChangeOp = false; // a ( is like starting a fresh sub equation
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -649,7 +649,7 @@ DoPrecedenceCheckAgain:
|
||||
case IDM_DWORD:
|
||||
case IDM_WORD:
|
||||
case IDM_BYTE:
|
||||
if ( m_bRecord )
|
||||
if (m_bRecord)
|
||||
{
|
||||
m_currentVal = m_input.ToRational(m_radix, m_precision);
|
||||
m_bRecord = false;
|
||||
@ -666,44 +666,41 @@ DoPrecedenceCheckAgain:
|
||||
break;
|
||||
|
||||
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();
|
||||
}
|
||||
else
|
||||
{
|
||||
HandleErrorCommand(wParam);
|
||||
}
|
||||
break;
|
||||
DisplayNum();
|
||||
}
|
||||
|
||||
// Doing +/- while in Record mode is not a unary operation
|
||||
if (IsBinOpCode(m_nLastCom))
|
||||
else
|
||||
{
|
||||
m_currentVal = m_lastVal;
|
||||
HandleErrorCommand(wParam);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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:
|
||||
|
||||
if(m_bSetCalcState)
|
||||
if (m_bSetCalcState)
|
||||
{
|
||||
// Not a Memory recall. set the result
|
||||
m_bSetCalcState = false;
|
||||
@ -714,31 +711,25 @@ DoPrecedenceCheckAgain:
|
||||
m_currentVal = Rational{ *m_memoryValue };
|
||||
}
|
||||
CheckAndAddLastBinOpToHistory();
|
||||
DisplayNum ();
|
||||
DisplayNum();
|
||||
break;
|
||||
|
||||
case IDC_MPLUS:
|
||||
{
|
||||
/* MPLUS adds m_currentVal to immediate memory and kills the "mem" */
|
||||
/* indicator if the result is zero. */
|
||||
PRAT memRat = m_memoryValue->ToPRAT();
|
||||
PRAT curRat = m_currentVal.ToPRAT();
|
||||
addrat(&memRat, curRat, m_precision);
|
||||
m_memoryValue = make_unique<Rational>(TruncateNumForIntMath(Rational{ memRat })); // Memory should follow the current int mode
|
||||
destroyrat(curRat);
|
||||
destroyrat(memRat);
|
||||
Rational result = m_memoryValue->Add(m_currentVal, m_precision);
|
||||
m_memoryValue = make_unique<Rational>(TruncateNumForIntMath(result)); // Memory should follow the current int mode
|
||||
|
||||
break;
|
||||
}
|
||||
case IDC_MMINUS:
|
||||
{
|
||||
/* MMINUS subtracts m_currentVal to immediate memory and kills the "mem" */
|
||||
/* indicator if the result is zero. */
|
||||
PRAT memRat = m_memoryValue->ToPRAT();
|
||||
PRAT curRat = m_currentVal.ToPRAT();
|
||||
subrat(&memRat, curRat, m_precision);
|
||||
m_memoryValue = make_unique<Rational>(TruncateNumForIntMath(Rational{ memRat }));
|
||||
destroyrat(curRat);
|
||||
destroyrat(memRat);
|
||||
Rational result = m_memoryValue->Sub(m_currentVal, m_precision);
|
||||
m_memoryValue = make_unique<Rational>(TruncateNumForIntMath(result));
|
||||
|
||||
break;
|
||||
}
|
||||
case IDC_STORE:
|
||||
@ -784,7 +775,7 @@ DoPrecedenceCheckAgain:
|
||||
break;
|
||||
|
||||
case IDC_INV:
|
||||
m_bInv=!m_bInv;
|
||||
m_bInv = !m_bInv;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1011,18 +1002,13 @@ int CCalcEngine::IdcSetAngleTypeDecMode(int idc)
|
||||
|
||||
bool CCalcEngine::IsCurrentTooBigForTrig()
|
||||
{
|
||||
bool result = false;
|
||||
PRAT maxTrigRat = m_maxTrigonometricNum.ToPRAT();
|
||||
PRAT curRat = m_currentVal.ToPRAT();
|
||||
if (NumObjIsGreaterEq(curRat, maxTrigRat, m_precision))
|
||||
if (m_currentVal.IsGreaterEq(m_maxTrigonometricNum, m_precision))
|
||||
{
|
||||
m_currentVal = Rational{};
|
||||
result = true;
|
||||
return true;
|
||||
}
|
||||
destroyrat(curRat);
|
||||
destroyrat(maxTrigRat);
|
||||
|
||||
return result;
|
||||
return false;
|
||||
}
|
||||
|
||||
int CCalcEngine::GetCurrentRadix()
|
||||
@ -1052,39 +1038,30 @@ wstring CCalcEngine::GetStringForDisplay(Rational const& rat, uint32_t radix)
|
||||
// Check for standard\scientific mode
|
||||
if (!m_fIntegerMode)
|
||||
{
|
||||
PRAT prat = rat.ToPRAT();
|
||||
result = NumObjToString(prat, radix, m_nFE, m_precision);
|
||||
destroyrat(prat);
|
||||
result = rat.ToString(radix, m_nFE, m_precision);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Programmer mode
|
||||
// Find most significant bit to determine if number is negative
|
||||
PRAT hnoNumCopy = TruncateNumForIntMath(rat).ToPRAT();
|
||||
auto tempRat = TruncateNumForIntMath(rat);
|
||||
|
||||
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);
|
||||
if ((radix == 10) && fMsb)
|
||||
{
|
||||
// If high bit is set, then get the decimal number in -ve 2'scompl form.
|
||||
PRAT chopRat = m_chopNumbers[m_numwidth].ToPRAT();
|
||||
NumObjNot(&hnoNumCopy, true, chopRat, m_radix, m_precision);
|
||||
destroyrat(chopRat);
|
||||
addrat(&hnoNumCopy, rat_one, m_precision);
|
||||
NumObjNegate(&hnoNumCopy);
|
||||
// If high bit is set, then get the decimal number in negative 2's compl form.
|
||||
tempRat = tempRat.Not(true, m_chopNumbers[m_numwidth], m_radix, m_precision);
|
||||
tempRat = tempRat.Add(1, m_precision);
|
||||
tempRat = tempRat.Negate();
|
||||
}
|
||||
|
||||
result = NumObjToString(hnoNumCopy, radix, m_nFE, m_precision);
|
||||
NumObjDestroy(&hnoNumCopy);
|
||||
result = tempRat.ToString(radix, m_nFE, m_precision);
|
||||
}
|
||||
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
|
||||
//
|
||||
typedef struct {
|
||||
PRAT hnoNum;
|
||||
Rational value;
|
||||
int32_t precision;
|
||||
uint32_t radix;
|
||||
INT nFE;
|
||||
@ -46,7 +46,7 @@ typedef struct {
|
||||
bool bUseSep;
|
||||
} 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
|
||||
CalcEngine::Rational CCalcEngine::TruncateNumForIntMath(CalcEngine::Rational const& rat)
|
||||
@ -56,27 +56,20 @@ CalcEngine::Rational CCalcEngine::TruncateNumForIntMath(CalcEngine::Rational con
|
||||
return rat;
|
||||
}
|
||||
|
||||
PRAT tempRat = rat.ToPRAT();
|
||||
|
||||
// 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 -ve number to Hex/Oct/Bin rep. Use 2's completement form
|
||||
// Can be converting a dec negative number to Hex/Oct/Bin rep. Use 2's complement form
|
||||
// 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
|
||||
NumObjNegate(&tempRat);
|
||||
subrat(&tempRat, rat_one, m_precision);
|
||||
NumObjNot(&tempRat, true, chopRat, m_radix, m_precision);
|
||||
result = result.Negate();
|
||||
result = result.Sub(1, m_precision);
|
||||
result = result.Not(true /* IntegerMode */, m_chopNumbers[m_numwidth], m_radix, m_precision);
|
||||
}
|
||||
|
||||
andrat(&tempRat, chopRat, m_radix, m_precision);
|
||||
destroyrat(chopRat);
|
||||
|
||||
Rational result{ tempRat };
|
||||
destroyrat(tempRat);
|
||||
result = result.And(m_chopNumbers[m_numwidth], m_radix, m_precision);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -90,27 +83,24 @@ void CCalcEngine::DisplayNum(void)
|
||||
// something important has changed since the last time DisplayNum was
|
||||
// called.
|
||||
//
|
||||
PRAT curRat = m_currentVal.ToPRAT();
|
||||
bool hasValChanged = !gldPrevious.hnoNum || !NumObjIsEq(gldPrevious.hnoNum, curRat, m_precision);
|
||||
destroyrat(curRat);
|
||||
if ( m_bRecord || gldPrevious.hnoNum == nullptr ||
|
||||
hasValChanged ||
|
||||
gldPrevious.precision != m_precision ||
|
||||
gldPrevious.radix != m_radix ||
|
||||
gldPrevious.nFE != (int)m_nFE ||
|
||||
gldPrevious.bUseSep != true ||
|
||||
gldPrevious.numwidth != m_numwidth ||
|
||||
gldPrevious.fIntMath != m_fIntegerMode ||
|
||||
gldPrevious.bRecord != m_bRecord )
|
||||
if (m_bRecord ||
|
||||
!gldPrevious.value.IsEq(m_currentVal, m_precision) ||
|
||||
gldPrevious.precision != m_precision ||
|
||||
gldPrevious.radix != m_radix ||
|
||||
gldPrevious.nFE != (int)m_nFE ||
|
||||
gldPrevious.bUseSep != true ||
|
||||
gldPrevious.numwidth != m_numwidth ||
|
||||
gldPrevious.fIntMath != m_fIntegerMode ||
|
||||
gldPrevious.bRecord != m_bRecord)
|
||||
{
|
||||
gldPrevious.precision = m_precision;
|
||||
gldPrevious.radix = m_radix;
|
||||
gldPrevious.nFE = (int)m_nFE;
|
||||
gldPrevious.numwidth = m_numwidth;
|
||||
gldPrevious.nFE = (int)m_nFE;
|
||||
gldPrevious.numwidth = m_numwidth;
|
||||
|
||||
gldPrevious.fIntMath = m_fIntegerMode;
|
||||
gldPrevious.bRecord = m_bRecord;
|
||||
gldPrevious.bUseSep = true;
|
||||
gldPrevious.fIntMath = m_fIntegerMode;
|
||||
gldPrevious.bRecord = m_bRecord;
|
||||
gldPrevious.bUseSep = true;
|
||||
|
||||
if (m_bRecord)
|
||||
{
|
||||
@ -128,10 +118,9 @@ void CCalcEngine::DisplayNum(void)
|
||||
}
|
||||
|
||||
// Displayed number can go thru transformation. So copy it after transformation
|
||||
destroyrat(gldPrevious.hnoNum);
|
||||
gldPrevious.hnoNum = m_currentVal.ToPRAT();
|
||||
gldPrevious.value = m_currentVal;
|
||||
|
||||
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);
|
||||
}
|
||||
@ -268,7 +257,7 @@ wstring CCalcEngine::GroupDigitsPerRadix(wstring_view numberString, uint32_t rad
|
||||
switch (radix)
|
||||
{
|
||||
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:
|
||||
return GroupDigits(L" ", { 3, 0 }, numberString);
|
||||
case 2:
|
||||
|
@ -21,273 +21,193 @@
|
||||
|
||||
using namespace std;
|
||||
using namespace CalcEngine;
|
||||
using namespace CalcEngine::RationalMath;
|
||||
|
||||
/* Routines for more complex mathematical functions/error checking. */
|
||||
CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& rat, DWORD op)
|
||||
{
|
||||
PRAT tempRat = rat.ToPRAT();
|
||||
Rational result{};
|
||||
try
|
||||
{
|
||||
switch (op)
|
||||
{
|
||||
case IDC_CHOP:
|
||||
m_bInv ? fracrat(&tempRat , m_radix, m_precision) : intrat(&tempRat, m_radix, m_precision);
|
||||
break;
|
||||
case IDC_CHOP:
|
||||
result = m_bInv ? Frac(rat, m_radix, m_precision) : Integer(rat, m_radix, m_precision);
|
||||
break;
|
||||
|
||||
/* Return complement. */
|
||||
case IDC_COM:
|
||||
{
|
||||
PRAT chopRat = m_chopNumbers[m_numwidth].ToPRAT();
|
||||
NumObjNot(&tempRat, m_fIntegerMode, chopRat, m_radix, m_precision);
|
||||
destroyrat(chopRat);
|
||||
break;
|
||||
}
|
||||
case IDC_COM:
|
||||
result = rat.Not(m_fIntegerMode, m_chopNumbers[m_numwidth], m_radix, m_precision);
|
||||
break;
|
||||
|
||||
// Rotate Left with hi bit wrapped over to lo bit
|
||||
case IDC_ROL:
|
||||
if (m_fIntegerMode)
|
||||
{
|
||||
intrat(&tempRat, m_radix, m_precision);
|
||||
case IDC_ROL:
|
||||
if (m_fIntegerMode)
|
||||
{
|
||||
result = Integer(rat, m_radix, m_precision);
|
||||
|
||||
PRAT curRat = m_currentVal.ToPRAT();
|
||||
ULONGLONG w64Bits = NumObjGetUlValue(curRat, m_radix, m_precision);
|
||||
ULONGLONG msb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1;
|
||||
uint64_t w64Bits = result.ToUInt64_t(m_radix, m_precision);
|
||||
uint64_t 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
|
||||
w64Bits |= msb; // Set the prev Msb as the current Lsb
|
||||
NumObjSetUlonglongValue(&curRat, w64Bits, m_radix, m_precision);
|
||||
m_currentVal = Rational{ curRat };
|
||||
destroyrat(curRat);
|
||||
}
|
||||
break;
|
||||
result = Rational{ w64Bits, m_radix, m_precision };
|
||||
}
|
||||
break;
|
||||
|
||||
// Rotate right with lo bit wrapped over to hi bit
|
||||
case IDC_ROR:
|
||||
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:
|
||||
case IDC_ROR:
|
||||
if (m_fIntegerMode)
|
||||
{
|
||||
PRAT hno = nullptr;
|
||||
PRAT hno100 = nullptr;
|
||||
result = Integer(rat, m_radix, m_precision);
|
||||
|
||||
try
|
||||
{
|
||||
// If the operator is multiply/divide, we evaluate this as "X [op] (Y%)"
|
||||
// Otherwise, we evaluate it as "X [op] (X * Y%)"
|
||||
if (m_nOpCode == IDC_MUL || m_nOpCode == IDC_DIV)
|
||||
{
|
||||
NumObjSetIntValue(&hno100, 100);
|
||||
uint64_t w64Bits = result.ToUInt64_t(m_radix, m_precision);
|
||||
uint64_t lsb = ((w64Bits & 0x01) == 1) ? 1 : 0;
|
||||
w64Bits >>= 1; //RShift by 1
|
||||
w64Bits |= (lsb << (m_dwWordBitWidth - 1));
|
||||
|
||||
divrat(&tempRat, hno100, 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;
|
||||
result = Rational{ w64Bits, m_radix, m_precision };
|
||||
}
|
||||
break;
|
||||
|
||||
case IDC_SIN: /* Sine; normal and arc */
|
||||
if (!m_fIntegerMode)
|
||||
{
|
||||
m_bInv ? asinanglerat(&tempRat, m_angletype, m_radix, m_precision) : NumObjSin(&tempRat, m_angletype, m_radix, m_precision);
|
||||
}
|
||||
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. */
|
||||
case IDC_PERCENT:
|
||||
{
|
||||
// If the operator is multiply/divide, we evaluate this as "X [op] (Y%)"
|
||||
// Otherwise, we evaluate it as "X [op] (X * Y%)"
|
||||
if (m_nOpCode == IDC_MUL || m_nOpCode == IDC_DIV)
|
||||
{
|
||||
PRAT hno = nullptr;
|
||||
|
||||
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;
|
||||
result = rat.Div(100, m_precision);
|
||||
}
|
||||
|
||||
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:
|
||||
else
|
||||
{
|
||||
if (!m_fIntegerMode)
|
||||
{
|
||||
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;
|
||||
result = m_lastVal.Div(100, m_precision);
|
||||
result = rat.Mul(result, m_precision);
|
||||
}
|
||||
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 )
|
||||
|
||||
Rational result{ tempRat };
|
||||
destroyrat(tempRat);
|
||||
return result;
|
||||
}
|
||||
catch(DWORD nErrCode)
|
||||
catch (DWORD nErrCode)
|
||||
{
|
||||
DisplayError(nErrCode);
|
||||
destroyrat(tempRat);
|
||||
return rat;
|
||||
result = rat;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Routine to display error messages and set m_bError flag. Errors are */
|
||||
|
@ -3,204 +3,388 @@
|
||||
|
||||
#include "pch.h"
|
||||
#include "Header Files/CalcEngine.h"
|
||||
#include "Ratpack/ratpak.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace CalcEngine;
|
||||
|
||||
/**************************************************************************\
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* # # ##### *
|
||||
* # # # # # *
|
||||
* # # # # # # # *
|
||||
* # ### ### # # *
|
||||
* # # ### # # # ### # # ### ##### # ### ### ### *
|
||||
* # ## # # # ## # # # # # # ## # # # *
|
||||
* # # # # # # # # # ##### # # ##### # *
|
||||
* # # # # # # # # # # # # # # ## *
|
||||
* # # # # # # # # # ### # # ### ### ## *
|
||||
* *
|
||||
* *
|
||||
* 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)
|
||||
Rational RationalMath::Frac(Rational const& rat, uint32_t radix, int32_t precision)
|
||||
{
|
||||
PRAT hno = nullptr;
|
||||
|
||||
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)
|
||||
PRAT prat = rat.ToPRAT();
|
||||
try
|
||||
{
|
||||
intrat( phno, radix, precision);
|
||||
addrat( phno, rat_one, precision);
|
||||
NumObjNegate( phno );
|
||||
fracrat(&prat, radix, precision);
|
||||
}
|
||||
else
|
||||
catch (DWORD error)
|
||||
{
|
||||
|
||||
xorrat( phno, chopNum, radix, precision);
|
||||
destroyrat(prat);
|
||||
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);
|
||||
}
|
||||
|
||||
/******************************************************************\
|
||||
*
|
||||
* Number format conversion routines
|
||||
*
|
||||
* History:
|
||||
* 06-Dec-1996 wrote them
|
||||
\******************************************************************/
|
||||
void NumObjSetIntValue(PRAT *phnol, LONG i )
|
||||
Rational RationalMath::Fact(Rational const& rat, uint32_t radix, int32_t precision)
|
||||
{
|
||||
PRAT pr = nullptr;
|
||||
PRAT prat = rat.ToPRAT();
|
||||
|
||||
pr = longtorat( i );
|
||||
NumObjAssign( phnol, pr );
|
||||
destroyrat(pr);
|
||||
try
|
||||
{
|
||||
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 );
|
||||
NumObjAssign( phnol, pr );
|
||||
destroyrat(pr);
|
||||
try
|
||||
{
|
||||
exprat(&prat, radix, precision);
|
||||
}
|
||||
catch (DWORD error)
|
||||
{
|
||||
destroyrat(prat);
|
||||
throw(error);
|
||||
}
|
||||
|
||||
Rational result{ prat };
|
||||
destroyrat(prat);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// A Set with 64 bit number
|
||||
void NumObjSetUlonglongValue(PRAT *phnol, ULONGLONG ul, uint32_t radix, int32_t precision)
|
||||
Rational RationalMath::Log(Rational const& rat, int32_t precision)
|
||||
{
|
||||
ULONG hi, lo;
|
||||
PRAT hno = nullptr;
|
||||
PRAT prat = rat.ToPRAT();
|
||||
|
||||
hi = HIDWORD(ul);
|
||||
lo = LODWORD(ul);
|
||||
NumObjSetIUlongValue(phnol, hi);
|
||||
NumObjSetIntValue(&hno, 32);
|
||||
lshrat(phnol, hno, radix, precision);
|
||||
NumObjSetIUlongValue(&hno, lo);
|
||||
orrat(phnol, hno, radix, precision);
|
||||
NumObjDestroy(&hno);
|
||||
try
|
||||
{
|
||||
lograt(&prat, precision);
|
||||
}
|
||||
catch (DWORD error)
|
||||
{
|
||||
destroyrat(prat);
|
||||
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"
|
||||
|
||||
using namespace CalcEngine;
|
||||
using namespace CalcEngine::RationalMath;
|
||||
|
||||
// Routines to perform standard operations &|^~<<>>+-/*% and pwr.
|
||||
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.
|
||||
PRAT resultRat = nullptr;
|
||||
if (lhs.IsZero())
|
||||
{
|
||||
NumObjAssign(&resultRat, rat_zero);
|
||||
}
|
||||
else
|
||||
{
|
||||
resultRat = lhs.ToPRAT();
|
||||
}
|
||||
auto result = (!lhs.IsZero() ? lhs : Rational{});
|
||||
|
||||
try
|
||||
{
|
||||
switch (operation)
|
||||
{
|
||||
case IDC_AND:
|
||||
andrat(&resultRat, rhsRat, m_radix, m_precision);
|
||||
result = result.And(rhs, m_radix, m_precision);
|
||||
break;
|
||||
|
||||
case IDC_OR:
|
||||
orrat(&resultRat, rhsRat, m_radix, m_precision);
|
||||
result = result.Or(rhs, m_radix, m_precision);
|
||||
break;
|
||||
|
||||
case IDC_XOR:
|
||||
xorrat(&resultRat, rhsRat, m_radix, m_precision);
|
||||
result = result.Xor(rhs, m_radix, m_precision);
|
||||
break;
|
||||
|
||||
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);
|
||||
if (NumObjIsGreaterEq(resultRat, hno, m_precision)) // Lsh/Rsh >= than current word size is always 0
|
||||
{
|
||||
throw CALC_E_NORESULT;
|
||||
}
|
||||
throw CALC_E_NORESULT;
|
||||
}
|
||||
|
||||
NumObjAssign(&hno, resultRat);
|
||||
NumObjAssign(&resultRat, rhsRat);
|
||||
|
||||
uint64_t w64Bits = NumObjGetUlValue(resultRat, m_radix, m_precision);
|
||||
uint64_t w64Bits = rhs.ToUInt64_t(m_radix, m_precision);
|
||||
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)
|
||||
{
|
||||
intrat(&resultRat, m_radix, m_precision);
|
||||
PRAT temp = m_chopNumbers[m_numwidth].ToPRAT();
|
||||
PRAT chopRat = m_chopNumbers[m_numwidth].ToPRAT();
|
||||
rshrat(&temp, hno, m_radix, m_precision);
|
||||
intrat(&temp, m_radix, m_precision);
|
||||
xorrat(&temp, chopRat, m_radix, m_precision);
|
||||
orrat(&resultRat, temp, m_radix, m_precision);
|
||||
destroyrat(temp);
|
||||
destroyrat(chopRat);
|
||||
result = Integer(result, m_radix, m_precision);
|
||||
|
||||
auto tempRat = m_chopNumbers[m_numwidth].Rsh(holdVal, m_radix, m_precision);
|
||||
tempRat = Integer(tempRat, m_radix, m_precision);
|
||||
|
||||
tempRat = tempRat.Xor(m_chopNumbers[m_numwidth], m_radix, m_precision);
|
||||
result = result.Or(tempRat, m_radix, m_precision);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
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);
|
||||
if (NumObjIsGreaterEq(resultRat, hno, m_precision))
|
||||
{
|
||||
throw CALC_E_NORESULT;
|
||||
}
|
||||
throw CALC_E_NORESULT;
|
||||
}
|
||||
|
||||
NumObjAssign(&hno, resultRat);
|
||||
NumObjAssign(&resultRat, rhsRat);
|
||||
|
||||
lshrat(&resultRat, hno, m_radix, m_precision);
|
||||
result = rhs.Lsh(result, m_radix, m_precision);
|
||||
break;
|
||||
|
||||
case IDC_ADD:
|
||||
addrat(&resultRat, rhsRat, m_precision);
|
||||
result = result.Add(rhs, m_precision);
|
||||
break;
|
||||
|
||||
case IDC_SUB:
|
||||
// in order to do ( rhsRat - resultRat ) we actually do -(resultRat - rhsRat ) because it's quicker
|
||||
subrat(&resultRat, rhsRat, m_precision);
|
||||
NumObjNegate(&resultRat);
|
||||
result = rhs.Sub(result, m_precision);
|
||||
break;
|
||||
|
||||
case IDC_MUL:
|
||||
mulrat(&resultRat, rhsRat, m_precision);
|
||||
result = result.Mul(rhs, m_precision);
|
||||
break;
|
||||
|
||||
case IDC_DIV:
|
||||
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;
|
||||
// REVIEW: These lengthly number assignments can be replaced with some quick pointer swaps.
|
||||
// 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);
|
||||
uint64_t w64Bits = rhs.ToUInt64_t(m_radix, m_precision);
|
||||
bool fMsb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1;
|
||||
|
||||
if(m_fIntegerMode)
|
||||
if (fMsb)
|
||||
{
|
||||
uint64_t w64Bits = NumObjGetUlValue(resultRat, m_radix, m_precision);
|
||||
bool fMsb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1;
|
||||
result = rhs.Not(true /* IntegerMode */, m_chopNumbers[m_numwidth], m_radix, m_precision);
|
||||
result = result.Add(1, m_precision);
|
||||
|
||||
if (fMsb)
|
||||
{
|
||||
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;
|
||||
}
|
||||
iNumeratorSign = -1;
|
||||
}
|
||||
|
||||
if (operation == IDC_DIV)
|
||||
{
|
||||
iFinalSign = iNumeratorSign * iDenominatorSign;
|
||||
divrat(&resultRat, hno, m_precision);
|
||||
}
|
||||
else
|
||||
{
|
||||
iFinalSign = iNumeratorSign;
|
||||
modrat(&resultRat, hno );
|
||||
}
|
||||
w64Bits = temp.ToUInt64_t(m_radix, m_precision);
|
||||
fMsb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1;
|
||||
|
||||
if (m_fIntegerMode && iFinalSign == -1)
|
||||
if (fMsb)
|
||||
{
|
||||
intrat(&resultRat, m_radix, m_precision);
|
||||
NumObjNegate(&resultRat);
|
||||
}
|
||||
temp = temp.Not(true /* IntegerMode */, m_chopNumbers[m_numwidth], m_radix, m_precision);
|
||||
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);
|
||||
NumObjAssign(&resultRat, rhsRat);
|
||||
|
||||
powrat(&resultRat, hno , m_radix, m_precision);
|
||||
|
||||
break;
|
||||
iFinalSign = iNumeratorSign * iDenominatorSign;
|
||||
result = result.Div(temp, m_precision);
|
||||
}
|
||||
case IDC_ROOT: // Calculates rhsRat to the resultRat(th) root.
|
||||
else
|
||||
{
|
||||
NumObjAssign(&hno, resultRat);
|
||||
NumObjAssign(&resultRat, rhsRat);
|
||||
|
||||
rootrat(&resultRat, hno, m_radix, m_precision);
|
||||
|
||||
break;
|
||||
iFinalSign = iNumeratorSign;
|
||||
result = result.Mod(temp);
|
||||
}
|
||||
|
||||
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)
|
||||
@ -187,15 +141,8 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa
|
||||
DisplayError(dwErrCode);
|
||||
|
||||
// On error, return the original value
|
||||
destroyrat(resultRat);
|
||||
resultRat = lhs.ToPRAT();
|
||||
result = lhs;
|
||||
}
|
||||
|
||||
destroyrat(hno);
|
||||
destroyrat(rhsRat);
|
||||
|
||||
Rational result{ resultRat };
|
||||
destroyrat(resultRat);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -1,29 +1,13 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// 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 "Header Files/CalcEngine.h"
|
||||
|
||||
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.
|
||||
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.
|
||||
if (m_fIntegerMode)
|
||||
{
|
||||
PRAT curRat = m_currentVal.ToPRAT();
|
||||
ULONGLONG w64Bits = NumObjGetUlValue(curRat, m_radix, m_precision);
|
||||
uint64_t w64Bits = m_currentVal.ToUInt64_t(m_radix, m_precision);
|
||||
bool fMsb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1; // make sure you use the old width
|
||||
|
||||
if (fMsb)
|
||||
{
|
||||
// If high bit is set, then get the decimal number in -ve 2'scompl form.
|
||||
PRAT chopRat = m_chopNumbers[m_numwidth].ToPRAT();
|
||||
NumObjNot(&curRat, true, chopRat, m_radix, m_precision);
|
||||
destroyrat(chopRat);
|
||||
addrat(&curRat, rat_one, m_precision);
|
||||
NumObjNegate(&curRat);
|
||||
m_currentVal = Rational{ curRat };
|
||||
}
|
||||
auto tempResult = m_currentVal.Not(true /* IntegerMode */, m_chopNumbers[m_numwidth], m_radix, m_precision);
|
||||
tempResult = tempResult.Add(1, m_precision);
|
||||
|
||||
destroyrat(curRat);
|
||||
m_currentVal = tempResult.Negate();
|
||||
}
|
||||
}
|
||||
|
||||
if (radixtype >= HEX_RADIX && radixtype <= BIN_RADIX)
|
||||
@ -84,9 +63,9 @@ LONG CCalcEngine::DwWordBitWidthFromeNumWidth(NUM_WIDTH /*numwidth*/)
|
||||
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;
|
||||
|
||||
// convert special bases into symbolic values
|
||||
@ -106,25 +85,16 @@ bool CCalcEngine::TryToggleBit(CalcEngine::Rational& rat, DWORD wbitno)
|
||||
return false; // ignore error cant happen
|
||||
}
|
||||
|
||||
PRAT hnumPow = nullptr;
|
||||
NumObjAssign(&hnumPow, rat_two);
|
||||
PRAT hnum = longtorat(wbitno);
|
||||
powrat(&hnumPow, hnum, m_radix, m_precision);
|
||||
|
||||
PRAT resultRat = rat.ToPRAT();
|
||||
intrat(&resultRat, m_radix, m_precision);
|
||||
if (NumObjIsZero(resultRat))
|
||||
Rational result = Integer(rat, m_radix, m_precision);
|
||||
if (result.IsZero())
|
||||
{
|
||||
// This is the same work around happenning in SciCalcFunctions. Ought to move to intrat function itself.
|
||||
// Basic bug is there which doesn treat 0/ n as 0, or -0 as 0 etc.
|
||||
NumObjAssign(&resultRat, rat_zero);
|
||||
// Basic bug is there which doesn't treat 0/ n as 0, or -0 as 0 etc.
|
||||
result = Rational{};
|
||||
}
|
||||
|
||||
xorrat(&resultRat, hnumPow, m_radix, m_precision);
|
||||
rat = Rational{ resultRat };
|
||||
destroyrat(resultRat);
|
||||
NumObjDestroy(&hnumPow);
|
||||
NumObjDestroy(&hnum);
|
||||
auto pow = Pow(2, static_cast<int32_t>(wbitno), m_radix, m_precision);
|
||||
rat = result.Xor(pow, m_radix, m_precision);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -293,9 +293,7 @@ wstring COpndCommand::GetString(uint32_t radix, int32_t precision, wchar_t decim
|
||||
|
||||
if (m_fInitialized)
|
||||
{
|
||||
PRAT valRat = m_value.ToPRAT();
|
||||
result = NumObjToString(valRat, radix, eNUMOBJ_FMT::FMT_FLOAT, precision);
|
||||
destroyrat(valRat);
|
||||
result = m_value.ToString(radix, eNUMOBJ_FMT::FMT_FLOAT, precision);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -12,6 +12,9 @@ namespace CalcEngine
|
||||
Rational() noexcept;
|
||||
Rational(Number const& n) 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;
|
||||
PRAT ToPRAT() const;
|
||||
@ -19,7 +22,29 @@ namespace CalcEngine
|
||||
Number const& P() const;
|
||||
Number const& Q() const;
|
||||
|
||||
Rational Negate() const;
|
||||
Rational Add(Rational const& rhs, int32_t precision) const;
|
||||
Rational Sub(Rational const& rhs, int32_t precision) const;
|
||||
Rational Mul(Rational const& rhs, int32_t precision) const;
|
||||
Rational Div(Rational const& rhs, int32_t precision) const;
|
||||
Rational Mod(Rational const& rhs) const;
|
||||
|
||||
Rational 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 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:
|
||||
Number m_p;
|
||||
|
@ -1,79 +1,35 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
/**************************************************************************\
|
||||
* *
|
||||
* *
|
||||
* *
|
||||
* # # ##### *
|
||||
* # # # # # *
|
||||
* # # # # # # # *
|
||||
* # ### ### # # *
|
||||
* # # ### # # # ### # # ### ##### # ### ### ### *
|
||||
* # ## # # # ## # # # # # # ## # # # *
|
||||
* # # # # # # # # # ##### # # ##### # *
|
||||
* # # # # # # # # # # # # # # ## *
|
||||
* # # # # # # # # # ### # # ### ### ## *
|
||||
* *
|
||||
* *
|
||||
* Infinte Precision Production Version *
|
||||
* *
|
||||
\**************************************************************************/
|
||||
//
|
||||
// RETAIL version of NUMOBJ math that uses Infinite Precision
|
||||
//
|
||||
#include "../Ratpack/ratpak.h"
|
||||
#include "Rational.h"
|
||||
|
||||
//
|
||||
// Unary functions
|
||||
//
|
||||
void NumObjInvert(PRAT *phno, int32_t precision);
|
||||
void NumObjNegate(PRAT *phno);
|
||||
void NumObjAbs(PRAT *phno);
|
||||
namespace CalcEngine::RationalMath
|
||||
{
|
||||
Rational Frac(Rational const& rat, uint32_t radix, int32_t precision);
|
||||
Rational Integer(Rational const& rat, uint32_t radix, int32_t precision);
|
||||
|
||||
void NumObjSin(PRAT *phno, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
|
||||
void NumObjCos(PRAT *phno, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
|
||||
void NumObjTan(PRAT *phno, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
|
||||
void NumObjAntiLog10(PRAT *phno, uint32_t radix, int32_t precision);
|
||||
Rational Pow(Rational const& base, Rational const& pow, uint32_t radix, int32_t precision);
|
||||
Rational Root(Rational const& base, Rational const& root, uint32_t radix, int32_t precision);
|
||||
Rational Fact(Rational const& rat, 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);
|
||||
|
||||
//
|
||||
// Comparison functions
|
||||
//
|
||||
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 Invert(Rational const& rat, int32_t precision);
|
||||
Rational Abs(Rational const& rat);
|
||||
|
||||
//
|
||||
// Assignment operator. ('=' in C language)
|
||||
//
|
||||
void NumObjAssign(PRAT *phnol, PRAT hnor);
|
||||
Rational Sin(Rational const& rat, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
|
||||
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);
|
||||
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);
|
||||
|
||||
//
|
||||
// Data type conversion functions
|
||||
//
|
||||
void NumObjSetIntValue(PRAT *phnol, LONG i );
|
||||
void NumObjSetUlonglongValue(PRAT *phnol, ULONGLONG ul, uint32_t radix, 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);
|
||||
Rational Sinh(Rational const& rat, uint32_t radix, int32_t precision);
|
||||
Rational Cosh(Rational const& rat, uint32_t radix, int32_t precision);
|
||||
Rational Tanh(Rational const& rat, uint32_t radix, int32_t precision);
|
||||
Rational ASinh(Rational const& rat, 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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user