mirror of
https://github.com/Microsoft/calculator.git
synced 2025-08-22 06:13:14 -07:00
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:
parent
f27bdba85a
commit
f5662250cf
82 changed files with 1322 additions and 1390 deletions
|
@ -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)
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 };
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
//
|
//
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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))
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 =");
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 };
|
||||||
}
|
}
|
||||||
|
|
|
@ -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{};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue