Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CalcEngine: Manage precision internally to Rational and convert functions to operator overrides #35

Merged
merged 21 commits into from
Feb 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
3cef856
Convert Rational class to always use BASEX as radix. Convert to corre…
joshkoon Feb 19, 2019
43bd7bb
Set a default base of base64 for Rational class.
joshkoon Feb 21, 2019
9c6ef25
Revert Rational default base to 64 and uncomment code to convert to/f…
joshkoon Feb 21, 2019
08e973a
Convert Rational::Negate to an operator override
joshkoon Feb 21, 2019
259d16e
Convert Rational::Add to + and += operator overrides.
joshkoon Feb 21, 2019
4961b7c
Convet Rational::Sub to - and -= operator overrides.
joshkoon Feb 21, 2019
09d8e60
Convert Rational::Div and ::Mul to use /, /=, *, *= operator overrides.
joshkoon Feb 21, 2019
34b2797
Convert Rational::Mod to use %= and % operator overrides
joshkoon Feb 21, 2019
5f641c1
Convert Rational::Rsh and ::Lsh to use >>=, >>, <<=, << operator over…
joshkoon Feb 21, 2019
2fecd35
Convert Rational::And, ::Or, ::Xor to use &=, &, |=, |, ^=, ^ operato…
joshkoon Feb 21, 2019
0d298e1
Convert Rational relational functions to operator overrides
joshkoon Feb 21, 2019
5e4eaf6
Remove unnecessary precision arguments from Rational class and remove…
joshkoon Feb 21, 2019
41db5fa
Remove unnecessary precision variable from RationalMath operations
joshkoon Feb 21, 2019
dde5f59
Replace unnecessary Rational::Not with Xor operation
joshkoon Feb 22, 2019
9d7cc0e
Formatting of Rational function order
joshkoon Feb 22, 2019
6a84805
Whitespace
joshkoon Feb 22, 2019
6150bea
Mark RATIONAL_PRECISION as inline constexpr
joshkoon Feb 22, 2019
2dc3455
Fix rounding issues in ratpak that result from using large precisions.
joshkoon Feb 22, 2019
75792d4
Clean up header includes for scimath and Rational
joshkoon Feb 24, 2019
14d8dc9
Remove unnecessary Rational::IsZero() in favor of == 0 comparisons
joshkoon Feb 25, 2019
1e3da53
Move assignment stmt out of IsCurrentTooBigForTrig
joshkoon Feb 25, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
229 changes: 126 additions & 103 deletions src/CalcManager/CEngine/Rational.cpp

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions src/CalcManager/CEngine/calc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ CCalcEngine::CCalcEngine(bool fPrecedence, bool fIntegerMode, CalculationManager

m_dwWordBitWidth = DwWordBitWidthFromeNumWidth(m_numwidth);

m_maxTrigonometricNum = RationalMath::Pow(10, 100, m_precision);
m_maxTrigonometricNum = RationalMath::Pow(10, 100);

SetRadixTypeAndNumWidth(DEC_RADIX, m_numwidth);
SettingsChanged();
Expand All @@ -117,8 +117,8 @@ void CCalcEngine::InitChopNumbers()
assert(m_chopNumbers.size() == m_maxDecimalValueStrings.size());
for (size_t i = 0; i < m_chopNumbers.size(); i++)
{
auto maxVal = m_chopNumbers[i].Div(2, m_precision);
maxVal = RationalMath::Integer(maxVal, m_precision);
auto maxVal = m_chopNumbers[i] / 2;
maxVal = RationalMath::Integer(maxVal);

m_maxDecimalValueStrings[i] = maxVal.ToString(10, FMT_FLOAT, m_precision);
}
Expand Down
31 changes: 12 additions & 19 deletions src/CalcManager/CEngine/scicomm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
{
if (IsCurrentTooBigForTrig())
{
m_currentVal = 0;
DisplayError(CALC_E_DOMAIN);
return;
}
Expand Down Expand Up @@ -382,7 +383,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
CheckAndAddLastBinOpToHistory(false);
}

m_lastVal = Rational{};
m_lastVal = 0;

m_bChangeOp = false;
m_precedenceOpCount = m_nTempCom = m_nLastCom = m_nOpCode = m_openParenCount = 0;
Expand Down Expand Up @@ -563,12 +564,12 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
m_nPrecOp[m_precedenceOpCount++] = 0;
}

