|
@ -5,7 +5,6 @@ root = true
|
|||
[*]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
end_of_line = crlf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
|
1
.gitignore
vendored
|
@ -290,4 +290,5 @@ __pycache__/
|
|||
# Calculator specific
|
||||
Generated Files/
|
||||
!/build/config/TRexDefs/**
|
||||
!src/Calculator/TemporaryKey.pfx
|
||||
!src/CalculatorUnitTests/CalculatorUnitTests_TemporaryKey.pfx
|
|
@ -15,30 +15,33 @@ name: $(BuildDefinitionName)_$(date:yyMM).$(date:dd)$(rev:rrr)
|
|||
jobs:
|
||||
- job: Localize
|
||||
pool:
|
||||
name: Package ES Custom Demands Lab A
|
||||
demands:
|
||||
- ClientAlias -equals PKGESUTILAPPS
|
||||
workspace:
|
||||
clean: outputs
|
||||
vmImage: vs2017-win2016
|
||||
variables:
|
||||
skipComponentGovernanceDetection: true
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
|
||||
- task: PkgESSetupBuild@10
|
||||
displayName: Initialize Package ES
|
||||
- task: MicrosoftTDBuild.tdbuild-task.tdbuild-task.TouchdownBuildTask@1
|
||||
displayName: Send resources to Touchdown Build
|
||||
inputs:
|
||||
productName: Calculator
|
||||
branchVersion: true
|
||||
teamId: 86
|
||||
authId: d3dd8113-65b3-4526-bdca-a00a7d1c37ba
|
||||
authKey: $(LocServiceKey)
|
||||
isPreview: false
|
||||
relativePathRoot: src/Calculator/Resources/en-US/
|
||||
resourceFilePath: '*.resw'
|
||||
outputDirectoryRoot: src/Calculator/Resources/
|
||||
|
||||
- task: PkgESTouchdownLocService@10
|
||||
displayName: Package ES Touchdown Loc Service
|
||||
- script: |
|
||||
cd $(Build.SourcesDirectory)
|
||||
git add -A
|
||||
git diff --cached --exit-code
|
||||
echo '##vso[task.setvariable variable=hasChanges]%errorlevel%'
|
||||
git diff --cached > $(Build.ArtifactStagingDirectory)\LocalizedStrings.patch
|
||||
displayName: Check for changes and create patch file
|
||||
|
||||
- task: PublishPipelineArtifact@0
|
||||
displayName: Publish patch file as artifact
|
||||
condition: eq(variables['hasChanges'], '1')
|
||||
inputs:
|
||||
IsCallToServiceStepSelected: true
|
||||
IsCheckedInFileSelected: true
|
||||
CheckinFilesAtOriginFilePath: true
|
||||
GitLocPath: Loc/Resources
|
||||
LocConfigFile: build/config/LocConfigPackageEs.xml
|
||||
AuthenticationMode: OAuth
|
||||
ClientApplicationID: d3dd8113-65b3-4526-bdca-a00a7d1c37ba
|
||||
ApplicationKeyID: $(LocServiceKey)
|
||||
SendToLoc: true
|
||||
artifactName: Patch
|
||||
targetPath: $(Build.ArtifactStagingDirectory)
|
|
@ -9,8 +9,8 @@ pr: none
|
|||
|
||||
variables:
|
||||
versionMajor: 10
|
||||
versionMinor: 1902
|
||||
versionBuild: $[counter('10.1902.*', 0)]
|
||||
versionMinor: 1903
|
||||
versionBuild: $[counter('10.1903.*', 0)]
|
||||
versionPatch: 0
|
||||
|
||||
name: '$(versionMajor).$(versionMinor).$(versionBuild).$(versionPatch)'
|
||||
|
|
|
@ -29,7 +29,7 @@ jobs:
|
|||
downloadDirectory: $(Build.SourcesDirectory)
|
||||
vstsFeed: WindowsApps
|
||||
vstsFeedPackage: calculator-internals
|
||||
vstsPackageVersion: 0.0.7
|
||||
vstsPackageVersion: 0.0.10
|
||||
|
||||
- template: ./build-single-architecture.yaml
|
||||
parameters:
|
||||
|
|
|
@ -20,6 +20,8 @@ jobs:
|
|||
vmImage: vs2017-win2016
|
||||
workspace:
|
||||
clean: outputs
|
||||
variables:
|
||||
skipComponentGovernanceDetection: true
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
|
|
|
@ -17,6 +17,8 @@ jobs:
|
|||
name: Package ES Lab E
|
||||
workspace:
|
||||
clean: outputs
|
||||
variables:
|
||||
skipComponentGovernanceDetection: true
|
||||
steps:
|
||||
- checkout: self
|
||||
clean: true
|
||||
|
@ -87,7 +89,7 @@ jobs:
|
|||
downloadDirectory: $(Build.SourcesDirectory)
|
||||
vstsFeed: WindowsApps
|
||||
vstsFeedPackage: calculator-internals
|
||||
vstsPackageVersion: 0.0.7
|
||||
vstsPackageVersion: 0.0.10
|
||||
|
||||
- task: PkgESStoreBrokerPackage@10
|
||||
displayName: Create StoreBroker Packages
|
||||
|
|
|
@ -14,6 +14,8 @@ jobs:
|
|||
name: Essential Experiences Interactive
|
||||
workspace:
|
||||
clean: outputs
|
||||
variables:
|
||||
skipComponentGovernanceDetection: true
|
||||
steps:
|
||||
- checkout: none
|
||||
|
||||
|
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 64 KiB |
Before Width: | Height: | Size: 3.1 MiB After Width: | Height: | Size: 3 MiB |
Before Width: | Height: | Size: 2.2 MiB After Width: | Height: | Size: 2.1 MiB |
Before Width: | Height: | Size: 3.2 MiB After Width: | Height: | Size: 3.1 MiB |
|
@ -9,6 +9,7 @@ In 2019, the Windows Calculator team is focused on:
|
|||
* Iterating upon the existing app design based on the latest [Fluent Design guidelines](https://developer.microsoft.com/en-us/windows/apps/design)
|
||||
* Improving testing and diagnostics within the project
|
||||
* Investigating new features with a focus on addressing top user feedback, including:
|
||||
* Adding graphing mode
|
||||
* Adding the ability for users to pin Calculator on top of other windows
|
||||
* Providing additional customization options
|
||||
* [Your feature idea here] - please review our [new feature development process](https://github.com/Microsoft/calculator/blob/master/docs/NewFeatureProcess.md) to get started!
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
root = true
|
||||
|
||||
[*.{xaml,cpp,h}]
|
||||
charset = utf-8-bom
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.{cpp,h}]
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
|
@ -56,7 +56,7 @@ bool CalcInput::TryToggleSign(bool isIntegerMode, wstring_view maxNumStr)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool CalcInput::TryAddDigit(unsigned int value, uint32_t radix, bool isIntegerMode, wstring_view maxNumStr, long wordBitWidth, int maxDigits)
|
||||
bool CalcInput::TryAddDigit(unsigned int value, uint32_t radix, bool isIntegerMode, wstring_view maxNumStr, int32_t wordBitWidth, int maxDigits)
|
||||
{
|
||||
// Convert from an integer into a character
|
||||
// This includes both normal digits and alpha 'digits' for radixes > 10
|
||||
|
|
|
@ -3,25 +3,26 @@
|
|||
|
||||
#include "pch.h"
|
||||
#include "Header Files/CalcEngine.h"
|
||||
#include "Header Files/CalcUtils.h"
|
||||
|
||||
bool IsOpInRange(WPARAM op, uint32_t x, uint32_t y)
|
||||
bool IsOpInRange(OpCode op, uint32_t x, uint32_t y)
|
||||
{
|
||||
return ((op >= x) && (op <= y));
|
||||
}
|
||||
|
||||
bool IsBinOpCode(WPARAM opCode)
|
||||
bool IsBinOpCode(OpCode opCode)
|
||||
{
|
||||
return IsOpInRange(opCode, IDC_AND, IDC_PWR);
|
||||
}
|
||||
|
||||
// WARNING: IDC_SIGN is a special unary op but still this doesn't catch this. Caller has to be aware
|
||||
// of it and catch it themselves or not needing this
|
||||
bool IsUnaryOpCode(WPARAM opCode)
|
||||
bool IsUnaryOpCode(OpCode opCode)
|
||||
{
|
||||
return IsOpInRange(opCode, IDC_UNARYFIRST, IDC_UNARYLAST);
|
||||
}
|
||||
|
||||
bool IsDigitOpCode(WPARAM opCode)
|
||||
bool IsDigitOpCode(OpCode opCode)
|
||||
{
|
||||
return IsOpInRange(opCode, IDC_0, IDC_F);
|
||||
}
|
||||
|
@ -31,7 +32,7 @@ bool IsDigitOpCode(WPARAM opCode)
|
|||
// so we abstract this as a separate routine. Note: There is another side to this. Some commands are not
|
||||
// gui mode setting to begin with, but once it is discovered it is invalid and we want to behave as though it
|
||||
// was never inout, we need to revert the state changes made as a result of this test
|
||||
bool IsGuiSettingOpCode(WPARAM opCode)
|
||||
bool IsGuiSettingOpCode(OpCode opCode)
|
||||
{
|
||||
if (IsOpInRange(opCode, IDM_HEX, IDM_BIN) ||
|
||||
IsOpInRange(opCode, IDM_QWORD, IDM_BYTE) ||
|
||||
|
|
|
@ -2,18 +2,25 @@
|
|||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#pragma once
|
||||
#include "Header Files/CalcEngine.h"
|
||||
#include "Command.h"
|
||||
#include "CalculatorVector.h"
|
||||
#include "ExpressionCommand.h"
|
||||
#include "CalcException.h"
|
||||
|
||||
constexpr int ASCII_0 = 48;
|
||||
|
||||
using namespace std;
|
||||
using namespace CalcEngine;
|
||||
|
||||
namespace {
|
||||
void IFT(ResultCode hr)
|
||||
{
|
||||
if (FAILED(hr))
|
||||
{
|
||||
throw hr;
|
||||
}
|
||||
}
|
||||
}
|
||||
void CHistoryCollector::ReinitHistory()
|
||||
{
|
||||
m_lastOpStartIndex = -1;
|
||||
|
@ -129,7 +136,7 @@ void CHistoryCollector::AddBinOpToHistory(int nOpCode, bool fNoRepetition)
|
|||
}
|
||||
|
||||
// This is expected to be called when a binary op in the last say 1+2+ is changing to another one say 1+2* (+ changed to *)
|
||||
// It needs to know by this change a Precedence inversion happened. i.e. previous op was lower or equal to its previous op, but the new
|
||||
// It needs to know by this change a Precedence inversion happened. i.e. previous op was lower or equal to its previous op, but the new
|
||||
// one isn't. (Eg. 1*2* to 1*2^). It can add explicit brackets to ensure the precedence is inverted. (Eg. (1*2) ^)
|
||||
void CHistoryCollector::ChangeLastBinOp(int nOpCode, bool fPrecInvToHigher)
|
||||
{
|
||||
|
@ -196,7 +203,7 @@ bool CHistoryCollector::FOpndAddedToHistory()
|
|||
|
||||
// AddUnaryOpToHistory
|
||||
//
|
||||
// This is does the postfix to prefix translation of the input and adds the text to the history. Eg. doing 2 + 4 (sqrt),
|
||||
// This is does the postfix to prefix translation of the input and adds the text to the history. Eg. doing 2 + 4 (sqrt),
|
||||
// this routine will ensure the last sqrt call unary operator, actually goes back in history and wraps 4 in sqrt(4)
|
||||
//
|
||||
void CHistoryCollector::AddUnaryOpToHistory(int nOpCode, bool fInv, ANGLE_TYPE angletype)
|
||||
|
@ -290,7 +297,7 @@ void CHistoryCollector::AddUnaryOpToHistory(int nOpCode, bool fInv, ANGLE_TYPE a
|
|||
}
|
||||
|
||||
// Called after = with the result of the equation
|
||||
// Responsible for clearing the top line of current running history display, as well as adding yet another element to
|
||||
// Responsible for clearing the top line of current running history display, as well as adding yet another element to
|
||||
// history of equations
|
||||
void CHistoryCollector::CompleteHistoryLine(wstring_view numStr)
|
||||
{
|
||||
|
@ -406,37 +413,39 @@ int CHistoryCollector::AddCommand(_In_ const std::shared_ptr<IExpressionCommand>
|
|||
return nCommands - 1;
|
||||
}
|
||||
|
||||
//To Update the operands in the Expression according to the current Radix
|
||||
// To Update the operands in the Expression according to the current Radix
|
||||
void CHistoryCollector::UpdateHistoryExpression(uint32_t radix, int32_t precision)
|
||||
{
|
||||
if (m_spTokens != nullptr)
|
||||
if (m_spTokens == nullptr)
|
||||
{
|
||||
unsigned int size;
|
||||
IFT(m_spTokens->GetSize(&size));
|
||||
return;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < size; ++i)
|
||||
unsigned int size;
|
||||
IFT(m_spTokens->GetSize(&size));
|
||||
|
||||
for (unsigned int i = 0; i < size; ++i)
|
||||
{
|
||||
std::pair<std::wstring, int> token;
|
||||
IFT(m_spTokens->GetAt(i, &token));
|
||||
int commandPosition = token.second;
|
||||
if (commandPosition != -1)
|
||||
{
|
||||
std::pair<std::wstring, int> token;
|
||||
IFT(m_spTokens->GetAt(i, &token));
|
||||
int commandPosition = token.second;
|
||||
if (commandPosition != -1)
|
||||
std::shared_ptr<IExpressionCommand> expCommand;
|
||||
IFT(m_spCommands->GetAt(commandPosition, &expCommand));
|
||||
if (expCommand != nullptr && CalculationManager::CommandType::OperandCommand == expCommand->GetCommandType())
|
||||
{
|
||||
std::shared_ptr<IExpressionCommand> expCommand;
|
||||
IFT(m_spCommands->GetAt(commandPosition, &expCommand));
|
||||
if (expCommand != nullptr && CalculationManager::CommandType::OperandCommand == expCommand->GetCommandType())
|
||||
std::shared_ptr<COpndCommand> opndCommand = std::static_pointer_cast<COpndCommand>(expCommand);
|
||||
if (opndCommand != nullptr)
|
||||
{
|
||||
std::shared_ptr<COpndCommand> opndCommand = std::static_pointer_cast<COpndCommand>(expCommand);
|
||||
if (opndCommand != nullptr)
|
||||
{
|
||||
token.first = opndCommand->GetString(radix, precision);
|
||||
IFT(m_spTokens->SetAt(i, token));
|
||||
opndCommand->SetCommands(GetOperandCommandsFromString(token.first));
|
||||
}
|
||||
token.first = opndCommand->GetString(radix, precision);
|
||||
IFT(m_spTokens->SetAt(i, token));
|
||||
opndCommand->SetCommands(GetOperandCommandsFromString(token.first));
|
||||
}
|
||||
}
|
||||
}
|
||||
SetExpressionDisplay();
|
||||
}
|
||||
SetExpressionDisplay();
|
||||
}
|
||||
|
||||
void CHistoryCollector::SetDecimalSymbol(wchar_t decimalSymbol)
|
||||
|
@ -444,7 +453,7 @@ void CHistoryCollector::SetDecimalSymbol(wchar_t decimalSymbol)
|
|||
m_decimalSymbol = decimalSymbol;
|
||||
}
|
||||
|
||||
//Update the commands corresponding to the passed string Number
|
||||
// Update the commands corresponding to the passed string Number
|
||||
std::shared_ptr<CalculatorVector<int>> CHistoryCollector::GetOperandCommandsFromString(wstring_view numStr)
|
||||
{
|
||||
std::shared_ptr<CalculatorVector<int>> commands = std::make_shared<CalculatorVector<int>>();
|
||||
|
|
|
@ -28,10 +28,10 @@ namespace CalcEngine
|
|||
|
||||
PNUMBER Number::ToPNUMBER() const
|
||||
{
|
||||
PNUMBER ret = _createnum(static_cast<ULONG>(this->Mantissa().size()) + 1);
|
||||
PNUMBER ret = _createnum(static_cast<uint32_t>(this->Mantissa().size()) + 1);
|
||||
ret->sign = this->Sign();
|
||||
ret->exp = this->Exp();
|
||||
ret->cdigit = static_cast<long>(this->Mantissa().size());
|
||||
ret->cdigit = static_cast<int32_t>(this->Mantissa().size());
|
||||
|
||||
MANTTYPE *ptrRet = ret->mant;
|
||||
for (auto const& digit : this->Mantissa())
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace CalcEngine
|
|||
|
||||
Rational::Rational(int32_t i)
|
||||
{
|
||||
PRAT pr = longtorat(static_cast<long>(i));
|
||||
PRAT pr = i32torat(static_cast<int32_t>(i));
|
||||
|
||||
m_p = Number{ pr->pp };
|
||||
m_q = Number{ pr->pq };
|
||||
|
@ -41,7 +41,7 @@ namespace CalcEngine
|
|||
|
||||
Rational::Rational(uint32_t ui)
|
||||
{
|
||||
PRAT pr = Ulongtorat(static_cast<unsigned long>(ui));
|
||||
PRAT pr = Ui32torat(static_cast<uint32_t>(ui));
|
||||
|
||||
m_p = Number{ pr->pp };
|
||||
m_q = Number{ pr->pq };
|
||||
|
@ -100,7 +100,7 @@ namespace CalcEngine
|
|||
addrat(&lhsRat, rhsRat, RATIONAL_PRECISION);
|
||||
destroyrat(rhsRat);
|
||||
}
|
||||
catch (DWORD error)
|
||||
catch (uint32_t error)
|
||||
{
|
||||
destroyrat(lhsRat);
|
||||
destroyrat(rhsRat);
|
||||
|
@ -123,7 +123,7 @@ namespace CalcEngine
|
|||
subrat(&lhsRat, rhsRat, RATIONAL_PRECISION);
|
||||
destroyrat(rhsRat);
|
||||
}
|
||||
catch (DWORD error)
|
||||
catch (uint32_t error)
|
||||
{
|
||||
destroyrat(lhsRat);
|
||||
destroyrat(rhsRat);
|
||||
|
@ -146,7 +146,7 @@ namespace CalcEngine
|
|||
mulrat(&lhsRat, rhsRat, RATIONAL_PRECISION);
|
||||
destroyrat(rhsRat);
|
||||
}
|
||||
catch (DWORD error)
|
||||
catch (uint32_t error)
|
||||
{
|
||||
destroyrat(lhsRat);
|
||||
destroyrat(rhsRat);
|
||||
|
@ -169,7 +169,7 @@ namespace CalcEngine
|
|||
divrat(&lhsRat, rhsRat, RATIONAL_PRECISION);
|
||||
destroyrat(rhsRat);
|
||||
}
|
||||
catch (DWORD error)
|
||||
catch (uint32_t error)
|
||||
{
|
||||
destroyrat(lhsRat);
|
||||
destroyrat(rhsRat);
|
||||
|
@ -192,7 +192,7 @@ namespace CalcEngine
|
|||
modrat(&lhsRat, rhsRat);
|
||||
destroyrat(rhsRat);
|
||||
}
|
||||
catch (DWORD error)
|
||||
catch (uint32_t error)
|
||||
{
|
||||
destroyrat(lhsRat);
|
||||
destroyrat(rhsRat);
|
||||
|
@ -215,7 +215,7 @@ namespace CalcEngine
|
|||
lshrat(&lhsRat, rhsRat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||
destroyrat(rhsRat);
|
||||
}
|
||||
catch (DWORD error)
|
||||
catch (uint32_t error)
|
||||
{
|
||||
destroyrat(lhsRat);
|
||||
destroyrat(rhsRat);
|
||||
|
@ -238,7 +238,7 @@ namespace CalcEngine
|
|||
rshrat(&lhsRat, rhsRat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||
destroyrat(rhsRat);
|
||||
}
|
||||
catch (DWORD error)
|
||||
catch (uint32_t error)
|
||||
{
|
||||
destroyrat(lhsRat);
|
||||
destroyrat(rhsRat);
|
||||
|
@ -261,7 +261,7 @@ namespace CalcEngine
|
|||
andrat(&lhsRat, rhsRat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||
destroyrat(rhsRat);
|
||||
}
|
||||
catch (DWORD error)
|
||||
catch (uint32_t error)
|
||||
{
|
||||
destroyrat(lhsRat);
|
||||
destroyrat(rhsRat);
|
||||
|
@ -283,7 +283,7 @@ namespace CalcEngine
|
|||
orrat(&lhsRat, rhsRat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||
destroyrat(rhsRat);
|
||||
}
|
||||
catch (DWORD error)
|
||||
catch (uint32_t error)
|
||||
{
|
||||
destroyrat(lhsRat);
|
||||
destroyrat(rhsRat);
|
||||
|
@ -305,7 +305,7 @@ namespace CalcEngine
|
|||
xorrat(&lhsRat, rhsRat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||
destroyrat(rhsRat);
|
||||
}
|
||||
catch (DWORD error)
|
||||
catch (uint32_t error)
|
||||
{
|
||||
destroyrat(lhsRat);
|
||||
destroyrat(rhsRat);
|
||||
|
@ -388,7 +388,7 @@ namespace CalcEngine
|
|||
{
|
||||
result = rat_equ(lhsRat, rhsRat, RATIONAL_PRECISION);
|
||||
}
|
||||
catch (DWORD error)
|
||||
catch (uint32_t error)
|
||||
{
|
||||
destroyrat(lhsRat);
|
||||
destroyrat(rhsRat);
|
||||
|
@ -416,7 +416,7 @@ namespace CalcEngine
|
|||
{
|
||||
result = rat_lt(lhsRat, rhsRat, RATIONAL_PRECISION);
|
||||
}
|
||||
catch (DWORD error)
|
||||
catch (uint32_t error)
|
||||
{
|
||||
destroyrat(lhsRat);
|
||||
destroyrat(rhsRat);
|
||||
|
@ -453,7 +453,7 @@ namespace CalcEngine
|
|||
{
|
||||
result = RatToString(rat, fmt, radix, precision);
|
||||
}
|
||||
catch (DWORD error)
|
||||
catch (uint32_t error)
|
||||
{
|
||||
destroyrat(rat);
|
||||
throw(error);
|
||||
|
@ -470,9 +470,9 @@ namespace CalcEngine
|
|||
uint64_t result;
|
||||
try
|
||||
{
|
||||
result = rattoUlonglong(rat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||
result = rattoUi64(rat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||
}
|
||||
catch (DWORD error)
|
||||
catch (uint32_t error)
|
||||
{
|
||||
destroyrat(rat);
|
||||
throw(error);
|
||||
|
|
|
@ -14,7 +14,7 @@ Rational RationalMath::Frac(Rational const& rat)
|
|||
{
|
||||
fracrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||
}
|
||||
catch (DWORD error)
|
||||
catch (uint32_t error)
|
||||
{
|
||||
destroyrat(prat);
|
||||
throw(error);
|
||||
|
@ -33,7 +33,7 @@ Rational RationalMath::Integer(Rational const& rat)
|
|||
{
|
||||
intrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||
}
|
||||
catch (DWORD error)
|
||||
catch (uint32_t error)
|
||||
{
|
||||
destroyrat(prat);
|
||||
throw(error);
|
||||
|
@ -55,7 +55,7 @@ Rational RationalMath::Pow(Rational const& base, Rational const& pow)
|
|||
powrat(&baseRat, powRat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||
destroyrat(powRat);
|
||||
}
|
||||
catch (DWORD error)
|
||||
catch (uint32_t error)
|
||||
{
|
||||
destroyrat(baseRat);
|
||||
destroyrat(powRat);
|
||||
|
@ -81,7 +81,7 @@ Rational RationalMath::Fact(Rational const& rat)
|
|||
{
|
||||
factrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||
}
|
||||
catch (DWORD error)
|
||||
catch (uint32_t error)
|
||||
{
|
||||
destroyrat(prat);
|
||||
throw(error);
|
||||
|
@ -101,7 +101,7 @@ Rational RationalMath::Exp(Rational const& rat)
|
|||
{
|
||||
exprat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||
}
|
||||
catch (DWORD error)
|
||||
catch (uint32_t error)
|
||||
{
|
||||
destroyrat(prat);
|
||||
throw(error);
|
||||
|
@ -121,7 +121,7 @@ Rational RationalMath::Log(Rational const& rat)
|
|||
{
|
||||
lograt(&prat, RATIONAL_PRECISION);
|
||||
}
|
||||
catch (DWORD error)
|
||||
catch (uint32_t error)
|
||||
{
|
||||
destroyrat(prat);
|
||||
throw(error);
|
||||
|
@ -156,7 +156,7 @@ Rational RationalMath::Sin(Rational const& rat, ANGLE_TYPE angletype)
|
|||
{
|
||||
sinanglerat(&prat, angletype, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||
}
|
||||
catch (DWORD error)
|
||||
catch (uint32_t error)
|
||||
{
|
||||
destroyrat(prat);
|
||||
throw(error);
|
||||
|
@ -176,7 +176,7 @@ Rational RationalMath::Cos(Rational const& rat, ANGLE_TYPE angletype)
|
|||
{
|
||||
cosanglerat(&prat, angletype, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||
}
|
||||
catch (DWORD error)
|
||||
catch (uint32_t error)
|
||||
{
|
||||
destroyrat(prat);
|
||||
throw(error);
|
||||
|
@ -196,7 +196,7 @@ Rational RationalMath::Tan(Rational const& rat, ANGLE_TYPE angletype)
|
|||
{
|
||||
tananglerat(&prat, angletype, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||
}
|
||||
catch (DWORD error)
|
||||
catch (uint32_t error)
|
||||
{
|
||||
destroyrat(prat);
|
||||
throw(error);
|
||||
|
@ -216,7 +216,7 @@ Rational RationalMath::ASin(Rational const& rat, ANGLE_TYPE angletype)
|
|||
{
|
||||
asinanglerat(&prat, angletype, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||
}
|
||||
catch (DWORD error)
|
||||
catch (uint32_t error)
|
||||
{
|
||||
destroyrat(prat);
|
||||
throw(error);
|
||||
|
@ -236,7 +236,7 @@ Rational RationalMath::ACos(Rational const& rat, ANGLE_TYPE angletype)
|
|||
{
|
||||
acosanglerat(&prat, angletype, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||
}
|
||||
catch (DWORD error)
|
||||
catch (uint32_t error)
|
||||
{
|
||||
destroyrat(prat);
|
||||
throw(error);
|
||||
|
@ -256,7 +256,7 @@ Rational RationalMath::ATan(Rational const& rat, ANGLE_TYPE angletype)
|
|||
{
|
||||
atananglerat(&prat, angletype, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||
}
|
||||
catch (DWORD error)
|
||||
catch (uint32_t error)
|
||||
{
|
||||
destroyrat(prat);
|
||||
throw(error);
|
||||
|
@ -276,7 +276,7 @@ Rational RationalMath::Sinh(Rational const& rat)
|
|||
{
|
||||
sinhrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||
}
|
||||
catch (DWORD error)
|
||||
catch (uint32_t error)
|
||||
{
|
||||
destroyrat(prat);
|
||||
throw(error);
|
||||
|
@ -296,7 +296,7 @@ Rational RationalMath::Cosh(Rational const& rat)
|
|||
{
|
||||
coshrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||
}
|
||||
catch (DWORD error)
|
||||
catch (uint32_t error)
|
||||
{
|
||||
destroyrat(prat);
|
||||
throw(error);
|
||||
|
@ -316,7 +316,7 @@ Rational RationalMath::Tanh(Rational const& rat)
|
|||
{
|
||||
tanhrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||
}
|
||||
catch (DWORD error)
|
||||
catch (uint32_t error)
|
||||
{
|
||||
destroyrat(prat);
|
||||
throw(error);
|
||||
|
@ -336,7 +336,7 @@ Rational RationalMath::ASinh(Rational const& rat)
|
|||
{
|
||||
asinhrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||
}
|
||||
catch (DWORD error)
|
||||
catch (uint32_t error)
|
||||
{
|
||||
destroyrat(prat);
|
||||
throw(error);
|
||||
|
@ -356,7 +356,7 @@ Rational RationalMath::ACosh(Rational const& rat)
|
|||
{
|
||||
acoshrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||
}
|
||||
catch (DWORD error)
|
||||
catch (uint32_t error)
|
||||
{
|
||||
destroyrat(prat);
|
||||
throw(error);
|
||||
|
@ -376,7 +376,7 @@ Rational RationalMath::ATanh(Rational const& rat)
|
|||
{
|
||||
atanhrat(&prat, RATIONAL_PRECISION);
|
||||
}
|
||||
catch (DWORD error)
|
||||
catch (uint32_t error)
|
||||
{
|
||||
destroyrat(prat);
|
||||
throw(error);
|
||||
|
|
|
@ -15,7 +15,7 @@ using namespace CalcEngine;
|
|||
|
||||
static constexpr int DEFAULT_MAX_DIGITS = 32;
|
||||
static constexpr int DEFAULT_PRECISION = 32;
|
||||
static constexpr long DEFAULT_RADIX = 10;
|
||||
static constexpr int32_t DEFAULT_RADIX = 10;
|
||||
|
||||
static constexpr wchar_t DEFAULT_DEC_SEPARATOR = L'.';
|
||||
static constexpr wchar_t DEFAULT_GRP_SEPARATOR = L',';
|
||||
|
|
|
@ -26,39 +26,41 @@
|
|||
using namespace std;
|
||||
using namespace CalcEngine;
|
||||
|
||||
// NPrecedenceOfOp
|
||||
//
|
||||
// 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.
|
||||
INT NPrecedenceOfOp(int nopCode)
|
||||
{
|
||||
static BYTE rgbPrec[] = { 0,0, IDC_OR,0, IDC_XOR,0, IDC_AND,1,
|
||||
IDC_ADD,2, IDC_SUB,2, IDC_RSHF,3, IDC_LSHF,3,
|
||||
IDC_MOD,3, IDC_DIV,3, IDC_MUL,3, IDC_PWR,4, IDC_ROOT, 4 };
|
||||
int iPrec;
|
||||
namespace {
|
||||
// NPrecedenceOfOp
|
||||
//
|
||||
// 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.
|
||||
int NPrecedenceOfOp(int nopCode)
|
||||
{
|
||||
static uint8_t rgbPrec[] = { 0,0, IDC_OR,0, IDC_XOR,0, IDC_AND,1,
|
||||
IDC_ADD,2, IDC_SUB,2, IDC_RSHF,3, IDC_LSHF,3,
|
||||
IDC_MOD,3, IDC_DIV,3, IDC_MUL,3, IDC_PWR,4, IDC_ROOT, 4 };
|
||||
unsigned int iPrec;
|
||||
|
||||
iPrec = 0;
|
||||
while ((iPrec < ARRAYSIZE(rgbPrec)) && (nopCode != rgbPrec[iPrec]))
|
||||
{
|
||||
iPrec += 2;
|
||||
}
|
||||
if (iPrec >= ARRAYSIZE(rgbPrec))
|
||||
{
|
||||
iPrec = 0;
|
||||
}
|
||||
return rgbPrec[iPrec + 1];
|
||||
while ((iPrec < size(rgbPrec)) && (nopCode != rgbPrec[iPrec]))
|
||||
{
|
||||
iPrec += 2;
|
||||
}
|
||||
if (iPrec >= size(rgbPrec))
|
||||
{
|
||||
iPrec = 0;
|
||||
}
|
||||
return rgbPrec[iPrec + 1];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// HandleErrorCommand
|
||||
//
|
||||
// When it is discovered by the state machine that at this point the input is not valid (eg. "1+)"), we want to proceed as though this input never
|
||||
// When it is discovered by the state machine that at this point the input is not valid (eg. "1+)"), we want to proceed as though this input never
|
||||
// occurred and may be some feedback to user like Beep. The rest of input can then continue by just ignoring this command.
|
||||
void CCalcEngine::HandleErrorCommand(WPARAM idc)
|
||||
void CCalcEngine::HandleErrorCommand(OpCode idc)
|
||||
{
|
||||
if (!IsGuiSettingOpCode(idc))
|
||||
{
|
||||
// we would have saved the prev command. Need to forget this state
|
||||
// We would have saved the prev command. Need to forget this state
|
||||
m_nTempCom = m_nLastCom;
|
||||
}
|
||||
}
|
||||
|
@ -81,7 +83,7 @@ void CCalcEngine::ClearTemporaryValues()
|
|||
m_bError = false;
|
||||
}
|
||||
|
||||
void CCalcEngine::ProcessCommand(WPARAM wParam)
|
||||
void CCalcEngine::ProcessCommand(OpCode wParam)
|
||||
{
|
||||
if (wParam == IDC_SET_RESULT)
|
||||
{
|
||||
|
@ -92,9 +94,9 @@ void CCalcEngine::ProcessCommand(WPARAM wParam)
|
|||
ProcessCommandWorker(wParam);
|
||||
}
|
||||
|
||||
void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
||||
void CCalcEngine::ProcessCommandWorker(OpCode wParam)
|
||||
{
|
||||
INT nx, ni;
|
||||
int nx, ni;
|
||||
|
||||
// Save the last command. Some commands are not saved in this manor, these
|
||||
// commands are:
|
||||
|
@ -105,7 +107,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
|||
if (!IsGuiSettingOpCode(wParam))
|
||||
{
|
||||
m_nLastCom = m_nTempCom;
|
||||
m_nTempCom = (INT)wParam;
|
||||
m_nTempCom = (int)wParam;
|
||||
}
|
||||
|
||||
if (m_bError)
|
||||
|
@ -126,7 +128,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
|||
}
|
||||
}
|
||||
|
||||
// Toggle Record/Display mode if appropriate.
|
||||
// Toggle Record/Display mode if appropriate.
|
||||
if (m_bRecord)
|
||||
{
|
||||
if (IsOpInRange(wParam, IDC_AND, IDC_MMINUS) ||
|
||||
|
@ -180,13 +182,13 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
|||
// BINARY OPERATORS:
|
||||
if (IsBinOpCode(wParam))
|
||||
{
|
||||
/* Change the operation if last input was operation. */
|
||||
// Change the operation if last input was operation.
|
||||
if (IsBinOpCode(m_nLastCom))
|
||||
{
|
||||
INT nPrev;
|
||||
int nPrev;
|
||||
bool fPrecInvToHigher = false; // Is Precedence Inversion from lower to higher precedence happening ??
|
||||
|
||||
m_nOpCode = (INT)wParam;
|
||||
m_nOpCode = (int)wParam;
|
||||
|
||||
// Check to see if by changing this binop, a Precedence inversion is happening.
|
||||
// Eg. 1 * 2 + and + is getting changed to ^. The previous precedence rules would have already computed
|
||||
|
@ -283,7 +285,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
|||
DisplayAnnounceBinaryOperator();
|
||||
|
||||
m_lastVal = m_currentVal;
|
||||
m_nOpCode = (INT)wParam;
|
||||
m_nOpCode = (int)wParam;
|
||||
m_HistoryCollector.AddBinOpToHistory(m_nOpCode);
|
||||
m_bNoPrevEqu = m_bChangeOp = true;
|
||||
return;
|
||||
|
@ -311,7 +313,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
|||
m_HistoryCollector.AddOpndToHistory(m_numberString, m_currentVal);
|
||||
}
|
||||
|
||||
m_HistoryCollector.AddUnaryOpToHistory((INT)wParam, m_bInv, m_angletype);
|
||||
m_HistoryCollector.AddUnaryOpToHistory((int)wParam, m_bInv, m_angletype);
|
||||
}
|
||||
|
||||
if ((wParam == IDC_SIN) || (wParam == IDC_COS) || (wParam == IDC_TAN) || (wParam == IDC_SINH) || (wParam == IDC_COSH) || (wParam == IDC_TANH))
|
||||
|
@ -324,7 +326,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
|||
}
|
||||
}
|
||||
|
||||
m_currentVal = SciCalcFunctions(m_currentVal, (DWORD)wParam);
|
||||
m_currentVal = SciCalcFunctions(m_currentVal, (uint32_t)wParam);
|
||||
|
||||
if (m_bError)
|
||||
return;
|
||||
|
@ -364,7 +366,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
|||
|
||||
CheckAndAddLastBinOpToHistory();
|
||||
|
||||
if (TryToggleBit(m_currentVal, (DWORD)wParam - IDC_BINEDITSTART))
|
||||
if (TryToggleBit(m_currentVal, (uint32_t)wParam - IDC_BINEDITSTART))
|
||||
{
|
||||
DisplayNum();
|
||||
}
|
||||
|
@ -440,7 +442,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
|||
m_nTempCom = m_nLastCom; // Put back this last saved command to the prev state so ) can be handled properly
|
||||
ProcessCommand(IDC_CLOSEP);
|
||||
m_nLastCom = m_nTempCom; // Actually this is IDC_CLOSEP
|
||||
m_nTempCom = (INT)wParam; // put back in the state where last op seen was IDC_CLOSEP, and current op is IDC_EQU
|
||||
m_nTempCom = (int)wParam; // put back in the state where last op seen was IDC_CLOSEP, and current op is IDC_EQU
|
||||
}
|
||||
|
||||
if (!m_bNoPrevEqu)
|
||||
|
@ -544,6 +546,11 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
|||
if ((m_openParenCount >= MAXPRECDEPTH && nx) || (!m_openParenCount && !nx)
|
||||
|| ((m_precedenceOpCount >= MAXPRECDEPTH && m_nPrecOp[m_precedenceOpCount - 1] != 0)))
|
||||
{
|
||||
if (!m_openParenCount && !nx)
|
||||
{
|
||||
m_pCalcDisplay->OnNoRightParenAdded();
|
||||
}
|
||||
|
||||
HandleErrorCommand(wParam);
|
||||
break;
|
||||
}
|
||||
|
@ -567,7 +574,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
|||
m_lastVal = 0;
|
||||
if (IsBinOpCode(m_nLastCom))
|
||||
{
|
||||
// We want 1 + ( to start as 1 + (0. Any number you type replaces 0. But if it is 1 + 3 (, it is
|
||||
// We want 1 + ( to start as 1 + (0. Any number you type replaces 0. But if it is 1 + 3 (, it is
|
||||
// treated as 1 + (3
|
||||
m_currentVal = 0;
|
||||
}
|
||||
|
@ -796,7 +803,7 @@ void CCalcEngine::CheckAndAddLastBinOpToHistory(bool addToHistory)
|
|||
{
|
||||
if (m_HistoryCollector.FOpndAddedToHistory())
|
||||
{
|
||||
// if last time opnd was added but the last command was not a binary operator, then it must have come
|
||||
// if last time opnd was added but the last command was not a binary operator, then it must have come
|
||||
// from commands which add the operand, like unary operator. So history at this is showing 1 + sqrt(4)
|
||||
// but in reality the sqrt(4) is getting replaced by new number (may be unary op, or MR or SUM etc.)
|
||||
// So erase the last operand
|
||||
|
@ -848,7 +855,7 @@ void CCalcEngine::DisplayAnnounceBinaryOperator()
|
|||
}
|
||||
|
||||
// Unary operator Function Name table Element
|
||||
// since unary operators button names aren't exactly friendly for history purpose,
|
||||
// since unary operators button names aren't exactly friendly for history purpose,
|
||||
// we have this separate table to get its localized name and for its Inv function if it exists.
|
||||
typedef struct
|
||||
{
|
||||
|
@ -940,7 +947,7 @@ wstring_view CCalcEngine::OpCodeToUnaryString(int nOpCode, bool fInv, ANGLE_TYPE
|
|||
// Try to lookup the ID in the UFNE table
|
||||
int ids = 0;
|
||||
int iufne = nOpCode - IDC_UNARYFIRST;
|
||||
if (iufne >= 0 && iufne < ARRAYSIZE(rgUfne))
|
||||
if (iufne >= 0 && (size_t)iufne < size(rgUfne))
|
||||
{
|
||||
if (fInv)
|
||||
{
|
||||
|
@ -1020,7 +1027,7 @@ wstring CCalcEngine::GetCurrentResultForRadix(uint32_t radix, int32_t precision)
|
|||
wstring numberString = GetStringForDisplay(rat, radix);
|
||||
if (!numberString.empty())
|
||||
{
|
||||
//revert the precision to previously stored precision
|
||||
// Revert the precision to previously stored precision
|
||||
ChangeConstants(m_radix, m_precision);
|
||||
}
|
||||
|
||||
|
@ -1053,7 +1060,7 @@ wstring CCalcEngine::GetStringForDisplay(Rational const& rat, uint32_t radix)
|
|||
|
||||
result = tempRat.ToString(radix, m_nFE, m_precision);
|
||||
}
|
||||
catch (DWORD)
|
||||
catch (uint32_t)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ typedef struct {
|
|||
Rational value;
|
||||
int32_t precision;
|
||||
uint32_t radix;
|
||||
INT nFE;
|
||||
int nFE;
|
||||
NUM_WIDTH numwidth;
|
||||
bool fIntMath;
|
||||
bool bRecord;
|
||||
|
|
|
@ -24,7 +24,7 @@ using namespace CalcEngine;
|
|||
using namespace CalcEngine::RationalMath;
|
||||
|
||||
/* Routines for more complex mathematical functions/error checking. */
|
||||
CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& rat, DWORD op)
|
||||
CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& rat, uint32_t op)
|
||||
{
|
||||
Rational result{};
|
||||
try
|
||||
|
@ -70,7 +70,7 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
|
|||
|
||||
uint64_t w64Bits = result.ToUInt64_t();
|
||||
uint64_t lsb = ((w64Bits & 0x01) == 1) ? 1 : 0;
|
||||
w64Bits >>= 1; //RShift by 1
|
||||
w64Bits >>= 1; // RShift by 1
|
||||
w64Bits |= (lsb << (m_dwWordBitWidth - 1));
|
||||
|
||||
result = w64Bits;
|
||||
|
@ -205,7 +205,7 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
|
|||
}
|
||||
} // end switch( op )
|
||||
}
|
||||
catch (DWORD nErrCode)
|
||||
catch (uint32_t nErrCode)
|
||||
{
|
||||
DisplayError(nErrCode);
|
||||
result = rat;
|
||||
|
@ -215,9 +215,9 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
|
|||
}
|
||||
|
||||
/* Routine to display error messages and set m_bError flag. Errors are */
|
||||
/* called with DisplayError (n), where n is a DWORD between 0 and 5. */
|
||||
/* called with DisplayError (n), where n is a uint32_t between 0 and 5. */
|
||||
|
||||
void CCalcEngine::DisplayError(DWORD nError)
|
||||
void CCalcEngine::DisplayError(uint32_t nError)
|
||||
{
|
||||
wstring errorString{ GetString(IDS_ERRORS_FIRST + SCODE_CODE(nError)) };
|
||||
|
||||
|
|
|
@ -133,7 +133,7 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa
|
|||
break;
|
||||
}
|
||||
}
|
||||
catch (DWORD dwErrCode)
|
||||
catch (uint32_t dwErrCode)
|
||||
{
|
||||
DisplayError(dwErrCode);
|
||||
|
||||
|
|
|
@ -6,15 +6,16 @@
|
|||
|
||||
using namespace CalcEngine;
|
||||
using namespace CalcEngine::RationalMath;
|
||||
using namespace std;
|
||||
|
||||
// To be called when either the radix or num width changes. You can use -1 in either of these values to mean
|
||||
// dont change that.
|
||||
void CCalcEngine::SetRadixTypeAndNumWidth(RADIX_TYPE radixtype, NUM_WIDTH numwidth)
|
||||
{
|
||||
// When in integer mode, the number is represented in 2's complement form. When a bit width is changing, we can
|
||||
// change the number representation back to sign, abs num form in ratpak. Soon when display sees this, it will
|
||||
// convert to 2's complement form, but this time all high bits will be propagated. Eg. -127, in byte mode is
|
||||
// represented as 1000,0001. This puts it back as sign=-1, 01111111 . But DisplayNum will see this and convert it
|
||||
// When in integer mode, the number is represented in 2's complement form. When a bit width is changing, we can
|
||||
// change the number representation back to sign, abs num form in ratpak. Soon when display sees this, it will
|
||||
// convert to 2's complement form, but this time all high bits will be propagated. Eg. -127, in byte mode is
|
||||
// represented as 1000,0001. This puts it back as sign=-1, 01111111 . But DisplayNum will see this and convert it
|
||||
// back to 1111,1111,1000,0001 when in Word mode.
|
||||
if (m_fIntegerMode)
|
||||
{
|
||||
|
@ -45,17 +46,17 @@ void CCalcEngine::SetRadixTypeAndNumWidth(RADIX_TYPE radixtype, NUM_WIDTH numwid
|
|||
// inform ratpak that a change in base or precision has occurred
|
||||
BaseOrPrecisionChanged();
|
||||
|
||||
// display the correct number for the new state (ie convert displayed
|
||||
// display the correct number for the new state (ie convert displayed
|
||||
// number to correct base)
|
||||
DisplayNum();
|
||||
}
|
||||
|
||||
LONG CCalcEngine::DwWordBitWidthFromeNumWidth(NUM_WIDTH /*numwidth*/)
|
||||
int32_t CCalcEngine::DwWordBitWidthFromeNumWidth(NUM_WIDTH /*numwidth*/)
|
||||
{
|
||||
static constexpr int nBitMax[] = { 64, 32, 16, 8 };
|
||||
LONG wmax = nBitMax[0];
|
||||
int32_t wmax = nBitMax[0];
|
||||
|
||||
if (m_numwidth >= 0 && m_numwidth < ARRAYSIZE(nBitMax))
|
||||
if (m_numwidth >= 0 && (size_t)m_numwidth < size(nBitMax))
|
||||
{
|
||||
wmax = nBitMax[m_numwidth];
|
||||
}
|
||||
|
@ -68,7 +69,7 @@ uint32_t CCalcEngine::NRadixFromRadixType(RADIX_TYPE radixtype)
|
|||
uint32_t radix = 10;
|
||||
|
||||
// convert special bases into symbolic values
|
||||
if (radixtype >= 0 && radixtype < ARRAYSIZE(rgnRadish))
|
||||
if (radixtype >= 0 && (size_t)radixtype < size(rgnRadish))
|
||||
{
|
||||
radix = rgnRadish[radixtype];
|
||||
}
|
||||
|
@ -76,9 +77,9 @@ uint32_t CCalcEngine::NRadixFromRadixType(RADIX_TYPE radixtype)
|
|||
}
|
||||
|
||||
// Toggles a given bit into the number representation. returns true if it changed it actually.
|
||||
bool CCalcEngine::TryToggleBit(CalcEngine::Rational& rat, DWORD wbitno)
|
||||
bool CCalcEngine::TryToggleBit(CalcEngine::Rational& rat, uint32_t wbitno)
|
||||
{
|
||||
DWORD wmax = DwWordBitWidthFromeNumWidth(m_numwidth);
|
||||
uint32_t wmax = DwWordBitWidthFromeNumWidth(m_numwidth);
|
||||
if (wbitno >= wmax)
|
||||
{
|
||||
return false; // ignore error cant happen
|
||||
|
@ -142,7 +143,7 @@ void CCalcEngine::UpdateMaxIntDigits()
|
|||
if (m_fIntegerMode)
|
||||
{
|
||||
m_cIntDigitsSav = static_cast<int>(m_maxDecimalValueStrings[m_numwidth].length()) - 1;
|
||||
// This is the max digits you can enter a decimal in fixed width mode aka integer mode -1. The last digit
|
||||
// This is the max digits you can enter a decimal in fixed width mode aka integer mode -1. The last digit
|
||||
// has to be checked separately
|
||||
}
|
||||
else
|
||||
|
@ -160,10 +161,10 @@ void CCalcEngine::ChangeBaseConstants(uint32_t radix, int maxIntDigits, int32_t
|
|||
{
|
||||
if (10 == radix)
|
||||
{
|
||||
ChangeConstants(radix, precision); // Base 10 precision for internal computing still needs to be 32, to
|
||||
ChangeConstants(radix, precision); // Base 10 precision for internal computing still needs to be 32, to
|
||||
// take care of decimals precisely. For eg. to get the HI word of a qword, we do a rsh, which depends on getting
|
||||
// 18446744073709551615 / 4294967296 = 4294967295.9999917... This is important it works this and doesn't reduce
|
||||
// the precision to number of digits allowed to enter. In other words, precision and # of allowed digits to be
|
||||
// 18446744073709551615 / 4294967296 = 4294967295.9999917... This is important it works this and doesn't reduce
|
||||
// the precision to number of digits allowed to enter. In other words, precision and # of allowed digits to be
|
||||
// entered are different.
|
||||
}
|
||||
else
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
class CalcException : public std::exception
|
||||
{
|
||||
public:
|
||||
CalcException(HRESULT hr)
|
||||
{
|
||||
m_hr = hr;
|
||||
}
|
||||
HRESULT GetException()
|
||||
{
|
||||
return m_hr;
|
||||
}
|
||||
private:
|
||||
HRESULT m_hr;
|
||||
};
|
||||
|
||||
void IFT(HRESULT hr)
|
||||
{
|
||||
if (FAILED(hr))
|
||||
{
|
||||
CalcException exception(hr);
|
||||
throw(exception);
|
||||
}
|
||||
}
|
|
@ -119,7 +119,6 @@
|
|||
<ClInclude Include="Ratpack\ratpak.h">
|
||||
<Filter>RatPack</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CalcException.h" />
|
||||
<ClInclude Include="CalculatorVector.h" />
|
||||
<ClInclude Include="Header Files\CalcEngine.h">
|
||||
<Filter>Header Files</Filter>
|
||||
|
@ -162,4 +161,4 @@
|
|||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
@ -7,8 +7,7 @@
|
|||
using namespace std;
|
||||
using namespace CalculationManager;
|
||||
|
||||
CalculatorHistory::CalculatorHistory(CALCULATOR_MODE eMode, size_t maxSize) :
|
||||
m_mode(eMode),
|
||||
CalculatorHistory::CalculatorHistory(size_t maxSize) :
|
||||
m_maxHistorySize(maxSize)
|
||||
{}
|
||||
|
||||
|
@ -23,7 +22,7 @@ unsigned int CalculatorHistory::AddToHistory(_In_ shared_ptr<CalculatorVector <p
|
|||
|
||||
// to be changed when pszexp is back
|
||||
tokens->GetString(&generatedExpression);
|
||||
// Prefixing and suffixing the special Unicode markers to ensure that the expression
|
||||
// Prefixing and suffixing the special Unicode markers to ensure that the expression
|
||||
// in the history doesn't get broken for RTL languages
|
||||
spHistoryItem->historyItemVector.expression = L'\u202d' + generatedExpression + L'\u202c';
|
||||
spHistoryItem->historyItemVector.result = wstring(result);
|
||||
|
@ -35,15 +34,13 @@ unsigned int CalculatorHistory::AddToHistory(_In_ shared_ptr<CalculatorVector <p
|
|||
|
||||
unsigned int CalculatorHistory::AddItem(_In_ shared_ptr<HISTORYITEM> const &spHistoryItem)
|
||||
{
|
||||
int lastIndex;
|
||||
|
||||
if (m_historyItems.size() >= m_maxHistorySize)
|
||||
{
|
||||
m_historyItems.erase(m_historyItems.begin());
|
||||
}
|
||||
|
||||
m_historyItems.push_back(spHistoryItem);
|
||||
lastIndex = static_cast<unsigned>(m_historyItems.size() - 1);
|
||||
unsigned int lastIndex = static_cast<unsigned>(m_historyItems.size() - 1);
|
||||
return lastIndex;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace CalculationManager
|
|||
{
|
||||
|
||||
public:
|
||||
CalculatorHistory(CALCULATOR_MODE eMode, 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);
|
||||
std::vector<std::shared_ptr<HISTORYITEM>> const& GetHistory();
|
||||
std::shared_ptr<HISTORYITEM> const& GetHistoryItem(unsigned int uIdx);
|
||||
|
@ -43,7 +43,6 @@ namespace CalculationManager
|
|||
|
||||
private:
|
||||
std::vector<std::shared_ptr<HISTORYITEM>> m_historyItems;
|
||||
CALCULATOR_MODE m_mode;
|
||||
const size_t m_maxHistorySize;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
|
@ -24,15 +24,15 @@ namespace CalculationManager
|
|||
{
|
||||
CalculatorManager::CalculatorManager(_In_ ICalcDisplay* displayCallback, _In_ IResourceProvider* resourceProvider) :
|
||||
m_displayCallback(displayCallback),
|
||||
m_currentCalculatorEngine(nullptr),
|
||||
m_resourceProvider(resourceProvider),
|
||||
m_inHistoryItemLoadMode(false),
|
||||
m_persistedPrimaryValue(),
|
||||
m_isExponentialFormat(false),
|
||||
m_currentDegreeMode(Command::CommandNULL),
|
||||
m_savedDegreeMode(Command::CommandDEG),
|
||||
m_isExponentialFormat(false),
|
||||
m_persistedPrimaryValue(),
|
||||
m_currentCalculatorEngine(nullptr),
|
||||
m_pStdHistory(new CalculatorHistory(CM_STD, MAX_HISTORY_ITEMS)),
|
||||
m_pSciHistory(new CalculatorHistory(CM_SCI, MAX_HISTORY_ITEMS)),
|
||||
m_inHistoryItemLoadMode(false)
|
||||
m_pStdHistory(new CalculatorHistory(MAX_HISTORY_ITEMS)),
|
||||
m_pSciHistory(new CalculatorHistory(MAX_HISTORY_ITEMS))
|
||||
{
|
||||
CCalcEngine::InitialOneTimeOnlySetup(*m_resourceProvider);
|
||||
}
|
||||
|
@ -109,7 +109,6 @@ namespace CalculationManager
|
|||
|
||||
/// <summary>
|
||||
/// Callback from the engine
|
||||
/// Used to set the current unmatched open parenthesis count
|
||||
/// </summary>
|
||||
/// <param name="parenthesisCount">string containing the parenthesis count</param>
|
||||
void CalculatorManager::SetParenDisplayText(const wstring& parenthesisCount)
|
||||
|
@ -117,6 +116,14 @@ namespace CalculationManager
|
|||
m_displayCallback->SetParenDisplayText(parenthesisCount);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback from the engine
|
||||
/// </summary>
|
||||
void CalculatorManager::OnNoRightParenAdded()
|
||||
{
|
||||
m_displayCallback->OnNoRightParenAdded();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reset CalculatorManager.
|
||||
/// Set the mode to the standard calculator
|
||||
|
@ -205,7 +212,7 @@ namespace CalculationManager
|
|||
|
||||
/// <summary>
|
||||
/// Send command to the Calc Engine
|
||||
/// Cast Command Enum to WPARAM.
|
||||
/// Cast Command Enum to OpCode.
|
||||
/// Handle special commands such as mode change and combination of two commands.
|
||||
/// </summary>
|
||||
/// <param name="command">Enum Command</command>
|
||||
|
@ -228,7 +235,7 @@ namespace CalculationManager
|
|||
this->SetProgrammerMode();
|
||||
break;
|
||||
default:
|
||||
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(command));
|
||||
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(command));
|
||||
}
|
||||
|
||||
m_savedCommands.clear(); // Clear the previous command history
|
||||
|
@ -256,44 +263,44 @@ namespace CalculationManager
|
|||
switch (command)
|
||||
{
|
||||
case Command::CommandASIN:
|
||||
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(Command::CommandINV));
|
||||
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(Command::CommandSIN));
|
||||
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandINV));
|
||||
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandSIN));
|
||||
break;
|
||||
case Command::CommandACOS:
|
||||
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(Command::CommandINV));
|
||||
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(Command::CommandCOS));
|
||||
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandINV));
|
||||
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandCOS));
|
||||
break;
|
||||
case Command::CommandATAN:
|
||||
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(Command::CommandINV));
|
||||
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(Command::CommandTAN));
|
||||
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandINV));
|
||||
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandTAN));
|
||||
break;
|
||||
case Command::CommandPOWE:
|
||||
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(Command::CommandINV));
|
||||
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(Command::CommandLN));
|
||||
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandINV));
|
||||
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandLN));
|
||||
break;
|
||||
case Command::CommandASINH:
|
||||
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(Command::CommandINV));
|
||||
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(Command::CommandSINH));
|
||||
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandINV));
|
||||
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandSINH));
|
||||
break;
|
||||
case Command::CommandACOSH:
|
||||
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(Command::CommandINV));
|
||||
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(Command::CommandCOSH));
|
||||
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandINV));
|
||||
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandCOSH));
|
||||
break;
|
||||
case Command::CommandATANH:
|
||||
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(Command::CommandINV));
|
||||
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(Command::CommandTANH));
|
||||
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandINV));
|
||||
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandTANH));
|
||||
break;
|
||||
case Command::CommandFE:
|
||||
m_isExponentialFormat = !m_isExponentialFormat;
|
||||
// fall through
|
||||
[[fallthrough]];
|
||||
default:
|
||||
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(command));
|
||||
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(command));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert Command to unsigned char.
|
||||
/// Convert Command to unsigned char.
|
||||
/// Since some Commands are higher than 255, they are saved after subtracting 255
|
||||
/// The smallest Command is CommandSIGN = 80, thus, subtracted value does not overlap with other values.
|
||||
/// </summary>
|
||||
|
@ -301,7 +308,10 @@ namespace CalculationManager
|
|||
unsigned char CalculatorManager::MapCommandForSerialize(Command command)
|
||||
{
|
||||
unsigned int commandToSave = static_cast<unsigned int>(command);
|
||||
commandToSave > UCHAR_MAX ? commandToSave -= UCHAR_MAX : commandToSave;
|
||||
if (commandToSave > UCHAR_MAX)
|
||||
{
|
||||
commandToSave -= UCHAR_MAX;
|
||||
}
|
||||
return static_cast<unsigned char>(commandToSave);
|
||||
}
|
||||
|
||||
|
@ -353,7 +363,7 @@ namespace CalculationManager
|
|||
/// <param name = "serializedPrimaryDisplay">Serialized Rational of primary display</param>
|
||||
void CalculatorManager::DeSerializePrimaryDisplay(const vector<long> &serializedPrimaryDisplay)
|
||||
{
|
||||
if (serializedPrimaryDisplay.size() == 0)
|
||||
if (serializedPrimaryDisplay.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -428,9 +438,9 @@ namespace CalculationManager
|
|||
if (*commandItr >= MEMORY_COMMAND_TO_UNSIGNED_CHAR(MemoryCommand::MemorizeNumber) &&
|
||||
*commandItr <= MEMORY_COMMAND_TO_UNSIGNED_CHAR(MemoryCommand::MemorizedNumberClearAll))
|
||||
{
|
||||
//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.
|
||||
//Hence, a simple cast to MemoryCommand is not sufficient.
|
||||
// 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.
|
||||
// Hence, a simple cast to MemoryCommand is not sufficient.
|
||||
MemoryCommand memoryCommand = static_cast<MemoryCommand>(*commandItr + UCHAR_MAX + 1);
|
||||
unsigned int indexOfMemory = 0;
|
||||
switch (memoryCommand)
|
||||
|
@ -483,22 +493,25 @@ namespace CalculationManager
|
|||
void CalculatorManager::MemorizeNumber()
|
||||
{
|
||||
m_savedCommands.push_back(MEMORY_COMMAND_TO_UNSIGNED_CHAR(MemoryCommand::MemorizeNumber));
|
||||
if (!(m_currentCalculatorEngine->FInErrorState()))
|
||||
|
||||
if (m_currentCalculatorEngine->FInErrorState())
|
||||
{
|
||||
m_currentCalculatorEngine->ProcessCommand(IDC_STORE);
|
||||
|
||||
auto memoryObjectPtr = m_currentCalculatorEngine->PersistedMemObject();
|
||||
if (memoryObjectPtr != nullptr)
|
||||
{
|
||||
m_memorizedNumbers.insert(m_memorizedNumbers.begin(), *memoryObjectPtr);
|
||||
}
|
||||
|
||||
if (m_memorizedNumbers.size() > m_maximumMemorySize)
|
||||
{
|
||||
m_memorizedNumbers.resize(m_maximumMemorySize);
|
||||
}
|
||||
this->SetMemorizedNumbersString();
|
||||
return;
|
||||
}
|
||||
|
||||
m_currentCalculatorEngine->ProcessCommand(IDC_STORE);
|
||||
|
||||
auto memoryObjectPtr = m_currentCalculatorEngine->PersistedMemObject();
|
||||
if (memoryObjectPtr != nullptr)
|
||||
{
|
||||
m_memorizedNumbers.insert(m_memorizedNumbers.begin(), *memoryObjectPtr);
|
||||
}
|
||||
|
||||
if (m_memorizedNumbers.size() > m_maximumMemorySize)
|
||||
{
|
||||
m_memorizedNumbers.resize(m_maximumMemorySize);
|
||||
}
|
||||
this->SetMemorizedNumbersString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -509,11 +522,14 @@ namespace CalculationManager
|
|||
void CalculatorManager::MemorizedNumberLoad(_In_ unsigned int indexOfMemory)
|
||||
{
|
||||
SaveMemoryCommand(MemoryCommand::MemorizedNumberLoad, indexOfMemory);
|
||||
if (!(m_currentCalculatorEngine->FInErrorState()))
|
||||
|
||||
if (m_currentCalculatorEngine->FInErrorState())
|
||||
{
|
||||
this->MemorizedNumberSelect(indexOfMemory);
|
||||
m_currentCalculatorEngine->ProcessCommand(IDC_RECALL);
|
||||
return;
|
||||
}
|
||||
|
||||
this->MemorizedNumberSelect(indexOfMemory);
|
||||
m_currentCalculatorEngine->ProcessCommand(IDC_RECALL);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -525,24 +541,27 @@ namespace CalculationManager
|
|||
void CalculatorManager::MemorizedNumberAdd(_In_ unsigned int indexOfMemory)
|
||||
{
|
||||
SaveMemoryCommand(MemoryCommand::MemorizedNumberAdd, indexOfMemory);
|
||||
if (!(m_currentCalculatorEngine->FInErrorState()))
|
||||
|
||||
if (m_currentCalculatorEngine->FInErrorState())
|
||||
{
|
||||
if (m_memorizedNumbers.empty())
|
||||
{
|
||||
this->MemorizeNumber();
|
||||
}
|
||||
else
|
||||
{
|
||||
this->MemorizedNumberSelect(indexOfMemory);
|
||||
m_currentCalculatorEngine->ProcessCommand(IDC_MPLUS);
|
||||
|
||||
this->MemorizedNumberChanged(indexOfMemory);
|
||||
|
||||
this->SetMemorizedNumbersString();
|
||||
}
|
||||
|
||||
m_displayCallback->MemoryItemChanged(indexOfMemory);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_memorizedNumbers.empty())
|
||||
{
|
||||
this->MemorizeNumber();
|
||||
}
|
||||
else
|
||||
{
|
||||
this->MemorizedNumberSelect(indexOfMemory);
|
||||
m_currentCalculatorEngine->ProcessCommand(IDC_MPLUS);
|
||||
|
||||
this->MemorizedNumberChanged(indexOfMemory);
|
||||
|
||||
this->SetMemorizedNumbersString();
|
||||
}
|
||||
|
||||
m_displayCallback->MemoryItemChanged(indexOfMemory);
|
||||
}
|
||||
|
||||
void CalculatorManager::MemorizedNumberClear(_In_ unsigned int indexOfMemory)
|
||||
|
@ -563,27 +582,30 @@ namespace CalculationManager
|
|||
void CalculatorManager::MemorizedNumberSubtract(_In_ unsigned int indexOfMemory)
|
||||
{
|
||||
SaveMemoryCommand(MemoryCommand::MemorizedNumberSubtract, indexOfMemory);
|
||||
if (!(m_currentCalculatorEngine->FInErrorState()))
|
||||
|
||||
if (m_currentCalculatorEngine->FInErrorState())
|
||||
{
|
||||
// To add negative of the number on display to the memory -x = x - 2x
|
||||
if (m_memorizedNumbers.empty())
|
||||
{
|
||||
this->MemorizeNumber();
|
||||
this->MemorizedNumberSubtract(0);
|
||||
this->MemorizedNumberSubtract(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->MemorizedNumberSelect(indexOfMemory);
|
||||
m_currentCalculatorEngine->ProcessCommand(IDC_MMINUS);
|
||||
|
||||
this->MemorizedNumberChanged(indexOfMemory);
|
||||
|
||||
this->SetMemorizedNumbersString();
|
||||
}
|
||||
|
||||
m_displayCallback->MemoryItemChanged(indexOfMemory);
|
||||
return;
|
||||
}
|
||||
|
||||
// To add negative of the number on display to the memory -x = x - 2x
|
||||
if (m_memorizedNumbers.empty())
|
||||
{
|
||||
this->MemorizeNumber();
|
||||
this->MemorizedNumberSubtract(0);
|
||||
this->MemorizedNumberSubtract(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->MemorizedNumberSelect(indexOfMemory);
|
||||
m_currentCalculatorEngine->ProcessCommand(IDC_MMINUS);
|
||||
|
||||
this->MemorizedNumberChanged(indexOfMemory);
|
||||
|
||||
this->SetMemorizedNumbersString();
|
||||
}
|
||||
|
||||
m_displayCallback->MemoryItemChanged(indexOfMemory);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -606,11 +628,13 @@ namespace CalculationManager
|
|||
/// <param name="indexOfMemory">Index of the target memory</param>
|
||||
void CalculatorManager::MemorizedNumberSelect(_In_ unsigned int indexOfMemory)
|
||||
{
|
||||
if (!(m_currentCalculatorEngine->FInErrorState()))
|
||||
if (m_currentCalculatorEngine->FInErrorState())
|
||||
{
|
||||
auto memoryObject = m_memorizedNumbers.at(indexOfMemory);
|
||||
m_currentCalculatorEngine->PersistedMemObject(memoryObject);
|
||||
return;
|
||||
}
|
||||
|
||||
auto memoryObject = m_memorizedNumbers.at(indexOfMemory);
|
||||
m_currentCalculatorEngine->PersistedMemObject(memoryObject);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -620,13 +644,15 @@ namespace CalculationManager
|
|||
/// <param name="indexOfMemory">Index of the target memory</param>
|
||||
void CalculatorManager::MemorizedNumberChanged(_In_ unsigned int indexOfMemory)
|
||||
{
|
||||
if (!(m_currentCalculatorEngine->FInErrorState()))
|
||||
if (m_currentCalculatorEngine->FInErrorState())
|
||||
{
|
||||
auto memoryObject = m_currentCalculatorEngine->PersistedMemObject();
|
||||
if (memoryObject != nullptr)
|
||||
{
|
||||
m_memorizedNumbers.at(indexOfMemory) = *memoryObject;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
auto memoryObject = m_currentCalculatorEngine->PersistedMemObject();
|
||||
if (memoryObject != nullptr)
|
||||
{
|
||||
m_memorizedNumbers.at(indexOfMemory) = *memoryObject;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -754,7 +780,7 @@ namespace CalculationManager
|
|||
}
|
||||
|
||||
void CalculatorManager::UpdateMaxIntDigits()
|
||||
{
|
||||
{
|
||||
m_currentCalculatorEngine->UpdateMaxIntDigits();
|
||||
}
|
||||
|
||||
|
@ -778,7 +804,7 @@ namespace CalculationManager
|
|||
/// How Rational is serialized :
|
||||
/// Serialized Rational.P(Number) + Serialized Rational.Q(Number)
|
||||
/// How Number is saved :
|
||||
/// [0] = Rational.P.Sign
|
||||
/// [0] = Rational.P.Sign
|
||||
/// [1] = Rational.P.Mantissa.size
|
||||
/// [2] = Rational.P.Exp
|
||||
/// [3] = Rational.P.Mantissa[0]
|
||||
|
@ -816,7 +842,7 @@ namespace CalculationManager
|
|||
/// <summary>
|
||||
/// Serialize Number to vector of long
|
||||
/// How Number is saved :
|
||||
/// [0] = Number.Sign
|
||||
/// [0] = Number.Sign
|
||||
/// [1] = Number.Mantissa.size
|
||||
/// [2] = Number.Exp
|
||||
/// [3] = Number.Mantissa[0]
|
||||
|
@ -843,7 +869,7 @@ namespace CalculationManager
|
|||
/// <summary>
|
||||
/// DeserializeNumber vector and construct a Number
|
||||
/// How Number is saved :
|
||||
/// [0] = Number.Sign
|
||||
/// [0] = Number.Sign
|
||||
/// [1] = Number.Mantissa.size
|
||||
/// [2] = Number.Exp
|
||||
/// [3] = Number.Mantissa[0]
|
||||
|
|
|
@ -27,9 +27,9 @@ namespace CalculationManager
|
|||
ProgrammerModePrecision = 64
|
||||
};
|
||||
|
||||
// Numbering continues from the Enum Command from Command.h
|
||||
// Numbering continues from the Enum Command from Command.h
|
||||
// with some gap to ensure there is no overlap of these ids
|
||||
// when static_cast<unsigned char> is performed on these ids
|
||||
// when static_cast<unsigned char> is performed on these ids
|
||||
// they shouldn't fall in any number range greater than 80. So never
|
||||
// make the memory command ids go below 330
|
||||
enum class MemoryCommand
|
||||
|
@ -42,7 +42,7 @@ namespace CalculationManager
|
|||
MemorizedNumberClear = 335
|
||||
};
|
||||
|
||||
class CalculatorManager sealed : public virtual ICalcDisplay
|
||||
class CalculatorManager final : public ICalcDisplay
|
||||
{
|
||||
private:
|
||||
ICalcDisplay* const m_displayCallback;
|
||||
|
@ -94,7 +94,8 @@ namespace CalculationManager
|
|||
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 OnHistoryItemAdded(_In_ unsigned int addedItemIndex) override;
|
||||
void SetParenDisplayText(const std::wstring& parenthesisCount);
|
||||
void SetParenDisplayText(const std::wstring& parenthesisCount) override;
|
||||
void OnNoRightParenAdded() override;
|
||||
void DisplayPasteError();
|
||||
void MaxDigitsReached() override;
|
||||
void BinaryOperatorReceived() override;
|
||||
|
@ -140,7 +141,7 @@ namespace CalculationManager
|
|||
std::shared_ptr<HISTORYITEM> const& GetHistoryItem(_In_ unsigned int uIdx);
|
||||
bool RemoveHistoryItem(_In_ unsigned int uIdx);
|
||||
void ClearHistory();
|
||||
const size_t MaxHistorySize() const { return m_pHistory->MaxHistorySize(); }
|
||||
size_t MaxHistorySize() const { return m_pHistory->MaxHistorySize(); }
|
||||
CalculationManager::Command GetCurrentDegreeMode();
|
||||
void SetHistory(_In_ CALCULATOR_MODE eMode, _In_ std::vector<std::shared_ptr<HISTORYITEM>> const& history);
|
||||
void SetInHistoryItemLoadMode(_In_ bool isHistoryItemLoadMode);
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace CalculationManager
|
|||
public:
|
||||
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
|
||||
// and the ids to define them with can be seen in EngineStrings.h
|
||||
// with SIDS prefix. Additionally it must provide values for string
|
||||
|
|
|
@ -3,13 +3,15 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "Ratpack/CalcErr.h"
|
||||
|
||||
template <typename TType>
|
||||
class CalculatorVector
|
||||
class CalculatorVector
|
||||
{
|
||||
public:
|
||||
HRESULT GetAt(_In_opt_ unsigned int index, _Out_ TType *item)
|
||||
ResultCode GetAt(_In_opt_ unsigned int index, _Out_ TType *item)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
ResultCode hr = S_OK;
|
||||
try
|
||||
{
|
||||
*item = m_vector.at(index);
|
||||
|
@ -21,15 +23,15 @@ public:
|
|||
return hr;
|
||||
}
|
||||
|
||||
HRESULT GetSize(_Out_ unsigned int *size)
|
||||
ResultCode GetSize(_Out_ unsigned int *size)
|
||||
{
|
||||
*size = static_cast<unsigned>(m_vector.size());
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT SetAt(_In_ unsigned int index, _In_opt_ TType item)
|
||||
ResultCode SetAt(_In_ unsigned int index, _In_opt_ TType item)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
ResultCode hr = S_OK;
|
||||
try
|
||||
{
|
||||
m_vector[index] = item;
|
||||
|
@ -41,9 +43,9 @@ public:
|
|||
return hr;
|
||||
}
|
||||
|
||||
HRESULT RemoveAt(_In_ unsigned int index)
|
||||
ResultCode RemoveAt(_In_ unsigned int index)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
ResultCode hr = S_OK;
|
||||
if (index < m_vector.size())
|
||||
{
|
||||
m_vector.erase(m_vector.begin() + index);
|
||||
|
@ -55,9 +57,9 @@ public:
|
|||
return hr;
|
||||
}
|
||||
|
||||
HRESULT InsertAt(_In_ unsigned int index, _In_ TType item)
|
||||
ResultCode InsertAt(_In_ unsigned int index, _In_ TType item)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
ResultCode hr = S_OK;
|
||||
try
|
||||
{
|
||||
auto iter = m_vector.begin() + index;
|
||||
|
@ -70,9 +72,9 @@ public:
|
|||
return hr;
|
||||
}
|
||||
|
||||
HRESULT Truncate(_In_ unsigned int index)
|
||||
ResultCode Truncate(_In_ unsigned int index)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
ResultCode hr = S_OK;
|
||||
if (index < m_vector.size())
|
||||
{
|
||||
auto startIter = m_vector.begin() + index;
|
||||
|
@ -85,9 +87,9 @@ public:
|
|||
return hr;
|
||||
}
|
||||
|
||||
HRESULT Append(_In_opt_ TType item)
|
||||
ResultCode Append(_In_opt_ TType item)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
ResultCode hr = S_OK;
|
||||
try
|
||||
{
|
||||
m_vector.push_back(item);
|
||||
|
@ -99,21 +101,21 @@ public:
|
|||
return hr;
|
||||
}
|
||||
|
||||
HRESULT RemoveAtEnd()
|
||||
ResultCode RemoveAtEnd()
|
||||
{
|
||||
m_vector.erase(--(m_vector.end()));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT Clear()
|
||||
ResultCode Clear()
|
||||
{
|
||||
m_vector.clear();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT GetString(_Out_ std::wstring* expression)
|
||||
ResultCode GetString(_Out_ std::wstring* expression)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
ResultCode hr = S_OK;
|
||||
unsigned int nTokens = 0;
|
||||
std::pair <std::wstring, int> currentPair;
|
||||
hr = this->GetSize(&nTokens);
|
||||
|
@ -144,7 +146,7 @@ public:
|
|||
return hr;
|
||||
}
|
||||
|
||||
HRESULT GetExpressionSuffix(_Out_ std::wstring* suffix)
|
||||
ResultCode GetExpressionSuffix(_Out_ std::wstring* suffix)
|
||||
{
|
||||
*suffix = L" =";
|
||||
return S_OK;
|
||||
|
|
|
@ -94,7 +94,7 @@ namespace CalculationManager
|
|||
CommandFAC = 113,
|
||||
CommandREC = 114,
|
||||
CommandDMS = 115,
|
||||
CommandCUBEROOT = 116, //x ^ 1/3
|
||||
CommandCUBEROOT = 116, // x ^ 1/3
|
||||
CommandPOW10 = 117, // 10 ^ x
|
||||
CommandPERCENT = 118,
|
||||
|
||||
|
|
|
@ -75,19 +75,19 @@ void CUnaryCommand::Accept(_In_ ISerializeCommandVisitor &commandVisitor)
|
|||
CBinaryCommand::CBinaryCommand(int command) :m_command(command)
|
||||
{}
|
||||
|
||||
void CBinaryCommand::SetCommand(int command)
|
||||
{
|
||||
m_command = command;
|
||||
void CBinaryCommand::SetCommand(int command)
|
||||
{
|
||||
m_command = command;
|
||||
}
|
||||
|
||||
int CBinaryCommand::GetCommand() const
|
||||
{
|
||||
return m_command;
|
||||
{
|
||||
return m_command;
|
||||
}
|
||||
|
||||
CalculationManager::CommandType CBinaryCommand::GetCommandType() const
|
||||
{
|
||||
return CalculationManager::CommandType::BinaryCommand;
|
||||
{
|
||||
return CalculationManager::CommandType::BinaryCommand;
|
||||
}
|
||||
|
||||
void CBinaryCommand::Accept(_In_ ISerializeCommandVisitor &commandVisitor)
|
||||
|
@ -98,8 +98,8 @@ void CBinaryCommand::Accept(_In_ ISerializeCommandVisitor &commandVisitor)
|
|||
COpndCommand::COpndCommand(shared_ptr<CalculatorVector<int>> const &commands, bool fNegative, bool fDecimal, bool fSciFmt) :
|
||||
m_commands(commands),
|
||||
m_fNegative(fNegative),
|
||||
m_fDecimal(fDecimal),
|
||||
m_fSciFmt(fSciFmt),
|
||||
m_fDecimal(fDecimal),
|
||||
m_fInitialized(false),
|
||||
m_value{}
|
||||
{}
|
||||
|
@ -111,8 +111,8 @@ void COpndCommand::Initialize(Rational const& rat)
|
|||
}
|
||||
|
||||
const shared_ptr<CalculatorVector<int>> & COpndCommand::GetCommands() const
|
||||
{
|
||||
return m_commands;
|
||||
{
|
||||
return m_commands;
|
||||
}
|
||||
|
||||
void COpndCommand::SetCommands(shared_ptr<CalculatorVector<int>> const& commands)
|
||||
|
@ -166,7 +166,7 @@ void COpndCommand::RemoveFromEnd()
|
|||
{
|
||||
unsigned int nCommands;
|
||||
m_commands->GetSize(&nCommands);
|
||||
|
||||
|
||||
if (nCommands == 1)
|
||||
{
|
||||
ClearAllAndAppendCommand(CalculationManager::Command::Command0);
|
||||
|
@ -185,8 +185,8 @@ void COpndCommand::RemoveFromEnd()
|
|||
}
|
||||
|
||||
bool COpndCommand::IsNegative() const
|
||||
{
|
||||
return m_fNegative;
|
||||
{
|
||||
return m_fNegative;
|
||||
}
|
||||
|
||||
bool COpndCommand::IsSciFmt() const
|
||||
|
@ -195,13 +195,13 @@ bool COpndCommand::IsSciFmt() const
|
|||
}
|
||||
|
||||
bool COpndCommand::IsDecimalPresent() const
|
||||
{
|
||||
return m_fDecimal;
|
||||
{
|
||||
return m_fDecimal;
|
||||
}
|
||||
|
||||
CalculationManager::CommandType COpndCommand::GetCommandType() const
|
||||
{
|
||||
return CalculationManager::CommandType::OperandCommand;
|
||||
{
|
||||
return CalculationManager::CommandType::OperandCommand;
|
||||
}
|
||||
|
||||
void COpndCommand::ClearAllAndAppendCommand(CalculationManager::Command command)
|
||||
|
@ -283,7 +283,7 @@ const wstring & COpndCommand::GetToken(wchar_t decimalSymbol)
|
|||
m_token.clear();
|
||||
m_token.append(&chZero);
|
||||
}
|
||||
|
||||
|
||||
return m_token;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
|
||||
|
||||
// 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.
|
||||
// Also, the order of the controls must match the order of the control names
|
||||
// in the string table.
|
||||
|
@ -97,7 +97,7 @@
|
|||
#define IDC_FAC 113
|
||||
#define IDC_REC 114
|
||||
#define IDC_DMS 115
|
||||
#define IDC_CUBEROOT 116 //x ^ 1/3
|
||||
#define IDC_CUBEROOT 116 // x ^ 1/3
|
||||
#define IDC_POW10 117 // 10 ^ x
|
||||
#define IDC_PERCENT 118
|
||||
#define IDC_UNARYLAST IDC_PERCENT
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "RadixType.h"
|
||||
#include "History.h" // for History Collector
|
||||
#include "CalcInput.h"
|
||||
#include "CalcUtils.h"
|
||||
#include "ICalcDisplay.h"
|
||||
#include "Rational.h"
|
||||
#include "RationalMath.h"
|
||||
|
@ -52,8 +53,8 @@ namespace CalculatorUnitTests
|
|||
class CCalcEngine {
|
||||
public:
|
||||
CCalcEngine(bool fPrecedence, bool fIntegerMode, CalculationManager::IResourceProvider* const pResourceProvider, __in_opt ICalcDisplay *pCalcDisplay, __in_opt std::shared_ptr<IHistoryDisplay> pHistoryDisplay);
|
||||
void ProcessCommand(WPARAM wID);
|
||||
void DisplayError (DWORD nError);
|
||||
void ProcessCommand(OpCode wID);
|
||||
void DisplayError (uint32_t nError);
|
||||
std::unique_ptr<CalcEngine::Rational> PersistedMemObject();
|
||||
void PersistedMemObject(CalcEngine::Rational const& memObject);
|
||||
bool FInErrorState() { return m_bError; }
|
||||
|
@ -85,7 +86,7 @@ private:
|
|||
// if it hasn't yet been computed
|
||||
bool m_bChangeOp; /* Flag for changing operation. */
|
||||
bool m_bRecord; // Global mode: recording or displaying
|
||||
bool m_bSetCalcState; //Flag for setting the engine result state
|
||||
bool m_bSetCalcState; // Flag for setting the engine result state
|
||||
CalcEngine::CalcInput m_input; // Global calc input object for decimal strings
|
||||
eNUMOBJ_FMT m_nFE; /* Scientific notation conversion flag. */
|
||||
CalcEngine::Rational m_maxTrigonometricNum;
|
||||
|
@ -116,7 +117,7 @@ private:
|
|||
int m_nLastCom; // Last command entered.
|
||||
ANGLE_TYPE m_angletype; // Current Angle type when in dec mode. one of deg, rad or grad
|
||||
NUM_WIDTH m_numwidth; // one of qword, dword, word or byte mode.
|
||||
LONG m_dwWordBitWidth; // # of bits in currently selected word size
|
||||
int32_t m_dwWordBitWidth; // # of bits in currently selected word size
|
||||
|
||||
CHistoryCollector m_HistoryCollector; // Accumulator of each line of history as various commands are processed
|
||||
|
||||
|
@ -127,8 +128,8 @@ private:
|
|||
wchar_t m_groupSeparator;
|
||||
|
||||
private:
|
||||
void ProcessCommandWorker(WPARAM wParam);
|
||||
void HandleErrorCommand(WPARAM idc);
|
||||
void ProcessCommandWorker(OpCode wParam);
|
||||
void HandleErrorCommand(OpCode idc);
|
||||
void HandleMaxDigitsReached();
|
||||
void DisplayNum(void);
|
||||
int IsNumberInvalid(const std::wstring& numberString, int iMaxExp, int iMaxMantissa, uint32_t radix) const;
|
||||
|
@ -136,13 +137,13 @@ private:
|
|||
void SetPrimaryDisplay(const std::wstring& szText, bool isError = false);
|
||||
void ClearTemporaryValues();
|
||||
CalcEngine::Rational TruncateNumForIntMath(CalcEngine::Rational const& rat);
|
||||
CalcEngine::Rational SciCalcFunctions(CalcEngine::Rational const& rat, DWORD op);
|
||||
CalcEngine::Rational SciCalcFunctions(CalcEngine::Rational const& rat, uint32_t op);
|
||||
CalcEngine::Rational DoOperation(int operation, CalcEngine::Rational const& lhs, CalcEngine::Rational const& rhs);
|
||||
void SetRadixTypeAndNumWidth(RADIX_TYPE radixtype, NUM_WIDTH numwidth);
|
||||
LONG DwWordBitWidthFromeNumWidth(NUM_WIDTH numwidth);
|
||||
int32_t DwWordBitWidthFromeNumWidth(NUM_WIDTH numwidth);
|
||||
uint32_t NRadixFromRadixType( RADIX_TYPE radixtype);
|
||||
|
||||
bool TryToggleBit(CalcEngine::Rational& rat, DWORD wbitno);
|
||||
bool TryToggleBit(CalcEngine::Rational& rat, uint32_t wbitno);
|
||||
void CheckAndAddLastBinOpToHistory(bool addToHistory = true);
|
||||
int IdcSetAngleTypeDecMode(int idc);
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include "Rational.h"
|
||||
|
||||
// Space to hold enough digits for a quadword binary number (64) plus digit separator strings for that number (20)
|
||||
constexpr int MAX_STRLEN = 84;
|
||||
constexpr int MAX_STRLEN = 84;
|
||||
|
||||
namespace CalcEngine
|
||||
{
|
||||
|
@ -47,7 +47,7 @@ namespace CalcEngine
|
|||
|
||||
void Clear();
|
||||
bool TryToggleSign(bool isIntegerMode, std::wstring_view maxNumStr);
|
||||
bool TryAddDigit(unsigned int value, uint32_t radix, bool isIntegerMode, std::wstring_view maxNumStr, long wordBitWidth, int maxDigits);
|
||||
bool TryAddDigit(unsigned int value, uint32_t radix, bool isIntegerMode, std::wstring_view maxNumStr, int32_t wordBitWidth, int maxDigits);
|
||||
bool TryAddDecimalPt();
|
||||
bool HasDecimalPt();
|
||||
bool TryBeginExponent();
|
||||
|
|
|
@ -3,11 +3,13 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
bool IsOpInRange(WPARAM op, uint32_t x, uint32_t y);
|
||||
bool IsBinOpCode(WPARAM opCode);
|
||||
using OpCode = uintptr_t;
|
||||
|
||||
bool IsOpInRange(OpCode op, uint32_t x, uint32_t y);
|
||||
bool IsBinOpCode(OpCode opCode);
|
||||
|
||||
// WARNING: IDC_SIGN is a special unary op but still this doesn't catch this. Caller has to be aware
|
||||
// of it and catch it themselves or not needing this
|
||||
bool IsUnaryOpCode(WPARAM opCode);
|
||||
bool IsDigitOpCode(WPARAM opCode);
|
||||
bool IsGuiSettingOpCode(WPARAM opCode);
|
||||
bool IsUnaryOpCode(OpCode opCode);
|
||||
bool IsDigitOpCode(OpCode opCode);
|
||||
bool IsGuiSettingOpCode(OpCode opCode);
|
||||
|
|
|
@ -128,7 +128,7 @@
|
|||
#define SIDS_NFACTORIAL L"33"
|
||||
#define SIDS_RECIPROCAL L"34"
|
||||
#define SIDS_DMS L"35"
|
||||
#define SIDS_CUBEROOT L"36"
|
||||
#define SIDS_CUBEROOT L"36"
|
||||
#define SIDS_POWTEN L"37"
|
||||
#define SIDS_PERCENT L"38"
|
||||
#define SIDS_SCIENTIFIC_NOTATION L"39"
|
||||
|
@ -200,7 +200,7 @@
|
|||
#define SIDS_NOMEM L"105"
|
||||
#define SIDS_TOOMANY L"106"
|
||||
#define SIDS_OVERFLOW L"107"
|
||||
#define SIDS_NORESULT L"108"
|
||||
#define SIDS_NORESULT L"108"
|
||||
#define SIDS_INSUFFICIENT_DATA L"109"
|
||||
// 110 is skipped by CSTRINGSENGMAX
|
||||
#define SIDS_ERR_UNK_CH L"111"
|
||||
|
@ -214,7 +214,7 @@
|
|||
#define SIDS_ERR_INPUT_OVERFLOW L"119"
|
||||
#define SIDS_ERR_OUTPUT_OVERFLOW L"120"
|
||||
|
||||
__declspec(selectany) std::wstring g_sids[] =
|
||||
__declspec(selectany) std::wstring g_sids[] =
|
||||
{
|
||||
std::wstring(SIDS_PLUS_MINUS),
|
||||
std::wstring(SIDS_C),
|
||||
|
@ -252,7 +252,7 @@ __declspec(selectany) std::wstring g_sids[] =
|
|||
std::wstring(SIDS_NFACTORIAL),
|
||||
std::wstring(SIDS_RECIPROCAL),
|
||||
std::wstring(SIDS_DMS),
|
||||
std::wstring(SIDS_CUBEROOT),
|
||||
std::wstring(SIDS_CUBEROOT),
|
||||
std::wstring(SIDS_POWTEN),
|
||||
std::wstring(SIDS_PERCENT),
|
||||
std::wstring(SIDS_SCIENTIFIC_NOTATION),
|
||||
|
@ -324,7 +324,7 @@ __declspec(selectany) std::wstring g_sids[] =
|
|||
std::wstring(SIDS_NOMEM),
|
||||
std::wstring(SIDS_TOOMANY),
|
||||
std::wstring(SIDS_OVERFLOW),
|
||||
std::wstring(SIDS_NORESULT),
|
||||
std::wstring(SIDS_NORESULT),
|
||||
std::wstring(SIDS_INSUFFICIENT_DATA),
|
||||
std::wstring(SIDS_ERR_UNK_CH),
|
||||
std::wstring(SIDS_ERR_UNK_FN),
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
// maximum depth you can get by precedence. It is just an array's size limit.
|
||||
static constexpr size_t MAXPRECDEPTH = 25;
|
||||
|
||||
// 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
|
||||
// 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
|
||||
// rely on CCalcEngine calling it in appropriate order.
|
||||
class CHistoryCollector {
|
||||
public:
|
||||
|
@ -39,13 +39,13 @@ private:
|
|||
ICalcDisplay *m_pCalcDisplay;
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
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;
|
||||
std::shared_ptr<CalculatorVector <std::pair<std::wstring, int>>> m_spTokens;
|
||||
std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> m_spCommands;
|
||||
|
|
|
@ -13,6 +13,7 @@ public:
|
|||
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 SetParenDisplayText(const std::wstring& pszText) = 0;
|
||||
virtual void OnNoRightParenAdded() = 0;
|
||||
virtual void MaxDigitsReached() = 0; // not an error but still need to inform UI layer.
|
||||
virtual void BinaryOperatorReceived() = 0;
|
||||
virtual void OnHistoryItemAdded(_In_ unsigned int addedItemIndex) = 0;
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
// CalcErr.h
|
||||
//
|
||||
// Defines the error codes thrown by ratpak and caught by Calculator
|
||||
|
@ -24,7 +26,7 @@
|
|||
// R - Reserved - not currently used for anything
|
||||
//
|
||||
// r - reserved portion of the facility code. Reserved for internal
|
||||
// use. Used to indicate HRESULT values that are not status
|
||||
// use. Used to indicate int32_t values that are not status
|
||||
// values, but are instead message ids for display strings.
|
||||
//
|
||||
// Facility - is the facility code
|
||||
|
@ -34,49 +36,51 @@
|
|||
// This format is based loosely on an OLE HRESULT and is compatible with the
|
||||
// SUCCEEDED and FAILED macros as well as the HRESULT_CODE macro
|
||||
|
||||
typedef int32_t ResultCode;
|
||||
|
||||
// CALC_E_DIVIDEBYZERO
|
||||
//
|
||||
// The current operation would require a divide by zero to complete
|
||||
#define CALC_E_DIVIDEBYZERO ((DWORD)0x80000000)
|
||||
#define CALC_E_DIVIDEBYZERO ((uint32_t)0x80000000)
|
||||
|
||||
// CALC_E_DOMAIN
|
||||
//
|
||||
// The given input is not within the domain of this function
|
||||
#define CALC_E_DOMAIN ((DWORD)0x80000001)
|
||||
#define CALC_E_DOMAIN ((uint32_t)0x80000001)
|
||||
|
||||
// CALC_E_INDEFINITE
|
||||
//
|
||||
// The result of this function is undefined
|
||||
#define CALC_E_INDEFINITE ((DWORD)0x80000002)
|
||||
#define CALC_E_INDEFINITE ((uint32_t)0x80000002)
|
||||
|
||||
// CALC_E_POSINFINITY
|
||||
//
|
||||
// The result of this function is Positive Infinity.
|
||||
#define CALC_E_POSINFINITY ((DWORD)0x80000003)
|
||||
#define CALC_E_POSINFINITY ((uint32_t)0x80000003)
|
||||
|
||||
// CALC_E_NEGINFINITY
|
||||
//
|
||||
// The result of this function is Negative Infinity
|
||||
#define CALC_E_NEGINFINITY ((DWORD)0x80000004)
|
||||
#define CALC_E_NEGINFINITY ((uint32_t)0x80000004)
|
||||
|
||||
// CALC_E_INVALIDRANGE
|
||||
//
|
||||
// The given input is within the domain of the function but is beyond
|
||||
// the range for which calc can successfully compute the answer
|
||||
#define CALC_E_INVALIDRANGE ((DWORD)0x80000006)
|
||||
#define CALC_E_INVALIDRANGE ((uint32_t)0x80000006)
|
||||
|
||||
// CALC_E_OUTOFMEMORY
|
||||
//
|
||||
// There is not enough free memory to complete the requested function
|
||||
#define CALC_E_OUTOFMEMORY ((DWORD)0x80000007)
|
||||
#define CALC_E_OUTOFMEMORY ((uint32_t)0x80000007)
|
||||
|
||||
// CALC_E_OVERFLOW
|
||||
//
|
||||
// The result of this operation is an overflow
|
||||
#define CALC_E_OVERFLOW ((DWORD)0x80000008)
|
||||
#define CALC_E_OVERFLOW ((uint32_t)0x80000008)
|
||||
|
||||
// CALC_E_NORESULT
|
||||
//
|
||||
// The result of this operation is undefined
|
||||
#define CALC_E_NORESULT ((DWORD)0x80000009)
|
||||
#define CALC_E_NORESULT ((uint32_t)0x80000009)
|
||||
|
||||
|
|
|
@ -2,17 +2,17 @@
|
|||
// Licensed under the MIT License.
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Package Title ratpak
|
||||
// File basex.c
|
||||
// Copyright (C) 1995-97 Microsoft
|
||||
// Date 03-14-97
|
||||
//
|
||||
//
|
||||
// Description
|
||||
//
|
||||
// Contains number routines for internal base computations, these assume
|
||||
// internal base is a power of 2.
|
||||
//
|
||||
// Package Title ratpak
|
||||
// File basex.c
|
||||
// Copyright (C) 1995-97 Microsoft
|
||||
// Date 03-14-97
|
||||
//
|
||||
//
|
||||
// Description
|
||||
//
|
||||
// Contains number routines for internal base computations, these assume
|
||||
// internal base is a power of 2.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "pch.h"
|
||||
#include "ratpak.h"
|
||||
|
@ -41,14 +41,14 @@ void __inline mulnumx( PNUMBER *pa, PNUMBER b )
|
|||
{
|
||||
// If b is not one we multiply
|
||||
if ( (*pa)->cdigit > 1 || (*pa)->mant[0] != 1 || (*pa)->exp != 0 )
|
||||
{
|
||||
{
|
||||
// pa and b are both non-one.
|
||||
_mulnumx( pa, b );
|
||||
}
|
||||
else
|
||||
{
|
||||
// if pa is one and b isn't just copy b. and adjust the sign.
|
||||
long sign = (*pa)->sign;
|
||||
int32_t sign = (*pa)->sign;
|
||||
DUPNUM(*pa,b);
|
||||
(*pa)->sign *= sign;
|
||||
}
|
||||
|
@ -86,14 +86,14 @@ void _mulnumx( PNUMBER *pa, PNUMBER b )
|
|||
MANTTYPE *ptrc; // ptrc is a pointer to the mantissa of c.
|
||||
MANTTYPE *ptrcoffset; // ptrcoffset, is the anchor location of the next
|
||||
// single digit multiply partial result.
|
||||
long iadigit=0; // Index of digit being used in the first number.
|
||||
long ibdigit=0; // Index of digit being used in the second 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.
|
||||
MANTTYPE da=0; // da is the digit from the fist number.
|
||||
TWO_MANTTYPE cy=0; // cy is the carry resulting from the addition of
|
||||
// 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.
|
||||
long icdigit=0; // Index of digit being calculated in final result.
|
||||
int32_t icdigit=0; // Index of digit being calculated in final result.
|
||||
|
||||
a=*pa;
|
||||
|
||||
|
@ -110,14 +110,14 @@ void _mulnumx( PNUMBER *pa, PNUMBER b )
|
|||
{
|
||||
da = *ptra++;
|
||||
ptrb = b->mant;
|
||||
|
||||
// Shift ptrc, and ptrcoffset, one for each digit
|
||||
|
||||
// Shift ptrc, and ptrcoffset, one for each digit
|
||||
ptrc = ptrcoffset++;
|
||||
|
||||
for ( ibdigit = b->cdigit; ibdigit > 0; ibdigit-- )
|
||||
{
|
||||
cy = 0;
|
||||
mcy = (DWORDLONG)da * (*ptrb);
|
||||
mcy = (uint64_t)da * (*ptrb);
|
||||
if ( mcy )
|
||||
{
|
||||
icdigit = 0;
|
||||
|
@ -126,28 +126,28 @@ void _mulnumx( PNUMBER *pa, PNUMBER b )
|
|||
c->cdigit++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If result is nonzero, or while result of carry is nonzero...
|
||||
while ( mcy || cy )
|
||||
{
|
||||
|
||||
|
||||
// update carry from addition(s) and multiply.
|
||||
cy += (TWO_MANTTYPE)ptrc[icdigit]+((DWORD)mcy&((DWORD)~BASEX));
|
||||
|
||||
// update result digit from
|
||||
ptrc[icdigit++]=(MANTTYPE)((DWORD)cy&((DWORD)~BASEX));
|
||||
|
||||
cy += (TWO_MANTTYPE)ptrc[icdigit]+((uint32_t)mcy&((uint32_t)~BASEX));
|
||||
|
||||
// update result digit from
|
||||
ptrc[icdigit++]=(MANTTYPE)((uint32_t)cy&((uint32_t)~BASEX));
|
||||
|
||||
// update carries from
|
||||
mcy >>= BASEXPWR;
|
||||
cy >>= BASEXPWR;
|
||||
}
|
||||
|
||||
|
||||
ptrb++;
|
||||
ptrc++;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// prevent different kinds of zeros, by stripping leading duplicate zeros.
|
||||
// digits are in order of increasing significance.
|
||||
while ( c->cdigit > 1 && c->mant[c->cdigit-1] == 0 )
|
||||
|
@ -160,9 +160,9 @@ void _mulnumx( PNUMBER *pa, PNUMBER b )
|
|||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: numpowlongx
|
||||
// FUNCTION: numpowi32x
|
||||
//
|
||||
// ARGUMENTS: root as number power as long
|
||||
// ARGUMENTS: root as number power as int32_t
|
||||
// number.
|
||||
//
|
||||
// RETURN: None root is changed.
|
||||
|
@ -174,10 +174,10 @@ void _mulnumx( PNUMBER *pa, PNUMBER b )
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void numpowlongx( _Inout_ PNUMBER *proot, _In_ long power )
|
||||
void numpowi32x( _Inout_ PNUMBER *proot, _In_ int32_t power )
|
||||
|
||||
{
|
||||
PNUMBER lret = longtonum( 1, BASEX );
|
||||
PNUMBER lret = i32tonum( 1, BASEX );
|
||||
|
||||
// Once the power remaining is zero we are done.
|
||||
while ( power > 0 )
|
||||
|
@ -198,7 +198,7 @@ void numpowlongx( _Inout_ PNUMBER *proot, _In_ long power )
|
|||
}
|
||||
destroynum( *proot );
|
||||
*proot=lret;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void _divnumx( PNUMBER *pa, PNUMBER b, int32_t precision);
|
||||
|
@ -232,7 +232,7 @@ void __inline divnumx( PNUMBER *pa, PNUMBER b, int32_t precision)
|
|||
else
|
||||
{
|
||||
// if pa is one and b is not one, just copy b, and adjust the sign.
|
||||
long sign = (*pa)->sign;
|
||||
int32_t sign = (*pa)->sign;
|
||||
DUPNUM(*pa,b);
|
||||
(*pa)->sign *= sign;
|
||||
}
|
||||
|
@ -266,23 +266,23 @@ void _divnumx( PNUMBER *pa, PNUMBER b, int32_t precision)
|
|||
// guesses one bit too far.
|
||||
PNUMBER tmp = nullptr; // current guess being worked on for divide.
|
||||
PNUMBER rem = nullptr; // remainder after applying guess.
|
||||
long 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.
|
||||
|
||||
long 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.
|
||||
|
||||
a=*pa;
|
||||
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.
|
||||
thismax = a->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.
|
||||
thismax = b->cdigit;
|
||||
}
|
||||
|
@ -301,14 +301,14 @@ void _divnumx( PNUMBER *pa, PNUMBER b, int32_t precision)
|
|||
|
||||
while ( cdigits++ < thismax && !zernum(rem) )
|
||||
{
|
||||
long digit = 0;
|
||||
int32_t digit = 0;
|
||||
*ptrc = 0;
|
||||
while ( !lessnum( rem, b ) )
|
||||
{
|
||||
digit = 1;
|
||||
DUPNUM( tmp, b );
|
||||
destroynum( lasttmp );
|
||||
lasttmp=longtonum( 0, BASEX );
|
||||
lasttmp=i32tonum( 0, BASEX );
|
||||
while ( lessnum( tmp, rem ) )
|
||||
{
|
||||
destroynum( lasttmp );
|
||||
|
@ -317,7 +317,7 @@ void _divnumx( PNUMBER *pa, PNUMBER b, int32_t precision)
|
|||
digit *= 2;
|
||||
}
|
||||
if ( lessnum( rem, tmp ) )
|
||||
{
|
||||
{
|
||||
// too far, back up...
|
||||
destroynum( tmp );
|
||||
digit /= 2;
|
||||
|
@ -326,7 +326,7 @@ void _divnumx( PNUMBER *pa, PNUMBER b, int32_t precision)
|
|||
}
|
||||
|
||||
tmp->sign *= -1;
|
||||
addnum( &rem, tmp, BASEX );
|
||||
addnum( &rem, tmp, BASEX );
|
||||
destroynum( tmp );
|
||||
destroynum( lasttmp );
|
||||
*ptrc |= digit;
|
||||
|
@ -341,7 +341,7 @@ void _divnumx( PNUMBER *pa, PNUMBER b, int32_t precision)
|
|||
}
|
||||
|
||||
if ( !cdigits )
|
||||
{
|
||||
{
|
||||
// A zero, make sure no weird exponents creep in
|
||||
c->exp = 0;
|
||||
c->cdigit = 1;
|
||||
|
@ -350,7 +350,7 @@ void _divnumx( PNUMBER *pa, PNUMBER b, int32_t precision)
|
|||
{
|
||||
c->cdigit = 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.
|
||||
while ( c->cdigit > 1 && c->mant[c->cdigit-1] == 0 )
|
||||
{
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
// Description
|
||||
//
|
||||
// Contains conversion, input and output routines for numbers rationals
|
||||
// and longs.
|
||||
// and i32s.
|
||||
//
|
||||
//
|
||||
//
|
||||
|
@ -29,12 +29,87 @@ static constexpr wstring_view DIGITS = L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabc
|
|||
|
||||
// ratio of internal 'digits' to output 'digits'
|
||||
// Calculated elsewhere as part of initialization and when base is changed
|
||||
long g_ratio; // int(log(2L^BASEXPWR)/log(radix))
|
||||
int32_t g_ratio; // int(log(2L^BASEXPWR)/log(radix))
|
||||
// Default decimal separator
|
||||
wchar_t g_decimalSeparator = L'.';
|
||||
|
||||
// The following defines and Calc_ULong* functions were taken from
|
||||
// https://github.com/dotnet/coreclr/blob/8b1595b74c943b33fa794e63e440e6f4c9679478/src/pal/inc/rt/intsafe.h
|
||||
// under MIT License
|
||||
// See also
|
||||
// * https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros
|
||||
// * https://sourceforge.net/p/predef/wiki/Architectures/
|
||||
#if defined(MIDL_PASS) || defined(RC_INVOKED) || defined(_M_CEE_PURE) \
|
||||
|| defined(_M_AMD64) || defined(__ARM_ARCH) || defined(__x86_64__) || defined(_M_ARM64)
|
||||
|
||||
#ifndef Calc_UInt32x32To64
|
||||
#define Calc_UInt32x32To64(a, b) ((uint64_t)((uint32_t)(a)) * (uint64_t)((uint32_t)(b)))
|
||||
#endif
|
||||
|
||||
#elif defined(_M_IX86) || defined(__i386__) || defined(_M_ARM)
|
||||
|
||||
#ifndef Calc_UInt32x32To64
|
||||
#define Calc_UInt32x32To64(a, b) (uint64_t)((uint64_t)(uint32_t)(a) * (uint32_t)(b))
|
||||
#endif
|
||||
#else
|
||||
|
||||
#error Must define a target architecture.
|
||||
|
||||
#endif
|
||||
|
||||
#define CALC_INTSAFE_E_ARITHMETIC_OVERFLOW ((int32_t)0x80070216L) // 0x216 = 534 = ERROR_ARITHMETIC_OVERFLOW
|
||||
#define CALC_ULONG_ERROR ((uint32_t)0xffffffffU)
|
||||
|
||||
namespace {
|
||||
int32_t
|
||||
Calc_ULongAdd(
|
||||
_In_ uint32_t ulAugend,
|
||||
_In_ uint32_t ulAddend,
|
||||
_Out_ uint32_t* pulResult)
|
||||
{
|
||||
int32_t hr = CALC_INTSAFE_E_ARITHMETIC_OVERFLOW;
|
||||
*pulResult = CALC_ULONG_ERROR;
|
||||
|
||||
if ((ulAugend + ulAddend) >= ulAugend)
|
||||
{
|
||||
*pulResult = (ulAugend + ulAddend);
|
||||
hr = S_OK;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
int32_t
|
||||
Calc_ULongLongToULong(
|
||||
_In_ uint64_t ullOperand,
|
||||
_Out_ uint32_t* pulResult)
|
||||
{
|
||||
int32_t hr = CALC_INTSAFE_E_ARITHMETIC_OVERFLOW;
|
||||
*pulResult = CALC_ULONG_ERROR;
|
||||
|
||||
if (ullOperand <= UINT32_MAX)
|
||||
{
|
||||
*pulResult = (uint32_t)ullOperand;
|
||||
hr = S_OK;
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
int32_t
|
||||
Calc_ULongMult(
|
||||
_In_ uint32_t ulMultiplicand,
|
||||
_In_ uint32_t ulMultiplier,
|
||||
_Out_ uint32_t* pulResult)
|
||||
{
|
||||
uint64_t ull64Result = Calc_UInt32x32To64(ulMultiplicand, ulMultiplier);
|
||||
|
||||
return Calc_ULongLongToULong(ull64Result, pulResult);
|
||||
}
|
||||
}
|
||||
|
||||
// Used to strip trailing zeros, and prevent combinatorial explosions
|
||||
bool stripzeroesnum(_Inout_ PNUMBER pnum, long starting);
|
||||
bool stripzeroesnum(_Inout_ PNUMBER pnum, int32_t starting);
|
||||
|
||||
void SetDecimalSeparator(wchar_t decimalSeparator)
|
||||
{
|
||||
|
@ -61,7 +136,7 @@ void* zmalloc(size_t a)
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void _dupnum(_In_ PNUMBER dest, _In_ PNUMBER src)
|
||||
void _dupnum(_In_ PNUMBER dest, _In_ const NUMBER * const src)
|
||||
{
|
||||
memcpy(dest, src, (int)(sizeof(NUMBER) + ((src)->cdigit)*(sizeof(MANTTYPE))));
|
||||
}
|
||||
|
@ -125,16 +200,16 @@ void _destroyrat( _In_ PRAT prat )
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
PNUMBER _createnum( _In_ ULONG size )
|
||||
PNUMBER _createnum( _In_ uint32_t size )
|
||||
|
||||
{
|
||||
PNUMBER pnumret= nullptr;
|
||||
ULONG cbAlloc;
|
||||
uint32_t cbAlloc;
|
||||
|
||||
// sizeof( MANTTYPE ) is the size of a 'digit'
|
||||
if (SUCCEEDED(ULongAdd(size, 1, &cbAlloc)) &&
|
||||
SUCCEEDED(ULongMult(cbAlloc, sizeof(MANTTYPE), &cbAlloc)) &&
|
||||
SUCCEEDED(ULongAdd(cbAlloc, sizeof(NUMBER), &cbAlloc)))
|
||||
if (SUCCEEDED(Calc_ULongAdd(size, 1, &cbAlloc)) &&
|
||||
SUCCEEDED(Calc_ULongMult(cbAlloc, sizeof(MANTTYPE), &cbAlloc)) &&
|
||||
SUCCEEDED(Calc_ULongAdd(cbAlloc, sizeof(NUMBER), &cbAlloc)))
|
||||
{
|
||||
pnumret = (PNUMBER)zmalloc( cbAlloc );
|
||||
if ( pnumret == nullptr)
|
||||
|
@ -203,7 +278,7 @@ PRAT numtorat( _In_ PNUMBER pin, uint32_t radix)
|
|||
PNUMBER pnRadixn= nullptr;
|
||||
DUPNUM( pnRadixn, pin );
|
||||
|
||||
PNUMBER qnRadixn=longtonum( 1, radix);
|
||||
PNUMBER qnRadixn=i32tonum( 1, radix);
|
||||
|
||||
// Ensure p and q start out as integers.
|
||||
if ( pnRadixn->exp < 0 )
|
||||
|
@ -245,24 +320,24 @@ PRAT numtorat( _In_ PNUMBER pin, uint32_t radix)
|
|||
PNUMBER nRadixxtonum( _In_ PNUMBER a, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
unsigned long bitmask;
|
||||
unsigned long cdigits;
|
||||
uint32_t bitmask;
|
||||
uint32_t cdigits;
|
||||
MANTTYPE *ptr;
|
||||
|
||||
PNUMBER sum = longtonum( 0, radix );
|
||||
PNUMBER powofnRadix = longtonum( BASEX, radix );
|
||||
PNUMBER sum = i32tonum( 0, radix );
|
||||
PNUMBER powofnRadix = i32tonum( BASEX, radix );
|
||||
|
||||
// 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
|
||||
// requested precision.
|
||||
cdigits = precision + 1;
|
||||
if ( cdigits > (unsigned long)a->cdigit )
|
||||
if ( cdigits > (uint32_t)a->cdigit )
|
||||
{
|
||||
cdigits = (unsigned long)a->cdigit;
|
||||
cdigits = (uint32_t)a->cdigit;
|
||||
}
|
||||
|
||||
// scale by the internal base to the internal exponent offset of the LSD
|
||||
numpowlong( &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
|
||||
for ( ptr = &(a->mant[a->cdigit-1]); cdigits > 0;
|
||||
|
@ -303,8 +378,8 @@ PNUMBER nRadixxtonum( _In_ PNUMBER a, uint32_t radix, int32_t precision)
|
|||
|
||||
PNUMBER numtonRadixx(_In_ PNUMBER a, uint32_t radix)
|
||||
{
|
||||
PNUMBER pnumret = longtonum(0, BASEX); // pnumret is the number in internal form.
|
||||
PNUMBER num_radix = longtonum(radix, BASEX);
|
||||
PNUMBER pnumret = i32tonum(0, BASEX); // pnumret is the number in internal form.
|
||||
PNUMBER num_radix = i32tonum(radix, BASEX);
|
||||
MANTTYPE *ptrdigit = a->mant; // pointer to digit being worked on.
|
||||
|
||||
// Digits are in reverse order, back over them LSD first.
|
||||
|
@ -312,20 +387,20 @@ PNUMBER numtonRadixx(_In_ PNUMBER a, uint32_t radix)
|
|||
|
||||
PNUMBER thisdigit = nullptr; // thisdigit holds the current digit of a
|
||||
// being summed into result.
|
||||
long 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++ )
|
||||
{
|
||||
mulnumx( &pnumret, num_radix);
|
||||
// WARNING:
|
||||
// This should just smack in each digit into a 'special' thisdigit.
|
||||
// and not do the overhead of recreating the number type each time.
|
||||
thisdigit = longtonum( *ptrdigit--, BASEX );
|
||||
thisdigit = i32tonum( *ptrdigit--, BASEX );
|
||||
addnum( &pnumret, thisdigit, BASEX );
|
||||
destroynum( thisdigit );
|
||||
}
|
||||
|
||||
// Calculate the exponent of the external base for scaling.
|
||||
numpowlongx( &num_radix, a->exp );
|
||||
numpowi32x( &num_radix, a->exp );
|
||||
|
||||
// ... and scale the result.
|
||||
mulnumx( &pnumret, num_radix);
|
||||
|
@ -391,7 +466,7 @@ PRAT StringToRat(bool mantissaIsNegative, wstring_view mantissa, bool exponentIs
|
|||
}
|
||||
|
||||
// Deal with exponent
|
||||
long expt = 0;
|
||||
int32_t expt = 0;
|
||||
if (!exponent.empty())
|
||||
{
|
||||
// Exponent specified, convert to number form.
|
||||
|
@ -404,18 +479,18 @@ PRAT StringToRat(bool mantissaIsNegative, wstring_view mantissa, bool exponentIs
|
|||
}
|
||||
|
||||
// Convert exponent number form to native integral form, and cleanup.
|
||||
expt = numtolong(numExp, radix);
|
||||
expt = numtoi32(numExp, radix);
|
||||
destroynum(numExp);
|
||||
}
|
||||
|
||||
// Convert native integral exponent form to rational multiplier form.
|
||||
PNUMBER pnumexp = longtonum(radix, BASEX);
|
||||
numpowlongx(&pnumexp, abs(expt));
|
||||
PNUMBER pnumexp = i32tonum(radix, BASEX);
|
||||
numpowi32x(&pnumexp, abs(expt));
|
||||
|
||||
PRAT pratexp = nullptr;
|
||||
createrat(pratexp);
|
||||
DUPNUM(pratexp->pp, pnumexp);
|
||||
pratexp->pq = longtonum(1, BASEX);
|
||||
pratexp->pq = i32tonum(1, BASEX);
|
||||
destroynum(pnumexp);
|
||||
|
||||
if (exponentIsNegative)
|
||||
|
@ -574,11 +649,11 @@ wchar_t NormalizeCharDigit(wchar_t c, uint32_t radix)
|
|||
|
||||
PNUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precision)
|
||||
{
|
||||
long expSign = 1L; // expSign is exponent sign ( +/- 1 )
|
||||
long expValue = 0L; // expValue is exponent mantissa, should be unsigned
|
||||
int32_t expSign = 1L; // expSign is exponent sign ( +/- 1 )
|
||||
int32_t expValue = 0L; // expValue is exponent mantissa, should be unsigned
|
||||
|
||||
PNUMBER pnumret = nullptr;
|
||||
createnum(pnumret, static_cast<ULONG>(numberString.length()));
|
||||
createnum(pnumret, static_cast<uint32_t>(numberString.length()));
|
||||
pnumret->sign = 1L;
|
||||
pnumret->cdigit = 0;
|
||||
pnumret->exp = 0;
|
||||
|
@ -612,6 +687,7 @@ PNUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precis
|
|||
break;
|
||||
}
|
||||
// Drop through in the 'e'-as-a-digit case
|
||||
[[fallthrough]];
|
||||
default:
|
||||
state = machine[state][NZ];
|
||||
break;
|
||||
|
@ -636,7 +712,7 @@ PNUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precis
|
|||
if (pos != wstring_view::npos)
|
||||
{
|
||||
expValue *= radix;
|
||||
expValue += static_cast<long>(pos);
|
||||
expValue += static_cast<int32_t>(pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -646,7 +722,7 @@ PNUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precis
|
|||
break;
|
||||
case LD:
|
||||
pnumret->exp++;
|
||||
// Fall through
|
||||
[[fallthrough]];
|
||||
case DD:
|
||||
{
|
||||
curChar = NormalizeCharDigit(curChar, radix);
|
||||
|
@ -682,7 +758,7 @@ PNUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precis
|
|||
}
|
||||
else
|
||||
{
|
||||
while (pnumret->cdigit < static_cast<long>(numberString.length()))
|
||||
while (pnumret->cdigit < static_cast<int32_t>(numberString.length()))
|
||||
{
|
||||
pnumret->cdigit++;
|
||||
pnumret->exp--;
|
||||
|
@ -705,65 +781,65 @@ PNUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precis
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: longtorat
|
||||
// FUNCTION: i32torat
|
||||
//
|
||||
// ARGUMENTS: long
|
||||
// ARGUMENTS: int32_t
|
||||
//
|
||||
// RETURN: Rational representation of long input.
|
||||
// RETURN: Rational representation of int32_t input.
|
||||
//
|
||||
// DESCRIPTION: Converts long input to rational (p over q)
|
||||
// form, where q is 1 and p is the long.
|
||||
// DESCRIPTION: Converts int32_t input to rational (p over q)
|
||||
// form, where q is 1 and p is the int32_t.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
PRAT longtorat( _In_ long inlong )
|
||||
PRAT i32torat( _In_ int32_t ini32 )
|
||||
|
||||
{
|
||||
PRAT pratret= nullptr;
|
||||
createrat( pratret );
|
||||
pratret->pp = longtonum(inlong, BASEX );
|
||||
pratret->pq = longtonum(1L, BASEX );
|
||||
pratret->pp = i32tonum(ini32, BASEX );
|
||||
pratret->pq = i32tonum(1L, BASEX );
|
||||
return( pratret );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: Ulongtorat
|
||||
// FUNCTION: Ui32torat
|
||||
//
|
||||
// ARGUMENTS: ulong
|
||||
// ARGUMENTS: ui32
|
||||
//
|
||||
// RETURN: Rational representation of unsigned long input.
|
||||
// RETURN: Rational representation of uint32_t input.
|
||||
//
|
||||
// DESCRIPTION: Converts unsigned long input to rational (p over q)
|
||||
// form, where q is 1 and p is the unsigned long. Being unsigned cant take negative
|
||||
// DESCRIPTION: Converts uint32_t input to rational (p over q)
|
||||
// form, where q is 1 and p is the uint32_t. Being unsigned cant take negative
|
||||
// numbers, but the full range of unsigned numbers
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
PRAT Ulongtorat( _In_ unsigned long inulong )
|
||||
PRAT Ui32torat( _In_ uint32_t inui32 )
|
||||
|
||||
{
|
||||
PRAT pratret= nullptr;
|
||||
createrat( pratret );
|
||||
pratret->pp = Ulongtonum(inulong, BASEX );
|
||||
pratret->pq = longtonum(1L, BASEX );
|
||||
pratret->pp = Ui32tonum(inui32, BASEX );
|
||||
pratret->pq = i32tonum(1L, BASEX );
|
||||
return( pratret );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: longtonum
|
||||
// FUNCTION: i32tonum
|
||||
//
|
||||
// ARGUMENTS: long input and radix requested.
|
||||
// ARGUMENTS: int32_t input and radix requested.
|
||||
//
|
||||
// RETURN: number
|
||||
//
|
||||
// DESCRIPTION: Returns a number representation in the
|
||||
// base requested of the long value passed in.
|
||||
// base requested of the int32_t value passed in.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
PNUMBER longtonum( long inlong, uint32_t radix)
|
||||
PNUMBER i32tonum( int32_t ini32, uint32_t radix)
|
||||
|
||||
{
|
||||
MANTTYPE *pmant;
|
||||
|
@ -773,10 +849,10 @@ PNUMBER longtonum( long inlong, uint32_t radix)
|
|||
pmant = pnumret->mant;
|
||||
pnumret->cdigit = 0;
|
||||
pnumret->exp = 0;
|
||||
if ( inlong < 0 )
|
||||
if ( ini32 < 0 )
|
||||
{
|
||||
pnumret->sign = -1;
|
||||
inlong *= -1;
|
||||
ini32 *= -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -784,30 +860,30 @@ PNUMBER longtonum( long inlong, uint32_t radix)
|
|||
}
|
||||
|
||||
do {
|
||||
*pmant++ = (MANTTYPE)(inlong % radix);
|
||||
inlong /= radix;
|
||||
*pmant++ = (MANTTYPE)(ini32 % radix);
|
||||
ini32 /= radix;
|
||||
pnumret->cdigit++;
|
||||
} while ( inlong );
|
||||
} while ( ini32 );
|
||||
|
||||
return( pnumret );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: Ulongtonum
|
||||
// FUNCTION: Ui32tonum
|
||||
//
|
||||
// ARGUMENTS: ULONG input and radix requested.
|
||||
// ARGUMENTS: uint32_t input and radix requested.
|
||||
//
|
||||
// RETURN: number
|
||||
//
|
||||
// DESCRIPTION: Returns a number representation in the
|
||||
// base requested of the unsigned long value passed in. Being unsigned number it has no
|
||||
// base requested of the uint32_t value passed in. Being unsigned number it has no
|
||||
// negative number and takes the full range of unsigned number
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
PNUMBER Ulongtonum(unsigned long inlong, uint32_t radix)
|
||||
PNUMBER Ui32tonum(uint32_t ini32, uint32_t radix)
|
||||
{
|
||||
MANTTYPE *pmant;
|
||||
PNUMBER pnumret= nullptr;
|
||||
|
@ -817,12 +893,12 @@ PNUMBER Ulongtonum(unsigned long inlong, uint32_t radix)
|
|||
pnumret->cdigit = 0;
|
||||
pnumret->exp = 0;
|
||||
pnumret->sign = 1;
|
||||
|
||||
|
||||
do {
|
||||
*pmant++ = (MANTTYPE)(inlong % radix);
|
||||
inlong /= radix;
|
||||
*pmant++ = (MANTTYPE)(ini32 % radix);
|
||||
ini32 /= radix;
|
||||
pnumret->cdigit++;
|
||||
} while ( inlong );
|
||||
} while ( ini32 );
|
||||
|
||||
return( pnumret );
|
||||
}
|
||||
|
@ -830,23 +906,23 @@ PNUMBER Ulongtonum(unsigned long inlong, uint32_t radix)
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: rattolong
|
||||
// FUNCTION: rattoi32
|
||||
//
|
||||
// ARGUMENTS: rational number in internal base, integer radix and int32_t precision.
|
||||
//
|
||||
// RETURN: long
|
||||
// RETURN: int32_t
|
||||
//
|
||||
// DESCRIPTION: returns the long representation of the
|
||||
// DESCRIPTION: returns the int32_t representation of the
|
||||
// number input. Assumes that the number is in the internal
|
||||
// base.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
long rattolong( _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_long, precision) || rat_lt( prat, rat_min_long, precision) )
|
||||
if ( rat_gt( prat, rat_max_i32, precision) || rat_lt( prat, rat_min_i32, precision) )
|
||||
{
|
||||
// Don't attempt rattolong of anything too big or small
|
||||
// Don't attempt rattoi32 of anything too big or small
|
||||
throw( CALC_E_DOMAIN );
|
||||
}
|
||||
|
||||
|
@ -857,7 +933,7 @@ long rattolong( _In_ PRAT prat , uint32_t radix, int32_t precision)
|
|||
divnumx( &(pint->pp), pint->pq, precision);
|
||||
DUPNUM( pint->pq, num_one );
|
||||
|
||||
long lret = numtolong( pint->pp, BASEX );
|
||||
int32_t lret = numtoi32( pint->pp, BASEX );
|
||||
|
||||
destroyrat(pint);
|
||||
|
||||
|
@ -866,22 +942,22 @@ long rattolong( _In_ PRAT prat , uint32_t radix, int32_t precision)
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: rattoUlong
|
||||
// FUNCTION: rattoUi32
|
||||
//
|
||||
// ARGUMENTS: rational number in internal base, integer radix and int32_t precision.
|
||||
//
|
||||
// RETURN: Ulong
|
||||
// RETURN: Ui32
|
||||
//
|
||||
// DESCRIPTION: returns the Ulong representation of the
|
||||
// DESCRIPTION: returns the Ui32 representation of the
|
||||
// number input. Assumes that the number is in the internal
|
||||
// base.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
unsigned long rattoUlong( _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) )
|
||||
{
|
||||
// Don't attempt rattoulong of anything too big or small
|
||||
// Don't attempt rattoui32 of anything too big or small
|
||||
throw( CALC_E_DOMAIN );
|
||||
}
|
||||
|
||||
|
@ -892,7 +968,7 @@ unsigned long rattoUlong( _In_ PRAT prat, uint32_t radix, int32_t precision)
|
|||
divnumx( &(pint->pp), pint->pq, precision);
|
||||
DUPNUM( pint->pq, num_one );
|
||||
|
||||
unsigned long lret = numtolong( 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);
|
||||
|
||||
|
@ -902,11 +978,11 @@ unsigned long rattoUlong( _In_ PRAT prat, uint32_t radix, int32_t precision)
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: rattoUlonglong
|
||||
// FUNCTION: rattoUi64
|
||||
//
|
||||
// ARGUMENTS: rational number in internal base, integer radix and int32_t precision
|
||||
//
|
||||
// RETURN: Ulonglong
|
||||
// RETURN: Ui64
|
||||
//
|
||||
// DESCRIPTION: returns the 64 bit (irrespective of which processor this is running in) representation of the
|
||||
// number input. Assumes that the number is in the internal
|
||||
|
@ -915,50 +991,50 @@ unsigned long rattoUlong( _In_ PRAT prat, uint32_t radix, int32_t precision)
|
|||
// internal base chosen happens to be 2^32, this is easier.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ULONGLONG rattoUlonglong( _In_ PRAT prat, uint32_t radix, int32_t precision)
|
||||
uint64_t rattoUi64( _In_ PRAT prat, uint32_t radix, int32_t precision)
|
||||
{
|
||||
PRAT pint = nullptr;
|
||||
|
||||
// first get the LO 32 bit word
|
||||
DUPRAT(pint, prat);
|
||||
andrat(&pint, rat_dword, radix, precision); // & 0xFFFFFFFF (2 ^ 32 -1)
|
||||
unsigned long lo = rattoUlong(pint, radix, precision); // wont throw exception because already hi-dword chopped off
|
||||
uint32_t lo = rattoUi32(pint, radix, precision); // wont throw exception because already hi-dword chopped off
|
||||
|
||||
DUPRAT(pint, prat); // previous pint will get freed by this as well
|
||||
PRAT prat32 = longtorat(32);
|
||||
PRAT prat32 = i32torat(32);
|
||||
rshrat(&pint, prat32, radix, precision);
|
||||
intrat( &pint, radix, precision);
|
||||
andrat(&pint, rat_dword, radix, precision); // & 0xFFFFFFFF (2 ^ 32 -1)
|
||||
unsigned long hi = rattoUlong(pint, radix, precision);
|
||||
uint32_t hi = rattoUi32(pint, radix, precision);
|
||||
|
||||
destroyrat(prat32);
|
||||
destroyrat(pint);
|
||||
|
||||
return (((ULONGLONG)hi << 32) | lo);
|
||||
return (((uint64_t)hi << 32) | lo);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: numtolong
|
||||
// FUNCTION: numtoi32
|
||||
//
|
||||
// ARGUMENTS: number input and base of that number.
|
||||
//
|
||||
// RETURN: long
|
||||
// RETURN: int32_t
|
||||
//
|
||||
// DESCRIPTION: returns the long representation of the
|
||||
// DESCRIPTION: returns the int32_t representation of the
|
||||
// number input. Assumes that the number is really in the
|
||||
// base claimed.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
long numtolong( _In_ PNUMBER pnum, uint32_t radix )
|
||||
int32_t numtoi32( _In_ PNUMBER pnum, uint32_t radix )
|
||||
{
|
||||
long lret = 0;
|
||||
int32_t lret = 0;
|
||||
|
||||
MANTTYPE *pmant = pnum->mant;
|
||||
pmant += pnum->cdigit - 1;
|
||||
|
||||
long expt = pnum->exp;
|
||||
for (long length = pnum->cdigit; length > 0 && length + expt > 0; length--)
|
||||
int32_t expt = pnum->exp;
|
||||
for (int32_t length = pnum->cdigit; length > 0 && length + expt > 0; length--)
|
||||
{
|
||||
lret *= radix;
|
||||
lret += *(pmant--);
|
||||
|
@ -985,10 +1061,10 @@ long numtolong( _In_ PNUMBER pnum, uint32_t radix )
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool stripzeroesnum(_Inout_ PNUMBER pnum, long starting)
|
||||
bool stripzeroesnum(_Inout_ PNUMBER pnum, int32_t starting)
|
||||
{
|
||||
MANTTYPE *pmant;
|
||||
long cdigits;
|
||||
int32_t cdigits;
|
||||
bool fstrip = false;
|
||||
|
||||
// point pmant to the LeastCalculatedDigit
|
||||
|
@ -1041,10 +1117,10 @@ bool stripzeroesnum(_Inout_ PNUMBER pnum, long starting)
|
|||
wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_t precision)
|
||||
{
|
||||
stripzeroesnum(pnum, precision + 2);
|
||||
long length = pnum->cdigit;
|
||||
long exponent = pnum->exp + length; // Actual number of digits to the left of decimal
|
||||
int32_t length = pnum->cdigit;
|
||||
int32_t exponent = pnum->exp + length; // Actual number of digits to the left of decimal
|
||||
|
||||
long oldFormat = format;
|
||||
int32_t oldFormat = format;
|
||||
if (exponent > precision && format == FMT_FLOAT)
|
||||
{
|
||||
// Force scientific mode to prevent user from assuming 33rd digit is exact.
|
||||
|
@ -1064,7 +1140,7 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_
|
|||
if (!zernum(pnum) && (pnum->cdigit >= precision || (length - exponent > precision && exponent >= -MAX_ZEROS_AFTER_DECIMAL)))
|
||||
{
|
||||
// Otherwise round.
|
||||
round = longtonum(radix, radix);
|
||||
round = i32tonum(radix, radix);
|
||||
divnum(&round, num_two, radix, precision);
|
||||
|
||||
// Make round number exponent one below the LSD for the number.
|
||||
|
@ -1109,7 +1185,7 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_
|
|||
if (round != nullptr)
|
||||
{
|
||||
addnum(&pnum, round, radix);
|
||||
long offset = (pnum->cdigit + pnum->exp) - (round->cdigit + round->exp);
|
||||
int32_t offset = (pnum->cdigit + pnum->exp) - (round->cdigit + round->exp);
|
||||
destroynum(round);
|
||||
if (stripzeroesnum(pnum, offset))
|
||||
{
|
||||
|
@ -1125,7 +1201,7 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_
|
|||
|
||||
// Set up all the post rounding stuff.
|
||||
bool useSciForm = false;
|
||||
long eout = exponent - 1; // Displayed exponent.
|
||||
int32_t eout = exponent - 1; // Displayed exponent.
|
||||
MANTTYPE *pmant = pnum->mant + pnum->cdigit - 1;
|
||||
// Case where too many digits are to the left of the decimal or
|
||||
// FMT_SCIENTIFIC or FMT_ENGINEERING was specified.
|
||||
|
@ -1239,7 +1315,7 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_
|
|||
//
|
||||
// ARGUMENTS:
|
||||
// PRAT *representation of a number.
|
||||
// long representation of base to dump to screen.
|
||||
// i32 representation of base to dump to screen.
|
||||
// fmt, one of FMT_FLOAT FMT_SCIENTIFIC or FMT_ENGINEERING
|
||||
// precision uint32_t
|
||||
//
|
||||
|
@ -1269,8 +1345,8 @@ PNUMBER RatToNumber(_In_ PRAT prat, uint32_t radix, int32_t precision)
|
|||
DUPRAT(temprat, prat);
|
||||
// Convert p and q of rational form from internal base to requested base.
|
||||
// Scale by largest power of BASEX possible.
|
||||
long scaleby = min(temprat->pp->exp, temprat->pq->exp);
|
||||
scaleby = max(scaleby, 0);
|
||||
int32_t scaleby = min(temprat->pp->exp, temprat->pq->exp);
|
||||
scaleby = max<int32_t>(scaleby, 0);
|
||||
|
||||
temprat->pp->exp -= scaleby;
|
||||
temprat->pq->exp -= scaleby;
|
||||
|
@ -1358,12 +1434,12 @@ PNUMBER gcd( _In_ PNUMBER a, _In_ PNUMBER b)
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: longfactnum
|
||||
// FUNCTION: i32factnum
|
||||
//
|
||||
// ARGUMENTS:
|
||||
// long integer to factorialize.
|
||||
// long integer representing base of answer.
|
||||
// unsigned long integer for radix
|
||||
// int32_t integer to factorialize.
|
||||
// int32_t integer representing base of answer.
|
||||
// uint32_t integer for radix
|
||||
//
|
||||
// RETURN: Factorial of input in radix PNUMBER form.
|
||||
//
|
||||
|
@ -1371,17 +1447,17 @@ PNUMBER gcd( _In_ PNUMBER a, _In_ PNUMBER b)
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
PNUMBER longfactnum(long inlong, uint32_t radix)
|
||||
PNUMBER i32factnum(int32_t ini32, uint32_t radix)
|
||||
|
||||
{
|
||||
PNUMBER lret= nullptr;
|
||||
PNUMBER tmp= nullptr;
|
||||
|
||||
lret = longtonum( 1, radix);
|
||||
lret = i32tonum( 1, radix);
|
||||
|
||||
while ( inlong > 0 )
|
||||
while ( ini32 > 0 )
|
||||
{
|
||||
tmp = longtonum( inlong--, radix);
|
||||
tmp = i32tonum( ini32--, radix);
|
||||
mulnum( &lret, tmp, radix);
|
||||
destroynum( tmp );
|
||||
}
|
||||
|
@ -1390,30 +1466,30 @@ PNUMBER longfactnum(long inlong, uint32_t radix)
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: longprodnum
|
||||
// FUNCTION: i32prodnum
|
||||
//
|
||||
// ARGUMENTS:
|
||||
// long integer to factorialize.
|
||||
// long integer representing base of answer.
|
||||
// unsigned long integer for radix
|
||||
// int32_t integer to factorialize.
|
||||
// int32_t integer representing base of answer.
|
||||
// uint32_t integer for radix
|
||||
//
|
||||
// RETURN: Factorial of input in base PNUMBER form.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
PNUMBER longprodnum(long start, long stop, uint32_t radix)
|
||||
PNUMBER i32prodnum(int32_t start, int32_t stop, uint32_t radix)
|
||||
|
||||
{
|
||||
PNUMBER lret= nullptr;
|
||||
PNUMBER tmp= nullptr;
|
||||
|
||||
lret = longtonum( 1, radix);
|
||||
lret = i32tonum( 1, radix);
|
||||
|
||||
while ( start <= stop )
|
||||
{
|
||||
if ( start )
|
||||
{
|
||||
tmp = longtonum( start, radix);
|
||||
tmp = i32tonum( start, radix);
|
||||
mulnum( &lret, tmp, radix);
|
||||
destroynum( tmp );
|
||||
}
|
||||
|
@ -1424,10 +1500,10 @@ PNUMBER longprodnum(long start, long stop, uint32_t radix)
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: numpowlong
|
||||
// FUNCTION: numpowi32
|
||||
//
|
||||
// ARGUMENTS: root as number power as long and radix of
|
||||
// number along with the precision value in long.
|
||||
// ARGUMENTS: root as number power as int32_t and radix of
|
||||
// number along with the precision value in int32_t.
|
||||
//
|
||||
// RETURN: None root is changed.
|
||||
//
|
||||
|
@ -1436,9 +1512,9 @@ PNUMBER longprodnum(long start, long stop, uint32_t radix)
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void numpowlong( _Inout_ PNUMBER *proot, long power, uint32_t radix, int32_t precision)
|
||||
void numpowi32( _Inout_ PNUMBER *proot, int32_t power, uint32_t radix, int32_t precision)
|
||||
{
|
||||
PNUMBER lret = longtonum( 1, radix );
|
||||
PNUMBER lret = i32tonum( 1, radix );
|
||||
|
||||
while ( power > 0 )
|
||||
{
|
||||
|
@ -1457,9 +1533,9 @@ void numpowlong( _Inout_ PNUMBER *proot, long power, uint32_t radix, int32_t pre
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: ratpowlong
|
||||
// FUNCTION: ratpowi32
|
||||
//
|
||||
// ARGUMENTS: root as rational, power as long and precision as uint32_t.
|
||||
// ARGUMENTS: root as rational, power as int32_t and precision as int32_t.
|
||||
//
|
||||
// RETURN: None root is changed.
|
||||
//
|
||||
|
@ -1468,14 +1544,14 @@ void numpowlong( _Inout_ PNUMBER *proot, long power, uint32_t radix, int32_t pre
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ratpowlong( _Inout_ PRAT *proot, long power, int32_t precision)
|
||||
void ratpowi32( _Inout_ PRAT *proot, int32_t power, int32_t precision)
|
||||
|
||||
{
|
||||
if ( power < 0 )
|
||||
{
|
||||
// Take the positive power and invert answer.
|
||||
PNUMBER pnumtemp = nullptr;
|
||||
ratpowlong( proot, -power, precision);
|
||||
ratpowi32( proot, -power, precision);
|
||||
pnumtemp = (*proot)->pp;
|
||||
(*proot)->pp = (*proot)->pq;
|
||||
(*proot)->pq = pnumtemp;
|
||||
|
@ -1484,7 +1560,7 @@ void ratpowlong( _Inout_ PRAT *proot, long power, int32_t precision)
|
|||
{
|
||||
PRAT lret= nullptr;
|
||||
|
||||
lret = longtorat( 1 );
|
||||
lret = i32torat( 1 );
|
||||
|
||||
while ( power > 0 )
|
||||
{
|
||||
|
|
|
@ -46,11 +46,11 @@ void _exprat( PRAT *px, int32_t precision)
|
|||
{
|
||||
CREATETAYLOR();
|
||||
|
||||
addnum(&(pret->pp),num_one, BASEX);
|
||||
addnum(&(pret->pq),num_one, BASEX);
|
||||
addnum(&(pret->pp),num_one, BASEX);
|
||||
addnum(&(pret->pq),num_one, BASEX);
|
||||
DUPRAT(thisterm,pret);
|
||||
|
||||
n2=longtonum(0L, BASEX);
|
||||
n2=i32tonum(0L, BASEX);
|
||||
|
||||
do {
|
||||
NEXTTERM(*px, INC(n2) DIVNUM(n2), precision);
|
||||
|
@ -64,7 +64,7 @@ void exprat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
{
|
||||
PRAT pwr= nullptr;
|
||||
PRAT pint= nullptr;
|
||||
long intpwr;
|
||||
int32_t intpwr;
|
||||
|
||||
if ( rat_gt( *px, rat_max_exp, precision) || rat_lt( *px, rat_min_exp, precision) )
|
||||
{
|
||||
|
@ -77,11 +77,11 @@ void exprat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
|
||||
intrat(&pint, radix, precision);
|
||||
|
||||
intpwr = rattolong(pint, radix, precision);
|
||||
ratpowlong( &pwr, intpwr, precision);
|
||||
intpwr = rattoi32(pint, radix, precision);
|
||||
ratpowi32( &pwr, intpwr, precision);
|
||||
|
||||
subrat(px, pint, precision);
|
||||
|
||||
|
||||
// It just so happens to be an integral power of e.
|
||||
if ( rat_gt( *px, rat_negsmallest, precision) && rat_lt( *px, rat_smallest, precision) )
|
||||
{
|
||||
|
@ -131,7 +131,7 @@ void _lograt( PRAT *px, int32_t precision)
|
|||
CREATETAYLOR();
|
||||
|
||||
createrat(thisterm);
|
||||
|
||||
|
||||
// sub one from x
|
||||
(*px)->pq->sign *= -1;
|
||||
addnum(&((*px)->pp),(*px)->pq, BASEX);
|
||||
|
@ -140,7 +140,7 @@ void _lograt( PRAT *px, int32_t precision)
|
|||
DUPRAT(pret,*px);
|
||||
DUPRAT(thisterm,*px);
|
||||
|
||||
n2=longtonum(1L, BASEX);
|
||||
n2=i32tonum(1L, BASEX);
|
||||
(*px)->pp->sign *= -1;
|
||||
|
||||
do {
|
||||
|
@ -158,14 +158,14 @@ void lograt( PRAT *px, int32_t precision)
|
|||
bool fneglog;
|
||||
PRAT pwr = nullptr; // pwr is the large scaling factor.
|
||||
PRAT offset = nullptr; // offset is the incremental scaling factor.
|
||||
|
||||
|
||||
|
||||
|
||||
// Check for someone taking the log of zero or a negative number.
|
||||
if ( rat_le( *px, rat_zero, precision) )
|
||||
{
|
||||
throw( CALC_E_DOMAIN );
|
||||
}
|
||||
|
||||
|
||||
// Get number > 1, for scaling
|
||||
fneglog = rat_lt( *px, rat_one, precision);
|
||||
if ( fneglog )
|
||||
|
@ -176,17 +176,17 @@ void lograt( PRAT *px, int32_t precision)
|
|||
(*px)->pp = (*px)->pq;
|
||||
(*px)->pq = pnumtemp;
|
||||
}
|
||||
|
||||
|
||||
// Scale the number within BASEX factor of 1, for the large scale.
|
||||
// log(x*2^(BASEXPWR*k)) = BASEXPWR*k*log(2)+log(x)
|
||||
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.
|
||||
long intpwr;
|
||||
int32_t intpwr;
|
||||
intpwr=LOGRAT2(*px)-1;
|
||||
(*px)->pq->exp += intpwr;
|
||||
pwr=longtorat(intpwr*BASEXPWR);
|
||||
pwr=i32torat(intpwr*BASEXPWR);
|
||||
mulrat(&pwr, ln_two, precision);
|
||||
// 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.
|
||||
|
@ -206,17 +206,17 @@ void lograt( PRAT *px, int32_t precision)
|
|||
}
|
||||
|
||||
_lograt(px, precision);
|
||||
|
||||
|
||||
// Add the large and small scaling factors, take into account
|
||||
// small scaling was done in e_to_one_half chunks.
|
||||
divrat(&offset, rat_two, precision);
|
||||
addrat(&pwr, offset, precision);
|
||||
|
||||
|
||||
// And add the resulting scaling factor to the answer.
|
||||
addrat(px, pwr, precision);
|
||||
|
||||
trimit(px, precision);
|
||||
|
||||
|
||||
// If number started out < 1 rescale answer to negative.
|
||||
if ( fneglog )
|
||||
{
|
||||
|
@ -224,9 +224,9 @@ void lograt( PRAT *px, int32_t precision)
|
|||
}
|
||||
|
||||
destroyrat(offset);
|
||||
destroyrat(pwr);
|
||||
destroyrat(pwr);
|
||||
}
|
||||
|
||||
|
||||
void log10rat( PRAT *px, int32_t precision)
|
||||
|
||||
{
|
||||
|
@ -235,7 +235,7 @@ void log10rat( PRAT *px, int32_t precision)
|
|||
}
|
||||
|
||||
//
|
||||
// return if the given x is even number. The assumption here is its denominator is 1 and we are testing the numerator is
|
||||
// return if the given x is even number. The assumption here is its denominator is 1 and we are testing the numerator is
|
||||
// even or not
|
||||
bool IsEven(PRAT x, uint32_t radix, int32_t precision)
|
||||
{
|
||||
|
@ -309,7 +309,7 @@ void powratNumeratorDenominator(PRAT *px, PRAT y, uint32_t radix, int32_t precis
|
|||
|
||||
// Calculate the following use the Powers of Powers rule:
|
||||
// px ^ (yNum/yDenom) == px ^ yNum ^ (1/yDenom)
|
||||
// 1. For px ^ yNum, we call powratcomp directly which will call ratpowlong
|
||||
// 1. For px ^ yNum, we call powratcomp directly which will call ratpowi32
|
||||
// and store the result in pxPowNum
|
||||
// 2. For pxPowNum ^ (1/yDenom), we call powratcomp
|
||||
// 3. Validate the result of 2 by adding/subtracting 0.5, flooring and call powratcomp with yDenom
|
||||
|
@ -318,7 +318,7 @@ void powratNumeratorDenominator(PRAT *px, PRAT y, uint32_t radix, int32_t precis
|
|||
// 1. Initialize result.
|
||||
PRAT pxPow = nullptr;
|
||||
DUPRAT(pxPow, *px);
|
||||
|
||||
|
||||
// 2. Calculate pxPow = px ^ yNumerator
|
||||
// if yNumerator is not 1
|
||||
if (!rat_equ(yNumerator, rat_one, precision))
|
||||
|
@ -341,7 +341,7 @@ void powratNumeratorDenominator(PRAT *px, PRAT y, uint32_t radix, int32_t precis
|
|||
PRAT originalResult = nullptr;
|
||||
DUPRAT(originalResult, pxPow);
|
||||
powratcomp(&originalResult, oneoveryDenom, radix, precision);
|
||||
|
||||
|
||||
// ##################################
|
||||
// Round the originalResult to roundedResult
|
||||
// ##################################
|
||||
|
@ -375,7 +375,7 @@ void powratNumeratorDenominator(PRAT *px, PRAT y, uint32_t radix, int32_t precis
|
|||
else
|
||||
{
|
||||
DUPRAT(*px, originalResult);
|
||||
}
|
||||
}
|
||||
|
||||
destroyrat(oneoveryDenom);
|
||||
destroyrat(originalResult);
|
||||
|
@ -408,7 +408,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)
|
||||
{
|
||||
long sign = ((*px)->pp->sign * (*px)->pq->sign);
|
||||
int32_t sign = ((*px)->pp->sign * (*px)->pq->sign);
|
||||
|
||||
// Take the absolute value
|
||||
(*px)->pp->sign = 1;
|
||||
|
@ -429,7 +429,7 @@ void powratcomp(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
|
|||
sign = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
PRAT pxint= nullptr;
|
||||
DUPRAT(pxint,*px);
|
||||
|
@ -451,12 +451,12 @@ void powratcomp(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
|
|||
fracrat(&podd, radix, precision);
|
||||
if ( rat_gt( podd, rat_negsmallest, precision) && rat_lt( podd, rat_smallest, precision) )
|
||||
{
|
||||
// If power is an integer let ratpowlong deal with it.
|
||||
// If power is an integer let ratpowi32 deal with it.
|
||||
PRAT iy = nullptr;
|
||||
long inty;
|
||||
int32_t inty;
|
||||
DUPRAT(iy,y);
|
||||
subrat(&iy, podd, precision);
|
||||
inty = rattolong(iy, radix, precision);
|
||||
inty = rattoi32(iy, radix, precision);
|
||||
|
||||
PRAT plnx = nullptr;
|
||||
DUPRAT(plnx,*px);
|
||||
|
@ -472,7 +472,7 @@ void powratcomp(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
|
|||
throw( CALC_E_DOMAIN );
|
||||
}
|
||||
destroyrat(plnx);
|
||||
ratpowlong(px, inty, precision);
|
||||
ratpowi32(px, inty, precision);
|
||||
if ( ( inty & 1 ) == 0 )
|
||||
{
|
||||
sign=1;
|
||||
|
@ -491,7 +491,7 @@ void powratcomp(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
|
|||
PRAT pNumerator = nullptr;
|
||||
PRAT pDenominator = nullptr;
|
||||
bool fBadExponent = false;
|
||||
|
||||
|
||||
// Get the numbers in arbitrary precision rational number format
|
||||
DUPRAT(pNumerator, rat_zero); // pNumerator->pq is 1 one
|
||||
DUPRAT(pDenominator, rat_zero); // pDenominator->pq is 1 one
|
||||
|
@ -516,7 +516,7 @@ void powratcomp(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
|
|||
}
|
||||
destroyrat(pNumerator);
|
||||
destroyrat(pDenominator);
|
||||
|
||||
|
||||
if (fBadExponent)
|
||||
{
|
||||
throw( CALC_E_DOMAIN );
|
||||
|
|
|
@ -72,18 +72,18 @@ void _gamma( PRAT *pn, uint32_t radix, int32_t precision)
|
|||
PRAT mpy= nullptr;
|
||||
PRAT ratprec = nullptr;
|
||||
PRAT ratRadix = nullptr;
|
||||
long oldprec;
|
||||
|
||||
int32_t oldprec;
|
||||
|
||||
// Set up constants and initial conditions
|
||||
oldprec = precision;
|
||||
ratprec = longtorat( oldprec );
|
||||
|
||||
ratprec = i32torat( oldprec );
|
||||
|
||||
// Find the best 'A' for convergence to the required precision.
|
||||
a=longtorat( radix );
|
||||
a=i32torat( radix );
|
||||
lograt(&a, 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
|
||||
addrat(&a, rat_two, precision);
|
||||
DUPRAT(tmp,a);
|
||||
|
@ -91,12 +91,12 @@ void _gamma( PRAT *pn, uint32_t radix, int32_t precision)
|
|||
mulrat(&tmp, *pn, precision);
|
||||
addrat(&a, tmp, precision);
|
||||
addrat(&a, rat_one, 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));
|
||||
DUPRAT(tmp,*pn);
|
||||
one_pt_five=longtorat( 3L );
|
||||
one_pt_five=i32torat( 3L );
|
||||
divrat( &one_pt_five, rat_two, precision);
|
||||
addrat( &tmp, one_pt_five, precision);
|
||||
DUPRAT(term,a);
|
||||
|
@ -105,22 +105,22 @@ void _gamma( PRAT *pn, uint32_t radix, int32_t precision)
|
|||
exprat( &tmp, radix, precision);
|
||||
mulrat( &term, tmp, precision);
|
||||
lograt( &term, precision);
|
||||
ratRadix = longtorat(radix);
|
||||
ratRadix = i32torat(radix);
|
||||
DUPRAT(tmp,ratRadix);
|
||||
lograt( &tmp, precision);
|
||||
subrat( &term, tmp, precision);
|
||||
precision += rattolong( term, radix, precision);
|
||||
|
||||
precision += rattoi32( term, radix, precision);
|
||||
|
||||
// Set up initial terms for series, refer to series in above comment block.
|
||||
DUPRAT(factorial,rat_one); // Start factorial out with one
|
||||
count = longtonum( 0L, BASEX );
|
||||
count = i32tonum( 0L, BASEX );
|
||||
|
||||
DUPRAT(mpy,a);
|
||||
powratcomp(&mpy,*pn, radix, precision);
|
||||
// a2=a^2
|
||||
DUPRAT(a2,a);
|
||||
mulrat(&a2, a, precision);
|
||||
|
||||
|
||||
// sum=(1/n)-(a/(n+1))
|
||||
DUPRAT(sum,rat_one);
|
||||
divrat(&sum, *pn, precision);
|
||||
|
@ -136,14 +136,14 @@ void _gamma( PRAT *pn, uint32_t radix, int32_t precision)
|
|||
divrat(&err, ratRadix, precision);
|
||||
|
||||
// Just get something not tiny in term
|
||||
DUPRAT(term, rat_two );
|
||||
DUPRAT(term, rat_two );
|
||||
|
||||
// Loop until precision is reached, or asked to halt.
|
||||
while ( !zerrat( term ) && rat_gt( term, err, precision) )
|
||||
{
|
||||
addrat(pn, rat_two, precision);
|
||||
|
||||
// WARNING: mixing numbers and rationals here.
|
||||
|
||||
// WARNING: mixing numbers and rationals here.
|
||||
// for speed and efficiency.
|
||||
INC(count);
|
||||
mulnumx(&(factorial->pp),count);
|
||||
|
@ -166,15 +166,15 @@ void _gamma( PRAT *pn, uint32_t radix, int32_t precision)
|
|||
DUPRAT(term,rat_one);
|
||||
divrat( &term, *pn, precision);
|
||||
subrat( &term, tmp, precision);
|
||||
|
||||
|
||||
divrat (&term, factorial, precision);
|
||||
addrat( &sum, term, precision);
|
||||
ABSRAT(term);
|
||||
}
|
||||
|
||||
|
||||
// Multiply by factor.
|
||||
mulrat( &sum, mpy, precision);
|
||||
|
||||
|
||||
// And cleanup
|
||||
precision = oldprec;
|
||||
destroyrat(ratprec);
|
||||
|
@ -199,13 +199,13 @@ void factrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
PRAT fact = nullptr;
|
||||
PRAT frac = nullptr;
|
||||
PRAT neg_rat_one = nullptr;
|
||||
|
||||
|
||||
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.
|
||||
throw CALC_E_OVERFLOW;
|
||||
}
|
||||
|
||||
|
||||
DUPRAT(fact,rat_one);
|
||||
|
||||
DUPRAT(neg_rat_one,rat_one);
|
||||
|
@ -226,7 +226,7 @@ void factrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
mulrat( &fact, *px, precision);
|
||||
subrat( px, rat_one, precision);
|
||||
}
|
||||
|
||||
|
||||
// Added to make numbers 'close enough' to integers use integer factorial.
|
||||
if ( LOGRATRADIX(*px) <= -precision)
|
||||
{
|
||||
|
|
|
@ -69,13 +69,13 @@ void _asinrat( PRAT *px, int32_t precision)
|
|||
|
||||
{
|
||||
CREATETAYLOR();
|
||||
DUPRAT(pret,*px);
|
||||
DUPRAT(pret,*px);
|
||||
DUPRAT(thisterm,*px);
|
||||
DUPNUM(n2,num_one);
|
||||
|
||||
do
|
||||
{
|
||||
NEXTTERM(xx,MULNUM(n2) MULNUM(n2)
|
||||
NEXTTERM(xx,MULNUM(n2) MULNUM(n2)
|
||||
INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
}
|
||||
while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
|
||||
|
@ -92,7 +92,7 @@ void asinanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32
|
|||
void asinrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
long sgn;
|
||||
int32_t sgn;
|
||||
PRAT pret= nullptr;
|
||||
PRAT phack= nullptr;
|
||||
|
||||
|
@ -100,7 +100,7 @@ void asinrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
|
||||
(*px)->pp->sign = 1;
|
||||
(*px)->pq->sign = 1;
|
||||
|
||||
|
||||
// Avoid the really bad part of the asin curve near +/-1.
|
||||
DUPRAT(phack,*px);
|
||||
subrat(&phack, rat_one, precision);
|
||||
|
@ -185,15 +185,15 @@ void _acosrat( PRAT *px, int32_t precision)
|
|||
{
|
||||
CREATETAYLOR();
|
||||
|
||||
createrat(thisterm);
|
||||
thisterm->pp=longtonum( 1L, BASEX );
|
||||
thisterm->pq=longtonum( 1L, BASEX );
|
||||
createrat(thisterm);
|
||||
thisterm->pp=i32tonum( 1L, BASEX );
|
||||
thisterm->pq=i32tonum( 1L, BASEX );
|
||||
|
||||
DUPNUM(n2,num_one);
|
||||
|
||||
do
|
||||
{
|
||||
NEXTTERM(xx,MULNUM(n2) MULNUM(n2)
|
||||
NEXTTERM(xx,MULNUM(n2) MULNUM(n2)
|
||||
INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
}
|
||||
while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
|
||||
|
@ -204,13 +204,13 @@ void _acosrat( PRAT *px, int32_t precision)
|
|||
void acosrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
long sgn;
|
||||
int32_t sgn;
|
||||
|
||||
sgn = (*px)->pp->sign*(*px)->pq->sign;
|
||||
|
||||
(*px)->pp->sign = 1;
|
||||
(*px)->pq->sign = 1;
|
||||
|
||||
|
||||
if ( rat_equ( *px, rat_one, precision) )
|
||||
{
|
||||
if ( sgn == -1 )
|
||||
|
@ -274,7 +274,7 @@ void _atanrat( PRAT *px, int32_t precision)
|
|||
{
|
||||
CREATETAYLOR();
|
||||
|
||||
DUPRAT(pret,*px);
|
||||
DUPRAT(pret,*px);
|
||||
DUPRAT(thisterm,*px);
|
||||
|
||||
DUPNUM(n2,num_one);
|
||||
|
@ -291,14 +291,14 @@ void _atanrat( PRAT *px, int32_t precision)
|
|||
void atanrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
long sgn;
|
||||
int32_t sgn;
|
||||
PRAT tmpx= nullptr;
|
||||
|
||||
sgn = (*px)->pp->sign * (*px)->pq->sign;
|
||||
|
||||
(*px)->pp->sign = 1;
|
||||
(*px)->pq->sign = 1;
|
||||
|
||||
|
||||
if ( rat_gt( (*px), pt_eight_five, precision) )
|
||||
{
|
||||
if ( rat_gt( (*px), rat_two, precision) )
|
||||
|
@ -314,7 +314,7 @@ void atanrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
subrat(px, tmpx, precision);
|
||||
destroyrat( tmpx );
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
(*px)->pp->sign = sgn;
|
||||
DUPRAT(tmpx,*px);
|
||||
|
|
|
@ -60,7 +60,7 @@ void asinhrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
if ( rat_gt( *px, pt_eight_five, precision) || rat_lt( *px, neg_pt_eight_five, precision) )
|
||||
{
|
||||
PRAT ptmp = nullptr;
|
||||
DUPRAT(ptmp,(*px));
|
||||
DUPRAT(ptmp,(*px));
|
||||
mulrat(&ptmp, *px, precision);
|
||||
addrat(&ptmp, rat_one, precision);
|
||||
rootrat(&ptmp, rat_two, radix, precision);
|
||||
|
@ -73,14 +73,14 @@ void asinhrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
CREATETAYLOR();
|
||||
xx->pp->sign *= -1;
|
||||
|
||||
DUPRAT(pret,(*px));
|
||||
DUPRAT(pret,(*px));
|
||||
DUPRAT(thisterm,(*px));
|
||||
|
||||
DUPNUM(n2,num_one);
|
||||
|
||||
do
|
||||
{
|
||||
NEXTTERM(xx,MULNUM(n2) MULNUM(n2)
|
||||
NEXTTERM(xx,MULNUM(n2) MULNUM(n2)
|
||||
INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
}
|
||||
while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
|
||||
|
@ -99,7 +99,7 @@ void asinhrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
// hyperbolic cose of
|
||||
// RETURN: acosh of x in PRAT form.
|
||||
//
|
||||
// EXPLANATION: This uses
|
||||
// EXPLANATION: This uses
|
||||
//
|
||||
// acosh(x)=ln(x+sqrt(x^2-1))
|
||||
//
|
||||
|
@ -117,7 +117,7 @@ void acoshrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
else
|
||||
{
|
||||
PRAT ptmp = nullptr;
|
||||
DUPRAT(ptmp,(*px));
|
||||
DUPRAT(ptmp,(*px));
|
||||
mulrat(&ptmp, *px, precision);
|
||||
subrat(&ptmp, rat_one, precision);
|
||||
rootrat(&ptmp,rat_two, radix, precision);
|
||||
|
@ -148,7 +148,7 @@ void atanhrat( PRAT *px, int32_t precision)
|
|||
|
||||
{
|
||||
PRAT ptmp = nullptr;
|
||||
DUPRAT(ptmp,(*px));
|
||||
DUPRAT(ptmp,(*px));
|
||||
subrat(&ptmp, rat_one, precision);
|
||||
addrat(px, rat_one, precision);
|
||||
divrat(px, ptmp, precision);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
@ -16,13 +16,13 @@
|
|||
#include "pch.h"
|
||||
#include "ratpak.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
void lshrat( PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
PRAT pwr= nullptr;
|
||||
long intb;
|
||||
int32_t intb;
|
||||
|
||||
intrat(pa, radix, precision);
|
||||
if ( !zernum( (*pa)->pp ) )
|
||||
|
@ -33,9 +33,9 @@ void lshrat( PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
|
|||
// Don't attempt lsh of anything big
|
||||
throw( CALC_E_DOMAIN );
|
||||
}
|
||||
intb = rattolong(b, radix, precision);
|
||||
intb = rattoi32(b, radix, precision);
|
||||
DUPRAT(pwr,rat_two);
|
||||
ratpowlong(&pwr, intb, precision);
|
||||
ratpowi32(&pwr, intb, precision);
|
||||
mulrat(pa, pwr, precision);
|
||||
destroyrat(pwr);
|
||||
}
|
||||
|
@ -45,20 +45,20 @@ void rshrat( PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
|
|||
|
||||
{
|
||||
PRAT pwr= nullptr;
|
||||
long intb;
|
||||
int32_t intb;
|
||||
|
||||
intrat(pa, radix, precision);
|
||||
if ( !zernum( (*pa)->pp ) )
|
||||
{
|
||||
{
|
||||
// If input is zero we're done.
|
||||
if ( rat_lt( b, rat_min_exp, precision) )
|
||||
{
|
||||
// Don't attempt rsh of anything big and negative.
|
||||
throw( CALC_E_DOMAIN );
|
||||
}
|
||||
intb = rattolong(b, radix, precision);
|
||||
intb = rattoi32(b, radix, precision);
|
||||
DUPRAT(pwr,rat_two);
|
||||
ratpowlong(&pwr, intb, precision);
|
||||
ratpowi32(&pwr, intb, precision);
|
||||
divrat(pa, pwr, precision);
|
||||
destroyrat(pwr);
|
||||
}
|
||||
|
@ -138,8 +138,8 @@ void boolnum( PNUMBER *pa, PNUMBER b, int func )
|
|||
MANTTYPE *pcha;
|
||||
MANTTYPE *pchb;
|
||||
MANTTYPE *pchc;
|
||||
long cdigits;
|
||||
long mexp;
|
||||
int32_t cdigits;
|
||||
int32_t mexp;
|
||||
MANTTYPE da;
|
||||
MANTTYPE db;
|
||||
|
||||
|
@ -155,11 +155,11 @@ void boolnum( PNUMBER *pa, PNUMBER b, int func )
|
|||
pchc = c->mant;
|
||||
for ( ;cdigits > 0; cdigits--, mexp++ )
|
||||
{
|
||||
da = ( ( ( mexp >= a->exp ) && ( cdigits + a->exp - c->exp >
|
||||
(c->cdigit - a->cdigit) ) ) ?
|
||||
da = ( ( ( mexp >= a->exp ) && ( cdigits + a->exp - c->exp >
|
||||
(c->cdigit - a->cdigit) ) ) ?
|
||||
*pcha++ : 0 );
|
||||
db = ( ( ( mexp >= b->exp ) && ( cdigits + b->exp - c->exp >
|
||||
(c->cdigit - b->cdigit) ) ) ?
|
||||
db = ( ( ( mexp >= b->exp ) && ( cdigits + b->exp - c->exp >
|
||||
(c->cdigit - b->cdigit) ) ) ?
|
||||
*pchb++ : 0 );
|
||||
switch ( func )
|
||||
{
|
||||
|
@ -205,15 +205,14 @@ void modrat( PRAT *pa, PRAT b )
|
|||
throw CALC_E_INDEFINITE;
|
||||
}
|
||||
DUPRAT(tmp,b);
|
||||
|
||||
|
||||
mulnumx( &((*pa)->pp), tmp->pq );
|
||||
mulnumx( &(tmp->pp), (*pa)->pq );
|
||||
remnum( &((*pa)->pp), tmp->pp, BASEX );
|
||||
mulnumx( &((*pa)->pq), tmp->pq );
|
||||
|
||||
//Get *pa back in the integer over integer form.
|
||||
|
||||
// Get *pa back in the integer over integer form.
|
||||
RENORMALIZE(*pa);
|
||||
|
||||
destroyrat( tmp );
|
||||
}
|
||||
|
||||
|
|
|
@ -2,20 +2,20 @@
|
|||
// Licensed under the MIT License.
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Package Title ratpak
|
||||
// File num.c
|
||||
// Copyright (C) 1995-97 Microsoft
|
||||
// Date 01-16-95
|
||||
//
|
||||
//
|
||||
// Description
|
||||
//
|
||||
// Contains number routines for add, mul, div, rem and other support
|
||||
// and longs.
|
||||
//
|
||||
// Special Information
|
||||
//
|
||||
//
|
||||
// Package Title ratpak
|
||||
// File num.c
|
||||
// Copyright (C) 1995-97 Microsoft
|
||||
// Date 01-16-95
|
||||
//
|
||||
//
|
||||
// Description
|
||||
//
|
||||
// Contains number routines for add, mul, div, rem and other support
|
||||
// and longs.
|
||||
//
|
||||
// Special Information
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "pch.h"
|
||||
#include "ratpak.h"
|
||||
|
@ -66,18 +66,18 @@ void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
MANTTYPE *pcha; // pcha is a pointer to the mantissa of a.
|
||||
MANTTYPE *pchb; // pchb is a pointer to the mantissa of b.
|
||||
MANTTYPE *pchc; // pchc is a pointer to the mantissa of c.
|
||||
long 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.
|
||||
long 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 db; // db is a single 'digit' after possible padding.
|
||||
MANTTYPE cy=0; // cy is the value of a carry after adding two 'digits'
|
||||
long fcompla = 0; // fcompla is a flag to signal a is negative.
|
||||
long fcomplb = 0; // fcomplb is a flag to signal b 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.
|
||||
|
||||
a=*pa;
|
||||
|
||||
|
||||
|
||||
|
||||
// Calculate the overlap of the numbers after alignment, this includes
|
||||
// necessary padding 0's
|
||||
cdigits = max( a->cdigit+a->exp, b->cdigit+b->exp ) -
|
||||
|
@ -90,7 +90,7 @@ void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
pcha = a->mant;
|
||||
pchb = b->mant;
|
||||
pchc = c->mant;
|
||||
|
||||
|
||||
// Figure out the sign of the numbers
|
||||
if ( a->sign != b->sign )
|
||||
{
|
||||
|
@ -98,21 +98,21 @@ void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
fcompla = ( a->sign == -1 );
|
||||
fcomplb = ( b->sign == -1 );
|
||||
}
|
||||
|
||||
|
||||
// Loop over all the digits, real and 0 padded. Here we know a and b are
|
||||
// aligned
|
||||
// aligned
|
||||
for ( ;cdigits > 0; cdigits--, mexp++ )
|
||||
{
|
||||
|
||||
|
||||
// Get digit from a, taking padding into account.
|
||||
da = ( ( ( mexp >= a->exp ) && ( cdigits + a->exp - c->exp >
|
||||
(c->cdigit - a->cdigit) ) ) ?
|
||||
da = ( ( ( mexp >= a->exp ) && ( cdigits + a->exp - c->exp >
|
||||
(c->cdigit - a->cdigit) ) ) ?
|
||||
*pcha++ : 0 );
|
||||
// Get digit from b, taking padding into account.
|
||||
db = ( ( ( mexp >= b->exp ) && ( cdigits + b->exp - c->exp >
|
||||
(c->cdigit - b->cdigit) ) ) ?
|
||||
db = ( ( ( mexp >= b->exp ) && ( cdigits + b->exp - c->exp >
|
||||
(c->cdigit - b->cdigit) ) ) ?
|
||||
*pchb++ : 0 );
|
||||
|
||||
|
||||
// Handle complementing for a and b digit. Might be a better way, but
|
||||
// haven't found it yet.
|
||||
if ( fcompla )
|
||||
|
@ -123,20 +123,20 @@ void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
{
|
||||
db = (MANTTYPE)(radix) - 1 - db;
|
||||
}
|
||||
|
||||
|
||||
// Update carry as necessary
|
||||
cy = da + db + cy;
|
||||
*pchc++ = (MANTTYPE)(cy % (MANTTYPE)radix);
|
||||
cy /= (MANTTYPE)radix;
|
||||
}
|
||||
|
||||
|
||||
// Handle carry from last sum as extra digit
|
||||
if ( cy && !(fcompla || fcomplb) )
|
||||
{
|
||||
*pchc++ = cy;
|
||||
c->cdigit++;
|
||||
}
|
||||
|
||||
|
||||
// Compute sign of result
|
||||
if ( !(fcompla || fcomplb) )
|
||||
{
|
||||
|
@ -150,14 +150,14 @@ void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
}
|
||||
else
|
||||
{
|
||||
// In this particular case an overflow or underflow has occurred
|
||||
// and all the digits need to be complemented, at one time an
|
||||
// attempt to handle this above was made, it turned out to be much
|
||||
// In this particular case an overflow or underflow has occurred
|
||||
// and all the digits need to be complemented, at one time an
|
||||
// attempt to handle this above was made, it turned out to be much
|
||||
// slower on average.
|
||||
c->sign = -1;
|
||||
cy = 1;
|
||||
for ( ( cdigits = c->cdigit ), (pchc = c->mant);
|
||||
cdigits > 0;
|
||||
cdigits > 0;
|
||||
cdigits-- )
|
||||
{
|
||||
cy = (MANTTYPE)radix - (MANTTYPE)1 - *pchc + cy;
|
||||
|
@ -166,7 +166,7 @@ void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Remove leading zeros, remember digits are in order of
|
||||
// increasing significance. i.e. 100 would be 0,0,1
|
||||
while ( c->cdigit > 1 && *(--pchc) == 0 )
|
||||
|
@ -205,7 +205,7 @@ void __inline mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
}
|
||||
else
|
||||
{ // if pa is one and b isn't just copy b, and adjust the sign.
|
||||
long sign = (*pa)->sign;
|
||||
int32_t sign = (*pa)->sign;
|
||||
DUPNUM(*pa,b);
|
||||
(*pa)->sign *= sign;
|
||||
}
|
||||
|
@ -226,14 +226,14 @@ void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
MANTTYPE *pchc; // pchc is a pointer to the mantissa of c.
|
||||
MANTTYPE *pchcoffset; // pchcoffset, is the anchor location of the next
|
||||
// single digit multiply partial result.
|
||||
long iadigit = 0; // Index of digit being used in the first number.
|
||||
long ibdigit = 0; // Index of digit being used in the second 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.
|
||||
MANTTYPE da = 0; // da is the digit from the fist number.
|
||||
TWO_MANTTYPE cy = 0; // cy is the carry resulting from the addition of
|
||||
// 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.
|
||||
long icdigit = 0; // Index of digit being calculated in final result.
|
||||
int32_t icdigit = 0; // Index of digit being calculated in final result.
|
||||
|
||||
a=*pa;
|
||||
ibdigit = a->cdigit + b->cdigit - 1;
|
||||
|
@ -249,8 +249,8 @@ void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
{
|
||||
da = *pcha++;
|
||||
pchb = b->mant;
|
||||
|
||||
// Shift pchc, and pchcoffset, one for each digit
|
||||
|
||||
// Shift pchc, and pchcoffset, one for each digit
|
||||
pchc = pchcoffset++;
|
||||
|
||||
for ( ibdigit = b->cdigit; ibdigit > 0; ibdigit-- )
|
||||
|
@ -268,23 +268,23 @@ void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
// If result is nonzero, or while result of carry is nonzero...
|
||||
while ( mcy || cy )
|
||||
{
|
||||
|
||||
|
||||
// update carry from addition(s) and multiply.
|
||||
cy += (TWO_MANTTYPE)pchc[icdigit]+(mcy%(TWO_MANTTYPE)radix);
|
||||
|
||||
// update result digit from
|
||||
|
||||
// update result digit from
|
||||
pchc[icdigit++]=(MANTTYPE)(cy%(TWO_MANTTYPE)radix);
|
||||
|
||||
|
||||
// update carries from
|
||||
mcy /= (TWO_MANTTYPE)radix;
|
||||
cy /= (TWO_MANTTYPE)radix;
|
||||
}
|
||||
|
||||
|
||||
pchb++;
|
||||
pchc++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// prevent different kinds of zeros, by stripping leading duplicate zeros.
|
||||
// digits are in order of increasing significance.
|
||||
while ( c->cdigit > 1 && c->mant[c->cdigit-1] == 0 )
|
||||
|
@ -317,7 +317,7 @@ void remnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
{
|
||||
PNUMBER tmp = nullptr; // tmp is the working remainder.
|
||||
PNUMBER lasttmp = nullptr; // lasttmp is the last remainder which worked.
|
||||
|
||||
|
||||
// Once *pa is less than b, *pa is the remainder.
|
||||
while ( !lessnum( *pa, b ) )
|
||||
{
|
||||
|
@ -334,22 +334,22 @@ void remnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
}
|
||||
|
||||
destroynum( lasttmp );
|
||||
lasttmp=longtonum( 0, radix);
|
||||
lasttmp=i32tonum( 0, radix);
|
||||
|
||||
while ( lessnum( tmp, *pa ) )
|
||||
while ( lessnum( tmp, *pa ) )
|
||||
{
|
||||
DUPNUM( lasttmp, tmp );
|
||||
addnum( &tmp, tmp, radix);
|
||||
}
|
||||
|
||||
if ( lessnum( *pa, tmp ) )
|
||||
{
|
||||
{
|
||||
// too far, back up...
|
||||
destroynum( tmp );
|
||||
tmp=lasttmp;
|
||||
lasttmp= nullptr;
|
||||
}
|
||||
|
||||
|
||||
// Subtract the working remainder from the remainder holder.
|
||||
tmp->sign = -1*(*pa)->sign;
|
||||
addnum( pa, tmp, radix);
|
||||
|
@ -357,7 +357,7 @@ void remnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
|||
destroynum( tmp );
|
||||
destroynum( lasttmp );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -381,7 +381,7 @@ void __inline divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
|
|||
|
||||
{
|
||||
if ( b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0 )
|
||||
{
|
||||
{
|
||||
// b is not one
|
||||
_divnum( pa, b, radix, precision);
|
||||
}
|
||||
|
@ -394,7 +394,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)
|
||||
{
|
||||
PNUMBER a = *pa;
|
||||
long thismax = precision + 2;
|
||||
int32_t thismax = precision + 2;
|
||||
if (thismax < a->cdigit)
|
||||
{
|
||||
thismax = a->cdigit;
|
||||
|
@ -418,10 +418,10 @@ void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
|
|||
tmp->sign = a->sign;
|
||||
rem->exp = b->cdigit + b->exp - rem->cdigit;
|
||||
|
||||
// Build a table of multiplications of the divisor, this is quicker for
|
||||
// Build a table of multiplications of the divisor, this is quicker for
|
||||
// more than radix 'digits'
|
||||
list<PNUMBER> numberList{ longtonum(0L, radix) };
|
||||
for (unsigned long i = 1; i < radix; i++)
|
||||
list<PNUMBER> numberList{ i32tonum(0L, radix) };
|
||||
for (uint32_t i = 1; i < radix; i++)
|
||||
{
|
||||
PNUMBER newValue = nullptr;
|
||||
DUPNUM(newValue, numberList.front());
|
||||
|
@ -431,8 +431,8 @@ void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
|
|||
}
|
||||
destroynum(tmp);
|
||||
|
||||
long digit;
|
||||
long cdigits = 0;
|
||||
int32_t digit;
|
||||
int32_t cdigits = 0;
|
||||
while (cdigits++ < thismax && !zernum(rem))
|
||||
{
|
||||
digit = radix - 1;
|
||||
|
@ -505,11 +505,11 @@ void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
|
|||
bool equnum( PNUMBER a, PNUMBER b )
|
||||
|
||||
{
|
||||
long diff;
|
||||
int32_t diff;
|
||||
MANTTYPE *pa;
|
||||
MANTTYPE *pb;
|
||||
long cdigits;
|
||||
long ccdigits;
|
||||
int32_t cdigits;
|
||||
int32_t ccdigits;
|
||||
MANTTYPE da;
|
||||
MANTTYPE db;
|
||||
|
||||
|
@ -535,21 +535,21 @@ bool equnum( PNUMBER a, PNUMBER b )
|
|||
pb += b->cdigit - 1;
|
||||
cdigits = max( a->cdigit, b->cdigit );
|
||||
ccdigits = cdigits;
|
||||
|
||||
|
||||
// Loop over all digits until we run out of digits or there is a
|
||||
// difference in the digits.
|
||||
for ( ;cdigits > 0; cdigits-- )
|
||||
{
|
||||
da = ( (cdigits > (ccdigits - a->cdigit) ) ?
|
||||
da = ( (cdigits > (ccdigits - a->cdigit) ) ?
|
||||
*pa-- : 0 );
|
||||
db = ( (cdigits > (ccdigits - b->cdigit) ) ?
|
||||
db = ( (cdigits > (ccdigits - b->cdigit) ) ?
|
||||
*pb-- : 0 );
|
||||
if ( da != db )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// In this case, they are equal.
|
||||
return true;
|
||||
}
|
||||
|
@ -573,11 +573,11 @@ bool equnum( PNUMBER a, PNUMBER b )
|
|||
bool lessnum( PNUMBER a, PNUMBER b )
|
||||
|
||||
{
|
||||
long diff;
|
||||
int32_t diff;
|
||||
MANTTYPE *pa;
|
||||
MANTTYPE *pb;
|
||||
long cdigits;
|
||||
long ccdigits;
|
||||
int32_t cdigits;
|
||||
int32_t ccdigits;
|
||||
MANTTYPE da;
|
||||
MANTTYPE db;
|
||||
|
||||
|
@ -604,9 +604,9 @@ bool lessnum( PNUMBER a, PNUMBER b )
|
|||
ccdigits = cdigits;
|
||||
for ( ;cdigits > 0; cdigits-- )
|
||||
{
|
||||
da = ( (cdigits > (ccdigits - a->cdigit) ) ?
|
||||
da = ( (cdigits > (ccdigits - a->cdigit) ) ?
|
||||
*pa-- : 0 );
|
||||
db = ( (cdigits > (ccdigits - b->cdigit) ) ?
|
||||
db = ( (cdigits > (ccdigits - b->cdigit) ) ?
|
||||
*pb-- : 0 );
|
||||
diff = da-db;
|
||||
if ( diff )
|
||||
|
@ -635,12 +635,12 @@ bool lessnum( PNUMBER a, PNUMBER b )
|
|||
bool zernum( PNUMBER a )
|
||||
|
||||
{
|
||||
long length;
|
||||
int32_t length;
|
||||
MANTTYPE *pcha;
|
||||
length = a->cdigit;
|
||||
pcha = a->mant;
|
||||
|
||||
// loop over all the digits until you find a nonzero or until you run
|
||||
|
||||
// loop over all the digits until you find a nonzero or until you run
|
||||
// out of digits
|
||||
while ( length-- > 0 )
|
||||
{
|
||||
|
|
|
@ -56,7 +56,7 @@ void gcdrat( PRAT *pa, int32_t precision)
|
|||
destroynum( pgcd );
|
||||
*pa=a;
|
||||
|
||||
RENORMALIZE(*pa);
|
||||
RENORMALIZE(*pa);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -82,7 +82,7 @@ void fracrat( PRAT *pa , uint32_t radix, int32_t precision)
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -100,7 +100,7 @@ void fracrat( PRAT *pa , uint32_t radix, int32_t precision)
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
void mulrat( PRAT *pa, PRAT b, int32_t precision)
|
||||
|
||||
|
||||
{
|
||||
// Only do the multiply if it isn't zero.
|
||||
if ( !zernum( (*pa)->pp ) )
|
||||
|
@ -170,7 +170,7 @@ void divrat( PRAT *pa, PRAT b, int32_t precision)
|
|||
|
||||
#ifdef DIVGCD
|
||||
gcdrat( pa );
|
||||
#endif
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
@ -215,13 +215,13 @@ void addrat( PRAT *pa, PRAT b, int32_t precision)
|
|||
|
||||
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
|
||||
// we have to do this since the optimization here is only
|
||||
// we have to do this since the optimization here is only
|
||||
// working with the top half of the rationals.
|
||||
(*pa)->pp->sign *= (*pa)->pq->sign;
|
||||
(*pa)->pp->sign *= (*pa)->pq->sign;
|
||||
(*pa)->pq->sign = 1;
|
||||
b->pp->sign *= b->pq->sign;
|
||||
b->pp->sign *= b->pq->sign;
|
||||
b->pq->sign = 1;
|
||||
addnum( &((*pa)->pp), b->pp, BASEX );
|
||||
}
|
||||
|
@ -236,15 +236,15 @@ void addrat( PRAT *pa, PRAT b, int32_t precision)
|
|||
destroynum( (*pa)->pq );
|
||||
(*pa)->pq = bot;
|
||||
trimit(pa, precision);
|
||||
|
||||
|
||||
// Get rid of negative zeros here.
|
||||
(*pa)->pp->sign *= (*pa)->pq->sign;
|
||||
(*pa)->pp->sign *= (*pa)->pq->sign;
|
||||
(*pa)->pq->sign = 1;
|
||||
}
|
||||
|
||||
#ifdef ADDGCD
|
||||
gcdrat( pa );
|
||||
#endif
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
@ -264,7 +264,7 @@ void addrat( PRAT *pa, PRAT b, int32_t precision)
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
void rootrat( PRAT *py, PRAT n, uint32_t radix, int32_t precision)
|
||||
{
|
||||
{
|
||||
// Initialize 1/n
|
||||
PRAT oneovern= nullptr;
|
||||
DUPRAT(oneovern,rat_one);
|
||||
|
|
|
@ -1,480 +1,482 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_num_one= {
|
||||
#pragma once
|
||||
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_num_one= {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_num_two= {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_num_two= {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 2,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_num_five= {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_num_five= {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 5,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_num_six= {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_num_six= {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 6,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_num_ten= {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_num_ten= {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 10,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_rat_smallest = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_smallest = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
NUMBER init_q_rat_smallest = {
|
||||
inline const NUMBER init_q_rat_smallest = {
|
||||
1,
|
||||
4,
|
||||
0,
|
||||
{ 0, 190439170, 901055854, 10097,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_rat_negsmallest = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_negsmallest = {
|
||||
-1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
NUMBER init_q_rat_negsmallest = {
|
||||
inline const NUMBER init_q_rat_negsmallest = {
|
||||
1,
|
||||
4,
|
||||
0,
|
||||
{ 0, 190439170, 901055854, 10097,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_pt_eight_five = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_pt_eight_five = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 85,}
|
||||
};
|
||||
NUMBER init_q_pt_eight_five = {
|
||||
inline const NUMBER init_q_pt_eight_five = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 100,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_rat_six = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_six = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 6,}
|
||||
};
|
||||
NUMBER init_q_rat_six = {
|
||||
inline const NUMBER init_q_rat_six = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_rat_two = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_two = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 2,}
|
||||
};
|
||||
NUMBER init_q_rat_two = {
|
||||
inline const NUMBER init_q_rat_two = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_rat_zero = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_zero = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 0,}
|
||||
};
|
||||
NUMBER init_q_rat_zero = {
|
||||
inline const NUMBER init_q_rat_zero = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_rat_one = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_one = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
NUMBER init_q_rat_one = {
|
||||
inline const NUMBER init_q_rat_one = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_rat_neg_one = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_neg_one = {
|
||||
-1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
NUMBER init_q_rat_neg_one = {
|
||||
inline const NUMBER init_q_rat_neg_one = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_rat_half = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_half = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
NUMBER init_q_rat_half = {
|
||||
inline const NUMBER init_q_rat_half = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 2,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_rat_ten = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_ten = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 10,}
|
||||
};
|
||||
NUMBER init_q_rat_ten = {
|
||||
inline const NUMBER init_q_rat_ten = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_pi = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_pi = {
|
||||
1,
|
||||
6,
|
||||
0,
|
||||
{ 125527896, 283898350, 1960493936, 1672850762, 1288168272, 8,}
|
||||
};
|
||||
NUMBER init_q_pi = {
|
||||
inline const NUMBER init_q_pi = {
|
||||
1,
|
||||
6,
|
||||
0,
|
||||
{ 1288380402, 1120116153, 1860424692, 1944118326, 1583591604, 2,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_two_pi = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_two_pi = {
|
||||
1,
|
||||
6,
|
||||
0,
|
||||
{ 251055792, 567796700, 1773504224, 1198217877, 428852897, 17,}
|
||||
};
|
||||
NUMBER init_q_two_pi = {
|
||||
inline const NUMBER init_q_two_pi = {
|
||||
1,
|
||||
6,
|
||||
0,
|
||||
{ 1288380402, 1120116153, 1860424692, 1944118326, 1583591604, 2,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_pi_over_two = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_pi_over_two = {
|
||||
1,
|
||||
6,
|
||||
0,
|
||||
{ 125527896, 283898350, 1960493936, 1672850762, 1288168272, 8,}
|
||||
};
|
||||
NUMBER init_q_pi_over_two = {
|
||||
inline const NUMBER init_q_pi_over_two = {
|
||||
1,
|
||||
6,
|
||||
0,
|
||||
{ 429277156, 92748659, 1573365737, 1740753005, 1019699561, 5,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_one_pt_five_pi = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_one_pt_five_pi = {
|
||||
1,
|
||||
6,
|
||||
0,
|
||||
{ 1241201312, 270061909, 1051574664, 1924965045, 1340320627, 70,}
|
||||
};
|
||||
NUMBER init_q_one_pt_five_pi = {
|
||||
inline const NUMBER init_q_one_pt_five_pi = {
|
||||
1,
|
||||
6,
|
||||
0,
|
||||
{ 1579671539, 1837970263, 1067644340, 523549916, 2119366659, 14,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_e_to_one_half = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_e_to_one_half = {
|
||||
1,
|
||||
6,
|
||||
0,
|
||||
{ 256945612, 216219427, 223516738, 477442596, 581063757, 23,}
|
||||
};
|
||||
NUMBER init_q_e_to_one_half = {
|
||||
inline const NUMBER init_q_e_to_one_half = {
|
||||
1,
|
||||
6,
|
||||
0,
|
||||
{ 1536828363, 698484484, 1127331835, 224219346, 245499408, 14,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_rat_exp = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_exp = {
|
||||
1,
|
||||
6,
|
||||
0,
|
||||
{ 943665199, 1606559160, 1094967530, 1759391384, 1671799163, 1123581,}
|
||||
};
|
||||
NUMBER init_q_rat_exp = {
|
||||
inline const NUMBER init_q_rat_exp = {
|
||||
1,
|
||||
6,
|
||||
0,
|
||||
{ 879242208, 2022880100, 617392930, 1374929092, 1367479163, 413342,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_ln_ten = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_ln_ten = {
|
||||
1,
|
||||
6,
|
||||
0,
|
||||
{ 2086268922, 165794492, 1416063951, 1851428830, 1893239400, 65366841,}
|
||||
};
|
||||
NUMBER init_q_ln_ten = {
|
||||
inline const NUMBER init_q_ln_ten = {
|
||||
1,
|
||||
6,
|
||||
0,
|
||||
{ 26790652, 564532679, 783998273, 216030448, 1564709968, 28388458,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_ln_two = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_ln_two = {
|
||||
1,
|
||||
6,
|
||||
0,
|
||||
{ 1789230241, 1057927868, 715399197, 908801241, 1411265331, 3,}
|
||||
};
|
||||
NUMBER init_q_ln_two = {
|
||||
inline const NUMBER init_q_ln_two = {
|
||||
1,
|
||||
6,
|
||||
0,
|
||||
{ 1559869847, 1930657510, 1228561531, 219003871, 593099283, 5,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_rad_to_deg = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rad_to_deg = {
|
||||
1,
|
||||
6,
|
||||
0,
|
||||
{ 2127722024, 1904928383, 2016479213, 2048947859, 1578647346, 492,}
|
||||
};
|
||||
NUMBER init_q_rad_to_deg = {
|
||||
inline const NUMBER init_q_rad_to_deg = {
|
||||
1,
|
||||
6,
|
||||
0,
|
||||
{ 125527896, 283898350, 1960493936, 1672850762, 1288168272, 8,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_rad_to_grad = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rad_to_grad = {
|
||||
1,
|
||||
6,
|
||||
0,
|
||||
{ 2125526288, 684931327, 570267400, 129125085, 1038224725, 547,}
|
||||
};
|
||||
NUMBER init_q_rad_to_grad = {
|
||||
inline const NUMBER init_q_rad_to_grad = {
|
||||
1,
|
||||
6,
|
||||
0,
|
||||
{ 125527896, 283898350, 1960493936, 1672850762, 1288168272, 8,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_rat_qword = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_qword = {
|
||||
1,
|
||||
3,
|
||||
0,
|
||||
{ 2147483647, 2147483647, 3,}
|
||||
};
|
||||
NUMBER init_q_rat_qword = {
|
||||
inline const NUMBER init_q_rat_qword = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_rat_dword = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_dword = {
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
{ 2147483647, 1,}
|
||||
};
|
||||
NUMBER init_q_rat_dword = {
|
||||
inline const NUMBER init_q_rat_dword = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_rat_max_long = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_max_i32 = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 2147483647,}
|
||||
};
|
||||
NUMBER init_q_rat_max_long = {
|
||||
inline const NUMBER init_q_rat_max_i32 = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_rat_min_long = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_min_i32 = {
|
||||
-1,
|
||||
2,
|
||||
0,
|
||||
{ 0, 1,}
|
||||
};
|
||||
NUMBER init_q_rat_min_long = {
|
||||
inline const NUMBER init_q_rat_min_i32 = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_rat_word = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_word = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 65535,}
|
||||
};
|
||||
NUMBER init_q_rat_word = {
|
||||
inline const NUMBER init_q_rat_word = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_rat_byte = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_byte = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 255,}
|
||||
};
|
||||
NUMBER init_q_rat_byte = {
|
||||
inline const NUMBER init_q_rat_byte = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_rat_400 = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_400 = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 400,}
|
||||
};
|
||||
NUMBER init_q_rat_400 = {
|
||||
inline const NUMBER init_q_rat_400 = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_rat_360 = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_360 = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 360,}
|
||||
};
|
||||
NUMBER init_q_rat_360 = {
|
||||
inline const NUMBER init_q_rat_360 = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_rat_200 = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_200 = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 200,}
|
||||
};
|
||||
NUMBER init_q_rat_200 = {
|
||||
inline const NUMBER init_q_rat_200 = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_rat_180 = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_180 = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 180,}
|
||||
};
|
||||
NUMBER init_q_rat_180 = {
|
||||
inline const NUMBER init_q_rat_180 = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_rat_max_exp = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_max_exp = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 100000,}
|
||||
};
|
||||
NUMBER init_q_rat_max_exp = {
|
||||
inline const NUMBER init_q_rat_max_exp = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_rat_min_exp = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_min_exp = {
|
||||
-1,
|
||||
1,
|
||||
0,
|
||||
{ 100000,}
|
||||
};
|
||||
NUMBER init_q_rat_min_exp = {
|
||||
inline const NUMBER init_q_rat_min_exp = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 1,}
|
||||
};
|
||||
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_rat_max_fact = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_max_fact = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 3249, }
|
||||
};
|
||||
NUMBER init_q_rat_max_fact = {
|
||||
inline const NUMBER init_q_rat_max_fact = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
{ 1, }
|
||||
};
|
||||
|
||||
// Autogenerated by _dumprawrat in support.c
|
||||
NUMBER init_p_rat_min_fact = {
|
||||
// Autogenerated by _dumprawrat in support.cpp
|
||||
inline const NUMBER init_p_rat_min_fact = {
|
||||
-1,
|
||||
1,
|
||||
0,
|
||||
{ 1000, }
|
||||
};
|
||||
NUMBER init_q_rat_min_fact = {
|
||||
inline const NUMBER init_q_rat_min_fact = {
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
|
|
|
@ -24,8 +24,8 @@ static constexpr uint32_t BASEX = 0x80000000; // Internal radix used in calculat
|
|||
// this to 2^32 after solving scaling problems with
|
||||
// overflow detection esp. in mul
|
||||
|
||||
typedef unsigned long MANTTYPE;
|
||||
typedef unsigned __int64 TWO_MANTTYPE;
|
||||
typedef uint32_t MANTTYPE;
|
||||
typedef uint64_t TWO_MANTTYPE;
|
||||
|
||||
enum eNUMOBJ_FMT {
|
||||
FMT_FLOAT, // returns floating point, or exponential if number is too big
|
||||
|
@ -54,10 +54,10 @@ typedef enum eANGLE_TYPE ANGLE_TYPE;
|
|||
#pragma warning(disable:4200) // nonstandard extension used : zero-sized array in struct/union
|
||||
typedef struct _number
|
||||
{
|
||||
long sign; // The sign of the mantissa, +1, or -1
|
||||
long cdigit; // The number of digits, or what passes for digits in the
|
||||
int32_t sign; // The sign of the mantissa, +1, or -1
|
||||
int32_t cdigit; // The number of digits, or what passes for digits in the
|
||||
// radix being used.
|
||||
long exp; // The offset of digits from the radix point
|
||||
int32_t exp; // The offset of digits from the radix point
|
||||
// (decimal point in radix 10)
|
||||
MANTTYPE mant[];
|
||||
// This is actually allocated as a continuation of the
|
||||
|
@ -127,8 +127,8 @@ extern PRAT rat_max_exp;
|
|||
extern PRAT rat_min_exp;
|
||||
extern PRAT rat_max_fact;
|
||||
extern PRAT rat_min_fact;
|
||||
extern PRAT rat_max_long;
|
||||
extern PRAT rat_min_long;
|
||||
extern PRAT rat_max_i32;
|
||||
extern PRAT rat_min_i32;
|
||||
|
||||
// DUPNUM Duplicates a number taking care of allocation and internals
|
||||
#define DUPNUM(a,b) destroynum(a);createnum( a, (b)->cdigit );_dupnum(a, b);
|
||||
|
@ -208,7 +208,7 @@ _destroynum(x),(x)=nullptr
|
|||
|
||||
// TRIMNUM ASSUMES the number is in radix form NOT INTERNAL BASEX!!!
|
||||
#define TRIMNUM(x, precision) if ( !g_ftrueinfinite ) { \
|
||||
long trim = (x)->cdigit - precision-g_ratio;\
|
||||
int32_t trim = (x)->cdigit - precision-g_ratio;\
|
||||
if ( trim > 1 ) \
|
||||
{ \
|
||||
memmove( (x)->mant, &((x)->mant[trim]), sizeof(MANTTYPE)*((x)->cdigit-trim) ); \
|
||||
|
@ -218,14 +218,14 @@ memmove( (x)->mant, &((x)->mant[trim]), sizeof(MANTTYPE)*((x)->cdigit-trim) ); \
|
|||
}
|
||||
// TRIMTOP ASSUMES the number is in INTERNAL BASEX!!!
|
||||
#define TRIMTOP(x, precision) if ( !g_ftrueinfinite ) { \
|
||||
long trim = (x)->pp->cdigit - (precision/g_ratio) - 2;\
|
||||
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->exp += trim; \
|
||||
} \
|
||||
trim = min((x)->pp->exp,(x)->pq->exp);\
|
||||
trim = std::min((x)->pp->exp,(x)->pq->exp);\
|
||||
(x)->pp->exp -= trim;\
|
||||
(x)->pq->exp -= trim;\
|
||||
}
|
||||
|
@ -246,8 +246,8 @@ memmove( (x)->pp->mant, &((x)->pp->mant[trim]), sizeof(MANTTYPE)*((x)->pp->cdigi
|
|||
DUPRAT(xx,*px); \
|
||||
mulrat(&xx,*px, precision); \
|
||||
createrat(pret); \
|
||||
pret->pp=longtonum( 0L, BASEX ); \
|
||||
pret->pq=longtonum( 0L, BASEX );
|
||||
pret->pp=i32tonum( 0L, BASEX ); \
|
||||
pret->pq=i32tonum( 0L, BASEX );
|
||||
|
||||
#define DESTROYTAYLOR() destroynum( n2 ); \
|
||||
destroyrat( xx );\
|
||||
|
@ -294,7 +294,7 @@ extern bool g_ftrueinfinite; // set to true to allow infinite precision
|
|||
// don't use unless you know what you are doing
|
||||
// used to help decide when to stop calculating.
|
||||
|
||||
extern long g_ratio; // Internally calculated ratio of internal radix
|
||||
extern int32_t g_ratio; // Internally calculated ratio of internal radix
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
|
@ -321,10 +321,10 @@ 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
|
||||
extern void flatrat(_Inout_ PRAT& prat, uint32_t radix, int32_t precision);
|
||||
|
||||
extern long numtolong(_In_ PNUMBER pnum, uint32_t radix );
|
||||
extern long rattolong(_In_ PRAT prat, uint32_t radix, int32_t precision);
|
||||
ULONGLONG rattoUlonglong(_In_ PRAT prat, uint32_t radix, int32_t precision);
|
||||
extern PNUMBER _createnum(_In_ ULONG size ); // returns an empty number structure with size digits
|
||||
extern int32_t numtoi32(_In_ PNUMBER pnum, uint32_t radix );
|
||||
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);
|
||||
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 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.
|
||||
|
@ -332,10 +332,10 @@ extern PNUMBER StringToNumber(std::wstring_view numberString, uint32_t radix, in
|
|||
// 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 PNUMBER longfactnum(long inlong, uint32_t radix);
|
||||
extern PNUMBER longprodnum(long start, long stop, uint32_t radix);
|
||||
extern PNUMBER longtonum(long inlong, uint32_t radix);
|
||||
extern PNUMBER Ulongtonum(unsigned long inlong, 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 i32tonum(int32_t ini32, uint32_t radix);
|
||||
extern PNUMBER Ui32tonum(uint32_t ini32, uint32_t radix);
|
||||
extern PNUMBER numtonRadixx(PNUMBER a, uint32_t radix);
|
||||
|
||||
// creates a empty/undefined rational representation (p/q)
|
||||
|
@ -393,8 +393,8 @@ extern void log10rat( _Inout_ PRAT *px, int32_t precision);
|
|||
// returns a new rat structure with the natural log of x->p/x->q
|
||||
extern void lograt( _Inout_ PRAT *px, int32_t precision);
|
||||
|
||||
extern PRAT longtorat( long inlong );
|
||||
extern PRAT Ulongtorat( unsigned long inulong );
|
||||
extern PRAT i32torat( int32_t ini32 );
|
||||
extern PRAT Ui32torat( uint32_t inui32 );
|
||||
extern PRAT numtorat( _In_ PNUMBER pin, uint32_t radix);
|
||||
|
||||
extern void sinhrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
|
||||
|
@ -411,7 +411,7 @@ extern void tanrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
|
|||
// angle type
|
||||
extern void tananglerat( _Inout_ PRAT *px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
|
||||
|
||||
extern void _dupnum(_In_ PNUMBER dest, _In_ PNUMBER src);
|
||||
extern void _dupnum(_In_ PNUMBER dest, _In_ const NUMBER * const src);
|
||||
|
||||
extern void _destroynum( _In_ PNUMBER pnum );
|
||||
extern void _destroyrat( _In_ PRAT prat );
|
||||
|
@ -429,13 +429,13 @@ 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 mulnumx( _Inout_ PNUMBER *pa, _In_ PNUMBER b );
|
||||
extern void mulrat( _Inout_ PRAT *pa, _In_ PRAT b, int32_t precision);
|
||||
extern void numpowlong( _Inout_ PNUMBER *proot, long power, uint32_t radix, int32_t precision);
|
||||
extern void numpowlongx( _Inout_ PNUMBER *proot, long power );
|
||||
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 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 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 ratpowlong( _Inout_ PRAT *proot, long 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 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);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -31,8 +31,8 @@ static int cbitsofprecision = 0;
|
|||
#define READRAWNUM(v)
|
||||
#define DUMPRAWRAT(v) _dumprawrat(#v,v, wcout)
|
||||
#define DUMPRAWNUM(v) fprintf( stderr, \
|
||||
"// Autogenerated by _dumprawrat in support.c\n" ); \
|
||||
fprintf( stderr, "NUMBER init_" #v "= {\n" ); \
|
||||
"// Autogenerated by _dumprawrat in support.cpp\n" ); \
|
||||
fprintf( stderr, "inline const NUMBER init_" #v "= {\n" ); \
|
||||
_dumprawnum(v, wcout); \
|
||||
fprintf( stderr, "};\n" )
|
||||
|
||||
|
@ -45,8 +45,8 @@ static int cbitsofprecision = 0;
|
|||
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 = longtonum(v, BASEX); DUMPRAWNUM(v); }
|
||||
#define INIT_AND_DUMP_RAW_RAT_IF_NULL(r, v) if (r == nullptr) { r = longtorat(v); DUMPRAWRAT(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_RAT_IF_NULL(r, v) if (r == nullptr) { r = i32torat(v); DUMPRAWRAT(v); }
|
||||
|
||||
static constexpr int RATIO_FOR_DECIMAL = 9;
|
||||
static constexpr int DECIMAL = 10;
|
||||
|
@ -58,7 +58,7 @@ static int cbitsofprecision = RATIO_FOR_DECIMAL * DECIMAL * CALC_DECIMAL_DIGITS_
|
|||
|
||||
#endif
|
||||
|
||||
bool g_ftrueinfinite = false; // Set to true if you don't want
|
||||
bool g_ftrueinfinite = false; // Set to true if you don't want
|
||||
// chopping internally
|
||||
// precision used internally
|
||||
|
||||
|
@ -87,7 +87,7 @@ PRAT rat_exp= nullptr;
|
|||
PRAT rad_to_deg= nullptr;
|
||||
PRAT rad_to_grad= nullptr;
|
||||
PRAT rat_qword= nullptr;
|
||||
PRAT rat_dword= nullptr; // unsigned max ulong
|
||||
PRAT rat_dword= nullptr; // unsigned max ui32
|
||||
PRAT rat_word= nullptr;
|
||||
PRAT rat_byte= nullptr;
|
||||
PRAT rat_360= nullptr;
|
||||
|
@ -101,8 +101,8 @@ PRAT rat_max_exp= nullptr;
|
|||
PRAT rat_min_exp= nullptr;
|
||||
PRAT rat_max_fact = nullptr;
|
||||
PRAT rat_min_fact = nullptr;
|
||||
PRAT rat_min_long= nullptr; // min signed long
|
||||
PRAT rat_max_long= nullptr; // max signed long
|
||||
PRAT rat_min_i32= nullptr; // min signed i32
|
||||
PRAT rat_max_i32= nullptr; // max signed i32
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
|
@ -119,8 +119,8 @@ PRAT rat_max_long= nullptr; // max signed long
|
|||
|
||||
void ChangeConstants(uint32_t radix, int32_t precision)
|
||||
{
|
||||
// ratio is set to the number of digits in the current radix, you can get
|
||||
// in the internal BASEX radix, this is important for length calculations
|
||||
// ratio is set to the number of digits in the current radix, you can get
|
||||
// in the internal BASEX radix, this is important for length calculations
|
||||
// in translating from radix to BASEX and back.
|
||||
|
||||
uint64_t limit = static_cast<uint64_t>(BASEX) / static_cast<uint64_t>(radix);
|
||||
|
@ -132,7 +132,7 @@ void ChangeConstants(uint32_t radix, int32_t precision)
|
|||
g_ratio += !g_ratio;
|
||||
|
||||
destroyrat(rat_nRadix);
|
||||
rat_nRadix=longtorat( radix );
|
||||
rat_nRadix=i32torat( radix );
|
||||
|
||||
// Check to see what we have to recalculate and what we don't
|
||||
if (cbitsofprecision < (g_ratio * static_cast<int32_t>(radix) * precision))
|
||||
|
@ -166,7 +166,7 @@ void ChangeConstants(uint32_t radix, int32_t precision)
|
|||
INIT_AND_DUMP_RAW_RAT_IF_NULL(rat_min_fact, -1000);
|
||||
|
||||
DUPRAT(rat_smallest, rat_nRadix);
|
||||
ratpowlong(&rat_smallest, -precision, precision);
|
||||
ratpowi32(&rat_smallest, -precision, precision);
|
||||
DUPRAT(rat_negsmallest, rat_smallest);
|
||||
rat_negsmallest->pp->sign = -1;
|
||||
DUMPRAWRAT(rat_smallest);
|
||||
|
@ -183,29 +183,29 @@ void ChangeConstants(uint32_t radix, int32_t precision)
|
|||
if (pt_eight_five == nullptr)
|
||||
{
|
||||
createrat(pt_eight_five);
|
||||
pt_eight_five->pp = longtonum(85L, BASEX);
|
||||
pt_eight_five->pq = longtonum(100L, BASEX);
|
||||
pt_eight_five->pp = i32tonum(85L, BASEX);
|
||||
pt_eight_five->pq = i32tonum(100L, BASEX);
|
||||
DUMPRAWRAT(pt_eight_five);
|
||||
}
|
||||
|
||||
DUPRAT(rat_qword, rat_two);
|
||||
numpowlong(&(rat_qword->pp), 64, BASEX, precision);
|
||||
numpowi32(&(rat_qword->pp), 64, BASEX, precision);
|
||||
subrat(&rat_qword, rat_one, precision);
|
||||
DUMPRAWRAT(rat_qword);
|
||||
|
||||
DUPRAT(rat_dword, rat_two);
|
||||
numpowlong(&(rat_dword->pp), 32, BASEX, precision);
|
||||
numpowi32(&(rat_dword->pp), 32, BASEX, precision);
|
||||
subrat(&rat_dword, rat_one, precision);
|
||||
DUMPRAWRAT(rat_dword);
|
||||
|
||||
DUPRAT(rat_max_long, rat_two);
|
||||
numpowlong(&(rat_max_long->pp), 31, BASEX, precision);
|
||||
DUPRAT(rat_min_long, rat_max_long);
|
||||
subrat(&rat_max_long, rat_one, precision); // rat_max_long = 2^31 -1
|
||||
DUMPRAWRAT(rat_max_long);
|
||||
DUPRAT(rat_max_i32, rat_two);
|
||||
numpowi32(&(rat_max_i32->pp), 31, BASEX, precision);
|
||||
DUPRAT(rat_min_i32, rat_max_i32);
|
||||
subrat(&rat_max_i32, rat_one, precision); // rat_max_i32 = 2^31 -1
|
||||
DUMPRAWRAT(rat_max_i32);
|
||||
|
||||
rat_min_long->pp->sign *= -1; // rat_min_long = -2^31
|
||||
DUMPRAWRAT(rat_min_long);
|
||||
rat_min_i32->pp->sign *= -1; // rat_min_i32 = -2^31
|
||||
DUMPRAWRAT(rat_min_i32);
|
||||
|
||||
DUPRAT(rat_min_exp, rat_max_exp);
|
||||
rat_min_exp->pp->sign *= -1;
|
||||
|
@ -213,9 +213,9 @@ void ChangeConstants(uint32_t radix, int32_t precision)
|
|||
|
||||
cbitsofprecision = g_ratio * radix * precision;
|
||||
|
||||
// Apparently when dividing 180 by pi, another (internal) digit of
|
||||
// Apparently when dividing 180 by pi, another (internal) digit of
|
||||
// precision is needed.
|
||||
long extraPrecision = precision + g_ratio;
|
||||
int32_t extraPrecision = precision + g_ratio;
|
||||
DUPRAT(pi, rat_half);
|
||||
asinrat(&pi, radix, extraPrecision);
|
||||
mulrat(&pi, rat_six, extraPrecision);
|
||||
|
@ -253,12 +253,12 @@ void ChangeConstants(uint32_t radix, int32_t precision)
|
|||
|
||||
|
||||
destroyrat(rad_to_deg);
|
||||
rad_to_deg = longtorat(180L);
|
||||
rad_to_deg = i32torat(180L);
|
||||
divrat(&rad_to_deg, pi, extraPrecision);
|
||||
DUMPRAWRAT(rad_to_deg);
|
||||
|
||||
destroyrat(rad_to_grad);
|
||||
rad_to_grad = longtorat(200L);
|
||||
rad_to_grad = i32torat(200L);
|
||||
divrat(&rad_to_grad, pi, extraPrecision);
|
||||
DUMPRAWRAT(rad_to_grad);
|
||||
}
|
||||
|
@ -267,7 +267,7 @@ void ChangeConstants(uint32_t radix, int32_t precision)
|
|||
_readconstants();
|
||||
|
||||
DUPRAT(rat_smallest, rat_nRadix);
|
||||
ratpowlong(&rat_smallest, -precision, precision);
|
||||
ratpowi32(&rat_smallest, -precision, precision);
|
||||
DUPRAT(rat_negsmallest, rat_smallest);
|
||||
rat_negsmallest->pp->sign = -1;
|
||||
}
|
||||
|
@ -333,7 +333,7 @@ bool rat_equ( PRAT a, PRAT b, int32_t precision)
|
|||
//
|
||||
// FUNCTION: rat_ge
|
||||
//
|
||||
// ARGUMENTS: PRAT a, PRAT b and long precision
|
||||
// ARGUMENTS: PRAT a, PRAT b and int32_t precision
|
||||
//
|
||||
// RETURN: true if a is greater than or equal to b
|
||||
//
|
||||
|
@ -348,7 +348,7 @@ bool rat_ge( PRAT a, PRAT b, int32_t precision)
|
|||
b->pp->sign *= -1;
|
||||
addrat( &rattmp, b, precision);
|
||||
b->pp->sign *= -1;
|
||||
bool bret = ( zernum( rattmp->pp ) ||
|
||||
bool bret = ( zernum( rattmp->pp ) ||
|
||||
rattmp->pp->sign * rattmp->pq->sign == 1 );
|
||||
destroyrat( rattmp );
|
||||
return( bret );
|
||||
|
@ -384,7 +384,7 @@ bool rat_gt( PRAT a, PRAT b, int32_t precision)
|
|||
//
|
||||
// FUNCTION: rat_le
|
||||
//
|
||||
// ARGUMENTS: PRAT a, PRAT b and long precision
|
||||
// ARGUMENTS: PRAT a, PRAT b and int32_t precision
|
||||
//
|
||||
// RETURN: true if a is less than or equal to b
|
||||
//
|
||||
|
@ -411,7 +411,7 @@ bool rat_le( PRAT a, PRAT b, int32_t precision)
|
|||
//
|
||||
// FUNCTION: rat_lt
|
||||
//
|
||||
// ARGUMENTS: PRAT a, PRAT b and long precision
|
||||
// ARGUMENTS: PRAT a, PRAT b and int32_t precision
|
||||
//
|
||||
// RETURN: true if a is less than b
|
||||
//
|
||||
|
@ -472,10 +472,10 @@ void scale( PRAT *px, PRAT scalefact, uint32_t radix, int32_t precision )
|
|||
{
|
||||
PRAT pret = nullptr;
|
||||
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.
|
||||
long 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) );
|
||||
if ( logscale > 0 )
|
||||
{
|
||||
|
@ -508,9 +508,9 @@ void scale2pi( PRAT *px, uint32_t radix, int32_t precision )
|
|||
PRAT my_two_pi = nullptr;
|
||||
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.
|
||||
long 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) );
|
||||
if ( logscale > 0 )
|
||||
{
|
||||
|
@ -652,27 +652,27 @@ void _readconstants( void )
|
|||
READRAWRAT(rat_min_exp);
|
||||
READRAWRAT(rat_max_fact);
|
||||
READRAWRAT(rat_min_fact);
|
||||
READRAWRAT(rat_min_long);
|
||||
READRAWRAT(rat_max_long);
|
||||
READRAWRAT(rat_min_i32);
|
||||
READRAWRAT(rat_max_i32);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: trimit
|
||||
//
|
||||
// ARGUMENTS: PRAT *px, long precision
|
||||
// ARGUMENTS: PRAT *px, int32_t precision
|
||||
//
|
||||
//
|
||||
// DESCRIPTION: Chops off digits from rational numbers to avoid time
|
||||
// explosions in calculations of functions using series.
|
||||
// It can be shown that it is enough to only keep the first n digits
|
||||
// of the largest of p or q in the rational p over q form, and of course
|
||||
// scale the smaller by the same number of digits. This will give you
|
||||
// n-1 digits of accuracy. This dramatically speeds up calculations
|
||||
// DESCRIPTION: Chops off digits from rational numbers to avoid time
|
||||
// explosions in calculations of functions using series.
|
||||
// It can be shown that it is enough to only keep the first n digits
|
||||
// of the largest of p or q in the rational p over q form, and of course
|
||||
// scale the smaller by the same number of digits. This will give you
|
||||
// n-1 digits of accuracy. This dramatically speeds up calculations
|
||||
// involving hundreds of digits or more.
|
||||
// The last part of this trim dealing with exponents never affects accuracy
|
||||
//
|
||||
// RETURN: none, modifies the pointed to PRAT
|
||||
// RETURN: none, modifies the pointed to PRAT
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
@ -680,8 +680,8 @@ void trimit( PRAT *px, int32_t precision)
|
|||
|
||||
{
|
||||
if ( !g_ftrueinfinite )
|
||||
{
|
||||
long trim;
|
||||
{
|
||||
int32_t trim;
|
||||
PNUMBER pp=(*px)->pp;
|
||||
PNUMBER pq=(*px)->pq;
|
||||
trim = g_ratio * (min((pp->cdigit+pp->exp),(pq->cdigit+pq->exp))-1) - precision;
|
||||
|
|
|
@ -47,8 +47,8 @@ void scalerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t p
|
|||
// EXPLANATION: This uses Taylor series
|
||||
//
|
||||
// n
|
||||
// ___ 2j+1
|
||||
// \ ] j X
|
||||
// ___ 2j+1
|
||||
// \ ] j X
|
||||
// \ -1 * ---------
|
||||
// / (2j+1)!
|
||||
// /__]
|
||||
|
@ -73,7 +73,7 @@ void _sinrat( PRAT *px, int32_t precision)
|
|||
{
|
||||
CREATETAYLOR();
|
||||
|
||||
DUPRAT(pret,*px);
|
||||
DUPRAT(pret,*px);
|
||||
DUPRAT(thisterm,*px);
|
||||
|
||||
DUPNUM(n2,num_one);
|
||||
|
@ -84,11 +84,11 @@ void _sinrat( PRAT *px, int32_t precision)
|
|||
} while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
|
||||
|
||||
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.
|
||||
inbetween(px, rat_one, precision);
|
||||
|
||||
|
||||
// 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) )
|
||||
{
|
||||
|
@ -166,14 +166,14 @@ void _cosrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
CREATETAYLOR();
|
||||
|
||||
destroynum(pret->pp);
|
||||
destroynum(pret->pq);
|
||||
destroynum(pret->pq);
|
||||
|
||||
pret->pp=longtonum( 1L, radix);
|
||||
pret->pq=longtonum( 1L, radix);
|
||||
pret->pp=i32tonum( 1L, radix);
|
||||
pret->pq=i32tonum( 1L, radix);
|
||||
|
||||
DUPRAT(thisterm,pret)
|
||||
|
||||
n2=longtonum(0L, radix);
|
||||
|
||||
n2=i32tonum(0L, radix);
|
||||
xx->pp->sign *= -1;
|
||||
|
||||
do {
|
||||
|
@ -181,7 +181,7 @@ void _cosrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
} while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
|
||||
|
||||
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.
|
||||
inbetween(px, rat_one, precision);
|
||||
// Since *px might be epsilon near zero we must set it to zero.
|
||||
|
|
|
@ -80,7 +80,7 @@ void _sinhrat( PRAT *px, int32_t precision)
|
|||
|
||||
CREATETAYLOR();
|
||||
|
||||
DUPRAT(pret,*px);
|
||||
DUPRAT(pret,*px);
|
||||
DUPRAT(thisterm,pret);
|
||||
|
||||
DUPNUM(n2,num_one);
|
||||
|
@ -159,12 +159,12 @@ void _coshrat( PRAT *px, uint32_t radix, int32_t precision)
|
|||
|
||||
CREATETAYLOR();
|
||||
|
||||
pret->pp=longtonum( 1L, radix);
|
||||
pret->pq=longtonum( 1L, radix);
|
||||
pret->pp=i32tonum( 1L, radix);
|
||||
pret->pq=i32tonum( 1L, radix);
|
||||
|
||||
DUPRAT(thisterm,pret)
|
||||
|
||||
n2=longtonum(0L, radix);
|
||||
n2=i32tonum(0L, radix);
|
||||
|
||||
do {
|
||||
NEXTTERM(xx,INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
|
@ -194,7 +194,7 @@ void coshrat( PRAT *px, uint32_t radix, int32_t 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.
|
||||
if ( rat_lt(*px, rat_one, precision) )
|
||||
{
|
||||
|
|
|
@ -46,7 +46,7 @@ UnitConverter::UnitConverter(_In_ const shared_ptr<IConverterDataLoader>& dataLo
|
|||
{
|
||||
m_dataLoader = dataLoader;
|
||||
m_currencyDataLoader = currencyDataLoader;
|
||||
//declaring the delimiter character conversion map
|
||||
// declaring the delimiter character conversion map
|
||||
quoteConversions[L'|'] = L"{p}";
|
||||
quoteConversions[L'['] = L"{lc}";
|
||||
quoteConversions[L']'] = L"{rc}";
|
||||
|
@ -90,7 +90,7 @@ vector<Category> UnitConverter::GetCategories()
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the current category in use by this converter,
|
||||
/// Sets the current category in use by this converter,
|
||||
/// and returns a list of unit types that exist under the given category.
|
||||
/// </summary>
|
||||
/// <param name="input">Category struct which we are setting</param>
|
||||
|
@ -109,22 +109,8 @@ CategorySelectionInitializer UnitConverter::SetCurrentCategory(const Category& i
|
|||
vector<Unit>& unitVector = m_categoryToUnits[m_currentCategory];
|
||||
for (unsigned int i = 0; i < unitVector.size(); i++)
|
||||
{
|
||||
if (unitVector[i].id == m_fromType.id)
|
||||
{
|
||||
unitVector[i].isConversionSource = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
unitVector[i].isConversionSource = false;
|
||||
}
|
||||
if (unitVector[i].id == m_toType.id)
|
||||
{
|
||||
unitVector[i].isConversionTarget = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
unitVector[i].isConversionTarget = false;
|
||||
}
|
||||
unitVector[i].isConversionSource = (unitVector[i].id == m_fromType.id);
|
||||
unitVector[i].isConversionTarget = (unitVector[i].id == m_toType.id);
|
||||
}
|
||||
m_currentCategory = input;
|
||||
if (!m_currentCategory.supportsNegative && m_currentDisplay.front() == L'-')
|
||||
|
@ -156,21 +142,23 @@ Category UnitConverter::GetCurrentCategory()
|
|||
/// <param name="toType">Unit struct we are converting to</param>
|
||||
void UnitConverter::SetCurrentUnitTypes(const Unit& fromType, const Unit& toType)
|
||||
{
|
||||
if (CheckLoad())
|
||||
if (!CheckLoad())
|
||||
{
|
||||
m_fromType = fromType;
|
||||
m_toType = toType;
|
||||
Calculate();
|
||||
|
||||
UpdateCurrencySymbols();
|
||||
UpdateViewModel();
|
||||
return;
|
||||
}
|
||||
|
||||
m_fromType = fromType;
|
||||
m_toType = toType;
|
||||
Calculate();
|
||||
|
||||
UpdateCurrencySymbols();
|
||||
UpdateViewModel();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Switches the active field, indicating that we are now entering data into
|
||||
/// what was originally the return field, and storing results into what was
|
||||
/// originally the current field. We swap appropriate values,
|
||||
/// originally the current field. We swap appropriate values,
|
||||
/// but do not callback, as values have not changed.
|
||||
/// </summary>
|
||||
/// <param name="newValue">
|
||||
|
@ -181,22 +169,24 @@ void UnitConverter::SetCurrentUnitTypes(const Unit& fromType, const Unit& toType
|
|||
/// </param>
|
||||
void UnitConverter::SwitchActive(const wstring& newValue)
|
||||
{
|
||||
if (CheckLoad())
|
||||
if (!CheckLoad())
|
||||
{
|
||||
swap(m_fromType, m_toType);
|
||||
swap(m_currentHasDecimal, m_returnHasDecimal);
|
||||
m_returnDisplay = m_currentDisplay;
|
||||
m_currentDisplay = newValue;
|
||||
m_currentHasDecimal = (m_currentDisplay.find(L'.') != m_currentDisplay.npos);
|
||||
m_switchedActive = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_currencyDataLoader != nullptr && m_vmCurrencyCallback != nullptr)
|
||||
{
|
||||
shared_ptr<ICurrencyConverterDataLoader> currencyDataLoader = GetCurrencyConverterDataLoader();
|
||||
const pair<wstring, wstring> currencyRatios = currencyDataLoader->GetCurrencyRatioEquality(m_fromType, m_toType);
|
||||
swap(m_fromType, m_toType);
|
||||
swap(m_currentHasDecimal, m_returnHasDecimal);
|
||||
m_returnDisplay = m_currentDisplay;
|
||||
m_currentDisplay = newValue;
|
||||
m_currentHasDecimal = (m_currentDisplay.find(L'.') != m_currentDisplay.npos);
|
||||
m_switchedActive = true;
|
||||
|
||||
m_vmCurrencyCallback->CurrencyRatiosCallback(currencyRatios.first, currencyRatios.second);
|
||||
}
|
||||
if (m_currencyDataLoader != nullptr && m_vmCurrencyCallback != nullptr)
|
||||
{
|
||||
shared_ptr<ICurrencyConverterDataLoader> currencyDataLoader = GetCurrencyConverterDataLoader();
|
||||
const pair<wstring, wstring> currencyRatios = currencyDataLoader->GetCurrencyRatioEquality(m_fromType, m_toType);
|
||||
|
||||
m_vmCurrencyCallback->CurrencyRatiosCallback(currencyRatios.first, currencyRatios.second);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -291,55 +281,53 @@ wstring UnitConverter::ConversionDataToString(ConversionData d, const wchar_t *
|
|||
/// </summary>
|
||||
wstring UnitConverter::Serialize()
|
||||
{
|
||||
if (CheckLoad())
|
||||
{
|
||||
wstringstream out(wstringstream::out);
|
||||
const wchar_t * delimiter = L";";
|
||||
|
||||
out << UnitToString(m_fromType, delimiter) << "|";
|
||||
out << UnitToString(m_toType, 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 << m_currentDisplay << delimiter << m_returnDisplay << delimiter << "|";
|
||||
wstringstream categoryString(wstringstream::out);
|
||||
wstringstream categoryToUnitString(wstringstream::out);
|
||||
wstringstream unitToUnitToDoubleString(wstringstream::out);
|
||||
for (const Category& c : m_categories)
|
||||
{
|
||||
categoryString << CategoryToString(c, delimiter) << ",";
|
||||
}
|
||||
|
||||
for (const auto& cur : m_categoryToUnits)
|
||||
{
|
||||
categoryToUnitString << CategoryToString(cur.first, delimiter) << "[";
|
||||
for (const Unit& u : cur.second)
|
||||
{
|
||||
categoryToUnitString << UnitToString(u, delimiter) << ",";
|
||||
}
|
||||
categoryToUnitString << "[" << "]";
|
||||
}
|
||||
|
||||
for (const auto& cur : m_ratioMap)
|
||||
{
|
||||
unitToUnitToDoubleString << UnitToString(cur.first, delimiter) << "[";
|
||||
for (const auto& curConversion : cur.second)
|
||||
{
|
||||
unitToUnitToDoubleString << UnitToString(curConversion.first, delimiter) << ":";
|
||||
unitToUnitToDoubleString << ConversionDataToString(curConversion.second, delimiter) << ":,";
|
||||
}
|
||||
unitToUnitToDoubleString << "[" << "]";
|
||||
}
|
||||
|
||||
out << categoryString.str() << "|";
|
||||
out << categoryToUnitString.str() << "|";
|
||||
out << unitToUnitToDoubleString.str() << "|";
|
||||
wstring test = out.str();
|
||||
return test;
|
||||
}
|
||||
else
|
||||
if (!CheckLoad())
|
||||
{
|
||||
return wstring();
|
||||
}
|
||||
|
||||
wstringstream out(wstringstream::out);
|
||||
const wchar_t * delimiter = L";";
|
||||
|
||||
out << UnitToString(m_fromType, delimiter) << "|";
|
||||
out << UnitToString(m_toType, 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 << m_currentDisplay << delimiter << m_returnDisplay << delimiter << "|";
|
||||
wstringstream categoryString(wstringstream::out);
|
||||
wstringstream categoryToUnitString(wstringstream::out);
|
||||
wstringstream unitToUnitToDoubleString(wstringstream::out);
|
||||
for (const Category& c : m_categories)
|
||||
{
|
||||
categoryString << CategoryToString(c, delimiter) << ",";
|
||||
}
|
||||
|
||||
for (const auto& cur : m_categoryToUnits)
|
||||
{
|
||||
categoryToUnitString << CategoryToString(cur.first, delimiter) << "[";
|
||||
for (const Unit& u : cur.second)
|
||||
{
|
||||
categoryToUnitString << UnitToString(u, delimiter) << ",";
|
||||
}
|
||||
categoryToUnitString << "[" << "]";
|
||||
}
|
||||
|
||||
for (const auto& cur : m_ratioMap)
|
||||
{
|
||||
unitToUnitToDoubleString << UnitToString(cur.first, delimiter) << "[";
|
||||
for (const auto& curConversion : cur.second)
|
||||
{
|
||||
unitToUnitToDoubleString << UnitToString(curConversion.first, delimiter) << ":";
|
||||
unitToUnitToDoubleString << ConversionDataToString(curConversion.second, delimiter) << ":,";
|
||||
}
|
||||
unitToUnitToDoubleString << "[" << "]";
|
||||
}
|
||||
|
||||
out << categoryString.str() << "|";
|
||||
out << categoryToUnitString.str() << "|";
|
||||
out << unitToUnitToDoubleString.str() << "|";
|
||||
wstring test = out.str();
|
||||
return test;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -349,55 +337,58 @@ wstring UnitConverter::Serialize()
|
|||
void UnitConverter::DeSerialize(const wstring& serializedData)
|
||||
{
|
||||
Reset();
|
||||
if (!serializedData.empty())
|
||||
|
||||
if (serializedData.empty())
|
||||
{
|
||||
vector<wstring> outerTokens = StringToVector(serializedData, L"|");
|
||||
assert(outerTokens.size() == EXPECTEDSERIALIZEDTOKENCOUNT);
|
||||
m_fromType = StringToUnit(outerTokens[0]);
|
||||
m_toType = StringToUnit(outerTokens[1]);
|
||||
m_currentCategory = StringToCategory(outerTokens[2]);
|
||||
vector<wstring> stateDataTokens = StringToVector(outerTokens[3], L";");
|
||||
assert(stateDataTokens.size() == EXPECTEDSTATEDATATOKENCOUNT);
|
||||
m_currentHasDecimal = (stateDataTokens[0].compare(L"1") == 0);
|
||||
m_returnHasDecimal = (stateDataTokens[1].compare(L"1") == 0);
|
||||
m_switchedActive = (stateDataTokens[2].compare(L"1") == 0);
|
||||
m_currentDisplay = stateDataTokens[3];
|
||||
m_returnDisplay = stateDataTokens[4];
|
||||
vector<wstring> categoryListTokens = StringToVector(outerTokens[4], L",");
|
||||
for (wstring token : categoryListTokens)
|
||||
{
|
||||
m_categories.push_back(StringToCategory(token));
|
||||
}
|
||||
vector<wstring> unitVectorTokens = StringToVector(outerTokens[5], L"]");
|
||||
for (wstring unitVector : unitVectorTokens)
|
||||
{
|
||||
vector<wstring> mapcomponents = StringToVector(unitVector, L"[");
|
||||
assert(mapcomponents.size() == EXPECTEDMAPCOMPONENTTOKENCOUNT);
|
||||
Category key = StringToCategory(mapcomponents[0]);
|
||||
vector<wstring> units = StringToVector(mapcomponents[1], L",");
|
||||
for (wstring unit : units)
|
||||
{
|
||||
m_categoryToUnits[key].push_back(StringToUnit(unit));
|
||||
}
|
||||
}
|
||||
vector<wstring> ratioMapTokens = StringToVector(outerTokens[6], L"]");
|
||||
for (wstring token : ratioMapTokens)
|
||||
{
|
||||
vector<wstring> ratioMapComponentTokens = StringToVector(token, L"[");
|
||||
assert(ratioMapComponentTokens.size() == EXPECTEDMAPCOMPONENTTOKENCOUNT);
|
||||
Unit key = StringToUnit(ratioMapComponentTokens[0]);
|
||||
vector<wstring> ratioMapList = StringToVector(ratioMapComponentTokens[1], L",");
|
||||
for (wstring subtoken : ratioMapList)
|
||||
{
|
||||
vector<wstring> ratioMapSubComponentTokens = StringToVector(subtoken, L":");
|
||||
assert(ratioMapSubComponentTokens.size() == EXPECTEDMAPCOMPONENTTOKENCOUNT);
|
||||
Unit subkey = StringToUnit(ratioMapSubComponentTokens[0]);
|
||||
ConversionData conversion = StringToConversionData(ratioMapSubComponentTokens[1]);
|
||||
m_ratioMap[key][subkey] = conversion;
|
||||
}
|
||||
}
|
||||
UpdateViewModel();
|
||||
return;
|
||||
}
|
||||
|
||||
vector<wstring> outerTokens = StringToVector(serializedData, L"|");
|
||||
assert(outerTokens.size() == EXPECTEDSERIALIZEDTOKENCOUNT);
|
||||
m_fromType = StringToUnit(outerTokens[0]);
|
||||
m_toType = StringToUnit(outerTokens[1]);
|
||||
m_currentCategory = StringToCategory(outerTokens[2]);
|
||||
vector<wstring> stateDataTokens = StringToVector(outerTokens[3], L";");
|
||||
assert(stateDataTokens.size() == EXPECTEDSTATEDATATOKENCOUNT);
|
||||
m_currentHasDecimal = (stateDataTokens[0].compare(L"1") == 0);
|
||||
m_returnHasDecimal = (stateDataTokens[1].compare(L"1") == 0);
|
||||
m_switchedActive = (stateDataTokens[2].compare(L"1") == 0);
|
||||
m_currentDisplay = stateDataTokens[3];
|
||||
m_returnDisplay = stateDataTokens[4];
|
||||
vector<wstring> categoryListTokens = StringToVector(outerTokens[4], L",");
|
||||
for (wstring token : categoryListTokens)
|
||||
{
|
||||
m_categories.push_back(StringToCategory(token));
|
||||
}
|
||||
vector<wstring> unitVectorTokens = StringToVector(outerTokens[5], L"]");
|
||||
for (wstring unitVector : unitVectorTokens)
|
||||
{
|
||||
vector<wstring> mapcomponents = StringToVector(unitVector, L"[");
|
||||
assert(mapcomponents.size() == EXPECTEDMAPCOMPONENTTOKENCOUNT);
|
||||
Category key = StringToCategory(mapcomponents[0]);
|
||||
vector<wstring> units = StringToVector(mapcomponents[1], L",");
|
||||
for (wstring unit : units)
|
||||
{
|
||||
m_categoryToUnits[key].push_back(StringToUnit(unit));
|
||||
}
|
||||
}
|
||||
vector<wstring> ratioMapTokens = StringToVector(outerTokens[6], L"]");
|
||||
for (wstring token : ratioMapTokens)
|
||||
{
|
||||
vector<wstring> ratioMapComponentTokens = StringToVector(token, L"[");
|
||||
assert(ratioMapComponentTokens.size() == EXPECTEDMAPCOMPONENTTOKENCOUNT);
|
||||
Unit key = StringToUnit(ratioMapComponentTokens[0]);
|
||||
vector<wstring> ratioMapList = StringToVector(ratioMapComponentTokens[1], L",");
|
||||
for (wstring subtoken : ratioMapList)
|
||||
{
|
||||
vector<wstring> ratioMapSubComponentTokens = StringToVector(subtoken, L":");
|
||||
assert(ratioMapSubComponentTokens.size() == EXPECTEDMAPCOMPONENTTOKENCOUNT);
|
||||
Unit subkey = StringToUnit(ratioMapSubComponentTokens[0]);
|
||||
ConversionData conversion = StringToConversionData(ratioMapSubComponentTokens[1]);
|
||||
m_ratioMap[key][subkey] = conversion;
|
||||
}
|
||||
}
|
||||
UpdateViewModel();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -406,21 +397,23 @@ void UnitConverter::DeSerialize(const wstring& serializedData)
|
|||
/// <param name="userPreferences">wstring holding the serialized data. If it does not have expected number of parameters, we will ignore it</param>
|
||||
void UnitConverter::RestoreUserPreferences(const wstring& userPreferences)
|
||||
{
|
||||
if (!userPreferences.empty())
|
||||
if (userPreferences.empty())
|
||||
{
|
||||
vector<wstring> outerTokens = StringToVector(userPreferences, L"|");
|
||||
if (outerTokens.size() == 3)
|
||||
{
|
||||
m_fromType = StringToUnit(outerTokens[0]);
|
||||
m_toType = StringToUnit(outerTokens[1]);
|
||||
m_currentCategory = StringToCategory(outerTokens[2]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
vector<wstring> outerTokens = StringToVector(userPreferences, L"|");
|
||||
if (outerTokens.size() == 3)
|
||||
{
|
||||
m_fromType = StringToUnit(outerTokens[0]);
|
||||
m_toType = StringToUnit(outerTokens[1]);
|
||||
m_currentCategory = StringToCategory(outerTokens[2]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serializes the Category and Associated Units in the converter and returns it as a string
|
||||
/// </summary>
|
||||
/// </summary>
|
||||
wstring UnitConverter::SaveUserPreferences()
|
||||
{
|
||||
wstringstream out(wstringstream::out);
|
||||
|
@ -441,7 +434,7 @@ wstring UnitConverter::Quote(const wstring& s)
|
|||
{
|
||||
wstringstream quotedString(wstringstream::out);
|
||||
|
||||
//Iterate over the delimiter characters we need to quote
|
||||
// Iterate over the delimiter characters we need to quote
|
||||
wstring::const_iterator cursor = s.begin();
|
||||
while(cursor != s.end())
|
||||
{
|
||||
|
@ -479,7 +472,7 @@ wstring UnitConverter::Unquote(const wstring& s)
|
|||
}
|
||||
if (cursor == s.end())
|
||||
{
|
||||
//badly formatted
|
||||
// Badly formatted
|
||||
break;
|
||||
}
|
||||
else
|
||||
|
@ -503,144 +496,146 @@ wstring UnitConverter::Unquote(const wstring& s)
|
|||
/// <param name="command">Command enum representing the command that was entered</param>
|
||||
void UnitConverter::SendCommand(Command command)
|
||||
{
|
||||
if (CheckLoad())
|
||||
if (!CheckLoad())
|
||||
{
|
||||
//TODO: Localization of characters
|
||||
bool clearFront = false;
|
||||
if (m_currentDisplay == L"0")
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Localization of characters
|
||||
bool clearFront = false;
|
||||
if (m_currentDisplay == L"0")
|
||||
{
|
||||
clearFront = true;
|
||||
}
|
||||
bool clearBack = false;
|
||||
if ((m_currentHasDecimal && m_currentDisplay.size() - 1 >= MAXIMUMDIGITSALLOWED) || (!m_currentHasDecimal && m_currentDisplay.size() >= MAXIMUMDIGITSALLOWED))
|
||||
{
|
||||
clearBack = true;
|
||||
}
|
||||
if (command != Command::Negate && m_switchedActive)
|
||||
{
|
||||
ClearValues();
|
||||
m_switchedActive = false;
|
||||
clearFront = true;
|
||||
clearBack = false;
|
||||
}
|
||||
switch (command)
|
||||
{
|
||||
case Command::Zero:
|
||||
m_currentDisplay += L"0";
|
||||
break;
|
||||
|
||||
case Command::One:
|
||||
m_currentDisplay += L"1";
|
||||
break;
|
||||
|
||||
case Command::Two:
|
||||
m_currentDisplay += L"2";
|
||||
break;
|
||||
|
||||
case Command::Three:
|
||||
m_currentDisplay += L"3";
|
||||
break;
|
||||
|
||||
case Command::Four:
|
||||
m_currentDisplay += L"4";
|
||||
break;
|
||||
|
||||
case Command::Five:
|
||||
m_currentDisplay += L"5";
|
||||
break;
|
||||
|
||||
case Command::Six:
|
||||
m_currentDisplay += L"6";
|
||||
break;
|
||||
|
||||
case Command::Seven:
|
||||
m_currentDisplay += L"7";
|
||||
break;
|
||||
|
||||
case Command::Eight:
|
||||
m_currentDisplay += L"8";
|
||||
break;
|
||||
|
||||
case Command::Nine:
|
||||
m_currentDisplay += L"9";
|
||||
break;
|
||||
|
||||
case Command::Decimal:
|
||||
clearFront = false;
|
||||
clearBack = false;
|
||||
if (!m_currentHasDecimal)
|
||||
{
|
||||
clearFront = true;
|
||||
m_currentDisplay += L".";
|
||||
m_currentHasDecimal = true;
|
||||
}
|
||||
bool clearBack = false;
|
||||
if ((m_currentHasDecimal && m_currentDisplay.size() - 1 >= MAXIMUMDIGITSALLOWED) || (!m_currentHasDecimal && m_currentDisplay.size() >= MAXIMUMDIGITSALLOWED))
|
||||
break;
|
||||
|
||||
case Command::Backspace:
|
||||
clearFront = false;
|
||||
clearBack = false;
|
||||
if ((m_currentDisplay.front() != '-' && m_currentDisplay.size() > 1) || m_currentDisplay.size() > 2)
|
||||
{
|
||||
clearBack = true;
|
||||
}
|
||||
if (command != Command::Negate && m_switchedActive)
|
||||
{
|
||||
ClearValues();
|
||||
m_switchedActive = false;
|
||||
clearFront = true;
|
||||
clearBack = false;
|
||||
}
|
||||
switch (command)
|
||||
{
|
||||
case Command::Zero:
|
||||
m_currentDisplay += L"0";
|
||||
break;
|
||||
|
||||
case Command::One:
|
||||
m_currentDisplay += L"1";
|
||||
break;
|
||||
|
||||
case Command::Two:
|
||||
m_currentDisplay += L"2";
|
||||
break;
|
||||
|
||||
case Command::Three:
|
||||
m_currentDisplay += L"3";
|
||||
break;
|
||||
|
||||
case Command::Four:
|
||||
m_currentDisplay += L"4";
|
||||
break;
|
||||
|
||||
case Command::Five:
|
||||
m_currentDisplay += L"5";
|
||||
break;
|
||||
|
||||
case Command::Six:
|
||||
m_currentDisplay += L"6";
|
||||
break;
|
||||
|
||||
case Command::Seven:
|
||||
m_currentDisplay += L"7";
|
||||
break;
|
||||
|
||||
case Command::Eight:
|
||||
m_currentDisplay += L"8";
|
||||
break;
|
||||
|
||||
case Command::Nine:
|
||||
m_currentDisplay += L"9";
|
||||
break;
|
||||
|
||||
case Command::Decimal:
|
||||
clearFront = false;
|
||||
clearBack = false;
|
||||
if (!m_currentHasDecimal)
|
||||
if (m_currentDisplay.back() == '.')
|
||||
{
|
||||
m_currentDisplay += L".";
|
||||
m_currentHasDecimal = true;
|
||||
m_currentHasDecimal = false;
|
||||
}
|
||||
break;
|
||||
m_currentDisplay.pop_back();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_currentDisplay = L"0";
|
||||
m_currentHasDecimal = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case Command::Backspace:
|
||||
clearFront = false;
|
||||
clearBack = false;
|
||||
if ((m_currentDisplay.front() != '-' && m_currentDisplay.size() > 1) || m_currentDisplay.size() > 2)
|
||||
case Command::Negate:
|
||||
clearFront = false;
|
||||
clearBack = false;
|
||||
if (m_currentCategory.supportsNegative)
|
||||
{
|
||||
if (m_currentDisplay.front() == '-')
|
||||
{
|
||||
if (m_currentDisplay.back() == '.')
|
||||
{
|
||||
m_currentHasDecimal = false;
|
||||
}
|
||||
m_currentDisplay.pop_back();
|
||||
m_currentDisplay.erase(0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_currentDisplay = L"0";
|
||||
m_currentHasDecimal = false;
|
||||
m_currentDisplay.insert(0, 1, '-');
|
||||
}
|
||||
break;
|
||||
|
||||
case Command::Negate:
|
||||
clearFront = false;
|
||||
clearBack = false;
|
||||
if (m_currentCategory.supportsNegative)
|
||||
{
|
||||
if (m_currentDisplay.front() == '-')
|
||||
{
|
||||
m_currentDisplay.erase(0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_currentDisplay.insert(0, 1, '-');
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Command::Clear:
|
||||
clearFront = false;
|
||||
clearBack = false;
|
||||
ClearValues();
|
||||
break;
|
||||
|
||||
case Command::Reset:
|
||||
clearFront = false;
|
||||
clearBack = false;
|
||||
ClearValues();
|
||||
Reset();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
if (clearFront)
|
||||
{
|
||||
m_currentDisplay.erase(0, 1);
|
||||
}
|
||||
if (clearBack)
|
||||
{
|
||||
m_currentDisplay.erase(m_currentDisplay.size() - 1, 1);
|
||||
m_vmCallback->MaxDigitsReached();
|
||||
}
|
||||
case Command::Clear:
|
||||
clearFront = false;
|
||||
clearBack = false;
|
||||
ClearValues();
|
||||
break;
|
||||
|
||||
Calculate();
|
||||
case Command::Reset:
|
||||
clearFront = false;
|
||||
clearBack = false;
|
||||
ClearValues();
|
||||
Reset();
|
||||
break;
|
||||
|
||||
UpdateViewModel();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (clearFront)
|
||||
{
|
||||
m_currentDisplay.erase(0, 1);
|
||||
}
|
||||
if (clearBack)
|
||||
{
|
||||
m_currentDisplay.erase(m_currentDisplay.size() - 1, 1);
|
||||
m_vmCallback->MaxDigitsReached();
|
||||
}
|
||||
|
||||
Calculate();
|
||||
|
||||
UpdateViewModel();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -728,7 +723,7 @@ vector<tuple<wstring, Unit>> UnitConverter::CalculateSuggested()
|
|||
vector<SuggestedValueIntermediate> intermediateVector;
|
||||
vector<SuggestedValueIntermediate> intermediateWhimsicalVector;
|
||||
unordered_map<Unit, ConversionData, UnitHash> ratios = m_ratioMap[m_fromType];
|
||||
//Calculate converted values for every other unit type in this category, along with their magnitude
|
||||
// Calculate converted values for every other unit type in this category, along with their magnitude
|
||||
for (const auto& cur : ratios)
|
||||
{
|
||||
if (cur.first != m_fromType && cur.first != m_toType)
|
||||
|
@ -745,21 +740,21 @@ vector<tuple<wstring, Unit>> UnitConverter::CalculateSuggested()
|
|||
}
|
||||
}
|
||||
|
||||
//Sort the resulting list by absolute magnitude, breaking ties by choosing the positive value
|
||||
// Sort the resulting list by absolute magnitude, breaking ties by choosing the positive value
|
||||
sort(intermediateVector.begin(), intermediateVector.end(), []
|
||||
(SuggestedValueIntermediate first, SuggestedValueIntermediate second)
|
||||
{
|
||||
if (abs(first.magnitude) == abs(second.magnitude))
|
||||
{
|
||||
return first.magnitude > second.magnitude;
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
if (abs(first.magnitude) == abs(second.magnitude))
|
||||
{
|
||||
return first.magnitude > second.magnitude;
|
||||
}
|
||||
else
|
||||
{
|
||||
return abs(first.magnitude) < abs(second.magnitude);
|
||||
}
|
||||
});
|
||||
|
||||
//Now that the list is sorted, iterate over it and populate the return vector with properly rounded and formatted return strings
|
||||
// Now that the list is sorted, iterate over it and populate the return vector with properly rounded and formatted return strings
|
||||
for (const auto& entry : intermediateVector)
|
||||
{
|
||||
wstring roundedString;
|
||||
|
@ -783,7 +778,7 @@ vector<tuple<wstring, Unit>> UnitConverter::CalculateSuggested()
|
|||
}
|
||||
|
||||
// The Whimsicals are determined differently
|
||||
//Sort the resulting list by absolute magnitude, breaking ties by choosing the positive value
|
||||
// Sort the resulting list by absolute magnitude, breaking ties by choosing the positive value
|
||||
sort(intermediateWhimsicalVector.begin(), intermediateWhimsicalVector.end(), []
|
||||
(SuggestedValueIntermediate first, SuggestedValueIntermediate second)
|
||||
{
|
||||
|
@ -797,7 +792,7 @@ vector<tuple<wstring, Unit>> UnitConverter::CalculateSuggested()
|
|||
}
|
||||
});
|
||||
|
||||
//Now that the list is sorted, iterate over it and populate the return vector with properly rounded and formatted return strings
|
||||
// Now that the list is sorted, iterate over it and populate the return vector with properly rounded and formatted return strings
|
||||
vector<tuple<wstring, Unit>> whimsicalReturnVector;
|
||||
|
||||
for (const auto& entry : intermediateWhimsicalVector)
|
||||
|
@ -844,47 +839,49 @@ void UnitConverter::Reset()
|
|||
ClearValues();
|
||||
m_switchedActive = false;
|
||||
|
||||
if (!m_categories.empty())
|
||||
if (m_categories.empty())
|
||||
{
|
||||
m_currentCategory = m_categories[0];
|
||||
return;
|
||||
}
|
||||
|
||||
m_categoryToUnits.clear();
|
||||
m_ratioMap.clear();
|
||||
bool readyCategoryFound = false;
|
||||
for (const Category& category : m_categories)
|
||||
m_currentCategory = m_categories[0];
|
||||
|
||||
m_categoryToUnits.clear();
|
||||
m_ratioMap.clear();
|
||||
bool readyCategoryFound = false;
|
||||
for (const Category& category : m_categories)
|
||||
{
|
||||
shared_ptr<IConverterDataLoader> activeDataLoader = GetDataLoaderForCategory(category);
|
||||
if (activeDataLoader == nullptr)
|
||||
{
|
||||
shared_ptr<IConverterDataLoader> activeDataLoader = GetDataLoaderForCategory(category);
|
||||
if (activeDataLoader == nullptr)
|
||||
{
|
||||
// The data loader is different depending on the category, e.g. currency data loader
|
||||
// is different from the static data loader.
|
||||
// If there is no data loader for this category, continue.
|
||||
continue;
|
||||
}
|
||||
|
||||
vector<Unit> units = activeDataLoader->LoadOrderedUnits(category);
|
||||
m_categoryToUnits[category] = units;
|
||||
|
||||
// Just because the units are empty, doesn't mean the user can't select this category,
|
||||
// we just want to make sure we don't let an unready category be the default.
|
||||
if (!units.empty())
|
||||
{
|
||||
for (Unit u : units)
|
||||
{
|
||||
m_ratioMap[u] = activeDataLoader->LoadOrderedRatios(u);
|
||||
}
|
||||
|
||||
if (!readyCategoryFound)
|
||||
{
|
||||
m_currentCategory = category;
|
||||
readyCategoryFound = true;
|
||||
}
|
||||
}
|
||||
// The data loader is different depending on the category, e.g. currency data loader
|
||||
// is different from the static data loader.
|
||||
// If there is no data loader for this category, continue.
|
||||
continue;
|
||||
}
|
||||
|
||||
InitializeSelectedUnits();
|
||||
Calculate();
|
||||
vector<Unit> units = activeDataLoader->LoadOrderedUnits(category);
|
||||
m_categoryToUnits[category] = units;
|
||||
|
||||
// Just because the units are empty, doesn't mean the user can't select this category,
|
||||
// we just want to make sure we don't let an unready category be the default.
|
||||
if (!units.empty())
|
||||
{
|
||||
for (Unit u : units)
|
||||
{
|
||||
m_ratioMap[u] = activeDataLoader->LoadOrderedRatios(u);
|
||||
}
|
||||
|
||||
if (!readyCategoryFound)
|
||||
{
|
||||
m_currentCategory = category;
|
||||
readyCategoryFound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
InitializeSelectedUnits();
|
||||
Calculate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -1029,22 +1026,24 @@ void UnitConverter::Calculate()
|
|||
/// <param name="input">wstring to trim</param>
|
||||
void UnitConverter::TrimString(wstring& returnString)
|
||||
{
|
||||
if (returnString.find(L'.') != m_returnDisplay.npos)
|
||||
if (returnString.find(L'.') == m_returnDisplay.npos)
|
||||
{
|
||||
wstring::iterator iter;
|
||||
for (iter = returnString.end() - 1; ;iter--)
|
||||
return;
|
||||
}
|
||||
|
||||
wstring::iterator iter;
|
||||
for (iter = returnString.end() - 1; ;iter--)
|
||||
{
|
||||
if (*iter != L'0')
|
||||
{
|
||||
if (*iter != L'0')
|
||||
{
|
||||
returnString.erase(iter + 1, returnString.end());
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (*(returnString.end()-1) == L'.')
|
||||
{
|
||||
returnString.erase(returnString.end()-1, returnString.end());
|
||||
returnString.erase(iter + 1, returnString.end());
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (*(returnString.end()-1) == L'.')
|
||||
{
|
||||
returnString.erase(returnString.end()-1, returnString.end());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -51,7 +51,7 @@ namespace UnitConversionManager
|
|||
// null checks.
|
||||
//
|
||||
// unitId, name, abbreviation, isConversionSource, isConversionTarget, isWhimsical
|
||||
const Unit EMPTY_UNIT = Unit{ -1, L"", L"", true, true, false };
|
||||
inline const Unit EMPTY_UNIT = Unit{ -1, L"", L"", true, true, false };
|
||||
|
||||
struct Category
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
@ -7,15 +7,21 @@
|
|||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
// Windows headers define min/max macros.
|
||||
// Disable it for project code.
|
||||
#define NOMINMAX
|
||||
|
||||
#include <assert.h>
|
||||
#include <windows.h>
|
||||
#include <winerror.h>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
#include <list>
|
||||
#include <regex>
|
||||
#include <unordered_map>
|
||||
#include <intsafe.h>
|
||||
|
|
|
@ -32,14 +32,11 @@ using namespace Windows::UI::Xaml::Data;
|
|||
using namespace Windows::UI::Xaml::Input;
|
||||
using namespace Windows::UI::Xaml::Media;
|
||||
|
||||
namespace CalculatorApp::ViewModel::ApplicationViewModelProperties
|
||||
namespace
|
||||
{
|
||||
StringReference Mode(L"Mode");
|
||||
StringReference PreviousMode(L"PreviousMode");
|
||||
StringReference ClearMemoryVisibility(L"ClearMemoryVisibility");
|
||||
StringReference AppBarVisibility(L"AppBarVisibility");
|
||||
StringReference CategoryName(L"CategoryName");
|
||||
StringReference Categories(L"Categories");
|
||||
StringReference CategoriesPropertyName(L"Categories");
|
||||
StringReference ClearMemoryVisibilityPropertyName(L"ClearMemoryVisibility");
|
||||
StringReference AppBarVisibilityPropertyName(L"AppBarVisibility");
|
||||
}
|
||||
|
||||
ApplicationViewModel::ApplicationViewModel() :
|
||||
|
@ -60,7 +57,7 @@ void ApplicationViewModel::Mode::set(ViewMode value)
|
|||
PreviousMode = m_mode;
|
||||
m_mode = value;
|
||||
OnModeChanged();
|
||||
RaisePropertyChanged(ApplicationViewModelProperties::Mode);
|
||||
RaisePropertyChanged(ModePropertyName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,7 +66,7 @@ void ApplicationViewModel::Categories::set(IObservableVector<NavCategoryGroup^>^
|
|||
if (m_categories != value)
|
||||
{
|
||||
m_categories = value;
|
||||
RaisePropertyChanged(ApplicationViewModelProperties::Categories);
|
||||
RaisePropertyChanged(CategoriesPropertyName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,11 +160,11 @@ void ApplicationViewModel::OnModeChanged()
|
|||
//
|
||||
// Save the changed mode, so that the new window launches in this mode.
|
||||
// Don't save until after we have adjusted to the new mode, so we don't save a mode that fails to load.
|
||||
ApplicationData::Current->LocalSettings->Values->Insert(ApplicationViewModelProperties::Mode, NavCategory::Serialize(m_mode));
|
||||
ApplicationData::Current->LocalSettings->Values->Insert(ModePropertyName, NavCategory::Serialize(m_mode));
|
||||
|
||||
TraceLogger::GetInstance().LogModeChangeEnd(m_mode, ApplicationView::GetApplicationViewIdForWindow(CoreWindow::GetForCurrentThread()));
|
||||
RaisePropertyChanged(ApplicationViewModelProperties::ClearMemoryVisibility);
|
||||
RaisePropertyChanged(ApplicationViewModelProperties::AppBarVisibility);
|
||||
RaisePropertyChanged(ClearMemoryVisibilityPropertyName);
|
||||
RaisePropertyChanged(AppBarVisibilityPropertyName);
|
||||
}
|
||||
|
||||
void ApplicationViewModel::OnCopyCommand(Object^ parameter)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
@ -11,16 +11,6 @@ namespace CalculatorApp
|
|||
{
|
||||
namespace ViewModel
|
||||
{
|
||||
namespace ApplicationViewModelProperties
|
||||
{
|
||||
extern Platform::StringReference Mode;
|
||||
extern Platform::StringReference PreviousMode;
|
||||
extern Platform::StringReference ClearMemoryVisibility;
|
||||
extern Platform::StringReference AppBarVisibility;
|
||||
extern Platform::StringReference CategoryName;
|
||||
extern Platform::StringReference Categories;
|
||||
}
|
||||
|
||||
[Windows::UI::Xaml::Data::Bindable]
|
||||
public ref class ApplicationViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
|
||||
{
|
||||
|
@ -32,9 +22,9 @@ namespace CalculatorApp
|
|||
OBSERVABLE_OBJECT();
|
||||
OBSERVABLE_PROPERTY_RW(StandardCalculatorViewModel^, CalculatorViewModel);
|
||||
OBSERVABLE_PROPERTY_RW(DateCalculatorViewModel^, DateCalcViewModel);
|
||||
OBSERVABLE_PROPERTY_RW(CalculatorApp::ViewModel::UnitConverterViewModel^, ConverterViewModel);
|
||||
OBSERVABLE_PROPERTY_RW(UnitConverterViewModel^, ConverterViewModel);
|
||||
OBSERVABLE_PROPERTY_RW(CalculatorApp::Common::ViewMode, PreviousMode);
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String^, CategoryName);
|
||||
OBSERVABLE_NAMED_PROPERTY_RW(Platform::String^, CategoryName);
|
||||
|
||||
COMMAND_FOR_METHOD(CopyCommand, ApplicationViewModel::OnCopyCommand);
|
||||
COMMAND_FOR_METHOD(PasteCommand, ApplicationViewModel::OnPasteCommand);
|
||||
|
@ -48,6 +38,13 @@ namespace CalculatorApp
|
|||
|
||||
void set(CalculatorApp::Common::ViewMode value);
|
||||
}
|
||||
static property Platform::String^ ModePropertyName
|
||||
{
|
||||
Platform::String^ get()
|
||||
{
|
||||
return Platform::StringReference(L"Mode");
|
||||
}
|
||||
}
|
||||
|
||||
property Windows::Foundation::Collections::IObservableVector<CalculatorApp::Common::NavCategoryGroup^>^ Categories
|
||||
{
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
namespace CalculatorApp { namespace Common
|
||||
namespace CalculatorApp { namespace Common
|
||||
{
|
||||
ref class AlwaysSelectedCollectionView sealed:
|
||||
ref class AlwaysSelectedCollectionView sealed:
|
||||
public Windows::UI::Xaml::DependencyObject,
|
||||
public Windows::UI::Xaml::Data::ICollectionView
|
||||
{
|
||||
|
@ -14,11 +14,11 @@ namespace CalculatorApp { namespace Common
|
|||
m_currentPosition(-1)
|
||||
{
|
||||
m_source = source;
|
||||
|
||||
|
||||
Windows::UI::Xaml::Interop::IBindableObservableVector^ observable = dynamic_cast<Windows::UI::Xaml::Interop::IBindableObservableVector^>(source);
|
||||
if (observable)
|
||||
{
|
||||
observable->VectorChanged +=
|
||||
observable->VectorChanged +=
|
||||
ref new Windows::UI::Xaml::Interop::BindableVectorChangedEventHandler(this, &AlwaysSelectedCollectionView::OnSourceBindableVectorChanged);
|
||||
}
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ namespace CalculatorApp { namespace Common
|
|||
return ref new Platform::Collections::Vector<Platform::Object^>();
|
||||
}
|
||||
}
|
||||
property bool HasMoreItems
|
||||
property bool HasMoreItems
|
||||
{
|
||||
virtual bool get() = Windows::UI::Xaml::Data::ICollectionView::HasMoreItems::get
|
||||
{
|
||||
|
@ -77,7 +77,7 @@ namespace CalculatorApp { namespace Common
|
|||
}
|
||||
|
||||
// The item is not in the collection
|
||||
// We're going to schedule a call back later so we
|
||||
// We're going to schedule a call back later so we
|
||||
// restore the selection to the way we wanted it to begin with
|
||||
if (m_currentPosition >= 0 && m_currentPosition < static_cast<int>(m_source->Size))
|
||||
{
|
||||
|
@ -161,7 +161,7 @@ namespace CalculatorApp { namespace Common
|
|||
m_currentChanging -= token;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// IVector<Object^>
|
||||
// Not implemented methods
|
||||
virtual void Append(Platform::Object^ /*item*/) = Windows::Foundation::Collections::IVector<Platform::Object^>::Append
|
||||
|
@ -219,7 +219,7 @@ namespace CalculatorApp { namespace Common
|
|||
return m_source->Size;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// IObservableVector<Object^>
|
||||
event Windows::Foundation::Collections::VectorChangedEventHandler<Platform::Object^>^ VectorChanged
|
||||
{
|
||||
|
@ -262,9 +262,9 @@ namespace CalculatorApp { namespace Common
|
|||
|
||||
private:
|
||||
virtual Platform::Object^ Convert(
|
||||
Platform::Object^ value,
|
||||
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
|
||||
Platform::Object^ /*parameter*/,
|
||||
Platform::Object^ value,
|
||||
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
|
||||
Platform::Object^ /*parameter*/,
|
||||
Platform::String^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::Convert
|
||||
{
|
||||
auto result = dynamic_cast<Windows::UI::Xaml::Interop::IBindableVector^>(value);
|
||||
|
@ -276,9 +276,9 @@ namespace CalculatorApp { namespace Common
|
|||
}
|
||||
|
||||
virtual Platform::Object^ ConvertBack(
|
||||
Platform::Object^ /*value*/,
|
||||
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
|
||||
Platform::Object^ /*parameter*/,
|
||||
Platform::Object^ /*value*/,
|
||||
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
|
||||
Platform::Object^ /*parameter*/,
|
||||
Platform::String^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::ConvertBack
|
||||
{
|
||||
return Windows::UI::Xaml::DependencyProperty::UnsetValue;
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pch.h"
|
||||
#include "AppResourceProvider.h"
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
|
@ -20,6 +20,8 @@ namespace CalculatorApp::Common::Automation
|
|||
StringReference CategoryNameChanged(L"CategoryNameChanged");
|
||||
StringReference UpdateCurrencyRates(L"UpdateCurrencyRates");
|
||||
StringReference DisplayCopied(L"DisplayCopied");
|
||||
StringReference OpenParenthesisCountChanged(L"OpenParenthesisCountChanged");
|
||||
StringReference NoParenthesisAdded(L"NoParenthesisAdded");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,3 +144,21 @@ NarratorAnnouncement^ CalculatorAnnouncement::GetDisplayCopiedAnnouncement(Strin
|
|||
AutomationNotificationKind::ActionCompleted,
|
||||
AutomationNotificationProcessing::ImportantMostRecent);
|
||||
}
|
||||
|
||||
NarratorAnnouncement^ CalculatorAnnouncement::GetOpenParenthesisCountChangedAnnouncement(String^ announcement)
|
||||
{
|
||||
return ref new NarratorAnnouncement(
|
||||
announcement,
|
||||
CalculatorActivityIds::OpenParenthesisCountChanged,
|
||||
AutomationNotificationKind::ActionCompleted,
|
||||
AutomationNotificationProcessing::ImportantMostRecent);
|
||||
}
|
||||
|
||||
NarratorAnnouncement^ CalculatorAnnouncement::GetNoRightParenthesisAddedAnnouncement(String^ announcement)
|
||||
{
|
||||
return ref new NarratorAnnouncement(
|
||||
announcement,
|
||||
CalculatorActivityIds::NoParenthesisAdded,
|
||||
AutomationNotificationKind::ActionCompleted,
|
||||
AutomationNotificationProcessing::ImportantMostRecent);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
@ -88,7 +88,10 @@ namespace CalculatorApp::Common::Automation
|
|||
static NarratorAnnouncement^ GetCategoryNameChangedAnnouncement(Platform::String^ announcement);
|
||||
|
||||
static NarratorAnnouncement^ GetUpdateCurrencyRatesAnnouncement(Platform::String^ announcement);
|
||||
|
||||
|
||||
static NarratorAnnouncement^ GetDisplayCopiedAnnouncement(Platform::String^ announcement);
|
||||
|
||||
static NarratorAnnouncement^ GetOpenParenthesisCountChangedAnnouncement(Platform::String^ announcement);
|
||||
static NarratorAnnouncement^ GetNoRightParenthesisAddedAnnouncement(Platform::String ^ announcement);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -18,17 +18,17 @@ void BindableBase::OnPropertyChanged(String^ 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
Platform::String^ BindableBase::GetStringRepresentation()
|
||||
Platform::String^ BindableBase::GetStringRepresentation()
|
||||
{
|
||||
return this->ToString();
|
||||
return this->ToString();
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ namespace CalculatorApp
|
|||
D = (int) CM::Command::CommandD,
|
||||
E = (int) CM::Command::CommandE,
|
||||
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,
|
||||
Cosh = (int) CM::Command::CommandCOSH,
|
||||
Tanh = (int) CM::Command::CommandTANH,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Licensed under the MIT License.
|
||||
|
||||
// This class provides the concrete implementation for the ICalcDisplay interface
|
||||
// that is declared in the Calculation Manager Library.
|
||||
// that is declared in the Calculation Manager Library.
|
||||
#include "pch.h"
|
||||
#include "CalculatorDisplay.h"
|
||||
#include "StandardCalculatorViewModel.h"
|
||||
|
@ -29,8 +29,7 @@ void CalculatorDisplay::SetPrimaryDisplay(_In_ const wstring& displayStringValue
|
|||
{
|
||||
if (m_callbackReference)
|
||||
{
|
||||
auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>();
|
||||
if (calcVM)
|
||||
if (auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>())
|
||||
{
|
||||
calcVM->SetPrimaryDisplay(displayStringValue, isError);
|
||||
}
|
||||
|
@ -41,20 +40,29 @@ void CalculatorDisplay::SetParenDisplayText(_In_ const std::wstring& parenthesis
|
|||
{
|
||||
if (m_callbackReference != nullptr)
|
||||
{
|
||||
auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>();
|
||||
if (calcVM)
|
||||
if (auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>())
|
||||
{
|
||||
calcVM->SetParenthesisCount(parenthesisCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CalculatorDisplay::OnNoRightParenAdded()
|
||||
{
|
||||
if (m_callbackReference != nullptr)
|
||||
{
|
||||
if (auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>())
|
||||
{
|
||||
calcVM->OnNoRightParenAdded();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CalculatorDisplay::SetIsInError(bool isError)
|
||||
{
|
||||
if (m_callbackReference != nullptr)
|
||||
{
|
||||
auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>();
|
||||
if (calcVM)
|
||||
if (auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>())
|
||||
{
|
||||
calcVM->IsInError = isError;
|
||||
}
|
||||
|
@ -65,8 +73,7 @@ void CalculatorDisplay::SetExpressionDisplay(_Inout_ std::shared_ptr<CalculatorV
|
|||
{
|
||||
if (m_callbackReference != nullptr)
|
||||
{
|
||||
auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>();
|
||||
if (calcVM)
|
||||
if(auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>())
|
||||
{
|
||||
calcVM->SetExpressionDisplay(tokens, commands);
|
||||
}
|
||||
|
@ -77,8 +84,7 @@ void CalculatorDisplay::SetMemorizedNumbers(_In_ const vector<std::wstring>& new
|
|||
{
|
||||
if (m_callbackReference != nullptr)
|
||||
{
|
||||
auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>();
|
||||
if (calcVM)
|
||||
if (auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>())
|
||||
{
|
||||
calcVM->SetMemorizedNumbers(newMemorizedNumbers);
|
||||
}
|
||||
|
@ -89,8 +95,7 @@ void CalculatorDisplay::OnHistoryItemAdded(_In_ unsigned int addedItemIndex)
|
|||
{
|
||||
if (m_historyCallbackReference != nullptr)
|
||||
{
|
||||
auto historyVM = m_historyCallbackReference.Resolve<ViewModel::HistoryViewModel>();
|
||||
if (historyVM)
|
||||
if (auto historyVM = m_historyCallbackReference.Resolve<ViewModel::HistoryViewModel>())
|
||||
{
|
||||
historyVM->OnHistoryItemAdded(addedItemIndex);
|
||||
}
|
||||
|
@ -101,8 +106,7 @@ void CalculatorDisplay::MaxDigitsReached()
|
|||
{
|
||||
if (m_callbackReference != nullptr)
|
||||
{
|
||||
auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>();
|
||||
if (calcVM)
|
||||
if (auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>())
|
||||
{
|
||||
calcVM->OnMaxDigitsReached();
|
||||
}
|
||||
|
@ -113,8 +117,7 @@ void CalculatorDisplay::BinaryOperatorReceived()
|
|||
{
|
||||
if (m_callbackReference != nullptr)
|
||||
{
|
||||
auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>();
|
||||
if (calcVM)
|
||||
if (auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>())
|
||||
{
|
||||
calcVM->OnBinaryOperatorReceived();
|
||||
}
|
||||
|
@ -125,8 +128,7 @@ void CalculatorDisplay::MemoryItemChanged(unsigned int indexOfMemory)
|
|||
{
|
||||
if (m_callbackReference != nullptr)
|
||||
{
|
||||
auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>();
|
||||
if (calcVM)
|
||||
if (auto calcVM = m_callbackReference.Resolve<ViewModel::StandardCalculatorViewModel>())
|
||||
{
|
||||
calcVM->OnMemoryItemChanged(indexOfMemory);
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ namespace CalculatorApp
|
|||
void SetMemorizedNumbers(_In_ const std::vector<std::wstring>& memorizedNumbers) override;
|
||||
void OnHistoryItemAdded(_In_ unsigned int addedItemIndex) override;
|
||||
void SetParenDisplayText(_In_ const std::wstring& parenthesisCount) override;
|
||||
void OnNoRightParenAdded() override;
|
||||
void MaxDigitsReached() override;
|
||||
void BinaryOperatorReceived() override;
|
||||
void MemoryItemChanged(unsigned int indexOfMemory) override;
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace CalculatorApp
|
|||
public:
|
||||
ConversionResultTaskHelper(unsigned int delay, const std::function<void()> functionToRun);
|
||||
~ConversionResultTaskHelper();
|
||||
|
||||
|
||||
private:
|
||||
concurrency::task<void> CompleteAfter(unsigned int timeout);
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ constexpr wstring_view c_validCharacterSet{ L"0123456789()+-*/.abcdefABCDEF" };
|
|||
// [\s\x85] means white-space characters
|
||||
static const wstring c_wspc = L"[\\s\\x85]*";
|
||||
static const wstring c_wspcLParens = c_wspc + L"[(]*" + c_wspc;
|
||||
static const wstring c_wspcLParenSigned = c_wspc + L"([-+]?[(])*" + c_wspc;
|
||||
static const wstring c_wspcRParens = c_wspc + L"[)]*" + c_wspc;
|
||||
static const wstring c_signedDecFloat = L"[-+]?\\d*(\\d|[.])\\d*";
|
||||
|
||||
|
@ -44,8 +45,8 @@ static const array<wregex, 1> standardModePatterns =
|
|||
};
|
||||
static const array<wregex, 2> scientificModePatterns =
|
||||
{
|
||||
wregex(c_wspcLParens + c_signedDecFloat + c_wspcRParens),
|
||||
wregex(c_wspcLParens + c_signedDecFloat + L"[e]([+]|[-])+\\d+" + c_wspcRParens)
|
||||
wregex(L"(" + c_wspc + L"[-+]?)|(" + c_wspcLParenSigned + L")" + c_signedDecFloat + c_wspcRParens),
|
||||
wregex(L"(" + c_wspc + L"[-+]?)|(" + c_wspcLParenSigned + L")" + c_signedDecFloat + L"[e]([+]|[-])+\\d+" + c_wspcRParens)
|
||||
};
|
||||
static const array<array<wregex, 5>, 4> programmerModePatterns =
|
||||
{ {
|
||||
|
@ -129,17 +130,17 @@ String^ CopyPasteManager::ValidatePasteExpression(String^ pastedText, ViewMode m
|
|||
if (pastedText->Length() > MaxPasteableLength)
|
||||
{
|
||||
// return NoOp to indicate don't paste anything.
|
||||
TraceLogger::GetInstance().LogInvalidInputPasted(L"PastedExpressionSizeGreaterThanMaxAllowed", L"MoreThanMaxInput", mode, programmerNumberBase, bitLengthType);
|
||||
TraceLogger::GetInstance().LogInvalidPastedInputOccurred(L"PastedExpressionSizeGreaterThanMaxAllowed", mode, programmerNumberBase, bitLengthType);
|
||||
return StringReference(PasteErrorString);
|
||||
}
|
||||
|
||||
wstring pasteExpression = pastedText->Data();
|
||||
|
||||
// Get english translated expression
|
||||
// Get english translated expression
|
||||
String^ englishString = LocalizationSettings::GetInstance().GetEnglishValueFromLocalizedDigits(pasteExpression);
|
||||
|
||||
// Removing the spaces, comma separator from the pasteExpression to allow pasting of expressions like 1 + 2+1,333
|
||||
pasteExpression = Utils::RemoveUnwantedCharsFromWstring(englishString->Data());
|
||||
pasteExpression = RemoveUnwantedCharsFromWstring(englishString->Data());
|
||||
|
||||
// If the last character is an = sign, remove it from the pasteExpression to allow evaluating the result on paste.
|
||||
if (!pasteExpression.empty() && pasteExpression.back() == L'=')
|
||||
|
@ -164,7 +165,7 @@ String^ CopyPasteManager::ValidatePasteExpression(String^ pastedText, ViewMode m
|
|||
// validate each operand with patterns for different modes
|
||||
if (!ExpressionRegExMatch(operands, mode, modeType, programmerNumberBase, bitLengthType))
|
||||
{
|
||||
TraceLogger::GetInstance().LogInvalidInputPasted(L"InvalidExpressionForPresentMode", pastedText->Data(), mode, programmerNumberBase, bitLengthType);
|
||||
TraceLogger::GetInstance().LogInvalidPastedInputOccurred(L"InvalidExpressionForPresentMode", mode, programmerNumberBase, bitLengthType);
|
||||
return StringReference(PasteErrorString);
|
||||
}
|
||||
|
||||
|
@ -193,7 +194,7 @@ vector<wstring> CopyPasteManager::ExtractOperands(const wstring& pasteExpression
|
|||
|
||||
if (operands.size() >= MaxOperandCount)
|
||||
{
|
||||
TraceLogger::GetInstance().LogInvalidInputPasted(L"OperandCountGreaterThanMaxCount", pasteExpression.c_str(), mode, programmerNumberBase, bitLengthType);
|
||||
TraceLogger::GetInstance().LogInvalidPastedInputOccurred(L"OperandCountGreaterThanMaxCount", mode, programmerNumberBase, bitLengthType);
|
||||
operands.clear();
|
||||
return operands;
|
||||
}
|
||||
|
@ -207,7 +208,7 @@ vector<wstring> CopyPasteManager::ExtractOperands(const wstring& pasteExpression
|
|||
// to disallow pasting of 1e+12345 as 1e+1234, max exponent that can be pasted is 9999.
|
||||
if (expLength > MaxExponentLength)
|
||||
{
|
||||
TraceLogger::GetInstance().LogInvalidInputPasted(L"ExponentLengthGreaterThanMaxLength", pasteExpression.c_str(), mode, programmerNumberBase, bitLengthType);
|
||||
TraceLogger::GetInstance().LogInvalidPastedInputOccurred(L"ExponentLengthGreaterThanMaxLength", mode, programmerNumberBase, bitLengthType);
|
||||
operands.clear();
|
||||
return operands;
|
||||
}
|
||||
|
@ -402,9 +403,9 @@ pair<size_t, uint64_t> CopyPasteManager::GetMaxOperandLengthAndValue(ViewMode mo
|
|||
|
||||
wstring CopyPasteManager::SanitizeOperand(const wstring& operand)
|
||||
{
|
||||
wchar_t unWantedChars[] = { L'\'', L'_', L'`', L'(', L')', L'-' };
|
||||
wchar_t unWantedChars[] = { L'\'', L'_', L'`', L'(', L')', L'-', L'+' };
|
||||
|
||||
return Utils::RemoveUnwantedCharsFromWstring(operand, unWantedChars, ARRAYSIZE(unWantedChars));
|
||||
return Utils::RemoveUnwantedCharsFromWstring(operand, unWantedChars, static_cast<int>(size(unWantedChars)));
|
||||
}
|
||||
|
||||
bool CopyPasteManager::TryOperandToULL(const wstring& operand, int numberBase, unsigned long long int& result)
|
||||
|
@ -567,3 +568,21 @@ size_t CopyPasteManager::ProgrammerOperandLength(const wstring& operand, int num
|
|||
|
||||
return len;
|
||||
}
|
||||
|
||||
// return wstring after removing characters like space, comma, double quotes, and monetary prefix currency symbols supported by the Windows keyboard:
|
||||
// yen or yuan(¥) - 165
|
||||
// unspecified currency sign(¤) - 164
|
||||
// Ghanaian cedi(₵) - 8373
|
||||
// dollar or peso($) - 36
|
||||
// colón(₡) - 8353
|
||||
// won(₩) - 8361
|
||||
// shekel(₪) - 8362
|
||||
// naira(₦) - 8358
|
||||
// Indian rupee(₹) - 8377
|
||||
// pound(£) - 163
|
||||
// euro(€) - 8364
|
||||
wstring CopyPasteManager::RemoveUnwantedCharsFromWstring(const wstring& input)
|
||||
{
|
||||
wchar_t unWantedChars[] = { L' ', L',', L'"', 165, 164, 8373, 36, 8353, 8361, 8362, 8358, 8377, 163, 8364, 8234, 8235, 8236, 8237 };
|
||||
return Utils::RemoveUnwantedCharsFromWstring(input, unWantedChars, 18);
|
||||
}
|
||||
|
|
|
@ -58,6 +58,7 @@ namespace CalculatorApp
|
|||
static size_t OperandLength(std::wstring operand, CalculatorApp::Common::ViewMode mode, CalculatorApp::Common::CategoryGroupType modeType, int programmerNumberBase = -1);
|
||||
static size_t StandardScientificOperandLength(std::wstring operand);
|
||||
static size_t ProgrammerOperandLength(const std::wstring& operand, int numberBase);
|
||||
static std::wstring RemoveUnwantedCharsFromWstring(const std::wstring& input);
|
||||
|
||||
static constexpr size_t MaxStandardOperandLength = 16;
|
||||
static constexpr size_t MaxScientificOperandLength = 32;
|
||||
|
|
|
@ -12,10 +12,11 @@ using namespace CalculatorApp::Common::DateCalculation;
|
|||
DateCalculationEngine::DateCalculationEngine(_In_ String^ calendarIdentifier)
|
||||
{
|
||||
m_calendar = ref new Calendar();
|
||||
m_calendar->ChangeTimeZone("UTC");
|
||||
m_calendar->ChangeCalendarSystem(calendarIdentifier);
|
||||
}
|
||||
|
||||
// Adding Duration to a Date
|
||||
// Adding Duration to a Date
|
||||
// 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)
|
||||
{
|
||||
|
@ -52,7 +53,7 @@ bool DateCalculationEngine::AddDuration(_In_ DateTime startDate, _In_ const Date
|
|||
bool DateCalculationEngine::SubtractDuration(_In_ DateTime startDate, _In_ const DateDifference& duration, _Out_ DateTime *endDate)
|
||||
{
|
||||
// For Subtract the Algorithm is different than Add. Here the smaller units are subtracted first
|
||||
// and then the larger units.
|
||||
// and then the larger units.
|
||||
try
|
||||
{
|
||||
m_calendar->SetDateTime(startDate);
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
const ULONGLONG c_millisecond = 10000;
|
||||
const ULONGLONG c_second = 1000 * c_millisecond;
|
||||
const ULONGLONG c_minute = 60 * c_second;
|
||||
const ULONGLONG c_hour = 60 * c_minute;
|
||||
const ULONGLONG c_day = 24 * c_hour;
|
||||
const uint64_t c_millisecond = 10000;
|
||||
const uint64_t c_second = 1000 * c_millisecond;
|
||||
const uint64_t c_minute = 60 * c_second;
|
||||
const uint64_t c_hour = 60 * c_minute;
|
||||
const uint64_t c_day = 24 * c_hour;
|
||||
|
||||
const int c_unitsOfDate = 4; // Units Year,Month,Week,Day
|
||||
const int c_unitsGreaterThanDays = 3; // Units Greater than Days (Year/Month/Week) 3
|
||||
|
|
|
@ -21,10 +21,10 @@ namespace CalculatorApp
|
|||
|
||||
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 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
|
||||
{
|
||||
TTarget^ target = m_weakTarget.Resolve<TTarget>();
|
||||
|
|
|
@ -56,7 +56,7 @@ namespace CalculatorApp
|
|||
{
|
||||
// Lights up all of the buttons in the given range
|
||||
// The range is defined by a pair of iterators
|
||||
template <typename T>
|
||||
template <typename T>
|
||||
void LightUpButtons(const T& buttons)
|
||||
{
|
||||
auto iterator = buttons.first;
|
||||
|
@ -72,14 +72,14 @@ namespace CalculatorApp
|
|||
|
||||
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
|
||||
if (dynamic_cast<ToggleButton^>(button))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// The button will go into the visual Pressed state with this call
|
||||
// The button will go into the visual Pressed state with this call
|
||||
VisualStateManager::GoToState(button, "Pressed", true);
|
||||
|
||||
// This timer will fire after lightUpTime and make the button
|
||||
|
@ -89,7 +89,7 @@ namespace CalculatorApp
|
|||
TimeSpan lightUpTime{};
|
||||
lightUpTime.Duration = 500000L; // Half second (in 100-ns units)
|
||||
timer->Interval = lightUpTime;
|
||||
|
||||
|
||||
WeakReference timerWeakReference(timer);
|
||||
WeakReference buttonWeakReference(button);
|
||||
timer->Tick += ref new EventHandler<Object^>(
|
||||
|
@ -206,7 +206,7 @@ void KeyboardShortcutManager::HonorEscape()
|
|||
}
|
||||
|
||||
void KeyboardShortcutManager::OnCharacterPropertyChanged(
|
||||
DependencyObject^ target,
|
||||
DependencyObject^ target,
|
||||
String^ oldValue,
|
||||
String^ newValue)
|
||||
{
|
||||
|
@ -263,10 +263,10 @@ void KeyboardShortcutManager::OnVirtualKeyPropertyChanged(
|
|||
reader_writer_lock::scoped_lock lock(s_keyboardShortcutMapLock);
|
||||
|
||||
auto button = static_cast<ButtonBase^>(target);
|
||||
|
||||
|
||||
int viewId = Utils::GetWindowId();
|
||||
auto iterViewMap = s_VirtualKeysForButtons.find(viewId);
|
||||
|
||||
|
||||
// Check if the View Id has already been registered
|
||||
if (iterViewMap != s_VirtualKeysForButtons.end())
|
||||
{
|
||||
|
@ -281,7 +281,7 @@ void KeyboardShortcutManager::OnVirtualKeyPropertyChanged(
|
|||
}
|
||||
|
||||
void KeyboardShortcutManager::OnVirtualKeyControlChordPropertyChanged(
|
||||
DependencyObject^ target,
|
||||
DependencyObject^ target,
|
||||
MyVirtualKey /*oldValue*/,
|
||||
MyVirtualKey newValue)
|
||||
{
|
||||
|
@ -537,7 +537,7 @@ void KeyboardShortcutManager::OnKeyDownHandler(CoreWindow^ sender, KeyEventArgs^
|
|||
|
||||
// Handle Ctrl + E for DateCalculator
|
||||
if ((key == VirtualKey::E) &&
|
||||
isControlKeyPressed &&
|
||||
isControlKeyPressed &&
|
||||
!isShiftKeyPressed)
|
||||
{
|
||||
const auto& lookupMap = GetCurrentKeyDictionary(static_cast<MyVirtualKey>(key));
|
||||
|
@ -710,7 +710,7 @@ void KeyboardShortcutManager::OnAcceleratorKeyActivated(CoreDispatcher^, Acceler
|
|||
{
|
||||
int viewId = Utils::GetWindowId();
|
||||
auto iterViewMap = s_AboutFlyout.find(viewId);
|
||||
|
||||
|
||||
if ((iterViewMap != s_AboutFlyout.end()) && (iterViewMap->second != nullptr))
|
||||
{
|
||||
iterViewMap->second->Hide();
|
||||
|
@ -721,9 +721,9 @@ void KeyboardShortcutManager::OnAcceleratorKeyActivated(CoreDispatcher^, Acceler
|
|||
void KeyboardShortcutManager::Initialize()
|
||||
{
|
||||
auto coreWindow = Window::Current->CoreWindow;
|
||||
coreWindow->CharacterReceived +=
|
||||
coreWindow->CharacterReceived +=
|
||||
ref new TypedEventHandler<CoreWindow^, CharacterReceivedEventArgs^>(&KeyboardShortcutManager::OnCharacterReceivedHandler);
|
||||
coreWindow->KeyDown +=
|
||||
coreWindow->KeyDown +=
|
||||
ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(&KeyboardShortcutManager::OnKeyDownHandler);
|
||||
coreWindow->KeyUp +=
|
||||
ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(&KeyboardShortcutManager::OnKeyUpHandler);
|
||||
|
@ -758,7 +758,7 @@ void KeyboardShortcutManager::UpdateDropDownState(bool isOpen)
|
|||
void KeyboardShortcutManager::UpdateDropDownState(Flyout^ aboutPageFlyout)
|
||||
{
|
||||
int viewId = Utils::GetWindowId();
|
||||
|
||||
|
||||
if (s_AboutFlyout.find(viewId) != s_AboutFlyout.end())
|
||||
{
|
||||
s_AboutFlyout.erase(viewId);
|
||||
|
@ -803,7 +803,7 @@ void KeyboardShortcutManager::RegisterNewAppViewId()
|
|||
{
|
||||
s_CharacterForButtons.insert(std::make_pair(appViewId, std::multimap<wchar_t, WeakReference>()));
|
||||
}
|
||||
|
||||
|
||||
if (s_VirtualKeysForButtons.find(appViewId) == s_VirtualKeysForButtons.end())
|
||||
{
|
||||
s_VirtualKeysForButtons.insert(std::make_pair(appViewId, std::multimap<MyVirtualKey, WeakReference>()));
|
||||
|
@ -823,17 +823,17 @@ void KeyboardShortcutManager::RegisterNewAppViewId()
|
|||
{
|
||||
s_VirtualKeyAltChordsForButtons.insert(std::make_pair(appViewId, std::multimap<MyVirtualKey, WeakReference>()));
|
||||
}
|
||||
|
||||
|
||||
if (s_VirtualKeyControlShiftChordsForButtons.find(appViewId) == s_VirtualKeyControlShiftChordsForButtons.end())
|
||||
{
|
||||
s_VirtualKeyControlShiftChordsForButtons.insert(std::make_pair(appViewId, std::multimap<MyVirtualKey, WeakReference>()));
|
||||
}
|
||||
|
||||
|
||||
if (s_VirtualKeyInverseChordsForButtons.find(appViewId) == s_VirtualKeyInverseChordsForButtons.end())
|
||||
{
|
||||
s_VirtualKeyInverseChordsForButtons.insert(std::make_pair(appViewId, std::multimap<MyVirtualKey, WeakReference>()));
|
||||
}
|
||||
|
||||
|
||||
if (s_VirtualKeyControlInverseChordsForButtons.find(appViewId) == s_VirtualKeyControlInverseChordsForButtons.end())
|
||||
{
|
||||
s_VirtualKeyControlInverseChordsForButtons.insert(std::make_pair(appViewId, std::multimap<MyVirtualKey, WeakReference>()));
|
||||
|
|
|
@ -206,7 +206,7 @@ FontWeight LocalizationService::GetFontWeightOverride()
|
|||
double LocalizationService::GetFontScaleFactorOverride(LanguageFontType fontType)
|
||||
{
|
||||
assert(m_overrideFontApiValues);
|
||||
|
||||
|
||||
switch (fontType)
|
||||
{
|
||||
case LanguageFontType::UIText:
|
||||
|
@ -271,12 +271,12 @@ void LocalizationService::UpdateFontFamilyAndSize(DependencyObject^ target)
|
|||
{
|
||||
control->FontSize = sizeToUse;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
control->ClearValue(Control::FontSizeProperty);
|
||||
}
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
auto textBlock = dynamic_cast<TextBlock^>(target);
|
||||
if (textBlock)
|
||||
|
@ -290,7 +290,7 @@ void LocalizationService::UpdateFontFamilyAndSize(DependencyObject^ target)
|
|||
{
|
||||
textBlock->FontSize = sizeToUse;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
textBlock->ClearValue(TextBlock::FontSizeProperty);
|
||||
}
|
||||
|
@ -309,7 +309,7 @@ void LocalizationService::UpdateFontFamilyAndSize(DependencyObject^ target)
|
|||
{
|
||||
richTextBlock->FontSize = sizeToUse;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
richTextBlock->ClearValue(RichTextBlock::FontSizeProperty);
|
||||
}
|
||||
|
@ -328,7 +328,7 @@ void LocalizationService::UpdateFontFamilyAndSize(DependencyObject^ target)
|
|||
{
|
||||
textElement->FontSize = sizeToUse;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
textElement->ClearValue(TextElement::FontSizeProperty);
|
||||
}
|
||||
|
@ -416,7 +416,7 @@ IIterable<String^>^ LocalizationService::GetLanguageIdentifiers()
|
|||
int result = GetUserDefaultLocaleName(currentLocale, LOCALE_NAME_MAX_LENGTH);
|
||||
if (result != 0)
|
||||
{
|
||||
// GetUserDefaultLocaleName may return an invalid bcp47 language tag with trailing non-BCP47 friendly characters,
|
||||
// GetUserDefaultLocaleName may return an invalid bcp47 language tag with trailing non-BCP47 friendly characters,
|
||||
// which if present would start with an underscore, for example sort order
|
||||
// (see https://msdn.microsoft.com/en-us/library/windows/desktop/dd373814(v=vs.85).aspx).
|
||||
// Therefore, if there is an underscore in the locale name, trim all characters from the underscore onwards.
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#pragma once
|
||||
#include "LocalizationService.h"
|
||||
|
||||
#include <iterator>
|
||||
|
||||
namespace CalculatorApp
|
||||
{
|
||||
namespace Common
|
||||
|
@ -41,7 +43,7 @@ namespace CalculatorApp
|
|||
result = GetLocaleInfoEx(m_resolvedName.c_str(),
|
||||
LOCALE_SDECIMAL,
|
||||
decimalString,
|
||||
ARRAYSIZE(decimalString));
|
||||
static_cast<int>(std::size(decimalString)));
|
||||
if (result == 0)
|
||||
{
|
||||
throw std::runtime_error("Unexpected error while getting locale info");
|
||||
|
@ -51,7 +53,7 @@ namespace CalculatorApp
|
|||
result = GetLocaleInfoEx(m_resolvedName.c_str(),
|
||||
LOCALE_STHOUSAND,
|
||||
groupingSymbolString,
|
||||
ARRAYSIZE(groupingSymbolString));
|
||||
static_cast<int>(std::size(groupingSymbolString)));
|
||||
if (result == 0)
|
||||
{
|
||||
throw std::runtime_error("Unexpected error while getting locale info");
|
||||
|
@ -61,7 +63,7 @@ namespace CalculatorApp
|
|||
result = GetLocaleInfoEx(m_resolvedName.c_str(),
|
||||
LOCALE_SGROUPING,
|
||||
numberGroupingString,
|
||||
ARRAYSIZE(numberGroupingString));
|
||||
static_cast<int>(std::size(numberGroupingString)));
|
||||
if (result == 0)
|
||||
{
|
||||
throw std::runtime_error("Unexpected error while getting locale info");
|
||||
|
@ -72,7 +74,7 @@ namespace CalculatorApp
|
|||
result = ::GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT,
|
||||
LOCALE_SLIST,
|
||||
listSeparatorString,
|
||||
ARRAYSIZE(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)
|
||||
{
|
||||
throw std::runtime_error("Unexpected error while getting locale info");
|
||||
|
@ -122,7 +124,7 @@ namespace CalculatorApp
|
|||
::GetLocaleInfoEx(LOCALE_NAME_USER_DEFAULT,
|
||||
LOCALE_IFIRSTDAYOFWEEK, // The first day in a week
|
||||
reinterpret_cast<PWSTR>(day), // Argument is of type PWSTR
|
||||
ARRAYSIZE(day)); // Max return size are 80 characters
|
||||
static_cast<int>(std::size(day))); // Max return size are 80 characters
|
||||
|
||||
// The LOCALE_IFIRSTDAYOFWEEK integer value varies from 0, 1, .. 6 for Monday, Tuesday, ... Sunday
|
||||
// DayOfWeek enum value varies from 0, 1, .. 6 for Sunday, Monday, ... Saturday
|
||||
|
|
|
@ -20,11 +20,11 @@ namespace CalculatorApp
|
|||
va_list args = NULL;
|
||||
va_start(args, pMessage);
|
||||
DWORD fmtReturnVal = FormatMessage(FORMAT_MESSAGE_FROM_STRING,
|
||||
pMessage,
|
||||
pMessage,
|
||||
0,
|
||||
0,
|
||||
spBuffer.get(),
|
||||
length,
|
||||
spBuffer.get(),
|
||||
length,
|
||||
&args);
|
||||
va_end(args);
|
||||
|
||||
|
|
|
@ -141,7 +141,7 @@ namespace CalculatorApp
|
|||
|
||||
property Platform::String^ AccessKey
|
||||
{
|
||||
Platform::String^ get()
|
||||
Platform::String^ get()
|
||||
{
|
||||
return m_accessKey;
|
||||
}
|
||||
|
@ -220,11 +220,11 @@ namespace CalculatorApp
|
|||
static Windows::Foundation::Collections::IObservableVector<NavCategoryGroup^>^ CreateMenuOptions();
|
||||
|
||||
static Platform::String^ GetHeaderResourceKey(CategoryGroupType type);
|
||||
|
||||
|
||||
internal:
|
||||
static NavCategoryGroup^ CreateCalculatorCategory();
|
||||
static NavCategoryGroup^ CreateConverterCategory();
|
||||
|
||||
|
||||
private:
|
||||
NavCategoryGroup(const NavCategoryGroupInitializer& groupInitializer);
|
||||
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "pch.h"
|
||||
#include "TraceLogger.h"
|
||||
#include "NetworkManager.h"
|
||||
|
@ -59,7 +57,7 @@ namespace CalculatorApp
|
|||
constexpr auto EVENT_NAME_MEMORY_FLYOUT_OPEN_BEGIN = L"MemoryFlyoutOpenBegin";
|
||||
constexpr auto EVENT_NAME_MEMORY_FLYOUT_OPEN_END = L"MemoryFlyoutOpenEnd";
|
||||
constexpr auto EVENT_NAME_MEMORY_CLEAR_ALL = L"MemoryClearAll";
|
||||
constexpr auto EVENT_NAME_INVALID_INPUT_PASTED = L"InvalidInputPasted";
|
||||
constexpr auto EVENT_NAME_INVALID_PASTED_INPUT_OCCURRED = L"InvalidPastedInputOccurred";
|
||||
constexpr auto EVENT_NAME_VALID_INPUT_PASTED = L"ValidInputPasted";
|
||||
constexpr auto EVENT_NAME_BITFLIP_PANE_CLICKED = L"BitFlipPaneClicked";
|
||||
constexpr auto EVENT_NAME_BITFLIP_BUTTONS_USED = L"BitFlipToggleButtonUsed";
|
||||
|
@ -81,6 +79,9 @@ namespace CalculatorApp
|
|||
|
||||
constexpr auto EVENT_NAME_EXCEPTION = L"Exception";
|
||||
|
||||
constexpr auto PDT_PRIVACY_DATA_TAG = L"PartA_PrivTags";
|
||||
constexpr auto PDT_PRODUCT_AND_SERVICE_USAGE = 0x0000'0000'0200'0000u;
|
||||
|
||||
#ifdef SEND_TELEMETRY
|
||||
// c.f. WINEVENT_KEYWORD_RESERVED_63-56 0xFF00000000000000 // Bits 63-56 - channel keywords
|
||||
// c.f. WINEVENT_KEYWORD_* 0x00FF000000000000 // Bits 55-48 - system-reserved keywords
|
||||
|
@ -102,7 +103,7 @@ namespace CalculatorApp
|
|||
g_calculatorProvider(
|
||||
L"MicrosoftCalculator",
|
||||
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 }
|
||||
{
|
||||
// initialize the function array
|
||||
|
@ -247,7 +248,7 @@ namespace CalculatorApp
|
|||
{
|
||||
windowIdLog.insert(pair<int, bool>(windowId, false));
|
||||
}
|
||||
// if the event is not logged already for the present mode
|
||||
// if the event is not logged already for the present mode
|
||||
if (currentMode != mode)
|
||||
{
|
||||
currentMode = mode;
|
||||
|
@ -270,7 +271,7 @@ namespace CalculatorApp
|
|||
{
|
||||
windowIdLog.insert(pair<int, bool>(windowId, false));
|
||||
}
|
||||
// if the event is not logged already for the present mode
|
||||
// if the event is not logged already for the present mode
|
||||
if (currentMode != mode)
|
||||
{
|
||||
currentMode = mode;
|
||||
|
@ -292,7 +293,7 @@ namespace CalculatorApp
|
|||
{
|
||||
windowIdLog.insert(pair<int, bool>(windowId, false));
|
||||
}
|
||||
// if the event is not logged already for the present mode
|
||||
// if the event is not logged already for the present mode
|
||||
if (currentMode != mode)
|
||||
{
|
||||
currentMode = mode;
|
||||
|
@ -481,9 +482,9 @@ namespace CalculatorApp
|
|||
LogTelemetryEvent(EVENT_NAME_MEMORY_BODY_OPENED, fields);
|
||||
}
|
||||
|
||||
//If calculator is launched in any mode other than standard then this call will come which is not intended. But there is no way to avoid it.
|
||||
//So don't use this function to analyze the count of mode change in session instead use CalculatorViewedInSession and ConverterViewedInSession to do that.
|
||||
//Use of this function is to analyze perf of mode change.
|
||||
// If calculator is launched in any mode other than standard then this call will come which is not intended. But there is no way to avoid it.
|
||||
// So don't use this function to analyze the count of mode change in session instead use CalculatorViewedInSession and ConverterViewedInSession to do that.
|
||||
// Use of this function is to analyze perf of mode change.
|
||||
void TraceLogger::LogModeChangeBegin(ViewMode fromMode, ViewMode toMode, int windowId)
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
|
@ -498,7 +499,7 @@ namespace CalculatorApp
|
|||
}
|
||||
}
|
||||
|
||||
//comment: same as LogModeChangeBegin
|
||||
// comment: same as LogModeChangeBegin
|
||||
void TraceLogger::LogModeChangeEnd(ViewMode toMode, int windowId) const
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
|
@ -577,7 +578,7 @@ namespace CalculatorApp
|
|||
// Writer lock for the static resources
|
||||
reader_writer_lock::scoped_lock lock(s_traceLoggerLock);
|
||||
auto iterMap = s_memoryMap.find(windowId);
|
||||
|
||||
|
||||
LoggingFields fields{};
|
||||
LogTelemetryEvent(EVENT_NAME_MEMORY_CLEAR_ALL, fields);
|
||||
|
||||
|
@ -641,17 +642,17 @@ namespace CalculatorApp
|
|||
LogTelemetryEvent(EVENT_NAME_SINGLE_MEMORY_USED, fields);
|
||||
}
|
||||
|
||||
void TraceLogger::LogInvalidInputPasted(wstring_view reason, wstring_view pastedExpression, ViewMode mode, int programmerNumberBase, int bitLengthType)
|
||||
void TraceLogger::LogInvalidPastedInputOccurred(wstring_view reason, ViewMode mode, int programmerNumberBase, int bitLengthType)
|
||||
{
|
||||
if (!GetTraceLoggingProviderEnabled()) return;
|
||||
|
||||
LoggingFields fields{};
|
||||
fields.AddString(L"Mode", NavCategory::GetFriendlyName(mode)->Data());
|
||||
fields.AddString(L"Reason", reason);
|
||||
fields.AddString(L"PastedExpression", pastedExpression);
|
||||
fields.AddString(L"ProgrammerNumberBase", GetProgrammerType(programmerNumberBase).c_str());
|
||||
fields.AddString(L"BitLengthType", GetProgrammerType(bitLengthType).c_str());
|
||||
LogTelemetryEvent(EVENT_NAME_INVALID_INPUT_PASTED, fields);
|
||||
fields.AddUInt64(PDT_PRIVACY_DATA_TAG, PDT_PRODUCT_AND_SERVICE_USAGE);
|
||||
LogTelemetryEvent(EVENT_NAME_INVALID_PASTED_INPUT_OCCURRED, fields);
|
||||
}
|
||||
|
||||
void TraceLogger::LogValidInputPasted(ViewMode mode) const
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
|
||||
static const int maxFunctionSize = (int)CalculationManager::Command::CommandBINEDITEND;
|
||||
|
||||
// A trace logging provider can only be instantiated and registered once per module.
|
||||
// This class implements a singleton model ensure that only one instance is created.
|
||||
// A trace logging provider can only be instantiated and registered once per module.
|
||||
// This class implements a singleton model ensure that only one instance is created.
|
||||
namespace CalculatorApp
|
||||
{
|
||||
struct FuncLog
|
||||
|
@ -64,7 +64,7 @@ namespace CalculatorApp
|
|||
void LogMemoryFlyoutOpenBegin(unsigned int) const;
|
||||
void LogDebug(std::wstring_view debugData);
|
||||
void LogMemoryFlyoutOpenEnd(unsigned int) const;
|
||||
void LogInvalidInputPasted(std::wstring_view reason, std::wstring_view pastedExpression, CalculatorApp::Common::ViewMode mode, int ProgrammerNumberBase, int bitLengthType);
|
||||
void LogInvalidPastedInputOccurred(std::wstring_view reason, CalculatorApp::Common::ViewMode mode, int ProgrammerNumberBase, int bitLengthType);
|
||||
void LogValidInputPasted(CalculatorApp::Common::ViewMode mode) const;
|
||||
void UpdateFunctionUsage(int func);
|
||||
void LogFunctionUsage(int);
|
||||
|
@ -105,7 +105,7 @@ namespace CalculatorApp
|
|||
|
||||
// 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
|
||||
// We're using Verbose level for events that are called frequently and needed only for debugging or capturing perf for specific scenarios
|
||||
// We're using Verbose level for events that are called frequently and needed only for debugging or capturing perf for specific scenarios
|
||||
// b) should decide whether or not to log to telemetry and pass 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;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
//
|
||||
|
@ -54,7 +54,7 @@ double Utils::GetDoubleFromWstring(wstring input)
|
|||
return ::atof(inputString.c_str());
|
||||
}
|
||||
|
||||
//returns windowId for the current view
|
||||
// Returns windowId for the current view
|
||||
int Utils::GetWindowId()
|
||||
{
|
||||
int windowId = -1;
|
||||
|
@ -80,20 +80,13 @@ void Utils::RunOnUIThreadNonblocking(std::function<void()>&& function, _In_ Core
|
|||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
return !input.empty() && input.back() == target;
|
||||
}
|
||||
|
||||
//return wstring after removing characters like space, comma, and double quotes
|
||||
wstring Utils::RemoveUnwantedCharsFromWstring(wstring input)
|
||||
{
|
||||
wchar_t unWantedChars[] = { L' ', L',', L'"', 8234, 8235, 8236, 8237 };
|
||||
return RemoveUnwantedCharsFromWstring(input, unWantedChars, 6);
|
||||
}
|
||||
|
||||
//return wstring after removing characters specified by unwantedChars array
|
||||
// Return wstring after removing characters specified by unwantedChars array
|
||||
wstring Utils::RemoveUnwantedCharsFromWstring(wstring input, wchar_t* unwantedChars, unsigned int size)
|
||||
{
|
||||
for (unsigned int i = 0; i < size; ++i)
|
||||
|
@ -110,7 +103,7 @@ void Utils::SerializeCommandsAndTokens(_In_ shared_ptr<CalculatorVector <pair<ws
|
|||
unsigned int commandsSize;
|
||||
IFTPlatformException(commands->GetSize(&commandsSize));
|
||||
|
||||
// save the size of the commands vector
|
||||
// Save the size of the commands vector
|
||||
writer->WriteUInt32(commandsSize);
|
||||
|
||||
SerializeCommandVisitor cmdVisitor(writer);
|
||||
|
|
|
@ -42,10 +42,16 @@
|
|||
}\
|
||||
} private: t m_##n; public:
|
||||
|
||||
#define NAMED_OBSERVABLE_PROPERTY_RW(t, n)\
|
||||
#define OBSERVABLE_NAMED_PROPERTY_R(t, n)\
|
||||
OBSERVABLE_PROPERTY_R(t, n)\
|
||||
internal: static property Platform::String^ n##PropertyName {\
|
||||
Platform::String^ get() { return Platform::StringReference(L#n); }\
|
||||
} public:
|
||||
|
||||
#define OBSERVABLE_NAMED_PROPERTY_RW(t, n)\
|
||||
OBSERVABLE_PROPERTY_RW(t, n)\
|
||||
private: property Platform::StringReference n##_PropertyName {\
|
||||
Platform::StringReference get() { return Platform::StringReference(L#n); }\
|
||||
internal: static property Platform::String^ n##PropertyName {\
|
||||
Platform::String^ get() { return Platform::StringReference(L#n); }\
|
||||
} public:
|
||||
|
||||
#define OBSERVABLE_PROPERTY_FIELD(n) m_##n
|
||||
|
@ -54,11 +60,11 @@
|
|||
#ifndef UNIT_TESTS
|
||||
#define OBSERVABLE_OBJECT() virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler^ PropertyChanged;\
|
||||
internal: void RaisePropertyChanged(Platform::String^ p) {\
|
||||
PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs(p)); } public:
|
||||
PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs(p)); } public:
|
||||
#else
|
||||
#define OBSERVABLE_OBJECT() virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler^ PropertyChanged;\
|
||||
internal: void RaisePropertyChanged(Platform::String^ p) {\
|
||||
} public:
|
||||
} public:
|
||||
#endif
|
||||
|
||||
// The callback specified in the macro is a method in the class that will be called every time the object changes
|
||||
|
@ -68,21 +74,21 @@
|
|||
internal: void RaisePropertyChanged(Platform::String^ p) {\
|
||||
PropertyChanged(this, ref new Windows::UI::Xaml::Data::PropertyChangedEventArgs(p));\
|
||||
c(p);\
|
||||
} public:
|
||||
} public:
|
||||
#else
|
||||
#define OBSERVABLE_OBJECT_CALLBACK(c) virtual event Windows::UI::Xaml::Data::PropertyChangedEventHandler^ PropertyChanged;\
|
||||
internal: void RaisePropertyChanged(Platform::String^ p) {\
|
||||
c(p);\
|
||||
} public:
|
||||
} public:
|
||||
#endif
|
||||
|
||||
// The variable member generated by this macro should not be used in the class code, use the
|
||||
// property getter instead.
|
||||
// The variable member generated by this macro should not be used in the class code, use the
|
||||
// property getter instead.
|
||||
#define COMMAND_FOR_METHOD(p, m) property Windows::UI::Xaml::Input::ICommand^ p {\
|
||||
Windows::UI::Xaml::Input::ICommand^ get() {\
|
||||
if (!donotuse_##p) {\
|
||||
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)\
|
||||
property t n {\
|
||||
|
@ -141,7 +147,7 @@ namespace Utils
|
|||
const wchar_t PDF = 0x202c; // Pop Directional Formatting
|
||||
const wchar_t LRO = 0x202d; // Left-to-Right Override
|
||||
|
||||
// Regular DependencyProperty
|
||||
// Regular DependencyProperty
|
||||
template <typename TOwner, typename TType>
|
||||
Windows::UI::Xaml::DependencyProperty^ RegisterDependencyProperty(
|
||||
_In_ const wchar_t* const name,
|
||||
|
@ -205,7 +211,7 @@ namespace Utils
|
|||
ref new Windows::UI::Xaml::PropertyChangedCallback(callback)));
|
||||
}
|
||||
|
||||
// Attached DependencyProperty
|
||||
// Attached DependencyProperty
|
||||
template <typename TOwner, typename TType>
|
||||
Windows::UI::Xaml::DependencyProperty^ RegisterDependencyPropertyAttached(
|
||||
_In_ const wchar_t* const name,
|
||||
|
@ -280,7 +286,6 @@ namespace Utils
|
|||
Platform::String^ GetStringValue(Platform::String^ input);
|
||||
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 input);
|
||||
double GetDoubleFromWstring(std::wstring input);
|
||||
int GetWindowId();
|
||||
void RunOnUIThreadNonblocking(std::function<void()>&& function, _In_ Windows::UI::Core::CoreDispatcher^ currentDispatcher);
|
||||
|
|
|
@ -14,9 +14,9 @@ namespace CalculatorApp { namespace Common
|
|||
private:
|
||||
|
||||
virtual Platform::Object^ Convert(
|
||||
Platform::Object^ value,
|
||||
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
|
||||
Platform::Object^ /*parameter*/,
|
||||
Platform::Object^ value,
|
||||
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
|
||||
|
@ -24,9 +24,9 @@ namespace CalculatorApp { namespace Common
|
|||
}
|
||||
|
||||
virtual Platform::Object^ ConvertBack(
|
||||
Platform::Object^ value,
|
||||
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
|
||||
Platform::Object^ /*parameter*/,
|
||||
Platform::Object^ value,
|
||||
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
|
||||
Platform::Object^ /*parameter*/,
|
||||
Platform::String^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::ConvertBack
|
||||
{
|
||||
if (value)
|
||||
|
@ -47,9 +47,9 @@ namespace CalculatorApp { namespace Common
|
|||
private:
|
||||
|
||||
virtual Platform::Object^ Convert(
|
||||
Platform::Object^ value,
|
||||
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
|
||||
Platform::Object^ /*parameter*/,
|
||||
Platform::Object^ value,
|
||||
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
|
||||
|
@ -57,9 +57,9 @@ namespace CalculatorApp { namespace Common
|
|||
}
|
||||
|
||||
virtual Platform::Object^ ConvertBack(
|
||||
Platform::Object^ value,
|
||||
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
|
||||
Platform::Object^ /*parameter*/,
|
||||
Platform::Object^ value,
|
||||
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
|
||||
Platform::Object^ /*parameter*/,
|
||||
Platform::String^ /*language*/) = Windows::UI::Xaml::Data::IValueConverter::ConvertBack
|
||||
{
|
||||
// The value to be valid has to be a boxed int32 value
|
||||
|
|
|
@ -203,7 +203,7 @@ void CurrencyDataLoader::LoadData()
|
|||
}
|
||||
}
|
||||
|
||||
co_return didLoad;
|
||||
co_return didLoad;
|
||||
}).then([this](bool didLoad)
|
||||
{
|
||||
UpdateDisplayedTimestamp();
|
||||
|
@ -329,7 +329,7 @@ task<bool> CurrencyDataLoader::TryLoadDataFromCacheAsync()
|
|||
{
|
||||
loadComplete = co_await TryLoadDataFromWebAsync();
|
||||
}
|
||||
|
||||
|
||||
if (!loadComplete)
|
||||
{
|
||||
loadComplete = co_await TryFinishLoadFromCacheAsync();
|
||||
|
|
|
@ -87,7 +87,7 @@ namespace CalculatorApp
|
|||
|
||||
bool TryParseWebResponses(
|
||||
_In_ Platform::String^ staticDataJson,
|
||||
_In_ Platform::String^ allRatiosJson,
|
||||
_In_ Platform::String^ allRatiosJson,
|
||||
_Inout_ std::vector<UCM::CurrencyStaticData>& staticData,
|
||||
_Inout_ CurrencyRatioMap& allRatiosData);
|
||||
bool TryParseStaticData(_In_ Platform::String^ rawJson, _Inout_ std::vector<UCM::CurrencyStaticData>& staticData);
|
||||
|
|
|
@ -200,7 +200,7 @@ void UnitConverterDataLoader::GetUnits(_In_ unordered_map<ViewMode, vector<Order
|
|||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Exbibits, GetLocalizedStringName(L"UnitName_Exbibits"), GetLocalizedStringName(L"UnitAbbreviation_Exbibits"), 24 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Exbibytes, GetLocalizedStringName(L"UnitName_Exbibytes"), GetLocalizedStringName(L"UnitAbbreviation_Exbibytes"), 26 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Gibibits, GetLocalizedStringName(L"UnitName_Gibibits"), GetLocalizedStringName(L"UnitAbbreviation_Gibibits"), 12 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Gibibytes, GetLocalizedStringName(L"UnitName_Gibibytes"), GetLocalizedStringName(L"UnitAbbreviation_Gibibytes"), 14 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Gibibytes, GetLocalizedStringName(L"UnitName_Gibibytes"), GetLocalizedStringName(L"UnitAbbreviation_Gibibytes"), 14 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Gigabit, GetLocalizedStringName(L"UnitName_Gigabit"), GetLocalizedStringName(L"UnitAbbreviation_Gigabit"), 11 });
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Gigabyte, GetLocalizedStringName(L"UnitName_Gigabyte"), GetLocalizedStringName(L"UnitAbbreviation_Gigabyte"),13, true, false, false});
|
||||
dataUnits.push_back(OrderedUnit{ UnitConverterUnits::Data_Kibibits, GetLocalizedStringName(L"UnitName_Kibibits"), GetLocalizedStringName(L"UnitAbbreviation_Kibibits"), 4 });
|
||||
|
|
|
@ -22,14 +22,14 @@ using namespace Windows::Globalization;
|
|||
using namespace Windows::Globalization::DateTimeFormatting;
|
||||
using namespace Windows::System::UserProfile;
|
||||
|
||||
namespace CalculatorApp::ViewModel::DateCalculatorViewModelProperties
|
||||
namespace
|
||||
{
|
||||
StringReference StrDateDiffResult(L"StrDateDiffResult");
|
||||
StringReference StrDateDiffResultAutomationName(L"StrDateDiffResultAutomationName");
|
||||
StringReference StrDateDiffResultInDays(L"StrDateDiffResultInDays");
|
||||
StringReference StrDateResult(L"StrDateResult");
|
||||
StringReference StrDateResultAutomationName(L"StrDateResultAutomationName");
|
||||
StringReference IsDiffInDays(L"IsDiffInDays");
|
||||
StringReference StrDateDiffResultPropertyName(L"StrDateDiffResult");
|
||||
StringReference StrDateDiffResultAutomationNamePropertyName(L"StrDateDiffResultAutomationName");
|
||||
StringReference StrDateDiffResultInDaysPropertyName(L"StrDateDiffResultInDays");
|
||||
StringReference StrDateResultPropertyName(L"StrDateResult");
|
||||
StringReference StrDateResultAutomationNamePropertyName(L"StrDateResultAutomationName");
|
||||
StringReference IsDiffInDaysPropertyName(L"IsDiffInDays");
|
||||
}
|
||||
|
||||
DateCalculatorViewModel::DateCalculatorViewModel() :
|
||||
|
@ -43,11 +43,7 @@ DateCalculatorViewModel::DateCalculatorViewModel() :
|
|||
m_StrDateDiffResultAutomationName(L""),
|
||||
m_StrDateDiffResultInDays(L""),
|
||||
m_StrDateResult(L""),
|
||||
m_StrDateResultAutomationName(L""),
|
||||
m_fromDate({ 0 }),
|
||||
m_toDate({ 0 }),
|
||||
m_startDate({ 0 }),
|
||||
m_dateResult({ 0 })
|
||||
m_StrDateResultAutomationName(L"")
|
||||
{
|
||||
const auto& localizationSettings = LocalizationSettings::GetInstance();
|
||||
|
||||
|
@ -56,24 +52,24 @@ DateCalculatorViewModel::DateCalculatorViewModel() :
|
|||
|
||||
// Initialize Date Calc engine
|
||||
m_dateCalcEngine = make_shared<DateCalculationEngine>(localizationSettings.GetCalendarIdentifier());
|
||||
|
||||
// Initialize dates of DatePicker controls to today's date
|
||||
auto calendar = ref new Calendar();
|
||||
// We force the timezone to UTC, in order to avoid being affected by Daylight Saving Time
|
||||
// when we calculate the difference between 2 dates.
|
||||
calendar->ChangeTimeZone("UTC");
|
||||
auto today = calendar->GetDateTime();
|
||||
|
||||
// FromDate and ToDate should be clipped (adjusted to a consistent hour in UTC)
|
||||
m_fromDate = today;
|
||||
m_toDate = today;
|
||||
FromDate = ClipTime(today);
|
||||
ToDate = ClipTime(today);
|
||||
m_fromDate = ClipTime(today);
|
||||
m_toDate = ClipTime(today);
|
||||
|
||||
// StartDate should not be clipped
|
||||
StartDate = today;
|
||||
m_startDate = today;
|
||||
m_dateResult = today;
|
||||
|
||||
// Initialize the list separator delimiter appended with a space at the end, e.g. ", "
|
||||
// This will be used for date difference formatting: Y years, M months, W weeks, D days
|
||||
m_listSeparator = ref new String((localizationSettings.GetListSeparator() + L" ").c_str());
|
||||
m_listSeparator = localizationSettings.GetListSeparator() + L" ";
|
||||
|
||||
// Initialize the output results
|
||||
UpdateDisplayResult();
|
||||
|
@ -86,15 +82,6 @@ DateCalculatorViewModel::DateCalculatorViewModel() :
|
|||
m_offsetValues->Append(ref new String(numberStr.c_str()));
|
||||
}
|
||||
|
||||
/* In the ClipTime function, we used to change timezone to UTC before clipping the time.
|
||||
The comment from the previous developers said this was done to eliminate the effects of
|
||||
Daylight Savings Time. We can't think of a good reason why this change in timezone is
|
||||
necessary and did find bugs related to the change, therefore, we have removed the
|
||||
change. Just in case, we will see if the clipped time is ever a different day from the
|
||||
original day, which would hopefully indicate the change in timezone was actually
|
||||
necessary. We will collect telemetry if we find this case. If we don't see any
|
||||
telemetry events after the application has been used for some time, we will feel safe
|
||||
and can remove this function. */
|
||||
DayOfWeek trueDayOfWeek = calendar->DayOfWeek;
|
||||
|
||||
DateTime clippedTime = ClipTime(today);
|
||||
|
@ -110,18 +97,18 @@ DateCalculatorViewModel::DateCalculatorViewModel() :
|
|||
|
||||
void DateCalculatorViewModel::OnPropertyChanged(_In_ String^ prop)
|
||||
{
|
||||
if (prop == DateCalculatorViewModelProperties::StrDateDiffResult)
|
||||
if (prop == StrDateDiffResultPropertyName)
|
||||
{
|
||||
UpdateStrDateDiffResultAutomationName();
|
||||
}
|
||||
else if (prop == DateCalculatorViewModelProperties::StrDateResult)
|
||||
else if (prop == StrDateResultPropertyName)
|
||||
{
|
||||
UpdateStrDateResultAutomationName();
|
||||
}
|
||||
else if (prop != DateCalculatorViewModelProperties::StrDateDiffResultAutomationName
|
||||
&& prop != DateCalculatorViewModelProperties::StrDateDiffResultInDays
|
||||
&& prop != DateCalculatorViewModelProperties::StrDateResultAutomationName
|
||||
&& prop != DateCalculatorViewModelProperties::IsDiffInDays)
|
||||
else if (prop != StrDateDiffResultAutomationNamePropertyName
|
||||
&& prop != StrDateDiffResultInDaysPropertyName
|
||||
&& prop != StrDateResultAutomationNamePropertyName
|
||||
&& prop != IsDiffInDaysPropertyName)
|
||||
{
|
||||
OnInputsChanged();
|
||||
}
|
||||
|
@ -180,9 +167,9 @@ void DateCalculatorViewModel::UpdateDisplayResult()
|
|||
StrDateDiffResultInDays = L"";
|
||||
StrDateDiffResult = AppResourceProvider::GetInstance().GetResourceString(L"Date_SameDates");
|
||||
}
|
||||
else if ((m_dateDiffResult.year == 0) &&
|
||||
(m_dateDiffResult.month == 0) &&
|
||||
(m_dateDiffResult.week == 0))
|
||||
else if ((m_dateDiffResult.year == 0) &&
|
||||
(m_dateDiffResult.month == 0) &&
|
||||
(m_dateDiffResult.week == 0))
|
||||
{
|
||||
IsDiffInDays = true;
|
||||
StrDateDiffResultInDays = L"";
|
||||
|
@ -245,22 +232,23 @@ void DateCalculatorViewModel::InitializeDateOutputFormats(_In_ String^ calendarI
|
|||
|
||||
String^ DateCalculatorViewModel::GetDateDiffString() const
|
||||
{
|
||||
String^ result = L"";
|
||||
wstring result;
|
||||
bool addDelimiter = false;
|
||||
AppResourceProvider resourceLoader = AppResourceProvider::GetInstance();
|
||||
|
||||
auto yearCount = m_dateDiffResult.year;
|
||||
if (yearCount > 0)
|
||||
{
|
||||
result = String::Concat(GetLocalizedNumberString(yearCount), L" ");
|
||||
result += GetLocalizedNumberString(yearCount)->Data();
|
||||
result += L" ";
|
||||
|
||||
if (yearCount > 1)
|
||||
{
|
||||
result = String::Concat(result, resourceLoader.GetResourceString(L"Date_Years"));
|
||||
result += resourceLoader.GetResourceString(L"Date_Years")->Data();
|
||||
}
|
||||
else
|
||||
{
|
||||
result = String::Concat(result, resourceLoader.GetResourceString(L"Date_Year"));
|
||||
result += resourceLoader.GetResourceString(L"Date_Year")->Data();
|
||||
}
|
||||
|
||||
// set the flags to add a delimiter whenever the next unit is added
|
||||
|
@ -272,22 +260,23 @@ String^ DateCalculatorViewModel::GetDateDiffString() const
|
|||
{
|
||||
if (addDelimiter)
|
||||
{
|
||||
result = String::Concat(result, m_listSeparator);
|
||||
result += m_listSeparator;
|
||||
}
|
||||
else
|
||||
{
|
||||
addDelimiter = true;
|
||||
}
|
||||
|
||||
result = String::Concat(result, String::Concat(GetLocalizedNumberString(monthCount), L" "));
|
||||
result += GetLocalizedNumberString(monthCount)->Data();
|
||||
result += L" ";
|
||||
|
||||
if (monthCount > 1)
|
||||
{
|
||||
result = String::Concat(result, resourceLoader.GetResourceString(L"Date_Months"));
|
||||
result += resourceLoader.GetResourceString(L"Date_Months")->Data();
|
||||
}
|
||||
else
|
||||
{
|
||||
result = String::Concat(result, resourceLoader.GetResourceString(L"Date_Month"));
|
||||
result += resourceLoader.GetResourceString(L"Date_Month")->Data();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -296,22 +285,23 @@ String^ DateCalculatorViewModel::GetDateDiffString() const
|
|||
{
|
||||
if (addDelimiter)
|
||||
{
|
||||
result = String::Concat(result, m_listSeparator);
|
||||
result += m_listSeparator;
|
||||
}
|
||||
else
|
||||
{
|
||||
addDelimiter = true;
|
||||
}
|
||||
|
||||
result = String::Concat(result, String::Concat(GetLocalizedNumberString(weekCount), L" "));
|
||||
result += GetLocalizedNumberString(weekCount)->Data();
|
||||
result += L" ";
|
||||
|
||||
if (weekCount > 1)
|
||||
{
|
||||
result = String::Concat(result, resourceLoader.GetResourceString(L"Date_Weeks"));
|
||||
result += resourceLoader.GetResourceString(L"Date_Weeks")->Data();
|
||||
}
|
||||
else
|
||||
{
|
||||
result = String::Concat(result, resourceLoader.GetResourceString(L"Date_Week"));
|
||||
result += resourceLoader.GetResourceString(L"Date_Week")->Data();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -320,43 +310,45 @@ String^ DateCalculatorViewModel::GetDateDiffString() const
|
|||
{
|
||||
if (addDelimiter)
|
||||
{
|
||||
result = String::Concat(result, m_listSeparator);
|
||||
result += m_listSeparator;
|
||||
}
|
||||
else
|
||||
{
|
||||
addDelimiter = true;
|
||||
}
|
||||
|
||||
result = String::Concat(result, String::Concat(GetLocalizedNumberString(dayCount), L" "));
|
||||
result += GetLocalizedNumberString(dayCount)->Data();
|
||||
result += L" ";
|
||||
|
||||
if (dayCount > 1)
|
||||
{
|
||||
result = String::Concat(result, resourceLoader.GetResourceString(L"Date_Days"));
|
||||
result += resourceLoader.GetResourceString(L"Date_Days")->Data();
|
||||
}
|
||||
else
|
||||
{
|
||||
result = String::Concat(result, resourceLoader.GetResourceString(L"Date_Day"));
|
||||
result += resourceLoader.GetResourceString(L"Date_Day")->Data();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return ref new String(result.data());
|
||||
}
|
||||
|
||||
String^ DateCalculatorViewModel::GetDateDiffStringInDays() const
|
||||
{
|
||||
String^ strDateUnit;
|
||||
wstring result = GetLocalizedNumberString(m_dateDiffResultInDays.day)->Data();
|
||||
result += L" ";
|
||||
|
||||
// Display the result as '1 day' or 'N days'
|
||||
if (m_dateDiffResultInDays.day > 1)
|
||||
{
|
||||
strDateUnit = AppResourceProvider::GetInstance().GetResourceString(L"Date_Days");
|
||||
result += AppResourceProvider::GetInstance().GetResourceString(L"Date_Days")->Data();
|
||||
}
|
||||
else
|
||||
{
|
||||
strDateUnit = AppResourceProvider::GetInstance().GetResourceString(L"Date_Day");
|
||||
result += AppResourceProvider::GetInstance().GetResourceString(L"Date_Day")->Data();
|
||||
}
|
||||
|
||||
return String::Concat(GetLocalizedNumberString(m_dateDiffResultInDays.day), String::Concat(L" ", strDateUnit));
|
||||
return ref new String(result.data());
|
||||
}
|
||||
|
||||
void DateCalculatorViewModel::OnCopyCommand(Platform::Object^ parameter)
|
||||
|
@ -378,13 +370,14 @@ String^ DateCalculatorViewModel::GetLocalizedNumberString(int value) const
|
|||
return ref new String(numberStr.c_str());
|
||||
}
|
||||
|
||||
// Adjusts the given DateTime to 12AM of the same day
|
||||
// Adjusts the given DateTime to 12AM (UTC) of the same day
|
||||
DateTime DateCalculatorViewModel::ClipTime(DateTime dateTime)
|
||||
{
|
||||
auto calendar = ref new Calendar();
|
||||
calendar->ChangeTimeZone("UTC");
|
||||
calendar->SetDateTime(dateTime);
|
||||
calendar->Period = 1;
|
||||
calendar->Hour = 12;
|
||||
calendar->Period = calendar->FirstPeriodInThisDay;
|
||||
calendar->Hour = calendar->FirstHourInThisPeriod;
|
||||
calendar->Minute = 0;
|
||||
calendar->Second = 0;
|
||||
calendar->Nanosecond = 0;
|
||||
|
|
|
@ -23,8 +23,8 @@ namespace CalculatorApp
|
|||
// Input Properties
|
||||
OBSERVABLE_PROPERTY_RW(bool, IsDateDiffMode);
|
||||
OBSERVABLE_PROPERTY_RW(bool, IsAddMode);
|
||||
OBSERVABLE_PROPERTY_RW(bool, IsDiffInDays); // If diff is only in days or the dates are the same,
|
||||
// then show only one result and avoid redundancy
|
||||
OBSERVABLE_PROPERTY_R(bool, IsDiffInDays); // If diff is only in days or the dates are the same,
|
||||
// then show only one result and avoid redundancy
|
||||
|
||||
OBSERVABLE_PROPERTY_RW(int, DaysOffset);
|
||||
OBSERVABLE_PROPERTY_RW(int, MonthsOffset);
|
||||
|
@ -82,11 +82,11 @@ namespace CalculatorApp
|
|||
}
|
||||
|
||||
// Output Properties
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String^, StrDateDiffResult);
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String^, StrDateDiffResultAutomationName);
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String^, StrDateDiffResultInDays);
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String^, StrDateResult);
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String^, StrDateResultAutomationName);
|
||||
OBSERVABLE_PROPERTY_R(Platform::String^, StrDateDiffResult);
|
||||
OBSERVABLE_PROPERTY_R(Platform::String^, StrDateDiffResultAutomationName);
|
||||
OBSERVABLE_PROPERTY_R(Platform::String^, StrDateDiffResultInDays);
|
||||
OBSERVABLE_PROPERTY_R(Platform::String^, StrDateResult);
|
||||
OBSERVABLE_PROPERTY_R(Platform::String^, StrDateResultAutomationName);
|
||||
|
||||
COMMAND_FOR_METHOD(CopyCommand, DateCalculatorViewModel::OnCopyCommand);
|
||||
|
||||
|
@ -104,8 +104,6 @@ namespace CalculatorApp
|
|||
Platform::String^ GetLocalizedNumberString(int value) const;
|
||||
static Windows::Foundation::DateTime ClipTime(Windows::Foundation::DateTime dateTime);
|
||||
|
||||
static void CheckClipTimeSameDay(Windows::Globalization::Calendar^ reference);
|
||||
|
||||
property bool IsOutOfBound
|
||||
{
|
||||
bool get() { return m_isOutOfBound; }
|
||||
|
@ -146,7 +144,7 @@ namespace CalculatorApp
|
|||
CalculatorApp::Common::DateCalculation::DateUnit m_daysOutputFormat;
|
||||
CalculatorApp::Common::DateCalculation::DateUnit m_allDateUnitsOutputFormat;
|
||||
Windows::Globalization::DateTimeFormatting::DateTimeFormatter^ m_dateTimeFormatter;
|
||||
Platform::String^ m_listSeparator;
|
||||
std::wstring m_listSeparator;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,18 +17,18 @@ namespace CalculatorApp
|
|||
internal:
|
||||
|
||||
HistoryItemViewModel(Platform::String^ expression,
|
||||
Platform::String^ result,
|
||||
Platform::String^ result,
|
||||
_In_ std::shared_ptr<CalculatorVector <std::pair<std::wstring, int>>> const &spTokens,
|
||||
_In_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const &spCommands);
|
||||
|
||||
std::shared_ptr<CalculatorVector <std::pair<std::wstring, int>>> const& GetTokens()
|
||||
{
|
||||
return m_spTokens;
|
||||
return m_spTokens;
|
||||
}
|
||||
|
||||
std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const& GetCommands()
|
||||
{
|
||||
return m_spCommands;
|
||||
{
|
||||
return m_spCommands;
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
|
@ -64,7 +64,7 @@ void HistoryViewModel::ReloadHistory(_In_ ViewMode currentMode)
|
|||
if (historyListModel.size() > 0)
|
||||
{
|
||||
for (auto ritr = historyListModel.rbegin(); ritr != historyListModel.rend(); ++ritr)
|
||||
{
|
||||
{
|
||||
wstring expression = (*ritr)->historyItemVector.expression;
|
||||
wstring result = (*ritr)->historyItemVector.result;
|
||||
localizer.LocalizeDisplayValue(&expression);
|
||||
|
|
|
@ -30,37 +30,34 @@ constexpr int StandardModePrecision = 16;
|
|||
constexpr int ScientificModePrecision = 32;
|
||||
constexpr int ProgrammerModePrecision = 64;
|
||||
|
||||
namespace CalculatorApp::ViewModel
|
||||
namespace
|
||||
{
|
||||
namespace CalculatorViewModelProperties
|
||||
{
|
||||
StringReference IsMemoryEmpty(L"IsMemoryEmpty");
|
||||
StringReference IsScientific(L"IsScientific");
|
||||
StringReference IsStandard(L"IsStandard");
|
||||
StringReference IsProgrammer(L"IsProgrammer");
|
||||
StringReference DisplayValue(L"DisplayValue");
|
||||
StringReference IsInError(L"IsInError");
|
||||
StringReference BinaryDisplayValue(L"BinaryDisplayValue");
|
||||
}
|
||||
|
||||
namespace CalculatorResourceKeys
|
||||
{
|
||||
StringReference CalculatorExpression(L"Format_CalculatorExpression");
|
||||
StringReference CalculatorResults(L"Format_CalculatorResults");
|
||||
StringReference CalculatorResults_DecimalSeparator_Announced(L"Format_CalculatorResults_Decimal");
|
||||
StringReference HexButton(L"Format_HexButtonValue");
|
||||
StringReference DecButton(L"Format_DecButtonValue");
|
||||
StringReference OctButton(L"Format_OctButtonValue");
|
||||
StringReference BinButton(L"Format_BinButtonValue");
|
||||
StringReference LeftParenthesisAutomationFormat(L"Format_OpenParenthesisAutomationNamePrefix");
|
||||
StringReference MaxDigitsReachedFormat(L"Format_MaxDigitsReached");
|
||||
StringReference ButtonPressFeedbackFormat(L"Format_ButtonPressAuditoryFeedback");
|
||||
StringReference MemorySave(L"Format_MemorySave");
|
||||
StringReference MemoryItemChanged(L"Format_MemorySlotChanged");
|
||||
StringReference MemoryItemCleared(L"Format_MemorySlotCleared");
|
||||
StringReference MemoryCleared(L"Memory_Cleared");
|
||||
StringReference DisplayCopied(L"Display_Copied");
|
||||
}
|
||||
StringReference IsStandardPropertyName(L"IsStandard");
|
||||
StringReference IsScientificPropertyName(L"IsScientific");
|
||||
StringReference IsProgrammerPropertyName(L"IsProgrammer");
|
||||
StringReference DisplayValuePropertyName(L"DisplayValue");
|
||||
StringReference CalculationResultAutomationNamePropertyName(L"CalculationResultAutomationName");
|
||||
}
|
||||
|
||||
namespace CalculatorResourceKeys
|
||||
{
|
||||
StringReference CalculatorExpression(L"Format_CalculatorExpression");
|
||||
StringReference CalculatorResults(L"Format_CalculatorResults");
|
||||
StringReference CalculatorResults_DecimalSeparator_Announced(L"Format_CalculatorResults_Decimal");
|
||||
StringReference HexButton(L"Format_HexButtonValue");
|
||||
StringReference DecButton(L"Format_DecButtonValue");
|
||||
StringReference OctButton(L"Format_OctButtonValue");
|
||||
StringReference BinButton(L"Format_BinButtonValue");
|
||||
StringReference LeftParenthesisAutomationFormat(L"Format_OpenParenthesisAutomationNamePrefix");
|
||||
StringReference OpenParenthesisCountAutomationFormat(L"Format_OpenParenthesisCountAutomationNamePrefix");
|
||||
StringReference NoParenthesisAdded(L"NoRightParenthesisAdded_Announcement");
|
||||
StringReference MaxDigitsReachedFormat(L"Format_MaxDigitsReached");
|
||||
StringReference ButtonPressFeedbackFormat(L"Format_ButtonPressAuditoryFeedback");
|
||||
StringReference MemorySave(L"Format_MemorySave");
|
||||
StringReference MemoryItemChanged(L"Format_MemorySlotChanged");
|
||||
StringReference MemoryItemCleared(L"Format_MemorySlotCleared");
|
||||
StringReference MemoryCleared(L"Memory_Cleared");
|
||||
StringReference DisplayCopied(L"Display_Copied");
|
||||
}
|
||||
|
||||
StandardCalculatorViewModel::StandardCalculatorViewModel() :
|
||||
|
@ -92,7 +89,9 @@ StandardCalculatorViewModel::StandardCalculatorViewModel() :
|
|||
m_localizedMemorySavedAutomationFormat(nullptr),
|
||||
m_localizedMemoryItemChangedAutomationFormat(nullptr),
|
||||
m_localizedMemoryItemClearedAutomationFormat(nullptr),
|
||||
m_localizedMemoryCleared(nullptr)
|
||||
m_localizedMemoryCleared(nullptr),
|
||||
m_localizedOpenParenthesisCountChangedAutomationFormat(nullptr),
|
||||
m_localizedNoRightParenthesisAddedFormat(nullptr)
|
||||
{
|
||||
WeakReference calculatorViewModel(this);
|
||||
m_calculatorDisplay.SetCallback(calculatorViewModel);
|
||||
|
@ -226,6 +225,34 @@ void StandardCalculatorViewModel::SetParenthesisCount(_In_ const wstring& parent
|
|||
}
|
||||
}
|
||||
|
||||
void StandardCalculatorViewModel::SetOpenParenthesisCountNarratorAnnouncement()
|
||||
{
|
||||
String^ parenthesisCount = ((m_OpenParenthesisCount == nullptr) ? "0" : m_OpenParenthesisCount);
|
||||
wstring localizedParenthesisCount = parenthesisCount->Data();
|
||||
LocalizationSettings::GetInstance().LocalizeDisplayValue(&localizedParenthesisCount);
|
||||
|
||||
String^ announcement = LocalizationStringUtil::GetLocalizedNarratorAnnouncement(
|
||||
CalculatorResourceKeys::OpenParenthesisCountAutomationFormat,
|
||||
m_localizedOpenParenthesisCountChangedAutomationFormat,
|
||||
localizedParenthesisCount.c_str());
|
||||
|
||||
Announcement = CalculatorAnnouncement::GetOpenParenthesisCountChangedAnnouncement(announcement);
|
||||
}
|
||||
|
||||
void StandardCalculatorViewModel::OnNoRightParenAdded()
|
||||
{
|
||||
SetNoParenAddedNarratorAnnouncement();
|
||||
}
|
||||
|
||||
void StandardCalculatorViewModel::SetNoParenAddedNarratorAnnouncement()
|
||||
{
|
||||
String^ announcement = LocalizationStringUtil::GetLocalizedNarratorAnnouncement(
|
||||
CalculatorResourceKeys::NoParenthesisAdded,
|
||||
m_localizedNoRightParenthesisAddedFormat);
|
||||
|
||||
Announcement = CalculatorAnnouncement::GetNoRightParenthesisAddedAnnouncement(announcement);
|
||||
}
|
||||
|
||||
void StandardCalculatorViewModel::DisableButtons(CommandType selectedExpressionCommandType)
|
||||
{
|
||||
if (selectedExpressionCommandType == CommandType::OperandCommand)
|
||||
|
@ -483,7 +510,7 @@ void StandardCalculatorViewModel::HandleUpdatedOperandData(Command cmdenum)
|
|||
|
||||
if (IsOperandTextCompletelySelected)
|
||||
{
|
||||
//Clear older text;
|
||||
// Clear older text;
|
||||
m_selectedExpressionLastData = L"";
|
||||
if (ch == L'x')
|
||||
{
|
||||
|
@ -525,6 +552,7 @@ void StandardCalculatorViewModel::HandleUpdatedOperandData(Command cmdenum)
|
|||
length = m_selectedExpressionLastData->Length() + 1;
|
||||
if (length > 50)
|
||||
{
|
||||
delete [] temp;
|
||||
return;
|
||||
}
|
||||
for (; i < length; ++i)
|
||||
|
@ -550,8 +578,7 @@ void StandardCalculatorViewModel::HandleUpdatedOperandData(Command cmdenum)
|
|||
|
||||
bool StandardCalculatorViewModel::IsOperator(Command cmdenum)
|
||||
{
|
||||
if ((cmdenum == Command::Command0) || (cmdenum == Command::Command1) || (cmdenum == Command::Command2) || (cmdenum == Command::Command3) || (cmdenum == Command::Command4) || (cmdenum == Command::Command5)
|
||||
|| (cmdenum == Command::Command6) || (cmdenum == Command::Command7) || (cmdenum == Command::Command8) || (cmdenum == Command::Command9) || (cmdenum == Command::CommandPNT) || (cmdenum == Command::CommandBACK)
|
||||
if ((cmdenum >= Command::Command0 && cmdenum <= Command::Command9) || (cmdenum == Command::CommandPNT) || (cmdenum == Command::CommandBACK)
|
||||
|| (cmdenum == Command::CommandEXP) || (cmdenum == Command::CommandFE) || (cmdenum == Command::ModeBasic) || (cmdenum == Command::ModeProgrammer) || (cmdenum == Command::ModeScientific)
|
||||
|| (cmdenum == Command::CommandINV) || (cmdenum == Command::CommandCENTR) || (cmdenum == Command::CommandDEG) || (cmdenum == Command::CommandRAD) || (cmdenum == Command::CommandGRAD)
|
||||
|| ((cmdenum >= Command::CommandBINEDITSTART) && (cmdenum <= Command::CommandBINEDITEND)))
|
||||
|
@ -572,7 +599,7 @@ void StandardCalculatorViewModel::OnButtonPressed(Object^ parameter)
|
|||
if (IsInError)
|
||||
{
|
||||
m_standardCalculatorManager.SendCommand(Command::CommandCLEAR);
|
||||
|
||||
|
||||
if (!IsRecoverableCommand((int)numOpEnum))
|
||||
{
|
||||
return;
|
||||
|
@ -624,8 +651,7 @@ void StandardCalculatorViewModel::OnButtonPressed(Object^ parameter)
|
|||
{
|
||||
m_CurrentAngleType = numOpEnum;
|
||||
}
|
||||
if ((cmdenum == Command::Command0) || (cmdenum == Command::Command1) || (cmdenum == Command::Command2) || (cmdenum == Command::Command3) || (cmdenum == Command::Command4) || (cmdenum == Command::Command5)
|
||||
|| (cmdenum == Command::Command6) || (cmdenum == Command::Command7) || (cmdenum == Command::Command8) || (cmdenum == Command::Command9) || (cmdenum == Command::CommandPNT) || (cmdenum == Command::CommandBACK) || (cmdenum == Command::CommandEXP))
|
||||
if ((cmdenum >= Command::Command0 && cmdenum <= Command::Command9) || (cmdenum == Command::CommandPNT) || (cmdenum == Command::CommandBACK) || (cmdenum == Command::CommandEXP))
|
||||
{
|
||||
IsOperatorCommand = false;
|
||||
}
|
||||
|
@ -835,8 +861,8 @@ void StandardCalculatorViewModel::OnPaste(String^ pastedString, ViewMode mode)
|
|||
Command cmdenum = ConvertToOperatorsEnum(mappedNumOp);
|
||||
m_standardCalculatorManager.SendCommand(cmdenum);
|
||||
|
||||
// The CalcEngine state machine won't allow the negate command to be sent before any
|
||||
// other digits, so instead a flag is set and the command is sent after the first appropriate
|
||||
// The CalcEngine state machine won't allow the negate command to be sent before any
|
||||
// other digits, so instead a flag is set and the command is sent after the first appropriate
|
||||
// command.
|
||||
if (sendNegate)
|
||||
{
|
||||
|
@ -1162,10 +1188,10 @@ Array<unsigned char>^ StandardCalculatorViewModel::Serialize()
|
|||
writer->WriteInt32(data);
|
||||
}
|
||||
|
||||
//For ProgrammerMode
|
||||
// For ProgrammerMode
|
||||
writer->WriteUInt32(static_cast<UINT32>(CurrentRadixType));
|
||||
|
||||
//Serialize commands of calculator manager
|
||||
// Serialize commands of calculator manager
|
||||
vector<unsigned char> serializedCommand = m_standardCalculatorManager.SerializeCommands();
|
||||
writer->WriteUInt32(static_cast<UINT32>(serializedCommand.size()));
|
||||
writer->WriteBytes(ref new Array<unsigned char>(serializedCommand.data(), static_cast<unsigned int>(serializedCommand.size())));
|
||||
|
@ -1175,7 +1201,7 @@ Array<unsigned char>^ StandardCalculatorViewModel::Serialize()
|
|||
Utils::SerializeCommandsAndTokens(m_tokens, m_commands, writer);
|
||||
}
|
||||
|
||||
//Convert viewmodel data in writer to bytes
|
||||
// Convert viewmodel data in writer to bytes
|
||||
IBuffer^ buffer = writer->DetachBuffer();
|
||||
DataReader^ reader = DataReader::FromBuffer(buffer);
|
||||
Platform::Array<unsigned char>^ viewModelDataAsBytes = ref new Array<unsigned char>(buffer->Length);
|
||||
|
@ -1223,7 +1249,7 @@ void StandardCalculatorViewModel::Deserialize(Array<unsigned char>^ state)
|
|||
m_standardCalculatorManager.DeSerializePrimaryDisplay(serializedPrimaryDisplay);
|
||||
|
||||
CurrentRadixType = reader->ReadUInt32();
|
||||
//Read command data and Deserialize
|
||||
// Read command data and Deserialize
|
||||
UINT32 modeldatalength = reader->ReadUInt32();
|
||||
Array<unsigned char>^ modelDataAsBytes = ref new Array<unsigned char>(modeldatalength);
|
||||
reader->ReadBytes(modelDataAsBytes);
|
||||
|
@ -1242,30 +1268,30 @@ void StandardCalculatorViewModel::Deserialize(Array<unsigned char>^ state)
|
|||
|
||||
void StandardCalculatorViewModel::OnPropertyChanged(String^ propertyname)
|
||||
{
|
||||
if (propertyname == CalculatorViewModelProperties::IsScientific)
|
||||
if (propertyname == IsScientificPropertyName)
|
||||
{
|
||||
if (IsScientific)
|
||||
{
|
||||
OnButtonPressed(NumbersAndOperatorsEnum::IsScientificMode);
|
||||
}
|
||||
}
|
||||
else if (propertyname == CalculatorViewModelProperties::IsProgrammer)
|
||||
else if (propertyname == IsProgrammerPropertyName)
|
||||
{
|
||||
if (IsProgrammer)
|
||||
{
|
||||
OnButtonPressed(NumbersAndOperatorsEnum::IsProgrammerMode);
|
||||
}
|
||||
}
|
||||
else if (propertyname == CalculatorViewModelProperties::IsStandard)
|
||||
else if (propertyname == IsStandardPropertyName)
|
||||
{
|
||||
if (IsStandard)
|
||||
{
|
||||
OnButtonPressed(NumbersAndOperatorsEnum::IsStandardMode);
|
||||
}
|
||||
}
|
||||
else if (propertyname == CalculatorViewModelProperties::DisplayValue)
|
||||
else if (propertyname == DisplayValuePropertyName)
|
||||
{
|
||||
RaisePropertyChanged(CalculationResultAutomationName_PropertyName);
|
||||
RaisePropertyChanged(CalculationResultAutomationNamePropertyName);
|
||||
Announcement = GetDisplayUpdatedNarratorAnnouncement();
|
||||
}
|
||||
}
|
||||
|
@ -1570,7 +1596,7 @@ void StandardCalculatorViewModel::Recalculate(bool fromHistory)
|
|||
m_standardCalculatorManager.SendCommand(static_cast<CalculationManager::Command>(currentCommands[i]));
|
||||
}
|
||||
|
||||
if (fromHistory) // This is for the cases where the expression is loaded from history
|
||||
if (fromHistory) // This is for the cases where the expression is loaded from history
|
||||
{
|
||||
// To maintain F-E state of the engine, as the last operand hasn't reached engine by now
|
||||
m_standardCalculatorManager.SendCommand(Command::CommandFE);
|
||||
|
@ -1614,7 +1640,7 @@ bool StandardCalculatorViewModel::IsOpnd(int nOpCode)
|
|||
Command::CommandPNT
|
||||
};
|
||||
|
||||
for (int i = 0; i < ARRAYSIZE(opnd); i++)
|
||||
for (unsigned int i = 0; i < size(opnd); i++)
|
||||
{
|
||||
if (nOpCode == static_cast<int>(opnd[i]))
|
||||
{
|
||||
|
@ -1645,7 +1671,7 @@ bool StandardCalculatorViewModel::IsUnaryOp(int nOpCode)
|
|||
Command::CommandCUB
|
||||
};
|
||||
|
||||
for (int i = 0; i < ARRAYSIZE(unaryOp); i++)
|
||||
for (unsigned int i = 0; i < size(unaryOp); i++)
|
||||
{
|
||||
if (nOpCode == static_cast<int>(unaryOp[i]))
|
||||
{
|
||||
|
@ -1672,7 +1698,7 @@ bool StandardCalculatorViewModel::IsTrigOp(int nOpCode)
|
|||
Command::CommandATAN
|
||||
};
|
||||
|
||||
for (int i = 0; i < ARRAYSIZE(trigOp); i++)
|
||||
for (unsigned int i = 0; i < size(trigOp); i++)
|
||||
{
|
||||
if (nOpCode == static_cast<int>(trigOp[i]))
|
||||
{
|
||||
|
@ -1695,7 +1721,7 @@ bool StandardCalculatorViewModel::IsBinOp(int nOpCode)
|
|||
Command::CommandPWR
|
||||
};
|
||||
|
||||
for (int i = 0; i < ARRAYSIZE(binOp); i++)
|
||||
for (unsigned int i = 0; i < size(binOp); i++)
|
||||
{
|
||||
if (nOpCode == static_cast<int>(binOp[i]))
|
||||
{
|
||||
|
@ -1729,7 +1755,7 @@ bool StandardCalculatorViewModel::IsRecoverableCommand(int nOpCode)
|
|||
Command::CommandF
|
||||
};
|
||||
|
||||
for (int i = 0; i < ARRAYSIZE(recoverableCommands); i++)
|
||||
for (unsigned int i = 0; i < size(recoverableCommands); i++)
|
||||
{
|
||||
if (nOpCode == static_cast<int>(recoverableCommands[i]))
|
||||
{
|
||||
|
@ -1947,7 +1973,7 @@ void StandardCalculatorViewModel::UpdatecommandsInRecordingMode()
|
|||
}
|
||||
else
|
||||
{
|
||||
//reset all vars
|
||||
// Reset all vars
|
||||
isDecimal = false;
|
||||
isNegative = false;
|
||||
isExpMode = false;
|
||||
|
|
|
@ -31,12 +31,6 @@ namespace CalculatorApp
|
|||
#define ASCII_0 48
|
||||
public delegate void HideMemoryClickedHandler();
|
||||
public delegate void ProgModeRadixChangeHandler();
|
||||
namespace CalculatorViewModelProperties
|
||||
{
|
||||
extern Platform::StringReference IsMemoryEmpty;
|
||||
extern Platform::StringReference IsInError;
|
||||
extern Platform::StringReference BinaryDisplayValue;
|
||||
}
|
||||
|
||||
[Windows::UI::Xaml::Data::Bindable]
|
||||
public ref class StandardCalculatorViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
|
||||
|
@ -51,14 +45,14 @@ namespace CalculatorApp
|
|||
OBSERVABLE_OBJECT_CALLBACK(OnPropertyChanged);
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String^, DisplayValue);
|
||||
OBSERVABLE_PROPERTY_RW(HistoryViewModel^, HistoryVM);
|
||||
OBSERVABLE_PROPERTY_RW(bool, IsInError);
|
||||
OBSERVABLE_NAMED_PROPERTY_RW(bool, IsInError);
|
||||
OBSERVABLE_PROPERTY_RW(bool, IsOperatorCommand);
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String^, DisplayStringExpression);
|
||||
OBSERVABLE_PROPERTY_RW(Windows::Foundation::Collections::IVector<Common::DisplayExpressionToken^>^, ExpressionTokens);
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String^, DecimalDisplayValue);
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String^, HexDisplayValue);
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String^, OctalDisplayValue);
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String^, BinaryDisplayValue);
|
||||
OBSERVABLE_NAMED_PROPERTY_RW(Platform::String^, BinaryDisplayValue);
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String^, HexDisplayValue_AutomationName);
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String^, DecDisplayValue_AutomationName);
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String^, OctDisplayValue_AutomationName);
|
||||
|
@ -69,19 +63,19 @@ namespace CalculatorApp
|
|||
OBSERVABLE_PROPERTY_RW(bool, IsDecimalEnabled);
|
||||
OBSERVABLE_PROPERTY_RW(bool, IsCurrentViewPinned);
|
||||
OBSERVABLE_PROPERTY_RW(Windows::Foundation::Collections::IVector<MemoryItemViewModel^>^, MemorizedNumbers);
|
||||
OBSERVABLE_PROPERTY_RW(bool, IsMemoryEmpty);
|
||||
OBSERVABLE_NAMED_PROPERTY_RW(bool, IsMemoryEmpty);
|
||||
OBSERVABLE_PROPERTY_RW(bool, IsFToEChecked);
|
||||
OBSERVABLE_PROPERTY_RW(bool, IsFToEEnabled);
|
||||
OBSERVABLE_PROPERTY_RW(bool, IsHyperbolicChecked);
|
||||
OBSERVABLE_PROPERTY_RW(bool, AreHEXButtonsEnabled);
|
||||
NAMED_OBSERVABLE_PROPERTY_RW(Platform::String^, CalculationResultAutomationName);
|
||||
NAMED_OBSERVABLE_PROPERTY_RW(Platform::String^, CalculationExpressionAutomationName);
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String^, CalculationResultAutomationName);
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String^, CalculationExpressionAutomationName);
|
||||
OBSERVABLE_PROPERTY_RW(bool, IsShiftProgrammerChecked);
|
||||
OBSERVABLE_PROPERTY_RW(bool, IsQwordEnabled);
|
||||
OBSERVABLE_PROPERTY_RW(bool, IsDwordEnabled);
|
||||
OBSERVABLE_PROPERTY_RW(bool, IsWordEnabled);
|
||||
OBSERVABLE_PROPERTY_RW(bool, IsByteEnabled);
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String^, OpenParenthesisCount);
|
||||
OBSERVABLE_NAMED_PROPERTY_RW(Platform::String^, OpenParenthesisCount);
|
||||
OBSERVABLE_PROPERTY_RW(int, CurrentRadixType);
|
||||
OBSERVABLE_PROPERTY_RW(bool, AreTokensUpdated);
|
||||
OBSERVABLE_PROPERTY_RW(bool, AreHistoryShortcutsEnabled);
|
||||
|
@ -263,7 +257,7 @@ namespace CalculatorApp
|
|||
|
||||
property Platform::String^ LeftParenthesisAutomationName
|
||||
{
|
||||
Platform::String^ get()
|
||||
Platform::String^ get()
|
||||
{
|
||||
return GetLeftParenthesisAutomationName();
|
||||
}
|
||||
|
@ -276,7 +270,7 @@ namespace CalculatorApp
|
|||
|
||||
NumbersAndOperatorsEnum MapCharacterToButtonId(const wchar_t ch, bool& canSendNegate);
|
||||
|
||||
//Memory feature related methods. They are internal because they need to called from the MainPage code-behind
|
||||
// Memory feature related methods. They are internal because they need to called from the MainPage code-behind
|
||||
void OnMemoryButtonPressed();
|
||||
void OnMemoryItemPressed(Platform::Object^ memoryItemPosition);
|
||||
void OnMemoryAdd(Platform::Object^ memoryItemPosition);
|
||||
|
@ -290,6 +284,9 @@ namespace CalculatorApp
|
|||
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);
|
||||
void SetHistoryExpressionDisplay(_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const &tokens, _Inout_ std::shared_ptr<CalculatorVector <std::shared_ptr<IExpressionCommand>>> const &commands);
|
||||
void SetParenthesisCount(_In_ const std::wstring& parenthesisCount);
|
||||
void SetOpenParenthesisCountNarratorAnnouncement();
|
||||
void OnNoRightParenAdded();
|
||||
void SetNoParenAddedNarratorAnnouncement();
|
||||
void OnMaxDigitsReached();
|
||||
void OnBinaryOperatorReceived();
|
||||
void OnMemoryItemChanged(unsigned int indexOfMemory);
|
||||
|
@ -337,6 +334,8 @@ namespace CalculatorApp
|
|||
Platform::String^ m_localizedMemoryItemChangedAutomationFormat;
|
||||
Platform::String^ m_localizedMemoryItemClearedAutomationFormat;
|
||||
Platform::String^ m_localizedMemoryCleared;
|
||||
Platform::String^ m_localizedOpenParenthesisCountChangedAutomationFormat;
|
||||
Platform::String^ m_localizedNoRightParenthesisAddedFormat;
|
||||
|
||||
bool m_pinned;
|
||||
bool m_isOperandEnabled;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
|
@ -53,48 +53,40 @@ constexpr size_t SELECTED_TARGET_UNIT = 2;
|
|||
|
||||
// x millisecond delay before we consider conversion to be final
|
||||
constexpr unsigned int CONVERSION_FINALIZED_DELAY_IN_MS = 1000;
|
||||
const wregex regexTrimSpacesStart = wregex(L"^\\s+");
|
||||
const wregex regexTrimSpacesEnd = wregex(L"\\s+$");
|
||||
|
||||
namespace CalculatorApp::ViewModel
|
||||
namespace
|
||||
{
|
||||
namespace UnitConverterViewModelProperties
|
||||
{
|
||||
StringReference CurrentCategory(L"CurrentCategory");
|
||||
StringReference Unit1(L"Unit1");
|
||||
StringReference Unit2(L"Unit2");
|
||||
StringReference Value1Active(L"Value1Active");
|
||||
StringReference Value2Active(L"Value2Active");
|
||||
StringReference Value1(L"Value1");
|
||||
StringReference Value2(L"Value2");
|
||||
StringReference Value1AutomationName(L"Value1AutomationName");
|
||||
StringReference Value2AutomationName(L"Value2AutomationName");
|
||||
StringReference SupplementaryVisibility(L"SupplementaryVisibility");
|
||||
StringReference SupplementaryResults(L"SupplementaryResults");
|
||||
StringReference Unit1AutomationName(L"Unit1AutomationName");
|
||||
StringReference Unit2AutomationName(L"Unit2AutomationName");
|
||||
StringReference CurrencySymbol1(L"CurrencySymbol1");
|
||||
StringReference CurrencySymbol2(L"CurrencySymbol2");
|
||||
StringReference CurrencySymbolVisibility(L"CurrencySymbolVisibility");
|
||||
StringReference CurrencyRatioEquality(L"CurrencyRatioEquality");
|
||||
StringReference CurrencyRatioEqualityAutomationName(L"CurrencyRatioEqualityAutomationName");
|
||||
StringReference NetworkBehavior(L"NetworkBehavior");
|
||||
StringReference CurrencyDataLoadFailed(L"CurrencyDataLoadFailed");
|
||||
StringReference CurrencyDataIsWeekOld(L"CurrencyDataIsWeekOld");
|
||||
StringReference IsCurrencyLoadingVisible(L"IsCurrencyLoadingVisible");
|
||||
}
|
||||
StringReference CurrentCategoryPropertyName(L"CurrentCategory");
|
||||
StringReference Unit1AutomationNamePropertyName(L"Unit1AutomationName");
|
||||
StringReference Unit2AutomationNamePropertyName(L"Unit2AutomationName");
|
||||
StringReference Unit1PropertyName(L"Unit1");
|
||||
StringReference Unit2PropertyName(L"Unit2");
|
||||
StringReference Value1PropertyName(L"Value1");
|
||||
StringReference Value2PropertyName(L"Value2");
|
||||
StringReference Value1ActivePropertyName(L"Value1Active");
|
||||
StringReference Value2ActivePropertyName(L"Value2Active");
|
||||
StringReference Value1AutomationNamePropertyName(L"Value1AutomationName");
|
||||
StringReference Value2AutomationNamePropertyName(L"Value2AutomationName");
|
||||
StringReference CurrencySymbol1PropertyName(L"CurrencySymbol1");
|
||||
StringReference CurrencySymbol2PropertyName(L"CurrencySymbol2");
|
||||
StringReference CurrencySymbolVisibilityPropertyName(L"CurrencySymbolVisibility");
|
||||
StringReference SupplementaryVisibilityPropertyName(L"SupplementaryVisibility");
|
||||
}
|
||||
|
||||
namespace UnitConverterResourceKeys
|
||||
{
|
||||
StringReference ValueFromFormat(L"Format_ValueFrom");
|
||||
StringReference ValueFromDecimalFormat(L"Format_ValueFrom_Decimal");
|
||||
StringReference ValueToFormat(L"Format_ValueTo");
|
||||
StringReference ConversionResultFormat(L"Format_ConversionResult");
|
||||
StringReference InputUnit_Name(L"InputUnit_Name");
|
||||
StringReference OutputUnit_Name(L"OutputUnit_Name");
|
||||
StringReference MaxDigitsReachedFormat(L"Format_MaxDigitsReached");
|
||||
StringReference UpdatingCurrencyRates(L"UpdatingCurrencyRates");
|
||||
StringReference CurrencyRatesUpdated(L"CurrencyRatesUpdated");
|
||||
StringReference CurrencyRatesUpdateFailed(L"CurrencyRatesUpdateFailed");
|
||||
}
|
||||
namespace CalculatorApp::ViewModel::UnitConverterResourceKeys
|
||||
{
|
||||
StringReference ValueFromFormat(L"Format_ValueFrom");
|
||||
StringReference ValueFromDecimalFormat(L"Format_ValueFrom_Decimal");
|
||||
StringReference ValueToFormat(L"Format_ValueTo");
|
||||
StringReference ConversionResultFormat(L"Format_ConversionResult");
|
||||
StringReference InputUnit_Name(L"InputUnit_Name");
|
||||
StringReference OutputUnit_Name(L"OutputUnit_Name");
|
||||
StringReference MaxDigitsReachedFormat(L"Format_MaxDigitsReached");
|
||||
StringReference UpdatingCurrencyRates(L"UpdatingCurrencyRates");
|
||||
StringReference CurrencyRatesUpdated(L"CurrencyRatesUpdated");
|
||||
StringReference CurrencyRatesUpdateFailed(L"CurrencyRatesUpdateFailed");
|
||||
}
|
||||
|
||||
UnitConverterViewModel::UnitConverterViewModel(const shared_ptr<UCM::IUnitConverter>& model) :
|
||||
|
@ -142,7 +134,7 @@ UnitConverterViewModel::UnitConverterViewModel(const shared_ptr<UCM::IUnitConver
|
|||
m_currencyFormatter->Mode = CurrencyFormatterMode::UseCurrencyCode;
|
||||
m_currencyFormatter->ApplyRoundingForCurrency(RoundingAlgorithm::RoundHalfDown);
|
||||
m_currencyMaxFractionDigits = m_currencyFormatter->FractionDigits;
|
||||
|
||||
|
||||
auto resourceLoader = AppResourceProvider::GetInstance();
|
||||
m_localizedValueFromFormat = resourceLoader.GetResourceString(UnitConverterResourceKeys::ValueFromFormat);
|
||||
m_localizedValueToFormat = resourceLoader.GetResourceString(UnitConverterResourceKeys::ValueToFormat);
|
||||
|
@ -202,12 +194,10 @@ void UnitConverterViewModel::BuildUnitList(const vector<UCM::Unit>& modelUnitLis
|
|||
m_Units->Clear();
|
||||
for (const UCM::Unit& modelUnit : modelUnitList)
|
||||
{
|
||||
if (modelUnit.isWhimsical)
|
||||
if (!modelUnit.isWhimsical)
|
||||
{
|
||||
continue;
|
||||
m_Units->Append(ref new Unit(modelUnit));
|
||||
}
|
||||
|
||||
m_Units->Append(ref new Unit(modelUnit));
|
||||
}
|
||||
|
||||
if (m_Units->Size == 0)
|
||||
|
@ -257,7 +247,7 @@ void UnitConverterViewModel::OnUnitChanged(Object^ parameter)
|
|||
|
||||
void UnitConverterViewModel::OnSwitchActive(Platform::Object^ unused)
|
||||
{
|
||||
// this can be false if this switch occurs without the user having explicitly updated any strings
|
||||
// this can be false if this switch occurs without the user having explicitly updated any strings
|
||||
// (for example, during deserialization). We only want to try this cleanup if there's actually
|
||||
// something to clean up.
|
||||
if (m_relocalizeStringOnSwitch)
|
||||
|
@ -279,10 +269,10 @@ void UnitConverterViewModel::OnSwitchActive(Platform::Object^ unused)
|
|||
|
||||
m_valueFromUnlocalized.swap(m_valueToUnlocalized);
|
||||
Utils::Swap(&m_localizedValueFromFormat, &m_localizedValueToFormat);
|
||||
|
||||
|
||||
Utils::Swap(&m_Unit1AutomationName, &m_Unit2AutomationName);
|
||||
RaisePropertyChanged(UnitConverterViewModelProperties::Unit1AutomationName);
|
||||
RaisePropertyChanged(UnitConverterViewModelProperties::Unit2AutomationName);
|
||||
RaisePropertyChanged(Unit1AutomationNamePropertyName);
|
||||
RaisePropertyChanged(Unit2AutomationNamePropertyName);
|
||||
|
||||
m_isInputBlocked = false;
|
||||
m_model->SwitchActive(m_valueFromUnlocalized);
|
||||
|
@ -324,7 +314,7 @@ String^ UnitConverterViewModel::ConvertToLocalizedString(const std::wstring& str
|
|||
if (allowPartialStrings)
|
||||
{
|
||||
// allow "in progress" strings, like "3." that occur during the composition of
|
||||
// a final number. Without this, when typing the three characters in "3.2"
|
||||
// a final number. Without this, when typing the three characters in "3.2"
|
||||
// you don't see the decimal point when typing it, you only see it once you've finally
|
||||
// typed a post-decimal digit.
|
||||
|
||||
|
@ -341,17 +331,22 @@ String^ UnitConverterViewModel::ConvertToLocalizedString(const std::wstring& str
|
|||
{
|
||||
wstring currencyResult = m_currencyFormatter->Format(stod(stringToLocalize))->Data();
|
||||
wstring currencyCode = m_currencyFormatter->Currency->Data();
|
||||
|
||||
|
||||
// CurrencyFormatter always includes LangCode or Symbol. Make it include LangCode
|
||||
// because this includes a non-breaking space. Remove the LangCode.
|
||||
auto pos = currencyResult.find(currencyCode);
|
||||
if (pos != wstring::npos)
|
||||
{
|
||||
currencyResult.erase(pos, currencyCode.length());
|
||||
pos = currencyResult.find(L'\u00a0'); // non-breaking space
|
||||
if (pos != wstring::npos)
|
||||
std::wsmatch sm;
|
||||
if (regex_search(currencyResult, sm, regexTrimSpacesStart))
|
||||
{
|
||||
currencyResult.erase(pos, 1);
|
||||
currencyResult.erase(sm.prefix().length(), sm.length());
|
||||
}
|
||||
|
||||
if (regex_search(currencyResult, sm, regexTrimSpacesEnd))
|
||||
{
|
||||
currencyResult.erase(sm.prefix().length(), sm.length());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -367,7 +362,7 @@ String^ UnitConverterViewModel::ConvertToLocalizedString(const std::wstring& str
|
|||
if (hasDecimal)
|
||||
{
|
||||
// Since the output from GetLocaleInfoEx() and DecimalFormatter are differing for decimal string
|
||||
// we are adding the below work-around of editing the string returned by DecimalFormatter
|
||||
// we are adding the below work-around of editing the string returned by DecimalFormatter
|
||||
// and replacing the decimal separator with the one returned by GetLocaleInfoEx()
|
||||
String^ formattedSampleString = m_decimalFormatter->Format(stod("1.1"));
|
||||
wstring formattedSampleWString = wstring(formattedSampleString->Data());
|
||||
|
@ -378,7 +373,7 @@ String^ UnitConverterViewModel::ConvertToLocalizedString(const std::wstring& str
|
|||
{
|
||||
resultWithDecimal.replace(pos, 1, &m_decimalSeparator);
|
||||
}
|
||||
|
||||
|
||||
// Copy back the edited string to the result
|
||||
result = ref new String(resultWithDecimal.c_str());
|
||||
}
|
||||
|
@ -479,7 +474,7 @@ void UnitConverterViewModel::OnButtonPressed(Platform::Object^ parameter)
|
|||
NumbersAndOperatorsEnum numOpEnum = CalculatorButtonPressedEventArgs::GetOperationFromCommandParameter(parameter);
|
||||
UCM::Command command = CommandFromButtonId(numOpEnum);
|
||||
|
||||
//Don't clear the display if combo box is open and escape is pressed
|
||||
// Don't clear the display if combo box is open and escape is pressed
|
||||
if (command == UCM::Command::Clear && IsDropDownOpen)
|
||||
{
|
||||
return;
|
||||
|
@ -556,13 +551,13 @@ void UnitConverterViewModel::OnPropertyChanged(Platform::String^ prop)
|
|||
{
|
||||
static bool isCategoryChanging = false;
|
||||
|
||||
if (prop->Equals(UnitConverterViewModelProperties::CurrentCategory))
|
||||
if (prop == CurrentCategoryPropertyName)
|
||||
{
|
||||
isCategoryChanging = true;
|
||||
CategoryChanged->Execute(nullptr);
|
||||
isCategoryChanging = false;
|
||||
}
|
||||
else if (prop->Equals(UnitConverterViewModelProperties::Unit1) || prop->Equals(UnitConverterViewModelProperties::Unit2))
|
||||
else if (prop == Unit1PropertyName || prop == Unit2PropertyName)
|
||||
{
|
||||
// Category changes will handle updating units after they've both been updated.
|
||||
// This event should only be used to update units from explicit user interaction.
|
||||
|
@ -571,7 +566,7 @@ void UnitConverterViewModel::OnPropertyChanged(Platform::String^ prop)
|
|||
UnitChanged->Execute(nullptr);
|
||||
}
|
||||
// Get the localized automation name for each CalculationResults field
|
||||
if (prop->Equals(UnitConverterViewModelProperties::Unit1))
|
||||
if (prop == Unit1PropertyName)
|
||||
{
|
||||
UpdateValue1AutomationName();
|
||||
}
|
||||
|
@ -580,15 +575,15 @@ void UnitConverterViewModel::OnPropertyChanged(Platform::String^ prop)
|
|||
UpdateValue2AutomationName();
|
||||
}
|
||||
}
|
||||
else if (prop->Equals(UnitConverterViewModelProperties::Value1))
|
||||
else if (prop == Value1PropertyName)
|
||||
{
|
||||
UpdateValue1AutomationName();
|
||||
}
|
||||
else if (prop->Equals(UnitConverterViewModelProperties::Value2))
|
||||
else if (prop == Value2PropertyName)
|
||||
{
|
||||
UpdateValue2AutomationName();
|
||||
}
|
||||
else if (prop->Equals(UnitConverterViewModelProperties::Value1Active) || prop->Equals(UnitConverterViewModelProperties::Value2Active))
|
||||
else if (prop == Value1ActivePropertyName || prop == Value2ActivePropertyName)
|
||||
{
|
||||
// if one of the values is activated, and as a result both are true, it means
|
||||
// that we're trying to switch.
|
||||
|
@ -600,11 +595,11 @@ void UnitConverterViewModel::OnPropertyChanged(Platform::String^ prop)
|
|||
UpdateValue1AutomationName();
|
||||
UpdateValue2AutomationName();
|
||||
}
|
||||
else if (prop->Equals(UnitConverterViewModelProperties::SupplementaryResults))
|
||||
else if (prop == SupplementaryResultsPropertyName)
|
||||
{
|
||||
RaisePropertyChanged(UnitConverterViewModelProperties::SupplementaryVisibility);
|
||||
RaisePropertyChanged(SupplementaryVisibilityPropertyName);
|
||||
}
|
||||
else if (prop->Equals(UnitConverterViewModelProperties::Value1AutomationName))
|
||||
else if (prop == Value1AutomationNamePropertyName)
|
||||
{
|
||||
m_isValue1Updating = false;
|
||||
if (!m_isValue2Updating)
|
||||
|
@ -612,7 +607,7 @@ void UnitConverterViewModel::OnPropertyChanged(Platform::String^ prop)
|
|||
AnnounceConversionResult();
|
||||
}
|
||||
}
|
||||
else if (prop->Equals(UnitConverterViewModelProperties::Value2AutomationName))
|
||||
else if (prop == Value2AutomationNamePropertyName)
|
||||
{
|
||||
m_isValue2Updating = false;
|
||||
if (!m_isValue1Updating)
|
||||
|
@ -620,9 +615,9 @@ void UnitConverterViewModel::OnPropertyChanged(Platform::String^ prop)
|
|||
AnnounceConversionResult();
|
||||
}
|
||||
}
|
||||
else if (prop->Equals(UnitConverterViewModelProperties::CurrencySymbol1) || prop->Equals(UnitConverterViewModelProperties::CurrencySymbol2))
|
||||
else if (prop == CurrencySymbol1PropertyName || prop == CurrencySymbol2PropertyName)
|
||||
{
|
||||
RaisePropertyChanged(UnitConverterViewModelProperties::CurrencySymbolVisibility);
|
||||
RaisePropertyChanged(CurrencySymbolVisibilityPropertyName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -643,10 +638,8 @@ String^ UnitConverterViewModel::Serialize()
|
|||
String^ serializedData = ref new String(wstring(out.str()).c_str());
|
||||
return serializedData;
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void UnitConverterViewModel::Deserialize(Platform::String^ state)
|
||||
|
@ -674,7 +667,7 @@ void UnitConverterViewModel::Deserialize(Platform::String^ state)
|
|||
RaisePropertyChanged(nullptr); // Update since all props have been updated.
|
||||
}
|
||||
|
||||
//Saving User Preferences of Category and Associated-Units across Sessions.
|
||||
// Saving User Preferences of Category and Associated-Units across Sessions.
|
||||
void UnitConverterViewModel::SaveUserPreferences()
|
||||
{
|
||||
if (UnitsAreValid())
|
||||
|
@ -695,7 +688,7 @@ void UnitConverterViewModel::SaveUserPreferences()
|
|||
}
|
||||
}
|
||||
|
||||
//Restoring User Preferences of Category and Associated-Units.
|
||||
// Restoring User Preferences of Category and Associated-Units.
|
||||
void UnitConverterViewModel::RestoreUserPreferences()
|
||||
{
|
||||
if (!IsCurrencyCurrentCategory)
|
||||
|
@ -849,7 +842,7 @@ void UnitConverterViewModel::RefreshSupplementaryResults()
|
|||
}
|
||||
|
||||
m_cacheMutex.unlock();
|
||||
RaisePropertyChanged(UnitConverterViewModelProperties::SupplementaryResults);
|
||||
RaisePropertyChanged(SupplementaryResultsPropertyName);
|
||||
//EventWriteConverterSupplementaryResultsUpdated();
|
||||
}
|
||||
|
||||
|
@ -879,14 +872,11 @@ void UnitConverterViewModel::UpdateInputBlocked(_In_ const wstring& currencyInpu
|
|||
{
|
||||
// currencyInput is in en-US and has the default decimal separator, so this is safe to do.
|
||||
auto posOfDecimal = currencyInput.find(L'.');
|
||||
m_isInputBlocked = false;
|
||||
if (posOfDecimal != wstring::npos && IsCurrencyCurrentCategory)
|
||||
{
|
||||
m_isInputBlocked = (posOfDecimal + static_cast<size_t>(m_currencyMaxFractionDigits) + 1 == currencyInput.length());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_isInputBlocked = false;
|
||||
}
|
||||
}
|
||||
|
||||
NumbersAndOperatorsEnum UnitConverterViewModel::MapCharacterToButtonId(
|
||||
|
@ -973,7 +963,7 @@ void UnitConverterViewModel::OnPaste(String^ stringToPaste, ViewMode mode)
|
|||
{
|
||||
if (isFirstLegalChar)
|
||||
{
|
||||
// Send Clear before sending something that will actually apply
|
||||
// Send Clear before sending something that will actually apply
|
||||
// to the field.
|
||||
m_model->SendCommand(UCM::Command::Clear);
|
||||
isFirstLegalChar = false;
|
||||
|
@ -988,7 +978,7 @@ void UnitConverterViewModel::OnPaste(String^ stringToPaste, ViewMode mode)
|
|||
}
|
||||
|
||||
// Negate is only allowed if it's the first legal character, which is handled above.
|
||||
if (NumbersAndOperatorsEnum::None != op && NumbersAndOperatorsEnum::Negate != op)
|
||||
if (NumbersAndOperatorsEnum::Negate != op)
|
||||
{
|
||||
UCM::Command cmd = CommandFromButtonId(op);
|
||||
m_model->SendCommand(cmd);
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace CalculatorApp
|
|||
public ref class Category sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
|
||||
{
|
||||
internal:
|
||||
Category(const UnitConversionManager::Category& category) :
|
||||
Category(const UnitConversionManager::Category& category) :
|
||||
m_original(category)
|
||||
{ }
|
||||
|
||||
|
@ -52,7 +52,7 @@ namespace CalculatorApp
|
|||
public ref class Unit sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
|
||||
{
|
||||
internal:
|
||||
Unit(const UnitConversionManager::Unit& unit) :
|
||||
Unit(const UnitConversionManager::Unit& unit) :
|
||||
m_original(unit)
|
||||
{ }
|
||||
|
||||
|
@ -138,32 +138,13 @@ namespace CalculatorApp
|
|||
return ref new Activatable<TActivatable>(activatable);
|
||||
}
|
||||
|
||||
namespace UnitConverterViewModelProperties
|
||||
{
|
||||
extern Platform::StringReference CurrentCategory;
|
||||
extern Platform::StringReference Unit1;
|
||||
extern Platform::StringReference Unit2;
|
||||
extern Platform::StringReference Value1Active;
|
||||
extern Platform::StringReference Value2Active;
|
||||
extern Platform::StringReference SupplementaryVisibility;
|
||||
extern Platform::StringReference SupplementaryResults;
|
||||
extern Platform::StringReference CurrencySymbol1;
|
||||
extern Platform::StringReference CurrencySymbol2;
|
||||
extern Platform::StringReference CurrencySymbolVisibility;
|
||||
extern Platform::StringReference CurrencyRatioEquality;
|
||||
extern Platform::StringReference NetworkBehavior;
|
||||
extern Platform::StringReference CurrencyDataLoadFailed;
|
||||
extern Platform::StringReference CurrencyDataIsWeekOld;
|
||||
extern Platform::StringReference IsCurrencyLoadingVisible;
|
||||
}
|
||||
|
||||
[Windows::UI::Xaml::Data::Bindable]
|
||||
public ref class UnitConverterViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
|
||||
{
|
||||
internal:
|
||||
UnitConverterViewModel(const std::shared_ptr<UnitConversionManager::IUnitConverter>& model);
|
||||
|
||||
public:
|
||||
public:
|
||||
OBSERVABLE_OBJECT_CALLBACK(OnPropertyChanged);
|
||||
|
||||
OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector<Category^>^, Categories);
|
||||
|
@ -176,7 +157,7 @@ namespace CalculatorApp
|
|||
OBSERVABLE_PROPERTY_RW(Platform::String^, CurrencySymbol2);
|
||||
OBSERVABLE_PROPERTY_RW(Unit^, Unit2);
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String^, Value2);
|
||||
OBSERVABLE_PROPERTY_R(Windows::Foundation::Collections::IObservableVector<SupplementaryResult^>^, SupplementaryResults);
|
||||
OBSERVABLE_NAMED_PROPERTY_R(Windows::Foundation::Collections::IObservableVector<SupplementaryResult^>^, SupplementaryResults);
|
||||
OBSERVABLE_PROPERTY_RW(bool, Value1Active);
|
||||
OBSERVABLE_PROPERTY_RW(bool, Value2Active);
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String^, Value1AutomationName);
|
||||
|
@ -187,14 +168,14 @@ namespace CalculatorApp
|
|||
OBSERVABLE_PROPERTY_RW(bool, IsDecimalEnabled);
|
||||
OBSERVABLE_PROPERTY_RW(bool, IsDropDownOpen);
|
||||
OBSERVABLE_PROPERTY_RW(bool, IsDropDownEnabled);
|
||||
OBSERVABLE_PROPERTY_RW(bool, IsCurrencyLoadingVisible);
|
||||
OBSERVABLE_NAMED_PROPERTY_RW(bool, IsCurrencyLoadingVisible);
|
||||
OBSERVABLE_PROPERTY_RW(bool, IsCurrencyCurrentCategory);
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String^, CurrencyRatioEquality);
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String^, CurrencyRatioEqualityAutomationName);
|
||||
OBSERVABLE_PROPERTY_RW(Platform::String^, CurrencyTimestamp);
|
||||
OBSERVABLE_PROPERTY_RW(CalculatorApp::NetworkAccessBehavior, NetworkBehavior);
|
||||
OBSERVABLE_PROPERTY_RW(bool, CurrencyDataLoadFailed);
|
||||
OBSERVABLE_PROPERTY_RW(bool, CurrencyDataIsWeekOld);
|
||||
OBSERVABLE_NAMED_PROPERTY_RW(CalculatorApp::NetworkAccessBehavior, NetworkBehavior);
|
||||
OBSERVABLE_NAMED_PROPERTY_RW(bool, CurrencyDataLoadFailed);
|
||||
OBSERVABLE_NAMED_PROPERTY_RW(bool, CurrencyDataIsWeekOld);
|
||||
|
||||
property Windows::UI::Xaml::Visibility SupplementaryVisibility
|
||||
{
|
||||
|
@ -224,7 +205,7 @@ namespace CalculatorApp
|
|||
COMMAND_FOR_METHOD(PasteCommand, UnitConverterViewModel::OnPasteCommand);
|
||||
|
||||
void AnnounceConversionResult();
|
||||
|
||||
|
||||
internal:
|
||||
void ResetView();
|
||||
void PopulateData();
|
||||
|
@ -242,8 +223,8 @@ namespace CalculatorApp
|
|||
void UpdateValue2AutomationName();
|
||||
Platform::String^ Serialize();
|
||||
void Deserialize(Platform::String^ state);
|
||||
|
||||
//Saving And Restoring User Preferences of Category and Associated-Units across Sessions.
|
||||
|
||||
// Saving And Restoring User Preferences of Category and Associated-Units across Sessions.
|
||||
void SaveUserPreferences();
|
||||
void RestoreUserPreferences();
|
||||
|
||||
|
@ -360,9 +341,9 @@ namespace CalculatorApp
|
|||
UnitConverterVMCallback(UnitConverterViewModel^ viewModel) : m_viewModel(viewModel)
|
||||
{}
|
||||
|
||||
void DisplayCallback(const std::wstring& from, const std::wstring& to) override
|
||||
{
|
||||
m_viewModel->UpdateDisplay(from, to);
|
||||
void DisplayCallback(const std::wstring& from, const std::wstring& to) override
|
||||
{
|
||||
m_viewModel->UpdateDisplay(from, to);
|
||||
}
|
||||
|
||||
void SuggestedValueCallback(
|
||||
|
|
|
@ -10,6 +10,10 @@
|
|||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
|
||||
// Windows headers define min/max macros.
|
||||
// Disable it for project code.
|
||||
#define NOMINMAX
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <collection.h>
|
||||
|
@ -26,7 +30,7 @@
|
|||
#include <sstream>
|
||||
#include <concrt.h>
|
||||
#include <regex>
|
||||
|
||||
#include <iterator>
|
||||
// C++\WinRT Headers
|
||||
#include "winrt/base.h"
|
||||
#include "winrt/Windows.Foundation.Diagnostics.h"
|
||||
|
|