Fix the project code style, as it is not consistent. (#236)

Fixes #202
This PR fixes code style for the project files.

The Problem
Different files in the project use different code style. That is not consistent and leads to harder maintenance of the project.

Description of the changes:
Have investigated and determined the most used code style across the given codebase
Have configured IDE and applied code style to all project files.
Have crafted clang-formatter config.
see https://clang.llvm.org/docs/ClangFormat.html
https://clang.llvm.org/docs/ClangFormatStyleOptions.html
Some cases were fixed manually
How changes were validated:
manual/ad-hoc testing, automated testing

All tests pass as before because these are only code style changes.
Additional
Please review, and let me know if I have any mistake in the code style. In case of any mistake, I will change the configuration and re-apply it to the project.
This commit is contained in:
Oleg Abrazhaev 2019-05-02 20:59:19 +02:00 committed by Daniel Belcher
commit 2826d37056
237 changed files with 12824 additions and 11843 deletions

99
.clang-format Normal file
View file

@ -0,0 +1,99 @@
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Right
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: true
BinPackArguments: true
BinPackParameters: true
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeBraces: Allman
BreakBeforeInheritanceComma: false
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeComma
BreakAfterJavaFieldAnnotations: true
BreakStringLiterals: true
ColumnLimit: 160
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: true
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: false
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: false
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^<ext/.*\.h>'
Priority: 2
- Regex: '^<.*\.h>'
Priority: 1
- Regex: '^<.*'
Priority: 2
- Regex: '.*'
Priority: 3
IncludeIsMainRegex: '([-_](test|unittest))?$'
IndentCaseLabels: false
IndentPPDirectives: None
IndentWidth: 4
IndentWrappedFunctionNames: false
JavaScriptQuotes: Single
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: All
ObjCBlockIndentWidth: 4
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Left
ReflowComments: true
SortIncludes: false
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: false
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 4
UseTab: Never
#...
# unsupported rules
#BreakInheritanceList: AfterColon
#Language: None
#ObjCBinPackProtocolList: Auto
#PenaltyBreakTemplateDeclaration: 10
#SpaceBeforeCpp11BracedList: false
#SpaceBeforeCtorInitializerColon: true
#SpaceBeforeInheritanceColon: true
#SpaceBeforeRangeBasedForLoopColon: true

View file

@ -0,0 +1,53 @@
#!/bin/bash
function usage {
echo "Usage: $0 DIR..."
exit 1
}
# Variable that will hold the name of the clang-format command
FMT=""
# Some distros just call it clang-format. Others (e.g. Ubuntu) are insistent
# that the version number be part of the command. We prefer clang-format if
# that's present, otherwise we work backwards from highest version to lowest
# version.
for clangfmt in clang-format{,-{4,3}.{9,8,7,6,5,4,3,2,1,0}}; do
if which "$clangfmt" &>/dev/null; then
FMT="$clangfmt"
break
fi
done
# Check if we found a working clang-format
if [ -z "$FMT" ]; then
echo "failed to find clang-format"
exit 1
fi
SRC_PATH="$@"
if [ -z "$SRC_PATH" ]; then
SRC_PATH="../../../src"
fi
# Check all of the arguments first to make sure they're all directories
for dir in "$SRC_PATH"; do
if [ ! -d "${dir}" ]; then
echo "${dir} is not a directory"
usage
fi
done
# Run clang-format -i on all of the things
for dir in "$SRC_PATH"; do
pushd "${dir}" &>/dev/null
find . \
\( -name '*.c' \
-o -name '*.cc' \
-o -name '*.cpp' \
-o -name '*.h' \
-o -name '*.hh' \
-o -name '*.hpp' \) \
-exec "${FMT}" -style=file -i '{}' \;
popd &>/dev/null
done

View file

@ -124,7 +124,7 @@ bool CalcInput::TryAddDigit(unsigned int value, uint32_t radix, bool isIntegerMo
else if (radix == 10) else if (radix == 10)
{ {
// If value length is at least the max, we know we can't add another digit. // If value length is at least the max, we know we can't add another digit.
if(pNumSec->value.size() < maxNumStr.size()) if (pNumSec->value.size() < maxNumStr.size())
{ {
// Compare value to substring of maxNumStr of value.size() length. // Compare value to substring of maxNumStr of value.size() length.
// If cmpResult > 0: // If cmpResult > 0:

View file

@ -33,9 +33,7 @@ bool IsDigitOpCode(OpCode opCode)
// was never inout, we need to revert the state changes made as a result of this test // was never inout, we need to revert the state changes made as a result of this test
bool IsGuiSettingOpCode(OpCode opCode) bool IsGuiSettingOpCode(OpCode opCode)
{ {
if (IsOpInRange(opCode, IDM_HEX, IDM_BIN) || if (IsOpInRange(opCode, IDM_HEX, IDM_BIN) || IsOpInRange(opCode, IDM_QWORD, IDM_BYTE) || IsOpInRange(opCode, IDM_DEG, IDM_GRAD))
IsOpInRange(opCode, IDM_QWORD, IDM_BYTE) ||
IsOpInRange(opCode, IDM_DEG, IDM_GRAD))
{ {
return true; return true;
} }

View file

@ -11,7 +11,8 @@ constexpr int ASCII_0 = 48;
using namespace std; using namespace std;
using namespace CalcEngine; using namespace CalcEngine;
namespace { namespace
{
void IFT(ResultCode hr) void IFT(ResultCode hr)
{ {
if (FAILED(hr)) if (FAILED(hr))
@ -38,11 +39,8 @@ 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(pHistoryDisplay), m_pCalcDisplay(pCalcDisplay), m_iCurLineHistStart(-1), m_decimalSymbol(decimalSymbol)
m_pCalcDisplay(pCalcDisplay),
m_iCurLineHistStart(-1),
m_decimalSymbol(decimalSymbol)
{ {
ReinitHistory(); ReinitHistory();
} }
@ -302,7 +300,8 @@ void CHistoryCollector::CompleteHistoryLine(wstring_view numStr)
{ {
if (nullptr != m_pCalcDisplay) if (nullptr != m_pCalcDisplay)
{ {
m_pCalcDisplay->SetExpressionDisplay(std::make_shared<CalculatorVector<std::pair<std::wstring, int>>>(), std::make_shared<CalculatorVector<std::shared_ptr<IExpressionCommand>>>()); m_pCalcDisplay->SetExpressionDisplay(std::make_shared<CalculatorVector<std::pair<std::wstring, int>>>(),
std::make_shared<CalculatorVector<std::shared_ptr<IExpressionCommand>>>());
} }
if (nullptr != m_pHistoryDisplay) if (nullptr != m_pHistoryDisplay)
@ -323,14 +322,14 @@ void CHistoryCollector::ClearHistoryLine(wstring_view errStr)
{ {
if (nullptr != m_pCalcDisplay) if (nullptr != m_pCalcDisplay)
{ {
m_pCalcDisplay->SetExpressionDisplay(std::make_shared<CalculatorVector<std::pair<std::wstring, int>>>(), std::make_shared<CalculatorVector<std::shared_ptr<IExpressionCommand>>>()); m_pCalcDisplay->SetExpressionDisplay(std::make_shared<CalculatorVector<std::pair<std::wstring, int>>>(),
std::make_shared<CalculatorVector<std::shared_ptr<IExpressionCommand>>>());
} }
m_iCurLineHistStart = -1; // It will get recomputed at the first Opnd m_iCurLineHistStart = -1; // It will get recomputed at the first Opnd
ReinitHistory(); 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.
// Also returns the 0 based index in the string just added. Can throw out of memory error // Also returns the 0 based index in the string just added. Can throw out of memory error
int CHistoryCollector::IchAddSzToEquationSz(wstring_view str, int icommandIndex) int CHistoryCollector::IchAddSzToEquationSz(wstring_view str, int icommandIndex)
@ -392,14 +391,13 @@ void CHistoryCollector::SetExpressionDisplay()
{ {
m_pCalcDisplay->SetExpressionDisplay(m_spTokens, m_spCommands); m_pCalcDisplay->SetExpressionDisplay(m_spTokens, m_spCommands);
} }
} }
int CHistoryCollector::AddCommand(_In_ const std::shared_ptr<IExpressionCommand> & spCommand) int CHistoryCollector::AddCommand(_In_ const std::shared_ptr<IExpressionCommand>& spCommand)
{ {
if (m_spCommands == nullptr) if (m_spCommands == nullptr)
{ {
m_spCommands = std::make_shared <CalculatorVector<std::shared_ptr<IExpressionCommand>>>(); m_spCommands = std::make_shared<CalculatorVector<std::shared_ptr<IExpressionCommand>>>();
} }
if (FAILED(m_spCommands->Append(spCommand))) if (FAILED(m_spCommands->Append(spCommand)))

View file

@ -7,20 +7,15 @@ using namespace std;
namespace CalcEngine namespace CalcEngine
{ {
Number::Number() noexcept : Number::Number() noexcept : Number(1, 0, { 0 })
Number(1, 0, { 0 }) {
{} }
Number::Number(int32_t sign, int32_t exp, vector<uint32_t> const& mantissa) noexcept : Number::Number(int32_t sign, int32_t exp, vector<uint32_t> const& mantissa) noexcept : m_sign{ sign }, m_exp{ exp }, m_mantissa{ mantissa }
m_sign{ sign }, {
m_exp{ exp }, }
m_mantissa{ mantissa }
{}
Number::Number(PNUMBER p) noexcept : Number::Number(PNUMBER p) noexcept : m_sign{ p->sign }, m_exp{ p->exp }, m_mantissa{}
m_sign{ p->sign },
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(p->mant, p->mant + p->cdigit, back_inserter(m_mantissa));
@ -33,7 +28,7 @@ namespace CalcEngine
ret->exp = this->Exp(); ret->exp = this->Exp();
ret->cdigit = static_cast<int32_t>(this->Mantissa().size()); ret->cdigit = static_cast<int32_t>(this->Mantissa().size());
MANTTYPE *ptrRet = ret->mant; MANTTYPE* ptrRet = ret->mant;
for (auto const& digit : this->Mantissa()) for (auto const& digit : this->Mantissa())
{ {
*ptrRet++ = digit; *ptrRet++ = digit;
@ -59,6 +54,6 @@ namespace CalcEngine
bool Number::IsZero() const bool Number::IsZero() const
{ {
return all_of(m_mantissa.begin(), m_mantissa.end(), [](auto &&i) { return i == 0; }); return all_of(m_mantissa.begin(), m_mantissa.end(), [](auto&& i) { return i == 0; });
} }
} }

View file

@ -7,10 +7,9 @@ using namespace std;
namespace CalcEngine namespace CalcEngine
{ {
Rational::Rational() noexcept : Rational::Rational() noexcept : m_p{}, m_q{ 1, 0, { 1 } }
m_p{}, {
m_q{ 1, 0, { 1 } } }
{}
Rational::Rational(Number const& n) noexcept Rational::Rational(Number const& n) noexcept
{ {
@ -24,10 +23,9 @@ 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 const& p, Number const& q) noexcept : m_p{ p }, m_q{ q }
m_p{ p }, {
m_q{ q } }
{}
Rational::Rational(int32_t i) Rational::Rational(int32_t i)
{ {
@ -60,10 +58,9 @@ namespace CalcEngine
m_q = Number{ temp.Q() }; m_q = Number{ temp.Q() };
} }
Rational::Rational(PRAT prat) noexcept : Rational::Rational(PRAT prat) noexcept : m_p{ Number{ prat->pp } }, m_q{ Number{ prat->pq } }
m_p{ Number{prat->pp} }, {
m_q{ Number{prat->pq} } }
{}
PRAT Rational::ToPRAT() const PRAT Rational::ToPRAT() const
{ {
@ -353,7 +350,8 @@ namespace CalcEngine
/// Calculate the remainder after division, the sign of a result will match the sign of lhs. /// Calculate the remainder after division, the sign of a result will match the sign of lhs.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// This function has the same behavior as the standard C/C++ operator '%', to calculate the modulus after division instead, use <see cref="Rational::operator%"/> instead. /// This function has the same behavior as the standard C/C++ operator '%', to calculate the modulus after division instead, use <see
/// cref="Rational::operator%"/> instead.
/// </remarks> /// </remarks>
Rational operator%(Rational lhs, Rational const& rhs) Rational operator%(Rational lhs, Rational const& rhs)
{ {

View file

@ -58,42 +58,43 @@ void CCalcEngine::InitialOneTimeOnlySetup(CalculationManager::IResourceProvider&
// CCalcEngine::CCalcEngine // CCalcEngine::CCalcEngine
// //
////////////////////////////////////////////////// //////////////////////////////////////////////////
CCalcEngine::CCalcEngine(bool fPrecedence, bool fIntegerMode, CalculationManager::IResourceProvider* const pResourceProvider, __in_opt ICalcDisplay *pCalcDisplay, __in_opt shared_ptr<IHistoryDisplay> pHistoryDisplay) : CCalcEngine::CCalcEngine(bool fPrecedence, bool fIntegerMode, CalculationManager::IResourceProvider* const pResourceProvider,
m_fPrecedence(fPrecedence), __in_opt ICalcDisplay* pCalcDisplay, __in_opt shared_ptr<IHistoryDisplay> pHistoryDisplay)
m_fIntegerMode(fIntegerMode), : m_fPrecedence(fPrecedence)
m_pCalcDisplay(pCalcDisplay), , m_fIntegerMode(fIntegerMode)
m_resourceProvider(pResourceProvider), , m_pCalcDisplay(pCalcDisplay)
m_nOpCode(0), , m_resourceProvider(pResourceProvider)
m_nPrevOpCode(0), , m_nOpCode(0)
m_bChangeOp(false), , m_nPrevOpCode(0)
m_bRecord(false), , m_bChangeOp(false)
m_bSetCalcState(false), , m_bRecord(false)
m_input(DEFAULT_DEC_SEPARATOR), , m_bSetCalcState(false)
m_nFE(FMT_FLOAT), , m_input(DEFAULT_DEC_SEPARATOR)
m_memoryValue{ make_unique<Rational>() }, , m_nFE(FMT_FLOAT)
m_holdVal{}, , m_memoryValue{ make_unique<Rational>() }
m_currentVal{}, , m_holdVal{}
m_lastVal{}, , m_currentVal{}
m_parenVals{}, , m_lastVal{}
m_precedenceVals{}, , m_parenVals{}
m_bError(false), , m_precedenceVals{}
m_bInv(false), , m_bError(false)
m_bNoPrevEqu(true), , m_bInv(false)
m_radix(DEFAULT_RADIX), , m_bNoPrevEqu(true)
m_precision(DEFAULT_PRECISION), , m_radix(DEFAULT_RADIX)
m_cIntDigitsSav(DEFAULT_MAX_DIGITS), , m_precision(DEFAULT_PRECISION)
m_decGrouping(), , m_cIntDigitsSav(DEFAULT_MAX_DIGITS)
m_numberString(DEFAULT_NUMBER_STR), , m_decGrouping()
m_nTempCom(0), , m_numberString(DEFAULT_NUMBER_STR)
m_openParenCount(0), , m_nTempCom(0)
m_nOp(), , m_openParenCount(0)
m_nPrecOp(), , m_nOp()
m_precedenceOpCount(0), , m_nPrecOp()
m_nLastCom(0), , m_precedenceOpCount(0)
m_angletype(ANGLE_DEG), , m_nLastCom(0)
m_numwidth(QWORD_WIDTH), , m_angletype(ANGLE_DEG)
m_HistoryCollector(pCalcDisplay, pHistoryDisplay, DEFAULT_DEC_SEPARATOR), , m_numwidth(QWORD_WIDTH)
m_groupSeparator(DEFAULT_GRP_SEPARATOR) , m_HistoryCollector(pCalcDisplay, pHistoryDisplay, DEFAULT_DEC_SEPARATOR)
, m_groupSeparator(DEFAULT_GRP_SEPARATOR)
{ {
InitChopNumbers(); InitChopNumbers();

View file

@ -20,16 +20,16 @@
using namespace std; using namespace std;
using namespace CalcEngine; using namespace CalcEngine;
namespace { namespace
{
// NPrecedenceOfOp // NPrecedenceOfOp
// //
// returns a virtual number for precedence for the operator. We expect binary operator only, otherwise the lowest number // returns a virtual number for precedence for the operator. We expect binary operator only, otherwise the lowest number
// 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 uint8_t rgbPrec[] = { 0,0, IDC_OR,0, IDC_XOR,0, IDC_AND,1, static uint8_t rgbPrec[] = { 0, 0, IDC_OR, 0, IDC_XOR, 0, IDC_AND, 1, IDC_ADD, 2, IDC_SUB, 2, IDC_RSHF,
IDC_ADD,2, IDC_SUB,2, IDC_RSHF,3, IDC_LSHF,3, 3, IDC_LSHF, 3, IDC_MOD, 3, IDC_DIV, 3, IDC_MUL, 3, IDC_PWR, 4, IDC_ROOT, 4 };
IDC_MOD,3, IDC_DIV,3, IDC_MUL,3, IDC_PWR,4, IDC_ROOT, 4 };
unsigned int iPrec; unsigned int iPrec;
iPrec = 0; iPrec = 0;
@ -42,7 +42,6 @@ namespace {
iPrec = 0; iPrec = 0;
} }
return rgbPrec[iPrec + 1]; return rgbPrec[iPrec + 1];
} }
} }
@ -125,14 +124,9 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
// Toggle Record/Display mode if appropriate. // Toggle Record/Display mode if appropriate.
if (m_bRecord) if (m_bRecord)
{ {
if (IsOpInRange(wParam, IDC_AND, IDC_MMINUS) || if (IsOpInRange(wParam, IDC_AND, IDC_MMINUS) || IsOpInRange(wParam, IDC_OPENP, IDC_CLOSEP) || IsOpInRange(wParam, IDM_HEX, IDM_BIN)
IsOpInRange(wParam, IDC_OPENP, IDC_CLOSEP) || || IsOpInRange(wParam, IDM_QWORD, IDM_BYTE) || IsOpInRange(wParam, IDM_DEG, IDM_GRAD)
IsOpInRange(wParam, IDM_HEX, IDM_BIN) || || IsOpInRange(wParam, IDC_BINEDITSTART, IDC_BINEDITSTART + 63) || (IDC_INV == wParam) || (IDC_SIGN == wParam && 10 != m_radix))
IsOpInRange(wParam, IDM_QWORD, IDM_BYTE) ||
IsOpInRange(wParam, IDM_DEG, IDM_GRAD) ||
IsOpInRange(wParam, IDC_BINEDITSTART, IDC_BINEDITSTART + 63) ||
(IDC_INV == wParam) ||
(IDC_SIGN == wParam && 10 != m_radix))
{ {
m_bRecord = false; m_bRecord = false;
m_currentVal = m_input.ToRational(m_radix, m_precision); m_currentVal = m_input.ToRational(m_radix, m_precision);
@ -272,7 +266,6 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
m_HistoryCollector.PopLastOpndStart(); m_HistoryCollector.PopLastOpndStart();
goto DoPrecedenceCheckAgain; goto DoPrecedenceCheckAgain;
} }
} }
} }
@ -337,11 +330,9 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
/* reset the m_bInv flag and indicators if it is set /* reset the m_bInv flag and indicators if it is set
and have been used */ and have been used */
if (m_bInv && if (m_bInv
((wParam == IDC_CHOP) || && ((wParam == IDC_CHOP) || (wParam == IDC_SIN) || (wParam == IDC_COS) || (wParam == IDC_TAN) || (wParam == IDC_LN) || (wParam == IDC_DMS)
(wParam == IDC_SIN) || (wParam == IDC_COS) || (wParam == IDC_TAN) || || (wParam == IDC_DEGREES) || (wParam == IDC_SINH) || (wParam == IDC_COSH) || (wParam == IDC_TANH)))
(wParam == IDC_LN) || (wParam == IDC_DMS) || (wParam == IDC_DEGREES) ||
(wParam == IDC_SINH) || (wParam == IDC_COSH) || (wParam == IDC_TANH)))
{ {
m_bInv = false; m_bInv = false;
} }
@ -386,13 +377,13 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
m_nPrevOpCode = 0; m_nPrevOpCode = 0;
m_bNoPrevEqu = true; m_bNoPrevEqu = true;
/* clear the parenthesis status box indicator, this will not be /* clear the parenthesis status box indicator, this will not be
cleared for CENTR */ cleared for CENTR */
if (nullptr != m_pCalcDisplay) if (nullptr != m_pCalcDisplay)
{ {
m_pCalcDisplay->SetParenthesisNumber(0); m_pCalcDisplay->SetParenthesisNumber(0);
m_pCalcDisplay->SetExpressionDisplay(make_shared<CalculatorVector<pair<wstring, int>>>(), make_shared<CalculatorVector<shared_ptr<IExpressionCommand>>>()); m_pCalcDisplay->SetExpressionDisplay(make_shared<CalculatorVector<pair<wstring, int>>>(),
make_shared<CalculatorVector<shared_ptr<IExpressionCommand>>>());
} }
m_HistoryCollector.ClearHistoryLine(wstring()); m_HistoryCollector.ClearHistoryLine(wstring());
@ -485,7 +476,8 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
m_HistoryCollector.CompleteHistoryLine(groupedString); m_HistoryCollector.CompleteHistoryLine(groupedString);
if (nullptr != m_pCalcDisplay) if (nullptr != m_pCalcDisplay)
{ {
m_pCalcDisplay->SetExpressionDisplay(make_shared<CalculatorVector<pair<wstring, int>>>(), make_shared<CalculatorVector<shared_ptr<IExpressionCommand>>>()); m_pCalcDisplay->SetExpressionDisplay(make_shared<CalculatorVector<pair<wstring, int>>>(),
make_shared<CalculatorVector<shared_ptr<IExpressionCommand>>>());
} }
} }
@ -749,7 +741,6 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
m_bInv = !m_bInv; m_bInv = !m_bInv;
break; break;
} }
} }
// Helper function to resolve one item on the precedence stack. // Helper function to resolve one item on the precedence stack.
@ -814,7 +805,6 @@ void CCalcEngine::CheckAndAddLastBinOpToHistory(bool addToHistory)
// So erase the last operand // So erase the last operand
m_HistoryCollector.RemoveLastOpndFromHistory(); m_HistoryCollector.RemoveLastOpndFromHistory();
} }
} }
else if (m_HistoryCollector.FOpndAddedToHistory() && !m_bError) else if (m_HistoryCollector.FOpndAddedToHistory() && !m_bError)
{ {
@ -823,8 +813,7 @@ void CCalcEngine::CheckAndAddLastBinOpToHistory(bool addToHistory)
// 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) && if ((IsUnaryOpCode(m_nLastCom) || IDC_SIGN == m_nLastCom || IDC_CLOSEP == m_nLastCom) && 0 == m_openParenCount)
0 == m_openParenCount)
{ {
if (addToHistory) if (addToHistory)
{ {
@ -877,9 +866,8 @@ struct FunctionNameElement
}; };
// Table for each unary operator // Table for each unary operator
static const std::unordered_map<int, FunctionNameElement> unaryOperatorStringTable = static const std::unordered_map<int, FunctionNameElement> unaryOperatorStringTable = {
{ { IDC_CHOP, { L"", SIDS_FRAC } },
{ IDC_CHOP, { L"", SIDS_FRAC} },
{ IDC_SIN, { SIDS_SIND, SIDS_ASIND, SIDS_SINR, SIDS_ASINR, SIDS_SING, SIDS_ASING } }, { IDC_SIN, { SIDS_SIND, SIDS_ASIND, SIDS_SINR, SIDS_ASINR, SIDS_SING, SIDS_ASING } },
{ IDC_COS, { SIDS_COSD, SIDS_ACOSD, SIDS_COSR, SIDS_ACOSR, SIDS_COSG, SIDS_ACOSG } }, { IDC_COS, { SIDS_COSD, SIDS_ACOSD, SIDS_COSR, SIDS_ACOSR, SIDS_COSG, SIDS_ACOSG } },
@ -889,7 +877,7 @@ static const std::unordered_map<int, FunctionNameElement> unaryOperatorStringTab
{ IDC_COSH, { L"", SIDS_ACOSH } }, { IDC_COSH, { L"", SIDS_ACOSH } },
{ IDC_TANH, { L"", SIDS_ATANH } }, { IDC_TANH, { L"", SIDS_ATANH } },
{ IDC_LN , { L"", SIDS_POWE } }, { IDC_LN, { L"", SIDS_POWE } },
{ IDC_SQR, { SIDS_SQR } }, { IDC_SQR, { SIDS_SQR } },
{ IDC_CUB, { SIDS_CUBE } }, { IDC_CUB, { SIDS_CUBE } },
{ IDC_FAC, { SIDS_FACT } }, { IDC_FAC, { SIDS_FACT } },

View file

@ -25,7 +25,6 @@ constexpr uint32_t MAX_GROUPING_SIZE = 16;
constexpr wstring_view c_decPreSepStr = L"[+-]?(\\d*)["; constexpr wstring_view c_decPreSepStr = L"[+-]?(\\d*)[";
constexpr wstring_view c_decPostSepStr = L"]?(\\d*)(?:e[+-]?(\\d*))?$"; constexpr wstring_view c_decPostSepStr = L"]?(\\d*)(?:e[+-]?(\\d*))?$";
/****************************************************************************\ /****************************************************************************\
* void DisplayNum(void) * void DisplayNum(void)
* *
@ -37,7 +36,8 @@ constexpr wstring_view c_decPostSepStr = L"]?(\\d*)(?:e[+-]?(\\d*))?$";
// //
// State of calc last time DisplayNum was called // State of calc last time DisplayNum was called
// //
typedef struct { typedef struct
{
Rational value; Rational value;
int32_t precision; int32_t precision;
uint32_t radix; uint32_t radix;
@ -66,7 +66,7 @@ CalcEngine::Rational CCalcEngine::TruncateNumForIntMath(CalcEngine::Rational con
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 ^= m_chopNumbers[m_numwidth]; result ^= m_chopNumbers[m_numwidth];
} }
@ -84,15 +84,8 @@ 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 || if (m_bRecord || gldPrevious.value != m_currentVal || gldPrevious.precision != m_precision || gldPrevious.radix != m_radix || gldPrevious.nFE != (int)m_nFE
gldPrevious.value != m_currentVal || || gldPrevious.bUseSep != true || gldPrevious.numwidth != m_numwidth || gldPrevious.fIntMath != m_fIntegerMode || gldPrevious.bRecord != m_bRecord)
gldPrevious.precision != m_precision ||
gldPrevious.radix != m_radix ||
gldPrevious.nFE != (int)m_nFE ||
gldPrevious.bUseSep != true ||
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;

View file

@ -226,4 +226,3 @@ void CCalcEngine::DisplayError(uint32_t nError)
m_HistoryCollector.ClearHistoryLine(errorString); m_HistoryCollector.ClearHistoryLine(errorString);
} }

View file

@ -126,7 +126,7 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa
} }
else else
{ {
//other modes, use modrat (modulus after division) // other modes, use modrat (modulus after division)
result = Mod(result, temp); result = Mod(result, temp);
} }
} }

View file

@ -7,11 +7,12 @@
using namespace std; using namespace std;
using namespace CalculationManager; using namespace CalculationManager;
CalculatorHistory::CalculatorHistory(size_t maxSize) : CalculatorHistory::CalculatorHistory(size_t maxSize) : m_maxHistorySize(maxSize)
m_maxHistorySize(maxSize) {
{} }
unsigned int CalculatorHistory::AddToHistory(_In_ shared_ptr<CalculatorVector <pair<wstring, int>>> const &tokens, _In_ shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> const &commands, _In_ wstring_view result) unsigned int CalculatorHistory::AddToHistory(_In_ shared_ptr<CalculatorVector<pair<wstring, int>>> const& tokens,
_In_ shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> const& commands, _In_ wstring_view result)
{ {
unsigned int addedIndex; unsigned int addedIndex;
wstring generatedExpression; wstring generatedExpression;
@ -31,8 +32,7 @@ unsigned int CalculatorHistory::AddToHistory(_In_ shared_ptr<CalculatorVector <p
return addedIndex; return addedIndex;
} }
unsigned int CalculatorHistory::AddItem(_In_ shared_ptr<HISTORYITEM> const& spHistoryItem)
unsigned int CalculatorHistory::AddItem(_In_ shared_ptr<HISTORYITEM> const &spHistoryItem)
{ {
if (m_historyItems.size() >= m_maxHistorySize) if (m_historyItems.size() >= m_maxHistorySize)
{ {

View file

@ -15,7 +15,7 @@ namespace CalculationManager
struct HISTORYITEMVECTOR struct HISTORYITEMVECTOR
{ {
std::shared_ptr<CalculatorVector <std::pair<std::wstring, int>>> spTokens; std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> spTokens;
std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> spCommands; std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> spCommands;
std::wstring expression; std::wstring expression;
std::wstring result; std::wstring result;
@ -26,19 +26,21 @@ namespace CalculationManager
HISTORYITEMVECTOR historyItemVector; HISTORYITEMVECTOR historyItemVector;
}; };
class CalculatorHistory : class CalculatorHistory : public IHistoryDisplay
public IHistoryDisplay
{ {
public: public:
CalculatorHistory(const size_t maxSize); CalculatorHistory(const size_t maxSize);
unsigned int AddToHistory(_In_ std::shared_ptr<CalculatorVector <std::pair<std::wstring, int>>> const &spTokens, _In_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const &spCommands, std::wstring_view result); unsigned int AddToHistory(_In_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const& spTokens,
_In_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const& spCommands, std::wstring_view result);
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();
unsigned int AddItem(_In_ std::shared_ptr<HISTORYITEM> const &spHistoryItem); unsigned int AddItem(_In_ std::shared_ptr<HISTORYITEM> const& spHistoryItem);
bool RemoveItem(unsigned int uIdx); bool RemoveItem(unsigned int uIdx);
size_t MaxHistorySize() const { return m_maxHistorySize; } size_t MaxHistorySize() const
{
return m_maxHistorySize;
}
~CalculatorHistory(void); ~CalculatorHistory(void);
private: private:

View file

@ -14,25 +14,21 @@ static constexpr size_t SERIALIZED_NUMBER_MINSIZE = 3;
// Converts Memory Command enum value to unsigned char, // Converts Memory Command enum value to unsigned char,
// while ignoring Warning C4309: 'conversion' : truncation of constant value // while ignoring Warning C4309: 'conversion' : truncation of constant value
#define MEMORY_COMMAND_TO_UNSIGNED_CHAR(c)\ #define MEMORY_COMMAND_TO_UNSIGNED_CHAR(c) __pragma(warning(push)) __pragma(warning(disable : 4309)) static_cast<unsigned char>(c) __pragma(warning(pop))
__pragma(warning(push))\
__pragma(warning(disable: 4309))\
static_cast<unsigned char>(c)\
__pragma(warning(pop))
namespace CalculationManager namespace CalculationManager
{ {
CalculatorManager::CalculatorManager(_In_ ICalcDisplay* displayCallback, _In_ IResourceProvider* resourceProvider) : CalculatorManager::CalculatorManager(_In_ ICalcDisplay* displayCallback, _In_ IResourceProvider* resourceProvider)
m_displayCallback(displayCallback), : m_displayCallback(displayCallback)
m_currentCalculatorEngine(nullptr), , m_currentCalculatorEngine(nullptr)
m_resourceProvider(resourceProvider), , m_resourceProvider(resourceProvider)
m_inHistoryItemLoadMode(false), , m_inHistoryItemLoadMode(false)
m_persistedPrimaryValue(), , m_persistedPrimaryValue()
m_isExponentialFormat(false), , m_isExponentialFormat(false)
m_currentDegreeMode(Command::CommandNULL), , m_currentDegreeMode(Command::CommandNULL)
m_savedDegreeMode(Command::CommandDEG), , m_savedDegreeMode(Command::CommandDEG)
m_pStdHistory(new CalculatorHistory(MAX_HISTORY_ITEMS)), , m_pStdHistory(new CalculatorHistory(MAX_HISTORY_ITEMS))
m_pSciHistory(new CalculatorHistory(MAX_HISTORY_ITEMS)) , m_pSciHistory(new CalculatorHistory(MAX_HISTORY_ITEMS))
{ {
CCalcEngine::InitialOneTimeOnlySetup(*m_resourceProvider); CCalcEngine::InitialOneTimeOnlySetup(*m_resourceProvider);
} }
@ -89,7 +85,8 @@ namespace CalculationManager
/// Used to set the expression display value on ViewModel /// Used to set the expression display value on ViewModel
/// </summary> /// </summary>
/// <param name="expressionString">wstring representing expression to be displayed</param> /// <param name="expressionString">wstring representing expression to be displayed</param>
void CalculatorManager::SetExpressionDisplay(_Inout_ shared_ptr<CalculatorVector<pair<wstring, int>>> const &tokens, _Inout_ shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> const &commands) void CalculatorManager::SetExpressionDisplay(_Inout_ shared_ptr<CalculatorVector<pair<wstring, int>>> const& tokens,
_Inout_ shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> const& commands)
{ {
if (!m_inHistoryItemLoadMode) if (!m_inHistoryItemLoadMode)
{ {
@ -165,7 +162,8 @@ namespace CalculationManager
{ {
if (!m_standardCalculatorEngine) if (!m_standardCalculatorEngine)
{ {
m_standardCalculatorEngine = make_unique<CCalcEngine>(false /* Respect Order of Operations */, false /* Set to Integer Mode */, m_resourceProvider, this, m_pStdHistory); m_standardCalculatorEngine =
make_unique<CCalcEngine>(false /* Respect Order of Operations */, false /* Set to Integer Mode */, m_resourceProvider, this, m_pStdHistory);
} }
m_currentCalculatorEngine = m_standardCalculatorEngine.get(); m_currentCalculatorEngine = m_standardCalculatorEngine.get();
@ -183,7 +181,8 @@ namespace CalculationManager
{ {
if (!m_scientificCalculatorEngine) if (!m_scientificCalculatorEngine)
{ {
m_scientificCalculatorEngine = make_unique<CCalcEngine>(true /* Respect Order of Operations */, false /* Set to Integer Mode */, m_resourceProvider, this, m_pSciHistory); m_scientificCalculatorEngine =
make_unique<CCalcEngine>(true /* Respect Order of Operations */, false /* Set to Integer Mode */, m_resourceProvider, this, m_pSciHistory);
} }
m_currentCalculatorEngine = m_scientificCalculatorEngine.get(); m_currentCalculatorEngine = m_scientificCalculatorEngine.get();
@ -198,9 +197,10 @@ namespace CalculationManager
/// </summary> /// </summary>
void CalculatorManager::SetProgrammerMode() void CalculatorManager::SetProgrammerMode()
{ {
if(!m_programmerCalculatorEngine) if (!m_programmerCalculatorEngine)
{ {
m_programmerCalculatorEngine = make_unique<CCalcEngine>(true /* Respect Order of Operations */, true /* Set to Integer Mode */, m_resourceProvider, this, nullptr); m_programmerCalculatorEngine =
make_unique<CCalcEngine>(true /* Respect Order of Operations */, true /* Set to Integer Mode */, m_resourceProvider, this, nullptr);
} }
m_currentCalculatorEngine = m_programmerCalculatorEngine.get(); m_currentCalculatorEngine = m_programmerCalculatorEngine.get();
@ -209,7 +209,6 @@ namespace CalculationManager
m_currentCalculatorEngine->ChangePrecision(static_cast<int>(CalculatorPrecision::ProgrammerModePrecision)); m_currentCalculatorEngine->ChangePrecision(static_cast<int>(CalculatorPrecision::ProgrammerModePrecision));
} }
/// <summary> /// <summary>
/// Send command to the Calc Engine /// Send command to the Calc Engine
/// Cast Command Enum to OpCode. /// Cast Command Enum to OpCode.
@ -220,8 +219,8 @@ namespace CalculationManager
{ {
// When the expression line is cleared, we save the current state, which includes, // When the expression line is cleared, we save the current state, which includes,
// primary display, memory, and degree mode // primary display, memory, and degree mode
if (command == Command::CommandCLEAR || command == Command::CommandEQU if (command == Command::CommandCLEAR || command == Command::CommandEQU || command == Command::ModeBasic || command == Command::ModeScientific
|| command == Command::ModeBasic || command == Command::ModeScientific || command == Command::ModeProgrammer) || command == Command::ModeProgrammer)
{ {
switch (command) switch (command)
{ {
@ -361,7 +360,7 @@ namespace CalculationManager
/// DeSerialize the primary display from vector of long /// DeSerialize the primary display from vector of long
/// </summary> /// </summary>
/// <param name = "serializedPrimaryDisplay">Serialized Rational of primary display</param> /// <param name = "serializedPrimaryDisplay">Serialized Rational of primary display</param>
void CalculatorManager::DeSerializePrimaryDisplay(const vector<long> &serializedPrimaryDisplay) void CalculatorManager::DeSerializePrimaryDisplay(const vector<long>& serializedPrimaryDisplay)
{ {
if (serializedPrimaryDisplay.empty()) if (serializedPrimaryDisplay.empty())
{ {
@ -404,7 +403,7 @@ namespace CalculationManager
/// DeSerialize the Memory from vector of long /// DeSerialize the Memory from vector of long
/// </summary> /// </summary>
/// <param name = "serializedMemory">Serialized Rational of memory</param> /// <param name = "serializedMemory">Serialized Rational of memory</param>
void CalculatorManager::DeSerializeMemory(const vector<long> &serializedMemory) void CalculatorManager::DeSerializeMemory(const vector<long>& serializedMemory)
{ {
vector<long>::const_iterator itr = serializedMemory.begin(); vector<long>::const_iterator itr = serializedMemory.begin();
while (itr != serializedMemory.end()) while (itr != serializedMemory.end())
@ -435,8 +434,8 @@ namespace CalculationManager
for (auto commandItr = serializedData.begin(); commandItr != serializedData.end(); ++commandItr) for (auto commandItr = serializedData.begin(); commandItr != serializedData.end(); ++commandItr)
{ {
if (*commandItr >= MEMORY_COMMAND_TO_UNSIGNED_CHAR(MemoryCommand::MemorizeNumber) && if (*commandItr >= MEMORY_COMMAND_TO_UNSIGNED_CHAR(MemoryCommand::MemorizeNumber)
*commandItr <= MEMORY_COMMAND_TO_UNSIGNED_CHAR(MemoryCommand::MemorizedNumberClearAll)) && *commandItr <= MEMORY_COMMAND_TO_UNSIGNED_CHAR(MemoryCommand::MemorizedNumberClearAll))
{ {
// MemoryCommands(which have values above 255) are pushed on m_savedCommands upon casting to unsigned char. // MemoryCommands(which have values above 255) are pushed on m_savedCommands upon casting to unsigned char.
// SerializeCommands uses m_savedCommands, which is then used in DeSerializeCommands. // SerializeCommands uses m_savedCommands, which is then used in DeSerializeCommands.
@ -622,10 +621,10 @@ namespace CalculationManager
} }
/// <summary> /// <summary>
/// Helper function that selects a memory from the vector and set it to CCalcEngine /// Helper function that selects a memory from the vector and set it to CCalcEngine
/// 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)
{ {
if (m_currentCalculatorEngine->FInErrorState()) if (m_currentCalculatorEngine->FInErrorState())
@ -673,9 +672,7 @@ namespace CalculationManager
vector<shared_ptr<HISTORYITEM>> const& CalculatorManager::GetHistoryItems(_In_ CALCULATOR_MODE mode) vector<shared_ptr<HISTORYITEM>> const& CalculatorManager::GetHistoryItems(_In_ CALCULATOR_MODE mode)
{ {
return (mode == CM_STD) ? return (mode == CM_STD) ? m_pStdHistory->GetHistory() : m_pSciHistory->GetHistory();
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)

View file

@ -91,7 +91,8 @@ namespace CalculationManager
// ICalcDisplay // ICalcDisplay
void SetPrimaryDisplay(_In_ const std::wstring& displayString, _In_ bool isError) override; void SetPrimaryDisplay(_In_ const std::wstring& displayString, _In_ bool isError) override;
void SetIsInError(bool isError) override; void SetIsInError(bool isError) override;
void SetExpressionDisplay(_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const &tokens, _Inout_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const &commands) override; void SetExpressionDisplay(_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const& tokens,
_Inout_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const& commands) override;
void SetMemorizedNumbers(_In_ const std::vector<std::wstring>& memorizedNumbers) override; void SetMemorizedNumbers(_In_ const std::vector<std::wstring>& memorizedNumbers) override;
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;
@ -101,7 +102,6 @@ namespace CalculationManager
void BinaryOperatorReceived() override; void BinaryOperatorReceived() override;
void MemoryItemChanged(unsigned int indexOfMemory) override; void MemoryItemChanged(unsigned int indexOfMemory) override;
CalculatorManager(ICalcDisplay* displayCallback, IResourceProvider* resourceProvider); CalculatorManager(ICalcDisplay* displayCallback, IResourceProvider* resourceProvider);
~CalculatorManager(); ~CalculatorManager();
@ -114,10 +114,10 @@ namespace CalculationManager
void DeSerializeCommands(_In_ const std::vector<unsigned char>& serializedData); void DeSerializeCommands(_In_ const std::vector<unsigned char>& serializedData);
void SerializeMemory(); void SerializeMemory();
std::vector<long> GetSerializedMemory(); std::vector<long> GetSerializedMemory();
void DeSerializeMemory(const std::vector<long> &serializedMemory); void DeSerializeMemory(const std::vector<long>& serializedMemory);
void SerializePrimaryDisplay(); void SerializePrimaryDisplay();
std::vector<long> GetSerializedPrimaryDisplay(); std::vector<long> GetSerializedPrimaryDisplay();
void DeSerializePrimaryDisplay(const std::vector<long> &serializedPrimaryDisplay); void DeSerializePrimaryDisplay(const std::vector<long>& serializedPrimaryDisplay);
Command SerializeSavedDegreeMode(); Command SerializeSavedDegreeMode();
void MemorizeNumber(); void MemorizeNumber();
@ -128,7 +128,10 @@ namespace CalculationManager
void MemorizedNumberClearAll(); void MemorizedNumberClearAll();
bool IsEngineRecording(); bool IsEngineRecording();
std::vector<unsigned char> GetSavedCommands(){ return m_savedCommands; } std::vector<unsigned char> GetSavedCommands()
{
return m_savedCommands;
}
void SetRadix(RADIX_TYPE iRadixType); void SetRadix(RADIX_TYPE iRadixType);
void SetMemorizedNumbersString(); void SetMemorizedNumbersString();
std::wstring GetResultForRadix(uint32_t radix, int32_t precision); std::wstring GetResultForRadix(uint32_t radix, int32_t precision);
@ -141,7 +144,10 @@ namespace CalculationManager
std::shared_ptr<HISTORYITEM> const& GetHistoryItem(_In_ unsigned int uIdx); std::shared_ptr<HISTORYITEM> const& GetHistoryItem(_In_ unsigned int uIdx);
bool RemoveHistoryItem(_In_ unsigned int uIdx); bool RemoveHistoryItem(_In_ unsigned int uIdx);
void ClearHistory(); void ClearHistory();
size_t MaxHistorySize() const { return m_pHistory->MaxHistorySize(); } size_t MaxHistorySize() const
{
return m_pHistory->MaxHistorySize();
}
CalculationManager::Command GetCurrentDegreeMode(); CalculationManager::Command GetCurrentDegreeMode();
void SetHistory(_In_ CALCULATOR_MODE eMode, _In_ std::vector<std::shared_ptr<HISTORYITEM>> const& history); void SetHistory(_In_ CALCULATOR_MODE eMode, _In_ std::vector<std::shared_ptr<HISTORYITEM>> const& history);
void SetInHistoryItemLoadMode(_In_ bool isHistoryItemLoadMode); void SetInHistoryItemLoadMode(_In_ bool isHistoryItemLoadMode);

View file

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

View file

@ -14,7 +14,7 @@ template <typename TType>
class CalculatorVector class CalculatorVector
{ {
public: public:
ResultCode GetAt(_In_opt_ unsigned int index, _Out_ TType *item) ResultCode GetAt(_In_opt_ unsigned int index, _Out_ TType* item)
{ {
ResultCode hr = S_OK; ResultCode hr = S_OK;
try try
@ -28,7 +28,7 @@ public:
return hr; return hr;
} }
ResultCode GetSize(_Out_ unsigned int *size) ResultCode GetSize(_Out_ unsigned int* size)
{ {
*size = static_cast<unsigned>(m_vector.size()); *size = static_cast<unsigned>(m_vector.size());
return S_OK; return S_OK;
@ -122,7 +122,7 @@ public:
{ {
ResultCode hr = S_OK; ResultCode hr = S_OK;
unsigned int nTokens = 0; unsigned int nTokens = 0;
std::pair <std::wstring, int> currentPair; std::pair<std::wstring, int> currentPair;
hr = this->GetSize(&nTokens); hr = this->GetSize(&nTokens);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
{ {

View file

@ -7,9 +7,19 @@ namespace UnitConversionManager
{ {
enum class Command enum class Command
{ {
Zero, One, Two, Three, Four, Five, Six, Seven, Eight, Nine, Zero,
One,
Two,
Three,
Four,
Five,
Six,
Seven,
Eight,
Nine,
Decimal, Decimal,
Negate, Backspace, Negate,
Backspace,
Clear, Clear,
Reset, Reset,
None None
@ -20,9 +30,19 @@ namespace CurrencyConversionManager
{ {
enum class Command enum class Command
{ {
Zero, One, Two, Three, Four, Five, Six, Seven, Eight, Nine, Zero,
One,
Two,
Three,
Four,
Five,
Six,
Seven,
Eight,
Nine,
Decimal, Decimal,
Negate, Backspace, Negate,
Backspace,
Clear, Clear,
None None
}; };
@ -85,7 +105,6 @@ namespace CalculationManager
CommandCOSH = 106, CommandCOSH = 106,
CommandTANH = 107, CommandTANH = 107,
CommandLN = 108, CommandLN = 108,
CommandLOG = 109, CommandLOG = 109,
CommandSQRT = 110, CommandSQRT = 110,

View file

@ -13,8 +13,9 @@ constexpr wchar_t chNegate = L'-';
constexpr wchar_t chExp = L'e'; constexpr wchar_t chExp = L'e';
constexpr wchar_t chPlus = L'+'; constexpr wchar_t chPlus = L'+';
CParentheses::CParentheses(_In_ int command) :m_command(command) CParentheses::CParentheses(_In_ int command) : m_command(command)
{} {
}
int CParentheses::GetCommand() const int CParentheses::GetCommand() const
{ {
@ -26,7 +27,7 @@ CalculationManager::CommandType CParentheses::GetCommandType() const
return CalculationManager::CommandType::Parentheses; return CalculationManager::CommandType::Parentheses;
} }
void CParentheses::Accept(_In_ ISerializeCommandVisitor &commandVisitor) void CParentheses::Accept(_In_ ISerializeCommandVisitor& commandVisitor)
{ {
commandVisitor.Visit(*this); commandVisitor.Visit(*this);
} }
@ -44,7 +45,7 @@ CUnaryCommand::CUnaryCommand(int command1, int command2)
m_command->Append(command2); m_command->Append(command2);
} }
const shared_ptr<CalculatorVector<int>> & CUnaryCommand::GetCommands() const const shared_ptr<CalculatorVector<int>>& CUnaryCommand::GetCommands() const
{ {
return m_command; return m_command;
} }
@ -67,13 +68,14 @@ void CUnaryCommand::SetCommands(int command1, int command2)
m_command->Append(command2); m_command->Append(command2);
} }
void CUnaryCommand::Accept(_In_ ISerializeCommandVisitor &commandVisitor) void CUnaryCommand::Accept(_In_ ISerializeCommandVisitor& commandVisitor)
{ {
commandVisitor.Visit(*this); commandVisitor.Visit(*this);
} }
CBinaryCommand::CBinaryCommand(int command) :m_command(command) CBinaryCommand::CBinaryCommand(int command) : m_command(command)
{} {
}
void CBinaryCommand::SetCommand(int command) void CBinaryCommand::SetCommand(int command)
{ {
@ -90,19 +92,15 @@ CalculationManager::CommandType CBinaryCommand::GetCommandType() const
return CalculationManager::CommandType::BinaryCommand; return CalculationManager::CommandType::BinaryCommand;
} }
void CBinaryCommand::Accept(_In_ ISerializeCommandVisitor &commandVisitor) void CBinaryCommand::Accept(_In_ ISerializeCommandVisitor& commandVisitor)
{ {
commandVisitor.Visit(*this); commandVisitor.Visit(*this);
} }
COpndCommand::COpndCommand(shared_ptr<CalculatorVector<int>> const &commands, bool fNegative, bool fDecimal, bool fSciFmt) : COpndCommand::COpndCommand(shared_ptr<CalculatorVector<int>> const& commands, bool fNegative, bool fDecimal, bool fSciFmt)
m_commands(commands), : m_commands(commands), m_fNegative(fNegative), m_fSciFmt(fSciFmt), m_fDecimal(fDecimal), m_fInitialized(false), m_value{}
m_fNegative(fNegative), {
m_fSciFmt(fSciFmt), }
m_fDecimal(fDecimal),
m_fInitialized(false),
m_value{}
{}
void COpndCommand::Initialize(Rational const& rat) void COpndCommand::Initialize(Rational const& rat)
{ {
@ -110,7 +108,7 @@ void COpndCommand::Initialize(Rational const& rat)
m_fInitialized = true; m_fInitialized = true;
} }
const shared_ptr<CalculatorVector<int>> & COpndCommand::GetCommands() const const shared_ptr<CalculatorVector<int>>& COpndCommand::GetCommands() const
{ {
return m_commands; return m_commands;
} }
@ -213,7 +211,7 @@ void COpndCommand::ClearAllAndAppendCommand(CalculationManager::Command command)
m_fDecimal = false; m_fDecimal = false;
} }
const wstring & COpndCommand::GetToken(wchar_t decimalSymbol) const wstring& COpndCommand::GetToken(wchar_t decimalSymbol)
{ {
static const wchar_t chZero = L'0'; static const wchar_t chZero = L'0';
@ -299,7 +297,7 @@ wstring COpndCommand::GetString(uint32_t radix, int32_t precision)
return result; return result;
} }
void COpndCommand::Accept(_In_ ISerializeCommandVisitor &commandVisitor) void COpndCommand::Accept(_In_ ISerializeCommandVisitor& commandVisitor)
{ {
commandVisitor.Visit(*this); commandVisitor.Visit(*this);
} }

View file

@ -12,7 +12,7 @@ public:
CParentheses(_In_ int command); CParentheses(_In_ int command);
int GetCommand() const override; int GetCommand() const override;
CalculationManager::CommandType GetCommandType() const override; CalculationManager::CommandType GetCommandType() const override;
void Accept(_In_ ISerializeCommandVisitor &commandVisitor) override; void Accept(_In_ ISerializeCommandVisitor& commandVisitor) override;
private: private:
int m_command; int m_command;
@ -23,11 +23,11 @@ class CUnaryCommand final : public IUnaryCommand
public: public:
CUnaryCommand(int command); CUnaryCommand(int command);
CUnaryCommand(int command1, int command2); CUnaryCommand(int command1, int command2);
const std::shared_ptr<CalculatorVector<int>> & GetCommands() const override; const std::shared_ptr<CalculatorVector<int>>& GetCommands() const override;
CalculationManager::CommandType GetCommandType() const override; CalculationManager::CommandType GetCommandType() const override;
void SetCommand(int command) override; void SetCommand(int command) override;
void SetCommands(int command1, int command2) override; void SetCommands(int command1, int command2) override;
void Accept(_In_ ISerializeCommandVisitor &commandVisitor) override; void Accept(_In_ ISerializeCommandVisitor& commandVisitor) override;
private: private:
std::shared_ptr<CalculatorVector<int>> m_command; std::shared_ptr<CalculatorVector<int>> m_command;
@ -40,7 +40,7 @@ public:
void SetCommand(int command) override; void SetCommand(int command) override;
int GetCommand() const override; int GetCommand() const override;
CalculationManager::CommandType GetCommandType() const override; CalculationManager::CommandType GetCommandType() const override;
void Accept(_In_ ISerializeCommandVisitor &commandVisitor) override; void Accept(_In_ ISerializeCommandVisitor& commandVisitor) override;
private: private:
int m_command; int m_command;
@ -49,14 +49,10 @@ private:
class COpndCommand final : public IOpndCommand class COpndCommand final : public IOpndCommand
{ {
public: public:
COpndCommand( COpndCommand(std::shared_ptr<CalculatorVector<int>> const& commands, bool fNegative, bool fDecimal, bool fSciFmt);
std::shared_ptr<CalculatorVector<int>> const &commands,
bool fNegative,
bool fDecimal,
bool fSciFmt);
void Initialize(CalcEngine::Rational const& rat); void Initialize(CalcEngine::Rational const& rat);
const std::shared_ptr<CalculatorVector<int>> & GetCommands() const override; const std::shared_ptr<CalculatorVector<int>>& GetCommands() const override;
void SetCommands(std::shared_ptr<CalculatorVector<int>> const& commands) override; void SetCommands(std::shared_ptr<CalculatorVector<int>> const& commands) override;
void AppendCommand(int command) override; void AppendCommand(int command) override;
void ToggleSign() override; void ToggleSign() override;
@ -64,9 +60,9 @@ public:
bool IsNegative() const override; bool IsNegative() const override;
bool IsSciFmt() const override; bool IsSciFmt() const override;
bool IsDecimalPresent() const override; bool IsDecimalPresent() const override;
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);
private: private:
@ -83,8 +79,8 @@ private:
class ISerializeCommandVisitor class ISerializeCommandVisitor
{ {
public: public:
virtual void Visit(_In_ COpndCommand &opndCmd) = 0; virtual void Visit(_In_ COpndCommand& opndCmd) = 0;
virtual void Visit(_In_ CUnaryCommand &unaryCmd) = 0; virtual void Visit(_In_ CUnaryCommand& unaryCmd) = 0;
virtual void Visit(_In_ CBinaryCommand &binaryCmd) = 0; virtual void Visit(_In_ CBinaryCommand& binaryCmd) = 0;
virtual void Visit(_In_ CParentheses &paraCmd) = 0; virtual void Visit(_In_ CParentheses& paraCmd) = 0;
}; };

View file

@ -13,7 +13,7 @@ class IExpressionCommand
{ {
public: public:
virtual CalculationManager::CommandType GetCommandType() const = 0; virtual CalculationManager::CommandType GetCommandType() const = 0;
virtual void Accept(_In_ ISerializeCommandVisitor &commandVisitor) = 0; virtual void Accept(_In_ ISerializeCommandVisitor& commandVisitor) = 0;
}; };
class IOperatorCommand : public IExpressionCommand class IOperatorCommand : public IExpressionCommand
@ -25,7 +25,7 @@ public:
class IUnaryCommand : public IOperatorCommand class IUnaryCommand : public IOperatorCommand
{ {
public: public:
virtual const std::shared_ptr<CalculatorVector<int>> & GetCommands() const = 0; virtual const std::shared_ptr<CalculatorVector<int>>& GetCommands() const = 0;
virtual void SetCommands(int command1, int command2) = 0; virtual void SetCommands(int command1, int command2) = 0;
}; };
@ -39,14 +39,14 @@ public:
class IOpndCommand : public IExpressionCommand class IOpndCommand : public IExpressionCommand
{ {
public: public:
virtual const std::shared_ptr<CalculatorVector<int>> & GetCommands() const= 0; virtual const std::shared_ptr<CalculatorVector<int>>& GetCommands() const = 0;
virtual void AppendCommand(int command) = 0; virtual void AppendCommand(int command) = 0;
virtual void ToggleSign() = 0; virtual void ToggleSign() = 0;
virtual void RemoveFromEnd() = 0; virtual void RemoveFromEnd() = 0;
virtual bool IsNegative() const = 0; virtual bool IsNegative() const = 0;
virtual bool IsSciFmt() const = 0; virtual bool IsSciFmt() const = 0;
virtual bool IsDecimalPresent() const = 0; virtual bool IsDecimalPresent() const = 0;
virtual const std::wstring & GetToken(wchar_t decimalSymbol) = 0; virtual const std::wstring& GetToken(wchar_t decimalSymbol) = 0;
virtual void SetCommands(std::shared_ptr<CalculatorVector<int>> const& commands) = 0; virtual void SetCommands(std::shared_ptr<CalculatorVector<int>> const& commands) = 0;
}; };

View file

@ -45,7 +45,6 @@
#define IDC_WORD IDM_WORD #define IDC_WORD IDM_WORD
#define IDC_BYTE IDM_BYTE #define IDC_BYTE IDM_BYTE
// Key IDs: // Key IDs:
// These id's must be consecutive from IDC_FIRSTCONTROL to IDC_LASTCONTROL. // These id's must be consecutive from IDC_FIRSTCONTROL to IDC_LASTCONTROL.
// The actual values don't matter but the order and sequence are very important. // The actual values don't matter but the order and sequence are very important.
@ -77,7 +76,6 @@
#define IDC_ROOT 96 #define IDC_ROOT 96
#define IDC_PWR 97 #define IDC_PWR 97
#define IDC_UNARYFIRST IDC_CHOP #define IDC_UNARYFIRST IDC_CHOP
#define IDC_CHOP 98 // Unary operators must be between IDC_CHOP and IDC_EQU #define IDC_CHOP 98 // Unary operators must be between IDC_CHOP and IDC_EQU
#define IDC_ROL 99 #define IDC_ROL 99
@ -116,7 +114,6 @@
#define IDC_EXP 127 #define IDC_EXP 127
#define IDC_OPENP 128 #define IDC_OPENP 128
#define IDC_CLOSEP 129 #define IDC_CLOSEP 129
@ -208,9 +205,7 @@
#define IDC_BINPOS63 763 #define IDC_BINPOS63 763
#define IDC_BINEDITEND 763 #define IDC_BINEDITEND 763
// The strings in the following range IDS_ENGINESTR_FIRST ... IDS_ENGINESTR_MAX are strings allocated in the // The strings in the following range IDS_ENGINESTR_FIRST ... IDS_ENGINESTR_MAX are strings allocated in the
// resource for the purpose internal to Engine and cant be used by the clients // resource for the purpose internal to Engine and cant be used by the clients
#define IDS_ENGINESTR_FIRST 0 #define IDS_ENGINESTR_FIRST 0
#define IDS_ENGINESTR_MAX 200 #define IDS_ENGINESTR_MAX 200

View file

@ -31,7 +31,8 @@
// The real exports follows later // The real exports follows later
// This is expected to be in same order as IDM_QWORD, IDM_DWORD etc. // This is expected to be in same order as IDM_QWORD, IDM_DWORD etc.
enum eNUM_WIDTH { enum eNUM_WIDTH
{
QWORD_WIDTH, // Number width of 64 bits mode (default) QWORD_WIDTH, // Number width of 64 bits mode (default)
DWORD_WIDTH, // Number width of 32 bits mode DWORD_WIDTH, // Number width of 32 bits mode
WORD_WIDTH, // Number width of 16 bits mode WORD_WIDTH, // Number width of 16 bits mode
@ -50,37 +51,59 @@ namespace CalculatorEngineTests
class CalcEngineTests; class CalcEngineTests;
} }
class CCalcEngine { class CCalcEngine
{
public: public:
CCalcEngine(bool fPrecedence, bool fIntegerMode, CalculationManager::IResourceProvider* const pResourceProvider, __in_opt ICalcDisplay *pCalcDisplay, __in_opt std::shared_ptr<IHistoryDisplay> pHistoryDisplay); CCalcEngine(bool fPrecedence, bool fIntegerMode, CalculationManager::IResourceProvider* const pResourceProvider, __in_opt ICalcDisplay* pCalcDisplay,
__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() { return m_bError; } bool FInErrorState()
bool FInRecordingState() { return m_bRecord; } {
return m_bError;
}
bool FInRecordingState()
{
return m_bRecord;
}
void SettingsChanged(); void SettingsChanged();
bool IsCurrentTooBigForTrig(); bool IsCurrentTooBigForTrig();
int GetCurrentRadix(); int GetCurrentRadix();
std::wstring GetCurrentResultForRadix(uint32_t radix, int32_t precision); std::wstring GetCurrentResultForRadix(uint32_t radix, int32_t precision);
void ChangePrecision(int32_t precision) { m_precision = precision; ChangeConstants(m_radix, precision); } void ChangePrecision(int32_t precision)
{
m_precision = 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);
std::wstring GetStringForDisplay(CalcEngine::Rational const& rat, uint32_t radix); std::wstring GetStringForDisplay(CalcEngine::Rational const& rat, uint32_t radix);
void UpdateMaxIntDigits(); void UpdateMaxIntDigits();
wchar_t DecimalSeparator() const; wchar_t DecimalSeparator() const;
// Static methods for the instance // Static methods for the instance
static void InitialOneTimeOnlySetup(CalculationManager::IResourceProvider& resourceProvider); // Once per load time to call to initialize all shared global variables static void
InitialOneTimeOnlySetup(CalculationManager::IResourceProvider& resourceProvider); // Once per load time to call to initialize all shared global variables
// returns the ptr to string representing the operator. Mostly same as the button, but few special cases for x^y etc. // returns the ptr to string representing the operator. Mostly same as the button, but few special cases for x^y etc.
static std::wstring_view GetString(int ids) { return s_engineStrings[std::to_wstring(ids)]; } static std::wstring_view GetString(int ids)
static std::wstring_view GetString(std::wstring ids) { return s_engineStrings[ids]; } {
static std::wstring_view OpCodeToString(int nOpCode) { return GetString(IdStrFromCmdId(nOpCode)); } return s_engineStrings[std::to_wstring(ids)];
}
static std::wstring_view GetString(std::wstring ids)
{
return s_engineStrings[ids];
}
static std::wstring_view OpCodeToString(int nOpCode)
{
return GetString(IdStrFromCmdId(nOpCode));
}
static std::wstring_view OpCodeToUnaryString(int nOpCode, bool fInv, ANGLE_TYPE angletype); static std::wstring_view OpCodeToUnaryString(int nOpCode, bool fInv, ANGLE_TYPE angletype);
private: private:
bool m_fPrecedence; bool m_fPrecedence;
bool m_fIntegerMode; /* This is true if engine is explicitly called to be in integer mode. All bases are restricted to be in integers only */ bool m_fIntegerMode; /* This is true if engine is explicitly called to be in integer mode. All bases are restricted to be in integers only */
ICalcDisplay *m_pCalcDisplay; ICalcDisplay* m_pCalcDisplay;
CalculationManager::IResourceProvider* const m_resourceProvider; CalculationManager::IResourceProvider* const m_resourceProvider;
int m_nOpCode; /* ID value of operation. */ int m_nOpCode; /* ID value of operation. */
int m_nPrevOpCode; // opcode which computed the number in m_currentVal. 0 if it is already bracketed or plain number or int m_nPrevOpCode; // opcode which computed the number in m_currentVal. 0 if it is already bracketed or plain number or
@ -143,7 +166,7 @@ private:
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(RADIX_TYPE radixtype, NUM_WIDTH numwidth); void SetRadixTypeAndNumWidth(RADIX_TYPE radixtype, NUM_WIDTH numwidth);
int32_t DwWordBitWidthFromeNumWidth(NUM_WIDTH numwidth); int32_t DwWordBitWidthFromeNumWidth(NUM_WIDTH numwidth);
uint32_t NRadixFromRadixType( RADIX_TYPE radixtype); uint32_t NRadixFromRadixType(RADIX_TYPE radixtype);
bool TryToggleBit(CalcEngine::Rational& rat, uint32_t wbitno); bool TryToggleBit(CalcEngine::Rational& rat, uint32_t wbitno);
void CheckAndAddLastBinOpToHistory(bool addToHistory = true); void CheckAndAddLastBinOpToHistory(bool addToHistory = true);
@ -151,7 +174,10 @@ private:
void InitChopNumbers(); void InitChopNumbers();
static void LoadEngineStrings(CalculationManager::IResourceProvider& resourceProvider); static void LoadEngineStrings(CalculationManager::IResourceProvider& resourceProvider);
static int IdStrFromCmdId(int id) { return id - IDC_FIRSTCONTROL + IDS_ENGINESTR_FIRST; } static int IdStrFromCmdId(int id)
{
return id - IDC_FIRSTCONTROL + IDS_ENGINESTR_FIRST;
}
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);

View file

@ -13,16 +13,24 @@ namespace CalcEngine
class CalcNumSec class CalcNumSec
{ {
public: public:
CalcNumSec() : CalcNumSec() : value(), m_isNegative(false)
value(), {
m_isNegative(false) }
{}
void Clear(); void Clear();
bool IsEmpty() { return value.empty(); } bool IsEmpty()
{
return value.empty();
}
bool IsNegative() { return m_isNegative; } bool IsNegative()
void IsNegative(bool isNegative) { m_isNegative = isNegative; } {
return m_isNegative;
}
void IsNegative(bool isNegative)
{
m_isNegative = isNegative;
}
std::wstring value; std::wstring value;
@ -34,16 +42,12 @@ namespace CalcEngine
{ {
public: public:
CalcInput() : CalcInput(L'.') CalcInput() : CalcInput(L'.')
{} {
}
CalcInput(wchar_t decSymbol) : CalcInput(wchar_t decSymbol) : m_hasExponent(false), m_hasDecimal(false), m_decPtIndex(0), m_decSymbol(decSymbol), m_base(), m_exponent()
m_hasExponent(false), {
m_hasDecimal(false), }
m_decPtIndex(0),
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);

View file

@ -171,9 +171,7 @@ inline constexpr auto SIDS_ERR_INPUT_OVERFLOW = L"119";
inline constexpr auto SIDS_ERR_OUTPUT_OVERFLOW = L"120"; inline constexpr auto SIDS_ERR_OUTPUT_OVERFLOW = L"120";
// Include the resource key ID from above into this vector to load it into memory for the engine to use // Include the resource key ID from above into this vector to load it into memory for the engine to use
inline constexpr std::array<std::wstring_view, 120> g_sids = inline constexpr std::array<std::wstring_view, 120> g_sids = { SIDS_PLUS_MINUS,
{
SIDS_PLUS_MINUS,
SIDS_C, SIDS_C,
SIDS_CE, SIDS_CE,
SIDS_BACKSPACE, SIDS_BACKSPACE,
@ -292,5 +290,4 @@ inline constexpr std::array<std::wstring_view, 120> g_sids =
SIDS_ERR_UNEX_END, SIDS_ERR_UNEX_END,
SIDS_ERR_SG_INV_ERROR, SIDS_ERR_SG_INV_ERROR,
SIDS_ERR_INPUT_OVERFLOW, SIDS_ERR_INPUT_OVERFLOW,
SIDS_ERR_OUTPUT_OVERFLOW SIDS_ERR_OUTPUT_OVERFLOW };
};

View file

@ -14,9 +14,10 @@ static constexpr size_t MAXPRECDEPTH = 25;
// Helper class really a internal class to CCalcEngine, to accumulate each history line of text by collecting the // Helper class really a internal class to CCalcEngine, to accumulate each history line of text by collecting the
// operands, operator, unary operator etc. Since it is a separate entity, it can be unit tested on its own but does // operands, operator, unary operator etc. Since it is a separate entity, it can be unit tested on its own but does
// rely on CCalcEngine calling it in appropriate order. // rely on CCalcEngine calling it in appropriate order.
class CHistoryCollector { class CHistoryCollector
{
public: public:
CHistoryCollector(ICalcDisplay *pCalcDisplay, std::shared_ptr<IHistoryDisplay> pHistoryDisplay, wchar_t decimalSymbol); // Can throw errors CHistoryCollector(ICalcDisplay* pCalcDisplay, std::shared_ptr<IHistoryDisplay> pHistoryDisplay, wchar_t decimalSymbol); // Can throw errors
~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();
@ -31,24 +32,25 @@ public:
bool FOpndAddedToHistory(); bool FOpndAddedToHistory();
void CompleteHistoryLine(std::wstring_view numStr); void CompleteHistoryLine(std::wstring_view numStr);
void ClearHistoryLine(std::wstring_view errStr); void ClearHistoryLine(std::wstring_view errStr);
int AddCommand(_In_ const std::shared_ptr<IExpressionCommand> & spCommand); int AddCommand(_In_ const std::shared_ptr<IExpressionCommand>& spCommand);
void UpdateHistoryExpression(uint32_t radix, int32_t precision); void UpdateHistoryExpression(uint32_t radix, int32_t precision);
void SetDecimalSymbol(wchar_t decimalSymbol); void SetDecimalSymbol(wchar_t decimalSymbol);
private: private:
std::shared_ptr<IHistoryDisplay> m_pHistoryDisplay; std::shared_ptr<IHistoryDisplay> m_pHistoryDisplay;
ICalcDisplay *m_pCalcDisplay; ICalcDisplay* m_pCalcDisplay;
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> m_operandIndices; // Stack of index of opnd's beginning for each '('. A parallel array to m_hnoParNum, but abstracted independently of that 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
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<CalculatorVector <std::pair<std::wstring, int>>> m_spTokens; std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> m_spTokens;
std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> m_spCommands; std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> m_spCommands;
private: private:

View file

@ -7,11 +7,13 @@
#include "../ExpressionCommandInterface.h" #include "../ExpressionCommandInterface.h"
// Callback interface to be implemented by the clients of CCalcEngine // Callback interface to be implemented by the clients of CCalcEngine
class ICalcDisplay { class ICalcDisplay
{
public: public:
virtual void SetPrimaryDisplay(const std::wstring& pszText, bool isError) = 0; virtual void SetPrimaryDisplay(const std::wstring& pszText, bool isError) = 0;
virtual void SetIsInError(bool isInError) = 0; virtual void SetIsInError(bool isInError) = 0;
virtual void SetExpressionDisplay(_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const &tokens, _Inout_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const &commands) = 0; virtual void SetExpressionDisplay(_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const& tokens,
_Inout_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const& commands) = 0;
virtual void SetParenthesisNumber(_In_ unsigned int count) = 0; virtual void SetParenthesisNumber(_In_ unsigned int count) = 0;
virtual void OnNoRightParenAdded() = 0; virtual void OnNoRightParenAdded() = 0;
virtual void MaxDigitsReached() = 0; // not an error but still need to inform UI layer. virtual void MaxDigitsReached() = 0; // not an error but still need to inform UI layer.

View file

@ -4,8 +4,11 @@
#pragma once #pragma once
// Callback interface to be implemented by the clients of CCalcEngine if they require equation history // Callback interface to be implemented by the clients of CCalcEngine if they require equation history
class IHistoryDisplay { class IHistoryDisplay
{
public: public:
virtual ~IHistoryDisplay() {}; virtual ~IHistoryDisplay(){};
virtual unsigned int AddToHistory(_In_ std::shared_ptr<CalculatorVector <std::pair<std::wstring, int>>> const &tokens, _In_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const &commands, _In_ std::wstring_view result) = 0; virtual unsigned int AddToHistory(_In_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const& tokens,
_In_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const& commands,
_In_ std::wstring_view result) = 0;
}; };

View file

@ -4,7 +4,8 @@
#pragma once #pragma once
// This is expected to be in same order as IDM_HEX, IDM_DEC, IDM_OCT, IDM_BIN // This is expected to be in same order as IDM_HEX, IDM_DEC, IDM_OCT, IDM_BIN
enum eRADIX_TYPE { enum eRADIX_TYPE
{
HEX_RADIX, HEX_RADIX,
DEC_RADIX, DEC_RADIX,
OCT_RADIX, OCT_RADIX,

View file

@ -83,4 +83,3 @@ typedef int32_t ResultCode;
// //
// The result of this operation is undefined // The result of this operation is undefined
#define CALC_E_NORESULT ((uint32_t)0x80000009) #define CALC_E_NORESULT ((uint32_t)0x80000009)

View file

@ -17,7 +17,7 @@
#include "ratpak.h" #include "ratpak.h"
#include <cstring> // for memmove #include <cstring> // for memmove
void _mulnumx( PNUMBER *pa, PNUMBER b ); void _mulnumx(PNUMBER* pa, PNUMBER b);
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// //
@ -34,22 +34,22 @@ void _mulnumx( PNUMBER *pa, PNUMBER b );
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void __inline mulnumx( PNUMBER *pa, PNUMBER b ) void __inline mulnumx(PNUMBER* pa, PNUMBER b)
{ {
if ( b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0 ) if (b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0)
{ {
// If b is not one we multiply // If b is not one we multiply
if ( (*pa)->cdigit > 1 || (*pa)->mant[0] != 1 || (*pa)->exp != 0 ) if ((*pa)->cdigit > 1 || (*pa)->mant[0] != 1 || (*pa)->exp != 0)
{ {
// pa and b are both non-one. // pa and b are both non-one.
_mulnumx( pa, b ); _mulnumx(pa, b);
} }
else else
{ {
// if pa is one and b isn't just copy b. and adjust the sign. // if pa is one and b isn't just copy b. and adjust the sign.
int32_t sign = (*pa)->sign; int32_t sign = (*pa)->sign;
DUPNUM(*pa,b); DUPNUM(*pa, b);
(*pa)->sign *= sign; (*pa)->sign *= sign;
} }
} }
@ -76,29 +76,29 @@ void __inline mulnumx( PNUMBER *pa, PNUMBER b )
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void _mulnumx( PNUMBER *pa, PNUMBER b ) void _mulnumx(PNUMBER* pa, PNUMBER b)
{ {
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 *ptra; // ptra is a pointer to the mantissa of a. MANTTYPE* ptra; // ptra is a pointer to the mantissa of a.
MANTTYPE *ptrb; // ptrb is a pointer to the mantissa of b. MANTTYPE* ptrb; // ptrb is a pointer to the mantissa of b.
MANTTYPE *ptrc; // ptrc is a pointer to the mantissa of c. MANTTYPE* ptrc; // ptrc is a pointer to the mantissa of c.
MANTTYPE *ptrcoffset; // ptrcoffset, is the anchor location of the next MANTTYPE* ptrcoffset; // ptrcoffset, is the anchor location of the next
// single digit multiply partial result. // single digit multiply partial result.
int32_t iadigit=0; // Index of digit being used in the first number. int32_t iadigit = 0; // Index of digit being used in the first number.
int32_t ibdigit=0; // Index of digit being used in the second number. int32_t ibdigit = 0; // Index of digit being used in the second number.
MANTTYPE da=0; // da is the digit from the fist number. MANTTYPE da = 0; // da is the digit from the fist number.
TWO_MANTTYPE cy=0; // cy is the carry resulting from the addition of TWO_MANTTYPE cy = 0; // cy is the carry resulting from the addition of
// a multiplied row into the result. // a multiplied row into the result.
TWO_MANTTYPE mcy=0; // mcy is the resultant from a single TWO_MANTTYPE mcy = 0; // mcy is the resultant from a single
// multiply, AND the carry of that multiply. // multiply, AND the carry of that multiply.
int32_t icdigit=0; // Index of digit being calculated in final result. int32_t icdigit = 0; // Index of digit being calculated in final result.
a=*pa; a = *pa;
ibdigit = a->cdigit + b->cdigit - 1; ibdigit = a->cdigit + b->cdigit - 1;
createnum( c, ibdigit + 1 ); createnum(c, ibdigit + 1);
c->cdigit = ibdigit; c->cdigit = ibdigit;
c->sign = a->sign * b->sign; c->sign = a->sign * b->sign;
@ -106,7 +106,7 @@ void _mulnumx( PNUMBER *pa, PNUMBER b )
ptra = a->mant; ptra = a->mant;
ptrcoffset = c->mant; ptrcoffset = c->mant;
for ( iadigit = a->cdigit; iadigit > 0; iadigit-- ) for (iadigit = a->cdigit; iadigit > 0; iadigit--)
{ {
da = *ptra++; da = *ptra++;
ptrb = b->mant; ptrb = b->mant;
@ -114,28 +114,27 @@ void _mulnumx( PNUMBER *pa, PNUMBER b )
// Shift ptrc, and ptrcoffset, one for each digit // Shift ptrc, and ptrcoffset, one for each digit
ptrc = ptrcoffset++; ptrc = ptrcoffset++;
for ( ibdigit = b->cdigit; ibdigit > 0; ibdigit-- ) for (ibdigit = b->cdigit; ibdigit > 0; ibdigit--)
{ {
cy = 0; cy = 0;
mcy = (uint64_t)da * (*ptrb); mcy = (uint64_t)da * (*ptrb);
if ( mcy ) if (mcy)
{ {
icdigit = 0; icdigit = 0;
if ( ibdigit == 1 && iadigit == 1 ) if (ibdigit == 1 && iadigit == 1)
{ {
c->cdigit++; c->cdigit++;
} }
} }
// If result is nonzero, or while result of carry is nonzero... // If result is nonzero, or while result of carry is nonzero...
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 += (TWO_MANTTYPE)ptrc[icdigit] + ((uint32_t)mcy & ((uint32_t)~BASEX));
// update result digit from // update result digit from
ptrc[icdigit++]=(MANTTYPE)((uint32_t)cy&((uint32_t)~BASEX)); ptrc[icdigit++] = (MANTTYPE)((uint32_t)cy & ((uint32_t)~BASEX));
// update carries from // update carries from
mcy >>= BASEXPWR; mcy >>= BASEXPWR;
@ -144,19 +143,18 @@ void _mulnumx( PNUMBER *pa, PNUMBER b )
ptrb++; ptrb++;
ptrc++; ptrc++;
} }
} }
// prevent different kinds of zeros, by stripping leading duplicate zeros. // prevent different kinds of zeros, by stripping leading duplicate zeros.
// digits are in order of increasing significance. // digits are in order of increasing significance.
while ( c->cdigit > 1 && c->mant[c->cdigit-1] == 0 ) while (c->cdigit > 1 && c->mant[c->cdigit - 1] == 0)
{ {
c->cdigit--; c->cdigit--;
} }
destroynum( *pa ); destroynum(*pa);
*pa=c; *pa = c;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
@ -174,34 +172,33 @@ void _mulnumx( PNUMBER *pa, PNUMBER b )
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void numpowi32x( _Inout_ PNUMBER *proot, _In_ int32_t power ) void numpowi32x(_Inout_ PNUMBER* proot, _In_ int32_t power)
{ {
PNUMBER lret = i32tonum( 1, BASEX ); PNUMBER lret = i32tonum(1, BASEX);
// Once the power remaining is zero we are done. // Once the power remaining is zero we are done.
while ( power > 0 ) while (power > 0)
{ {
// If this bit in the power decomposition is on, multiply the result // If this bit in the power decomposition is on, multiply the result
// by the root number. // by the root number.
if ( power & 1 ) if (power & 1)
{ {
mulnumx( &lret, *proot ); mulnumx(&lret, *proot);
} }
// multiply the root number by itself to scale for the next bit (i.e. // multiply the root number by itself to scale for the next bit (i.e.
// square it. // square it.
mulnumx( proot, *proot ); mulnumx(proot, *proot);
// move the next bit of the power into place. // move the next bit of the power into place.
power >>= 1; power >>= 1;
} }
destroynum( *proot ); destroynum(*proot);
*proot=lret; *proot = lret;
} }
void _divnumx( PNUMBER *pa, PNUMBER b, int32_t precision); void _divnumx(PNUMBER* pa, PNUMBER b, int32_t precision);
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// //
@ -218,22 +215,22 @@ void _divnumx( PNUMBER *pa, PNUMBER b, int32_t precision);
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void __inline divnumx( PNUMBER *pa, PNUMBER b, int32_t precision) void __inline divnumx(PNUMBER* pa, PNUMBER b, int32_t precision)
{ {
if ( b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0 ) if (b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0)
{ {
// b is not one. // b is not one.
if ( (*pa)->cdigit > 1 || (*pa)->mant[0] != 1 || (*pa)->exp != 0 ) if ((*pa)->cdigit > 1 || (*pa)->mant[0] != 1 || (*pa)->exp != 0)
{ {
// pa and b are both not one. // pa and b are both not one.
_divnumx( pa, b, precision); _divnumx(pa, b, precision);
} }
else else
{ {
// if pa is one and b is not one, just copy b, and adjust the sign. // if pa is one and b is not one, just copy b, and adjust the sign.
int32_t sign = (*pa)->sign; int32_t sign = (*pa)->sign;
DUPNUM(*pa,b); DUPNUM(*pa, b);
(*pa)->sign *= sign; (*pa)->sign *= sign;
} }
} }
@ -257,30 +254,30 @@ void __inline divnumx( PNUMBER *pa, PNUMBER b, int32_t precision)
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void _divnumx( PNUMBER *pa, PNUMBER b, int32_t precision) void _divnumx(PNUMBER* pa, PNUMBER b, int32_t precision)
{ {
PNUMBER a= nullptr; // a is the dereferenced number pointer from *pa PNUMBER a = nullptr; // a is the dereferenced number pointer from *pa
PNUMBER c= nullptr; // c will contain the result. PNUMBER c = nullptr; // c will contain the result.
PNUMBER lasttmp = nullptr; // lasttmp allows a backup when the algorithm PNUMBER lasttmp = nullptr; // lasttmp allows a backup when the algorithm
// guesses one bit too far. // guesses one bit too far.
PNUMBER tmp = nullptr; // current guess being worked on for divide. PNUMBER tmp = nullptr; // current guess being worked on for divide.
PNUMBER rem = nullptr; // remainder after applying guess. PNUMBER rem = nullptr; // remainder after applying guess.
int32_t cdigits; // count of digits for answer. int32_t cdigits; // count of digits for answer.
MANTTYPE *ptrc; // ptrc is a pointer to the mantissa of c. MANTTYPE* ptrc; // ptrc is a pointer to the mantissa of c.
int32_t thismax = precision + g_ratio; // set a maximum number of internal digits int32_t thismax = precision + g_ratio; // set a maximum number of internal digits
// to shoot for in the divide. // to shoot for in the divide.
a=*pa; a = *pa;
if ( thismax < a->cdigit ) if (thismax < a->cdigit)
{ {
// a has more digits than precision specified, bump up digits to shoot // a has more digits than precision specified, bump up digits to shoot
// for. // for.
thismax = a->cdigit; thismax = a->cdigit;
} }
if ( thismax < b->cdigit ) if (thismax < b->cdigit)
{ {
// b has more digits than precision specified, bump up digits to shoot // b has more digits than precision specified, bump up digits to shoot
// for. // for.
@ -288,59 +285,59 @@ 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;
cdigits = 0; cdigits = 0;
DUPNUM( rem, a ); DUPNUM(rem, a);
rem->sign = b->sign; rem->sign = b->sign;
rem->exp = b->cdigit + b->exp - rem->cdigit; rem->exp = b->cdigit + b->exp - rem->cdigit;
while ( cdigits++ < thismax && !zernum(rem) ) while (cdigits++ < thismax && !zernum(rem))
{ {
int32_t digit = 0; int32_t digit = 0;
*ptrc = 0; *ptrc = 0;
while ( !lessnum( rem, b ) ) while (!lessnum(rem, b))
{ {
digit = 1; digit = 1;
DUPNUM( tmp, b ); DUPNUM(tmp, b);
destroynum( lasttmp ); destroynum(lasttmp);
lasttmp=i32tonum( 0, BASEX ); lasttmp = i32tonum(0, BASEX);
while ( lessnum( tmp, rem ) ) while (lessnum(tmp, rem))
{ {
destroynum( lasttmp ); destroynum(lasttmp);
DUPNUM(lasttmp,tmp); DUPNUM(lasttmp, tmp);
addnum( &tmp, tmp, BASEX ); addnum(&tmp, tmp, BASEX);
digit *= 2; digit *= 2;
} }
if ( lessnum( rem, tmp ) ) if (lessnum(rem, tmp))
{ {
// too far, back up... // too far, back up...
destroynum( tmp ); destroynum(tmp);
digit /= 2; digit /= 2;
tmp=lasttmp; tmp = lasttmp;
lasttmp= nullptr; lasttmp = nullptr;
} }
tmp->sign *= -1; tmp->sign *= -1;
addnum( &rem, tmp, BASEX ); addnum(&rem, tmp, BASEX);
destroynum( tmp ); destroynum(tmp);
destroynum( lasttmp ); destroynum(lasttmp);
*ptrc |= digit; *ptrc |= digit;
} }
rem->exp++; rem->exp++;
ptrc--; ptrc--;
} }
cdigits--; cdigits--;
if ( c->mant != ++ptrc ) if (c->mant != ++ptrc)
{ {
memmove( c->mant, ptrc, (int)(cdigits*sizeof(MANTTYPE)) ); memmove(c->mant, ptrc, (int)(cdigits * sizeof(MANTTYPE)));
} }
if ( !cdigits ) if (!cdigits)
{ {
// A zero, make sure no weird exponents creep in // A zero, make sure no weird exponents creep in
c->exp = 0; c->exp = 0;
@ -352,16 +349,14 @@ void _divnumx( PNUMBER *pa, PNUMBER b, int32_t precision)
c->exp -= cdigits; c->exp -= cdigits;
// prevent different kinds of zeros, by stripping leading duplicate // prevent different kinds of zeros, by stripping leading duplicate
// zeros. digits are in order of increasing significance. // zeros. digits are in order of increasing significance.
while ( c->cdigit > 1 && c->mant[c->cdigit-1] == 0 ) while (c->cdigit > 1 && c->mant[c->cdigit - 1] == 0)
{ {
c->cdigit--; c->cdigit--;
} }
} }
destroynum( rem ); destroynum(rem);
destroynum( *pa ); destroynum(*pa);
*pa=c; *pa = c;
} }

View file

@ -42,8 +42,7 @@ wchar_t g_decimalSeparator = L'.';
// See also // See also
// * https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros // * https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros
// * https://sourceforge.net/p/predef/wiki/Architectures/ // * https://sourceforge.net/p/predef/wiki/Architectures/
#if defined(MIDL_PASS) || defined(RC_INVOKED) || defined(_M_CEE_PURE) \ #if defined(MIDL_PASS) || defined(RC_INVOKED) || defined(_M_CEE_PURE) || defined(_M_AMD64) || defined(__ARM_ARCH) || defined(__x86_64__) || defined(_M_ARM64)
|| defined(_M_AMD64) || defined(__ARM_ARCH) || defined(__x86_64__) || defined(_M_ARM64)
#ifndef Calc_UInt32x32To64 #ifndef Calc_UInt32x32To64
#define Calc_UInt32x32To64(a, b) ((uint64_t)((uint32_t)(a)) * (uint64_t)((uint32_t)(b))) #define Calc_UInt32x32To64(a, b) ((uint64_t)((uint32_t)(a)) * (uint64_t)((uint32_t)(b)))
@ -63,12 +62,9 @@ wchar_t g_decimalSeparator = L'.';
#define CALC_INTSAFE_E_ARITHMETIC_OVERFLOW ((int32_t)0x80070216L) // 0x216 = 534 = ERROR_ARITHMETIC_OVERFLOW #define CALC_INTSAFE_E_ARITHMETIC_OVERFLOW ((int32_t)0x80070216L) // 0x216 = 534 = ERROR_ARITHMETIC_OVERFLOW
#define CALC_ULONG_ERROR ((uint32_t)0xffffffffU) #define CALC_ULONG_ERROR ((uint32_t)0xffffffffU)
namespace { namespace
int32_t {
Calc_ULongAdd( int32_t Calc_ULongAdd(_In_ uint32_t ulAugend, _In_ uint32_t ulAddend, _Out_ uint32_t* pulResult)
_In_ uint32_t ulAugend,
_In_ uint32_t ulAddend,
_Out_ uint32_t* pulResult)
{ {
int32_t hr = CALC_INTSAFE_E_ARITHMETIC_OVERFLOW; int32_t hr = CALC_INTSAFE_E_ARITHMETIC_OVERFLOW;
*pulResult = CALC_ULONG_ERROR; *pulResult = CALC_ULONG_ERROR;
@ -82,10 +78,7 @@ namespace {
return hr; return hr;
} }
int32_t int32_t Calc_ULongLongToULong(_In_ uint64_t ullOperand, _Out_ uint32_t* pulResult)
Calc_ULongLongToULong(
_In_ uint64_t ullOperand,
_Out_ uint32_t* pulResult)
{ {
int32_t hr = CALC_INTSAFE_E_ARITHMETIC_OVERFLOW; int32_t hr = CALC_INTSAFE_E_ARITHMETIC_OVERFLOW;
*pulResult = CALC_ULONG_ERROR; *pulResult = CALC_ULONG_ERROR;
@ -99,11 +92,7 @@ namespace {
return hr; return hr;
} }
int32_t int32_t Calc_ULongMult(_In_ uint32_t ulMultiplicand, _In_ uint32_t ulMultiplier, _Out_ uint32_t* pulResult)
Calc_ULongMult(
_In_ uint32_t ulMultiplicand,
_In_ uint32_t ulMultiplier,
_Out_ uint32_t* pulResult)
{ {
uint64_t ull64Result = Calc_UInt32x32To64(ulMultiplicand, ulMultiplier); uint64_t ull64Result = Calc_UInt32x32To64(ulMultiplicand, ulMultiplier);
@ -139,9 +128,9 @@ 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, (int)(sizeof(NUMBER) + ((src)->cdigit) * (sizeof(MANTTYPE))));
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -156,16 +145,15 @@ void _dupnum(_In_ PNUMBER dest, _In_ const NUMBER * const src)
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void _destroynum( _In_ PNUMBER pnum ) void _destroynum(_In_ PNUMBER pnum)
{ {
if ( pnum != nullptr) if (pnum != nullptr)
{ {
free( pnum ); free(pnum);
} }
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// FUNCTION: _destroyrat // FUNCTION: _destroyrat
@ -179,18 +167,17 @@ void _destroynum( _In_ PNUMBER pnum )
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void _destroyrat( _In_ PRAT prat ) void _destroyrat(_In_ PRAT prat)
{ {
if ( prat != nullptr) if (prat != nullptr)
{ {
destroynum( prat->pp ); destroynum(prat->pp);
destroynum( prat->pq ); destroynum(prat->pq);
free( prat ); free(prat);
} }
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// FUNCTION: _createnum // FUNCTION: _createnum
@ -203,28 +190,27 @@ void _destroyrat( _In_ PRAT prat )
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
PNUMBER _createnum( _In_ uint32_t size ) PNUMBER _createnum(_In_ uint32_t size)
{ {
PNUMBER pnumret= nullptr; PNUMBER pnumret = nullptr;
uint32_t cbAlloc; uint32_t cbAlloc;
// sizeof( MANTTYPE ) is the size of a 'digit' // sizeof( MANTTYPE ) is the size of a 'digit'
if (SUCCEEDED(Calc_ULongAdd(size, 1, &cbAlloc)) && if (SUCCEEDED(Calc_ULongAdd(size, 1, &cbAlloc)) && SUCCEEDED(Calc_ULongMult(cbAlloc, sizeof(MANTTYPE), &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 = (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);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -241,25 +227,22 @@ PNUMBER _createnum( _In_ uint32_t size )
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
PRAT _createrat(void)
PRAT _createrat( void )
{ {
PRAT prat= nullptr; PRAT prat = nullptr;
prat = (PRAT)zmalloc( sizeof( RAT ) ); prat = (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);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// FUNCTION: numtorat // FUNCTION: numtorat
@ -275,37 +258,34 @@ PRAT _createrat( void )
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
PRAT numtorat( _In_ PNUMBER pin, uint32_t radix) PRAT numtorat(_In_ PNUMBER pin, uint32_t radix)
{ {
PNUMBER pnRadixn= nullptr; PNUMBER pnRadixn = nullptr;
DUPNUM( pnRadixn, pin ); DUPNUM(pnRadixn, pin);
PNUMBER qnRadixn=i32tonum( 1, radix); PNUMBER qnRadixn = i32tonum(1, radix);
// Ensure p and q start out as integers. // Ensure p and q start out as integers.
if ( pnRadixn->exp < 0 ) if (pnRadixn->exp < 0)
{ {
qnRadixn->exp -= pnRadixn->exp; qnRadixn->exp -= pnRadixn->exp;
pnRadixn->exp = 0; pnRadixn->exp = 0;
} }
PRAT pout= nullptr; PRAT pout = nullptr;
createrat(pout); createrat(pout);
// There is probably a better way to do this. // There is probably a better way to do this.
pout->pp = numtonRadixx(pnRadixn, radix); pout->pp = numtonRadixx(pnRadixn, radix);
pout->pq = numtonRadixx(qnRadixn, radix); pout->pq = numtonRadixx(qnRadixn, radix);
destroynum(pnRadixn);
destroynum(qnRadixn);
destroynum( pnRadixn ); return (pout);
destroynum( qnRadixn );
return( pout );
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// //
// FUNCTION: nRadixxtonum // FUNCTION: nRadixxtonum
@ -320,37 +300,36 @@ 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)
{ {
uint32_t bitmask; uint32_t bitmask;
uint32_t cdigits; uint32_t cdigits;
MANTTYPE *ptr; MANTTYPE* ptr;
PNUMBER sum = i32tonum( 0, radix ); PNUMBER sum = i32tonum(0, radix);
PNUMBER powofnRadix = i32tonum( BASEX, radix ); PNUMBER powofnRadix = i32tonum(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.
cdigits = precision + 1; cdigits = precision + 1;
if ( cdigits > (uint32_t)a->cdigit ) if (cdigits > (uint32_t)a->cdigit)
{ {
cdigits = (uint32_t)a->cdigit; cdigits = (uint32_t)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 ( ptr = &(a->mant[a->cdigit-1]); cdigits > 0; for (ptr = &(a->mant[a->cdigit - 1]); cdigits > 0; ptr--, cdigits--)
ptr--, cdigits-- )
{ {
// Loop over all the bits from MSB to LSB // Loop over all the bits from MSB to LSB
for ( bitmask = BASEX/2; bitmask > 0; bitmask /= 2 ) for (bitmask = BASEX / 2; bitmask > 0; bitmask /= 2)
{ {
addnum( &sum, sum, radix ); addnum(&sum, sum, radix);
if ( *ptr & bitmask ) if (*ptr & bitmask)
{ {
sum->mant[0] |= 1; sum->mant[0] |= 1;
} }
@ -358,11 +337,11 @@ PNUMBER nRadixxtonum( _In_ PNUMBER a, uint32_t radix, int32_t precision)
} }
// Scale answer by power of internal exponent. // Scale answer by power of internal exponent.
mulnum( &sum, powofnRadix, radix ); mulnum(&sum, powofnRadix, radix);
destroynum( powofnRadix ); destroynum(powofnRadix);
sum->sign = a->sign; sum->sign = a->sign;
return( sum ); return (sum);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -383,37 +362,37 @@ PNUMBER numtonRadixx(_In_ PNUMBER a, uint32_t radix)
{ {
PNUMBER pnumret = i32tonum(0, BASEX); // pnumret is the number in internal form. PNUMBER pnumret = i32tonum(0, BASEX); // pnumret is the number in internal form.
PNUMBER num_radix = i32tonum(radix, BASEX); PNUMBER num_radix = i32tonum(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 = nullptr; // thisdigit holds the current digit of a
// being summed into result. // being summed into result.
int32_t idigit; // idigit is the iterate of digits in a. int32_t idigit; // idigit is the iterate of digits in a.
for ( idigit = 0; idigit < a->cdigit; idigit++ ) for (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 = i32tonum(*ptrdigit--, BASEX);
addnum( &pnumret, thisdigit, BASEX ); addnum(&pnumret, thisdigit, BASEX);
destroynum( thisdigit ); destroynum(thisdigit);
} }
// Calculate the exponent of the external base for scaling. // Calculate the exponent of the external base for scaling.
numpowi32x( &num_radix, a->exp ); numpowi32x(&num_radix, a->exp);
// ... and scale the result. // ... and scale the result.
mulnumx( &pnumret, num_radix); mulnumx(&pnumret, num_radix);
destroynum(num_radix); destroynum(num_radix);
// And propagate the sign. // And propagate the sign.
pnumret->sign = a->sign; pnumret->sign = a->sign;
return( pnumret ); return (pnumret);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -583,28 +562,14 @@ static constexpr uint8_t EXPSZ = 12;
static constexpr uint8_t EXPDZ = 13; static constexpr uint8_t EXPDZ = 13;
static constexpr uint8_t ERR = 14; static constexpr uint8_t ERR = 14;
#if defined( DEBUG ) #if defined(DEBUG)
char *statestr[] = { char* statestr[] = {
"START", "START", "MANTS", "LZ", "LZDP", "LD", "DZ", "DD", "DDP", "EXPB", "EXPS", "EXPD", "EXPBZ", "EXPSZ", "EXPDZ", "ERR",
"MANTS",
"LZ",
"LZDP",
"LD",
"DZ",
"DD",
"DDP",
"EXPB",
"EXPS",
"EXPD",
"EXPBZ",
"EXPSZ",
"EXPDZ",
"ERR",
}; };
#endif #endif
// New state is machine[state][terminal] // New state is machine[state][terminal]
static constexpr uint8_t machine[ERR+1][EX+1]= { static constexpr uint8_t machine[ERR + 1][EX + 1] = {
// DP, ZR, NZ, SG, EX // DP, ZR, NZ, SG, EX
// START // START
{ LZDP, LZ, LD, MANTS, ERR }, { LZDP, LZ, LD, MANTS, ERR },
@ -642,7 +607,7 @@ wchar_t NormalizeCharDigit(wchar_t c, uint32_t radix)
{ {
// Allow upper and lower case letters as equivalent, base // Allow upper and lower case letters as equivalent, base
// is in the range where this is not ambiguous. // is in the range where this is not ambiguous.
if (size_t{ radix } >= DIGITS.find(L'A') && size_t { radix } <= DIGITS.find(L'Z')) if (size_t{ radix } >= DIGITS.find(L'A') && size_t{ radix } <= DIGITS.find(L'Z'))
{ {
return towupper(c); return towupper(c);
} }
@ -660,7 +625,7 @@ PNUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precis
pnumret->sign = 1L; pnumret->sign = 1L;
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;
uint8_t state = START; // state is the state of the input state machine. uint8_t state = START; // state is the state of the input state machine.
wchar_t curChar; wchar_t curChar;
@ -795,14 +760,14 @@ PNUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precis
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
PRAT i32torat( _In_ int32_t ini32 ) PRAT i32torat(_In_ int32_t ini32)
{ {
PRAT pratret= nullptr; PRAT pratret = nullptr;
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);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -819,14 +784,14 @@ PRAT i32torat( _In_ int32_t ini32 )
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
PRAT Ui32torat( _In_ uint32_t inui32 ) PRAT Ui32torat(_In_ uint32_t inui32)
{ {
PRAT pratret= nullptr; PRAT pratret = nullptr;
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);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -842,17 +807,17 @@ PRAT Ui32torat( _In_ uint32_t inui32 )
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
PNUMBER i32tonum( int32_t ini32, uint32_t radix) PNUMBER i32tonum(int32_t ini32, uint32_t radix)
{ {
MANTTYPE *pmant; MANTTYPE* pmant;
PNUMBER pnumret= nullptr; PNUMBER pnumret = nullptr;
createnum( pnumret, MAX_LONG_SIZE ); createnum(pnumret, MAX_LONG_SIZE);
pmant = pnumret->mant; pmant = pnumret->mant;
pnumret->cdigit = 0; pnumret->cdigit = 0;
pnumret->exp = 0; pnumret->exp = 0;
if ( ini32 < 0 ) if (ini32 < 0)
{ {
pnumret->sign = -1; pnumret->sign = -1;
ini32 *= -1; ini32 *= -1;
@ -862,13 +827,14 @@ PNUMBER i32tonum( int32_t ini32, uint32_t radix)
pnumret->sign = 1; pnumret->sign = 1;
} }
do { do
{
*pmant++ = (MANTTYPE)(ini32 % radix); *pmant++ = (MANTTYPE)(ini32 % radix);
ini32 /= radix; ini32 /= radix;
pnumret->cdigit++; pnumret->cdigit++;
} while ( ini32 ); } while (ini32);
return( pnumret ); return (pnumret);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -885,28 +851,27 @@ 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 = nullptr;
createnum( pnumret, MAX_LONG_SIZE ); createnum(pnumret, MAX_LONG_SIZE);
pmant = pnumret->mant; pmant = pnumret->mant;
pnumret->cdigit = 0; pnumret->cdigit = 0;
pnumret->exp = 0; pnumret->exp = 0;
pnumret->sign = 1; pnumret->sign = 1;
do { do
{
*pmant++ = (MANTTYPE)(ini32 % radix); *pmant++ = (MANTTYPE)(ini32 % radix);
ini32 /= radix; ini32 /= radix;
pnumret->cdigit++; pnumret->cdigit++;
} while ( ini32 ); } while (ini32);
return( pnumret ); return (pnumret);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// FUNCTION: rattoi32 // FUNCTION: rattoi32
@ -921,26 +886,26 @@ PNUMBER Ui32tonum(uint32_t ini32, uint32_t radix)
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
int32_t rattoi32( _In_ PRAT prat , uint32_t radix, int32_t precision) 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);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -956,29 +921,28 @@ int32_t rattoi32( _In_ PRAT prat , uint32_t radix, int32_t precision)
// base. // base.
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
uint32_t rattoUi32( _In_ PRAT prat, uint32_t radix, int32_t precision) 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);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// FUNCTION: rattoUi64 // FUNCTION: rattoUi64
@ -994,7 +958,7 @@ uint32_t rattoUi32( _In_ PRAT prat, uint32_t radix, int32_t precision)
// internal base chosen happens to be 2^32, this is easier. // internal base chosen happens to be 2^32, this is easier.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
uint64_t rattoUi64( _In_ PRAT prat, uint32_t radix, int32_t precision) uint64_t rattoUi64(_In_ PRAT prat, uint32_t radix, int32_t precision)
{ {
PRAT pint = nullptr; PRAT pint = nullptr;
@ -1006,7 +970,7 @@ uint64_t rattoUi64( _In_ PRAT prat, uint32_t radix, int32_t precision)
DUPRAT(pint, prat); // previous pint will get freed by this as well DUPRAT(pint, prat); // previous pint will get freed by this as well
PRAT prat32 = i32torat(32); PRAT prat32 = i32torat(32);
rshrat(&pint, prat32, radix, precision); rshrat(&pint, prat32, radix, precision);
intrat( &pint, radix, precision); intrat(&pint, radix, precision);
andrat(&pint, rat_dword, radix, precision); // & 0xFFFFFFFF (2 ^ 32 -1) andrat(&pint, rat_dword, radix, precision); // & 0xFFFFFFFF (2 ^ 32 -1)
uint32_t hi = rattoUi32(pint, radix, precision); uint32_t hi = rattoUi32(pint, radix, precision);
@ -1029,11 +993,11 @@ uint64_t rattoUi64( _In_ PRAT prat, uint32_t radix, int32_t precision)
// base claimed. // base claimed.
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
int32_t numtoi32( _In_ PNUMBER pnum, uint32_t radix ) 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;
pmant += pnum->cdigit - 1; pmant += pnum->cdigit - 1;
int32_t expt = pnum->exp; int32_t expt = pnum->exp;
@ -1066,22 +1030,22 @@ 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)
{ {
MANTTYPE *pmant; MANTTYPE* pmant;
int32_t cdigits; int32_t cdigits;
bool fstrip = false; bool fstrip = false;
// point pmant to the LeastCalculatedDigit // point pmant to the LeastCalculatedDigit
pmant=pnum->mant; pmant = pnum->mant;
cdigits=pnum->cdigit; cdigits = pnum->cdigit;
// point pmant to the LSD // point pmant to the LSD
if ( cdigits > starting ) if (cdigits > starting)
{ {
pmant += cdigits - starting; 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) ) while ((cdigits > 0) && !(*pmant))
{ {
// 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.
@ -1091,15 +1055,15 @@ bool stripzeroesnum(_Inout_ PNUMBER pnum, int32_t starting)
} }
// If there are zeros to remove. // If there are zeros to remove.
if ( fstrip ) if (fstrip)
{ {
// Remove them. // Remove them.
memmove( pnum->mant, pmant, (int)(cdigits*sizeof(MANTTYPE)) ); memmove(pnum->mant, pmant, (int)(cdigits * sizeof(MANTTYPE)));
// And adjust exponent and digit count accordingly. // And adjust exponent and digit count accordingly.
pnum->exp += ( pnum->cdigit - cdigits ); pnum->exp += (pnum->cdigit - cdigits);
pnum->cdigit = cdigits; pnum->cdigit = cdigits;
} }
return( fstrip ); return (fstrip);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1205,7 +1169,7 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_
// Set up all the post rounding stuff. // Set up all the post rounding stuff.
bool useSciForm = false; bool useSciForm = false;
int32_t eout = exponent - 1; // Displayed exponent. int32_t eout = exponent - 1; // Displayed exponent.
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
// FMT_SCIENTIFIC or FMT_ENGINEERING was specified. // FMT_SCIENTIFIC or FMT_ENGINEERING was specified.
if ((format == FMT_SCIENTIFIC) || (format == FMT_ENGINEERING)) if ((format == FMT_SCIENTIFIC) || (format == FMT_ENGINEERING))
@ -1397,17 +1361,17 @@ void flatrat(_Inout_ PRAT& prat, uint32_t radix, int32_t precision)
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
PNUMBER gcd( _In_ PNUMBER a, _In_ PNUMBER b) PNUMBER gcd(_In_ PNUMBER a, _In_ PNUMBER b)
{ {
PNUMBER r= nullptr; PNUMBER r = nullptr;
PNUMBER larger= nullptr; PNUMBER larger = nullptr;
PNUMBER smaller= nullptr; PNUMBER smaller = nullptr;
if (zernum(a)) if (zernum(a))
{ {
return b; return b;
} }
else if(zernum(b)) else if (zernum(b))
{ {
return a; return a;
} }
@ -1453,18 +1417,18 @@ PNUMBER gcd( _In_ PNUMBER a, _In_ PNUMBER b)
PNUMBER i32factnum(int32_t ini32, uint32_t radix) PNUMBER i32factnum(int32_t ini32, uint32_t radix)
{ {
PNUMBER lret= nullptr; PNUMBER lret = nullptr;
PNUMBER tmp= nullptr; PNUMBER tmp = nullptr;
lret = i32tonum( 1, radix); lret = i32tonum(1, radix);
while ( ini32 > 0 ) while (ini32 > 0)
{ {
tmp = i32tonum( ini32--, radix); tmp = i32tonum(ini32--, radix);
mulnum( &lret, tmp, radix); mulnum(&lret, tmp, radix);
destroynum( tmp ); destroynum(tmp);
} }
return( lret ); return (lret);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1483,22 +1447,22 @@ PNUMBER i32factnum(int32_t ini32, uint32_t radix)
PNUMBER i32prodnum(int32_t start, int32_t stop, uint32_t radix) PNUMBER i32prodnum(int32_t start, int32_t stop, uint32_t radix)
{ {
PNUMBER lret= nullptr; PNUMBER lret = nullptr;
PNUMBER tmp= nullptr; PNUMBER tmp = nullptr;
lret = i32tonum( 1, radix); lret = i32tonum(1, radix);
while ( start <= stop ) while (start <= stop)
{ {
if ( start ) if (start)
{ {
tmp = i32tonum( start, radix); tmp = i32tonum(start, radix);
mulnum( &lret, tmp, radix); mulnum(&lret, tmp, radix);
destroynum( tmp ); destroynum(tmp);
} }
start++; start++;
} }
return( lret ); return (lret);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1515,23 +1479,22 @@ PNUMBER i32prodnum(int32_t start, int32_t stop, uint32_t radix)
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void numpowi32( _Inout_ PNUMBER *proot, int32_t power, uint32_t radix, int32_t precision) void numpowi32(_Inout_ PNUMBER* proot, int32_t power, uint32_t radix, int32_t precision)
{ {
PNUMBER lret = i32tonum( 1, radix ); PNUMBER lret = i32tonum(1, radix);
while ( power > 0 ) while (power > 0)
{ {
if ( power & 1 ) if (power & 1)
{ {
mulnum( &lret, *proot, radix ); mulnum(&lret, *proot, radix);
} }
mulnum( proot, *proot, radix ); mulnum(proot, *proot, radix);
TRIMNUM(*proot, precision); TRIMNUM(*proot, precision);
power >>= 1; power >>= 1;
} }
destroynum( *proot ); destroynum(*proot);
*proot=lret; *proot = lret;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1547,37 +1510,37 @@ void numpowi32( _Inout_ PNUMBER *proot, int32_t power, uint32_t radix, int32_t p
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void ratpowi32( _Inout_ PRAT *proot, int32_t power, int32_t precision) 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 = nullptr;
ratpowi32( proot, -power, precision); ratpowi32(proot, -power, precision);
pnumtemp = (*proot)->pp; pnumtemp = (*proot)->pp;
(*proot)->pp = (*proot)->pq; (*proot)->pp = (*proot)->pq;
(*proot)->pq = pnumtemp; (*proot)->pq = pnumtemp;
} }
else else
{ {
PRAT lret= nullptr; PRAT lret = nullptr;
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);
trimit(proot, precision); trimit(proot, precision);
power >>= 1; power >>= 1;
} }
destroyrat( *proot ); destroyrat(*proot);
*proot=lret; *proot = lret;
} }
} }

View file

@ -16,7 +16,6 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "ratpak.h" #include "ratpak.h"
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// FUNCTION: exprat // FUNCTION: exprat
@ -40,51 +39,52 @@
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void _exprat( PRAT *px, int32_t precision) void _exprat(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);
do { do
{
NEXTTERM(*px, INC(n2) DIVNUM(n2), precision); NEXTTERM(*px, INC(n2) DIVNUM(n2), precision);
} while ( !SMALL_ENOUGH_RAT( thisterm, precision) ); } while (!SMALL_ENOUGH_RAT(thisterm, precision));
DESTROYTAYLOR(); DESTROYTAYLOR();
} }
void exprat( PRAT *px, uint32_t radix, int32_t precision) void exprat(PRAT* px, uint32_t radix, int32_t precision)
{ {
PRAT pwr= nullptr; PRAT pwr = nullptr;
PRAT pint= nullptr; PRAT pint = nullptr;
int32_t intpwr; int32_t intpwr;
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);
DUPRAT(pint,*px); DUPRAT(pint, *px);
intrat(&pint, radix, precision); intrat(&pint, radix, precision);
intpwr = rattoi32(pint, radix, precision); intpwr = rattoi32(pint, radix, precision);
ratpowi32( &pwr, intpwr, precision); ratpowi32(&pwr, intpwr, precision);
subrat(px, pint, precision); subrat(px, pint, precision);
// It just so happens to be an integral power of e. // It just so happens to be an integral power of e.
if ( rat_gt( *px, rat_negsmallest, precision) && rat_lt( *px, rat_smallest, precision) ) if (rat_gt(*px, rat_negsmallest, precision) && rat_lt(*px, rat_smallest, precision))
{ {
DUPRAT(*px,pwr); DUPRAT(*px, pwr);
} }
else else
{ {
@ -92,11 +92,10 @@ void exprat( PRAT *px, uint32_t radix, int32_t precision)
mulrat(px, pwr, precision); mulrat(px, pwr, precision);
} }
destroyrat( pwr ); destroyrat(pwr);
destroyrat( pint ); destroyrat(pint);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// FUNCTION: lograt, _lograt // FUNCTION: lograt, _lograt
@ -124,7 +123,7 @@ void exprat( PRAT *px, uint32_t radix, int32_t precision)
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void _lograt( PRAT *px, int32_t precision) void _lograt(PRAT* px, int32_t precision)
{ {
CREATETAYLOR(); CREATETAYLOR();
@ -133,44 +132,43 @@ 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);
DUPRAT(thisterm,*px); DUPRAT(thisterm, *px);
n2=i32tonum(1L, BASEX); n2 = i32tonum(1L, BASEX);
(*px)->pp->sign *= -1; (*px)->pp->sign *= -1;
do { do
{
NEXTTERM(*px, MULNUM(n2) INC(n2) DIVNUM(n2), precision); NEXTTERM(*px, MULNUM(n2) INC(n2) DIVNUM(n2), precision);
TRIMTOP(*px, precision); TRIMTOP(*px, precision);
} while ( !SMALL_ENOUGH_RAT( thisterm, precision) ); } while (!SMALL_ENOUGH_RAT(thisterm, precision));
DESTROYTAYLOR(); DESTROYTAYLOR();
} }
void lograt(PRAT* px, int32_t precision)
void lograt( PRAT *px, int32_t precision)
{ {
bool fneglog; bool fneglog;
PRAT pwr = nullptr; // pwr is the large scaling factor. PRAT pwr = nullptr; // pwr is the large scaling factor.
PRAT offset = nullptr; // offset is the incremental scaling factor. PRAT offset = nullptr; // offset is the incremental scaling factor.
// 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
fneglog = rat_lt( *px, rat_one, precision); fneglog = rat_lt(*px, rat_one, precision);
if ( fneglog ) if (fneglog)
{ {
// WARNING: This is equivalent to doing *px = 1 / *px // WARNING: This is equivalent to doing *px = 1 / *px
PNUMBER pnumtemp= nullptr; PNUMBER pnumtemp = nullptr;
pnumtemp = (*px)->pp; pnumtemp = (*px)->pp;
(*px)->pp = (*px)->pq; (*px)->pp = (*px)->pq;
(*px)->pq = pnumtemp; (*px)->pq = pnumtemp;
@ -178,14 +176,14 @@ void lograt( PRAT *px, int32_t precision)
// Scale the number within BASEX factor of 1, for the large scale. // Scale the number within BASEX factor of 1, for the large scale.
// log(x*2^(BASEXPWR*k)) = BASEXPWR*k*log(2)+log(x) // log(x*2^(BASEXPWR*k)) = BASEXPWR*k*log(2)+log(x)
if ( LOGRAT2(*px) > 1 ) if (LOGRAT2(*px) > 1)
{ {
// Take advantage of px's base BASEX to scale quickly down to // Take advantage of px's base BASEX to scale quickly down to
// a reasonable range. // a reasonable range.
int32_t intpwr; int32_t intpwr;
intpwr=LOGRAT2(*px)-1; intpwr = LOGRAT2(*px) - 1;
(*px)->pq->exp += intpwr; (*px)->pq->exp += intpwr;
pwr=i32torat(intpwr*BASEXPWR); pwr = i32torat(intpwr * BASEXPWR);
mulrat(&pwr, ln_two, precision); mulrat(&pwr, ln_two, precision);
// ln(x+e)-ln(x) looks close to e when x is close to one using some // ln(x+e)-ln(x) looks close to e when x is close to one using some
// expansions. This means we can trim past precision digits+1. // expansions. This means we can trim past precision digits+1.
@ -193,15 +191,15 @@ void lograt( PRAT *px, int32_t precision)
} }
else else
{ {
DUPRAT(pwr,rat_zero); DUPRAT(pwr, rat_zero);
} }
DUPRAT(offset,rat_zero); DUPRAT(offset, rat_zero);
// Scale the number between 1 and e_to_one_half, for the small scale. // Scale the number between 1 and e_to_one_half, for the small scale.
while ( rat_gt( *px, e_to_one_half, precision) ) while (rat_gt(*px, e_to_one_half, precision))
{ {
divrat( px, e_to_one_half, precision); divrat(px, e_to_one_half, precision);
addrat( &offset, rat_one, precision); addrat(&offset, rat_one, precision);
} }
_lograt(px, precision); _lograt(px, precision);
@ -217,7 +215,7 @@ void lograt( PRAT *px, int32_t precision)
trimit(px, precision); trimit(px, precision);
// If number started out < 1 rescale answer to negative. // If number started out < 1 rescale answer to negative.
if ( fneglog ) if (fneglog)
{ {
(*px)->pp->sign *= -1; (*px)->pp->sign *= -1;
} }
@ -226,7 +224,7 @@ void lograt( PRAT *px, int32_t precision)
destroyrat(pwr); destroyrat(pwr);
} }
void log10rat( PRAT *px, int32_t precision) void log10rat(PRAT* px, int32_t precision)
{ {
lograt(px, precision); lograt(px, precision);
@ -246,7 +244,7 @@ bool IsEven(PRAT x, uint32_t radix, int32_t precision)
fracrat(&tmp, radix, precision); fracrat(&tmp, radix, precision);
addrat(&tmp, tmp, precision); addrat(&tmp, tmp, precision);
subrat(&tmp, rat_one, precision); subrat(&tmp, rat_one, precision);
if ( rat_lt( tmp, rat_zero, precision)) if (rat_lt(tmp, rat_zero, precision))
{ {
bRet = true; bRet = true;
} }
@ -269,7 +267,7 @@ bool IsEven(PRAT x, uint32_t radix, int32_t precision)
// //
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void powrat(PRAT *px, PRAT y, uint32_t radix, int32_t precision) void powrat(PRAT* px, PRAT y, uint32_t radix, int32_t precision)
{ {
// Handle cases where px or y is 0 by calling powratcomp directly // Handle cases where px or y is 0 by calling powratcomp directly
if (zerrat(*px) || zerrat(y)) if (zerrat(*px) || zerrat(y))
@ -296,7 +294,7 @@ void powrat(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
} }
} }
void powratNumeratorDenominator(PRAT *px, PRAT y, uint32_t radix, int32_t precision) void powratNumeratorDenominator(PRAT* px, PRAT y, uint32_t radix, int32_t precision)
{ {
// Prepare rationals // Prepare rationals
PRAT yNumerator = nullptr; PRAT yNumerator = nullptr;
@ -405,7 +403,7 @@ void powratNumeratorDenominator(PRAT *px, PRAT y, uint32_t radix, int32_t precis
// //
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void powratcomp(PRAT *px, PRAT y, uint32_t radix, int32_t precision) void powratcomp(PRAT* px, PRAT y, uint32_t radix, int32_t precision)
{ {
int32_t sign = SIGN(*px); int32_t sign = SIGN(*px);
@ -413,75 +411,73 @@ void powratcomp(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
(*px)->pp->sign = 1; (*px)->pp->sign = 1;
(*px)->pq->sign = 1; (*px)->pq->sign = 1;
if ( zerrat( *px ) ) if (zerrat(*px))
{ {
// *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))
{ {
// *px and y are both zero, special case a 1 return. // *px and y are both zero, special case a 1 return.
DUPRAT(*px,rat_one); DUPRAT(*px, rat_one);
// Ensure sign is positive. // Ensure sign is positive.
sign = 1; sign = 1;
} }
} }
else else
{ {
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) && if (rat_gt(pxint, rat_negsmallest, precision) && rat_lt(pxint, rat_smallest, precision) && (sign == 1))
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);
// Ensure sign is positive. // Ensure sign is positive.
sign = 1; sign = 1;
} }
else else
{ {
// Only do the exp if the number isn't zero or one // Only do the exp if the number isn't zero or one
PRAT podd = nullptr; PRAT podd = nullptr;
DUPRAT(podd,y); DUPRAT(podd, y);
fracrat(&podd, radix, precision); fracrat(&podd, radix, precision);
if ( rat_gt( podd, rat_negsmallest, precision) && rat_lt( podd, rat_smallest, precision) ) if (rat_gt(podd, rat_negsmallest, precision) && rat_lt(podd, rat_smallest, precision))
{ {
// If power is an integer let ratpowi32 deal with it. // If power is an integer let ratpowi32 deal with it.
PRAT iy = nullptr; PRAT iy = nullptr;
int32_t inty; int32_t inty;
DUPRAT(iy,y); DUPRAT(iy, y);
subrat(&iy, podd, precision); subrat(&iy, podd, precision);
inty = rattoi32(iy, radix, precision); inty = rattoi32(iy, radix, precision);
PRAT plnx = nullptr; PRAT plnx = nullptr;
DUPRAT(plnx,*px); DUPRAT(plnx, *px);
lograt(&plnx, precision); lograt(&plnx, precision);
mulrat(&plnx, iy, precision); mulrat(&plnx, iy, precision);
if ( rat_gt( plnx, rat_max_exp, precision) || rat_lt( plnx, rat_min_exp, precision) ) if (rat_gt(plnx, rat_max_exp, precision) || rat_lt(plnx, rat_min_exp, precision))
{ {
// Don't attempt exp of anything large or small.A // Don't attempt exp of anything large or small.A
destroyrat(plnx); destroyrat(plnx);
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);
if ( ( inty & 1 ) == 0 ) if ((inty & 1) == 0)
{ {
sign=1; sign = 1;
} }
destroyrat(iy); destroyrat(iy);
} }
else else
{ {
// power is a fraction // power is a fraction
if ( sign == -1 ) if (sign == -1)
{ {
// Need to throw an error if the exponent has an even denominator. // Need to throw an error if the exponent has an even denominator.
// As a first step, the numerator and denominator must be divided by 2 as many times as // As a first step, the numerator and denominator must be divided by 2 as many times as
@ -518,7 +514,7 @@ void powratcomp(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
if (fBadExponent) if (fBadExponent)
{ {
throw( CALC_E_DOMAIN ); throw(CALC_E_DOMAIN);
} }
} }
else else

View file

@ -15,8 +15,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "ratpak.h" #include "ratpak.h"
#define ABSRAT(x) (((x)->pp->sign = 1), ((x)->pq->sign = 1))
#define ABSRAT(x) (((x)->pp->sign=1),((x)->pq->sign=1))
#define NEGATE(x) ((x)->pp->sign *= -1) #define NEGATE(x) ((x)->pp->sign *= -1)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -55,37 +54,36 @@
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void _gamma(PRAT* pn, uint32_t radix, int32_t precision)
void _gamma( PRAT *pn, uint32_t radix, int32_t precision)
{ {
PRAT factorial= nullptr; PRAT factorial = nullptr;
PNUMBER count= nullptr; PNUMBER count = nullptr;
PRAT tmp= nullptr; PRAT tmp = nullptr;
PRAT one_pt_five= nullptr; PRAT one_pt_five = nullptr;
PRAT a= nullptr; PRAT a = nullptr;
PRAT a2= nullptr; PRAT a2 = nullptr;
PRAT term= nullptr; PRAT term = nullptr;
PRAT sum= nullptr; PRAT sum = nullptr;
PRAT err= nullptr; PRAT err = nullptr;
PRAT mpy= nullptr; PRAT mpy = nullptr;
PRAT ratprec = nullptr; PRAT ratprec = nullptr;
PRAT ratRadix = nullptr; PRAT ratRadix = nullptr;
int32_t oldprec; int32_t oldprec;
// Set up constants and initial conditions // Set up constants and initial conditions
oldprec = precision; oldprec = precision;
ratprec = i32torat( oldprec ); ratprec = i32torat(oldprec);
// Find the best 'A' for convergence to the required precision. // Find the best 'A' for convergence to the required precision.
a=i32torat( radix ); a = i32torat(radix);
lograt(&a, precision); lograt(&a, precision);
mulrat(&a, ratprec, precision); mulrat(&a, ratprec, precision);
// Really is -ln(n)+1, but -ln(n) will be < 1 // Really is -ln(n)+1, but -ln(n) will be < 1
// if we scale n between 0.5 and 1.5 // if we scale n between 0.5 and 1.5
addrat(&a, rat_two, precision); addrat(&a, rat_two, precision);
DUPRAT(tmp,a); DUPRAT(tmp, a);
lograt(&tmp, precision); lograt(&tmp, precision);
mulrat(&tmp, *pn, precision); mulrat(&tmp, *pn, precision);
addrat(&a, tmp, precision); addrat(&a, tmp, precision);
@ -94,85 +92,85 @@ void _gamma( PRAT *pn, uint32_t radix, int32_t precision)
// Calculate the necessary bump in precision and up the precision. // Calculate the necessary bump in precision and up the precision.
// The following code is equivalent to // The following code is equivalent to
// precision += ln(exp(a)*pow(a,n+1.5))-ln(radix)); // precision += ln(exp(a)*pow(a,n+1.5))-ln(radix));
DUPRAT(tmp,*pn); DUPRAT(tmp, *pn);
one_pt_five=i32torat( 3L ); one_pt_five = i32torat(3L);
divrat( &one_pt_five, rat_two, precision); divrat(&one_pt_five, rat_two, precision);
addrat( &tmp, one_pt_five, precision); addrat(&tmp, one_pt_five, precision);
DUPRAT(term,a); DUPRAT(term, a);
powratcomp( &term, tmp, radix, precision); powratcomp(&term, tmp, radix, precision);
DUPRAT( tmp, a ); DUPRAT(tmp, a);
exprat( &tmp, radix, precision); exprat(&tmp, radix, precision);
mulrat( &term, tmp, precision); mulrat(&term, tmp, precision);
lograt( &term, precision); lograt(&term, precision);
ratRadix = i32torat(radix); ratRadix = i32torat(radix);
DUPRAT(tmp,ratRadix); DUPRAT(tmp, ratRadix);
lograt( &tmp, precision); lograt(&tmp, precision);
subrat( &term, tmp, precision); subrat(&term, tmp, precision);
precision += rattoi32( term, radix, precision); precision += rattoi32(term, radix, precision);
// Set up initial terms for series, refer to series in above comment block. // Set up initial terms for series, refer to series in above comment block.
DUPRAT(factorial,rat_one); // Start factorial out with one DUPRAT(factorial, rat_one); // Start factorial out with one
count = i32tonum( 0L, BASEX ); count = i32tonum(0L, BASEX);
DUPRAT(mpy,a); DUPRAT(mpy, a);
powratcomp(&mpy,*pn, radix, precision); powratcomp(&mpy, *pn, radix, precision);
// a2=a^2 // a2=a^2
DUPRAT(a2,a); DUPRAT(a2, a);
mulrat(&a2, a, precision); mulrat(&a2, a, precision);
// sum=(1/n)-(a/(n+1)) // sum=(1/n)-(a/(n+1))
DUPRAT(sum,rat_one); DUPRAT(sum, rat_one);
divrat(&sum, *pn, precision); divrat(&sum, *pn, precision);
DUPRAT(tmp,*pn); DUPRAT(tmp, *pn);
addrat(&tmp, rat_one, precision); addrat(&tmp, rat_one, precision);
DUPRAT(term,a); DUPRAT(term, a);
divrat(&term, tmp, precision); divrat(&term, tmp, precision);
subrat(&sum, term, precision); subrat(&sum, term, precision);
DUPRAT(err,ratRadix); DUPRAT(err, ratRadix);
NEGATE(ratprec); NEGATE(ratprec);
powratcomp(&err,ratprec, radix, precision); powratcomp(&err, ratprec, radix, precision);
divrat(&err, ratRadix, precision); divrat(&err, ratRadix, precision);
// Just get something not tiny in term // Just get something not tiny in term
DUPRAT(term, rat_two ); DUPRAT(term, rat_two);
// Loop until precision is reached, or asked to halt. // Loop until precision is reached, or asked to halt.
while ( !zerrat( term ) && rat_gt( term, err, precision) ) while (!zerrat(term) && rat_gt(term, err, 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);
DUPRAT(tmp,*pn); DUPRAT(tmp, *pn);
addrat( &tmp, rat_one, precision); addrat(&tmp, rat_one, precision);
destroyrat(term); destroyrat(term);
createrat(term); createrat(term);
DUPNUM(term->pp,count); DUPNUM(term->pp, count);
DUPNUM(term->pq,num_one); DUPNUM(term->pq, num_one);
addrat( &term, rat_one, precision); addrat(&term, rat_one, precision);
mulrat( &term, tmp, precision); mulrat(&term, tmp, precision);
DUPRAT(tmp,a); DUPRAT(tmp, a);
divrat( &tmp, term, precision); divrat(&tmp, term, precision);
DUPRAT(term,rat_one); DUPRAT(term, rat_one);
divrat( &term, *pn, precision); divrat(&term, *pn, precision);
subrat( &term, tmp, precision); subrat(&term, tmp, precision);
divrat (&term, factorial, precision); divrat(&term, factorial, precision);
addrat( &sum, term, precision); addrat(&sum, term, precision);
ABSRAT(term); ABSRAT(term);
} }
// Multiply by factor. // Multiply by factor.
mulrat( &sum, mpy, precision); mulrat(&sum, mpy, precision);
// And cleanup // And cleanup
precision = oldprec; precision = oldprec;
@ -188,70 +186,67 @@ void _gamma( PRAT *pn, uint32_t radix, int32_t precision)
destroyrat(factorial); destroyrat(factorial);
destroyrat(*pn); destroyrat(*pn);
DUPRAT(*pn,sum); DUPRAT(*pn, sum);
destroyrat(sum); destroyrat(sum);
} }
void factrat( PRAT *px, uint32_t radix, int32_t precision) void factrat(PRAT* px, uint32_t radix, int32_t precision)
{ {
PRAT fact = nullptr; PRAT fact = nullptr;
PRAT frac = nullptr; PRAT frac = nullptr;
PRAT neg_rat_one = nullptr; PRAT neg_rat_one = nullptr;
if ( rat_gt( *px, rat_max_fact, precision) || rat_lt( *px, rat_min_fact, precision) ) if (rat_gt(*px, rat_max_fact, precision) || rat_lt(*px, rat_min_fact, precision))
{ {
// Don't attempt factorial of anything too large or small. // Don't attempt factorial of anything too large or small.
throw CALC_E_OVERFLOW; throw CALC_E_OVERFLOW;
} }
DUPRAT(fact,rat_one); DUPRAT(fact, rat_one);
DUPRAT(neg_rat_one,rat_one); DUPRAT(neg_rat_one, rat_one);
neg_rat_one->pp->sign *= -1; neg_rat_one->pp->sign *= -1;
DUPRAT( frac, *px ); DUPRAT(frac, *px);
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) ) && if ((zerrat(frac) || (LOGRATRADIX(frac) <= -precision)) && (SIGN(*px) == -1))
( SIGN(*px) == -1 ) )
{ {
throw CALC_E_DOMAIN; throw CALC_E_DOMAIN;
} }
while ( rat_gt( *px, rat_zero, precision) && while (rat_gt(*px, rat_zero, precision) && (LOGRATRADIX(*px) > -precision))
( LOGRATRADIX(*px) > -precision) )
{ {
mulrat( &fact, *px, precision); mulrat(&fact, *px, precision);
subrat( px, rat_one, precision); subrat(px, rat_one, precision);
} }
// Added to make numbers 'close enough' to integers use integer factorial. // Added to make numbers 'close enough' to integers use integer factorial.
if ( LOGRATRADIX(*px) <= -precision) if (LOGRATRADIX(*px) <= -precision)
{ {
DUPRAT((*px),rat_zero); DUPRAT((*px), rat_zero);
intrat(&fact, radix, precision); intrat(&fact, radix, precision);
} }
while ( rat_lt( *px, neg_rat_one, precision) ) while (rat_lt(*px, neg_rat_one, precision))
{ {
addrat( px, rat_one, precision); addrat(px, rat_one, precision);
divrat( &fact, *px, precision); divrat(&fact, *px, precision);
} }
if ( rat_neq( *px, rat_zero, precision) ) if (rat_neq(*px, rat_zero, precision))
{ {
addrat( px, rat_one, precision); addrat(px, rat_one, precision);
_gamma( px, radix, precision); _gamma(px, radix, precision);
mulrat( px, fact, precision); mulrat(px, fact, precision);
} }
else else
{ {
DUPRAT(*px,fact); DUPRAT(*px, fact);
} }
destroyrat(fact); destroyrat(fact);
destroyrat(frac); destroyrat(frac);
destroyrat(neg_rat_one); destroyrat(neg_rat_one);
} }

View file

@ -17,26 +17,23 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "ratpak.h" #include "ratpak.h"
void ascalerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, int32_t precision)
void ascalerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, int32_t precision)
{ {
switch ( angletype ) switch (angletype)
{ {
case ANGLE_RAD: case ANGLE_RAD:
break; break;
case ANGLE_DEG: case ANGLE_DEG:
divrat( pa, two_pi, precision); divrat(pa, two_pi, precision);
mulrat( pa, rat_360, precision); mulrat(pa, rat_360, precision);
break; break;
case ANGLE_GRAD: case ANGLE_GRAD:
divrat( pa, two_pi, precision); divrat(pa, two_pi, precision);
mulrat( pa, rat_400, precision); mulrat(pa, rat_400, precision);
break; break;
} }
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// FUNCTION: asinrat, _asinrat // FUNCTION: asinrat, _asinrat
@ -64,86 +61,83 @@ void ascalerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, int32_t precision)
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void _asinrat( PRAT *px, int32_t precision) void _asinrat(PRAT* px, int32_t precision)
{ {
CREATETAYLOR(); CREATETAYLOR();
DUPRAT(pret,*px); DUPRAT(pret, *px);
DUPRAT(thisterm,*px); DUPRAT(thisterm, *px);
DUPNUM(n2,num_one); DUPNUM(n2, num_one);
do do
{ {
NEXTTERM(xx,MULNUM(n2) MULNUM(n2) NEXTTERM(xx, MULNUM(n2) MULNUM(n2) INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision); } while (!SMALL_ENOUGH_RAT(thisterm, precision));
}
while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
DESTROYTAYLOR(); DESTROYTAYLOR();
} }
void asinanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision) void asinanglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
{ {
asinrat( pa, radix, precision); asinrat(pa, radix, precision);
ascalerat( pa, angletype, precision); ascalerat(pa, angletype, precision);
} }
void asinrat( PRAT *px, uint32_t radix, int32_t precision) void asinrat(PRAT* px, uint32_t radix, int32_t precision)
{ {
PRAT pret= nullptr; PRAT pret = nullptr;
PRAT phack= nullptr; PRAT phack = nullptr;
int32_t sgn = SIGN(*px); int32_t sgn = SIGN(*px);
(*px)->pp->sign = 1; (*px)->pp->sign = 1;
(*px)->pq->sign = 1; (*px)->pq->sign = 1;
// Avoid the really bad part of the asin curve near +/-1. // Avoid the really bad part of the asin curve near +/-1.
DUPRAT(phack,*px); DUPRAT(phack, *px);
subrat(&phack, rat_one, precision); subrat(&phack, rat_one, precision);
// Since *px might be epsilon near zero we must set it to zero. // Since *px might be epsilon near zero we must set it to zero.
if ( rat_le(phack, rat_smallest, precision) && rat_ge(phack, rat_negsmallest, precision) ) if (rat_le(phack, rat_smallest, precision) && rat_ge(phack, rat_negsmallest, precision))
{ {
destroyrat(phack); destroyrat(phack);
DUPRAT( *px, pi_over_two ); DUPRAT(*px, pi_over_two);
} }
else else
{ {
destroyrat(phack); destroyrat(phack);
if ( rat_gt( *px, pt_eight_five, precision) ) if (rat_gt(*px, pt_eight_five, precision))
{ {
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
{ {
DUPRAT(*px,rat_one); DUPRAT(*px, rat_one);
} }
} }
DUPRAT(pret,*px); DUPRAT(pret, *px);
mulrat( px, pret, precision); mulrat(px, pret, precision);
(*px)->pp->sign *= -1; (*px)->pp->sign *= -1;
addrat( px, rat_one, precision); addrat(px, rat_one, precision);
rootrat( px, rat_two, radix, precision); rootrat(px, rat_two, radix, precision);
_asinrat( px, precision); _asinrat(px, precision);
(*px)->pp->sign *= -1; (*px)->pp->sign *= -1;
addrat( px, pi_over_two, precision); addrat(px, pi_over_two, precision);
destroyrat(pret); destroyrat(pret);
} }
else else
{ {
_asinrat( px, precision); _asinrat(px, precision);
} }
} }
(*px)->pp->sign = sgn; (*px)->pp->sign = sgn;
(*px)->pq->sign = 1; (*px)->pq->sign = 1;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// FUNCTION: acosrat, _acosrat // FUNCTION: acosrat, _acosrat
@ -170,35 +164,33 @@ void asinrat( PRAT *px, uint32_t radix, int32_t precision)
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void acosanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision) void acosanglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
{ {
acosrat( pa, radix, precision); acosrat(pa, radix, precision);
ascalerat( pa, angletype, precision); ascalerat(pa, angletype, precision);
} }
void _acosrat( PRAT *px, int32_t precision) void _acosrat(PRAT* px, int32_t precision)
{ {
CREATETAYLOR(); CREATETAYLOR();
createrat(thisterm); createrat(thisterm);
thisterm->pp=i32tonum( 1L, BASEX ); thisterm->pp = i32tonum(1L, BASEX);
thisterm->pq=i32tonum( 1L, BASEX ); thisterm->pq = i32tonum(1L, BASEX);
DUPNUM(n2,num_one); DUPNUM(n2, num_one);
do do
{ {
NEXTTERM(xx,MULNUM(n2) MULNUM(n2) NEXTTERM(xx, MULNUM(n2) MULNUM(n2) INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision); } while (!SMALL_ENOUGH_RAT(thisterm, precision));
}
while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
DESTROYTAYLOR(); DESTROYTAYLOR();
} }
void acosrat( PRAT *px, uint32_t radix, int32_t precision) void acosrat(PRAT* px, uint32_t radix, int32_t precision)
{ {
int32_t sgn = SIGN(*px); int32_t sgn = SIGN(*px);
@ -206,21 +198,21 @@ void acosrat( 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_equ( *px, rat_one, precision) ) if (rat_equ(*px, rat_one, precision))
{ {
if ( sgn == -1 ) if (sgn == -1)
{ {
DUPRAT(*px,pi); DUPRAT(*px, pi);
} }
else else
{ {
DUPRAT( *px, rat_zero ); DUPRAT(*px, rat_zero);
} }
} }
else else
{ {
(*px)->pp->sign = sgn; (*px)->pp->sign = sgn;
asinrat( px, radix, precision); asinrat(px, radix, precision);
(*px)->pp->sign *= -1; (*px)->pp->sign *= -1;
addrat(px, pi_over_two, precision); addrat(px, pi_over_two, precision);
} }
@ -257,66 +249,67 @@ void acosrat( PRAT *px, uint32_t radix, int32_t precision)
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void atananglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision) void atananglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
{ {
atanrat( pa, radix, precision); atanrat(pa, radix, precision);
ascalerat( pa, angletype, precision); ascalerat(pa, angletype, precision);
} }
void _atanrat( PRAT *px, int32_t precision) void _atanrat(PRAT* px, int32_t precision)
{ {
CREATETAYLOR(); CREATETAYLOR();
DUPRAT(pret,*px); DUPRAT(pret, *px);
DUPRAT(thisterm,*px); DUPRAT(thisterm, *px);
DUPNUM(n2,num_one); DUPNUM(n2, num_one);
xx->pp->sign *= -1; xx->pp->sign *= -1;
do { do
NEXTTERM(xx,MULNUM(n2) INC(n2) INC(n2) DIVNUM(n2), precision); {
} while ( !SMALL_ENOUGH_RAT( thisterm, precision) ); NEXTTERM(xx, MULNUM(n2) INC(n2) INC(n2) DIVNUM(n2), precision);
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
DESTROYTAYLOR(); DESTROYTAYLOR();
} }
void atanrat( PRAT *px, uint32_t radix, int32_t precision) void atanrat(PRAT* px, uint32_t radix, int32_t precision)
{ {
PRAT tmpx= nullptr; PRAT tmpx = nullptr;
int32_t sgn = SIGN(*px); int32_t sgn = SIGN(*px);
(*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;
DUPRAT(*px,pi_over_two); DUPRAT(*px, pi_over_two);
subrat(px, tmpx, precision); subrat(px, tmpx, precision);
destroyrat( tmpx ); destroyrat(tmpx);
} }
else else
{ {
(*px)->pp->sign = sgn; (*px)->pp->sign = sgn;
DUPRAT(tmpx,*px); DUPRAT(tmpx, *px);
mulrat( &tmpx, *px, precision); mulrat(&tmpx, *px, precision);
addrat( &tmpx, rat_one, precision); addrat(&tmpx, rat_one, precision);
rootrat( &tmpx, rat_two, radix, precision); rootrat(&tmpx, rat_two, radix, precision);
divrat( px, tmpx, precision); divrat(px, tmpx, precision);
destroyrat( tmpx ); destroyrat(tmpx);
asinrat( px, radix, precision); asinrat(px, radix, precision);
(*px)->pp->sign = sgn; (*px)->pp->sign = sgn;
(*px)->pq->sign = 1; (*px)->pq->sign = 1;
} }
@ -325,11 +318,10 @@ void atanrat( PRAT *px, uint32_t radix, int32_t precision)
{ {
(*px)->pp->sign = sgn; (*px)->pp->sign = sgn;
(*px)->pq->sign = 1; (*px)->pq->sign = 1;
_atanrat( px, precision); _atanrat(px, precision);
} }
if ( rat_gt( *px, pi_over_two, precision) ) if (rat_gt(*px, pi_over_two, precision))
{ {
subrat( px, pi, precision); subrat(px, pi, precision);
} }
} }

View file

@ -18,8 +18,6 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "ratpak.h" #include "ratpak.h"
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// FUNCTION: asinhrat // FUNCTION: asinhrat
@ -49,17 +47,17 @@
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void asinhrat( PRAT *px, uint32_t radix, int32_t precision) void asinhrat(PRAT* px, uint32_t radix, int32_t precision)
{ {
PRAT neg_pt_eight_five = nullptr; PRAT neg_pt_eight_five = nullptr;
DUPRAT(neg_pt_eight_five,pt_eight_five); DUPRAT(neg_pt_eight_five, pt_eight_five);
neg_pt_eight_five->pp->sign *= -1; neg_pt_eight_five->pp->sign *= -1;
if ( rat_gt( *px, pt_eight_five, precision) || rat_lt( *px, neg_pt_eight_five, precision) ) if (rat_gt(*px, pt_eight_five, precision) || rat_lt(*px, neg_pt_eight_five, precision))
{ {
PRAT ptmp = nullptr; PRAT ptmp = nullptr;
DUPRAT(ptmp,(*px)); DUPRAT(ptmp, (*px));
mulrat(&ptmp, *px, precision); mulrat(&ptmp, *px, precision);
addrat(&ptmp, rat_one, precision); addrat(&ptmp, rat_one, precision);
rootrat(&ptmp, rat_two, radix, precision); rootrat(&ptmp, rat_two, radix, precision);
@ -72,24 +70,21 @@ void asinhrat( PRAT *px, uint32_t radix, int32_t precision)
CREATETAYLOR(); CREATETAYLOR();
xx->pp->sign *= -1; xx->pp->sign *= -1;
DUPRAT(pret,(*px)); DUPRAT(pret, (*px));
DUPRAT(thisterm,(*px)); DUPRAT(thisterm, (*px));
DUPNUM(n2,num_one); DUPNUM(n2, num_one);
do do
{ {
NEXTTERM(xx,MULNUM(n2) MULNUM(n2) NEXTTERM(xx, MULNUM(n2) MULNUM(n2) INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision); } while (!SMALL_ENOUGH_RAT(thisterm, precision));
}
while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
DESTROYTAYLOR(); DESTROYTAYLOR();
} }
destroyrat(neg_pt_eight_five); destroyrat(neg_pt_eight_five);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// FUNCTION: acoshrat // FUNCTION: acoshrat
@ -106,20 +101,20 @@ void asinhrat( PRAT *px, uint32_t radix, int32_t precision)
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void acoshrat( PRAT *px, uint32_t radix, int32_t precision) void acoshrat(PRAT* px, uint32_t radix, int32_t precision)
{ {
if ( rat_lt( *px, rat_one, precision) ) if (rat_lt(*px, rat_one, precision))
{ {
throw CALC_E_DOMAIN; throw CALC_E_DOMAIN;
} }
else else
{ {
PRAT ptmp = nullptr; PRAT ptmp = nullptr;
DUPRAT(ptmp,(*px)); DUPRAT(ptmp, (*px));
mulrat(&ptmp, *px, precision); mulrat(&ptmp, *px, precision);
subrat(&ptmp, rat_one, precision); subrat(&ptmp, rat_one, precision);
rootrat(&ptmp,rat_two, radix, precision); rootrat(&ptmp, rat_two, radix, precision);
addrat(px, ptmp, precision); addrat(px, ptmp, precision);
lograt(px, precision); lograt(px, precision);
destroyrat(ptmp); destroyrat(ptmp);
@ -143,11 +138,11 @@ void acoshrat( PRAT *px, uint32_t radix, int32_t precision)
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void atanhrat( PRAT *px, int32_t precision) void atanhrat(PRAT* px, int32_t precision)
{ {
PRAT ptmp = nullptr; PRAT ptmp = nullptr;
DUPRAT(ptmp,(*px)); DUPRAT(ptmp, (*px));
subrat(&ptmp, rat_one, precision); subrat(&ptmp, rat_one, precision);
addrat(px, rat_one, precision); addrat(px, rat_one, precision);
divrat(px, ptmp, precision); divrat(px, ptmp, precision);
@ -156,4 +151,3 @@ void atanhrat( PRAT *px, int32_t precision)
divrat(px, rat_two, precision); divrat(px, rat_two, precision);
destroyrat(ptmp); destroyrat(ptmp);
} }

View file

@ -17,7 +17,7 @@
using namespace std; using namespace std;
void lshrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision) void lshrat(PRAT* pa, PRAT b, uint32_t radix, int32_t precision)
{ {
PRAT pwr = nullptr; PRAT pwr = nullptr;
@ -40,7 +40,7 @@ void lshrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
} }
} }
void rshrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision) void rshrat(PRAT* pa, PRAT b, uint32_t radix, int32_t precision)
{ {
PRAT pwr = nullptr; PRAT pwr = nullptr;
@ -63,29 +63,29 @@ void rshrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
} }
} }
void boolrat(PRAT *pa, PRAT b, int func, uint32_t radix, int32_t precision); void boolrat(PRAT* pa, PRAT b, int func, uint32_t radix, int32_t precision);
void boolnum(PNUMBER *pa, PNUMBER b, int func); void boolnum(PNUMBER* pa, PNUMBER b, int func);
enum
enum { {
FUNC_AND, FUNC_AND,
FUNC_OR, FUNC_OR,
FUNC_XOR FUNC_XOR
} BOOL_FUNCS; } BOOL_FUNCS;
void andrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision) void andrat(PRAT* pa, PRAT b, uint32_t radix, int32_t precision)
{ {
boolrat(pa, b, FUNC_AND, radix, precision); boolrat(pa, b, FUNC_AND, radix, precision);
} }
void orrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision) void orrat(PRAT* pa, PRAT b, uint32_t radix, int32_t precision)
{ {
boolrat(pa, b, FUNC_OR, radix, precision); boolrat(pa, b, FUNC_OR, radix, precision);
} }
void xorrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision) void xorrat(PRAT* pa, PRAT b, uint32_t radix, int32_t precision)
{ {
boolrat(pa, b, FUNC_XOR, radix, precision); boolrat(pa, b, FUNC_XOR, radix, precision);
@ -103,7 +103,7 @@ void xorrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void boolrat(PRAT *pa, PRAT b, int func, uint32_t radix, int32_t precision) void boolrat(PRAT* pa, PRAT b, int func, uint32_t radix, int32_t precision)
{ {
PRAT tmp = nullptr; PRAT tmp = nullptr;
@ -129,22 +129,21 @@ void boolrat(PRAT *pa, PRAT b, int func, uint32_t radix, int32_t precision)
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void boolnum(PNUMBER *pa, PNUMBER b, int func) void boolnum(PNUMBER* pa, PNUMBER b, int func)
{ {
PNUMBER c = nullptr; PNUMBER c = nullptr;
PNUMBER a = nullptr; PNUMBER a = nullptr;
MANTTYPE *pcha; MANTTYPE* pcha;
MANTTYPE *pchb; MANTTYPE* pchb;
MANTTYPE *pchc; MANTTYPE* pchc;
int32_t cdigits; int32_t cdigits;
int32_t mexp; int32_t mexp;
MANTTYPE da; MANTTYPE da;
MANTTYPE db; MANTTYPE db;
a = *pa; a = *pa;
cdigits = max(a->cdigit + a->exp, b->cdigit + b->exp) - cdigits = max(a->cdigit + a->exp, b->cdigit + b->exp) - min(a->exp, b->exp);
min(a->exp, b->exp);
createnum(c, cdigits); createnum(c, cdigits);
c->exp = min(a->exp, b->exp); c->exp = min(a->exp, b->exp);
mexp = c->exp; mexp = c->exp;
@ -154,12 +153,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 > da = (((mexp >= a->exp) && (cdigits + a->exp - c->exp > (c->cdigit - a->cdigit))) ? *pcha++ : 0);
(c->cdigit - a->cdigit))) ? db = (((mexp >= b->exp) && (cdigits + b->exp - c->exp > (c->cdigit - b->cdigit))) ? *pchb++ : 0);
*pcha++ : 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:
@ -196,7 +191,7 @@ void boolnum(PNUMBER *pa, PNUMBER b, int func)
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void remrat(PRAT *pa, PRAT b) void remrat(PRAT* pa, PRAT b)
{ {
if (zerrat(b)) if (zerrat(b))
@ -233,9 +228,9 @@ void remrat(PRAT *pa, PRAT b)
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void modrat(PRAT *pa, PRAT b) void modrat(PRAT* pa, PRAT b)
{ {
//contrary to remrat(X, 0) returning 0, modrat(X, 0) must return X // contrary to remrat(X, 0) returning 0, modrat(X, 0) must return X
if (zerrat(b)) if (zerrat(b))
{ {
return; return;

View file

@ -41,51 +41,49 @@ using namespace std;
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix); void _addnum(PNUMBER* pa, PNUMBER b, uint32_t radix);
void __inline addnum( PNUMBER *pa, PNUMBER b, uint32_t radix) void __inline addnum(PNUMBER* pa, PNUMBER b, uint32_t radix)
{ {
if ( b->cdigit > 1 || b->mant[0] != 0 ) if (b->cdigit > 1 || b->mant[0] != 0)
{ // If b is zero we are done. { // If b is zero we are done.
if ( (*pa)->cdigit > 1 || (*pa)->mant[0] != 0 ) if ((*pa)->cdigit > 1 || (*pa)->mant[0] != 0)
{ // pa and b are both nonzero. { // pa and b are both nonzero.
_addnum( pa, b, radix); _addnum(pa, b, radix);
} }
else else
{ // if pa is zero and b isn't just copy b. { // if pa is zero and b isn't just copy b.
DUPNUM(*pa,b); DUPNUM(*pa, b);
} }
} }
} }
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 int32_t cdigits; // cdigits is the max count of the digits results
// used as a counter. // 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. int32_t fcompla = 0; // fcompla is a flag to signal a is negative.
int32_t fcomplb = 0; // fcomplb is a flag to signal b is negative. int32_t fcomplb = 0; // fcomplb is a flag to signal b is negative.
a=*pa; a = *pa;
// Calculate the overlap of the numbers after alignment, this includes // Calculate the overlap of the numbers after alignment, this includes
// necessary padding 0's // necessary padding 0's
cdigits = max( a->cdigit+a->exp, b->cdigit+b->exp ) - cdigits = max(a->cdigit + a->exp, b->cdigit + b->exp) - min(a->exp, b->exp);
min( a->exp, b->exp );
createnum( c, cdigits + 1 ); createnum(c, cdigits + 1);
c->exp = min( a->exp, b->exp ); c->exp = min(a->exp, b->exp);
mexp = c->exp; mexp = c->exp;
c->cdigit = cdigits; c->cdigit = cdigits;
pcha = a->mant; pcha = a->mant;
@ -93,36 +91,31 @@ void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
pchc = c->mant; pchc = c->mant;
// Figure out the sign of the numbers // Figure out the sign of the numbers
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
// aligned // aligned
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 > da = (((mexp >= a->exp) && (cdigits + a->exp - c->exp > (c->cdigit - a->cdigit))) ? *pcha++ : 0);
(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 > db = (((mexp >= b->exp) && (cdigits + b->exp - c->exp > (c->cdigit - b->cdigit))) ? *pchb++ : 0);
(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 = (MANTTYPE)(radix)-1 - da;
} }
if ( fcomplb ) if (fcomplb)
{ {
db = (MANTTYPE)(radix) - 1 - db; db = (MANTTYPE)(radix)-1 - db;
} }
// Update carry as necessary // Update carry as necessary
@ -132,20 +125,20 @@ void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
} }
// Handle carry from last sum as extra digit // Handle carry from last sum as extra digit
if ( cy && !(fcompla || fcomplb) ) if (cy && !(fcompla || fcomplb))
{ {
*pchc++ = cy; *pchc++ = cy;
c->cdigit++; c->cdigit++;
} }
// Compute sign of result // Compute sign of result
if ( !(fcompla || fcomplb) ) if (!(fcompla || fcomplb))
{ {
c->sign = a->sign; c->sign = a->sign;
} }
else else
{ {
if ( cy ) if (cy)
{ {
c->sign = 1; c->sign = 1;
} }
@ -157,12 +150,10 @@ void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
// slower on average. // slower on average.
c->sign = -1; c->sign = -1;
cy = 1; cy = 1;
for ( ( cdigits = c->cdigit ), (pchc = c->mant); for ((cdigits = c->cdigit), (pchc = c->mant); cdigits > 0; cdigits--)
cdigits > 0;
cdigits-- )
{ {
cy = (MANTTYPE)radix - (MANTTYPE)1 - *pchc + cy; cy = (MANTTYPE)radix - (MANTTYPE)1 - *pchc + cy;
*pchc++ = (MANTTYPE)( cy % (MANTTYPE)radix); *pchc++ = (MANTTYPE)(cy % (MANTTYPE)radix);
cy /= (MANTTYPE)radix; cy /= (MANTTYPE)radix;
} }
} }
@ -170,12 +161,12 @@ void _addnum( PNUMBER *pa, PNUMBER b, uint32_t 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--;
} }
destroynum( *pa ); destroynum(*pa);
*pa=c; *pa = c;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -193,21 +184,21 @@ void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix); void _mulnum(PNUMBER* pa, PNUMBER b, uint32_t radix);
void __inline mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix) void __inline mulnum(PNUMBER* pa, PNUMBER b, uint32_t radix)
{ {
if ( b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0 ) if (b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0)
{ // If b is one we don't multiply exactly. { // If b is one we don't multiply exactly.
if ( (*pa)->cdigit > 1 || (*pa)->mant[0] != 1 || (*pa)->exp != 0 ) if ((*pa)->cdigit > 1 || (*pa)->mant[0] != 1 || (*pa)->exp != 0)
{ // pa and b are both non-one. { // pa and b are both non-one.
_mulnum( pa, b, radix); _mulnum(pa, b, radix);
} }
else else
{ // if pa is one and b isn't just copy b, and adjust the sign. { // if pa is one and b isn't just copy b, and adjust the sign.
int32_t sign = (*pa)->sign; int32_t sign = (*pa)->sign;
DUPNUM(*pa,b); DUPNUM(*pa, b);
(*pa)->sign *= sign; (*pa)->sign *= sign;
} }
} }
@ -217,15 +208,15 @@ void __inline mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
} }
} }
void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix) void _mulnum(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.
MANTTYPE *pchcoffset; // pchcoffset, is the anchor location of the next MANTTYPE* pchcoffset; // pchcoffset, is the anchor location of the next
// single digit multiply partial result. // single digit multiply partial result.
int32_t iadigit = 0; // Index of digit being used in the first number. int32_t iadigit = 0; // Index of digit being used in the first number.
int32_t ibdigit = 0; // Index of digit being used in the second number. int32_t ibdigit = 0; // Index of digit being used in the second number.
@ -236,9 +227,9 @@ void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
// multiply, AND the carry of that multiply. // multiply, AND the carry of that multiply.
int32_t icdigit = 0; // Index of digit being calculated in final result. int32_t icdigit = 0; // Index of digit being calculated in final result.
a=*pa; a = *pa;
ibdigit = a->cdigit + b->cdigit - 1; ibdigit = a->cdigit + b->cdigit - 1;
createnum( c, ibdigit + 1 ); createnum(c, ibdigit + 1);
c->cdigit = ibdigit; c->cdigit = ibdigit;
c->sign = a->sign * b->sign; c->sign = a->sign * b->sign;
@ -246,7 +237,7 @@ void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
pcha = a->mant; pcha = a->mant;
pchcoffset = c->mant; pchcoffset = c->mant;
for ( iadigit = a->cdigit; iadigit > 0; iadigit-- ) for (iadigit = a->cdigit; iadigit > 0; iadigit--)
{ {
da = *pcha++; da = *pcha++;
pchb = b->mant; pchb = b->mant;
@ -254,27 +245,26 @@ void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
// Shift pchc, and pchcoffset, one for each digit // Shift pchc, and pchcoffset, one for each digit
pchc = pchcoffset++; pchc = pchcoffset++;
for ( ibdigit = b->cdigit; ibdigit > 0; ibdigit-- ) for (ibdigit = b->cdigit; ibdigit > 0; ibdigit--)
{ {
cy = 0; cy = 0;
mcy = (TWO_MANTTYPE)da * *pchb; mcy = (TWO_MANTTYPE)da * *pchb;
if ( mcy ) if (mcy)
{ {
icdigit = 0; icdigit = 0;
if ( ibdigit == 1 && iadigit == 1 ) if (ibdigit == 1 && iadigit == 1)
{ {
c->cdigit++; c->cdigit++;
} }
} }
// If result is nonzero, or while result of carry is nonzero... // If result is nonzero, or while result of carry is nonzero...
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 += (TWO_MANTTYPE)pchc[icdigit] + (mcy % (TWO_MANTTYPE)radix);
// update result digit from // update result digit from
pchc[icdigit++]=(MANTTYPE)(cy%(TWO_MANTTYPE)radix); pchc[icdigit++] = (MANTTYPE)(cy % (TWO_MANTTYPE)radix);
// update carries from // update carries from
mcy /= (TWO_MANTTYPE)radix; mcy /= (TWO_MANTTYPE)radix;
@ -288,16 +278,15 @@ void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
// prevent different kinds of zeros, by stripping leading duplicate zeros. // prevent different kinds of zeros, by stripping leading duplicate zeros.
// digits are in order of increasing significance. // digits are in order of increasing significance.
while ( c->cdigit > 1 && c->mant[c->cdigit-1] == 0 ) while (c->cdigit > 1 && c->mant[c->cdigit - 1] == 0)
{ {
c->cdigit--; c->cdigit--;
} }
destroynum( *pa ); destroynum(*pa);
*pa=c; *pa = c;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// //
// FUNCTION: remnum // FUNCTION: remnum
@ -313,55 +302,53 @@ void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void remnum( PNUMBER *pa, PNUMBER b, uint32_t radix) void remnum(PNUMBER* pa, PNUMBER b, uint32_t radix)
{ {
PNUMBER tmp = nullptr; // tmp is the working remainder. PNUMBER tmp = nullptr; // tmp is the working remainder.
PNUMBER lasttmp = nullptr; // lasttmp is the last remainder which worked. PNUMBER lasttmp = nullptr; // lasttmp is the last remainder which worked.
// Once *pa is less than b, *pa is the remainder. // Once *pa is less than b, *pa is the remainder.
while ( !lessnum( *pa, b ) ) while (!lessnum(*pa, b))
{ {
DUPNUM( tmp, b ); DUPNUM(tmp, b);
if ( lessnum( tmp, *pa ) ) if (lessnum(tmp, *pa))
{ {
// Start off close to the right answer for subtraction. // Start off close to the right answer for subtraction.
tmp->exp = (*pa)->cdigit+(*pa)->exp - tmp->cdigit; tmp->exp = (*pa)->cdigit + (*pa)->exp - tmp->cdigit;
if ( MSD(*pa) <= MSD(tmp) ) if (MSD(*pa) <= MSD(tmp))
{ {
// Don't take the chance that the numbers are equal. // Don't take the chance that the numbers are equal.
tmp->exp--; tmp->exp--;
} }
} }
destroynum( lasttmp ); destroynum(lasttmp);
lasttmp=i32tonum( 0, radix); lasttmp = i32tonum(0, radix);
while ( lessnum( tmp, *pa ) ) while (lessnum(tmp, *pa))
{ {
DUPNUM( lasttmp, tmp ); DUPNUM(lasttmp, tmp);
addnum( &tmp, tmp, radix); addnum(&tmp, tmp, radix);
} }
if ( lessnum( *pa, tmp ) ) if (lessnum(*pa, tmp))
{ {
// too far, back up... // too far, back up...
destroynum( tmp ); destroynum(tmp);
tmp=lasttmp; tmp = lasttmp;
lasttmp= nullptr; lasttmp = nullptr;
} }
// Subtract the working remainder from the remainder holder. // Subtract the working remainder from the remainder holder.
tmp->sign = -1*(*pa)->sign; tmp->sign = -1 * (*pa)->sign;
addnum( pa, tmp, radix); addnum(pa, tmp, radix);
destroynum( tmp );
destroynum( lasttmp );
destroynum(tmp);
destroynum(lasttmp);
} }
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
// FUNCTION: divnum // FUNCTION: divnum
@ -376,15 +363,15 @@ void remnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision); void _divnum(PNUMBER* pa, PNUMBER b, uint32_t radix, int32_t precision);
void __inline divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision) void __inline divnum(PNUMBER* pa, PNUMBER b, uint32_t radix, int32_t precision)
{ {
if ( b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0 ) if (b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0)
{ {
// b is not one // b is not one
_divnum( pa, b, radix, precision); _divnum(pa, b, radix, precision);
} }
else else
{ // But we do have to set the sign. { // But we do have to set the sign.
@ -392,7 +379,7 @@ void __inline divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
} }
} }
void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision) void _divnum(PNUMBER* pa, PNUMBER b, uint32_t radix, int32_t precision)
{ {
PNUMBER a = *pa; PNUMBER a = *pa;
int32_t thismax = precision + 2; int32_t thismax = precision + 2;
@ -411,7 +398,7 @@ void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
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;
PNUMBER rem = nullptr; PNUMBER rem = nullptr;
PNUMBER tmp = nullptr; PNUMBER tmp = nullptr;
DUPNUM(rem, a); DUPNUM(rem, a);
@ -489,7 +476,6 @@ void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
*pa = c; *pa = c;
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
// FUNCTION: equnum // FUNCTION: equnum
@ -503,26 +489,26 @@ void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool equnum( PNUMBER a, PNUMBER b ) bool equnum(PNUMBER a, PNUMBER b)
{ {
int32_t diff; int32_t diff;
MANTTYPE *pa; MANTTYPE* pa;
MANTTYPE *pb; MANTTYPE* pb;
int32_t cdigits; int32_t cdigits;
int32_t ccdigits; int32_t ccdigits;
MANTTYPE da; MANTTYPE da;
MANTTYPE db; MANTTYPE db;
diff = ( a->cdigit + a->exp ) - ( b->cdigit + b->exp ); diff = (a->cdigit + a->exp) - (b->cdigit + b->exp);
if ( diff < 0 ) 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 else
{ {
if ( diff > 0 ) 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;
@ -534,18 +520,16 @@ bool equnum( PNUMBER a, PNUMBER b )
pb = b->mant; pb = b->mant;
pa += a->cdigit - 1; pa += a->cdigit - 1;
pb += b->cdigit - 1; pb += b->cdigit - 1;
cdigits = max( a->cdigit, b->cdigit ); cdigits = max(a->cdigit, b->cdigit);
ccdigits = cdigits; ccdigits = cdigits;
// Loop over all digits until we run out of digits or there is a // Loop over all digits until we run out of digits or there is a
// difference in the digits. // difference in the digits.
for ( ;cdigits > 0; cdigits-- ) for (; cdigits > 0; cdigits--)
{ {
da = ( (cdigits > (ccdigits - a->cdigit) ) ? da = ((cdigits > (ccdigits - a->cdigit)) ? *pa-- : 0);
*pa-- : 0 ); db = ((cdigits > (ccdigits - b->cdigit)) ? *pb-- : 0);
db = ( (cdigits > (ccdigits - b->cdigit) ) ? if (da != db)
*pb-- : 0 );
if ( da != db )
{ {
return false; return false;
} }
@ -571,27 +555,26 @@ bool equnum( PNUMBER a, PNUMBER b )
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool lessnum( PNUMBER a, PNUMBER b ) bool lessnum(PNUMBER a, PNUMBER b)
{ {
int32_t diff; int32_t diff;
MANTTYPE *pa; MANTTYPE* pa;
MANTTYPE *pb; MANTTYPE* pb;
int32_t cdigits; int32_t cdigits;
int32_t ccdigits; int32_t ccdigits;
MANTTYPE da; MANTTYPE da;
MANTTYPE db; MANTTYPE db;
diff = (a->cdigit + a->exp) - (b->cdigit + b->exp);
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
return true; return true;
} }
else else
{ {
if ( diff > 0 ) if (diff > 0)
{ {
return false; return false;
} }
@ -601,18 +584,16 @@ bool lessnum( PNUMBER a, PNUMBER b )
pb = b->mant; pb = b->mant;
pa += a->cdigit - 1; pa += a->cdigit - 1;
pb += b->cdigit - 1; pb += b->cdigit - 1;
cdigits = max( a->cdigit, b->cdigit ); cdigits = max(a->cdigit, b->cdigit);
ccdigits = cdigits; ccdigits = cdigits;
for ( ;cdigits > 0; cdigits-- ) for (; cdigits > 0; cdigits--)
{ {
da = ( (cdigits > (ccdigits - a->cdigit) ) ? da = ((cdigits > (ccdigits - a->cdigit)) ? *pa-- : 0);
*pa-- : 0 ); db = ((cdigits > (ccdigits - b->cdigit)) ? *pb-- : 0);
db = ( (cdigits > (ccdigits - b->cdigit) ) ? diff = da - db;
*pb-- : 0 ); if (diff)
diff = da-db;
if ( diff )
{ {
return( diff < 0 ); return (diff < 0);
} }
} }
// In this case, they are equal. // In this case, they are equal.
@ -633,19 +614,19 @@ bool lessnum( PNUMBER a, PNUMBER b )
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool zernum( PNUMBER a ) bool zernum(PNUMBER a)
{ {
int32_t length; int32_t length;
MANTTYPE *pcha; MANTTYPE* pcha;
length = a->cdigit; length = a->cdigit;
pcha = a->mant; 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 ) while (length-- > 0)
{ {
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;

View file

@ -37,23 +37,23 @@ using namespace std;
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void gcdrat( PRAT *pa, int32_t precision) void gcdrat(PRAT* pa, int32_t precision)
{ {
PNUMBER pgcd= nullptr; PNUMBER pgcd = nullptr;
PRAT a= nullptr; PRAT a = nullptr;
a=*pa; a = *pa;
pgcd = gcd( a->pp, a->pq ); 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);
*pa=a; *pa = a;
RENORMALIZE(*pa); RENORMALIZE(*pa);
} }
@ -70,16 +70,16 @@ void gcdrat( PRAT *pa, int32_t precision)
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void fracrat( PRAT *pa , uint32_t radix, int32_t precision) void fracrat(PRAT* pa, uint32_t radix, int32_t precision)
{ {
// Only do the flatrat operation if number is nonzero. // Only do the flatrat operation if number is nonzero.
// and only if the bottom part is not one. // and only if the bottom part is not one.
if ( !zernum( (*pa)->pp ) && !equnum( (*pa)->pq, num_one ) ) if (!zernum((*pa)->pp) && !equnum((*pa)->pq, num_one))
{ {
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);
@ -98,26 +98,25 @@ void fracrat( PRAT *pa , uint32_t radix, int32_t precision)
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void mulrat( PRAT *pa, PRAT b, int32_t precision) void mulrat(PRAT* pa, 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
{ {
// If it is zero, blast a one in the denominator. // If it is zero, blast a one in the denominator.
DUPNUM( ((*pa)->pq), num_one ); DUPNUM(((*pa)->pq), num_one);
} }
#ifdef MULGCD #ifdef MULGCD
gcdrat( pa ); gcdrat(pa);
#endif #endif
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -133,44 +132,41 @@ void mulrat( PRAT *pa, PRAT b, int32_t precision)
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void divrat(PRAT* pa, PRAT b, int32_t precision)
void divrat( PRAT *pa, 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);
} }
else else
{ {
// Top is zero. // Top is zero.
if ( zerrat( b ) ) if (zerrat(b))
{ {
// 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
{ {
// 0/x make a unique 0. // 0/x make a unique 0.
DUPNUM( ((*pa)->pq), num_one ); DUPNUM(((*pa)->pq), num_one);
} }
} }
#ifdef DIVGCD #ifdef DIVGCD
gcdrat( pa ); gcdrat(pa);
#endif #endif
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -186,11 +182,11 @@ void divrat( PRAT *pa, PRAT b, int32_t precision)
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void subrat( PRAT *pa, PRAT b, int32_t precision) void subrat(PRAT* pa, PRAT b, int32_t precision)
{ {
b->pp->sign *= -1; b->pp->sign *= -1;
addrat( pa, b, precision); addrat(pa, b, precision);
b->pp->sign *= -1; b->pp->sign *= -1;
} }
@ -207,12 +203,12 @@ void subrat( PRAT *pa, PRAT b, int32_t precision)
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void addrat( PRAT *pa, PRAT b, int32_t precision) void addrat(PRAT* pa, PRAT b, int32_t precision)
{ {
PNUMBER bot= nullptr; PNUMBER bot = nullptr;
if ( equnum( (*pa)->pq, b->pq ) ) if (equnum((*pa)->pq, b->pq))
{ {
// Very special case, q's match., // Very special case, q's match.,
// make sure signs are involved in the calculation // make sure signs are involved in the calculation
@ -222,17 +218,17 @@ void addrat( PRAT *pa, 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);
@ -242,13 +238,10 @@ void addrat( PRAT *pa, PRAT b, int32_t precision)
} }
#ifdef ADDGCD #ifdef ADDGCD
gcdrat( pa ); gcdrat(pa);
#endif #endif
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// FUNCTION: rootrat // FUNCTION: rootrat
@ -262,11 +255,11 @@ void addrat( PRAT *pa, PRAT b, int32_t precision)
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void rootrat( PRAT *py, PRAT n, uint32_t radix, int32_t precision) void rootrat(PRAT* py, PRAT n, uint32_t radix, int32_t precision)
{ {
// Initialize 1/n // Initialize 1/n
PRAT oneovern= nullptr; PRAT oneovern = nullptr;
DUPRAT(oneovern,rat_one); DUPRAT(oneovern, rat_one);
divrat(&oneovern, n, precision); divrat(&oneovern, n, precision);
powrat(py, oneovern, radix, precision); powrat(py, oneovern, radix, precision);
@ -274,7 +267,6 @@ void rootrat( PRAT *py, PRAT n, uint32_t radix, int32_t precision)
destroyrat(oneovern); destroyrat(oneovern);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// FUNCTION: zerrat // FUNCTION: zerrat
@ -288,10 +280,8 @@ void rootrat( PRAT *py, PRAT n, uint32_t radix, int32_t precision)
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool zerrat( PRAT a ) bool zerrat(PRAT a)
{ {
return( zernum(a->pp) ); return (zernum(a->pp));
} }

View file

@ -4,481 +4,591 @@
#pragma once #pragma once
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_num_one= { inline const NUMBER init_num_one = { 1,
1,
1, 1,
0, 0,
{ 1,} {
}; 1,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_num_two= { inline const NUMBER init_num_two = { 1,
1,
1, 1,
0, 0,
{ 2,} {
}; 2,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_num_five= { inline const NUMBER init_num_five = { 1,
1,
1, 1,
0, 0,
{ 5,} {
}; 5,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_num_six= { inline const NUMBER init_num_six = { 1,
1,
1, 1,
0, 0,
{ 6,} {
}; 6,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_num_ten= { inline const NUMBER init_num_ten = { 1,
1,
1, 1,
0, 0,
{ 10,} {
}; 10,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_smallest = { inline const NUMBER init_p_rat_smallest = { 1,
1,
1, 1,
0, 0,
{ 1,} {
};
inline const NUMBER init_q_rat_smallest = {
1, 1,
} };
inline const NUMBER init_q_rat_smallest = { 1,
4, 4,
0, 0,
{ 0, 190439170, 901055854, 10097,} {
}; 0,
190439170,
901055854,
10097,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_negsmallest = { inline const NUMBER init_p_rat_negsmallest = { -1,
-1,
1, 1,
0, 0,
{ 1,} {
};
inline const NUMBER init_q_rat_negsmallest = {
1, 1,
} };
inline const NUMBER init_q_rat_negsmallest = { 1,
4, 4,
0, 0,
{ 0, 190439170, 901055854, 10097,} {
}; 0,
190439170,
901055854,
10097,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_pt_eight_five = { inline const NUMBER init_p_pt_eight_five = { 1,
1,
1, 1,
0, 0,
{ 85,} {
}; 85,
inline const NUMBER init_q_pt_eight_five = { } };
1, inline const NUMBER init_q_pt_eight_five = { 1,
1, 1,
0, 0,
{ 100,} {
}; 100,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_six = { inline const NUMBER init_p_rat_six = { 1,
1,
1, 1,
0, 0,
{ 6,} {
}; 6,
inline const NUMBER init_q_rat_six = { } };
1, inline const NUMBER init_q_rat_six = { 1,
1, 1,
0, 0,
{ 1,} {
}; 1,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_two = { inline const NUMBER init_p_rat_two = { 1,
1,
1, 1,
0, 0,
{ 2,} {
}; 2,
inline const NUMBER init_q_rat_two = { } };
1, inline const NUMBER init_q_rat_two = { 1,
1, 1,
0, 0,
{ 1,} {
}; 1,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_zero = { inline const NUMBER init_p_rat_zero = { 1,
1,
1, 1,
0, 0,
{ 0,} {
}; 0,
inline const NUMBER init_q_rat_zero = { } };
1, inline const NUMBER init_q_rat_zero = { 1,
1, 1,
0, 0,
{ 1,} {
}; 1,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_one = { inline const NUMBER init_p_rat_one = { 1,
1,
1, 1,
0, 0,
{ 1,} {
};
inline const NUMBER init_q_rat_one = {
1, 1,
} };
inline const NUMBER init_q_rat_one = { 1,
1, 1,
0, 0,
{ 1,} {
}; 1,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_neg_one = { inline const NUMBER init_p_rat_neg_one = { -1,
-1,
1, 1,
0, 0,
{ 1,} {
};
inline const NUMBER init_q_rat_neg_one = {
1, 1,
} };
inline const NUMBER init_q_rat_neg_one = { 1,
1, 1,
0, 0,
{ 1,} {
}; 1,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_half = { inline const NUMBER init_p_rat_half = { 1,
1,
1, 1,
0, 0,
{ 1,} {
};
inline const NUMBER init_q_rat_half = {
1, 1,
} };
inline const NUMBER init_q_rat_half = { 1,
1, 1,
0, 0,
{ 2,} {
}; 2,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_ten = { inline const NUMBER init_p_rat_ten = { 1,
1,
1, 1,
0, 0,
{ 10,} {
}; 10,
inline const NUMBER init_q_rat_ten = { } };
1, inline const NUMBER init_q_rat_ten = { 1,
1, 1,
0, 0,
{ 1,} {
}; 1,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_pi = { inline const NUMBER init_p_pi = { 1,
1,
6, 6,
0, 0,
{ 125527896, 283898350, 1960493936, 1672850762, 1288168272, 8,} {
}; 125527896,
inline const NUMBER init_q_pi = { 283898350,
1, 1960493936,
1672850762,
1288168272,
8,
} };
inline const NUMBER init_q_pi = { 1,
6, 6,
0, 0,
{ 1288380402, 1120116153, 1860424692, 1944118326, 1583591604, 2,} {
}; 1288380402,
1120116153,
1860424692,
1944118326,
1583591604,
2,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_two_pi = { inline const NUMBER init_p_two_pi = { 1,
1,
6, 6,
0, 0,
{ 251055792, 567796700, 1773504224, 1198217877, 428852897, 17,} {
}; 251055792,
inline const NUMBER init_q_two_pi = { 567796700,
1, 1773504224,
1198217877,
428852897,
17,
} };
inline const NUMBER init_q_two_pi = { 1,
6, 6,
0, 0,
{ 1288380402, 1120116153, 1860424692, 1944118326, 1583591604, 2,} {
}; 1288380402,
1120116153,
1860424692,
1944118326,
1583591604,
2,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_pi_over_two = { inline const NUMBER init_p_pi_over_two = { 1,
1,
6, 6,
0, 0,
{ 125527896, 283898350, 1960493936, 1672850762, 1288168272, 8,} {
}; 125527896,
inline const NUMBER init_q_pi_over_two = { 283898350,
1, 1960493936,
1672850762,
1288168272,
8,
} };
inline const NUMBER init_q_pi_over_two = { 1,
6, 6,
0, 0,
{ 429277156, 92748659, 1573365737, 1740753005, 1019699561, 5,} {
}; 429277156,
92748659,
1573365737,
1740753005,
1019699561,
5,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_one_pt_five_pi = { inline const NUMBER init_p_one_pt_five_pi = { 1,
1,
6, 6,
0, 0,
{ 1241201312, 270061909, 1051574664, 1924965045, 1340320627, 70,} {
}; 1241201312,
inline const NUMBER init_q_one_pt_five_pi = { 270061909,
1, 1051574664,
1924965045,
1340320627,
70,
} };
inline const NUMBER init_q_one_pt_five_pi = { 1,
6, 6,
0, 0,
{ 1579671539, 1837970263, 1067644340, 523549916, 2119366659, 14,} {
}; 1579671539,
1837970263,
1067644340,
523549916,
2119366659,
14,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_e_to_one_half = { inline const NUMBER init_p_e_to_one_half = { 1,
1,
6, 6,
0, 0,
{ 256945612, 216219427, 223516738, 477442596, 581063757, 23,} {
}; 256945612,
inline const NUMBER init_q_e_to_one_half = { 216219427,
1, 223516738,
477442596,
581063757,
23,
} };
inline const NUMBER init_q_e_to_one_half = { 1,
6, 6,
0, 0,
{ 1536828363, 698484484, 1127331835, 224219346, 245499408, 14,} {
}; 1536828363,
698484484,
1127331835,
224219346,
245499408,
14,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_exp = { inline const NUMBER init_p_rat_exp = { 1,
1,
6, 6,
0, 0,
{ 943665199, 1606559160, 1094967530, 1759391384, 1671799163, 1123581,} {
}; 943665199,
inline const NUMBER init_q_rat_exp = { 1606559160,
1, 1094967530,
1759391384,
1671799163,
1123581,
} };
inline const NUMBER init_q_rat_exp = { 1,
6, 6,
0, 0,
{ 879242208, 2022880100, 617392930, 1374929092, 1367479163, 413342,} {
}; 879242208,
2022880100,
617392930,
1374929092,
1367479163,
413342,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_ln_ten = { inline const NUMBER init_p_ln_ten = { 1,
1,
6, 6,
0, 0,
{ 2086268922, 165794492, 1416063951, 1851428830, 1893239400, 65366841,} {
}; 2086268922,
inline const NUMBER init_q_ln_ten = { 165794492,
1, 1416063951,
1851428830,
1893239400,
65366841,
} };
inline const NUMBER init_q_ln_ten = { 1,
6, 6,
0, 0,
{ 26790652, 564532679, 783998273, 216030448, 1564709968, 28388458,} {
}; 26790652,
564532679,
783998273,
216030448,
1564709968,
28388458,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_ln_two = { inline const NUMBER init_p_ln_two = { 1,
1,
6, 6,
0, 0,
{ 1789230241, 1057927868, 715399197, 908801241, 1411265331, 3,} {
}; 1789230241,
inline const NUMBER init_q_ln_two = { 1057927868,
1, 715399197,
908801241,
1411265331,
3,
} };
inline const NUMBER init_q_ln_two = { 1,
6, 6,
0, 0,
{ 1559869847, 1930657510, 1228561531, 219003871, 593099283, 5,} {
}; 1559869847,
1930657510,
1228561531,
219003871,
593099283,
5,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rad_to_deg = { inline const NUMBER init_p_rad_to_deg = { 1,
1,
6, 6,
0, 0,
{ 2127722024, 1904928383, 2016479213, 2048947859, 1578647346, 492,} {
}; 2127722024,
inline const NUMBER init_q_rad_to_deg = { 1904928383,
1, 2016479213,
2048947859,
1578647346,
492,
} };
inline const NUMBER init_q_rad_to_deg = { 1,
6, 6,
0, 0,
{ 125527896, 283898350, 1960493936, 1672850762, 1288168272, 8,} {
}; 125527896,
283898350,
1960493936,
1672850762,
1288168272,
8,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rad_to_grad = { inline const NUMBER init_p_rad_to_grad = { 1,
1,
6, 6,
0, 0,
{ 2125526288, 684931327, 570267400, 129125085, 1038224725, 547,} {
}; 2125526288,
inline const NUMBER init_q_rad_to_grad = { 684931327,
1, 570267400,
129125085,
1038224725,
547,
} };
inline const NUMBER init_q_rad_to_grad = { 1,
6, 6,
0, 0,
{ 125527896, 283898350, 1960493936, 1672850762, 1288168272, 8,} {
}; 125527896,
283898350,
1960493936,
1672850762,
1288168272,
8,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_qword = { inline const NUMBER init_p_rat_qword = { 1,
1,
3, 3,
0, 0,
{ 2147483647, 2147483647, 3,} {
}; 2147483647,
inline const NUMBER init_q_rat_qword = { 2147483647,
1, 3,
} };
inline const NUMBER init_q_rat_qword = { 1,
1, 1,
0, 0,
{ 1,} {
};
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_dword = {
1, 1,
} };
// Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_dword = { 1,
2, 2,
0, 0,
{ 2147483647, 1,} {
}; 2147483647,
inline const NUMBER init_q_rat_dword = {
1, 1,
} };
inline const NUMBER init_q_rat_dword = { 1,
1, 1,
0, 0,
{ 1,} {
}; 1,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_max_i32 = { inline const NUMBER init_p_rat_max_i32 = { 1,
1,
1, 1,
0, 0,
{ 2147483647,} {
}; 2147483647,
inline const NUMBER init_q_rat_max_i32 = { } };
1, inline const NUMBER init_q_rat_max_i32 = { 1,
1, 1,
0, 0,
{ 1,} {
}; 1,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_min_i32 = { inline const NUMBER init_p_rat_min_i32 = { -1,
-1,
2, 2,
0, 0,
{ 0, 1,} {
}; 0,
inline const NUMBER init_q_rat_min_i32 = {
1, 1,
} };
inline const NUMBER init_q_rat_min_i32 = { 1,
1, 1,
0, 0,
{ 1,} {
}; 1,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_word = { inline const NUMBER init_p_rat_word = { 1,
1,
1, 1,
0, 0,
{ 65535,} {
}; 65535,
inline const NUMBER init_q_rat_word = { } };
1, inline const NUMBER init_q_rat_word = { 1,
1, 1,
0, 0,
{ 1,} {
}; 1,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_byte = { inline const NUMBER init_p_rat_byte = { 1,
1,
1, 1,
0, 0,
{ 255,} {
}; 255,
inline const NUMBER init_q_rat_byte = { } };
1, inline const NUMBER init_q_rat_byte = { 1,
1, 1,
0, 0,
{ 1,} {
}; 1,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_400 = { inline const NUMBER init_p_rat_400 = { 1,
1,
1, 1,
0, 0,
{ 400,} {
}; 400,
inline const NUMBER init_q_rat_400 = { } };
1, inline const NUMBER init_q_rat_400 = { 1,
1, 1,
0, 0,
{ 1,} {
}; 1,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_360 = { inline const NUMBER init_p_rat_360 = { 1,
1,
1, 1,
0, 0,
{ 360,} {
}; 360,
inline const NUMBER init_q_rat_360 = { } };
1, inline const NUMBER init_q_rat_360 = { 1,
1, 1,
0, 0,
{ 1,} {
}; 1,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_200 = { inline const NUMBER init_p_rat_200 = { 1,
1,
1, 1,
0, 0,
{ 200,} {
}; 200,
inline const NUMBER init_q_rat_200 = { } };
1, inline const NUMBER init_q_rat_200 = { 1,
1, 1,
0, 0,
{ 1,} {
}; 1,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_180 = { inline const NUMBER init_p_rat_180 = { 1,
1,
1, 1,
0, 0,
{ 180,} {
}; 180,
inline const NUMBER init_q_rat_180 = { } };
1, inline const NUMBER init_q_rat_180 = { 1,
1, 1,
0, 0,
{ 1,} {
}; 1,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_max_exp = { inline const NUMBER init_p_rat_max_exp = { 1,
1,
1, 1,
0, 0,
{ 100000,} {
}; 100000,
inline const NUMBER init_q_rat_max_exp = { } };
1, inline const NUMBER init_q_rat_max_exp = { 1,
1, 1,
0, 0,
{ 1,} {
}; 1,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_min_exp = { inline const NUMBER init_p_rat_min_exp = { -1,
-1,
1, 1,
0, 0,
{ 100000,} {
}; 100000,
inline const NUMBER init_q_rat_min_exp = { } };
1, inline const NUMBER init_q_rat_min_exp = { 1,
1, 1,
0, 0,
{ 1,} {
}; 1,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_max_fact = { inline const NUMBER init_p_rat_max_fact = { 1,
1,
1, 1,
0, 0,
{ 3249, } {
}; 3249,
inline const NUMBER init_q_rat_max_fact = { } };
1, inline const NUMBER init_q_rat_max_fact = { 1,
1, 1,
0, 0,
{ 1, } {
}; 1,
} };
// Autogenerated by _dumprawrat in support.cpp // Autogenerated by _dumprawrat in support.cpp
inline const NUMBER init_p_rat_min_fact = { inline const NUMBER init_p_rat_min_fact = { -1,
-1,
1, 1,
0, 0,
{ 1000, } {
}; 1000,
inline const NUMBER init_q_rat_min_fact = { } };
1, inline const NUMBER init_q_rat_min_fact = { 1,
1, 1,
0, 0,
{ 1, } {
}; 1,
} };

View file

@ -23,7 +23,7 @@
#include <cstring> // for memmove #include <cstring> // for memmove
#include <sal.h> // for SAL #include <sal.h> // for SAL
static constexpr uint32_t BASEXPWR = 31L;// Internal log2(BASEX) static constexpr uint32_t BASEXPWR = 31L; // Internal log2(BASEX)
static constexpr uint32_t BASEX = 0x80000000; // Internal radix used in calculations, hope to raise static constexpr uint32_t BASEX = 0x80000000; // Internal radix used in calculations, hope to raise
// this to 2^32 after solving scaling problems with // this to 2^32 after solving scaling problems with
// overflow detection esp. in mul // overflow detection esp. in mul
@ -31,14 +31,16 @@ static constexpr uint32_t BASEX = 0x80000000; // Internal radix used in calculat
typedef uint32_t MANTTYPE; typedef uint32_t MANTTYPE;
typedef uint64_t TWO_MANTTYPE; typedef uint64_t TWO_MANTTYPE;
enum eNUMOBJ_FMT { enum eNUMOBJ_FMT
{
FMT_FLOAT, // returns floating point, or exponential if number is too big FMT_FLOAT, // returns floating point, or exponential if number is too big
FMT_SCIENTIFIC, // always returns scientific notation FMT_SCIENTIFIC, // always returns scientific notation
FMT_ENGINEERING // always returns engineering notation such that exponent is a multiple of 3 FMT_ENGINEERING // always returns engineering notation such that exponent is a multiple of 3
}; };
enum eANGLE_TYPE { enum eANGLE_TYPE
{
ANGLE_DEG, // Calculate trig using 360 degrees per revolution ANGLE_DEG, // Calculate trig using 360 degrees per revolution
ANGLE_RAD, // Calculate trig using 2 pi radians per revolution ANGLE_RAD, // Calculate trig using 2 pi radians per revolution
ANGLE_GRAD // Calculate trig using 400 gradients per revolution ANGLE_GRAD // Calculate trig using 400 gradients per revolution
@ -55,7 +57,7 @@ typedef enum eANGLE_TYPE ANGLE_TYPE;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#pragma warning(push) #pragma warning(push)
#pragma warning(disable:4200) // nonstandard extension used : zero-sized array in struct/union #pragma warning(disable : 4200) // nonstandard extension used : zero-sized array in struct/union
typedef struct _number typedef struct _number
{ {
int32_t sign; // The sign of the mantissa, +1, or -1 int32_t sign; // The sign of the mantissa, +1, or -1
@ -69,7 +71,6 @@ typedef struct _number
} NUMBER, *PNUMBER, **PPNUMBER; } NUMBER, *PNUMBER, **PPNUMBER;
#pragma warning(pop) #pragma warning(pop)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// RAT type is a representation radix on 2 NUMBER types. // RAT type is a representation radix on 2 NUMBER types.
@ -78,10 +79,10 @@ typedef struct _number
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
typedef struct _rat typedef struct _rat
{ {
PNUMBER pp; PNUMBER pp;
PNUMBER pq; PNUMBER pq;
} RAT, *PRAT; } RAT, *PRAT;
static constexpr uint32_t MAX_LONG_SIZE = 33; // Base 2 requires 32 'digits' static constexpr uint32_t MAX_LONG_SIZE = 33; // Base 2 requires 32 'digits'
@ -135,27 +136,34 @@ extern PRAT rat_max_i32;
extern PRAT rat_min_i32; extern PRAT rat_min_i32;
// DUPNUM Duplicates a number taking care of allocation and internals // DUPNUM Duplicates a number taking care of allocation and internals
#define DUPNUM(a,b) destroynum(a);createnum( a, (b)->cdigit );_dupnum(a, b); #define DUPNUM(a, b) \
destroynum(a); \
createnum(a, (b)->cdigit); \
_dupnum(a, b);
// DUPRAT Duplicates a rational taking care of allocation and internals // DUPRAT Duplicates a rational taking care of allocation and internals
#define DUPRAT(a,b) destroyrat(a);createrat(a);DUPNUM((a)->pp,(b)->pp);DUPNUM((a)->pq,(b)->pq); #define DUPRAT(a, b) \
destroyrat(a); \
createrat(a); \
DUPNUM((a)->pp, (b)->pp); \
DUPNUM((a)->pq, (b)->pq);
// LOG*RADIX calculates the integral portion of the log of a number in // LOG*RADIX calculates the integral portion of the log of a number in
// the base currently being used, only accurate to within g_ratio // the base currently being used, only accurate to within g_ratio
#define LOGNUMRADIX(pnum) (((pnum)->cdigit+(pnum)->exp)*g_ratio) #define LOGNUMRADIX(pnum) (((pnum)->cdigit + (pnum)->exp) * g_ratio)
#define LOGRATRADIX(prat) (LOGNUMRADIX((prat)->pp)-LOGNUMRADIX((prat)->pq)) #define LOGRATRADIX(prat) (LOGNUMRADIX((prat)->pp) - LOGNUMRADIX((prat)->pq))
// LOG*2 calculates the integral portion of the log of a number in // LOG*2 calculates the integral portion of the log of a number in
// the internal base being used, only accurate to within g_ratio // the internal base being used, only accurate to within g_ratio
#define LOGNUM2(pnum) ((pnum)->cdigit+(pnum)->exp) #define LOGNUM2(pnum) ((pnum)->cdigit + (pnum)->exp)
#define LOGRAT2(prat) (LOGNUM2((prat)->pp)-LOGNUM2((prat)->pq)) #define LOGRAT2(prat) (LOGNUM2((prat)->pp) - LOGNUM2((prat)->pq))
// SIGN returns the sign of the rational // SIGN returns the sign of the rational
#define SIGN(prat) ((prat)->pp->sign*(prat)->pq->sign) #define SIGN(prat) ((prat)->pp->sign * (prat)->pq->sign)
#if defined( DEBUG_RATPAK ) #if defined(DEBUG_RATPAK)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// Debug versions of rational number creation and destruction routines. // Debug versions of rational number creation and destruction routines.
@ -163,37 +171,39 @@ extern PRAT rat_min_i32;
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#define createrat(y) (y)=_createrat(); \ #define createrat(y) \
{ \ (y) = _createrat(); \
{ \
std::wstringstream outputString; \ std::wstringstream outputString; \
outputString << "createrat " << y << " " << # y << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \ outputString << "createrat " << y << " " << #y << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
OutputDebugString(outputString.str().c_str()); \ OutputDebugString(outputString.str().c_str()); \
} }
#define destroyrat(x) \ #define destroyrat(x) \
{ \ { \
std::wstringstream outputString; \ std::wstringstream outputString; \
outputString << "destroyrat " << x << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \ outputString << "destroyrat " << x << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
OutputDebugString(outputString.str().c_str()); \ OutputDebugString(outputString.str().c_str()); \
} \ } \
_destroyrat(x),(x)=nullptr _destroyrat(x), (x) = nullptr
#define createnum(y,x) (y)=_createnum(x); \ #define createnum(y, x) \
{ \ (y) = _createnum(x); \
{ \
std::wstringstream outputString; \ std::wstringstream outputString; \
outputString << "createnum " << y << " " << # y << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \ outputString << "createnum " << y << " " << #y << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
OutputDebugString(outputString.str().c_str()); \ OutputDebugString(outputString.str().c_str()); \
} }
#define destroynum(x) \ #define destroynum(x) \
{ \ { \
std::wstringstream outputString; \ std::wstringstream outputString; \
outputString << "destroynum " << x << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \ outputString << "destroynum " << x << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
OutputDebugString(outputString.str().c_str()); \ OutputDebugString(outputString.str().c_str()); \
} \ } \
_destroynum(x),(x)=nullptr _destroynum(x), (x) = nullptr
#else #else
#define createrat(y) (y)=_createrat() #define createrat(y) (y) = _createrat()
#define destroyrat(x) _destroyrat(x),(x)=nullptr #define destroyrat(x) _destroyrat(x), (x) = nullptr
#define createnum(y,x) (y)=_createnum(x) #define createnum(y, x) (y) = _createnum(x)
#define destroynum(x) _destroynum(x),(x)=nullptr #define destroynum(x) _destroynum(x), (x) = nullptr
#endif #endif
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -204,40 +214,47 @@ _destroynum(x),(x)=nullptr
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// RENORMALIZE, gets the exponents non-negative. // RENORMALIZE, gets the exponents non-negative.
#define RENORMALIZE(x) if ( (x)->pp->exp < 0 ) { \ #define RENORMALIZE(x) \
if ((x)->pp->exp < 0) \
{ \
(x)->pq->exp -= (x)->pp->exp; \ (x)->pq->exp -= (x)->pp->exp; \
(x)->pp->exp = 0; \ (x)->pp->exp = 0; \
} \ } \
if ( (x)->pq->exp < 0 ) { \ if ((x)->pq->exp < 0) \
{ \
(x)->pp->exp -= (x)->pq->exp; \ (x)->pp->exp -= (x)->pq->exp; \
(x)->pq->exp = 0; \ (x)->pq->exp = 0; \
} }
// TRIMNUM ASSUMES the number is in radix form NOT INTERNAL BASEX!!! // TRIMNUM ASSUMES the number is in radix form NOT INTERNAL BASEX!!!
#define TRIMNUM(x, precision) if ( !g_ftrueinfinite ) { \ #define TRIMNUM(x, precision) \
int32_t trim = (x)->cdigit - precision-g_ratio;\ if (!g_ftrueinfinite) \
if ( trim > 1 ) \
{ \ { \
memmove( (x)->mant, &((x)->mant[trim]), sizeof(MANTTYPE)*((x)->cdigit-trim) ); \ int32_t trim = (x)->cdigit - precision - g_ratio; \
if (trim > 1) \
{ \
memmove((x)->mant, &((x)->mant[trim]), sizeof(MANTTYPE) * ((x)->cdigit - trim)); \
(x)->cdigit -= trim; \ (x)->cdigit -= trim; \
(x)->exp += trim; \ (x)->exp += trim; \
} \ } \
} }
// TRIMTOP ASSUMES the number is in INTERNAL BASEX!!! // TRIMTOP ASSUMES the number is in INTERNAL BASEX!!!
#define TRIMTOP(x, precision) if ( !g_ftrueinfinite ) { \ #define TRIMTOP(x, precision) \
int32_t trim = (x)->pp->cdigit - (precision/g_ratio) - 2;\ if (!g_ftrueinfinite) \
if ( trim > 1 ) \
{ \ { \
memmove( (x)->pp->mant, &((x)->pp->mant[trim]), sizeof(MANTTYPE)*((x)->pp->cdigit-trim) ); \ int32_t trim = (x)->pp->cdigit - (precision / g_ratio) - 2; \
if (trim > 1) \
{ \
memmove((x)->pp->mant, &((x)->pp->mant[trim]), sizeof(MANTTYPE) * ((x)->pp->cdigit - trim)); \
(x)->pp->cdigit -= trim; \ (x)->pp->cdigit -= trim; \
(x)->pp->exp += trim; \ (x)->pp->exp += trim; \
} \ } \
trim = std::min((x)->pp->exp,(x)->pq->exp);\ trim = std::min((x)->pp->exp, (x)->pq->exp); \
(x)->pp->exp -= trim;\ (x)->pp->exp -= trim; \
(x)->pq->exp -= trim;\ (x)->pq->exp -= trim; \
} }
#define SMALL_ENOUGH_RAT(a, precision) (zernum((a)->pp) || ( ( ( (a)->pq->cdigit + (a)->pq->exp ) - ( (a)->pp->cdigit + (a)->pp->exp ) - 1 ) * g_ratio > precision ) ) #define SMALL_ENOUGH_RAT(a, precision) (zernum((a)->pp) || ((((a)->pq->cdigit + (a)->pq->exp) - ((a)->pp->cdigit + (a)->pp->exp) - 1) * g_ratio > precision))
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
@ -246,50 +263,55 @@ memmove( (x)->pp->mant, &((x)->pp->mant[trim]), sizeof(MANTTYPE)*((x)->pp->cdigi
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#define CREATETAYLOR() PRAT xx=nullptr;\ #define CREATETAYLOR() \
PNUMBER n2=nullptr; \ PRAT xx = nullptr; \
PRAT pret=nullptr; \ PNUMBER n2 = nullptr; \
PRAT thisterm=nullptr; \ PRAT pret = nullptr; \
DUPRAT(xx,*px); \ PRAT thisterm = nullptr; \
mulrat(&xx,*px, precision); \ DUPRAT(xx, *px); \
mulrat(&xx, *px, precision); \
createrat(pret); \ createrat(pret); \
pret->pp=i32tonum( 0L, BASEX ); \ pret->pp = i32tonum(0L, BASEX); \
pret->pq=i32tonum( 0L, BASEX ); pret->pq = i32tonum(0L, BASEX);
#define DESTROYTAYLOR() destroynum( n2 ); \ #define DESTROYTAYLOR() \
destroyrat( xx );\ destroynum(n2); \
destroyrat( thisterm );\ destroyrat(xx); \
destroyrat( *px );\ destroyrat(thisterm); \
trimit(&pret, precision);\ destroyrat(*px); \
*px=pret; trimit(&pret, precision); \
*px = pret;
// INC(a) is the rational equivalent of a++ // INC(a) is the rational equivalent of a++
// Check to see if we can avoid doing this the hard way. // Check to see if we can avoid doing this the hard way.
#define INC(a) if ( (a)->mant[0] < BASEX - 1 ) \ #define INC(a) \
if ((a)->mant[0] < BASEX - 1) \
{ \ { \
(a)->mant[0]++; \ (a)->mant[0]++; \
} \ } \
else \ else \
{ \ { \
addnum( &(a), num_one, BASEX); \ addnum(&(a), num_one, BASEX); \
} }
#define MSD(x) ((x)->mant[(x)->cdigit-1]) #define MSD(x) ((x)->mant[(x)->cdigit - 1])
// MULNUM(b) is the rational equivalent of thisterm *= b where thisterm is // MULNUM(b) is the rational equivalent of thisterm *= b where thisterm is
// a rational and b is a number, NOTE this is a mixed type operation for // a rational and b is a number, NOTE this is a mixed type operation for
// efficiency reasons. // efficiency reasons.
#define MULNUM(b) mulnumx( &(thisterm->pp), b); #define MULNUM(b) mulnumx(&(thisterm->pp), b);
// DIVNUM(b) is the rational equivalent of thisterm /= b where thisterm is // DIVNUM(b) is the rational equivalent of thisterm /= b where thisterm is
// a rational and b is a number, NOTE this is a mixed type operation for // a rational and b is a number, NOTE this is a mixed type operation for
// efficiency reasons. // efficiency reasons.
#define DIVNUM(b) mulnumx( &(thisterm->pq), b); #define DIVNUM(b) mulnumx(&(thisterm->pq), b);
// NEXTTERM(p,d) is the rational equivalent of // NEXTTERM(p,d) is the rational equivalent of
// thisterm *= p // thisterm *= p
// d <d is usually an expansion of operations to get thisterm updated.> // d <d is usually an expansion of operations to get thisterm updated.>
// pret += thisterm // pret += thisterm
#define NEXTTERM(p,d,precision) mulrat(&thisterm,p,precision);d addrat( &pret, thisterm, precision ) #define NEXTTERM(p, d, precision) \
mulrat(&thisterm, p, precision); \
d addrat(&pret, thisterm, precision)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
@ -315,10 +337,10 @@ extern void SetDecimalSeparator(wchar_t decimalSeparator);
// Call whenever either radix or precision changes, is smarter about recalculating constants. // Call whenever either radix or precision changes, is smarter about recalculating constants.
extern void ChangeConstants(uint32_t radix, int32_t precision); extern void ChangeConstants(uint32_t radix, int32_t precision);
extern bool equnum(_In_ PNUMBER a, _In_ PNUMBER b ); // returns true of a == b extern bool equnum(_In_ PNUMBER a, _In_ PNUMBER b); // returns true of a == b
extern bool lessnum(_In_ PNUMBER a, _In_ PNUMBER b ); // returns true of a < b extern bool lessnum(_In_ PNUMBER a, _In_ PNUMBER b); // returns true of a < b
extern bool zernum(_In_ PNUMBER a ); // returns true of a == 0 extern bool zernum(_In_ PNUMBER a); // returns true of a == 0
extern bool zerrat(_In_ PRAT a ); // returns true if a == 0/q extern bool zerrat(_In_ PRAT a); // returns true if a == 0/q
extern std::wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_t precision); extern std::wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_t precision);
// returns a text representation of a PRAT // returns a text representation of a PRAT
@ -328,16 +350,18 @@ 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
extern void flatrat(_Inout_ PRAT& prat, uint32_t radix, int32_t precision); extern void flatrat(_Inout_ PRAT& prat, uint32_t radix, int32_t precision);
extern int32_t numtoi32(_In_ PNUMBER pnum, uint32_t radix ); extern int32_t numtoi32(_In_ PNUMBER pnum, uint32_t radix);
extern int32_t rattoi32(_In_ PRAT prat, uint32_t radix, int32_t precision); extern int32_t rattoi32(_In_ PRAT prat, uint32_t radix, int32_t precision);
uint64_t rattoUi64(_In_ PRAT prat, uint32_t radix, int32_t precision); uint64_t rattoUi64(_In_ PRAT prat, uint32_t radix, int32_t precision);
extern PNUMBER _createnum(_In_ uint32_t size ); // returns an empty number structure with size digits extern PNUMBER _createnum(_In_ uint32_t size); // returns an empty number structure with size digits
extern PNUMBER nRadixxtonum(_In_ PNUMBER a, uint32_t radix, int32_t precision); extern PNUMBER nRadixxtonum(_In_ PNUMBER a, uint32_t radix, int32_t precision);
extern PNUMBER gcd(_In_ PNUMBER a, _In_ PNUMBER b ); extern PNUMBER gcd(_In_ PNUMBER a, _In_ PNUMBER b);
extern PNUMBER StringToNumber(std::wstring_view numberString, uint32_t radix, int32_t precision); // takes a text representation of a number and returns a number. extern PNUMBER StringToNumber(std::wstring_view numberString, uint32_t radix,
int32_t precision); // takes a text representation of a number and returns a number.
// takes a text representation of a number as a mantissa with sign and an exponent with sign. // takes a text representation of a number as a mantissa with sign and an exponent with sign.
extern PRAT StringToRat(bool mantissaIsNegative, std::wstring_view mantissa, bool exponentIsNegative, std::wstring_view exponent, uint32_t radix, int32_t precision); extern PRAT StringToRat(bool mantissaIsNegative, std::wstring_view mantissa, bool exponentIsNegative, std::wstring_view exponent, uint32_t radix,
int32_t precision);
extern PNUMBER i32factnum(int32_t ini32, uint32_t radix); extern PNUMBER i32factnum(int32_t ini32, uint32_t radix);
extern PNUMBER i32prodnum(int32_t start, int32_t stop, uint32_t radix); extern PNUMBER i32prodnum(int32_t start, int32_t stop, uint32_t radix);
@ -346,119 +370,119 @@ extern PNUMBER Ui32tonum(uint32_t ini32, uint32_t radix);
extern PNUMBER numtonRadixx(PNUMBER a, uint32_t radix); extern PNUMBER numtonRadixx(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(void);
// 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
extern void acosanglerat( _Inout_ PRAT *px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision); extern void acosanglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
// returns a new rat structure with the acosh of x->p/x->q // returns a new rat structure with the acosh of x->p/x->q
extern void acoshrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision); extern void acoshrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the acos of x->p/x->q // returns a new rat structure with the acos of x->p/x->q
extern void acosrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision); extern void acosrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the asin of x->p/x->q taking into account // returns a new rat structure with the asin of x->p/x->q taking into account
// angle type // angle type
extern void asinanglerat( _Inout_ PRAT *px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision); extern void asinanglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
extern void asinhrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision); extern void asinhrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the asinh of x->p/x->q // returns a new rat structure with the asinh of x->p/x->q
// returns a new rat structure with the asin of x->p/x->q // returns a new rat structure with the asin of x->p/x->q
extern void asinrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision); extern void asinrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the atan of x->p/x->q taking into account // returns a new rat structure with the atan of x->p/x->q taking into account
// angle type // angle type
extern void atananglerat( _Inout_ PRAT *px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision); extern void atananglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
// returns a new rat structure with the atanh of x->p/x->q // returns a new rat structure with the atanh of x->p/x->q
extern void atanhrat( _Inout_ PRAT *px, int32_t precision); extern void atanhrat(_Inout_ PRAT* px, int32_t precision);
// returns a new rat structure with the atan of x->p/x->q // returns a new rat structure with the atan of x->p/x->q
extern void atanrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision); extern void atanrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the cosh of x->p/x->q // returns a new rat structure with the cosh of x->p/x->q
extern void coshrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision); extern void coshrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the cos of x->p/x->q // returns a new rat structure with the cos of x->p/x->q
extern void cosrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision); extern void cosrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the cos of x->p/x->q taking into account // returns a new rat structure with the cos of x->p/x->q taking into account
// angle type // angle type
extern void cosanglerat( _Inout_ PRAT *px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision); extern void cosanglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
// returns a new rat structure with the exp of x->p/x->q this should not be called explicitly. // returns a new rat structure with the exp of x->p/x->q this should not be called explicitly.
extern void _exprat( _Inout_ PRAT *px, int32_t precision); extern void _exprat(_Inout_ PRAT* px, int32_t precision);
// returns a new rat structure with the exp of x->p/x->q // returns a new rat structure with the exp of x->p/x->q
extern void exprat( _Inout_ PRAT *px, uint32_t radix, int32_t precision); extern void exprat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the log base 10 of x->p/x->q // returns a new rat structure with the log base 10 of x->p/x->q
extern void log10rat( _Inout_ PRAT *px, int32_t precision); extern void log10rat(_Inout_ PRAT* px, int32_t precision);
// returns a new rat structure with the natural log of x->p/x->q // returns a new rat structure with the natural log of x->p/x->q
extern void lograt( _Inout_ PRAT *px, int32_t precision); extern void lograt(_Inout_ PRAT* px, int32_t precision);
extern PRAT i32torat( int32_t ini32 ); extern PRAT i32torat(int32_t ini32);
extern PRAT Ui32torat( uint32_t inui32 ); extern PRAT Ui32torat(uint32_t inui32);
extern PRAT numtorat( _In_ PNUMBER pin, uint32_t radix); extern PRAT numtorat(_In_ PNUMBER pin, uint32_t radix);
extern void sinhrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision); extern void sinhrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
extern void sinrat( _Inout_ PRAT *px ); extern void sinrat(_Inout_ PRAT* px);
// returns a new rat structure with the sin of x->p/x->q taking into account // returns a new rat structure with the sin of x->p/x->q taking into account
// angle type // angle type
extern void sinanglerat( _Inout_ PRAT *px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision); extern void sinanglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
extern void tanhrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision); extern void tanhrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
extern void tanrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision); extern void tanrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
// returns a new rat structure with the tan of x->p/x->q taking into account // returns a new rat structure with the tan of x->p/x->q taking into account
// angle type // angle type
extern void tananglerat( _Inout_ PRAT *px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision); extern void tananglerat(_Inout_ PRAT* px, ANGLE_TYPE 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* const src);
extern void _destroynum( _In_ PNUMBER pnum ); extern void _destroynum(_In_ PNUMBER pnum);
extern void _destroyrat( _In_ PRAT prat ); extern void _destroyrat(_In_ PRAT prat);
extern void addnum( _Inout_ PNUMBER *pa, _In_ PNUMBER b, uint32_t radix); extern void addnum(_Inout_ PNUMBER* pa, _In_ PNUMBER b, uint32_t radix);
extern void addrat( _Inout_ PRAT *pa, _In_ PRAT b, int32_t precision); extern void addrat(_Inout_ PRAT* pa, _In_ PRAT b, int32_t precision);
extern void andrat( _Inout_ PRAT *pa, _In_ PRAT b, uint32_t radix, int32_t precision); extern void andrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void divnum( _Inout_ PNUMBER *pa, _In_ PNUMBER b, uint32_t radix, int32_t precision); extern void divnum(_Inout_ PNUMBER* pa, _In_ PNUMBER b, uint32_t radix, int32_t precision);
extern void divnumx( _Inout_ PNUMBER *pa, _In_ PNUMBER b, int32_t precision); extern void divnumx(_Inout_ PNUMBER* pa, _In_ PNUMBER b, int32_t precision);
extern void divrat( _Inout_ PRAT *pa, _In_ PRAT b, int32_t precision); extern void divrat(_Inout_ PRAT* pa, _In_ PRAT b, int32_t precision);
extern void fracrat( _Inout_ PRAT *pa , uint32_t radix, int32_t precision); extern void fracrat(_Inout_ PRAT* pa, uint32_t radix, int32_t precision);
extern void factrat( _Inout_ PRAT *pa, uint32_t radix, int32_t precision); extern void factrat(_Inout_ PRAT* pa, uint32_t radix, int32_t precision);
extern void remrat(_Inout_ PRAT *pa, _In_ PRAT b); extern void remrat(_Inout_ PRAT* pa, _In_ PRAT b);
extern void modrat(_Inout_ PRAT *pa, _In_ PRAT b); extern void modrat(_Inout_ PRAT* pa, _In_ PRAT b);
extern void gcdrat( _Inout_ PRAT *pa, int32_t precision); extern void gcdrat(_Inout_ PRAT* pa, int32_t precision);
extern void intrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision); extern void intrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
extern void mulnum( _Inout_ PNUMBER *pa, _In_ PNUMBER b, uint32_t radix); extern void mulnum(_Inout_ PNUMBER* pa, _In_ PNUMBER b, uint32_t radix);
extern void mulnumx( _Inout_ PNUMBER *pa, _In_ PNUMBER b ); extern void mulnumx(_Inout_ PNUMBER* pa, _In_ PNUMBER b);
extern void mulrat( _Inout_ PRAT *pa, _In_ PRAT b, int32_t precision); extern void mulrat(_Inout_ PRAT* pa, _In_ PRAT b, int32_t precision);
extern void numpowi32( _Inout_ PNUMBER *proot, int32_t power, uint32_t radix, int32_t precision); extern void numpowi32(_Inout_ PNUMBER* proot, int32_t power, uint32_t radix, int32_t precision);
extern void numpowi32x( _Inout_ PNUMBER *proot, int32_t power ); extern void numpowi32x(_Inout_ PNUMBER* proot, int32_t power);
extern void orrat( _Inout_ PRAT *pa, _In_ PRAT b, uint32_t radix, int32_t precision); extern void orrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void powrat( _Inout_ PRAT *pa, _In_ PRAT b , uint32_t radix, int32_t precision); extern void powrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void powratNumeratorDenominator(_Inout_ PRAT *pa, _In_ PRAT b, uint32_t radix, int32_t precision); extern void powratNumeratorDenominator(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void powratcomp(_Inout_ PRAT *pa, _In_ PRAT b, uint32_t radix, int32_t precision); extern void powratcomp(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void ratpowi32( _Inout_ PRAT *proot, int32_t power, int32_t precision); extern void ratpowi32(_Inout_ PRAT* proot, int32_t power, int32_t precision);
extern void remnum( _Inout_ PNUMBER *pa, _In_ PNUMBER b, uint32_t radix); extern void remnum(_Inout_ PNUMBER* pa, _In_ PNUMBER b, uint32_t radix);
extern void rootrat( _Inout_ PRAT *pa, _In_ PRAT b , uint32_t radix, int32_t precision); extern void rootrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void scale2pi( _Inout_ PRAT *px, uint32_t radix, int32_t precision); extern void scale2pi(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
extern void scale( _Inout_ PRAT *px, _In_ PRAT scalefact, uint32_t radix, int32_t precision); extern void scale(_Inout_ PRAT* px, _In_ PRAT scalefact, uint32_t radix, int32_t precision);
extern void subrat( _Inout_ PRAT *pa, _In_ PRAT b, int32_t precision); extern void subrat(_Inout_ PRAT* pa, _In_ PRAT b, int32_t precision);
extern void xorrat( _Inout_ PRAT *pa, _In_ PRAT b, uint32_t radix, int32_t precision); extern void xorrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void lshrat( _Inout_ PRAT *pa, _In_ PRAT b , uint32_t radix, int32_t precision); extern void lshrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern void rshrat( _Inout_ PRAT *pa, _In_ PRAT b, uint32_t radix, int32_t precision); extern void rshrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
extern bool rat_equ( _In_ PRAT a, _In_ PRAT b, int32_t precision); extern bool rat_equ(_In_ PRAT a, _In_ PRAT b, int32_t precision);
extern bool rat_neq( _In_ PRAT a, _In_ PRAT b, int32_t precision); extern bool rat_neq(_In_ PRAT a, _In_ PRAT b, int32_t precision);
extern bool rat_gt( _In_ PRAT a, _In_ PRAT b, int32_t precision); extern bool rat_gt(_In_ PRAT a, _In_ PRAT b, int32_t precision);
extern bool rat_ge( _In_ PRAT a, _In_ PRAT b, int32_t precision); 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_ PRAT* px, int32_t precision);
extern void _dumprawrat(_In_ const wchar_t *varname, _In_ PRAT rat, std::wostream& out); extern void _dumprawrat(_In_ const wchar_t* varname, _In_ PRAT rat, std::wostream& out);
extern void _dumprawnum(_In_ const wchar_t *varname, _In_ PNUMBER num, std::wostream& out); extern void _dumprawnum(_In_ const wchar_t* varname, _In_ PNUMBER num, std::wostream& out);

View file

@ -25,30 +25,41 @@
using namespace std; using namespace std;
void _readconstants( void ); void _readconstants(void);
#if defined( GEN_CONST ) #if defined(GEN_CONST)
static int cbitsofprecision = 0; static int cbitsofprecision = 0;
#define READRAWRAT(v) #define READRAWRAT(v)
#define READRAWNUM(v) #define READRAWNUM(v)
#define DUMPRAWRAT(v) _dumprawrat(#v,v, wcout) #define DUMPRAWRAT(v) _dumprawrat(#v, v, wcout)
#define DUMPRAWNUM(v) fprintf( stderr, \ #define DUMPRAWNUM(v) \
"// Autogenerated by _dumprawrat in support.cpp\n" ); \ fprintf(stderr, "// Autogenerated by _dumprawrat in support.cpp\n"); \
fprintf( stderr, "inline const NUMBER init_" #v "= {\n" ); \ fprintf(stderr, "inline const NUMBER init_" #v "= {\n"); \
_dumprawnum(v, wcout); \ _dumprawnum(v, wcout); \
fprintf( stderr, "};\n" ) fprintf(stderr, "};\n")
#else #else
#define DUMPRAWRAT(v) #define DUMPRAWRAT(v)
#define DUMPRAWNUM(v) #define DUMPRAWNUM(v)
#define READRAWRAT(v) createrat(v); DUPNUM((v)->pp,(&(init_p_##v))); \ #define READRAWRAT(v) \
DUPNUM((v)->pq,(&(init_q_##v))); createrat(v); \
#define READRAWNUM(v) DUPNUM(v,(&(init_##v))) DUPNUM((v)->pp, (&(init_p_##v))); \
DUPNUM((v)->pq, (&(init_q_##v)));
#define READRAWNUM(v) DUPNUM(v, (&(init_##v)))
#define INIT_AND_DUMP_RAW_NUM_IF_NULL(r, v) if (r == nullptr) { r = i32tonum(v, BASEX); DUMPRAWNUM(v); } #define INIT_AND_DUMP_RAW_NUM_IF_NULL(r, v) \
#define INIT_AND_DUMP_RAW_RAT_IF_NULL(r, v) if (r == nullptr) { r = i32torat(v); DUMPRAWRAT(v); } if (r == nullptr) \
{ \
r = i32tonum(v, BASEX); \
DUMPRAWNUM(v); \
}
#define INIT_AND_DUMP_RAW_RAT_IF_NULL(r, v) \
if (r == nullptr) \
{ \
r = i32torat(v); \
DUMPRAWRAT(v); \
}
static constexpr int RATIO_FOR_DECIMAL = 9; static constexpr int RATIO_FOR_DECIMAL = 9;
static constexpr int DECIMAL = 10; static constexpr int DECIMAL = 10;
@ -64,47 +75,47 @@ bool g_ftrueinfinite = false; // Set to true if you don't want
// chopping internally // chopping internally
// precision used internally // precision used internally
PNUMBER num_one= nullptr; PNUMBER num_one = nullptr;
PNUMBER num_two= nullptr; PNUMBER num_two = nullptr;
PNUMBER num_five= nullptr; PNUMBER num_five = nullptr;
PNUMBER num_six= nullptr; PNUMBER num_six = nullptr;
PNUMBER num_ten= nullptr; PNUMBER num_ten = nullptr;
PRAT ln_ten= nullptr; PRAT ln_ten = nullptr;
PRAT ln_two= nullptr; PRAT ln_two = nullptr;
PRAT rat_zero= nullptr; PRAT rat_zero = nullptr;
PRAT rat_one= nullptr; PRAT rat_one = nullptr;
PRAT rat_neg_one= nullptr; PRAT rat_neg_one = nullptr;
PRAT rat_two= nullptr; PRAT rat_two = nullptr;
PRAT rat_six= nullptr; PRAT rat_six = nullptr;
PRAT rat_half= nullptr; PRAT rat_half = nullptr;
PRAT rat_ten= nullptr; PRAT rat_ten = nullptr;
PRAT pt_eight_five= nullptr; PRAT pt_eight_five = nullptr;
PRAT pi= nullptr; PRAT pi = nullptr;
PRAT pi_over_two= nullptr; PRAT pi_over_two = nullptr;
PRAT two_pi= nullptr; PRAT two_pi = nullptr;
PRAT one_pt_five_pi= nullptr; PRAT one_pt_five_pi = nullptr;
PRAT e_to_one_half= nullptr; PRAT e_to_one_half = nullptr;
PRAT rat_exp= nullptr; PRAT rat_exp = nullptr;
PRAT rad_to_deg= nullptr; PRAT rad_to_deg = nullptr;
PRAT rad_to_grad= nullptr; PRAT rad_to_grad = nullptr;
PRAT rat_qword= nullptr; PRAT rat_qword = nullptr;
PRAT rat_dword= nullptr; // unsigned max ui32 PRAT rat_dword = nullptr; // unsigned max ui32
PRAT rat_word= nullptr; PRAT rat_word = nullptr;
PRAT rat_byte= nullptr; PRAT rat_byte = nullptr;
PRAT rat_360= nullptr; PRAT rat_360 = nullptr;
PRAT rat_400= nullptr; PRAT rat_400 = nullptr;
PRAT rat_180= nullptr; PRAT rat_180 = nullptr;
PRAT rat_200= nullptr; PRAT rat_200 = nullptr;
PRAT rat_nRadix= nullptr; PRAT rat_nRadix = nullptr;
PRAT rat_smallest= nullptr; PRAT rat_smallest = nullptr;
PRAT rat_negsmallest= nullptr; PRAT rat_negsmallest = nullptr;
PRAT rat_max_exp= nullptr; PRAT rat_max_exp = nullptr;
PRAT rat_min_exp= nullptr; PRAT rat_min_exp = nullptr;
PRAT rat_max_fact = nullptr; PRAT rat_max_fact = nullptr;
PRAT rat_min_fact = nullptr; PRAT rat_min_fact = nullptr;
PRAT rat_min_i32= nullptr; // min signed i32 PRAT rat_min_i32 = nullptr; // min signed i32
PRAT rat_max_i32= nullptr; // max signed i32 PRAT rat_max_i32 = nullptr; // max signed i32
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// //
@ -127,14 +138,14 @@ void ChangeConstants(uint32_t radix, int32_t precision)
uint64_t limit = static_cast<uint64_t>(BASEX) / static_cast<uint64_t>(radix); uint64_t limit = static_cast<uint64_t>(BASEX) / static_cast<uint64_t>(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; g_ratio += !g_ratio;
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))
@ -253,7 +264,6 @@ void ChangeConstants(uint32_t radix, int32_t precision)
lograt(&ln_two, extraPrecision); lograt(&ln_two, extraPrecision);
DUMPRAWRAT(ln_two); DUMPRAWRAT(ln_two);
destroyrat(rad_to_deg); destroyrat(rad_to_deg);
rad_to_deg = i32torat(180L); rad_to_deg = i32torat(180L);
divrat(&rad_to_deg, pi, extraPrecision); divrat(&rad_to_deg, pi, extraPrecision);
@ -273,7 +283,6 @@ void ChangeConstants(uint32_t radix, int32_t precision)
DUPRAT(rat_negsmallest, rat_smallest); DUPRAT(rat_negsmallest, rat_smallest);
rat_negsmallest->pp->sign = -1; rat_negsmallest->pp->sign = -1;
} }
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -287,21 +296,21 @@ void ChangeConstants(uint32_t radix, int32_t precision)
// //
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void intrat( PRAT *px, uint32_t radix, int32_t precision) void intrat(PRAT* px, uint32_t radix, int32_t precision)
{ {
// Only do the intrat operation if number is nonzero. // Only do the intrat operation if number is nonzero.
// and only if the bottom part is not one. // and only if the bottom part is not one.
if ( !zernum( (*px)->pp ) && !equnum( (*px)->pq, num_one ) ) if (!zernum((*px)->pp) && !equnum((*px)->pq, num_one))
{ {
flatrat(*px, radix, precision); flatrat(*px, radix, precision);
// Subtract the fractional part of the rational // Subtract the fractional part of the rational
PRAT pret = nullptr; PRAT pret = nullptr;
DUPRAT(pret,*px); DUPRAT(pret, *px);
remrat( &pret, rat_one ); remrat(&pret, rat_one);
subrat( px, pret, precision); subrat(px, pret, precision);
destroyrat( pret ); destroyrat(pret);
// Simplify the value if possible to resolve rounding errors // Simplify the value if possible to resolve rounding errors
flatrat(*px, radix, precision); flatrat(*px, radix, precision);
@ -319,16 +328,16 @@ void intrat( PRAT *px, uint32_t radix, int32_t precision)
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool rat_equ( PRAT a, PRAT b, int32_t precision) bool rat_equ(PRAT a, PRAT b, int32_t precision)
{ {
PRAT rattmp= nullptr; PRAT rattmp = nullptr;
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);
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -342,20 +351,19 @@ bool rat_equ( PRAT a, PRAT b, int32_t precision)
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool rat_ge( PRAT a, PRAT b, int32_t precision) bool rat_ge(PRAT a, PRAT b, int32_t precision)
{ {
PRAT rattmp= nullptr; PRAT rattmp = nullptr;
DUPRAT(rattmp,a); DUPRAT(rattmp, a);
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);
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
// FUNCTION: rat_gt // FUNCTION: rat_gt
@ -367,17 +375,17 @@ bool rat_ge( PRAT a, PRAT b, int32_t precision)
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool rat_gt( PRAT a, PRAT b, int32_t precision) bool rat_gt(PRAT a, PRAT b, int32_t precision)
{ {
PRAT rattmp= nullptr; PRAT rattmp = nullptr;
DUPRAT(rattmp,a); DUPRAT(rattmp, a);
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);
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -391,21 +399,19 @@ bool rat_gt( PRAT a, PRAT b, int32_t precision)
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool rat_le( PRAT a, PRAT b, int32_t precision) bool rat_le(PRAT a, PRAT b, int32_t precision)
{ {
PRAT rattmp = nullptr;
PRAT rattmp= nullptr; DUPRAT(rattmp, a);
DUPRAT(rattmp,a);
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);
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
// FUNCTION: rat_lt // FUNCTION: rat_lt
@ -417,20 +423,19 @@ bool rat_le( PRAT a, PRAT b, int32_t precision)
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool rat_lt( PRAT a, PRAT b, int32_t precision) bool rat_lt(PRAT a, PRAT b, int32_t precision)
{ {
PRAT rattmp= nullptr; PRAT rattmp = nullptr;
DUPRAT(rattmp,a); DUPRAT(rattmp, a);
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);
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// //
// FUNCTION: rat_neq // FUNCTION: rat_neq
@ -442,17 +447,16 @@ bool rat_lt( PRAT a, PRAT b, int32_t precision)
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool rat_neq(PRAT a, PRAT b, int32_t precision)
bool rat_neq( PRAT a, PRAT b, int32_t precision)
{ {
PRAT rattmp= nullptr; PRAT rattmp = nullptr;
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);
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -466,27 +470,26 @@ bool rat_neq( PRAT a, PRAT b, int32_t precision)
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void scale( PRAT *px, PRAT scalefact, uint32_t radix, int32_t precision ) void scale(PRAT* px, PRAT scalefact, uint32_t radix, int32_t precision)
{ {
PRAT pret = nullptr; PRAT pret = nullptr;
DUPRAT(pret,*px); DUPRAT(pret, *px);
// 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) - int32_t logscale = g_ratio * ((pret->pp->cdigit + pret->pp->exp) - (pret->pq->cdigit + pret->pq->exp));
(pret->pq->cdigit+pret->pq->exp) ); if (logscale > 0)
if ( logscale > 0 )
{ {
precision += logscale; precision += logscale;
} }
divrat( &pret, scalefact, precision); divrat(&pret, scalefact, precision);
intrat(&pret, radix, precision); intrat(&pret, radix, precision);
mulrat( &pret, scalefact, precision); mulrat(&pret, scalefact, precision);
pret->pp->sign *= -1; pret->pp->sign *= -1;
addrat( px, pret, precision); addrat(px, pret, precision);
destroyrat( pret ); destroyrat(pret);
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -500,38 +503,37 @@ void scale( PRAT *px, PRAT scalefact, uint32_t radix, int32_t precision )
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void scale2pi( PRAT *px, uint32_t radix, int32_t precision ) void scale2pi(PRAT* px, uint32_t radix, int32_t precision)
{ {
PRAT pret = nullptr; PRAT pret = nullptr;
PRAT my_two_pi = nullptr; PRAT my_two_pi = nullptr;
DUPRAT(pret,*px); DUPRAT(pret, *px);
// 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) - int32_t logscale = g_ratio * ((pret->pp->cdigit + pret->pp->exp) - (pret->pq->cdigit + pret->pq->exp));
(pret->pq->cdigit+pret->pq->exp) ); if (logscale > 0)
if ( logscale > 0 )
{ {
precision += logscale; precision += logscale;
DUPRAT(my_two_pi,rat_half); DUPRAT(my_two_pi, rat_half);
asinrat( &my_two_pi, radix, precision); asinrat(&my_two_pi, radix, precision);
mulrat( &my_two_pi, rat_six, precision); mulrat(&my_two_pi, rat_six, precision);
mulrat( &my_two_pi, rat_two, precision); mulrat(&my_two_pi, rat_two, precision);
} }
else else
{ {
DUPRAT(my_two_pi,two_pi); DUPRAT(my_two_pi, two_pi);
logscale = 0; logscale = 0;
} }
divrat( &pret, my_two_pi, precision); divrat(&pret, my_two_pi, precision);
intrat(&pret, radix, precision); intrat(&pret, radix, precision);
mulrat( &pret, my_two_pi, precision); mulrat(&pret, my_two_pi, precision);
pret->pp->sign *= -1; pret->pp->sign *= -1;
addrat( px, pret, precision); addrat(px, pret, precision);
destroyrat( my_two_pi ); destroyrat(my_two_pi);
destroyrat( pret ); destroyrat(pret);
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -544,19 +546,19 @@ void scale2pi( PRAT *px, uint32_t radix, int32_t precision )
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void inbetween( PRAT *px, PRAT range, int32_t precision) void inbetween(PRAT* px, PRAT range, int32_t precision)
{ {
if ( rat_gt(*px,range, precision) ) if (rat_gt(*px, range, precision))
{ {
DUPRAT(*px,range); DUPRAT(*px, range);
} }
else else
{ {
range->pp->sign *= -1; range->pp->sign *= -1;
if ( rat_lt(*px, range, precision) ) if (rat_lt(*px, range, precision))
{ {
DUPRAT(*px,range); DUPRAT(*px, range);
} }
range->pp->sign *= -1; range->pp->sign *= -1;
} }
@ -573,11 +575,11 @@ void inbetween( PRAT *px, PRAT range, int32_t precision)
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void _dumprawrat( const wchar_t *varname, PRAT rat, wostream& out) void _dumprawrat(const wchar_t* varname, PRAT rat, wostream& out)
{ {
_dumprawnum(varname, rat->pp, out ); _dumprawnum(varname, rat->pp, out);
_dumprawnum(varname, rat->pq, out ); _dumprawnum(varname, rat->pq, out);
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -591,26 +593,26 @@ void _dumprawrat( const wchar_t *varname, PRAT rat, wostream& out)
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void _dumprawnum(const wchar_t *varname, PNUMBER num, wostream& out) void _dumprawnum(const wchar_t* varname, PNUMBER num, wostream& out)
{ {
int i; int i;
out << L"NUMBER " << varname << L" = {\n"; out << L"NUMBER " << varname << L" = {\n";
out << L"\t"<< num->sign << L",\n"; out << L"\t" << num->sign << L",\n";
out << L"\t" << num->cdigit << L",\n"; out << L"\t" << num->cdigit << L",\n";
out << L"\t" << num->exp << L",\n"; out << L"\t" << num->exp << L",\n";
out << L"\t{ "; out << L"\t{ ";
for ( i = 0; i < num->cdigit; i++ ) for (i = 0; i < num->cdigit; i++)
{ {
out << L" "<< num->mant[i] << L","; out << L" " << num->mant[i] << L",";
} }
out << L"}\n"; out << L"}\n";
out << L"};\n"; out << L"};\n";
} }
void _readconstants( void ) void _readconstants(void)
{ {
READRAWNUM(num_one); READRAWNUM(num_one);
@ -674,42 +676,42 @@ void _readconstants( void )
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void trimit( PRAT *px, int32_t precision) void trimit(PRAT* px, int32_t precision)
{ {
if ( !g_ftrueinfinite ) if (!g_ftrueinfinite)
{ {
int32_t trim; int32_t trim;
PNUMBER pp=(*px)->pp; PNUMBER pp = (*px)->pp;
PNUMBER pq=(*px)->pq; PNUMBER pq = (*px)->pq;
trim = g_ratio * (min((pp->cdigit+pp->exp),(pq->cdigit+pq->exp))-1) - precision; 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;
if ( trim <= pp->exp ) if (trim <= pp->exp)
{ {
pp->exp -= trim; pp->exp -= trim;
} }
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;
} }
if ( trim <= pq->exp ) if (trim <= pq->exp)
{ {
pq->exp -= trim; pq->exp -= trim;
} }
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;
} }
} }
trim = min(pp->exp,pq->exp); trim = min(pp->exp, pq->exp);
pp->exp -= trim; pp->exp -= trim;
pq->exp -= trim; pq->exp -= trim;
} }

View file

@ -16,25 +16,22 @@
#include "ratpak.h" #include "ratpak.h"
void scalerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
void scalerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision )
{ {
switch ( angletype ) switch (angletype)
{ {
case ANGLE_RAD: case ANGLE_RAD:
scale2pi( pa, radix, precision); scale2pi(pa, radix, precision);
break; break;
case ANGLE_DEG: case ANGLE_DEG:
scale( pa, rat_360, radix, precision); scale(pa, rat_360, radix, precision);
break; break;
case ANGLE_GRAD: case ANGLE_GRAD:
scale( pa, rat_400, radix, precision); scale(pa, rat_400, radix, precision);
break; break;
} }
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// //
// FUNCTION: sinrat, _sinrat // FUNCTION: sinrat, _sinrat
@ -66,21 +63,21 @@ void scalerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t p
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void _sinrat(PRAT* px, int32_t precision)
void _sinrat( PRAT *px, int32_t precision)
{ {
CREATETAYLOR(); CREATETAYLOR();
DUPRAT(pret,*px); DUPRAT(pret, *px);
DUPRAT(thisterm,*px); DUPRAT(thisterm, *px);
DUPNUM(n2,num_one); DUPNUM(n2, num_one);
xx->pp->sign *= -1; xx->pp->sign *= -1;
do { do
NEXTTERM(xx,INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision); {
} while ( !SMALL_ENOUGH_RAT( thisterm, precision) ); NEXTTERM(xx, INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
DESTROYTAYLOR(); DESTROYTAYLOR();
@ -89,42 +86,42 @@ void _sinrat( PRAT *px, int32_t precision)
inbetween(px, rat_one, precision); inbetween(px, rat_one, precision);
// Since *px might be epsilon near zero we must set it to zero. // Since *px might be epsilon near zero we must set it to zero.
if ( rat_le(*px, rat_smallest, precision) && rat_ge(*px, rat_negsmallest, precision) ) if (rat_le(*px, rat_smallest, precision) && rat_ge(*px, rat_negsmallest, precision))
{ {
DUPRAT(*px,rat_zero); DUPRAT(*px, rat_zero);
} }
} }
void sinrat( PRAT *px, uint32_t radix, int32_t precision) void sinrat(PRAT* px, uint32_t radix, int32_t precision)
{ {
scale2pi(px, radix, precision); scale2pi(px, radix, precision);
_sinrat(px, precision); _sinrat(px, precision);
} }
void sinanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision) void sinanglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
{ {
scalerat( pa, angletype, radix, precision); scalerat(pa, angletype, radix, precision);
switch ( angletype ) switch (angletype)
{ {
case ANGLE_DEG: case ANGLE_DEG:
if ( rat_gt( *pa, rat_180, precision) ) if (rat_gt(*pa, rat_180, precision))
{ {
subrat(pa, rat_360, precision); subrat(pa, rat_360, precision);
} }
divrat( pa, rat_180, precision); divrat(pa, rat_180, precision);
mulrat( pa, pi, precision); mulrat(pa, pi, precision);
break; break;
case ANGLE_GRAD: case ANGLE_GRAD:
if ( rat_gt( *pa, rat_200, precision) ) if (rat_gt(*pa, rat_200, precision))
{ {
subrat(pa,rat_400, precision); subrat(pa, rat_400, precision);
} }
divrat( pa, rat_200, precision); divrat(pa, rat_200, precision);
mulrat( pa, pi, precision); mulrat(pa, pi, precision);
break; break;
} }
_sinrat( pa, precision); _sinrat(pa, precision);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -158,8 +155,7 @@ void sinanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void _cosrat(PRAT* px, uint32_t radix, int32_t precision)
void _cosrat( PRAT *px, uint32_t radix, int32_t precision)
{ {
CREATETAYLOR(); CREATETAYLOR();
@ -167,67 +163,68 @@ void _cosrat( PRAT *px, uint32_t radix, int32_t precision)
destroynum(pret->pp); destroynum(pret->pp);
destroynum(pret->pq); destroynum(pret->pq);
pret->pp=i32tonum( 1L, radix); pret->pp = i32tonum(1L, radix);
pret->pq=i32tonum( 1L, radix); pret->pq = i32tonum(1L, radix);
DUPRAT(thisterm,pret) DUPRAT(thisterm, pret)
n2=i32tonum(0L, radix); n2 = i32tonum(0L, radix);
xx->pp->sign *= -1; xx->pp->sign *= -1;
do { do
NEXTTERM(xx,INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision); {
} while ( !SMALL_ENOUGH_RAT( thisterm, precision) ); NEXTTERM(xx, INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
DESTROYTAYLOR(); DESTROYTAYLOR();
// Since *px might be epsilon above 1 or below -1, due to TRIMIT we need // Since *px might be epsilon above 1 or below -1, due to TRIMIT we need
// this trick here. // this trick here.
inbetween(px, rat_one, precision); inbetween(px, rat_one, precision);
// Since *px might be epsilon near zero we must set it to zero. // Since *px might be epsilon near zero we must set it to zero.
if ( rat_le(*px, rat_smallest, precision) && rat_ge(*px, rat_negsmallest, precision) ) if (rat_le(*px, rat_smallest, precision) && rat_ge(*px, rat_negsmallest, precision))
{ {
DUPRAT(*px,rat_zero); DUPRAT(*px, rat_zero);
} }
} }
void cosrat( PRAT *px, uint32_t radix, int32_t precision) void cosrat(PRAT* px, uint32_t radix, int32_t precision)
{ {
scale2pi(px, radix, precision); scale2pi(px, radix, precision);
_cosrat(px, radix, precision); _cosrat(px, radix, precision);
} }
void cosanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision) void cosanglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
{ {
scalerat( pa, angletype, radix, precision); scalerat(pa, angletype, radix, precision);
switch ( angletype ) switch (angletype)
{ {
case ANGLE_DEG: case ANGLE_DEG:
if ( rat_gt( *pa, rat_180, precision) ) if (rat_gt(*pa, rat_180, precision))
{ {
PRAT ptmp= nullptr; PRAT ptmp = nullptr;
DUPRAT(ptmp,rat_360); DUPRAT(ptmp, rat_360);
subrat(&ptmp, *pa, precision); subrat(&ptmp, *pa, precision);
destroyrat(*pa); destroyrat(*pa);
*pa=ptmp; *pa = ptmp;
} }
divrat( pa, rat_180, precision); divrat(pa, rat_180, precision);
mulrat( pa, pi, precision); mulrat(pa, pi, precision);
break; break;
case ANGLE_GRAD: case ANGLE_GRAD:
if ( rat_gt( *pa, rat_200, precision) ) if (rat_gt(*pa, rat_200, precision))
{ {
PRAT ptmp= nullptr; PRAT ptmp = nullptr;
DUPRAT(ptmp,rat_400); DUPRAT(ptmp, rat_400);
subrat(&ptmp, *pa, precision); subrat(&ptmp, *pa, precision);
destroyrat(*pa); destroyrat(*pa);
*pa=ptmp; *pa = ptmp;
} }
divrat( pa, rat_200, precision); divrat(pa, rat_200, precision);
mulrat( pa, pi, precision); mulrat(pa, pi, precision);
break; break;
} }
_cosrat( pa, radix, precision); _cosrat(pa, radix, precision);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -242,55 +239,52 @@ void cosanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void _tanrat(PRAT* px, uint32_t radix, int32_t precision)
void _tanrat( PRAT *px, uint32_t radix, int32_t precision)
{ {
PRAT ptmp= nullptr; PRAT ptmp = nullptr;
DUPRAT(ptmp,*px); DUPRAT(ptmp, *px);
_sinrat(px, precision); _sinrat(px, precision);
_cosrat(&ptmp, radix, precision); _cosrat(&ptmp, radix, 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);
destroyrat(ptmp); destroyrat(ptmp);
} }
void tanrat( PRAT *px, uint32_t radix, int32_t precision) void tanrat(PRAT* px, uint32_t radix, int32_t precision)
{ {
scale2pi(px, radix, precision); scale2pi(px, radix, precision);
_tanrat(px, radix, precision); _tanrat(px, radix, precision);
} }
void tananglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision) void tananglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
{ {
scalerat( pa, angletype, radix, precision); scalerat(pa, angletype, radix, precision);
switch ( angletype ) switch (angletype)
{ {
case ANGLE_DEG: case ANGLE_DEG:
if ( rat_gt( *pa, rat_180, precision) ) if (rat_gt(*pa, rat_180, precision))
{ {
subrat(pa, rat_180, precision); subrat(pa, rat_180, precision);
} }
divrat( pa, rat_180, precision); divrat(pa, rat_180, precision);
mulrat( pa, pi, precision); mulrat(pa, pi, precision);
break; break;
case ANGLE_GRAD: case ANGLE_GRAD:
if ( rat_gt( *pa, rat_200, precision) ) if (rat_gt(*pa, rat_200, precision))
{ {
subrat(pa, rat_200, precision); subrat(pa, rat_200, precision);
} }
divrat( pa, rat_200, precision); divrat(pa, rat_200, precision);
mulrat( pa, pi, precision); mulrat(pa, pi, precision);
break; break;
} }
_tanrat( pa, radix, precision); _tanrat(pa, radix, precision);
} }

View file

@ -16,22 +16,19 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "ratpak.h" #include "ratpak.h"
bool IsValidForHypFunc(PRAT px, int32_t precision) bool IsValidForHypFunc(PRAT px, int32_t precision)
{ {
PRAT ptmp = nullptr; PRAT ptmp = nullptr;
bool bRet = true; bool bRet = true;
DUPRAT(ptmp,rat_min_exp); DUPRAT(ptmp, rat_min_exp);
divrat(&ptmp, rat_ten, precision); divrat(&ptmp, rat_ten, precision);
if ( rat_lt( px, ptmp, precision) ) if (rat_lt(px, ptmp, precision))
{ {
bRet = false; bRet = false;
} }
destroyrat( ptmp ); destroyrat(ptmp);
return bRet; return bRet;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -67,48 +64,48 @@ bool IsValidForHypFunc(PRAT px, int32_t precision)
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void _sinhrat(PRAT* px, int32_t precision)
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();
DUPRAT(pret,*px); DUPRAT(pret, *px);
DUPRAT(thisterm,pret); DUPRAT(thisterm, pret);
DUPNUM(n2,num_one); DUPNUM(n2, num_one);
do { do
NEXTTERM(xx,INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision); {
} while ( !SMALL_ENOUGH_RAT( thisterm, precision) ); NEXTTERM(xx, INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
DESTROYTAYLOR(); DESTROYTAYLOR();
} }
void sinhrat( PRAT *px, uint32_t radix, int32_t precision) void sinhrat(PRAT* px, uint32_t radix, int32_t precision)
{ {
PRAT tmpx= nullptr; PRAT tmpx = nullptr;
if ( rat_ge( *px, rat_one, precision) ) if (rat_ge(*px, rat_one, precision))
{ {
DUPRAT(tmpx,*px); DUPRAT(tmpx, *px);
exprat(px, radix, precision); exprat(px, radix, precision);
tmpx->pp->sign *= -1; tmpx->pp->sign *= -1;
exprat(&tmpx, radix, precision); exprat(&tmpx, radix, precision);
subrat( px, tmpx, precision); subrat(px, tmpx, precision);
divrat( px, rat_two, precision); divrat(px, rat_two, precision);
destroyrat( tmpx ); destroyrat(tmpx);
} }
else else
{ {
_sinhrat( px, precision); _sinhrat(px, precision);
} }
} }
@ -146,58 +143,58 @@ void sinhrat( PRAT *px, uint32_t radix, int32_t precision)
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void _coshrat(PRAT* px, uint32_t radix, int32_t precision)
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();
pret->pp=i32tonum( 1L, radix); pret->pp = i32tonum(1L, radix);
pret->pq=i32tonum( 1L, radix); pret->pq = i32tonum(1L, radix);
DUPRAT(thisterm,pret) DUPRAT(thisterm, pret)
n2=i32tonum(0L, radix); n2 = i32tonum(0L, radix);
do { do
NEXTTERM(xx,INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision); {
} while ( !SMALL_ENOUGH_RAT( thisterm, precision) ); NEXTTERM(xx, INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
DESTROYTAYLOR(); DESTROYTAYLOR();
} }
void coshrat( PRAT *px, uint32_t radix, int32_t precision) void coshrat(PRAT* px, uint32_t radix, int32_t precision)
{ {
PRAT tmpx= nullptr; PRAT tmpx = nullptr;
(*px)->pp->sign = 1; (*px)->pp->sign = 1;
(*px)->pq->sign = 1; (*px)->pq->sign = 1;
if ( rat_ge( *px, rat_one, precision) ) if (rat_ge(*px, rat_one, precision))
{ {
DUPRAT(tmpx,*px); DUPRAT(tmpx, *px);
exprat(px, radix, precision); exprat(px, radix, precision);
tmpx->pp->sign *= -1; tmpx->pp->sign *= -1;
exprat(&tmpx, radix, precision); exprat(&tmpx, radix, precision);
addrat( px, tmpx, precision); addrat(px, tmpx, precision);
divrat( px, rat_two, precision); divrat(px, rat_two, precision);
destroyrat( tmpx ); destroyrat(tmpx);
} }
else else
{ {
_coshrat( px, radix, precision); _coshrat(px, radix, precision);
} }
// Since *px might be epsilon below 1 due to TRIMIT // Since *px might be epsilon below 1 due to TRIMIT
// we need this trick here. // we need this trick here.
if ( rat_lt(*px, rat_one, precision) ) if (rat_lt(*px, rat_one, precision))
{ {
DUPRAT(*px,rat_one); DUPRAT(*px, rat_one);
} }
} }
@ -214,17 +211,16 @@ void coshrat( PRAT *px, uint32_t radix, int32_t precision)
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void tanhrat( PRAT *px, uint32_t radix, int32_t precision) void tanhrat(PRAT* px, uint32_t radix, int32_t precision)
{ {
PRAT ptmp= nullptr; PRAT ptmp = nullptr;
DUPRAT(ptmp,*px); DUPRAT(ptmp, *px);
sinhrat(px, radix, precision); sinhrat(px, radix, precision);
coshrat(&ptmp, radix, precision); coshrat(&ptmp, radix, precision);
mulnumx(&((*px)->pp),ptmp->pq); mulnumx(&((*px)->pp), ptmp->pq);
mulnumx(&((*px)->pq),ptmp->pp); mulnumx(&((*px)->pq), ptmp->pp);
destroyrat(ptmp); destroyrat(ptmp);
} }

View file

@ -34,8 +34,7 @@ unordered_map<wstring, wchar_t> unquoteConversions;
/// Constructor, sets up all the variables and requires a configLoader /// Constructor, sets up all the variables and requires a configLoader
/// </summary> /// </summary>
/// <param name="dataLoader">An instance of the IConverterDataLoader interface which we use to read in category/unit names and conversion data</param> /// <param name="dataLoader">An instance of the IConverterDataLoader interface which we use to read in category/unit names and conversion data</param>
UnitConverter::UnitConverter(_In_ const shared_ptr<IConverterDataLoader>& dataLoader) : UnitConverter::UnitConverter(_In_ const shared_ptr<IConverterDataLoader>& dataLoader) : UnitConverter::UnitConverter(dataLoader, nullptr)
UnitConverter::UnitConverter(dataLoader, nullptr)
{ {
} }
@ -192,14 +191,14 @@ void UnitConverter::SwitchActive(const wstring& newValue)
} }
} }
wstring UnitConverter::CategoryToString(const Category& c, const wchar_t * delimiter) wstring UnitConverter::CategoryToString(const Category& c, const wchar_t* delimiter)
{ {
wstringstream out(wstringstream::out); wstringstream out(wstringstream::out);
out << Quote(std::to_wstring(c.id)) << delimiter << Quote(std::to_wstring(c.supportsNegative)) << delimiter << Quote(c.name) << delimiter; out << Quote(std::to_wstring(c.id)) << delimiter << Quote(std::to_wstring(c.supportsNegative)) << delimiter << Quote(c.name) << delimiter;
return out.str(); return out.str();
} }
vector<wstring> UnitConverter::StringToVector(const wstring& w, const wchar_t * delimiter, bool addRemainder) vector<wstring> UnitConverter::StringToVector(const wstring& w, const wchar_t* delimiter, bool addRemainder)
{ {
size_t delimiterIndex = w.find(delimiter); size_t delimiterIndex = w.find(delimiter);
size_t startIndex = 0; size_t startIndex = 0;
@ -229,10 +228,12 @@ Category UnitConverter::StringToCategory(const wstring& w)
return serializedCategory; return serializedCategory;
} }
wstring UnitConverter::UnitToString(const Unit& u, const wchar_t * delimiter) wstring UnitConverter::UnitToString(const Unit& u, const wchar_t* delimiter)
{ {
wstringstream out(wstringstream::out); wstringstream out(wstringstream::out);
out << Quote(std::to_wstring(u.id)) << delimiter << Quote(u.name) << delimiter << Quote(u.abbreviation) << delimiter << std::to_wstring(u.isConversionSource) << delimiter << std::to_wstring(u.isConversionTarget) << delimiter << std::to_wstring(u.isWhimsical) << delimiter; out << Quote(std::to_wstring(u.id)) << delimiter << Quote(u.name) << delimiter << Quote(u.abbreviation) << delimiter
<< std::to_wstring(u.isConversionSource) << delimiter << std::to_wstring(u.isConversionTarget) << delimiter << std::to_wstring(u.isWhimsical)
<< delimiter;
return out.str(); return out.str();
} }
@ -262,7 +263,7 @@ ConversionData UnitConverter::StringToConversionData(const wstring& w)
return serializedConversionData; return serializedConversionData;
} }
wstring UnitConverter::ConversionDataToString(ConversionData d, const wchar_t * delimiter) wstring UnitConverter::ConversionDataToString(ConversionData d, const wchar_t* delimiter)
{ {
wstringstream out(wstringstream::out); wstringstream out(wstringstream::out);
out.precision(32); out.precision(32);
@ -289,12 +290,13 @@ wstring UnitConverter::Serialize()
} }
wstringstream out(wstringstream::out); wstringstream out(wstringstream::out);
const wchar_t * delimiter = L";"; const wchar_t* delimiter = L";";
out << UnitToString(m_fromType, delimiter) << "|"; out << UnitToString(m_fromType, delimiter) << "|";
out << UnitToString(m_toType, delimiter) << "|"; out << UnitToString(m_toType, delimiter) << "|";
out << CategoryToString(m_currentCategory, delimiter) << "|"; out << CategoryToString(m_currentCategory, delimiter) << "|";
out << std::to_wstring(m_currentHasDecimal) << delimiter << std::to_wstring(m_returnHasDecimal) << delimiter << std::to_wstring(m_switchedActive) << delimiter; out << std::to_wstring(m_currentHasDecimal) << delimiter << std::to_wstring(m_returnHasDecimal) << delimiter << std::to_wstring(m_switchedActive)
<< delimiter;
out << m_currentDisplay << delimiter << m_returnDisplay << delimiter << "|"; out << m_currentDisplay << delimiter << m_returnDisplay << delimiter << "|";
wstringstream categoryString(wstringstream::out); wstringstream categoryString(wstringstream::out);
wstringstream categoryToUnitString(wstringstream::out); wstringstream categoryToUnitString(wstringstream::out);
@ -311,7 +313,8 @@ wstring UnitConverter::Serialize()
{ {
categoryToUnitString << UnitToString(u, delimiter) << ","; categoryToUnitString << UnitToString(u, delimiter) << ",";
} }
categoryToUnitString << "[" << "]"; categoryToUnitString << "["
<< "]";
} }
for (const auto& cur : m_ratioMap) for (const auto& cur : m_ratioMap)
@ -322,7 +325,8 @@ wstring UnitConverter::Serialize()
unitToUnitToDoubleString << UnitToString(curConversion.first, delimiter) << ":"; unitToUnitToDoubleString << UnitToString(curConversion.first, delimiter) << ":";
unitToUnitToDoubleString << ConversionDataToString(curConversion.second, delimiter) << ":,"; unitToUnitToDoubleString << ConversionDataToString(curConversion.second, delimiter) << ":,";
} }
unitToUnitToDoubleString << "[" << "]"; unitToUnitToDoubleString << "["
<< "]";
} }
out << categoryString.str() << "|"; out << categoryString.str() << "|";
@ -429,7 +433,6 @@ void UnitConverter::RestoreUserPreferences(const wstring& userPreferences)
m_toType = toType; m_toType = toType;
} }
} }
} }
/// <summary> /// <summary>
@ -438,7 +441,7 @@ void UnitConverter::RestoreUserPreferences(const wstring& userPreferences)
wstring UnitConverter::SaveUserPreferences() wstring UnitConverter::SaveUserPreferences()
{ {
wstringstream out(wstringstream::out); wstringstream out(wstringstream::out);
const wchar_t * delimiter = L";"; const wchar_t* delimiter = L";";
out << UnitToString(m_fromType, delimiter) << "|"; out << UnitToString(m_fromType, delimiter) << "|";
out << UnitToString(m_toType, delimiter) << "|"; out << UnitToString(m_toType, delimiter) << "|";
@ -457,7 +460,7 @@ wstring UnitConverter::Quote(const wstring& s)
// Iterate over the delimiter characters we need to quote // Iterate over the delimiter characters we need to quote
wstring::const_iterator cursor = s.begin(); wstring::const_iterator cursor = s.begin();
while(cursor != s.end()) while (cursor != s.end())
{ {
if (quoteConversions.find(*cursor) != quoteConversions.end()) if (quoteConversions.find(*cursor) != quoteConversions.end())
{ {
@ -481,9 +484,9 @@ wstring UnitConverter::Unquote(const wstring& s)
wstringstream quotedSubString(wstringstream::out); wstringstream quotedSubString(wstringstream::out);
wstringstream unquotedString(wstringstream::out); wstringstream unquotedString(wstringstream::out);
wstring::const_iterator cursor = s.begin(); wstring::const_iterator cursor = s.begin();
while(cursor != s.end()) while (cursor != s.end())
{ {
if(*cursor == LEFTESCAPECHAR) if (*cursor == LEFTESCAPECHAR)
{ {
quotedSubString.str(L""); quotedSubString.str(L"");
while (cursor != s.end() && *cursor != RIGHTESCAPECHAR) while (cursor != s.end() && *cursor != RIGHTESCAPECHAR)
@ -529,7 +532,8 @@ void UnitConverter::SendCommand(Command command)
clearFront = true; clearFront = true;
} }
bool clearBack = false; bool clearBack = false;
if ((m_currentHasDecimal && m_currentDisplay.size() - 1 >= MAXIMUMDIGITSALLOWED) || (!m_currentHasDecimal && m_currentDisplay.size() >= MAXIMUMDIGITSALLOWED)) if ((m_currentHasDecimal && m_currentDisplay.size() - 1 >= MAXIMUMDIGITSALLOWED)
|| (!m_currentHasDecimal && m_currentDisplay.size() >= MAXIMUMDIGITSALLOWED))
{ {
clearBack = true; clearBack = true;
} }
@ -643,7 +647,6 @@ void UnitConverter::SendCommand(Command command)
break; break;
} }
if (clearFront) if (clearFront)
{ {
m_currentDisplay.erase(0, 1); m_currentDisplay.erase(0, 1);
@ -684,8 +687,7 @@ void UnitConverter::SetViewModelCurrencyCallback(_In_ const shared_ptr<IViewMode
task<pair<bool, wstring>> UnitConverter::RefreshCurrencyRatios() task<pair<bool, wstring>> UnitConverter::RefreshCurrencyRatios()
{ {
shared_ptr<ICurrencyConverterDataLoader> currencyDataLoader = GetCurrencyConverterDataLoader(); shared_ptr<ICurrencyConverterDataLoader> currencyDataLoader = GetCurrencyConverterDataLoader();
return create_task([this, currencyDataLoader]() return create_task([this, currencyDataLoader]() {
{
if (currencyDataLoader != nullptr) if (currencyDataLoader != nullptr)
{ {
return currencyDataLoader->TryLoadDataFromWebOverrideAsync(); return currencyDataLoader->TryLoadDataFromWebOverrideAsync();
@ -694,8 +696,9 @@ task<pair<bool, wstring>> UnitConverter::RefreshCurrencyRatios()
{ {
return task_from_result(false); return task_from_result(false);
} }
}).then([this, currencyDataLoader](bool didLoad) })
{ .then(
[this, currencyDataLoader](bool didLoad) {
wstring timestamp = L""; wstring timestamp = L"";
if (currencyDataLoader != nullptr) if (currencyDataLoader != nullptr)
{ {
@ -703,7 +706,8 @@ task<pair<bool, wstring>> UnitConverter::RefreshCurrencyRatios()
} }
return make_pair(didLoad, timestamp); return make_pair(didLoad, timestamp);
}, task_continuation_context::use_default()); },
task_continuation_context::use_default());
} }
shared_ptr<ICurrencyConverterDataLoader> UnitConverter::GetCurrencyConverterDataLoader() shared_ptr<ICurrencyConverterDataLoader> UnitConverter::GetCurrencyConverterDataLoader()
@ -752,7 +756,7 @@ vector<tuple<wstring, Unit>> UnitConverter::CalculateSuggested()
newEntry.magnitude = log10(convertedValue); newEntry.magnitude = log10(convertedValue);
newEntry.value = convertedValue; newEntry.value = convertedValue;
newEntry.type = cur.first; newEntry.type = cur.first;
if(newEntry.type.isWhimsical == false) if (newEntry.type.isWhimsical == false)
intermediateVector.push_back(newEntry); intermediateVector.push_back(newEntry);
else else
intermediateWhimsicalVector.push_back(newEntry); intermediateWhimsicalVector.push_back(newEntry);
@ -760,9 +764,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(), [] sort(intermediateVector.begin(), intermediateVector.end(), [](SuggestedValueIntermediate first, SuggestedValueIntermediate second) {
(SuggestedValueIntermediate first, 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;
@ -798,9 +800,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(), [] sort(intermediateWhimsicalVector.begin(), intermediateWhimsicalVector.end(), [](SuggestedValueIntermediate first, SuggestedValueIntermediate second) {
(SuggestedValueIntermediate first, 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;
@ -922,7 +922,6 @@ shared_ptr<IConverterDataLoader> UnitConverter::GetDataLoaderForCategory(const C
/// </summary> /// </summary>
void UnitConverter::InitializeSelectedUnits() void UnitConverter::InitializeSelectedUnits()
{ {
if (m_categoryToUnits.empty()) if (m_categoryToUnits.empty())
{ {
return; return;
@ -1057,7 +1056,7 @@ void UnitConverter::TrimString(wstring& returnString)
} }
wstring::iterator iter; wstring::iterator iter;
for (iter = returnString.end() - 1; ;iter--) for (iter = returnString.end() - 1;; iter--)
{ {
if (*iter != L'0') if (*iter != L'0')
{ {
@ -1065,9 +1064,9 @@ void UnitConverter::TrimString(wstring& returnString)
break; break;
} }
} }
if (*(returnString.end()-1) == L'.') if (*(returnString.end() - 1) == L'.')
{ {
returnString.erase(returnString.end()-1, returnString.end()); returnString.erase(returnString.end() - 1, returnString.end());
} }
} }

View file

@ -15,13 +15,22 @@ namespace UnitConversionManager
struct Unit struct Unit
{ {
Unit(){} Unit()
{
}
Unit(int id, std::wstring name, std::wstring abbreviation, bool isConversionSource, bool isConversionTarget, bool isWhimsical) Unit(int id, std::wstring name, std::wstring abbreviation, bool isConversionSource, bool isConversionTarget, bool isWhimsical)
: id(id), name(name), accessibleName(name), abbreviation(abbreviation), isConversionSource(isConversionSource), isConversionTarget(isConversionTarget), isWhimsical(isWhimsical) : id(id)
, name(name)
, accessibleName(name)
, abbreviation(abbreviation)
, isConversionSource(isConversionSource)
, isConversionTarget(isConversionTarget)
, isWhimsical(isWhimsical)
{ {
} }
Unit(int id, std::wstring currencyName, std::wstring countryName, std::wstring abbreviation, bool isRtlLanguage, bool isConversionSource, bool isConversionTarget) Unit(int id, std::wstring currencyName, std::wstring countryName, std::wstring abbreviation, bool isRtlLanguage, bool isConversionSource,
bool isConversionTarget)
: id(id), abbreviation(abbreviation), isConversionSource(isConversionSource), isConversionTarget(isConversionTarget), isWhimsical(false) : id(id), abbreviation(abbreviation), isConversionSource(isConversionSource), isConversionTarget(isConversionTarget), isWhimsical(false)
{ {
std::wstring nameValue1 = isRtlLanguage ? currencyName : countryName; std::wstring nameValue1 = isRtlLanguage ? currencyName : countryName;
@ -31,7 +40,9 @@ namespace UnitConversionManager
accessibleName = nameValue1 + L" " + nameValue2; accessibleName = nameValue1 + L" " + nameValue2;
} }
virtual ~Unit() {} virtual ~Unit()
{
}
int id; int id;
std::wstring name; std::wstring name;
@ -41,12 +52,12 @@ namespace UnitConversionManager
bool isConversionTarget; bool isConversionTarget;
bool isWhimsical; bool isWhimsical;
bool operator!= (const Unit& that) const bool operator!=(const Unit& that) const
{ {
return that.id != id; return that.id != id;
} }
bool operator== (const Unit& that) const bool operator==(const Unit& that) const
{ {
return that.id == id; return that.id == id;
} }
@ -61,7 +72,9 @@ namespace UnitConversionManager
struct Category struct Category
{ {
Category(){} Category()
{
}
Category(int id, std::wstring name, bool supportsNegative) : id(id), name(name), supportsNegative(supportsNegative) Category(int id, std::wstring name, bool supportsNegative) : id(id), name(name), supportsNegative(supportsNegative)
{ {
@ -71,12 +84,12 @@ namespace UnitConversionManager
std::wstring name; std::wstring name;
bool supportsNegative; bool supportsNegative;
bool operator!= (const Category& that) const bool operator!=(const Category& that) const
{ {
return that.id != id; return that.id != id;
} }
bool operator== (const Category& that) const bool operator==(const Category& that) const
{ {
return that.id == id; return that.id == id;
} }
@ -85,7 +98,8 @@ namespace UnitConversionManager
class UnitHash class UnitHash
{ {
public: public:
size_t operator() (const Unit & x) const { size_t operator()(const Unit& x) const
{
return x.id; return x.id;
} }
}; };
@ -93,7 +107,8 @@ namespace UnitConversionManager
class CategoryHash class CategoryHash
{ {
public: public:
size_t operator() (const Category & x) const { size_t operator()(const Category& x) const
{
return x.id; return x.id;
} }
}; };
@ -107,12 +122,16 @@ namespace UnitConversionManager
struct ConversionData struct ConversionData
{ {
ConversionData(){} ConversionData()
{
}
ConversionData(double ratio, double offset, bool offsetFirst) : ratio(ratio), offset(offset), offsetFirst(offsetFirst) ConversionData(double ratio, double offset, bool offsetFirst) : ratio(ratio), offset(offset), offsetFirst(offsetFirst)
{ {
} }
virtual ~ConversionData() {} virtual ~ConversionData()
{
}
double ratio; double ratio;
double offset; double offset;
@ -136,13 +155,17 @@ namespace UnitConversionManager
}; };
typedef std::tuple<std::vector<UnitConversionManager::Unit>, UnitConversionManager::Unit, UnitConversionManager::Unit> CategorySelectionInitializer; typedef std::tuple<std::vector<UnitConversionManager::Unit>, UnitConversionManager::Unit, UnitConversionManager::Unit> CategorySelectionInitializer;
typedef std::unordered_map<UnitConversionManager::Unit, std::unordered_map<UnitConversionManager::Unit, UnitConversionManager::ConversionData, UnitConversionManager::UnitHash>, UnitConversionManager::UnitHash> UnitToUnitToConversionDataMap; typedef std::unordered_map<UnitConversionManager::Unit,
typedef std::unordered_map<UnitConversionManager::Category, std::vector<UnitConversionManager::Unit>, UnitConversionManager::CategoryHash> CategoryToUnitVectorMap; std::unordered_map<UnitConversionManager::Unit, UnitConversionManager::ConversionData, UnitConversionManager::UnitHash>,
UnitConversionManager::UnitHash>
UnitToUnitToConversionDataMap;
typedef std::unordered_map<UnitConversionManager::Category, std::vector<UnitConversionManager::Unit>, UnitConversionManager::CategoryHash>
CategoryToUnitVectorMap;
class IViewModelCurrencyCallback class IViewModelCurrencyCallback
{ {
public: public:
virtual ~IViewModelCurrencyCallback() { }; virtual ~IViewModelCurrencyCallback(){};
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;
@ -153,7 +176,7 @@ namespace UnitConversionManager
class IConverterDataLoader class IConverterDataLoader
{ {
public: public:
virtual ~IConverterDataLoader() { }; virtual ~IConverterDataLoader(){};
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> LoadOrderedCategories() = 0; virtual std::vector<Category> LoadOrderedCategories() = 0;
virtual std::vector<Unit> LoadOrderedUnits(const Category& c) = 0; virtual std::vector<Unit> LoadOrderedUnits(const Category& c) = 0;
@ -165,8 +188,10 @@ namespace UnitConversionManager
{ {
public: public:
virtual void SetViewModelCallback(const std::shared_ptr<UnitConversionManager::IViewModelCurrencyCallback>& callback) = 0; virtual void SetViewModelCallback(const std::shared_ptr<UnitConversionManager::IViewModelCurrencyCallback>& callback) = 0;
virtual std::pair<std::wstring, std::wstring> GetCurrencySymbols(_In_ const UnitConversionManager::Unit& unit1, _In_ const UnitConversionManager::Unit& unit2) = 0; virtual std::pair<std::wstring, std::wstring> GetCurrencySymbols(_In_ const UnitConversionManager::Unit& unit1,
virtual std::pair<std::wstring, std::wstring> GetCurrencyRatioEquality(_In_ const UnitConversionManager::Unit& unit1, _In_ const UnitConversionManager::Unit& unit2) = 0; _In_ const UnitConversionManager::Unit& unit2) = 0;
virtual std::pair<std::wstring, std::wstring> GetCurrencyRatioEquality(_In_ const UnitConversionManager::Unit& unit1,
_In_ const UnitConversionManager::Unit& unit2) = 0;
virtual std::wstring GetCurrencyTimestamp() = 0; virtual std::wstring GetCurrencyTimestamp() = 0;
virtual concurrency::task<bool> TryLoadDataFromCacheAsync() = 0; virtual concurrency::task<bool> TryLoadDataFromCacheAsync() = 0;
@ -177,7 +202,7 @@ namespace UnitConversionManager
class IUnitConverterVMCallback class IUnitConverterVMCallback
{ {
public: public:
virtual ~IUnitConverterVMCallback() { }; virtual ~IUnitConverterVMCallback(){};
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;
@ -186,7 +211,9 @@ namespace UnitConversionManager
class IUnitConverter class IUnitConverter
{ {
public: public:
virtual ~IUnitConverter() { } virtual ~IUnitConverter()
{
}
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;
@ -230,7 +257,7 @@ namespace UnitConversionManager
void ResetCategoriesAndRatios() override; void ResetCategoriesAndRatios() override;
// IUnitConverter // IUnitConverter
static std::vector<std::wstring> StringToVector(const std::wstring& w, const wchar_t * delimiter, bool addRemainder = false); static std::vector<std::wstring> StringToVector(const std::wstring& w, const wchar_t* delimiter, bool addRemainder = false);
static std::wstring Quote(const std::wstring& s); static std::wstring Quote(const std::wstring& s);
static std::wstring Unquote(const std::wstring& s); static std::wstring Unquote(const std::wstring& s);
@ -243,11 +270,11 @@ namespace UnitConversionManager
void InitializeSelectedUnits(); void InitializeSelectedUnits();
std::wstring RoundSignificant(double num, int numSignificant); std::wstring RoundSignificant(double num, int numSignificant);
Category StringToCategory(const std::wstring& w); Category StringToCategory(const std::wstring& w);
std::wstring CategoryToString(const Category& c, const wchar_t * delimiter); std::wstring CategoryToString(const Category& c, const wchar_t* delimiter);
std::wstring UnitToString(const Unit& u, const wchar_t * delimiter); std::wstring UnitToString(const Unit& u, const wchar_t* delimiter);
Unit StringToUnit(const std::wstring& w); Unit StringToUnit(const std::wstring& w);
ConversionData StringToConversionData(const std::wstring& w); ConversionData StringToConversionData(const std::wstring& w);
std::wstring ConversionDataToString(ConversionData d, const wchar_t * delimiter); std::wstring ConversionDataToString(ConversionData d, const wchar_t* delimiter);
void UpdateCurrencySymbols(); void UpdateCurrencySymbols();
void UpdateViewModel(); void UpdateViewModel();
bool AnyUnitIsEmpty(); bool AnyUnitIsEmpty();

View file

@ -38,13 +38,13 @@ namespace
StringReference ClearMemoryVisibilityPropertyName(L"ClearMemoryVisibility"); StringReference ClearMemoryVisibilityPropertyName(L"ClearMemoryVisibility");
} }
ApplicationViewModel::ApplicationViewModel() : ApplicationViewModel::ApplicationViewModel()
m_CalculatorViewModel(nullptr), : m_CalculatorViewModel(nullptr)
m_DateCalcViewModel(nullptr), , m_DateCalcViewModel(nullptr)
m_ConverterViewModel(nullptr), , m_ConverterViewModel(nullptr)
m_PreviousMode(ViewMode::None), , m_PreviousMode(ViewMode::None)
m_mode(ViewMode::None), , m_mode(ViewMode::None)
m_categories(nullptr) , m_categories(nullptr)
{ {
SetMenuCategories(); SetMenuCategories();
} }
@ -60,7 +60,7 @@ void ApplicationViewModel::Mode::set(ViewMode value)
} }
} }
void ApplicationViewModel::Categories::set(IObservableVector<NavCategoryGroup^>^ value) void ApplicationViewModel::Categories::set(IObservableVector<NavCategoryGroup ^> ^ value)
{ {
if (m_categories != value) if (m_categories != value)
{ {
@ -90,7 +90,7 @@ void ApplicationViewModel::Initialize(ViewMode mode)
throw; throw;
} }
} }
catch (Exception^ e) catch (Exception ^ e)
{ {
TraceLogger::GetInstance().LogPlatformException(__FUNCTIONW__, e); TraceLogger::GetInstance().LogPlatformException(__FUNCTIONW__, e);
if (!TryRecoverFromNavigationModeFailure()) if (!TryRecoverFromNavigationModeFailure())
@ -165,7 +165,7 @@ void ApplicationViewModel::OnModeChanged()
RaisePropertyChanged(ClearMemoryVisibilityPropertyName); RaisePropertyChanged(ClearMemoryVisibilityPropertyName);
} }
void ApplicationViewModel::OnCopyCommand(Object^ parameter) void ApplicationViewModel::OnCopyCommand(Object ^ parameter)
{ {
if (NavCategory::IsConverterViewMode(m_mode)) if (NavCategory::IsConverterViewMode(m_mode))
{ {
@ -181,7 +181,7 @@ void ApplicationViewModel::OnCopyCommand(Object^ parameter)
} }
} }
void ApplicationViewModel::OnPasteCommand(Object^ parameter) void ApplicationViewModel::OnPasteCommand(Object ^ parameter)
{ {
if (NavCategory::IsConverterViewMode(m_mode)) if (NavCategory::IsConverterViewMode(m_mode))
{ {

View file

@ -11,8 +11,7 @@ namespace CalculatorApp
{ {
namespace ViewModel namespace ViewModel
{ {
[Windows::UI::Xaml::Data::Bindable] [Windows::UI::Xaml::Data::Bindable] public ref class ApplicationViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
public ref class ApplicationViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
{ {
public: public:
ApplicationViewModel(); ApplicationViewModel();
@ -20,11 +19,11 @@ namespace CalculatorApp
void Initialize(CalculatorApp::Common::ViewMode mode); // Use for first init, use deserialize for rehydration void Initialize(CalculatorApp::Common::ViewMode mode); // Use for first init, use deserialize for rehydration
OBSERVABLE_OBJECT(); OBSERVABLE_OBJECT();
OBSERVABLE_PROPERTY_RW(StandardCalculatorViewModel^, CalculatorViewModel); OBSERVABLE_PROPERTY_RW(StandardCalculatorViewModel ^, CalculatorViewModel);
OBSERVABLE_PROPERTY_RW(DateCalculatorViewModel^, DateCalcViewModel); OBSERVABLE_PROPERTY_RW(DateCalculatorViewModel ^, DateCalcViewModel);
OBSERVABLE_PROPERTY_RW(UnitConverterViewModel^, ConverterViewModel); OBSERVABLE_PROPERTY_RW(UnitConverterViewModel ^, ConverterViewModel);
OBSERVABLE_PROPERTY_RW(CalculatorApp::Common::ViewMode, PreviousMode); OBSERVABLE_PROPERTY_RW(CalculatorApp::Common::ViewMode, PreviousMode);
OBSERVABLE_NAMED_PROPERTY_RW(Platform::String^, CategoryName); OBSERVABLE_NAMED_PROPERTY_RW(Platform::String ^, CategoryName);
COMMAND_FOR_METHOD(CopyCommand, ApplicationViewModel::OnCopyCommand); COMMAND_FOR_METHOD(CopyCommand, ApplicationViewModel::OnCopyCommand);
COMMAND_FOR_METHOD(PasteCommand, ApplicationViewModel::OnPasteCommand); COMMAND_FOR_METHOD(PasteCommand, ApplicationViewModel::OnPasteCommand);
@ -60,8 +59,7 @@ namespace CalculatorApp
{ {
Windows::UI::Xaml::Visibility get() Windows::UI::Xaml::Visibility get()
{ {
return CalculatorApp::Common::NavCategory::IsCalculatorViewMode(Mode) return CalculatorApp::Common::NavCategory::IsCalculatorViewMode(Mode) ? Windows::UI::Xaml::Visibility::Visible
? Windows::UI::Xaml::Visibility::Visible
: Windows::UI::Xaml::Visibility::Collapsed; : Windows::UI::Xaml::Visibility::Collapsed;
} }
} }
@ -71,13 +69,13 @@ namespace CalculatorApp
void OnModeChanged(); void OnModeChanged();
void OnCopyCommand(Platform::Object^ parameter); void OnCopyCommand(Platform::Object ^ parameter);
void OnPasteCommand(Platform::Object^ parameter); void OnPasteCommand(Platform::Object ^ parameter);
void SetMenuCategories(); void SetMenuCategories();
CalculatorApp::Common::ViewMode m_mode; CalculatorApp::Common::ViewMode m_mode;
Windows::Foundation::Collections::IObservableVector<CalculatorApp::Common::NavCategoryGroup^>^ m_categories; Windows::Foundation::Collections::IObservableVector<CalculatorApp::Common::NavCategoryGroup ^> ^ m_categories;
}; };
} }
} }

View file

@ -3,30 +3,30 @@
#pragma once #pragma once
namespace CalculatorApp { namespace Common namespace CalculatorApp
{ {
ref class AlwaysSelectedCollectionView sealed: namespace Common
public Windows::UI::Xaml::DependencyObject,
public Windows::UI::Xaml::Data::ICollectionView
{ {
internal: ref class AlwaysSelectedCollectionView sealed : public Windows::UI::Xaml::DependencyObject, public Windows::UI::Xaml::Data::ICollectionView
AlwaysSelectedCollectionView(Windows::UI::Xaml::Interop::IBindableVector^ source): {
m_currentPosition(-1) internal : AlwaysSelectedCollectionView(Windows::UI::Xaml::Interop::IBindableVector ^ source) : m_currentPosition(-1)
{ {
m_source = source; m_source = source;
Windows::UI::Xaml::Interop::IBindableObservableVector^ observable = dynamic_cast<Windows::UI::Xaml::Interop::IBindableObservableVector^>(source); Windows::UI::Xaml::Interop::IBindableObservableVector ^ observable =
dynamic_cast<Windows::UI::Xaml::Interop::IBindableObservableVector ^>(source);
if (observable) if (observable)
{ {
observable->VectorChanged += observable->VectorChanged += ref new Windows::UI::Xaml::Interop::BindableVectorChangedEventHandler(
ref new Windows::UI::Xaml::Interop::BindableVectorChangedEventHandler(this, &AlwaysSelectedCollectionView::OnSourceBindableVectorChanged); this, &AlwaysSelectedCollectionView::OnSourceBindableVectorChanged);
} }
} }
private: private:
// ICollectionView // ICollectionView
// Not implemented methods // Not implemented methods
virtual WF::IAsyncOperation<Windows::UI::Xaml::Data::LoadMoreItemsResult>^ LoadMoreItemsAsync(unsigned int) = Windows::UI::Xaml::Data::ICollectionView::LoadMoreItemsAsync virtual WF::IAsyncOperation<
Windows::UI::Xaml::Data::LoadMoreItemsResult> ^ LoadMoreItemsAsync(unsigned int) = Windows::UI::Xaml::Data::ICollectionView::LoadMoreItemsAsync
{ {
throw ref new Platform::NotImplementedException(); throw ref new Platform::NotImplementedException();
} }
@ -46,14 +46,13 @@ namespace CalculatorApp { namespace Common
{ {
throw ref new Platform::NotImplementedException(); throw ref new Platform::NotImplementedException();
} }
property Windows::Foundation::Collections::IObservableVector<Platform::Object^>^ CollectionGroups property Windows::Foundation::Collections::IObservableVector<Platform::Object ^> ^ CollectionGroups {
virtual Windows::Foundation::Collections::IObservableVector<Platform::Object
^> ^ get() = Windows::UI::Xaml::Data::ICollectionView::CollectionGroups::get
{ {
virtual Windows::Foundation::Collections::IObservableVector<Platform::Object^>^ get() = Windows::UI::Xaml::Data::ICollectionView::CollectionGroups::get return ref new Platform::Collections::Vector<Platform::Object ^>();
{
return ref new Platform::Collections::Vector<Platform::Object^>();
} }
} } property bool HasMoreItems
property bool HasMoreItems
{ {
virtual bool get() = Windows::UI::Xaml::Data::ICollectionView::HasMoreItems::get virtual bool get() = Windows::UI::Xaml::Data::ICollectionView::HasMoreItems::get
{ {
@ -62,7 +61,7 @@ namespace CalculatorApp { namespace Common
} }
// Implemented methods // Implemented methods
virtual bool MoveCurrentTo(Platform::Object^ item) = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentTo virtual bool MoveCurrentTo(Platform::Object ^ item) = Windows::UI::Xaml::Data::ICollectionView::MoveCurrentTo
{ {
if (item) if (item)
{ {
@ -82,11 +81,7 @@ namespace CalculatorApp { namespace Common
if (m_currentPosition >= 0 && m_currentPosition < static_cast<int>(m_source->Size)) if (m_currentPosition >= 0 && m_currentPosition < static_cast<int>(m_source->Size))
{ {
this->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, this->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal,
ref new Windows::UI::Core::DispatchedHandler( ref new Windows::UI::Core::DispatchedHandler([this]() { m_currentChanged(this, nullptr); }));
[this]()
{
m_currentChanged(this, nullptr);
}));
} }
return false; return false;
} }
@ -168,53 +163,57 @@ namespace CalculatorApp { namespace Common
{ {
throw ref new Platform::NotImplementedException(); throw ref new Platform::NotImplementedException();
} }
virtual void Clear() = Windows::Foundation::Collections::IVector<Platform::Object^>::Clear virtual void Clear() = Windows::Foundation::Collections::IVector<Platform::Object ^>::Clear
{ {
throw ref new Platform::NotImplementedException(); throw ref new Platform::NotImplementedException();
} }
virtual unsigned int GetMany(unsigned int /*startIndex*/, Platform::WriteOnlyArray<Platform::Object^>^ /*items*/) = Windows::Foundation::Collections::IVector<Platform::Object^>::GetMany virtual unsigned int
GetMany(unsigned int /*startIndex*/,
Platform::WriteOnlyArray<Platform::Object ^> ^ /*items*/) = Windows::Foundation::Collections::IVector<Platform::Object ^>::GetMany
{ {
throw ref new Platform::NotImplementedException(); throw ref new Platform::NotImplementedException();
} }
virtual Windows::Foundation::Collections::IVectorView<Platform::Object^>^ GetView() = Windows::Foundation::Collections::IVector<Platform::Object^>::GetView virtual Windows::Foundation::Collections::IVectorView<Platform::Object ^> ^ GetView() = Windows::Foundation::Collections::IVector<Platform::Object
^>::GetView
{ {
throw ref new Platform::NotImplementedException(); throw ref new Platform::NotImplementedException();
} }
virtual void InsertAt(unsigned int /*index*/, Platform::Object^ /*item*/) = Windows::Foundation::Collections::IVector<Platform::Object^>::InsertAt virtual void InsertAt(unsigned int /*index*/, Platform::Object ^ /*item*/) = Windows::Foundation::Collections::IVector<Platform::Object ^>::InsertAt
{ {
throw ref new Platform::NotImplementedException(); throw ref new Platform::NotImplementedException();
} }
virtual void RemoveAt(unsigned int /*index*/) = Windows::Foundation::Collections::IVector<Platform::Object^>::RemoveAt virtual void RemoveAt(unsigned int /*index*/) = Windows::Foundation::Collections::IVector<Platform::Object ^>::RemoveAt
{ {
throw ref new Platform::NotImplementedException(); throw ref new Platform::NotImplementedException();
} }
virtual void RemoveAtEnd() = Windows::Foundation::Collections::IVector<Platform::Object^>::RemoveAtEnd virtual void RemoveAtEnd() = Windows::Foundation::Collections::IVector<Platform::Object ^>::RemoveAtEnd
{ {
throw ref new Platform::NotImplementedException(); throw ref new Platform::NotImplementedException();
} }
virtual void ReplaceAll(const Platform::Array<Platform::Object^>^ /*items*/) = Windows::Foundation::Collections::IVector<Platform::Object^>::ReplaceAll virtual void
ReplaceAll(const Platform::Array<Platform::Object ^> ^ /*items*/) = Windows::Foundation::Collections::IVector<Platform::Object ^>::ReplaceAll
{ {
throw ref new Platform::NotImplementedException(); throw ref new Platform::NotImplementedException();
} }
virtual void SetAt(unsigned int /*index*/, Platform::Object^ /*item*/) = Windows::Foundation::Collections::IVector<Platform::Object^>::SetAt virtual void SetAt(unsigned int /*index*/, Platform::Object ^ /*item*/) = Windows::Foundation::Collections::IVector<Platform::Object ^>::SetAt
{ {
throw ref new Platform::NotImplementedException(); throw ref new Platform::NotImplementedException();
} }
// Implemented methods // Implemented methods
virtual Platform::Object^ GetAt(unsigned int index) = Windows::Foundation::Collections::IVector<Platform::Object^>::GetAt virtual Platform::Object ^ GetAt(unsigned int index) = Windows::Foundation::Collections::IVector<Platform::Object ^>::GetAt
{ {
return m_source->GetAt(index); return m_source->GetAt(index);
} }
virtual bool IndexOf(Platform::Object^ item, unsigned int* index) = Windows::Foundation::Collections::IVector<Platform::Object^>::IndexOf virtual bool IndexOf(Platform::Object ^ item, unsigned int* index) = Windows::Foundation::Collections::IVector<Platform::Object ^>::IndexOf
{ {
return m_source->IndexOf(item, index); return m_source->IndexOf(item, index);
} }
property unsigned int Size property unsigned int Size
{ {
virtual unsigned int get() = Windows::Foundation::Collections::IVector<Platform::Object^>::Size::get virtual unsigned int get() = Windows::Foundation::Collections::IVector<Platform::Object ^>::Size::get
{ {
return m_source->Size; return m_source->Size;
} }
@ -241,33 +240,33 @@ namespace CalculatorApp { namespace Common
} }
// Event handlers // Event handlers
void OnSourceBindableVectorChanged(Windows::UI::Xaml::Interop::IBindableObservableVector^ source, Platform::Object^ e) void OnSourceBindableVectorChanged(Windows::UI::Xaml::Interop::IBindableObservableVector ^ source, Platform::Object ^ e)
{ {
Windows::Foundation::Collections::IVectorChangedEventArgs^ args = safe_cast<Windows::Foundation::Collections::IVectorChangedEventArgs^>(e); Windows::Foundation::Collections::IVectorChangedEventArgs ^ args = safe_cast<Windows::Foundation::Collections::IVectorChangedEventArgs ^>(e);
m_vectorChanged(this, args); m_vectorChanged(this, args);
} }
Windows::UI::Xaml::Interop::IBindableVector^ m_source; Windows::UI::Xaml::Interop::IBindableVector ^ m_source;
int m_currentPosition; int m_currentPosition;
event WF::EventHandler<Platform::Object^>^ m_currentChanged; event WF::EventHandler<Platform::Object ^> ^ m_currentChanged;
event Windows::UI::Xaml::Data::CurrentChangingEventHandler^ m_currentChanging; event Windows::UI::Xaml::Data::CurrentChangingEventHandler ^ m_currentChanging;
event Windows::Foundation::Collections::VectorChangedEventHandler<Platform::Object^>^ m_vectorChanged; event Windows::Foundation::Collections::VectorChangedEventHandler<Platform::Object ^> ^ m_vectorChanged;
}; };
public ref class AlwaysSelectedCollectionViewConverter sealed: public Windows::UI::Xaml::Data::IValueConverter public
ref class AlwaysSelectedCollectionViewConverter sealed : public Windows::UI::Xaml::Data::IValueConverter
{ {
public: public:
AlwaysSelectedCollectionViewConverter() AlwaysSelectedCollectionViewConverter()
{ } {
}
private: private:
virtual Platform::Object^ Convert( virtual Platform::Object
Platform::Object^ value, ^ Convert(Platform::Object ^ value, Windows::UI::Xaml::Interop::TypeName /*targetType*/, Platform::Object ^ /*parameter*/,
Windows::UI::Xaml::Interop::TypeName /*targetType*/, Platform::String ^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::Convert
Platform::Object^ /*parameter*/,
Platform::String^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::Convert
{ {
auto result = dynamic_cast<Windows::UI::Xaml::Interop::IBindableVector^>(value); auto result = dynamic_cast<Windows::UI::Xaml::Interop::IBindableVector ^>(value);
if (result) if (result)
{ {
return ref new AlwaysSelectedCollectionView(result); return ref new AlwaysSelectedCollectionView(result);
@ -275,13 +274,12 @@ namespace CalculatorApp { namespace Common
return Windows::UI::Xaml::DependencyProperty::UnsetValue; // Can't convert return Windows::UI::Xaml::DependencyProperty::UnsetValue; // Can't convert
} }
virtual Platform::Object^ ConvertBack( virtual Platform::Object
Platform::Object^ /*value*/, ^ ConvertBack(Platform::Object ^ /*value*/, Windows::UI::Xaml::Interop::TypeName /*targetType*/, Platform::Object ^ /*parameter*/,
Windows::UI::Xaml::Interop::TypeName /*targetType*/, Platform::String ^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::ConvertBack
Platform::Object^ /*parameter*/,
Platform::String^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::ConvertBack
{ {
return Windows::UI::Xaml::DependencyProperty::UnsetValue; return Windows::UI::Xaml::DependencyProperty::UnsetValue;
} }
}; };
}} }
}

View file

@ -14,18 +14,18 @@ AppResourceProvider::AppResourceProvider()
m_cEngineStringResLoader = ResourceLoader::GetForViewIndependentUse(L"CEngineStrings"); m_cEngineStringResLoader = ResourceLoader::GetForViewIndependentUse(L"CEngineStrings");
} }
AppResourceProvider & AppResourceProvider::GetInstance() AppResourceProvider& AppResourceProvider::GetInstance()
{ {
static AppResourceProvider s_instance; static AppResourceProvider s_instance;
return s_instance; return s_instance;
} }
String^ AppResourceProvider::GetResourceString(_In_ String^ key) String ^ AppResourceProvider::GetResourceString(_In_ String ^ key)
{ {
return m_stringResLoader->GetString(key); return m_stringResLoader->GetString(key);
} }
String^ AppResourceProvider::GetCEngineString(_In_ String^ key) String ^ AppResourceProvider::GetCEngineString(_In_ String ^ key)
{ {
return m_cEngineStringResLoader->GetString(key); return m_cEngineStringResLoader->GetString(key);
} }

View file

@ -8,13 +8,13 @@ namespace CalculatorApp
class AppResourceProvider class AppResourceProvider
{ {
public: public:
static AppResourceProvider & GetInstance(); static AppResourceProvider& GetInstance();
Platform::String^ GetResourceString(_In_ Platform::String^ key); Platform::String ^ GetResourceString(_In_ Platform::String ^ key);
Platform::String^ GetCEngineString(_In_ Platform::String^ key); Platform::String ^ GetCEngineString(_In_ Platform::String ^ key);
private: private:
AppResourceProvider(); AppResourceProvider();
Windows::ApplicationModel::Resources::ResourceLoader^ m_stringResLoader; Windows::ApplicationModel::Resources::ResourceLoader ^ m_stringResLoader;
Windows::ApplicationModel::Resources::ResourceLoader^ m_cEngineStringResLoader; Windows::ApplicationModel::Resources::ResourceLoader ^ m_cEngineStringResLoader;
}; };
} }

View file

@ -11,16 +11,17 @@
namespace CalculatorApp::Common::Automation namespace CalculatorApp::Common::Automation
{ {
public interface class INarratorAnnouncementHost public
interface class INarratorAnnouncementHost
{ {
public: public:
// Is the host available on this OS. // Is the host available on this OS.
bool IsHostAvailable(); bool IsHostAvailable();
// Make a new instance of a concrete host. // Make a new instance of a concrete host.
INarratorAnnouncementHost^ MakeHost(); INarratorAnnouncementHost ^ MakeHost();
// Make an announcement using the concrete host's preferred method. // Make an announcement using the concrete host's preferred method.
void Announce(NarratorAnnouncement^ announcement); void Announce(NarratorAnnouncement ^ announcement);
}; };
} }

View file

@ -9,9 +9,9 @@ using namespace Windows::UI::Xaml::Automation;
using namespace Windows::UI::Xaml::Automation::Peers; using namespace Windows::UI::Xaml::Automation::Peers;
using namespace Windows::UI::Xaml::Controls; using namespace Windows::UI::Xaml::Controls;
LiveRegionHost::LiveRegionHost() : LiveRegionHost::LiveRegionHost() : m_host(nullptr)
m_host(nullptr) {
{} }
bool LiveRegionHost::IsHostAvailable() bool LiveRegionHost::IsHostAvailable()
{ {
@ -19,12 +19,12 @@ bool LiveRegionHost::IsHostAvailable()
return true; return true;
} }
INarratorAnnouncementHost^ LiveRegionHost::MakeHost() INarratorAnnouncementHost ^ LiveRegionHost::MakeHost()
{ {
return ref new LiveRegionHost(); return ref new LiveRegionHost();
} }
void LiveRegionHost::Announce(NarratorAnnouncement^ announcement) void LiveRegionHost::Announce(NarratorAnnouncement ^ announcement)
{ {
if (m_host == nullptr) if (m_host == nullptr)
{ {
@ -33,7 +33,7 @@ void LiveRegionHost::Announce(NarratorAnnouncement^ announcement)
} }
AutomationProperties::SetName(m_host, announcement->Announcement); AutomationProperties::SetName(m_host, announcement->Announcement);
AutomationPeer^ peer = FrameworkElementAutomationPeer::FromElement(m_host); AutomationPeer ^ peer = FrameworkElementAutomationPeer::FromElement(m_host);
if (peer != nullptr) if (peer != nullptr)
{ {
peer->RaiseAutomationEvent(AutomationEvents::LiveRegionChanged); peer->RaiseAutomationEvent(AutomationEvents::LiveRegionChanged);

View file

@ -16,17 +16,18 @@ namespace CalculatorApp::Common::Automation
// When the app switches to min version RS3, this class can be removed // When the app switches to min version RS3, this class can be removed
// and the app will switch to using the Notification API. // and the app will switch to using the Notification API.
// TODO - MSFT 12735088 // TODO - MSFT 12735088
public ref class LiveRegionHost sealed : public INarratorAnnouncementHost public
ref class LiveRegionHost sealed : public INarratorAnnouncementHost
{ {
public: public:
LiveRegionHost(); LiveRegionHost();
virtual bool IsHostAvailable(); virtual bool IsHostAvailable();
virtual INarratorAnnouncementHost^ MakeHost(); virtual INarratorAnnouncementHost ^ MakeHost();
virtual void Announce(NarratorAnnouncement^ announcement); virtual void Announce(NarratorAnnouncement ^ announcement);
private: private:
Windows::UI::Xaml::UIElement^ m_host; Windows::UI::Xaml::UIElement ^ m_host;
}; };
} }

View file

@ -25,24 +25,18 @@ namespace CalculatorApp::Common::Automation
} }
} }
NarratorAnnouncement::NarratorAnnouncement( NarratorAnnouncement::NarratorAnnouncement(String ^ announcement, String ^ activityId, AutomationNotificationKind kind,
String^ announcement,
String^ activityId,
AutomationNotificationKind kind,
AutomationNotificationProcessing processing) AutomationNotificationProcessing processing)
: : m_announcement(announcement), m_activityId(activityId), m_kind(kind), m_processing(processing)
m_announcement(announcement), {
m_activityId(activityId), }
m_kind(kind),
m_processing(processing)
{}
String^ NarratorAnnouncement::Announcement::get() String ^ NarratorAnnouncement::Announcement::get()
{ {
return m_announcement; return m_announcement;
} }
String^ NarratorAnnouncement::ActivityId::get() String ^ NarratorAnnouncement::ActivityId::get()
{ {
return m_activityId; return m_activityId;
} }
@ -57,108 +51,73 @@ AutomationNotificationProcessing NarratorAnnouncement::Processing::get()
return m_processing; return m_processing;
} }
bool NarratorAnnouncement::IsValid(NarratorAnnouncement^ announcement) bool NarratorAnnouncement::IsValid(NarratorAnnouncement ^ announcement)
{ {
return announcement != nullptr return announcement != nullptr && announcement->Announcement != nullptr && !announcement->Announcement->IsEmpty();
&& announcement->Announcement != nullptr
&& !announcement->Announcement->IsEmpty();
} }
NarratorAnnouncement^ CalculatorAnnouncement::GetDisplayUpdatedAnnouncement(String^ announcement) NarratorAnnouncement ^ CalculatorAnnouncement::GetDisplayUpdatedAnnouncement(String ^ announcement)
{ {
return ref new NarratorAnnouncement( return ref new NarratorAnnouncement(announcement, CalculatorActivityIds::DisplayUpdated, AutomationNotificationKind::Other,
announcement,
CalculatorActivityIds::DisplayUpdated,
AutomationNotificationKind::Other,
AutomationNotificationProcessing::ImportantMostRecent); AutomationNotificationProcessing::ImportantMostRecent);
} }
NarratorAnnouncement^ CalculatorAnnouncement::GetMaxDigitsReachedAnnouncement(String^ announcement) NarratorAnnouncement ^ CalculatorAnnouncement::GetMaxDigitsReachedAnnouncement(String ^ announcement)
{ {
return ref new NarratorAnnouncement( return ref new NarratorAnnouncement(announcement, CalculatorActivityIds::MaxDigitsReached, AutomationNotificationKind::Other,
announcement,
CalculatorActivityIds::MaxDigitsReached,
AutomationNotificationKind::Other,
AutomationNotificationProcessing::ImportantMostRecent); AutomationNotificationProcessing::ImportantMostRecent);
} }
NarratorAnnouncement^ CalculatorAnnouncement::GetMemoryClearedAnnouncement(String^ announcement) NarratorAnnouncement ^ CalculatorAnnouncement::GetMemoryClearedAnnouncement(String ^ announcement)
{ {
return ref new NarratorAnnouncement( return ref new NarratorAnnouncement(announcement, CalculatorActivityIds::MemoryCleared, AutomationNotificationKind::ItemRemoved,
announcement,
CalculatorActivityIds::MemoryCleared,
AutomationNotificationKind::ItemRemoved,
AutomationNotificationProcessing::ImportantMostRecent); AutomationNotificationProcessing::ImportantMostRecent);
} }
NarratorAnnouncement^ CalculatorAnnouncement::GetMemoryItemChangedAnnouncement(String^ announcement) NarratorAnnouncement ^ CalculatorAnnouncement::GetMemoryItemChangedAnnouncement(String ^ announcement)
{ {
return ref new NarratorAnnouncement( return ref new NarratorAnnouncement(announcement, CalculatorActivityIds::MemoryItemChanged, AutomationNotificationKind::ActionCompleted,
announcement,
CalculatorActivityIds::MemoryItemChanged,
AutomationNotificationKind::ActionCompleted,
AutomationNotificationProcessing::MostRecent); AutomationNotificationProcessing::MostRecent);
} }
NarratorAnnouncement^ CalculatorAnnouncement::GetMemoryItemAddedAnnouncement(String^ announcement) NarratorAnnouncement ^ CalculatorAnnouncement::GetMemoryItemAddedAnnouncement(String ^ announcement)
{ {
return ref new NarratorAnnouncement( return ref new NarratorAnnouncement(announcement, CalculatorActivityIds::MemoryItemAdded, AutomationNotificationKind::ItemAdded,
announcement,
CalculatorActivityIds::MemoryItemAdded,
AutomationNotificationKind::ItemAdded,
AutomationNotificationProcessing::MostRecent); AutomationNotificationProcessing::MostRecent);
} }
NarratorAnnouncement^ CalculatorAnnouncement::GetHistoryClearedAnnouncement(String^ announcement) NarratorAnnouncement ^ CalculatorAnnouncement::GetHistoryClearedAnnouncement(String ^ announcement)
{ {
return ref new NarratorAnnouncement( return ref new NarratorAnnouncement(announcement, CalculatorActivityIds::HistoryCleared, AutomationNotificationKind::ItemRemoved,
announcement,
CalculatorActivityIds::HistoryCleared,
AutomationNotificationKind::ItemRemoved,
AutomationNotificationProcessing::MostRecent); AutomationNotificationProcessing::MostRecent);
} }
NarratorAnnouncement^ CalculatorAnnouncement::GetCategoryNameChangedAnnouncement(String^ announcement) NarratorAnnouncement ^ CalculatorAnnouncement::GetCategoryNameChangedAnnouncement(String ^ announcement)
{ {
return ref new NarratorAnnouncement( return ref new NarratorAnnouncement(announcement, CalculatorActivityIds::CategoryNameChanged, AutomationNotificationKind::ActionCompleted,
announcement,
CalculatorActivityIds::CategoryNameChanged,
AutomationNotificationKind::ActionCompleted,
AutomationNotificationProcessing::ImportantMostRecent); AutomationNotificationProcessing::ImportantMostRecent);
} }
NarratorAnnouncement^ CalculatorAnnouncement::GetUpdateCurrencyRatesAnnouncement(String^ announcement) NarratorAnnouncement ^ CalculatorAnnouncement::GetUpdateCurrencyRatesAnnouncement(String ^ announcement)
{ {
return ref new NarratorAnnouncement( return ref new NarratorAnnouncement(announcement, CalculatorActivityIds::UpdateCurrencyRates, AutomationNotificationKind::ActionCompleted,
announcement,
CalculatorActivityIds::UpdateCurrencyRates,
AutomationNotificationKind::ActionCompleted,
AutomationNotificationProcessing::ImportantMostRecent); AutomationNotificationProcessing::ImportantMostRecent);
} }
NarratorAnnouncement^ CalculatorAnnouncement::GetDisplayCopiedAnnouncement(String^ announcement) NarratorAnnouncement ^ CalculatorAnnouncement::GetDisplayCopiedAnnouncement(String ^ announcement)
{ {
return ref new NarratorAnnouncement( return ref new NarratorAnnouncement(announcement, CalculatorActivityIds::DisplayCopied, AutomationNotificationKind::ActionCompleted,
announcement,
CalculatorActivityIds::DisplayCopied,
AutomationNotificationKind::ActionCompleted,
AutomationNotificationProcessing::ImportantMostRecent); AutomationNotificationProcessing::ImportantMostRecent);
} }
NarratorAnnouncement^ CalculatorAnnouncement::GetOpenParenthesisCountChangedAnnouncement(String^ announcement) NarratorAnnouncement ^ CalculatorAnnouncement::GetOpenParenthesisCountChangedAnnouncement(String ^ announcement)
{ {
return ref new NarratorAnnouncement( return ref new NarratorAnnouncement(announcement, CalculatorActivityIds::OpenParenthesisCountChanged, AutomationNotificationKind::ActionCompleted,
announcement,
CalculatorActivityIds::OpenParenthesisCountChanged,
AutomationNotificationKind::ActionCompleted,
AutomationNotificationProcessing::ImportantMostRecent); AutomationNotificationProcessing::ImportantMostRecent);
} }
NarratorAnnouncement^ CalculatorAnnouncement::GetNoRightParenthesisAddedAnnouncement(String^ announcement) NarratorAnnouncement ^ CalculatorAnnouncement::GetNoRightParenthesisAddedAnnouncement(String ^ announcement)
{ {
return ref new NarratorAnnouncement( return ref new NarratorAnnouncement(announcement, CalculatorActivityIds::NoParenthesisAdded, AutomationNotificationKind::ActionCompleted,
announcement,
CalculatorActivityIds::NoParenthesisAdded,
AutomationNotificationKind::ActionCompleted,
AutomationNotificationProcessing::ImportantMostRecent); AutomationNotificationProcessing::ImportantMostRecent);
} }

View file

@ -11,7 +11,8 @@ namespace CalculatorApp::Common::Automation
// enums should be removed and the Windows types should be used // enums should be removed and the Windows types should be used
// instead. // instead.
// TODO - MSFT 12735088 // TODO - MSFT 12735088
public enum class AutomationNotificationKind public
enum class AutomationNotificationKind
{ {
ItemAdded = 0, ItemAdded = 0,
ItemRemoved = 1, ItemRemoved = 1,
@ -20,7 +21,8 @@ namespace CalculatorApp::Common::Automation
Other = 4 Other = 4
}; };
public enum class AutomationNotificationProcessing public
enum class AutomationNotificationProcessing
{ {
ImportantAll = 0, ImportantAll = 0,
ImportantMostRecent = 1, ImportantMostRecent = 1,
@ -29,18 +31,15 @@ namespace CalculatorApp::Common::Automation
CurrentThenMostRecent = 4 CurrentThenMostRecent = 4
}; };
public ref class NarratorAnnouncement sealed public
ref class NarratorAnnouncement sealed
{ {
public: public:
property Platform::String^ Announcement property Platform::String
{ ^ Announcement { Platform::String ^ get(); }
Platform::String^ get();
}
property Platform::String^ ActivityId property Platform::String
{ ^ ActivityId { Platform::String ^ get(); }
Platform::String^ get();
}
property AutomationNotificationKind Kind property AutomationNotificationKind Kind
{ {
@ -52,21 +51,18 @@ namespace CalculatorApp::Common::Automation
AutomationNotificationProcessing get(); AutomationNotificationProcessing get();
} }
static bool IsValid(NarratorAnnouncement^ announcement); static bool IsValid(NarratorAnnouncement ^ announcement);
private: private:
// Make CalculatorAnnouncement a friend class so it is the only // Make CalculatorAnnouncement a friend class so it is the only
// class that can access the private constructor. // class that can access the private constructor.
friend class CalculatorAnnouncement; friend class CalculatorAnnouncement;
NarratorAnnouncement( NarratorAnnouncement(Platform::String ^ announcement, Platform::String ^ activityId, AutomationNotificationKind kind,
Platform::String^ announcement,
Platform::String^ activityId,
AutomationNotificationKind kind,
AutomationNotificationProcessing processing); AutomationNotificationProcessing processing);
Platform::String^ m_announcement; Platform::String ^ m_announcement;
Platform::String^ m_activityId; Platform::String ^ m_activityId;
AutomationNotificationKind m_kind; AutomationNotificationKind m_kind;
AutomationNotificationProcessing m_processing; AutomationNotificationProcessing m_processing;
}; };
@ -76,22 +72,22 @@ namespace CalculatorApp::Common::Automation
class CalculatorAnnouncement class CalculatorAnnouncement
{ {
public: public:
static NarratorAnnouncement^ GetDisplayUpdatedAnnouncement(Platform::String^ announcement); static NarratorAnnouncement ^ GetDisplayUpdatedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement^ GetMaxDigitsReachedAnnouncement(Platform::String^ announcement); static NarratorAnnouncement ^ GetMaxDigitsReachedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement^ GetMemoryClearedAnnouncement(Platform::String^ announcement); static NarratorAnnouncement ^ GetMemoryClearedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement^ GetMemoryItemChangedAnnouncement(Platform::String^ announcement); static NarratorAnnouncement ^ GetMemoryItemChangedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement^ GetMemoryItemAddedAnnouncement(Platform::String^ announcement); static NarratorAnnouncement ^ GetMemoryItemAddedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement^ GetHistoryClearedAnnouncement(Platform::String^ announcement); static NarratorAnnouncement ^ GetHistoryClearedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement^ GetCategoryNameChangedAnnouncement(Platform::String^ announcement); static NarratorAnnouncement ^ GetCategoryNameChangedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement^ GetUpdateCurrencyRatesAnnouncement(Platform::String^ announcement); static NarratorAnnouncement ^ GetUpdateCurrencyRatesAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement^ GetDisplayCopiedAnnouncement(Platform::String^ announcement); static NarratorAnnouncement ^ GetDisplayCopiedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement^ GetOpenParenthesisCountChangedAnnouncement(Platform::String^ announcement); static NarratorAnnouncement ^ GetOpenParenthesisCountChangedAnnouncement(Platform::String ^ announcement);
static NarratorAnnouncement^ GetNoRightParenthesisAddedAnnouncement(Platform::String ^ announcement); static NarratorAnnouncement ^ GetNoRightParenthesisAddedAnnouncement(Platform::String ^ announcement);
}; };
} }

View file

@ -9,8 +9,8 @@
using namespace CalculatorApp::Common::Automation; using namespace CalculatorApp::Common::Automation;
using namespace std; using namespace std;
INarratorAnnouncementHost^ NarratorAnnouncementHostFactory::s_hostProducer; INarratorAnnouncementHost ^ NarratorAnnouncementHostFactory::s_hostProducer;
vector<INarratorAnnouncementHost^> NarratorAnnouncementHostFactory::s_hosts; vector<INarratorAnnouncementHost ^> NarratorAnnouncementHostFactory::s_hosts;
// This static variable is used only to call the initialization function, to initialize the other static variables. // This static variable is used only to call the initialization function, to initialize the other static variables.
int NarratorAnnouncementHostFactory::s_init = NarratorAnnouncementHostFactory::Initialize(); int NarratorAnnouncementHostFactory::s_init = NarratorAnnouncementHostFactory::Initialize();
@ -32,15 +32,12 @@ void NarratorAnnouncementHostFactory::RegisterHosts()
{ {
// The host that will be used is the first available host, // The host that will be used is the first available host,
// therefore, order of hosts is important here. // therefore, order of hosts is important here.
NarratorAnnouncementHostFactory::s_hosts = { NarratorAnnouncementHostFactory::s_hosts = { ref new NotificationHost(), ref new LiveRegionHost() };
ref new NotificationHost(),
ref new LiveRegionHost()
};
} }
INarratorAnnouncementHost^ NarratorAnnouncementHostFactory::GetHostProducer() INarratorAnnouncementHost ^ NarratorAnnouncementHostFactory::GetHostProducer()
{ {
for (INarratorAnnouncementHost^ host : NarratorAnnouncementHostFactory::s_hosts) for (INarratorAnnouncementHost ^ host : NarratorAnnouncementHostFactory::s_hosts)
{ {
if (host->IsHostAvailable()) if (host->IsHostAvailable())
{ {
@ -52,7 +49,7 @@ INarratorAnnouncementHost^ NarratorAnnouncementHostFactory::GetHostProducer()
return nullptr; return nullptr;
} }
INarratorAnnouncementHost^ NarratorAnnouncementHostFactory::MakeHost() INarratorAnnouncementHost ^ NarratorAnnouncementHostFactory::MakeHost()
{ {
if (NarratorAnnouncementHostFactory::s_hostProducer == nullptr) if (NarratorAnnouncementHostFactory::s_hostProducer == nullptr)
{ {

View file

@ -14,18 +14,20 @@ namespace CalculatorApp::Common::Automation
class NarratorAnnouncementHostFactory class NarratorAnnouncementHostFactory
{ {
public: public:
static INarratorAnnouncementHost^ MakeHost(); static INarratorAnnouncementHost ^ MakeHost();
private: private:
NarratorAnnouncementHostFactory() {} NarratorAnnouncementHostFactory()
{
}
static int Initialize(); static int Initialize();
static void RegisterHosts(); static void RegisterHosts();
static INarratorAnnouncementHost^ GetHostProducer(); static INarratorAnnouncementHost ^ GetHostProducer();
private: private:
static int s_init; static int s_init;
static INarratorAnnouncementHost^ s_hostProducer; static INarratorAnnouncementHost ^ s_hostProducer;
static std::vector<INarratorAnnouncementHost^> s_hosts; static std::vector<INarratorAnnouncementHost ^> s_hosts;
}; };
} }

View file

@ -13,17 +13,16 @@ using namespace Windows::UI::Xaml;
using namespace Windows::UI::Xaml::Automation; using namespace Windows::UI::Xaml::Automation;
using namespace Windows::UI::Xaml::Automation::Peers; using namespace Windows::UI::Xaml::Automation::Peers;
DependencyProperty^ NarratorNotifier::s_announcementProperty; DependencyProperty ^ NarratorNotifier::s_announcementProperty;
NarratorNotifier::NarratorNotifier() NarratorNotifier::NarratorNotifier()
{ {
m_announcementHost = NarratorAnnouncementHostFactory::MakeHost(); m_announcementHost = NarratorAnnouncementHostFactory::MakeHost();
} }
void NarratorNotifier::Announce(NarratorAnnouncement^ announcement) void NarratorNotifier::Announce(NarratorAnnouncement ^ announcement)
{ {
if (NarratorAnnouncement::IsValid(announcement) if (NarratorAnnouncement::IsValid(announcement) && m_announcementHost != nullptr)
&& m_announcementHost != nullptr)
{ {
m_announcementHost->Announce(announcement); m_announcementHost->Announce(announcement);
} }
@ -31,20 +30,18 @@ void NarratorNotifier::Announce(NarratorAnnouncement^ announcement)
void NarratorNotifier::RegisterDependencyProperties() void NarratorNotifier::RegisterDependencyProperties()
{ {
s_announcementProperty = DependencyProperty::Register( s_announcementProperty = DependencyProperty::Register(L"Announcement", // The name of the dependency property.
L"Announcement", // The name of the dependency property.
NarratorAnnouncement::typeid, // The type of the dependency property. NarratorAnnouncement::typeid, // The type of the dependency property.
NarratorNotifier::typeid, // The owner of the dependency property. NarratorNotifier::typeid, // The owner of the dependency property.
ref new PropertyMetadata( ref new PropertyMetadata(nullptr, // Default value of the dependency property.
nullptr, // Default value of the dependency property.
ref new PropertyChangedCallback(OnAnnouncementChanged))); ref new PropertyChangedCallback(OnAnnouncementChanged)));
} }
void NarratorNotifier::OnAnnouncementChanged(_In_ DependencyObject^ dependencyObject, _In_ DependencyPropertyChangedEventArgs^ e) void NarratorNotifier::OnAnnouncementChanged(_In_ DependencyObject ^ dependencyObject, _In_ DependencyPropertyChangedEventArgs ^ e)
{ {
auto instance = safe_cast<NarratorNotifier^>(dependencyObject); auto instance = safe_cast<NarratorNotifier ^>(dependencyObject);
if (instance != nullptr) if (instance != nullptr)
{ {
instance->Announce(safe_cast<NarratorAnnouncement^>(e->NewValue)); instance->Announce(safe_cast<NarratorAnnouncement ^>(e->NewValue));
} }
} }

View file

@ -8,12 +8,13 @@
namespace CalculatorApp::Common::Automation namespace CalculatorApp::Common::Automation
{ {
public ref class NarratorNotifier sealed : public Windows::UI::Xaml::DependencyObject public
ref class NarratorNotifier sealed : public Windows::UI::Xaml::DependencyObject
{ {
public: public:
NarratorNotifier(); NarratorNotifier();
void Announce(NarratorAnnouncement^ announcement); void Announce(NarratorAnnouncement ^ announcement);
property NarratorAnnouncement^ Announcement property NarratorAnnouncement^ Announcement
{ {
@ -26,32 +27,25 @@ namespace CalculatorApp::Common::Automation
static void RegisterDependencyProperties(); static void RegisterDependencyProperties();
static property Windows::UI::Xaml::DependencyProperty^ AnnouncementProperty static property Windows::UI::Xaml::DependencyProperty
{ ^ AnnouncementProperty { Windows::UI::Xaml::DependencyProperty ^ get() { return s_announcementProperty; } }
Windows::UI::Xaml::DependencyProperty^ get()
{
return s_announcementProperty;
}
}
static NarratorAnnouncement^ GetAnnouncement(Windows::UI::Xaml::DependencyObject^ element) static NarratorAnnouncement
{ ^ GetAnnouncement(Windows::UI::Xaml::DependencyObject
return safe_cast<NarratorAnnouncement^>(element->GetValue(s_announcementProperty)); ^ element) { return safe_cast<NarratorAnnouncement ^>(element->GetValue(s_announcementProperty)); }
}
static void SetAnnouncement(Windows::UI::Xaml::DependencyObject^ element, NarratorAnnouncement^ value) static void SetAnnouncement(Windows::UI::Xaml::DependencyObject ^ element, NarratorAnnouncement ^ value)
{ {
element->SetValue(s_announcementProperty, value); element->SetValue(s_announcementProperty, value);
} }
private: private:
static void OnAnnouncementChanged( static void OnAnnouncementChanged(_In_ Windows::UI::Xaml::DependencyObject ^ dependencyObject,
_In_ Windows::UI::Xaml::DependencyObject^ dependencyObject, _In_ Windows::UI::Xaml::DependencyPropertyChangedEventArgs ^ eventArgs);
_In_ Windows::UI::Xaml::DependencyPropertyChangedEventArgs^ eventArgs);
static Windows::UI::Xaml::DependencyProperty^ s_announcementProperty; static Windows::UI::Xaml::DependencyProperty ^ s_announcementProperty;
private: private:
INarratorAnnouncementHost^ m_announcementHost; INarratorAnnouncementHost ^ m_announcementHost;
}; };
} }

View file

@ -10,23 +10,21 @@ using namespace Windows::UI::Xaml::Automation;
using namespace Windows::UI::Xaml::Automation::Peers; using namespace Windows::UI::Xaml::Automation::Peers;
using namespace Windows::UI::Xaml::Controls; using namespace Windows::UI::Xaml::Controls;
NotificationHost::NotificationHost() : NotificationHost::NotificationHost() : m_host(nullptr)
m_host(nullptr) {
{} }
bool NotificationHost::IsHostAvailable() bool NotificationHost::IsHostAvailable()
{ {
return ApiInformation::IsMethodPresent( return ApiInformation::IsMethodPresent(L"Windows.UI.Xaml.Automation.Peers.AutomationPeer", L"RaiseNotificationEvent");
L"Windows.UI.Xaml.Automation.Peers.AutomationPeer",
L"RaiseNotificationEvent");
} }
INarratorAnnouncementHost^ NotificationHost::MakeHost() INarratorAnnouncementHost ^ NotificationHost::MakeHost()
{ {
return ref new NotificationHost(); return ref new NotificationHost();
} }
void NotificationHost::Announce(NarratorAnnouncement^ announcement) void NotificationHost::Announce(NarratorAnnouncement ^ announcement)
{ {
if (m_host == nullptr) if (m_host == nullptr)
{ {
@ -36,16 +34,12 @@ void NotificationHost::Announce(NarratorAnnouncement^ announcement)
auto peer = FrameworkElementAutomationPeer::FromElement(m_host); auto peer = FrameworkElementAutomationPeer::FromElement(m_host);
if (peer != nullptr) if (peer != nullptr)
{ {
peer->RaiseNotificationEvent( peer->RaiseNotificationEvent(GetWindowsNotificationKind(announcement->Kind), GetWindowsNotificationProcessing(announcement->Processing),
GetWindowsNotificationKind(announcement->Kind), announcement->Announcement, announcement->ActivityId);
GetWindowsNotificationProcessing(announcement->Processing),
announcement->Announcement,
announcement->ActivityId);
} }
} }
StandardPeers::AutomationNotificationKind NotificationHost::GetWindowsNotificationKind( StandardPeers::AutomationNotificationKind NotificationHost::GetWindowsNotificationKind(CustomPeers::AutomationNotificationKind customKindType)
CustomPeers::AutomationNotificationKind customKindType)
{ {
switch (customKindType) switch (customKindType)
{ {
@ -71,8 +65,8 @@ StandardPeers::AutomationNotificationKind NotificationHost::GetWindowsNotificati
return StandardPeers::AutomationNotificationKind::Other; return StandardPeers::AutomationNotificationKind::Other;
} }
StandardPeers::AutomationNotificationProcessing NotificationHost::GetWindowsNotificationProcessing( StandardPeers::AutomationNotificationProcessing
CustomPeers::AutomationNotificationProcessing customProcessingType) NotificationHost::GetWindowsNotificationProcessing(CustomPeers::AutomationNotificationProcessing customProcessingType)
{ {
switch (customProcessingType) switch (customProcessingType)
{ {

View file

@ -10,25 +10,25 @@
namespace CalculatorApp::Common::Automation namespace CalculatorApp::Common::Automation
{ {
public ref class NotificationHost sealed : public INarratorAnnouncementHost public
ref class NotificationHost sealed : public INarratorAnnouncementHost
{ {
public: public:
NotificationHost(); NotificationHost();
virtual bool IsHostAvailable(); virtual bool IsHostAvailable();
virtual INarratorAnnouncementHost^ MakeHost(); virtual INarratorAnnouncementHost ^ MakeHost();
virtual void Announce(NarratorAnnouncement^ announcement); virtual void Announce(NarratorAnnouncement ^ announcement);
private: private:
static Windows::UI::Xaml::Automation::Peers::AutomationNotificationKind GetWindowsNotificationKind( static Windows::UI::Xaml::Automation::Peers::AutomationNotificationKind
CalculatorApp::Common::Automation::AutomationNotificationKind customKindType); GetWindowsNotificationKind(CalculatorApp::Common::Automation::AutomationNotificationKind customKindType);
static Windows::UI::Xaml::Automation::Peers::AutomationNotificationProcessing GetWindowsNotificationProcessing( static Windows::UI::Xaml::Automation::Peers::AutomationNotificationProcessing
CalculatorApp::Common::Automation::AutomationNotificationProcessing customProcessingType); GetWindowsNotificationProcessing(CalculatorApp::Common::Automation::AutomationNotificationProcessing customProcessingType);
private: private:
Windows::UI::Xaml::UIElement^ m_host; Windows::UI::Xaml::UIElement ^ m_host;
}; };
} }

View file

@ -13,22 +13,22 @@ using namespace Windows::UI::Xaml::Data;
/// Notifies listeners that a property value has changed. /// Notifies listeners that a property value has changed.
/// </summary> /// </summary>
/// <param name="propertyName">Name of the property used to notify listeners.</param> /// <param name="propertyName">Name of the property used to notify listeners.</param>
void BindableBase::OnPropertyChanged(String^ propertyName) void BindableBase::OnPropertyChanged(String ^ propertyName)
{ {
PropertyChanged(this, ref new PropertyChangedEventArgs(propertyName)); PropertyChanged(this, ref new PropertyChangedEventArgs(propertyName));
} }
Windows::UI::Xaml::Data::ICustomProperty^ BindableBase::GetCustomProperty(Platform::String^ name) Windows::UI::Xaml::Data::ICustomProperty ^ BindableBase::GetCustomProperty(Platform::String ^ name)
{ {
return nullptr; return nullptr;
} }
Windows::UI::Xaml::Data::ICustomProperty^ BindableBase::GetIndexedProperty(Platform::String^ name, Windows::UI::Xaml::Interop::TypeName type) Windows::UI::Xaml::Data::ICustomProperty ^ BindableBase::GetIndexedProperty(Platform::String ^ name, Windows::UI::Xaml::Interop::TypeName type)
{ {
return nullptr; return nullptr;
} }
Platform::String^ BindableBase::GetStringRepresentation() Platform::String ^ BindableBase::GetStringRepresentation()
{ {
return this->ToString(); return this->ToString();
} }

View file

@ -10,26 +10,29 @@ namespace CalculatorApp
/// <summary> /// <summary>
/// Implementation of <see cref="INotifyPropertyChanged"/> to simplify models. /// Implementation of <see cref="INotifyPropertyChanged"/> to simplify models.
/// </summary> /// </summary>
[Windows::Foundation::Metadata::WebHostHidden] [Windows::Foundation::Metadata::WebHostHidden] public ref class BindableBase : Windows::UI::Xaml::DependencyObject,
public ref class BindableBase : Windows::UI::Xaml::DependencyObject, Windows::UI::Xaml::Data::INotifyPropertyChanged, Windows::UI::Xaml::Data::ICustomPropertyProvider Windows::UI::Xaml::Data::INotifyPropertyChanged,
Windows::UI::Xaml::Data::ICustomPropertyProvider
{ {
public: public:
virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler^ PropertyChanged; virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler ^ PropertyChanged;
public: public:
// ICustomPropertyProvider // ICustomPropertyProvider
virtual Windows::UI::Xaml::Data::ICustomProperty^ GetCustomProperty(Platform::String^ name); virtual Windows::UI::Xaml::Data::ICustomProperty ^ GetCustomProperty(Platform::String ^ name);
virtual Windows::UI::Xaml::Data::ICustomProperty^ GetIndexedProperty(Platform::String^ name, Windows::UI::Xaml::Interop::TypeName type); virtual Windows::UI::Xaml::Data::ICustomProperty ^ GetIndexedProperty(Platform::String ^ name, Windows::UI::Xaml::Interop::TypeName type);
virtual Platform::String^ GetStringRepresentation(); virtual Platform::String ^ GetStringRepresentation();
property Windows::UI::Xaml::Interop::TypeName Type property Windows::UI::Xaml::Interop::TypeName Type
{ {
virtual Windows::UI::Xaml::Interop::TypeName get() { return this->GetType(); } virtual Windows::UI::Xaml::Interop::TypeName get()
{
return this->GetType();
}
} }
protected: protected:
virtual void OnPropertyChanged(Platform::String^ propertyName); virtual void OnPropertyChanged(Platform::String ^ propertyName);
}; };
} }
} }

View file

@ -8,9 +8,9 @@ using namespace CalculatorApp;
using namespace CalculatorApp::Common; using namespace CalculatorApp::Common;
using namespace Platform; using namespace Platform;
NumbersAndOperatorsEnum CalculatorButtonPressedEventArgs::GetOperationFromCommandParameter(_In_ Object^ commandParameter) NumbersAndOperatorsEnum CalculatorButtonPressedEventArgs::GetOperationFromCommandParameter(_In_ Object ^ commandParameter)
{ {
auto eventArgs = dynamic_cast<CalculatorButtonPressedEventArgs^>(commandParameter); auto eventArgs = dynamic_cast<CalculatorButtonPressedEventArgs ^>(commandParameter);
if (eventArgs != nullptr) if (eventArgs != nullptr)
{ {
return eventArgs->Operation; return eventArgs->Operation;
@ -21,9 +21,9 @@ NumbersAndOperatorsEnum CalculatorButtonPressedEventArgs::GetOperationFromComman
} }
} }
String^ CalculatorButtonPressedEventArgs::GetAuditoryFeedbackFromCommandParameter(_In_ Object^ commandParameter) String ^ CalculatorButtonPressedEventArgs::GetAuditoryFeedbackFromCommandParameter(_In_ Object ^ commandParameter)
{ {
auto eventArgs = dynamic_cast<CalculatorButtonPressedEventArgs^>(commandParameter); auto eventArgs = dynamic_cast<CalculatorButtonPressedEventArgs ^>(commandParameter);
if (eventArgs != nullptr) if (eventArgs != nullptr)
{ {
return eventArgs->AuditoryFeedback; return eventArgs->AuditoryFeedback;
@ -33,4 +33,3 @@ String^ CalculatorButtonPressedEventArgs::GetAuditoryFeedbackFromCommandParamete
return nullptr; return nullptr;
} }
} }

View file

@ -10,18 +10,20 @@ namespace CalculatorApp
{ {
namespace Common namespace Common
{ {
public ref class CalculatorButtonPressedEventArgs sealed public
ref class CalculatorButtonPressedEventArgs sealed
{ {
public: public:
PROPERTY_R(Platform::String^, AuditoryFeedback); PROPERTY_R(Platform::String ^, AuditoryFeedback);
PROPERTY_R(CalculatorApp::NumbersAndOperatorsEnum, Operation); PROPERTY_R(CalculatorApp::NumbersAndOperatorsEnum, Operation);
CalculatorButtonPressedEventArgs( CalculatorButtonPressedEventArgs(Platform::String ^ feedback, CalculatorApp::NumbersAndOperatorsEnum operation)
Platform::String^ feedback, CalculatorApp::NumbersAndOperatorsEnum operation) : : m_AuditoryFeedback(feedback), m_Operation(operation)
m_AuditoryFeedback(feedback), m_Operation(operation) {} {
}
static CalculatorApp::NumbersAndOperatorsEnum GetOperationFromCommandParameter(_In_ Platform::Object^ commandParameter); static CalculatorApp::NumbersAndOperatorsEnum GetOperationFromCommandParameter(_In_ Platform::Object ^ commandParameter);
static Platform::String^ GetAuditoryFeedbackFromCommandParameter(_In_ Platform::Object^ commandParameter); static Platform::String ^ GetAuditoryFeedbackFromCommandParameter(_In_ Platform::Object ^ commandParameter);
}; };
} }
} }

View file

@ -9,205 +9,207 @@ namespace CalculatorApp
{ {
namespace CM = CalculationManager; namespace CM = CalculationManager;
public enum class NumbersAndOperatorsEnum public
enum class NumbersAndOperatorsEnum
{ {
Zero = (int) CM::Command::Command0, Zero = (int)CM::Command::Command0,
One = (int) CM::Command::Command1, One = (int)CM::Command::Command1,
Two = (int) CM::Command::Command2, Two = (int)CM::Command::Command2,
Three = (int) CM::Command::Command3, Three = (int)CM::Command::Command3,
Four = (int) CM::Command::Command4, Four = (int)CM::Command::Command4,
Five = (int) CM::Command::Command5, Five = (int)CM::Command::Command5,
Six = (int) CM::Command::Command6, Six = (int)CM::Command::Command6,
Seven = (int) CM::Command::Command7, Seven = (int)CM::Command::Command7,
Eight = (int) CM::Command::Command8, Eight = (int)CM::Command::Command8,
Nine = (int) CM::Command::Command9, Nine = (int)CM::Command::Command9,
Add = (int) CM::Command::CommandADD, Add = (int)CM::Command::CommandADD,
Subtract = (int) CM::Command::CommandSUB, Subtract = (int)CM::Command::CommandSUB,
Multiply = (int) CM::Command::CommandMUL, Multiply = (int)CM::Command::CommandMUL,
Divide = (int) CM::Command::CommandDIV, Divide = (int)CM::Command::CommandDIV,
Invert = (int) CM::Command::CommandREC, Invert = (int)CM::Command::CommandREC,
Equals = (int) CM::Command::CommandEQU, Equals = (int)CM::Command::CommandEQU,
Decimal = (int) CM::Command::CommandPNT, Decimal = (int)CM::Command::CommandPNT,
Sqrt = (int) CM::Command::CommandSQRT, Sqrt = (int)CM::Command::CommandSQRT,
Percent = (int) CM::Command::CommandPERCENT, Percent = (int)CM::Command::CommandPERCENT,
Negate = (int) CM::Command::CommandSIGN, Negate = (int)CM::Command::CommandSIGN,
Backspace = (int) CM::Command::CommandBACK, Backspace = (int)CM::Command::CommandBACK,
ClearEntry = (int) CM::Command::CommandCENTR, ClearEntry = (int)CM::Command::CommandCENTR,
Clear = (int) CM::Command::CommandCLEAR, Clear = (int)CM::Command::CommandCLEAR,
Degree = (int) CM::Command::CommandDEG, Degree = (int)CM::Command::CommandDEG,
Radians = (int) CM::Command::CommandRAD, Radians = (int)CM::Command::CommandRAD,
Grads = (int) CM::Command::CommandGRAD, Grads = (int)CM::Command::CommandGRAD,
Degrees = (int) CM::Command::CommandDegrees, Degrees = (int)CM::Command::CommandDegrees,
OpenParenthesis = (int) CM::Command::CommandOPENP, OpenParenthesis = (int)CM::Command::CommandOPENP,
CloseParenthesis = (int) CM::Command::CommandCLOSEP, CloseParenthesis = (int)CM::Command::CommandCLOSEP,
Pi = (int) CM::Command::CommandPI, Pi = (int)CM::Command::CommandPI,
Sin = (int) CM::Command::CommandSIN, Sin = (int)CM::Command::CommandSIN,
Cos = (int) CM::Command::CommandCOS, Cos = (int)CM::Command::CommandCOS,
Tan = (int) CM::Command::CommandTAN, Tan = (int)CM::Command::CommandTAN,
Factorial = (int) CM::Command::CommandFAC, Factorial = (int)CM::Command::CommandFAC,
XPower2 = (int) CM::Command::CommandSQR, XPower2 = (int)CM::Command::CommandSQR,
Mod = (int) CM::Command::CommandMOD, Mod = (int)CM::Command::CommandMOD,
FToE = (int) CM::Command::CommandFE, FToE = (int)CM::Command::CommandFE,
LogBaseE = (int) CM::Command::CommandLN, LogBaseE = (int)CM::Command::CommandLN,
InvSin = (int) CM::Command::CommandASIN, InvSin = (int)CM::Command::CommandASIN,
InvCos = (int) CM::Command::CommandACOS, InvCos = (int)CM::Command::CommandACOS,
InvTan = (int) CM::Command::CommandATAN, InvTan = (int)CM::Command::CommandATAN,
LogBase10 = (int) CM::Command::CommandLOG, LogBase10 = (int)CM::Command::CommandLOG,
XPowerY = (int) CM::Command::CommandPWR, XPowerY = (int)CM::Command::CommandPWR,
YRootX = (int) CM::Command::CommandROOT, YRootX = (int)CM::Command::CommandROOT,
TenPowerX = (int) CM::Command::CommandPOW10, TenPowerX = (int)CM::Command::CommandPOW10,
EPowerX = (int) CM::Command::CommandPOWE, EPowerX = (int)CM::Command::CommandPOWE,
Exp = (int) CM::Command::CommandEXP, Exp = (int)CM::Command::CommandEXP,
IsScientificMode = (int) CM::Command::ModeScientific, IsScientificMode = (int)CM::Command::ModeScientific,
IsStandardMode = (int) CM::Command::ModeBasic, IsStandardMode = (int)CM::Command::ModeBasic,
None = (int) CM::Command::CommandNULL, None = (int)CM::Command::CommandNULL,
IsProgrammerMode = (int) CM::Command::ModeProgrammer, IsProgrammerMode = (int)CM::Command::ModeProgrammer,
DecButton = (int) CM::Command::CommandDec, DecButton = (int)CM::Command::CommandDec,
OctButton = (int) CM::Command::CommandOct, OctButton = (int)CM::Command::CommandOct,
HexButton = (int) CM::Command::CommandHex, HexButton = (int)CM::Command::CommandHex,
BinButton = (int) CM::Command::CommandBin, BinButton = (int)CM::Command::CommandBin,
And = (int) CM::Command::CommandAnd, And = (int)CM::Command::CommandAnd,
Ror = (int) CM::Command::CommandROR, Ror = (int)CM::Command::CommandROR,
Rol = (int) CM::Command::CommandROL, Rol = (int)CM::Command::CommandROL,
Or = (int) CM::Command::CommandOR, Or = (int)CM::Command::CommandOR,
Lsh = (int) CM::Command::CommandLSHF, Lsh = (int)CM::Command::CommandLSHF,
Rsh = (int) CM::Command::CommandRSHF, Rsh = (int)CM::Command::CommandRSHF,
Xor = (int) CM::Command::CommandXor, Xor = (int)CM::Command::CommandXor,
Not = (int) CM::Command::CommandNot, Not = (int)CM::Command::CommandNot,
A = (int) CM::Command::CommandA, A = (int)CM::Command::CommandA,
B = (int) CM::Command::CommandB, B = (int)CM::Command::CommandB,
C = (int) CM::Command::CommandC, C = (int)CM::Command::CommandC,
D = (int) CM::Command::CommandD, D = (int)CM::Command::CommandD,
E = (int) CM::Command::CommandE, E = (int)CM::Command::CommandE,
F = (int) CM::Command::CommandF, F = (int)CM::Command::CommandF,
Memory, // This is the memory button. Doesn't have a direct mapping to the CalcEngine. Memory, // This is the memory button. Doesn't have a direct mapping to the CalcEngine.
Sinh = (int) CM::Command::CommandSINH, Sinh = (int)CM::Command::CommandSINH,
Cosh = (int) CM::Command::CommandCOSH, Cosh = (int)CM::Command::CommandCOSH,
Tanh = (int) CM::Command::CommandTANH, Tanh = (int)CM::Command::CommandTANH,
InvSinh = (int) CM::Command::CommandASINH, InvSinh = (int)CM::Command::CommandASINH,
InvCosh = (int) CM::Command::CommandACOSH, InvCosh = (int)CM::Command::CommandACOSH,
InvTanh = (int) CM::Command::CommandATANH, InvTanh = (int)CM::Command::CommandATANH,
Qword = (int) CM::Command::CommandQword, Qword = (int)CM::Command::CommandQword,
Dword = (int) CM::Command::CommandDword, Dword = (int)CM::Command::CommandDword,
Word = (int) CM::Command::CommandWord, Word = (int)CM::Command::CommandWord,
Byte = (int) CM::Command::CommandByte, Byte = (int)CM::Command::CommandByte,
Cube = (int) CM::Command::CommandCUB, Cube = (int)CM::Command::CommandCUB,
DMS = (int) CM::Command::CommandDMS, DMS = (int)CM::Command::CommandDMS,
BINSTART = (int) CM::Command::CommandBINEDITSTART, BINSTART = (int)CM::Command::CommandBINEDITSTART,
BINPOS0 = (int) CM::Command::CommandBINPOS0, BINPOS0 = (int)CM::Command::CommandBINPOS0,
BINPOS1 = (int) CM::Command::CommandBINPOS1, BINPOS1 = (int)CM::Command::CommandBINPOS1,
BINPOS2 = (int) CM::Command::CommandBINPOS2, BINPOS2 = (int)CM::Command::CommandBINPOS2,
BINPOS3 = (int) CM::Command::CommandBINPOS3, BINPOS3 = (int)CM::Command::CommandBINPOS3,
BINPOS4 = (int) CM::Command::CommandBINPOS4, BINPOS4 = (int)CM::Command::CommandBINPOS4,
BINPOS5 = (int) CM::Command::CommandBINPOS5, BINPOS5 = (int)CM::Command::CommandBINPOS5,
BINPOS6 = (int) CM::Command::CommandBINPOS6, BINPOS6 = (int)CM::Command::CommandBINPOS6,
BINPOS7 = (int) CM::Command::CommandBINPOS7, BINPOS7 = (int)CM::Command::CommandBINPOS7,
BINPOS8 = (int) CM::Command::CommandBINPOS8, BINPOS8 = (int)CM::Command::CommandBINPOS8,
BINPOS9 = (int) CM::Command::CommandBINPOS9, BINPOS9 = (int)CM::Command::CommandBINPOS9,
BINPOS10 = (int) CM::Command::CommandBINPOS10, BINPOS10 = (int)CM::Command::CommandBINPOS10,
BINPOS11 = (int) CM::Command::CommandBINPOS11, BINPOS11 = (int)CM::Command::CommandBINPOS11,
BINPOS12 = (int) CM::Command::CommandBINPOS12, BINPOS12 = (int)CM::Command::CommandBINPOS12,
BINPOS13 = (int) CM::Command::CommandBINPOS13, BINPOS13 = (int)CM::Command::CommandBINPOS13,
BINPOS14 = (int) CM::Command::CommandBINPOS14, BINPOS14 = (int)CM::Command::CommandBINPOS14,
BINPOS15 = (int) CM::Command::CommandBINPOS15, BINPOS15 = (int)CM::Command::CommandBINPOS15,
BINPOS16 = (int) CM::Command::CommandBINPOS16, BINPOS16 = (int)CM::Command::CommandBINPOS16,
BINPOS17 = (int) CM::Command::CommandBINPOS17, BINPOS17 = (int)CM::Command::CommandBINPOS17,
BINPOS18 = (int) CM::Command::CommandBINPOS18, BINPOS18 = (int)CM::Command::CommandBINPOS18,
BINPOS19 = (int) CM::Command::CommandBINPOS19, BINPOS19 = (int)CM::Command::CommandBINPOS19,
BINPOS20 = (int) CM::Command::CommandBINPOS20, BINPOS20 = (int)CM::Command::CommandBINPOS20,
BINPOS21 = (int) CM::Command::CommandBINPOS21, BINPOS21 = (int)CM::Command::CommandBINPOS21,
BINPOS22 = (int) CM::Command::CommandBINPOS22, BINPOS22 = (int)CM::Command::CommandBINPOS22,
BINPOS23 = (int) CM::Command::CommandBINPOS23, BINPOS23 = (int)CM::Command::CommandBINPOS23,
BINPOS24 = (int) CM::Command::CommandBINPOS24, BINPOS24 = (int)CM::Command::CommandBINPOS24,
BINPOS25 = (int) CM::Command::CommandBINPOS25, BINPOS25 = (int)CM::Command::CommandBINPOS25,
BINPOS26 = (int) CM::Command::CommandBINPOS26, BINPOS26 = (int)CM::Command::CommandBINPOS26,
BINPOS27 = (int) CM::Command::CommandBINPOS27, BINPOS27 = (int)CM::Command::CommandBINPOS27,
BINPOS28 = (int) CM::Command::CommandBINPOS28, BINPOS28 = (int)CM::Command::CommandBINPOS28,
BINPOS29 = (int) CM::Command::CommandBINPOS29, BINPOS29 = (int)CM::Command::CommandBINPOS29,
BINPOS30 = (int) CM::Command::CommandBINPOS30, BINPOS30 = (int)CM::Command::CommandBINPOS30,
BINPOS31 = (int) CM::Command::CommandBINPOS31, BINPOS31 = (int)CM::Command::CommandBINPOS31,
BINPOS32 = (int) CM::Command::CommandBINPOS32, BINPOS32 = (int)CM::Command::CommandBINPOS32,
BINPOS33 = (int) CM::Command::CommandBINPOS33, BINPOS33 = (int)CM::Command::CommandBINPOS33,
BINPOS34 = (int) CM::Command::CommandBINPOS34, BINPOS34 = (int)CM::Command::CommandBINPOS34,
BINPOS35 = (int) CM::Command::CommandBINPOS35, BINPOS35 = (int)CM::Command::CommandBINPOS35,
BINPOS36 = (int) CM::Command::CommandBINPOS36, BINPOS36 = (int)CM::Command::CommandBINPOS36,
BINPOS37 = (int) CM::Command::CommandBINPOS37, BINPOS37 = (int)CM::Command::CommandBINPOS37,
BINPOS38 = (int) CM::Command::CommandBINPOS38, BINPOS38 = (int)CM::Command::CommandBINPOS38,
BINPOS39 = (int) CM::Command::CommandBINPOS39, BINPOS39 = (int)CM::Command::CommandBINPOS39,
BINPOS40 = (int) CM::Command::CommandBINPOS40, BINPOS40 = (int)CM::Command::CommandBINPOS40,
BINPOS41 = (int) CM::Command::CommandBINPOS41, BINPOS41 = (int)CM::Command::CommandBINPOS41,
BINPOS42 = (int) CM::Command::CommandBINPOS42, BINPOS42 = (int)CM::Command::CommandBINPOS42,
BINPOS43 = (int) CM::Command::CommandBINPOS43, BINPOS43 = (int)CM::Command::CommandBINPOS43,
BINPOS44 = (int) CM::Command::CommandBINPOS44, BINPOS44 = (int)CM::Command::CommandBINPOS44,
BINPOS45 = (int) CM::Command::CommandBINPOS45, BINPOS45 = (int)CM::Command::CommandBINPOS45,
BINPOS46 = (int) CM::Command::CommandBINPOS46, BINPOS46 = (int)CM::Command::CommandBINPOS46,
BINPOS47 = (int) CM::Command::CommandBINPOS47, BINPOS47 = (int)CM::Command::CommandBINPOS47,
BINPOS48 = (int) CM::Command::CommandBINPOS48, BINPOS48 = (int)CM::Command::CommandBINPOS48,
BINPOS49 = (int) CM::Command::CommandBINPOS49, BINPOS49 = (int)CM::Command::CommandBINPOS49,
BINPOS50 = (int) CM::Command::CommandBINPOS50, BINPOS50 = (int)CM::Command::CommandBINPOS50,
BINPOS51 = (int) CM::Command::CommandBINPOS51, BINPOS51 = (int)CM::Command::CommandBINPOS51,
BINPOS52 = (int) CM::Command::CommandBINPOS52, BINPOS52 = (int)CM::Command::CommandBINPOS52,
BINPOS53 = (int) CM::Command::CommandBINPOS53, BINPOS53 = (int)CM::Command::CommandBINPOS53,
BINPOS54 = (int) CM::Command::CommandBINPOS54, BINPOS54 = (int)CM::Command::CommandBINPOS54,
BINPOS55 = (int) CM::Command::CommandBINPOS55, BINPOS55 = (int)CM::Command::CommandBINPOS55,
BINPOS56 = (int) CM::Command::CommandBINPOS56, BINPOS56 = (int)CM::Command::CommandBINPOS56,
BINPOS57 = (int) CM::Command::CommandBINPOS57, BINPOS57 = (int)CM::Command::CommandBINPOS57,
BINPOS58 = (int) CM::Command::CommandBINPOS58, BINPOS58 = (int)CM::Command::CommandBINPOS58,
BINPOS59 = (int) CM::Command::CommandBINPOS59, BINPOS59 = (int)CM::Command::CommandBINPOS59,
BINPOS60 = (int) CM::Command::CommandBINPOS60, BINPOS60 = (int)CM::Command::CommandBINPOS60,
BINPOS61 = (int) CM::Command::CommandBINPOS61, BINPOS61 = (int)CM::Command::CommandBINPOS61,
BINPOS62 = (int) CM::Command::CommandBINPOS62, BINPOS62 = (int)CM::Command::CommandBINPOS62,
BINPOS63 = (int) CM::Command::CommandBINPOS63, BINPOS63 = (int)CM::Command::CommandBINPOS63,
BINEND = (int) CM::Command::CommandBINEDITEND, BINEND = (int)CM::Command::CommandBINEDITEND,
Hyp = (int) CM::Command::CommandHYP Hyp = (int)CM::Command::CommandHYP
}; };
// This contains list of functions whose usage we are tracelogging // This contains list of functions whose usage we are tracelogging
public enum class FunctionLogEnum public
enum class FunctionLogEnum
{ {
Invert = (int) CM::Command::CommandREC, Invert = (int)CM::Command::CommandREC,
Sqrt = (int) CM::Command::CommandSQRT, Sqrt = (int)CM::Command::CommandSQRT,
Percent = (int) CM::Command::CommandPERCENT, Percent = (int)CM::Command::CommandPERCENT,
Negate = (int) CM::Command::CommandSIGN, Negate = (int)CM::Command::CommandSIGN,
Degrees = (int) CM::Command::CommandDegrees, Degrees = (int)CM::Command::CommandDegrees,
Pi = (int) CM::Command::CommandPI, Pi = (int)CM::Command::CommandPI,
Sin = (int) CM::Command::CommandSIN, Sin = (int)CM::Command::CommandSIN,
Cos = (int) CM::Command::CommandCOS, Cos = (int)CM::Command::CommandCOS,
Tan = (int) CM::Command::CommandTAN, Tan = (int)CM::Command::CommandTAN,
Factorial = (int) CM::Command::CommandFAC, Factorial = (int)CM::Command::CommandFAC,
XPower2 = (int) CM::Command::CommandSQR, XPower2 = (int)CM::Command::CommandSQR,
Mod = (int) CM::Command::CommandMOD, Mod = (int)CM::Command::CommandMOD,
FToE = (int) CM::Command::CommandFE, FToE = (int)CM::Command::CommandFE,
LogBaseE = (int) CM::Command::CommandLN, LogBaseE = (int)CM::Command::CommandLN,
InvSin = (int) CM::Command::CommandASIN, InvSin = (int)CM::Command::CommandASIN,
InvCos = (int) CM::Command::CommandACOS, InvCos = (int)CM::Command::CommandACOS,
InvTan = (int) CM::Command::CommandATAN, InvTan = (int)CM::Command::CommandATAN,
LogBase10 = (int) CM::Command::CommandLOG, LogBase10 = (int)CM::Command::CommandLOG,
XPowerY = (int) CM::Command::CommandPWR, XPowerY = (int)CM::Command::CommandPWR,
YRootX = (int) CM::Command::CommandROOT, YRootX = (int)CM::Command::CommandROOT,
TenPowerX = (int) CM::Command::CommandPOW10, TenPowerX = (int)CM::Command::CommandPOW10,
EPowerX = (int) CM::Command::CommandPOWE, EPowerX = (int)CM::Command::CommandPOWE,
Exp = (int) CM::Command::CommandEXP, Exp = (int)CM::Command::CommandEXP,
DecButton = (int) CM::Command::CommandDec, DecButton = (int)CM::Command::CommandDec,
OctButton = (int) CM::Command::CommandOct, OctButton = (int)CM::Command::CommandOct,
HexButton = (int) CM::Command::CommandHex, HexButton = (int)CM::Command::CommandHex,
BinButton = (int) CM::Command::CommandBin, BinButton = (int)CM::Command::CommandBin,
And = (int) CM::Command::CommandAnd, And = (int)CM::Command::CommandAnd,
Ror = (int) CM::Command::CommandROR, Ror = (int)CM::Command::CommandROR,
Rol = (int) CM::Command::CommandROL, Rol = (int)CM::Command::CommandROL,
Or = (int) CM::Command::CommandOR, Or = (int)CM::Command::CommandOR,
Lsh = (int) CM::Command::CommandLSHF, Lsh = (int)CM::Command::CommandLSHF,
Rsh = (int) CM::Command::CommandRSHF, Rsh = (int)CM::Command::CommandRSHF,
Xor = (int) CM::Command::CommandXor, Xor = (int)CM::Command::CommandXor,
Not = (int) CM::Command::CommandNot, Not = (int)CM::Command::CommandNot,
Sinh = (int) CM::Command::CommandSINH, Sinh = (int)CM::Command::CommandSINH,
Cosh = (int) CM::Command::CommandCOSH, Cosh = (int)CM::Command::CommandCOSH,
Tanh = (int) CM::Command::CommandTANH, Tanh = (int)CM::Command::CommandTANH,
InvSinh = (int) CM::Command::CommandASINH, InvSinh = (int)CM::Command::CommandASINH,
InvCosh = (int) CM::Command::CommandACOSH, InvCosh = (int)CM::Command::CommandACOSH,
InvTanh = (int) CM::Command::CommandATANH, InvTanh = (int)CM::Command::CommandATANH,
Cube = (int) CM::Command::CommandCUB, Cube = (int)CM::Command::CommandCUB,
DMS = (int) CM::Command::CommandDMS, DMS = (int)CM::Command::CommandDMS,
}; };
} }

View file

@ -69,11 +69,12 @@ void CalculatorDisplay::SetIsInError(bool isError)
} }
} }
void CalculatorDisplay::SetExpressionDisplay(_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const &tokens, _Inout_ std::shared_ptr<CalculatorVector <std::shared_ptr<IExpressionCommand>>> const &commands) void CalculatorDisplay::SetExpressionDisplay(_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const& tokens,
_Inout_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const& commands)
{ {
if (m_callbackReference != nullptr) if (m_callbackReference != nullptr)
{ {
if(auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>()) if (auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>())
{ {
calcVM->SetExpressionDisplay(tokens, commands); calcVM->SetExpressionDisplay(tokens, commands);
} }

View file

@ -8,7 +8,7 @@
namespace CalculatorApp namespace CalculatorApp
{ {
// Callback interface to be implemented by the CalculatorManager // Callback interface to be implemented by the CalculatorManager
class CalculatorDisplay: public ICalcDisplay class CalculatorDisplay : public ICalcDisplay
{ {
public: public:
CalculatorDisplay(); CalculatorDisplay();
@ -18,7 +18,8 @@ namespace CalculatorApp
private: private:
void SetPrimaryDisplay(_In_ const std::wstring& displayString, _In_ bool isError) override; void SetPrimaryDisplay(_In_ const std::wstring& displayString, _In_ bool isError) override;
void SetIsInError(bool isError) override; void SetIsInError(bool isError) override;
void SetExpressionDisplay(_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const &tokens, _Inout_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const &commands) override; void SetExpressionDisplay(_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const& tokens,
_Inout_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const& commands) override;
void SetMemorizedNumbers(_In_ const std::vector<std::wstring>& memorizedNumbers) override; void SetMemorizedNumbers(_In_ const std::vector<std::wstring>& memorizedNumbers) override;
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;

View file

@ -8,19 +8,19 @@ using namespace CalculatorApp::Common;
using namespace concurrency; using namespace concurrency;
using namespace std; using namespace std;
ConversionResultTaskHelper::ConversionResultTaskHelper(unsigned int delay, const function<void()> functionToRun) : ConversionResultTaskHelper::ConversionResultTaskHelper(unsigned int delay, const function<void()> functionToRun)
m_delay{ delay }, : m_delay{ delay }, m_storedFunction{ functionToRun }
m_storedFunction{ functionToRun }
{ {
auto token = m_cts.get_token(); auto token = m_cts.get_token();
auto delayTask = CompleteAfter(delay); auto delayTask = CompleteAfter(delay);
delayTask.then([this, token]() delayTask.then(
{ [this, token]() {
if (!token.is_canceled()) if (!token.is_canceled())
{ {
m_storedFunction(); m_storedFunction();
} }
}, task_continuation_context::use_current()); },
task_continuation_context::use_current());
} }
ConversionResultTaskHelper::~ConversionResultTaskHelper() ConversionResultTaskHelper::~ConversionResultTaskHelper()

View file

@ -15,10 +15,7 @@ using namespace Windows::Foundation;
using namespace Windows::System; using namespace Windows::System;
using namespace Windows::ApplicationModel::DataTransfer; using namespace Windows::ApplicationModel::DataTransfer;
String^ CopyPasteManager::supportedFormats[] = String ^ CopyPasteManager::supportedFormats[] = { StandardDataFormats::Text };
{
StandardDataFormats::Text
};
static constexpr wstring_view c_validCharacterSet{ L"0123456789()+-*/.abcdefABCDEF" }; static constexpr wstring_view c_validCharacterSet{ L"0123456789()+-*/.abcdefABCDEF" };
@ -40,43 +37,26 @@ static const wstring c_binProgrammerChars = L"[0-1]+((_|'|`)[0-1]+)*";
static const wstring c_uIntSuffixes = L"[uU]?[lL]{0,2}"; static const wstring c_uIntSuffixes = L"[uU]?[lL]{0,2}";
// RegEx Patterns used by various modes // RegEx Patterns used by various modes
static const array<wregex, 1> standardModePatterns = static const array<wregex, 1> standardModePatterns = { wregex(c_wspc + c_signedDecFloat + c_wspc) };
{ static const array<wregex, 2> scientificModePatterns = { wregex(L"(" + c_wspc + L"[-+]?)|(" + c_wspcLParenSigned + L")" + c_signedDecFloat + c_wspcRParens),
wregex(c_wspc + c_signedDecFloat + c_wspc) wregex(L"(" + c_wspc + L"[-+]?)|(" + c_wspcLParenSigned + L")" + c_signedDecFloat
}; + L"[e]([+]|[-])+\\d+" + c_wspcRParens) };
static const array<wregex, 2> scientificModePatterns = static const array<array<wregex, 5>, 4> programmerModePatterns = {
{ { // Hex numbers like 5F, 4A0C, 0xa9, 0xFFull, 47CDh
wregex(L"(" + c_wspc + L"[-+]?)|(" + c_wspcLParenSigned + L")" + c_signedDecFloat + c_wspcRParens), { wregex(c_wspcLParens + L"(0[xX])?" + c_hexProgrammerChars + c_uIntSuffixes + c_wspcRParens),
wregex(L"(" + c_wspc + L"[-+]?)|(" + c_wspcLParenSigned + L")" + c_signedDecFloat + L"[e]([+]|[-])+\\d+" + c_wspcRParens) wregex(c_wspcLParens + c_hexProgrammerChars + L"[hH]?" + c_wspcRParens) },
};
static const array<array<wregex, 5>, 4> programmerModePatterns =
{ {
// Hex numbers like 5F, 4A0C, 0xa9, 0xFFull, 47CDh
{
wregex(c_wspcLParens + L"(0[xX])?" + c_hexProgrammerChars + c_uIntSuffixes + c_wspcRParens),
wregex(c_wspcLParens + c_hexProgrammerChars + L"[hH]?" + c_wspcRParens)
},
// Decimal numbers like -145, 145, 0n145, 123ull etc // Decimal numbers like -145, 145, 0n145, 123ull etc
{ { wregex(c_wspcLParens + L"[-+]?" + c_decProgrammerChars + L"[lL]{0,2}" + c_wspcRParens),
wregex(c_wspcLParens + L"[-+]?" + c_decProgrammerChars + L"[lL]{0,2}" +c_wspcRParens), wregex(c_wspcLParens + L"(0[nN])?" + c_decProgrammerChars + c_uIntSuffixes + c_wspcRParens) },
wregex(c_wspcLParens + L"(0[nN])?" + c_decProgrammerChars + c_uIntSuffixes + c_wspcRParens)
},
// Octal numbers like 06, 010, 0t77, 0o77, 077ull etc // Octal numbers like 06, 010, 0t77, 0o77, 077ull etc
{ { wregex(c_wspcLParens + L"(0[otOT])?" + c_octProgrammerChars + c_uIntSuffixes + c_wspcRParens) },
wregex(c_wspcLParens + L"(0[otOT])?" + c_octProgrammerChars + c_uIntSuffixes + c_wspcRParens)
},
// Binary numbers like 011010110, 0010110, 10101001, 1001b, 0b1001, 0y1001, 0b1001ull // Binary numbers like 011010110, 0010110, 10101001, 1001b, 0b1001, 0y1001, 0b1001ull
{ { wregex(c_wspcLParens + L"(0[byBY])?" + c_binProgrammerChars + c_uIntSuffixes + c_wspcRParens),
wregex(c_wspcLParens + L"(0[byBY])?" + c_binProgrammerChars + c_uIntSuffixes + c_wspcRParens), wregex(c_wspcLParens + c_binProgrammerChars + L"[bB]?" + c_wspcRParens) } }
wregex(c_wspcLParens + c_binProgrammerChars + L"[bB]?" + c_wspcRParens)
}
} };
static const array<wregex, 1> unitConverterPatterns =
{
wregex(c_wspc + L"[-+]?\\d*[.]?\\d*" + c_wspc)
}; };
static const array<wregex, 1> unitConverterPatterns = { wregex(c_wspc + L"[-+]?\\d*[.]?\\d*" + c_wspc) };
void CopyPasteManager::CopyToClipboard(String^ stringToCopy) void CopyPasteManager::CopyToClipboard(String ^ stringToCopy)
{ {
// Copy the string to the clipboard // Copy the string to the clipboard
auto dataPackage = ref new DataPackage(); auto dataPackage = ref new DataPackage();
@ -84,7 +64,7 @@ void CopyPasteManager::CopyToClipboard(String^ stringToCopy)
Clipboard::SetContent(dataPackage); Clipboard::SetContent(dataPackage);
} }
task<String^> CopyPasteManager::GetStringToPaste(ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, int bitLengthType) task<String ^> CopyPasteManager::GetStringToPaste(ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, int bitLengthType)
{ {
// Retrieve the text in the clipboard // Retrieve the text in the clipboard
auto dataPackageView = Clipboard::GetContent(); auto dataPackageView = Clipboard::GetContent();
@ -95,11 +75,9 @@ task<String^> CopyPasteManager::GetStringToPaste(ViewMode mode, CategoryGroupTyp
//-- add support to allow pasting for expressions like 1.3e12(as of now we allow 1.3e+12) //-- add support to allow pasting for expressions like 1.3e12(as of now we allow 1.3e+12)
return create_task((dataPackageView->GetTextAsync(::StandardDataFormats::Text))) return create_task((dataPackageView->GetTextAsync(::StandardDataFormats::Text)))
.then([mode, modeType, programmerNumberBase, bitLengthType](String^ pastedText) .then([mode, modeType, programmerNumberBase,
{ bitLengthType](String ^ pastedText) { return ValidatePasteExpression(pastedText, mode, modeType, programmerNumberBase, bitLengthType); },
return ValidatePasteExpression(pastedText, mode, modeType, programmerNumberBase, bitLengthType); task_continuation_context::use_arbitrary());
}
, task_continuation_context::use_arbitrary());
} }
int CopyPasteManager::ClipboardTextFormat() int CopyPasteManager::ClipboardTextFormat()
@ -116,14 +94,14 @@ int CopyPasteManager::ClipboardTextFormat()
return -1; return -1;
} }
String^ CopyPasteManager::ValidatePasteExpression(String^ pastedText, ViewMode mode, int programmerNumberBase, int bitLengthType) String ^ CopyPasteManager::ValidatePasteExpression(String ^ pastedText, ViewMode mode, int programmerNumberBase, int bitLengthType)
{ {
return CopyPasteManager::ValidatePasteExpression(pastedText, mode, NavCategory::GetGroupType(mode), programmerNumberBase, bitLengthType); return CopyPasteManager::ValidatePasteExpression(pastedText, mode, NavCategory::GetGroupType(mode), programmerNumberBase, bitLengthType);
} }
// return "NoOp" if pastedText is invalid else return pastedText // return "NoOp" if pastedText is invalid else return pastedText
String^ CopyPasteManager::ValidatePasteExpression(String^ pastedText, ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, int bitLengthType) String ^ CopyPasteManager::ValidatePasteExpression(String ^ pastedText, ViewMode mode, CategoryGroupType modeType, int programmerNumberBase, int bitLengthType)
{ {
if (pastedText->Length() > MaxPasteableLength) if (pastedText->Length() > MaxPasteableLength)
{ {
@ -135,7 +113,7 @@ String^ CopyPasteManager::ValidatePasteExpression(String^ pastedText, ViewMode m
wstring pasteExpression = pastedText->Data(); wstring pasteExpression = pastedText->Data();
// Get english translated expression // Get english translated expression
String^ englishString = LocalizationSettings::GetInstance().GetEnglishValueFromLocalizedDigits(pasteExpression); String ^ englishString = LocalizationSettings::GetInstance().GetEnglishValueFromLocalizedDigits(pasteExpression);
// Removing the spaces, comma separator from the pasteExpression to allow pasting of expressions like 1 + 2+1,333 // Removing the spaces, comma separator from the pasteExpression to allow pasting of expressions like 1 + 2+1,333
pasteExpression = RemoveUnwantedCharsFromWstring(englishString->Data()); pasteExpression = RemoveUnwantedCharsFromWstring(englishString->Data());
@ -223,7 +201,8 @@ vector<wstring> CopyPasteManager::ExtractOperands(const wstring& pasteExpression
if ((pasteExpression.at(i) == L'+') || (pasteExpression.at(i) == L'-')) if ((pasteExpression.at(i) == L'+') || (pasteExpression.at(i) == L'-'))
{ {
// don't break the expression into operands if the encountered character corresponds to sign command(+-) // don't break the expression into operands if the encountered character corresponds to sign command(+-)
if (isPreviousOpenParen || startOfExpression || isPreviousOperator || ((mode != ViewMode::Programmer) && !((i != 0) && (pasteExpression.at(i - 1) != L'e')))) if (isPreviousOpenParen || startOfExpression || isPreviousOperator
|| ((mode != ViewMode::Programmer) && !((i != 0) && (pasteExpression.at(i - 1) != L'e'))))
{ {
isPreviousOperator = false; isPreviousOperator = false;
continue; continue;
@ -453,11 +432,13 @@ bool CopyPasteManager::TryOperandToULL(const wstring& operand, int numberBase, u
size_t CopyPasteManager::OperandLength(const wstring& operand, ViewMode mode, CategoryGroupType modeType, int programmerNumberBase) size_t CopyPasteManager::OperandLength(const wstring& operand, ViewMode mode, CategoryGroupType modeType, int programmerNumberBase)
{ {
if (modeType == CategoryGroupType::Converter) { if (modeType == CategoryGroupType::Converter)
{
return operand.length(); return operand.length();
} }
switch(mode) { switch (mode)
{
case ViewMode::Standard: case ViewMode::Standard:
case ViewMode::Scientific: case ViewMode::Scientific:
return StandardScientificOperandLength(operand); return StandardScientificOperandLength(operand);
@ -494,7 +475,6 @@ size_t CopyPasteManager::StandardScientificOperandLength(const wstring& operand)
size_t CopyPasteManager::ProgrammerOperandLength(const wstring& operand, int numberBase) size_t CopyPasteManager::ProgrammerOperandLength(const wstring& operand, int numberBase)
{ {
vector<wstring> prefixes{}; vector<wstring> prefixes{};
vector<wstring> suffixes{}; vector<wstring> suffixes{};
switch (numberBase) switch (numberBase)

View file

@ -25,8 +25,9 @@ namespace CalculatorApp
class CopyPasteManager class CopyPasteManager
{ {
public: public:
static void CopyToClipboard(Platform::String^ stringToCopy); static void CopyToClipboard(Platform::String ^ stringToCopy);
static concurrency::task<Platform::String^> GetStringToPaste(CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, int programmerNumberBase = -1, int bitLengthType = -1); static concurrency::task<Platform::String ^> GetStringToPaste(CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType,
int programmerNumberBase = -1, int bitLengthType = -1);
static bool HasStringToPaste() static bool HasStringToPaste()
{ {
return ClipboardTextFormat() >= 0; return ClipboardTextFormat() >= 0;
@ -36,25 +37,23 @@ namespace CalculatorApp
private: private:
static int ClipboardTextFormat(); static int ClipboardTextFormat();
static Platform::String^ ValidatePasteExpression( static Platform::String
Platform::String^ pastedText, ^ ValidatePasteExpression(Platform::String ^ pastedText, CalculatorApp::Common::ViewMode mode, int programmerNumberBase, int bitLengthType);
CalculatorApp::Common::ViewMode mode, static Platform::String
int programmerNumberBase, ^ ValidatePasteExpression(Platform::String ^ pastedText, CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType,
int bitLengthType); int programmerNumberBase, int bitLengthType);
static Platform::String^ ValidatePasteExpression(
Platform::String^ pastedText,
CalculatorApp::Common::ViewMode mode,
CalculatorApp::Common::CategoryGroupType modeType,
int programmerNumberBase,
int bitLengthType);
static std::vector<std::wstring> ExtractOperands(const std::wstring& pasteExpression, CalculatorApp::Common::ViewMode mode, int programmerNumberBase = -1, int bitLengthType = -1); static std::vector<std::wstring> ExtractOperands(const std::wstring& pasteExpression, CalculatorApp::Common::ViewMode mode,
static bool ExpressionRegExMatch(std::vector<std::wstring> operands, CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, int programmerNumberBase = -1, int bitLengthType = -1); int programmerNumberBase = -1, int bitLengthType = -1);
static bool ExpressionRegExMatch(std::vector<std::wstring> operands, CalculatorApp::Common::ViewMode mode,
CalculatorApp::Common::CategoryGroupType modeType, int programmerNumberBase = -1, int bitLengthType = -1);
static std::pair<size_t, uint64_t> GetMaxOperandLengthAndValue(CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, int programmerNumberBase = -1, int bitLengthType = -1); static std::pair<size_t, uint64_t> GetMaxOperandLengthAndValue(CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType,
int programmerNumberBase = -1, int bitLengthType = -1);
static std::wstring SanitizeOperand(const std::wstring& operand); static std::wstring SanitizeOperand(const std::wstring& operand);
static bool TryOperandToULL(const std::wstring& operand, int numberBase, unsigned long long int& result); static bool TryOperandToULL(const std::wstring& operand, int numberBase, unsigned long long int& result);
static size_t OperandLength(const std::wstring& operand, CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, int programmerNumberBase = -1); static size_t OperandLength(const std::wstring& operand, CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType,
int programmerNumberBase = -1);
static size_t StandardScientificOperandLength(const std::wstring& operand); static size_t StandardScientificOperandLength(const std::wstring& operand);
static size_t ProgrammerOperandLength(const std::wstring& operand, int numberBase); static size_t ProgrammerOperandLength(const std::wstring& operand, int numberBase);
static std::wstring RemoveUnwantedCharsFromWstring(const std::wstring& input); static std::wstring RemoveUnwantedCharsFromWstring(const std::wstring& input);
@ -67,7 +66,7 @@ namespace CalculatorApp
static constexpr size_t MaxExponentLength = 4; static constexpr size_t MaxExponentLength = 4;
static constexpr size_t MaxProgrammerBitLength = 64; static constexpr size_t MaxProgrammerBitLength = 64;
static Platform::String^ supportedFormats[]; static Platform::String ^ supportedFormats[];
friend class CalculatorUnitTests::CopyPasteManagerTest; friend class CalculatorUnitTests::CopyPasteManagerTest;
}; };

View file

@ -9,7 +9,7 @@ using namespace Windows::Foundation;
using namespace Windows::Globalization; using namespace Windows::Globalization;
using namespace CalculatorApp::Common::DateCalculation; using namespace CalculatorApp::Common::DateCalculation;
DateCalculationEngine::DateCalculationEngine(_In_ String^ calendarIdentifier) DateCalculationEngine::DateCalculationEngine(_In_ String ^ calendarIdentifier)
{ {
m_calendar = ref new Calendar(); m_calendar = ref new Calendar();
m_calendar->ChangeTimeZone("UTC"); m_calendar->ChangeTimeZone("UTC");
@ -18,7 +18,7 @@ DateCalculationEngine::DateCalculationEngine(_In_ String^ calendarIdentifier)
// Adding Duration to a Date // Adding Duration to a Date
// Returns: True if function succeeds to calculate the date else returns False // Returns: True if function succeeds to calculate the date else returns False
bool DateCalculationEngine::AddDuration(_In_ DateTime startDate, _In_ const DateDifference& duration, _Out_ DateTime *endDate) bool DateCalculationEngine::AddDuration(_In_ DateTime startDate, _In_ const DateDifference& duration, _Out_ DateTime* endDate)
{ {
auto currentCalendarSystem = m_calendar->GetCalendarSystem(); auto currentCalendarSystem = m_calendar->GetCalendarSystem();
@ -28,9 +28,10 @@ bool DateCalculationEngine::AddDuration(_In_ DateTime startDate, _In_ const Date
// The Japanese Era system can have multiple year partitions within the same year. // The Japanese Era system can have multiple year partitions within the same year.
// For example, April 30, 2019 is denoted April 30, Heisei 31; May 1, 2019 is denoted as May 1, Reiwa 1. // For example, April 30, 2019 is denoted April 30, Heisei 31; May 1, 2019 is denoted as May 1, Reiwa 1.
// The Calendar treats Heisei 31 and Reiwa 1 as separate years, which results in some unexpected behaviors where subtracting a year from Reiwa 1 results in a date in Heisei 31. // The Calendar treats Heisei 31 and Reiwa 1 as separate years, which results in some unexpected behaviors where subtracting a year from Reiwa 1 results
// To provide the expected result across era boundaries, we first convert the Japanese era system to a Gregorian system, do date math, and then convert back to the Japanese era system. // in a date in Heisei 31. To provide the expected result across era boundaries, we first convert the Japanese era system to a Gregorian system, do date
// This works because the Japanese era system maintains the same year/month boundaries and durations as the Gregorian system and is only different in display value. // math, and then convert back to the Japanese era system. This works because the Japanese era system maintains the same year/month boundaries and
// durations as the Gregorian system and is only different in display value.
if (currentCalendarSystem == CalendarIdentifiers::Japanese) if (currentCalendarSystem == CalendarIdentifiers::Japanese)
{ {
m_calendar->ChangeCalendarSystem(CalendarIdentifiers::Gregorian); m_calendar->ChangeCalendarSystem(CalendarIdentifiers::Gregorian);
@ -51,7 +52,7 @@ bool DateCalculationEngine::AddDuration(_In_ DateTime startDate, _In_ const Date
*endDate = m_calendar->GetDateTime(); *endDate = m_calendar->GetDateTime();
} }
catch (Platform::InvalidArgumentException^ ex) catch (Platform::InvalidArgumentException ^ ex)
{ {
// ensure that we revert to the correct calendar system // ensure that we revert to the correct calendar system
m_calendar->ChangeCalendarSystem(currentCalendarSystem); m_calendar->ChangeCalendarSystem(currentCalendarSystem);
@ -67,7 +68,7 @@ bool DateCalculationEngine::AddDuration(_In_ DateTime startDate, _In_ const Date
// Subtracting Duration from a Date // Subtracting Duration from a Date
// Returns: True if function succeeds to calculate the date else returns False // Returns: True if function succeeds to calculate the date else returns False
bool DateCalculationEngine::SubtractDuration(_In_ DateTime startDate, _In_ const DateDifference& duration, _Out_ DateTime *endDate) bool DateCalculationEngine::SubtractDuration(_In_ DateTime startDate, _In_ const DateDifference& duration, _Out_ DateTime* endDate)
{ {
auto currentCalendarSystem = m_calendar->GetCalendarSystem(); auto currentCalendarSystem = m_calendar->GetCalendarSystem();
@ -79,9 +80,10 @@ bool DateCalculationEngine::SubtractDuration(_In_ DateTime startDate, _In_ const
// The Japanese Era system can have multiple year partitions within the same year. // The Japanese Era system can have multiple year partitions within the same year.
// For example, April 30, 2019 is denoted April 30, Heisei 31; May 1, 2019 is denoted as May 1, Reiwa 1. // For example, April 30, 2019 is denoted April 30, Heisei 31; May 1, 2019 is denoted as May 1, Reiwa 1.
// The Calendar treats Heisei 31 and Reiwa 1 as separate years, which results in some unexpected behaviors where subtracting a year from Reiwa 1 results in a date in Heisei 31. // The Calendar treats Heisei 31 and Reiwa 1 as separate years, which results in some unexpected behaviors where subtracting a year from Reiwa 1 results
// To provide the expected result across era boundaries, we first convert the Japanese era system to a Gregorian system, do date math, and then convert back to the Japanese era system. // in a date in Heisei 31. To provide the expected result across era boundaries, we first convert the Japanese era system to a Gregorian system, do date
// This works because the Japanese era system maintains the same year/month boundaries and durations as the Gregorian system and is only different in display value. // math, and then convert back to the Japanese era system. This works because the Japanese era system maintains the same year/month boundaries and
// durations as the Gregorian system and is only different in display value.
if (currentCalendarSystem == CalendarIdentifiers::Japanese) if (currentCalendarSystem == CalendarIdentifiers::Japanese)
{ {
m_calendar->ChangeCalendarSystem(CalendarIdentifiers::Gregorian); m_calendar->ChangeCalendarSystem(CalendarIdentifiers::Gregorian);
@ -101,7 +103,7 @@ bool DateCalculationEngine::SubtractDuration(_In_ DateTime startDate, _In_ const
} }
*endDate = m_calendar->GetDateTime(); *endDate = m_calendar->GetDateTime();
} }
catch (Platform::InvalidArgumentException^ ex) catch (Platform::InvalidArgumentException ^ ex)
{ {
// ensure that we revert to the correct calendar system // ensure that we revert to the correct calendar system
m_calendar->ChangeCalendarSystem(currentCalendarSystem); m_calendar->ChangeCalendarSystem(currentCalendarSystem);
@ -117,7 +119,7 @@ bool DateCalculationEngine::SubtractDuration(_In_ DateTime startDate, _In_ const
} }
// Calculate the difference between two dates // Calculate the difference between two dates
void DateCalculationEngine::GetDateDifference(_In_ DateTime date1, _In_ DateTime date2, _In_ DateUnit outputFormat, _Out_ DateDifference *difference) void DateCalculationEngine::GetDateDifference(_In_ DateTime date1, _In_ DateTime date2, _In_ DateUnit outputFormat, _Out_ DateDifference* difference)
{ {
DateTime startDate; DateTime startDate;
DateTime endDate; DateTime endDate;
@ -149,8 +151,7 @@ void DateCalculationEngine::GetDateDifference(_In_ DateTime date1, _In_ DateTime
UINT approximateDaysInYear; UINT approximateDaysInYear;
// If we're unable to calculate the days-in-month or days-in-year, we'll leave the values at 0. // If we're unable to calculate the days-in-month or days-in-year, we'll leave the values at 0.
if (TryGetCalendarDaysInMonth(startDate, daysInMonth) if (TryGetCalendarDaysInMonth(startDate, daysInMonth) && TryGetCalendarDaysInYear(endDate, approximateDaysInYear))
&& TryGetCalendarDaysInYear(endDate, approximateDaysInYear))
{ {
UINT daysIn[c_unitsOfDate] = { approximateDaysInYear, daysInMonth, c_daysInWeek, 1 }; UINT daysIn[c_unitsOfDate] = { approximateDaysInYear, daysInMonth, c_daysInWeek, 1 };
@ -172,7 +173,7 @@ void DateCalculationEngine::GetDateDifference(_In_ DateTime date1, _In_ DateTime
{ {
pivotDate = AdjustCalendarDate(pivotDate, dateUnit, static_cast<int>(differenceInDates[unitIndex])); pivotDate = AdjustCalendarDate(pivotDate, dateUnit, static_cast<int>(differenceInDates[unitIndex]));
} }
catch (Platform::InvalidArgumentException^) catch (Platform::InvalidArgumentException ^)
{ {
// Operation failed due to out of bound result // Operation failed due to out of bound result
// Do nothing // Do nothing
@ -208,7 +209,7 @@ void DateCalculationEngine::GetDateDifference(_In_ DateTime date1, _In_ DateTime
pivotDate = AdjustCalendarDate(pivotDate, dateUnit, 1); pivotDate = AdjustCalendarDate(pivotDate, dateUnit, 1);
differenceInDates[unitIndex] += 1; differenceInDates[unitIndex] += 1;
} }
catch (Platform::InvalidArgumentException^) catch (Platform::InvalidArgumentException ^)
{ {
// handling for 31st Dec, 9999 last valid date // handling for 31st Dec, 9999 last valid date
// Do nothing - break out // Do nothing - break out
@ -233,7 +234,6 @@ void DateCalculationEngine::GetDateDifference(_In_ DateTime date1, _In_ DateTime
difference->day = differenceInDates[3]; difference->day = differenceInDates[3];
} }
// Private Methods // Private Methods
// Gets number of days between the two date time values // Gets number of days between the two date time values
@ -311,9 +311,10 @@ DateTime DateCalculationEngine::AdjustCalendarDate(Windows::Foundation::DateTime
// The Japanese Era system can have multiple year partitions within the same year. // The Japanese Era system can have multiple year partitions within the same year.
// For example, April 30, 2019 is denoted April 30, Heisei 31; May 1, 2019 is denoted as May 1, Reiwa 1. // For example, April 30, 2019 is denoted April 30, Heisei 31; May 1, 2019 is denoted as May 1, Reiwa 1.
// The Calendar treats Heisei 31 and Reiwa 1 as separate years, which results in some unexpected behaviors where subtracting a year from Reiwa 1 results in a date in Heisei 31. // The Calendar treats Heisei 31 and Reiwa 1 as separate years, which results in some unexpected behaviors where subtracting a year from Reiwa 1 results in
// To provide the expected result across era boundaries, we first convert the Japanese era system to a Gregorian system, do date math, and then convert back to the Japanese era system. // a date in Heisei 31. To provide the expected result across era boundaries, we first convert the Japanese era system to a Gregorian system, do date math,
// This works because the Japanese era system maintains the same year/month boundaries and durations as the Gregorian system and is only different in display value. // and then convert back to the Japanese era system. This works because the Japanese era system maintains the same year/month boundaries and durations as
// the Gregorian system and is only different in display value.
auto currentCalendarSystem = m_calendar->GetCalendarSystem(); auto currentCalendarSystem = m_calendar->GetCalendarSystem();
if (currentCalendarSystem == CalendarIdentifiers::Japanese) if (currentCalendarSystem == CalendarIdentifiers::Japanese)
{ {

View file

@ -19,7 +19,8 @@ namespace CalculatorApp
{ {
namespace DateCalculation namespace DateCalculation
{ {
public enum class _Enum_is_bitflag_ DateUnit public
enum class _Enum_is_bitflag_ DateUnit
{ {
Year = 0x01, Year = 0x01,
Month = 0x02, Month = 0x02,
@ -40,16 +41,19 @@ namespace CalculatorApp
{ {
public: public:
// Constructor // Constructor
DateCalculationEngine(_In_ Platform::String^ calendarIdentifier); DateCalculationEngine(_In_ Platform::String ^ calendarIdentifier);
// Public Methods // Public Methods
bool __nothrow AddDuration(_In_ Windows::Foundation::DateTime startDate, _In_ const DateDifference& duration, _Out_ Windows::Foundation::DateTime *endDate); bool __nothrow AddDuration(_In_ Windows::Foundation::DateTime startDate, _In_ const DateDifference& duration,
bool __nothrow SubtractDuration(_In_ Windows::Foundation::DateTime startDate, _In_ const DateDifference& duration, _Out_ Windows::Foundation::DateTime *endDate); _Out_ Windows::Foundation::DateTime* endDate);
void __nothrow GetDateDifference(_In_ Windows::Foundation::DateTime date1, _In_ Windows::Foundation::DateTime date2, _In_ DateUnit outputFormat, _Out_ DateDifference *difference); bool __nothrow SubtractDuration(_In_ Windows::Foundation::DateTime startDate, _In_ const DateDifference& duration,
_Out_ Windows::Foundation::DateTime* endDate);
void __nothrow GetDateDifference(_In_ Windows::Foundation::DateTime date1, _In_ Windows::Foundation::DateTime date2, _In_ DateUnit outputFormat,
_Out_ DateDifference* difference);
private: private:
// Private Variables // Private Variables
Windows::Globalization::Calendar^ m_calendar; Windows::Globalization::Calendar ^ m_calendar;
// Private Methods // Private Methods
int GetDifferenceInDays(Windows::Foundation::DateTime date1, Windows::Foundation::DateTime date2); int GetDifferenceInDays(Windows::Foundation::DateTime date1, Windows::Foundation::DateTime date2);

View file

@ -8,33 +8,31 @@ namespace CalculatorApp
namespace Common namespace Common
{ {
template <typename TTarget> template <typename TTarget>
ref class DelegateCommand: public Windows::UI::Xaml::Input::ICommand ref class DelegateCommand : public Windows::UI::Xaml::Input::ICommand
{ {
internal: internal :
typedef void (TTarget::*CommandHandlerFunc)(Platform::Object^); typedef void (TTarget::*CommandHandlerFunc)(Platform::Object ^);
DelegateCommand(TTarget^ target, CommandHandlerFunc func): DelegateCommand(TTarget ^ target, CommandHandlerFunc func) : m_weakTarget(target), m_function(func)
m_weakTarget(target), {
m_function(func) }
{ }
private: private:
// Explicit, and private, implementation of ICommand, this way of programming makes it so // Explicit, and private, implementation of ICommand, this way of programming makes it so
// the ICommand methods will only be available if the ICommand interface is requested via a dynamic_cast // the ICommand methods will only be available if the ICommand interface is requested via a dynamic_cast
// The ICommand interface is meant to be consumed by Xaml and not by the app, this is a defensive measure against // The ICommand interface is meant to be consumed by Xaml and not by the app, this is a defensive measure against
// code in the app calling Execute. // code in the app calling Execute.
virtual void ExecuteImpl(Platform::Object^ parameter) sealed = Windows::UI::Xaml::Input::ICommand::Execute virtual void ExecuteImpl(Platform::Object ^ parameter) sealed = Windows::UI::Xaml::Input::ICommand::Execute
{ {
TTarget^ target = m_weakTarget.Resolve<TTarget>(); TTarget ^ target = m_weakTarget.Resolve<TTarget>();
if (target) if (target)
{ {
(target->*m_function)(parameter); (target->*m_function)(parameter);
} }
} }
virtual bool CanExecuteImpl(Platform::Object^ parameter) sealed = Windows::UI::Xaml::Input::ICommand::CanExecute virtual bool CanExecuteImpl(Platform::Object ^ parameter) sealed = Windows::UI::Xaml::Input::ICommand::CanExecute
{ {
return true; return true;
} }
@ -57,12 +55,10 @@ namespace CalculatorApp
CommandHandlerFunc m_function; CommandHandlerFunc m_function;
Platform::WeakReference m_weakTarget; Platform::WeakReference m_weakTarget;
}; };
template <typename TTarget, typename TFuncPtr> template <typename TTarget, typename TFuncPtr>
DelegateCommand<TTarget>^ MakeDelegate(TTarget^ target, TFuncPtr&& function) DelegateCommand<TTarget> ^ MakeDelegate(TTarget ^ target, TFuncPtr&& function) {
{
return ref new DelegateCommand<TTarget>(target, std::forward<TFuncPtr>(function)); return ref new DelegateCommand<TTarget>(target, std::forward<TFuncPtr>(function));
} }

View file

@ -7,30 +7,35 @@
namespace CalculatorApp::Common namespace CalculatorApp::Common
{ {
public enum class TokenType public
enum class TokenType
{ {
Operator, Operator,
Operand, Operand,
Separator Separator
}; };
[Windows::UI::Xaml::Data::Bindable] [Windows::UI::Xaml::Data::Bindable] public ref class DisplayExpressionToken sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
public ref class DisplayExpressionToken sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
{ {
internal: internal : DisplayExpressionToken(Platform::String ^ token, int tokenPosition, bool fEditable, TokenType type)
DisplayExpressionToken(Platform::String^ token, int tokenPosition, bool fEditable, TokenType type) : : m_Token(token), m_TokenPosition(tokenPosition), m_IsTokenEditable(fEditable), m_Type(type), m_OriginalToken(token), m_InEditMode(false)
m_Token(token), m_TokenPosition(tokenPosition), m_IsTokenEditable(fEditable), m_Type(type), m_OriginalToken(token), m_InEditMode(false) {
{} }
public: public:
OBSERVABLE_OBJECT(); OBSERVABLE_OBJECT();
OBSERVABLE_PROPERTY_RW(Platform::String^, Token); OBSERVABLE_PROPERTY_RW(Platform::String ^, Token);
OBSERVABLE_PROPERTY_RW(int, TokenPosition); OBSERVABLE_PROPERTY_RW(int, TokenPosition);
OBSERVABLE_PROPERTY_RW(bool, IsTokenEditable); OBSERVABLE_PROPERTY_RW(bool, IsTokenEditable);
OBSERVABLE_PROPERTY_RW(int, CommandIndex); OBSERVABLE_PROPERTY_RW(int, CommandIndex);
OBSERVABLE_PROPERTY_R(Platform::String^, OriginalToken); OBSERVABLE_PROPERTY_R(Platform::String ^, OriginalToken);
property bool IsTokenInEditMode { property bool IsTokenInEditMode
bool get() { return m_InEditMode; } {
bool get()
{
return m_InEditMode;
}
void set(bool val) void set(bool val)
{ {
if (!val) if (!val)
@ -40,8 +45,8 @@ namespace CalculatorApp::Common
m_InEditMode = val; m_InEditMode = val;
} }
} }
internal: internal : OBSERVABLE_PROPERTY_RW(TokenType, Type);
OBSERVABLE_PROPERTY_RW(TokenType, Type);
private: private:
bool m_InEditMode; bool m_InEditMode;
}; };

View file

@ -44,7 +44,7 @@ namespace CalculatorApp
} }
StringReference idRef(id.c_str()); StringReference idRef(id.c_str());
String^ str = m_resLoader->GetString(idRef); String ^ str = m_resLoader->GetString(idRef);
return str->Begin(); return str->Begin();
} }
} }

View file

@ -14,6 +14,6 @@ namespace CalculatorApp
virtual std::wstring GetCEngineString(const std::wstring& id) override; virtual std::wstring GetCEngineString(const std::wstring& id) override;
private: private:
Windows::ApplicationModel::Resources::ResourceLoader^ m_resLoader; Windows::ApplicationModel::Resources::ResourceLoader ^ m_resLoader;
}; };
} }

View file

@ -7,7 +7,9 @@
using namespace CalculatorApp::Common; using namespace CalculatorApp::Common;
using namespace Windows::Storage::Streams; using namespace Windows::Storage::Streams;
CommandDeserializer::CommandDeserializer(_In_ DataReader^ dataReader) :m_dataReader(dataReader){} CommandDeserializer::CommandDeserializer(_In_ DataReader ^ dataReader) : m_dataReader(dataReader)
{
}
std::shared_ptr<IExpressionCommand> CommandDeserializer::Deserialize(_In_ CalculationManager::CommandType cmdType) std::shared_ptr<IExpressionCommand> CommandDeserializer::Deserialize(_In_ CalculationManager::CommandType cmdType)
{ {

View file

@ -12,11 +12,11 @@ namespace CalculatorApp
class CommandDeserializer class CommandDeserializer
{ {
public: public:
CommandDeserializer(_In_ Windows::Storage::Streams::DataReader^ dataReader); CommandDeserializer(_In_ Windows::Storage::Streams::DataReader ^ dataReader);
std::shared_ptr<IExpressionCommand> Deserialize(_In_ CalculationManager::CommandType cmdType); std::shared_ptr<IExpressionCommand> Deserialize(_In_ CalculationManager::CommandType cmdType);
private: private:
Windows::Storage::Streams::DataReader^ m_dataReader; Windows::Storage::Streams::DataReader ^ m_dataReader;
COpndCommand DeserializeOperand(); COpndCommand DeserializeOperand();
CParentheses DeserializeParentheses(); CParentheses DeserializeParentheses();
CUnaryCommand DeserializeUnary(); CUnaryCommand DeserializeUnary();

View file

@ -7,11 +7,11 @@
using namespace CalculatorApp::Common; using namespace CalculatorApp::Common;
using namespace Windows::Storage::Streams; using namespace Windows::Storage::Streams;
SerializeCommandVisitor::SerializeCommandVisitor(_In_ DataWriter^ dataWriter) :m_dataWriter(dataWriter) SerializeCommandVisitor::SerializeCommandVisitor(_In_ DataWriter ^ dataWriter) : m_dataWriter(dataWriter)
{ {
} }
void SerializeCommandVisitor::Visit(_In_ COpndCommand &opndCmd) void SerializeCommandVisitor::Visit(_In_ COpndCommand& opndCmd)
{ {
m_dataWriter->WriteBoolean(opndCmd.IsNegative()); m_dataWriter->WriteBoolean(opndCmd.IsNegative());
m_dataWriter->WriteBoolean(opndCmd.IsDecimalPresent()); m_dataWriter->WriteBoolean(opndCmd.IsDecimalPresent());
@ -29,7 +29,7 @@ void SerializeCommandVisitor::Visit(_In_ COpndCommand &opndCmd)
} }
} }
void SerializeCommandVisitor::Visit(_In_ CUnaryCommand &unaryCmd) void SerializeCommandVisitor::Visit(_In_ CUnaryCommand& unaryCmd)
{ {
auto cmds = unaryCmd.GetCommands(); auto cmds = unaryCmd.GetCommands();
unsigned int cmdSize; unsigned int cmdSize;
@ -43,13 +43,13 @@ void SerializeCommandVisitor::Visit(_In_ CUnaryCommand &unaryCmd)
} }
} }
void SerializeCommandVisitor::Visit(_In_ CBinaryCommand &binaryCmd) void SerializeCommandVisitor::Visit(_In_ CBinaryCommand& binaryCmd)
{ {
int cmd = binaryCmd.GetCommand(); int cmd = binaryCmd.GetCommand();
m_dataWriter->WriteInt32(cmd); m_dataWriter->WriteInt32(cmd);
} }
void SerializeCommandVisitor::Visit(_In_ CParentheses &paraCmd) void SerializeCommandVisitor::Visit(_In_ CParentheses& paraCmd)
{ {
int parenthesisCmd = paraCmd.GetCommand(); int parenthesisCmd = paraCmd.GetCommand();
m_dataWriter->WriteInt32(parenthesisCmd); m_dataWriter->WriteInt32(parenthesisCmd);

View file

@ -12,15 +12,15 @@ namespace CalculatorApp
class SerializeCommandVisitor : public ISerializeCommandVisitor class SerializeCommandVisitor : public ISerializeCommandVisitor
{ {
public: public:
SerializeCommandVisitor(_In_ Windows::Storage::Streams::DataWriter^ dataWriter); SerializeCommandVisitor(_In_ Windows::Storage::Streams::DataWriter ^ dataWriter);
void Visit(_In_ COpndCommand &opndCmd); void Visit(_In_ COpndCommand& opndCmd);
void Visit(_In_ CUnaryCommand &unaryCmd); void Visit(_In_ CUnaryCommand& unaryCmd);
void Visit(_In_ CBinaryCommand &binaryCmd); void Visit(_In_ CBinaryCommand& binaryCmd);
void Visit(_In_ CParentheses &paraCmd); void Visit(_In_ CParentheses& paraCmd);
private: private:
Windows::Storage::Streams::DataWriter^ m_dataWriter; Windows::Storage::Streams::DataWriter ^ m_dataWriter;
}; };
} }
} }

View file

@ -70,11 +70,11 @@ namespace CalculatorApp
} }
} }
void LightUpButton(ButtonBase^ button) void LightUpButton(ButtonBase ^ button)
{ {
// If the button is a toggle button then we don't need // If the button is a toggle button then we don't need
// to change the UI of the button // to change the UI of the button
if (dynamic_cast<ToggleButton^>(button)) if (dynamic_cast<ToggleButton ^>(button))
{ {
return; return;
} }
@ -92,9 +92,7 @@ namespace CalculatorApp
WeakReference timerWeakReference(timer); WeakReference timerWeakReference(timer);
WeakReference buttonWeakReference(button); WeakReference buttonWeakReference(button);
timer->Tick += ref new EventHandler<Object^>( timer->Tick += ref new EventHandler<Object ^>([buttonWeakReference, timerWeakReference](Object ^, Object ^) {
[buttonWeakReference, timerWeakReference](Object^, Object^)
{
auto button = buttonWeakReference.Resolve<ButtonBase>(); auto button = buttonWeakReference.Resolve<ButtonBase>();
if (button) if (button)
{ {
@ -130,7 +128,7 @@ namespace CalculatorApp
} }
} }
void RunButtonCommand(ButtonBase^ button) void RunButtonCommand(ButtonBase ^ button)
{ {
if (button->IsEnabled) if (button->IsEnabled)
{ {
@ -141,14 +139,14 @@ namespace CalculatorApp
command->Execute(parameter); command->Execute(parameter);
} }
auto radio = dynamic_cast<RadioButton^>(button); auto radio = dynamic_cast<RadioButton ^>(button);
if (radio) if (radio)
{ {
radio->IsChecked = true; radio->IsChecked = true;
return; return;
} }
auto toggle = dynamic_cast<ToggleButton^>(button); auto toggle = dynamic_cast<ToggleButton ^>(button);
if (toggle) if (toggle)
{ {
toggle->IsChecked = !toggle->IsChecked->Value; toggle->IsChecked = !toggle->IsChecked->Value;
@ -163,7 +161,7 @@ static multimap<int, bool> s_ignoreNextEscape;
static multimap<int, bool> s_keepIgnoringEscape; static multimap<int, bool> s_keepIgnoringEscape;
static multimap<int, bool> s_fHonorShortcuts; static multimap<int, bool> s_fHonorShortcuts;
static multimap<int, bool> s_fHandledEnter; static multimap<int, bool> s_fHandledEnter;
static multimap<int, Flyout^> s_AboutFlyout; static multimap<int, Flyout ^> s_AboutFlyout;
void KeyboardShortcutManager::IgnoreEscape(bool onlyOnce) void KeyboardShortcutManager::IgnoreEscape(bool onlyOnce)
{ {
@ -205,15 +203,12 @@ void KeyboardShortcutManager::HonorEscape()
} }
} }
void KeyboardShortcutManager::OnCharacterPropertyChanged( void KeyboardShortcutManager::OnCharacterPropertyChanged(DependencyObject ^ target, String ^ oldValue, String ^ newValue)
DependencyObject^ target,
String^ oldValue,
String^ newValue)
{ {
// Writer lock for the static maps // Writer lock for the static maps
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock); reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
auto button = safe_cast<ButtonBase^>(target); auto button = safe_cast<ButtonBase ^>(target);
int viewId = Utils::GetWindowId(); int viewId = Utils::GetWindowId();
auto iterViewMap = s_CharacterForButtons.find(viewId); auto iterViewMap = s_CharacterForButtons.find(viewId);
@ -254,15 +249,12 @@ void KeyboardShortcutManager::OnCharacterPropertyChanged(
} }
} }
void KeyboardShortcutManager::OnVirtualKeyPropertyChanged( void KeyboardShortcutManager::OnVirtualKeyPropertyChanged(DependencyObject ^ target, MyVirtualKey /*oldValue*/, MyVirtualKey newValue)
DependencyObject^ target,
MyVirtualKey /*oldValue*/,
MyVirtualKey newValue)
{ {
// Writer lock for the static maps // Writer lock for the static maps
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock); reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
auto button = static_cast<ButtonBase^>(target); auto button = static_cast<ButtonBase ^>(target);
int viewId = Utils::GetWindowId(); int viewId = Utils::GetWindowId();
auto iterViewMap = s_VirtualKeysForButtons.find(viewId); auto iterViewMap = s_VirtualKeysForButtons.find(viewId);
@ -280,20 +272,17 @@ void KeyboardShortcutManager::OnVirtualKeyPropertyChanged(
} }
} }
void KeyboardShortcutManager::OnVirtualKeyControlChordPropertyChanged( void KeyboardShortcutManager::OnVirtualKeyControlChordPropertyChanged(DependencyObject ^ target, MyVirtualKey /*oldValue*/, MyVirtualKey newValue)
DependencyObject^ target,
MyVirtualKey /*oldValue*/,
MyVirtualKey newValue)
{ {
// Writer lock for the static maps // Writer lock for the static maps
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock); reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
Control^ control = dynamic_cast<ButtonBase^>(target); Control ^ control = dynamic_cast<ButtonBase ^>(target);
if (control == nullptr) if (control == nullptr)
{ {
// Handling Ctrl+E shortcut for Date Calc, target would be NavigationView^ in that case // Handling Ctrl+E shortcut for Date Calc, target would be NavigationView^ in that case
control = safe_cast<MUXC::NavigationView^>(target); control = safe_cast<MUXC::NavigationView ^>(target);
} }
int viewId = Utils::GetWindowId(); int viewId = Utils::GetWindowId();
@ -312,15 +301,12 @@ void KeyboardShortcutManager::OnVirtualKeyControlChordPropertyChanged(
} }
} }
void KeyboardShortcutManager::OnVirtualKeyShiftChordPropertyChanged( void KeyboardShortcutManager::OnVirtualKeyShiftChordPropertyChanged(DependencyObject ^ target, MyVirtualKey /*oldValue*/, MyVirtualKey newValue)
DependencyObject^ target,
MyVirtualKey /*oldValue*/,
MyVirtualKey newValue)
{ {
// Writer lock for the static maps // Writer lock for the static maps
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock); reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
auto button = safe_cast<ButtonBase^>(target); auto button = safe_cast<ButtonBase ^>(target);
int viewId = Utils::GetWindowId(); int viewId = Utils::GetWindowId();
auto iterViewMap = s_VirtualKeyShiftChordsForButtons.find(viewId); auto iterViewMap = s_VirtualKeyShiftChordsForButtons.find(viewId);
@ -338,15 +324,12 @@ void KeyboardShortcutManager::OnVirtualKeyShiftChordPropertyChanged(
} }
} }
void KeyboardShortcutManager::OnVirtualKeyAltChordPropertyChanged( void KeyboardShortcutManager::OnVirtualKeyAltChordPropertyChanged(DependencyObject ^ target, MyVirtualKey /*oldValue*/, MyVirtualKey newValue)
DependencyObject^ target,
MyVirtualKey /*oldValue*/,
MyVirtualKey newValue)
{ {
// Writer lock for the static maps // Writer lock for the static maps
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock); reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
MUXC::NavigationView^ navView = safe_cast<MUXC::NavigationView^>(target); MUXC::NavigationView ^ navView = safe_cast<MUXC::NavigationView ^>(target);
int viewId = Utils::GetWindowId(); int viewId = Utils::GetWindowId();
auto iterViewMap = s_VirtualKeyAltChordsForButtons.find(viewId); auto iterViewMap = s_VirtualKeyAltChordsForButtons.find(viewId);
@ -364,15 +347,12 @@ void KeyboardShortcutManager::OnVirtualKeyAltChordPropertyChanged(
} }
} }
void KeyboardShortcutManager::OnVirtualKeyControlShiftChordPropertyChanged( void KeyboardShortcutManager::OnVirtualKeyControlShiftChordPropertyChanged(DependencyObject ^ target, MyVirtualKey /*oldValue*/, MyVirtualKey newValue)
DependencyObject^ target,
MyVirtualKey /*oldValue*/,
MyVirtualKey newValue)
{ {
// Writer lock for the static maps // Writer lock for the static maps
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock); reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
auto button = safe_cast<ButtonBase^>(target); auto button = safe_cast<ButtonBase ^>(target);
int viewId = Utils::GetWindowId(); int viewId = Utils::GetWindowId();
auto iterViewMap = s_VirtualKeyControlShiftChordsForButtons.find(viewId); auto iterViewMap = s_VirtualKeyControlShiftChordsForButtons.find(viewId);
@ -390,15 +370,12 @@ void KeyboardShortcutManager::OnVirtualKeyControlShiftChordPropertyChanged(
} }
} }
void KeyboardShortcutManager::OnVirtualKeyInverseChordPropertyChanged( void KeyboardShortcutManager::OnVirtualKeyInverseChordPropertyChanged(DependencyObject ^ target, MyVirtualKey /*oldValue*/, MyVirtualKey newValue)
DependencyObject^ target,
MyVirtualKey /*oldValue*/,
MyVirtualKey newValue)
{ {
// Writer lock for the static maps // Writer lock for the static maps
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock); reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
auto button = safe_cast<ButtonBase^>(target); auto button = safe_cast<ButtonBase ^>(target);
int viewId = Utils::GetWindowId(); int viewId = Utils::GetWindowId();
auto iterViewMap = s_VirtualKeyInverseChordsForButtons.find(viewId); auto iterViewMap = s_VirtualKeyInverseChordsForButtons.find(viewId);
@ -416,15 +393,12 @@ void KeyboardShortcutManager::OnVirtualKeyInverseChordPropertyChanged(
} }
} }
void KeyboardShortcutManager::OnVirtualKeyControlInverseChordPropertyChanged( void KeyboardShortcutManager::OnVirtualKeyControlInverseChordPropertyChanged(DependencyObject ^ target, MyVirtualKey /*oldValue*/, MyVirtualKey newValue)
DependencyObject^ target,
MyVirtualKey /*oldValue*/,
MyVirtualKey newValue)
{ {
// Writer lock for the static maps // Writer lock for the static maps
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock); reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
auto button = safe_cast<ButtonBase^>(target); auto button = safe_cast<ButtonBase ^>(target);
int viewId = Utils::GetWindowId(); int viewId = Utils::GetWindowId();
auto iterViewMap = s_VirtualKeyControlInverseChordsForButtons.find(viewId); auto iterViewMap = s_VirtualKeyControlInverseChordsForButtons.find(viewId);
@ -445,7 +419,7 @@ void KeyboardShortcutManager::OnVirtualKeyControlInverseChordPropertyChanged(
// In the three event handlers below we will not mark the event as handled // In the three event handlers below we will not mark the event as handled
// because this is a supplemental operation and we don't want to interfere with // because this is a supplemental operation and we don't want to interfere with
// the normal keyboard handling. // the normal keyboard handling.
void KeyboardShortcutManager::OnCharacterReceivedHandler(CoreWindow^ sender, CharacterReceivedEventArgs^ args) void KeyboardShortcutManager::OnCharacterReceivedHandler(CoreWindow ^ sender, CharacterReceivedEventArgs ^ args)
{ {
int viewId = Utils::GetWindowId(); int viewId = Utils::GetWindowId();
auto currentHonorShortcuts = s_fHonorShortcuts.find(viewId); auto currentHonorShortcuts = s_fHonorShortcuts.find(viewId);
@ -472,7 +446,8 @@ const std::multimap<MyVirtualKey, WeakReference>& GetCurrentKeyDictionary(MyVirt
{ {
return s_VirtualKeyAltChordsForButtons.find(viewId)->second; return s_VirtualKeyAltChordsForButtons.find(viewId)->second;
} }
else if ((s_ShiftKeyPressed.find(viewId)->second) && ((Window::Current->CoreWindow->GetKeyState(VirtualKey::Control) & CoreVirtualKeyStates::Down) == CoreVirtualKeyStates::Down)) else if ((s_ShiftKeyPressed.find(viewId)->second)
&& ((Window::Current->CoreWindow->GetKeyState(VirtualKey::Control) & CoreVirtualKeyStates::Down) == CoreVirtualKeyStates::Down))
{ {
return s_VirtualKeyControlShiftChordsForButtons.find(viewId)->second; return s_VirtualKeyControlShiftChordsForButtons.find(viewId)->second;
} }
@ -521,7 +496,7 @@ const std::multimap<MyVirtualKey, WeakReference>& GetCurrentKeyDictionary(MyVirt
} }
} }
void KeyboardShortcutManager::OnKeyDownHandler(CoreWindow^ sender, KeyEventArgs^ args) void KeyboardShortcutManager::OnKeyDownHandler(CoreWindow ^ sender, KeyEventArgs ^ args)
{ {
// If keyboard shortcuts like Ctrl+C or Ctrl+V are not handled // If keyboard shortcuts like Ctrl+C or Ctrl+V are not handled
if (!args->Handled) if (!args->Handled)
@ -536,19 +511,17 @@ void KeyboardShortcutManager::OnKeyDownHandler(CoreWindow^ sender, KeyEventArgs^
bool isShiftKeyPressed = (currentShiftKeyPressed != s_ShiftKeyPressed.end()) && (currentShiftKeyPressed->second); bool isShiftKeyPressed = (currentShiftKeyPressed != s_ShiftKeyPressed.end()) && (currentShiftKeyPressed->second);
// Handle Ctrl + E for DateCalculator // Handle Ctrl + E for DateCalculator
if ((key == VirtualKey::E) && if ((key == VirtualKey::E) && isControlKeyPressed && !isShiftKeyPressed)
isControlKeyPressed &&
!isShiftKeyPressed)
{ {
const auto& lookupMap = GetCurrentKeyDictionary(static_cast<MyVirtualKey>(key)); const auto& lookupMap = GetCurrentKeyDictionary(static_cast<MyVirtualKey>(key));
auto buttons = lookupMap.equal_range(static_cast<MyVirtualKey>(key)); auto buttons = lookupMap.equal_range(static_cast<MyVirtualKey>(key));
auto navView = buttons.first->second.Resolve<MUXC::NavigationView>(); auto navView = buttons.first->second.Resolve<MUXC::NavigationView>();
auto appViewModel = safe_cast<ApplicationViewModel^>(navView->DataContext); auto appViewModel = safe_cast<ApplicationViewModel ^>(navView->DataContext);
appViewModel->Mode = ViewMode::Date; appViewModel->Mode = ViewMode::Date;
auto categoryName = AppResourceProvider::GetInstance().GetResourceString(L"DateCalculationModeText"); auto categoryName = AppResourceProvider::GetInstance().GetResourceString(L"DateCalculationModeText");
appViewModel->CategoryName = categoryName; appViewModel->CategoryName = categoryName;
auto menuItems = static_cast<IObservableVector<Object^>^>(navView->MenuItemsSource); auto menuItems = static_cast<IObservableVector<Object ^> ^>(navView->MenuItemsSource);
auto flatIndex = NavCategory::GetFlatIndex(ViewMode::Date); auto flatIndex = NavCategory::GetFlatIndex(ViewMode::Date);
navView->SelectedItem = menuItems->GetAt(flatIndex); navView->SelectedItem = menuItems->GetAt(flatIndex);
return; return;
@ -615,9 +588,9 @@ void KeyboardShortcutManager::OnKeyDownHandler(CoreWindow^ sender, KeyEventArgs^
{ {
RunFirstEnabledButtonCommand(buttons); RunFirstEnabledButtonCommand(buttons);
// Ctrl+C and Ctrl+V shifts focus to some button because of which enter doesn't work after copy/paste. So don't shift focus if Ctrl+C or Ctrl+V is pressed. // Ctrl+C and Ctrl+V shifts focus to some button because of which enter doesn't work after copy/paste. So don't shift focus if Ctrl+C or Ctrl+V
// When drop down is open, pressing escape shifts focus to clear button. So dont's shift focus if drop down is open. // is pressed. When drop down is open, pressing escape shifts focus to clear button. So dont's shift focus if drop down is open. Ctrl+Insert is
// Ctrl+Insert is equivalent to Ctrl+C and Shift+Insert is equivalent to Ctrl+V // equivalent to Ctrl+C and Shift+Insert is equivalent to Ctrl+V
if (currentIsDropDownOpen != s_IsDropDownOpen.end() && !currentIsDropDownOpen->second) if (currentIsDropDownOpen != s_IsDropDownOpen.end() && !currentIsDropDownOpen->second)
{ {
// Do not Light Up Buttons when Ctrl+C, Ctrl+V, Ctrl+Insert or Shift+Insert is pressed // Do not Light Up Buttons when Ctrl+C, Ctrl+V, Ctrl+Insert or Shift+Insert is pressed
@ -632,7 +605,7 @@ void KeyboardShortcutManager::OnKeyDownHandler(CoreWindow^ sender, KeyEventArgs^
} }
} }
void KeyboardShortcutManager::OnKeyUpHandler(CoreWindow^ sender, KeyEventArgs^ args) void KeyboardShortcutManager::OnKeyUpHandler(CoreWindow ^ sender, KeyEventArgs ^ args)
{ {
int viewId = Utils::GetWindowId(); int viewId = Utils::GetWindowId();
auto key = args->VirtualKey; auto key = args->VirtualKey;
@ -665,7 +638,7 @@ void KeyboardShortcutManager::OnKeyUpHandler(CoreWindow^ sender, KeyEventArgs^ a
} }
} }
void KeyboardShortcutManager::OnAcceleratorKeyActivated(CoreDispatcher^, AcceleratorKeyEventArgs^ args) void KeyboardShortcutManager::OnAcceleratorKeyActivated(CoreDispatcher ^, AcceleratorKeyEventArgs ^ args)
{ {
if (args->KeyStatus.IsKeyReleased) if (args->KeyStatus.IsKeyReleased)
{ {
@ -685,12 +658,12 @@ void KeyboardShortcutManager::OnAcceleratorKeyActivated(CoreDispatcher^, Acceler
auto item = listIterator->second.Resolve<MUXC::NavigationView>(); auto item = listIterator->second.Resolve<MUXC::NavigationView>();
if (item != nullptr) if (item != nullptr)
{ {
auto navView = safe_cast<MUXC::NavigationView^> (item); auto navView = safe_cast<MUXC::NavigationView ^>(item);
auto menuItems = static_cast<IObservableVector<Object^>^>(navView->MenuItemsSource); auto menuItems = static_cast<IObservableVector<Object ^> ^>(navView->MenuItemsSource);
if (menuItems != nullptr) if (menuItems != nullptr)
{ {
auto vm = safe_cast<ApplicationViewModel^>(navView->DataContext); auto vm = safe_cast<ApplicationViewModel ^>(navView->DataContext);
if (nullptr != vm) if (nullptr != vm)
{ {
ViewMode toMode = NavCategory::GetViewModeForVirtualKey(static_cast<MyVirtualKey>(key)); ViewMode toMode = NavCategory::GetViewModeForVirtualKey(static_cast<MyVirtualKey>(key));
@ -722,13 +695,11 @@ void KeyboardShortcutManager::Initialize()
{ {
auto coreWindow = Window::Current->CoreWindow; auto coreWindow = Window::Current->CoreWindow;
coreWindow->CharacterReceived += coreWindow->CharacterReceived +=
ref new TypedEventHandler<CoreWindow^, CharacterReceivedEventArgs^>(&KeyboardShortcutManager::OnCharacterReceivedHandler); ref new TypedEventHandler<CoreWindow ^, CharacterReceivedEventArgs ^>(&KeyboardShortcutManager::OnCharacterReceivedHandler);
coreWindow->KeyDown += coreWindow->KeyDown += ref new TypedEventHandler<CoreWindow ^, KeyEventArgs ^>(&KeyboardShortcutManager::OnKeyDownHandler);
ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(&KeyboardShortcutManager::OnKeyDownHandler); coreWindow->KeyUp += ref new TypedEventHandler<CoreWindow ^, KeyEventArgs ^>(&KeyboardShortcutManager::OnKeyUpHandler);
coreWindow->KeyUp +=
ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(&KeyboardShortcutManager::OnKeyUpHandler);
coreWindow->Dispatcher->AcceleratorKeyActivated += coreWindow->Dispatcher->AcceleratorKeyActivated +=
ref new TypedEventHandler<CoreDispatcher^, AcceleratorKeyEventArgs^>(&KeyboardShortcutManager::OnAcceleratorKeyActivated); ref new TypedEventHandler<CoreDispatcher ^, AcceleratorKeyEventArgs ^>(&KeyboardShortcutManager::OnAcceleratorKeyActivated);
KeyboardShortcutManager::RegisterNewAppViewId(); KeyboardShortcutManager::RegisterNewAppViewId();
} }
@ -755,7 +726,7 @@ void KeyboardShortcutManager::UpdateDropDownState(bool isOpen)
} }
} }
void KeyboardShortcutManager::UpdateDropDownState(Flyout^ aboutPageFlyout) void KeyboardShortcutManager::UpdateDropDownState(Flyout ^ aboutPageFlyout)
{ {
int viewId = Utils::GetWindowId(); int viewId = Utils::GetWindowId();

View file

@ -10,14 +10,17 @@ namespace CalculatorApp
{ {
namespace Common namespace Common
{ {
public ref class KeyboardShortcutManager sealed public
ref class KeyboardShortcutManager sealed
{ {
public: public:
KeyboardShortcutManager() {} KeyboardShortcutManager()
{
}
DEPENDENCY_PROPERTY_OWNER(KeyboardShortcutManager); DEPENDENCY_PROPERTY_OWNER(KeyboardShortcutManager);
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(Platform::String^, Character); DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(Platform::String ^, Character);
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(MyVirtualKey, VirtualKey); DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(MyVirtualKey, VirtualKey);
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(MyVirtualKey, VirtualKeyControlChord); DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(MyVirtualKey, VirtualKeyControlChord);
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(MyVirtualKey, VirtualKeyShiftChord); DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(MyVirtualKey, VirtualKeyShiftChord);
@ -26,9 +29,10 @@ namespace CalculatorApp
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(MyVirtualKey, VirtualKeyInverseChord); DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(MyVirtualKey, VirtualKeyInverseChord);
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(MyVirtualKey, VirtualKeyControlInverseChord); DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(MyVirtualKey, VirtualKeyControlInverseChord);
internal: internal :
static void Initialize(); static void
Initialize();
// Sometimes, like with popups, escape is treated as special and even // Sometimes, like with popups, escape is treated as special and even
// though it is handled we get it passed through to us. In those cases // though it is handled we get it passed through to us. In those cases
@ -42,57 +46,34 @@ namespace CalculatorApp
static void HandledEnter(bool ishandled); static void HandledEnter(bool ishandled);
static void UpdateDropDownState(bool); static void UpdateDropDownState(bool);
static void ShiftButtonChecked(bool checked); static void ShiftButtonChecked(bool checked);
static void UpdateDropDownState(Windows::UI::Xaml::Controls::Flyout^ aboutPageFlyout); static void UpdateDropDownState(Windows::UI::Xaml::Controls::Flyout ^ aboutPageFlyout);
static void RegisterNewAppViewId(); static void RegisterNewAppViewId();
static void OnWindowClosed(int viewId); static void OnWindowClosed(int viewId);
private: private:
static void OnCharacterPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, Platform::String ^ oldValue, Platform::String ^ newValue);
static void OnCharacterPropertyChanged( static void OnVirtualKeyPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, MyVirtualKey oldValue, MyVirtualKey newValue);
Windows::UI::Xaml::DependencyObject^ target,
Platform::String^ oldValue,
Platform::String^ newValue);
static void OnVirtualKeyPropertyChanged( static void OnVirtualKeyControlChordPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, MyVirtualKey oldValue, MyVirtualKey newValue);
Windows::UI::Xaml::DependencyObject^ target,
MyVirtualKey oldValue, static void OnVirtualKeyShiftChordPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, MyVirtualKey oldValue, MyVirtualKey newValue);
static void OnVirtualKeyInverseChordPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, MyVirtualKey oldValue, MyVirtualKey newValue);
static void OnVirtualKeyControlInverseChordPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, MyVirtualKey oldValue,
MyVirtualKey newValue); MyVirtualKey newValue);
static void OnVirtualKeyControlChordPropertyChanged( static void OnVirtualKeyAltChordPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, MyVirtualKey oldValue, MyVirtualKey newValue);
Windows::UI::Xaml::DependencyObject^ target,
MyVirtualKey oldValue, static void OnVirtualKeyControlShiftChordPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, MyVirtualKey oldValue,
MyVirtualKey newValue); MyVirtualKey newValue);
static void OnVirtualKeyShiftChordPropertyChanged( static void OnCharacterReceivedHandler(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::CharacterReceivedEventArgs ^ args);
Windows::UI::Xaml::DependencyObject^ target, static void OnKeyDownHandler(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::KeyEventArgs ^ args);
MyVirtualKey oldValue, static void OnKeyUpHandler(Windows::UI::Core::CoreWindow ^ sender, Windows::UI::Core::KeyEventArgs ^ args);
MyVirtualKey newValue); static void OnAcceleratorKeyActivated(Windows::UI::Core::CoreDispatcher ^, Windows::UI::Core::AcceleratorKeyEventArgs ^ args);
static void OnVirtualKeyInverseChordPropertyChanged(
Windows::UI::Xaml::DependencyObject^ target,
MyVirtualKey oldValue,
MyVirtualKey newValue);
static void OnVirtualKeyControlInverseChordPropertyChanged(
Windows::UI::Xaml::DependencyObject^ target,
MyVirtualKey oldValue,
MyVirtualKey newValue);
static void OnVirtualKeyAltChordPropertyChanged(
Windows::UI::Xaml::DependencyObject^ target,
MyVirtualKey oldValue,
MyVirtualKey newValue);
static void OnVirtualKeyControlShiftChordPropertyChanged(
Windows::UI::Xaml::DependencyObject^ target,
MyVirtualKey oldValue,
MyVirtualKey newValue);
static void OnCharacterReceivedHandler(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CharacterReceivedEventArgs^ args);
static void OnKeyDownHandler(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args);
static void OnKeyUpHandler(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::KeyEventArgs^ args);
static void OnAcceleratorKeyActivated(Windows::UI::Core::CoreDispatcher^, Windows::UI::Core::AcceleratorKeyEventArgs^ args);
}; };
} }
} }

View file

@ -33,16 +33,15 @@ DEPENDENCY_PROPERTY_INITIALIZATION(LocalizationService, FontSize);
static reader_writer_lock s_locServiceInstanceLock; static reader_writer_lock s_locServiceInstanceLock;
LocalizationService^ LocalizationService::s_singletonInstance = nullptr; LocalizationService ^ LocalizationService::s_singletonInstance = nullptr;
// Resources for the engine use numbers as keys. It's inconvenient, but also difficult to // Resources for the engine use numbers as keys. It's inconvenient, but also difficult to
// change given that the engine heavily relies on perfect ordering of certain elements. // change given that the engine heavily relies on perfect ordering of certain elements.
// The key for open parenthesis, '(', is "48". // The key for open parenthesis, '(', is "48".
static constexpr auto s_openParenResourceKey = L"48"; static constexpr auto s_openParenResourceKey = L"48";
LocalizationService^ LocalizationService::GetInstance() LocalizationService ^ LocalizationService::GetInstance()
{ {
if (s_singletonInstance == nullptr) if (s_singletonInstance == nullptr)
{ {
// Writer lock for the static maps // Writer lock for the static maps
@ -59,20 +58,20 @@ LocalizationService^ LocalizationService::GetInstance()
LocalizationService::LocalizationService() LocalizationService::LocalizationService()
{ {
m_language = ApplicationLanguages::Languages->GetAt(0); m_language = ApplicationLanguages::Languages->GetAt(0);
m_flowDirection = ResourceContext::GetForCurrentView()->QualifierValues->Lookup(L"LayoutDirection") m_flowDirection =
!= L"LTR" ? FlowDirection::RightToLeft : FlowDirection::LeftToRight; ResourceContext::GetForCurrentView()->QualifierValues->Lookup(L"LayoutDirection") != L"LTR" ? FlowDirection::RightToLeft : FlowDirection::LeftToRight;
auto resourceLoader = AppResourceProvider::GetInstance(); auto resourceLoader = AppResourceProvider::GetInstance();
m_fontFamilyOverride = resourceLoader.GetResourceString(L"LocalizedFontFamilyOverride"); m_fontFamilyOverride = resourceLoader.GetResourceString(L"LocalizedFontFamilyOverride");
String^ reserved = L"RESERVED_FOR_FONTLOC"; String ^ reserved = L"RESERVED_FOR_FONTLOC";
m_overrideFontApiValues = ((m_fontFamilyOverride != nullptr) && (m_fontFamilyOverride != reserved)); m_overrideFontApiValues = ((m_fontFamilyOverride != nullptr) && (m_fontFamilyOverride != reserved));
if (m_overrideFontApiValues) if (m_overrideFontApiValues)
{ {
String^ localizedUICaptionFontSizeFactorOverride = resourceLoader.GetResourceString(L"LocalizedUICaptionFontSizeFactorOverride"); String ^ localizedUICaptionFontSizeFactorOverride = resourceLoader.GetResourceString(L"LocalizedUICaptionFontSizeFactorOverride");
String^ localizedUITextFontSizeFactorOverride = resourceLoader.GetResourceString(L"LocalizedUITextFontSizeFactorOverride"); String ^ localizedUITextFontSizeFactorOverride = resourceLoader.GetResourceString(L"LocalizedUITextFontSizeFactorOverride");
String^ localizedFontWeightOverride = resourceLoader.GetResourceString(L"LocalizedFontWeightOverride"); String ^ localizedFontWeightOverride = resourceLoader.GetResourceString(L"LocalizedFontWeightOverride");
// If any of the font overrides are modified then all of them need to be modified // If any of the font overrides are modified then all of them need to be modified
assert(localizedFontWeightOverride != reserved); assert(localizedFontWeightOverride != reserved);
@ -87,7 +86,7 @@ LocalizationService::LocalizationService()
m_fontGroup = ref new LanguageFontGroup(m_language); m_fontGroup = ref new LanguageFontGroup(m_language);
} }
FontWeight LocalizationService::ParseFontWeight(String^ fontWeight) FontWeight LocalizationService::ParseFontWeight(String ^ fontWeight)
{ {
wstring weight = fontWeight->Data(); wstring weight = fontWeight->Data();
transform(weight.begin(), weight.end(), weight.begin(), towlower); transform(weight.begin(), weight.end(), weight.begin(), towlower);
@ -153,7 +152,7 @@ bool LocalizationService::IsRtlLayout()
return m_flowDirection == FlowDirection::RightToLeft; return m_flowDirection == FlowDirection::RightToLeft;
} }
String^ LocalizationService::GetLanguage() String ^ LocalizationService::GetLanguage()
{ {
return m_language; return m_language;
} }
@ -163,7 +162,7 @@ bool LocalizationService::GetOverrideFontApiValues()
return m_overrideFontApiValues; return m_overrideFontApiValues;
} }
FontFamily^ LocalizationService::GetLanguageFontFamilyForType(LanguageFontType fontType) FontFamily ^ LocalizationService::GetLanguageFontFamilyForType(LanguageFontType fontType)
{ {
if (m_overrideFontApiValues) if (m_overrideFontApiValues)
{ {
@ -175,7 +174,7 @@ FontFamily^ LocalizationService::GetLanguageFontFamilyForType(LanguageFontType f
} }
} }
LanguageFont^ LocalizationService::GetLanguageFont(LanguageFontType fontType) LanguageFont ^ LocalizationService::GetLanguageFont(LanguageFontType fontType)
{ {
assert(!m_overrideFontApiValues); assert(!m_overrideFontApiValues);
assert(m_fontGroup); assert(m_fontGroup);
@ -191,7 +190,7 @@ LanguageFont^ LocalizationService::GetLanguageFont(LanguageFontType fontType)
} }
} }
String^ LocalizationService::GetFontFamilyOverride() String ^ LocalizationService::GetFontFamilyOverride()
{ {
assert(m_overrideFontApiValues); assert(m_overrideFontApiValues);
return m_fontFamilyOverride; return m_fontFamilyOverride;
@ -218,24 +217,24 @@ double LocalizationService::GetFontScaleFactorOverride(LanguageFontType fontType
} }
} }
void LocalizationService::OnFontTypePropertyChanged(DependencyObject^ target, LanguageFontType /*oldValue*/, LanguageFontType /*newValue*/) void LocalizationService::OnFontTypePropertyChanged(DependencyObject ^ target, LanguageFontType /*oldValue*/, LanguageFontType /*newValue*/)
{ {
UpdateFontFamilyAndSize(target); UpdateFontFamilyAndSize(target);
} }
void LocalizationService::OnFontWeightPropertyChanged(DependencyObject^ target, FontWeight /*oldValue*/, FontWeight /*newValue*/) void LocalizationService::OnFontWeightPropertyChanged(DependencyObject ^ target, FontWeight /*oldValue*/, FontWeight /*newValue*/)
{ {
UpdateFontFamilyAndSize(target); UpdateFontFamilyAndSize(target);
} }
void LocalizationService::OnFontSizePropertyChanged(DependencyObject^ target, double /*oldValue*/, double /*newValue*/) void LocalizationService::OnFontSizePropertyChanged(DependencyObject ^ target, double /*oldValue*/, double /*newValue*/)
{ {
UpdateFontFamilyAndSize(target); UpdateFontFamilyAndSize(target);
} }
void LocalizationService::UpdateFontFamilyAndSize(DependencyObject^ target) void LocalizationService::UpdateFontFamilyAndSize(DependencyObject ^ target)
{ {
FontFamily^ fontFamily; FontFamily ^ fontFamily;
FontWeight fontWeight; FontWeight fontWeight;
bool fOverrideFontWeight = false; bool fOverrideFontWeight = false;
double scaleFactor; double scaleFactor;
@ -259,7 +258,7 @@ void LocalizationService::UpdateFontFamilyAndSize(DependencyObject^ target)
double sizeToUse = LocalizationService::GetFontSize(target) * scaleFactor; double sizeToUse = LocalizationService::GetFontSize(target) * scaleFactor;
auto control = dynamic_cast<Control^>(target); auto control = dynamic_cast<Control ^>(target);
if (control) if (control)
{ {
control->FontFamily = fontFamily; control->FontFamily = fontFamily;
@ -278,7 +277,7 @@ void LocalizationService::UpdateFontFamilyAndSize(DependencyObject^ target)
} }
else else
{ {
auto textBlock = dynamic_cast<TextBlock^>(target); auto textBlock = dynamic_cast<TextBlock ^>(target);
if (textBlock) if (textBlock)
{ {
textBlock->FontFamily = fontFamily; textBlock->FontFamily = fontFamily;
@ -297,7 +296,7 @@ void LocalizationService::UpdateFontFamilyAndSize(DependencyObject^ target)
} }
else else
{ {
RichTextBlock^ richTextBlock = dynamic_cast<RichTextBlock^>(target); RichTextBlock ^ richTextBlock = dynamic_cast<RichTextBlock ^>(target);
if (richTextBlock) if (richTextBlock)
{ {
richTextBlock->FontFamily = fontFamily; richTextBlock->FontFamily = fontFamily;
@ -316,7 +315,7 @@ void LocalizationService::UpdateFontFamilyAndSize(DependencyObject^ target)
} }
else else
{ {
TextElement^ textElement = dynamic_cast<TextElement^>(target); TextElement ^ textElement = dynamic_cast<TextElement ^>(target);
if (textElement) if (textElement)
{ {
textElement->FontFamily = fontFamily; textElement->FontFamily = fontFamily;
@ -340,9 +339,9 @@ void LocalizationService::UpdateFontFamilyAndSize(DependencyObject^ target)
// If successful, returns a formatter that respects the user's regional format settings, // If successful, returns a formatter that respects the user's regional format settings,
// as configured by running intl.cpl. // as configured by running intl.cpl.
DecimalFormatter^ LocalizationService::GetRegionalSettingsAwareDecimalFormatter() DecimalFormatter ^ LocalizationService::GetRegionalSettingsAwareDecimalFormatter()
{ {
IIterable<String^>^ languageIdentifiers = LocalizationService::GetLanguageIdentifiers(); IIterable<String ^> ^ languageIdentifiers = LocalizationService::GetLanguageIdentifiers();
if (languageIdentifiers != nullptr) if (languageIdentifiers != nullptr)
{ {
return ref new DecimalFormatter(languageIdentifiers, GlobalizationPreferences::HomeGeographicRegion); return ref new DecimalFormatter(languageIdentifiers, GlobalizationPreferences::HomeGeographicRegion);
@ -355,9 +354,9 @@ DecimalFormatter^ LocalizationService::GetRegionalSettingsAwareDecimalFormatter(
// as configured by running intl.cpl. // as configured by running intl.cpl.
// //
// This helper function creates a DateTimeFormatter with a TwentyFour hour clock // This helper function creates a DateTimeFormatter with a TwentyFour hour clock
DateTimeFormatter^ LocalizationService::GetRegionalSettingsAwareDateTimeFormatter(_In_ String^ format) DateTimeFormatter ^ LocalizationService::GetRegionalSettingsAwareDateTimeFormatter(_In_ String ^ format)
{ {
IIterable<String^>^ languageIdentifiers = LocalizationService::GetLanguageIdentifiers(); IIterable<String ^> ^ languageIdentifiers = LocalizationService::GetLanguageIdentifiers();
if (languageIdentifiers == nullptr) if (languageIdentifiers == nullptr)
{ {
languageIdentifiers = ApplicationLanguages::Languages; languageIdentifiers = ApplicationLanguages::Languages;
@ -368,41 +367,30 @@ DateTimeFormatter^ LocalizationService::GetRegionalSettingsAwareDateTimeFormatte
// If successful, returns a formatter that respects the user's regional format settings, // If successful, returns a formatter that respects the user's regional format settings,
// as configured by running intl.cpl. // as configured by running intl.cpl.
DateTimeFormatter^ LocalizationService::GetRegionalSettingsAwareDateTimeFormatter( DateTimeFormatter
_In_ String^ format, ^ LocalizationService::GetRegionalSettingsAwareDateTimeFormatter(_In_ String ^ format, _In_ String ^ calendarIdentifier, _In_ String ^ clockIdentifier)
_In_ String^ calendarIdentifier,
_In_ String^ clockIdentifier)
{ {
IIterable<String^>^ languageIdentifiers = LocalizationService::GetLanguageIdentifiers(); IIterable<String ^> ^ languageIdentifiers = LocalizationService::GetLanguageIdentifiers();
if (languageIdentifiers == nullptr) if (languageIdentifiers == nullptr)
{ {
languageIdentifiers = ApplicationLanguages::Languages; languageIdentifiers = ApplicationLanguages::Languages;
} }
return ref new DateTimeFormatter( return ref new DateTimeFormatter(format, languageIdentifiers, GlobalizationPreferences::HomeGeographicRegion, calendarIdentifier, clockIdentifier);
format,
languageIdentifiers,
GlobalizationPreferences::HomeGeographicRegion,
calendarIdentifier,
clockIdentifier);
} }
CurrencyFormatter^ LocalizationService::GetRegionalSettingsAwareCurrencyFormatter() CurrencyFormatter ^ LocalizationService::GetRegionalSettingsAwareCurrencyFormatter()
{ {
String^ userCurrency = (GlobalizationPreferences::Currencies->Size > 0) String ^ userCurrency =
? GlobalizationPreferences::Currencies->GetAt(0) (GlobalizationPreferences::Currencies->Size > 0) ? GlobalizationPreferences::Currencies->GetAt(0) : StringReference(DefaultCurrencyCode.data());
: StringReference(DefaultCurrencyCode.data());
IIterable<String^>^ languageIdentifiers = LocalizationService::GetLanguageIdentifiers(); IIterable<String ^> ^ languageIdentifiers = LocalizationService::GetLanguageIdentifiers();
if (languageIdentifiers == nullptr) if (languageIdentifiers == nullptr)
{ {
languageIdentifiers = ApplicationLanguages::Languages; languageIdentifiers = ApplicationLanguages::Languages;
} }
auto currencyFormatter = ref new CurrencyFormatter( auto currencyFormatter = ref new CurrencyFormatter(userCurrency, languageIdentifiers, GlobalizationPreferences::HomeGeographicRegion);
userCurrency,
languageIdentifiers,
GlobalizationPreferences::HomeGeographicRegion);
int fractionDigits = LocalizationSettings::GetInstance().GetCurrencyTrailingDigits(); int fractionDigits = LocalizationSettings::GetInstance().GetCurrencyTrailingDigits();
currencyFormatter->FractionDigits = fractionDigits; currencyFormatter->FractionDigits = fractionDigits;
@ -410,7 +398,7 @@ CurrencyFormatter^ LocalizationService::GetRegionalSettingsAwareCurrencyFormatte
return currencyFormatter; return currencyFormatter;
} }
IIterable<String^>^ LocalizationService::GetLanguageIdentifiers() IIterable<String ^> ^ LocalizationService::GetLanguageIdentifiers()
{ {
WCHAR currentLocale[LOCALE_NAME_MAX_LENGTH] = {}; WCHAR currentLocale[LOCALE_NAME_MAX_LENGTH] = {};
int result = GetUserDefaultLocaleName(currentLocale, LOCALE_NAME_MAX_LENGTH); int result = GetUserDefaultLocaleName(currentLocale, LOCALE_NAME_MAX_LENGTH);
@ -426,12 +414,12 @@ IIterable<String^>^ LocalizationService::GetLanguageIdentifiers()
*underscore = L'\0'; *underscore = L'\0';
} }
String^ localeString = ref new String(currentLocale); String ^ localeString = ref new String(currentLocale);
// validate if the locale we have is valid // validate if the locale we have is valid
// otherwise we fallback to the default. // otherwise we fallback to the default.
if (Language::IsWellFormed(localeString)) if (Language::IsWellFormed(localeString))
{ {
auto languageList = ref new Vector<String^>(); auto languageList = ref new Vector<String ^>();
languageList->Append(localeString); languageList->Append(localeString);
return languageList; return languageList;
} }
@ -448,44 +436,29 @@ unordered_map<wstring, wstring> LocalizationService::GetTokenToReadableNameMap()
// standard project resources. // standard project resources.
static vector<pair<wstring, wstring>> s_parenEngineKeyResourceMap = { static vector<pair<wstring, wstring>> s_parenEngineKeyResourceMap = {
// Sine permutations // Sine permutations
make_pair<wstring, wstring>(L"67", L"SineDegrees"), make_pair<wstring, wstring>(L"67", L"SineDegrees"), make_pair<wstring, wstring>(L"73", L"SineRadians"),
make_pair<wstring, wstring>(L"73", L"SineRadians"), make_pair<wstring, wstring>(L"79", L"SineGradians"), make_pair<wstring, wstring>(L"70", L"InverseSineDegrees"),
make_pair<wstring, wstring>(L"79", L"SineGradians"), make_pair<wstring, wstring>(L"76", L"InverseSineRadians"), make_pair<wstring, wstring>(L"82", L"InverseSineGradians"),
make_pair<wstring, wstring>(L"70", L"InverseSineDegrees"), make_pair<wstring, wstring>(L"25", L"HyperbolicSine"), make_pair<wstring, wstring>(L"85", L"InverseHyperbolicSine"),
make_pair<wstring, wstring>(L"76", L"InverseSineRadians"),
make_pair<wstring, wstring>(L"82", L"InverseSineGradians"),
make_pair<wstring, wstring>(L"25", L"HyperbolicSine"),
make_pair<wstring, wstring>(L"85", L"InverseHyperbolicSine"),
// Cosine permutations // Cosine permutations
make_pair<wstring, wstring>(L"68", L"CosineDegrees"), make_pair<wstring, wstring>(L"68", L"CosineDegrees"), make_pair<wstring, wstring>(L"74", L"CosineRadians"),
make_pair<wstring, wstring>(L"74", L"CosineRadians"), make_pair<wstring, wstring>(L"80", L"CosineGradians"), make_pair<wstring, wstring>(L"71", L"InverseCosineDegrees"),
make_pair<wstring, wstring>(L"80", L"CosineGradians"), make_pair<wstring, wstring>(L"77", L"InverseCosineRadians"), make_pair<wstring, wstring>(L"83", L"InverseCosineGradians"),
make_pair<wstring, wstring>(L"71", L"InverseCosineDegrees"), make_pair<wstring, wstring>(L"26", L"HyperbolicCosine"), make_pair<wstring, wstring>(L"86", L"InverseHyperbolicCosine"),
make_pair<wstring, wstring>(L"77", L"InverseCosineRadians"),
make_pair<wstring, wstring>(L"83", L"InverseCosineGradians"),
make_pair<wstring, wstring>(L"26", L"HyperbolicCosine"),
make_pair<wstring, wstring>(L"86", L"InverseHyperbolicCosine"),
// Tangent permutations // Tangent permutations
make_pair<wstring, wstring>(L"69", L"TangentDegrees"), make_pair<wstring, wstring>(L"69", L"TangentDegrees"), make_pair<wstring, wstring>(L"75", L"TangentRadians"),
make_pair<wstring, wstring>(L"75", L"TangentRadians"), make_pair<wstring, wstring>(L"81", L"TangentGradians"), make_pair<wstring, wstring>(L"72", L"InverseTangentDegrees"),
make_pair<wstring, wstring>(L"81", L"TangentGradians"), make_pair<wstring, wstring>(L"78", L"InverseTangentRadians"), make_pair<wstring, wstring>(L"84", L"InverseTangentGradians"),
make_pair<wstring, wstring>(L"72", L"InverseTangentDegrees"), make_pair<wstring, wstring>(L"27", L"HyperbolicTangent"), make_pair<wstring, wstring>(L"87", L"InverseHyperbolicTangent"),
make_pair<wstring, wstring>(L"78", L"InverseTangentRadians"),
make_pair<wstring, wstring>(L"84", L"InverseTangentGradians"),
make_pair<wstring, wstring>(L"27", L"HyperbolicTangent"),
make_pair<wstring, wstring>(L"87", L"InverseHyperbolicTangent"),
// Miscellaneous Scientific functions // Miscellaneous Scientific functions
make_pair<wstring, wstring>(L"94", L"Factorial"), make_pair<wstring, wstring>(L"94", L"Factorial"), make_pair<wstring, wstring>(L"35", L"DegreeMinuteSecond"),
make_pair<wstring, wstring>(L"35", L"DegreeMinuteSecond"), make_pair<wstring, wstring>(L"28", L"NaturalLog"), make_pair<wstring, wstring>(L"91", L"Square")
make_pair<wstring, wstring>(L"28", L"NaturalLog"),
make_pair<wstring, wstring>(L"91", L"Square")
}; };
static vector<pair<wstring, wstring>> s_noParenEngineKeyResourceMap = { static vector<pair<wstring, wstring>> s_noParenEngineKeyResourceMap = { // Programmer mode functions
// Programmer mode functions
make_pair<wstring, wstring>(L"9", L"LeftShift"), make_pair<wstring, wstring>(L"9", L"LeftShift"),
make_pair<wstring, wstring>(L"10", L"RightShift"), make_pair<wstring, wstring>(L"10", L"RightShift"),
@ -523,7 +496,7 @@ unordered_map<wstring, wstring> LocalizationService::GetTokenToReadableNameMap()
return tokenToReadableNameMap; return tokenToReadableNameMap;
} }
String^ LocalizationService::GetNarratorReadableToken(String^ rawToken) String ^ LocalizationService::GetNarratorReadableToken(String ^ rawToken)
{ {
static unordered_map<wstring, wstring> s_tokenToReadableNameMap = GetTokenToReadableNameMap(); static unordered_map<wstring, wstring> s_tokenToReadableNameMap = GetTokenToReadableNameMap();
@ -534,12 +507,12 @@ String^ LocalizationService::GetNarratorReadableToken(String^ rawToken)
} }
else else
{ {
static const String^ openParen = AppResourceProvider::GetInstance().GetCEngineString(StringReference(s_openParenResourceKey)); static const String ^ openParen = AppResourceProvider::GetInstance().GetCEngineString(StringReference(s_openParenResourceKey));
return ref new String(itr->second.c_str()) + L" " + openParen; return ref new String(itr->second.c_str()) + L" " + openParen;
} }
} }
String^ LocalizationService::GetNarratorReadableString(String^ rawString) String ^ LocalizationService::GetNarratorReadableString(String ^ rawString)
{ {
wstringstream readableString{}; wstringstream readableString{};
readableString << L""; readableString << L"";

View file

@ -5,81 +5,83 @@
#include "Utils.h" #include "Utils.h"
namespace CalculatorApp { namespace Common namespace CalculatorApp
{ {
namespace Common
{
namespace LocalizationServiceProperties namespace LocalizationServiceProperties
{ {
static constexpr std::wstring_view DefaultCurrencyCode{ L"USD" }; static constexpr std::wstring_view DefaultCurrencyCode{ L"USD" };
} }
public enum class LanguageFontType public
enum class LanguageFontType
{ {
UIText, UIText,
UICaption, UICaption,
}; };
public ref class LocalizationService sealed public
ref class LocalizationService sealed
{ {
public: public:
DEPENDENCY_PROPERTY_OWNER(LocalizationService); DEPENDENCY_PROPERTY_OWNER(LocalizationService);
DEPENDENCY_PROPERTY_ATTACHED_WITH_DEFAULT_AND_CALLBACK(LanguageFontType, FontType, LanguageFontType::UIText); DEPENDENCY_PROPERTY_ATTACHED_WITH_DEFAULT_AND_CALLBACK(LanguageFontType, FontType, LanguageFontType::UIText);
DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(double, FontSize); DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(double, FontSize);
internal: internal : static LocalizationService ^ GetInstance();
static LocalizationService^ GetInstance();
Windows::UI::Xaml::FlowDirection GetFlowDirection(); Windows::UI::Xaml::FlowDirection GetFlowDirection();
bool IsRtlLayout(); bool IsRtlLayout();
bool GetOverrideFontApiValues(); bool GetOverrideFontApiValues();
Platform::String^ GetLanguage(); Platform::String ^ GetLanguage();
Windows::UI::Xaml::Media::FontFamily^ GetLanguageFontFamilyForType(LanguageFontType fontType); Windows::UI::Xaml::Media::FontFamily ^ GetLanguageFontFamilyForType(LanguageFontType fontType);
Platform::String^ GetFontFamilyOverride(); Platform::String ^ GetFontFamilyOverride();
Windows::UI::Text::FontWeight GetFontWeightOverride(); Windows::UI::Text::FontWeight GetFontWeightOverride();
double GetFontScaleFactorOverride(LanguageFontType fontType); double GetFontScaleFactorOverride(LanguageFontType fontType);
static Windows::Globalization::NumberFormatting::DecimalFormatter^ GetRegionalSettingsAwareDecimalFormatter(); static Windows::Globalization::NumberFormatting::DecimalFormatter ^ GetRegionalSettingsAwareDecimalFormatter();
static Windows::Globalization::DateTimeFormatting::DateTimeFormatter^ GetRegionalSettingsAwareDateTimeFormatter(_In_ Platform::String^ format); static Windows::Globalization::DateTimeFormatting::DateTimeFormatter ^ GetRegionalSettingsAwareDateTimeFormatter(_In_ Platform::String ^ format);
static Windows::Globalization::DateTimeFormatting::DateTimeFormatter^ GetRegionalSettingsAwareDateTimeFormatter( static Windows::Globalization::DateTimeFormatting::DateTimeFormatter
_In_ Platform::String^ format, ^ GetRegionalSettingsAwareDateTimeFormatter(_In_ Platform::String ^ format, _In_ Platform::String ^ calendarIdentifier,
_In_ Platform::String^ calendarIdentifier, _In_ Platform::String ^ clockIdentifier);
_In_ Platform::String^ clockIdentifier);
static Windows::Globalization::NumberFormatting::CurrencyFormatter^ GetRegionalSettingsAwareCurrencyFormatter(); static Windows::Globalization::NumberFormatting::CurrencyFormatter ^ GetRegionalSettingsAwareCurrencyFormatter();
static Platform::String^ GetNarratorReadableToken(Platform::String^ rawToken); static Platform::String ^ GetNarratorReadableToken(Platform::String ^ rawToken);
static Platform::String^ GetNarratorReadableString(Platform::String^ rawString); static Platform::String ^ GetNarratorReadableString(Platform::String ^ rawString);
private: private:
Windows::Globalization::Fonts::LanguageFont^ GetLanguageFont(LanguageFontType fontType); Windows::Globalization::Fonts::LanguageFont ^ GetLanguageFont(LanguageFontType fontType);
Windows::UI::Text::FontWeight ParseFontWeight(Platform::String^ fontWeight); Windows::UI::Text::FontWeight ParseFontWeight(Platform::String ^ fontWeight);
static Windows::Foundation::Collections::IIterable<Platform::String^>^ GetLanguageIdentifiers(); static Windows::Foundation::Collections::IIterable<Platform::String ^> ^ GetLanguageIdentifiers();
// Attached property callbacks // Attached property callbacks
static void OnFontTypePropertyChanged(Windows::UI::Xaml::DependencyObject^ target, LanguageFontType oldValue, LanguageFontType newValue); static void OnFontTypePropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, LanguageFontType oldValue, LanguageFontType newValue);
static void OnFontWeightPropertyChanged(Windows::UI::Xaml::DependencyObject^ target, Windows::UI::Text::FontWeight oldValue, Windows::UI::Text::FontWeight newValue); static void OnFontWeightPropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, Windows::UI::Text::FontWeight oldValue,
static void OnFontSizePropertyChanged(Windows::UI::Xaml::DependencyObject^ target, double oldValue, double newValue); Windows::UI::Text::FontWeight newValue);
static void OnFontSizePropertyChanged(Windows::UI::Xaml::DependencyObject ^ target, double oldValue, double newValue);
static void UpdateFontFamilyAndSize(Windows::UI::Xaml::DependencyObject^ target); static void UpdateFontFamilyAndSize(Windows::UI::Xaml::DependencyObject ^ target);
static std::unordered_map<std::wstring, std::wstring> GetTokenToReadableNameMap(); static std::unordered_map<std::wstring, std::wstring> GetTokenToReadableNameMap();
private: private:
LocalizationService(); LocalizationService();
static LocalizationService^ s_singletonInstance; static LocalizationService ^ s_singletonInstance;
Windows::Globalization::Fonts::LanguageFontGroup^ m_fontGroup; Windows::Globalization::Fonts::LanguageFontGroup ^ m_fontGroup;
Platform::String^ m_language; Platform::String ^ m_language;
Windows::UI::Xaml::FlowDirection m_flowDirection; Windows::UI::Xaml::FlowDirection m_flowDirection;
bool m_overrideFontApiValues; bool m_overrideFontApiValues;
Platform::String^ m_fontFamilyOverride; Platform::String ^ m_fontFamilyOverride;
Windows::UI::Text::FontWeight m_fontWeightOverride; Windows::UI::Text::FontWeight m_fontWeightOverride;
double m_uiTextFontScaleFactorOverride; double m_uiTextFontScaleFactorOverride;
double m_uiCaptionFontScaleFactorOverride; double m_uiCaptionFontScaleFactorOverride;
}; };
}} }
}

View file

@ -18,7 +18,7 @@ namespace CalculatorApp
int result = 0; int result = 0;
// Use DecimalFormatter as it respects the locale and the user setting // Use DecimalFormatter as it respects the locale and the user setting
Windows::Globalization::NumberFormatting::DecimalFormatter^ formatter; Windows::Globalization::NumberFormatting::DecimalFormatter ^ formatter;
formatter = CalculatorApp::Common::LocalizationService::GetRegionalSettingsAwareDecimalFormatter(); formatter = CalculatorApp::Common::LocalizationService::GetRegionalSettingsAwareDecimalFormatter();
formatter->FractionDigits = 0; formatter->FractionDigits = 0;
formatter->IsDecimalPointAlwaysDisplayed = false; formatter->IsDecimalPointAlwaysDisplayed = false;
@ -29,9 +29,7 @@ namespace CalculatorApp
} }
wchar_t resolvedName[LOCALE_NAME_MAX_LENGTH]; wchar_t resolvedName[LOCALE_NAME_MAX_LENGTH];
result = ResolveLocaleName(formatter->ResolvedLanguage->Data(), result = ResolveLocaleName(formatter->ResolvedLanguage->Data(), resolvedName, LOCALE_NAME_MAX_LENGTH);
resolvedName,
LOCALE_NAME_MAX_LENGTH);
if (result == 0) if (result == 0)
{ {
throw std::runtime_error("Unexpected error resolving locale name"); throw std::runtime_error("Unexpected error resolving locale name");
@ -40,30 +38,21 @@ namespace CalculatorApp
{ {
m_resolvedName = resolvedName; m_resolvedName = resolvedName;
wchar_t decimalString[LocaleSettingBufferSize] = L""; wchar_t decimalString[LocaleSettingBufferSize] = L"";
result = GetLocaleInfoEx(m_resolvedName.c_str(), result = GetLocaleInfoEx(m_resolvedName.c_str(), LOCALE_SDECIMAL, decimalString, static_cast<int>(std::size(decimalString)));
LOCALE_SDECIMAL,
decimalString,
static_cast<int>(std::size(decimalString)));
if (result == 0) if (result == 0)
{ {
throw std::runtime_error("Unexpected error while getting locale info"); throw std::runtime_error("Unexpected error while getting locale info");
} }
wchar_t groupingSymbolString[LocaleSettingBufferSize] = L""; wchar_t groupingSymbolString[LocaleSettingBufferSize] = L"";
result = GetLocaleInfoEx(m_resolvedName.c_str(), result = GetLocaleInfoEx(m_resolvedName.c_str(), LOCALE_STHOUSAND, groupingSymbolString, static_cast<int>(std::size(groupingSymbolString)));
LOCALE_STHOUSAND,
groupingSymbolString,
static_cast<int>(std::size(groupingSymbolString)));
if (result == 0) if (result == 0)
{ {
throw std::runtime_error("Unexpected error while getting locale info"); throw std::runtime_error("Unexpected error while getting locale info");
} }
wchar_t numberGroupingString[LocaleSettingBufferSize] = L""; wchar_t numberGroupingString[LocaleSettingBufferSize] = L"";
result = GetLocaleInfoEx(m_resolvedName.c_str(), result = GetLocaleInfoEx(m_resolvedName.c_str(), LOCALE_SGROUPING, numberGroupingString, static_cast<int>(std::size(numberGroupingString)));
LOCALE_SGROUPING,
numberGroupingString,
static_cast<int>(std::size(numberGroupingString)));
if (result == 0) if (result == 0)
{ {
throw std::runtime_error("Unexpected error while getting locale info"); throw std::runtime_error("Unexpected error while getting locale info");
@ -71,9 +60,7 @@ namespace CalculatorApp
// Get locale info for List Separator, eg. comma is used in many locales // Get locale info for List Separator, eg. comma is used in many locales
wchar_t listSeparatorString[4] = L""; wchar_t listSeparatorString[4] = L"";
result = ::GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, result = ::GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_SLIST, listSeparatorString,
LOCALE_SLIST,
listSeparatorString,
static_cast<int>(std::size(listSeparatorString))); // Max length of the expected return value is 4 static_cast<int>(std::size(listSeparatorString))); // Max length of the expected return value is 4
if (result == 0) if (result == 0)
{ {
@ -81,9 +68,7 @@ namespace CalculatorApp
} }
int currencyTrailingDigits = 0; int currencyTrailingDigits = 0;
result = GetLocaleInfoEx(m_resolvedName.c_str(), result = GetLocaleInfoEx(m_resolvedName.c_str(), LOCALE_ICURRDIGITS | LOCALE_RETURN_NUMBER, (LPWSTR)&currencyTrailingDigits,
LOCALE_ICURRDIGITS | LOCALE_RETURN_NUMBER,
(LPWSTR)&currencyTrailingDigits,
sizeof(currencyTrailingDigits) / sizeof(WCHAR)); sizeof(currencyTrailingDigits) / sizeof(WCHAR));
if (result == 0) if (result == 0)
{ {
@ -93,9 +78,7 @@ namespace CalculatorApp
// Currency symbol precedence is either 0 or 1. // Currency symbol precedence is either 0 or 1.
// A value of 0 indicates the symbol follows the currency value. // A value of 0 indicates the symbol follows the currency value.
int currencySymbolPrecedence = 1; int currencySymbolPrecedence = 1;
result = GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, result = GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_IPOSSYMPRECEDES | LOCALE_RETURN_NUMBER, (LPWSTR)&currencySymbolPrecedence,
LOCALE_IPOSSYMPRECEDES | LOCALE_RETURN_NUMBER,
(LPWSTR)&currencySymbolPrecedence,
sizeof(currencySymbolPrecedence) / sizeof(WCHAR)); sizeof(currencySymbolPrecedence) / sizeof(WCHAR));
// As CalcEngine only supports the first character of the decimal separator, // As CalcEngine only supports the first character of the decimal separator,
@ -112,10 +95,7 @@ namespace CalculatorApp
// Note: This function returns 0 on failure. // Note: This function returns 0 on failure.
// We'll ignore the failure in that case and the CalendarIdentifier would get set to GregorianCalendar. // We'll ignore the failure in that case and the CalendarIdentifier would get set to GregorianCalendar.
CALID calId; CALID calId;
::GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, ::GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT, LOCALE_ICALENDARTYPE | LOCALE_RETURN_NUMBER, reinterpret_cast<PWSTR>(&calId), sizeof(calId));
LOCALE_ICALENDARTYPE | LOCALE_RETURN_NUMBER,
reinterpret_cast<PWSTR>(&calId),
sizeof(calId));
m_calendarIdentifier = GetCalendarIdentifierFromCalid(calId); m_calendarIdentifier = GetCalendarIdentifierFromCalid(calId);
@ -149,7 +129,7 @@ namespace CalculatorApp
return localizationSettings; return localizationSettings;
} }
Platform::String^ GetLocaleName() const Platform::String ^ GetLocaleName() const
{ {
return ref new Platform::String(m_resolvedName.c_str()); return ref new Platform::String(m_resolvedName.c_str());
} }
@ -179,7 +159,7 @@ namespace CalculatorApp
} }
} }
Platform::String^ GetEnglishValueFromLocalizedDigits(const std::wstring& localizedString) const Platform::String ^ GetEnglishValueFromLocalizedDigits(const std::wstring& localizedString) const
{ {
if (m_resolvedName == L"en-US") if (m_resolvedName == L"en-US")
{ {
@ -201,7 +181,7 @@ namespace CalculatorApp
{ {
ch = j.ToString()->Data()[0]; ch = j.ToString()->Data()[0];
break; break;
//ch = val - L'0'; // ch = val - L'0';
} }
} }
} }
@ -305,7 +285,7 @@ namespace CalculatorApp
} }
} }
Platform::String^ GetCalendarIdentifier() const Platform::String ^ GetCalendarIdentifier() const
{ {
return m_calendarIdentifier; return m_calendarIdentifier;
} }
@ -378,7 +358,7 @@ namespace CalculatorApp
// Hexadecimal characters are not currently localized // Hexadecimal characters are not currently localized
static constexpr std::array<wchar_t, 6> s_hexSymbols{ L'A', L'B', L'C', L'D', L'E', L'F' }; static constexpr std::array<wchar_t, 6> s_hexSymbols{ L'A', L'B', L'C', L'D', L'E', L'F' };
std::wstring m_listSeparator; std::wstring m_listSeparator;
Platform::String^ m_calendarIdentifier; Platform::String ^ m_calendarIdentifier;
Windows::Globalization::DayOfWeek m_firstDayOfWeek; Windows::Globalization::DayOfWeek m_firstDayOfWeek;
int m_currencySymbolPrecedence; int m_currencySymbolPrecedence;
std::wstring m_resolvedName; std::wstring m_resolvedName;

View file

@ -19,13 +19,7 @@ namespace CalculatorApp
std::unique_ptr<wchar_t[]> spBuffer = std::unique_ptr<wchar_t[]>(new wchar_t[length]); std::unique_ptr<wchar_t[]> spBuffer = std::unique_ptr<wchar_t[]>(new 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, DWORD fmtReturnVal = FormatMessage(FORMAT_MESSAGE_FROM_STRING, pMessage, 0, 0, spBuffer.get(), length, &args);
pMessage,
0,
0,
spBuffer.get(),
length,
&args);
va_end(args); va_end(args);
if (fmtReturnVal != 0) if (fmtReturnVal != 0)

View file

@ -7,7 +7,8 @@ namespace CalculatorApp
{ {
namespace Common namespace Common
{ {
public enum class MyVirtualKey public
enum class MyVirtualKey
{ {
None = 0, None = 0,
LeftButton = 1, LeftButton = 1,

View file

@ -24,8 +24,8 @@ static constexpr bool POSITIVE_ONLY = false;
// The order of items in this list determines the order of groups in the menu. // The order of items in this list determines the order of groups in the menu.
static constexpr array<const NavCategoryGroupInitializer, 2> s_categoryGroupManifest = { static constexpr array<const NavCategoryGroupInitializer, 2> s_categoryGroupManifest = {
NavCategoryGroupInitializer { CategoryGroupType::Calculator, L"CalculatorModeTextCaps", L"CalculatorModeText", L"CalculatorModePluralText"}, NavCategoryGroupInitializer{ CategoryGroupType::Calculator, L"CalculatorModeTextCaps", L"CalculatorModeText", L"CalculatorModePluralText" },
NavCategoryGroupInitializer { CategoryGroupType::Converter, L"ConverterModeTextCaps", L"ConverterModeText", L"ConverterModePluralText" } NavCategoryGroupInitializer{ CategoryGroupType::Converter, L"ConverterModeTextCaps", L"ConverterModeText", L"ConverterModePluralText" }
}; };
// vvv THESE CONSTANTS SHOULD NEVER CHANGE vvv // vvv THESE CONSTANTS SHOULD NEVER CHANGE vvv
@ -50,54 +50,63 @@ static constexpr int CURRENCY_ID = 16;
// The order of items in this list determines the order of items in the menu. // The order of items in this list determines the order of items in the menu.
static constexpr array<const NavCategoryInitializer, 17> s_categoryManifest = { static constexpr array<const NavCategoryInitializer, 17> s_categoryManifest = {
NavCategoryInitializer { ViewMode::Standard, STANDARD_ID, L"Standard", L"StandardMode", L"\uE8EF", CategoryGroupType::Calculator, MyVirtualKey::Number1, SUPPORTS_ALL }, NavCategoryInitializer{ ViewMode::Standard, STANDARD_ID, L"Standard", L"StandardMode", L"\uE8EF", CategoryGroupType::Calculator, MyVirtualKey::Number1,
NavCategoryInitializer { ViewMode::Scientific, SCIENTIFIC_ID, L"Scientific", L"ScientificMode", L"\uF196", CategoryGroupType::Calculator, MyVirtualKey::Number2, SUPPORTS_ALL }, SUPPORTS_ALL },
NavCategoryInitializer { ViewMode::Programmer, PROGRAMMER_ID, L"Programmer", L"ProgrammerMode", L"\uECCE", CategoryGroupType::Calculator, MyVirtualKey::Number3, SUPPORTS_ALL }, NavCategoryInitializer{ ViewMode::Scientific, SCIENTIFIC_ID, L"Scientific", L"ScientificMode", L"\uF196", CategoryGroupType::Calculator,
NavCategoryInitializer { ViewMode::Date, DATE_ID, L"Date", L"DateCalculationMode", L"\uE787", CategoryGroupType::Calculator, MyVirtualKey::Number4, SUPPORTS_ALL }, MyVirtualKey::Number2, SUPPORTS_ALL },
NavCategoryInitializer { ViewMode::Currency, CURRENCY_ID, L"Currency", L"CategoryName_Currency", L"\uEB0D", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY }, NavCategoryInitializer{ ViewMode::Programmer, PROGRAMMER_ID, L"Programmer", L"ProgrammerMode", L"\uECCE", CategoryGroupType::Calculator,
NavCategoryInitializer { ViewMode::Volume, VOLUME_ID, L"Volume", L"CategoryName_Volume", L"\uF1AA", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY }, MyVirtualKey::Number3, SUPPORTS_ALL },
NavCategoryInitializer { ViewMode::Length, LENGTH_ID, L"Length", L"CategoryName_Length", L"\uECC6", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY }, NavCategoryInitializer{ ViewMode::Date, DATE_ID, L"Date", L"DateCalculationMode", L"\uE787", CategoryGroupType::Calculator, MyVirtualKey::Number4,
NavCategoryInitializer { ViewMode::Weight, WEIGHT_ID, L"Weight and Mass", L"CategoryName_Weight", L"\uF4C1", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY }, SUPPORTS_ALL },
NavCategoryInitializer { ViewMode::Temperature, TEMPERATURE_ID, L"Temperature", L"CategoryName_Temperature", L"\uE7A3", CategoryGroupType::Converter, MyVirtualKey::None, SUPPORTS_NEGATIVE }, NavCategoryInitializer{ ViewMode::Currency, CURRENCY_ID, L"Currency", L"CategoryName_Currency", L"\uEB0D", CategoryGroupType::Converter, MyVirtualKey::None,
NavCategoryInitializer { ViewMode::Energy, ENERGY_ID, L"Energy", L"CategoryName_Energy", L"\uECAD", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY }, POSITIVE_ONLY },
NavCategoryInitializer { ViewMode::Area, AREA_ID, L"Area", L"CategoryName_Area", L"\uE809", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY }, NavCategoryInitializer{ ViewMode::Volume, VOLUME_ID, L"Volume", L"CategoryName_Volume", L"\uF1AA", CategoryGroupType::Converter, MyVirtualKey::None,
NavCategoryInitializer { ViewMode::Speed, SPEED_ID, L"Speed", L"CategoryName_Speed", L"\uEADA", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY }, POSITIVE_ONLY },
NavCategoryInitializer { ViewMode::Time, TIME_ID, L"Time", L"CategoryName_Time", L"\uE917", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY }, NavCategoryInitializer{ ViewMode::Length, LENGTH_ID, L"Length", L"CategoryName_Length", L"\uECC6", CategoryGroupType::Converter, MyVirtualKey::None,
NavCategoryInitializer { ViewMode::Power, POWER_ID, L"Power", L"CategoryName_Power", L"\uE945", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY }, POSITIVE_ONLY },
NavCategoryInitializer { ViewMode::Data, DATA_ID, L"Data", L"CategoryName_Data", L"\uF20F", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY }, NavCategoryInitializer{ ViewMode::Weight, WEIGHT_ID, L"Weight and Mass", L"CategoryName_Weight", L"\uF4C1", CategoryGroupType::Converter,
NavCategoryInitializer { ViewMode::Pressure, PRESSURE_ID, L"Pressure", L"CategoryName_Pressure", L"\uEC4A", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY }, MyVirtualKey::None, POSITIVE_ONLY },
NavCategoryInitializer { ViewMode::Angle, ANGLE_ID, L"Angle", L"CategoryName_Angle", L"\uF515", CategoryGroupType::Converter, MyVirtualKey::None, POSITIVE_ONLY } NavCategoryInitializer{ ViewMode::Temperature, TEMPERATURE_ID, L"Temperature", L"CategoryName_Temperature", L"\uE7A3", CategoryGroupType::Converter,
MyVirtualKey::None, SUPPORTS_NEGATIVE },
NavCategoryInitializer{ ViewMode::Energy, ENERGY_ID, L"Energy", L"CategoryName_Energy", L"\uECAD", CategoryGroupType::Converter, MyVirtualKey::None,
POSITIVE_ONLY },
NavCategoryInitializer{ ViewMode::Area, AREA_ID, L"Area", L"CategoryName_Area", L"\uE809", CategoryGroupType::Converter, MyVirtualKey::None,
POSITIVE_ONLY },
NavCategoryInitializer{ ViewMode::Speed, SPEED_ID, L"Speed", L"CategoryName_Speed", L"\uEADA", CategoryGroupType::Converter, MyVirtualKey::None,
POSITIVE_ONLY },
NavCategoryInitializer{ ViewMode::Time, TIME_ID, L"Time", L"CategoryName_Time", L"\uE917", CategoryGroupType::Converter, MyVirtualKey::None,
POSITIVE_ONLY },
NavCategoryInitializer{ ViewMode::Power, POWER_ID, L"Power", L"CategoryName_Power", L"\uE945", CategoryGroupType::Converter, MyVirtualKey::None,
POSITIVE_ONLY },
NavCategoryInitializer{ ViewMode::Data, DATA_ID, L"Data", L"CategoryName_Data", L"\uF20F", CategoryGroupType::Converter, MyVirtualKey::None,
POSITIVE_ONLY },
NavCategoryInitializer{ ViewMode::Pressure, PRESSURE_ID, L"Pressure", L"CategoryName_Pressure", L"\uEC4A", CategoryGroupType::Converter, MyVirtualKey::None,
POSITIVE_ONLY },
NavCategoryInitializer{ ViewMode::Angle, ANGLE_ID, L"Angle", L"CategoryName_Angle", L"\uF515", CategoryGroupType::Converter, MyVirtualKey::None,
POSITIVE_ONLY }
}; };
// This function should only be used when storing the mode to app data. // This function should only be used when storing the mode to app data.
int NavCategory::Serialize(ViewMode mode) int NavCategory::Serialize(ViewMode mode)
{ {
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), auto iter =
[mode](const NavCategoryInitializer& initializer) find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode](const NavCategoryInitializer& initializer) { return initializer.viewMode == mode; });
{
return initializer.viewMode == mode;
});
return (iter != s_categoryManifest.end()) return (iter != s_categoryManifest.end()) ? iter->serializationId : -1;
? iter->serializationId
: -1;
} }
// This function should only be used when restoring the mode from app data. // This function should only be used when restoring the mode from app data.
ViewMode NavCategory::Deserialize(Platform::Object^ obj) ViewMode NavCategory::Deserialize(Platform::Object ^ obj)
{ {
// If we cast directly to ViewMode we will fail // If we cast directly to ViewMode we will fail
// because we technically store an int. // because we technically store an int.
// Need to cast to int, then ViewMode. // Need to cast to int, then ViewMode.
auto boxed = dynamic_cast<Box<int>^>(obj); auto boxed = dynamic_cast<Box<int> ^>(obj);
if (boxed != nullptr) if (boxed != nullptr)
{ {
int serializationId = boxed->Value; int serializationId = boxed->Value;
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest),
[serializationId](const NavCategoryInitializer& initializer) [serializationId](const NavCategoryInitializer& initializer) { return initializer.serializationId == serializationId; });
{
return initializer.serializationId == serializationId;
});
if (iter != s_categoryManifest.end()) if (iter != s_categoryManifest.end())
{ {
@ -110,11 +119,8 @@ ViewMode NavCategory::Deserialize(Platform::Object^ obj)
bool NavCategory::IsValidViewMode(ViewMode mode) bool NavCategory::IsValidViewMode(ViewMode mode)
{ {
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), auto iter =
[mode](const NavCategoryInitializer& initializer) find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode](const NavCategoryInitializer& initializer) { return initializer.viewMode == mode; });
{
return initializer.viewMode == mode;
});
return iter != s_categoryManifest.end(); return iter != s_categoryManifest.end();
} }
@ -139,64 +145,41 @@ bool NavCategory::IsConverterViewMode(ViewMode mode)
bool NavCategory::IsModeInCategoryGroup(ViewMode mode, CategoryGroupType type) bool NavCategory::IsModeInCategoryGroup(ViewMode mode, CategoryGroupType type)
{ {
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest),
[mode, type](const NavCategoryInitializer& initializer) [mode, type](const NavCategoryInitializer& initializer) { return initializer.viewMode == mode && initializer.groupType == type; });
{
return initializer.viewMode == mode && initializer.groupType == type;
});
return iter != s_categoryManifest.end(); return iter != s_categoryManifest.end();
} }
String^ NavCategory::GetFriendlyName(ViewMode mode) String ^ NavCategory::GetFriendlyName(ViewMode mode)
{ {
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), auto iter =
[mode](const NavCategoryInitializer& initializer) find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode](const NavCategoryInitializer& initializer) { return initializer.viewMode == mode; });
{
return initializer.viewMode == mode;
});
return (iter != s_categoryManifest.end()) return (iter != s_categoryManifest.end()) ? StringReference(iter->friendlyName) : L"None";
? StringReference(iter->friendlyName)
: L"None";
} }
ViewMode NavCategory::GetViewModeForFriendlyName(String^ name) ViewMode NavCategory::GetViewModeForFriendlyName(String ^ name)
{ {
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest),
[name](const NavCategoryInitializer& initializer) [name](const NavCategoryInitializer& initializer) { return wcscmp(initializer.friendlyName, name->Data()) == 0; });
{
return wcscmp(initializer.friendlyName, name->Data()) == 0;
});
return (iter != s_categoryManifest.end()) return (iter != s_categoryManifest.end()) ? iter->viewMode : ViewMode::None;
? iter->viewMode
: ViewMode::None;
} }
String^ NavCategory::GetNameResourceKey(ViewMode mode) String ^ NavCategory::GetNameResourceKey(ViewMode mode)
{ {
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), auto iter =
[mode](const NavCategoryInitializer& initializer) find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode](const NavCategoryInitializer& initializer) { return initializer.viewMode == mode; });
{
return initializer.viewMode == mode;
});
return (iter != s_categoryManifest.end()) return (iter != s_categoryManifest.end()) ? StringReference(iter->nameResourceKey) + "Text" : nullptr;
? StringReference(iter->nameResourceKey) + "Text"
: nullptr;
} }
CategoryGroupType NavCategory::GetGroupType(ViewMode mode) CategoryGroupType NavCategory::GetGroupType(ViewMode mode)
{ {
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), auto iter =
[mode](const NavCategoryInitializer& initializer) find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode](const NavCategoryInitializer& initializer) { return initializer.viewMode == mode; });
{
return initializer.viewMode == mode;
});
return (iter != s_categoryManifest.end()) return (iter != s_categoryManifest.end()) ? iter->groupType : CategoryGroupType::None;
? iter->groupType
: CategoryGroupType::None;
} }
// GetIndex is 0-based, GetPosition is 1-based // GetIndex is 0-based, GetPosition is 1-based
@ -210,9 +193,7 @@ int NavCategory::GetFlatIndex(ViewMode mode)
{ {
int index = -1; int index = -1;
CategoryGroupType type = CategoryGroupType::None; CategoryGroupType type = CategoryGroupType::None;
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode, &type, &index](const NavCategoryInitializer& initializer) {
[mode, &type, &index](const NavCategoryInitializer& initializer)
{
index++; index++;
if (initializer.groupType != type) if (initializer.groupType != type)
{ {
@ -223,18 +204,14 @@ int NavCategory::GetFlatIndex(ViewMode mode)
return initializer.viewMode == mode; return initializer.viewMode == mode;
}); });
return (iter != s_categoryManifest.end()) return (iter != s_categoryManifest.end()) ? index : -1;
? index
: -1;
} }
// GetIndex is 0-based, GetPosition is 1-based // GetIndex is 0-based, GetPosition is 1-based
int NavCategory::GetIndexInGroup(ViewMode mode, CategoryGroupType type) int NavCategory::GetIndexInGroup(ViewMode mode, CategoryGroupType type)
{ {
int index = -1; int index = -1;
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode, type, &index](const NavCategoryInitializer& initializer) {
[mode, type, &index](const NavCategoryInitializer& initializer)
{
if (initializer.groupType == type) if (initializer.groupType == type)
{ {
index++; index++;
@ -244,38 +221,27 @@ int NavCategory::GetIndexInGroup(ViewMode mode, CategoryGroupType type)
return false; return false;
}); });
return (iter != s_categoryManifest.end()) return (iter != s_categoryManifest.end()) ? index : -1;
? index
: -1;
} }
// GetIndex is 0-based, GetPosition is 1-based // GetIndex is 0-based, GetPosition is 1-based
int NavCategory::GetPosition(ViewMode mode) int NavCategory::GetPosition(ViewMode mode)
{ {
int position = 0; int position = 0;
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), [mode, &position](const NavCategoryInitializer& initializer) {
[mode, &position](const NavCategoryInitializer& initializer)
{
position++; position++;
return initializer.viewMode == mode; return initializer.viewMode == mode;
}); });
return (iter != s_categoryManifest.end()) return (iter != s_categoryManifest.end()) ? position : -1;
? position
: -1;
} }
ViewMode NavCategory::GetViewModeForVirtualKey(MyVirtualKey virtualKey) ViewMode NavCategory::GetViewModeForVirtualKey(MyVirtualKey virtualKey)
{ {
auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest), auto iter = find_if(begin(s_categoryManifest), end(s_categoryManifest),
[virtualKey](const NavCategoryInitializer& initializer) [virtualKey](const NavCategoryInitializer& initializer) { return initializer.virtualKey == virtualKey; });
{
return initializer.virtualKey == virtualKey;
});
return (iter != s_categoryManifest.end()) return (iter != s_categoryManifest.end()) ? iter->viewMode : ViewMode::None;
? iter->viewMode
: ViewMode::None;
} }
vector<MyVirtualKey> NavCategory::GetCategoryAcceleratorKeys() vector<MyVirtualKey> NavCategory::GetCategoryAcceleratorKeys()
@ -292,63 +258,54 @@ vector<MyVirtualKey> NavCategory::GetCategoryAcceleratorKeys()
return accelerators; return accelerators;
} }
NavCategoryGroup::NavCategoryGroup(const NavCategoryGroupInitializer& groupInitializer) : NavCategoryGroup::NavCategoryGroup(const NavCategoryGroupInitializer& groupInitializer) : m_Categories(ref new Vector<NavCategory ^>())
m_Categories(ref new Vector<NavCategory^>())
{ {
m_GroupType = groupInitializer.type; m_GroupType = groupInitializer.type;
auto resProvider = AppResourceProvider::GetInstance(); auto resProvider = AppResourceProvider::GetInstance();
String^ headerResourceKey = StringReference(groupInitializer.headerResourceKey); String ^ headerResourceKey = StringReference(groupInitializer.headerResourceKey);
String^ modeResourceKey = StringReference(groupInitializer.modeResourceKey); String ^ modeResourceKey = StringReference(groupInitializer.modeResourceKey);
String^ automationResourceKey = StringReference(groupInitializer.automationResourceKey); String ^ automationResourceKey = StringReference(groupInitializer.automationResourceKey);
m_Name = resProvider.GetResourceString(headerResourceKey); m_Name = resProvider.GetResourceString(headerResourceKey);
String^ groupMode = resProvider.GetResourceString(modeResourceKey); String ^ groupMode = resProvider.GetResourceString(modeResourceKey);
String^ automationName = resProvider.GetResourceString(automationResourceKey); String ^ automationName = resProvider.GetResourceString(automationResourceKey);
String^ navCategoryHeaderAutomationNameFormat = resProvider.GetResourceString(L"NavCategoryHeader_AutomationNameFormat"); String ^ navCategoryHeaderAutomationNameFormat = resProvider.GetResourceString(L"NavCategoryHeader_AutomationNameFormat");
m_AutomationName = ref new String(LocalizationStringUtil::GetLocalizedString( m_AutomationName =
navCategoryHeaderAutomationNameFormat->Data(), ref new String(LocalizationStringUtil::GetLocalizedString(navCategoryHeaderAutomationNameFormat->Data(), automationName->Data()).c_str());
automationName->Data()).c_str());
String^ navCategoryItemAutomationNameFormat = resProvider.GetResourceString(L"NavCategoryItem_AutomationNameFormat"); String ^ navCategoryItemAutomationNameFormat = resProvider.GetResourceString(L"NavCategoryItem_AutomationNameFormat");
for (const NavCategoryInitializer& categoryInitializer : s_categoryManifest) for (const NavCategoryInitializer& categoryInitializer : s_categoryManifest)
{ {
if (categoryInitializer.groupType == groupInitializer.type) if (categoryInitializer.groupType == groupInitializer.type)
{ {
String^ nameResourceKey = StringReference(categoryInitializer.nameResourceKey); String ^ nameResourceKey = StringReference(categoryInitializer.nameResourceKey);
String^ categoryName = resProvider.GetResourceString(nameResourceKey + "Text"); String ^ categoryName = resProvider.GetResourceString(nameResourceKey + "Text");
String^ categoryAutomationName = ref new String(LocalizationStringUtil::GetLocalizedString( String ^ categoryAutomationName = ref new String(
navCategoryItemAutomationNameFormat->Data(), LocalizationStringUtil::GetLocalizedString(navCategoryItemAutomationNameFormat->Data(), categoryName->Data(), m_Name->Data()).c_str());
categoryName->Data(),
m_Name->Data()).c_str());
m_Categories->Append(ref new NavCategory( m_Categories->Append(ref new NavCategory(categoryName, categoryAutomationName, StringReference(categoryInitializer.glyph),
categoryName, resProvider.GetResourceString(nameResourceKey + "AccessKey"), groupMode, categoryInitializer.viewMode,
categoryAutomationName,
StringReference(categoryInitializer.glyph),
resProvider.GetResourceString(nameResourceKey + "AccessKey"),
groupMode,
categoryInitializer.viewMode,
categoryInitializer.supportsNegative)); categoryInitializer.supportsNegative));
} }
} }
} }
IObservableVector<NavCategoryGroup^>^ NavCategoryGroup::CreateMenuOptions() IObservableVector<NavCategoryGroup ^> ^ NavCategoryGroup::CreateMenuOptions()
{ {
auto menuOptions = ref new Vector<NavCategoryGroup^>(); auto menuOptions = ref new Vector<NavCategoryGroup ^>();
menuOptions->Append(CreateCalculatorCategory()); menuOptions->Append(CreateCalculatorCategory());
menuOptions->Append(CreateConverterCategory()); menuOptions->Append(CreateConverterCategory());
return menuOptions; return menuOptions;
} }
NavCategoryGroup^ NavCategoryGroup::CreateCalculatorCategory() NavCategoryGroup ^ NavCategoryGroup::CreateCalculatorCategory()
{ {
return ref new NavCategoryGroup(s_categoryGroupManifest.at(0)); return ref new NavCategoryGroup(s_categoryGroupManifest.at(0));
} }
NavCategoryGroup^ NavCategoryGroup::CreateConverterCategory() NavCategoryGroup ^ NavCategoryGroup::CreateConverterCategory()
{ {
return ref new NavCategoryGroup(s_categoryGroupManifest.at(1)); return ref new NavCategoryGroup(s_categoryGroupManifest.at(1));
} }
@ -357,23 +314,15 @@ vector<NavCategoryInitializer> NavCategoryGroup::GetInitializerCategoryGroup(Cat
{ {
vector<NavCategoryInitializer> initializers{}; vector<NavCategoryInitializer> initializers{};
copy_if(begin(s_categoryManifest), end(s_categoryManifest), back_inserter(initializers), copy_if(begin(s_categoryManifest), end(s_categoryManifest), back_inserter(initializers),
[groupType](const NavCategoryInitializer& initializer) [groupType](const NavCategoryInitializer& initializer) { return initializer.groupType == groupType; });
{
return initializer.groupType == groupType;
});
return initializers; return initializers;
} }
String^ NavCategoryGroup::GetHeaderResourceKey(CategoryGroupType type) String ^ NavCategoryGroup::GetHeaderResourceKey(CategoryGroupType type)
{ {
auto iter = find_if(begin(s_categoryGroupManifest), end(s_categoryGroupManifest), auto iter = find_if(begin(s_categoryGroupManifest), end(s_categoryGroupManifest),
[type](const NavCategoryGroupInitializer& initializer) [type](const NavCategoryGroupInitializer& initializer) { return initializer.type == type; });
{
return initializer.type == type;
});
return (iter != s_categoryGroupManifest.end()) return (iter != s_categoryGroupManifest.end()) ? StringReference(iter->headerResourceKey) : nullptr;
? StringReference(iter->headerResourceKey)
: nullptr;
} }

View file

@ -24,7 +24,8 @@ namespace CalculatorApp
// Don't change the order of these enums // Don't change the order of these enums
// and definitely don't use int arithmetic // and definitely don't use int arithmetic
// to change modes. // to change modes.
public enum class ViewMode public
enum class ViewMode
{ {
None = -1, None = -1,
Standard = 0, Standard = 0,
@ -46,81 +47,74 @@ namespace CalculatorApp
Currency = 16 Currency = 16
}; };
public enum class CategoryGroupType public
enum class CategoryGroupType
{ {
None = -1, None = -1,
Calculator = 0, Calculator = 0,
Converter = 1 Converter = 1
}; };
private struct NavCategoryInitializer private
struct NavCategoryInitializer
{ {
constexpr NavCategoryInitializer( constexpr NavCategoryInitializer(ViewMode mode, int id, wchar_t const* name, wchar_t const* nameKey, wchar_t const* glyph, CategoryGroupType group,
ViewMode mode, MyVirtualKey vKey, bool categorySupportsNegative)
int id, : viewMode(mode)
wchar_t const * name, , serializationId(id)
wchar_t const * nameKey, , friendlyName(name)
wchar_t const * glyph, , nameResourceKey(nameKey)
CategoryGroupType group, , glyph(glyph)
MyVirtualKey vKey, , groupType(group)
bool categorySupportsNegative) , virtualKey(vKey)
: , supportsNegative(categorySupportsNegative)
viewMode(mode), {
serializationId(id), }
friendlyName(name),
nameResourceKey(nameKey),
glyph(glyph),
groupType(group),
virtualKey(vKey),
supportsNegative(categorySupportsNegative)
{}
const ViewMode viewMode; const ViewMode viewMode;
const int serializationId; const int serializationId;
const wchar_t * const friendlyName; const wchar_t* const friendlyName;
const wchar_t * const nameResourceKey; const wchar_t* const nameResourceKey;
const wchar_t * const glyph; const wchar_t* const glyph;
const CategoryGroupType groupType; const CategoryGroupType groupType;
const MyVirtualKey virtualKey; const MyVirtualKey virtualKey;
const bool supportsNegative; const bool supportsNegative;
}; };
private struct NavCategoryGroupInitializer private
struct NavCategoryGroupInitializer
{ {
constexpr NavCategoryGroupInitializer(CategoryGroupType t, wchar_t const * h, wchar_t const * n, wchar_t const * a) : constexpr NavCategoryGroupInitializer(CategoryGroupType t, wchar_t const* h, wchar_t const* n, wchar_t const* a)
type(t), headerResourceKey(h), modeResourceKey(n), automationResourceKey(a) : type(t), headerResourceKey(h), modeResourceKey(n), automationResourceKey(a)
{} {
}
const CategoryGroupType type; const CategoryGroupType type;
const wchar_t *headerResourceKey; const wchar_t* headerResourceKey;
const wchar_t *modeResourceKey; const wchar_t* modeResourceKey;
const wchar_t *automationResourceKey; const wchar_t* automationResourceKey;
}; };
[Windows::UI::Xaml::Data::Bindable] [Windows::UI::Xaml::Data::Bindable] public ref class NavCategory sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
public ref class NavCategory sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
{ {
public: public:
OBSERVABLE_OBJECT(); OBSERVABLE_OBJECT();
property Platform::String^ Name property Platform::String
{ ^ Name { Platform::String ^ get() { return m_name; } }
Platform::String^ get() { return m_name; }
}
property Platform::String^ AutomationName property Platform::String
{ ^ AutomationName { Platform::String ^ get() { return m_automationName; } }
Platform::String^ get() { return m_automationName; }
}
property Platform::String^ Glyph property Platform::String
{ ^ Glyph { Platform::String ^ get() { return m_glyph; } }
Platform::String^ get() { return m_glyph; }
}
property int Position property int Position
{ {
int get() { return m_position; } int get()
{
return m_position;
}
} }
property ViewMode Mode property ViewMode Mode
@ -131,22 +125,11 @@ namespace CalculatorApp
} }
} }
property Platform::String^ AutomationId property Platform::String
{ ^ AutomationId { Platform::String ^ get() { return m_viewMode.ToString(); } }
Platform::String^ get()
{
return m_viewMode.ToString();
}
}
property Platform::String^ AccessKey
{
Platform::String^ get()
{
return m_accessKey;
}
}
property Platform::String
^ AccessKey { Platform::String ^ get() { return m_accessKey; } }
property bool SupportsNegative property bool SupportsNegative
{ {
@ -158,16 +141,16 @@ namespace CalculatorApp
// For saving/restoring last mode used. // For saving/restoring last mode used.
static int Serialize(ViewMode mode); static int Serialize(ViewMode mode);
static ViewMode Deserialize(Platform::Object^ obj); static ViewMode Deserialize(Platform::Object ^ obj);
static ViewMode GetViewModeForFriendlyName(Platform::String^ name); static ViewMode GetViewModeForFriendlyName(Platform::String ^ name);
static bool IsValidViewMode(ViewMode mode); static bool IsValidViewMode(ViewMode mode);
static bool IsCalculatorViewMode(ViewMode mode); static bool IsCalculatorViewMode(ViewMode mode);
static bool IsDateCalculatorViewMode(ViewMode mode); static bool IsDateCalculatorViewMode(ViewMode mode);
static bool IsConverterViewMode(ViewMode mode); static bool IsConverterViewMode(ViewMode mode);
static Platform::String^ GetFriendlyName(ViewMode mode); static Platform::String ^ GetFriendlyName(ViewMode mode);
static Platform::String^ GetNameResourceKey(ViewMode mode); static Platform::String ^ GetNameResourceKey(ViewMode mode);
static CategoryGroupType GetGroupType(ViewMode mode); static CategoryGroupType GetGroupType(ViewMode mode);
// GetIndex is 0-based, GetPosition is 1-based // GetIndex is 0-based, GetPosition is 1-based
@ -178,15 +161,15 @@ namespace CalculatorApp
static ViewMode GetViewModeForVirtualKey(MyVirtualKey virtualKey); static ViewMode GetViewModeForVirtualKey(MyVirtualKey virtualKey);
internal: internal : NavCategory(Platform::String ^ name, Platform::String ^ automationName, Platform::String ^ glyph, Platform::String ^ accessKey,
NavCategory(Platform::String^ name, Platform::String^ automationName, Platform::String^ glyph, Platform::String^ accessKey, Platform::String^ mode, ViewMode viewMode, bool supportsNegative) : Platform::String ^ mode, ViewMode viewMode, bool supportsNegative)
m_name(name), : m_name(name)
m_automationName(automationName), , m_automationName(automationName)
m_glyph(glyph), , m_glyph(glyph)
m_accessKey(accessKey), , m_accessKey(accessKey)
m_mode(mode), , m_mode(mode)
m_viewMode(viewMode), , m_viewMode(viewMode)
m_supportsNegative(supportsNegative) , m_supportsNegative(supportsNegative)
{ {
m_position = NavCategory::GetPosition(m_viewMode); m_position = NavCategory::GetPosition(m_viewMode);
} }
@ -197,33 +180,30 @@ namespace CalculatorApp
static bool IsModeInCategoryGroup(ViewMode mode, CategoryGroupType groupType); static bool IsModeInCategoryGroup(ViewMode mode, CategoryGroupType groupType);
ViewMode m_viewMode; ViewMode m_viewMode;
Platform::String^ m_name; Platform::String ^ m_name;
Platform::String^ m_automationName; Platform::String ^ m_automationName;
Platform::String^ m_glyph; Platform::String ^ m_glyph;
Platform::String^ m_accessKey; Platform::String ^ m_accessKey;
Platform::String^ m_mode; Platform::String ^ m_mode;
int m_position; int m_position;
bool m_supportsNegative; bool m_supportsNegative;
}; };
[Windows::UI::Xaml::Data::Bindable] [Windows::UI::Xaml::Data::Bindable] public ref class NavCategoryGroup sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
public ref class NavCategoryGroup sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
{ {
public: public:
OBSERVABLE_OBJECT(); OBSERVABLE_OBJECT();
OBSERVABLE_PROPERTY_R(Platform::String^, Name); OBSERVABLE_PROPERTY_R(Platform::String ^, Name);
OBSERVABLE_PROPERTY_R(Platform::String^, AutomationName); OBSERVABLE_PROPERTY_R(Platform::String ^, AutomationName);
OBSERVABLE_PROPERTY_R(CategoryGroupType, GroupType); OBSERVABLE_PROPERTY_R(CategoryGroupType, GroupType);
OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector<NavCategory^>^, Categories); OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector<NavCategory ^> ^, Categories);
static Windows::Foundation::Collections::IObservableVector<NavCategoryGroup^>^ CreateMenuOptions(); static Windows::Foundation::Collections::IObservableVector<NavCategoryGroup ^> ^ CreateMenuOptions();
static Platform::String^ GetHeaderResourceKey(CategoryGroupType type); static Platform::String ^ GetHeaderResourceKey(CategoryGroupType type);
internal: internal : static NavCategoryGroup ^ CreateCalculatorCategory();
static NavCategoryGroup^ CreateCalculatorCategory(); static NavCategoryGroup ^ CreateConverterCategory();
static NavCategoryGroup^ CreateConverterCategory();
private: private:
NavCategoryGroup(const NavCategoryGroupInitializer& groupInitializer); NavCategoryGroup(const NavCategoryGroupInitializer& groupInitializer);

View file

@ -10,9 +10,8 @@ using namespace Windows::Networking::Connectivity;
NetworkManager::NetworkManager() NetworkManager::NetworkManager()
{ {
m_NetworkStatusChangedToken = m_NetworkStatusChangedToken = NetworkInformation::NetworkStatusChanged +=
NetworkInformation::NetworkStatusChanged += ref new NetworkStatusChangedEventHandler( ref new NetworkStatusChangedEventHandler(this, &NetworkManager::OnNetworkStatusChange, CallbackContext::Same);
this, &NetworkManager::OnNetworkStatusChange, CallbackContext::Same);
} }
NetworkManager::~NetworkManager() NetworkManager::~NetworkManager()
@ -23,14 +22,13 @@ NetworkManager::~NetworkManager()
NetworkAccessBehavior NetworkManager::GetNetworkAccessBehavior() NetworkAccessBehavior NetworkManager::GetNetworkAccessBehavior()
{ {
NetworkAccessBehavior behavior = NetworkAccessBehavior::Offline; NetworkAccessBehavior behavior = NetworkAccessBehavior::Offline;
ConnectionProfile^ connectionProfile = NetworkInformation::GetInternetConnectionProfile(); ConnectionProfile ^ connectionProfile = NetworkInformation::GetInternetConnectionProfile();
if (connectionProfile != nullptr) if (connectionProfile != nullptr)
{ {
NetworkConnectivityLevel connectivityLevel = connectionProfile->GetNetworkConnectivityLevel(); NetworkConnectivityLevel connectivityLevel = connectionProfile->GetNetworkConnectivityLevel();
if (connectivityLevel == NetworkConnectivityLevel::InternetAccess if (connectivityLevel == NetworkConnectivityLevel::InternetAccess || connectivityLevel == NetworkConnectivityLevel::ConstrainedInternetAccess)
|| connectivityLevel == NetworkConnectivityLevel::ConstrainedInternetAccess)
{ {
ConnectionCost^ connectionCost = connectionProfile->GetConnectionCost(); ConnectionCost ^ connectionCost = connectionProfile->GetConnectionCost();
behavior = ConvertCostInfoToBehavior(connectionCost); behavior = ConvertCostInfoToBehavior(connectionCost);
} }
} }
@ -38,16 +36,15 @@ NetworkAccessBehavior NetworkManager::GetNetworkAccessBehavior()
return behavior; return behavior;
} }
void NetworkManager::OnNetworkStatusChange(_In_ Object^ /*sender*/) void NetworkManager::OnNetworkStatusChange(_In_ Object ^ /*sender*/)
{ {
NetworkBehaviorChanged(GetNetworkAccessBehavior()); NetworkBehaviorChanged(GetNetworkAccessBehavior());
} }
// See app behavior guidelines at https://msdn.microsoft.com/en-us/library/windows/apps/xaml/jj835821(v=win.10).aspx // See app behavior guidelines at https://msdn.microsoft.com/en-us/library/windows/apps/xaml/jj835821(v=win.10).aspx
NetworkAccessBehavior NetworkManager::ConvertCostInfoToBehavior(_In_ ConnectionCost^ connectionCost) NetworkAccessBehavior NetworkManager::ConvertCostInfoToBehavior(_In_ ConnectionCost ^ connectionCost)
{ {
if (connectionCost->Roaming || connectionCost->OverDataLimit if (connectionCost->Roaming || connectionCost->OverDataLimit || connectionCost->NetworkCostType == NetworkCostType::Variable
|| connectionCost->NetworkCostType == NetworkCostType::Variable
|| connectionCost->NetworkCostType == NetworkCostType::Fixed) || connectionCost->NetworkCostType == NetworkCostType::Fixed)
{ {
return NetworkAccessBehavior::OptIn; return NetworkAccessBehavior::OptIn;

View file

@ -5,29 +5,32 @@
namespace CalculatorApp namespace CalculatorApp
{ {
public enum class NetworkAccessBehavior public
enum class NetworkAccessBehavior
{ {
Normal = 0, Normal = 0,
OptIn = 1, OptIn = 1,
Offline = 2 Offline = 2
}; };
public delegate void NetworkBehaviorChangedHandler(NetworkAccessBehavior behavior); public
delegate void NetworkBehaviorChangedHandler(NetworkAccessBehavior behavior);
public ref class NetworkManager sealed public
ref class NetworkManager sealed
{ {
public: public:
NetworkManager(); NetworkManager();
static NetworkAccessBehavior GetNetworkAccessBehavior(); static NetworkAccessBehavior GetNetworkAccessBehavior();
event NetworkBehaviorChangedHandler^ NetworkBehaviorChanged; event NetworkBehaviorChangedHandler ^ NetworkBehaviorChanged;
private: private:
~NetworkManager(); ~NetworkManager();
void OnNetworkStatusChange(_In_ Platform::Object^ sender); void OnNetworkStatusChange(_In_ Platform::Object ^ sender);
static NetworkAccessBehavior ConvertCostInfoToBehavior(_In_ Windows::Networking::Connectivity::ConnectionCost^ connectionCost); static NetworkAccessBehavior ConvertCostInfoToBehavior(_In_ Windows::Networking::Connectivity::ConnectionCost ^ connectionCost);
private: private:
Windows::Foundation::EventRegistrationToken m_NetworkStatusChangedToken; Windows::Foundation::EventRegistrationToken m_NetworkStatusChangedToken;

View file

@ -11,30 +11,19 @@ namespace CalculatorApp
class TraceActivity class TraceActivity
{ {
public: public:
TraceActivity() : TraceActivity() : m_channel(nullptr), m_activity(nullptr), m_fields(nullptr)
m_channel(nullptr), {
m_activity(nullptr), }
m_fields(nullptr)
{ }
TraceActivity( TraceActivity(winrt::Windows::Foundation::Diagnostics::LoggingChannel channel, std::wstring_view activityName,
winrt::Windows::Foundation::Diagnostics::LoggingChannel channel, winrt::Windows::Foundation::Diagnostics::LoggingFields fields)
std::wstring_view activityName, : m_channel(channel), m_activityName(activityName), m_fields(fields), m_activity(nullptr)
winrt::Windows::Foundation::Diagnostics::LoggingFields fields) :
m_channel(channel),
m_activityName(activityName),
m_fields(fields),
m_activity(nullptr)
{ {
// Write the activity's START event. Note that you must not specify keyword // Write the activity's START event. Note that you must not specify keyword
// or level for START and STOP events because they always use the activity's // or level for START and STOP events because they always use the activity's
// keyword and level. // keyword and level.
m_activity = m_channel.StartActivity( m_activity = m_channel.StartActivity(m_activityName, m_fields, winrt::Windows::Foundation::Diagnostics::LoggingLevel::Verbose,
m_activityName, winrt::Windows::Foundation::Diagnostics::LoggingOptions(WINEVENT_KEYWORD_RESPONSE_TIME));
m_fields,
winrt::Windows::Foundation::Diagnostics::LoggingLevel::Verbose,
winrt::Windows::Foundation::Diagnostics::LoggingOptions(WINEVENT_KEYWORD_RESPONSE_TIME)
);
} }
~TraceActivity() ~TraceActivity()

View file

@ -21,10 +21,8 @@ namespace CalculatorApp
{ {
static multimap<int, vector<wstring>> s_memoryMap; static multimap<int, vector<wstring>> s_memoryMap;
static constexpr array<const wchar_t * const, 9> s_programmerType{ static constexpr array<const wchar_t* const, 9> s_programmerType{ L"N/A", L"QwordType", L"DwordType", L"WordType", L"ByteType",
L"N/A", L"QwordType", L"DwordType", L"HexBase", L"DecBase", L"OctBase", L"BinBase" };
L"WordType", L"ByteType", L"HexBase",
L"DecBase", L"OctBase", L"BinBase" };
static reader_writer_lock s_traceLoggerLock; static reader_writer_lock s_traceLoggerLock;
// Telemetry events. Uploaded to asimov. // Telemetry events. Uploaded to asimov.
@ -99,11 +97,12 @@ namespace CalculatorApp
#pragma region TraceLogger setup and cleanup #pragma region TraceLogger setup and cleanup
TraceLogger::TraceLogger() : TraceLogger::TraceLogger()
g_calculatorProvider( : g_calculatorProvider(
L"MicrosoftCalculator", L"MicrosoftCalculator",
LoggingChannelOptions(GUID{ 0x4f50731a, 0x89cf, 0x4782, 0xb3, 0xe0, 0xdc, 0xe8, 0xc9, 0x4, 0x76, 0xba }), // Microsoft Telemetry group LoggingChannelOptions(GUID{ 0x4f50731a, 0x89cf, 0x4782, 0xb3, 0xe0, 0xdc, 0xe8, 0xc9, 0x4, 0x76, 0xba }), // Microsoft Telemetry group
GUID{ 0x905ca09, 0x610e, 0x401e, 0xb6, 0x50, 0x2f, 0x21, 0x29, 0x80, 0xb9, 0xe0 }), // Unique providerID {0905CA09-610E-401E-B650-2F212980B9E0} GUID{ 0x905ca09, 0x610e, 0x401e, 0xb6, 0x50, 0x2f, 0x21, 0x29, 0x80, 0xb9, 0xe0 })
, // Unique providerID {0905CA09-610E-401E-B650-2F212980B9E0}
m_appLaunchActivity{ nullptr } m_appLaunchActivity{ nullptr }
{ {
// initialize the function array // initialize the function array
@ -307,7 +306,8 @@ namespace CalculatorApp
void TraceLogger::LogSharedMemoryUsed(wstring_view fromMode, wstring_view toMode, unsigned int memorySize) const void TraceLogger::LogSharedMemoryUsed(wstring_view fromMode, wstring_view toMode, unsigned int memorySize) const
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{}; LoggingFields fields{};
fields.AddString(L"FromMode", fromMode); fields.AddString(L"FromMode", fromMode);
@ -318,7 +318,8 @@ namespace CalculatorApp
void TraceLogger::LogBitFlipPaneClicked() const void TraceLogger::LogBitFlipPaneClicked() const
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{}; LoggingFields fields{};
LogTelemetryEvent(EVENT_NAME_BITFLIP_PANE_CLICKED, fields); LogTelemetryEvent(EVENT_NAME_BITFLIP_PANE_CLICKED, fields);
@ -326,7 +327,8 @@ namespace CalculatorApp
void TraceLogger::LogBitFlipUsed() const void TraceLogger::LogBitFlipUsed() const
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{}; LoggingFields fields{};
LogTelemetryEvent(EVENT_NAME_BITFLIP_BUTTONS_USED, fields); LogTelemetryEvent(EVENT_NAME_BITFLIP_BUTTONS_USED, fields);
@ -339,11 +341,8 @@ namespace CalculatorApp
if (!isAppLaunchBeginLogged) if (!isAppLaunchBeginLogged)
{ {
m_appLaunchActivity = g_calculatorProvider.StartActivity( m_appLaunchActivity =
EVENT_NAME_APP_LAUNCH_BEGIN, g_calculatorProvider.StartActivity(EVENT_NAME_APP_LAUNCH_BEGIN, nullptr, LoggingLevel::Verbose, LoggingOptions(MICROSOFT_KEYWORD_TELEMETRY));
nullptr,
LoggingLevel::Verbose,
LoggingOptions(MICROSOFT_KEYWORD_TELEMETRY));
isAppLaunchBeginLogged = true; isAppLaunchBeginLogged = true;
} }
@ -376,7 +375,8 @@ namespace CalculatorApp
void TraceLogger::LogDebug(wstring_view debugData) void TraceLogger::LogDebug(wstring_view debugData)
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{}; LoggingFields fields{};
fields.AddString(L"DebugData", debugData); fields.AddString(L"DebugData", debugData);
@ -385,7 +385,8 @@ namespace CalculatorApp
void TraceLogger::LogOnAppLaunch(wstring_view previousExecutionState) const void TraceLogger::LogOnAppLaunch(wstring_view previousExecutionState) const
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{}; LoggingFields fields{};
fields.AddString(L"PreviousExecutionState", previousExecutionState); fields.AddString(L"PreviousExecutionState", previousExecutionState);
@ -394,7 +395,8 @@ namespace CalculatorApp
void TraceLogger::LogAboutFlyoutOpened() const void TraceLogger::LogAboutFlyoutOpened() const
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{}; LoggingFields fields{};
LogTelemetryEvent(EVENT_NAME_ABOUT_FLYOUT_OPENED, fields); LogTelemetryEvent(EVENT_NAME_ABOUT_FLYOUT_OPENED, fields);
@ -402,7 +404,8 @@ namespace CalculatorApp
void TraceLogger::LogNavBarOpened() const void TraceLogger::LogNavBarOpened() const
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{}; LoggingFields fields{};
LogTelemetryEvent(EVENT_NAME_NAV_BAR_OPENED, fields); LogTelemetryEvent(EVENT_NAME_NAV_BAR_OPENED, fields);
@ -410,7 +413,8 @@ namespace CalculatorApp
void TraceLogger::LogClearHistory() const void TraceLogger::LogClearHistory() const
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{}; LoggingFields fields{};
LogTelemetryEvent(EVENT_NAME_HISTORY_CLEAR, fields); LogTelemetryEvent(EVENT_NAME_HISTORY_CLEAR, fields);
@ -418,7 +422,8 @@ namespace CalculatorApp
void TraceLogger::LogHistoryFlyoutOpenBegin(unsigned int historyItemCount) const void TraceLogger::LogHistoryFlyoutOpenBegin(unsigned int historyItemCount) const
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
// we want to record the event only when history item count is atleast 20 // we want to record the event only when history item count is atleast 20
if (historyItemCount >= 20) if (historyItemCount >= 20)
@ -431,7 +436,8 @@ namespace CalculatorApp
void TraceLogger::LogHistoryFlyoutOpenEnd(int historyItemCount) const void TraceLogger::LogHistoryFlyoutOpenEnd(int historyItemCount) const
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
if (historyItemCount >= 20) if (historyItemCount >= 20)
{ {
@ -443,7 +449,8 @@ namespace CalculatorApp
void TraceLogger::LogHistoryBodyOpened() const void TraceLogger::LogHistoryBodyOpened() const
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{}; LoggingFields fields{};
LogTelemetryEvent(EVENT_NAME_HISTORY_BODY_OPENED, fields); LogTelemetryEvent(EVENT_NAME_HISTORY_BODY_OPENED, fields);
@ -451,7 +458,8 @@ namespace CalculatorApp
void TraceLogger::LogMemoryFlyoutOpenBegin(unsigned int memoryItemCount) const void TraceLogger::LogMemoryFlyoutOpenBegin(unsigned int memoryItemCount) const
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
// we want to record the event only when memory item count is atleast 4 // we want to record the event only when memory item count is atleast 4
if (memoryItemCount >= 4) if (memoryItemCount >= 4)
@ -464,7 +472,8 @@ namespace CalculatorApp
void TraceLogger::LogMemoryFlyoutOpenEnd(unsigned int memoryItemCount) const void TraceLogger::LogMemoryFlyoutOpenEnd(unsigned int memoryItemCount) const
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
if (memoryItemCount >= 4) if (memoryItemCount >= 4)
{ {
@ -476,7 +485,8 @@ namespace CalculatorApp
void TraceLogger::LogMemoryBodyOpened() const void TraceLogger::LogMemoryBodyOpened() const
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{}; LoggingFields fields{};
LogTelemetryEvent(EVENT_NAME_MEMORY_BODY_OPENED, fields); LogTelemetryEvent(EVENT_NAME_MEMORY_BODY_OPENED, fields);
@ -487,7 +497,8 @@ namespace CalculatorApp
// Use of this function is to analyze perf of mode change. // Use of this function is to analyze perf of mode change.
void TraceLogger::LogModeChangeBegin(ViewMode fromMode, ViewMode toMode, int windowId) void TraceLogger::LogModeChangeBegin(ViewMode fromMode, ViewMode toMode, int windowId)
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
if (NavCategory::IsValidViewMode(fromMode) && NavCategory::IsValidViewMode(toMode)) if (NavCategory::IsValidViewMode(fromMode) && NavCategory::IsValidViewMode(toMode))
{ {
@ -502,7 +513,8 @@ namespace CalculatorApp
// comment: same as LogModeChangeBegin // comment: same as LogModeChangeBegin
void TraceLogger::LogModeChangeEnd(ViewMode toMode, int windowId) const void TraceLogger::LogModeChangeEnd(ViewMode toMode, int windowId) const
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
if (NavCategory::IsValidViewMode(toMode)) if (NavCategory::IsValidViewMode(toMode))
{ {
@ -515,7 +527,8 @@ namespace CalculatorApp
void TraceLogger::LogHistoryItemLoadBegin() const void TraceLogger::LogHistoryItemLoadBegin() const
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{}; LoggingFields fields{};
LogTelemetryEvent(EVENT_NAME_HISTORY_ITEM_LOAD_BEGIN, fields); LogTelemetryEvent(EVENT_NAME_HISTORY_ITEM_LOAD_BEGIN, fields);
@ -523,7 +536,8 @@ namespace CalculatorApp
void TraceLogger::LogHistoryItemLoadEnd(unsigned int historyTokenCount) const void TraceLogger::LogHistoryItemLoadEnd(unsigned int historyTokenCount) const
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{}; LoggingFields fields{};
fields.AddUInt32(L"HistoryTokenCount", historyTokenCount); fields.AddUInt32(L"HistoryTokenCount", historyTokenCount);
@ -532,7 +546,8 @@ namespace CalculatorApp
void TraceLogger::LogNewWindowCreationBegin(int windowId) void TraceLogger::LogNewWindowCreationBegin(int windowId)
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{}; LoggingFields fields{};
fields.AddUInt32(L"WindowId", windowId); fields.AddUInt32(L"WindowId", windowId);
@ -541,7 +556,8 @@ namespace CalculatorApp
void TraceLogger::LogNewWindowCreationEnd(int windowId) void TraceLogger::LogNewWindowCreationEnd(int windowId)
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{}; LoggingFields fields{};
fields.AddUInt32(L"WindowId", windowId); fields.AddUInt32(L"WindowId", windowId);
@ -550,7 +566,8 @@ namespace CalculatorApp
void TraceLogger::LogError(wstring_view errorString) void TraceLogger::LogError(wstring_view errorString)
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{}; LoggingFields fields{};
fields.AddString(L"ErrorString", errorString); fields.AddString(L"ErrorString", errorString);
@ -559,7 +576,8 @@ namespace CalculatorApp
void TraceLogger::LogPrelaunchedAppActivatedByUser() void TraceLogger::LogPrelaunchedAppActivatedByUser()
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{}; LoggingFields fields{};
LogTelemetryEvent(EVENT_NAME_PRELAUNCHED_APP_ACTIVATED_BY_USER, fields); LogTelemetryEvent(EVENT_NAME_PRELAUNCHED_APP_ACTIVATED_BY_USER, fields);
@ -567,7 +585,8 @@ namespace CalculatorApp
void TraceLogger::LogAppPrelaunchedBySystem() void TraceLogger::LogAppPrelaunchedBySystem()
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{}; LoggingFields fields{};
LogTelemetryEvent(EVENT_NAME_APP_PRELAUNCHED_BY_SYSTEM, fields); LogTelemetryEvent(EVENT_NAME_APP_PRELAUNCHED_BY_SYSTEM, fields);
@ -588,9 +607,11 @@ namespace CalculatorApp
} }
} }
void TraceLogger::LogMemoryUsed(int windowId, unsigned int slotPosition, bool isStandard, bool isScientific, bool isProgrammer, unsigned int memorySize) const void TraceLogger::LogMemoryUsed(int windowId, unsigned int slotPosition, bool isStandard, bool isScientific, bool isProgrammer,
unsigned int memorySize) const
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
// Reader lock for the static resources // Reader lock for the static resources
reader_writer_lock::scoped_lock_read lock(s_traceLoggerLock); reader_writer_lock::scoped_lock_read lock(s_traceLoggerLock);
@ -625,7 +646,8 @@ namespace CalculatorApp
void TraceLogger::LogMultipleMemoryUsed(unsigned int slotPosition, unsigned int memorySize) const void TraceLogger::LogMultipleMemoryUsed(unsigned int slotPosition, unsigned int memorySize) const
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{}; LoggingFields fields{};
fields.AddUInt32(L"MemoryIndex", slotPosition); fields.AddUInt32(L"MemoryIndex", slotPosition);
@ -635,7 +657,8 @@ namespace CalculatorApp
void TraceLogger::LogSingleMemoryUsed(unsigned int memorySize) const void TraceLogger::LogSingleMemoryUsed(unsigned int memorySize) const
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{}; LoggingFields fields{};
fields.AddUInt32(L"MemoryListSize", memorySize); fields.AddUInt32(L"MemoryListSize", memorySize);
@ -644,7 +667,8 @@ namespace CalculatorApp
void TraceLogger::LogInvalidPastedInputOccurred(wstring_view reason, ViewMode mode, int programmerNumberBase, int bitLengthType) void TraceLogger::LogInvalidPastedInputOccurred(wstring_view reason, ViewMode mode, int programmerNumberBase, int bitLengthType)
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{}; LoggingFields fields{};
fields.AddString(L"Mode", NavCategory::GetFriendlyName(mode)->Data()); fields.AddString(L"Mode", NavCategory::GetFriendlyName(mode)->Data());
@ -657,7 +681,8 @@ namespace CalculatorApp
void TraceLogger::LogValidInputPasted(ViewMode mode) const void TraceLogger::LogValidInputPasted(ViewMode mode) const
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{}; LoggingFields fields{};
fields.AddString(L"Mode", NavCategory::GetFriendlyName(mode)->Data()); fields.AddString(L"Mode", NavCategory::GetFriendlyName(mode)->Data());
@ -666,7 +691,8 @@ namespace CalculatorApp
void TraceLogger::LogStandardException(wstring_view functionName, const exception& e) const void TraceLogger::LogStandardException(wstring_view functionName, const exception& e) const
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{}; LoggingFields fields{};
fields.AddString(L"FunctionName", functionName); fields.AddString(L"FunctionName", functionName);
@ -678,7 +704,8 @@ namespace CalculatorApp
void TraceLogger::LogWinRTException(wstring_view functionName, hresult_error const& e) const void TraceLogger::LogWinRTException(wstring_view functionName, hresult_error const& e) const
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{}; LoggingFields fields{};
fields.AddString(L"FunctionName", functionName); fields.AddString(L"FunctionName", functionName);
@ -687,9 +714,10 @@ namespace CalculatorApp
LogMeasureEvent(EVENT_NAME_EXCEPTION, fields); LogMeasureEvent(EVENT_NAME_EXCEPTION, fields);
} }
void TraceLogger::LogPlatformException(wstring_view functionName, Platform::Exception^ e) const void TraceLogger::LogPlatformException(wstring_view functionName, Platform::Exception ^ e) const
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{}; LoggingFields fields{};
fields.AddString(L"FunctionName", functionName); fields.AddString(L"FunctionName", functionName);
@ -733,11 +761,11 @@ namespace CalculatorApp
{ {
return s_programmerType[index]; return s_programmerType[index];
} }
//return "N/A" // return "N/A"
return s_programmerType[0]; return s_programmerType[0];
} }
bool TraceLogger::GetIndex(int &index) bool TraceLogger::GetIndex(int& index)
{ {
if (findIndex[index] > 0) if (findIndex[index] > 0)
{ {
@ -755,7 +783,8 @@ namespace CalculatorApp
void TraceLogger::LogMaxWindowCount() void TraceLogger::LogMaxWindowCount()
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{}; LoggingFields fields{};
fields.AddUInt32(L"WindowCount", (unsigned int)maxWindowCount); fields.AddUInt32(L"WindowCount", (unsigned int)maxWindowCount);
@ -764,7 +793,8 @@ namespace CalculatorApp
void TraceLogger::LogWindowActivated() const void TraceLogger::LogWindowActivated() const
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{}; LoggingFields fields{};
LogTelemetryEvent(EVENT_NAME_WINDOW_LAUNCHED_PROTOCOL, fields); LogTelemetryEvent(EVENT_NAME_WINDOW_LAUNCHED_PROTOCOL, fields);
@ -772,7 +802,8 @@ namespace CalculatorApp
void TraceLogger::LogWindowLaunched() const void TraceLogger::LogWindowLaunched() const
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{}; LoggingFields fields{};
LogTelemetryEvent(EVENT_NAME_WINDOW_LAUNCHED_TILESEARCH, fields); LogTelemetryEvent(EVENT_NAME_WINDOW_LAUNCHED_TILESEARCH, fields);
@ -840,7 +871,8 @@ namespace CalculatorApp
void TraceLogger::LogFunctionUsage(int windowId) void TraceLogger::LogFunctionUsage(int windowId)
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
for (int i = 0; i < functionCount; i++) for (int i = 0; i < functionCount; i++)
{ {
@ -897,8 +929,7 @@ namespace CalculatorApp
// Ignore first 3 calls during the initialization of the combo box selected items for Add mode // Ignore first 3 calls during the initialization of the combo box selected items for Add mode
int firstChangeEventCount = isAddMode ? 4 : 1; int firstChangeEventCount = isAddMode ? 4 : 1;
if (((*usageMap)[windowId] == firstChangeEventCount) if (((*usageMap)[windowId] == firstChangeEventCount) && (!(*isLoggedInSession)))
&& (!(*isLoggedInSession)))
{ {
LoggingFields fields{}; LoggingFields fields{};
fields.AddString(L"AddSubtractMode", isAddMode ? L"Add" : L"Subtract"); fields.AddString(L"AddSubtractMode", isAddMode ? L"Add" : L"Subtract");
@ -910,16 +941,12 @@ namespace CalculatorApp
void TraceLogger::LogDateClippedTimeDifferenceFound(Calendar const& today, DateTime const& clippedTime) const void TraceLogger::LogDateClippedTimeDifferenceFound(Calendar const& today, DateTime const& clippedTime) const
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
auto calendarSystem = today.GetCalendarSystem(); auto calendarSystem = today.GetCalendarSystem();
auto clock = today.GetClock(); auto clock = today.GetClock();
DateTimeFormatter dtFormatter{ DateTimeFormatter dtFormatter{ L"longdate shorttime", { L"en-US" }, GlobalizationPreferences::HomeGeographicRegion(), calendarSystem, clock };
L"longdate shorttime",
{ L"en-US" },
GlobalizationPreferences::HomeGeographicRegion(),
calendarSystem,
clock };
LoggingFields fields{}; LoggingFields fields{};
fields.AddString(L"ResolvedCalendarLanguage", today.ResolvedLanguage()); fields.AddString(L"ResolvedCalendarLanguage", today.ResolvedLanguage());
@ -934,7 +961,8 @@ namespace CalculatorApp
void TraceLogger::LogUserRequestedRefreshFailed() const void TraceLogger::LogUserRequestedRefreshFailed() const
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{}; LoggingFields fields{};
LogTelemetryEvent(L"UserRequestedRefreshFailed", fields); LogTelemetryEvent(L"UserRequestedRefreshFailed", fields);
@ -942,7 +970,8 @@ namespace CalculatorApp
void TraceLogger::LogConversionResult(wstring_view fromValue, wstring_view fromUnit, wstring_view toValue, wstring_view toUnit) const void TraceLogger::LogConversionResult(wstring_view fromValue, wstring_view fromUnit, wstring_view toValue, wstring_view toUnit) const
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
wstring behaviorString{}; wstring behaviorString{};
NetworkAccessBehavior behavior = NetworkManager::GetNetworkAccessBehavior(); NetworkAccessBehavior behavior = NetworkManager::GetNetworkAccessBehavior();
@ -979,10 +1008,10 @@ namespace CalculatorApp
void TraceLogger::LogCoreWindowWasNull() const void TraceLogger::LogCoreWindowWasNull() const
{ {
if (!GetTraceLoggingProviderEnabled()) return; if (!GetTraceLoggingProviderEnabled())
return;
LoggingFields fields{}; LoggingFields fields{};
LogTelemetryEvent(EVENT_NAME_CORE_WINDOW_WAS_NULL, fields); LogTelemetryEvent(EVENT_NAME_CORE_WINDOW_WAS_NULL, fields);
} }
} }

View file

@ -18,7 +18,10 @@ namespace CalculatorApp
public: public:
int count; int count;
std::wstring funcName; std::wstring funcName;
FuncLog() { count = 0; } FuncLog()
{
count = 0;
}
FuncLog(std::wstring fName) FuncLog(std::wstring fName)
{ {
funcName = fName; funcName = fName;
@ -30,7 +33,7 @@ namespace CalculatorApp
{ {
public: public:
TraceLogger(_In_ TraceLogger const&) = delete; TraceLogger(_In_ TraceLogger const&) = delete;
TraceLogger const & operator= (_In_ TraceLogger const&) = delete; TraceLogger const& operator=(_In_ TraceLogger const&) = delete;
~TraceLogger(); ~TraceLogger();
static TraceLogger& GetInstance(); static TraceLogger& GetInstance();
bool GetTraceLoggingProviderEnabled() const; bool GetTraceLoggingProviderEnabled() const;
@ -93,21 +96,22 @@ namespace CalculatorApp
// Trace methods for Date Calculator usage // Trace methods for Date Calculator usage
void LogDateDifferenceModeUsed(int windowId); void LogDateDifferenceModeUsed(int windowId);
void LogDateAddSubtractModeUsed(int windowId, bool isAddMode); void LogDateAddSubtractModeUsed(int windowId, bool isAddMode);
void LogDateClippedTimeDifferenceFound(winrt::Windows::Globalization::Calendar const& today, winrt::Windows::Foundation::DateTime const& clippedTime) const; void LogDateClippedTimeDifferenceFound(winrt::Windows::Globalization::Calendar const& today,
winrt::Windows::Foundation::DateTime const& clippedTime) const;
void LogStandardException(std::wstring_view functionName, _In_ const std::exception& e) const; void LogStandardException(std::wstring_view functionName, _In_ const std::exception& e) const;
void LogWinRTException(std::wstring_view functionName, _In_ winrt::hresult_error const& e) const; void LogWinRTException(std::wstring_view functionName, _In_ winrt::hresult_error const& e) const;
void LogPlatformException(std::wstring_view functionName, _In_ Platform::Exception^ e) const; void LogPlatformException(std::wstring_view functionName, _In_ Platform::Exception ^ e) const;
private: private:
// Create an instance of TraceLogger // Create an instance of TraceLogger
TraceLogger(); TraceLogger();
// Any new Log method should // Any new Log method should
// a) decide the level of logging. This will help us in limiting recording of events only up to a certain level. See this link for guidance https://msdn.microsoft.com/en-us/library/windows/desktop/aa363742(v=vs.85).aspx // a) decide the level of logging. This will help us in limiting recording of events only up to a certain level. See this link for guidance
// We're using Verbose level for events that are called frequently and needed only for debugging or capturing perf for specific scenarios // https://msdn.microsoft.com/en-us/library/windows/desktop/aa363742(v=vs.85).aspx We're using Verbose level for events that are called frequently and
// b) should decide whether or not to log to telemetry and pass TraceLoggingKeyword(MICROSOFT_KEYWORD_TELEMETRY) accordingly // needed only for debugging or capturing perf for specific scenarios b) should decide whether or not to log to telemetry and pass
// c) Should accept a variable number of additional data arguments if needed // TraceLoggingKeyword(MICROSOFT_KEYWORD_TELEMETRY) accordingly c) Should accept a variable number of additional data arguments if needed
void LogTelemetryEvent(std::wstring_view eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields) const; void LogTelemetryEvent(std::wstring_view eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields) const;
void LogMeasureEvent(std::wstring_view eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields) const; void LogMeasureEvent(std::wstring_view eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields) const;
void LogCriticalDataEvent(std::wstring_view eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields) const; void LogCriticalDataEvent(std::wstring_view eventName, winrt::Windows::Foundation::Diagnostics::LoggingFields fields) const;
@ -133,7 +137,7 @@ namespace CalculatorApp
bool isHypButtonLogged = false; bool isHypButtonLogged = false;
bool isAngleButtonInitialized = false; bool isAngleButtonInitialized = false;
unsigned int findIndex[maxFunctionSize] = { 0 }; unsigned int findIndex[maxFunctionSize] = { 0 };
bool GetIndex(int &index); bool GetIndex(int& index);
std::wstring GetProgrammerType(int index); std::wstring GetProgrammerType(int index);
size_t maxWindowCount = 0; size_t maxWindowCount = 0;
bool isAppLaunchBeginLogged = false; bool isAppLaunchBeginLogged = false;

View file

@ -30,12 +30,12 @@ void Utils::IFTPlatformException(HRESULT hr)
{ {
if (FAILED(hr)) if (FAILED(hr))
{ {
Platform::Exception^ exception = ref new Platform::Exception(hr); Platform::Exception ^ exception = ref new Platform::Exception(hr);
throw(exception); throw(exception);
} }
} }
String^ Utils::GetStringValue(String^ input) String ^ Utils::GetStringValue(String ^ input)
{ {
// Remove first and last " characters // Remove first and last " characters
if (input->Length() >= 3) if (input->Length() >= 3)
@ -68,20 +68,16 @@ int Utils::GetWindowId()
return windowId; return windowId;
} }
void Utils::RunOnUIThreadNonblocking(std::function<void()>&& function, _In_ CoreDispatcher^ currentDispatcher) void Utils::RunOnUIThreadNonblocking(std::function<void()>&& function, _In_ CoreDispatcher ^ currentDispatcher)
{ {
if (currentDispatcher != nullptr) if (currentDispatcher != nullptr)
{ {
auto task = create_task(currentDispatcher->RunAsync(CoreDispatcherPriority::Normal, auto task = create_task(currentDispatcher->RunAsync(CoreDispatcherPriority::Normal, ref new DispatchedHandler([function]() { function(); })));
ref new DispatchedHandler([function]()
{
function();
})));
} }
} }
// Returns if the last character of a wstring is the target wchar_t // Returns if the last character of a wstring is the target wchar_t
bool Utils::IsLastCharacterTarget(_In_ wstring const &input, _In_ wchar_t target) bool Utils::IsLastCharacterTarget(_In_ wstring const& input, _In_ wchar_t target)
{ {
return !input.empty() && input.back() == target; return !input.empty() && input.back() == target;
} }
@ -96,9 +92,8 @@ wstring Utils::RemoveUnwantedCharsFromWstring(wstring input, wchar_t* unwantedCh
return input; return input;
} }
void Utils::SerializeCommandsAndTokens(_In_ shared_ptr<CalculatorVector <pair<wstring, int>>> const &tokens, void Utils::SerializeCommandsAndTokens(_In_ shared_ptr<CalculatorVector<pair<wstring, int>>> const& tokens,
_In_ shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> const &commands, _In_ shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> const& commands, DataWriter ^ writer)
DataWriter^ writer)
{ {
unsigned int commandsSize; unsigned int commandsSize;
IFTPlatformException(commands->GetSize(&commandsSize)); IFTPlatformException(commands->GetSize(&commandsSize));
@ -134,7 +129,7 @@ void Utils::SerializeCommandsAndTokens(_In_ shared_ptr<CalculatorVector <pair<ws
} }
} }
const shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> Utils::DeserializeCommands(DataReader^ reader) const shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> Utils::DeserializeCommands(DataReader ^ reader)
{ {
shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> commandVector = make_shared<CalculatorVector<shared_ptr<IExpressionCommand>>>(); shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> commandVector = make_shared<CalculatorVector<shared_ptr<IExpressionCommand>>>();
auto commandVectorSize = reader->ReadUInt32(); auto commandVectorSize = reader->ReadUInt32();
@ -151,9 +146,9 @@ const shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> Utils::Deseri
return commandVector; return commandVector;
} }
const shared_ptr<CalculatorVector <pair<wstring, int>>> Utils::DeserializeTokens(DataReader^ reader) const shared_ptr<CalculatorVector<pair<wstring, int>>> Utils::DeserializeTokens(DataReader ^ reader)
{ {
shared_ptr<CalculatorVector <pair<wstring, int>>> tokenVector = make_shared<CalculatorVector<pair<wstring, int>>>(); shared_ptr<CalculatorVector<pair<wstring, int>>> tokenVector = make_shared<CalculatorVector<pair<wstring, int>>>();
auto tokensSize = reader->ReadUInt32(); auto tokensSize = reader->ReadUInt32();
for (unsigned int i = 0; i < tokensSize; ++i) for (unsigned int i = 0; i < tokensSize; ++i)
@ -193,14 +188,14 @@ bool Utils::IsDateTimeOlderThan(DateTime dateTime, const long long duration)
return dateTime.UniversalTime + duration < now.UniversalTime; return dateTime.UniversalTime + duration < now.UniversalTime;
} }
task<void> Utils::WriteFileToFolder(IStorageFolder^ folder, String^ fileName, String^ contents, CreationCollisionOption collisionOption) task<void> Utils::WriteFileToFolder(IStorageFolder ^ folder, String ^ fileName, String ^ contents, CreationCollisionOption collisionOption)
{ {
if (folder == nullptr) if (folder == nullptr)
{ {
co_return; co_return;
} }
StorageFile^ file = co_await folder->CreateFileAsync(fileName, collisionOption); StorageFile ^ file = co_await folder->CreateFileAsync(fileName, collisionOption);
if (file == nullptr) if (file == nullptr)
{ {
co_return; co_return;
@ -209,19 +204,19 @@ task<void> Utils::WriteFileToFolder(IStorageFolder^ folder, String^ fileName, St
co_await FileIO::WriteTextAsync(file, contents); co_await FileIO::WriteTextAsync(file, contents);
} }
task<String^> Utils::ReadFileFromFolder(IStorageFolder^ folder, String^ fileName) task<String ^> Utils::ReadFileFromFolder(IStorageFolder ^ folder, String ^ fileName)
{ {
if (folder == nullptr) if (folder == nullptr)
{ {
co_return nullptr; co_return nullptr;
} }
StorageFile^ file = co_await folder->GetFileAsync(fileName); StorageFile ^ file = co_await folder->GetFileAsync(fileName);
if (file == nullptr) if (file == nullptr)
{ {
co_return nullptr; co_return nullptr;
} }
String^ contents = co_await FileIO::ReadTextAsync(file); String ^ contents = co_await FileIO::ReadTextAsync(file);
co_return contents; co_return contents;
} }

View file

@ -9,92 +9,187 @@
// Utility macros to make Models easier to write // Utility macros to make Models easier to write
// generates a member variable called m_<n> // generates a member variable called m_<n>
#define PROPERTY_R(t, n)\ #define PROPERTY_R(t, n) \
property t n {\ property t n \
t get() { return m_##n; }\ { \
private: void set(t value) { m_##n = value; }\ t get() \
} private: t m_##n; public: { \
return m_##n; \
} \
\
private: \
void set(t value) \
{ \
m_##n = value; \
} \
} \
\
private: \
t m_##n; \
\
public:
#define PROPERTY_RW(t, n)\ #define PROPERTY_RW(t, n) \
property t n {\ property t n \
t get() { return m_##n; }\ { \
void set(t value) { m_##n = value; }\ t get() \
} private: t m_##n; public: { \
return m_##n; \
} \
void set(t value) \
{ \
m_##n = value; \
} \
} \
\
private: \
t m_##n; \
\
public:
#define OBSERVABLE_PROPERTY_R(t, n)\ #define OBSERVABLE_PROPERTY_R(t, n) \
property t n {\ property t n \
t get() { return m_##n; }\ { \
private: void set(t value) {\ t get() \
if (m_##n != value) {\ { \
m_##n = value;\ return m_##n; \
RaisePropertyChanged(L#n);\ } \
}}\ \
} private: t m_##n; public: private: \
void set(t value) \
{ \
if (m_##n != value) \
{ \
m_##n = value; \
RaisePropertyChanged(L#n); \
} \
} \
} \
\
private: \
t m_##n; \
\
public:
#define OBSERVABLE_PROPERTY_RW(t, n)\ #define OBSERVABLE_PROPERTY_RW(t, n) \
property t n {\ property t n \
t get() { return m_##n; }\ { \
void set(t value) {\ t get() \
if (m_##n != value) {\ { \
m_##n = value;\ return m_##n; \
RaisePropertyChanged(L#n);\ } \
}\ void set(t value) \
}\ { \
} private: t m_##n; public: if (m_##n != value) \
{ \
m_##n = value; \
RaisePropertyChanged(L#n); \
} \
} \
} \
\
private: \
t m_##n; \
\
public:
#define OBSERVABLE_NAMED_PROPERTY_R(t, n)\ #define OBSERVABLE_NAMED_PROPERTY_R(t, n) \
OBSERVABLE_PROPERTY_R(t, n)\ OBSERVABLE_PROPERTY_R(t, n) \
internal: static property Platform::String^ n##PropertyName {\ internal: \
Platform::String^ get() { return Platform::StringReference(L#n); }\ static property Platform::String ^ n##PropertyName \
} public: { \
Platform::String ^ get() { return Platform::StringReference(L#n); } \
} \
\
public:
#define OBSERVABLE_NAMED_PROPERTY_RW(t, n)\ #define OBSERVABLE_NAMED_PROPERTY_RW(t, n) \
OBSERVABLE_PROPERTY_RW(t, n)\ OBSERVABLE_PROPERTY_RW(t, n) \
internal: static property Platform::String^ n##PropertyName {\ internal: \
Platform::String^ get() { return Platform::StringReference(L#n); }\ static property Platform::String ^ n##PropertyName \
} public: { \
Platform::String ^ get() { return Platform::StringReference(L#n); } \
} \
\
public:
#define OBSERVABLE_PROPERTY_FIELD(n) m_##n #define OBSERVABLE_PROPERTY_FIELD(n) m_##n
// This variant of the observable object is for objects that don't want to react to property changes // This variant of the observable object is for objects that don't want to react to property changes
#ifndef UNIT_TESTS #ifndef UNIT_TESTS
#define OBSERVABLE_OBJECT() virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler^ PropertyChanged;\ #define OBSERVABLE_OBJECT() \
internal: void RaisePropertyChanged(Platform::String^ p) {\ virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler ^ PropertyChanged; \
PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs(p)); } public: internal: \
void RaisePropertyChanged(Platform::String ^ p) \
{ \
PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs(p)); \
} \
\
public:
#else #else
#define OBSERVABLE_OBJECT() virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler^ PropertyChanged;\ #define OBSERVABLE_OBJECT() \
internal: void RaisePropertyChanged(Platform::String^ p) {\ virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler ^ PropertyChanged; \
} public: internal: \
void RaisePropertyChanged(Platform::String ^ p) \
{ \
} \
\
public:
#endif #endif
// The callback specified in the macro is a method in the class that will be called every time the object changes // The callback specified in the macro is a method in the class that will be called every time the object changes
// the callback is supposed to be have a single parameter of type Platform::String^ // the callback is supposed to be have a single parameter of type Platform::String^
#ifndef UNIT_TESTS #ifndef UNIT_TESTS
#define OBSERVABLE_OBJECT_CALLBACK(c) virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler^ PropertyChanged;\ #define OBSERVABLE_OBJECT_CALLBACK(c) \
internal: void RaisePropertyChanged(Platform::String^ p) {\ virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler ^ PropertyChanged; \
PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs(p));\ internal: \
c(p);\ void RaisePropertyChanged(Platform::String ^ p) \
} public: { \
PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs(p)); \
c(p); \
} \
\
public:
#else #else
#define OBSERVABLE_OBJECT_CALLBACK(c) virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler^ PropertyChanged;\ #define OBSERVABLE_OBJECT_CALLBACK(c) \
internal: void RaisePropertyChanged(Platform::String^ p) {\ virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler ^ PropertyChanged; \
c(p);\ internal: \
} public: void RaisePropertyChanged(Platform::String ^ p) \
{ \
c(p); \
} \
\
public:
#endif #endif
// The variable member generated by this macro should not be used in the class code, use the // The variable member generated by this macro should not be used in the class code, use the
// property getter instead. // property getter instead.
#define COMMAND_FOR_METHOD(p, m) property Windows::UI::Xaml::Input::ICommand^ p {\ #define COMMAND_FOR_METHOD(p, m) \
property Windows::UI::Xaml::Input::ICommand^ p {\
Windows::UI::Xaml::Input::ICommand^ get() {\ Windows::UI::Xaml::Input::ICommand^ get() {\
if (!donotuse_##p) {\ if (!donotuse_##p) {\
donotuse_##p = CalculatorApp::Common::MakeDelegate(this, &m);\ donotuse_##p = CalculatorApp::Common::MakeDelegate(this, &m);\
} return donotuse_##p; }} private: Windows::UI::Xaml::Input::ICommand^ donotuse_##p; public: } return donotuse_##p; }} private: Windows::UI::Xaml::Input::ICommand^ donotuse_##p; \
\
public:
#define DEPENDENCY_PROPERTY_DECLARATION(t, n)\ #define DEPENDENCY_PROPERTY_DECLARATION(t, n) \
property t n {\ property t n \
t get() { return safe_cast<t>(GetValue(s_##n##Property)); }\ { \
void set(t value) { SetValue(s_##n##Property, value); } }\ t get() \
private: static Windows::UI::Xaml::DependencyProperty^ s_##n##Property; public: { \
return safe_cast<t>(GetValue(s_##n##Property)); \
} \
void set(t value) \
{ \
SetValue(s_##n##Property, value); \
} \
} \
\
private: \
static Windows::UI::Xaml::DependencyProperty ^ s_##n##Property; \
\
public:
// Utilities for DependencyProperties // Utilities for DependencyProperties
namespace Utils namespace Utils
@ -114,13 +209,13 @@ namespace Utils
}; };
template <typename T> template <typename T>
struct RemoveHat<T^> struct RemoveHat<T ^>
{ {
typedef T type; typedef T type;
}; };
template <typename T> template <typename T>
typename std::enable_if<IsRefClass<T>::value, T^>::type MakeDefault() typename std::enable_if<IsRefClass<T>::value, T ^>::type MakeDefault()
{ {
return nullptr; return nullptr;
} }
@ -283,140 +378,317 @@ namespace Utils
} }
void IFTPlatformException(HRESULT hr); void IFTPlatformException(HRESULT hr);
Platform::String^ GetStringValue(Platform::String^ input); Platform::String ^ GetStringValue(Platform::String ^ input);
bool IsLastCharacterTarget(std::wstring const &input, wchar_t target); bool IsLastCharacterTarget(std::wstring const& input, wchar_t target);
std::wstring RemoveUnwantedCharsFromWstring(std::wstring inputString, wchar_t* unwantedChars, unsigned int size); std::wstring RemoveUnwantedCharsFromWstring(std::wstring inputString, wchar_t* unwantedChars, unsigned int size);
double GetDoubleFromWstring(std::wstring input); double GetDoubleFromWstring(std::wstring input);
int GetWindowId(); int GetWindowId();
void RunOnUIThreadNonblocking(std::function<void()>&& function, _In_ Windows::UI::Core::CoreDispatcher^ currentDispatcher); void RunOnUIThreadNonblocking(std::function<void()>&& function, _In_ Windows::UI::Core::CoreDispatcher ^ currentDispatcher);
void SerializeCommandsAndTokens(_In_ std::shared_ptr<CalculatorVector <std::pair<std::wstring, int>>> const &tokens, void SerializeCommandsAndTokens(_In_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const& tokens,
_In_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const &commands, _In_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const& commands,
Windows::Storage::Streams::DataWriter^ writer); Windows::Storage::Streams::DataWriter ^ writer);
const std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> DeserializeCommands(Windows::Storage::Streams::DataReader^ reader); const std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> DeserializeCommands(Windows::Storage::Streams::DataReader ^ reader);
const std::shared_ptr<CalculatorVector <std::pair<std::wstring, int>>> DeserializeTokens(Windows::Storage::Streams::DataReader^ reader); const std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> DeserializeTokens(Windows::Storage::Streams::DataReader ^ reader);
Windows::Foundation::DateTime GetUniversalSystemTime(); Windows::Foundation::DateTime GetUniversalSystemTime();
bool IsDateTimeOlderThan(Windows::Foundation::DateTime dateTime, const long long duration); bool IsDateTimeOlderThan(Windows::Foundation::DateTime dateTime, const long long duration);
concurrency::task<void> WriteFileToFolder(Windows::Storage::IStorageFolder^ folder, Platform::String^ fileName, Platform::String^ contents, Windows::Storage::CreationCollisionOption collisionOption); concurrency::task<void> WriteFileToFolder(Windows::Storage::IStorageFolder ^ folder, Platform::String ^ fileName, Platform::String ^ contents,
concurrency::task<Platform::String^> ReadFileFromFolder(Windows::Storage::IStorageFolder^ folder, Platform::String^ fileName); Windows::Storage::CreationCollisionOption collisionOption);
concurrency::task<Platform::String ^> ReadFileFromFolder(Windows::Storage::IStorageFolder ^ folder, Platform::String ^ fileName);
} }
// This goes into the header to define the property, in the public: section of the class // This goes into the header to define the property, in the public: section of the class
#define DEPENDENCY_PROPERTY_OWNER(owner)\ #define DEPENDENCY_PROPERTY_OWNER(owner) \
private: typedef owner DependencyPropertiesOwner; public: private: \
typedef owner DependencyPropertiesOwner; \
\
public:
// Normal DependencyProperty // Normal DependencyProperty
#define DEPENDENCY_PROPERTY(type, name)\ #define DEPENDENCY_PROPERTY(type, name) \
property type name {\ property type name \
type get() { return safe_cast<type>(GetValue(s_##name##Property)); }\ { \
void set(type value) { SetValue(s_##name##Property, value); }\ type get() \
} private: static Windows::UI::Xaml::DependencyProperty^ s_##name##Property;\ { \
public: static property Windows::UI::Xaml::DependencyProperty^ name##Property {\ return safe_cast<type>(GetValue(s_##name##Property)); \
Windows::UI::Xaml::DependencyProperty^ get() { assert(s_##name##Property); return s_##name##Property; }\ } \
}\ void set(type value) \
private: static Windows::UI::Xaml::DependencyProperty^ Initialize##name##Property() {\ { \
return Utils::RegisterDependencyProperty<DependencyPropertiesOwner, type>(L#name); } public: SetValue(s_##name##Property, value); \
} \
} \
\
private: \
static Windows::UI::Xaml::DependencyProperty ^ s_##name##Property; \
\
public: \
static property Windows::UI::Xaml::DependencyProperty ^ name##Property \
{ \
Windows::UI::Xaml::DependencyProperty ^ get() { \
assert(s_##name##Property); \
return s_##name##Property; \
} \
} \
\
private: \
static Windows::UI::Xaml::DependencyProperty ^ Initialize##name##Property() \
{ \
return Utils::RegisterDependencyProperty<DependencyPropertiesOwner, type>(L#name); \
} \
\
public:
#define DEPENDENCY_PROPERTY_WITH_DEFAULT(type, name, defaultValue)\ #define DEPENDENCY_PROPERTY_WITH_DEFAULT(type, name, defaultValue) \
property type name {\ property type name \
type get() { return safe_cast<type>(GetValue(s_##name##Property)); }\ { \
void set(type value) { SetValue(s_##name##Property, value); }\ type get() \
} private: static Windows::UI::Xaml::DependencyProperty^ s_##name##Property;\ { \
public: static property Windows::UI::Xaml::DependencyProperty^ name##Property {\ return safe_cast<type>(GetValue(s_##name##Property)); \
Windows::UI::Xaml::DependencyProperty^ get() { assert(s_##name##Property); return s_##name##Property; }\ } \
}\ void set(type value) \
private: static Windows::UI::Xaml::DependencyProperty^ Initialize##name##Property() {\ { \
return Utils::RegisterDependencyProperty<DependencyPropertiesOwner, type>(L#name, defaultValue); } public: SetValue(s_##name##Property, value); \
} \
} \
\
private: \
static Windows::UI::Xaml::DependencyProperty ^ s_##name##Property; \
\
public: \
static property Windows::UI::Xaml::DependencyProperty ^ name##Property \
{ \
Windows::UI::Xaml::DependencyProperty ^ get() { \
assert(s_##name##Property); \
return s_##name##Property; \
} \
} \
\
private: \
static Windows::UI::Xaml::DependencyProperty ^ Initialize##name##Property() \
{ \
return Utils::RegisterDependencyProperty<DependencyPropertiesOwner, type>(L#name, defaultValue); \
} \
\
public:
#define DEPENDENCY_PROPERTY_WITH_CALLBACK(type, name)\ #define DEPENDENCY_PROPERTY_WITH_CALLBACK(type, name) \
property type name {\ property type name \
type get() { return safe_cast<type>(GetValue(s_##name##Property)); }\ { \
void set(type value) { SetValue(s_##name##Property, value); }\ type get() \
} private: static Windows::UI::Xaml::DependencyProperty^ s_##name##Property;\ { \
public: static property Windows::UI::Xaml::DependencyProperty^ name##Property {\ return safe_cast<type>(GetValue(s_##name##Property)); \
Windows::UI::Xaml::DependencyProperty^ get() { assert(s_##name##Property); return s_##name##Property; }\ } \
}\ void set(type value) \
private: static Windows::UI::Xaml::DependencyProperty^ Initialize##name##Property() {\ { \
return Utils::RegisterDependencyPropertyWithCallback<DependencyPropertiesOwner, type>(L#name, &On##name##PropertyChangedImpl); }\ SetValue(s_##name##Property, value); \
static void On##name##PropertyChangedImpl(Windows::UI::Xaml::DependencyObject^ sender, Windows::UI::Xaml::DependencyPropertyChangedEventArgs^ args) {\ } \
auto self = safe_cast<DependencyPropertiesOwner^>(sender);\ } \
self->On##name##PropertyChanged(safe_cast<type>(args->OldValue), safe_cast<type>(args->NewValue)); } public: \
private: \
static Windows::UI::Xaml::DependencyProperty ^ s_##name##Property; \
\
public: \
static property Windows::UI::Xaml::DependencyProperty ^ name##Property \
{ \
Windows::UI::Xaml::DependencyProperty ^ get() { \
assert(s_##name##Property); \
return s_##name##Property; \
} \
} \
\
private: \
static Windows::UI::Xaml::DependencyProperty ^ Initialize##name##Property() \
{ \
return Utils::RegisterDependencyPropertyWithCallback<DependencyPropertiesOwner, type>(L#name, &On##name##PropertyChangedImpl); \
} \
static void On##name##PropertyChangedImpl(Windows::UI::Xaml::DependencyObject ^ sender, Windows::UI::Xaml::DependencyPropertyChangedEventArgs ^ args) \
{ \
auto self = safe_cast<DependencyPropertiesOwner ^>(sender); \
self->On##name##PropertyChanged(safe_cast<type>(args->OldValue), safe_cast<type>(args->NewValue)); \
} \
\
public:
#define DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(type, name, defaultValue)\ #define DEPENDENCY_PROPERTY_WITH_DEFAULT_AND_CALLBACK(type, name, defaultValue) \
property type name {\ property type name \
type get() { return safe_cast<type>(GetValue(s_##name##Property)); }\ { \
void set(type value) { SetValue(s_##name##Property, value); }\ type get() \
} private: static Windows::UI::Xaml::DependencyProperty^ s_##name##Property;\ { \
public: static property Windows::UI::Xaml::DependencyProperty^ name##Property {\ return safe_cast<type>(GetValue(s_##name##Property)); \
Windows::UI::Xaml::DependencyProperty^ get() { assert(s_##name##Property); return s_##name##Property; }\ } \
}\ void set(type value) \
private: static Windows::UI::Xaml::DependencyProperty^ Initialize##name##Property() {\ { \
return Utils::RegisterDependencyPropertyWithCallback<DependencyPropertiesOwner, type>(L#name, defaultValue, &On##name##PropertyChangedImpl); }\ SetValue(s_##name##Property, value); \
static void On##name##PropertyChangedImpl(Windows::UI::Xaml::DependencyObject^ sender, Windows::UI::Xaml::DependencyPropertyChangedEventArgs^ args) {\ } \
auto self = safe_cast<DependencyPropertiesOwner^>(sender);\ } \
self->On##name##PropertyChanged(safe_cast<type>(args->OldValue), safe_cast<type>(args->NewValue)); } public: \
private: \
static Windows::UI::Xaml::DependencyProperty ^ s_##name##Property; \
\
public: \
static property Windows::UI::Xaml::DependencyProperty ^ name##Property \
{ \
Windows::UI::Xaml::DependencyProperty ^ get() { \
assert(s_##name##Property); \
return s_##name##Property; \
} \
} \
\
private: \
static Windows::UI::Xaml::DependencyProperty ^ Initialize##name##Property() \
{ \
return Utils::RegisterDependencyPropertyWithCallback<DependencyPropertiesOwner, type>(L#name, defaultValue, &On##name##PropertyChangedImpl); \
} \
static void On##name##PropertyChangedImpl(Windows::UI::Xaml::DependencyObject ^ sender, Windows::UI::Xaml::DependencyPropertyChangedEventArgs ^ args) \
{ \
auto self = safe_cast<DependencyPropertiesOwner ^>(sender); \
self->On##name##PropertyChanged(safe_cast<type>(args->OldValue), safe_cast<type>(args->NewValue)); \
} \
\
public:
// Attached DependencyProperty // Attached DependencyProperty
#define DEPENDENCY_PROPERTY_ATTACHED(type, name)\ #define DEPENDENCY_PROPERTY_ATTACHED(type, name) \
static type Get##name(Windows::UI::Xaml::DependencyObject^ target) { return safe_cast<type>(target->GetValue(s_##name##Property)); }\ static type Get##name(Windows::UI::Xaml::DependencyObject ^ target) \
static void Set##name(Windows::UI::Xaml::DependencyObject^ target, type value) { target->SetValue(s_##name##Property, value); }\ { \
private: static Windows::UI::Xaml::DependencyProperty^ s_##name##Property;\ return safe_cast<type>(target->GetValue(s_##name##Property)); \
public: static property Windows::UI::Xaml::DependencyProperty^ name##Property {\ } \
Windows::UI::Xaml::DependencyProperty^ get() { assert(s_##name##Property); return s_##name##Property; }\ static void Set##name(Windows::UI::Xaml::DependencyObject ^ target, type value) \
}\ { \
private: static Windows::UI::Xaml::DependencyProperty^ Initialize##name##Property() {\ target->SetValue(s_##name##Property, value); \
return Utils::RegisterDependencyPropertyAttached<DependencyPropertiesOwner, type>(L#name); } public: } \
\
private: \
static Windows::UI::Xaml::DependencyProperty ^ s_##name##Property; \
\
public: \
static property Windows::UI::Xaml::DependencyProperty ^ name##Property \
{ \
Windows::UI::Xaml::DependencyProperty ^ get() { \
assert(s_##name##Property); \
return s_##name##Property; \
} \
} \
\
private: \
static Windows::UI::Xaml::DependencyProperty ^ Initialize##name##Property() \
{ \
return Utils::RegisterDependencyPropertyAttached<DependencyPropertiesOwner, type>(L#name); \
} \
\
public:
#define DEPENDENCY_PROPERTY_ATTACHED_WITH_DEFAULT(type, name, defaultValue)\ #define DEPENDENCY_PROPERTY_ATTACHED_WITH_DEFAULT(type, name, defaultValue) \
static type Get##name(Windows::UI::Xaml::DependencyObject^ target) { return safe_cast<type>(target->GetValue(s_##name##Property)); }\ static type Get##name(Windows::UI::Xaml::DependencyObject ^ target) \
static void Set##name(Windows::UI::Xaml::DependencyObject^ target, type value) { target->SetValue(s_##name##Property, value); }\ { \
private: static Windows::UI::Xaml::DependencyProperty^ s_##name##Property;\ return safe_cast<type>(target->GetValue(s_##name##Property)); \
public: static property Windows::UI::Xaml::DependencyProperty^ name##Property {\ } \
Windows::UI::Xaml::DependencyProperty^ get() { assert(s_##name##Property); return s_##name##Property; }\ static void Set##name(Windows::UI::Xaml::DependencyObject ^ target, type value) \
}\ { \
private: static Windows::UI::Xaml::DependencyProperty^ Initialize##name##Property() {\ target->SetValue(s_##name##Property, value); \
return Utils::RegisterDependencyPropertyAttached<DependencyPropertiesOwner, type>(L#name, defaultValue); } public: } \
\
private: \
static Windows::UI::Xaml::DependencyProperty ^ s_##name##Property; \
\
public: \
static property Windows::UI::Xaml::DependencyProperty ^ name##Property \
{ \
Windows::UI::Xaml::DependencyProperty ^ get() { \
assert(s_##name##Property); \
return s_##name##Property; \
} \
} \
\
private: \
static Windows::UI::Xaml::DependencyProperty ^ Initialize##name##Property() \
{ \
return Utils::RegisterDependencyPropertyAttached<DependencyPropertiesOwner, type>(L#name, defaultValue); \
} \
\
public:
#define DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(type, name)\ #define DEPENDENCY_PROPERTY_ATTACHED_WITH_CALLBACK(type, name) \
static type Get##name(Windows::UI::Xaml::DependencyObject^ target) { return safe_cast<type>(target->GetValue(s_##name##Property)); }\ static type Get##name(Windows::UI::Xaml::DependencyObject ^ target) \
static void Set##name(Windows::UI::Xaml::DependencyObject^ target, type value) { target->SetValue(s_##name##Property, value); }\ { \
private: static Windows::UI::Xaml::DependencyProperty^ s_##name##Property;\ return safe_cast<type>(target->GetValue(s_##name##Property)); \
public: static property Windows::UI::Xaml::DependencyProperty^ name##Property {\ } \
Windows::UI::Xaml::DependencyProperty^ get() { assert(s_##name##Property); return s_##name##Property; }\ static void Set##name(Windows::UI::Xaml::DependencyObject ^ target, type value) \
}\ { \
private: static Windows::UI::Xaml::DependencyProperty^ Initialize##name##Property() {\ target->SetValue(s_##name##Property, value); \
return Utils::RegisterDependencyPropertyAttachedWithCallback<DependencyPropertiesOwner, type>(L#name, &On##name##PropertyChangedImpl); }\ } \
static void On##name##PropertyChangedImpl(Windows::UI::Xaml::DependencyObject^ sender, Windows::UI::Xaml::DependencyPropertyChangedEventArgs^ args) {\ \
On##name##PropertyChanged(sender, safe_cast<type>(args->OldValue), safe_cast<type>(args->NewValue)); } public: private: \
static Windows::UI::Xaml::DependencyProperty ^ s_##name##Property; \
\
public: \
static property Windows::UI::Xaml::DependencyProperty ^ name##Property \
{ \
Windows::UI::Xaml::DependencyProperty ^ get() { \
assert(s_##name##Property); \
return s_##name##Property; \
} \
} \
\
private: \
static Windows::UI::Xaml::DependencyProperty ^ Initialize##name##Property() \
{ \
return Utils::RegisterDependencyPropertyAttachedWithCallback<DependencyPropertiesOwner, type>(L#name, &On##name##PropertyChangedImpl); \
} \
static void On##name##PropertyChangedImpl(Windows::UI::Xaml::DependencyObject ^ sender, Windows::UI::Xaml::DependencyPropertyChangedEventArgs ^ args) \
{ \
On##name##PropertyChanged(sender, safe_cast<type>(args->OldValue), safe_cast<type>(args->NewValue)); \
} \
\
public:
#define DEPENDENCY_PROPERTY_ATTACHED_WITH_DEFAULT_AND_CALLBACK(type, name, defaultValue)\ #define DEPENDENCY_PROPERTY_ATTACHED_WITH_DEFAULT_AND_CALLBACK(type, name, defaultValue) \
static type Get##name(Windows::UI::Xaml::DependencyObject^ target) { return safe_cast<type>(target->GetValue(s_##name##Property)); }\ static type Get##name(Windows::UI::Xaml::DependencyObject ^ target) \
static void Set##name(Windows::UI::Xaml::DependencyObject^ target, type value) { target->SetValue(s_##name##Property, value); }\ { \
private: static Windows::UI::Xaml::DependencyProperty^ s_##name##Property;\ return safe_cast<type>(target->GetValue(s_##name##Property)); \
public: static property Windows::UI::Xaml::DependencyProperty^ name##Property {\ } \
Windows::UI::Xaml::DependencyProperty^ get() { assert(s_##name##Property); return s_##name##Property; }\ static void Set##name(Windows::UI::Xaml::DependencyObject ^ target, type value) \
}\ { \
private: static Windows::UI::Xaml::DependencyProperty^ Initialize##name##Property() {\ target->SetValue(s_##name##Property, value); \
return Utils::RegisterDependencyPropertyAttachedWithCallback<DependencyPropertiesOwner, type>(L#name, defaultValue, &On##name##PropertyChangedImpl); }\ } \
static void On##name##PropertyChangedImpl(Windows::UI::Xaml::DependencyObject^ sender, Windows::UI::Xaml::DependencyPropertyChangedEventArgs^ args) {\ \
On##name##PropertyChanged(sender, safe_cast<type>(args->OldValue), safe_cast<type>(args->NewValue)); } public: private: \
static Windows::UI::Xaml::DependencyProperty ^ s_##name##Property; \
\
public: \
static property Windows::UI::Xaml::DependencyProperty ^ name##Property \
{ \
Windows::UI::Xaml::DependencyProperty ^ get() { \
assert(s_##name##Property); \
return s_##name##Property; \
} \
} \
\
private: \
static Windows::UI::Xaml::DependencyProperty ^ Initialize##name##Property() \
{ \
return Utils::RegisterDependencyPropertyAttachedWithCallback<DependencyPropertiesOwner, type>(L#name, defaultValue, &On##name##PropertyChangedImpl); \
} \
static void On##name##PropertyChangedImpl(Windows::UI::Xaml::DependencyObject ^ sender, Windows::UI::Xaml::DependencyPropertyChangedEventArgs ^ args) \
{ \
On##name##PropertyChanged(sender, safe_cast<type>(args->OldValue), safe_cast<type>(args->NewValue)); \
} \
\
public:
// This goes into the cpp to initialize the static variable // This goes into the cpp to initialize the static variable
#define DEPENDENCY_PROPERTY_INITIALIZATION(owner, name)\ #define DEPENDENCY_PROPERTY_INITIALIZATION(owner, name) Windows::UI::Xaml::DependencyProperty ^ owner::s_##name##Property = owner::Initialize##name##Property();
Windows::UI::Xaml::DependencyProperty^ owner::s_##name##Property =\
owner::Initialize##name##Property();
namespace CalculatorApp namespace CalculatorApp
{ {
template <typename T> template <typename T>
T from_cx(Platform::Object^ from) T from_cx(Platform::Object ^ from)
{ {
T to{ nullptr }; T to{ nullptr };
winrt::check_hresult(reinterpret_cast<::IUnknown*>(from)->QueryInterface(winrt::guid_of<T>(), winrt::check_hresult(reinterpret_cast<::IUnknown*>(from)->QueryInterface(winrt::guid_of<T>(), reinterpret_cast<void**>(winrt::put_abi(to))));
reinterpret_cast<void**>(winrt::put_abi(to))));
return to; return to;
} }

View file

@ -3,31 +3,30 @@
#pragma once #pragma once
namespace CalculatorApp { namespace Common namespace CalculatorApp
{ {
public ref class ValidSelectedItemConverter sealed: public Windows::UI::Xaml::Data::IValueConverter namespace Common
{
public
ref class ValidSelectedItemConverter sealed : public Windows::UI::Xaml::Data::IValueConverter
{ {
public: public:
ValidSelectedItemConverter() ValidSelectedItemConverter()
{ } {
}
private: private:
virtual Platform::Object
virtual Platform::Object^ Convert( ^ Convert(Platform::Object ^ value, Windows::UI::Xaml::Interop::TypeName /*targetType*/, Platform::Object ^ /*parameter*/,
Platform::Object^ value, Platform::String ^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::Convert
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
Platform::Object^ /*parameter*/,
Platform::String^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::Convert
{ {
// Pass through as we don't want to change the value from the source // Pass through as we don't want to change the value from the source
return value; return value;
} }
virtual Platform::Object^ ConvertBack( virtual Platform::Object
Platform::Object^ value, ^ ConvertBack(Platform::Object ^ value, Windows::UI::Xaml::Interop::TypeName /*targetType*/, Platform::Object ^ /*parameter*/,
Windows::UI::Xaml::Interop::TypeName /*targetType*/, Platform::String ^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::ConvertBack
Platform::Object^ /*parameter*/,
Platform::String^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::ConvertBack
{ {
if (value) if (value)
{ {
@ -38,35 +37,32 @@ namespace CalculatorApp { namespace Common
} }
}; };
public ref class ValidSelectedIndexConverter sealed: public Windows::UI::Xaml::Data::IValueConverter public
ref class ValidSelectedIndexConverter sealed : public Windows::UI::Xaml::Data::IValueConverter
{ {
public: public:
ValidSelectedIndexConverter() ValidSelectedIndexConverter()
{ } {
}
private: private:
virtual Platform::Object
virtual Platform::Object^ Convert( ^ Convert(Platform::Object ^ value, Windows::UI::Xaml::Interop::TypeName /*targetType*/, Platform::Object ^ /*parameter*/,
Platform::Object^ value, Platform::String ^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::Convert
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
Platform::Object^ /*parameter*/,
Platform::String^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::Convert
{ {
// Pass through as we don't want to change the value from the source // Pass through as we don't want to change the value from the source
return value; return value;
} }
virtual Platform::Object^ ConvertBack( virtual Platform::Object
Platform::Object^ value, ^ ConvertBack(Platform::Object ^ value, Windows::UI::Xaml::Interop::TypeName /*targetType*/, Platform::Object ^ /*parameter*/,
Windows::UI::Xaml::Interop::TypeName /*targetType*/, Platform::String ^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::ConvertBack
Platform::Object^ /*parameter*/,
Platform::String^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::ConvertBack
{ {
// The value to be valid has to be a boxed int32 value // The value to be valid has to be a boxed int32 value
// extract that value and ensure it is valid, ie >= 0 // extract that value and ensure it is valid, ie >= 0
if (value) if (value)
{ {
auto box = dynamic_cast<Windows::Foundation::IPropertyValue^>(value); auto box = dynamic_cast<Windows::Foundation::IPropertyValue ^>(value);
if (box && box->Type == Windows::Foundation::PropertyType::Int32) if (box && box->Type == Windows::Foundation::PropertyType::Int32)
{ {
int index = box->GetInt32(); int index = box->GetInt32();
@ -80,4 +76,5 @@ namespace CalculatorApp { namespace Common
return Windows::UI::Xaml::DependencyProperty::UnsetValue; return Windows::UI::Xaml::DependencyProperty::UnsetValue;
} }
}; };
}} }
}

Some files were not shown because too many files have changed in this diff Show more