m_lastVal = Rational{};
m_lastVal = 0;
if (IsBinOpCode(m_nLastCom))
{
// We want 1 + ( to start as 1 + (0. Any number you type replaces 0. But if it is 1 + 3 (, it is
// treated as 1 + (3
m_currentVal = Rational{};
m_currentVal = 0;
}
m_nTempCom = 0;
m_nOpCode = 0;
Expand Down Expand Up @@ -691,7 +692,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
m_HistoryCollector.AddOpndToHistory(m_numberString, m_currentVal);
}

m_currentVal = m_currentVal.Negate();
m_currentVal = -(m_currentVal);

DisplayNum();
m_HistoryCollector.AddUnaryOpToHistory(IDC_SIGN, m_bInv, m_angletype);
Expand All @@ -708,7 +709,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
else
{
// Recall immediate memory value.
m_currentVal = Rational{ *m_memoryValue };
m_currentVal = *m_memoryValue;
}
CheckAndAddLastBinOpToHistory();
DisplayNum();
Expand All @@ -718,7 +719,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
{
/* MPLUS adds m_currentVal to immediate memory and kills the "mem" */
/* indicator if the result is zero. */
Rational result = m_memoryValue->Add(m_currentVal, m_precision);
Rational result = *m_memoryValue + m_currentVal;
m_memoryValue = make_unique<Rational>(TruncateNumForIntMath(result)); // Memory should follow the current int mode

break;
Expand All @@ -727,14 +728,14 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
{
/* MMINUS subtracts m_currentVal to immediate memory and kills the "mem" */
/* indicator if the result is zero. */
Rational result = m_memoryValue->Sub(m_currentVal, m_precision);
Rational result = *m_memoryValue - m_currentVal;
m_memoryValue = make_unique<Rational>(TruncateNumForIntMath(result));

break;
}
case IDC_STORE:
case IDC_MCLEAR:
m_memoryValue = make_unique<Rational>(wParam == IDC_STORE ? TruncateNumForIntMath(m_currentVal) : Rational{});
m_memoryValue = make_unique<Rational>(wParam == IDC_STORE ? TruncateNumForIntMath(m_currentVal) : 0);
break;

case IDC_PI:
Expand Down Expand Up @@ -1002,13 +1003,7 @@ int CCalcEngine::IdcSetAngleTypeDecMode(int idc)

bool CCalcEngine::IsCurrentTooBigForTrig()
joshkoon marked this conversation as resolved.
Show resolved Hide resolved
{
if (m_currentVal.IsGreaterEq(m_maxTrigonometricNum, m_precision))
{
m_currentVal = Rational{};
return true;
}

return false;
return m_currentVal >= m_maxTrigonometricNum;
}

int CCalcEngine::GetCurrentRadix()
Expand Down Expand Up @@ -1048,14 +1043,12 @@ wstring CCalcEngine::GetStringForDisplay(Rational const& rat, uint32_t radix)

try
{
uint64_t w64Bits = tempRat.ToUInt64_t(m_precision);
uint64_t w64Bits = tempRat.ToUInt64_t();
bool fMsb = ((w64Bits >> (m_dwWordBitWidth - 1)) & 1);
if ((radix == 10) && fMsb)
{
// If high bit is set, then get the decimal number in negative 2's compl form.
tempRat = tempRat.Not(m_chopNumbers[m_numwidth], m_precision);
tempRat = tempRat.Add(1, m_precision);
tempRat = tempRat.Negate();
tempRat = -((tempRat ^ m_chopNumbers[m_numwidth]) + 1);
}

result = tempRat.ToString(radix, m_nFE, m_precision);
Expand Down
13 changes: 6 additions & 7 deletions src/CalcManager/CEngine/scidisp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,19 +57,18 @@ CalcEngine::Rational CCalcEngine::TruncateNumForIntMath(CalcEngine::Rational con
}

// Truncate to an integer. Do not round here.
auto result = RationalMath::Integer(rat, m_precision);
auto result = RationalMath::Integer(rat);

// Can be converting a dec negative number to Hex/Oct/Bin rep. Use 2's complement form
// Check the range.
if (result.IsLess(0, m_precision))
if (result < 0)
{
// if negative make positive by doing a twos complement
joshkoon marked this conversation as resolved.
Show resolved Hide resolved
result = result.Negate();
result = result.Sub(1, m_precision);
result = result.Not(m_chopNumbers[m_numwidth], m_precision);
result = -(result) - 1;
result ^= m_chopNumbers[m_numwidth];
}

result = result.And(m_chopNumbers[m_numwidth], m_precision);
result &= m_chopNumbers[m_numwidth];

return result;
}
Expand All @@ -84,7 +83,7 @@ void CCalcEngine::DisplayNum(void)
// called.
//
if (m_bRecord ||
!gldPrevious.value.IsEq(m_currentVal, m_precision) ||
gldPrevious.value != m_currentVal ||
gldPrevious.precision != m_precision ||
gldPrevious.radix != m_radix ||
gldPrevious.nFE != (int)m_nFE ||
Expand Down
74 changes: 34 additions & 40 deletions src/CalcManager/CEngine/scifunc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,50 +32,48 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
switch (op)
{
case IDC_CHOP:
result = m_bInv ? Frac(rat, m_precision) : Integer(rat, m_precision);
result = m_bInv ? Frac(rat) : Integer(rat);
break;

/* Return complement. */
case IDC_COM:
if (m_radix == 10 && !m_fIntegerMode)
{
result = RationalMath::Integer(rat, m_precision);
result = result.Add(1, m_precision);
result = result.Negate();
result = -(RationalMath::Integer(rat) + 1);
}
else
{
result = rat.Xor(m_chopNumbers[m_numwidth], m_precision);
result = rat ^ m_chopNumbers[m_numwidth];
}
break;

// Rotate Left with hi bit wrapped over to lo bit
case IDC_ROL:
if (m_fIntegerMode)
{
result = Integer(rat, m_precision);
result = Integer(rat);

uint64_t w64Bits = result.ToUInt64_t(m_precision);
uint64_t w64Bits = result.ToUInt64_t();
uint64_t msb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1;
w64Bits <<= 1; // LShift by 1
w64Bits |= msb; // Set the prev Msb as the current Lsb

result = Rational{ w64Bits, m_precision };
result = w64Bits;
}
break;

// Rotate right with lo bit wrapped over to hi bit
case IDC_ROR:
if (m_fIntegerMode)
{
result = Integer(rat, m_precision);
result = Integer(rat);

uint64_t w64Bits = result.ToUInt64_t(m_precision);
uint64_t w64Bits = result.ToUInt64_t();
uint64_t lsb = ((w64Bits & 0x01) == 1) ? 1 : 0;
w64Bits >>= 1; //RShift by 1
w64Bits |= (lsb << (m_dwWordBitWidth - 1));

result = Rational{ w64Bits, m_precision };
result = w64Bits;
}
break;

Expand All @@ -85,89 +83,88 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
// Otherwise, we evaluate it as "X [op] (X * Y%)"
if (m_nOpCode == IDC_MUL || m_nOpCode == IDC_DIV)
{
result = rat.Div(100, m_precision);
result = rat / 100;
}
else
{
result = m_lastVal.Div(100, m_precision);
result = rat.Mul(result, m_precision);
result = rat * (m_lastVal / 100);
}
break;
}

case IDC_SIN: /* Sine; normal and arc */
if (!m_fIntegerMode)
{
result = m_bInv ? ASin(rat, m_angletype, m_precision) : Sin(rat, m_angletype, m_precision);
result = m_bInv ? ASin(rat, m_angletype) : Sin(rat, m_angletype);
}
break;

case IDC_SINH: /* Sine- hyperbolic and archyperbolic */
if (!m_fIntegerMode)
{
result = m_bInv ? ASinh(rat, m_precision) : Sinh(rat, m_precision);
result = m_bInv ? ASinh(rat) : Sinh(rat);
}
break;

case IDC_COS: /* Cosine, follows convention of sine function. */
if (!m_fIntegerMode)
{
result = m_bInv ? ACos(rat, m_angletype, m_precision) : Cos(rat, m_angletype, m_precision);
result = m_bInv ? ACos(rat, m_angletype) : Cos(rat, m_angletype);
}
break;

case IDC_COSH: /* Cosine hyperbolic, follows convention of sine h function. */
if (!m_fIntegerMode)
{
result = m_bInv ? ACosh(rat, m_precision) : Cosh(rat, m_precision);
result = m_bInv ? ACosh(rat) : Cosh(rat);
}
break;

case IDC_TAN: /* Same as sine and cosine. */
if (!m_fIntegerMode)
{
result = m_bInv ? ATan(rat, m_angletype, m_precision) : Tan(rat, m_angletype, m_precision);
result = m_bInv ? ATan(rat, m_angletype) : Tan(rat, m_angletype);
}
break;

case IDC_TANH: /* Same as sine h and cosine h. */
if (!m_fIntegerMode)
{
result = m_bInv ? ATanh(rat, m_precision) : Tanh(rat, m_precision);
result = m_bInv ? ATanh(rat) : Tanh(rat);
}
break;

case IDC_REC: /* Reciprocal. */
result = Invert(rat, m_precision);
result = Invert(rat);
break;

case IDC_SQR: /* Square */
result = Pow(rat, 2, m_precision);
result = Pow(rat, 2);
break;

case IDC_SQRT: /* Square Root */
result = Root(rat, 2, m_precision);
result = Root(rat, 2);
break;

case IDC_CUBEROOT:
case IDC_CUB: /* Cubing and cube root functions. */
result = IDC_CUBEROOT == op ? Root(rat, 3, m_precision) : Pow(rat, 3, m_precision);
result = IDC_CUBEROOT == op ? Root(rat, 3) : Pow(rat, 3);
break;

case IDC_LOG: /* Functions for common log. */
result = Log10(rat, m_precision);
result = Log10(rat);
break;

case IDC_POW10:
result = Pow(10, rat, m_precision);
result = Pow(10, rat);
break;

case IDC_LN: /* Functions for natural log. */
result = m_bInv ? Exp(rat, m_precision) : Log(rat, m_precision);
result = m_bInv ? Exp(rat) : Log(rat);
break;

case IDC_FAC: /* Calculate factorial. Inverse is ineffective. */
result = Fact(rat, m_precision);
result = Fact(rat);
break;

case IDC_DEGREES:
Expand All @@ -180,31 +177,28 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
{
if (!m_fIntegerMode)
{
Rational shftRat{ m_bInv ? 100 : 60 };
auto shftRat{ m_bInv ? 100 : 60 };

Rational degreeRat = Integer(rat, m_precision);
Rational degreeRat = Integer(rat);

Rational minuteRat = rat.Sub(degreeRat, m_precision);
minuteRat = minuteRat.Mul(shftRat, m_precision);
Rational minuteRat = (rat - degreeRat) * shftRat;

Rational secondRat = minuteRat;

minuteRat = Integer(minuteRat, m_precision);
minuteRat = Integer(minuteRat);

secondRat = secondRat.Sub(minuteRat, m_precision);
secondRat = secondRat.Mul(shftRat, m_precision);
secondRat = (secondRat - minuteRat) * shftRat;

//
// degreeRat == degrees, minuteRat == minutes, secondRat == seconds
//

shftRat = Rational{ m_bInv ? 60 : 100 };
secondRat = secondRat.Div(shftRat, m_precision);
shftRat = m_bInv ? 60 : 100;
secondRat /= shftRat;

minuteRat = minuteRat.Add(secondRat, m_precision);
minuteRat = minuteRat.Div(shftRat, m_precision);
minuteRat = (minuteRat + secondRat) / shftRat;

result = degreeRat.Add(minuteRat, m_precision);
result = degreeRat + minuteRat;
}
break;
}
Expand Down
Loading