Convert NumObj* functions to use Rationals and move under CalcEngine::RationalMath namespace

This commit is contained in:
Josh Koon 2019-01-29 14:55:35 -08:00
commit 22257ab042
11 changed files with 1198 additions and 872 deletions

View file

@ -2,8 +2,10 @@
#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;
using namespace CalcEngine::RationalMath;
namespace CalcEngine namespace CalcEngine
{ {
@ -29,6 +31,38 @@ namespace CalcEngine
m_q{ q } m_q{ q }
{} {}
Rational::Rational(int32_t i) noexcept
{
PRAT pr = longtorat(static_cast<long>(i));
m_p = Number{ pr->pp };
m_q = Number{ pr->pq };
destroyrat(pr);
}
Rational::Rational(uint32_t ui) noexcept
{
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) noexcept
{
uint32_t hi = HIDWORD(ui);
uint32_t lo = LODWORD(ui);
Rational temp = Lsh(hi, 32, radix, precision);
temp = Or(temp, 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} }
@ -58,4 +92,135 @@ namespace CalcEngine
{ {
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;
}
} }

View file

@ -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 = RationalMath::Div(m_chopNumbers[i], 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);
} }
} }

View file

@ -25,6 +25,7 @@
using namespace std; using namespace std;
using namespace CalcEngine; using namespace CalcEngine;
using namespace CalcEngine::RationalMath;
// NPrecedenceOfOp // NPrecedenceOfOp
// //
@ -32,9 +33,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 +47,7 @@ INT NPrecedenceOfOp(int nopCode)
{ {
iPrec = 0; iPrec = 0;
} }
return rgbPrec[iPrec+1]; return rgbPrec[iPrec + 1];
} }
@ -77,13 +78,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 +105,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
} }
@ -134,7 +135,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
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 +146,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 +157,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 +187,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 +222,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 +238,7 @@ DoPrecedenceCheckAgain:
} }
else else
{ {
m_nPrecNum = MAXPRECDEPTH-1; m_nPrecNum = MAXPRECDEPTH - 1;
HandleErrorCommand(wParam); HandleErrorCommand(wParam);
} }
m_nPrecNum++; m_nPrecNum++;
@ -253,13 +254,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 +275,7 @@ DoPrecedenceCheckAgain:
m_HistoryCollector.EnclosePrecInvertionBrackets(); m_HistoryCollector.EnclosePrecInvertionBrackets();
} }
m_HistoryCollector.PopLastOpndStart(); m_HistoryCollector.PopLastOpndStart();
goto DoPrecedenceCheckAgain ; goto DoPrecedenceCheckAgain;
} }
} }
@ -283,7 +284,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 +305,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 +330,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 */);
@ -353,7 +354,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,7 +373,7 @@ 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. */
{ {
@ -384,10 +385,10 @@ DoPrecedenceCheckAgain:
m_lastVal = Rational{}; m_lastVal = Rational{};
m_bChangeOp=false; m_bChangeOp = false;
m_nPrecNum=m_nTempCom=m_nLastCom=m_nOpCode= m_openParenCount =0; m_nPrecNum = m_nTempCom = m_nLastCom = m_nOpCode = m_openParenCount = 0;
m_nPrevOpCode = 0; m_nPrevOpCode = 0;
m_bNoPrevEqu= true; m_bNoPrevEqu = true;
/* clear the parenthesis status box indicator, this will not be /* clear the parenthesis status box indicator, this will not be
@ -487,15 +488,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 +511,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 +524,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 +542,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 +571,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 +650,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;
@ -691,10 +692,7 @@ DoPrecedenceCheckAgain:
m_HistoryCollector.AddOpndToHistory(m_numberString, m_currentVal); m_HistoryCollector.AddOpndToHistory(m_numberString, m_currentVal);
} }
PRAT curRat = m_currentVal.ToPRAT(); m_currentVal = Negate(m_currentVal);
NumObjNegate(&curRat);
m_currentVal = Rational{ curRat };
destroyrat(curRat);
DisplayNum(); DisplayNum();
m_HistoryCollector.AddUnaryOpToHistory(IDC_SIGN, m_bInv, m_angletype); m_HistoryCollector.AddUnaryOpToHistory(IDC_SIGN, m_bInv, m_angletype);
@ -703,7 +701,7 @@ DoPrecedenceCheckAgain:
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 +712,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 = Add(*m_memoryValue, 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 = Sub(*m_memoryValue, 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 +776,7 @@ DoPrecedenceCheckAgain:
break; break;
case IDC_INV: case IDC_INV:
m_bInv=!m_bInv; m_bInv = !m_bInv;
break; break;
} }
@ -1011,18 +1003,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 +1039,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 = Not(tempRat, true, m_chopNumbers[m_numwidth], m_radix, m_precision);
NumObjNot(&hnoNumCopy, true, chopRat, m_radix, m_precision); tempRat = Add(tempRat, 1, m_precision);
destroyrat(chopRat); tempRat = Negate(tempRat);
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);
}
} }
} }

View file

@ -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(Rational{}, m_precision))
{ {
// if negative make positive by doing a twos complement // if negative make positive by doing a twos complement
NumObjNegate(&tempRat); result = RationalMath::Negate(result);
subrat(&tempRat, rat_one, m_precision); result = RationalMath::Sub(result, 1, m_precision);
NumObjNot(&tempRat, true, chopRat, m_radix, m_precision); result = RationalMath::Not(result, true, m_chopNumbers[m_numwidth], m_radix, m_precision);
} }
andrat(&tempRat, chopRat, m_radix, m_precision); result = RationalMath::And(result, m_chopNumbers[m_numwidth], m_radix, m_precision);
destroyrat(chopRat);
Rational result{ tempRat };
destroyrat(tempRat);
return result; return result;
} }
@ -90,18 +83,15 @@ 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);
if ( m_bRecord || gldPrevious.hnoNum == nullptr ||
hasValChanged ||
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.bUseSep != true || gldPrevious.bUseSep != true ||
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.precision = m_precision; gldPrevious.precision = m_precision;
gldPrevious.radix = m_radix; gldPrevious.radix = m_radix;
@ -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);
} }
@ -157,7 +146,7 @@ int CCalcEngine::IsNumberInvalid(const wstring& numberString, int iMaxExp, int i
// in case there's an exponent: // in case there's an exponent:
// its optionally followed by a + or - // its optionally followed by a + or -
// which is followed by zero or more digits // which is followed by zero or more digits
wregex rx(wstring{ c_decPreSepStr } + m_decimalSeparator + wstring{ c_decPostSepStr }); wregex rx(wstring{ c_decPreSepStr } +m_decimalSeparator + wstring{ c_decPostSepStr });
wsmatch matches; wsmatch matches;
if (regex_match(numberString, matches, rx)) if (regex_match(numberString, matches, rx))
{ {

View file

@ -21,43 +21,37 @@
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 = Not(rat, true, m_chopNumbers[m_numwidth], m_radix, m_precision);
PRAT chopRat = m_chopNumbers[m_numwidth].ToPRAT();
NumObjNot(&tempRat, m_fIntegerMode, chopRat, m_radix, m_precision);
destroyrat(chopRat);
break; 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();
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 <<= 1; // LShift by 1
w64Bits |= msb; // Set the prev Msb as the current Lsb w64Bits |= msb; // Set the prev Msb as the current Lsb
NumObjSetUlonglongValue(&curRat, w64Bits, m_radix, m_precision);
m_currentVal = Rational{ curRat }; result = Rational{ w64Bits, m_radix, m_precision };
destroyrat(curRat);
} }
break; break;
@ -65,53 +59,29 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
case IDC_ROR: case IDC_ROR:
if (m_fIntegerMode) if (m_fIntegerMode)
{ {
intrat(&tempRat, m_radix, m_precision); result = Integer(rat, m_radix, m_precision);
PRAT curRat = m_currentVal.ToPRAT();
ULONGLONG w64Bits = NumObjGetUlValue(curRat, m_radix, m_precision);
ULONGLONG lsb = ((w64Bits & 0x01) == 1) ? 1 : 0; uint64_t w64Bits = result.ToUInt64_t(m_radix, m_precision);
uint64_t lsb = ((w64Bits & 0x01) == 1) ? 1 : 0;
w64Bits >>= 1; //RShift by 1 w64Bits >>= 1; //RShift by 1
w64Bits |= (lsb << (m_dwWordBitWidth - 1)); w64Bits |= (lsb << (m_dwWordBitWidth - 1));
NumObjSetUlonglongValue(&curRat, w64Bits, m_radix, m_precision);
m_currentVal = Rational{ curRat }; result = Rational{ w64Bits, m_radix, m_precision };
destroyrat(curRat);
} }
break; break;
case IDC_PERCENT: case IDC_PERCENT:
{
PRAT hno = nullptr;
PRAT hno100 = nullptr;
try
{ {
// If the operator is multiply/divide, we evaluate this as "X [op] (Y%)" // If the operator is multiply/divide, we evaluate this as "X [op] (Y%)"
// Otherwise, we evaluate it as "X [op] (X * Y%)" // Otherwise, we evaluate it as "X [op] (X * Y%)"
if (m_nOpCode == IDC_MUL || m_nOpCode == IDC_DIV) if (m_nOpCode == IDC_MUL || m_nOpCode == IDC_DIV)
{ {
NumObjSetIntValue(&hno100, 100); result = Div(rat, 100, m_precision);
divrat(&tempRat, hno100, m_precision);
destroyrat(hno100);
} }
else else
{ {
hno = m_lastVal.ToPRAT(); result = Div(m_lastVal, 100, m_precision);
NumObjSetIntValue(&hno100, 100); result = Mul(rat, result, m_precision);
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;
} }
@ -119,106 +89,76 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
case IDC_SIN: /* Sine; normal and arc */ case IDC_SIN: /* Sine; normal and arc */
if (!m_fIntegerMode) if (!m_fIntegerMode)
{ {
m_bInv ? asinanglerat(&tempRat, m_angletype, m_radix, m_precision) : NumObjSin(&tempRat, m_angletype, m_radix, m_precision); result = m_bInv ? ASin(rat, m_angletype, m_radix, m_precision) : Sin(rat, m_angletype, m_radix, m_precision);
} }
break; break;
case IDC_SINH: /* Sine- hyperbolic and archyperbolic */ case IDC_SINH: /* Sine- hyperbolic and archyperbolic */
if (!m_fIntegerMode) if (!m_fIntegerMode)
{ {
m_bInv ? asinhrat(&tempRat, m_radix, m_precision) : sinhrat(&tempRat, m_radix, m_precision); result = m_bInv ? ASinh(rat, m_radix, m_precision) : Sinh(rat, m_radix, m_precision);
} }
break; break;
case IDC_COS: /* Cosine, follows convention of sine function. */ case IDC_COS: /* Cosine, follows convention of sine function. */
if (!m_fIntegerMode) if (!m_fIntegerMode)
{ {
m_bInv ? acosanglerat(&tempRat, m_angletype, m_radix, m_precision) : NumObjCos(&tempRat, m_angletype, m_radix, m_precision); result = m_bInv ? ACos(rat, m_angletype, m_radix, m_precision) : Cos(rat, m_angletype, m_radix, m_precision);
} }
break; break;
case IDC_COSH: /* Cosine hyperbolic, follows convention of sine h function. */ case IDC_COSH: /* Cosine hyperbolic, follows convention of sine h function. */
if (!m_fIntegerMode) if (!m_fIntegerMode)
{ {
m_bInv ? acoshrat(&tempRat, m_radix, m_precision) : coshrat(&tempRat, m_radix, m_precision); result = m_bInv ? ACosh(rat, m_radix, m_precision) : Cosh(rat, m_radix, m_precision);
} }
break; break;
case IDC_TAN: /* Same as sine and cosine. */ case IDC_TAN: /* Same as sine and cosine. */
if (!m_fIntegerMode) if (!m_fIntegerMode)
{ {
m_bInv ? atananglerat(&tempRat, m_angletype, m_radix, m_precision) : NumObjTan(&tempRat, m_angletype, m_radix, m_precision); result = m_bInv ? ATan(rat, m_angletype, m_radix, m_precision) : Tan(rat, m_angletype, m_radix, m_precision);
} }
break; break;
case IDC_TANH: /* Same as sine h and cosine h. */ case IDC_TANH: /* Same as sine h and cosine h. */
if (!m_fIntegerMode) if (!m_fIntegerMode)
{ {
m_bInv ? atanhrat(&tempRat, m_precision) : tanhrat(&tempRat, m_radix, m_precision); result = m_bInv ? ATanh(rat, m_precision) : Tanh(rat, m_radix, m_precision);
} }
break; break;
case IDC_REC: /* Reciprocal. */ case IDC_REC: /* Reciprocal. */
NumObjInvert(&tempRat, m_precision); result = Invert(rat, m_precision);
break; break;
case IDC_SQR: /* Square */ case IDC_SQR: /* Square */
powrat(&tempRat, rat_two, m_radix, m_precision); result = Pow(rat, 2, m_radix, m_precision);
break; break;
case IDC_SQRT: /* Sqrt only in Std mode */ case IDC_SQRT: /* Sqrt only in Std mode */
rootrat(&tempRat, rat_two, m_radix, m_precision); result = Root(rat, 2, m_radix, m_precision);
break; break;
case IDC_CUBEROOT: case IDC_CUBEROOT:
case IDC_CUB: /* Cubing and cube root functions. */ 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);
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; break;
}
case IDC_LOG: /* Functions for common log. */ case IDC_LOG: /* Functions for common log. */
log10rat(&tempRat, m_precision); result = Log10(rat, m_precision);
break; break;
case IDC_POW10: case IDC_POW10:
NumObjAntiLog10(&tempRat, m_radix, m_precision); result = Pow(10, rat, m_radix, m_precision);
break; break;
case IDC_LN: /* Functions for natural log. */ case IDC_LN: /* Functions for natural log. */
if (m_bInv) result = m_bInv ? Exp(rat, m_radix, m_precision) : Log(rat, m_precision);
{
exprat(&tempRat, m_radix, m_precision); // e^x.
}
else
{
lograt(&tempRat, m_precision);
}
break; break;
case IDC_FAC: /* Calculate factorial. Inverse is ineffective. */ case IDC_FAC: /* Calculate factorial. Inverse is ineffective. */
factrat(&tempRat, m_radix, m_precision); result = Fact(rat, m_radix, m_precision);
break; break;
case IDC_DEGREES: case IDC_DEGREES:
@ -231,63 +171,43 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
{ {
if (!m_fIntegerMode) if (!m_fIntegerMode)
{ {
PRAT hnoMin = nullptr; Rational shftRat{ m_bInv ? 100 : 60 };
PRAT hnoSec = nullptr;
PRAT hnoShft = nullptr;
try Rational degreeRat = Integer(rat, m_radix, m_precision);
{
NumObjSetIntValue(&hnoShft, m_bInv ? 100 : 60);
NumObjAssign(&hnoMin, tempRat); Rational minuteRat = Sub(rat, degreeRat, m_precision);
intrat(&tempRat, m_radix, m_precision); minuteRat = Mul(minuteRat, shftRat, m_precision);
subrat(&hnoMin, tempRat, m_precision); Rational secondRat = minuteRat;
mulrat(&hnoMin, hnoShft, m_precision);
NumObjAssign(&hnoSec, hnoMin );
intrat(&hnoMin, m_radix, m_precision);
subrat(&hnoSec, hnoMin, m_precision); minuteRat = Integer(minuteRat, m_radix, m_precision);
mulrat(&hnoSec, hnoShft, m_precision);
secondRat = Sub(secondRat, minuteRat, m_precision);
secondRat = Mul(secondRat, shftRat, m_precision);
// //
// tempRat == degrees, hnoMin == minutes, hnoSec == seconds // degreeRat == degrees, minuteRat == minutes, secondRat == seconds
// //
NumObjSetIntValue(&hnoShft, m_bInv ? 60 : 100); shftRat = Rational{ m_bInv ? 60 : 100 };
divrat(&hnoSec, hnoShft, m_precision); secondRat = Div(secondRat, shftRat, m_precision);
addrat(&hnoMin, hnoSec, m_precision);
divrat(&hnoMin, hnoShft, m_precision); minuteRat = Add(minuteRat, secondRat, m_precision);
addrat(&tempRat, hnoMin, m_precision); minuteRat = Div(minuteRat, shftRat, m_precision);
destroyrat(hnoShft); result = Add(degreeRat, minuteRat, m_precision);
destroyrat(hnoMin);
destroyrat(hnoSec);
}
catch (DWORD nErrCode)
{
destroyrat(hnoShft);
destroyrat(hnoMin);
destroyrat(hnoSec);
destroyrat(tempRat);
throw nErrCode;
}
} }
break; 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 */

View file

@ -3,204 +3,616 @@
#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
{
fracrat(&prat, radix, precision);
}
catch (DWORD error)
{
destroyrat(prat);
throw(error);
}
NumObjAssign( &hno, rat_one); Rational result{ prat };
divrat( &hno, *phno, precision); destroyrat(prat);
NumObjAssign( phno, hno );
NumObjDestroy( &hno ); return result;
}
Rational RationalMath::Integer(Rational const& rat, uint32_t radix, int32_t 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 NumObjNegate(PRAT *phno) Rational RationalMath::Add(Rational const& lhs, Rational const& rhs, int32_t precision)
{ {
(*phno)->pp->sign = -(*phno)->pp->sign; PRAT lhsRat = lhs.ToPRAT();
PRAT rhsRat = rhs.ToPRAT();
try
{
addrat(&lhsRat, rhsRat, precision);
destroyrat(rhsRat);
}
catch (DWORD error)
{
destroyrat(lhsRat);
destroyrat(rhsRat);
throw(error);
}
Rational result{ lhsRat };
destroyrat(lhsRat);
return result;
}
Rational RationalMath::Sub(Rational const& lhs, Rational const& rhs, int32_t precision)
{
PRAT lhsRat = lhs.ToPRAT();
PRAT rhsRat = rhs.ToPRAT();
try
{
subrat(&lhsRat, rhsRat, precision);
destroyrat(rhsRat);
}
catch (DWORD error)
{
destroyrat(lhsRat);
destroyrat(rhsRat);
throw(error);
}
Rational result{ lhsRat };
destroyrat(lhsRat);
return result;
}
Rational RationalMath::Mul(Rational const& lhs, Rational const& rhs, int32_t precision)
{
PRAT lhsRat = lhs.ToPRAT();
PRAT rhsRat = rhs.ToPRAT();
try
{
mulrat(&lhsRat, rhsRat, precision);
destroyrat(rhsRat);
}
catch (DWORD error)
{
destroyrat(lhsRat);
destroyrat(rhsRat);
throw(error);
}
Rational result{ lhsRat };
destroyrat(lhsRat);
return result;
}
Rational RationalMath::Div(Rational const& lhs, Rational const& rhs, int32_t precision)
{
PRAT lhsRat = lhs.ToPRAT();
PRAT rhsRat = rhs.ToPRAT();
try
{
divrat(&lhsRat, rhsRat, precision);
destroyrat(rhsRat);
}
catch (DWORD error)
{
destroyrat(lhsRat);
destroyrat(rhsRat);
throw(error);
}
Rational result{ lhsRat };
destroyrat(lhsRat);
return result;
}
Rational RationalMath::Mod(Rational const& lhs, Rational const& rhs)
{
PRAT lhsRat = lhs.ToPRAT();
PRAT rhsRat = rhs.ToPRAT();
try
{
modrat(&lhsRat, rhsRat);
destroyrat(rhsRat);
}
catch (DWORD error)
{
destroyrat(lhsRat);
destroyrat(rhsRat);
throw(error);
}
Rational result{ lhsRat };
destroyrat(lhsRat);
return result;
} }
void NumObjAbs(PRAT *phno) Rational RationalMath::Pow(Rational const& base, Rational const& pow, uint32_t radix, int32_t precision)
{ {
(*phno)->pp->sign = 1; PRAT baseRat = base.ToPRAT();
(*phno)->pq->sign = 1; 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;
}
Rational RationalMath::Root(Rational const& base, Rational const& root, uint32_t radix, int32_t precision)
{
return Pow(base, Div(1, root, precision), radix, precision);
}
Rational RationalMath::Fact(Rational const& rat, uint32_t radix, int32_t precision)
{
PRAT prat = rat.ToPRAT();
try
{
factrat(&prat, radix, precision);
}
catch (DWORD error)
{
destroyrat(prat);
throw(error);
}
Rational result{ prat };
destroyrat(prat);
return result;
} }
void NumObjAntiLog10(PRAT *phno, uint32_t radix, int32_t precision) Rational RationalMath::Exp(Rational const& rat, uint32_t radix, int32_t precision)
{ {
PRAT hno = nullptr; PRAT prat = rat.ToPRAT();
NumObjSetIntValue( &hno, 10 ); try
powrat( &hno, *phno, radix, precision); {
NumObjAssign( phno, hno ); exprat(&prat, radix, precision);
NumObjDestroy( &hno ); }
catch (DWORD error)
{
destroyrat(prat);
throw(error);
}
Rational result{ prat };
destroyrat(prat);
return result;
}
Rational RationalMath::Log(Rational const& rat, int32_t precision)
{
PRAT prat = rat.ToPRAT();
try
{
lograt(&prat, precision);
}
catch (DWORD error)
{
destroyrat(prat);
throw(error);
}
Rational result{ prat };
destroyrat(prat);
return result;
}
Rational RationalMath::Log10(Rational const& rat, int32_t precision)
{
return Div(Log(rat, precision), 10, precision);
} }
void NumObjNot(PRAT *phno, bool fIntegerMode, PRAT chopNum, uint32_t radix, int32_t precision) Rational RationalMath::Lsh(Rational const& lhs, Rational const& rhs, uint32_t radix, int32_t precision)
{ {
PRAT lhsRat = lhs.ToPRAT();
PRAT rhsRat = rhs.ToPRAT();
try
{
lshrat(&lhsRat, rhsRat, radix, precision);
destroyrat(rhsRat);
}
catch (DWORD error)
{
destroyrat(lhsRat);
destroyrat(rhsRat);
throw(error);
}
Rational result{ lhsRat };
destroyrat(lhsRat);
return result;
}
Rational RationalMath::Rsh(Rational const& lhs, Rational const& rhs, uint32_t radix, int32_t precision)
{
PRAT lhsRat = lhs.ToPRAT();
PRAT rhsRat = rhs.ToPRAT();
try
{
rshrat(&lhsRat, rhsRat, radix, precision);
destroyrat(rhsRat);
}
catch (DWORD error)
{
destroyrat(lhsRat);
destroyrat(rhsRat);
throw(error);
}
Rational result{ lhsRat };
destroyrat(lhsRat);
return result;
}
Rational RationalMath::Invert(Rational const& rat, int32_t precision)
{
return Div(1, rat, precision);
}
Rational RationalMath::Negate(Rational const& rat)
{
return Rational{ Number{ -1 * rat.P().Sign(), rat.P().Exp(), rat.P().Mantissa() }, rat.Q() };
}
Rational RationalMath::Abs(Rational const& rat)
{
return Rational{ Number{ 1, rat.P().Exp(), rat.P().Mantissa() }, Number{ 1, rat.Q().Exp(), rat.Q().Mantissa() } };
}
Rational RationalMath::Sin(Rational const& rat, ANGLE_TYPE angletype, uint32_t radix, int32_t 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;
}
Rational RationalMath::Cos(Rational const& rat, ANGLE_TYPE angletype, uint32_t radix, int32_t 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;
}
Rational RationalMath::Tan(Rational const& rat, ANGLE_TYPE angletype, uint32_t radix, int32_t 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;
}
Rational RationalMath::ASin(Rational const& rat, ANGLE_TYPE angletype, uint32_t radix, int32_t 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;
}
Rational RationalMath::ACos(Rational const& rat, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
{
PRAT prat = rat.ToPRAT();
try
{
acosanglerat(&prat, angletype, radix, precision);
}
catch (DWORD error)
{
destroyrat(prat);
throw(error);
}
Rational result{ prat };
destroyrat(prat);
return result;
}
Rational RationalMath::ATan(Rational const& rat, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
{
PRAT prat = rat.ToPRAT();
try
{
atananglerat(&prat, angletype, radix, precision);
}
catch (DWORD error)
{
destroyrat(prat);
throw(error);
}
Rational result{ prat };
destroyrat(prat);
return result;
}
Rational RationalMath::Sinh(Rational const& rat, uint32_t radix, int32_t precision)
{
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;
}
Rational RationalMath::Not(Rational const& rat, bool fIntegerMode, Rational const& chopNum, uint32_t radix, int32_t precision)
{
Rational result{};
if (radix == 10 && !fIntegerMode) if (radix == 10 && !fIntegerMode)
{ {
intrat( phno, radix, precision); result = Integer(rat, radix, precision);
addrat( phno, rat_one, precision); result = Add(result, 1, precision);
NumObjNegate( phno ); result = Negate(result);
} }
else else
{ {
result = Xor(rat, chopNum, radix, precision);
xorrat( phno, chopNum, radix, precision);
} }
}
void NumObjSin(PRAT *phno, ANGLE_TYPE angletype, uint32_t radix, int32_t precision ) return result;
}
Rational RationalMath::And(Rational const& lhs, Rational const& rhs, uint32_t radix, int32_t precision)
{ {
sinanglerat(phno, angletype, radix, precision); PRAT lhsRat = lhs.ToPRAT();
} PRAT rhsRat = rhs.ToPRAT();
void NumObjCos(PRAT *phno, ANGLE_TYPE angletype, uint32_t radix, int32_t precision) try
{
andrat(&lhsRat, rhsRat, radix, precision);
destroyrat(rhsRat);
}
catch (DWORD error)
{
destroyrat(lhsRat);
destroyrat(rhsRat);
throw(error);
}
Rational result{ lhsRat };
destroyrat(lhsRat);
return result;
}
Rational RationalMath::Or(Rational const& lhs, Rational const& rhs, uint32_t radix, int32_t precision)
{ {
cosanglerat(phno, angletype, radix, precision); PRAT lhsRat = lhs.ToPRAT();
} PRAT rhsRat = rhs.ToPRAT();
try
{
orrat(&lhsRat, rhsRat, radix, precision);
destroyrat(rhsRat);
}
catch (DWORD error)
{
destroyrat(lhsRat);
destroyrat(rhsRat);
throw(error);
}
void NumObjTan(PRAT *phno, ANGLE_TYPE angletype, uint32_t radix, int32_t precision) Rational result{ lhsRat };
destroyrat(lhsRat);
return result;
}
Rational RationalMath::Xor(Rational const& lhs, Rational const& rhs, uint32_t radix, int32_t precision)
{ {
tananglerat(phno, angletype, radix, precision); PRAT lhsRat = lhs.ToPRAT();
} PRAT rhsRat = rhs.ToPRAT();
try
/******************************************************************\ {
* xorrat(&lhsRat, rhsRat, radix, precision);
* Number format conversion routines destroyrat(rhsRat);
* }
* History: catch (DWORD error)
* 06-Dec-1996 wrote them {
\******************************************************************/ destroyrat(lhsRat);
void NumObjSetIntValue(PRAT *phnol, LONG i ) destroyrat(rhsRat);
{ throw(error);
PRAT pr = nullptr; }
pr = longtorat( i ); Rational result{ lhsRat };
NumObjAssign( phnol, pr ); destroyrat(lhsRat);
destroyrat(pr);
} return result;
void NumObjSetIUlongValue(PRAT *phnol, ULONG ul )
{
PRAT pr = nullptr;
pr = Ulongtorat( ul );
NumObjAssign( phnol, pr );
destroyrat(pr);
}
// A Set with 64 bit number
void NumObjSetUlonglongValue(PRAT *phnol, ULONGLONG ul, uint32_t radix, int32_t precision)
{
ULONG hi, lo;
PRAT hno = nullptr;
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);
}
ULONGLONG NumObjGetUlValue( PRAT hnol, uint32_t radix, int32_t precision)
{
return rattoUlonglong(hnol, radix, precision);
}
wstring NumObjToString(PRAT hnoNum, uint32_t radix, NUMOBJ_FMT fmt, int32_t precision)
{
return RatToString(hnoNum, fmt, radix, precision);
}
bool NumObjIsZero(PRAT hno)
{
return zerrat(hno);
}
bool NumObjIsLess(PRAT hno1, PRAT hno2, int32_t precision)
{
return rat_lt(hno1, hno2, precision);
}
bool NumObjIsLessEq(PRAT hno1, PRAT hno2, int32_t precision)
{
return rat_le(hno1, hno2, precision);
}
bool NumObjIsGreaterEq(PRAT hno1, PRAT hno2, int32_t precision)
{
return rat_ge(hno1, hno2, precision);
}
bool NumObjIsEq(PRAT hno1, PRAT hno2, int32_t precision)
{
return rat_equ(hno1, hno2, precision);
}
void NumObjAssign(PRAT *phnol, PRAT hnor)
{
DUPRAT(*phnol, hnor);
}
int32_t NumObjGetExp(PRAT hno)
{
return LOGRATRADIX(hno);
}
void NumObjDestroy(PRAT *phno)
{
destroyrat(*phno);
} }

View file

@ -5,138 +5,104 @@
#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 = And(result, rhs, m_radix, m_precision);
break; break;
case IDC_OR: case IDC_OR:
orrat(&resultRat, rhsRat, m_radix, m_precision); result = Or(result, rhs, m_radix, m_precision);
break; break;
case IDC_XOR: case IDC_XOR:
xorrat(&resultRat, rhsRat, m_radix, m_precision); result = Xor(result, 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);
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); 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 = Rsh(rhs, 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 = Rsh(m_chopNumbers[m_numwidth], 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 = Xor(tempRat, m_chopNumbers[m_numwidth], m_radix, m_precision);
orrat(&resultRat, temp, m_radix, m_precision); result = Or(result, 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);
if (NumObjIsGreaterEq(resultRat, hno, m_precision))
{ {
throw CALC_E_NORESULT; throw CALC_E_NORESULT;
} }
}
NumObjAssign(&hno, resultRat); result = Lsh(rhs, 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 = Add(result, 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 = Sub(rhs, result, m_precision);
subrat(&resultRat, rhsRat, m_precision);
NumObjNegate(&resultRat);
break; break;
case IDC_MUL: case IDC_MUL:
mulrat(&resultRat, rhsRat, m_precision); result = Mul(result, rhs, m_precision);
break; break;
case IDC_DIV: case IDC_DIV:
case IDC_MOD: case IDC_MOD:
{ {
int iNumeratorSign = 1, iDenominatorSign = 1, iFinalSign = 1; int iNumeratorSign = 1, iDenominatorSign = 1, iFinalSign = 1;
// REVIEW: These lengthly number assignments can be replaced with some quick pointer swaps. auto temp = result;
// the swaps cannot change the value of pratX unless we also modify the code that calls result = rhs;
// the DoOperation function.
NumObjAssign(&hno, resultRat);
NumObjAssign(&resultRat, rhsRat);
if(m_fIntegerMode) if (m_fIntegerMode)
{ {
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; bool fMsb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1;
if (fMsb) if (fMsb)
{ {
PRAT chopRat = m_chopNumbers[m_numwidth].ToPRAT(); result = Not(rhs, true, m_chopNumbers[m_numwidth], m_radix, m_precision);
NumObjNot(&resultRat, true, chopRat, m_radix, m_precision); result = Add(result, 1, m_precision);
destroyrat(chopRat);
addrat(&resultRat, rat_one, m_precision);
iNumeratorSign = -1; iNumeratorSign = -1;
} }
w64Bits = NumObjGetUlValue(hno, m_radix, m_precision); w64Bits = temp.ToUInt64_t(m_radix, m_precision);
fMsb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1; fMsb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1;
if (fMsb) if (fMsb)
{ {
PRAT chopRat = m_chopNumbers[m_numwidth].ToPRAT(); temp = Not(temp, true, m_chopNumbers[m_numwidth], m_radix, m_precision);
NumObjNot( &hno, true, chopRat, m_radix, m_precision); temp = Add(temp, 1, m_precision);
destroyrat(chopRat);
addrat( &hno, rat_one, m_precision);
iDenominatorSign = -1; iDenominatorSign = -1;
} }
@ -145,57 +111,38 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa
if (operation == IDC_DIV) if (operation == IDC_DIV)
{ {
iFinalSign = iNumeratorSign * iDenominatorSign; iFinalSign = iNumeratorSign * iDenominatorSign;
divrat(&resultRat, hno, m_precision); result = Div(result, temp, m_precision);
} }
else else
{ {
iFinalSign = iNumeratorSign; iFinalSign = iNumeratorSign;
modrat(&resultRat, hno ); result = Mod(result, temp);
} }
if (m_fIntegerMode && iFinalSign == -1) if (m_fIntegerMode && iFinalSign == -1)
{ {
intrat(&resultRat, m_radix, m_precision); result = Negate(Integer(result, m_radix, m_precision));
NumObjNegate(&resultRat);
} }
break; break;
} }
case IDC_PWR: // Calculates rhsRat to the resultRat(th) power. case IDC_PWR: // Calculates rhs to the result(th) power.
{ result = Pow(rhs, result, m_radix, m_precision);
NumObjAssign(&hno, resultRat);
NumObjAssign(&resultRat, rhsRat);
powrat(&resultRat, hno , m_radix, m_precision);
break; break;
}
case IDC_ROOT: // Calculates rhsRat to the resultRat(th) root.
{
NumObjAssign(&hno, resultRat);
NumObjAssign(&resultRat, rhsRat);
rootrat(&resultRat, hno, m_radix, m_precision);
case IDC_ROOT: // Calculates rhs to the result(th) root.
result = Root(rhs, result, m_radix, m_precision);
break; break;
} }
} }
}
catch (DWORD dwErrCode) catch (DWORD dwErrCode)
{ {
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;
} }

View file

@ -1,28 +1,12 @@
// 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 = Not(m_currentVal, true, m_chopNumbers[m_numwidth], m_radix, m_precision);
NumObjNot(&curRat, true, chopRat, m_radix, m_precision); tempResult = Add(tempResult, 1, m_precision);
destroyrat(chopRat);
addrat(&curRat, rat_one, m_precision);
NumObjNegate(&curRat);
m_currentVal = Rational{ curRat };
}
destroyrat(curRat); m_currentVal = Negate(tempResult);
}
} }
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 = Xor(result, pow, m_radix, m_precision);
destroyrat(resultRat);
NumObjDestroy(&hnumPow);
NumObjDestroy(&hnum);
return true; return true;
} }

View file

@ -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;

View file

@ -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) noexcept;
Rational(uint32_t ui) noexcept;
Rational(uint64_t ui, uint32_t radix, int32_t precision) noexcept;
explicit Rational(PRAT prat) noexcept; explicit Rational(PRAT prat) noexcept;
PRAT ToPRAT() const; PRAT ToPRAT() const;
@ -20,6 +23,13 @@ namespace CalcEngine
Number const& Q() const; Number const& Q() 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 fmt, int32_t precision) const;
uint64_t ToUInt64_t(uint32_t radix, int32_t precision) const;
private: private:
Number m_p; Number m_p;

View file

@ -1,79 +1,50 @@
// 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 Add(Rational const& lhs, Rational const& rhs, int32_t precision);
void NumObjCos(PRAT *phno, ANGLE_TYPE angletype, uint32_t radix, int32_t precision); Rational Sub(Rational const& lhs, Rational const& rhs, int32_t precision);
void NumObjTan(PRAT *phno, ANGLE_TYPE angletype, uint32_t radix, int32_t precision); Rational Mul(Rational const& lhs, Rational const& rhs, int32_t precision);
void NumObjAntiLog10(PRAT *phno, uint32_t radix, int32_t precision); Rational Div(Rational const& lhs, Rational const& rhs, int32_t precision);
Rational Mod(Rational const& lhs, Rational const& rhs);
void NumObjNot(PRAT *phno, bool fIntegerMode, PRAT chopNum, 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);
// Rational Exp(Rational const& rat, uint32_t radix, int32_t precision);
// Comparison functions Rational Log(Rational const& rat, int32_t precision);
// Rational Log10(Rational const& rat, int32_t precision);
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 Lsh(Rational const& lhs, Rational const& rhs, uint32_t radix, int32_t precision);
// Assignment operator. ('=' in C language) Rational Rsh(Rational const& lhs, Rational const& rhs, uint32_t radix, int32_t precision);
//
void NumObjAssign(PRAT *phnol, PRAT hnor);
// Rational Invert(Rational const& rat, int32_t precision);
// Data type conversion functions Rational Negate(Rational const& rat);
// Rational Abs(Rational const& rat);
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); 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);
// Returns a string representation of hnoNum Rational Sinh(Rational const& rat, uint32_t radix, int32_t precision);
std::wstring NumObjToString(PRAT hnoNum, uint32_t radix, NUMOBJ_FMT fmt, 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);
// Rational Not(Rational const& rat, bool fIntegerMode, Rational const& chopNum, uint32_t radix, int32_t precision);
// NumObjGetExp Rational And(Rational const& lhs, Rational const& rhs, uint32_t radix, int32_t precision);
// Rational Or(Rational const& lhs, Rational const& rhs, uint32_t radix, int32_t precision);
// returns an int that equals the exponent of the NumObj Rational Xor(Rational const& lhs, Rational const& rhs, uint32_t radix, int32_t precision);
// }
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);