Fix C++ warnings

Check for exactly 1 before using the singular noun, rather than check for greater than 1, just in case somehow the variable being evaluated ends up as 0

In addition, should this code ever be refactored in such a way that the check to 0 is changed, this will ensure the end result does not change. In addition, it is naturally immediately apparent to the developers what is going on, potentially enhancing maintainability.

Additionally, make bitwise operations more obvious in their intentions.

Fix unused parameters in functions by using [[maybe_unused]]
This commit is contained in:
Rose 2022-08-29 11:17:22 -04:00
commit f5662250cf
82 changed files with 1322 additions and 1390 deletions

View file

@ -56,11 +56,11 @@ bool CalcInput::TryToggleSign(bool isIntegerMode, wstring_view maxNumStr)
return true; return true;
} }
bool CalcInput::TryAddDigit(unsigned int value, uint32_t radix, bool isIntegerMode, wstring_view maxNumStr, int32_t wordBitWidth, int maxDigits) bool CalcInput::TryAddDigit(unsigned int value, uint32_t radix, bool isIntegerMode, wstring_view maxNumStr, uint32_t wordBitWidth, int maxDigits)
{ {
// Convert from an integer into a character // Convert from an integer into a character
// This includes both normal digits and alpha 'digits' for radixes > 10 // This includes both normal digits and alpha 'digits' for radixes > 10
auto chDigit = static_cast<wchar_t>((value < 10) ? (L'0' + value) : (L'A' + value - 10)); auto chDigit = static_cast<wchar_t>(value < 10 ? L'0' + value : L'A' + value - 10);
CalcNumSec* pNumSec; CalcNumSec* pNumSec;
size_t maxCount; size_t maxCount;
@ -89,7 +89,7 @@ bool CalcInput::TryAddDigit(unsigned int value, uint32_t radix, bool isIntegerMo
} }
// Ignore leading zeros // Ignore leading zeros
if (pNumSec->IsEmpty() && (value == 0)) if (pNumSec->IsEmpty() && value == 0)
{ {
return true; return true;
} }
@ -108,17 +108,16 @@ bool CalcInput::TryAddDigit(unsigned int value, uint32_t radix, bool isIntegerMo
if (radix == 8) if (radix == 8)
{ {
switch (wordBitWidth % 3) const auto modResult = wordBitWidth % 3;
if (modResult == 1)
{ {
case 1:
// in 16 or 64bit word size, if the first digit is a 1 we can enter 6 (16bit) or 22 (64bit) digits // in 16 or 64bit word size, if the first digit is a 1 we can enter 6 (16bit) or 22 (64bit) digits
allowExtraDigit = (pNumSec->value.front() == L'1'); allowExtraDigit = pNumSec->value.front() == L'1';
break; }
else if (modResult == 2)
case 2: {
// in 8 or 32bit word size, if the first digit is a 3 or less we can enter 3 (8bit) or 11 (32bit) digits // in 8 or 32bit word size, if the first digit is a 3 or less we can enter 3 (8bit) or 11 (32bit) digits
allowExtraDigit = (pNumSec->value.front() <= L'3'); allowExtraDigit = pNumSec->value.front() <= L'3';
break;
} }
} }
else if (radix == 10) else if (radix == 10)
@ -137,14 +136,14 @@ bool CalcInput::TryAddDigit(unsigned int value, uint32_t radix, bool isIntegerMo
// If cmpResult == 0: // If cmpResult == 0:
// Undecided still. The case when max is "127", and current number is "12". Look for the new number being 7 or less to allow // Undecided still. The case when max is "127", and current number is "12". Look for the new number being 7 or less to allow
auto cmpResult = pNumSec->value.compare(0, wstring::npos, maxNumStr, 0, pNumSec->value.size()); const auto cmpResult = pNumSec->value.compare(0, wstring::npos, maxNumStr, 0, pNumSec->value.size());
if (cmpResult < 0) if (cmpResult < 0)
{ {
allowExtraDigit = true; allowExtraDigit = true;
} }
else if (cmpResult == 0) else if (cmpResult == 0)
{ {
auto lastChar = maxNumStr[pNumSec->value.size()]; const auto lastChar = maxNumStr[pNumSec->value.size()];
if (chDigit <= lastChar) if (chDigit <= lastChar)
{ {
allowExtraDigit = true; allowExtraDigit = true;
@ -189,7 +188,7 @@ bool CalcInput::TryAddDecimalPt()
return true; return true;
} }
bool CalcInput::HasDecimalPt() bool CalcInput::HasDecimalPt() const
{ {
return m_hasDecimal; return m_hasDecimal;
} }
@ -253,29 +252,31 @@ void CalcInput::Backspace()
void CalcInput::SetDecimalSymbol(wchar_t decSymbol) void CalcInput::SetDecimalSymbol(wchar_t decSymbol)
{ {
if (m_decSymbol != decSymbol) if (m_decSymbol == decSymbol)
{ {
m_decSymbol = decSymbol; return;
}
if (m_hasDecimal) m_decSymbol = decSymbol;
{
// Change to new decimal pt if (m_hasDecimal)
m_base.value[m_decPtIndex] = m_decSymbol; {
} // Change to new decimal pt
m_base.value[m_decPtIndex] = m_decSymbol;
} }
} }
bool CalcInput::IsEmpty() bool CalcInput::IsEmpty() const
{ {
return m_base.IsEmpty() && !m_hasExponent && m_exponent.IsEmpty() && !m_hasDecimal; return m_base.IsEmpty() && !m_hasExponent && m_exponent.IsEmpty() && !m_hasDecimal;
} }
wstring CalcInput::ToString(uint32_t radix) wstring CalcInput::ToString(uint32_t radix) const
{ {
// In theory both the base and exponent could be C_NUM_MAX_DIGITS long. // In theory both the base and exponent could be C_NUM_MAX_DIGITS long.
if ((m_base.value.size() > MAX_STRLEN) || (m_hasExponent && m_exponent.value.size() > MAX_STRLEN)) if (m_base.value.size() > MAX_STRLEN || m_hasExponent && m_exponent.value.size() > MAX_STRLEN)
{ {
return wstring(); return {};
} }
wstring result; wstring result;
@ -302,8 +303,8 @@ wstring CalcInput::ToString(uint32_t radix)
result += m_decSymbol; result += m_decSymbol;
} }
result += ((radix == 10) ? L'e' : L'^'); result += radix == 10 ? L'e' : L'^';
result += (m_exponent.IsNegative() ? L'-' : L'+'); result += m_exponent.IsNegative() ? L'-' : L'+';
if (m_exponent.IsEmpty()) if (m_exponent.IsEmpty())
{ {
@ -318,13 +319,13 @@ wstring CalcInput::ToString(uint32_t radix)
// Base and Exp can each be up to C_NUM_MAX_DIGITS in length, plus 4 characters for sign, dec, exp, and expSign. // Base and Exp can each be up to C_NUM_MAX_DIGITS in length, plus 4 characters for sign, dec, exp, and expSign.
if (result.size() > C_NUM_MAX_DIGITS * 2 + 4) if (result.size() > C_NUM_MAX_DIGITS * 2 + 4)
{ {
return wstring(); return {};
} }
return result; return result;
} }
Rational CalcInput::ToRational(uint32_t radix, int32_t precision) Rational CalcInput::ToRational(uint32_t radix, int32_t precision) const
{ {
PRAT rat = StringToRat(m_base.IsNegative(), m_base.value, m_exponent.IsNegative(), m_exponent.value, radix, precision); PRAT rat = StringToRat(m_base.IsNegative(), m_base.value, m_exponent.IsNegative(), m_exponent.value, radix, precision);
if (rat == nullptr) if (rat == nullptr)

View file

@ -6,7 +6,7 @@
bool IsOpInRange(OpCode op, uint32_t x, uint32_t y) bool IsOpInRange(OpCode op, uint32_t x, uint32_t y)
{ {
return ((op >= x) && (op <= y)); return op >= x && op <= y;
} }
bool IsBinOpCode(OpCode opCode) bool IsBinOpCode(OpCode opCode)
@ -18,7 +18,7 @@ bool IsBinOpCode(OpCode opCode)
// of it and catch it themselves or not needing this // of it and catch it themselves or not needing this
bool IsUnaryOpCode(OpCode opCode) bool IsUnaryOpCode(OpCode opCode)
{ {
return (IsOpInRange(opCode, IDC_UNARYFIRST, IDC_UNARYLAST) || IsOpInRange(opCode, IDC_UNARYEXTENDEDFIRST, IDC_UNARYEXTENDEDLAST)); return IsOpInRange(opCode, IDC_UNARYFIRST, IDC_UNARYLAST) || IsOpInRange(opCode, IDC_UNARYEXTENDEDFIRST, IDC_UNARYEXTENDEDLAST);
} }
bool IsDigitOpCode(OpCode opCode) bool IsDigitOpCode(OpCode opCode)
@ -49,8 +49,8 @@ bool IsGuiSettingOpCode(OpCode opCode)
case IDC_MPLUS: case IDC_MPLUS:
case IDC_MMINUS: case IDC_MMINUS:
return true; return true;
default:
// most of the commands
return false;
} }
// most of the commands
return false;
} }

View file

@ -14,7 +14,7 @@ using namespace CalcEngine;
namespace namespace
{ {
template <typename T> template <typename T>
static void Truncate(vector<T>& v, unsigned int index) void Truncate(vector<T>& v, unsigned int index)
{ {
if (index >= v.size()) if (index >= v.size())
{ {
@ -45,7 +45,7 @@ void CHistoryCollector::ReinitHistory()
// Constructor // Constructor
// Can throw Out of memory error // Can throw Out of memory error
CHistoryCollector::CHistoryCollector(ICalcDisplay* pCalcDisplay, std::shared_ptr<IHistoryDisplay> pHistoryDisplay, wchar_t decimalSymbol) CHistoryCollector::CHistoryCollector(ICalcDisplay* pCalcDisplay, std::shared_ptr<IHistoryDisplay> pHistoryDisplay, wchar_t decimalSymbol)
: m_pHistoryDisplay(pHistoryDisplay) : m_pHistoryDisplay(std::move(pHistoryDisplay))
, m_pCalcDisplay(pCalcDisplay) , m_pCalcDisplay(pCalcDisplay)
, m_iCurLineHistStart(-1) , m_iCurLineHistStart(-1)
, m_decimalSymbol(decimalSymbol) , m_decimalSymbol(decimalSymbol)
@ -66,13 +66,13 @@ CHistoryCollector::~CHistoryCollector()
void CHistoryCollector::AddOpndToHistory(wstring_view numStr, Rational const& rat, bool fRepetition) void CHistoryCollector::AddOpndToHistory(wstring_view numStr, Rational const& rat, bool fRepetition)
{ {
std::shared_ptr<std::vector<int>> commands = std::make_shared<vector<int>>(); auto commands = std::make_shared<vector<int>>();
// Check for negate // Check for negate
bool fNegative = (numStr[0] == L'-'); bool fNegative = numStr[0] == L'-';
bool fSciFmt = false; bool fSciFmt = false;
bool fDecimal = false; bool fDecimal = false;
for (size_t i = (fNegative ? 1 : 0); i < numStr.length(); i++) for (size_t i = fNegative ? 1 : 0; i < numStr.length(); i++)
{ {
if (numStr[i] == m_decimalSymbol) if (numStr[i] == m_decimalSymbol)
{ {
@ -98,8 +98,7 @@ void CHistoryCollector::AddOpndToHistory(wstring_view numStr, Rational const& ra
// Number // Number
else else
{ {
int num = static_cast<int>(numStr[i]) - ASCII_0; int num = static_cast<int>(numStr[i]) - ASCII_0 + IDC_0;
num += IDC_0;
commands->push_back(num); commands->push_back(num);
} }
} }
@ -143,19 +142,19 @@ void CHistoryCollector::AddBinOpToHistory(int nOpCode, bool isIntegerMode, bool
// This is expected to be called when a binary op in the last say 1+2+ is changing to another one say 1+2* (+ changed to *) // This is expected to be called when a binary op in the last say 1+2+ is changing to another one say 1+2* (+ changed to *)
// It needs to know by this change a Precedence inversion happened. i.e. previous op was lower or equal to its previous op, but the new // It needs to know by this change a Precedence inversion happened. i.e. previous op was lower or equal to its previous op, but the new
// one isn't. (Eg. 1*2* to 1*2^). It can add explicit brackets to ensure the precedence is inverted. (Eg. (1*2) ^) // one isn't. (Eg. 1*2* to 1*2^). It can add explicit brackets to ensure the precedence is inverted. (Eg. (1*2) ^)
void CHistoryCollector::ChangeLastBinOp(int nOpCode, bool fPrecInvToHigher, bool isIntgerMode) void CHistoryCollector::ChangeLastBinOp(int nOpCode, bool fPrecInvToHigher, bool isIntegerMode)
{ {
TruncateEquationSzFromIch(m_lastBinOpStartIndex); TruncateEquationSzFromIch(m_lastBinOpStartIndex);
if (fPrecInvToHigher) if (fPrecInvToHigher)
{ {
EnclosePrecInversionBrackets(); EnclosePrecInversionBrackets();
} }
AddBinOpToHistory(nOpCode, isIntgerMode); AddBinOpToHistory(nOpCode, isIntegerMode);
} }
void CHistoryCollector::PushLastOpndStart(int ichOpndStart) void CHistoryCollector::PushLastOpndStart(int ichOpndStart)
{ {
int ich = (ichOpndStart == -1) ? m_lastOpStartIndex : ichOpndStart; int ich = ichOpndStart == -1 ? m_lastOpStartIndex : ichOpndStart;
if (m_curOperandIndex < static_cast<int>(m_operandIndices.size())) if (m_curOperandIndex < static_cast<int>(m_operandIndices.size()))
{ {
@ -174,8 +173,7 @@ void CHistoryCollector::PopLastOpndStart()
void CHistoryCollector::AddOpenBraceToHistory() void CHistoryCollector::AddOpenBraceToHistory()
{ {
AddCommand(std::make_shared<CParentheses>(IDC_OPENP)); AddCommand(std::make_shared<CParentheses>(IDC_OPENP));
int ichOpndStart = IchAddSzToEquationSz(CCalcEngine::OpCodeToString(IDC_OPENP), -1); PushLastOpndStart(IchAddSzToEquationSz(CCalcEngine::OpCodeToString(IDC_OPENP), -1));
PushLastOpndStart(ichOpndStart);
SetExpressionDisplay(); SetExpressionDisplay();
m_lastBinOpStartIndex = -1; m_lastBinOpStartIndex = -1;
@ -195,15 +193,15 @@ void CHistoryCollector::AddCloseBraceToHistory()
void CHistoryCollector::EnclosePrecInversionBrackets() void CHistoryCollector::EnclosePrecInversionBrackets()
{ {
// Top of the Opnd starts index or 0 is nothing is in top // Top of the Opnd starts index or 0 is nothing is in top
int ichStart = (m_curOperandIndex > 0) ? m_operandIndices[m_curOperandIndex - 1] : 0; int ichStart = m_curOperandIndex > 0 ? m_operandIndices[m_curOperandIndex - 1] : 0;
InsertSzInEquationSz(CCalcEngine::OpCodeToString(IDC_OPENP), -1, ichStart); InsertSzInEquationSz(CCalcEngine::OpCodeToString(IDC_OPENP), -1, ichStart);
IchAddSzToEquationSz(CCalcEngine::OpCodeToString(IDC_CLOSEP), -1); IchAddSzToEquationSz(CCalcEngine::OpCodeToString(IDC_CLOSEP), -1);
} }
bool CHistoryCollector::FOpndAddedToHistory() bool CHistoryCollector::FOpndAddedToHistory() const
{ {
return (-1 != m_lastOpStartIndex); return m_lastOpStartIndex != -1;
} }
// AddUnaryOpToHistory // AddUnaryOpToHistory
@ -244,7 +242,7 @@ void CHistoryCollector::AddUnaryOpToHistory(int nOpCode, bool fInv, AngleType an
angleOpCode = CalculationManager::Command::CommandGRAD; angleOpCode = CalculationManager::Command::CommandGRAD;
} }
int command = nOpCode; int command;
switch (nOpCode) switch (nOpCode)
{ {
case IDC_SIN: case IDC_SIN:
@ -330,10 +328,9 @@ void CHistoryCollector::AddUnaryOpToHistory(int nOpCode, bool fInv, AngleType an
// history of equations // history of equations
void CHistoryCollector::CompleteHistoryLine(wstring_view numStr) void CHistoryCollector::CompleteHistoryLine(wstring_view numStr)
{ {
if (nullptr != m_pHistoryDisplay) if (m_pHistoryDisplay != nullptr)
{ {
unsigned int addedItemIndex = m_pHistoryDisplay->AddToHistory(m_spTokens, m_spCommands, numStr); m_pCalcDisplay->OnHistoryItemAdded(m_pHistoryDisplay->AddToHistory(m_spTokens, m_spCommands, numStr));
m_pCalcDisplay->OnHistoryItemAdded(addedItemIndex);
} }
m_spTokens = nullptr; m_spTokens = nullptr;
@ -354,16 +351,18 @@ void CHistoryCollector::CompleteEquation(std::wstring_view numStr)
void CHistoryCollector::ClearHistoryLine(wstring_view errStr) void CHistoryCollector::ClearHistoryLine(wstring_view errStr)
{ {
if (errStr.empty()) // in case of error let the display stay as it is if (!errStr.empty()) // in case of error let the display stay as it is
{ {
if (nullptr != m_pCalcDisplay) return;
{
m_pCalcDisplay->SetExpressionDisplay(
std::make_shared<std::vector<std::pair<std::wstring, int>>>(), std::make_shared<std::vector<std::shared_ptr<IExpressionCommand>>>());
}
m_iCurLineHistStart = -1; // It will get recomputed at the first Opnd
ReinitHistory();
} }
if (m_pCalcDisplay != nullptr)
{
m_pCalcDisplay->SetExpressionDisplay(
std::make_shared<std::vector<std::pair<std::wstring, int>>>(), std::make_shared<std::vector<std::shared_ptr<IExpressionCommand>>>());
}
m_iCurLineHistStart = -1; // It will get recomputed at the first Opnd
ReinitHistory();
} }
// Adds the given string psz to the globally maintained current equation string at the end. // Adds the given string psz to the globally maintained current equation string at the end.
@ -380,25 +379,25 @@ int CHistoryCollector::IchAddSzToEquationSz(wstring_view str, int icommandIndex)
} }
// Inserts a given string into the global m_pszEquation at the given index ich taking care of reallocations etc. // Inserts a given string into the global m_pszEquation at the given index ich taking care of reallocations etc.
void CHistoryCollector::InsertSzInEquationSz(wstring_view str, int icommandIndex, int ich) void CHistoryCollector::InsertSzInEquationSz(wstring_view str, int icommandIndex, int ich) const
{ {
m_spTokens->emplace(m_spTokens->begin() + ich, wstring(str), icommandIndex); m_spTokens->emplace(m_spTokens->begin() + ich, wstring(str), icommandIndex);
} }
// Chops off the current equation string from the given index // Chops off the current equation string from the given index
void CHistoryCollector::TruncateEquationSzFromIch(int ich) void CHistoryCollector::TruncateEquationSzFromIch(int ich) const
{ {
// Truncate commands // Truncate commands
int minIdx = -1; int minIdx = -1;
unsigned int nTokens = static_cast<unsigned int>(m_spTokens->size()); auto nTokens = m_spTokens->size();
for (unsigned int i = ich; i < nTokens; i++) for (size_t i = ich; i < nTokens; i++)
{ {
const auto& currentPair = (*m_spTokens)[i]; const auto& currentPair = (*m_spTokens)[i];
int curTokenId = currentPair.second; const int curTokenId = currentPair.second;
if (curTokenId != -1) if (curTokenId != -1)
{ {
if ((minIdx != -1) || (curTokenId < minIdx)) if (minIdx != -1 || curTokenId < minIdx)
{ {
minIdx = curTokenId; minIdx = curTokenId;
Truncate(*m_spCommands, minIdx); Truncate(*m_spCommands, minIdx);
@ -410,9 +409,9 @@ void CHistoryCollector::TruncateEquationSzFromIch(int ich)
} }
// Adds the m_pszEquation into the running history text // Adds the m_pszEquation into the running history text
void CHistoryCollector::SetExpressionDisplay() void CHistoryCollector::SetExpressionDisplay() const
{ {
if (nullptr != m_pCalcDisplay) if (m_pCalcDisplay != nullptr)
{ {
m_pCalcDisplay->SetExpressionDisplay(m_spTokens, m_spCommands); m_pCalcDisplay->SetExpressionDisplay(m_spTokens, m_spCommands);
} }
@ -465,13 +464,13 @@ void CHistoryCollector::SetDecimalSymbol(wchar_t decimalSymbol)
} }
// Update the commands corresponding to the passed string Number // Update the commands corresponding to the passed string Number
std::shared_ptr<std::vector<int>> CHistoryCollector::GetOperandCommandsFromString(wstring_view numStr) std::shared_ptr<std::vector<int>> CHistoryCollector::GetOperandCommandsFromString(wstring_view numStr) const
{ {
std::shared_ptr<std::vector<int>> commands = std::make_shared<std::vector<int>>(); std::shared_ptr<std::vector<int>> commands = std::make_shared<std::vector<int>>();
// Check for negate // Check for negate
bool fNegative = (numStr[0] == L'-'); bool fNegative = numStr[0] == L'-';
for (size_t i = (fNegative ? 1 : 0); i < numStr.length(); i++) for (size_t i = fNegative ? 1 : 0; i < numStr.length(); i++)
{ {
if (numStr[i] == m_decimalSymbol) if (numStr[i] == m_decimalSymbol)
{ {
@ -492,8 +491,7 @@ std::shared_ptr<std::vector<int>> CHistoryCollector::GetOperandCommandsFromStrin
// Number // Number
else else
{ {
int num = static_cast<int>(numStr[i]) - ASCII_0; int num = static_cast<int>(numStr[i]) - ASCII_0 + IDC_0;
num += IDC_0;
commands->push_back(num); commands->push_back(num);
} }
} }

View file

@ -22,10 +22,9 @@ namespace CalcEngine
Number::Number(PNUMBER p) noexcept Number::Number(PNUMBER p) noexcept
: m_sign{ p->sign } : m_sign{ p->sign }
, m_exp{ p->exp } , m_exp{ p->exp }
, m_mantissa{}
{ {
m_mantissa.reserve(p->cdigit); m_mantissa.reserve(p->cdigit);
copy(p->mant, p->mant + p->cdigit, back_inserter(m_mantissa)); copy_n(p->mant, p->cdigit, back_inserter(m_mantissa));
} }
PNUMBER Number::ToPNUMBER() const PNUMBER Number::ToPNUMBER() const

View file

@ -7,8 +7,7 @@ using namespace std;
namespace CalcEngine namespace CalcEngine
{ {
Rational::Rational() noexcept Rational::Rational() noexcept
: m_p{} : m_q{ 1, 0, { 1 } }
, m_q{ 1, 0, { 1 } }
{ {
} }
@ -24,15 +23,15 @@ namespace CalcEngine
m_q = Number(1, qExp, { 1 }); m_q = Number(1, qExp, { 1 });
} }
Rational::Rational(Number const& p, Number const& q) noexcept Rational::Rational(Number p, Number q) noexcept
: m_p{ p } : m_p{ std::move(p) }
, m_q{ q } , m_q{ std::move(q) }
{ {
} }
Rational::Rational(int32_t i) Rational::Rational(int32_t i)
{ {
PRAT pr = i32torat(static_cast<int32_t>(i)); PRAT pr = i32torat(i);
m_p = Number{ pr->pp }; m_p = Number{ pr->pp };
m_q = Number{ pr->pq }; m_q = Number{ pr->pq };
@ -42,7 +41,7 @@ namespace CalcEngine
Rational::Rational(uint32_t ui) Rational::Rational(uint32_t ui)
{ {
PRAT pr = Ui32torat(static_cast<uint32_t>(ui)); PRAT pr = Ui32torat(ui);
m_p = Number{ pr->pp }; m_p = Number{ pr->pp };
m_q = Number{ pr->pq }; m_q = Number{ pr->pq };
@ -52,8 +51,8 @@ namespace CalcEngine
Rational::Rational(uint64_t ui) Rational::Rational(uint64_t ui)
{ {
uint32_t hi = (uint32_t)(((ui) >> 32) & 0xffffffff); uint32_t hi = static_cast<uint32_t>(ui >> 32);
uint32_t lo = (uint32_t)ui; uint32_t lo = static_cast<uint32_t>(ui & 0xffffffff);
Rational temp = (Rational{ hi } << 32) | lo; Rational temp = (Rational{ hi } << 32) | lo;
@ -106,7 +105,7 @@ namespace CalcEngine
{ {
destroyrat(lhsRat); destroyrat(lhsRat);
destroyrat(rhsRat); destroyrat(rhsRat);
throw(error); throw error;
} }
*this = Rational{ lhsRat }; *this = Rational{ lhsRat };
@ -129,7 +128,7 @@ namespace CalcEngine
{ {
destroyrat(lhsRat); destroyrat(lhsRat);
destroyrat(rhsRat); destroyrat(rhsRat);
throw(error); throw error;
} }
*this = Rational{ lhsRat }; *this = Rational{ lhsRat };
@ -152,7 +151,7 @@ namespace CalcEngine
{ {
destroyrat(lhsRat); destroyrat(lhsRat);
destroyrat(rhsRat); destroyrat(rhsRat);
throw(error); throw error;
} }
*this = Rational{ lhsRat }; *this = Rational{ lhsRat };
@ -175,7 +174,7 @@ namespace CalcEngine
{ {
destroyrat(lhsRat); destroyrat(lhsRat);
destroyrat(rhsRat); destroyrat(rhsRat);
throw(error); throw error;
} }
*this = Rational{ lhsRat }; *this = Rational{ lhsRat };
@ -205,7 +204,7 @@ namespace CalcEngine
{ {
destroyrat(lhsRat); destroyrat(lhsRat);
destroyrat(rhsRat); destroyrat(rhsRat);
throw(error); throw error;
} }
*this = Rational{ lhsRat }; *this = Rational{ lhsRat };
@ -228,7 +227,7 @@ namespace CalcEngine
{ {
destroyrat(lhsRat); destroyrat(lhsRat);
destroyrat(rhsRat); destroyrat(rhsRat);
throw(error); throw error;
} }
*this = Rational{ lhsRat }; *this = Rational{ lhsRat };
@ -251,7 +250,7 @@ namespace CalcEngine
{ {
destroyrat(lhsRat); destroyrat(lhsRat);
destroyrat(rhsRat); destroyrat(rhsRat);
throw(error); throw error;
} }
*this = Rational{ lhsRat }; *this = Rational{ lhsRat };
@ -274,7 +273,7 @@ namespace CalcEngine
{ {
destroyrat(lhsRat); destroyrat(lhsRat);
destroyrat(rhsRat); destroyrat(rhsRat);
throw(error); throw error;
} }
*this = Rational{ lhsRat }; *this = Rational{ lhsRat };
@ -296,7 +295,7 @@ namespace CalcEngine
{ {
destroyrat(lhsRat); destroyrat(lhsRat);
destroyrat(rhsRat); destroyrat(rhsRat);
throw(error); throw error;
} }
*this = Rational{ lhsRat }; *this = Rational{ lhsRat };
@ -318,7 +317,7 @@ namespace CalcEngine
{ {
destroyrat(lhsRat); destroyrat(lhsRat);
destroyrat(rhsRat); destroyrat(rhsRat);
throw(error); throw error;
} }
*this = Rational{ lhsRat }; *this = Rational{ lhsRat };
@ -399,7 +398,7 @@ namespace CalcEngine
PRAT lhsRat = lhs.ToPRAT(); PRAT lhsRat = lhs.ToPRAT();
PRAT rhsRat = rhs.ToPRAT(); PRAT rhsRat = rhs.ToPRAT();
bool result = false; bool result;
try try
{ {
result = rat_equ(lhsRat, rhsRat, RATIONAL_PRECISION); result = rat_equ(lhsRat, rhsRat, RATIONAL_PRECISION);
@ -408,7 +407,7 @@ namespace CalcEngine
{ {
destroyrat(lhsRat); destroyrat(lhsRat);
destroyrat(rhsRat); destroyrat(rhsRat);
throw(error); throw error;
} }
destroyrat(lhsRat); destroyrat(lhsRat);
@ -427,7 +426,7 @@ namespace CalcEngine
PRAT lhsRat = lhs.ToPRAT(); PRAT lhsRat = lhs.ToPRAT();
PRAT rhsRat = rhs.ToPRAT(); PRAT rhsRat = rhs.ToPRAT();
bool result = false; bool result;
try try
{ {
result = rat_lt(lhsRat, rhsRat, RATIONAL_PRECISION); result = rat_lt(lhsRat, rhsRat, RATIONAL_PRECISION);
@ -436,7 +435,7 @@ namespace CalcEngine
{ {
destroyrat(lhsRat); destroyrat(lhsRat);
destroyrat(rhsRat); destroyrat(rhsRat);
throw(error); throw error;
} }
destroyrat(lhsRat); destroyrat(lhsRat);
@ -460,19 +459,19 @@ namespace CalcEngine
return !(lhs < rhs); return !(lhs < rhs);
} }
wstring Rational::ToString(uint32_t radix, NumberFormat fmt, int32_t precision) const wstring Rational::ToString(uint32_t radix, NumberFormat format, int32_t precision) const
{ {
PRAT rat = this->ToPRAT(); PRAT rat = this->ToPRAT();
wstring result{}; wstring result;
try try
{ {
result = RatToString(rat, fmt, radix, precision); result = RatToString(rat, format, radix, precision);
} }
catch (uint32_t error) catch (uint32_t error)
{ {
destroyrat(rat); destroyrat(rat);
throw(error); throw error;
} }
destroyrat(rat); destroyrat(rat);
@ -491,7 +490,7 @@ namespace CalcEngine
catch (uint32_t error) catch (uint32_t error)
{ {
destroyrat(rat); destroyrat(rat);
throw(error); throw error;
} }
destroyrat(rat); destroyrat(rat);

View file

@ -16,7 +16,7 @@ Rational RationalMath::Frac(Rational const& rat)
catch (uint32_t error) catch (uint32_t error)
{ {
destroyrat(prat); destroyrat(prat);
throw(error); throw error;
} }
Rational result{ prat }; Rational result{ prat };
@ -35,7 +35,7 @@ Rational RationalMath::Integer(Rational const& rat)
catch (uint32_t error) catch (uint32_t error)
{ {
destroyrat(prat); destroyrat(prat);
throw(error); throw error;
} }
Rational result{ prat }; Rational result{ prat };
@ -58,7 +58,7 @@ Rational RationalMath::Pow(Rational const& base, Rational const& pow)
{ {
destroyrat(baseRat); destroyrat(baseRat);
destroyrat(powRat); destroyrat(powRat);
throw(error); throw error;
} }
Rational result{ baseRat }; Rational result{ baseRat };
@ -83,7 +83,7 @@ Rational RationalMath::Fact(Rational const& rat)
catch (uint32_t error) catch (uint32_t error)
{ {
destroyrat(prat); destroyrat(prat);
throw(error); throw error;
} }
Rational result{ prat }; Rational result{ prat };
@ -103,7 +103,7 @@ Rational RationalMath::Exp(Rational const& rat)
catch (uint32_t error) catch (uint32_t error)
{ {
destroyrat(prat); destroyrat(prat);
throw(error); throw error;
} }
Rational result{ prat }; Rational result{ prat };
@ -123,7 +123,7 @@ Rational RationalMath::Log(Rational const& rat)
catch (uint32_t error) catch (uint32_t error)
{ {
destroyrat(prat); destroyrat(prat);
throw(error); throw error;
} }
Rational result{ prat }; Rational result{ prat };
@ -158,7 +158,7 @@ Rational RationalMath::Sin(Rational const& rat, AngleType angletype)
catch (uint32_t error) catch (uint32_t error)
{ {
destroyrat(prat); destroyrat(prat);
throw(error); throw error;
} }
Rational result{ prat }; Rational result{ prat };
@ -178,7 +178,7 @@ Rational RationalMath::Cos(Rational const& rat, AngleType angletype)
catch (uint32_t error) catch (uint32_t error)
{ {
destroyrat(prat); destroyrat(prat);
throw(error); throw error;
} }
Rational result{ prat }; Rational result{ prat };
@ -198,7 +198,7 @@ Rational RationalMath::Tan(Rational const& rat, AngleType angletype)
catch (uint32_t error) catch (uint32_t error)
{ {
destroyrat(prat); destroyrat(prat);
throw(error); throw error;
} }
Rational result{ prat }; Rational result{ prat };
@ -218,7 +218,7 @@ Rational RationalMath::ASin(Rational const& rat, AngleType angletype)
catch (uint32_t error) catch (uint32_t error)
{ {
destroyrat(prat); destroyrat(prat);
throw(error); throw error;
} }
Rational result{ prat }; Rational result{ prat };
@ -238,7 +238,7 @@ Rational RationalMath::ACos(Rational const& rat, AngleType angletype)
catch (uint32_t error) catch (uint32_t error)
{ {
destroyrat(prat); destroyrat(prat);
throw(error); throw error;
} }
Rational result{ prat }; Rational result{ prat };
@ -258,7 +258,7 @@ Rational RationalMath::ATan(Rational const& rat, AngleType angletype)
catch (uint32_t error) catch (uint32_t error)
{ {
destroyrat(prat); destroyrat(prat);
throw(error); throw error;
} }
Rational result{ prat }; Rational result{ prat };
@ -278,7 +278,7 @@ Rational RationalMath::Sinh(Rational const& rat)
catch (uint32_t error) catch (uint32_t error)
{ {
destroyrat(prat); destroyrat(prat);
throw(error); throw error;
} }
Rational result{ prat }; Rational result{ prat };
@ -298,7 +298,7 @@ Rational RationalMath::Cosh(Rational const& rat)
catch (uint32_t error) catch (uint32_t error)
{ {
destroyrat(prat); destroyrat(prat);
throw(error); throw error;
} }
Rational result{ prat }; Rational result{ prat };
@ -318,7 +318,7 @@ Rational RationalMath::Tanh(Rational const& rat)
catch (uint32_t error) catch (uint32_t error)
{ {
destroyrat(prat); destroyrat(prat);
throw(error); throw error;
} }
Rational result{ prat }; Rational result{ prat };
@ -338,7 +338,7 @@ Rational RationalMath::ASinh(Rational const& rat)
catch (uint32_t error) catch (uint32_t error)
{ {
destroyrat(prat); destroyrat(prat);
throw(error); throw error;
} }
Rational result{ prat }; Rational result{ prat };
@ -358,7 +358,7 @@ Rational RationalMath::ACosh(Rational const& rat)
catch (uint32_t error) catch (uint32_t error)
{ {
destroyrat(prat); destroyrat(prat);
throw(error); throw error;
} }
Rational result{ prat }; Rational result{ prat };
@ -378,7 +378,7 @@ Rational RationalMath::ATanh(Rational const& rat)
catch (uint32_t error) catch (uint32_t error)
{ {
destroyrat(prat); destroyrat(prat);
throw(error); throw error;
} }
Rational result{ prat }; Rational result{ prat };
@ -409,7 +409,7 @@ Rational RationalMath::Mod(Rational const& a, Rational const& b)
{ {
destroyrat(prat); destroyrat(prat);
destroyrat(pn); destroyrat(pn);
throw(error); throw error;
} }
auto res = Rational{ prat }; auto res = Rational{ prat };

View file

@ -74,19 +74,14 @@ CCalcEngine::CCalcEngine(
, m_bSetCalcState(false) , m_bSetCalcState(false)
, m_input(DEFAULT_DEC_SEPARATOR) , m_input(DEFAULT_DEC_SEPARATOR)
, m_nFE(NumberFormat::Float) , m_nFE(NumberFormat::Float)
, m_maxTrigonometricNum(RationalMath::Pow(10, 100))
, m_memoryValue{ make_unique<Rational>() } , m_memoryValue{ make_unique<Rational>() }
, m_holdVal{}
, m_currentVal{}
, m_lastVal{}
, m_parenVals{}
, m_precedenceVals{}
, m_bError(false) , m_bError(false)
, m_bInv(false) , m_bInv(false)
, m_bNoPrevEqu(true) , m_bNoPrevEqu(true)
, m_radix(DEFAULT_RADIX) , m_radix(DEFAULT_RADIX)
, m_precision(DEFAULT_PRECISION) , m_precision(DEFAULT_PRECISION)
, m_cIntDigitsSav(DEFAULT_MAX_DIGITS) , m_cIntDigitsSav(DEFAULT_MAX_DIGITS)
, m_decGrouping()
, m_numberString(DEFAULT_NUMBER_STR) , m_numberString(DEFAULT_NUMBER_STR)
, m_nTempCom(0) , m_nTempCom(0)
, m_openParenCount(0) , m_openParenCount(0)
@ -96,15 +91,12 @@ CCalcEngine::CCalcEngine(
, m_nLastCom(0) , m_nLastCom(0)
, m_angletype(AngleType::Degrees) , m_angletype(AngleType::Degrees)
, m_numwidth(NUM_WIDTH::QWORD_WIDTH) , m_numwidth(NUM_WIDTH::QWORD_WIDTH)
, m_HistoryCollector(pCalcDisplay, pHistoryDisplay, DEFAULT_DEC_SEPARATOR) , m_dwWordBitWidth(DwWordBitWidthFromNumWidth(m_numwidth))
, m_HistoryCollector(pCalcDisplay, std::move(pHistoryDisplay), DEFAULT_DEC_SEPARATOR)
, m_groupSeparator(DEFAULT_GRP_SEPARATOR) , m_groupSeparator(DEFAULT_GRP_SEPARATOR)
{ {
InitChopNumbers(); InitChopNumbers();
m_dwWordBitWidth = DwWordBitWidthFromeNumWidth(m_numwidth);
m_maxTrigonometricNum = RationalMath::Pow(10, 100);
SetRadixTypeAndNumWidth(RadixType::Decimal, m_numwidth); SetRadixTypeAndNumWidth(RadixType::Decimal, m_numwidth);
SettingsChanged(); SettingsChanged();
DisplayNum(); DisplayNum();
@ -125,14 +117,14 @@ 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++)
{ {
auto maxVal = m_chopNumbers[i] / 2; auto maxVal = m_chopNumbers[i] >> 1;
maxVal = RationalMath::Integer(maxVal); maxVal = RationalMath::Integer(maxVal);
m_maxDecimalValueStrings[i] = maxVal.ToString(10, NumberFormat::Float, m_precision); m_maxDecimalValueStrings[i] = maxVal.ToString(10, NumberFormat::Float, m_precision);
} }
} }
CalcEngine::Rational CCalcEngine::GetChopNumber() const Rational CCalcEngine::GetChopNumber() const
{ {
return m_chopNumbers[static_cast<int>(m_numwidth)]; return m_chopNumbers[static_cast<int>(m_numwidth)];
} }
@ -170,14 +162,6 @@ void CCalcEngine::SettingsChanged()
wstring grpStr = m_resourceProvider->GetCEngineString(L"sGrouping"); wstring grpStr = m_resourceProvider->GetCEngineString(L"sGrouping");
m_decGrouping = DigitGroupingStringToGroupingVector(grpStr.empty() ? DEFAULT_GRP_STR : grpStr); m_decGrouping = DigitGroupingStringToGroupingVector(grpStr.empty() ? DEFAULT_GRP_STR : grpStr);
bool numChanged = false;
// if the grouping pattern or thousands symbol changed we need to refresh the display
if (m_decGrouping != lastDecGrouping || m_groupSeparator != lastSep)
{
numChanged = true;
}
// if the decimal symbol has changed we always do the following things // if the decimal symbol has changed we always do the following things
if (m_decimalSeparator != lastDec) if (m_decimalSeparator != lastDec)
{ {
@ -189,10 +173,10 @@ void CCalcEngine::SettingsChanged()
s_engineStrings[SIDS_DECIMAL_SEPARATOR] = m_decimalSeparator; s_engineStrings[SIDS_DECIMAL_SEPARATOR] = m_decimalSeparator;
// we need to redraw to update the decimal point button // we need to redraw to update the decimal point button
numChanged = true; DisplayNum();
} }
// if the grouping pattern or thousands symbol changed we need to refresh the display
if (numChanged) else if (m_decGrouping != lastDecGrouping || m_groupSeparator != lastSep)
{ {
DisplayNum(); DisplayNum();
} }

View file

@ -30,17 +30,31 @@ namespace
// 0 is returned. Higher the number, higher the precedence of the operator. // 0 is returned. Higher the number, higher the precedence of the operator.
int NPrecedenceOfOp(int nopCode) int NPrecedenceOfOp(int nopCode)
{ {
static uint16_t rgbPrec[] = { 0, 0, IDC_OR, 0, IDC_XOR, 0, IDC_AND, 1, IDC_NAND, 1, IDC_NOR, 1, IDC_ADD, 2, IDC_SUB, 2, IDC_RSHF, 3, switch (nopCode)
IDC_LSHF, 3, IDC_RSHFL, 3, IDC_MOD, 3, IDC_DIV, 3, IDC_MUL, 3, IDC_PWR, 4, IDC_ROOT, 4, IDC_LOGBASEY, 4 };
for (unsigned int iPrec = 0; iPrec < size(rgbPrec); iPrec += 2)
{ {
if (nopCode == rgbPrec[iPrec]) default:
{ case IDC_OR:
return rgbPrec[iPrec + 1]; case IDC_XOR:
} return 0;
case IDC_AND:
case IDC_NAND:
case IDC_NOR:
return 1;
case IDC_ADD:
case IDC_SUB:
return 2;
case IDC_LSHF:
case IDC_RSHF:
case IDC_RSHFL:
case IDC_MOD:
case IDC_DIV:
case IDC_MUL:
return 3;
case IDC_PWR:
case IDC_ROOT:
case IDC_LOGBASEY:
return 4;
} }
return 0;
} }
} }
@ -57,9 +71,9 @@ void CCalcEngine::HandleErrorCommand(OpCode idc)
} }
} }
void CCalcEngine::HandleMaxDigitsReached() void CCalcEngine::HandleMaxDigitsReached() const
{ {
if (nullptr != m_pCalcDisplay) if (m_pCalcDisplay != nullptr)
{ {
m_pCalcDisplay->MaxDigitsReached(); m_pCalcDisplay->MaxDigitsReached();
} }
@ -75,9 +89,9 @@ void CCalcEngine::ClearTemporaryValues()
m_bError = false; m_bError = false;
} }
void CCalcEngine::ClearDisplay() void CCalcEngine::ClearDisplay() const
{ {
if (nullptr != m_pCalcDisplay) if (m_pCalcDisplay != nullptr)
{ {
m_pCalcDisplay->SetExpressionDisplay(make_shared<vector<pair<wstring, int>>>(), make_shared<vector<shared_ptr<IExpressionCommand>>>()); m_pCalcDisplay->SetExpressionDisplay(make_shared<vector<pair<wstring, int>>>(), make_shared<vector<shared_ptr<IExpressionCommand>>>());
} }
@ -105,7 +119,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
if (!IsGuiSettingOpCode(wParam)) if (!IsGuiSettingOpCode(wParam))
{ {
m_nLastCom = m_nTempCom; m_nLastCom = m_nTempCom;
m_nTempCom = (int)wParam; m_nTempCom = static_cast<int>(wParam);
} }
// Clear expression shown after = sign, when user do any action. // Clear expression shown after = sign, when user do any action.
@ -137,8 +151,8 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
{ {
if (IsBinOpCode(wParam) || IsUnaryOpCode(wParam) || IsOpInRange(wParam, IDC_FE, IDC_MMINUS) || IsOpInRange(wParam, IDC_OPENP, IDC_CLOSEP) if (IsBinOpCode(wParam) || IsUnaryOpCode(wParam) || IsOpInRange(wParam, IDC_FE, 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, IDM_HEX, IDM_BIN) || IsOpInRange(wParam, IDM_QWORD, IDM_BYTE) || IsOpInRange(wParam, IDM_DEG, IDM_GRAD)
|| IsOpInRange(wParam, IDC_BINEDITSTART, IDC_BINEDITEND) || (IDC_INV == wParam) || (IDC_SIGN == wParam && 10 != m_radix) || (IDC_RAND == wParam) || IsOpInRange(wParam, IDC_BINEDITSTART, IDC_BINEDITEND) || IDC_INV == wParam || IDC_SIGN == wParam && 10 != m_radix || IDC_RAND == wParam
|| (IDC_EULER == wParam)) || IDC_EULER == wParam)
{ {
m_bRecord = false; m_bRecord = false;
m_currentVal = m_input.ToRational(m_radix, m_precision); m_currentVal = m_input.ToRational(m_radix, m_precision);
@ -158,7 +172,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode 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 >= m_radix)
{ {
HandleErrorCommand(wParam); HandleErrorCommand(wParam);
return; return;
@ -184,7 +198,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
{ {
bool fPrecInvToHigher = false; // Is Precedence Inversion from lower to higher precedence happening ?? bool fPrecInvToHigher = false; // Is Precedence Inversion from lower to higher precedence happening ??
m_nOpCode = (int)wParam; m_nOpCode = static_cast<int>(wParam);
// Check to see if by changing this binop, a Precedence inversion is happening. // Check to see if by changing this binop, a Precedence inversion is happening.
// 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,10 +235,10 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
{ {
DoPrecedenceCheckAgain: DoPrecedenceCheckAgain:
int nx = NPrecedenceOfOp((int)wParam); int nx = NPrecedenceOfOp(static_cast<int>(wParam));
int ni = NPrecedenceOfOp(m_nOpCode); int ni = NPrecedenceOfOp(m_nOpCode);
if ((nx > ni) && m_fPrecedence) if (nx > ni && m_fPrecedence)
{ {
if (m_precedenceOpCount < MAXPRECDEPTH) if (m_precedenceOpCount < MAXPRECDEPTH)
{ {
@ -260,10 +274,9 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
} }
} }
if ((m_precedenceOpCount != 0) && (m_nPrecOp[m_precedenceOpCount - 1])) if (m_precedenceOpCount != 0 && m_nPrecOp[m_precedenceOpCount - 1])
{ {
m_precedenceOpCount--; m_nOpCode = m_nPrecOp[--m_precedenceOpCount];
m_nOpCode = m_nPrecOp[m_precedenceOpCount];
m_lastVal = m_precedenceVals[m_precedenceOpCount]; m_lastVal = m_precedenceVals[m_precedenceOpCount];
@ -285,14 +298,14 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
DisplayAnnounceBinaryOperator(); DisplayAnnounceBinaryOperator();
m_lastVal = m_currentVal; m_lastVal = m_currentVal;
m_nOpCode = (int)wParam; m_nOpCode = static_cast<int>(wParam);
m_HistoryCollector.AddBinOpToHistory(m_nOpCode, m_fIntegerMode); m_HistoryCollector.AddBinOpToHistory(m_nOpCode, m_fIntegerMode);
m_bNoPrevEqu = m_bChangeOp = true; m_bNoPrevEqu = m_bChangeOp = true;
return; return;
} }
// UNARY OPERATORS: // UNARY OPERATORS:
if (IsUnaryOpCode(wParam) || (wParam == IDC_DEGREES)) 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. */ /* If the last thing done was an operator, m_currentVal was cleared. */
@ -313,11 +326,11 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
m_HistoryCollector.AddOpndToHistory(m_numberString, m_currentVal); m_HistoryCollector.AddOpndToHistory(m_numberString, m_currentVal);
} }
m_HistoryCollector.AddUnaryOpToHistory((int)wParam, m_bInv, m_angletype); m_HistoryCollector.AddUnaryOpToHistory(static_cast<int>(wParam), m_bInv, m_angletype);
} }
if ((wParam == IDC_SIN) || (wParam == IDC_COS) || (wParam == IDC_TAN) || (wParam == IDC_SINH) || (wParam == IDC_COSH) || (wParam == IDC_TANH) if (wParam == IDC_SIN || wParam == IDC_COS || wParam == IDC_TAN || wParam == IDC_SINH || wParam == IDC_COSH || wParam == IDC_TANH
|| (wParam == IDC_SEC) || (wParam == IDC_CSC) || (wParam == IDC_COT) || (wParam == IDC_SECH) || (wParam == IDC_CSCH) || (wParam == IDC_COTH)) || wParam == IDC_SEC || wParam == IDC_CSC || wParam == IDC_COT || wParam == IDC_SECH || wParam == IDC_CSCH || wParam == IDC_COTH)
{ {
if (IsCurrentTooBigForTrig()) if (IsCurrentTooBigForTrig())
{ {
@ -327,7 +340,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
} }
} }
m_currentVal = SciCalcFunctions(m_currentVal, (uint32_t)wParam); m_currentVal = SciCalcFunctions(m_currentVal, static_cast<uint32_t>(wParam));
if (m_bError) if (m_bError)
return; return;
@ -345,9 +358,9 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
and have been used */ and have been used */
if (m_bInv if (m_bInv
&& ((wParam == IDC_CHOP) || (wParam == IDC_SIN) || (wParam == IDC_COS) || (wParam == IDC_TAN) || (wParam == IDC_LN) || (wParam == IDC_DMS) && (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_SEC) || (wParam == IDC_CSC) || wParam == IDC_DEGREES || wParam == IDC_SINH || wParam == IDC_COSH || wParam == IDC_TANH || wParam == IDC_SEC || wParam == IDC_CSC
|| (wParam == IDC_COT) || (wParam == IDC_SECH) || (wParam == IDC_CSCH) || (wParam == IDC_COTH))) || wParam == IDC_COT || wParam == IDC_SECH || wParam == IDC_CSCH || wParam == IDC_COTH))
{ {
m_bInv = false; m_bInv = false;
} }
@ -366,7 +379,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
CheckAndAddLastBinOpToHistory(); CheckAndAddLastBinOpToHistory();
if (TryToggleBit(m_currentVal, (uint32_t)wParam - IDC_BINEDITSTART)) if (TryToggleBit(m_currentVal, static_cast<uint32_t>(wParam) - IDC_BINEDITSTART))
{ {
DisplayNum(); DisplayNum();
} }
@ -396,7 +409,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
/* clear the parenthesis status box indicator, this will not be /* clear the parenthesis status box indicator, this will not be
cleared for CENTR */ cleared for CENTR */
if (nullptr != m_pCalcDisplay) if (m_pCalcDisplay != nullptr)
{ {
m_pCalcDisplay->SetParenthesisNumber(0); m_pCalcDisplay->SetParenthesisNumber(0);
ClearDisplay(); ClearDisplay();
@ -442,8 +455,8 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
// automatic closing of all the parenthesis to get a meaningful result as well as ensure data integrity // automatic closing of all the parenthesis to get a meaningful result as well as ensure data integrity
m_nTempCom = m_nLastCom; // Put back this last saved command to the prev state so ) can be handled properly m_nTempCom = m_nLastCom; // Put back this last saved command to the prev state so ) can be handled properly
ProcessCommand(IDC_CLOSEP); ProcessCommand(IDC_CLOSEP);
m_nLastCom = m_nTempCom; // Actually this is IDC_CLOSEP m_nLastCom = m_nTempCom; // Actually this is IDC_CLOSEP
m_nTempCom = (int)wParam; // put back in the state where last op seen was IDC_CLOSEP, and current op is IDC_EQU m_nTempCom = static_cast<int>(wParam); // put back in the state where last op seen was IDC_CLOSEP, and current op is IDC_EQU
} }
if (!m_bNoPrevEqu) if (!m_bNoPrevEqu)
@ -473,8 +486,8 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
m_lastVal = m_precedenceVals[m_precedenceOpCount]; m_lastVal = m_precedenceVals[m_precedenceOpCount];
// Precedence Inversion check // Precedence Inversion check
int ni = NPrecedenceOfOp(m_nPrevOpCode); auto ni = NPrecedenceOfOp(m_nPrevOpCode);
int nx = NPrecedenceOfOp(m_nOpCode); auto nx = NPrecedenceOfOp(m_nOpCode);
if (ni <= nx) if (ni <= nx)
{ {
m_HistoryCollector.EnclosePrecInversionBrackets(); m_HistoryCollector.EnclosePrecInversionBrackets();
@ -488,8 +501,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
if (!m_bError) if (!m_bError)
{ {
wstring groupedString = GroupDigitsPerRadix(m_numberString, m_radix); m_HistoryCollector.CompleteEquation(GroupDigitsPerRadix(m_numberString, m_radix));
m_HistoryCollector.CompleteEquation(groupedString);
} }
m_bChangeOp = false; m_bChangeOp = false;
@ -504,10 +516,10 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
// -OR- the paren holding array is empty and we try to remove a // -OR- the paren holding array is empty and we try to remove a
// paren // paren
// -OR- the precedence holding array is full // -OR- the precedence holding array is full
if ((m_openParenCount >= MAXPRECDEPTH && (wParam == IDC_OPENP)) || (!m_openParenCount && (wParam != IDC_OPENP)) if (m_openParenCount >= MAXPRECDEPTH && wParam == IDC_OPENP || !m_openParenCount && wParam != IDC_OPENP
|| ((m_precedenceOpCount >= MAXPRECDEPTH && m_nPrecOp[m_precedenceOpCount - 1] != 0))) || m_precedenceOpCount >= MAXPRECDEPTH && m_nPrecOp[m_precedenceOpCount - 1] != 0)
{ {
if (!m_openParenCount && (wParam != IDC_OPENP)) if (!m_openParenCount && wParam != IDC_OPENP)
{ {
m_pCalcDisplay->OnNoRightParenAdded(); m_pCalcDisplay->OnNoRightParenAdded();
} }
@ -518,7 +530,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
if (wParam == IDC_OPENP) if (wParam == IDC_OPENP)
{ {
// if there's an omitted multiplication sign // if there's an omitted multiplication sign
if (IsDigitOpCode(m_nLastCom) || IsUnaryOpCode(m_nLastCom) || m_nLastCom == IDC_PNT || m_nLastCom == IDC_CLOSEP) if (IsDigitOpCode(m_nLastCom) || IsUnaryOpCode(m_nLastCom) || m_nLastCom == IDC_PNT || m_nLastCom == IDC_CLOSEP)
{ {
ProcessCommand(IDC_MUL); ProcessCommand(IDC_MUL);
@ -530,7 +542,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
// Open level of parentheses, save number and operation. // Open level of parentheses, save number and operation.
m_parenVals[m_openParenCount] = m_lastVal; m_parenVals[m_openParenCount] = m_lastVal;
m_nOp[m_openParenCount++] = (m_bChangeOp ? m_nOpCode : 0); m_nOp[m_openParenCount++] = m_bChangeOp ? m_nOpCode : 0;
/* save a special marker on the precedence array */ /* save a special marker on the precedence array */
if (m_precedenceOpCount < m_nPrecOp.size()) if (m_precedenceOpCount < m_nPrecOp.size())
@ -567,7 +579,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
m_nPrevOpCode = m_nOpCode; m_nPrevOpCode = m_nOpCode;
// Now process the precedence stack till we get to an opcode which is zero. // Now process the precedence stack till we get to an opcode which is zero.
for (m_nOpCode = m_nPrecOp[--m_precedenceOpCount]; m_nOpCode; m_nOpCode = m_nPrecOp[--m_precedenceOpCount]) for (m_nOpCode = m_nPrecOp[--m_precedenceOpCount]; m_nOpCode != 0; m_nOpCode = m_nPrecOp[--m_precedenceOpCount])
{ {
// Precedence Inversion check // Precedence Inversion check
int ni = NPrecedenceOfOp(m_nPrevOpCode); int ni = NPrecedenceOfOp(m_nPrevOpCode);
@ -587,17 +599,15 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
m_HistoryCollector.AddCloseBraceToHistory(); m_HistoryCollector.AddCloseBraceToHistory();
// Now get back the operation and opcode at the beginning of this parenthesis pair // Now get back the operation and opcode at the beginning of this parenthesis pair
m_lastVal = m_parenVals[--m_openParenCount];
m_openParenCount -= 1;
m_lastVal = m_parenVals[m_openParenCount];
m_nOpCode = m_nOp[m_openParenCount]; m_nOpCode = m_nOp[m_openParenCount];
// m_bChangeOp should be true if m_nOpCode is valid // m_bChangeOp should be true if m_nOpCode is valid
m_bChangeOp = (m_nOpCode != 0); m_bChangeOp = m_nOpCode != 0;
} }
// Set the "(=xx" indicator. // Set the "(=xx" indicator.
if (nullptr != m_pCalcDisplay) if (m_pCalcDisplay != nullptr)
{ {
m_pCalcDisplay->SetParenthesisNumber(static_cast<unsigned int>(m_openParenCount)); m_pCalcDisplay->SetParenthesisNumber(static_cast<unsigned int>(m_openParenCount));
} }
@ -615,7 +625,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
case IDM_OCT: case IDM_OCT:
case IDM_BIN: case IDM_BIN:
{ {
SetRadixTypeAndNumWidth((RadixType)(wParam - IDM_HEX), (NUM_WIDTH)-1); SetRadixTypeAndNumWidth(static_cast<RadixType>(wParam - IDM_HEX), static_cast<NUM_WIDTH>(-1));
m_HistoryCollector.UpdateHistoryExpression(m_radix, m_precision); m_HistoryCollector.UpdateHistoryExpression(m_radix, m_precision);
break; break;
} }
@ -631,7 +641,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
} }
// Compat. mode BaseX: Qword, Dword, Word, Byte // Compat. mode BaseX: Qword, Dword, Word, Byte
SetRadixTypeAndNumWidth((RadixType)-1, (NUM_WIDTH)(wParam - IDM_QWORD)); SetRadixTypeAndNumWidth(static_cast<RadixType>(-1), static_cast<NUM_WIDTH>(wParam - IDM_QWORD));
break; break;
case IDM_DEG: case IDM_DEG:
@ -666,7 +676,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
m_HistoryCollector.AddOpndToHistory(m_numberString, m_currentVal); m_HistoryCollector.AddOpndToHistory(m_numberString, m_currentVal);
} }
m_currentVal = -(m_currentVal); m_currentVal = -m_currentVal;
DisplayNum(); DisplayNum();
m_HistoryCollector.AddUnaryOpToHistory(IDC_SIGN, m_bInv, m_angletype); m_HistoryCollector.AddUnaryOpToHistory(IDC_SIGN, m_bInv, m_angletype);
@ -731,7 +741,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
wstringstream str; wstringstream str;
str << fixed << setprecision(m_precision) << GenerateRandomNumber(); str << fixed << setprecision(m_precision) << GenerateRandomNumber();
auto rat = StringToRat(false, str.str(), false, L"", m_radix, m_precision); auto* rat = StringToRat(false, str.str(), false, L"", m_radix, m_precision);
if (rat != nullptr) if (rat != nullptr)
{ {
m_currentVal = Rational{ rat }; m_currentVal = Rational{ rat };
@ -762,7 +772,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
break; break;
case IDC_FE: case IDC_FE:
// Toggle exponential notation display. // Toggle exponential notation display.
m_nFE = NumberFormat(!(int)m_nFE); m_nFE = m_nFE == NumberFormat::Float ? NumberFormat::Scientific : NumberFormat::Float;
DisplayNum(); DisplayNum();
break; break;
@ -834,7 +844,7 @@ void CCalcEngine::ResolveHighestPrecedenceOperation()
// CheckAndAddLastBinOpToHistory // CheckAndAddLastBinOpToHistory
// //
// This is a very confusing helper routine to add the last entered binary operator to the history. This is expected to // This is a very confusing helper routine to add the last entered binary operator to the history. This is expected to
// leave the history with <exp> <binop> state. It can really add the last entered binary op, or it can actually remove // leave the history with <exp> <binop> state. It can really add the last entered binary op, or it can actually remove
// the last operand from history. This happens because you can 'type' or 'compute' over last operand in some cases, thereby // the last operand from history. This happens because you can 'type' or 'compute' over last operand in some cases, thereby
// effectively removing only it from the equation but still keeping the previous portion of the equation. Eg. 1 + 4 sqrt 5. The last // effectively removing only it from the equation but still keeping the previous portion of the equation. Eg. 1 + 4 sqrt 5. The last
@ -842,25 +852,28 @@ void CCalcEngine::ResolveHighestPrecedenceOperation()
// If you are messing with this, test cases like this CE, statistical functions, ( & MR buttons // If you are messing with this, test cases like this CE, statistical functions, ( & MR buttons
void CCalcEngine::CheckAndAddLastBinOpToHistory(bool addToHistory) void CCalcEngine::CheckAndAddLastBinOpToHistory(bool addToHistory)
{ {
// Cannot do anything if this is not added to history
if (!m_HistoryCollector.FOpndAddedToHistory())
{
return;
}
if (m_bChangeOp) if (m_bChangeOp)
{ {
if (m_HistoryCollector.FOpndAddedToHistory()) // if last time opnd was added but the last command was not a binary operator, then it must have come
{ // from commands which add the operand, like unary operator. So history at this is showing 1 + sqrt(4)
// if last time opnd was added but the last command was not a binary operator, then it must have come // but in reality the sqrt(4) is getting replaced by new number (may be unary op, or MR or SUM etc.)
// from commands which add the operand, like unary operator. So history at this is showing 1 + sqrt(4) // So erase the last operand
// but in reality the sqrt(4) is getting replaced by new number (may be unary op, or MR or SUM etc.) m_HistoryCollector.RemoveLastOpndFromHistory();
// So erase the last operand
m_HistoryCollector.RemoveLastOpndFromHistory();
}
} }
else if (m_HistoryCollector.FOpndAddedToHistory() && !m_bError) else if (!m_bError)
{ {
// Corner case, where opnd is already in history but still a new opnd starting (1 + 4 sqrt 5). This is yet another // Corner case, where opnd is already in history but still a new opnd starting (1 + 4 sqrt 5). This is yet another
// special casing of previous case under if (m_bChangeOp), but this time we can do better than just removing it // special casing of previous case under if (m_bChangeOp), but this time we can do better than just removing it
// Let us make a current value =. So in case of 4 SQRT (or a equation under braces) and then a new equation is started, we can just form // Let us make a current value =. So in case of 4 SQRT (or a equation under braces) and then a new equation is started, we can just form
// a useful equation of sqrt(4) = 2 and continue a new equation from now on. But no point in doing this for things like // a useful equation of sqrt(4) = 2 and continue a new equation from now on. But no point in doing this for things like
// MR, SUM etc. All you will get is 5 = 5 kind of no useful equation. // MR, SUM etc. All you will get is 5 = 5 kind of no useful equation.
if ((IsUnaryOpCode(m_nLastCom) || IDC_SIGN == m_nLastCom || IDC_CLOSEP == m_nLastCom) && 0 == m_openParenCount) if ((IsUnaryOpCode(m_nLastCom) || m_nLastCom == IDC_SIGN || m_nLastCom == IDC_CLOSEP) && m_openParenCount == 0)
{ {
if (addToHistory) if (addToHistory)
{ {
@ -876,23 +889,27 @@ void CCalcEngine::CheckAndAddLastBinOpToHistory(bool addToHistory)
// change the display area from a static text to an editbox, which has the focus can make // change the display area from a static text to an editbox, which has the focus can make
// Magnifier (Accessibility tool) work // Magnifier (Accessibility tool) work
void CCalcEngine::SetPrimaryDisplay(const wstring& szText, bool isError) void CCalcEngine::SetPrimaryDisplay(const wstring& szText, bool isError) const
{ {
if (m_pCalcDisplay != nullptr) if (m_pCalcDisplay == nullptr)
{ {
m_pCalcDisplay->SetPrimaryDisplay(szText, isError); return;
m_pCalcDisplay->SetIsInError(isError);
} }
m_pCalcDisplay->SetPrimaryDisplay(szText, isError);
m_pCalcDisplay->SetIsInError(isError);
} }
void CCalcEngine::DisplayAnnounceBinaryOperator() void CCalcEngine::DisplayAnnounceBinaryOperator() const
{ {
// If m_pCalcDisplay is null, this is not a high priority function // If m_pCalcDisplay is null, this is not a high priority function
// and should not be the reason we crash. // and should not be the reason we crash.
if (m_pCalcDisplay != nullptr) if (m_pCalcDisplay == nullptr)
{ {
m_pCalcDisplay->BinaryOperatorReceived(); return;
} }
m_pCalcDisplay->BinaryOperatorReceived();
} }
// Unary operator Function Name table Element // Unary operator Function Name table Element
@ -911,7 +928,7 @@ struct FunctionNameElement
wstring programmerModeString; wstring programmerModeString;
bool hasAngleStrings = ((!radString.empty()) || (!inverseRadString.empty()) || (!gradString.empty()) || (!inverseGradString.empty())); bool hasAngleStrings = !radString.empty() || !inverseRadString.empty() || !gradString.empty() || !inverseGradString.empty();
}; };
// Table for each unary operator // Table for each unary operator
@ -959,9 +976,9 @@ static const std::unordered_map<int, FunctionNameElement> operatorStringTable =
wstring_view CCalcEngine::OpCodeToUnaryString(int nOpCode, bool fInv, AngleType angletype) wstring_view CCalcEngine::OpCodeToUnaryString(int nOpCode, bool fInv, AngleType angletype)
{ {
// Try to lookup the ID in the UFNE table // Try to lookup the ID in the UFNE table
wstring ids = L""; wstring ids;
if (auto pair = operatorStringTable.find(nOpCode); pair != operatorStringTable.end()) if (const auto pair = operatorStringTable.find(nOpCode); pair != operatorStringTable.end())
{ {
const FunctionNameElement& element = pair->second; const FunctionNameElement& element = pair->second;
if (!element.hasAngleStrings || AngleType::Degrees == angletype) if (!element.hasAngleStrings || AngleType::Degrees == angletype)
@ -1000,21 +1017,21 @@ wstring_view CCalcEngine::OpCodeToUnaryString(int nOpCode, bool fInv, AngleType
} }
} }
if (!ids.empty()) if (ids.empty())
{ {
return GetString(ids); // If we didn't find an ID in the table, use the op code.
return OpCodeToString(nOpCode);
} }
// If we didn't find an ID in the table, use the op code. return GetString(ids);
return OpCodeToString(nOpCode);
} }
wstring_view CCalcEngine::OpCodeToBinaryString(int nOpCode, bool isIntegerMode) wstring_view CCalcEngine::OpCodeToBinaryString(int nOpCode, bool isIntegerMode)
{ {
// Try to lookup the ID in the UFNE table // Try to lookup the ID in the UFNE table
wstring ids = L""; wstring ids;
if (auto pair = operatorStringTable.find(nOpCode); pair != operatorStringTable.end()) if (const auto pair = operatorStringTable.find(nOpCode); pair != operatorStringTable.end())
{ {
if (isIntegerMode && !pair->second.programmerModeString.empty()) if (isIntegerMode && !pair->second.programmerModeString.empty())
{ {
@ -1026,28 +1043,28 @@ wstring_view CCalcEngine::OpCodeToBinaryString(int nOpCode, bool isIntegerMode)
} }
} }
if (!ids.empty()) if (ids.empty())
{ {
return GetString(ids); // If we didn't find an ID in the table, use the op code.
return OpCodeToString(nOpCode);
} }
// If we didn't find an ID in the table, use the op code. return GetString(ids);
return OpCodeToString(nOpCode);
} }
bool CCalcEngine::IsCurrentTooBigForTrig() bool CCalcEngine::IsCurrentTooBigForTrig() const
{ {
return m_currentVal >= m_maxTrigonometricNum; return m_currentVal >= m_maxTrigonometricNum;
} }
uint32_t CCalcEngine::GetCurrentRadix() uint32_t CCalcEngine::GetCurrentRadix() const
{ {
return m_radix; return m_radix;
} }
wstring CCalcEngine::GetCurrentResultForRadix(uint32_t radix, int32_t precision, bool groupDigitsPerRadix) wstring CCalcEngine::GetCurrentResultForRadix(uint32_t radix, int32_t precision, bool groupDigitsPerRadix)
{ {
Rational rat = (m_bRecord ? m_input.ToRational(m_radix, m_precision) : m_currentVal); const Rational rat = m_bRecord ? m_input.ToRational(m_radix, m_precision) : m_currentVal;
ChangeConstants(m_radix, precision); ChangeConstants(m_radix, precision);
@ -1068,7 +1085,7 @@ wstring CCalcEngine::GetCurrentResultForRadix(uint32_t radix, int32_t precision,
} }
} }
wstring CCalcEngine::GetStringForDisplay(Rational const& rat, uint32_t radix) wstring CCalcEngine::GetStringForDisplay(Rational const& rat, uint32_t radix) const
{ {
wstring result{}; wstring result{};
// Check for standard\scientific mode // Check for standard\scientific mode
@ -1084,9 +1101,7 @@ wstring CCalcEngine::GetStringForDisplay(Rational const& rat, uint32_t radix)
try try
{ {
uint64_t w64Bits = tempRat.ToUInt64_t(); if (radix == 10 && ((tempRat.ToUInt64_t() & (1ULL << (m_dwWordBitWidth - 1))) != 0))
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 complement form. // If high bit is set, then get the decimal number in negative 2's complement form.
tempRat = -((tempRat ^ GetChopNumber()) + 1); tempRat = -((tempRat ^ GetChopNumber()) + 1);
@ -1110,5 +1125,5 @@ double CCalcEngine::GenerateRandomNumber()
m_randomGeneratorEngine = std::make_unique<std::mt19937>(rd()); m_randomGeneratorEngine = std::make_unique<std::mt19937>(rd());
m_distr = std::make_unique<std::uniform_real_distribution<>>(0, 1); m_distr = std::make_unique<std::uniform_real_distribution<>>(0, 1);
} }
return (*m_distr.get())(*m_randomGeneratorEngine.get()); return (*m_distr)(*m_randomGeneratorEngine);
} }

View file

@ -48,10 +48,10 @@ typedef struct
bool bUseSep; bool bUseSep;
} LASTDISP; } LASTDISP;
static LASTDISP gldPrevious = { 0, -1, 0, -1, (NUM_WIDTH)-1, false, false, false }; static LASTDISP gldPrevious = { 0, -1, 0, -1, static_cast<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) const
{ {
if (!m_fIntegerMode) if (!m_fIntegerMode)
{ {
@ -60,22 +60,23 @@ CalcEngine::Rational CCalcEngine::TruncateNumForIntMath(CalcEngine::Rational con
// Truncate to an integer. Do not round here. // Truncate to an integer. Do not round here.
auto result = RationalMath::Integer(rat); auto result = RationalMath::Integer(rat);
const auto chopNumber = GetChopNumber();
// Can be converting a dec negative number to Hex/Oct/Bin rep. Use 2's complement form // Can be converting a dec negative number to Hex/Oct/Bin rep. Use 2's complement form
// Check the range. // Check the range.
if (result < 0) if (result < 0)
{ {
// if negative make positive by doing a twos complement // if negative make positive by doing a twos complement
result = -(result)-1; result = -result-1;
result ^= GetChopNumber(); result ^= chopNumber;
} }
result &= GetChopNumber(); result &= chopNumber;
return result; return result;
} }
void CCalcEngine::DisplayNum(void) void CCalcEngine::DisplayNum()
{ {
// //
// Only change the display if // Only change the display if
@ -84,12 +85,13 @@ 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.
// //
if (m_bRecord || gldPrevious.value != m_currentVal || gldPrevious.precision != m_precision || gldPrevious.radix != m_radix || gldPrevious.nFE != (int)m_nFE if (m_bRecord || gldPrevious.value != m_currentVal || gldPrevious.precision != m_precision || gldPrevious.radix != m_radix
|| !gldPrevious.bUseSep || gldPrevious.numwidth != m_numwidth || gldPrevious.fIntMath != m_fIntegerMode || gldPrevious.bRecord != m_bRecord) || gldPrevious.nFE != static_cast<int>(m_nFE) || !gldPrevious.bUseSep || gldPrevious.numwidth != m_numwidth || gldPrevious.fIntMath != m_fIntegerMode
|| gldPrevious.bRecord != m_bRecord)
{ {
gldPrevious.precision = m_precision; gldPrevious.precision = m_precision;
gldPrevious.radix = m_radix; gldPrevious.radix = m_radix;
gldPrevious.nFE = (int)m_nFE; gldPrevious.nFE = static_cast<int>(m_nFE);
gldPrevious.numwidth = m_numwidth; gldPrevious.numwidth = m_numwidth;
gldPrevious.fIntMath = m_fIntegerMode; gldPrevious.fIntMath = m_fIntegerMode;
@ -114,7 +116,7 @@ void CCalcEngine::DisplayNum(void)
// Displayed number can go through transformation. So copy it after transformation // Displayed number can go through transformation. So copy it after transformation
gldPrevious.value = m_currentVal; 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) != 0))
{ {
DisplayError(CALC_E_OVERFLOW); DisplayError(CALC_E_OVERFLOW);
} }
@ -156,7 +158,7 @@ int CCalcEngine::IsNumberInvalid(const wstring& numberString, int iMaxExp, int i
auto intEnd = exp.end(); auto intEnd = exp.end();
while (intItr != intEnd && *intItr == L'0') while (intItr != intEnd && *intItr == L'0')
{ {
intItr++; ++intItr;
} }
auto iMantissa = distance(intItr, intEnd) + matches.length(2); auto iMantissa = distance(intItr, intEnd) + matches.length(2);
@ -177,7 +179,7 @@ int CCalcEngine::IsNumberInvalid(const wstring& numberString, int iMaxExp, int i
{ {
if (radix == 16) if (radix == 16)
{ {
if (!(iswdigit(c) || (c >= L'A' && c <= L'F'))) if (!(iswdigit(c) || c >= L'A' && c <= L'F'))
{ {
iError = IDS_ERR_UNK_CH; iError = IDS_ERR_UNK_CH;
} }
@ -234,7 +236,7 @@ vector<uint32_t> CCalcEngine::DigitGroupingStringToGroupingVector(wstring_view g
// If we found a grouping and aren't at the end of the string yet, // If we found a grouping and aren't at the end of the string yet,
// jump to the next position in the string (the ';'). // jump to the next position in the string (the ';').
// The loop will then increment us to the next character, which should be a number. // The loop will then increment us to the next character, which should be a number.
if (next && (static_cast<size_t>(next - begin) < groupingString.length())) if (next && static_cast<size_t>(next - begin) < groupingString.length())
{ {
itr = next; itr = next;
} }
@ -243,7 +245,7 @@ vector<uint32_t> CCalcEngine::DigitGroupingStringToGroupingVector(wstring_view g
return grouping; return grouping;
} }
wstring CCalcEngine::GroupDigitsPerRadix(wstring_view numberString, uint32_t radix) wstring CCalcEngine::GroupDigitsPerRadix(wstring_view numberString, uint32_t radix) const
{ {
if (numberString.empty()) if (numberString.empty())
{ {
@ -253,7 +255,7 @@ wstring CCalcEngine::GroupDigitsPerRadix(wstring_view numberString, uint32_t rad
switch (radix) switch (radix)
{ {
case 10: case 10:
return GroupDigits(wstring{ m_groupSeparator }, m_decGrouping, numberString, (L'-' == numberString[0])); return GroupDigits(wstring{ m_groupSeparator }, m_decGrouping, numberString, L'-' == numberString[0]);
case 8: case 8:
return GroupDigits(L" ", { 3, 0 }, numberString); return GroupDigits(L" ", { 3, 0 }, numberString);
case 2: case 2:
@ -283,7 +285,7 @@ wstring CCalcEngine::GroupDigitsPerRadix(wstring_view numberString, uint32_t rad
* 5,3,2 - group 5, then 3, then 2, then no grouping after * 5,3,2 - group 5, then 3, then 2, then no grouping after
* *
\***************************************************************************/ \***************************************************************************/
wstring CCalcEngine::GroupDigits(wstring_view delimiter, vector<uint32_t> const& grouping, wstring_view displayString, bool isNumNegative) wstring CCalcEngine::GroupDigits(wstring_view delimiter, vector<uint32_t> const& grouping, wstring_view displayString, bool isNumNegative) const
{ {
// if there's nothing to do, bail // if there's nothing to do, bail
if (delimiter.empty() || grouping.empty()) if (delimiter.empty() || grouping.empty())
@ -293,11 +295,11 @@ wstring CCalcEngine::GroupDigits(wstring_view delimiter, vector<uint32_t> const&
// Find the position of exponential 'e' in the string // Find the position of exponential 'e' in the string
size_t exp = displayString.find(L'e'); size_t exp = displayString.find(L'e');
bool hasExponent = (exp != wstring_view::npos); bool hasExponent = exp != wstring_view::npos;
// Find the position of decimal point in the string // Find the position of decimal point in the string
size_t dec = displayString.find(m_decimalSeparator); size_t dec = displayString.find(m_decimalSeparator);
bool hasDecimal = (dec != wstring_view::npos); bool hasDecimal = dec != wstring_view::npos;
// Create an iterator that points to the end of the portion of the number subject to grouping (i.e. left of the decimal) // Create an iterator that points to the end of the portion of the number subject to grouping (i.e. left of the decimal)
auto ritr = displayString.rend(); auto ritr = displayString.rend();
@ -332,7 +334,7 @@ wstring CCalcEngine::GroupDigits(wstring_view delimiter, vector<uint32_t> const&
// Do not add a separator if: // Do not add a separator if:
// - grouping size is 0 // - grouping size is 0
// - we are at the end of the digit string // - we are at the end of the digit string
if (currGrouping != 0 && (groupingSize % currGrouping) == 0 && ritr != reverse_end) if (currGrouping != 0 && groupingSize % currGrouping == 0 && ritr != reverse_end)
{ {
result += delimiter; result += delimiter;
groupingSize = 0; // reset for a new group groupingSize = 0; // reset for a new group
@ -340,14 +342,13 @@ wstring CCalcEngine::GroupDigits(wstring_view delimiter, vector<uint32_t> const&
// Shift the grouping to next values if they exist // Shift the grouping to next values if they exist
if (groupItr != grouping.end()) if (groupItr != grouping.end())
{ {
++groupItr;
// Loop through grouping vector until we find a non-zero value. // Loop through grouping vector until we find a non-zero value.
// "0" values may appear in a form of either e.g. "3;0" or "3;0;0". // "0" values may appear in a form of either e.g. "3;0" or "3;0;0".
// A 0 in the last position means repeat the previous grouping. // A 0 in the last position means repeat the previous grouping.
// A 0 in another position is a group. So, "3;0;0" means "group 3, then group 0 repeatedly" // A 0 in another position is a group. So, "3;0;0" means "group 3, then group 0 repeatedly"
// This could be expressed as just "3" but GetLocaleInfo is returning 3;0;0 in some cases instead. // This could be expressed as just "3" but GetLocaleInfo is returning 3;0;0 in some cases instead.
for (currGrouping = 0; groupItr != grouping.end(); ++groupItr) currGrouping = 0;
while (++groupItr != grouping.end())
{ {
// If it's a non-zero value, that's our new group // If it's a non-zero value, that's our new group
if (*groupItr != 0) if (*groupItr != 0)

View file

@ -21,10 +21,10 @@
using namespace std; using namespace std;
using namespace CalcEngine; using namespace CalcEngine;
using namespace CalcEngine::RationalMath; using namespace 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, uint32_t op) Rational CCalcEngine::SciCalcFunctions(Rational const& rat, uint32_t op)
{ {
Rational result{}; Rational result{};
try try
@ -39,7 +39,7 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
case IDC_COM: case IDC_COM:
if (m_radix == 10 && !m_fIntegerMode) if (m_radix == 10 && !m_fIntegerMode)
{ {
result = -(RationalMath::Integer(rat) + 1); result = -(Integer(rat) + 1);
} }
else else
{ {
@ -78,16 +78,16 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
result = Integer(rat); result = Integer(rat);
uint64_t w64Bits = result.ToUInt64_t(); uint64_t w64Bits = result.ToUInt64_t();
uint64_t lsb = ((w64Bits & 0x01) == 1) ? 1 : 0; uint64_t lsb = w64Bits & 0x01;
w64Bits >>= 1; // RShift by 1 w64Bits >>= 1; // RShift by 1
if (op == IDC_ROR) if (op == IDC_ROR)
{ {
w64Bits |= (lsb << (m_dwWordBitWidth - 1)); w64Bits |= lsb << (m_dwWordBitWidth - 1);
} }
else else
{ {
w64Bits |= (m_carryBit << (m_dwWordBitWidth - 1)); w64Bits |= m_carryBit << (m_dwWordBitWidth - 1);
m_carryBit = lsb; m_carryBit = lsb;
} }
@ -268,11 +268,11 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
break; break;
} }
case IDC_CEIL: case IDC_CEIL:
result = (Frac(rat) > 0) ? Integer(rat + 1) : Integer(rat); result = Frac(rat) > 0 ? Integer(rat + 1) : Integer(rat);
break; break;
case IDC_FLOOR: case IDC_FLOOR:
result = (Frac(rat) < 0) ? Integer(rat - 1) : Integer(rat); result = Frac(rat) < 0 ? Integer(rat - 1) : Integer(rat);
break; break;
case IDC_ABS: case IDC_ABS:

View file

@ -10,7 +10,7 @@ using namespace CalcEngine::RationalMath;
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)
{ {
// 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.
auto result = (lhs != 0 ? lhs : 0); auto result = lhs != 0 ? lhs : 0;
try try
{ {
@ -29,7 +29,7 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa
break; break;
case IDC_NAND: case IDC_NAND:
result = (result & rhs) ^ GetChopNumber(); result = result & rhs ^ GetChopNumber();
break; break;
case IDC_NOR: case IDC_NOR:
@ -43,20 +43,18 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa
throw CALC_E_NORESULT; throw CALC_E_NORESULT;
} }
uint64_t w64Bits = rhs.ToUInt64_t();
bool fMsb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1;
Rational holdVal = result; Rational holdVal = result;
result = rhs >> holdVal; result = rhs >> holdVal;
if (fMsb) if ((rhs.ToUInt64_t() & (1ULL << (m_dwWordBitWidth - 1))) != 0)
{ {
result = Integer(result); result = Integer(result);
const auto chopNumber = GetChopNumber();
auto tempRat = GetChopNumber() >> holdVal; auto tempRat = chopNumber >> holdVal;
tempRat = Integer(tempRat); tempRat = Integer(tempRat);
result |= tempRat ^ GetChopNumber(); result |= tempRat ^ chopNumber;
} }
break; break;
} }
@ -94,59 +92,55 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa
case IDC_DIV: case IDC_DIV:
case IDC_MOD: case IDC_MOD:
{ {
int iNumeratorSign = 1, iDenominatorSign = 1; bool isNumeratorNegative = false, isDenominatorNegative = false;
auto temp = result; auto temp = result;
result = rhs; result = rhs;
if (m_fIntegerMode) if (m_fIntegerMode)
{ {
uint64_t w64Bits = rhs.ToUInt64_t(); uint64_t w64Bits = rhs.ToUInt64_t();
bool fMsb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1; const uint64_t mask = 1ULL << (m_dwWordBitWidth - 1);
if ((w64Bits & mask) != 0)
if (fMsb)
{ {
result = (rhs ^ GetChopNumber()) + 1; result = (rhs ^ GetChopNumber()) + 1;
iNumeratorSign = -1; isNumeratorNegative = true;
} }
w64Bits = temp.ToUInt64_t(); w64Bits = temp.ToUInt64_t();
fMsb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1;
if (fMsb) if ((w64Bits & mask) != 0)
{ {
temp = (temp ^ GetChopNumber()) + 1; temp = (temp ^ GetChopNumber()) + 1;
iDenominatorSign = -1; isDenominatorNegative = true;
} }
} }
if (operation == IDC_DIV) if (operation == IDC_DIV)
{ {
result /= temp; result /= temp;
if (m_fIntegerMode && (iNumeratorSign * iDenominatorSign) == -1) if (m_fIntegerMode && isNumeratorNegative != isDenominatorNegative)
{ {
result = -(Integer(result)); result = -Integer(result);
}
}
else if (m_fIntegerMode)
{
// Programmer mode, use remrat (remainder after division)
result %= temp;
if (isNumeratorNegative)
{
result = -Integer(result);
} }
} }
else else
{ {
if (m_fIntegerMode) // other modes, use modrat (modulus after division)
{ result = Mod(result, temp);
// Programmer mode, use remrat (remainder after division)
result %= temp;
if (iNumeratorSign == -1)
{
result = -(Integer(result));
}
}
else
{
// other modes, use modrat (modulus after division)
result = Mod(result, temp);
}
} }
break; break;
} }
@ -159,7 +153,7 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa
break; break;
case IDC_LOGBASEY: case IDC_LOGBASEY:
result = (Log(rhs) / Log(result)); result = Log(rhs) / Log(result);
break; break;
} }
} }

View file

@ -16,18 +16,11 @@ void CCalcEngine::SetRadixTypeAndNumWidth(RadixType radixtype, NUM_WIDTH numwidt
// convert to 2's complement form, but this time all high bits will be propagated. Eg. -127, in byte mode is // convert to 2's complement form, but this time all high bits will be propagated. Eg. -127, in byte mode is
// represented as 1000,0001. This puts it back as sign=-1, 01111111 . But DisplayNum will see this and convert it // represented as 1000,0001. This puts it back as sign=-1, 01111111 . But DisplayNum will see this and convert it
// 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 && (m_currentVal.ToUInt64_t() & (1ULL << (m_dwWordBitWidth - 1))) != 0)
{ {
uint64_t w64Bits = m_currentVal.ToUInt64_t(); // make sure you use the old width
bool fMsb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1; // make sure you use the old width // If high bit is set, then get the decimal number in -ve 2'scompl form.
m_currentVal = -((m_currentVal ^ GetChopNumber()) + 1);
if (fMsb)
{
// If high bit is set, then get the decimal number in -ve 2'scompl form.
auto tempResult = m_currentVal ^ GetChopNumber();
m_currentVal = -(tempResult + 1);
}
} }
if (radixtype >= RadixType::Hex && radixtype <= RadixType::Binary) if (radixtype >= RadixType::Hex && radixtype <= RadixType::Binary)
@ -39,7 +32,7 @@ void CCalcEngine::SetRadixTypeAndNumWidth(RadixType radixtype, NUM_WIDTH numwidt
if (numwidth >= NUM_WIDTH::QWORD_WIDTH && numwidth <= NUM_WIDTH::BYTE_WIDTH) if (numwidth >= NUM_WIDTH::QWORD_WIDTH && numwidth <= NUM_WIDTH::BYTE_WIDTH)
{ {
m_numwidth = numwidth; m_numwidth = numwidth;
m_dwWordBitWidth = DwWordBitWidthFromeNumWidth(numwidth); m_dwWordBitWidth = DwWordBitWidthFromNumWidth(numwidth);
} }
// inform ratpak that a change in base or precision has occurred // inform ratpak that a change in base or precision has occurred
@ -50,7 +43,7 @@ void CCalcEngine::SetRadixTypeAndNumWidth(RadixType radixtype, NUM_WIDTH numwidt
DisplayNum(); DisplayNum();
} }
int32_t CCalcEngine::DwWordBitWidthFromeNumWidth(NUM_WIDTH numwidth) uint32_t CCalcEngine::DwWordBitWidthFromNumWidth(NUM_WIDTH numwidth)
{ {
switch (numwidth) switch (numwidth)
{ {
@ -85,16 +78,16 @@ uint32_t CCalcEngine::NRadixFromRadixType(RadixType radixtype)
// Toggles a given bit into the number representation. returns true if it changed it actually. // Toggles a given bit into the number representation. returns true if it changed it actually.
bool CCalcEngine::TryToggleBit(CalcEngine::Rational& rat, uint32_t wbitno) bool CCalcEngine::TryToggleBit(CalcEngine::Rational& rat, uint32_t wbitno)
{ {
uint32_t wmax = DwWordBitWidthFromeNumWidth(m_numwidth); uint32_t wmax = DwWordBitWidthFromNumWidth(m_numwidth);
if (wbitno >= wmax) if (wbitno >= wmax)
{ {
return false; // ignore error cant happen return false; // ignore error can't happen
} }
Rational result = Integer(rat); Rational result = Integer(rat);
// 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.
result = (result != 0 ? result : 0); result = result != 0 ? result : 0;
// XOR the result with 2^wbitno power // XOR the result with 2^wbitno power
rat = result ^ Pow(2, static_cast<int32_t>(wbitno)); rat = result ^ Pow(2, static_cast<int32_t>(wbitno));
@ -159,13 +152,13 @@ void CCalcEngine::UpdateMaxIntDigits()
} }
else else
{ {
m_cIntDigitsSav = m_dwWordBitWidth / CCalcEngine::QuickLog2(m_radix); m_cIntDigitsSav = m_dwWordBitWidth / QuickLog2(m_radix);
} }
} }
void CCalcEngine::ChangeBaseConstants(uint32_t radix, int maxIntDigits, int32_t precision) void CCalcEngine::ChangeBaseConstants(uint32_t radix, int maxIntDigits, int32_t precision)
{ {
if (10 == radix) if (radix == 10)
{ {
ChangeConstants(radix, precision); // Base 10 precision for internal computing still needs to be 32, to ChangeConstants(radix, precision); // Base 10 precision for internal computing still needs to be 32, to
// take care of decimals precisely. For eg. to get the HI word of a qword, we do a rsh, which depends on getting // take care of decimals precisely. For eg. to get the HI word of a qword, we do a rsh, which depends on getting
@ -182,5 +175,5 @@ void CCalcEngine::ChangeBaseConstants(uint32_t radix, int maxIntDigits, int32_t
void CCalcEngine::BaseOrPrecisionChanged() void CCalcEngine::BaseOrPrecisionChanged()
{ {
UpdateMaxIntDigits(); UpdateMaxIntDigits();
CCalcEngine::ChangeBaseConstants(m_radix, m_cIntDigitsSav, m_precision); ChangeBaseConstants(m_radix, m_cIntDigitsSav, m_precision);
} }

View file

@ -9,7 +9,7 @@ using namespace CalculationManager;
namespace namespace
{ {
static wstring GetGeneratedExpression(const vector<pair<wstring, int>>& tokens) wstring GetGeneratedExpression(const vector<pair<wstring, int>>& tokens)
{ {
wstring expression; wstring expression;
bool isFirst = true; bool isFirst = true;
@ -41,7 +41,7 @@ unsigned int CalculatorHistory::AddToHistory(
_In_ shared_ptr<vector<shared_ptr<IExpressionCommand>>> const& commands, _In_ shared_ptr<vector<shared_ptr<IExpressionCommand>>> const& commands,
wstring_view result) wstring_view result)
{ {
shared_ptr<HISTORYITEM> spHistoryItem = make_shared<HISTORYITEM>(); const auto spHistoryItem = make_shared<HISTORYITEM>();
spHistoryItem->historyItemVector.spTokens = tokens; spHistoryItem->historyItemVector.spTokens = tokens;
spHistoryItem->historyItemVector.spCommands = commands; spHistoryItem->historyItemVector.spCommands = commands;

View file

@ -23,11 +23,11 @@ namespace CalculationManager
class CalculatorHistory : public IHistoryDisplay class CalculatorHistory : public IHistoryDisplay
{ {
public: public:
CalculatorHistory(const size_t maxSize); CalculatorHistory(size_t maxSize);
unsigned int AddToHistory( unsigned int AddToHistory(
_In_ std::shared_ptr<std::vector<std::pair<std::wstring, int>>> const& spTokens, _In_ std::shared_ptr<std::vector<std::pair<std::wstring, int>>> const& spTokens,
_In_ std::shared_ptr<std::vector<std::shared_ptr<IExpressionCommand>>> const& spCommands, _In_ std::shared_ptr<std::vector<std::shared_ptr<IExpressionCommand>>> const& spCommands,
std::wstring_view result); std::wstring_view result) override;
std::vector<std::shared_ptr<HISTORYITEM>> const& GetHistory(); std::vector<std::shared_ptr<HISTORYITEM>> const& GetHistory();
std::shared_ptr<HISTORYITEM> const& GetHistoryItem(unsigned int uIdx); std::shared_ptr<HISTORYITEM> const& GetHistoryItem(unsigned int uIdx);
void ClearHistory(); void ClearHistory();

View file

@ -22,7 +22,6 @@ namespace CalculationManager
, m_currentCalculatorEngine(nullptr) , m_currentCalculatorEngine(nullptr)
, m_resourceProvider(resourceProvider) , m_resourceProvider(resourceProvider)
, m_inHistoryItemLoadMode(false) , m_inHistoryItemLoadMode(false)
, m_persistedPrimaryValue()
, m_isExponentialFormat(false) , m_isExponentialFormat(false)
, m_currentDegreeMode(Command::CommandNULL) , m_currentDegreeMode(Command::CommandNULL)
, m_pStdHistory(new CalculatorHistory(MAX_HISTORY_ITEMS)) , m_pStdHistory(new CalculatorHistory(MAX_HISTORY_ITEMS))
@ -50,7 +49,7 @@ namespace CalculationManager
m_displayCallback->SetIsInError(isError); m_displayCallback->SetIsInError(isError);
} }
void CalculatorManager::DisplayPasteError() void CalculatorManager::DisplayPasteError() const
{ {
m_currentCalculatorEngine->DisplayError(CALC_E_DOMAIN /*code for "Invalid input" error*/); m_currentCalculatorEngine->DisplayError(CALC_E_DOMAIN /*code for "Invalid input" error*/);
} }
@ -212,37 +211,39 @@ namespace CalculationManager
/// <param name="command">Enum Command</command> /// <param name="command">Enum Command</command>
void CalculatorManager::SendCommand(_In_ Command command) void CalculatorManager::SendCommand(_In_ Command command)
{ {
// When the expression line is cleared, we save the current state, which includes,
// primary display, memory, and degree mode
if (command == Command::CommandCLEAR || command == Command::CommandEQU || command == Command::ModeBasic || command == Command::ModeScientific
|| command == Command::ModeProgrammer)
{
switch (command)
{
case Command::ModeBasic:
this->SetStandardMode();
break;
case Command::ModeScientific:
this->SetScientificMode();
break;
case Command::ModeProgrammer:
this->SetProgrammerMode();
break;
default:
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(command));
}
InputChanged();
return;
}
if (command == Command::CommandDEG || command == Command::CommandRAD || command == Command::CommandGRAD)
{
m_currentDegreeMode = command;
}
switch (command) switch (command)
{ {
case Command::CommandCLEAR:
// When the expression line is cleared, we save the current state, which includes,
// primary display, memory, and degree mode
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandCLEAR));
break;
case Command::CommandEQU:
// When the expression line is cleared, we save the current state, which includes,
// primary display, memory, and degree mode
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandEQU));
break;
case Command::ModeBasic:
this->SetStandardMode();
break;
case Command::ModeScientific:
this->SetScientificMode();
break;
case Command::ModeProgrammer:
this->SetProgrammerMode();
break;
case Command::CommandDEG:
m_currentDegreeMode = Command::CommandDEG;
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandDEG));
break;
case Command::CommandRAD:
m_currentDegreeMode = Command::CommandRAD;
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandRAD));
break;
case Command::CommandGRAD:
m_currentDegreeMode = Command::CommandGRAD;
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandGRAD));
break;
case Command::CommandASIN: case Command::CommandASIN:
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandINV)); m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandINV));
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandSIN)); m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandSIN));
@ -329,7 +330,7 @@ namespace CalculationManager
m_currentCalculatorEngine->ProcessCommand(IDC_STORE); m_currentCalculatorEngine->ProcessCommand(IDC_STORE);
auto memoryObjectPtr = m_currentCalculatorEngine->PersistedMemObject(); const auto memoryObjectPtr = m_currentCalculatorEngine->PersistedMemObject();
if (memoryObjectPtr != nullptr) if (memoryObjectPtr != nullptr)
{ {
m_memorizedNumbers.insert(m_memorizedNumbers.begin(), *memoryObjectPtr); m_memorizedNumbers.insert(m_memorizedNumbers.begin(), *memoryObjectPtr);
@ -447,7 +448,7 @@ namespace CalculationManager
/// Saved RAT number needs to be copied and passed in, as CCalcEngine destroyed the passed in RAT /// Saved RAT number needs to be copied and passed in, as CCalcEngine destroyed the passed in RAT
/// </summary> /// </summary>
/// <param name="indexOfMemory">Index of the target memory</param> /// <param name="indexOfMemory">Index of the target memory</param>
void CalculatorManager::MemorizedNumberSelect(_In_ unsigned int indexOfMemory) void CalculatorManager::MemorizedNumberSelect(_In_ unsigned int indexOfMemory) const
{ {
if (m_currentCalculatorEngine->FInErrorState()) if (m_currentCalculatorEngine->FInErrorState())
{ {
@ -471,23 +472,25 @@ namespace CalculationManager
} }
auto memoryObject = m_currentCalculatorEngine->PersistedMemObject(); auto memoryObject = m_currentCalculatorEngine->PersistedMemObject();
if (memoryObject != nullptr) if (memoryObject == nullptr)
{ {
m_memorizedNumbers.at(indexOfMemory) = *memoryObject; return;
} }
m_memorizedNumbers.at(indexOfMemory) = *memoryObject;
} }
vector<shared_ptr<HISTORYITEM>> const& CalculatorManager::GetHistoryItems() vector<shared_ptr<HISTORYITEM>> const& CalculatorManager::GetHistoryItems() const
{ {
return m_pHistory->GetHistory(); return m_pHistory->GetHistory();
} }
vector<shared_ptr<HISTORYITEM>> const& CalculatorManager::GetHistoryItems(_In_ CalculatorMode mode) vector<shared_ptr<HISTORYITEM>> const& CalculatorManager::GetHistoryItems(_In_ CalculatorMode mode) const
{ {
return (mode == CalculatorMode::Standard) ? m_pStdHistory->GetHistory() : m_pSciHistory->GetHistory(); return mode == CalculatorMode::Standard ? m_pStdHistory->GetHistory() : m_pSciHistory->GetHistory();
} }
shared_ptr<HISTORYITEM> const& CalculatorManager::GetHistoryItem(_In_ unsigned int uIdx) shared_ptr<HISTORYITEM> const& CalculatorManager::GetHistoryItem(_In_ unsigned int uIdx) const
{ {
return m_pHistory->GetHistoryItem(uIdx); return m_pHistory->GetHistoryItem(uIdx);
} }
@ -497,17 +500,17 @@ namespace CalculationManager
m_displayCallback->OnHistoryItemAdded(addedItemIndex); m_displayCallback->OnHistoryItemAdded(addedItemIndex);
} }
bool CalculatorManager::RemoveHistoryItem(_In_ unsigned int uIdx) bool CalculatorManager::RemoveHistoryItem(_In_ unsigned int uIdx) const
{ {
return m_pHistory->RemoveItem(uIdx); return m_pHistory->RemoveItem(uIdx);
} }
void CalculatorManager::ClearHistory() void CalculatorManager::ClearHistory() const
{ {
m_pHistory->ClearHistory(); m_pHistory->ClearHistory();
} }
void CalculatorManager::SetRadix(RadixType iRadixType) void CalculatorManager::SetRadix(RadixType iRadixType) const
{ {
switch (iRadixType) switch (iRadixType)
{ {
@ -529,7 +532,7 @@ namespace CalculationManager
SetMemorizedNumbersString(); SetMemorizedNumbersString();
} }
void CalculatorManager::SetMemorizedNumbersString() void CalculatorManager::SetMemorizedNumbersString() const
{ {
vector<wstring> resultVector; vector<wstring> resultVector;
for (auto const& memoryItem : m_memorizedNumbers) for (auto const& memoryItem : m_memorizedNumbers)
@ -545,7 +548,7 @@ namespace CalculationManager
m_displayCallback->SetMemorizedNumbers(resultVector); m_displayCallback->SetMemorizedNumbers(resultVector);
} }
CalculationManager::Command CalculatorManager::GetCurrentDegreeMode() Command CalculatorManager::GetCurrentDegreeMode()
{ {
if (m_currentDegreeMode == Command::CommandNULL) if (m_currentDegreeMode == Command::CommandNULL)
{ {
@ -554,32 +557,32 @@ namespace CalculationManager
return m_currentDegreeMode; return m_currentDegreeMode;
} }
wstring CalculatorManager::GetResultForRadix(uint32_t radix, int32_t precision, bool groupDigitsPerRadix) wstring CalculatorManager::GetResultForRadix(uint32_t radix, int32_t precision, bool groupDigitsPerRadix) const
{ {
return m_currentCalculatorEngine ? m_currentCalculatorEngine->GetCurrentResultForRadix(radix, precision, groupDigitsPerRadix) : L""; return m_currentCalculatorEngine != nullptr ? m_currentCalculatorEngine->GetCurrentResultForRadix(radix, precision, groupDigitsPerRadix) : L"";
} }
void CalculatorManager::SetPrecision(int32_t precision) void CalculatorManager::SetPrecision(int32_t precision) const
{ {
m_currentCalculatorEngine->ChangePrecision(precision); m_currentCalculatorEngine->ChangePrecision(precision);
} }
void CalculatorManager::UpdateMaxIntDigits() void CalculatorManager::UpdateMaxIntDigits() const
{ {
m_currentCalculatorEngine->UpdateMaxIntDigits(); m_currentCalculatorEngine->UpdateMaxIntDigits();
} }
wchar_t CalculatorManager::DecimalSeparator() wchar_t CalculatorManager::DecimalSeparator() const
{ {
return m_currentCalculatorEngine ? m_currentCalculatorEngine->DecimalSeparator() : m_resourceProvider->GetCEngineString(L"sDecimal")[0]; return m_currentCalculatorEngine != nullptr ? m_currentCalculatorEngine->DecimalSeparator() : m_resourceProvider->GetCEngineString(L"sDecimal")[0];
} }
bool CalculatorManager::IsEngineRecording() bool CalculatorManager::IsEngineRecording() const
{ {
return m_currentCalculatorEngine->FInRecordingState(); return m_currentCalculatorEngine->FInRecordingState();
} }
bool CalculatorManager::IsInputEmpty() bool CalculatorManager::IsInputEmpty() const
{ {
return m_currentCalculatorEngine->IsInputEmpty(); return m_currentCalculatorEngine->IsInputEmpty();
} }

View file

@ -44,7 +44,7 @@ namespace CalculationManager
class CalculatorManager final : public ICalcDisplay class CalculatorManager final : public ICalcDisplay
{ {
private: private:
static const unsigned int m_maximumMemorySize = 100; static constexpr unsigned int m_maximumMemorySize = 100;
ICalcDisplay* const m_displayCallback; ICalcDisplay* const m_displayCallback;
CCalcEngine* m_currentCalculatorEngine; CCalcEngine* m_currentCalculatorEngine;
std::unique_ptr<CCalcEngine> m_scientificCalculatorEngine; std::unique_ptr<CCalcEngine> m_scientificCalculatorEngine;
@ -58,7 +58,7 @@ namespace CalculationManager
bool m_isExponentialFormat; bool m_isExponentialFormat;
Command m_currentDegreeMode; Command m_currentDegreeMode;
void MemorizedNumberSelect(_In_ unsigned int); void MemorizedNumberSelect(_In_ unsigned int) const;
void MemorizedNumberChanged(_In_ unsigned int); void MemorizedNumberChanged(_In_ unsigned int);
void LoadPersistedPrimaryValue(); void LoadPersistedPrimaryValue();
@ -78,7 +78,7 @@ namespace CalculationManager
void OnHistoryItemAdded(_In_ unsigned int addedItemIndex) override; void OnHistoryItemAdded(_In_ unsigned int addedItemIndex) override;
void SetParenthesisNumber(_In_ unsigned int parenthesisCount) override; void SetParenthesisNumber(_In_ unsigned int parenthesisCount) override;
void OnNoRightParenAdded() override; void OnNoRightParenAdded() override;
void DisplayPasteError(); void DisplayPasteError() const;
void MaxDigitsReached() override; void MaxDigitsReached() override;
void BinaryOperatorReceived() override; void BinaryOperatorReceived() override;
void MemoryItemChanged(unsigned int indexOfMemory) override; void MemoryItemChanged(unsigned int indexOfMemory) override;
@ -98,20 +98,20 @@ namespace CalculationManager
void MemorizedNumberClear(_In_ unsigned int); void MemorizedNumberClear(_In_ unsigned int);
void MemorizedNumberClearAll(); void MemorizedNumberClearAll();
bool IsEngineRecording(); bool IsEngineRecording() const;
bool IsInputEmpty(); bool IsInputEmpty() const;
void SetRadix(RadixType iRadixType); void SetRadix(RadixType iRadixType) const;
void SetMemorizedNumbersString(); void SetMemorizedNumbersString() const;
std::wstring GetResultForRadix(uint32_t radix, int32_t precision, bool groupDigitsPerRadix); std::wstring GetResultForRadix(uint32_t radix, int32_t precision, bool groupDigitsPerRadix) const;
void SetPrecision(int32_t precision); void SetPrecision(int32_t precision) const;
void UpdateMaxIntDigits(); void UpdateMaxIntDigits() const;
wchar_t DecimalSeparator(); wchar_t DecimalSeparator() const;
std::vector<std::shared_ptr<HISTORYITEM>> const& GetHistoryItems(); std::vector<std::shared_ptr<HISTORYITEM>> const& GetHistoryItems() const;
std::vector<std::shared_ptr<HISTORYITEM>> const& GetHistoryItems(_In_ CalculatorMode mode); std::vector<std::shared_ptr<HISTORYITEM>> const& GetHistoryItems(_In_ CalculatorMode mode) const;
std::shared_ptr<HISTORYITEM> const& GetHistoryItem(_In_ unsigned int uIdx); std::shared_ptr<HISTORYITEM> const& GetHistoryItem(_In_ unsigned int uIdx) const;
bool RemoveHistoryItem(_In_ unsigned int uIdx); bool RemoveHistoryItem(_In_ unsigned int uIdx) const;
void ClearHistory(); void ClearHistory() const;
size_t MaxHistorySize() const size_t MaxHistorySize() const
{ {
return m_pHistory->MaxHistorySize(); return m_pHistory->MaxHistorySize();

View file

@ -10,9 +10,7 @@ namespace CalculationManager
class IResourceProvider class IResourceProvider
{ {
public: public:
virtual ~IResourceProvider() virtual ~IResourceProvider() = default;
{
}
// Should return a string from the resource table for strings used // Should return a string from the resource table for strings used
// by the calculation engine. The strings that must be defined // by the calculation engine. The strings that must be defined

View file

@ -104,7 +104,6 @@ COpndCommand::COpndCommand(shared_ptr<vector<int>> const& commands, bool fNegati
, m_fSciFmt(fSciFmt) , m_fSciFmt(fSciFmt)
, m_fDecimal(fDecimal) , m_fDecimal(fDecimal)
, m_fInitialized(false) , m_fInitialized(false)
, m_value{}
{ {
} }
@ -143,7 +142,7 @@ void COpndCommand::AppendCommand(int command)
void COpndCommand::ToggleSign() void COpndCommand::ToggleSign()
{ {
for (int nOpCode : *m_commands) for (const int nOpCode : *m_commands)
{ {
if (nOpCode != IDC_0) if (nOpCode != IDC_0)
{ {
@ -169,9 +168,7 @@ void COpndCommand::RemoveFromEnd()
} }
else else
{ {
int nOpCode = m_commands->at(nCommands - 1); if (m_commands->at(nCommands - 1) == IDC_PNT)
if (nOpCode == IDC_PNT)
{ {
m_fDecimal = false; m_fDecimal = false;
} }
@ -212,14 +209,14 @@ void COpndCommand::ClearAllAndAppendCommand(CalculationManager::Command command)
const wstring& COpndCommand::GetToken(wchar_t decimalSymbol) const wstring& COpndCommand::GetToken(wchar_t decimalSymbol)
{ {
static const wchar_t chZero = L'0'; static constexpr wchar_t chZero = L'0';
const size_t nCommands = m_commands->size(); const size_t nCommands = m_commands->size();
m_token.clear(); m_token.clear();
for (size_t i = 0; i < nCommands; i++) for (size_t i = 0; i < nCommands; i++)
{ {
int nOpCode = (*m_commands)[i]; auto nOpCode = (*m_commands)[i];
if (nOpCode == IDC_PNT) if (nOpCode == IDC_PNT)
{ {
@ -228,8 +225,7 @@ const wstring& COpndCommand::GetToken(wchar_t decimalSymbol)
else if (nOpCode == IDC_EXP) else if (nOpCode == IDC_EXP)
{ {
m_token += chExp; m_token += chExp;
int nextOpCode = m_commands->at(i + 1); if (m_commands->at(i + 1) != IDC_SIGN)
if (nextOpCode != IDC_SIGN)
{ {
m_token += chPlus; m_token += chPlus;
} }
@ -240,8 +236,7 @@ const wstring& COpndCommand::GetToken(wchar_t decimalSymbol)
} }
else else
{ {
wstring num = to_wstring(nOpCode - IDC_0); m_token.append(to_wstring(nOpCode - IDC_0));
m_token.append(num);
} }
} }
@ -273,7 +268,7 @@ const wstring& COpndCommand::GetToken(wchar_t decimalSymbol)
return m_token; return m_token;
} }
wstring COpndCommand::GetString(uint32_t radix, int32_t precision) wstring COpndCommand::GetString(uint32_t radix, int32_t precision) const
{ {
if (m_fInitialized) if (m_fInitialized)
{ {

View file

@ -63,7 +63,7 @@ public:
const std::wstring& GetToken(wchar_t decimalSymbol) override; const std::wstring& GetToken(wchar_t decimalSymbol) override;
CalculationManager::CommandType GetCommandType() const override; CalculationManager::CommandType GetCommandType() const override;
void Accept(_In_ ISerializeCommandVisitor& commandVisitor) override; void Accept(_In_ ISerializeCommandVisitor& commandVisitor) override;
std::wstring GetString(uint32_t radix, int32_t precision); std::wstring GetString(uint32_t radix, int32_t precision) const;
private: private:
std::shared_ptr<std::vector<int>> m_commands; std::shared_ptr<std::vector<int>> m_commands;

View file

@ -33,7 +33,7 @@ public:
class IBinaryCommand : public IOperatorCommand class IBinaryCommand : public IOperatorCommand
{ {
public: public:
virtual void SetCommand(int command) override = 0; void SetCommand(int command) override = 0;
virtual int GetCommand() const = 0; virtual int GetCommand() const = 0;
}; };

View file

@ -56,14 +56,14 @@ public:
CCalcEngine( CCalcEngine(
bool fPrecedence, bool fPrecedence,
bool fIntegerMode, bool fIntegerMode,
CalculationManager::IResourceProvider* const pResourceProvider, CalculationManager::IResourceProvider* pResourceProvider,
__in_opt ICalcDisplay* pCalcDisplay, __in_opt ICalcDisplay* pCalcDisplay,
__in_opt std::shared_ptr<IHistoryDisplay> pHistoryDisplay); __in_opt std::shared_ptr<IHistoryDisplay> pHistoryDisplay);
void ProcessCommand(OpCode wID); void ProcessCommand(OpCode wID);
void DisplayError(uint32_t nError); void DisplayError(uint32_t nError);
std::unique_ptr<CalcEngine::Rational> PersistedMemObject(); std::unique_ptr<CalcEngine::Rational> PersistedMemObject();
void PersistedMemObject(CalcEngine::Rational const& memObject); void PersistedMemObject(CalcEngine::Rational const& memObject);
bool FInErrorState() bool FInErrorState() const
{ {
return m_bError; return m_bError;
} }
@ -71,21 +71,21 @@ public:
{ {
return m_input.IsEmpty() && (m_numberString.empty() || m_numberString == L"0"); return m_input.IsEmpty() && (m_numberString.empty() || m_numberString == L"0");
} }
bool FInRecordingState() bool FInRecordingState() const
{ {
return m_bRecord; return m_bRecord;
} }
void SettingsChanged(); void SettingsChanged();
bool IsCurrentTooBigForTrig(); bool IsCurrentTooBigForTrig() const;
uint32_t GetCurrentRadix(); uint32_t GetCurrentRadix() const;
std::wstring GetCurrentResultForRadix(uint32_t radix, int32_t precision, bool groupDigitsPerRadix); std::wstring GetCurrentResultForRadix(uint32_t radix, int32_t precision, bool groupDigitsPerRadix);
void ChangePrecision(int32_t precision) void ChangePrecision(int32_t precision)
{ {
m_precision = precision; m_precision = precision;
ChangeConstants(m_radix, precision); ChangeConstants(m_radix, precision);
} }
std::wstring GroupDigitsPerRadix(std::wstring_view numberString, uint32_t radix); std::wstring GroupDigitsPerRadix(std::wstring_view numberString, uint32_t radix) const;
std::wstring GetStringForDisplay(CalcEngine::Rational const& rat, uint32_t radix); std::wstring GetStringForDisplay(CalcEngine::Rational const& rat, uint32_t radix) const;
void UpdateMaxIntDigits(); void UpdateMaxIntDigits();
wchar_t DecimalSeparator() const; wchar_t DecimalSeparator() const;
@ -149,38 +149,38 @@ private:
int m_nLastCom; // Last command entered. int m_nLastCom; // Last command entered.
AngleType m_angletype; // Current Angle type when in dec mode. one of deg, rad or grad AngleType m_angletype; // Current Angle type when in dec mode. one of deg, rad or grad
NUM_WIDTH m_numwidth; // one of qword, dword, word or byte mode. NUM_WIDTH m_numwidth; // one of qword, dword, word or byte mode.
int32_t m_dwWordBitWidth; // # of bits in currently selected word size uint32_t m_dwWordBitWidth; // # of bits in currently selected word size
std::unique_ptr<std::mt19937> m_randomGeneratorEngine; std::unique_ptr<std::mt19937> m_randomGeneratorEngine;
std::unique_ptr<std::uniform_real_distribution<>> m_distr; std::unique_ptr<std::uniform_real_distribution<>> m_distr;
uint64_t m_carryBit; uint64_t m_carryBit{};
CHistoryCollector m_HistoryCollector; // Accumulator of each line of history as various commands are processed CHistoryCollector m_HistoryCollector; // Accumulator of each line of history as various commands are processed
std::array<CalcEngine::Rational, NUM_WIDTH_LENGTH> m_chopNumbers; // word size enforcement std::array<CalcEngine::Rational, NUM_WIDTH_LENGTH> m_chopNumbers; // word size enforcement
std::array<std::wstring, NUM_WIDTH_LENGTH> m_maxDecimalValueStrings; // maximum values represented by a given word width based off m_chopNumbers std::array<std::wstring, NUM_WIDTH_LENGTH> m_maxDecimalValueStrings; // maximum values represented by a given word width based off m_chopNumbers
static std::unordered_map<std::wstring_view, std::wstring> s_engineStrings; // the string table shared across all instances static std::unordered_map<std::wstring_view, std::wstring> s_engineStrings; // the string table shared across all instances
wchar_t m_decimalSeparator; wchar_t m_decimalSeparator{};
wchar_t m_groupSeparator; wchar_t m_groupSeparator;
private: private:
void ProcessCommandWorker(OpCode wParam); void ProcessCommandWorker(OpCode wParam);
void ResolveHighestPrecedenceOperation(); void ResolveHighestPrecedenceOperation();
void HandleErrorCommand(OpCode idc); void HandleErrorCommand(OpCode idc);
void HandleMaxDigitsReached(); void HandleMaxDigitsReached() const;
void DisplayNum(void); void DisplayNum();
int IsNumberInvalid(const std::wstring& numberString, int iMaxExp, int iMaxMantissa, uint32_t radix) const; int IsNumberInvalid(const std::wstring& numberString, int iMaxExp, int iMaxMantissa, uint32_t radix) const;
void DisplayAnnounceBinaryOperator(); void DisplayAnnounceBinaryOperator() const;
void SetPrimaryDisplay(const std::wstring& szText, bool isError = false); void SetPrimaryDisplay(const std::wstring& szText, bool isError = false) const;
void ClearTemporaryValues(); void ClearTemporaryValues();
void ClearDisplay(); void ClearDisplay() const;
CalcEngine::Rational TruncateNumForIntMath(CalcEngine::Rational const& rat); CalcEngine::Rational TruncateNumForIntMath(CalcEngine::Rational const& rat) const;
CalcEngine::Rational SciCalcFunctions(CalcEngine::Rational const& rat, uint32_t op); CalcEngine::Rational SciCalcFunctions(CalcEngine::Rational const& rat, uint32_t op);
CalcEngine::Rational DoOperation(int operation, CalcEngine::Rational const& lhs, CalcEngine::Rational const& rhs); CalcEngine::Rational DoOperation(int operation, CalcEngine::Rational const& lhs, CalcEngine::Rational const& rhs);
void SetRadixTypeAndNumWidth(RadixType radixtype, NUM_WIDTH numwidth); void SetRadixTypeAndNumWidth(RadixType radixtype, NUM_WIDTH numwidth);
int32_t DwWordBitWidthFromeNumWidth(NUM_WIDTH numwidth); static uint32_t DwWordBitWidthFromNumWidth(NUM_WIDTH numwidth);
uint32_t NRadixFromRadixType(RadixType radixtype); static uint32_t NRadixFromRadixType(RadixType radixtype);
double GenerateRandomNumber(); double GenerateRandomNumber();
bool TryToggleBit(CalcEngine::Rational& rat, uint32_t wbitno); bool TryToggleBit(CalcEngine::Rational& rat, uint32_t wbitno);
@ -197,7 +197,7 @@ private:
} }
static std::vector<uint32_t> DigitGroupingStringToGroupingVector(std::wstring_view groupingString); static std::vector<uint32_t> DigitGroupingStringToGroupingVector(std::wstring_view groupingString);
std::wstring GroupDigits(std::wstring_view delimiter, std::vector<uint32_t> const& grouping, std::wstring_view displayString, bool isNumNegative = false); std::wstring GroupDigits(std::wstring_view delimiter, std::vector<uint32_t> const& grouping, std::wstring_view displayString, bool isNumNegative = false) const;
static int QuickLog2(int iNum); static int QuickLog2(int iNum);
static void ChangeBaseConstants(uint32_t radix, int maxIntDigits, int32_t precision); static void ChangeBaseConstants(uint32_t radix, int maxIntDigits, int32_t precision);

View file

@ -14,18 +14,17 @@ namespace CalcEngine
{ {
public: public:
CalcNumSec() CalcNumSec()
: value() : m_isNegative(false)
, m_isNegative(false)
{ {
} }
void Clear(); void Clear();
bool IsEmpty() bool IsEmpty() const
{ {
return value.empty(); return value.empty();
} }
bool IsNegative() bool IsNegative() const
{ {
return m_isNegative; return m_isNegative;
} }
@ -53,22 +52,20 @@ namespace CalcEngine
, m_hasDecimal(false) , m_hasDecimal(false)
, m_decPtIndex(0) , m_decPtIndex(0)
, m_decSymbol(decSymbol) , m_decSymbol(decSymbol)
, m_base()
, m_exponent()
{ {
} }
void Clear(); void Clear();
bool TryToggleSign(bool isIntegerMode, std::wstring_view maxNumStr); bool TryToggleSign(bool isIntegerMode, std::wstring_view maxNumStr);
bool TryAddDigit(unsigned int value, uint32_t radix, bool isIntegerMode, std::wstring_view maxNumStr, int32_t wordBitWidth, int maxDigits); bool TryAddDigit(unsigned int value, uint32_t radix, bool isIntegerMode, std::wstring_view maxNumStr, uint32_t wordBitWidth, int maxDigits);
bool TryAddDecimalPt(); bool TryAddDecimalPt();
bool HasDecimalPt(); bool HasDecimalPt() const;
bool TryBeginExponent(); bool TryBeginExponent();
void Backspace(); void Backspace();
void SetDecimalSymbol(wchar_t decSymbol); void SetDecimalSymbol(wchar_t decSymbol);
bool IsEmpty(); bool IsEmpty() const;
std::wstring ToString(uint32_t radix); std::wstring ToString(uint32_t radix) const;
Rational ToRational(uint32_t radix, int32_t precision); Rational ToRational(uint32_t radix, int32_t precision) const;
private: private:
bool m_hasExponent; bool m_hasExponent;

View file

@ -21,15 +21,15 @@ public:
~CHistoryCollector(); ~CHistoryCollector();
void AddOpndToHistory(std::wstring_view numStr, CalcEngine::Rational const& rat, bool fRepetition = false); void AddOpndToHistory(std::wstring_view numStr, CalcEngine::Rational const& rat, bool fRepetition = false);
void RemoveLastOpndFromHistory(); void RemoveLastOpndFromHistory();
void AddBinOpToHistory(int nOpCode, bool isIntgerMode, bool fNoRepetition = true); void AddBinOpToHistory(int nOpCode, bool isIntegerMode, bool fNoRepetition = true);
void ChangeLastBinOp(int nOpCode, bool fPrecInvToHigher, bool isIntgerMode); void ChangeLastBinOp(int nOpCode, bool fPrecInvToHigher, bool isIntegerMode);
void AddUnaryOpToHistory(int nOpCode, bool fInv, AngleType angletype); void AddUnaryOpToHistory(int nOpCode, bool fInv, AngleType angletype);
void AddOpenBraceToHistory(); void AddOpenBraceToHistory();
void AddCloseBraceToHistory(); void AddCloseBraceToHistory();
void PushLastOpndStart(int ichOpndStart = -1); void PushLastOpndStart(int ichOpndStart = -1);
void PopLastOpndStart(); void PopLastOpndStart();
void EnclosePrecInversionBrackets(); void EnclosePrecInversionBrackets();
bool FOpndAddedToHistory(); bool FOpndAddedToHistory() const;
void CompleteHistoryLine(std::wstring_view numStr); void CompleteHistoryLine(std::wstring_view numStr);
void CompleteEquation(std::wstring_view numStr); void CompleteEquation(std::wstring_view numStr);
void ClearHistoryLine(std::wstring_view errStr); void ClearHistoryLine(std::wstring_view errStr);
@ -44,12 +44,12 @@ private:
int m_iCurLineHistStart; // index of the beginning of the current equation int m_iCurLineHistStart; // index of the beginning of the current equation
// a sort of state, set to the index before 2 after 2 in the expression 2 + 3 say. Useful for auto correct portion of history and for // a sort of state, set to the index before 2 after 2 in the expression 2 + 3 say. Useful for auto correct portion of history and for
// attaching the unary op around the last operand // attaching the unary op around the last operand
int m_lastOpStartIndex; // index of the beginning of the last operand added to the history int m_lastOpStartIndex{}; // index of the beginning of the last operand added to the history
int m_lastBinOpStartIndex; // index of the beginning of the last binary operator added to the history int m_lastBinOpStartIndex{}; // index of the beginning of the last binary operator added to the history
std::array<int, MAXPRECDEPTH> std::array<int, MAXPRECDEPTH>
m_operandIndices; // Stack of index of opnd's beginning for each '('. A parallel array to m_hnoParNum, but abstracted independently of that m_operandIndices{}; // Stack of index of opnd's beginning for each '('. A parallel array to m_hnoParNum, but abstracted independently of that
int m_curOperandIndex; // Stack index for the above stack int m_curOperandIndex{}; // Stack index for the above stack
bool m_bLastOpndBrace; // iff the last opnd in history is already braced so we can avoid putting another one for unary operator bool m_bLastOpndBrace{}; // iff the last opnd in history is already braced so we can avoid putting another one for unary operator
wchar_t m_decimalSymbol; wchar_t m_decimalSymbol;
std::shared_ptr<std::vector<std::pair<std::wstring, int>>> m_spTokens; std::shared_ptr<std::vector<std::pair<std::wstring, int>>> m_spTokens;
std::shared_ptr<std::vector<std::shared_ptr<IExpressionCommand>>> m_spCommands; std::shared_ptr<std::vector<std::shared_ptr<IExpressionCommand>>> m_spCommands;
@ -57,8 +57,8 @@ private:
private: private:
void ReinitHistory(); void ReinitHistory();
int IchAddSzToEquationSz(std::wstring_view str, int icommandIndex); int IchAddSzToEquationSz(std::wstring_view str, int icommandIndex);
void TruncateEquationSzFromIch(int ich); void TruncateEquationSzFromIch(int ich) const;
void SetExpressionDisplay(); void SetExpressionDisplay() const;
void InsertSzInEquationSz(std::wstring_view str, int icommandIndex, int ich); void InsertSzInEquationSz(std::wstring_view str, int icommandIndex, int ich) const;
std::shared_ptr<std::vector<int>> GetOperandCommandsFromString(std::wstring_view numStr); std::shared_ptr<std::vector<int>> GetOperandCommandsFromString(std::wstring_view numStr) const;
}; };

View file

@ -9,7 +9,7 @@
class IHistoryDisplay class IHistoryDisplay
{ {
public: public:
virtual ~IHistoryDisplay(){}; virtual ~IHistoryDisplay() = default;
virtual unsigned int AddToHistory( virtual unsigned int AddToHistory(
_In_ std::shared_ptr<std::vector<std::pair<std::wstring, int>>> const& tokens, _In_ std::shared_ptr<std::vector<std::pair<std::wstring, int>>> const& tokens,
_In_ std::shared_ptr<std::vector<std::shared_ptr<IExpressionCommand>>> const& commands, _In_ std::shared_ptr<std::vector<std::shared_ptr<IExpressionCommand>>> const& commands,

View file

@ -19,7 +19,7 @@ namespace CalcEngine
public: public:
Rational() noexcept; Rational() noexcept;
Rational(Number const& n) noexcept; Rational(Number const& n) noexcept;
Rational(Number const& p, Number const& q) noexcept; Rational(Number p, Number q) noexcept;
Rational(int32_t i); Rational(int32_t i);
Rational(uint32_t ui); Rational(uint32_t ui);
Rational(uint64_t ui); Rational(uint64_t ui);

View file

@ -8,22 +8,22 @@ namespace UnitConversionManager::NumberFormattingUtils
/// <summary> /// <summary>
/// Trims out any trailing zeros or decimals in the given input string /// Trims out any trailing zeros or decimals in the given input string
/// </summary> /// </summary>
/// <param name="number">number to trim</param> /// <param name="input">input to trim</param>
void TrimTrailingZeros(_Inout_ wstring& number) void TrimTrailingZeros(_Inout_ wstring& input)
{ {
if (number.find(L'.') == wstring::npos) if (input.find(L'.') == wstring::npos)
{ {
return; return;
} }
if (auto i = number.find_last_not_of(L'0'); i != wstring::npos) if (const auto i = input.find_last_not_of(L'0'); i != wstring::npos)
{ {
number.erase(number.cbegin() + i + 1, number.cend()); input.erase(input.cbegin() + i + 1, input.cend());
} }
if (number.back() == L'.') if (input.back() == L'.')
{ {
number.pop_back(); input.pop_back();
} }
} }
@ -56,14 +56,14 @@ namespace UnitConversionManager::NumberFormattingUtils
/// <summary> /// <summary>
/// Rounds the given double to the given number of significant digits /// Rounds the given double to the given number of significant digits
/// </summary> /// </summary>
/// <param name="num">input double</param> /// <param name="value">input double</param>
/// <param name="numSignificant">unsigned int number of significant digits to round to</param> /// <param name="numSignificant">unsigned int number of significant digits to round to</param>
wstring RoundSignificantDigits(double num, unsigned int numSignificant) wstring RoundSignificantDigits(double value, unsigned int numSignificant)
{ {
wstringstream out(wstringstream::out); wstringstream out(wstringstream::out);
out << fixed; out << fixed;
out.precision(numSignificant); out.precision(numSignificant);
out << num; out << value;
return out.str(); return out.str();
} }

View file

@ -36,7 +36,7 @@
// This format is based loosely on an OLE HRESULT and is compatible with the // This format is based loosely on an OLE HRESULT and is compatible with the
// SUCCEEDED and FAILED macros as well as the HRESULT_CODE macro // SUCCEEDED and FAILED macros as well as the HRESULT_CODE macro
typedef int32_t ResultCode; using ResultCode = int32_t;
// CALC_E_DIVIDEBYZERO // CALC_E_DIVIDEBYZERO
// //

View file

@ -117,7 +117,7 @@ void _mulnumx(PNUMBER* pa, PNUMBER b)
for (ibdigit = b->cdigit; ibdigit > 0; ibdigit--) for (ibdigit = b->cdigit; ibdigit > 0; ibdigit--)
{ {
cy = 0; cy = 0;
mcy = (uint64_t)da * (*ptrb); mcy = static_cast<uint64_t>(da) * *ptrb;
if (mcy) if (mcy)
{ {
icdigit = 0; icdigit = 0;
@ -131,10 +131,10 @@ void _mulnumx(PNUMBER* pa, PNUMBER b)
while (mcy || cy) while (mcy || cy)
{ {
// update carry from addition(s) and multiply. // update carry from addition(s) and multiply.
cy += (TWO_MANTTYPE)ptrc[icdigit] + ((uint32_t)mcy & ((uint32_t)~BASEX)); cy += static_cast<TWO_MANTTYPE>(ptrc[icdigit]) + (static_cast<uint32_t>(mcy) & ~BASEX);
// update result digit from // update result digit from
ptrc[icdigit++] = (MANTTYPE)((uint32_t)cy & ((uint32_t)~BASEX)); ptrc[icdigit++] = static_cast<uint32_t>(cy) & ~BASEX;
// update carries from // update carries from
mcy >>= BASEXPWR; mcy >>= BASEXPWR;
@ -286,7 +286,7 @@ void _divnumx(PNUMBER* pa, PNUMBER b, int32_t precision)
// Create c (the divide answer) and set up exponent and sign. // Create c (the divide answer) and set up exponent and sign.
createnum(c, thismax + 1); createnum(c, thismax + 1);
c->exp = (a->cdigit + a->exp) - (b->cdigit + b->exp) + 1; c->exp = a->cdigit + a->exp - (b->cdigit + b->exp) + 1;
c->sign = a->sign * b->sign; c->sign = a->sign * b->sign;
ptrc = c->mant + thismax; ptrc = c->mant + thismax;
@ -298,7 +298,7 @@ void _divnumx(PNUMBER* pa, PNUMBER b, int32_t precision)
while (cdigits++ < thismax && !zernum(rem)) while (cdigits++ < thismax && !zernum(rem))
{ {
int32_t digit = 0; uint32_t digit = 0;
*ptrc = 0; *ptrc = 0;
while (!lessnum(rem, b)) while (!lessnum(rem, b))
{ {
@ -334,7 +334,7 @@ void _divnumx(PNUMBER* pa, PNUMBER b, int32_t precision)
cdigits--; cdigits--;
if (c->mant != ++ptrc) if (c->mant != ++ptrc)
{ {
memmove(c->mant, ptrc, (int)(cdigits * sizeof(MANTTYPE))); memmove(c->mant, ptrc, cdigits * sizeof(MANTTYPE));
} }
if (!cdigits) if (!cdigits)

View file

@ -19,7 +19,6 @@
#include <algorithm> #include <algorithm>
#include "winerror_cross_platform.h" #include "winerror_cross_platform.h"
#include <sstream>
#include <cstring> // for memmove, memcpy #include <cstring> // for memmove, memcpy
#include "ratpak.h" #include "ratpak.h"
@ -69,9 +68,9 @@ namespace
int32_t hr = CALC_INTSAFE_E_ARITHMETIC_OVERFLOW; int32_t hr = CALC_INTSAFE_E_ARITHMETIC_OVERFLOW;
*pulResult = CALC_ULONG_ERROR; *pulResult = CALC_ULONG_ERROR;
if ((ulAugend + ulAddend) >= ulAugend) if (ulAugend + ulAddend >= ulAugend)
{ {
*pulResult = (ulAugend + ulAddend); *pulResult = ulAugend + ulAddend;
hr = S_OK; hr = S_OK;
} }
@ -85,7 +84,7 @@ namespace
if (ullOperand <= UINT32_MAX) if (ullOperand <= UINT32_MAX)
{ {
*pulResult = (uint32_t)ullOperand; *pulResult = static_cast<uint32_t>(ullOperand);
hr = S_OK; hr = S_OK;
} }
@ -130,7 +129,7 @@ void* zmalloc(size_t a)
void _dupnum(_In_ PNUMBER dest, _In_ const NUMBER* const src) void _dupnum(_In_ PNUMBER dest, _In_ const NUMBER* const src)
{ {
memcpy(dest, src, (int)(sizeof(NUMBER) + ((src)->cdigit) * (sizeof(MANTTYPE)))); memcpy(dest, src, sizeof(NUMBER) + src->cdigit * sizeof(MANTTYPE));
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -148,10 +147,12 @@ void _dupnum(_In_ PNUMBER dest, _In_ const NUMBER* const src)
void _destroynum(_Frees_ptr_opt_ PNUMBER pnum) void _destroynum(_Frees_ptr_opt_ PNUMBER pnum)
{ {
if (pnum != nullptr) if (pnum == nullptr)
{ {
free(pnum); return;
} }
free(pnum);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -170,12 +171,13 @@ void _destroynum(_Frees_ptr_opt_ PNUMBER pnum)
void _destroyrat(_Frees_ptr_opt_ PRAT prat) void _destroyrat(_Frees_ptr_opt_ PRAT prat)
{ {
if (prat != nullptr) if (prat == nullptr)
{ {
destroynum(prat->pp); return;
destroynum(prat->pq);
free(prat);
} }
destroynum(prat->pp);
destroynum(prat->pq);
free(prat);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -200,17 +202,17 @@ PNUMBER _createnum(_In_ uint32_t size)
if (SUCCEEDED(Calc_ULongAdd(size, 1, &cbAlloc)) && SUCCEEDED(Calc_ULongMult(cbAlloc, sizeof(MANTTYPE), &cbAlloc)) if (SUCCEEDED(Calc_ULongAdd(size, 1, &cbAlloc)) && SUCCEEDED(Calc_ULongMult(cbAlloc, sizeof(MANTTYPE), &cbAlloc))
&& SUCCEEDED(Calc_ULongAdd(cbAlloc, sizeof(NUMBER), &cbAlloc))) && SUCCEEDED(Calc_ULongAdd(cbAlloc, sizeof(NUMBER), &cbAlloc)))
{ {
pnumret = (PNUMBER)zmalloc(cbAlloc); pnumret = static_cast<PNUMBER>(zmalloc(cbAlloc));
if (pnumret == nullptr) if (pnumret == nullptr)
{ {
throw(CALC_E_OUTOFMEMORY); throw CALC_E_OUTOFMEMORY;
} }
} }
else else
{ {
throw(CALC_E_INVALIDRANGE); throw CALC_E_INVALIDRANGE;
} }
return (pnumret); return pnumret;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -227,20 +229,20 @@ PNUMBER _createnum(_In_ uint32_t size)
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
PRAT _createrat(void) PRAT _createrat()
{ {
PRAT prat = nullptr; PRAT prat = nullptr;
prat = (PRAT)zmalloc(sizeof(RAT)); prat = static_cast<PRAT>(zmalloc(sizeof(RAT)));
if (prat == nullptr) if (prat == nullptr)
{ {
throw(CALC_E_OUTOFMEMORY); throw CALC_E_OUTOFMEMORY;
} }
prat->pp = nullptr; prat->pp = nullptr;
prat->pq = nullptr; prat->pq = nullptr;
return (prat); return prat;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -283,7 +285,7 @@ PRAT numtorat(_In_ PNUMBER pin, uint32_t radix)
destroynum(pnRadixn); destroynum(pnRadixn);
destroynum(qnRadixn); destroynum(qnRadixn);
return (pout); return pout;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -303,26 +305,26 @@ PRAT numtorat(_In_ PNUMBER pin, uint32_t radix)
PNUMBER nRadixxtonum(_In_ PNUMBER a, uint32_t radix, int32_t precision) PNUMBER nRadixxtonum(_In_ PNUMBER a, uint32_t radix, int32_t precision)
{ {
PNUMBER sum = i32tonum(0, radix); PNUMBER sum = Ui32tonum(0, radix);
PNUMBER powofnRadix = i32tonum(BASEX, radix); PNUMBER powofnRadix = Ui32tonum(BASEX, radix);
// A large penalty is paid for conversion of digits no one will see anyway. // A large penalty is paid for conversion of digits no one will see anyway.
// limit the digits to the minimum of the existing precision or the // limit the digits to the minimum of the existing precision or the
// requested precision. // requested precision.
uint32_t cdigits = precision + 1; int32_t cdigits = precision + 1;
if (cdigits > (uint32_t)a->cdigit) if (cdigits > a->cdigit)
{ {
cdigits = (uint32_t)a->cdigit; cdigits = a->cdigit;
} }
// scale by the internal base to the internal exponent offset of the LSD // scale by the internal base to the internal exponent offset of the LSD
numpowi32(&powofnRadix, a->exp + (a->cdigit - cdigits), radix, precision); numpowi32(&powofnRadix, a->exp + (a->cdigit - cdigits), radix, precision);
// Loop over all the relative digits from MSD to LSD // Loop over all the relative digits from MSD to LSD
for (MANTTYPE* ptr = &(a->mant[a->cdigit - 1]); cdigits > 0; ptr--, cdigits--) for (MANTTYPE* ptr = &a->mant[a->cdigit - 1]; cdigits > 0; ptr--, cdigits--)
{ {
// Loop over all the bits from MSB to LSB // Loop over all the bits from MSB to LSB
for (uint32_t bitmask = BASEX / 2; bitmask > 0; bitmask /= 2) for (auto bitmask = BASEX >> 1; bitmask > 0; bitmask >>= 1)
{ {
addnum(&sum, sum, radix); addnum(&sum, sum, radix);
if (*ptr & bitmask) if (*ptr & bitmask)
@ -337,7 +339,7 @@ PNUMBER nRadixxtonum(_In_ PNUMBER a, uint32_t radix, int32_t precision)
destroynum(powofnRadix); destroynum(powofnRadix);
sum->sign = a->sign; sum->sign = a->sign;
return (sum); return sum;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -356,21 +358,21 @@ PNUMBER nRadixxtonum(_In_ PNUMBER a, uint32_t radix, int32_t precision)
PNUMBER numtonRadixx(_In_ PNUMBER a, uint32_t radix) PNUMBER numtonRadixx(_In_ PNUMBER a, uint32_t radix)
{ {
PNUMBER pnumret = i32tonum(0, BASEX); // pnumret is the number in internal form. PNUMBER pnumret = Ui32tonum(0, BASEX); // pnumret is the number in internal form.
PNUMBER num_radix = i32tonum(radix, BASEX); PNUMBER num_radix = Ui32tonum(radix, BASEX);
MANTTYPE* ptrdigit = a->mant; // pointer to digit being worked on. MANTTYPE* ptrdigit = a->mant; // pointer to digit being worked on.
// Digits are in reverse order, back over them LSD first. // Digits are in reverse order, back over them LSD first.
ptrdigit += a->cdigit - 1; ptrdigit += a->cdigit - 1;
PNUMBER thisdigit = nullptr; // thisdigit holds the current digit of a PNUMBER thisdigit; // thisdigit holds the current digit of a
for (int32_t idigit = 0; idigit < a->cdigit; idigit++) for (int32_t idigit = 0; idigit < a->cdigit; idigit++)
{ {
mulnumx(&pnumret, num_radix); mulnumx(&pnumret, num_radix);
// WARNING: // WARNING:
// This should just smack in each digit into a 'special' thisdigit. // This should just smack in each digit into a 'special' thisdigit.
// and not do the overhead of recreating the number type each time. // and not do the overhead of recreating the number type each time.
thisdigit = i32tonum(*ptrdigit--, BASEX); thisdigit = Ui32tonum(*ptrdigit--, BASEX);
addnum(&pnumret, thisdigit, BASEX); addnum(&pnumret, thisdigit, BASEX);
destroynum(thisdigit); destroynum(thisdigit);
} }
@ -386,7 +388,7 @@ PNUMBER numtonRadixx(_In_ PNUMBER a, uint32_t radix)
// And propagate the sign. // And propagate the sign.
pnumret->sign = a->sign; pnumret->sign = a->sign;
return (pnumret); return pnumret;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -611,12 +613,12 @@ wchar_t NormalizeCharDigit(wchar_t c, uint32_t radix)
PNUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precision) PNUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precision)
{ {
int32_t expSign = 1L; // expSign is exponent sign ( +/- 1 ) int32_t expSign = 1; // expSign is exponent sign ( +/- 1 )
int32_t expValue = 0L; // expValue is exponent mantissa, should be unsigned int32_t expValue = 0; // expValue is exponent mantissa, should be unsigned
PNUMBER pnumret = nullptr; PNUMBER pnumret = nullptr;
createnum(pnumret, static_cast<uint32_t>(numberString.length())); createnum(pnumret, static_cast<uint32_t>(numberString.length()));
pnumret->sign = 1L; pnumret->sign = 1;
pnumret->cdigit = 0; pnumret->cdigit = 0;
pnumret->exp = 0; pnumret->exp = 0;
MANTTYPE* pmant = pnumret->mant + numberString.length() - 1; MANTTYPE* pmant = pnumret->mant + numberString.length() - 1;
@ -625,7 +627,7 @@ PNUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precis
for (const auto& c : numberString) for (const auto& c : numberString)
{ {
// If the character is the decimal separator, use L'.' for the purposes of the state machine. // If the character is the decimal separator, use L'.' for the purposes of the state machine.
wchar_t curChar = (c == g_decimalSeparator ? L'.' : c); wchar_t curChar = c == g_decimalSeparator ? L'.' : c;
// Switch states based on the character we encountered // Switch states based on the character we encountered
switch (curChar) switch (curChar)
@ -658,11 +660,11 @@ PNUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precis
switch (state) switch (state)
{ {
case MANTS: case MANTS:
pnumret->sign = (curChar == L'-') ? -1 : 1; pnumret->sign = curChar == L'-' ? -1 : 1;
break; break;
case EXPSZ: case EXPSZ:
case EXPS: case EXPS:
expSign = (curChar == L'-') ? -1 : 1; expSign = curChar == L'-' ? -1 : 1;
break; break;
case EXPDZ: case EXPDZ:
case EXPD: case EXPD:
@ -758,11 +760,11 @@ PNUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precis
PRAT i32torat(int32_t ini32) PRAT i32torat(int32_t ini32)
{ {
PRAT pratret = nullptr; PRAT pratret;
createrat(pratret); createrat(pratret);
pratret->pp = i32tonum(ini32, BASEX); pratret->pp = i32tonum(ini32, BASEX);
pratret->pq = i32tonum(1L, BASEX); pratret->pq = i32tonum(1L, BASEX);
return (pratret); return pratret;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -782,11 +784,11 @@ PRAT i32torat(int32_t ini32)
PRAT Ui32torat(uint32_t inui32) PRAT Ui32torat(uint32_t inui32)
{ {
PRAT pratret = nullptr; PRAT pratret;
createrat(pratret); createrat(pratret);
pratret->pp = Ui32tonum(inui32, BASEX); pratret->pp = Ui32tonum(inui32, BASEX);
pratret->pq = i32tonum(1L, BASEX); pratret->pq = i32tonum(1L, BASEX);
return (pratret); return pratret;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -806,7 +808,7 @@ PNUMBER i32tonum(int32_t ini32, uint32_t radix)
{ {
MANTTYPE* pmant; MANTTYPE* pmant;
PNUMBER pnumret = nullptr; PNUMBER pnumret;
createnum(pnumret, MAX_LONG_SIZE); createnum(pnumret, MAX_LONG_SIZE);
pmant = pnumret->mant; pmant = pnumret->mant;
@ -824,12 +826,12 @@ PNUMBER i32tonum(int32_t ini32, uint32_t radix)
do do
{ {
*pmant++ = (MANTTYPE)(ini32 % radix); *pmant++ = static_cast<MANTTYPE>(ini32 % radix);
ini32 /= radix; ini32 /= radix;
pnumret->cdigit++; pnumret->cdigit++;
} while (ini32); } while (ini32);
return (pnumret); return pnumret;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -849,7 +851,7 @@ PNUMBER i32tonum(int32_t ini32, uint32_t radix)
PNUMBER Ui32tonum(uint32_t ini32, uint32_t radix) PNUMBER Ui32tonum(uint32_t ini32, uint32_t radix)
{ {
MANTTYPE* pmant; MANTTYPE* pmant;
PNUMBER pnumret = nullptr; PNUMBER pnumret;
createnum(pnumret, MAX_LONG_SIZE); createnum(pnumret, MAX_LONG_SIZE);
pmant = pnumret->mant; pmant = pnumret->mant;
@ -859,12 +861,12 @@ PNUMBER Ui32tonum(uint32_t ini32, uint32_t radix)
do do
{ {
*pmant++ = (MANTTYPE)(ini32 % radix); *pmant++ = static_cast<MANTTYPE>(ini32 % radix);
ini32 /= radix; ini32 /= radix;
pnumret->cdigit++; pnumret->cdigit++;
} while (ini32); } while (ini32);
return (pnumret); return pnumret;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -886,21 +888,21 @@ int32_t rattoi32(_In_ PRAT prat, uint32_t radix, int32_t precision)
if (rat_gt(prat, rat_max_i32, precision) || rat_lt(prat, rat_min_i32, precision)) if (rat_gt(prat, rat_max_i32, precision) || rat_lt(prat, rat_min_i32, precision))
{ {
// Don't attempt rattoi32 of anything too big or small // Don't attempt rattoi32 of anything too big or small
throw(CALC_E_DOMAIN); throw CALC_E_DOMAIN;
} }
PRAT pint = nullptr; PRAT pint = nullptr;
DUPRAT(pint, prat); DUPRAT(pint, prat);
intrat(&pint, radix, precision); intrat(&pint, radix, precision);
divnumx(&(pint->pp), pint->pq, precision); divnumx(&pint->pp, pint->pq, precision);
DUPNUM(pint->pq, num_one); DUPNUM(pint->pq, num_one);
int32_t lret = numtoi32(pint->pp, BASEX); int32_t lret = numtoi32(pint->pp, BASEX);
destroyrat(pint); destroyrat(pint);
return (lret); return lret;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -921,21 +923,21 @@ uint32_t rattoUi32(_In_ PRAT prat, uint32_t radix, int32_t precision)
if (rat_gt(prat, rat_dword, precision) || rat_lt(prat, rat_zero, precision)) if (rat_gt(prat, rat_dword, precision) || rat_lt(prat, rat_zero, precision))
{ {
// Don't attempt rattoui32 of anything too big or small // Don't attempt rattoui32 of anything too big or small
throw(CALC_E_DOMAIN); throw CALC_E_DOMAIN;
} }
PRAT pint = nullptr; PRAT pint = nullptr;
DUPRAT(pint, prat); DUPRAT(pint, prat);
intrat(&pint, radix, precision); intrat(&pint, radix, precision);
divnumx(&(pint->pp), pint->pq, precision); divnumx(&pint->pp, pint->pq, precision);
DUPNUM(pint->pq, num_one); DUPNUM(pint->pq, num_one);
uint32_t lret = numtoi32(pint->pp, BASEX); // This happens to work even if it is only signed uint32_t lret = numtoi32(pint->pp, BASEX); // This happens to work even if it is only signed
destroyrat(pint); destroyrat(pint);
return (lret); return lret;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -972,7 +974,7 @@ uint64_t rattoUi64(_In_ PRAT prat, uint32_t radix, int32_t precision)
destroyrat(prat32); destroyrat(prat32);
destroyrat(pint); destroyrat(pint);
return (((uint64_t)hi << 32) | lo); return (static_cast<uint64_t>(hi) << 32) | lo;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -992,17 +994,16 @@ int32_t numtoi32(_In_ PNUMBER pnum, uint32_t radix)
{ {
int32_t lret = 0; int32_t lret = 0;
MANTTYPE* pmant = pnum->mant; MANTTYPE* pmant = pnum->mant + pnum->cdigit - 1;
pmant += pnum->cdigit - 1;
int32_t expt = pnum->exp; auto expt = pnum->exp;
for (int32_t length = pnum->cdigit; length > 0 && length + expt > 0; length--) for (auto length = pnum->cdigit; length > 0 && length + expt > 0; length--)
{ {
lret *= radix; lret *= radix;
lret += *(pmant--); lret += *pmant--;
} }
while (expt-- > 0) for (; expt > 0; --expt)
{ {
lret *= radix; lret *= radix;
} }
@ -1025,37 +1026,34 @@ int32_t numtoi32(_In_ PNUMBER pnum, uint32_t radix)
bool stripzeroesnum(_Inout_ PNUMBER pnum, int32_t starting) bool stripzeroesnum(_Inout_ PNUMBER pnum, int32_t starting)
{ {
bool fstrip = false;
// point pmant to the LeastCalculatedDigit // point pmant to the LeastCalculatedDigit
MANTTYPE* pmant = pnum->mant; MANTTYPE* pmant = pnum->mant;
int32_t cdigits = pnum->cdigit; int32_t cdigits = pnum->cdigit;
// point pmant to the LSD // point pmant to the LSD
if (cdigits > starting) if (cdigits > starting)
{ {
pmant += cdigits - starting; pmant = pmant + cdigits - starting;
cdigits = starting; cdigits = starting;
} }
// Check we haven't gone too far, and we are still looking at zeros. // Check we haven't gone too far, and we are still looking at zeros.
while ((cdigits > 0) && !(*pmant)) if (cdigits < 1 || *pmant != 0)
return false;
do
{ {
// move to next significant digit and keep track of digits we can // move to next significant digit and keep track of digits we can
// ignore later. // ignore later.
pmant++; pmant++;
cdigits--; cdigits--;
fstrip = true; } while (cdigits > 0 && *pmant == 0);
}
// If there are zeros to remove. // Remove the zeros
if (fstrip) memmove(pnum->mant, pmant, cdigits * sizeof(MANTTYPE));
{ // And adjust exponent and digit count accordingly.
// Remove them. pnum->exp += pnum->cdigit - cdigits;
memmove(pnum->mant, pmant, (int)(cdigits * sizeof(MANTTYPE))); pnum->cdigit = cdigits;
// And adjust exponent and digit count accordingly. return true;
pnum->exp += (pnum->cdigit - cdigits);
pnum->cdigit = cdigits;
}
return (fstrip);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1096,10 +1094,10 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, NumberFormat format, uint32_t radi
// - if number is zero no rounding // - if number is zero no rounding
// - if number of digits is less than the maximum output no rounding // - if number of digits is less than the maximum output no rounding
PNUMBER round = nullptr; PNUMBER round = nullptr;
if (!zernum(pnum) && (pnum->cdigit >= precision || (length - exponent > precision && exponent >= -MAX_ZEROS_AFTER_DECIMAL))) if (!zernum(pnum) && (pnum->cdigit >= precision || length - exponent > precision && exponent >= -MAX_ZEROS_AFTER_DECIMAL))
{ {
// Otherwise round. // Otherwise round.
round = i32tonum(radix, radix); round = Ui32tonum(radix, radix);
divnum(&round, num_two, radix, precision); divnum(&round, num_two, radix, precision);
// Make round number exponent one below the LSD for the number. // Make round number exponent one below the LSD for the number.
@ -1119,7 +1117,7 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, NumberFormat format, uint32_t radi
if (format == NumberFormat::Float) if (format == NumberFormat::Float)
{ {
// Figure out if the exponent will fill more space than the non-exponent field. // Figure out if the exponent will fill more space than the non-exponent field.
if ((length - exponent > precision) || (exponent > precision + 3)) if (length - exponent > precision || exponent > precision + 3)
{ {
if (exponent >= -MAX_ZEROS_AFTER_DECIMAL) if (exponent >= -MAX_ZEROS_AFTER_DECIMAL)
{ {
@ -1144,7 +1142,7 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, NumberFormat format, uint32_t radi
if (round != nullptr) if (round != nullptr)
{ {
addnum(&pnum, round, radix); addnum(&pnum, round, radix);
int32_t offset = (pnum->cdigit + pnum->exp) - (round->cdigit + round->exp); int32_t offset = pnum->cdigit + pnum->exp - (round->cdigit + round->exp);
destroynum(round); destroynum(round);
if (stripzeroesnum(pnum, offset)) if (stripzeroesnum(pnum, offset))
{ {
@ -1164,14 +1162,14 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, NumberFormat format, uint32_t radi
MANTTYPE* pmant = pnum->mant + pnum->cdigit - 1; MANTTYPE* pmant = pnum->mant + pnum->cdigit - 1;
// Case where too many digits are to the left of the decimal or // Case where too many digits are to the left of the decimal or
// NumberFormat::Scientific or NumberFormat::Engineering was specified. // NumberFormat::Scientific or NumberFormat::Engineering was specified.
if ((format == NumberFormat::Scientific) || (format == NumberFormat::Engineering)) if (format == NumberFormat::Scientific || format == NumberFormat::Engineering)
{ {
useSciForm = true; useSciForm = true;
if (eout != 0) if (eout != 0)
{ {
if (format == NumberFormat::Engineering) if (format == NumberFormat::Engineering)
{ {
exponent = (eout % 3); exponent = eout % 3;
eout -= exponent; eout -= exponent;
exponent++; exponent++;
@ -1197,12 +1195,12 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, NumberFormat format, uint32_t radi
wstring result; wstring result;
// Make sure negative zeros aren't allowed. // Make sure negative zeros aren't allowed.
if ((pnum->sign == -1) && (length > 0)) if (pnum->sign == -1 && length > 0)
{ {
result = L'-'; result = L'-';
} }
if (exponent <= 0 && !useSciForm) if (exponent < 1 && !useSciForm)
{ {
result += L'0'; result += L'0';
result += g_decimalSeparator; result += g_decimalSeparator;
@ -1217,32 +1215,30 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, NumberFormat format, uint32_t radi
while (length > 0) while (length > 0)
{ {
exponent--;
result += DIGITS[*pmant--]; result += DIGITS[*pmant--];
length--; length--;
// Be more regular in using a decimal point. // Be more regular in using a decimal point.
if (exponent == 0) if (--exponent == 0)
{ {
result += g_decimalSeparator; result += g_decimalSeparator;
} }
} }
while (exponent > 0) if (exponent > 0)
{ {
result += L'0'; do
exponent--;
// Be more regular in using a decimal point.
if (exponent == 0)
{ {
result += g_decimalSeparator; result += L'0';
} } while (--exponent > 0);
// Be more regular in using a decimal point.
result += g_decimalSeparator;
} }
if (useSciForm) if (useSciForm)
{ {
result += (radix == 10 ? L'e' : L'^'); result += radix == 10 ? L'e' : L'^';
result += (eout < 0 ? L'-' : L'+'); result += eout < 0 ? L'-' : L'+';
eout = abs(eout); eout = abs(eout);
wstring expString{}; wstring expString{};
do do
@ -1283,7 +1279,7 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, NumberFormat format, uint32_t radi
// why a pointer to the rational is passed in. // why a pointer to the rational is passed in.
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
wstring RatToString(_Inout_ PRAT& prat, NumberFormat format, uint32_t radix, int32_t precision) wstring RatToString(_Inout_ const PRAT& prat, NumberFormat format, uint32_t radix, int32_t precision)
{ {
PNUMBER p = RatToNumber(prat, radix, precision); PNUMBER p = RatToNumber(prat, radix, precision);
@ -1415,7 +1411,7 @@ PNUMBER i32factnum(int32_t ini32, uint32_t radix)
mulnum(&lret, tmp, radix); mulnum(&lret, tmp, radix);
destroynum(tmp); destroynum(tmp);
} }
return (lret); return lret;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1439,17 +1435,18 @@ PNUMBER i32prodnum(int32_t start, int32_t stop, uint32_t radix)
lret = i32tonum(1, radix); lret = i32tonum(1, radix);
while (start <= stop) for (; start <= stop; start++)
{ {
if (start) if (!start)
{ {
tmp = i32tonum(start, radix); continue;
mulnum(&lret, tmp, radix);
destroynum(tmp);
} }
start++;
tmp = i32tonum(start, radix);
mulnum(&lret, tmp, radix);
destroynum(tmp);
} }
return (lret); return lret;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1470,7 +1467,7 @@ void numpowi32(_Inout_ PNUMBER* proot, int32_t power, uint32_t radix, int32_t pr
{ {
PNUMBER lret = i32tonum(1, radix); PNUMBER lret = i32tonum(1, radix);
while (power > 0) for (; power > 0; power >>= 1)
{ {
if (power & 1) if (power & 1)
{ {
@ -1478,7 +1475,6 @@ void numpowi32(_Inout_ PNUMBER* proot, int32_t power, uint32_t radix, int32_t pr
} }
mulnum(proot, *proot, radix); mulnum(proot, *proot, radix);
TRIMNUM(*proot, precision); TRIMNUM(*proot, precision);
power >>= 1;
} }
destroynum(*proot); destroynum(*proot);
*proot = lret; *proot = lret;
@ -1503,7 +1499,7 @@ void ratpowi32(_Inout_ PRAT* proot, int32_t power, int32_t precision)
if (power < 0) if (power < 0)
{ {
// Take the positive power and invert answer. // Take the positive power and invert answer.
PNUMBER pnumtemp = nullptr; PNUMBER pnumtemp;
ratpowi32(proot, -power, precision); ratpowi32(proot, -power, precision);
pnumtemp = (*proot)->pp; pnumtemp = (*proot)->pp;
(*proot)->pp = (*proot)->pq; (*proot)->pp = (*proot)->pq;
@ -1511,16 +1507,14 @@ void ratpowi32(_Inout_ PRAT* proot, int32_t power, int32_t precision)
} }
else else
{ {
PRAT lret = nullptr; PRAT lret = i32torat(1);
lret = i32torat(1);
while (power > 0) while (power > 0)
{ {
if (power & 1) if (power & 1)
{ {
mulnumx(&(lret->pp), (*proot)->pp); mulnumx(&lret->pp, (*proot)->pp);
mulnumx(&(lret->pq), (*proot)->pq); mulnumx(&lret->pq, (*proot)->pq);
} }
mulrat(proot, *proot, precision); mulrat(proot, *proot, precision);
trimit(&lret, precision); trimit(&lret, precision);

View file

@ -44,8 +44,8 @@ void _exprat(_Inout_ PRAT* px, int32_t precision)
{ {
CREATETAYLOR(); CREATETAYLOR();
addnum(&(pret->pp), num_one, BASEX); addnum(&pret->pp, num_one, BASEX);
addnum(&(pret->pq), num_one, BASEX); addnum(&pret->pq, num_one, BASEX);
DUPRAT(thisterm, pret); DUPRAT(thisterm, pret);
n2 = i32tonum(0L, BASEX); n2 = i32tonum(0L, BASEX);
@ -67,7 +67,7 @@ void exprat(_Inout_ PRAT* px, uint32_t radix, int32_t precision)
if (rat_gt(*px, rat_max_exp, precision) || rat_lt(*px, rat_min_exp, precision)) if (rat_gt(*px, rat_max_exp, precision) || rat_lt(*px, rat_min_exp, precision))
{ {
// Don't attempt exp of anything large. // Don't attempt exp of anything large.
throw(CALC_E_DOMAIN); throw CALC_E_DOMAIN;
} }
DUPRAT(pwr, rat_exp); DUPRAT(pwr, rat_exp);
@ -131,7 +131,7 @@ void _lograt(PRAT* px, int32_t precision)
// sub one from x // sub one from x
(*px)->pq->sign *= -1; (*px)->pq->sign *= -1;
addnum(&((*px)->pp), (*px)->pq, BASEX); addnum(&(*px)->pp, (*px)->pq, BASEX);
(*px)->pq->sign *= -1; (*px)->pq->sign *= -1;
DUPRAT(pret, *px); DUPRAT(pret, *px);
@ -158,7 +158,7 @@ void lograt(_Inout_ PRAT* px, int32_t precision)
// Check for someone taking the log of zero or a negative number. // Check for someone taking the log of zero or a negative number.
if (rat_le(*px, rat_zero, precision)) if (rat_le(*px, rat_zero, precision))
{ {
throw(CALC_E_DOMAIN); throw CALC_E_DOMAIN;
} }
// Get number > 1, for scaling // Get number > 1, for scaling
@ -409,7 +409,7 @@ void powratcomp(_Inout_ PRAT* px, _In_ PRAT y, uint32_t radix, int32_t precision
// *px is zero. // *px is zero.
if (rat_lt(y, rat_zero, precision)) if (rat_lt(y, rat_zero, precision))
{ {
throw(CALC_E_DOMAIN); throw CALC_E_DOMAIN;
} }
else if (zerrat(y)) else if (zerrat(y))
{ {
@ -424,7 +424,7 @@ void powratcomp(_Inout_ PRAT* px, _In_ PRAT y, uint32_t radix, int32_t precision
PRAT pxint = nullptr; PRAT pxint = nullptr;
DUPRAT(pxint, *px); DUPRAT(pxint, *px);
subrat(&pxint, rat_one, precision); subrat(&pxint, rat_one, precision);
if (rat_gt(pxint, rat_negsmallest, precision) && rat_lt(pxint, rat_smallest, precision) && (sign == 1)) if (rat_gt(pxint, rat_negsmallest, precision) && rat_lt(pxint, rat_smallest, precision) && sign == 1)
{ {
// *px is one, special case a 1 return. // *px is one, special case a 1 return.
DUPRAT(*px, rat_one); DUPRAT(*px, rat_one);
@ -456,7 +456,7 @@ void powratcomp(_Inout_ PRAT* px, _In_ PRAT y, uint32_t radix, int32_t precision
destroyrat(iy); destroyrat(iy);
destroyrat(pxint); destroyrat(pxint);
destroyrat(podd); destroyrat(podd);
throw(CALC_E_DOMAIN); throw CALC_E_DOMAIN;
} }
destroyrat(plnx); destroyrat(plnx);
ratpowi32(px, inty, precision); ratpowi32(px, inty, precision);
@ -506,7 +506,7 @@ void powratcomp(_Inout_ PRAT* px, _In_ PRAT y, uint32_t radix, int32_t precision
if (fBadExponent) if (fBadExponent)
{ {
throw(CALC_E_DOMAIN); throw CALC_E_DOMAIN;
} }
} }
else else

View file

@ -136,12 +136,12 @@ void _gamma(PRAT* pn, uint32_t radix, int32_t precision)
{ {
addrat(pn, rat_two, precision); addrat(pn, rat_two, precision);
// WARNING: mixing numbers and rationals here. // WARNING: mixing numbers and rationals here.
// for speed and efficiency. // for speed and efficiency.
INC(count); INC(count);
mulnumx(&(factorial->pp), count); mulnumx(&factorial->pp, count);
INC(count) INC(count)
mulnumx(&(factorial->pp), count); mulnumx(&factorial->pp, count);
divrat(&factorial, a2, precision); divrat(&factorial, a2, precision);
@ -207,11 +207,11 @@ void factrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision)
fracrat(&frac, radix, precision); fracrat(&frac, radix, precision);
// Check for negative integers and throw an error. // Check for negative integers and throw an error.
if ((zerrat(frac) || (LOGRATRADIX(frac) <= -precision)) && (SIGN(*px) == -1)) if ((zerrat(frac) || LOGRATRADIX(frac) <= -precision) && SIGN(*px) == -1)
{ {
throw CALC_E_DOMAIN; throw CALC_E_DOMAIN;
} }
while (rat_gt(*px, rat_zero, precision) && (LOGRATRADIX(*px) > -precision)) while (rat_gt(*px, rat_zero, precision) && LOGRATRADIX(*px) > -precision)
{ {
mulrat(&fact, *px, precision); mulrat(&fact, *px, precision);
subrat(px, rat_one, precision); subrat(px, rat_one, precision);

View file

@ -86,7 +86,6 @@ void asinanglerat(_Inout_ PRAT* pa, AngleType angletype, uint32_t radix, int32_t
void asinrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision) void asinrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision)
{ {
PRAT pret = nullptr;
PRAT phack = nullptr; PRAT phack = nullptr;
int32_t sgn = SIGN(*px); int32_t sgn = SIGN(*px);
@ -107,12 +106,13 @@ void asinrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision)
destroyrat(phack); destroyrat(phack);
if (rat_gt(*px, pt_eight_five, precision)) if (rat_gt(*px, pt_eight_five, precision))
{ {
PRAT pret = nullptr;
if (rat_gt(*px, rat_one, precision)) if (rat_gt(*px, rat_one, precision))
{ {
subrat(px, rat_one, precision); subrat(px, rat_one, precision);
if (rat_gt(*px, rat_smallest, precision)) if (rat_gt(*px, rat_smallest, precision))
{ {
throw(CALC_E_DOMAIN); throw CALC_E_DOMAIN;
} }
else else
{ {
@ -285,14 +285,14 @@ void atanrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision)
(*px)->pp->sign = 1; (*px)->pp->sign = 1;
(*px)->pq->sign = 1; (*px)->pq->sign = 1;
if (rat_gt((*px), pt_eight_five, precision)) if (rat_gt(*px, pt_eight_five, precision))
{ {
if (rat_gt((*px), rat_two, precision)) if (rat_gt(*px, rat_two, precision))
{ {
(*px)->pp->sign = sgn; (*px)->pp->sign = sgn;
(*px)->pq->sign = 1; (*px)->pq->sign = 1;
DUPRAT(tmpx, rat_one); DUPRAT(tmpx, rat_one);
divrat(&tmpx, (*px), precision); divrat(&tmpx, *px, precision);
_atanrat(&tmpx, precision); _atanrat(&tmpx, precision);
tmpx->pp->sign = sgn; tmpx->pp->sign = sgn;
tmpx->pq->sign = 1; tmpx->pq->sign = 1;

View file

@ -29,7 +29,7 @@ void lshrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision)
if (rat_gt(b, rat_max_exp, precision)) if (rat_gt(b, rat_max_exp, precision))
{ {
// Don't attempt lsh of anything big // Don't attempt lsh of anything big
throw(CALC_E_DOMAIN); throw CALC_E_DOMAIN;
} }
const int32_t intb = rattoi32(b, radix, precision); const int32_t intb = rattoi32(b, radix, precision);
DUPRAT(pwr, rat_two); DUPRAT(pwr, rat_two);
@ -51,7 +51,7 @@ void rshrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision)
if (rat_lt(b, rat_min_exp, precision)) if (rat_lt(b, rat_min_exp, precision))
{ {
// Don't attempt rsh of anything big and negative. // Don't attempt rsh of anything big and negative.
throw(CALC_E_DOMAIN); throw CALC_E_DOMAIN;
} }
const int32_t intb = rattoi32(b, radix, precision); const int32_t intb = rattoi32(b, radix, precision);
DUPRAT(pwr, rat_two); DUPRAT(pwr, rat_two);
@ -109,7 +109,7 @@ void boolrat(PRAT* pa, PRAT b, int func, uint32_t radix, int32_t precision)
DUPRAT(tmp, b); DUPRAT(tmp, b);
intrat(&tmp, radix, precision); intrat(&tmp, radix, precision);
boolnum(&((*pa)->pp), tmp->pp, func); boolnum(&(*pa)->pp, tmp->pp, func);
destroyrat(tmp); destroyrat(tmp);
} }
@ -151,8 +151,8 @@ void boolnum(PNUMBER* pa, PNUMBER b, int func)
pchc = c->mant; pchc = c->mant;
for (; cdigits > 0; cdigits--, mexp++) for (; cdigits > 0; cdigits--, mexp++)
{ {
da = (((mexp >= a->exp) && (cdigits + a->exp - c->exp > (c->cdigit - a->cdigit))) ? *pcha++ : 0); da = mexp >= a->exp && cdigits + a->exp - c->exp > c->cdigit - a->cdigit ? *pcha++ : 0;
db = (((mexp >= b->exp) && (cdigits + b->exp - c->exp > (c->cdigit - b->cdigit))) ? *pchb++ : 0); db = mexp >= b->exp && cdigits + b->exp - c->exp > c->cdigit - b->cdigit ? *pchb++ : 0;
switch (func) switch (func)
{ {
case FUNC_AND: case FUNC_AND:
@ -167,7 +167,7 @@ void boolnum(PNUMBER* pa, PNUMBER b, int func)
} }
} }
c->sign = a->sign; c->sign = a->sign;
while (c->cdigit > 1 && *(--pchc) == 0) while (c->cdigit > 1 && *--pchc == 0)
{ {
c->cdigit--; c->cdigit--;
} }
@ -200,10 +200,10 @@ void remrat(_Inout_ PRAT* pa, _In_ PRAT b)
PRAT tmp = nullptr; PRAT tmp = nullptr;
DUPRAT(tmp, b); DUPRAT(tmp, b);
mulnumx(&((*pa)->pp), tmp->pq); mulnumx(&(*pa)->pp, tmp->pq);
mulnumx(&(tmp->pp), (*pa)->pq); mulnumx(&tmp->pp, (*pa)->pq);
remnum(&((*pa)->pp), tmp->pp, BASEX); remnum(&(*pa)->pp, tmp->pp, BASEX);
mulnumx(&((*pa)->pq), tmp->pq); mulnumx(&(*pa)->pq, tmp->pq);
// Get *pa back in the integer over integer form. // Get *pa back in the integer over integer form.
RENORMALIZE(*pa); RENORMALIZE(*pa);
@ -237,12 +237,12 @@ void modrat(_Inout_ PRAT* pa, _In_ PRAT b)
PRAT tmp = nullptr; PRAT tmp = nullptr;
DUPRAT(tmp, b); DUPRAT(tmp, b);
auto needAdjust = (SIGN(*pa) == -1 ? (SIGN(b) == 1) : (SIGN(b) == -1)); const auto needAdjust = SIGN(*pa) == -1 ? SIGN(b) == 1 : SIGN(b) == -1;
mulnumx(&((*pa)->pp), tmp->pq); mulnumx(&(*pa)->pp, tmp->pq);
mulnumx(&(tmp->pp), (*pa)->pq); mulnumx(&tmp->pp, (*pa)->pq);
remnum(&((*pa)->pp), tmp->pp, BASEX); remnum(&(*pa)->pp, tmp->pp, BASEX);
mulnumx(&((*pa)->pq), tmp->pq); mulnumx(&(*pa)->pq, tmp->pq);
if (needAdjust && !zerrat(*pa)) if (needAdjust && !zerrat(*pa))
{ {

View file

@ -62,18 +62,18 @@ void addnum(_Inout_ PNUMBER* pa, _In_ PNUMBER b, uint32_t radix)
void _addnum(PNUMBER* pa, PNUMBER b, uint32_t radix) void _addnum(PNUMBER* pa, PNUMBER b, uint32_t radix)
{ {
PNUMBER c = nullptr; // c will contain the result. PNUMBER c = nullptr; // c will contain the result.
PNUMBER a = nullptr; // a is the dereferenced number pointer from *pa PNUMBER a = nullptr; // a is the dereferenced number pointer from *pa
MANTTYPE* pcha; // pcha is a pointer to the mantissa of a. MANTTYPE* pcha; // pcha is a pointer to the mantissa of a.
MANTTYPE* pchb; // pchb is a pointer to the mantissa of b. MANTTYPE* pchb; // pchb is a pointer to the mantissa of b.
MANTTYPE* pchc; // pchc is a pointer to the mantissa of c. MANTTYPE* pchc; // pchc is a pointer to the mantissa of c.
int32_t cdigits; // cdigits is the max count of the digits results used as a counter. int32_t cdigits; // cdigits is the max count of the digits results used as a counter.
int32_t mexp; // mexp is the exponent of the result. int32_t mexp; // mexp is the exponent of the result.
MANTTYPE da; // da is a single 'digit' after possible padding. MANTTYPE da; // da is a single 'digit' after possible padding.
MANTTYPE db; // db is a single 'digit' after possible padding. MANTTYPE db; // db is a single 'digit' after possible padding.
MANTTYPE cy = 0; // cy is the value of a carry after adding two 'digits' MANTTYPE cy = 0; // cy is the value of a carry after adding two 'digits'
int32_t fcompla = 0; // fcompla is a flag to signal a is negative. bool fcompla = false; // fcompla is a flag to signal a is negative.
int32_t fcomplb = 0; // fcomplb is a flag to signal b is negative. bool fcomplb = false; // fcomplb is a flag to signal b is negative.
a = *pa; a = *pa;
@ -93,8 +93,8 @@ void _addnum(PNUMBER* pa, PNUMBER b, uint32_t radix)
if (a->sign != b->sign) if (a->sign != b->sign)
{ {
cy = 1; cy = 1;
fcompla = (a->sign == -1); fcompla = a->sign == -1;
fcomplb = (b->sign == -1); fcomplb = b->sign == -1;
} }
// Loop over all the digits, real and 0 padded. Here we know a and b are // Loop over all the digits, real and 0 padded. Here we know a and b are
@ -102,25 +102,25 @@ void _addnum(PNUMBER* pa, PNUMBER b, uint32_t radix)
for (; cdigits > 0; cdigits--, mexp++) for (; cdigits > 0; cdigits--, mexp++)
{ {
// Get digit from a, taking padding into account. // Get digit from a, taking padding into account.
da = (((mexp >= a->exp) && (cdigits + a->exp - c->exp > (c->cdigit - a->cdigit))) ? *pcha++ : 0); da = mexp >= a->exp && cdigits + a->exp - c->exp > c->cdigit - a->cdigit ? *pcha++ : 0;
// Get digit from b, taking padding into account. // Get digit from b, taking padding into account.
db = (((mexp >= b->exp) && (cdigits + b->exp - c->exp > (c->cdigit - b->cdigit))) ? *pchb++ : 0); db = mexp >= b->exp && cdigits + b->exp - c->exp > c->cdigit - b->cdigit ? *pchb++ : 0;
// Handle complementing for a and b digit. Might be a better way, but // Handle complementing for a and b digit. Might be a better way, but
// haven't found it yet. // haven't found it yet.
if (fcompla) if (fcompla)
{ {
da = (MANTTYPE)(radix)-1 - da; da = radix - 1 - da;
} }
if (fcomplb) if (fcomplb)
{ {
db = (MANTTYPE)(radix)-1 - db; db = radix - 1 - db;
} }
// Update carry as necessary // Update carry as necessary
cy = da + db + cy; cy = da + db + cy;
*pchc++ = (MANTTYPE)(cy % (MANTTYPE)radix); *pchc++ = cy % radix;
cy /= (MANTTYPE)radix; cy /= radix;
} }
// Handle carry from last sum as extra digit // Handle carry from last sum as extra digit
@ -135,32 +135,29 @@ void _addnum(PNUMBER* pa, PNUMBER b, uint32_t radix)
{ {
c->sign = a->sign; c->sign = a->sign;
} }
else if (cy)
{
c->sign = 1;
}
else else
{ {
if (cy) // In this particular case an overflow or underflow has occurred
// and all the digits need to be complemented, at one time an
// attempt to handle this above was made, it turned out to be much
// slower on average.
c->sign = -1;
cy = 1;
for (cdigits = c->cdigit, pchc = c->mant; cdigits > 0; cdigits--)
{ {
c->sign = 1; cy = radix - 1 - *pchc + cy;
} *pchc++ = cy % radix;
else cy /= radix;
{
// In this particular case an overflow or underflow has occurred
// and all the digits need to be complemented, at one time an
// attempt to handle this above was made, it turned out to be much
// slower on average.
c->sign = -1;
cy = 1;
for ((cdigits = c->cdigit), (pchc = c->mant); cdigits > 0; cdigits--)
{
cy = (MANTTYPE)radix - (MANTTYPE)1 - *pchc + cy;
*pchc++ = (MANTTYPE)(cy % (MANTTYPE)radix);
cy /= (MANTTYPE)radix;
}
} }
} }
// Remove leading zeros, remember digits are in order of // Remove leading zeros, remember digits are in order of
// increasing significance. i.e. 100 would be 0,0,1 // increasing significance. i.e. 100 would be 0,0,1
while (c->cdigit > 1 && *(--pchc) == 0) while (c->cdigit > 1 && *--pchc == 0)
{ {
c->cdigit--; c->cdigit--;
} }
@ -247,7 +244,7 @@ void _mulnum(PNUMBER* pa, PNUMBER b, uint32_t radix)
for (ibdigit = b->cdigit; ibdigit > 0; ibdigit--) for (ibdigit = b->cdigit; ibdigit > 0; ibdigit--)
{ {
cy = 0; cy = 0;
mcy = (TWO_MANTTYPE)da * *pchb; mcy = static_cast<TWO_MANTTYPE>(da) * *pchb;
if (mcy) if (mcy)
{ {
icdigit = 0; icdigit = 0;
@ -260,14 +257,14 @@ void _mulnum(PNUMBER* pa, PNUMBER b, uint32_t radix)
while (mcy || cy) while (mcy || cy)
{ {
// update carry from addition(s) and multiply. // update carry from addition(s) and multiply.
cy += (TWO_MANTTYPE)pchc[icdigit] + (mcy % (TWO_MANTTYPE)radix); cy += static_cast<TWO_MANTTYPE>(pchc[icdigit]) + mcy % static_cast<TWO_MANTTYPE>(radix);
// update result digit from // update result digit from
pchc[icdigit++] = (MANTTYPE)(cy % (TWO_MANTTYPE)radix); pchc[icdigit++] = static_cast<MANTTYPE>(cy % static_cast<TWO_MANTTYPE>(radix));
// update carries from // update carries from
mcy /= (TWO_MANTTYPE)radix; mcy /= static_cast<TWO_MANTTYPE>(radix);
cy /= (TWO_MANTTYPE)radix; cy /= static_cast<TWO_MANTTYPE>(radix);
} }
pchb++; pchb++;
@ -340,7 +337,7 @@ void remnum(_Inout_ PNUMBER* pa, _In_ PNUMBER b, uint32_t radix)
} }
// Subtract the working remainder from the remainder holder. // Subtract the working remainder from the remainder holder.
tmp->sign = -1 * (*pa)->sign; tmp->sign = -(*pa)->sign;
addnum(pa, tmp, radix); addnum(pa, tmp, radix);
destroynum(tmp); destroynum(tmp);
@ -394,7 +391,7 @@ void _divnum(PNUMBER* pa, PNUMBER b, uint32_t radix, int32_t precision)
PNUMBER c = nullptr; PNUMBER c = nullptr;
createnum(c, thismax + 1); createnum(c, thismax + 1);
c->exp = (a->cdigit + a->exp) - (b->cdigit + b->exp) + 1; c->exp = a->cdigit + a->exp - (b->cdigit + b->exp) + 1;
c->sign = a->sign * b->sign; c->sign = a->sign * b->sign;
MANTTYPE* ptrc = c->mant + thismax; MANTTYPE* ptrc = c->mant + thismax;
@ -408,7 +405,7 @@ void _divnum(PNUMBER* pa, PNUMBER b, uint32_t radix, int32_t precision)
// Build a table of multiplications of the divisor, this is quicker for // Build a table of multiplications of the divisor, this is quicker for
// more than radix 'digits' // more than radix 'digits'
list<PNUMBER> numberList{ i32tonum(0L, radix) }; list<PNUMBER> numberList{ i32tonum(0L, radix) };
for (uint32_t i = 1; i < radix; i++) for (auto i = radix; i > 1; i--)
{ {
PNUMBER newValue = nullptr; PNUMBER newValue = nullptr;
DUPNUM(newValue, numberList.front()); DUPNUM(newValue, numberList.front());
@ -419,8 +416,8 @@ void _divnum(PNUMBER* pa, PNUMBER b, uint32_t radix, int32_t precision)
destroynum(tmp); destroynum(tmp);
int32_t digit; int32_t digit;
int32_t cdigits = 0; int32_t cdigits;
while (cdigits++ < thismax && !zernum(rem)) for (cdigits = 0; cdigits < thismax && !zernum(rem); cdigits++)
{ {
digit = radix - 1; digit = radix - 1;
PNUMBER multiple = nullptr; PNUMBER multiple = nullptr;
@ -440,13 +437,12 @@ void _divnum(PNUMBER* pa, PNUMBER b, uint32_t radix, int32_t precision)
multiple->sign *= -1; multiple->sign *= -1;
} }
rem->exp++; rem->exp++;
*ptrc-- = (MANTTYPE)digit; *ptrc-- = static_cast<MANTTYPE>(digit);
} }
cdigits--;
if (c->mant != ++ptrc) if (c->mant != ++ptrc)
{ {
memmove(c->mant, ptrc, (int)(cdigits * sizeof(MANTTYPE))); memmove(c->mant, ptrc, cdigits * sizeof(MANTTYPE));
} }
// Cleanup table structure // Cleanup table structure
@ -491,7 +487,6 @@ void _divnum(PNUMBER* pa, PNUMBER b, uint32_t radix, int32_t precision)
bool equnum(_In_ PNUMBER a, _In_ PNUMBER b) bool equnum(_In_ PNUMBER a, _In_ PNUMBER b)
{ {
int32_t diff;
MANTTYPE* pa; MANTTYPE* pa;
MANTTYPE* pb; MANTTYPE* pb;
int32_t cdigits; int32_t cdigits;
@ -499,45 +494,34 @@ bool equnum(_In_ PNUMBER a, _In_ PNUMBER b)
MANTTYPE da; MANTTYPE da;
MANTTYPE db; MANTTYPE db;
diff = (a->cdigit + a->exp) - (b->cdigit + b->exp); if (a->cdigit + a->exp != b->cdigit + b->exp)
if (diff < 0)
{ {
// If the exponents are different, these are different numbers. // If the exponents are different, these are different numbers.
return false; return false;
} }
else
// OK the exponents match.
pa = a->mant;
pb = b->mant;
pa = pa + a->cdigit - 1;
pb = pb + b->cdigit - 1;
cdigits = max(a->cdigit, b->cdigit);
ccdigits = cdigits;
// Loop over all digits until we run out of digits or there is a
// difference in the digits.
for (; cdigits > 0; cdigits--)
{ {
if (diff > 0) da = cdigits > ccdigits - a->cdigit ? *pa-- : 0;
db = cdigits > ccdigits - b->cdigit ? *pb-- : 0;
if (da != db)
{ {
// If the exponents are different, these are different numbers.
return false; return false;
} }
else
{
// OK the exponents match.
pa = a->mant;
pb = b->mant;
pa += a->cdigit - 1;
pb += b->cdigit - 1;
cdigits = max(a->cdigit, b->cdigit);
ccdigits = cdigits;
// Loop over all digits until we run out of digits or there is a
// difference in the digits.
for (; cdigits > 0; cdigits--)
{
da = ((cdigits > (ccdigits - a->cdigit)) ? *pa-- : 0);
db = ((cdigits > (ccdigits - b->cdigit)) ? *pb-- : 0);
if (da != db)
{
return false;
}
}
// In this case, they are equal.
return true;
}
} }
// In this case, they are equal.
return true;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -557,7 +541,8 @@ bool equnum(_In_ PNUMBER a, _In_ PNUMBER b)
bool lessnum(_In_ PNUMBER a, _In_ PNUMBER b) bool lessnum(_In_ PNUMBER a, _In_ PNUMBER b)
{ {
int32_t diff = (a->cdigit + a->exp) - (b->cdigit + b->exp); int32_t diff = a->cdigit + a->exp - (b->cdigit + b->exp);
if (diff < 0) if (diff < 0)
{ {
// The exponent of a is less than b // The exponent of a is less than b
@ -567,20 +552,22 @@ bool lessnum(_In_ PNUMBER a, _In_ PNUMBER b)
{ {
return false; return false;
} }
MANTTYPE* pa = a->mant;
MANTTYPE* pb = b->mant; MANTTYPE* pa = a->mant + a->cdigit - 1;
pa += a->cdigit - 1; MANTTYPE* pb = b->mant + b->cdigit - 1;
pb += b->cdigit - 1; auto cdigits = max(a->cdigit, b->cdigit);
int32_t cdigits = max(a->cdigit, b->cdigit); for (auto ccdigits = cdigits; ccdigits > 0; ccdigits--)
int32_t ccdigits = cdigits;
for (; cdigits > 0; cdigits--)
{ {
MANTTYPE da = ((cdigits > (ccdigits - a->cdigit)) ? *pa-- : 0); MANTTYPE da = ccdigits > cdigits - a->cdigit ? *pa-- : 0;
MANTTYPE db = ((cdigits > (ccdigits - b->cdigit)) ? *pb-- : 0); MANTTYPE db = ccdigits > cdigits - b->cdigit ? *pb-- : 0;
diff = da - db; diff = da - db;
if (diff) if (diff < 0)
{ {
return (diff < 0); return true;
}
if (diff > 0)
{
return false;
} }
} }
// In this case, they are equal. // In this case, they are equal.
@ -602,20 +589,19 @@ bool lessnum(_In_ PNUMBER a, _In_ PNUMBER b)
bool zernum(_In_ PNUMBER a) bool zernum(_In_ PNUMBER a)
{ {
int32_t length; MANTTYPE* pcha = a->mant;
MANTTYPE* pcha;
length = a->cdigit;
pcha = a->mant;
// loop over all the digits until you find a nonzero or until you run // loop over all the digits until you find a nonzero or until you run
// out of digits // out of digits
while (length-- > 0) for (auto length = a->cdigit; length > 0; length--)
{ {
if (*pcha++) if (*pcha)
{ {
// One of the digits isn't zero, therefore the number isn't zero // One of the digits isn't zero, therefore the number isn't zero
return false; return false;
} }
++pcha;
} }
// All of the digits are zero, therefore the number is zero // All of the digits are zero, therefore the number is zero
return true; return true;

View file

@ -40,16 +40,13 @@ using namespace std;
void gcdrat(_Inout_ PRAT* pa, int32_t precision) void gcdrat(_Inout_ PRAT* pa, int32_t precision)
{ {
PNUMBER pgcd = nullptr; PRAT a = *pa;
PRAT a = nullptr; PNUMBER pgcd = gcd(a->pp, a->pq);
a = *pa;
pgcd = gcd(a->pp, a->pq);
if (!zernum(pgcd)) if (!zernum(pgcd))
{ {
divnumx(&(a->pp), pgcd, precision); divnumx(&a->pp, pgcd, precision);
divnumx(&(a->pq), pgcd, precision); divnumx(&a->pq, pgcd, precision);
} }
destroynum(pgcd); destroynum(pgcd);
@ -79,7 +76,7 @@ void fracrat(_Inout_ PRAT* pa, uint32_t radix, int32_t precision)
flatrat(*pa, radix, precision); flatrat(*pa, radix, precision);
} }
remnum(&((*pa)->pp), (*pa)->pq, BASEX); remnum(&(*pa)->pp, (*pa)->pq, BASEX);
// Get *pa back in the integer over integer form. // Get *pa back in the integer over integer form.
RENORMALIZE(*pa); RENORMALIZE(*pa);
@ -104,8 +101,8 @@ void mulrat(_Inout_ PRAT* pa, _In_ PRAT b, int32_t precision)
// Only do the multiply if it isn't zero. // Only do the multiply if it isn't zero.
if (!zernum((*pa)->pp)) if (!zernum((*pa)->pp))
{ {
mulnumx(&((*pa)->pp), b->pp); mulnumx(&(*pa)->pp, b->pp);
mulnumx(&((*pa)->pq), b->pq); mulnumx(&(*pa)->pq, b->pq);
trimit(pa, precision); trimit(pa, precision);
} }
else else
@ -138,13 +135,13 @@ void divrat(_Inout_ PRAT* pa, _In_ PRAT b, int32_t precision)
if (!zernum((*pa)->pp)) if (!zernum((*pa)->pp))
{ {
// Only do the divide if the top isn't zero. // Only do the divide if the top isn't zero.
mulnumx(&((*pa)->pp), b->pq); mulnumx(&(*pa)->pp, b->pq);
mulnumx(&((*pa)->pq), b->pp); mulnumx(&(*pa)->pq, b->pp);
if (zernum((*pa)->pq)) if (zernum((*pa)->pq))
{ {
// raise an exception if the bottom is 0. // raise an exception if the bottom is 0.
throw(CALC_E_DIVIDEBYZERO); throw CALC_E_DIVIDEBYZERO;
} }
trimit(pa, precision); trimit(pa, precision);
} }
@ -155,7 +152,7 @@ void divrat(_Inout_ PRAT* pa, _In_ PRAT b, int32_t precision)
{ {
// If bottom is zero // If bottom is zero
// 0 / 0 is indefinite, raise an exception. // 0 / 0 is indefinite, raise an exception.
throw(CALC_E_INDEFINITE); throw CALC_E_INDEFINITE;
} }
else else
{ {
@ -218,16 +215,16 @@ void addrat(_Inout_ PRAT* pa, _In_ PRAT b, int32_t precision)
(*pa)->pq->sign = 1; (*pa)->pq->sign = 1;
b->pp->sign *= b->pq->sign; b->pp->sign *= b->pq->sign;
b->pq->sign = 1; b->pq->sign = 1;
addnum(&((*pa)->pp), b->pp, BASEX); addnum(&(*pa)->pp, b->pp, BASEX);
} }
else else
{ {
// Usual case q's aren't the same. // Usual case q's aren't the same.
DUPNUM(bot, (*pa)->pq); DUPNUM(bot, (*pa)->pq);
mulnumx(&bot, b->pq); mulnumx(&bot, b->pq);
mulnumx(&((*pa)->pp), b->pq); mulnumx(&(*pa)->pp, b->pq);
mulnumx(&((*pa)->pq), b->pp); mulnumx(&(*pa)->pq, b->pp);
addnum(&((*pa)->pp), (*pa)->pq, BASEX); addnum(&(*pa)->pp, (*pa)->pq, BASEX);
destroynum((*pa)->pq); destroynum((*pa)->pq);
(*pa)->pq = bot; (*pa)->pq = bot;
trimit(pa, precision); trimit(pa, precision);
@ -283,5 +280,5 @@ void rootrat(_Inout_ PRAT* py, _In_ PRAT n, uint32_t radix, int32_t precision)
bool zerrat(_In_ PRAT a) bool zerrat(_In_ PRAT a)
{ {
return (zernum(a->pp)); return zernum(a->pp);
} }

View file

@ -339,7 +339,7 @@ extern bool zerrat(_In_ PRAT a); // returns true if a == 0/q
extern std::wstring NumberToString(_Inout_ PNUMBER& pnum, NumberFormat format, uint32_t radix, int32_t precision); extern std::wstring NumberToString(_Inout_ PNUMBER& pnum, NumberFormat format, uint32_t radix, int32_t precision);
// returns a text representation of a PRAT // returns a text representation of a PRAT
extern std::wstring RatToString(_Inout_ PRAT& prat, NumberFormat format, uint32_t radix, int32_t precision); extern std::wstring RatToString(_Inout_ const PRAT& prat, NumberFormat format, uint32_t radix, int32_t precision);
// converts a PRAT into a PNUMBER // converts a PRAT into a PNUMBER
extern PNUMBER RatToNumber(_In_ PRAT prat, uint32_t radix, int32_t precision); extern PNUMBER RatToNumber(_In_ PRAT prat, uint32_t radix, int32_t precision);
// flattens a PRAT by converting it to a PNUMBER and back to a PRAT // flattens a PRAT by converting it to a PNUMBER and back to a PRAT
@ -367,7 +367,7 @@ extern PNUMBER Ui32tonum(uint32_t ini32, uint32_t radix);
extern PNUMBER numtonRadixx(_In_ PNUMBER a, uint32_t radix); extern PNUMBER numtonRadixx(_In_ PNUMBER a, uint32_t radix);
// creates a empty/undefined rational representation (p/q) // creates a empty/undefined rational representation (p/q)
extern PRAT _createrat(void); extern PRAT _createrat();
// returns a new rat structure with the acos of x->p/x->q taking into account // returns a new rat structure with the acos of x->p/x->q taking into account
// angle type // angle type
@ -439,7 +439,7 @@ extern void tanrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// angle type // angle type
extern void tananglerat(_Inout_ PRAT* px, AngleType angletype, uint32_t radix, int32_t precision); extern void tananglerat(_Inout_ PRAT* px, AngleType angletype, uint32_t radix, int32_t precision);
extern void _dupnum(_In_ PNUMBER dest, _In_ const NUMBER* const src); extern void _dupnum(_In_ PNUMBER dest, _In_ const NUMBER* src);
extern void _destroynum(_Frees_ptr_opt_ PNUMBER pnum); extern void _destroynum(_Frees_ptr_opt_ PNUMBER pnum);
extern void _destroyrat(_Frees_ptr_opt_ PRAT prat); extern void _destroyrat(_Frees_ptr_opt_ PRAT prat);
@ -480,6 +480,6 @@ extern bool rat_ge(_In_ PRAT a, _In_ PRAT b, int32_t precision);
extern bool rat_lt(_In_ PRAT a, _In_ PRAT b, int32_t precision); extern bool rat_lt(_In_ PRAT a, _In_ PRAT b, int32_t precision);
extern bool rat_le(_In_ PRAT a, _In_ PRAT b, int32_t precision); extern bool rat_le(_In_ PRAT a, _In_ PRAT b, int32_t precision);
extern void inbetween(_In_ PRAT* px, _In_ PRAT range, int32_t precision); extern void inbetween(_In_ PRAT* px, _In_ PRAT range, int32_t precision);
extern void trimit(_Inout_ PRAT* px, int32_t precision); extern void trimit(_Inout_ const PRAT* px, int32_t precision);
extern void _dumprawrat(_In_ const wchar_t* varname, _In_ PRAT rat, std::wostream& out); extern void _dumprawrat(_In_ const wchar_t* varname, _In_ PRAT rat, std::wostream& out);
extern void _dumprawnum(_In_ const wchar_t* varname, _In_ PNUMBER num, std::wostream& out); extern void _dumprawnum(_In_ const wchar_t* varname, _In_ PNUMBER num, std::wostream& out);

View file

@ -25,7 +25,7 @@
using namespace std; using namespace std;
void _readconstants(void); void _readconstants();
#if defined(GEN_CONST) #if defined(GEN_CONST)
static int cbitsofprecision = 0; static int cbitsofprecision = 0;
@ -136,19 +136,20 @@ void ChangeConstants(uint32_t radix, int32_t precision)
// in the internal BASEX radix, this is important for length calculations // in the internal BASEX radix, this is important for length calculations
// in translating from radix to BASEX and back. // in translating from radix to BASEX and back.
uint64_t limit = static_cast<uint64_t>(BASEX) / static_cast<uint64_t>(radix); const uint32_t limit = BASEX / radix;
g_ratio = 0; g_ratio = 0;
for (uint32_t digit = 1; digit < limit; digit *= radix) for (uint32_t digit = 1; digit < limit; digit *= radix)
{ {
g_ratio++; g_ratio++;
} }
g_ratio += !g_ratio; if (g_ratio == 0)
g_ratio = 1; // g_ratio is always at least 1
destroyrat(rat_nRadix); destroyrat(rat_nRadix);
rat_nRadix = i32torat(radix); rat_nRadix = i32torat(radix);
// Check to see what we have to recalculate and what we don't // Check to see what we have to recalculate and what we don't
if (cbitsofprecision < (g_ratio * static_cast<int32_t>(radix) * precision)) if (cbitsofprecision < g_ratio * static_cast<int32_t>(radix) * precision)
{ {
g_ftrueinfinite = false; g_ftrueinfinite = false;
@ -202,17 +203,17 @@ void ChangeConstants(uint32_t radix, int32_t precision)
} }
DUPRAT(rat_qword, rat_two); DUPRAT(rat_qword, rat_two);
numpowi32(&(rat_qword->pp), 64, BASEX, precision); numpowi32(&rat_qword->pp, 64, BASEX, precision);
subrat(&rat_qword, rat_one, precision); subrat(&rat_qword, rat_one, precision);
DUMPRAWRAT(rat_qword); DUMPRAWRAT(rat_qword);
DUPRAT(rat_dword, rat_two); DUPRAT(rat_dword, rat_two);
numpowi32(&(rat_dword->pp), 32, BASEX, precision); numpowi32(&rat_dword->pp, 32, BASEX, precision);
subrat(&rat_dword, rat_one, precision); subrat(&rat_dword, rat_one, precision);
DUMPRAWRAT(rat_dword); DUMPRAWRAT(rat_dword);
DUPRAT(rat_max_i32, rat_two); DUPRAT(rat_max_i32, rat_two);
numpowi32(&(rat_max_i32->pp), 31, BASEX, precision); numpowi32(&rat_max_i32->pp, 31, BASEX, precision);
DUPRAT(rat_min_i32, rat_max_i32); DUPRAT(rat_min_i32, rat_max_i32);
subrat(&rat_max_i32, rat_one, precision); // rat_max_i32 = 2^31 -1 subrat(&rat_max_i32, rat_one, precision); // rat_max_i32 = 2^31 -1
DUMPRAWRAT(rat_max_i32); DUMPRAWRAT(rat_max_i32);
@ -337,7 +338,7 @@ bool rat_equ(_In_ PRAT a, _In_ PRAT b, int32_t precision)
addrat(&rattmp, b, precision); addrat(&rattmp, b, precision);
bool bret = zernum(rattmp->pp); bool bret = zernum(rattmp->pp);
destroyrat(rattmp); destroyrat(rattmp);
return (bret); return bret;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -359,9 +360,9 @@ bool rat_ge(_In_ PRAT a, _In_ PRAT b, int32_t precision)
b->pp->sign *= -1; b->pp->sign *= -1;
addrat(&rattmp, b, precision); addrat(&rattmp, b, precision);
b->pp->sign *= -1; b->pp->sign *= -1;
bool bret = (zernum(rattmp->pp) || SIGN(rattmp) == 1); bool bret = zernum(rattmp->pp) || SIGN(rattmp) == 1;
destroyrat(rattmp); destroyrat(rattmp);
return (bret); return bret;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -383,9 +384,9 @@ bool rat_gt(_In_ PRAT a, _In_ PRAT b, int32_t precision)
b->pp->sign *= -1; b->pp->sign *= -1;
addrat(&rattmp, b, precision); addrat(&rattmp, b, precision);
b->pp->sign *= -1; b->pp->sign *= -1;
bool bret = (!zernum(rattmp->pp) && SIGN(rattmp) == 1); bool bret = !zernum(rattmp->pp) && SIGN(rattmp) == 1;
destroyrat(rattmp); destroyrat(rattmp);
return (bret); return bret;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -407,9 +408,9 @@ bool rat_le(_In_ PRAT a, _In_ PRAT b, int32_t precision)
b->pp->sign *= -1; b->pp->sign *= -1;
addrat(&rattmp, b, precision); addrat(&rattmp, b, precision);
b->pp->sign *= -1; b->pp->sign *= -1;
bool bret = (zernum(rattmp->pp) || SIGN(rattmp) == -1); bool bret = zernum(rattmp->pp) || SIGN(rattmp) == -1;
destroyrat(rattmp); destroyrat(rattmp);
return (bret); return bret;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -431,9 +432,9 @@ bool rat_lt(_In_ PRAT a, _In_ PRAT b, int32_t precision)
b->pp->sign *= -1; b->pp->sign *= -1;
addrat(&rattmp, b, precision); addrat(&rattmp, b, precision);
b->pp->sign *= -1; b->pp->sign *= -1;
bool bret = (!zernum(rattmp->pp) && SIGN(rattmp) == -1); bool bret = !zernum(rattmp->pp) && SIGN(rattmp) == -1;
destroyrat(rattmp); destroyrat(rattmp);
return (bret); return bret;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -454,9 +455,9 @@ bool rat_neq(_In_ PRAT a, _In_ PRAT b, int32_t precision)
DUPRAT(rattmp, a); DUPRAT(rattmp, a);
rattmp->pp->sign *= -1; rattmp->pp->sign *= -1;
addrat(&rattmp, b, precision); addrat(&rattmp, b, precision);
bool bret = !(zernum(rattmp->pp)); bool bret = !zernum(rattmp->pp);
destroyrat(rattmp); destroyrat(rattmp);
return (bret); return bret;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -477,7 +478,7 @@ void scale(_Inout_ PRAT* px, _In_ PRAT scalefact, uint32_t radix, int32_t precis
// Logscale is a quick way to tell how much extra precision is needed for // Logscale is a quick way to tell how much extra precision is needed for
// scaling by scalefact. // scaling by scalefact.
int32_t logscale = g_ratio * ((pret->pp->cdigit + pret->pp->exp) - (pret->pq->cdigit + pret->pq->exp)); int32_t logscale = g_ratio * (pret->pp->cdigit + pret->pp->exp - (pret->pq->cdigit + pret->pq->exp));
if (logscale > 0) if (logscale > 0)
{ {
precision += logscale; precision += logscale;
@ -511,7 +512,7 @@ void scale2pi(_Inout_ PRAT* px, uint32_t radix, int32_t precision)
// Logscale is a quick way to tell how much extra precision is needed for // Logscale is a quick way to tell how much extra precision is needed for
// scaling by 2 pi. // scaling by 2 pi.
int32_t logscale = g_ratio * ((pret->pp->cdigit + pret->pp->exp) - (pret->pq->cdigit + pret->pq->exp)); int32_t logscale = g_ratio * (pret->pp->cdigit + pret->pp->exp - (pret->pq->cdigit + pret->pq->exp));
if (logscale > 0) if (logscale > 0)
{ {
precision += logscale; precision += logscale;
@ -610,7 +611,7 @@ void _dumprawnum(_In_ const wchar_t* varname, _In_ PNUMBER num, wostream& out)
out << L"};\n"; out << L"};\n";
} }
void _readconstants(void) void _readconstants()
{ {
READRAWNUM(num_one); READRAWNUM(num_one);
@ -674,14 +675,14 @@ void _readconstants(void)
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void trimit(_Inout_ PRAT* px, int32_t precision) void trimit(_Inout_ const PRAT* px, int32_t precision)
{ {
if (!g_ftrueinfinite) if (!g_ftrueinfinite)
{ {
PNUMBER pp = (*px)->pp; PNUMBER pp = (*px)->pp;
PNUMBER pq = (*px)->pq; PNUMBER pq = (*px)->pq;
int32_t trim = g_ratio * (min((pp->cdigit + pp->exp), (pq->cdigit + pq->exp)) - 1) - precision; int32_t trim = g_ratio * (min(pp->cdigit + pp->exp, pq->cdigit + pq->exp) - 1) - precision;
if (trim > g_ratio) if (trim > g_ratio)
{ {
trim /= g_ratio; trim /= g_ratio;
@ -692,7 +693,7 @@ void trimit(_Inout_ PRAT* px, int32_t precision)
} }
else else
{ {
memmove(pp->mant, &(pp->mant[trim - pp->exp]), sizeof(MANTTYPE) * (pp->cdigit - trim + pp->exp)); memmove(pp->mant, &pp->mant[trim - pp->exp], sizeof(MANTTYPE) * (pp->cdigit - trim + pp->exp));
pp->cdigit -= trim - pp->exp; pp->cdigit -= trim - pp->exp;
pp->exp = 0; pp->exp = 0;
} }
@ -703,7 +704,7 @@ void trimit(_Inout_ PRAT* px, int32_t precision)
} }
else else
{ {
memmove(pq->mant, &(pq->mant[trim - pq->exp]), sizeof(MANTTYPE) * (pq->cdigit - trim + pq->exp)); memmove(pq->mant, &pq->mant[trim - pq->exp], sizeof(MANTTYPE) * (pq->cdigit - trim + pq->exp));
pq->cdigit -= trim - pq->exp; pq->cdigit -= trim - pq->exp;
pq->exp = 0; pq->exp = 0;
} }

View file

@ -250,7 +250,7 @@ void _tanrat(PRAT* px, uint32_t radix, int32_t precision)
if (zerrat(ptmp)) if (zerrat(ptmp))
{ {
destroyrat(ptmp); destroyrat(ptmp);
throw(CALC_E_DOMAIN); throw CALC_E_DOMAIN;
} }
divrat(px, ptmp, precision); divrat(px, ptmp, precision);

View file

@ -70,7 +70,7 @@ void _sinhrat(PRAT* px, int32_t precision)
if (!IsValidForHypFunc(*px, precision)) if (!IsValidForHypFunc(*px, precision))
{ {
// Don't attempt exp of anything large or small // Don't attempt exp of anything large or small
throw(CALC_E_DOMAIN); throw CALC_E_DOMAIN;
} }
CREATETAYLOR(); CREATETAYLOR();
@ -149,7 +149,7 @@ void _coshrat(PRAT* px, uint32_t radix, int32_t precision)
if (!IsValidForHypFunc(*px, precision)) if (!IsValidForHypFunc(*px, precision))
{ {
// Don't attempt exp of anything large or small // Don't attempt exp of anything large or small
throw(CALC_E_DOMAIN); throw CALC_E_DOMAIN;
} }
CREATETAYLOR(); CREATETAYLOR();
@ -219,8 +219,8 @@ void tanhrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision)
DUPRAT(ptmp, *px); DUPRAT(ptmp, *px);
sinhrat(px, radix, precision); sinhrat(px, radix, precision);
coshrat(&ptmp, radix, precision); coshrat(&ptmp, radix, precision);
mulnumx(&((*px)->pp), ptmp->pq); mulnumx(&(*px)->pp, ptmp->pq);
mulnumx(&((*px)->pq), ptmp->pp); mulnumx(&(*px)->pq, ptmp->pp);
destroyrat(ptmp); destroyrat(ptmp);
} }

View file

@ -24,8 +24,8 @@ static constexpr uint32_t OPTIMALDIGITSALLOWED = 7U;
static constexpr wchar_t LEFTESCAPECHAR = L'{'; static constexpr wchar_t LEFTESCAPECHAR = L'{';
static constexpr wchar_t RIGHTESCAPECHAR = L'}'; static constexpr wchar_t RIGHTESCAPECHAR = L'}';
static const double OPTIMALDECIMALALLOWED = 1e-6; // pow(10, -1 * (OPTIMALDIGITSALLOWED - 1)); static constexpr double OPTIMALDECIMALALLOWED = 1e-6; // pow(10, -1 * (OPTIMALDIGITSALLOWED - 1));
static const double MINIMUMDECIMALALLOWED = 1e-14; // pow(10, -1 * (MAXIMUMDIGITSALLOWED - 1)); static constexpr double MINIMUMDECIMALALLOWED = 1e-14; // pow(10, -1 * (MAXIMUMDIGITSALLOWED - 1));
unordered_map<wchar_t, wstring> quoteConversions; unordered_map<wchar_t, wstring> quoteConversions;
unordered_map<wstring, wchar_t> unquoteConversions; unordered_map<wstring, wchar_t> unquoteConversions;
@ -65,8 +65,8 @@ UnitConverter::UnitConverter(_In_ const shared_ptr<IConverterDataLoader>& dataLo
unquoteConversions[L"{sc}"] = L';'; unquoteConversions[L"{sc}"] = L';';
unquoteConversions[L"{lb}"] = LEFTESCAPECHAR; unquoteConversions[L"{lb}"] = LEFTESCAPECHAR;
unquoteConversions[L"{rb}"] = RIGHTESCAPECHAR; unquoteConversions[L"{rb}"] = RIGHTESCAPECHAR;
ClearValues(); UnitConverter::ClearValues();
ResetCategoriesAndRatios(); UnitConverter::ResetCategoriesAndRatios();
} }
void UnitConverter::Initialize() void UnitConverter::Initialize()
@ -76,10 +76,12 @@ void UnitConverter::Initialize()
bool UnitConverter::CheckLoad() bool UnitConverter::CheckLoad()
{ {
if (m_categories.empty()) if (!m_categories.empty())
{ {
ResetCategoriesAndRatios(); return true;
} }
ResetCategoriesAndRatios();
return !m_categories.empty(); return !m_categories.empty();
} }
@ -111,8 +113,8 @@ CategorySelectionInitializer UnitConverter::SetCurrentCategory(const Category& i
{ {
for (auto& unit : m_categoryToUnits[m_currentCategory.id]) for (auto& unit : m_categoryToUnits[m_currentCategory.id])
{ {
unit.isConversionSource = (unit.id == m_fromType.id); unit.isConversionSource = unit.id == m_fromType.id;
unit.isConversionTarget = (unit.id == m_toType.id); unit.isConversionTarget = unit.id == m_toType.id;
} }
m_currentCategory = input; m_currentCategory = input;
if (!m_currentCategory.supportsNegative && m_currentDisplay.front() == L'-') if (!m_currentCategory.supportsNegative && m_currentDisplay.front() == L'-')
@ -184,7 +186,7 @@ void UnitConverter::SwitchActive(const wstring& newValue)
swap(m_currentHasDecimal, m_returnHasDecimal); swap(m_currentHasDecimal, m_returnHasDecimal);
m_returnDisplay = m_currentDisplay; m_returnDisplay = m_currentDisplay;
m_currentDisplay = newValue; m_currentDisplay = newValue;
m_currentHasDecimal = (m_currentDisplay.find(L'.') != wstring::npos); m_currentHasDecimal = m_currentDisplay.find(L'.') != wstring::npos;
m_switchedActive = true; m_switchedActive = true;
if (m_currencyDataLoader != nullptr && m_vmCurrencyCallback != nullptr) if (m_currencyDataLoader != nullptr && m_vmCurrencyCallback != nullptr)
@ -196,12 +198,12 @@ void UnitConverter::SwitchActive(const wstring& newValue)
} }
} }
bool UnitConversionManager::UnitConverter::IsSwitchedActive() const bool UnitConverter::IsSwitchedActive() const
{ {
return m_switchedActive; return m_switchedActive;
} }
wstring UnitConverter::CategoryToString(const Category& c, wstring_view delimiter) wstring UnitConverter::CategoryToString(const Category& c, wstring_view delimiter) const
{ {
return Quote(std::to_wstring(c.id)) return Quote(std::to_wstring(c.id))
.append(delimiter) .append(delimiter)
@ -229,7 +231,7 @@ vector<wstring> UnitConverter::StringToVector(wstring_view w, wstring_view delim
} }
return serializedTokens; return serializedTokens;
} }
wstring UnitConverter::UnitToString(const Unit& u, wstring_view delimiter) wstring UnitConverter::UnitToString(const Unit& u, wstring_view delimiter) const
{ {
return Quote(std::to_wstring(u.id)) return Quote(std::to_wstring(u.id))
.append(delimiter) .append(delimiter)
@ -247,26 +249,26 @@ wstring UnitConverter::UnitToString(const Unit& u, wstring_view delimiter)
Unit UnitConverter::StringToUnit(wstring_view w) Unit UnitConverter::StringToUnit(wstring_view w)
{ {
vector<wstring> tokenList = StringToVector(w, L";"); const vector<wstring> tokenList = StringToVector(w, L";");
assert(tokenList.size() == EXPECTEDSERIALIZEDUNITTOKENCOUNT); assert(tokenList.size() == EXPECTEDSERIALIZEDUNITTOKENCOUNT);
Unit serializedUnit; Unit serializedUnit;
serializedUnit.id = wcstol(Unquote(tokenList[0]).c_str(), nullptr, 10); serializedUnit.id = wcstol(Unquote(tokenList[0]).c_str(), nullptr, 10);
serializedUnit.name = Unquote(tokenList[1]); serializedUnit.name = Unquote(tokenList[1]);
serializedUnit.accessibleName = serializedUnit.name; serializedUnit.accessibleName = serializedUnit.name;
serializedUnit.abbreviation = Unquote(tokenList[2]); serializedUnit.abbreviation = Unquote(tokenList[2]);
serializedUnit.isConversionSource = (tokenList[3] == L"1"); serializedUnit.isConversionSource = tokenList[3] == L"1";
serializedUnit.isConversionTarget = (tokenList[4] == L"1"); serializedUnit.isConversionTarget = tokenList[4] == L"1";
serializedUnit.isWhimsical = (tokenList[5] == L"1"); serializedUnit.isWhimsical = tokenList[5] == L"1";
return serializedUnit; return serializedUnit;
} }
Category UnitConverter::StringToCategory(wstring_view w) Category UnitConverter::StringToCategory(wstring_view w)
{ {
vector<wstring> tokenList = StringToVector(w, L";"); const vector<wstring> tokenList = StringToVector(w, L";");
assert(tokenList.size() == EXPECTEDSERIALIZEDCATEGORYTOKENCOUNT); assert(tokenList.size() == EXPECTEDSERIALIZEDCATEGORYTOKENCOUNT);
Category serializedCategory; Category serializedCategory;
serializedCategory.id = wcstol(Unquote(tokenList[0]).c_str(), nullptr, 10); serializedCategory.id = wcstol(Unquote(tokenList[0]).c_str(), nullptr, 10);
serializedCategory.supportsNegative = (tokenList[1] == L"1"); serializedCategory.supportsNegative = tokenList[1] == L"1";
serializedCategory.name = Unquote(tokenList[2]); serializedCategory.name = Unquote(tokenList[2]);
return serializedCategory; return serializedCategory;
} }
@ -282,18 +284,18 @@ void UnitConverter::RestoreUserPreferences(wstring_view userPreferences)
return; return;
} }
vector<wstring> outerTokens = StringToVector(userPreferences, L"|"); const vector<wstring> outerTokens = StringToVector(userPreferences, L"|");
if (outerTokens.size() != 3) if (outerTokens.size() != 3)
{ {
return; return;
} }
auto fromType = StringToUnit(outerTokens[0]); const auto fromType = StringToUnit(outerTokens[0]);
auto toType = StringToUnit(outerTokens[1]); const auto toType = StringToUnit(outerTokens[1]);
m_currentCategory = StringToCategory(outerTokens[2]); m_currentCategory = StringToCategory(outerTokens[2]);
// Only restore from the saved units if they are valid in the current available units. // Only restore from the saved units if they are valid in the current available units.
auto itr = m_categoryToUnits.find(m_currentCategory.id); const auto itr = m_categoryToUnits.find(m_currentCategory.id);
if (itr != m_categoryToUnits.end()) if (itr != m_categoryToUnits.end())
{ {
const auto& curUnits = itr->second; const auto& curUnits = itr->second;
@ -398,8 +400,8 @@ void UnitConverter::SendCommand(Command command)
} }
// TODO: Localization of characters // TODO: Localization of characters
bool clearFront = false; bool clearFront;
bool clearBack = false; bool clearBack;
if (command != Command::Negate && m_switchedActive) if (command != Command::Negate && m_switchedActive)
{ {
ClearValues(); ClearValues();
@ -409,10 +411,10 @@ void UnitConverter::SendCommand(Command command)
} }
else else
{ {
clearFront = (m_currentDisplay == L"0"); clearFront = m_currentDisplay == L"0";
clearBack = clearBack =
((m_currentHasDecimal && m_currentDisplay.size() - 1 >= MAXIMUMDIGITSALLOWED) m_currentHasDecimal && m_currentDisplay.size() - 1 >= MAXIMUMDIGITSALLOWED
|| (!m_currentHasDecimal && m_currentDisplay.size() >= MAXIMUMDIGITSALLOWED)); || !m_currentHasDecimal && m_currentDisplay.size() >= MAXIMUMDIGITSALLOWED;
} }
switch (command) switch (command)
@ -470,7 +472,7 @@ void UnitConverter::SendCommand(Command command)
case Command::Backspace: case Command::Backspace:
clearFront = false; clearFront = false;
clearBack = false; clearBack = false;
if ((m_currentDisplay.front() != L'-' && m_currentDisplay.size() > 1) || m_currentDisplay.size() > 2) if (m_currentDisplay.front() != L'-' && m_currentDisplay.size() > 1 || m_currentDisplay.size() > 2)
{ {
if (m_currentDisplay.back() == L'.') if (m_currentDisplay.back() == L'.')
{ {
@ -514,6 +516,7 @@ void UnitConverter::SendCommand(Command command)
ResetCategoriesAndRatios(); ResetCategoriesAndRatios();
break; break;
case Command::None:
default: default:
break; break;
} }
@ -548,7 +551,7 @@ void UnitConverter::SetViewModelCurrencyCallback(_In_ const shared_ptr<IViewMode
{ {
m_vmCurrencyCallback = newCallback; m_vmCurrencyCallback = newCallback;
shared_ptr<ICurrencyConverterDataLoader> currencyDataLoader = GetCurrencyConverterDataLoader(); const shared_ptr<ICurrencyConverterDataLoader> currencyDataLoader = GetCurrencyConverterDataLoader();
if (currencyDataLoader != nullptr) if (currencyDataLoader != nullptr)
{ {
currencyDataLoader->SetViewModelCallback(newCallback); currencyDataLoader->SetViewModelCallback(newCallback);
@ -582,7 +585,7 @@ future<pair<bool, wstring>> UnitConverter::RefreshCurrencyRatios()
}); });
} }
shared_ptr<ICurrencyConverterDataLoader> UnitConverter::GetCurrencyConverterDataLoader() shared_ptr<ICurrencyConverterDataLoader> UnitConverter::GetCurrencyConverterDataLoader() const
{ {
return dynamic_pointer_cast<ICurrencyConverterDataLoader>(m_currencyDataLoader); return dynamic_pointer_cast<ICurrencyConverterDataLoader>(m_currencyDataLoader);
} }
@ -600,7 +603,7 @@ double UnitConverter::Convert(double value, const ConversionData& conversionData
} }
else else
{ {
return (value * conversionData.ratio) + conversionData.offset; return value * conversionData.ratio + conversionData.offset;
} }
} }
@ -636,7 +639,7 @@ vector<tuple<wstring, Unit>> UnitConverter::CalculateSuggested()
} }
// Sort the resulting list by absolute magnitude, breaking ties by choosing the positive value // Sort the resulting list by absolute magnitude, breaking ties by choosing the positive value
sort(intermediateVector.begin(), intermediateVector.end(), [](SuggestedValueIntermediate first, SuggestedValueIntermediate second) { sort(intermediateVector.begin(), intermediateVector.end(), [](SuggestedValueIntermediate first, const SuggestedValueIntermediate second) {
if (abs(first.magnitude) == abs(second.magnitude)) if (abs(first.magnitude) == abs(second.magnitude))
{ {
return first.magnitude > second.magnitude; return first.magnitude > second.magnitude;
@ -672,7 +675,7 @@ vector<tuple<wstring, Unit>> UnitConverter::CalculateSuggested()
// The Whimsicals are determined differently // The Whimsicals are determined differently
// Sort the resulting list by absolute magnitude, breaking ties by choosing the positive value // Sort the resulting list by absolute magnitude, breaking ties by choosing the positive value
sort(intermediateWhimsicalVector.begin(), intermediateWhimsicalVector.end(), [](SuggestedValueIntermediate first, SuggestedValueIntermediate second) { sort(intermediateWhimsicalVector.begin(), intermediateWhimsicalVector.end(), [](const SuggestedValueIntermediate first, const SuggestedValueIntermediate second) {
if (abs(first.magnitude) == abs(second.magnitude)) if (abs(first.magnitude) == abs(second.magnitude))
{ {
return first.magnitude > second.magnitude; return first.magnitude > second.magnitude;
@ -797,7 +800,7 @@ void UnitConverter::InitializeSelectedUnits()
return; return;
} }
auto itr = m_categoryToUnits.find(m_currentCategory.id); const auto itr = m_categoryToUnits.find(m_currentCategory.id);
if (itr == m_categoryToUnits.end()) if (itr == m_categoryToUnits.end())
{ {
return; return;
@ -856,7 +859,7 @@ void UnitConverter::ClearValues()
/// <summary> /// <summary>
/// Checks if either unit is EMPTY_UNIT. /// Checks if either unit is EMPTY_UNIT.
/// </summary> /// </summary>
bool UnitConverter::AnyUnitIsEmpty() bool UnitConverter::AnyUnitIsEmpty() const
{ {
return m_fromType == EMPTY_UNIT || m_toType == EMPTY_UNIT; return m_fromType == EMPTY_UNIT || m_toType == EMPTY_UNIT;
} }
@ -876,7 +879,7 @@ void UnitConverter::Calculate()
} }
unordered_map<Unit, ConversionData, UnitHash> conversionTable = m_ratioMap[m_fromType]; unordered_map<Unit, ConversionData, UnitHash> conversionTable = m_ratioMap[m_fromType];
if (AnyUnitIsEmpty() || (conversionTable[m_toType].ratio == 1.0 && conversionTable[m_toType].offset == 0.0)) if (AnyUnitIsEmpty() || conversionTable[m_toType].ratio == 1.0 && conversionTable[m_toType].offset == 0.0)
{ {
m_returnDisplay = m_currentDisplay; m_returnDisplay = m_currentDisplay;
m_returnHasDecimal = m_currentHasDecimal; m_returnHasDecimal = m_currentHasDecimal;
@ -884,11 +887,10 @@ void UnitConverter::Calculate()
} }
else else
{ {
double currentValue = stod(m_currentDisplay); const double currentValue = stod(m_currentDisplay);
const double returnValue = Convert(currentValue, conversionTable[m_toType]); const double returnValue = Convert(currentValue, conversionTable[m_toType]);
const auto isCurrencyConverter = m_currencyDataLoader != nullptr && m_currencyDataLoader->SupportsCategory(this->m_currentCategory); if (const auto isCurrencyConverter = m_currencyDataLoader != nullptr && m_currencyDataLoader->SupportsCategory(this->m_currentCategory))
if (isCurrencyConverter)
{ {
// We don't need to trim the value when it's a currency. // We don't need to trim the value when it's a currency.
m_returnDisplay = RoundSignificantDigits(returnValue, MAXIMUMDIGITSALLOWED); m_returnDisplay = RoundSignificantDigits(returnValue, MAXIMUMDIGITSALLOWED);
@ -897,7 +899,7 @@ void UnitConverter::Calculate()
else else
{ {
const unsigned int numPreDecimal = GetNumberDigitsWholeNumberPart(returnValue); const unsigned int numPreDecimal = GetNumberDigitsWholeNumberPart(returnValue);
if (numPreDecimal > MAXIMUMDIGITSALLOWED || (returnValue != 0 && abs(returnValue) < MINIMUMDECIMALALLOWED)) if (numPreDecimal > MAXIMUMDIGITSALLOWED || returnValue != 0 && abs(returnValue) < MINIMUMDECIMALALLOWED)
{ {
m_returnDisplay = ToScientificNumber(returnValue); m_returnDisplay = ToScientificNumber(returnValue);
} }
@ -913,30 +915,31 @@ void UnitConverter::Calculate()
{ {
// Fewer digits are needed following the decimal if the number is large, // Fewer digits are needed following the decimal if the number is large,
// we calculate the number of decimals necessary based on the number of digits in the integer part. // we calculate the number of decimals necessary based on the number of digits in the integer part.
auto numberDigits = max(OPTIMALDIGITSALLOWED, min(MAXIMUMDIGITSALLOWED, currentNumberSignificantDigits)); const auto numberDigits = max(OPTIMALDIGITSALLOWED, min(MAXIMUMDIGITSALLOWED, currentNumberSignificantDigits));
precision = numberDigits > numPreDecimal ? numberDigits - numPreDecimal : 0; precision = numberDigits > numPreDecimal ? numberDigits - numPreDecimal : 0;
} }
m_returnDisplay = RoundSignificantDigits(returnValue, precision); m_returnDisplay = RoundSignificantDigits(returnValue, precision);
TrimTrailingZeros(m_returnDisplay); TrimTrailingZeros(m_returnDisplay);
} }
m_returnHasDecimal = (m_returnDisplay.find(L'.') != wstring::npos); m_returnHasDecimal = m_returnDisplay.find(L'.') != wstring::npos;
} }
} }
UpdateViewModel(); UpdateViewModel();
} }
void UnitConverter::UpdateCurrencySymbols() void UnitConverter::UpdateCurrencySymbols() const
{ {
if (m_currencyDataLoader != nullptr && m_vmCurrencyCallback != nullptr) if (m_currencyDataLoader == nullptr || m_vmCurrencyCallback == nullptr)
{ {
shared_ptr<ICurrencyConverterDataLoader> currencyDataLoader = GetCurrencyConverterDataLoader(); return;
const pair<wstring, wstring> currencySymbols = currencyDataLoader->GetCurrencySymbols(m_fromType, m_toType);
const pair<wstring, wstring> currencyRatios = currencyDataLoader->GetCurrencyRatioEquality(m_fromType, m_toType);
m_vmCurrencyCallback->CurrencySymbolsCallback(currencySymbols.first, currencySymbols.second);
m_vmCurrencyCallback->CurrencyRatiosCallback(currencyRatios.first, currencyRatios.second);
} }
const shared_ptr<ICurrencyConverterDataLoader> currencyDataLoader = GetCurrencyConverterDataLoader();
const pair<wstring, wstring> currencySymbols = currencyDataLoader->GetCurrencySymbols(m_fromType, m_toType);
const pair<wstring, wstring> currencyRatios = currencyDataLoader->GetCurrencyRatioEquality(m_fromType, m_toType);
m_vmCurrencyCallback->CurrencySymbolsCallback(currencySymbols.first, currencySymbols.second);
m_vmCurrencyCallback->CurrencyRatiosCallback(currencyRatios.first, currencyRatios.second);
} }
void UnitConverter::UpdateViewModel() void UnitConverter::UpdateViewModel()

View file

@ -15,9 +15,8 @@ namespace UnitConversionManager
struct Unit struct Unit
{ {
Unit() Unit() = default;
{
}
Unit(int id, std::wstring_view name, std::wstring abbreviation, bool isConversionSource, bool isConversionTarget, bool isWhimsical) Unit(int id, std::wstring_view name, std::wstring abbreviation, bool isConversionSource, bool isConversionTarget, bool isWhimsical)
: id(id) : id(id)
, name(name) , name(name)
@ -43,8 +42,8 @@ namespace UnitConversionManager
, isConversionTarget(isConversionTarget) , isConversionTarget(isConversionTarget)
, isWhimsical(false) , isWhimsical(false)
{ {
auto nameValue1 = isRtlLanguage ? currencyName : countryName; const auto nameValue1 = isRtlLanguage ? currencyName : countryName;
auto nameValue2 = isRtlLanguage ? countryName : currencyName; const auto nameValue2 = isRtlLanguage ? countryName : currencyName;
name = nameValue1; name = nameValue1;
name.append(L" - ").append(nameValue2); name.append(L" - ").append(nameValue2);
@ -81,9 +80,7 @@ namespace UnitConversionManager
struct Category struct Category
{ {
Category() Category() = default;
{
}
Category(int id, std::wstring name, bool supportsNegative) Category(int id, std::wstring name, bool supportsNegative)
: id(id) : id(id)
@ -125,9 +122,8 @@ namespace UnitConversionManager
struct ConversionData struct ConversionData
{ {
ConversionData() ConversionData() = default;
{
}
ConversionData(double ratio, double offset, bool offsetFirst) ConversionData(double ratio, double offset, bool offsetFirst)
: ratio(ratio) : ratio(ratio)
, offset(offset) , offset(offset)
@ -156,18 +152,17 @@ namespace UnitConversionManager
std::wstring targetCurrencyCode; std::wstring targetCurrencyCode;
}; };
typedef std::tuple<std::vector<UnitConversionManager::Unit>, UnitConversionManager::Unit, UnitConversionManager::Unit> CategorySelectionInitializer; using CategorySelectionInitializer = std::tuple<std::vector<UnitConversionManager::Unit>, UnitConversionManager::Unit, UnitConversionManager::Unit>;
typedef std::unordered_map< using UnitToUnitToConversionDataMap = std::unordered_map<
UnitConversionManager::Unit, UnitConversionManager::Unit,
std::unordered_map<UnitConversionManager::Unit, UnitConversionManager::ConversionData, UnitConversionManager::UnitHash>, std::unordered_map<UnitConversionManager::Unit, UnitConversionManager::ConversionData, UnitConversionManager::UnitHash>,
UnitConversionManager::UnitHash> UnitConversionManager::UnitHash>;
UnitToUnitToConversionDataMap; using CategoryToUnitVectorMap = std::unordered_map<int, std::vector<UnitConversionManager::Unit>>;
typedef std::unordered_map<int, std::vector<UnitConversionManager::Unit>> CategoryToUnitVectorMap;
class IViewModelCurrencyCallback class IViewModelCurrencyCallback
{ {
public: public:
virtual ~IViewModelCurrencyCallback(){}; virtual ~IViewModelCurrencyCallback() = default;
virtual void CurrencyDataLoadFinished(bool didLoad) = 0; virtual void CurrencyDataLoadFinished(bool didLoad) = 0;
virtual void CurrencySymbolsCallback(_In_ const std::wstring& fromSymbol, _In_ const std::wstring& toSymbol) = 0; virtual void CurrencySymbolsCallback(_In_ const std::wstring& fromSymbol, _In_ const std::wstring& toSymbol) = 0;
virtual void CurrencyRatiosCallback(_In_ const std::wstring& ratioEquality, _In_ const std::wstring& accRatioEquality) = 0; virtual void CurrencyRatiosCallback(_In_ const std::wstring& ratioEquality, _In_ const std::wstring& accRatioEquality) = 0;
@ -178,7 +173,7 @@ namespace UnitConversionManager
class IConverterDataLoader class IConverterDataLoader
{ {
public: public:
virtual ~IConverterDataLoader(){}; virtual ~IConverterDataLoader() = default;
virtual void LoadData() = 0; // prepare data if necessary before calling other functions virtual void LoadData() = 0; // prepare data if necessary before calling other functions
virtual std::vector<Category> GetOrderedCategories() = 0; virtual std::vector<Category> GetOrderedCategories() = 0;
virtual std::vector<Unit> GetOrderedUnits(const Category& c) = 0; virtual std::vector<Unit> GetOrderedUnits(const Category& c) = 0;
@ -204,7 +199,7 @@ namespace UnitConversionManager
class IUnitConverterVMCallback class IUnitConverterVMCallback
{ {
public: public:
virtual ~IUnitConverterVMCallback(){}; virtual ~IUnitConverterVMCallback() = default;
virtual void DisplayCallback(const std::wstring& from, const std::wstring& to) = 0; virtual void DisplayCallback(const std::wstring& from, const std::wstring& to) = 0;
virtual void SuggestedValueCallback(const std::vector<std::tuple<std::wstring, Unit>>& suggestedValues) = 0; virtual void SuggestedValueCallback(const std::vector<std::tuple<std::wstring, Unit>>& suggestedValues) = 0;
virtual void MaxDigitsReached() = 0; virtual void MaxDigitsReached() = 0;
@ -213,9 +208,7 @@ namespace UnitConversionManager
class IUnitConverter class IUnitConverter
{ {
public: public:
virtual ~IUnitConverter() virtual ~IUnitConverter() = default;
{
}
virtual void Initialize() = 0; // Use to initialize first time, use deserialize instead to rehydrate virtual void Initialize() = 0; // Use to initialize first time, use deserialize instead to rehydrate
virtual std::vector<Category> GetCategories() = 0; virtual std::vector<Category> GetCategories() = 0;
virtual CategorySelectionInitializer SetCurrentCategory(const Category& input) = 0; virtual CategorySelectionInitializer SetCurrentCategory(const Category& input) = 0;
@ -263,21 +256,20 @@ namespace UnitConversionManager
private: private:
bool CheckLoad(); bool CheckLoad();
double Convert(double value, const ConversionData& conversionData); static double Convert(double value, const ConversionData& conversionData);
std::vector<std::tuple<std::wstring, Unit>> CalculateSuggested(); std::vector<std::tuple<std::wstring, Unit>> CalculateSuggested();
void ClearValues(); void ClearValues();
void InitializeSelectedUnits(); void InitializeSelectedUnits();
Category StringToCategory(std::wstring_view w); static Category StringToCategory(std::wstring_view w);
std::wstring CategoryToString(const Category& c, std::wstring_view delimiter); std::wstring CategoryToString(const Category& c, std::wstring_view delimiter) const;
std::wstring UnitToString(const Unit& u, std::wstring_view delimiter); std::wstring UnitToString(const Unit& u, std::wstring_view delimiter) const;
Unit StringToUnit(std::wstring_view w); static Unit StringToUnit(std::wstring_view w);
void UpdateCurrencySymbols(); void UpdateCurrencySymbols() const;
void UpdateViewModel(); void UpdateViewModel();
bool AnyUnitIsEmpty(); bool AnyUnitIsEmpty() const;
std::shared_ptr<IConverterDataLoader> GetDataLoaderForCategory(const Category& category); std::shared_ptr<IConverterDataLoader> GetDataLoaderForCategory(const Category& category);
std::shared_ptr<ICurrencyConverterDataLoader> GetCurrencyConverterDataLoader(); std::shared_ptr<ICurrencyConverterDataLoader> GetCurrencyConverterDataLoader() const;
private:
std::shared_ptr<IConverterDataLoader> m_dataLoader; std::shared_ptr<IConverterDataLoader> m_dataLoader;
std::shared_ptr<IConverterDataLoader> m_currencyDataLoader; std::shared_ptr<IConverterDataLoader> m_currencyDataLoader;
std::shared_ptr<IUnitConverterVMCallback> m_vmCallback; std::shared_ptr<IUnitConverterVMCallback> m_vmCallback;

View file

@ -288,9 +288,8 @@ bool CopyPasteManager::ExpressionRegExMatch(
} }
else if (mode == ViewMode::Programmer) else if (mode == ViewMode::Programmer)
{ {
patterns.assign( auto pattern = &programmerModePatterns[static_cast<int>(programmerNumberBase) - static_cast<int>(NumberBase::HexBase)];
programmerModePatterns[(int)programmerNumberBase - (int)NumberBase::HexBase].begin(), patterns.assign(pattern->begin(), pattern->end());
programmerModePatterns[(int)programmerNumberBase - (int)NumberBase::HexBase].end());
} }
else if (modeType == CategoryGroupType::Converter) else if (modeType == CategoryGroupType::Converter)
{ {
@ -505,18 +504,15 @@ ULONG32 CopyPasteManager::StandardScientificOperandLength(Platform::String ^ ope
const bool hasDecimal = operandWstring.find('.') != wstring::npos; const bool hasDecimal = operandWstring.find('.') != wstring::npos;
auto length = operandWstring.length(); auto length = operandWstring.length();
if (hasDecimal) if (hasDecimal && length >= 2)
{ {
if (length >= 2) if ((operandWstring[0] == L'0') && (operandWstring[1] == L'.'))
{ {
if ((operandWstring[0] == L'0') && (operandWstring[1] == L'.')) length -= 2;
{ }
length -= 2; else
} {
else length -= 1;
{
length -= 1;
}
} }
} }

View file

@ -171,7 +171,6 @@ IBox<DateDifference> ^ DateCalculationEngine::TryGetDateDifference(_In_ DateTime
if (static_cast<int>(outputFormat & dateUnit)) if (static_cast<int>(outputFormat & dateUnit))
{ {
bool isEndDateHit = false;
differenceInDates[unitIndex] = (daysDiff / daysIn[unitIndex]); differenceInDates[unitIndex] = (daysDiff / daysIn[unitIndex]);
if (differenceInDates[unitIndex] != 0) if (differenceInDates[unitIndex] != 0)
@ -188,11 +187,12 @@ IBox<DateDifference> ^ DateCalculationEngine::TryGetDateDifference(_In_ DateTime
} }
} }
int tempDaysDiff; for (;;)
do
{ {
tempDaysDiff = GetDifferenceInDays(pivotDate, endDate); int tempDaysDiff = GetDifferenceInDays(pivotDate, endDate);
if (tempDaysDiff == 0)
break;
if (tempDaysDiff < 0) if (tempDaysDiff < 0)
{ {
@ -205,30 +205,23 @@ IBox<DateDifference> ^ DateCalculationEngine::TryGetDateDifference(_In_ DateTime
differenceInDates[unitIndex] -= 1; differenceInDates[unitIndex] -= 1;
pivotDate = tempPivotDate; pivotDate = tempPivotDate;
pivotDate = AdjustCalendarDate(pivotDate, dateUnit, static_cast<int>(differenceInDates[unitIndex])); pivotDate = AdjustCalendarDate(pivotDate, dateUnit, static_cast<int>(differenceInDates[unitIndex]));
isEndDateHit = true; // This is the closest the pivot can get to the end date for this unit
break;
} }
else if (tempDaysDiff > 0)
{
if (isEndDateHit)
{
// This is the closest the pivot can get to the end date for this unit
break;
}
// pivotDate is still below the end date // pivotDate is still below the end date
try try
{ {
pivotDate = AdjustCalendarDate(tempPivotDate, dateUnit, static_cast<int>(differenceInDates[unitIndex] + 1)); pivotDate = AdjustCalendarDate(tempPivotDate, dateUnit, static_cast<int>(differenceInDates[unitIndex] + 1));
differenceInDates[unitIndex] += 1; differenceInDates[unitIndex] += 1;
}
catch (Platform::InvalidArgumentException ^)
{
// Operation failed due to out of bound result
// For example: 31st Dec, 9999 - last valid date
return nullptr;
}
} }
} while (tempDaysDiff != 0); // dates are the same - exit the loop catch (Platform::InvalidArgumentException ^)
{
// Operation failed due to out of bound result
// For example: 31st Dec, 9999 - last valid date
return nullptr;
}
}
tempPivotDate = AdjustCalendarDate(tempPivotDate, dateUnit, static_cast<int>(differenceInDates[unitIndex])); tempPivotDate = AdjustCalendarDate(tempPivotDate, dateUnit, static_cast<int>(differenceInDates[unitIndex]));
pivotDate = tempPivotDate; pivotDate = tempPivotDate;
@ -269,60 +262,52 @@ int DateCalculationEngine::GetDifferenceInDays(DateTime date1, DateTime date2)
// Returns true if successful, false otherwise. // Returns true if successful, false otherwise.
bool DateCalculationEngine::TryGetCalendarDaysInMonth(_In_ DateTime date, _Out_ UINT& daysInMonth) bool DateCalculationEngine::TryGetCalendarDaysInMonth(_In_ DateTime date, _Out_ UINT& daysInMonth)
{ {
bool result = false;
m_calendar->SetDateTime(date); m_calendar->SetDateTime(date);
// NumberOfDaysInThisMonth returns -1 if unknown. // NumberOfDaysInThisMonth returns -1 if unknown.
int daysInThisMonth = m_calendar->NumberOfDaysInThisMonth; int daysInThisMonth = m_calendar->NumberOfDaysInThisMonth;
if (daysInThisMonth != -1) if (daysInThisMonth == -1)
{ {
daysInMonth = static_cast<UINT>(daysInThisMonth); return false;
result = true;
} }
return result; daysInMonth = static_cast<UINT>(daysInThisMonth);
return true;
} }
// Gets number of Calendar days in the year in which this date falls. // Gets number of Calendar days in the year in which this date falls.
// Returns true if successful, false otherwise. // Returns true if successful, false otherwise.
bool DateCalculationEngine::TryGetCalendarDaysInYear(_In_ DateTime date, _Out_ UINT& daysInYear) bool DateCalculationEngine::TryGetCalendarDaysInYear(_In_ DateTime date, _Out_ UINT& daysInYear)
{ {
bool result = false;
UINT days = 0; UINT days = 0;
m_calendar->SetDateTime(date); m_calendar->SetDateTime(date);
// NumberOfMonthsInThisYear returns -1 if unknown. // NumberOfMonthsInThisYear returns -1 if unknown.
int monthsInYear = m_calendar->NumberOfMonthsInThisYear; int monthsInYear = m_calendar->NumberOfMonthsInThisYear;
if (monthsInYear != -1) if (monthsInYear == -1)
{ {
bool monthResult = true; return false;
// Not all years begin with Month 1.
int firstMonthThisYear = m_calendar->FirstMonthInThisYear;
for (int month = 0; month < monthsInYear; month++)
{
m_calendar->Month = firstMonthThisYear + month;
// NumberOfDaysInThisMonth returns -1 if unknown.
int daysInMonth = m_calendar->NumberOfDaysInThisMonth;
if (daysInMonth == -1)
{
monthResult = false;
break;
}
days += daysInMonth;
}
if (monthResult)
{
daysInYear = days;
result = true;
}
} }
return result; // Not all years begin with Month 1.
int firstMonthThisYear = m_calendar->FirstMonthInThisYear;
for (int month = 0; month < monthsInYear; month++)
{
m_calendar->Month = firstMonthThisYear + month;
// NumberOfDaysInThisMonth returns -1 if unknown.
int daysInMonth = m_calendar->NumberOfDaysInThisMonth;
if (daysInMonth == -1)
{
return false;
}
days += daysInMonth;
}
daysInYear = days;
return true;
} }
// Adds/Subtracts certain value for a particular date unit // Adds/Subtracts certain value for a particular date unit
@ -342,17 +327,17 @@ DateTime DateCalculationEngine::AdjustCalendarDate(Windows::Foundation::DateTime
m_calendar->ChangeCalendarSystem(CalendarIdentifiers::Gregorian); m_calendar->ChangeCalendarSystem(CalendarIdentifiers::Gregorian);
} }
switch (dateUnit) if (dateUnit == DateUnit::Year)
{ {
case DateUnit::Year:
m_calendar->AddYears(difference); m_calendar->AddYears(difference);
break; }
case DateUnit::Month: else if (dateUnit == DateUnit::Month)
{
m_calendar->AddMonths(difference); m_calendar->AddMonths(difference);
break; }
case DateUnit::Week: else if (dateUnit == DateUnit::Week)
{
m_calendar->AddWeeks(difference); m_calendar->AddWeeks(difference);
break;
} }
m_calendar->ChangeCalendarSystem(currentCalendarSystem); m_calendar->ChangeCalendarSystem(currentCalendarSystem);

View file

@ -39,8 +39,7 @@ namespace CalculatorApp
// 3;2;0 0x023 - group 1st 3 and then every 2 digits // 3;2;0 0x023 - group 1st 3 and then every 2 digits
// 4;0 0x004 - group every 4 digits // 4;0 0x004 - group every 4 digits
// 5;3;2;0 0x235 - group 5, then 3, then every 2 // 5;3;2;0 0x235 - group 5, then 3, then every 2
wstring numberGroupingString = localizationSettings->GetNumberGroupingStr(); return localizationSettings->GetNumberGroupingStr();
return numberGroupingString;
} }
StringReference idRef(id.data(), id.length()); StringReference idRef(id.data(), id.length());

View file

@ -17,24 +17,16 @@ std::shared_ptr<IExpressionCommand> CommandDeserializer::Deserialize(_In_ Calcul
switch (cmdType) switch (cmdType)
{ {
case CalculationManager::CommandType::OperandCommand: case CalculationManager::CommandType::OperandCommand:
return std::make_shared<COpndCommand>(DeserializeOperand()); return std::make_shared<COpndCommand>(DeserializeOperand());
break;
case CalculationManager::CommandType::Parentheses: case CalculationManager::CommandType::Parentheses:
return std::make_shared<CParentheses>(DeserializeParentheses()); return std::make_shared<CParentheses>(DeserializeParentheses());
break;
case CalculationManager::CommandType::UnaryCommand: case CalculationManager::CommandType::UnaryCommand:
return std::make_shared<CUnaryCommand>(DeserializeUnary()); return std::make_shared<CUnaryCommand>(DeserializeUnary());
break;
case CalculationManager::CommandType::BinaryCommand: case CalculationManager::CommandType::BinaryCommand:
return std::make_shared<CBinaryCommand>(DeserializeBinary()); return std::make_shared<CBinaryCommand>(DeserializeBinary());
break;
default: default:
throw ref new Platform::Exception(E_INVALIDARG, ref new Platform::String(L"Unknown command type")); throw ref new Platform::Exception(E_INVALIDARG, ref new Platform::String(L"Unknown command type"));
@ -50,7 +42,7 @@ COpndCommand CommandDeserializer::DeserializeOperand()
std::shared_ptr<std::vector<int>> cmdVector = std::make_shared<std::vector<int>>(); std::shared_ptr<std::vector<int>> cmdVector = std::make_shared<std::vector<int>>();
auto cmdVectorSize = m_dataReader->ReadUInt32(); auto cmdVectorSize = m_dataReader->ReadUInt32();
for (unsigned int j = 0; j < cmdVectorSize; ++j) for (auto j = cmdVectorSize; j > 0; --j)
{ {
int eachOpndcmd = m_dataReader->ReadInt32(); int eachOpndcmd = m_dataReader->ReadInt32();
cmdVector->push_back(eachOpndcmd); cmdVector->push_back(eachOpndcmd);

View file

@ -84,9 +84,9 @@ LocalizationService::LocalizationService(_In_ const wchar_t * const overridedLan
try try
{ {
// Convert wstring to string for locale // Convert wstring to string for locale
int size_needed = WideCharToMultiByte(CP_UTF8, 0, &localeName[0], (int)localeName.size(), NULL, 0, NULL, NULL); int size_needed = WideCharToMultiByte(CP_UTF8, 0, &localeName[0], static_cast<int>(localeName.size()), NULL, 0, NULL, NULL);
string localeNameStr(size_needed, 0); string localeNameStr(size_needed, 0);
WideCharToMultiByte(CP_UTF8, 0, &localeName[0], (int)localeName.size(), &localeNameStr[0], size_needed, NULL, NULL); WideCharToMultiByte(CP_UTF8, 0, &localeName[0], static_cast<int>(localeName.size()), &localeNameStr[0], size_needed, NULL, NULL);
m_locale = locale(localeNameStr.data()); m_locale = locale(localeNameStr.data());
} }

View file

@ -188,7 +188,6 @@ namespace CalculatorApp::ViewModel
return m_listSeparator; return m_listSeparator;
} }
private: private:
void Initialize(Windows::Globalization::NumberFormatting::DecimalFormatter ^ formatter) void Initialize(Windows::Globalization::NumberFormatting::DecimalFormatter ^ formatter)
{ {
@ -346,7 +345,7 @@ namespace CalculatorApp::ViewModel
int m_currencySymbolPrecedence; int m_currencySymbolPrecedence;
Platform::String ^ m_resolvedName; Platform::String ^ m_resolvedName;
int m_currencyTrailingDigits; int m_currencyTrailingDigits;
static const unsigned int LocaleSettingBufferSize = 16; static constexpr unsigned int LocaleSettingBufferSize = 16;
}; };
} }
} }

View file

@ -16,7 +16,7 @@ namespace CalculatorApp::ViewModel
{ {
std::wstring returnString = L""; std::wstring returnString = L"";
const UINT32 length = 1024; const UINT32 length = 1024;
std::unique_ptr<wchar_t[]> spBuffer = std::unique_ptr<wchar_t[]>(new wchar_t[length]); std::unique_ptr<wchar_t[]> spBuffer = std::make_unique<wchar_t[]>(length);
va_list args = NULL; va_list args = NULL;
va_start(args, pMessage); va_start(args, pMessage);
DWORD fmtReturnVal = FormatMessage(FORMAT_MESSAGE_FROM_STRING, pMessage->Data(), 0, 0, spBuffer.get(), length, &args); DWORD fmtReturnVal = FormatMessage(FORMAT_MESSAGE_FROM_STRING, pMessage->Data(), 0, 0, spBuffer.get(), length, &args);

View file

@ -104,7 +104,6 @@ namespace CalculatorApp
if (NavCategoryStates::IsValidViewMode(mode)) if (NavCategoryStates::IsValidViewMode(mode))
{ {
auto fields = ref new LoggingFields(); auto fields = ref new LoggingFields();
;
fields->AddString(StringReference(CALC_MODE), NavCategoryStates::GetFriendlyName(mode)); fields->AddString(StringReference(CALC_MODE), NavCategoryStates::GetFriendlyName(mode));
TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_MODE_CHANGED), fields); TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_MODE_CHANGED), fields);
} }

View file

@ -213,7 +213,7 @@ namespace Utils
template <typename T> template <typename T>
struct IsRefClass struct IsRefClass
{ {
static const bool value = __is_ref_class(T); static constexpr bool value = __is_ref_class(T);
}; };
template <typename T> template <typename T>

View file

@ -277,7 +277,7 @@ double CurrencyDataLoader::RoundCurrencyRatio(double ratio)
{ {
numberDecimals = max( numberDecimals = max(
FORMATTER_RATE_MIN_DECIMALS, FORMATTER_RATE_MIN_DECIMALS,
(int)(-log10(ratio)) + FORMATTER_RATE_MIN_SIGNIFICANT_DECIMALS); static_cast<int>(-log10(ratio)) + FORMATTER_RATE_MIN_SIGNIFICANT_DECIMALS);
} }
unsigned long long scale = (unsigned long long)powl(10l, numberDecimals); unsigned long long scale = (unsigned long long)powl(10l, numberDecimals);

View file

@ -45,7 +45,7 @@ DateCalculatorViewModel::DateCalculatorViewModel()
, m_StrDateResult(L"") , m_StrDateResult(L"")
, m_StrDateResultAutomationName(L"") , m_StrDateResultAutomationName(L"")
{ {
LocalizationSettings^ localizationSettings = LocalizationSettings::GetInstance(); LocalizationSettings ^ localizationSettings = LocalizationSettings::GetInstance();
// Initialize Date Output format instances // Initialize Date Output format instances
InitializeDateOutputFormats(localizationSettings->GetCalendarIdentifier()); InitializeDateOutputFormats(localizationSettings->GetCalendarIdentifier());
@ -74,7 +74,7 @@ DateCalculatorViewModel::DateCalculatorViewModel()
UpdateDisplayResult(); UpdateDisplayResult();
m_offsetValues = ref new Vector<String ^>(); m_offsetValues = ref new Vector<String ^>();
for (int i = 0; i <= c_maxOffsetValue; i++) for (unsigned int i = 0; i <= c_maxOffsetValue; i++)
{ {
wstring numberStr(to_wstring(i)); wstring numberStr(to_wstring(i));
localizationSettings->LocalizeDisplayValue(&numberStr); localizationSettings->LocalizeDisplayValue(&numberStr);
@ -157,10 +157,14 @@ void DateCalculatorViewModel::OnInputsChanged()
// Subtract number of Days, Months and Years from a Date // Subtract number of Days, Months and Years from a Date
dateTimeResult = m_dateCalcEngine->SubtractDuration(StartDate, dateDiff); dateTimeResult = m_dateCalcEngine->SubtractDuration(StartDate, dateDiff);
} }
IsOutOfBound = dateTimeResult == nullptr;
if (!m_isOutOfBound) if (dateTimeResult == nullptr)
{ {
IsOutOfBound = true;
}
else
{
IsOutOfBound = false;
DateResult = dateTimeResult->Value; DateResult = dateTimeResult->Value;
} }
} }
@ -254,13 +258,13 @@ String ^ DateCalculatorViewModel::GetDateDiffString() const
result += GetLocalizedNumberString(yearCount)->Data(); result += GetLocalizedNumberString(yearCount)->Data();
result += L' '; result += L' ';
if (yearCount > 1) if (yearCount == 1)
{ {
result += resourceLoader->GetResourceString(L"Date_Years")->Data(); result += resourceLoader->GetResourceString(L"Date_Year")->Data();
} }
else else
{ {
result += resourceLoader->GetResourceString(L"Date_Year")->Data(); result += resourceLoader->GetResourceString(L"Date_Years")->Data();
} }
// set the flags to add a delimiter whenever the next unit is added // set the flags to add a delimiter whenever the next unit is added
@ -282,13 +286,13 @@ String ^ DateCalculatorViewModel::GetDateDiffString() const
result += GetLocalizedNumberString(monthCount)->Data(); result += GetLocalizedNumberString(monthCount)->Data();
result += L' '; result += L' ';
if (monthCount > 1) if (monthCount == 1)
{ {
result += resourceLoader->GetResourceString(L"Date_Months")->Data(); result += resourceLoader->GetResourceString(L"Date_Month")->Data();
} }
else else
{ {
result += resourceLoader->GetResourceString(L"Date_Month")->Data(); result += resourceLoader->GetResourceString(L"Date_Months")->Data();
} }
} }
@ -307,13 +311,13 @@ String ^ DateCalculatorViewModel::GetDateDiffString() const
result += GetLocalizedNumberString(weekCount)->Data(); result += GetLocalizedNumberString(weekCount)->Data();
result += L' '; result += L' ';
if (weekCount > 1) if (weekCount == 1)
{ {
result += resourceLoader->GetResourceString(L"Date_Weeks")->Data(); result += resourceLoader->GetResourceString(L"Date_Week")->Data();
} }
else else
{ {
result += resourceLoader->GetResourceString(L"Date_Week")->Data(); result += resourceLoader->GetResourceString(L"Date_Weeks")->Data();
} }
} }
@ -332,13 +336,13 @@ String ^ DateCalculatorViewModel::GetDateDiffString() const
result += GetLocalizedNumberString(dayCount)->Data(); result += GetLocalizedNumberString(dayCount)->Data();
result += L' '; result += L' ';
if (dayCount > 1) if (dayCount == 1)
{ {
result += resourceLoader->GetResourceString(L"Date_Days")->Data(); result += resourceLoader->GetResourceString(L"Date_Day")->Data();
} }
else else
{ {
result += resourceLoader->GetResourceString(L"Date_Day")->Data(); result += resourceLoader->GetResourceString(L"Date_Days")->Data();
} }
} }
@ -351,13 +355,13 @@ String ^ DateCalculatorViewModel::GetDateDiffStringInDays() const
result += L' '; result += L' ';
// Display the result as '1 day' or 'N days' // Display the result as '1 day' or 'N days'
if (m_dateDiffResultInDays.day > 1) if (m_dateDiffResultInDays.day == 1)
{ {
result += AppResourceProvider::GetInstance()->GetResourceString(L"Date_Days")->Data(); result += AppResourceProvider::GetInstance()->GetResourceString(L"Date_Day")->Data();
} }
else else
{ {
result += AppResourceProvider::GetInstance()->GetResourceString(L"Date_Day")->Data(); result += AppResourceProvider::GetInstance()->GetResourceString(L"Date_Days")->Data();
} }
return ref new String(result.data()); return ref new String(result.data());
@ -365,14 +369,7 @@ String ^ DateCalculatorViewModel::GetDateDiffStringInDays() const
void DateCalculatorViewModel::OnCopyCommand(Platform::Object ^ parameter) void DateCalculatorViewModel::OnCopyCommand(Platform::Object ^ parameter)
{ {
if (m_IsDateDiffMode) CopyPasteManager::CopyToClipboard(m_IsDateDiffMode ? m_StrDateDiffResult : m_StrDateResult);
{
CopyPasteManager::CopyToClipboard(m_StrDateDiffResult);
}
else
{
CopyPasteManager::CopyToClipboard(m_StrDateResult);
}
} }
String ^ DateCalculatorViewModel::GetLocalizedNumberString(int value) const String ^ DateCalculatorViewModel::GetLocalizedNumberString(int value) const
@ -393,15 +390,13 @@ DateTime DateCalculatorViewModel::ClipTime(DateTime dateTime, bool adjustUsingLo
if (adjustUsingLocalTime) if (adjustUsingLocalTime)
{ {
FILETIME fileTime; FILETIME fileTime;
fileTime.dwLowDateTime = (DWORD)(dateTime.UniversalTime & 0xffffffff); fileTime.dwLowDateTime = static_cast<DWORD>(dateTime.UniversalTime & 0xffffffff);
fileTime.dwHighDateTime = (DWORD)(dateTime.UniversalTime >> 32); fileTime.dwHighDateTime = static_cast<DWORD>(dateTime.UniversalTime >> 32);
FILETIME localFileTime; FILETIME localFileTime;
FileTimeToLocalFileTime(&fileTime, &localFileTime); FileTimeToLocalFileTime(&fileTime, &localFileTime);
referenceDateTime.UniversalTime = (DWORD)localFileTime.dwHighDateTime; referenceDateTime.UniversalTime = (static_cast<INT64>(localFileTime.dwHighDateTime) << 32) | localFileTime.dwLowDateTime;
referenceDateTime.UniversalTime <<= 32;
referenceDateTime.UniversalTime |= (DWORD)localFileTime.dwLowDateTime;
} }
else else
{ {

View file

@ -6,7 +6,7 @@
#include "Common/Utils.h" #include "Common/Utils.h"
#include "Common/DateCalculator.h" #include "Common/DateCalculator.h"
const int c_maxOffsetValue = 999; constexpr unsigned int c_maxOffsetValue = 999;
namespace CalculatorApp namespace CalculatorApp
{ {

View file

@ -30,9 +30,9 @@ void GraphingSettingsViewModel::SetGrapher(Grapher ^ grapher)
{ {
if (grapher != nullptr) if (grapher != nullptr)
{ {
if (grapher->TrigUnitMode == (int)Graphing::EvalTrigUnitMode::Invalid) if (grapher->TrigUnitMode == static_cast<int>(Graphing::EvalTrigUnitMode::Invalid))
{ {
grapher->TrigUnitMode = (int)Graphing::EvalTrigUnitMode::Radians; grapher->TrigUnitMode = static_cast<int>(Graphing::EvalTrigUnitMode::Radians);
} }
} }
Graph = grapher; Graph = grapher;

View file

@ -116,13 +116,13 @@ void HistoryViewModel::ShowItem(_In_ HistoryItemViewModel ^ e)
{ {
unsigned int index; unsigned int index;
Items->IndexOf(e, &index); Items->IndexOf(e, &index);
TraceLogger::GetInstance()->LogHistoryItemLoad((ViewMode)m_currentMode, Items->Size, (int)(index)); TraceLogger::GetInstance()->LogHistoryItemLoad((ViewMode)m_currentMode, Items->Size, static_cast<int>(index));
HistoryItemClicked(e); HistoryItemClicked(e);
} }
void HistoryViewModel::DeleteItem(_In_ HistoryItemViewModel ^ e) void HistoryViewModel::DeleteItem(_In_ HistoryItemViewModel ^ e)
{ {
uint32_t itemIndex; unsigned int itemIndex;
if (Items->IndexOf(e, &itemIndex)) if (Items->IndexOf(e, &itemIndex))
{ {
if (m_calculatorManager->RemoveHistoryItem(itemIndex)) if (m_calculatorManager->RemoveHistoryItem(itemIndex))

View file

@ -1552,7 +1552,7 @@ wstring StandardCalculatorViewModel::AddPadding(wstring binaryString)
{ {
return binaryString; return binaryString;
} }
size_t pad = 4 - LengthWithoutPadding(binaryString) % 4; size_t pad = 4 - (LengthWithoutPadding(binaryString) & 3);
if (pad == 4) if (pad == 4)
{ {
pad = 0; pad = 0;

View file

@ -277,7 +277,7 @@ void UnitConverterViewModel::OnSwitchActive(Platform::Object ^ unused)
String ^ UnitConverterViewModel::ConvertToLocalizedString(const std::wstring& stringToLocalize, bool allowPartialStrings, CurrencyFormatterParameter cfp) String ^ UnitConverterViewModel::ConvertToLocalizedString(const std::wstring& stringToLocalize, bool allowPartialStrings, CurrencyFormatterParameter cfp)
{ {
Platform::String ^ result; Platform::String ^ result = nullptr;
if (stringToLocalize.empty()) if (stringToLocalize.empty())
{ {
@ -693,7 +693,8 @@ void UnitConverterViewModel::RefreshCurrencyRatios()
auto that(this); auto that(this);
auto refreshTask = create_task([that] { return that->m_model->RefreshCurrencyRatios().get(); }); auto refreshTask = create_task([that] { return that->m_model->RefreshCurrencyRatios().get(); });
refreshTask.then( refreshTask.then(
[that](const pair<bool, wstring>& refreshResult) { [that](const pair<bool, wstring>& refreshResult)
{
bool didLoad = refreshResult.first; bool didLoad = refreshResult.first;
wstring timestamp = refreshResult.second; wstring timestamp = refreshResult.second;

View file

@ -42,14 +42,3 @@
#include "winrt/Windows.UI.Xaml.h" #include "winrt/Windows.UI.Xaml.h"
#include "winrt/Windows.Foundation.Metadata.h" #include "winrt/Windows.Foundation.Metadata.h"
#include "winrt/Windows.Management.Policies.h" #include "winrt/Windows.Management.Policies.h"
// The following namespaces exist as a convenience to resolve
// ambiguity for Windows types in the Windows::UI::Xaml::Automation::Peers
// namespace that only exist on RS3.
// Once the app switches to min version RS3, the namespaces can be removed.
// TODO - MSFT 12735088
namespace StandardPeers = Windows::UI::Xaml::Automation::Peers;
namespace CalculatorApp::ViewModel::Common::Automation
{
}
namespace CustomPeers = CalculatorApp::ViewModel::Common::Automation;

View file

@ -16,9 +16,7 @@ namespace DateCalculationUnitTests
SystemTimeToFileTime(&systemTime, lpFileTime); SystemTimeToFileTime(&systemTime, lpFileTime);
Windows::Foundation::DateTime dateTime; Windows::Foundation::DateTime dateTime;
dateTime.UniversalTime = (DWORD)lpFileTime->dwHighDateTime; dateTime.UniversalTime = (static_cast<INT64>(lpFileTime->dwHighDateTime) << 32) | (lpFileTime->dwLowDateTime);
dateTime.UniversalTime <<= 32;
dateTime.UniversalTime |= (DWORD)lpFileTime->dwLowDateTime;
return dateTime; return dateTime;
} }
@ -28,8 +26,8 @@ namespace DateCalculationUnitTests
static SYSTEMTIME DateTimeToSystemTime(Windows::Foundation::DateTime dateTime) static SYSTEMTIME DateTimeToSystemTime(Windows::Foundation::DateTime dateTime)
{ {
FILETIME fileTime; FILETIME fileTime;
fileTime.dwLowDateTime = (DWORD)(dateTime.UniversalTime & 0xffffffff); fileTime.dwLowDateTime = static_cast<DWORD>(dateTime.UniversalTime & 0xffffffff);
fileTime.dwHighDateTime = (DWORD)(dateTime.UniversalTime >> 32); fileTime.dwHighDateTime = static_cast<DWORD>(dateTime.UniversalTime >> 32);
SYSTEMTIME systemTime; SYSTEMTIME systemTime;
FileTimeToSystemTime(&fileTime, &systemTime); FileTimeToSystemTime(&fileTime, &systemTime);

View file

@ -83,12 +83,12 @@ namespace CalculatorFunctionalTests
void AddSingleHistoryItem() void AddSingleHistoryItem()
{ {
Initialize(); Initialize();
int initialSize = m_historyViewModel->ItemsCount; auto initialSize = m_historyViewModel->ItemsCount;
m_standardViewModel->SendCommandToCalcManager(static_cast<int>(Command::Command1)); m_standardViewModel->SendCommandToCalcManager(static_cast<int>(Command::Command1));
m_standardViewModel->SendCommandToCalcManager(static_cast<int>(Command::CommandADD)); m_standardViewModel->SendCommandToCalcManager(static_cast<int>(Command::CommandADD));
m_standardViewModel->SendCommandToCalcManager(static_cast<int>(Command::Command8)); m_standardViewModel->SendCommandToCalcManager(static_cast<int>(Command::Command8));
m_standardViewModel->SendCommandToCalcManager(static_cast<int>(Command::CommandEQU)); m_standardViewModel->SendCommandToCalcManager(static_cast<int>(Command::CommandEQU));
int sizeAfterItemAdd = m_historyViewModel->ItemsCount; auto sizeAfterItemAdd = m_historyViewModel->ItemsCount;
auto historyItem = static_cast<HistoryItemViewModel ^>(m_historyViewModel->Items->GetAt(0)); auto historyItem = static_cast<HistoryItemViewModel ^>(m_historyViewModel->Items->GetAt(0));
String ^ expression = L"1 + 8 ="; String ^ expression = L"1 + 8 =";
VERIFY_ARE_EQUAL(initialSize + 1, sizeAfterItemAdd); VERIFY_ARE_EQUAL(initialSize + 1, sizeAfterItemAdd);
@ -143,7 +143,7 @@ namespace CalculatorFunctionalTests
Command nextCommand = Command(130 + i); Command nextCommand = Command(130 + i);
m_standardViewModel->SendCommandToCalcManager(static_cast<int>(Command::Command1)); m_standardViewModel->SendCommandToCalcManager(static_cast<int>(Command::Command1));
m_standardViewModel->SendCommandToCalcManager(static_cast<int>(Command::CommandADD)); m_standardViewModel->SendCommandToCalcManager(static_cast<int>(Command::CommandADD));
m_standardViewModel->SendCommandToCalcManager((int)nextCommand); m_standardViewModel->SendCommandToCalcManager(static_cast<int>(nextCommand));
m_standardViewModel->SendCommandToCalcManager(static_cast<int>(Command::CommandEQU)); m_standardViewModel->SendCommandToCalcManager(static_cast<int>(Command::CommandEQU));
} }
@ -154,7 +154,7 @@ namespace CalculatorFunctionalTests
Command nextCommand = Command(130 + i); Command nextCommand = Command(130 + i);
m_standardViewModel->SendCommandToCalcManager(static_cast<int>(Command::Command1)); m_standardViewModel->SendCommandToCalcManager(static_cast<int>(Command::Command1));
m_standardViewModel->SendCommandToCalcManager(static_cast<int>(Command::CommandADD)); m_standardViewModel->SendCommandToCalcManager(static_cast<int>(Command::CommandADD));
m_standardViewModel->SendCommandToCalcManager((int)nextCommand); m_standardViewModel->SendCommandToCalcManager(static_cast<int>(nextCommand));
m_standardViewModel->SendCommandToCalcManager(static_cast<int>(Command::CommandEQU)); m_standardViewModel->SendCommandToCalcManager(static_cast<int>(Command::CommandEQU));
} }
@ -164,7 +164,7 @@ namespace CalculatorFunctionalTests
for (int i = 0; i < scientificItems; i++) for (int i = 0; i < scientificItems; i++)
{ {
wstring expr = L"1 + " + wstring(i.ToString()->Data()) + L" ="; wstring expr = L"1 + " + wstring(i.ToString()->Data()) + L" =";
int output = 1 + i; auto output = 1 + i;
String ^ result = output.ToString(); String ^ result = output.ToString();
auto historyItem = static_cast<HistoryItemViewModel ^>(m_historyViewModel->Items->GetAt(m_historyViewModel->ItemsCount - 1 - i)); auto historyItem = static_cast<HistoryItemViewModel ^>(m_historyViewModel->Items->GetAt(m_historyViewModel->ItemsCount - 1 - i));
VERIFY_ARE_EQUAL(historyItem->Expression, StringReference(expr.c_str())); VERIFY_ARE_EQUAL(historyItem->Expression, StringReference(expr.c_str()));
@ -177,7 +177,7 @@ namespace CalculatorFunctionalTests
for (int i = 0; i < standardItems; i++) for (int i = 0; i < standardItems; i++)
{ {
wstring expr = L"1 + " + wstring(i.ToString()->Data()) + L" ="; wstring expr = L"1 + " + wstring(i.ToString()->Data()) + L" =";
int output = 1 + i; auto output = 1 + i;
String ^ result = output.ToString(); String ^ result = output.ToString();
auto historyItem = static_cast<HistoryItemViewModel ^>(m_historyViewModel->Items->GetAt(m_historyViewModel->ItemsCount - 1 - i)); auto historyItem = static_cast<HistoryItemViewModel ^>(m_historyViewModel->Items->GetAt(m_historyViewModel->ItemsCount - 1 - i));
VERIFY_ARE_EQUAL(historyItem->Expression, StringReference(expr.c_str())); VERIFY_ARE_EQUAL(historyItem->Expression, StringReference(expr.c_str()));
@ -210,16 +210,16 @@ namespace CalculatorFunctionalTests
Command commands[] = { Command::CommandSIN, Command::CommandCOS, Command::CommandTAN, Command commands[] = { Command::CommandSIN, Command::CommandCOS, Command::CommandTAN,
Command::CommandASIN, Command::CommandACOS, Command::CommandATAN }; Command::CommandASIN, Command::CommandACOS, Command::CommandATAN };
Command mode[] = { Command::CommandDEG, Command::CommandRAD, Command::CommandGRAD }; Command mode[] = { Command::CommandDEG, Command::CommandRAD, Command::CommandGRAD };
int modes = sizeof(mode) / sizeof(Command); size_t modes = sizeof(mode) / sizeof(Command);
int commandsSize = sizeof(commands) / sizeof(Command); size_t commandsSize = sizeof(commands) / sizeof(Command);
ResourceLoader ^ m_uiResourceLoader = ResourceLoader::GetForViewIndependentUse(L"CEngineStrings"); ResourceLoader ^ m_uiResourceLoader = ResourceLoader::GetForViewIndependentUse(L"CEngineStrings");
int itemIndex = 0; int itemIndex = 0;
int commandResource = 67; int commandResource = 67;
m_standardViewModel->SendCommandToCalcManager(static_cast<int>(Command::ModeScientific)); m_standardViewModel->SendCommandToCalcManager(static_cast<int>(Command::ModeScientific));
for (int index = 0; index < modes; index++) for (size_t index = 0; index < modes; index++)
{ {
m_standardViewModel->SendCommandToCalcManager((int)mode[index]); m_standardViewModel->SendCommandToCalcManager(static_cast<int>(mode[index]));
for (int command = 0; command < commandsSize; command++) for (size_t command = 0; command < commandsSize; command++)
{ {
m_standardViewModel->SendCommandToCalcManager(static_cast<int>(Command::Command1)); m_standardViewModel->SendCommandToCalcManager(static_cast<int>(Command::Command1));
m_standardViewModel->SendCommandToCalcManager(static_cast<int>(commands[command])); m_standardViewModel->SendCommandToCalcManager(static_cast<int>(commands[command]));
@ -390,13 +390,13 @@ namespace CalculatorFunctionalTests
void HistoryStandardOrderOfOperationsHelper(String ^ expectedResult, String ^ expectedExpression, Command testCommands[]) void HistoryStandardOrderOfOperationsHelper(String ^ expectedResult, String ^ expectedExpression, Command testCommands[])
{ {
Initialize(); Initialize();
int initialSize = m_historyViewModel->ItemsCount; auto initialSize = m_historyViewModel->ItemsCount;
Command* currentCommand = testCommands; Command* currentCommand = testCommands;
while (*currentCommand != Command::CommandNULL) while (*currentCommand != Command::CommandNULL)
{ {
m_standardViewModel->SendCommandToCalcManager(static_cast<int>(*currentCommand++)); m_standardViewModel->SendCommandToCalcManager(static_cast<int>(*currentCommand++));
} }
int sizeAfterCommandsAdd = m_historyViewModel->ItemsCount; auto sizeAfterCommandsAdd = m_historyViewModel->ItemsCount;
if (expectedResult->IsEmpty()) if (expectedResult->IsEmpty())
{ {
VERIFY_ARE_EQUAL(initialSize, sizeAfterCommandsAdd); VERIFY_ARE_EQUAL(initialSize, sizeAfterCommandsAdd);
@ -554,13 +554,13 @@ namespace CalculatorFunctionalTests
Initialize(); Initialize();
Command commands[] = { Command::Command1, Command::CommandMUL, Command::Command2, Command::CommandMUL, Command::Command3, Command commands[] = { Command::Command1, Command::CommandMUL, Command::Command2, Command::CommandMUL, Command::Command3,
Command::CommandMUL, Command::Command4, Command::CommandMUL, Command::Command5, Command::CommandMUL, Command::CommandNULL }; Command::CommandMUL, Command::Command4, Command::CommandMUL, Command::Command5, Command::CommandMUL, Command::CommandNULL };
int initialSize = m_historyViewModel->ItemsCount; auto initialSize = m_historyViewModel->ItemsCount;
Command* currentCommand = commands; Command* currentCommand = commands;
while (*currentCommand != Command::CommandNULL) while (*currentCommand != Command::CommandNULL)
{ {
m_standardViewModel->SendCommandToCalcManager(static_cast<int>(*currentCommand++)); m_standardViewModel->SendCommandToCalcManager(static_cast<int>(*currentCommand++));
} }
int sizeAfterCommandsAdd = m_historyViewModel->ItemsCount; auto sizeAfterCommandsAdd = m_historyViewModel->ItemsCount;
VERIFY_ARE_EQUAL(initialSize + 4, sizeAfterCommandsAdd); VERIFY_ARE_EQUAL(initialSize + 4, sizeAfterCommandsAdd);
auto historyItem = static_cast<HistoryItemViewModel ^>(m_historyViewModel->Items->GetAt(0)); auto historyItem = static_cast<HistoryItemViewModel ^>(m_historyViewModel->Items->GetAt(0));
VERIFY_ARE_EQUAL(historyItem->Expression, L"24 \x00D7 5 ="); VERIFY_ARE_EQUAL(historyItem->Expression, L"24 \x00D7 5 =");

View file

@ -728,7 +728,7 @@ namespace CalculatorUnitTests
viewModel->DisplayValue = L"1001"; viewModel->DisplayValue = L"1001";
viewModel->OnMemoryButtonPressed(); viewModel->OnMemoryButtonPressed();
viewModel->OnMemoryButtonPressed(); viewModel->OnMemoryButtonPressed();
VERIFY_ARE_EQUAL((int)viewModel->MemorizedNumbers->Size, 2); VERIFY_ARE_EQUAL(viewModel->MemorizedNumbers->Size, 2);
} }
// When memory list is empty and M+ is pressed // When memory list is empty and M+ is pressed
@ -900,7 +900,7 @@ namespace CalculatorUnitTests
{ {
viewModel->OnMemoryButtonPressed(); viewModel->OnMemoryButtonPressed();
} }
VERIFY_ARE_EQUAL((int)viewModel->MemorizedNumbers->Size, 100); VERIFY_ARE_EQUAL(viewModel->MemorizedNumbers->Size, 100);
} }
// When memory slot is pressed verify if the display value is updated correctly // When memory slot is pressed verify if the display value is updated correctly

View file

@ -33,7 +33,7 @@ TEST_METHOD(IsLastCharacterFailureEmptyInput)
TEST_METHOD(IsLastCharacterFailureNullTarget) TEST_METHOD(IsLastCharacterFailureNullTarget)
{ {
VERIFY_IS_FALSE(Utils::IsLastCharacterTarget({}, NULL)); VERIFY_IS_FALSE(Utils::IsLastCharacterTarget({}, L'\0'));
} }
} }
; ;

View file

@ -231,14 +231,10 @@ namespace GraphControl
{ {
return; return;
} }
bool keepCurrentView = true;
// If the equation has changed, the IsLineEnabled state is reset. // If the equation has changed, the IsLineEnabled state is reset.
// This checks if the equation has been reset and sets keepCurrentView to false in this case. // This checks if the equation has been reset and sets keepCurrentView to false in this case.
if (!equation->HasGraphError && !equation->IsValidated && equation->IsLineEnabled) const bool keepCurrentView = equation->HasGraphError || equation->IsValidated || !equation->IsLineEnabled;
{
keepCurrentView = false;
}
PlotGraph(keepCurrentView); PlotGraph(keepCurrentView);
} }
@ -301,8 +297,8 @@ namespace GraphControl
} }
} }
int valid = 0; unsigned int valid = 0;
int invalid = 0; unsigned int invalid = 0;
for (Equation ^ eq : Equations) for (Equation ^ eq : Equations)
{ {
if (eq->HasGraphError) if (eq->HasGraphError)
@ -396,7 +392,7 @@ namespace GraphControl
{ {
auto graphedEquations = initResult.value(); auto graphedEquations = initResult.value();
for (int i = 0; i < validEqs.size(); i++) for (size_t i = 0; i < validEqs.size(); i++)
{ {
validEqs[i]->GraphedEquation = graphedEquations[i]; validEqs[i]->GraphedEquation = graphedEquations[i];
} }
@ -557,13 +553,15 @@ namespace GraphControl
if (m_graph != nullptr && m_renderMain != nullptr) if (m_graph != nullptr && m_renderMain != nullptr)
{ {
auto workItemHandler = ref new WorkItemHandler([this, variableName, newValue](IAsyncAction ^ action) { auto workItemHandler = ref new WorkItemHandler(
m_renderMain->GetCriticalSection().lock(); [this, variableName, newValue](IAsyncAction ^ action)
m_graph->SetArgValue(variableName->Data(), newValue); {
m_renderMain->GetCriticalSection().unlock(); m_renderMain->GetCriticalSection().lock();
m_graph->SetArgValue(variableName->Data(), newValue);
m_renderMain->GetCriticalSection().unlock();
m_renderMain->RunRenderPass(); m_renderMain->RunRenderPass();
}); });
ThreadPool::RunAsync(workItemHandler, WorkItemPriority::High, WorkItemOptions::None); ThreadPool::RunAsync(workItemHandler, WorkItemPriority::High, WorkItemOptions::None);
} }
@ -618,7 +616,7 @@ namespace GraphControl
return validEqs; return validEqs;
} }
void Grapher::OnForceProportionalAxesPropertyChanged(bool /*oldValue*/, bool newValue) void Grapher::OnForceProportionalAxesPropertyChanged(bool oldValue [[maybe_unused]], bool newValue)
{ {
m_calculatedForceProportional = newValue; m_calculatedForceProportional = newValue;
TryUpdateGraph(false); TryUpdateGraph(false);
@ -842,7 +840,7 @@ namespace GraphControl
{ {
// Get the raw data // Get the raw data
vector<BYTE> byteVector = BitmapOut->GetData(); vector<BYTE> byteVector = BitmapOut->GetData();
auto arr = ArrayReference<BYTE>(byteVector.data(), (unsigned int)byteVector.size()); auto arr = ArrayReference<BYTE>(byteVector.data(), static_cast<unsigned int>(byteVector.size()));
// create a memory stream wrapper // create a memory stream wrapper
InMemoryRandomAccessStream ^ stream = ref new InMemoryRandomAccessStream(); InMemoryRandomAccessStream ^ stream = ref new InMemoryRandomAccessStream();
@ -880,18 +878,7 @@ void Grapher::OnCoreKeyUp(CoreWindow ^ sender, KeyEventArgs ^ e)
return; return;
} }
switch (e->VirtualKey) HandleKey(e->VirtualKey);
{
case VirtualKey::Left:
case VirtualKey::Right:
case VirtualKey::Down:
case VirtualKey::Up:
case VirtualKey::Shift:
{
HandleKey(false, e->VirtualKey);
}
break;
}
} }
void Grapher::OnCoreKeyDown(CoreWindow ^ sender, KeyEventArgs ^ e) void Grapher::OnCoreKeyDown(CoreWindow ^ sender, KeyEventArgs ^ e)
@ -904,61 +891,59 @@ void Grapher::OnCoreKeyDown(CoreWindow ^ sender, KeyEventArgs ^ e)
return; return;
} }
switch (e->VirtualKey) HandleKeyDown(e->VirtualKey);
}
void Grapher::HandleKey(VirtualKey key)
{
switch (key)
{ {
case VirtualKey::Left: case VirtualKey::Left:
m_KeysPressed[KeysPressedSlots::Left] = false;
break;
case VirtualKey::Right: case VirtualKey::Right:
case VirtualKey::Down: m_KeysPressed[KeysPressedSlots::Right] = false;
break;
case VirtualKey::Up: case VirtualKey::Up:
m_KeysPressed[KeysPressedSlots::Up] = false;
break;
case VirtualKey::Down:
m_KeysPressed[KeysPressedSlots::Down] = false;
break;
case VirtualKey::Shift: case VirtualKey::Shift:
{ m_KeysPressed[KeysPressedSlots::Accelerator] = false;
HandleKey(true, e->VirtualKey); break;
}
break;
} }
} }
void Grapher::HandleKey(bool keyDown, VirtualKey key) void Grapher::HandleKeyDown(VirtualKey key)
{ {
int pressedKeys = 0; bool pressedKey;
if (key == VirtualKey::Left) switch (key)
{ {
m_KeysPressed[KeysPressedSlots::Left] = keyDown; case VirtualKey::Left:
if (keyDown) m_KeysPressed[KeysPressedSlots::Left] = true;
{ pressedKey = true;
pressedKeys++; break;
} case VirtualKey::Right:
} m_KeysPressed[KeysPressedSlots::Right] = true;
if (key == VirtualKey::Right) pressedKey = true;
{ break;
m_KeysPressed[KeysPressedSlots::Right] = keyDown; case VirtualKey::Up:
if (keyDown) m_KeysPressed[KeysPressedSlots::Up] = true;
{ pressedKey = true;
pressedKeys++; break;
} case VirtualKey::Down:
} m_KeysPressed[KeysPressedSlots::Down] = true;
if (key == VirtualKey::Up) pressedKey = true;
{ break;
m_KeysPressed[KeysPressedSlots::Up] = keyDown; case VirtualKey::Shift:
if (keyDown) m_KeysPressed[KeysPressedSlots::Accelerator] = true;
{ pressedKey = true;
pressedKeys++; break;
}
}
if (key == VirtualKey::Down)
{
m_KeysPressed[KeysPressedSlots::Down] = keyDown;
if (keyDown)
{
pressedKeys++;
}
}
if (key == VirtualKey::Shift)
{
m_KeysPressed[KeysPressedSlots::Accelerator] = keyDown;
} }
if (pressedKeys > 0 && !m_Moving) if (pressedKey && !m_Moving)
{ {
m_Moving = true; m_Moving = true;
// Key(s) we care about, so ensure we are ticking our timer (and that we have one to tick) // Key(s) we care about, so ensure we are ticking our timer (and that we have one to tick)
@ -970,7 +955,6 @@ void Grapher::HandleKey(bool keyDown, VirtualKey key)
TimeSpan ts; TimeSpan ts;
ts.Duration = 100000; // .1 second ts.Duration = 100000; // .1 second
m_TracingTrackingTimer->Interval = ts; m_TracingTrackingTimer->Interval = ts;
auto i = m_TracingTrackingTimer->Interval;
} }
m_TracingTrackingTimer->Start(); m_TracingTrackingTimer->Start();
} }
@ -979,7 +963,7 @@ void Grapher::HandleKey(bool keyDown, VirtualKey key)
void Grapher::HandleTracingMovementTick(Object ^ sender, Object ^ e) void Grapher::HandleTracingMovementTick(Object ^ sender, Object ^ e)
{ {
int delta = 5; int delta = 5;
int liveKeys = 0; bool liveKeys = false;
if (m_KeysPressed[KeysPressedSlots::Accelerator]) if (m_KeysPressed[KeysPressedSlots::Accelerator])
{ {
@ -990,7 +974,7 @@ void Grapher::HandleTracingMovementTick(Object ^ sender, Object ^ e)
if (m_KeysPressed[KeysPressedSlots::Left]) if (m_KeysPressed[KeysPressedSlots::Left])
{ {
liveKeys++; liveKeys = true;
curPos.X -= delta; curPos.X -= delta;
if (curPos.X < 0) if (curPos.X < 0)
{ {
@ -998,9 +982,9 @@ void Grapher::HandleTracingMovementTick(Object ^ sender, Object ^ e)
} }
} }
if (m_KeysPressed[KeysPressedSlots::Right]) else if (m_KeysPressed[KeysPressedSlots::Right])
{ {
liveKeys++; liveKeys = true;
curPos.X += delta; curPos.X += delta;
if (curPos.X > ActualWidth - delta) if (curPos.X > ActualWidth - delta)
{ {
@ -1010,7 +994,7 @@ void Grapher::HandleTracingMovementTick(Object ^ sender, Object ^ e)
if (m_KeysPressed[KeysPressedSlots::Up]) if (m_KeysPressed[KeysPressedSlots::Up])
{ {
liveKeys++; liveKeys = true;
curPos.Y -= delta; curPos.Y -= delta;
if (curPos.Y < 0) if (curPos.Y < 0)
{ {
@ -1018,9 +1002,9 @@ void Grapher::HandleTracingMovementTick(Object ^ sender, Object ^ e)
} }
} }
if (m_KeysPressed[KeysPressedSlots::Down]) else if (m_KeysPressed[KeysPressedSlots::Down])
{ {
liveKeys++; liveKeys = true;
curPos.Y += delta; curPos.Y += delta;
if (curPos.Y > ActualHeight - delta) if (curPos.Y > ActualHeight - delta)
{ {
@ -1028,18 +1012,18 @@ void Grapher::HandleTracingMovementTick(Object ^ sender, Object ^ e)
} }
} }
if (liveKeys == 0) if (liveKeys)
{
ActiveTraceCursorPosition = curPos;
PointerValueChangedEvent(curPos);
}
else
{ {
m_Moving = false; m_Moving = false;
// Non of the keys we care about are being hit any longer so shut down our timer // Non of the keys we care about are being hit any longer so shut down our timer
m_TracingTrackingTimer->Stop(); m_TracingTrackingTimer->Stop();
} }
else
{
ActiveTraceCursorPosition = curPos;
PointerValueChangedEvent(curPos);
}
} }
String ^ Grapher::ConvertToLinear(String ^ mmlString) String ^ Grapher::ConvertToLinear(String ^ mmlString)
@ -1061,7 +1045,7 @@ String ^ Grapher::FormatMathML(String ^ mmlString)
return ref new String(formattedExpression.c_str()); return ref new String(formattedExpression.c_str());
} }
void Grapher::OnAxesColorPropertyChanged(Windows::UI::Color /*oldValue*/, Windows::UI::Color newValue) void Grapher::OnAxesColorPropertyChanged(Windows::UI::Color oldValue [[maybe_unused]], Windows::UI::Color newValue)
{ {
if (m_graph) if (m_graph)
{ {
@ -1071,7 +1055,7 @@ void Grapher::OnAxesColorPropertyChanged(Windows::UI::Color /*oldValue*/, Window
} }
} }
void Grapher::OnGraphBackgroundPropertyChanged(Windows::UI::Color /*oldValue*/, Windows::UI::Color newValue) void Grapher::OnGraphBackgroundPropertyChanged(Windows::UI::Color oldValue [[maybe_unused]], Windows::UI::Color newValue)
{ {
if (m_renderMain) if (m_renderMain)
{ {
@ -1085,7 +1069,7 @@ void Grapher::OnGraphBackgroundPropertyChanged(Windows::UI::Color /*oldValue*/,
} }
} }
void Grapher::OnGridLinesColorPropertyChanged(Windows::UI::Color /*oldValue*/, Windows::UI::Color newValue) void Grapher::OnGridLinesColorPropertyChanged(Windows::UI::Color oldValue [[maybe_unused]], Windows::UI::Color newValue)
{ {
if (m_renderMain != nullptr && m_graph != nullptr) if (m_renderMain != nullptr && m_graph != nullptr)
{ {

View file

@ -29,7 +29,7 @@ public enum class GraphViewChangedReason
{ {
Manipulation, Manipulation,
Reset Reset
}; };
[Windows::UI::Xaml::Markup::ContentPropertyAttribute(Name = L"Equations")] public ref class Grapher sealed [Windows::UI::Xaml::Markup::ContentPropertyAttribute(Name = L"Equations")] public ref class Grapher sealed
: public Windows::UI::Xaml::Controls::Control, : public Windows::UI::Xaml::Controls::Control,
@ -126,7 +126,7 @@ public enum class GraphViewChangedReason
{ {
void set(int value) void set(int value)
{ {
if (value != (int)m_solver->EvalOptions().GetTrigUnitMode()) if (value != static_cast<int>(m_solver->EvalOptions().GetTrigUnitMode()))
{ {
m_solver->EvalOptions().SetTrigUnitMode((Graphing::EvalTrigUnitMode)value); m_solver->EvalOptions().SetTrigUnitMode((Graphing::EvalTrigUnitMode)value);
m_trigUnitsChanged = true; m_trigUnitsChanged = true;
@ -136,7 +136,7 @@ public enum class GraphViewChangedReason
int get() int get()
{ {
return (int)m_solver->EvalOptions().GetTrigUnitMode(); return static_cast<int>(m_solver->EvalOptions().GetTrigUnitMode());
} }
} }
@ -275,12 +275,12 @@ public enum class GraphViewChangedReason
#pragma endregion #pragma endregion
private: private:
void OnForceProportionalAxesPropertyChanged(bool oldValue, bool newValue); void OnForceProportionalAxesPropertyChanged(bool oldValue [[maybe_unused]], bool newValue);
void OnUseCommaDecimalSeperatorPropertyChanged(bool oldValue, bool newValue); void OnUseCommaDecimalSeperatorPropertyChanged(bool oldValue, bool newValue);
void OnEquationsPropertyChanged(EquationCollection ^ oldValue, EquationCollection ^ newValue); void OnEquationsPropertyChanged(EquationCollection ^ oldValue, EquationCollection ^ newValue);
void OnAxesColorPropertyChanged(Windows::UI::Color oldValue, Windows::UI::Color newValue); void OnAxesColorPropertyChanged(Windows::UI::Color oldValue [[maybe_unused]], Windows::UI::Color newValue);
void OnGraphBackgroundPropertyChanged(Windows::UI::Color oldValue, Windows::UI::Color newValue); void OnGraphBackgroundPropertyChanged(Windows::UI::Color oldValue [[maybe_unused]], Windows::UI::Color newValue);
void OnGridLinesColorPropertyChanged(Windows::UI::Color /*oldValue*/, Windows::UI::Color newValue); void OnGridLinesColorPropertyChanged(Windows::UI::Color oldValue [[maybe_unused]], Windows::UI::Color newValue);
void OnLineWidthPropertyChanged(double oldValue, double newValue); void OnLineWidthPropertyChanged(double oldValue, double newValue);
void OnEquationChanged(Equation ^ equation); void OnEquationChanged(Equation ^ equation);
void OnEquationStyleChanged(Equation ^ equation); void OnEquationStyleChanged(Equation ^ equation);
@ -300,13 +300,13 @@ public enum class GraphViewChangedReason
void UpdateTracingChanged(); void UpdateTracingChanged();
void HandleTracingMovementTick(Object ^ sender, Object ^ e); void HandleTracingMovementTick(Object ^ sender, Object ^ e);
void HandleKey(bool keyDown, Windows::System::VirtualKey key); void HandleKey(Windows::System::VirtualKey key);
void HandleKeyDown(Windows::System::VirtualKey key);
void SetEquationsAsValid(); void SetEquationsAsValid();
void SetEquationErrors(); void SetEquationErrors();
std::optional<std::vector<std::shared_ptr<Graphing::IEquation>>> TryInitializeGraph(bool keepCurrentView, _In_ const Graphing::IExpression* graphingExp = nullptr); std::optional<std::vector<std::shared_ptr<Graphing::IEquation>>> TryInitializeGraph(bool keepCurrentView, _In_ const Graphing::IExpression* graphingExp = nullptr);
private: private:
DX::RenderMain ^ m_renderMain = nullptr; DX::RenderMain ^ m_renderMain = nullptr;

View file

@ -39,7 +39,7 @@ namespace GraphControl::DX
// Converts a length in device-independent pixels (DIPs) to a length in physical pixels. // Converts a length in device-independent pixels (DIPs) to a length in physical pixels.
inline float ConvertDipsToPixels(float dips, float dpi) inline float ConvertDipsToPixels(float dips, float dpi)
{ {
static const float dipsPerInch = 96.0f; static constexpr float dipsPerInch = 96.0f;
return floorf(dips * dpi / dipsPerInch + 0.5f); // Round to nearest integer. return floorf(dips * dpi / dipsPerInch + 0.5f); // Round to nearest integer.
} }

View file

@ -58,7 +58,7 @@ namespace GraphControl::DX
{ {
if (auto renderer = m_graph->GetRenderer()) if (auto renderer = m_graph->GetRenderer())
{ {
float dpi = m_deviceResources.GetDpi(); auto dpi = m_deviceResources.GetDpi();
renderer->SetDpi(dpi, dpi); renderer->SetDpi(dpi, dpi);
renderer->SetGraphSize(static_cast<unsigned int>(m_swapChainPanel->ActualWidth), static_cast<unsigned int>(m_swapChainPanel->ActualHeight)); renderer->SetGraphSize(static_cast<unsigned int>(m_swapChainPanel->ActualWidth), static_cast<unsigned int>(m_swapChainPanel->ActualHeight));
@ -78,41 +78,45 @@ namespace GraphControl::DX
void RenderMain::DrawNearestPoint::set(bool value) void RenderMain::DrawNearestPoint::set(bool value)
{ {
if (m_drawNearestPoint != value) if (m_drawNearestPoint == value)
{ {
m_drawNearestPoint = value; return;
if (!m_drawNearestPoint) }
{ m_drawNearestPoint = value;
m_Tracing = false;
} if (!m_drawNearestPoint)
{
m_Tracing = false;
} }
} }
void RenderMain::PointerLocation::set(Point location) void RenderMain::PointerLocation::set(Point location)
{ {
if (m_pointerLocation != location) if (m_pointerLocation == location)
{ {
m_pointerLocation = location; return;
}
m_pointerLocation = location;
bool wasPointRendered = m_Tracing; bool wasPointRendered = m_Tracing;
if (CanRenderPoint() || wasPointRendered) if (CanRenderPoint() || wasPointRendered)
{ {
RunRenderPassAsync(); RunRenderPassAsync();
}
} }
} }
void RenderMain::ActiveTracing::set(bool value) void RenderMain::ActiveTracing::set(bool value)
{ {
if (m_drawActiveTracing != value) if (m_drawActiveTracing == value)
{ {
m_drawActiveTracing = value; return;
}
m_drawActiveTracing = value;
bool wasPointRendered = m_Tracing; bool wasPointRendered = m_Tracing;
if (CanRenderPoint() || wasPointRendered) if (CanRenderPoint() || wasPointRendered)
{ {
RunRenderPassAsync(); RunRenderPassAsync();
}
} }
} }
@ -232,18 +236,20 @@ namespace GraphControl::DX
} }
auto device = m_deviceResources; auto device = m_deviceResources;
auto workItemHandler = ref new WorkItemHandler([this, allowCancel](IAsyncAction ^ action) { auto workItemHandler = ref new WorkItemHandler(
critical_section::scoped_lock lock(m_criticalSection); [this, allowCancel](IAsyncAction ^ action)
// allowCancel is passed as false when the grapher relies on the render pass to validate that an equation can be succesfully rendered.
// Passing false garauntees that another render pass doesn't cancel this one.
if (allowCancel && action->Status == ::AsyncStatus::Canceled)
{ {
return; critical_section::scoped_lock lock(m_criticalSection);
}
RunRenderPassInternal(); // allowCancel is passed as false when the grapher relies on the render pass to validate that an equation can be succesfully rendered.
}); // Passing false garauntees that another render pass doesn't cancel this one.
if (allowCancel && action->Status == ::AsyncStatus::Canceled)
{
return;
}
RunRenderPassInternal();
});
m_renderPass = ThreadPool::RunAsync(workItemHandler, WorkItemPriority::High, WorkItemOptions::None); m_renderPass = ThreadPool::RunAsync(workItemHandler, WorkItemPriority::High, WorkItemOptions::None);
@ -277,8 +283,6 @@ namespace GraphControl::DX
// Returns true if the frame was rendered and is ready to be displayed. // Returns true if the frame was rendered and is ready to be displayed.
bool RenderMain::Render() bool RenderMain::Render()
{ {
bool successful = true;
// Must call BeginDraw before any draw commands. // Must call BeginDraw before any draw commands.
ID2D1Factory3* pFactory = m_deviceResources.GetD2DFactory(); ID2D1Factory3* pFactory = m_deviceResources.GetD2DFactory();
ID2D1DeviceContext* pRenderTarget = m_deviceResources.GetD2DDeviceContext(); ID2D1DeviceContext* pRenderTarget = m_deviceResources.GetD2DDeviceContext();
@ -288,88 +292,91 @@ namespace GraphControl::DX
// Clear the back buffer and set the background color. // Clear the back buffer and set the background color.
context->ClearRenderTargetView(m_deviceResources.GetBackBufferRenderTargetView(), m_backgroundColor); context->ClearRenderTargetView(m_deviceResources.GetBackBufferRenderTargetView(), m_backgroundColor);
if (m_graph) if (!m_graph)
{ {
if (auto renderer = m_graph->GetRenderer()) // Nothing else to render
return true;
}
bool successful = true;
if (auto renderer = m_graph->GetRenderer())
{
pRenderTarget->BeginDraw();
bool hasMissingData = false;
m_HResult = renderer->DrawD2D1(pFactory, pRenderTarget, hasMissingData);
successful = SUCCEEDED(m_HResult);
// We ignore D2DERR_RECREATE_TARGET here. This error indicates that the device
// is lost. It will be handled during the next call to Present.
HRESULT endDraw = pRenderTarget->EndDraw();
if (endDraw != D2DERR_RECREATE_TARGET)
{ {
pRenderTarget->BeginDraw(); DX::ThrowIfFailed(endDraw);
}
bool hasMissingData = false; if (successful)
m_HResult = renderer->DrawD2D1(pFactory, pRenderTarget, hasMissingData); {
if (m_drawNearestPoint || m_drawActiveTracing)
successful = SUCCEEDED(m_HResult);
// We ignore D2DERR_RECREATE_TARGET here. This error indicates that the device
// is lost. It will be handled during the next call to Present.
HRESULT endDraw = pRenderTarget->EndDraw();
if (endDraw != D2DERR_RECREATE_TARGET)
{ {
DX::ThrowIfFailed(endDraw); Point trackPoint = m_pointerLocation;
} if (m_drawActiveTracing)
if (successful)
{
if (m_drawNearestPoint || m_drawActiveTracing)
{ {
Point trackPoint = m_pointerLocation; // Active tracing takes over for draw nearest point input from the mouse pointer.
if (m_drawActiveTracing) trackPoint = m_activeTracingPointerLocation;
}
int formulaId = -1;
double outNearestPointValueX, outNearestPointValueY;
double rhoValueOut, thetaValueOut, tValueOut;
float outNearestPointLocationX, outNearestPointLocationY;
double xAxisMin, xAxisMax, yAxisMin, yAxisMax;
renderer->GetDisplayRanges(xAxisMin, xAxisMax, yAxisMin, yAxisMax);
double precision = this->GetPrecision(xAxisMax, xAxisMin);
if (renderer->GetClosePointData(
trackPoint.X,
trackPoint.Y,
precision,
formulaId,
outNearestPointLocationX,
outNearestPointLocationY,
outNearestPointValueX,
outNearestPointValueY,
rhoValueOut,
thetaValueOut,
tValueOut)
== S_OK)
{
if (!isnan(outNearestPointLocationX) && !isnan(outNearestPointLocationY))
{ {
// Active tracing takes over for draw nearest point input from the mouse pointer. auto lineColors = m_graph->GetOptions().GetGraphColors();
trackPoint = m_activeTracingPointerLocation;
}
int formulaId = -1; if (formulaId >= 0 && static_cast<unsigned int>(formulaId) < lineColors.size())
double outNearestPointValueX, outNearestPointValueY;
double rhoValueOut, thetaValueOut, tValueOut;
float outNearestPointLocationX, outNearestPointLocationY;
double xAxisMin, xAxisMax, yAxisMin, yAxisMax;
renderer->GetDisplayRanges(xAxisMin, xAxisMax, yAxisMin, yAxisMax);
double precision = this->GetPrecision(xAxisMax, xAxisMin);
if (renderer->GetClosePointData(
trackPoint.X,
trackPoint.Y,
precision,
formulaId,
outNearestPointLocationX,
outNearestPointLocationY,
outNearestPointValueX,
outNearestPointValueY,
rhoValueOut,
thetaValueOut,
tValueOut)
== S_OK)
{
if (!isnan(outNearestPointLocationX) && !isnan(outNearestPointLocationY))
{ {
auto lineColors = m_graph->GetOptions().GetGraphColors(); auto dotColor = lineColors[formulaId];
m_nearestPointRenderer.SetColor(D2D1::ColorF(dotColor.R * 65536 + dotColor.G * 256 + dotColor.B, 1.0));
if (formulaId >= 0 && static_cast<unsigned int>(formulaId) < lineColors.size())
{
auto dotColor = lineColors[formulaId];
m_nearestPointRenderer.SetColor(D2D1::ColorF(dotColor.R * 65536 + dotColor.G * 256 + dotColor.B, 1.0));
}
m_TraceLocation = Point(outNearestPointLocationX, outNearestPointLocationY);
m_nearestPointRenderer.Render(m_TraceLocation);
m_Tracing = true;
m_TraceLocation = Point(outNearestPointLocationX, outNearestPointLocationY);
m_XTraceValue = outNearestPointValueX;
m_YTraceValue = outNearestPointValueY;
}
else
{
m_Tracing = false;
} }
m_TraceLocation = Point(outNearestPointLocationX, outNearestPointLocationY);
m_nearestPointRenderer.Render(m_TraceLocation);
m_Tracing = true;
m_TraceLocation = Point(outNearestPointLocationX, outNearestPointLocationY);
m_XTraceValue = outNearestPointValueX;
m_YTraceValue = outNearestPointValueY;
} }
else else
{ {
m_Tracing = false; m_Tracing = false;
} }
} }
else
{
m_Tracing = false;
}
} }
} }
} }
return successful; return successful;
} }
@ -473,10 +480,12 @@ namespace GraphControl::DX
void RenderMain::OnVisibilityChanged(CoreWindow ^ sender, VisibilityChangedEventArgs ^ args) void RenderMain::OnVisibilityChanged(CoreWindow ^ sender, VisibilityChangedEventArgs ^ args)
{ {
if (args->Visible) if (!args->Visible)
{ {
RunRenderPass(); return;
} }
RunRenderPass();
} }
void RenderMain::OnDpiChanged(DisplayInformation ^ sender, Object ^ args) void RenderMain::OnDpiChanged(DisplayInformation ^ sender, Object ^ args)
@ -491,7 +500,7 @@ namespace GraphControl::DX
{ {
if (auto renderer = m_graph->GetRenderer()) if (auto renderer = m_graph->GetRenderer())
{ {
float dpi = m_deviceResources.GetDpi(); auto dpi = m_deviceResources.GetDpi();
renderer->SetDpi(dpi, dpi); renderer->SetDpi(dpi, dpi);
} }
} }

View file

@ -31,7 +31,7 @@ namespace GraphControl
return s_selfInstance; return s_selfInstance;
} }
void TraceLogger::LogEquationCountChanged(int currentValidEquations, int currentInvalidEquations) void TraceLogger::LogEquationCountChanged(unsigned int currentValidEquations, unsigned int currentInvalidEquations)
{ {
static bool firstRun = true; static bool firstRun = true;
if (firstRun) if (firstRun)
@ -80,11 +80,11 @@ namespace GraphControl
TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_FUNCTION_ANALYSIS_PERFORMED), fields); TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_FUNCTION_ANALYSIS_PERFORMED), fields);
} }
void TraceLogger::LogVariableCountChanged(int variablesCount) void TraceLogger::LogVariableCountChanged(unsigned int variablesCount)
{ {
auto fields = ref new LoggingFields(); auto fields = ref new LoggingFields();
fields->AddString(StringReference(CALC_MODE), StringReference(GRAPHING_MODE)); fields->AddString(StringReference(CALC_MODE), StringReference(GRAPHING_MODE));
fields->AddInt64(StringReference(L"VariableCount"), variablesCount); fields->AddUInt64(StringReference(L"VariableCount"), variablesCount);
TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_VARIABLES_COUNT_CHANGED), fields); TraceLoggingCommon::GetInstance()->LogLevel2Event(StringReference(EVENT_NAME_VARIABLES_COUNT_CHANGED), fields);
} }

View file

@ -15,9 +15,9 @@ namespace GraphControl
internal: internal:
static TraceLogger ^ GetInstance(); static TraceLogger ^ GetInstance();
void LogEquationCountChanged(int currentValidEquations, int currentInvalidEquations); void LogEquationCountChanged(unsigned int currentValidEquations, unsigned int currentInvalidEquations);
void LogFunctionAnalysisPerformed(int analysisErrorType, uint32 tooComplexFlag); void LogFunctionAnalysisPerformed(int analysisErrorType, uint32 tooComplexFlag);
void LogVariableCountChanged(int variablesCount); void LogVariableCountChanged(unsigned int variablesCount);
void LogLineWidthChanged(); void LogLineWidthChanged();
private: private:

View file

@ -180,7 +180,7 @@ namespace Utils
template <typename T> template <typename T>
struct IsRefClass struct IsRefClass
{ {
static const bool value = __is_ref_class(T); static constexpr bool value = __is_ref_class(T);
}; };
template <typename T> template <typename T>

View file

@ -9,7 +9,7 @@ namespace MockGraphingImpl
{ {
class Bitmap : public Graphing::IBitmap class Bitmap : public Graphing::IBitmap
{ {
virtual const std::vector<BYTE>& GetData() const const std::vector<BYTE>& GetData() const override
{ {
return std::vector<BYTE>(); return std::vector<BYTE>();
} }

View file

@ -16,49 +16,50 @@ namespace MockGraphingImpl
{ {
m_graphRenderer = std::make_shared<GraphRenderer>(); m_graphRenderer = std::make_shared<GraphRenderer>();
} }
virtual std::optional<std::vector<std::shared_ptr<Graphing::IEquation>>> TryInitialize(const Graphing::IExpression* graphingExp = nullptr)
std::optional<std::vector<std::shared_ptr<Graphing::IEquation>>> TryInitialize(const Graphing::IExpression* graphingExp = nullptr) override
{ {
if (graphingExp != nullptr) if (graphingExp != nullptr)
{ {
std::vector<std::shared_ptr<Graphing::IEquation>> equations; std::vector<std::shared_ptr<Graphing::IEquation>> equations;
equations.push_back(nullptr); equations.push_back(nullptr);
m_variables.push_back(std::make_shared<MockVariable>(MockVariable{})); m_variables.push_back(std::make_shared<MockVariable>(MockVariable{}));
return std::optional<std::vector<std::shared_ptr<Graphing::IEquation>>>(equations); return std::optional(equations);
} }
return std::nullopt; return std::nullopt;
} }
HRESULT GetInitializationError() HRESULT GetInitializationError() override
{ {
return S_OK; return S_OK;
} }
virtual Graphing::IGraphingOptions& GetOptions() Graphing::IGraphingOptions& GetOptions() override
{ {
return m_graphingOptions; return m_graphingOptions;
} }
virtual std::vector<std::shared_ptr<Graphing::IVariable>> GetVariables() std::vector<std::shared_ptr<Graphing::IVariable>> GetVariables() override
{ {
return m_variables; return m_variables;
} }
virtual void SetArgValue(std::wstring variableName, double value) void SetArgValue(std::wstring variableName, double value) override
{ {
} }
virtual std::shared_ptr<Graphing::Renderer::IGraphRenderer> GetRenderer() const std::shared_ptr<Graphing::Renderer::IGraphRenderer> GetRenderer() const override
{ {
return m_graphRenderer; return m_graphRenderer;
} }
virtual bool TryResetSelection() bool TryResetSelection() override
{ {
return true; return true;
} }
virtual std::shared_ptr<Graphing::Analyzer::IGraphAnalyzer> GetAnalyzer() const std::shared_ptr<Graphing::Analyzer::IGraphAnalyzer> GetAnalyzer() const override
{ {
return nullptr; return nullptr;
} }

View file

@ -22,22 +22,23 @@ namespace MockGraphingImpl
{ {
} }
virtual HRESULT SetGraphSize(unsigned int width, unsigned int height) HRESULT SetGraphSize(unsigned int width, unsigned int height) override
{
return S_OK;
}
virtual HRESULT SetDpi(float dpiX, float dpiY)
{ {
return S_OK; return S_OK;
} }
virtual HRESULT DrawD2D1(ID2D1Factory* pDirect2dFactory, ID2D1RenderTarget* pRenderTarget, bool& hasSomeMissingDataOut) HRESULT SetDpi(float dpiX, float dpiY) override
{
return S_OK;
}
HRESULT DrawD2D1(ID2D1Factory* pDirect2dFactory, ID2D1RenderTarget* pRenderTarget, bool& hasSomeMissingDataOut) override
{ {
hasSomeMissingDataOut = false; hasSomeMissingDataOut = false;
return S_OK; return S_OK;
} }
virtual HRESULT GetClosePointData( HRESULT GetClosePointData(
double inScreenPointX, double inScreenPointX,
double inScreenPointY, double inScreenPointY,
double precision, double precision,
@ -48,7 +49,7 @@ namespace MockGraphingImpl
double& yValueOut, double& yValueOut,
double& rhoValueOut, double& rhoValueOut,
double& thetaValueOut, double& thetaValueOut,
double& tValueOut) double& tValueOut) override
{ {
formulaIdOut = 0; formulaIdOut = 0;
xScreenPointOut = 0; xScreenPointOut = 0;
@ -59,7 +60,7 @@ namespace MockGraphingImpl
return S_OK; return S_OK;
} }
virtual HRESULT ScaleRange(double centerX, double centerY, double scale) HRESULT ScaleRange(double centerX, double centerY, double scale) override
{ {
m_xMin = scale * (m_xMin - centerX) + centerX; m_xMin = scale * (m_xMin - centerX) + centerX;
m_xMax = scale * (m_xMax - centerX) + centerX; m_xMax = scale * (m_xMax - centerX) + centerX;
@ -68,19 +69,22 @@ namespace MockGraphingImpl
return S_OK; return S_OK;
} }
virtual HRESULT ChangeRange(Graphing::Renderer::ChangeRangeAction action) HRESULT ChangeRange(Graphing::Renderer::ChangeRangeAction action) override
{ {
return S_OK; return S_OK;
} }
virtual HRESULT MoveRangeByRatio(double ratioX, double ratioY)
HRESULT MoveRangeByRatio(double ratioX, double ratioY) override
{ {
return S_OK; return S_OK;
} }
virtual HRESULT ResetRange()
HRESULT ResetRange() override
{ {
return S_OK; return S_OK;
} }
virtual HRESULT GetDisplayRanges(double& xMin, double& xMax, double& yMin, double& yMax)
HRESULT GetDisplayRanges(double& xMin, double& xMax, double& yMin, double& yMax) override
{ {
xMin = m_xMin; xMin = m_xMin;
xMax = m_xMax; xMax = m_xMax;
@ -88,7 +92,8 @@ namespace MockGraphingImpl
yMax = m_yMax; yMax = m_yMax;
return S_OK; return S_OK;
} }
virtual HRESULT SetDisplayRanges(double xMin, double xMax, double yMin, double yMax)
HRESULT SetDisplayRanges(double xMin, double xMax, double yMin, double yMax) override
{ {
m_xMin = xMin; m_xMin = xMin;
m_xMax = xMax; m_xMax = xMax;
@ -97,12 +102,12 @@ namespace MockGraphingImpl
return S_OK; return S_OK;
} }
virtual HRESULT PrepareGraph() HRESULT PrepareGraph() override
{ {
return S_OK; return S_OK;
} }
virtual HRESULT GetBitmap(std::shared_ptr<Graphing::IBitmap>& bitmapOut, bool& hasSomeMissingDataOut) HRESULT GetBitmap(std::shared_ptr<Graphing::IBitmap>& bitmapOut, bool& hasSomeMissingDataOut) override
{ {
bitmapOut = std::make_shared<Bitmap>(); bitmapOut = std::make_shared<Bitmap>();
hasSomeMissingDataOut = false; hasSomeMissingDataOut = false;

View file

@ -20,17 +20,7 @@ namespace MockGraphingImpl
, m_markHorizontalAsymptotes(false) , m_markHorizontalAsymptotes(false)
, m_markObliqueAsymptotes(false) , m_markObliqueAsymptotes(false)
, m_maxExecutionTime(0) , m_maxExecutionTime(0)
, m_colors()
, m_backColor()
, m_allowKeyGraphFeaturesForFunctionsWithParameters(false) , m_allowKeyGraphFeaturesForFunctionsWithParameters(false)
, m_zerosColor()
, m_extremaColor()
, m_inflectionPointsColor()
, m_asymptotesColor()
, m_axisColor()
, m_boxColor()
, m_gridColor()
, m_fontColor()
, m_showAxis(true) , m_showAxis(true)
, m_showGrid(true) , m_showGrid(true)
, m_showBox(true) , m_showBox(true)
@ -43,358 +33,404 @@ namespace MockGraphingImpl
{ {
} }
virtual void ResetMarkKeyGraphFeaturesData() void ResetMarkKeyGraphFeaturesData() override
{ {
} }
virtual bool GetMarkZeros() const bool GetMarkZeros() const override
{ {
return m_markZeros; return m_markZeros;
} }
virtual void SetMarkZeros(bool value)
void SetMarkZeros(bool value) override
{ {
m_markZeros = value; m_markZeros = value;
} }
virtual bool GetMarkYIntercept() const bool GetMarkYIntercept() const override
{ {
return m_markYIntercept; return m_markYIntercept;
} }
virtual void SetMarkYIntercept(bool value)
void SetMarkYIntercept(bool value) override
{ {
m_markYIntercept = value; m_markYIntercept = value;
} }
virtual bool GetMarkMinima() const bool GetMarkMinima() const override
{ {
return m_markMinima; return m_markMinima;
} }
virtual void SetMarkMinima(bool value)
void SetMarkMinima(bool value) override
{ {
m_markMinima = value; m_markMinima = value;
} }
virtual bool GetMarkMaxima() const bool GetMarkMaxima() const override
{ {
return m_markMaxima; return m_markMaxima;
} }
virtual void SetMarkMaxima(bool value)
void SetMarkMaxima(bool value) override
{ {
m_markMaxima = value; m_markMaxima = value;
} }
virtual bool GetMarkInflectionPoints() const bool GetMarkInflectionPoints() const override
{ {
return m_markInflectionPoints; return m_markInflectionPoints;
} }
virtual void SetMarkInflectionPoints(bool value)
void SetMarkInflectionPoints(bool value) override
{ {
m_markInflectionPoints = value; m_markInflectionPoints = value;
} }
virtual bool GetMarkVerticalAsymptotes() const bool GetMarkVerticalAsymptotes() const override
{ {
return m_markVerticalAsymptotes; return m_markVerticalAsymptotes;
} }
virtual void SetMarkVerticalAsymptotes(bool value)
void SetMarkVerticalAsymptotes(bool value) override
{ {
m_markVerticalAsymptotes = value; m_markVerticalAsymptotes = value;
} }
virtual bool GetMarkHorizontalAsymptotes() const bool GetMarkHorizontalAsymptotes() const override
{ {
return m_markHorizontalAsymptotes; return m_markHorizontalAsymptotes;
} }
virtual void SetMarkHorizontalAsymptotes(bool value)
void SetMarkHorizontalAsymptotes(bool value) override
{ {
m_markHorizontalAsymptotes = value; m_markHorizontalAsymptotes = value;
} }
virtual bool GetMarkObliqueAsymptotes() const bool GetMarkObliqueAsymptotes() const override
{ {
return m_markObliqueAsymptotes; return m_markObliqueAsymptotes;
} }
virtual void SetMarkObliqueAsymptotes(bool value)
void SetMarkObliqueAsymptotes(bool value) override
{ {
m_markObliqueAsymptotes = value; m_markObliqueAsymptotes = value;
} }
virtual unsigned long long GetMaxExecutionTime() const unsigned long long GetMaxExecutionTime() const override
{ {
return m_maxExecutionTime; return m_maxExecutionTime;
} }
virtual void SetMaxExecutionTime(unsigned long long value)
void SetMaxExecutionTime(unsigned long long value) override
{ {
m_maxExecutionTime = value; m_maxExecutionTime = value;
} }
virtual void ResetMaxExecutionTime() void ResetMaxExecutionTime() override
{ {
m_maxExecutionTime = 0; m_maxExecutionTime = 0;
}; }
virtual std::vector<Graphing::Color> GetGraphColors() const std::vector<Graphing::Color> GetGraphColors() const override
{ {
return m_colors; return m_colors;
} }
virtual bool SetGraphColors(const std::vector<Graphing::Color>& colors)
bool SetGraphColors(const std::vector<Graphing::Color>& colors) override
{ {
m_colors = colors; m_colors = colors;
return true; return true;
} }
virtual void ResetGraphColors()
void ResetGraphColors() override
{ {
m_colors.clear(); m_colors.clear();
} }
virtual Graphing::Color GetBackColor() const Graphing::Color GetBackColor() const override
{ {
return m_backColor; return m_backColor;
} }
virtual void SetBackColor(const Graphing::Color& value)
void SetBackColor(const Graphing::Color& value) override
{ {
m_backColor = value; m_backColor = value;
} }
virtual void ResetBackColor() void ResetBackColor() override
{ {
m_backColor = Graphing::Color(); m_backColor = Graphing::Color();
} }
virtual void SetAllowKeyGraphFeaturesForFunctionsWithParameters(bool kgf) void SetAllowKeyGraphFeaturesForFunctionsWithParameters(bool kgf) override
{ {
m_allowKeyGraphFeaturesForFunctionsWithParameters = kgf; m_allowKeyGraphFeaturesForFunctionsWithParameters = kgf;
} }
virtual bool GetAllowKeyGraphFeaturesForFunctionsWithParameters() const
bool GetAllowKeyGraphFeaturesForFunctionsWithParameters() const override
{ {
return m_allowKeyGraphFeaturesForFunctionsWithParameters; return m_allowKeyGraphFeaturesForFunctionsWithParameters;
} }
virtual void ResetAllowKeyGraphFeaturesForFunctionsWithParameters()
void ResetAllowKeyGraphFeaturesForFunctionsWithParameters() override
{ {
m_allowKeyGraphFeaturesForFunctionsWithParameters = true; m_allowKeyGraphFeaturesForFunctionsWithParameters = true;
} }
virtual Graphing::Color GetZerosColor() const Graphing::Color GetZerosColor() const override
{ {
return m_zerosColor; return m_zerosColor;
} }
virtual void SetZerosColor(const Graphing::Color& value)
void SetZerosColor(const Graphing::Color& value) override
{ {
m_zerosColor = value; m_zerosColor = value;
} }
virtual void ResetZerosColor()
void ResetZerosColor() override
{ {
m_zerosColor = Graphing::Color(); m_zerosColor = Graphing::Color();
} }
virtual Graphing::Color GetExtremaColor() const Graphing::Color GetExtremaColor() const override
{ {
return m_extremaColor; return m_extremaColor;
} }
virtual void SetExtremaColor(const Graphing::Color& value)
void SetExtremaColor(const Graphing::Color& value) override
{ {
m_extremaColor = value; m_extremaColor = value;
} }
virtual void ResetExtremaColor()
void ResetExtremaColor() override
{ {
m_extremaColor = Graphing::Color(); m_extremaColor = Graphing::Color();
} }
virtual Graphing::Color GetInflectionPointsColor() const Graphing::Color GetInflectionPointsColor() const override
{ {
return m_inflectionPointsColor; return m_inflectionPointsColor;
} }
virtual void SetInflectionPointsColor(const Graphing::Color& value)
void SetInflectionPointsColor(const Graphing::Color& value) override
{ {
m_inflectionPointsColor = value; m_inflectionPointsColor = value;
} }
virtual void ResetInflectionPointsColor()
void ResetInflectionPointsColor() override
{ {
m_inflectionPointsColor = Graphing::Color(); m_inflectionPointsColor = Graphing::Color();
} }
virtual Graphing::Color GetAsymptotesColor() const Graphing::Color GetAsymptotesColor() const override
{ {
return m_asymptotesColor; return m_asymptotesColor;
} }
virtual void SetAsymptotesColor(const Graphing::Color& value)
void SetAsymptotesColor(const Graphing::Color& value) override
{ {
m_asymptotesColor = value; m_asymptotesColor = value;
} }
virtual void ResetAsymptotesColor()
void ResetAsymptotesColor() override
{ {
m_asymptotesColor = Graphing::Color(); m_asymptotesColor = Graphing::Color();
} }
virtual Graphing::Color GetAxisColor() const Graphing::Color GetAxisColor() const override
{ {
return m_axisColor; return m_axisColor;
} }
virtual void SetAxisColor(const Graphing::Color& value)
void SetAxisColor(const Graphing::Color& value) override
{ {
m_axisColor = value; m_axisColor = value;
} }
virtual void ResetAxisColor()
void ResetAxisColor() override
{ {
m_axisColor = Graphing::Color(); m_axisColor = Graphing::Color();
} }
virtual Graphing::Color GetBoxColor() const Graphing::Color GetBoxColor() const override
{ {
return m_boxColor; return m_boxColor;
} }
virtual void SetBoxColor(const Graphing::Color& value)
void SetBoxColor(const Graphing::Color& value) override
{ {
m_boxColor = value; m_boxColor = value;
} }
virtual void ResetBoxColor()
void ResetBoxColor() override
{ {
m_boxColor = Graphing::Color(); m_boxColor = Graphing::Color();
} }
virtual Graphing::Color GetGridColor() const Graphing::Color GetGridColor() const override
{ {
return m_gridColor; return m_gridColor;
} }
virtual void SetGridColor(const Graphing::Color& value)
void SetGridColor(const Graphing::Color& value) override
{ {
m_gridColor = value; m_gridColor = value;
} }
virtual void ResetGridColor()
void ResetGridColor() override
{ {
m_gridColor = Graphing::Color(); m_gridColor = Graphing::Color();
} }
virtual Graphing::Color GetFontColor() const Graphing::Color GetFontColor() const override
{ {
return m_fontColor; return m_fontColor;
} }
virtual void SetFontColor(const Graphing::Color& value)
void SetFontColor(const Graphing::Color& value) override
{ {
m_fontColor = value; m_fontColor = value;
} }
virtual void ResetFontColor()
void ResetFontColor() override
{ {
m_fontColor = Graphing::Color(); m_fontColor = Graphing::Color();
} }
virtual bool GetShowAxis() const bool GetShowAxis() const override
{ {
return m_showAxis; return m_showAxis;
} }
virtual void SetShowAxis(bool value)
void SetShowAxis(bool value) override
{ {
m_showAxis = value; m_showAxis = value;
} }
virtual void ResetShowAxis()
void ResetShowAxis() override
{ {
m_showAxis = true; m_showAxis = true;
} }
virtual bool GetShowGrid() const bool GetShowGrid() const override
{ {
return m_showGrid; return m_showGrid;
} }
virtual void SetShowGrid(bool value)
void SetShowGrid(bool value) override
{ {
m_showGrid = value; m_showGrid = value;
} }
virtual void ResetShowGrid()
void ResetShowGrid() override
{ {
m_showGrid = true; m_showGrid = true;
} }
virtual bool GetShowBox() const bool GetShowBox() const override
{ {
return m_showBox; return m_showBox;
} }
virtual void SetShowBox(bool value)
void SetShowBox(bool value) override
{ {
m_showBox = value; m_showBox = value;
} }
virtual void ResetShowBox()
void ResetShowBox() override
{ {
m_showBox = true; m_showBox = true;
} }
virtual bool GetForceProportional() const bool GetForceProportional() const override
{ {
return m_forceProportional; return m_forceProportional;
} }
virtual void SetForceProportional(bool value)
void SetForceProportional(bool value) override
{ {
m_forceProportional = value; m_forceProportional = value;
} }
virtual void ResetForceProportional()
void ResetForceProportional() override
{ {
m_forceProportional = false; m_forceProportional = false;
} }
virtual std::wstring GetAliasX() const std::wstring GetAliasX() const override
{ {
return m_aliasX; return m_aliasX;
} }
virtual void SetAliasX(const std::wstring& value)
void SetAliasX(const std::wstring& value) override
{ {
m_aliasX = value; m_aliasX = value;
} }
virtual void ResetAliasX()
void ResetAliasX() override
{ {
m_aliasX = L""; m_aliasX = L"";
} }
virtual std::wstring GetAliasY() const std::wstring GetAliasY() const override
{ {
return m_aliasY; return m_aliasY;
} }
virtual void SetAliasY(const std::wstring& value)
void SetAliasY(const std::wstring& value) override
{ {
m_aliasY = value; m_aliasY = value;
} }
virtual void ResetAliasY()
void ResetAliasY() override
{ {
m_aliasY = L""; m_aliasY = L"";
} }
virtual Graphing::Renderer::LineStyle GetLineStyle() const Graphing::Renderer::LineStyle GetLineStyle() const override
{ {
return m_lineStyle; return m_lineStyle;
} }
virtual void SetLineStyle(Graphing::Renderer::LineStyle value)
void SetLineStyle(Graphing::Renderer::LineStyle value) override
{ {
m_lineStyle = value; m_lineStyle = value;
} }
virtual void ResetLineStyle()
void ResetLineStyle() override
{ {
m_lineStyle = Graphing::Renderer::LineStyle::Solid; m_lineStyle = Graphing::Renderer::LineStyle::Solid;
} }
virtual std::pair<double, double> GetDefaultXRange() const std::pair<double, double> GetDefaultXRange() const override
{ {
return m_XRange; return m_XRange;
} }
virtual bool SetDefaultXRange(const std::pair<double, double>& minmax) bool SetDefaultXRange(const std::pair<double, double>& minmax) override
{ {
m_XRange = minmax; m_XRange = minmax;
return true; return true;
} }
virtual void ResetDefaultXRange()
void ResetDefaultXRange() override
{ {
m_XRange = { 0, 0 }; m_XRange = { 0, 0 };
} }
virtual std::pair<double, double> GetDefaultYRange() const std::pair<double, double> GetDefaultYRange() const override
{ {
return m_YRange; return m_YRange;
} }
virtual bool SetDefaultYRange(const std::pair<double, double>& minmax) bool SetDefaultYRange(const std::pair<double, double>& minmax) override
{ {
m_YRange = minmax; m_YRange = minmax;
return true; return true;
} }
virtual void ResetDefaultYRange()
void ResetDefaultYRange() override
{ {
m_YRange = { 0, 0 }; m_YRange = { 0, 0 };
} }

View file

@ -59,15 +59,13 @@ namespace MockGraphingImpl
class MockExpression : public Graphing::IExpression class MockExpression : public Graphing::IExpression
{ {
public: public:
MockExpression() MockExpression() = default;
{
}
unsigned int GetExpressionID() const override unsigned int GetExpressionID() const override
{ {
return 0; return 0;
} }
bool IsEmptySet() const bool IsEmptySet() const override
{ {
return false; return false;
} }
@ -76,9 +74,7 @@ namespace MockGraphingImpl
class MockVariable : public Graphing::IVariable class MockVariable : public Graphing::IVariable
{ {
public: public:
MockVariable() MockVariable() = default;
{
}
int GetVariableID() const override int GetVariableID() const override
{ {
@ -96,9 +92,7 @@ namespace MockGraphingImpl
class MathSolver : public Graphing::IMathSolver class MathSolver : public Graphing::IMathSolver
{ {
public: public:
MathSolver() MathSolver() = default;
{
}
Graphing::IParsingOptions& ParsingOptions() override Graphing::IParsingOptions& ParsingOptions() override
{ {
@ -125,7 +119,7 @@ namespace MockGraphingImpl
return std::make_unique<MockExpression>(MockExpression{}); return std::make_unique<MockExpression>(MockExpression{});
} }
void HRErrorToErrorInfo(HRESULT hr, int& errorCodeOut, int& errorTypeOut) void HRErrorToErrorInfo(HRESULT hr, int& errorCodeOut, int& errorTypeOut) override
{ {
} }
@ -138,7 +132,7 @@ namespace MockGraphingImpl
return L""; return L"";
} }
Graphing::IGraphFunctionAnalysisData IMathSolver::Analyze(const Graphing::Analyzer::IGraphAnalyzer* analyzer) Graphing::IGraphFunctionAnalysisData IMathSolver::Analyze(const Graphing::Analyzer::IGraphAnalyzer* analyzer) override
{ {
return Graphing::IGraphFunctionAnalysisData{}; return Graphing::IGraphFunctionAnalysisData{};
} }

View file

@ -75,34 +75,34 @@ namespace Graphing
uint8_t A; uint8_t A;
constexpr Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept constexpr Color(uint8_t r, uint8_t g, uint8_t b, uint8_t a) noexcept
: R{ r }, G{ g }, B{ b }, A{ a } : R{ r }
{} , G{ g }
, B{ b }
, A{ a }
{
}
constexpr Color(uint8_t r, uint8_t g, uint8_t b) noexcept constexpr Color(uint8_t r, uint8_t g, uint8_t b) noexcept
: Color{ r, g, b, 0xFF } : Color{ r, g, b, 0xFF }
{} {
}
constexpr Color() noexcept constexpr Color() noexcept
: Color{ 0, 0, 0 } : Color{ 0, 0, 0 }
{} {
}
constexpr explicit Color(uint32_t value) noexcept constexpr explicit Color(uint32_t value) noexcept
: Color{ : Color{ static_cast<uint8_t>(value >> redChannelShift),
static_cast<uint8_t>(value >> redChannelShift), static_cast<uint8_t>(value >> greenChannelShift),
static_cast<uint8_t>(value >> greenChannelShift), static_cast<uint8_t>(value >> blueChannelShift),
static_cast<uint8_t>(value >> blueChannelShift), static_cast<uint8_t>(value >> alphaChannelShift) }
static_cast<uint8_t>(value >> alphaChannelShift)
}
{ {
} }
constexpr explicit operator uint32_t() const constexpr explicit operator uint32_t() const
{ {
return (A << alphaChannelShift) return (A << alphaChannelShift) | (R << redChannelShift) | (G << greenChannelShift) | (B << blueChannelShift);
| (R << redChannelShift)
| (G << greenChannelShift)
| (B << blueChannelShift);
} }
}; };
} }

View file

@ -10,7 +10,7 @@ namespace Graphing
{ {
struct IEquation : public NonCopyable, public NonMoveable struct IEquation : public NonCopyable, public NonMoveable
{ {
virtual ~IEquation() = default; ~IEquation() override = default;
virtual std::shared_ptr<IEquationOptions> GetGraphEquationOptions() const = 0; virtual std::shared_ptr<IEquationOptions> GetGraphEquationOptions() const = 0;
@ -19,4 +19,4 @@ namespace Graphing
virtual bool TrySelectEquation() = 0; virtual bool TrySelectEquation() = 0;
virtual bool IsEquationSelected() const = 0; virtual bool IsEquationSelected() const = 0;
}; };
} }

View file

@ -10,7 +10,7 @@ namespace Graphing
{ {
struct IEquationOptions : public NonCopyable, public NonMoveable struct IEquationOptions : public NonCopyable, public NonMoveable
{ {
virtual ~IEquationOptions() = default; ~IEquationOptions() override = default;
virtual Graphing::Color GetGraphColor() const = 0; virtual Graphing::Color GetGraphColor() const = 0;
virtual void SetGraphColor(const Graphing::Color& color) = 0; virtual void SetGraphColor(const Graphing::Color& color) = 0;
@ -36,4 +36,4 @@ namespace Graphing
virtual void SetSelectedEquationPointRadius(float value) = 0; virtual void SetSelectedEquationPointRadius(float value) = 0;
virtual void ResetSelectedEquationPointRadius() = 0; virtual void ResetSelectedEquationPointRadius() = 0;
}; };
} }

View file

@ -14,7 +14,7 @@ namespace Graphing
{ {
struct IGraph : public NonCopyable, public NonMoveable struct IGraph : public NonCopyable, public NonMoveable
{ {
virtual ~IGraph() = default; ~IGraph() override = default;
virtual std::optional<std::vector<std::shared_ptr<IEquation>>> TryInitialize(const IExpression* graphingExp = nullptr) = 0; virtual std::optional<std::vector<std::shared_ptr<IEquation>>> TryInitialize(const IExpression* graphingExp = nullptr) = 0;

View file

@ -11,14 +11,14 @@
namespace Graphing::Analyzer namespace Graphing::Analyzer
{ {
typedef unsigned int NativeAnalysisType; // PerformAnalysisType using NativeAnalysisType = unsigned int; // PerformAnalysisType
struct IGraphAnalyzer : public NonCopyable, public NonMoveable struct IGraphAnalyzer : public NonCopyable, public NonMoveable
{ {
virtual ~IGraphAnalyzer() = default; ~IGraphAnalyzer() override = default;
virtual bool CanFunctionAnalysisBePerformed(bool& variableIsNotX) = 0; virtual bool CanFunctionAnalysisBePerformed(bool& variableIsNotX) = 0;
virtual HRESULT PerformFunctionAnalysis(NativeAnalysisType analysisType) = 0; virtual HRESULT PerformFunctionAnalysis(NativeAnalysisType analysisType) = 0;
virtual HRESULT GetAnalysisTypeCaption(const AnalysisType type, std::wstring& captionOut) const = 0; virtual HRESULT GetAnalysisTypeCaption(AnalysisType type, std::wstring& captionOut) const = 0;
virtual HRESULT GetMessage(const GraphAnalyzerMessage msg, std::wstring& msgOut) const = 0; virtual HRESULT GetMessage(GraphAnalyzerMessage msg, std::wstring& msgOut) const = 0;
}; };
} }

View file

@ -17,7 +17,7 @@ namespace Graphing::Renderer
{ {
struct IGraphRenderer : public NonCopyable, public NonMoveable struct IGraphRenderer : public NonCopyable, public NonMoveable
{ {
virtual ~IGraphRenderer() = default; ~IGraphRenderer() override = default;
virtual HRESULT SetGraphSize(unsigned int width, unsigned int height) = 0; virtual HRESULT SetGraphSize(unsigned int width, unsigned int height) = 0;
virtual HRESULT SetDpi(float dpiX, float dpiY) = 0; virtual HRESULT SetDpi(float dpiX, float dpiY) = 0;

View file

@ -12,7 +12,7 @@ namespace Graphing
{ {
struct IGraphingOptions : public NonCopyable, public NonMoveable struct IGraphingOptions : public NonCopyable, public NonMoveable
{ {
virtual ~IGraphingOptions() = default; ~IGraphingOptions() override = default;
virtual void ResetMarkKeyGraphFeaturesData() = 0; virtual void ResetMarkKeyGraphFeaturesData() = 0;

View file

@ -31,7 +31,7 @@ namespace Graphing
struct IParsingOptions : public NonCopyable, public NonMoveable struct IParsingOptions : public NonCopyable, public NonMoveable
{ {
virtual ~IParsingOptions() = default; ~IParsingOptions() override = default;
virtual void SetFormatType(FormatType type) = 0; virtual void SetFormatType(FormatType type) = 0;
virtual void SetLocalizationType(LocalizationType value) = 0; virtual void SetLocalizationType(LocalizationType value) = 0;
@ -39,7 +39,7 @@ namespace Graphing
struct IEvalOptions : public NonCopyable, public NonMoveable struct IEvalOptions : public NonCopyable, public NonMoveable
{ {
virtual ~IEvalOptions() = default; ~IEvalOptions() override = default;
virtual EvalTrigUnitMode GetTrigUnitMode() const = 0; virtual EvalTrigUnitMode GetTrigUnitMode() const = 0;
virtual void SetTrigUnitMode(EvalTrigUnitMode value) = 0; virtual void SetTrigUnitMode(EvalTrigUnitMode value) = 0;
@ -47,7 +47,7 @@ namespace Graphing
struct IFormatOptions : public NonCopyable, public NonMoveable struct IFormatOptions : public NonCopyable, public NonMoveable
{ {
virtual ~IFormatOptions() = default; ~IFormatOptions() override = default;
virtual void SetFormatType(FormatType type) = 0; virtual void SetFormatType(FormatType type) = 0;
virtual void SetMathMLPrefix(const std::wstring& value) = 0; virtual void SetMathMLPrefix(const std::wstring& value) = 0;
@ -56,7 +56,7 @@ namespace Graphing
struct IMathSolver : public NonCopyable, public NonMoveable struct IMathSolver : public NonCopyable, public NonMoveable
{ {
virtual ~IMathSolver() = default; ~IMathSolver() override = default;
static GRAPHINGAPI std::unique_ptr<IMathSolver> CreateMathSolver(); static GRAPHINGAPI std::unique_ptr<IMathSolver> CreateMathSolver();