merge with master and use m_resolvedName for all GetLocalInfoEx calls in LocalizationSettings.h
99
.clang-format
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
AccessModifierOffset: -4
|
||||||
|
AlignAfterOpenBracket: AlwaysBreak
|
||||||
|
AlignConsecutiveAssignments: false
|
||||||
|
AlignConsecutiveDeclarations: false
|
||||||
|
AlignEscapedNewlines: Right
|
||||||
|
AlignOperands: true
|
||||||
|
AlignTrailingComments: true
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: false
|
||||||
|
AllowShortBlocksOnASingleLine: false
|
||||||
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
AllowShortFunctionsOnASingleLine: None
|
||||||
|
AllowShortIfStatementsOnASingleLine: false
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
AlwaysBreakAfterDefinitionReturnType: None
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
|
AlwaysBreakTemplateDeclarations: true
|
||||||
|
BinPackArguments: false
|
||||||
|
BinPackParameters: false
|
||||||
|
BreakBeforeBinaryOperators: NonAssignment
|
||||||
|
BreakBeforeBraces: Allman
|
||||||
|
BreakBeforeInheritanceComma: false
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializersBeforeComma: false
|
||||||
|
BreakConstructorInitializers: BeforeComma
|
||||||
|
BreakAfterJavaFieldAnnotations: true
|
||||||
|
BreakStringLiterals: true
|
||||||
|
ColumnLimit: 160
|
||||||
|
CommentPragmas: '^ IWYU pragma:'
|
||||||
|
CompactNamespaces: true
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||||
|
ConstructorInitializerIndentWidth: 4
|
||||||
|
ContinuationIndentWidth: 4
|
||||||
|
Cpp11BracedListStyle: false
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
DisableFormat: false
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
FixNamespaceComments: false
|
||||||
|
IncludeBlocks: Preserve
|
||||||
|
IncludeCategories:
|
||||||
|
- Regex: '^<ext/.*\.h>'
|
||||||
|
Priority: 2
|
||||||
|
- Regex: '^<.*\.h>'
|
||||||
|
Priority: 1
|
||||||
|
- Regex: '^<.*'
|
||||||
|
Priority: 2
|
||||||
|
- Regex: '.*'
|
||||||
|
Priority: 3
|
||||||
|
IncludeIsMainRegex: '([-_](test|unittest))?$'
|
||||||
|
IndentCaseLabels: false
|
||||||
|
IndentPPDirectives: None
|
||||||
|
IndentWidth: 4
|
||||||
|
IndentWrappedFunctionNames: false
|
||||||
|
JavaScriptQuotes: Single
|
||||||
|
JavaScriptWrapImports: true
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
|
MacroBlockBegin: ''
|
||||||
|
MacroBlockEnd: ''
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
NamespaceIndentation: All
|
||||||
|
ObjCBlockIndentWidth: 4
|
||||||
|
ObjCSpaceAfterProperty: false
|
||||||
|
ObjCSpaceBeforeProtocolList: true
|
||||||
|
PenaltyBreakAssignment: 2
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 19
|
||||||
|
PenaltyBreakComment: 300
|
||||||
|
PenaltyBreakFirstLessLess: 120
|
||||||
|
PenaltyBreakString: 1000
|
||||||
|
PenaltyExcessCharacter: 1000000
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 60
|
||||||
|
PointerAlignment: Left
|
||||||
|
ReflowComments: true
|
||||||
|
SortIncludes: false
|
||||||
|
SortUsingDeclarations: true
|
||||||
|
SpaceAfterCStyleCast: false
|
||||||
|
SpaceAfterTemplateKeyword: true
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceBeforeParens: ControlStatements
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesBeforeTrailingComments: 1
|
||||||
|
SpacesInAngles: false
|
||||||
|
SpacesInContainerLiterals: false
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpacesInParentheses: false
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
Standard: Cpp11
|
||||||
|
TabWidth: 4
|
||||||
|
UseTab: Never
|
||||||
|
#...
|
||||||
|
# unsupported rules
|
||||||
|
#BreakInheritanceList: AfterColon
|
||||||
|
#Language: None
|
||||||
|
#ObjCBinPackProtocolList: Auto
|
||||||
|
#PenaltyBreakTemplateDeclaration: 10
|
||||||
|
#SpaceBeforeCpp11BracedList: false
|
||||||
|
#SpaceBeforeCtorInitializerColon: true
|
||||||
|
#SpaceBeforeInheritanceColon: true
|
||||||
|
#SpaceBeforeRangeBasedForLoopColon: true
|
||||||
|
|
23
.gitattributes
vendored
|
@ -12,29 +12,6 @@
|
||||||
###############################################################################
|
###############################################################################
|
||||||
*.cs diff=csharp
|
*.cs diff=csharp
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Set the merge driver for project and solution files
|
|
||||||
#
|
|
||||||
# Merging from the command prompt will add diff markers to the files if there
|
|
||||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
|
||||||
# the diff markers are never inserted). Diff markers may cause the following
|
|
||||||
# file extensions to fail to load in VS. An alternative would be to treat
|
|
||||||
# these files as binary and thus will always conflict and require user
|
|
||||||
# intervention with every merge. To do so, just uncomment the entries below
|
|
||||||
###############################################################################
|
|
||||||
*.sln merge=binary
|
|
||||||
*.csproj merge=binary
|
|
||||||
*.vbproj merge=binary
|
|
||||||
*.vcxproj merge=binary
|
|
||||||
*.vcproj merge=binary
|
|
||||||
*.dbproj merge=binary
|
|
||||||
*.fsproj merge=binary
|
|
||||||
*.lsproj merge=binary
|
|
||||||
*.wixproj merge=binary
|
|
||||||
*.modelproj merge=binary
|
|
||||||
*.sqlproj merge=binary
|
|
||||||
*.wwaproj merge=binary
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# behavior for image files
|
# behavior for image files
|
||||||
#
|
#
|
||||||
|
|
21
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
@ -6,19 +6,23 @@ labels: ''
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
<!--Before filing a bug
|
<!--
|
||||||
|
Before filing a bug
|
||||||
- Ensure the bug reproduces on the latest version of the app.
|
- Ensure the bug reproduces on the latest version of the app.
|
||||||
- Search existing issues and make sure this issue is not already filed.-->
|
- Search existing issues and make sure this issue is not already filed.
|
||||||
|
-->
|
||||||
|
|
||||||
**Describe the bug**
|
**Describe the bug**
|
||||||
<!-- A clear and concise description of what the bug is. -->
|
<!-- A clear and concise description of what the bug is. -->
|
||||||
|
|
||||||
**Steps To Reproduce**
|
**Steps To Reproduce**
|
||||||
<!--Steps to reproduce the behavior:
|
<!--
|
||||||
|
Steps to reproduce the behavior:
|
||||||
1. Go to '...'
|
1. Go to '...'
|
||||||
2. Click on '....'
|
2. Click on '....'
|
||||||
3. Scroll down to '....'
|
3. Scroll down to '....'
|
||||||
4. See error-->
|
4. See error
|
||||||
|
-->
|
||||||
|
|
||||||
**Expected behavior**
|
**Expected behavior**
|
||||||
<!-- A clear and concise description of what you expected to happen. -->
|
<!-- A clear and concise description of what you expected to happen. -->
|
||||||
|
@ -26,15 +30,20 @@ assignees: ''
|
||||||
**Screenshots**
|
**Screenshots**
|
||||||
<!-- If applicable, add screenshots to help explain your problem. -->
|
<!-- If applicable, add screenshots to help explain your problem. -->
|
||||||
|
|
||||||
**Device and Application Information (please complete the following information):**
|
**Device and Application Information**
|
||||||
- OS Build:
|
- OS Build:
|
||||||
- Architecture:
|
- Architecture:
|
||||||
- Application Version:
|
- Application Version:
|
||||||
|
- Region:
|
||||||
|
- Dev Version Installed:
|
||||||
|
|
||||||
<!--Run the following commands in Powershell and copy/paste the output.
|
<!--
|
||||||
|
Run the following commands in Powershell and copy/paste the output.
|
||||||
" - OS Build: $([Environment]::OSVersion.Version)"
|
" - OS Build: $([Environment]::OSVersion.Version)"
|
||||||
" - Architecture: $((Get-AppxPackage -Name Microsoft.WindowsCalculator).Architecture)"
|
" - Architecture: $((Get-AppxPackage -Name Microsoft.WindowsCalculator).Architecture)"
|
||||||
" - Application Version: $((Get-AppxPackage -Name Microsoft.WindowsCalculator).Version)"
|
" - Application Version: $((Get-AppxPackage -Name Microsoft.WindowsCalculator).Version)"
|
||||||
|
" - Region: $((Get-Culture).Name)"
|
||||||
|
" - Dev Version Installed: $($null -ne (Get-AppxPackage -Name Microsoft.WindowsCalculator.Dev))"
|
||||||
-->
|
-->
|
||||||
|
|
||||||
**Additional context**
|
**Additional context**
|
||||||
|
|
42
.github/ISSUE_TEMPLATE/feature_request.md
vendored
|
@ -2,42 +2,42 @@
|
||||||
name: Feature request
|
name: Feature request
|
||||||
about: Propose a new feature in the app
|
about: Propose a new feature in the app
|
||||||
title: ''
|
title: ''
|
||||||
labels: ''
|
labels: 'Enhancement'
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
|
See https://github.com/Microsoft/calculator/blob/master/docs/NewFeatureProcess.md for suggestions on how to write a good feature pitch. Just want to submit an idea quickly? Try Feedback Hub instead: https://insider.windows.com/en-us/fb/?contextid=130
|
||||||
See https://github.com/Microsoft/calculator/blob/master/docs/NewFeatureProcess.md for
|
|
||||||
suggestions on how to write a good feature pitch. Just want to submit an idea quickly? Try Feedback
|
|
||||||
Hub instead: https://insider.windows.com/en-us/fb/?contextid=130
|
|
||||||
|
|
||||||
-->
|
-->
|
||||||
|
|
||||||
**Problem Statement**
|
**Problem Statement**
|
||||||
<!-- What problem are we trying to solve? Who’s the target audience? Is there a customer need or
|
<!--
|
||||||
pain point we need to remedy? Is there a business goal or metric we are trying to improve? Do we
|
What problem are we trying to solve? Who’s the target audience? Is there a customer need or pain point we need to remedy? Is there a business goal or metric we are trying to improve? Do we have a hypothesis we want to prove or disprove?
|
||||||
have a hypothesis we want to prove or disprove? -->
|
-->
|
||||||
|
|
||||||
**Evidence or User Insights**
|
**Evidence or User Insights**
|
||||||
<!-- Why should we do this? Potential sources of data: Feedback Hub, other GitHub issues, other
|
<!--
|
||||||
anecdotes from listening to customers in person or online, request from another team, telemetry
|
Why should we do this? Potential sources of data: Feedback Hub, other GitHub issues, other anecdotes from listening to customers in person or online, request from another team, telemetry data, user research, market or competitive research
|
||||||
data, user research, market or competitive research -->
|
-->
|
||||||
|
|
||||||
**Proposal**
|
**Proposal**
|
||||||
<!-- How will the solution/feature help us solve the problem? How will it meet the target
|
<!--
|
||||||
audience’s needs? If there are business goals or metrics, how does this improve them? -->
|
How will the solution/feature help us solve the problem? How will it meet the target audience’s needs? If there are business goals or metrics, how does this improve them?
|
||||||
|
-->
|
||||||
|
|
||||||
**Goals**
|
**Goals**
|
||||||
<!-- What you want to accomplish with this feature. Typical examples include
|
<!--
|
||||||
“User Can *perform some task*” -->
|
What you want to accomplish with this feature. Typical examples include
|
||||||
|
"User Can *perform some task*"
|
||||||
|
-->
|
||||||
|
|
||||||
**Non-Goals**
|
**Non-Goals**
|
||||||
<!-- Things we are explicitly not doing or supporting or that are out of scope, including reasons
|
<!--
|
||||||
why. -->
|
Things we are explicitly not doing or supporting or that are out of scope, including reasons why.
|
||||||
|
-->
|
||||||
|
|
||||||
**Low-Fidelity Concept**
|
**Low-Fidelity Concept**
|
||||||
<!-- Show as much of the experience as needed to explain the idea. This can be as simple as a
|
<!--
|
||||||
napkin drawing but can also be a code prototype, a PowerPoint walkthrough, or a design
|
Show as much of the experience as needed to explain the idea. This can be as simple as a napkin drawing but can also be a code prototype, or a design comp. Keep it simple at this stage, as it can be refined later during the pre-production stage.
|
||||||
comp. -->
|
-->
|
||||||
|
|
54
.github/ISSUE_TEMPLATE/localization_suggestion.md
vendored
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
---
|
||||||
|
name: Localization Suggestion
|
||||||
|
about: Report a problem or suggested change to Calculator's localized content.
|
||||||
|
title: '[Localization] '
|
||||||
|
labels: 'Area: World-Readiness'
|
||||||
|
assignees: ''
|
||||||
|
---
|
||||||
|
<!--
|
||||||
|
PLEASE NOTE:
|
||||||
|
We cannot _merge_ any suggested localization changes to our localized resources files. These files are automatically generated from an internal localization process. Any suggestion submitted this way will be duplicated into our internal localization system, and then closed here.
|
||||||
|
|
||||||
|
Alternatively, you can launch feedback-hub://, click on the "Language Community" tab on the left-side of the app, and follow the steps to submit a localization suggestion that way. (The "Language Community" tab currently will only be visible if your system is running a non-English language).
|
||||||
|
|
||||||
|
Before filing a bug
|
||||||
|
- Ensure the bug reproduces on the latest version of the app.
|
||||||
|
- Search existing issues and make sure this issue is not already filed.
|
||||||
|
-->
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
<!-- A clear and concise description of what the bug is. -->
|
||||||
|
|
||||||
|
**Steps To Reproduce**
|
||||||
|
<!--
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '....'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See error
|
||||||
|
-->
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
<!-- A clear and concise description of what you expected to happen. -->
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
<!-- If applicable, add screenshots to help explain your problem. -->
|
||||||
|
|
||||||
|
**Device and Application Information**
|
||||||
|
- OS Build:
|
||||||
|
- Architecture:
|
||||||
|
- Application Version:
|
||||||
|
- Region:
|
||||||
|
- Dev Version Installed:
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Run the following commands in Powershell and copy/paste the output.
|
||||||
|
" - OS Build: $([Environment]::OSVersion.Version)"
|
||||||
|
" - Architecture: $((Get-AppxPackage -Name Microsoft.WindowsCalculator).Architecture)"
|
||||||
|
" - Application Version: $((Get-AppxPackage -Name Microsoft.WindowsCalculator).Version)"
|
||||||
|
" - Region: $((Get-Culture).Name)"
|
||||||
|
" - Dev Version Installed: $($null -ne (Get-AppxPackage -Name Microsoft.WindowsCalculator.Dev))"
|
||||||
|
-->
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
<!-- Add any other context about the problem here. -->
|
2
.gitignore
vendored
|
@ -289,5 +289,7 @@ __pycache__/
|
||||||
|
|
||||||
# Calculator specific
|
# Calculator specific
|
||||||
Generated Files/
|
Generated Files/
|
||||||
|
src/GraphControl/GraphingImplOverrides.props
|
||||||
!/build/config/TRexDefs/**
|
!/build/config/TRexDefs/**
|
||||||
|
!src/Calculator/TemporaryKey.pfx
|
||||||
!src/CalculatorUnitTests/CalculatorUnitTests_TemporaryKey.pfx
|
!src/CalculatorUnitTests/CalculatorUnitTests_TemporaryKey.pfx
|
|
@ -3,7 +3,8 @@ The Calculator team encourages community feedback and contributions. Thank you f
|
||||||
making Calculator better! There are several ways you can get involved.
|
making Calculator better! There are several ways you can get involved.
|
||||||
|
|
||||||
## Reporting issues and suggesting new features
|
## Reporting issues and suggesting new features
|
||||||
If Calculator is not working properly, please file a report in the [Feedback Hub](https://insider.windows.com/en-us/fb/?contextid=130&newFeedback=True).
|
If Calculator is not working properly, please file a report in the
|
||||||
|
[Feedback Hub](https://insider.windows.com/en-us/fb/?contextid=130&newFeedback=True).
|
||||||
Feedback Hub reports automatically include diagnostic data, such as the version of Calculator
|
Feedback Hub reports automatically include diagnostic data, such as the version of Calculator
|
||||||
you're using.
|
you're using.
|
||||||
|
|
||||||
|
@ -17,21 +18,38 @@ all community interactions must abide by the [Code of Conduct](CODE_OF_CONDUCT.m
|
||||||
|
|
||||||
## Finding issues you can help with
|
## Finding issues you can help with
|
||||||
Looking for something to work on?
|
Looking for something to work on?
|
||||||
[Issues marked *good first issue*](https://github.com/Microsoft/calculator/labels/good%20first%20issue)
|
Issues marked [``good first issue``](https://github.com/Microsoft/calculator/labels/good%20first%20issue)
|
||||||
are a good place to start.
|
are a good place to start.
|
||||||
|
|
||||||
You can also check [the *help wanted* tag](https://github.com/Microsoft/calculator/labels/help%20wanted)
|
You can also check the [``help wanted``](https://github.com/Microsoft/calculator/labels/help%20wanted) tag to find
|
||||||
to find other issues to help with.
|
other issues to help with. If you're interested in working on a fix, leave a comment to let everyone know and to help
|
||||||
|
avoid duplicated effort from others.
|
||||||
|
|
||||||
## Contributions we accept
|
## Contributions we accept
|
||||||
We welcome your contributions to the Calculator project, especially to fix bugs and to make
|
We welcome your contributions to the Calculator project, especially to fix bugs and to make
|
||||||
improvements which address the top issues reported by Calculator users.
|
improvements which address the top issues reported by Calculator users. Some general guidelines:
|
||||||
|
|
||||||
We have a high bar for new features and changes to the user experience. We prefer to evaluate
|
* **DO** create one pull request per Issue, and ensure that the Issue is linked in the pull request.
|
||||||
*prototypes* to ensure that the design meets users' needs before we start discussing implementation
|
* **DO** follow our [Coding and Style](#style-guidelines) guidelines, and keep code changes as small as possible.
|
||||||
details and reviewing code. We follow a [user-centered process for developing features](docs/NewFeatureProcess.md).
|
* **DO** include corresponding tests whenever possible.
|
||||||
New features need sponsorship from the Calculator team, but we welcome community contributions at
|
* **DO** check for additional occurrences of the same problem in other parts of the codebase before submitting your PR.
|
||||||
many stages of the process.
|
* **DO** [link the issue](https://github.com/blog/957-introducing-issue-mentions) you are addressing in the
|
||||||
|
pull request.
|
||||||
|
* **DO** write a good description for your pull request. More detail is better. Describe *why* the change is being
|
||||||
|
made and *why* you have chosen a particular solution. Describe any manual testing you performed to validate your change.
|
||||||
|
* **DO NOT** submit a PR unless it is linked to an Issue marked
|
||||||
|
[`triage approved`](https://github.com/Microsoft/calculator/issues?q=is%3Aissue+is%3Aopen+label%3A%22Triage%3A+Approved%22).
|
||||||
|
This enables us to have a discussion on the idea before anyone invests time in an implementation.
|
||||||
|
* **DO NOT** merge multiple changes into one PR unless they have the same root cause.
|
||||||
|
* **DO NOT** submit pure formatting/typo changes to code that has not been modified otherwise.
|
||||||
|
|
||||||
|
We follow a [user-centered process for developing features](docs/NewFeatureProcess.md). New features
|
||||||
|
need sponsorship from the Calculator team, but we welcome community contributions at many stages of
|
||||||
|
the process.
|
||||||
|
|
||||||
|
> Submitting a pull request for an approved Issue is not a guarantee it will be approved.
|
||||||
|
> The change must meet our high bar for code quality, architecture, and performance, as well as
|
||||||
|
> [other requirements](#docs/NewFeatureProcess.md#technical-review).
|
||||||
|
|
||||||
## Making changes to the code
|
## Making changes to the code
|
||||||
|
|
||||||
|
@ -41,7 +59,8 @@ To learn how to build the code and run tests, follow the instructions in the [RE
|
||||||
### Style guidelines
|
### Style guidelines
|
||||||
The code in this project uses several different coding styles, depending on the age and history of
|
The code in this project uses several different coding styles, depending on the age and history of
|
||||||
the code. Please attempt to match the style of surrounding code as much as possible. In new
|
the code. Please attempt to match the style of surrounding code as much as possible. In new
|
||||||
components, prefer the patterns described in the [C++ core guidelines](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines)
|
components, prefer the patterns described in the
|
||||||
|
[C++ core guidelines](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines)
|
||||||
and the [modern C++/WinRT language projections](https://docs.microsoft.com/en-us/windows/uwp/cpp-and-winrt-apis/).
|
and the [modern C++/WinRT language projections](https://docs.microsoft.com/en-us/windows/uwp/cpp-and-winrt-apis/).
|
||||||
|
|
||||||
### Testing
|
### Testing
|
||||||
|
@ -61,18 +80,9 @@ to group your changes into a small number of commits which we can review one at
|
||||||
When completing a pull request, we will generally squash your changes into a single commit. Please
|
When completing a pull request, we will generally squash your changes into a single commit. Please
|
||||||
let us know if your pull request needs to be merged as separate commits.
|
let us know if your pull request needs to be merged as separate commits.
|
||||||
|
|
||||||
## Submitting a pull request and participating in code review
|
## Review Process
|
||||||
Writing a good description for your pull request is crucial to help reviewers and future
|
|
||||||
maintainers understand your change. More detail is better.
|
|
||||||
- [Link the issue you're addressing in the pull request](https://github.com/blog/957-introducing-issue-mentions).
|
|
||||||
- Describe *why* the change is being made and *why* you've chosen a particular solution.
|
|
||||||
- Describe any manual testing you performed to validate your change.
|
|
||||||
|
|
||||||
Please submit one pull request per issue. Large pull requests which have unrelated changes can be
|
|
||||||
difficult to review.
|
|
||||||
|
|
||||||
After submitting a pull request, members of the calculator team will review your code. We will
|
After submitting a pull request, members of the calculator team will review your code. We will
|
||||||
assign the request to an appropriate reviewer within two days. Any member of the community may
|
assign the request to an appropriate reviewer. Any member of the community may
|
||||||
participate in the review, but at least one member of the Calculator team will ultimately approve
|
participate in the review, but at least one member of the Calculator team will ultimately approve
|
||||||
the request.
|
the request.
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,13 @@ Calculator ships regularly with new features and bug fixes. You can get the late
|
||||||
- Standard Calculator functionality which offers basic operations and evaluates commands immediately as they are entered.
|
- Standard Calculator functionality which offers basic operations and evaluates commands immediately as they are entered.
|
||||||
- Scientific Calculator functionality which offers expanded operations and evaluates commands using order of operations.
|
- Scientific Calculator functionality which offers expanded operations and evaluates commands using order of operations.
|
||||||
- Programmer Calculator functionality which offers common mathematical operations for developers including conversion between common bases.
|
- Programmer Calculator functionality which offers common mathematical operations for developers including conversion between common bases.
|
||||||
|
- Date Calculation functionality which offers the difference between two dates, as well as the ability to add/subtract years, months and/or days to/from a given input date.
|
||||||
- Calculation history and memory capabilities.
|
- Calculation history and memory capabilities.
|
||||||
- Conversion between many units of measurement.
|
- Conversion between many units of measurement.
|
||||||
- Currency conversion based on data retrieved from [Bing](https://www.bing.com).
|
- Currency conversion based on data retrieved from [Bing](https://www.bing.com).
|
||||||
|
- [Infinite precision](https://en.wikipedia.org/wiki/Arbitrary-precision_arithmetic) for basic
|
||||||
|
arithmetic operations (addition, subtraction, multiplication, division) so that calculations
|
||||||
|
never lose precision.
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
Prerequisites:
|
Prerequisites:
|
||||||
|
|
91
Tools/Scripts/clang-format/clang-format-all.ps1
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
<#
|
||||||
|
.DESCRIPTION
|
||||||
|
Helper script to format all header and source files in the repository.
|
||||||
|
|
||||||
|
By default, the script will recursively search under the repo root for
|
||||||
|
files to format. Users can give explicit parameters indicating how the
|
||||||
|
search should include and exclude filetypes.
|
||||||
|
|
||||||
|
If users don't want the search functionality, they can instead provide
|
||||||
|
an explicit list of files to format.
|
||||||
|
|
||||||
|
.PARAMETER RepoRoot
|
||||||
|
Full path to the root of the repository which is the target of the search.
|
||||||
|
Will default to the root of the current working directory.
|
||||||
|
|
||||||
|
.PARAMETER Include
|
||||||
|
Array of filetype extensions to target for formatting.
|
||||||
|
By default, targets standard extensions for header and source files.
|
||||||
|
Follows the same rules as the -Include parameter for Get-ChildItem.
|
||||||
|
|
||||||
|
.PARAMETER Exclude
|
||||||
|
Array of filetype extensions to exclude from formatting.
|
||||||
|
By default, excludes generated XAML files.
|
||||||
|
Follows the same rules as the -Exclude paramter for Get-ChildItem.
|
||||||
|
|
||||||
|
.PARAMETER Files
|
||||||
|
Array of files to format. The script will exit if one of the provided
|
||||||
|
filepaths does not exist.
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
.\clang-format-all.ps1
|
||||||
|
|
||||||
|
Formats all header and source files under the repository root.
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
.\clang-format-all.ps1 -RepoRoot 'S:\repos\calculator' -Include '*.h', '*.cpp' -Exclude '*.g.*'
|
||||||
|
|
||||||
|
Formats all *.h and *.cpp files under 'S:\repos\calculator', excluding files with an extension
|
||||||
|
like *.g.*
|
||||||
|
|
||||||
|
.EXAMPLE
|
||||||
|
.\clang-format-all.ps1 -File 'S:\repos\calculator\src\CalcViewModel\UnitConverterViewModel.h', 'S:\repos\calculator\src\CalcViewModel\MemoryItemViewModel.cpp'
|
||||||
|
|
||||||
|
Formats the specified files.
|
||||||
|
#>
|
||||||
|
[CmdletBinding( DefaultParameterSetName = 'Search' )]
|
||||||
|
param(
|
||||||
|
[Parameter( ParameterSetName = 'Search' )]
|
||||||
|
[ValidateScript({ Test-Path -PathType Container -Path $_ })]
|
||||||
|
[string] $RepoRoot = "$( git rev-parse --show-toplevel )",
|
||||||
|
|
||||||
|
[Parameter( ParameterSetName = 'Search' )]
|
||||||
|
[string[]] $Include = ( '*.h', '*.hh', '*.hpp', '*.c', '*.cc', '*.cpp' ),
|
||||||
|
|
||||||
|
[Parameter( ParameterSetName = 'Search' )]
|
||||||
|
[string[]] $Exclude = '*.g.*',
|
||||||
|
|
||||||
|
[Parameter(
|
||||||
|
ParameterSetName = 'Explicit',
|
||||||
|
Mandatory)]
|
||||||
|
[ValidateScript({
|
||||||
|
$_ | Where-Object { -not (Test-Path -PathType Leaf -Path $_) } |
|
||||||
|
ForEach-Object { throw "Could not find file: [$_]" }
|
||||||
|
|
||||||
|
return $true
|
||||||
|
})]
|
||||||
|
[string[]] $Files
|
||||||
|
)
|
||||||
|
|
||||||
|
if ($PSCmdlet.ParameterSetName -eq 'Explicit')
|
||||||
|
{
|
||||||
|
# Use the file paths we were given.
|
||||||
|
$targetFiles = @($Files)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
# Gather the files to be formatted.
|
||||||
|
$targetFiles = @(
|
||||||
|
Get-ChildItem -Recurse -Path $RepoRoot -Include $Include -Exclude $Exclude |
|
||||||
|
Select-Object -ExpandProperty FullName
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Format the files.
|
||||||
|
$formatParams = @(
|
||||||
|
'-i' # In-place
|
||||||
|
'-style=file' # Search for a .clang-format file in the parent directory of the source file.
|
||||||
|
'-verbose'
|
||||||
|
)
|
||||||
|
|
||||||
|
clang-format $formatParams $targetFiles
|
53
Tools/Scripts/clang-format/clang-format-all.sh
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
function usage {
|
||||||
|
echo "Usage: $0 DIR..."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Variable that will hold the name of the clang-format command
|
||||||
|
FMT=""
|
||||||
|
|
||||||
|
# Some distros just call it clang-format. Others (e.g. Ubuntu) are insistent
|
||||||
|
# that the version number be part of the command. We prefer clang-format if
|
||||||
|
# that's present, otherwise we work backwards from highest version to lowest
|
||||||
|
# version.
|
||||||
|
for clangfmt in clang-format{,-{4,3}.{9,8,7,6,5,4,3,2,1,0}}; do
|
||||||
|
if which "$clangfmt" &>/dev/null; then
|
||||||
|
FMT="$clangfmt"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Check if we found a working clang-format
|
||||||
|
if [ -z "$FMT" ]; then
|
||||||
|
echo "failed to find clang-format"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
SRC_PATH="$@"
|
||||||
|
if [ -z "$SRC_PATH" ]; then
|
||||||
|
SRC_PATH="../../../src"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check all of the arguments first to make sure they're all directories
|
||||||
|
for dir in "$SRC_PATH"; do
|
||||||
|
if [ ! -d "${dir}" ]; then
|
||||||
|
echo "${dir} is not a directory"
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Run clang-format -i on all of the things
|
||||||
|
for dir in "$SRC_PATH"; do
|
||||||
|
pushd "${dir}" &>/dev/null
|
||||||
|
find . \
|
||||||
|
\( -name '*.c' \
|
||||||
|
-o -name '*.cc' \
|
||||||
|
-o -name '*.cpp' \
|
||||||
|
-o -name '*.h' \
|
||||||
|
-o -name '*.hh' \
|
||||||
|
-o -name '*.hpp' \) \
|
||||||
|
-exec "${FMT}" -style=file -i '{}' \;
|
||||||
|
popd &>/dev/null
|
||||||
|
done
|
|
@ -1,5 +1,5 @@
|
||||||
<SignConfigXML>
|
<SignConfigXML>
|
||||||
<job platform="" configuration="" certSubject="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" jobname="EngFunSimpleSign" approvers="gstolt;vigarg">
|
<job platform="" configuration="" certSubject="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" jobname="EngFunSimpleSign" approvers="">
|
||||||
<file src="__INPATHROOT__\Microsoft.WindowsCalculator_8wekyb3d8bbwe.appxbundle" signType="136020001" dest="__OUTPATHROOT__\Microsoft.WindowsCalculator_8wekyb3d8bbwe.appxbundle" />
|
<file src="__INPATHROOT__\Microsoft.WindowsCalculator_8wekyb3d8bbwe.appxbundle" signType="136020001" dest="__OUTPATHROOT__\Microsoft.WindowsCalculator_8wekyb3d8bbwe.appxbundle" />
|
||||||
</job>
|
</job>
|
||||||
</SignConfigXML>
|
</SignConfigXML>
|
|
@ -33,6 +33,10 @@ jobs:
|
||||||
platform: ARM64
|
platform: ARM64
|
||||||
condition: not(eq(variables['Build.Reason'], 'PullRequest'))
|
condition: not(eq(variables['Build.Reason'], 'PullRequest'))
|
||||||
|
|
||||||
|
- template: ./templates/run-ui-tests.yaml
|
||||||
|
parameters:
|
||||||
|
platform: x64
|
||||||
|
|
||||||
- template: ./templates/run-unit-tests.yaml
|
- template: ./templates/run-unit-tests.yaml
|
||||||
parameters:
|
parameters:
|
||||||
platform: x64
|
platform: x64
|
||||||
|
|
|
@ -15,30 +15,33 @@ name: $(BuildDefinitionName)_$(date:yyMM).$(date:dd)$(rev:rrr)
|
||||||
jobs:
|
jobs:
|
||||||
- job: Localize
|
- job: Localize
|
||||||
pool:
|
pool:
|
||||||
name: Package ES Custom Demands Lab A
|
vmImage: vs2017-win2016
|
||||||
demands:
|
variables:
|
||||||
- ClientAlias -equals PKGESUTILAPPS
|
skipComponentGovernanceDetection: true
|
||||||
workspace:
|
|
||||||
clean: outputs
|
|
||||||
steps:
|
steps:
|
||||||
- checkout: self
|
|
||||||
clean: true
|
|
||||||
|
|
||||||
- task: PkgESSetupBuild@10
|
- task: MicrosoftTDBuild.tdbuild-task.tdbuild-task.TouchdownBuildTask@1
|
||||||
displayName: Initialize Package ES
|
displayName: Send resources to Touchdown Build
|
||||||
inputs:
|
inputs:
|
||||||
productName: Calculator
|
teamId: 86
|
||||||
branchVersion: true
|
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
|
- script: |
|
||||||
displayName: Package ES Touchdown Loc Service
|
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:
|
inputs:
|
||||||
IsCallToServiceStepSelected: true
|
artifactName: Patch
|
||||||
IsCheckedInFileSelected: true
|
targetPath: $(Build.ArtifactStagingDirectory)
|
||||||
CheckinFilesAtOriginFilePath: true
|
|
||||||
GitLocPath: Loc/Resources
|
|
||||||
LocConfigFile: build/config/LocConfigPackageEs.xml
|
|
||||||
AuthenticationMode: OAuth
|
|
||||||
ClientApplicationID: d3dd8113-65b3-4526-bdca-a00a7d1c37ba
|
|
||||||
ApplicationKeyID: $(LocServiceKey)
|
|
||||||
SendToLoc: true
|
|
|
@ -9,8 +9,8 @@ pr: none
|
||||||
|
|
||||||
variables:
|
variables:
|
||||||
versionMajor: 10
|
versionMajor: 10
|
||||||
versionMinor: 1902
|
versionMinor: 1904
|
||||||
versionBuild: $[counter('10.1902.*', 0)]
|
versionBuild: $[counter('10.1904.*', 0)]
|
||||||
versionPatch: 0
|
versionPatch: 0
|
||||||
|
|
||||||
name: '$(versionMajor).$(versionMinor).$(versionBuild).$(versionPatch)'
|
name: '$(versionMajor).$(versionMinor).$(versionBuild).$(versionPatch)'
|
||||||
|
|
|
@ -29,7 +29,7 @@ jobs:
|
||||||
downloadDirectory: $(Build.SourcesDirectory)
|
downloadDirectory: $(Build.SourcesDirectory)
|
||||||
vstsFeed: WindowsApps
|
vstsFeed: WindowsApps
|
||||||
vstsFeedPackage: calculator-internals
|
vstsFeedPackage: calculator-internals
|
||||||
vstsPackageVersion: 0.0.7
|
vstsPackageVersion: 0.0.10
|
||||||
|
|
||||||
- template: ./build-single-architecture.yaml
|
- template: ./build-single-architecture.yaml
|
||||||
parameters:
|
parameters:
|
||||||
|
|
|
@ -30,7 +30,7 @@ steps:
|
||||||
inputs:
|
inputs:
|
||||||
solution: src/Calculator.sln
|
solution: src/Calculator.sln
|
||||||
vsVersion: 15.0
|
vsVersion: 15.0
|
||||||
msbuildArgs: /bl:$(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\Calculator.binlog /p:OutDir=$(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\ /p:GenerateProjectSpecificOutputFolder=true /p:AppVersion=$(Build.BuildNumber) ${{ parameters.extraMsBuildArgs }}
|
msbuildArgs: /bl:$(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\Calculator.binlog /p:OutDir=$(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\ /p:GenerateProjectSpecificOutputFolder=true /p:AppVersion=$(Build.BuildNumber) /t:Publish /p:PublishDir=$(Build.BinariesDirectory)\$(BuildConfiguration)\$(BuildPlatform)\publish\ ${{ parameters.extraMsBuildArgs }}
|
||||||
platform: $(BuildPlatform)
|
platform: $(BuildPlatform)
|
||||||
configuration: $(BuildConfiguration)
|
configuration: $(BuildConfiguration)
|
||||||
clean: true
|
clean: true
|
||||||
|
|
|
@ -20,6 +20,8 @@ jobs:
|
||||||
vmImage: vs2017-win2016
|
vmImage: vs2017-win2016
|
||||||
workspace:
|
workspace:
|
||||||
clean: outputs
|
clean: outputs
|
||||||
|
variables:
|
||||||
|
skipComponentGovernanceDetection: true
|
||||||
steps:
|
steps:
|
||||||
- checkout: self
|
- checkout: self
|
||||||
clean: true
|
clean: true
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# This template contains a job which builds artifacts needed to release the app to the store and to
|
# This template contains a job which builds artifacts needed to release the app to the store and to
|
||||||
# Windows using Microsoft-internal systems. It relies Microsoft-internal resources and will not
|
# Windows using Microsoft-internal systems. It relies on Microsoft-internal resources and will not
|
||||||
# work outside of Microsoft.
|
# work outside of Microsoft.
|
||||||
# Specifically, this job:
|
# Specifically, this job:
|
||||||
# - Signs the bundle using a secure system. If you want to build your own, use SignTool following
|
# - Signs the bundle using a secure system. If you want to build your own, use SignTool following
|
||||||
|
@ -17,6 +17,8 @@ jobs:
|
||||||
name: Package ES Lab E
|
name: Package ES Lab E
|
||||||
workspace:
|
workspace:
|
||||||
clean: outputs
|
clean: outputs
|
||||||
|
variables:
|
||||||
|
skipComponentGovernanceDetection: true
|
||||||
steps:
|
steps:
|
||||||
- checkout: self
|
- checkout: self
|
||||||
clean: true
|
clean: true
|
||||||
|
@ -44,6 +46,8 @@ jobs:
|
||||||
|
|
||||||
- task: PkgESCodeSign@10
|
- task: PkgESCodeSign@10
|
||||||
displayName: Send bundle to Package ES code signing service
|
displayName: Send bundle to Package ES code signing service
|
||||||
|
env:
|
||||||
|
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
|
||||||
inputs:
|
inputs:
|
||||||
signConfigXml: build\config\SignConfig.xml
|
signConfigXml: build\config\SignConfig.xml
|
||||||
inPathRoot: $(Build.ArtifactStagingDirectory)\appxBundle
|
inPathRoot: $(Build.ArtifactStagingDirectory)\appxBundle
|
||||||
|
@ -87,7 +91,7 @@ jobs:
|
||||||
downloadDirectory: $(Build.SourcesDirectory)
|
downloadDirectory: $(Build.SourcesDirectory)
|
||||||
vstsFeed: WindowsApps
|
vstsFeed: WindowsApps
|
||||||
vstsFeedPackage: calculator-internals
|
vstsFeedPackage: calculator-internals
|
||||||
vstsPackageVersion: 0.0.7
|
vstsPackageVersion: 0.0.10
|
||||||
|
|
||||||
- task: PkgESStoreBrokerPackage@10
|
- task: PkgESStoreBrokerPackage@10
|
||||||
displayName: Create StoreBroker Packages
|
displayName: Create StoreBroker Packages
|
||||||
|
|
55
build/pipelines/templates/run-ui-tests.yaml
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
# This template contains jobs to run UI tests using WinAppDriver.
|
||||||
|
|
||||||
|
parameters:
|
||||||
|
platform: ''
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
- job: UITests${{ parameters.platform }}
|
||||||
|
displayName: UITests ${{ parameters.platform }}
|
||||||
|
dependsOn: Build${{ parameters.platform }}
|
||||||
|
condition: succeeded()
|
||||||
|
pool:
|
||||||
|
vmImage: windows-2019
|
||||||
|
variables:
|
||||||
|
skipComponentGovernanceDetection: true
|
||||||
|
steps:
|
||||||
|
- checkout: none
|
||||||
|
|
||||||
|
- task: DownloadBuildArtifacts@0
|
||||||
|
displayName: Download AppxBundle and CalculatorUITests
|
||||||
|
inputs:
|
||||||
|
artifactName: drop
|
||||||
|
itemPattern: |
|
||||||
|
drop/Release/${{ parameters.platform }}/Calculator/AppPackages/**
|
||||||
|
drop/Release/${{ parameters.platform }}/publish/**
|
||||||
|
|
||||||
|
- task: PowerShell@2
|
||||||
|
displayName: Install certificate
|
||||||
|
inputs:
|
||||||
|
filePath: $(Build.ArtifactStagingDirectory)/drop/Release/${{ parameters.platform }}/Calculator/AppPackages/Calculator_$(Build.BuildNumber)_Test/Add-AppDevPackage.ps1
|
||||||
|
arguments: -CertificatePath $(Build.ArtifactStagingDirectory)/drop/Release/${{ parameters.platform }}/Calculator/AppPackages/Calculator_$(Build.BuildNumber)_Test/Calculator_$(Build.BuildNumber)_${{ parameters.platform }}.cer -Force
|
||||||
|
|
||||||
|
- task: PowerShell@2
|
||||||
|
displayName: Install app
|
||||||
|
inputs:
|
||||||
|
filePath: $(Build.ArtifactStagingDirectory)/drop/Release/${{ parameters.platform }}/Calculator/AppPackages/Calculator_$(Build.BuildNumber)_Test/Add-AppDevPackage.ps1
|
||||||
|
arguments: -Force
|
||||||
|
|
||||||
|
- task: WinAppDriver.winappdriver-pipelines-task.winappdriver-pipelines-task.Windows Application Driver@0
|
||||||
|
displayName: 'WinAppDriver - Start'
|
||||||
|
inputs:
|
||||||
|
AgentResolution: 1080p
|
||||||
|
|
||||||
|
- task: VSTest@2
|
||||||
|
displayName: Run CalculatorUITests
|
||||||
|
inputs:
|
||||||
|
testAssemblyVer2: $(Build.ArtifactStagingDirectory)/drop/Release/${{ parameters.platform }}/publish/CalculatorUITests.dll
|
||||||
|
vsTestVersion: 16.0
|
||||||
|
runSettingsFile: $(Build.ArtifactStagingDirectory)/drop/Release/${{ parameters.platform }}/publish/CalculatorUITests.runsettings
|
||||||
|
platform: ${{ parameters.platform }}
|
||||||
|
configuration: Release
|
||||||
|
|
||||||
|
- task: WinAppDriver.winappdriver-pipelines-task.winappdriver-pipelines-task.Windows Application Driver@0
|
||||||
|
displayName: 'WinAppDriver - Stop'
|
||||||
|
inputs:
|
||||||
|
OperationType: Stop
|
|
@ -14,6 +14,8 @@ jobs:
|
||||||
name: Essential Experiences Interactive
|
name: Essential Experiences Interactive
|
||||||
workspace:
|
workspace:
|
||||||
clean: outputs
|
clean: outputs
|
||||||
|
variables:
|
||||||
|
skipComponentGovernanceDetection: true
|
||||||
steps:
|
steps:
|
||||||
- checkout: none
|
- checkout: none
|
||||||
|
|
||||||
|
|
|
@ -153,7 +153,9 @@ The CalcEngine contains the logic for interpreting and performing operations acc
|
||||||
|
|
||||||
### RatPack
|
### RatPack
|
||||||
|
|
||||||
The RatPack (short for Rational Pack) is the core of the Calculator model and contains the logic for performing its mathematical operations. The interface to this layer is defined in [ratpak.h][ratpak.h].
|
The RatPack (short for Rational Pack) is the core of the Calculator model and contains the logic for
|
||||||
|
performing its mathematical operations (using [infinite precision][Infinite Precision] arithmetic
|
||||||
|
instead of regular floating point arithmetic). The interface to this layer is defined in [ratpak.h][ratpak.h].
|
||||||
|
|
||||||
[References]:####################################################################################################
|
[References]:####################################################################################################
|
||||||
|
|
||||||
|
|
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 |
|
@ -1,7 +1,8 @@
|
||||||
# New feature process
|
# New feature process
|
||||||
|
|
||||||
## Where do I submit my idea for a new feature?
|
## Where do I submit my idea for a new feature?
|
||||||
The easiest way to submit new feature requests is through [Feedback Hub](https://insider.windows.com/en-us/fb/?contextid=130).
|
The easiest way to submit new feature requests is through
|
||||||
|
[Feedback Hub](https://insider.windows.com/en-us/fb/?contextid=130).
|
||||||
In Feedback Hub, any Windows user (even if they aren't on GitHub) can upvote suggestions. The
|
In Feedback Hub, any Windows user (even if they aren't on GitHub) can upvote suggestions. The
|
||||||
Calculator team reviews these suggestions regularly, and when we're ready to work on an idea we
|
Calculator team reviews these suggestions regularly, and when we're ready to work on an idea we
|
||||||
create [feature pitch issues here on GitHub](https://github.com/Microsoft/calculator/issues?q=is%3Aissue+is%3Aopen+project%3AMicrosoft%2Fcalculator%2F1).
|
create [feature pitch issues here on GitHub](https://github.com/Microsoft/calculator/issues?q=is%3Aissue+is%3Aopen+project%3AMicrosoft%2Fcalculator%2F1).
|
||||||
|
@ -12,73 +13,45 @@ product. The [Feature Tracking board](https://github.com/Microsoft/calculator/pr
|
||||||
all the features we're working on and where they're at in the process.
|
all the features we're working on and where they're at in the process.
|
||||||
|
|
||||||
## Do I need to follow this process? Can I just start coding and submit a PR?
|
## Do I need to follow this process? Can I just start coding and submit a PR?
|
||||||
You *do not* need to follow this process for bug fixes, performance improvements, or changes to the
|
You **do not** need to follow this process for bug fixes, performance improvements, or changes to the
|
||||||
development tools. To contribute these changes, [discuss the proposed change in an issue](https://github.com/Microsoft/calculator/issues/new)
|
development tools. To contribute these changes,
|
||||||
|
[discuss the proposed change in an issue](https://github.com/Microsoft/calculator/issues/new)
|
||||||
and then submit a pull request.
|
and then submit a pull request.
|
||||||
|
|
||||||
You *do* need to follow this process for any change which "users will notice". This applies
|
You **do** need to follow this process for any change which "users will notice". This applies
|
||||||
especially to new features and major visual changes.
|
especially to new features and major visual changes.
|
||||||
|
|
||||||
## Step 1: Feature pitch
|
## Step 1: Feature pitch
|
||||||
The feature pitch concisely describes a point of view on the problem the new feature should solve.
|
Feature pitches are submitted as issues on GitHub using the
|
||||||
It will typically include these sections:
|
[Feature Request template](https://github.com/Microsoft/calculator/issues/new?assignees=&labels=&template=feature_request.md&title=).
|
||||||
|
We encourage discussion on open issues, and as discussion progresses we will edit the issue description to refine the
|
||||||
|
idea until it is ready for review.
|
||||||
|
|
||||||
* **Problem Statement**: What problem are we trying to solve? Who’s the target audience? Is there a
|
We review pitches regularly, and will approve or close issues based on whether they broadly align with the
|
||||||
customer need or pain point we need to remedy? Is there a business goal or metric we are trying
|
[Calculator roadmap](https://github.com/Microsoft/calculator/blob/master/docs/Roadmap.md). Approved pitches are moved
|
||||||
to improve? Do we have a hypothesis we want to prove or disprove?
|
into [pre-production](https://github.com/Microsoft/calculator/projects/1) on the feature tracking board.
|
||||||
* **Evidence or User Insights**: Why should we do this? Potential sources of data: Feedback Hub,
|
|
||||||
other GitHub issues, other anecdotes from listening to customers in person or online, request
|
|
||||||
from another team, telemetry data, user research, market or competitive research
|
|
||||||
* **Proposal**: How will the solution/feature help us solve the problem? How will it meet the
|
|
||||||
target audience’s needs? If there are business goals or metrics, how does this improve them?
|
|
||||||
* **Goals**: What you want to accomplish with this feature. Typical examples include “User Can
|
|
||||||
*perform some task*”
|
|
||||||
* **Non-Goals**: Things we are explicitly not doing or supporting or that are out of scope,
|
|
||||||
including reasons why.
|
|
||||||
* **Low-Fidelity Concept**: Show as much of the experience as needed to explain the idea. This
|
|
||||||
can be as simple as a napkin drawing but can also be a code prototype, a PowerPoint walkthrough,
|
|
||||||
or a design comp.
|
|
||||||
|
|
||||||
The low-fidelity concept should be kept simple at this stage and refined during the pre-production
|
|
||||||
process.
|
|
||||||
|
|
||||||
Feature pitches are submitted as issues on GitHub. We encourage discussion on open issues, and as
|
|
||||||
discussion progresses we will edit the issue description to refine the idea.
|
|
||||||
|
|
||||||
## Step 2: Pre-production
|
## Step 2: Pre-production
|
||||||
In the pre-production phase, we experiment with a variety of ways to address the goals described in
|
For most features, the output of this phase is a specification which describes how the feature will work, supported by
|
||||||
the feature pitch. The output of this phase is a specification which demonstrates how the feature
|
design renderings and code prototypes as needed. The original issue will continue to track the overall progress of the
|
||||||
will work, supported by design renderings and code prototypes as needed. Sometimes we'll learn new
|
feature, but we will create and iterate on spec documentation in the
|
||||||
things about a feature proposal during pre-production, and we'll edit or close the original pitch.
|
[Calculator Spec repo](https://github.com/Microsoft/calculator-specs). Sometimes we'll learn new things about a feature
|
||||||
|
proposal during pre-production, and we'll edit or close the original pitch.
|
||||||
|
|
||||||
We welcome community participation in the pre-production process. The GitHub issue will be the
|
We welcome community participation throughout pre-production. The best ideas often come from trying many ideas during
|
||||||
primary place to share progress updates.
|
the pre-production phase. To enable rapid
|
||||||
|
|
||||||
The best ideas often come from trying many ideas during the pre-production phase. To enable rapid
|
|
||||||
experimentation, we encourage developing and sharing rough ideas—maybe even with pencil and
|
experimentation, we encourage developing and sharing rough ideas—maybe even with pencil and
|
||||||
paper—before making designs pixel-perfect or making code robust and maintainable.
|
paper—before making designs pixel-perfect or making code robust and maintainable.
|
||||||
|
|
||||||
### Spec review
|
After the [spec review](https://github.com/Microsoft/calculator-specs#spec-review) is completed, we will move the issue
|
||||||
Once there is a high-fidelity design which addresses the goals described in the original pitch, the
|
into [production](https://github.com/Microsoft/calculator/projects/1) on the feature tracking board. In _some_ cases,
|
||||||
Microsoft product team will review the prototype and ensure all items on this checklist are
|
all of the details of an idea can be captured concisely in original feature pitch. When that happens, we may move ideas
|
||||||
addressed:
|
directly into production.
|
||||||
|
|
||||||
- [ ] Is there a high-fidelity design which gives reviewers a clear idea of how the feature will
|
|
||||||
look and function when implemented?
|
|
||||||
- [ ] Has the plan been shared with the community (documented on the wiki and updates posted in the
|
|
||||||
original issue) and have others been given an opportunity to provide suggestions?
|
|
||||||
- [ ] Are [Fluent design principles](https://docs.microsoft.com/en-us/windows/uwp/design/fluent-design-system/)
|
|
||||||
followed? If we do something which deviates from the guidelines, do we have a good reason?
|
|
||||||
- [ ] Does the design include provisions for [all users](https://docs.microsoft.com/en-us/windows/uwp/design/accessibility/designing-inclusive-software)
|
|
||||||
and [all cultures](https://docs.microsoft.com/en-us/windows/uwp/design/globalizing/guidelines-and-checklist-for-globalizing-your-app)?
|
|
||||||
- [ ] Is it technically feasible to build this feature? Take a look at the "before committing"
|
|
||||||
checklist below and identify any issues which are likely to be blockers.
|
|
||||||
|
|
||||||
## Step 3: Production
|
## Step 3: Production
|
||||||
A feature can be implemented by the original proposer, a Microsoft team member, or by other
|
A feature can be implemented by the original submitter, a Microsoft team member, or by other
|
||||||
community members. Code contributions and testing help are greatly appreciated. Please let us know
|
community members. Code contributions and testing help are greatly appreciated. Please let everyone know if you're
|
||||||
in the issue comments if you're actively working on a feature so we can ensure it's assigned to
|
actively working on a feature to help avoid duplicated efforts from others.
|
||||||
you.
|
|
||||||
|
|
||||||
You might be able to reuse code written during the prototype process, although there will typically
|
You might be able to reuse code written during the prototype process, although there will typically
|
||||||
be more work required to make the solution robust. Once the code is ready, you can begin
|
be more work required to make the solution robust. Once the code is ready, you can begin
|
||||||
|
@ -122,7 +95,8 @@ new features, the Microsoft team considers at least these items:
|
||||||
- [ ] Run the perf tests to measure any increase in startup time. Move work out of the startup
|
- [ ] Run the perf tests to measure any increase in startup time. Move work out of the startup
|
||||||
path if possible.
|
path if possible.
|
||||||
- [ ] If the change adds additional logging:
|
- [ ] If the change adds additional logging:
|
||||||
- [ ] All logging should use [TraceLogging](https://docs.microsoft.com/en-us/windows/desktop/tracelogging/trace-logging-about).
|
- [ ] All logging should use
|
||||||
|
[TraceLogging](https://docs.microsoft.com/en-us/windows/desktop/tracelogging/trace-logging-about).
|
||||||
- [ ] Unnecessary log events should be removed, or configured so that they are collected only when
|
- [ ] Unnecessary log events should be removed, or configured so that they are collected only when
|
||||||
needed to debug issues or measure feature usage.
|
needed to debug issues or measure feature usage.
|
||||||
- [ ] If the change reads user data from files or app settings:
|
- [ ] If the change reads user data from files or app settings:
|
||||||
|
|
|
@ -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)
|
* 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
|
* Improving testing and diagnostics within the project
|
||||||
* Investigating new features with a focus on addressing top user feedback, including:
|
* 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
|
* Adding the ability for users to pin Calculator on top of other windows
|
||||||
* Providing additional customization options
|
* 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!
|
* [Your feature idea here] - please review our [new feature development process](https://github.com/Microsoft/calculator/blob/master/docs/NewFeatureProcess.md) to get started!
|
||||||
|
|
|
@ -123,7 +123,7 @@
|
||||||
<AppxPackageTestDir>@(AppxBundleOutput->'%(RootDir)%(Directory)')</AppxPackageTestDir>
|
<AppxPackageTestDir>@(AppxBundleOutput->'%(RootDir)%(Directory)')</AppxPackageTestDir>
|
||||||
<UniversalTestCustomMacros Condition="'$(Configuration)'=='Debug'">$(UniversalTestCustomMacros)AppxPackageVCLibsDependency=$(AppxPackageTestDir)Dependencies\$(PlatformTarget)\Microsoft.VCLibs.$(PlatformTarget).Debug.14.00.appx;</UniversalTestCustomMacros>
|
<UniversalTestCustomMacros Condition="'$(Configuration)'=='Debug'">$(UniversalTestCustomMacros)AppxPackageVCLibsDependency=$(AppxPackageTestDir)Dependencies\$(PlatformTarget)\Microsoft.VCLibs.$(PlatformTarget).Debug.14.00.appx;</UniversalTestCustomMacros>
|
||||||
<UniversalTestCustomMacros Condition="'$(Configuration)'=='Release'">$(UniversalTestCustomMacros)AppxPackageVCLibsDependency=$(AppxPackageTestDir)Dependencies\$(PlatformTarget)\Microsoft.VCLibs.$(PlatformTarget).14.00.appx;</UniversalTestCustomMacros>
|
<UniversalTestCustomMacros Condition="'$(Configuration)'=='Release'">$(UniversalTestCustomMacros)AppxPackageVCLibsDependency=$(AppxPackageTestDir)Dependencies\$(PlatformTarget)\Microsoft.VCLibs.$(PlatformTarget).14.00.appx;</UniversalTestCustomMacros>
|
||||||
<UniversalTestCustomMacros>$(UniversalTestCustomMacros)AppxPackageWinUIDependency=$(AppxPackageTestDir)Dependencies\$(PlatformTarget)\Microsoft.UI.Xaml.2.0.appx;</UniversalTestCustomMacros>
|
<UniversalTestCustomMacros>$(UniversalTestCustomMacros)AppxPackageWinUIDependency=$(AppxPackageTestDir)Dependencies\$(PlatformTarget)\Microsoft.UI.Xaml.2.1.appx;</UniversalTestCustomMacros>
|
||||||
<UniversalTestCustomMacros>$(UniversalTestCustomMacros)AppxPackagePublicKeyFile=@(AppxPackagePublicKeyFile->'%(FullPath)');AppxBundleOutput=@(AppxBundleOutput->'%(FullPath)');</UniversalTestCustomMacros>
|
<UniversalTestCustomMacros>$(UniversalTestCustomMacros)AppxPackagePublicKeyFile=@(AppxPackagePublicKeyFile->'%(FullPath)');AppxBundleOutput=@(AppxBundleOutput->'%(FullPath)');</UniversalTestCustomMacros>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
</Target>
|
</Target>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
#include "pch.h"
|
#include <sstream>
|
||||||
#include "Header Files/CalcEngine.h"
|
#include "Header Files/CalcEngine.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -56,7 +56,7 @@ bool CalcInput::TryToggleSign(bool isIntegerMode, wstring_view maxNumStr)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CalcInput::TryAddDigit(unsigned int value, uint32_t radix, bool isIntegerMode, wstring_view maxNumStr, 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
|
// Convert from an integer into a character
|
||||||
// This includes both normal digits and alpha 'digits' for radixes > 10
|
// This includes both normal digits and alpha 'digits' for radixes > 10
|
||||||
|
|
|
@ -1,27 +1,27 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
#include "Header Files/CalcEngine.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));
|
return ((op >= x) && (op <= y));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsBinOpCode(WPARAM opCode)
|
bool IsBinOpCode(OpCode opCode)
|
||||||
{
|
{
|
||||||
return IsOpInRange(opCode, IDC_AND, IDC_PWR);
|
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
|
// 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
|
// 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);
|
return IsOpInRange(opCode, IDC_UNARYFIRST, IDC_UNARYLAST);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsDigitOpCode(WPARAM opCode)
|
bool IsDigitOpCode(OpCode opCode)
|
||||||
{
|
{
|
||||||
return IsOpInRange(opCode, IDC_0, IDC_F);
|
return IsOpInRange(opCode, IDC_0, IDC_F);
|
||||||
}
|
}
|
||||||
|
@ -31,11 +31,9 @@ bool IsDigitOpCode(WPARAM opCode)
|
||||||
// so we abstract this as a separate routine. Note: There is another side to this. Some commands are not
|
// 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
|
// 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
|
// 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) ||
|
if (IsOpInRange(opCode, IDM_HEX, IDM_BIN) || IsOpInRange(opCode, IDM_QWORD, IDM_BYTE) || IsOpInRange(opCode, IDM_DEG, IDM_GRAD))
|
||||||
IsOpInRange(opCode, IDM_QWORD, IDM_BYTE) ||
|
|
||||||
IsOpInRange(opCode, IDM_DEG, IDM_GRAD))
|
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,26 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
#pragma once
|
|
||||||
#include "Header Files/CalcEngine.h"
|
#include "Header Files/CalcEngine.h"
|
||||||
#include "Command.h"
|
#include "Command.h"
|
||||||
#include "CalculatorVector.h"
|
#include "CalculatorVector.h"
|
||||||
#include "ExpressionCommand.h"
|
#include "ExpressionCommand.h"
|
||||||
#include "CalcException.h"
|
|
||||||
|
|
||||||
constexpr int ASCII_0 = 48;
|
constexpr int ASCII_0 = 48;
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace CalcEngine;
|
using namespace CalcEngine;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
void IFT(ResultCode hr)
|
||||||
|
{
|
||||||
|
if (FAILED(hr))
|
||||||
|
{
|
||||||
|
throw hr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
void CHistoryCollector::ReinitHistory()
|
void CHistoryCollector::ReinitHistory()
|
||||||
{
|
{
|
||||||
m_lastOpStartIndex = -1;
|
m_lastOpStartIndex = -1;
|
||||||
|
@ -32,11 +39,11 @@ void CHistoryCollector::ReinitHistory()
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
// Can throw Out of memory error
|
// Can throw Out of memory error
|
||||||
CHistoryCollector::CHistoryCollector(ICalcDisplay *pCalcDisplay, std::shared_ptr<IHistoryDisplay> pHistoryDisplay, wchar_t decimalSymbol) :
|
CHistoryCollector::CHistoryCollector(ICalcDisplay* pCalcDisplay, std::shared_ptr<IHistoryDisplay> pHistoryDisplay, wchar_t decimalSymbol)
|
||||||
m_pHistoryDisplay(pHistoryDisplay),
|
: m_pHistoryDisplay(pHistoryDisplay)
|
||||||
m_pCalcDisplay(pCalcDisplay),
|
, m_pCalcDisplay(pCalcDisplay)
|
||||||
m_iCurLineHistStart(-1),
|
, m_iCurLineHistStart(-1)
|
||||||
m_decimalSymbol(decimalSymbol)
|
, m_decimalSymbol(decimalSymbol)
|
||||||
{
|
{
|
||||||
ReinitHistory();
|
ReinitHistory();
|
||||||
}
|
}
|
||||||
|
@ -296,7 +303,8 @@ void CHistoryCollector::CompleteHistoryLine(wstring_view numStr)
|
||||||
{
|
{
|
||||||
if (nullptr != m_pCalcDisplay)
|
if (nullptr != m_pCalcDisplay)
|
||||||
{
|
{
|
||||||
m_pCalcDisplay->SetExpressionDisplay(std::make_shared<CalculatorVector<std::pair<std::wstring, int>>>(), std::make_shared<CalculatorVector<std::shared_ptr<IExpressionCommand>>>());
|
m_pCalcDisplay->SetExpressionDisplay(
|
||||||
|
std::make_shared<CalculatorVector<std::pair<std::wstring, int>>>(), std::make_shared<CalculatorVector<std::shared_ptr<IExpressionCommand>>>());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nullptr != m_pHistoryDisplay)
|
if (nullptr != m_pHistoryDisplay)
|
||||||
|
@ -317,14 +325,14 @@ void CHistoryCollector::ClearHistoryLine(wstring_view errStr)
|
||||||
{
|
{
|
||||||
if (nullptr != m_pCalcDisplay)
|
if (nullptr != m_pCalcDisplay)
|
||||||
{
|
{
|
||||||
m_pCalcDisplay->SetExpressionDisplay(std::make_shared<CalculatorVector<std::pair<std::wstring, int>>>(), std::make_shared<CalculatorVector<std::shared_ptr<IExpressionCommand>>>());
|
m_pCalcDisplay->SetExpressionDisplay(
|
||||||
|
std::make_shared<CalculatorVector<std::pair<std::wstring, int>>>(), std::make_shared<CalculatorVector<std::shared_ptr<IExpressionCommand>>>());
|
||||||
}
|
}
|
||||||
m_iCurLineHistStart = -1; // It will get recomputed at the first Opnd
|
m_iCurLineHistStart = -1; // It will get recomputed at the first Opnd
|
||||||
ReinitHistory();
|
ReinitHistory();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Adds the given string psz to the globally maintained current equation string at the end.
|
// Adds the given string psz to the globally maintained current equation string at the end.
|
||||||
// Also returns the 0 based index in the string just added. Can throw out of memory error
|
// Also returns the 0 based index in the string just added. Can throw out of memory error
|
||||||
int CHistoryCollector::IchAddSzToEquationSz(wstring_view str, int icommandIndex)
|
int CHistoryCollector::IchAddSzToEquationSz(wstring_view str, int icommandIndex)
|
||||||
|
@ -386,7 +394,6 @@ void CHistoryCollector::SetExpressionDisplay()
|
||||||
{
|
{
|
||||||
m_pCalcDisplay->SetExpressionDisplay(m_spTokens, m_spCommands);
|
m_pCalcDisplay->SetExpressionDisplay(m_spTokens, m_spCommands);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int CHistoryCollector::AddCommand(_In_ const std::shared_ptr<IExpressionCommand>& spCommand)
|
int CHistoryCollector::AddCommand(_In_ const std::shared_ptr<IExpressionCommand>& spCommand)
|
||||||
|
@ -409,8 +416,11 @@ int CHistoryCollector::AddCommand(_In_ const std::shared_ptr<IExpressionCommand>
|
||||||
// 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)
|
void CHistoryCollector::UpdateHistoryExpression(uint32_t radix, int32_t precision)
|
||||||
{
|
{
|
||||||
if (m_spTokens != nullptr)
|
if (m_spTokens == nullptr)
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
IFT(m_spTokens->GetSize(&size));
|
IFT(m_spTokens->GetSize(&size));
|
||||||
|
|
||||||
|
@ -437,7 +447,6 @@ void CHistoryCollector::UpdateHistoryExpression(uint32_t radix, int32_t precisio
|
||||||
}
|
}
|
||||||
SetExpressionDisplay();
|
SetExpressionDisplay();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void CHistoryCollector::SetDecimalSymbol(wchar_t decimalSymbol)
|
void CHistoryCollector::SetDecimalSymbol(wchar_t decimalSymbol)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,26 +1,28 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
|
||||||
#include "pch.h"
|
#include <algorithm>
|
||||||
#include "Header Files/Number.h"
|
#include "Header Files/Number.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
namespace CalcEngine
|
namespace CalcEngine
|
||||||
{
|
{
|
||||||
Number::Number() noexcept :
|
Number::Number() noexcept
|
||||||
Number(1, 0, { 0 })
|
: Number(1, 0, { 0 })
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Number::Number(int32_t sign, int32_t exp, vector<uint32_t> const& mantissa) noexcept :
|
Number::Number(int32_t sign, int32_t exp, vector<uint32_t> const& mantissa) noexcept
|
||||||
m_sign{ sign },
|
: m_sign{ sign }
|
||||||
m_exp{ exp },
|
, m_exp{ exp }
|
||||||
m_mantissa{ mantissa }
|
, m_mantissa{ mantissa }
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Number::Number(PNUMBER p) noexcept :
|
Number::Number(PNUMBER p) noexcept
|
||||||
m_sign{ p->sign },
|
: m_sign{ p->sign }
|
||||||
m_exp{ p->exp },
|
, m_exp{ p->exp }
|
||||||
m_mantissa{}
|
, m_mantissa{}
|
||||||
{
|
{
|
||||||
m_mantissa.reserve(p->cdigit);
|
m_mantissa.reserve(p->cdigit);
|
||||||
copy(p->mant, p->mant + p->cdigit, back_inserter(m_mantissa));
|
copy(p->mant, p->mant + p->cdigit, back_inserter(m_mantissa));
|
||||||
|
@ -28,10 +30,10 @@ namespace CalcEngine
|
||||||
|
|
||||||
PNUMBER Number::ToPNUMBER() const
|
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->sign = this->Sign();
|
||||||
ret->exp = this->Exp();
|
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;
|
MANTTYPE* ptrRet = ret->mant;
|
||||||
for (auto const& digit : this->Mantissa())
|
for (auto const& digit : this->Mantissa())
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
|
||||||
#include "pch.h"
|
#include <intsafe.h>
|
||||||
#include "Header Files/Rational.h"
|
#include "Header Files/Rational.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
namespace CalcEngine
|
namespace CalcEngine
|
||||||
{
|
{
|
||||||
Rational::Rational() noexcept :
|
Rational::Rational() noexcept
|
||||||
m_p{},
|
: m_p{}
|
||||||
m_q{ 1, 0, { 1 } }
|
, m_q{ 1, 0, { 1 } }
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Rational::Rational(Number const& n) noexcept
|
Rational::Rational(Number const& n) noexcept
|
||||||
{
|
{
|
||||||
|
@ -24,14 +25,15 @@ namespace CalcEngine
|
||||||
m_q = Number(1, qExp, { 1 });
|
m_q = Number(1, qExp, { 1 });
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational::Rational(Number const& p, Number const& q) noexcept :
|
Rational::Rational(Number const& p, Number const& q) noexcept
|
||||||
m_p{ p },
|
: m_p{ p }
|
||||||
m_q{ q }
|
, m_q{ q }
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Rational::Rational(int32_t i)
|
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_p = Number{ pr->pp };
|
||||||
m_q = Number{ pr->pq };
|
m_q = Number{ pr->pq };
|
||||||
|
@ -41,7 +43,7 @@ namespace CalcEngine
|
||||||
|
|
||||||
Rational::Rational(uint32_t ui)
|
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_p = Number{ pr->pp };
|
||||||
m_q = Number{ pr->pq };
|
m_q = Number{ pr->pq };
|
||||||
|
@ -60,10 +62,11 @@ namespace CalcEngine
|
||||||
m_q = Number{ temp.Q() };
|
m_q = Number{ temp.Q() };
|
||||||
}
|
}
|
||||||
|
|
||||||
Rational::Rational(PRAT prat) noexcept :
|
Rational::Rational(PRAT prat) noexcept
|
||||||
m_p{ Number{prat->pp} },
|
: m_p{ Number{ prat->pp } }
|
||||||
m_q{ Number{prat->pq} }
|
, m_q{ Number{ prat->pq } }
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
PRAT Rational::ToPRAT() const
|
PRAT Rational::ToPRAT() const
|
||||||
{
|
{
|
||||||
|
@ -100,7 +103,7 @@ namespace CalcEngine
|
||||||
addrat(&lhsRat, rhsRat, RATIONAL_PRECISION);
|
addrat(&lhsRat, rhsRat, RATIONAL_PRECISION);
|
||||||
destroyrat(rhsRat);
|
destroyrat(rhsRat);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (uint32_t error)
|
||||||
{
|
{
|
||||||
destroyrat(lhsRat);
|
destroyrat(lhsRat);
|
||||||
destroyrat(rhsRat);
|
destroyrat(rhsRat);
|
||||||
|
@ -123,7 +126,7 @@ namespace CalcEngine
|
||||||
subrat(&lhsRat, rhsRat, RATIONAL_PRECISION);
|
subrat(&lhsRat, rhsRat, RATIONAL_PRECISION);
|
||||||
destroyrat(rhsRat);
|
destroyrat(rhsRat);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (uint32_t error)
|
||||||
{
|
{
|
||||||
destroyrat(lhsRat);
|
destroyrat(lhsRat);
|
||||||
destroyrat(rhsRat);
|
destroyrat(rhsRat);
|
||||||
|
@ -146,7 +149,7 @@ namespace CalcEngine
|
||||||
mulrat(&lhsRat, rhsRat, RATIONAL_PRECISION);
|
mulrat(&lhsRat, rhsRat, RATIONAL_PRECISION);
|
||||||
destroyrat(rhsRat);
|
destroyrat(rhsRat);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (uint32_t error)
|
||||||
{
|
{
|
||||||
destroyrat(lhsRat);
|
destroyrat(lhsRat);
|
||||||
destroyrat(rhsRat);
|
destroyrat(rhsRat);
|
||||||
|
@ -169,7 +172,7 @@ namespace CalcEngine
|
||||||
divrat(&lhsRat, rhsRat, RATIONAL_PRECISION);
|
divrat(&lhsRat, rhsRat, RATIONAL_PRECISION);
|
||||||
destroyrat(rhsRat);
|
destroyrat(rhsRat);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (uint32_t error)
|
||||||
{
|
{
|
||||||
destroyrat(lhsRat);
|
destroyrat(lhsRat);
|
||||||
destroyrat(rhsRat);
|
destroyrat(rhsRat);
|
||||||
|
@ -182,6 +185,13 @@ namespace CalcEngine
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calculate the remainder after division, the sign of a result will match the sign of the current object.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This function has the same behavior as the standard C/C++ operator '%'
|
||||||
|
/// to calculate the modulus after division instead, use <see cref="RationalMath::Mod"/> instead.
|
||||||
|
/// </remarks>
|
||||||
Rational& Rational::operator%=(Rational const& rhs)
|
Rational& Rational::operator%=(Rational const& rhs)
|
||||||
{
|
{
|
||||||
PRAT lhsRat = this->ToPRAT();
|
PRAT lhsRat = this->ToPRAT();
|
||||||
|
@ -189,10 +199,10 @@ namespace CalcEngine
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
modrat(&lhsRat, rhsRat);
|
remrat(&lhsRat, rhsRat);
|
||||||
destroyrat(rhsRat);
|
destroyrat(rhsRat);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (uint32_t error)
|
||||||
{
|
{
|
||||||
destroyrat(lhsRat);
|
destroyrat(lhsRat);
|
||||||
destroyrat(rhsRat);
|
destroyrat(rhsRat);
|
||||||
|
@ -215,7 +225,7 @@ namespace CalcEngine
|
||||||
lshrat(&lhsRat, rhsRat, RATIONAL_BASE, RATIONAL_PRECISION);
|
lshrat(&lhsRat, rhsRat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
destroyrat(rhsRat);
|
destroyrat(rhsRat);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (uint32_t error)
|
||||||
{
|
{
|
||||||
destroyrat(lhsRat);
|
destroyrat(lhsRat);
|
||||||
destroyrat(rhsRat);
|
destroyrat(rhsRat);
|
||||||
|
@ -238,7 +248,7 @@ namespace CalcEngine
|
||||||
rshrat(&lhsRat, rhsRat, RATIONAL_BASE, RATIONAL_PRECISION);
|
rshrat(&lhsRat, rhsRat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
destroyrat(rhsRat);
|
destroyrat(rhsRat);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (uint32_t error)
|
||||||
{
|
{
|
||||||
destroyrat(lhsRat);
|
destroyrat(lhsRat);
|
||||||
destroyrat(rhsRat);
|
destroyrat(rhsRat);
|
||||||
|
@ -261,7 +271,7 @@ namespace CalcEngine
|
||||||
andrat(&lhsRat, rhsRat, RATIONAL_BASE, RATIONAL_PRECISION);
|
andrat(&lhsRat, rhsRat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
destroyrat(rhsRat);
|
destroyrat(rhsRat);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (uint32_t error)
|
||||||
{
|
{
|
||||||
destroyrat(lhsRat);
|
destroyrat(lhsRat);
|
||||||
destroyrat(rhsRat);
|
destroyrat(rhsRat);
|
||||||
|
@ -283,7 +293,7 @@ namespace CalcEngine
|
||||||
orrat(&lhsRat, rhsRat, RATIONAL_BASE, RATIONAL_PRECISION);
|
orrat(&lhsRat, rhsRat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
destroyrat(rhsRat);
|
destroyrat(rhsRat);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (uint32_t error)
|
||||||
{
|
{
|
||||||
destroyrat(lhsRat);
|
destroyrat(lhsRat);
|
||||||
destroyrat(rhsRat);
|
destroyrat(rhsRat);
|
||||||
|
@ -305,7 +315,7 @@ namespace CalcEngine
|
||||||
xorrat(&lhsRat, rhsRat, RATIONAL_BASE, RATIONAL_PRECISION);
|
xorrat(&lhsRat, rhsRat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
destroyrat(rhsRat);
|
destroyrat(rhsRat);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (uint32_t error)
|
||||||
{
|
{
|
||||||
destroyrat(lhsRat);
|
destroyrat(lhsRat);
|
||||||
destroyrat(rhsRat);
|
destroyrat(rhsRat);
|
||||||
|
@ -342,6 +352,13 @@ namespace CalcEngine
|
||||||
return lhs;
|
return lhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calculate the remainder after division, the sign of a result will match the sign of lhs.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This function has the same behavior as the standard C/C++ operator '%', to calculate the modulus after division instead, use <see
|
||||||
|
/// cref="Rational::operator%"/> instead.
|
||||||
|
/// </remarks>
|
||||||
Rational operator%(Rational lhs, Rational const& rhs)
|
Rational operator%(Rational lhs, Rational const& rhs)
|
||||||
{
|
{
|
||||||
lhs %= rhs;
|
lhs %= rhs;
|
||||||
|
@ -388,7 +405,7 @@ namespace CalcEngine
|
||||||
{
|
{
|
||||||
result = rat_equ(lhsRat, rhsRat, RATIONAL_PRECISION);
|
result = rat_equ(lhsRat, rhsRat, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (uint32_t error)
|
||||||
{
|
{
|
||||||
destroyrat(lhsRat);
|
destroyrat(lhsRat);
|
||||||
destroyrat(rhsRat);
|
destroyrat(rhsRat);
|
||||||
|
@ -416,7 +433,7 @@ namespace CalcEngine
|
||||||
{
|
{
|
||||||
result = rat_lt(lhsRat, rhsRat, RATIONAL_PRECISION);
|
result = rat_lt(lhsRat, rhsRat, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (uint32_t error)
|
||||||
{
|
{
|
||||||
destroyrat(lhsRat);
|
destroyrat(lhsRat);
|
||||||
destroyrat(rhsRat);
|
destroyrat(rhsRat);
|
||||||
|
@ -453,7 +470,7 @@ namespace CalcEngine
|
||||||
{
|
{
|
||||||
result = RatToString(rat, fmt, radix, precision);
|
result = RatToString(rat, fmt, radix, precision);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (uint32_t error)
|
||||||
{
|
{
|
||||||
destroyrat(rat);
|
destroyrat(rat);
|
||||||
throw(error);
|
throw(error);
|
||||||
|
@ -470,9 +487,9 @@ namespace CalcEngine
|
||||||
uint64_t result;
|
uint64_t result;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
result = rattoUlonglong(rat, RATIONAL_BASE, RATIONAL_PRECISION);
|
result = rattoUi64(rat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (uint32_t error)
|
||||||
{
|
{
|
||||||
destroyrat(rat);
|
destroyrat(rat);
|
||||||
throw(error);
|
throw(error);
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
#include "Header Files/RationalMath.h"
|
#include "Header Files/RationalMath.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -14,7 +13,7 @@ Rational RationalMath::Frac(Rational const& rat)
|
||||||
{
|
{
|
||||||
fracrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
fracrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (uint32_t error)
|
||||||
{
|
{
|
||||||
destroyrat(prat);
|
destroyrat(prat);
|
||||||
throw(error);
|
throw(error);
|
||||||
|
@ -33,7 +32,7 @@ Rational RationalMath::Integer(Rational const& rat)
|
||||||
{
|
{
|
||||||
intrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
intrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (uint32_t error)
|
||||||
{
|
{
|
||||||
destroyrat(prat);
|
destroyrat(prat);
|
||||||
throw(error);
|
throw(error);
|
||||||
|
@ -55,7 +54,7 @@ Rational RationalMath::Pow(Rational const& base, Rational const& pow)
|
||||||
powrat(&baseRat, powRat, RATIONAL_BASE, RATIONAL_PRECISION);
|
powrat(&baseRat, powRat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
destroyrat(powRat);
|
destroyrat(powRat);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (uint32_t error)
|
||||||
{
|
{
|
||||||
destroyrat(baseRat);
|
destroyrat(baseRat);
|
||||||
destroyrat(powRat);
|
destroyrat(powRat);
|
||||||
|
@ -81,7 +80,7 @@ Rational RationalMath::Fact(Rational const& rat)
|
||||||
{
|
{
|
||||||
factrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
factrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (uint32_t error)
|
||||||
{
|
{
|
||||||
destroyrat(prat);
|
destroyrat(prat);
|
||||||
throw(error);
|
throw(error);
|
||||||
|
@ -101,7 +100,7 @@ Rational RationalMath::Exp(Rational const& rat)
|
||||||
{
|
{
|
||||||
exprat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
exprat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (uint32_t error)
|
||||||
{
|
{
|
||||||
destroyrat(prat);
|
destroyrat(prat);
|
||||||
throw(error);
|
throw(error);
|
||||||
|
@ -121,7 +120,7 @@ Rational RationalMath::Log(Rational const& rat)
|
||||||
{
|
{
|
||||||
lograt(&prat, RATIONAL_PRECISION);
|
lograt(&prat, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (uint32_t error)
|
||||||
{
|
{
|
||||||
destroyrat(prat);
|
destroyrat(prat);
|
||||||
throw(error);
|
throw(error);
|
||||||
|
@ -156,7 +155,7 @@ Rational RationalMath::Sin(Rational const& rat, ANGLE_TYPE angletype)
|
||||||
{
|
{
|
||||||
sinanglerat(&prat, angletype, RATIONAL_BASE, RATIONAL_PRECISION);
|
sinanglerat(&prat, angletype, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (uint32_t error)
|
||||||
{
|
{
|
||||||
destroyrat(prat);
|
destroyrat(prat);
|
||||||
throw(error);
|
throw(error);
|
||||||
|
@ -176,7 +175,7 @@ Rational RationalMath::Cos(Rational const& rat, ANGLE_TYPE angletype)
|
||||||
{
|
{
|
||||||
cosanglerat(&prat, angletype, RATIONAL_BASE, RATIONAL_PRECISION);
|
cosanglerat(&prat, angletype, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (uint32_t error)
|
||||||
{
|
{
|
||||||
destroyrat(prat);
|
destroyrat(prat);
|
||||||
throw(error);
|
throw(error);
|
||||||
|
@ -196,7 +195,7 @@ Rational RationalMath::Tan(Rational const& rat, ANGLE_TYPE angletype)
|
||||||
{
|
{
|
||||||
tananglerat(&prat, angletype, RATIONAL_BASE, RATIONAL_PRECISION);
|
tananglerat(&prat, angletype, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (uint32_t error)
|
||||||
{
|
{
|
||||||
destroyrat(prat);
|
destroyrat(prat);
|
||||||
throw(error);
|
throw(error);
|
||||||
|
@ -216,7 +215,7 @@ Rational RationalMath::ASin(Rational const& rat, ANGLE_TYPE angletype)
|
||||||
{
|
{
|
||||||
asinanglerat(&prat, angletype, RATIONAL_BASE, RATIONAL_PRECISION);
|
asinanglerat(&prat, angletype, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (uint32_t error)
|
||||||
{
|
{
|
||||||
destroyrat(prat);
|
destroyrat(prat);
|
||||||
throw(error);
|
throw(error);
|
||||||
|
@ -236,7 +235,7 @@ Rational RationalMath::ACos(Rational const& rat, ANGLE_TYPE angletype)
|
||||||
{
|
{
|
||||||
acosanglerat(&prat, angletype, RATIONAL_BASE, RATIONAL_PRECISION);
|
acosanglerat(&prat, angletype, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (uint32_t error)
|
||||||
{
|
{
|
||||||
destroyrat(prat);
|
destroyrat(prat);
|
||||||
throw(error);
|
throw(error);
|
||||||
|
@ -256,7 +255,7 @@ Rational RationalMath::ATan(Rational const& rat, ANGLE_TYPE angletype)
|
||||||
{
|
{
|
||||||
atananglerat(&prat, angletype, RATIONAL_BASE, RATIONAL_PRECISION);
|
atananglerat(&prat, angletype, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (uint32_t error)
|
||||||
{
|
{
|
||||||
destroyrat(prat);
|
destroyrat(prat);
|
||||||
throw(error);
|
throw(error);
|
||||||
|
@ -276,7 +275,7 @@ Rational RationalMath::Sinh(Rational const& rat)
|
||||||
{
|
{
|
||||||
sinhrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
sinhrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (uint32_t error)
|
||||||
{
|
{
|
||||||
destroyrat(prat);
|
destroyrat(prat);
|
||||||
throw(error);
|
throw(error);
|
||||||
|
@ -296,7 +295,7 @@ Rational RationalMath::Cosh(Rational const& rat)
|
||||||
{
|
{
|
||||||
coshrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
coshrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (uint32_t error)
|
||||||
{
|
{
|
||||||
destroyrat(prat);
|
destroyrat(prat);
|
||||||
throw(error);
|
throw(error);
|
||||||
|
@ -316,7 +315,7 @@ Rational RationalMath::Tanh(Rational const& rat)
|
||||||
{
|
{
|
||||||
tanhrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
tanhrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (uint32_t error)
|
||||||
{
|
{
|
||||||
destroyrat(prat);
|
destroyrat(prat);
|
||||||
throw(error);
|
throw(error);
|
||||||
|
@ -336,7 +335,7 @@ Rational RationalMath::ASinh(Rational const& rat)
|
||||||
{
|
{
|
||||||
asinhrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
asinhrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (uint32_t error)
|
||||||
{
|
{
|
||||||
destroyrat(prat);
|
destroyrat(prat);
|
||||||
throw(error);
|
throw(error);
|
||||||
|
@ -356,7 +355,7 @@ Rational RationalMath::ACosh(Rational const& rat)
|
||||||
{
|
{
|
||||||
acoshrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
acoshrat(&prat, RATIONAL_BASE, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (uint32_t error)
|
||||||
{
|
{
|
||||||
destroyrat(prat);
|
destroyrat(prat);
|
||||||
throw(error);
|
throw(error);
|
||||||
|
@ -376,7 +375,7 @@ Rational RationalMath::ATanh(Rational const& rat)
|
||||||
{
|
{
|
||||||
atanhrat(&prat, RATIONAL_PRECISION);
|
atanhrat(&prat, RATIONAL_PRECISION);
|
||||||
}
|
}
|
||||||
catch (DWORD error)
|
catch (uint32_t error)
|
||||||
{
|
{
|
||||||
destroyrat(prat);
|
destroyrat(prat);
|
||||||
throw(error);
|
throw(error);
|
||||||
|
@ -387,3 +386,33 @@ Rational RationalMath::ATanh(Rational const& rat)
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Calculate the modulus after division, the sign of the result will match the sign of b.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// When one of the operand is negative
|
||||||
|
/// the result will differ from the C/C++ operator '%'
|
||||||
|
/// use <see cref="Rational::operator%"/> instead to calculate the remainder after division.
|
||||||
|
/// </remarks>
|
||||||
|
Rational RationalMath::Mod(Rational const& a, Rational const& b)
|
||||||
|
{
|
||||||
|
PRAT prat = a.ToPRAT();
|
||||||
|
PRAT pn = b.ToPRAT();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
modrat(&prat, pn);
|
||||||
|
destroyrat(pn);
|
||||||
|
}
|
||||||
|
catch (uint32_t error)
|
||||||
|
{
|
||||||
|
destroyrat(prat);
|
||||||
|
destroyrat(pn);
|
||||||
|
throw(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto res = Rational{ prat };
|
||||||
|
destroyrat(prat);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
#include "pch.h"
|
#include <cassert>
|
||||||
#include "Header Files/CalcEngine.h"
|
#include "Header Files/CalcEngine.h"
|
||||||
|
|
||||||
#include "CalculatorResource.h"
|
#include "CalculatorResource.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -15,7 +14,7 @@ using namespace CalcEngine;
|
||||||
|
|
||||||
static constexpr int DEFAULT_MAX_DIGITS = 32;
|
static constexpr int DEFAULT_MAX_DIGITS = 32;
|
||||||
static constexpr int DEFAULT_PRECISION = 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_DEC_SEPARATOR = L'.';
|
||||||
static constexpr wchar_t DEFAULT_GRP_SEPARATOR = L',';
|
static constexpr wchar_t DEFAULT_GRP_SEPARATOR = L',';
|
||||||
|
@ -25,13 +24,18 @@ static constexpr wstring_view DEFAULT_NUMBER_STR = L"0";
|
||||||
// Read strings for keys, errors, trig types, etc.
|
// Read strings for keys, errors, trig types, etc.
|
||||||
// These will be copied from the resources to local memory.
|
// These will be copied from the resources to local memory.
|
||||||
|
|
||||||
array<wstring, CSTRINGSENGMAX> CCalcEngine::s_engineStrings;
|
unordered_map<wstring, wstring> CCalcEngine::s_engineStrings;
|
||||||
|
|
||||||
void CCalcEngine::LoadEngineStrings(CalculationManager::IResourceProvider& resourceProvider)
|
void CCalcEngine::LoadEngineStrings(CalculationManager::IResourceProvider& resourceProvider)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < s_engineStrings.size(); i++)
|
for (const auto& sid : g_sids)
|
||||||
{
|
{
|
||||||
s_engineStrings[i] = resourceProvider.GetCEngineString(g_sids[i]);
|
auto locKey = wstring{ sid };
|
||||||
|
auto locString = resourceProvider.GetCEngineString(locKey);
|
||||||
|
if (!locString.empty())
|
||||||
|
{
|
||||||
|
s_engineStrings[locKey] = locString;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,42 +58,47 @@ void CCalcEngine::InitialOneTimeOnlySetup(CalculationManager::IResourceProvider&
|
||||||
// CCalcEngine::CCalcEngine
|
// CCalcEngine::CCalcEngine
|
||||||
//
|
//
|
||||||
//////////////////////////////////////////////////
|
//////////////////////////////////////////////////
|
||||||
CCalcEngine::CCalcEngine(bool fPrecedence, bool fIntegerMode, CalculationManager::IResourceProvider* const pResourceProvider, __in_opt ICalcDisplay *pCalcDisplay, __in_opt shared_ptr<IHistoryDisplay> pHistoryDisplay) :
|
CCalcEngine::CCalcEngine(
|
||||||
m_fPrecedence(fPrecedence),
|
bool fPrecedence,
|
||||||
m_fIntegerMode(fIntegerMode),
|
bool fIntegerMode,
|
||||||
m_pCalcDisplay(pCalcDisplay),
|
CalculationManager::IResourceProvider* const pResourceProvider,
|
||||||
m_resourceProvider(pResourceProvider),
|
__in_opt ICalcDisplay* pCalcDisplay,
|
||||||
m_nOpCode(0),
|
__in_opt shared_ptr<IHistoryDisplay> pHistoryDisplay)
|
||||||
m_nPrevOpCode(0),
|
: m_fPrecedence(fPrecedence)
|
||||||
m_bChangeOp(false),
|
, m_fIntegerMode(fIntegerMode)
|
||||||
m_bRecord(false),
|
, m_pCalcDisplay(pCalcDisplay)
|
||||||
m_bSetCalcState(false),
|
, m_resourceProvider(pResourceProvider)
|
||||||
m_input(DEFAULT_DEC_SEPARATOR),
|
, m_nOpCode(0)
|
||||||
m_nFE(FMT_FLOAT),
|
, m_nPrevOpCode(0)
|
||||||
m_memoryValue{ make_unique<Rational>() },
|
, m_bChangeOp(false)
|
||||||
m_holdVal{},
|
, m_bRecord(false)
|
||||||
m_currentVal{},
|
, m_bSetCalcState(false)
|
||||||
m_lastVal{},
|
, m_input(DEFAULT_DEC_SEPARATOR)
|
||||||
m_parenVals{},
|
, m_nFE(FMT_FLOAT)
|
||||||
m_precedenceVals{},
|
, m_memoryValue{ make_unique<Rational>() }
|
||||||
m_bError(false),
|
, m_holdVal{}
|
||||||
m_bInv(false),
|
, m_currentVal{}
|
||||||
m_bNoPrevEqu(true),
|
, m_lastVal{}
|
||||||
m_radix(DEFAULT_RADIX),
|
, m_parenVals{}
|
||||||
m_precision(DEFAULT_PRECISION),
|
, m_precedenceVals{}
|
||||||
m_cIntDigitsSav(DEFAULT_MAX_DIGITS),
|
, m_bError(false)
|
||||||
m_decGrouping(),
|
, m_bInv(false)
|
||||||
m_numberString(DEFAULT_NUMBER_STR),
|
, m_bNoPrevEqu(true)
|
||||||
m_nTempCom(0),
|
, m_radix(DEFAULT_RADIX)
|
||||||
m_openParenCount(0),
|
, m_precision(DEFAULT_PRECISION)
|
||||||
m_nOp(),
|
, m_cIntDigitsSav(DEFAULT_MAX_DIGITS)
|
||||||
m_nPrecOp(),
|
, m_decGrouping()
|
||||||
m_precedenceOpCount(0),
|
, m_numberString(DEFAULT_NUMBER_STR)
|
||||||
m_nLastCom(0),
|
, m_nTempCom(0)
|
||||||
m_angletype(ANGLE_DEG),
|
, m_openParenCount(0)
|
||||||
m_numwidth(QWORD_WIDTH),
|
, m_nOp()
|
||||||
m_HistoryCollector(pCalcDisplay, pHistoryDisplay, DEFAULT_DEC_SEPARATOR),
|
, m_nPrecOp()
|
||||||
m_groupSeparator(DEFAULT_GRP_SEPARATOR)
|
, m_precedenceOpCount(0)
|
||||||
|
, m_nLastCom(0)
|
||||||
|
, m_angletype(ANGLE_DEG)
|
||||||
|
, m_numwidth(QWORD_WIDTH)
|
||||||
|
, m_HistoryCollector(pCalcDisplay, pHistoryDisplay, DEFAULT_DEC_SEPARATOR)
|
||||||
|
, m_groupSeparator(DEFAULT_GRP_SEPARATOR)
|
||||||
{
|
{
|
||||||
InitChopNumbers();
|
InitChopNumbers();
|
||||||
|
|
||||||
|
@ -168,7 +177,7 @@ void CCalcEngine::SettingsChanged()
|
||||||
m_HistoryCollector.SetDecimalSymbol(m_decimalSeparator);
|
m_HistoryCollector.SetDecimalSymbol(m_decimalSeparator);
|
||||||
|
|
||||||
// put the new decimal symbol into the table used to draw the decimal key
|
// put the new decimal symbol into the table used to draw the decimal key
|
||||||
s_engineStrings[IDS_DECIMAL] = m_decimalSeparator;
|
s_engineStrings[SIDS_DECIMAL_SEPARATOR] = m_decimalSeparator;
|
||||||
|
|
||||||
// we need to redraw to update the decimal point button
|
// we need to redraw to update the decimal point button
|
||||||
numChanged = true;
|
numChanged = true;
|
||||||
|
|
|
@ -12,53 +12,48 @@
|
||||||
*
|
*
|
||||||
* Author:
|
* Author:
|
||||||
\****************************************************************************/
|
\****************************************************************************/
|
||||||
#include "pch.h"
|
|
||||||
|
#include <string>
|
||||||
#include "Header Files/CalcEngine.h"
|
#include "Header Files/CalcEngine.h"
|
||||||
#include "Header Files/CalcUtils.h"
|
#include "Header Files/CalcUtils.h"
|
||||||
|
|
||||||
#define IDC_RADSIN IDC_UNARYLAST+1
|
|
||||||
#define IDC_RADCOS IDC_UNARYLAST+2
|
|
||||||
#define IDC_RADTAN IDC_UNARYLAST+3
|
|
||||||
#define IDC_GRADSIN IDC_UNARYLAST+4
|
|
||||||
#define IDC_GRADCOS IDC_UNARYLAST+5
|
|
||||||
#define IDC_GRADTAN IDC_UNARYLAST+6
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace CalcEngine;
|
using namespace CalcEngine;
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
// NPrecedenceOfOp
|
// NPrecedenceOfOp
|
||||||
//
|
//
|
||||||
// returns a virtual number for precedence for the operator. We expect binary operator only, otherwise the lowest number
|
// returns a virtual number for precedence for the operator. We expect binary operator only, otherwise the lowest number
|
||||||
// 0 is returned. Higher the number, higher the precedence of the operator.
|
// 0 is returned. Higher the number, higher the precedence of the operator.
|
||||||
INT NPrecedenceOfOp(int nopCode)
|
int NPrecedenceOfOp(int nopCode)
|
||||||
{
|
{
|
||||||
static BYTE rgbPrec[] = { 0,0, IDC_OR,0, IDC_XOR,0, IDC_AND,1,
|
static uint8_t rgbPrec[] = { 0, 0, IDC_OR, 0, IDC_XOR, 0, IDC_AND, 1, IDC_ADD, 2, IDC_SUB, 2, IDC_RSHF,
|
||||||
IDC_ADD,2, IDC_SUB,2, IDC_RSHF,3, IDC_LSHF,3,
|
3, IDC_LSHF, 3, IDC_MOD, 3, IDC_DIV, 3, IDC_MUL, 3, IDC_PWR, 4, IDC_ROOT, 4 };
|
||||||
IDC_MOD,3, IDC_DIV,3, IDC_MUL,3, IDC_PWR,4, IDC_ROOT, 4 };
|
unsigned int iPrec;
|
||||||
int iPrec;
|
|
||||||
|
|
||||||
iPrec = 0;
|
iPrec = 0;
|
||||||
while ((iPrec < ARRAYSIZE(rgbPrec)) && (nopCode != rgbPrec[iPrec]))
|
while ((iPrec < size(rgbPrec)) && (nopCode != rgbPrec[iPrec]))
|
||||||
{
|
{
|
||||||
iPrec += 2;
|
iPrec += 2;
|
||||||
}
|
}
|
||||||
if (iPrec >= ARRAYSIZE(rgbPrec))
|
if (iPrec >= size(rgbPrec))
|
||||||
{
|
{
|
||||||
iPrec = 0;
|
iPrec = 0;
|
||||||
}
|
}
|
||||||
return rgbPrec[iPrec + 1];
|
return rgbPrec[iPrec + 1];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleErrorCommand
|
// 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.
|
// 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))
|
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;
|
m_nTempCom = m_nLastCom;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,7 +76,7 @@ void CCalcEngine::ClearTemporaryValues()
|
||||||
m_bError = false;
|
m_bError = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCalcEngine::ProcessCommand(WPARAM wParam)
|
void CCalcEngine::ProcessCommand(OpCode wParam)
|
||||||
{
|
{
|
||||||
if (wParam == IDC_SET_RESULT)
|
if (wParam == IDC_SET_RESULT)
|
||||||
{
|
{
|
||||||
|
@ -92,9 +87,9 @@ void CCalcEngine::ProcessCommand(WPARAM wParam)
|
||||||
ProcessCommandWorker(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
|
// Save the last command. Some commands are not saved in this manor, these
|
||||||
// commands are:
|
// commands are:
|
||||||
|
@ -105,7 +100,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
||||||
if (!IsGuiSettingOpCode(wParam))
|
if (!IsGuiSettingOpCode(wParam))
|
||||||
{
|
{
|
||||||
m_nLastCom = m_nTempCom;
|
m_nLastCom = m_nTempCom;
|
||||||
m_nTempCom = (INT)wParam;
|
m_nTempCom = (int)wParam;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_bError)
|
if (m_bError)
|
||||||
|
@ -129,14 +124,9 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
||||||
// Toggle Record/Display mode if appropriate.
|
// Toggle Record/Display mode if appropriate.
|
||||||
if (m_bRecord)
|
if (m_bRecord)
|
||||||
{
|
{
|
||||||
if (IsOpInRange(wParam, IDC_AND, IDC_MMINUS) ||
|
if (IsOpInRange(wParam, IDC_AND, IDC_MMINUS) || IsOpInRange(wParam, IDC_OPENP, IDC_CLOSEP) || IsOpInRange(wParam, IDM_HEX, IDM_BIN)
|
||||||
IsOpInRange(wParam, IDC_OPENP, IDC_CLOSEP) ||
|
|| IsOpInRange(wParam, IDM_QWORD, IDM_BYTE) || IsOpInRange(wParam, IDM_DEG, IDM_GRAD)
|
||||||
IsOpInRange(wParam, IDM_HEX, IDM_BIN) ||
|
|| IsOpInRange(wParam, IDC_BINEDITSTART, IDC_BINEDITSTART + 63) || (IDC_INV == wParam) || (IDC_SIGN == wParam && 10 != m_radix))
|
||||||
IsOpInRange(wParam, IDM_QWORD, IDM_BYTE) ||
|
|
||||||
IsOpInRange(wParam, IDM_DEG, IDM_GRAD) ||
|
|
||||||
IsOpInRange(wParam, IDC_BINEDITSTART, IDC_BINEDITSTART + 63) ||
|
|
||||||
(IDC_INV == wParam) ||
|
|
||||||
(IDC_SIGN == wParam && 10 != m_radix))
|
|
||||||
{
|
{
|
||||||
m_bRecord = false;
|
m_bRecord = false;
|
||||||
m_currentVal = m_input.ToRational(m_radix, m_precision);
|
m_currentVal = m_input.ToRational(m_radix, m_precision);
|
||||||
|
@ -180,13 +170,13 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
||||||
// BINARY OPERATORS:
|
// BINARY OPERATORS:
|
||||||
if (IsBinOpCode(wParam))
|
if (IsBinOpCode(wParam))
|
||||||
{
|
{
|
||||||
/* Change the operation if last input was operation. */
|
// Change the operation if last input was operation.
|
||||||
if (IsBinOpCode(m_nLastCom))
|
if (IsBinOpCode(m_nLastCom))
|
||||||
{
|
{
|
||||||
INT nPrev;
|
int nPrev;
|
||||||
bool fPrecInvToHigher = false; // Is Precedence Inversion from lower to higher precedence happening ??
|
bool fPrecInvToHigher = false; // Is Precedence Inversion from lower to higher precedence happening ??
|
||||||
|
|
||||||
m_nOpCode = (INT)wParam;
|
m_nOpCode = (int)wParam;
|
||||||
|
|
||||||
// Check to see if by changing this binop, a Precedence inversion is happening.
|
// Check to see if by changing this binop, a Precedence inversion is happening.
|
||||||
// Eg. 1 * 2 + and + is getting changed to ^. The previous precedence rules would have already computed
|
// Eg. 1 * 2 + and + is getting changed to ^. The previous precedence rules would have already computed
|
||||||
|
@ -276,14 +266,13 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
||||||
m_HistoryCollector.PopLastOpndStart();
|
m_HistoryCollector.PopLastOpndStart();
|
||||||
goto DoPrecedenceCheckAgain;
|
goto DoPrecedenceCheckAgain;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DisplayAnnounceBinaryOperator();
|
DisplayAnnounceBinaryOperator();
|
||||||
|
|
||||||
m_lastVal = m_currentVal;
|
m_lastVal = m_currentVal;
|
||||||
m_nOpCode = (INT)wParam;
|
m_nOpCode = (int)wParam;
|
||||||
m_HistoryCollector.AddBinOpToHistory(m_nOpCode);
|
m_HistoryCollector.AddBinOpToHistory(m_nOpCode);
|
||||||
m_bNoPrevEqu = m_bChangeOp = true;
|
m_bNoPrevEqu = m_bChangeOp = true;
|
||||||
return;
|
return;
|
||||||
|
@ -311,7 +300,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
||||||
m_HistoryCollector.AddOpndToHistory(m_numberString, m_currentVal);
|
m_HistoryCollector.AddOpndToHistory(m_numberString, m_currentVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_HistoryCollector.AddUnaryOpToHistory((INT)wParam, m_bInv, m_angletype);
|
m_HistoryCollector.AddUnaryOpToHistory((int)wParam, m_bInv, m_angletype);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((wParam == IDC_SIN) || (wParam == IDC_COS) || (wParam == IDC_TAN) || (wParam == IDC_SINH) || (wParam == IDC_COSH) || (wParam == IDC_TANH))
|
if ((wParam == IDC_SIN) || (wParam == IDC_COS) || (wParam == IDC_TAN) || (wParam == IDC_SINH) || (wParam == IDC_COSH) || (wParam == IDC_TANH))
|
||||||
|
@ -324,7 +313,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_currentVal = SciCalcFunctions(m_currentVal, (DWORD)wParam);
|
m_currentVal = SciCalcFunctions(m_currentVal, (uint32_t)wParam);
|
||||||
|
|
||||||
if (m_bError)
|
if (m_bError)
|
||||||
return;
|
return;
|
||||||
|
@ -341,11 +330,9 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
||||||
/* reset the m_bInv flag and indicators if it is set
|
/* reset the m_bInv flag and indicators if it is set
|
||||||
and have been used */
|
and have been used */
|
||||||
|
|
||||||
if (m_bInv &&
|
if (m_bInv
|
||||||
((wParam == IDC_CHOP) ||
|
&& ((wParam == IDC_CHOP) || (wParam == IDC_SIN) || (wParam == IDC_COS) || (wParam == IDC_TAN) || (wParam == IDC_LN) || (wParam == IDC_DMS)
|
||||||
(wParam == IDC_SIN) || (wParam == IDC_COS) || (wParam == IDC_TAN) ||
|
|| (wParam == IDC_DEGREES) || (wParam == IDC_SINH) || (wParam == IDC_COSH) || (wParam == IDC_TANH)))
|
||||||
(wParam == IDC_LN) || (wParam == IDC_DMS) || (wParam == IDC_DEGREES) ||
|
|
||||||
(wParam == IDC_SINH) || (wParam == IDC_COSH) || (wParam == IDC_TANH)))
|
|
||||||
{
|
{
|
||||||
m_bInv = false;
|
m_bInv = false;
|
||||||
}
|
}
|
||||||
|
@ -364,7 +351,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
||||||
|
|
||||||
CheckAndAddLastBinOpToHistory();
|
CheckAndAddLastBinOpToHistory();
|
||||||
|
|
||||||
if (TryToggleBit(m_currentVal, (DWORD)wParam - IDC_BINEDITSTART))
|
if (TryToggleBit(m_currentVal, (uint32_t)wParam - IDC_BINEDITSTART))
|
||||||
{
|
{
|
||||||
DisplayNum();
|
DisplayNum();
|
||||||
}
|
}
|
||||||
|
@ -390,13 +377,13 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
||||||
m_nPrevOpCode = 0;
|
m_nPrevOpCode = 0;
|
||||||
m_bNoPrevEqu = true;
|
m_bNoPrevEqu = true;
|
||||||
|
|
||||||
|
|
||||||
/* clear the parenthesis status box indicator, this will not be
|
/* clear the parenthesis status box indicator, this will not be
|
||||||
cleared for CENTR */
|
cleared for CENTR */
|
||||||
if (nullptr != m_pCalcDisplay)
|
if (nullptr != m_pCalcDisplay)
|
||||||
{
|
{
|
||||||
m_pCalcDisplay->SetParenDisplayText(L"");
|
m_pCalcDisplay->SetParenthesisNumber(0);
|
||||||
m_pCalcDisplay->SetExpressionDisplay(make_shared<CalculatorVector<pair<wstring, int>>>(), make_shared<CalculatorVector<shared_ptr<IExpressionCommand>>>());
|
m_pCalcDisplay->SetExpressionDisplay(
|
||||||
|
make_shared<CalculatorVector<pair<wstring, int>>>(), make_shared<CalculatorVector<shared_ptr<IExpressionCommand>>>());
|
||||||
}
|
}
|
||||||
|
|
||||||
m_HistoryCollector.ClearHistoryLine(wstring());
|
m_HistoryCollector.ClearHistoryLine(wstring());
|
||||||
|
@ -440,7 +427,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
|
m_nTempCom = m_nLastCom; // Put back this last saved command to the prev state so ) can be handled properly
|
||||||
ProcessCommand(IDC_CLOSEP);
|
ProcessCommand(IDC_CLOSEP);
|
||||||
m_nLastCom = m_nTempCom; // Actually this is IDC_CLOSEP
|
m_nLastCom = m_nTempCom; // Actually this is IDC_CLOSEP
|
||||||
m_nTempCom = (INT)wParam; // put back in the state where last op seen was IDC_CLOSEP, and current op is IDC_EQU
|
m_nTempCom = (int)wParam; // put back in the state where last op seen was IDC_CLOSEP, and current op is IDC_EQU
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_bNoPrevEqu)
|
if (!m_bNoPrevEqu)
|
||||||
|
@ -461,45 +448,12 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
||||||
m_HistoryCollector.AddOpndToHistory(m_numberString, m_currentVal);
|
m_HistoryCollector.AddOpndToHistory(m_numberString, m_currentVal);
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
// Evaluate the precedence stack.
|
||||||
|
ResolveHighestPrecedenceOperation();
|
||||||
if (m_nOpCode) /* Is there a valid operation around? */
|
while (m_fPrecedence && m_precedenceOpCount > 0)
|
||||||
{
|
{
|
||||||
/* If this is the first EQU in a string, set m_holdVal=m_currentVal */
|
m_precedenceOpCount--;
|
||||||
/* Otherwise let m_currentVal=m_holdVal. This keeps m_currentVal constant */
|
m_nOpCode = m_nPrecOp[m_precedenceOpCount];
|
||||||
/* through all EQUs in a row. */
|
|
||||||
if (m_bNoPrevEqu)
|
|
||||||
{
|
|
||||||
m_holdVal = m_currentVal;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_currentVal = m_holdVal;
|
|
||||||
DisplayNum(); // to update the m_numberString
|
|
||||||
m_HistoryCollector.AddBinOpToHistory(m_nOpCode, false);
|
|
||||||
m_HistoryCollector.AddOpndToHistory(m_numberString, m_currentVal); // Adding the repeated last op to history
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do the current or last operation.
|
|
||||||
m_currentVal = DoOperation(m_nOpCode, m_currentVal, m_lastVal);
|
|
||||||
m_nPrevOpCode = m_nOpCode;
|
|
||||||
m_lastVal = m_currentVal;
|
|
||||||
|
|
||||||
/* Check for errors. If this wasn't done, DisplayNum */
|
|
||||||
/* would immediately overwrite any error message. */
|
|
||||||
if (!m_bError)
|
|
||||||
DisplayNum();
|
|
||||||
|
|
||||||
/* No longer the first EQU. */
|
|
||||||
m_bNoPrevEqu = false;
|
|
||||||
}
|
|
||||||
else if (!m_bError)
|
|
||||||
DisplayNum();
|
|
||||||
|
|
||||||
if (m_precedenceOpCount == 0 || !m_fPrecedence)
|
|
||||||
break;
|
|
||||||
|
|
||||||
m_nOpCode = m_nPrecOp[--m_precedenceOpCount];
|
|
||||||
m_lastVal = m_precedenceVals[m_precedenceOpCount];
|
m_lastVal = m_precedenceVals[m_precedenceOpCount];
|
||||||
|
|
||||||
// Precedence Inversion check
|
// Precedence Inversion check
|
||||||
|
@ -512,7 +466,9 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
||||||
m_HistoryCollector.PopLastOpndStart();
|
m_HistoryCollector.PopLastOpndStart();
|
||||||
|
|
||||||
m_bNoPrevEqu = true;
|
m_bNoPrevEqu = true;
|
||||||
} while (m_precedenceOpCount >= 0);
|
|
||||||
|
ResolveHighestPrecedenceOperation();
|
||||||
|
}
|
||||||
|
|
||||||
if (!m_bError)
|
if (!m_bError)
|
||||||
{
|
{
|
||||||
|
@ -520,7 +476,8 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
||||||
m_HistoryCollector.CompleteHistoryLine(groupedString);
|
m_HistoryCollector.CompleteHistoryLine(groupedString);
|
||||||
if (nullptr != m_pCalcDisplay)
|
if (nullptr != m_pCalcDisplay)
|
||||||
{
|
{
|
||||||
m_pCalcDisplay->SetExpressionDisplay(make_shared<CalculatorVector<pair<wstring, int>>>(), make_shared<CalculatorVector<shared_ptr<IExpressionCommand>>>());
|
m_pCalcDisplay->SetExpressionDisplay(
|
||||||
|
make_shared<CalculatorVector<pair<wstring, int>>>(), make_shared<CalculatorVector<shared_ptr<IExpressionCommand>>>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -544,6 +501,11 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
||||||
if ((m_openParenCount >= MAXPRECDEPTH && nx) || (!m_openParenCount && !nx)
|
if ((m_openParenCount >= MAXPRECDEPTH && nx) || (!m_openParenCount && !nx)
|
||||||
|| ((m_precedenceOpCount >= MAXPRECDEPTH && m_nPrecOp[m_precedenceOpCount - 1] != 0)))
|
|| ((m_precedenceOpCount >= MAXPRECDEPTH && m_nPrecOp[m_precedenceOpCount - 1] != 0)))
|
||||||
{
|
{
|
||||||
|
if (!m_openParenCount && !nx)
|
||||||
|
{
|
||||||
|
m_pCalcDisplay->OnNoRightParenAdded();
|
||||||
|
}
|
||||||
|
|
||||||
HandleErrorCommand(wParam);
|
HandleErrorCommand(wParam);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -625,7 +587,7 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
||||||
// Set the "(=xx" indicator.
|
// Set the "(=xx" indicator.
|
||||||
if (nullptr != m_pCalcDisplay)
|
if (nullptr != m_pCalcDisplay)
|
||||||
{
|
{
|
||||||
m_pCalcDisplay->SetParenDisplayText(m_openParenCount ? to_wstring(m_openParenCount) : L"");
|
m_pCalcDisplay->SetParenthesisNumber(m_openParenCount >= 0 ? static_cast<unsigned int>(m_openParenCount) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_bError)
|
if (!m_bError)
|
||||||
|
@ -779,7 +741,48 @@ void CCalcEngine::ProcessCommandWorker(WPARAM wParam)
|
||||||
m_bInv = !m_bInv;
|
m_bInv = !m_bInv;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper function to resolve one item on the precedence stack.
|
||||||
|
void CCalcEngine::ResolveHighestPrecedenceOperation()
|
||||||
|
{
|
||||||
|
// Is there a valid operation around?
|
||||||
|
if (m_nOpCode)
|
||||||
|
{
|
||||||
|
// If this is the first EQU in a string, set m_holdVal=m_currentVal
|
||||||
|
// Otherwise let m_currentVal=m_holdVal. This keeps m_currentVal constant
|
||||||
|
// through all EQUs in a row.
|
||||||
|
if (m_bNoPrevEqu)
|
||||||
|
{
|
||||||
|
m_holdVal = m_currentVal;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_currentVal = m_holdVal;
|
||||||
|
DisplayNum(); // to update the m_numberString
|
||||||
|
m_HistoryCollector.AddBinOpToHistory(m_nOpCode, false);
|
||||||
|
m_HistoryCollector.AddOpndToHistory(m_numberString, m_currentVal); // Adding the repeated last op to history
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do the current or last operation.
|
||||||
|
m_currentVal = DoOperation(m_nOpCode, m_currentVal, m_lastVal);
|
||||||
|
m_nPrevOpCode = m_nOpCode;
|
||||||
|
m_lastVal = m_currentVal;
|
||||||
|
|
||||||
|
// Check for errors. If this wasn't done, DisplayNum
|
||||||
|
// would immediately overwrite any error message.
|
||||||
|
if (!m_bError)
|
||||||
|
{
|
||||||
|
DisplayNum();
|
||||||
|
}
|
||||||
|
|
||||||
|
// No longer the first EQU.
|
||||||
|
m_bNoPrevEqu = false;
|
||||||
|
}
|
||||||
|
else if (!m_bError)
|
||||||
|
{
|
||||||
|
DisplayNum();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckAndAddLastBinOpToHistory
|
// CheckAndAddLastBinOpToHistory
|
||||||
|
@ -802,7 +805,6 @@ void CCalcEngine::CheckAndAddLastBinOpToHistory(bool addToHistory)
|
||||||
// So erase the last operand
|
// So erase the last operand
|
||||||
m_HistoryCollector.RemoveLastOpndFromHistory();
|
m_HistoryCollector.RemoveLastOpndFromHistory();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (m_HistoryCollector.FOpndAddedToHistory() && !m_bError)
|
else if (m_HistoryCollector.FOpndAddedToHistory() && !m_bError)
|
||||||
{
|
{
|
||||||
|
@ -811,8 +813,7 @@ void CCalcEngine::CheckAndAddLastBinOpToHistory(bool addToHistory)
|
||||||
// Let us make a current value =. So in case of 4 SQRT (or a equation under braces) and then a new equation is started, we can just form
|
// Let us make a current value =. So in case of 4 SQRT (or a equation under braces) and then a new equation is started, we can just form
|
||||||
// a useful equation of sqrt(4) = 2 and continue a new equation from now on. But no point in doing this for things like
|
// a useful equation of sqrt(4) = 2 and continue a new equation from now on. But no point in doing this for things like
|
||||||
// MR, SUM etc. All you will get is 5 = 5 kind of no useful equation.
|
// MR, SUM etc. All you will get is 5 = 5 kind of no useful equation.
|
||||||
if ((IsUnaryOpCode(m_nLastCom) || IDC_SIGN == m_nLastCom || IDC_CLOSEP == m_nLastCom) &&
|
if ((IsUnaryOpCode(m_nLastCom) || IDC_SIGN == m_nLastCom || IDC_CLOSEP == m_nLastCom) && 0 == m_openParenCount)
|
||||||
0 == m_openParenCount)
|
|
||||||
{
|
{
|
||||||
if (addToHistory)
|
if (addToHistory)
|
||||||
{
|
{
|
||||||
|
@ -850,155 +851,93 @@ void CCalcEngine::DisplayAnnounceBinaryOperator()
|
||||||
// Unary operator Function Name table Element
|
// 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.
|
// we have this separate table to get its localized name and for its Inv function if it exists.
|
||||||
typedef struct
|
struct FunctionNameElement
|
||||||
{
|
{
|
||||||
int idsFunc; // index of string for the unary op function. Can be NULL, in which case it same as button name
|
wstring degreeString; // Used by default if there are no rad or grad specific strings.
|
||||||
int idsFuncInv; // index of string for Inv of unary op. Can be NULL, in case it is same as idsFunc
|
wstring inverseDegreeString; // Will fall back to degreeString if empty
|
||||||
bool fDontUseInExpEval; // true if this cant be used in reverse direction as well, ie. during expression evaluation
|
|
||||||
} UFNE;
|
wstring radString;
|
||||||
|
wstring inverseRadString; // Will fall back to radString if empty
|
||||||
|
|
||||||
|
wstring gradString;
|
||||||
|
wstring inverseGradString; // Will fall back to gradString if empty
|
||||||
|
|
||||||
|
bool hasAngleStrings = ((!radString.empty()) || (!inverseRadString.empty()) || (!gradString.empty()) || (!inverseGradString.empty()));
|
||||||
|
};
|
||||||
|
|
||||||
// Table for each unary operator
|
// Table for each unary operator
|
||||||
static const UFNE rgUfne[] =
|
static const std::unordered_map<int, FunctionNameElement> unaryOperatorStringTable = {
|
||||||
{
|
{ IDC_CHOP, { L"", SIDS_FRAC } },
|
||||||
/* IDC_CHOP */{ 0, IDS_FRAC, false },
|
|
||||||
/* IDC_ROL */{ 0, 0, true },
|
|
||||||
/* IDC_ROR */{ 0, 0, true },
|
|
||||||
|
|
||||||
/* IDC_COM */{ 0, 0, true },
|
{ IDC_SIN, { SIDS_SIND, SIDS_ASIND, SIDS_SINR, SIDS_ASINR, SIDS_SING, SIDS_ASING } },
|
||||||
/* IDC_SIN */{ IDS_SIND, IDS_ASIND, false }, // default in this table is degrees for sin,cos & tan
|
{ IDC_COS, { SIDS_COSD, SIDS_ACOSD, SIDS_COSR, SIDS_ACOSR, SIDS_COSG, SIDS_ACOSG } },
|
||||||
/* IDC_COS */{ IDS_COSD, IDS_ACOSD, false },
|
{ IDC_TAN, { SIDS_TAND, SIDS_ATAND, SIDS_TANR, SIDS_ATANR, SIDS_TANG, SIDS_ATANG } },
|
||||||
/* IDC_TAN */{ IDS_TAND, IDS_ATAND, false },
|
|
||||||
|
|
||||||
/* IDC_SINH */{ 0, IDS_ASINH, false },
|
{ IDC_SINH, { L"", SIDS_ASINH } },
|
||||||
/* IDC_COSH */{ 0, IDS_ACOSH, false },
|
{ IDC_COSH, { L"", SIDS_ACOSH } },
|
||||||
/* IDC_TANH */{ 0, IDS_ATANH, false },
|
{ IDC_TANH, { L"", SIDS_ATANH } },
|
||||||
|
|
||||||
/* IDC_LN */{ 0, IDS_POWE, false },
|
{ IDC_LN, { L"", SIDS_POWE } },
|
||||||
/* IDC_LOG */{ 0, 0, false },
|
{ IDC_SQR, { SIDS_SQR } },
|
||||||
/* IDC_SQRT */{ 0, 0, false },
|
{ IDC_CUB, { SIDS_CUBE } },
|
||||||
/* IDC_SQR */{ IDS_SQR, 0, false },
|
{ IDC_FAC, { SIDS_FACT } },
|
||||||
/* IDC_CUB */{ IDS_CUBE, 0, false },
|
{ IDC_REC, { SIDS_RECIPROC } },
|
||||||
/* IDC_FAC */{ IDS_FACT, 0, false },
|
{ IDC_DMS, { L"", SIDS_DEGREES } },
|
||||||
/* IDC_REC */{ IDS_REC, 0, false },
|
{ IDC_SIGN, { SIDS_NEGATE } },
|
||||||
/* IDC_DMS */{ 0, IDS_DEGREES, false },
|
{ IDC_DEGREES, { SIDS_DEGREES } }
|
||||||
/* IDC_CUBEROOT */{ 0, 0, false },
|
|
||||||
/* IDC_POW10 */{ 0, 0, false },
|
|
||||||
/* IDC_PERCENT */{ 0, 0, false },
|
|
||||||
|
|
||||||
/* IDC_RADSIN */{ IDS_SINR, IDS_ASINR, false },
|
|
||||||
/* IDC_RADCOS */{ IDS_COSR, IDS_ACOSR, false },
|
|
||||||
/* IDC_RADTAN */{ IDS_TANR, IDS_ATANR, false },
|
|
||||||
/* IDC_GRADCOS */{ IDS_SING, IDS_ASING, false },
|
|
||||||
/* IDC_GRADCOS */{ IDS_COSG, IDS_ACOSG, false },
|
|
||||||
/* IDC_GRADTAN */{ IDS_TANG, IDS_ATANG, false },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
wstring_view CCalcEngine::OpCodeToUnaryString(int nOpCode, bool fInv, ANGLE_TYPE angletype)
|
wstring_view CCalcEngine::OpCodeToUnaryString(int nOpCode, bool fInv, ANGLE_TYPE angletype)
|
||||||
{
|
{
|
||||||
// Special cases for Sign and Degrees
|
// Try to lookup the ID in the UFNE table
|
||||||
if (IDC_SIGN == nOpCode)
|
wstring ids = L"";
|
||||||
|
|
||||||
|
if (auto pair = unaryOperatorStringTable.find(nOpCode); pair != unaryOperatorStringTable.end())
|
||||||
{
|
{
|
||||||
return GetString(IDS_NEGATE);
|
const FunctionNameElement& element = pair->second;
|
||||||
}
|
if (!element.hasAngleStrings || ANGLE_DEG == angletype)
|
||||||
if (IDC_DEGREES == nOpCode)
|
|
||||||
{
|
{
|
||||||
return GetString(IDS_DEGREES);
|
if (fInv)
|
||||||
|
{
|
||||||
|
ids = element.inverseDegreeString;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Correct the trigonometric functions with type of angle argument they take
|
if (ids.empty())
|
||||||
if (ANGLE_RAD == angletype)
|
|
||||||
{
|
{
|
||||||
switch (nOpCode)
|
ids = element.degreeString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (ANGLE_RAD == angletype)
|
||||||
{
|
{
|
||||||
case IDC_SIN:
|
if (fInv)
|
||||||
nOpCode = IDC_RADSIN;
|
{
|
||||||
break;
|
ids = element.inverseRadString;
|
||||||
case IDC_COS:
|
}
|
||||||
nOpCode = IDC_RADCOS;
|
if (ids.empty())
|
||||||
break;
|
{
|
||||||
case IDC_TAN:
|
ids = element.radString;
|
||||||
nOpCode = IDC_RADTAN;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ANGLE_GRAD == angletype)
|
else if (ANGLE_GRAD == angletype)
|
||||||
{
|
|
||||||
switch (nOpCode)
|
|
||||||
{
|
|
||||||
case IDC_SIN:
|
|
||||||
nOpCode = IDC_GRADSIN;
|
|
||||||
break;
|
|
||||||
case IDC_COS:
|
|
||||||
nOpCode = IDC_GRADCOS;
|
|
||||||
break;
|
|
||||||
case IDC_TAN:
|
|
||||||
nOpCode = IDC_GRADTAN;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to lookup the ID in the UFNE table
|
|
||||||
int ids = 0;
|
|
||||||
int iufne = nOpCode - IDC_UNARYFIRST;
|
|
||||||
if (iufne >= 0 && iufne < ARRAYSIZE(rgUfne))
|
|
||||||
{
|
{
|
||||||
if (fInv)
|
if (fInv)
|
||||||
{
|
{
|
||||||
ids = rgUfne[iufne].idsFuncInv;
|
ids = element.inverseGradString;
|
||||||
}
|
}
|
||||||
if (0 == ids)
|
if (ids.empty())
|
||||||
{
|
{
|
||||||
ids = rgUfne[iufne].idsFunc;
|
ids = element.gradString;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we didn't find an ID in the table, use the op code.
|
if (!ids.empty())
|
||||||
if (0 == ids)
|
|
||||||
{
|
{
|
||||||
ids = IdStrFromCmdId(nOpCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
return GetString(ids);
|
return GetString(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// If we didn't find an ID in the table, use the op code.
|
||||||
// Sets the Angle Mode for special unary op IDC's which are used to index to the table rgUfne
|
return OpCodeToString(nOpCode);
|
||||||
// and returns the equivalent plain IDC for trigonometric function. If it isn't a trigonometric function
|
|
||||||
// returns the passed in idc itself.
|
|
||||||
int CCalcEngine::IdcSetAngleTypeDecMode(int idc)
|
|
||||||
{
|
|
||||||
int idcAngleCmd = IDM_DEG;
|
|
||||||
|
|
||||||
switch (idc)
|
|
||||||
{
|
|
||||||
case IDC_RADSIN:
|
|
||||||
idcAngleCmd = IDM_RAD;
|
|
||||||
idc = IDC_SIN;
|
|
||||||
break;
|
|
||||||
case IDC_RADCOS:
|
|
||||||
idcAngleCmd = IDM_RAD;
|
|
||||||
idc = IDC_COS;
|
|
||||||
break;
|
|
||||||
case IDC_RADTAN:
|
|
||||||
idcAngleCmd = IDM_RAD;
|
|
||||||
idc = IDC_TAN;
|
|
||||||
break;
|
|
||||||
case IDC_GRADSIN:
|
|
||||||
idcAngleCmd = IDM_GRAD;
|
|
||||||
idc = IDC_SIN;
|
|
||||||
break;
|
|
||||||
case IDC_GRADCOS:
|
|
||||||
idcAngleCmd = IDM_GRAD;
|
|
||||||
idc = IDC_COS;
|
|
||||||
break;
|
|
||||||
case IDC_GRADTAN:
|
|
||||||
idcAngleCmd = IDM_GRAD;
|
|
||||||
idc = IDC_TAN;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ProcessCommand(idcAngleCmd);
|
|
||||||
return idc;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CCalcEngine::IsCurrentTooBigForTrig()
|
bool CCalcEngine::IsCurrentTooBigForTrig()
|
||||||
|
@ -1020,7 +959,7 @@ wstring CCalcEngine::GetCurrentResultForRadix(uint32_t radix, int32_t precision)
|
||||||
wstring numberString = GetStringForDisplay(rat, radix);
|
wstring numberString = GetStringForDisplay(rat, radix);
|
||||||
if (!numberString.empty())
|
if (!numberString.empty())
|
||||||
{
|
{
|
||||||
//revert the precision to previously stored precision
|
// Revert the precision to previously stored precision
|
||||||
ChangeConstants(m_radix, m_precision);
|
ChangeConstants(m_radix, m_precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1053,7 +992,7 @@ wstring CCalcEngine::GetStringForDisplay(Rational const& rat, uint32_t radix)
|
||||||
|
|
||||||
result = tempRat.ToString(radix, m_nFE, m_precision);
|
result = tempRat.ToString(radix, m_nFE, m_precision);
|
||||||
}
|
}
|
||||||
catch (DWORD)
|
catch (uint32_t)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,9 @@
|
||||||
*
|
*
|
||||||
* Author:
|
* Author:
|
||||||
\****************************************************************************/
|
\****************************************************************************/
|
||||||
#include "pch.h"
|
|
||||||
|
#include <sstream>
|
||||||
|
#include <regex>
|
||||||
#include "Header Files/CalcEngine.h"
|
#include "Header Files/CalcEngine.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -23,7 +25,6 @@ constexpr uint32_t MAX_GROUPING_SIZE = 16;
|
||||||
constexpr wstring_view c_decPreSepStr = L"[+-]?(\\d*)[";
|
constexpr wstring_view c_decPreSepStr = L"[+-]?(\\d*)[";
|
||||||
constexpr wstring_view c_decPostSepStr = L"]?(\\d*)(?:e[+-]?(\\d*))?$";
|
constexpr wstring_view c_decPostSepStr = L"]?(\\d*)(?:e[+-]?(\\d*))?$";
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************\
|
/****************************************************************************\
|
||||||
* void DisplayNum(void)
|
* void DisplayNum(void)
|
||||||
*
|
*
|
||||||
|
@ -35,11 +36,12 @@ constexpr wstring_view c_decPostSepStr = L"]?(\\d*)(?:e[+-]?(\\d*))?$";
|
||||||
//
|
//
|
||||||
// State of calc last time DisplayNum was called
|
// State of calc last time DisplayNum was called
|
||||||
//
|
//
|
||||||
typedef struct {
|
typedef struct
|
||||||
|
{
|
||||||
Rational value;
|
Rational value;
|
||||||
int32_t precision;
|
int32_t precision;
|
||||||
uint32_t radix;
|
uint32_t radix;
|
||||||
INT nFE;
|
int nFE;
|
||||||
NUM_WIDTH numwidth;
|
NUM_WIDTH numwidth;
|
||||||
bool fIntMath;
|
bool fIntMath;
|
||||||
bool bRecord;
|
bool bRecord;
|
||||||
|
@ -82,15 +84,8 @@ void CCalcEngine::DisplayNum(void)
|
||||||
// something important has changed since the last time DisplayNum was
|
// something important has changed since the last time DisplayNum was
|
||||||
// called.
|
// called.
|
||||||
//
|
//
|
||||||
if (m_bRecord ||
|
if (m_bRecord || gldPrevious.value != m_currentVal || gldPrevious.precision != m_precision || gldPrevious.radix != m_radix || gldPrevious.nFE != (int)m_nFE
|
||||||
gldPrevious.value != m_currentVal ||
|
|| gldPrevious.bUseSep != true || gldPrevious.numwidth != m_numwidth || gldPrevious.fIntMath != m_fIntegerMode || gldPrevious.bRecord != m_bRecord)
|
||||||
gldPrevious.precision != m_precision ||
|
|
||||||
gldPrevious.radix != m_radix ||
|
|
||||||
gldPrevious.nFE != (int)m_nFE ||
|
|
||||||
gldPrevious.bUseSep != true ||
|
|
||||||
gldPrevious.numwidth != m_numwidth ||
|
|
||||||
gldPrevious.fIntMath != m_fIntegerMode ||
|
|
||||||
gldPrevious.bRecord != m_bRecord)
|
|
||||||
{
|
{
|
||||||
gldPrevious.precision = m_precision;
|
gldPrevious.precision = m_precision;
|
||||||
gldPrevious.radix = m_radix;
|
gldPrevious.radix = m_radix;
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
/*** ***/
|
/*** ***/
|
||||||
/*** ***/
|
/*** ***/
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
#include "pch.h"
|
|
||||||
#include "Header Files/CalcEngine.h"
|
#include "Header Files/CalcEngine.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -24,7 +23,7 @@ using namespace CalcEngine;
|
||||||
using namespace CalcEngine::RationalMath;
|
using namespace CalcEngine::RationalMath;
|
||||||
|
|
||||||
/* Routines for more complex mathematical functions/error checking. */
|
/* Routines for more complex mathematical functions/error checking. */
|
||||||
CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& rat, DWORD op)
|
CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& rat, uint32_t op)
|
||||||
{
|
{
|
||||||
Rational result{};
|
Rational result{};
|
||||||
try
|
try
|
||||||
|
@ -205,7 +204,7 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
|
||||||
}
|
}
|
||||||
} // end switch( op )
|
} // end switch( op )
|
||||||
}
|
}
|
||||||
catch (DWORD nErrCode)
|
catch (uint32_t nErrCode)
|
||||||
{
|
{
|
||||||
DisplayError(nErrCode);
|
DisplayError(nErrCode);
|
||||||
result = rat;
|
result = rat;
|
||||||
|
@ -215,9 +214,9 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Routine to display error messages and set m_bError flag. Errors are */
|
/* 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)) };
|
wstring errorString{ GetString(IDS_ERRORS_FIRST + SCODE_CODE(nError)) };
|
||||||
|
|
||||||
|
@ -227,4 +226,3 @@ void CCalcEngine::DisplayError(DWORD nError)
|
||||||
|
|
||||||
m_HistoryCollector.ClearHistoryLine(errorString);
|
m_HistoryCollector.ClearHistoryLine(errorString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
#include "Header Files/CalcEngine.h"
|
#include "Header Files/CalcEngine.h"
|
||||||
|
|
||||||
using namespace CalcEngine;
|
using namespace CalcEngine;
|
||||||
|
@ -78,7 +77,7 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa
|
||||||
case IDC_DIV:
|
case IDC_DIV:
|
||||||
case IDC_MOD:
|
case IDC_MOD:
|
||||||
{
|
{
|
||||||
int iNumeratorSign = 1, iDenominatorSign = 1, iFinalSign = 1;
|
int iNumeratorSign = 1, iDenominatorSign = 1;
|
||||||
auto temp = result;
|
auto temp = result;
|
||||||
result = rhs;
|
result = rhs;
|
||||||
|
|
||||||
|
@ -107,20 +106,30 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa
|
||||||
|
|
||||||
if (operation == IDC_DIV)
|
if (operation == IDC_DIV)
|
||||||
{
|
{
|
||||||
iFinalSign = iNumeratorSign * iDenominatorSign;
|
|
||||||
result /= temp;
|
result /= temp;
|
||||||
}
|
if (m_fIntegerMode && (iNumeratorSign * iDenominatorSign) == -1)
|
||||||
else
|
|
||||||
{
|
|
||||||
iFinalSign = iNumeratorSign;
|
|
||||||
result %= temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_fIntegerMode && iFinalSign == -1)
|
|
||||||
{
|
{
|
||||||
result = -(Integer(result));
|
result = -(Integer(result));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (m_fIntegerMode)
|
||||||
|
{
|
||||||
|
// Programmer mode, use remrat (remainder after division)
|
||||||
|
result %= temp;
|
||||||
|
|
||||||
|
if (iNumeratorSign == -1)
|
||||||
|
{
|
||||||
|
result = -(Integer(result));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// other modes, use modrat (modulus after division)
|
||||||
|
result = Mod(result, temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +142,7 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (DWORD dwErrCode)
|
catch (uint32_t dwErrCode)
|
||||||
{
|
{
|
||||||
DisplayError(dwErrCode);
|
DisplayError(dwErrCode);
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
#include "Header Files/CalcEngine.h"
|
#include "Header Files/CalcEngine.h"
|
||||||
|
|
||||||
using namespace CalcEngine;
|
using namespace CalcEngine;
|
||||||
using namespace CalcEngine::RationalMath;
|
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
|
// 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.
|
// dont change that.
|
||||||
|
@ -50,12 +50,12 @@ void CCalcEngine::SetRadixTypeAndNumWidth(RADIX_TYPE radixtype, NUM_WIDTH numwid
|
||||||
DisplayNum();
|
DisplayNum();
|
||||||
}
|
}
|
||||||
|
|
||||||
LONG CCalcEngine::DwWordBitWidthFromeNumWidth(NUM_WIDTH /*numwidth*/)
|
int32_t CCalcEngine::DwWordBitWidthFromeNumWidth(NUM_WIDTH /*numwidth*/)
|
||||||
{
|
{
|
||||||
static constexpr int nBitMax[] = { 64, 32, 16, 8 };
|
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];
|
wmax = nBitMax[m_numwidth];
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ uint32_t CCalcEngine::NRadixFromRadixType(RADIX_TYPE radixtype)
|
||||||
uint32_t radix = 10;
|
uint32_t radix = 10;
|
||||||
|
|
||||||
// convert special bases into symbolic values
|
// convert special bases into symbolic values
|
||||||
if (radixtype >= 0 && radixtype < ARRAYSIZE(rgnRadish))
|
if (radixtype >= 0 && (size_t)radixtype < size(rgnRadish))
|
||||||
{
|
{
|
||||||
radix = rgnRadish[radixtype];
|
radix = rgnRadish[radixtype];
|
||||||
}
|
}
|
||||||
|
@ -76,9 +76,9 @@ uint32_t CCalcEngine::NRadixFromRadixType(RADIX_TYPE radixtype)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Toggles a given bit into the number representation. returns true if it changed it actually.
|
// Toggles a given bit into the number representation. returns true if it changed it actually.
|
||||||
bool CCalcEngine::TryToggleBit(CalcEngine::Rational& rat, 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)
|
if (wbitno >= wmax)
|
||||||
{
|
{
|
||||||
return false; // ignore error cant happen
|
return false; // ignore error cant happen
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -157,6 +157,7 @@
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<WarningLevel>Level4</WarningLevel>
|
<WarningLevel>Level4</WarningLevel>
|
||||||
<TreatWarningAsError>true</TreatWarningAsError>
|
<TreatWarningAsError>true</TreatWarningAsError>
|
||||||
|
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
|
@ -173,6 +174,7 @@
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<WarningLevel>Level4</WarningLevel>
|
<WarningLevel>Level4</WarningLevel>
|
||||||
<TreatWarningAsError>true</TreatWarningAsError>
|
<TreatWarningAsError>true</TreatWarningAsError>
|
||||||
|
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
|
@ -189,6 +191,7 @@
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<WarningLevel>Level4</WarningLevel>
|
<WarningLevel>Level4</WarningLevel>
|
||||||
<TreatWarningAsError>true</TreatWarningAsError>
|
<TreatWarningAsError>true</TreatWarningAsError>
|
||||||
|
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
|
@ -205,6 +208,7 @@
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<WarningLevel>Level4</WarningLevel>
|
<WarningLevel>Level4</WarningLevel>
|
||||||
<TreatWarningAsError>true</TreatWarningAsError>
|
<TreatWarningAsError>true</TreatWarningAsError>
|
||||||
|
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
|
@ -222,6 +226,7 @@
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<WarningLevel>Level4</WarningLevel>
|
<WarningLevel>Level4</WarningLevel>
|
||||||
<TreatWarningAsError>true</TreatWarningAsError>
|
<TreatWarningAsError>true</TreatWarningAsError>
|
||||||
|
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
|
@ -238,6 +243,7 @@
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<WarningLevel>Level4</WarningLevel>
|
<WarningLevel>Level4</WarningLevel>
|
||||||
<TreatWarningAsError>true</TreatWarningAsError>
|
<TreatWarningAsError>true</TreatWarningAsError>
|
||||||
|
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
|
@ -254,6 +260,7 @@
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<WarningLevel>Level4</WarningLevel>
|
<WarningLevel>Level4</WarningLevel>
|
||||||
<TreatWarningAsError>true</TreatWarningAsError>
|
<TreatWarningAsError>true</TreatWarningAsError>
|
||||||
|
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
|
@ -270,6 +277,7 @@
|
||||||
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||||
<WarningLevel>Level4</WarningLevel>
|
<WarningLevel>Level4</WarningLevel>
|
||||||
<TreatWarningAsError>true</TreatWarningAsError>
|
<TreatWarningAsError>true</TreatWarningAsError>
|
||||||
|
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
<SubSystem>Console</SubSystem>
|
<SubSystem>Console</SubSystem>
|
||||||
|
@ -278,7 +286,6 @@
|
||||||
</Link>
|
</Link>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="CalcException.h" />
|
|
||||||
<ClInclude Include="CalculatorHistory.h" />
|
<ClInclude Include="CalculatorHistory.h" />
|
||||||
<ClInclude Include="CalculatorManager.h" />
|
<ClInclude Include="CalculatorManager.h" />
|
||||||
<ClInclude Include="CalculatorResource.h" />
|
<ClInclude Include="CalculatorResource.h" />
|
||||||
|
|
|
@ -119,7 +119,6 @@
|
||||||
<ClInclude Include="Ratpack\ratpak.h">
|
<ClInclude Include="Ratpack\ratpak.h">
|
||||||
<Filter>RatPack</Filter>
|
<Filter>RatPack</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="CalcException.h" />
|
|
||||||
<ClInclude Include="CalculatorVector.h" />
|
<ClInclude Include="CalculatorVector.h" />
|
||||||
<ClInclude Include="Header Files\CalcEngine.h">
|
<ClInclude Include="Header Files\CalcEngine.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
|
|
|
@ -1,18 +1,21 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
#include "pch.h"
|
#include <cassert>
|
||||||
#include "CalculatorHistory.h"
|
#include "CalculatorHistory.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace CalculationManager;
|
using namespace CalculationManager;
|
||||||
|
|
||||||
CalculatorHistory::CalculatorHistory(CALCULATOR_MODE eMode, size_t maxSize) :
|
CalculatorHistory::CalculatorHistory(size_t maxSize)
|
||||||
m_mode(eMode),
|
: m_maxHistorySize(maxSize)
|
||||||
m_maxHistorySize(maxSize)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
unsigned int CalculatorHistory::AddToHistory(_In_ shared_ptr<CalculatorVector <pair<wstring, int>>> const &tokens, _In_ shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> const &commands, _In_ wstring_view result)
|
unsigned int CalculatorHistory::AddToHistory(
|
||||||
|
_In_ shared_ptr<CalculatorVector<pair<wstring, int>>> const& tokens,
|
||||||
|
_In_ shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> const& commands,
|
||||||
|
_In_ wstring_view result)
|
||||||
{
|
{
|
||||||
unsigned int addedIndex;
|
unsigned int addedIndex;
|
||||||
wstring generatedExpression;
|
wstring generatedExpression;
|
||||||
|
@ -32,18 +35,15 @@ unsigned int CalculatorHistory::AddToHistory(_In_ shared_ptr<CalculatorVector <p
|
||||||
return addedIndex;
|
return addedIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
unsigned int CalculatorHistory::AddItem(_In_ shared_ptr<HISTORYITEM> const& spHistoryItem)
|
unsigned int CalculatorHistory::AddItem(_In_ shared_ptr<HISTORYITEM> const& spHistoryItem)
|
||||||
{
|
{
|
||||||
int lastIndex;
|
|
||||||
|
|
||||||
if (m_historyItems.size() >= m_maxHistorySize)
|
if (m_historyItems.size() >= m_maxHistorySize)
|
||||||
{
|
{
|
||||||
m_historyItems.erase(m_historyItems.begin());
|
m_historyItems.erase(m_historyItems.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
m_historyItems.push_back(spHistoryItem);
|
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;
|
return lastIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,24 +26,27 @@ namespace CalculationManager
|
||||||
HISTORYITEMVECTOR historyItemVector;
|
HISTORYITEMVECTOR historyItemVector;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CalculatorHistory :
|
class CalculatorHistory : public IHistoryDisplay
|
||||||
public IHistoryDisplay
|
|
||||||
{
|
{
|
||||||
|
|
||||||
public:
|
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);
|
unsigned int AddToHistory(
|
||||||
|
_In_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const& spTokens,
|
||||||
|
_In_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const& spCommands,
|
||||||
|
std::wstring_view result);
|
||||||
std::vector<std::shared_ptr<HISTORYITEM>> const& GetHistory();
|
std::vector<std::shared_ptr<HISTORYITEM>> const& GetHistory();
|
||||||
std::shared_ptr<HISTORYITEM> const& GetHistoryItem(unsigned int uIdx);
|
std::shared_ptr<HISTORYITEM> const& GetHistoryItem(unsigned int uIdx);
|
||||||
void ClearHistory();
|
void ClearHistory();
|
||||||
unsigned int AddItem(_In_ std::shared_ptr<HISTORYITEM> const& spHistoryItem);
|
unsigned int AddItem(_In_ std::shared_ptr<HISTORYITEM> const& spHistoryItem);
|
||||||
bool RemoveItem(unsigned int uIdx);
|
bool RemoveItem(unsigned int uIdx);
|
||||||
const size_t MaxHistorySize() const { return m_maxHistorySize; }
|
size_t MaxHistorySize() const
|
||||||
|
{
|
||||||
|
return m_maxHistorySize;
|
||||||
|
}
|
||||||
~CalculatorHistory(void);
|
~CalculatorHistory(void);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<std::shared_ptr<HISTORYITEM>> m_historyItems;
|
std::vector<std::shared_ptr<HISTORYITEM>> m_historyItems;
|
||||||
CALCULATOR_MODE m_mode;
|
|
||||||
const size_t m_maxHistorySize;
|
const size_t m_maxHistorySize;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
#include "pch.h"
|
#include <climits> // for UCHAR_MAX
|
||||||
#include "Header Files/CalcEngine.h"
|
#include "Header Files/CalcEngine.h"
|
||||||
#include "CalculatorManager.h"
|
#include "CalculatorManager.h"
|
||||||
#include "CalculatorResource.h"
|
#include "CalculatorResource.h"
|
||||||
|
@ -14,25 +14,21 @@ static constexpr size_t SERIALIZED_NUMBER_MINSIZE = 3;
|
||||||
|
|
||||||
// Converts Memory Command enum value to unsigned char,
|
// Converts Memory Command enum value to unsigned char,
|
||||||
// while ignoring Warning C4309: 'conversion' : truncation of constant value
|
// while ignoring Warning C4309: 'conversion' : truncation of constant value
|
||||||
#define MEMORY_COMMAND_TO_UNSIGNED_CHAR(c)\
|
#define MEMORY_COMMAND_TO_UNSIGNED_CHAR(c) __pragma(warning(push)) __pragma(warning(disable : 4309)) static_cast<unsigned char>(c) __pragma(warning(pop))
|
||||||
__pragma(warning(push))\
|
|
||||||
__pragma(warning(disable: 4309))\
|
|
||||||
static_cast<unsigned char>(c)\
|
|
||||||
__pragma(warning(pop))
|
|
||||||
|
|
||||||
namespace CalculationManager
|
namespace CalculationManager
|
||||||
{
|
{
|
||||||
CalculatorManager::CalculatorManager(_In_ ICalcDisplay* displayCallback, _In_ IResourceProvider* resourceProvider) :
|
CalculatorManager::CalculatorManager(_In_ ICalcDisplay* displayCallback, _In_ IResourceProvider* resourceProvider)
|
||||||
m_displayCallback(displayCallback),
|
: m_displayCallback(displayCallback)
|
||||||
m_resourceProvider(resourceProvider),
|
, m_currentCalculatorEngine(nullptr)
|
||||||
m_currentDegreeMode(Command::CommandNULL),
|
, m_resourceProvider(resourceProvider)
|
||||||
m_savedDegreeMode(Command::CommandDEG),
|
, m_inHistoryItemLoadMode(false)
|
||||||
m_isExponentialFormat(false),
|
, m_persistedPrimaryValue()
|
||||||
m_persistedPrimaryValue(),
|
, m_isExponentialFormat(false)
|
||||||
m_currentCalculatorEngine(nullptr),
|
, m_currentDegreeMode(Command::CommandNULL)
|
||||||
m_pStdHistory(new CalculatorHistory(CM_STD, MAX_HISTORY_ITEMS)),
|
, m_savedDegreeMode(Command::CommandDEG)
|
||||||
m_pSciHistory(new CalculatorHistory(CM_SCI, MAX_HISTORY_ITEMS)),
|
, m_pStdHistory(new CalculatorHistory(MAX_HISTORY_ITEMS))
|
||||||
m_inHistoryItemLoadMode(false)
|
, m_pSciHistory(new CalculatorHistory(MAX_HISTORY_ITEMS))
|
||||||
{
|
{
|
||||||
CCalcEngine::InitialOneTimeOnlySetup(*m_resourceProvider);
|
CCalcEngine::InitialOneTimeOnlySetup(*m_resourceProvider);
|
||||||
}
|
}
|
||||||
|
@ -89,7 +85,9 @@ namespace CalculationManager
|
||||||
/// Used to set the expression display value on ViewModel
|
/// Used to set the expression display value on ViewModel
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="expressionString">wstring representing expression to be displayed</param>
|
/// <param name="expressionString">wstring representing expression to be displayed</param>
|
||||||
void CalculatorManager::SetExpressionDisplay(_Inout_ shared_ptr<CalculatorVector<pair<wstring, int>>> const &tokens, _Inout_ shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> const &commands)
|
void CalculatorManager::SetExpressionDisplay(
|
||||||
|
_Inout_ shared_ptr<CalculatorVector<pair<wstring, int>>> const& tokens,
|
||||||
|
_Inout_ shared_ptr<CalculatorVector<shared_ptr<IExpressionCommand>>> const& commands)
|
||||||
{
|
{
|
||||||
if (!m_inHistoryItemLoadMode)
|
if (!m_inHistoryItemLoadMode)
|
||||||
{
|
{
|
||||||
|
@ -109,12 +107,19 @@ namespace CalculationManager
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Callback from the engine
|
/// Callback from the engine
|
||||||
/// Used to set the current unmatched open parenthesis count
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="parenthesisCount">string containing the parenthesis count</param>
|
/// <param name="parenthesisCount">string containing the parenthesis count</param>
|
||||||
void CalculatorManager::SetParenDisplayText(const wstring& parenthesisCount)
|
void CalculatorManager::SetParenthesisNumber(_In_ unsigned int parenthesisCount)
|
||||||
{
|
{
|
||||||
m_displayCallback->SetParenDisplayText(parenthesisCount);
|
m_displayCallback->SetParenthesisNumber(parenthesisCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Callback from the engine
|
||||||
|
/// </summary>
|
||||||
|
void CalculatorManager::OnNoRightParenAdded()
|
||||||
|
{
|
||||||
|
m_displayCallback->OnNoRightParenAdded();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -158,7 +163,8 @@ namespace CalculationManager
|
||||||
{
|
{
|
||||||
if (!m_standardCalculatorEngine)
|
if (!m_standardCalculatorEngine)
|
||||||
{
|
{
|
||||||
m_standardCalculatorEngine = make_unique<CCalcEngine>(false /* Respect Order of Operations */, false /* Set to Integer Mode */, m_resourceProvider, this, m_pStdHistory);
|
m_standardCalculatorEngine =
|
||||||
|
make_unique<CCalcEngine>(false /* Respect Order of Operations */, false /* Set to Integer Mode */, m_resourceProvider, this, m_pStdHistory);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_currentCalculatorEngine = m_standardCalculatorEngine.get();
|
m_currentCalculatorEngine = m_standardCalculatorEngine.get();
|
||||||
|
@ -176,7 +182,8 @@ namespace CalculationManager
|
||||||
{
|
{
|
||||||
if (!m_scientificCalculatorEngine)
|
if (!m_scientificCalculatorEngine)
|
||||||
{
|
{
|
||||||
m_scientificCalculatorEngine = make_unique<CCalcEngine>(true /* Respect Order of Operations */, false /* Set to Integer Mode */, m_resourceProvider, this, m_pSciHistory);
|
m_scientificCalculatorEngine =
|
||||||
|
make_unique<CCalcEngine>(true /* Respect Order of Operations */, false /* Set to Integer Mode */, m_resourceProvider, this, m_pSciHistory);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_currentCalculatorEngine = m_scientificCalculatorEngine.get();
|
m_currentCalculatorEngine = m_scientificCalculatorEngine.get();
|
||||||
|
@ -193,7 +200,8 @@ namespace CalculationManager
|
||||||
{
|
{
|
||||||
if (!m_programmerCalculatorEngine)
|
if (!m_programmerCalculatorEngine)
|
||||||
{
|
{
|
||||||
m_programmerCalculatorEngine = make_unique<CCalcEngine>(true /* Respect Order of Operations */, true /* Set to Integer Mode */, m_resourceProvider, this, nullptr);
|
m_programmerCalculatorEngine =
|
||||||
|
make_unique<CCalcEngine>(true /* Respect Order of Operations */, true /* Set to Integer Mode */, m_resourceProvider, this, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_currentCalculatorEngine = m_programmerCalculatorEngine.get();
|
m_currentCalculatorEngine = m_programmerCalculatorEngine.get();
|
||||||
|
@ -202,10 +210,9 @@ namespace CalculationManager
|
||||||
m_currentCalculatorEngine->ChangePrecision(static_cast<int>(CalculatorPrecision::ProgrammerModePrecision));
|
m_currentCalculatorEngine->ChangePrecision(static_cast<int>(CalculatorPrecision::ProgrammerModePrecision));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Send command to the Calc Engine
|
/// Send command to the Calc Engine
|
||||||
/// Cast Command Enum to WPARAM.
|
/// Cast Command Enum to OpCode.
|
||||||
/// Handle special commands such as mode change and combination of two commands.
|
/// Handle special commands such as mode change and combination of two commands.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="command">Enum Command</command>
|
/// <param name="command">Enum Command</command>
|
||||||
|
@ -213,8 +220,8 @@ namespace CalculationManager
|
||||||
{
|
{
|
||||||
// When the expression line is cleared, we save the current state, which includes,
|
// When the expression line is cleared, we save the current state, which includes,
|
||||||
// primary display, memory, and degree mode
|
// primary display, memory, and degree mode
|
||||||
if (command == Command::CommandCLEAR || command == Command::CommandEQU
|
if (command == Command::CommandCLEAR || command == Command::CommandEQU || command == Command::ModeBasic || command == Command::ModeScientific
|
||||||
|| command == Command::ModeBasic || command == Command::ModeScientific || command == Command::ModeProgrammer)
|
|| command == Command::ModeProgrammer)
|
||||||
{
|
{
|
||||||
switch (command)
|
switch (command)
|
||||||
{
|
{
|
||||||
|
@ -228,7 +235,7 @@ namespace CalculationManager
|
||||||
this->SetProgrammerMode();
|
this->SetProgrammerMode();
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(command));
|
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(command));
|
||||||
}
|
}
|
||||||
|
|
||||||
m_savedCommands.clear(); // Clear the previous command history
|
m_savedCommands.clear(); // Clear the previous command history
|
||||||
|
@ -256,38 +263,38 @@ namespace CalculationManager
|
||||||
switch (command)
|
switch (command)
|
||||||
{
|
{
|
||||||
case Command::CommandASIN:
|
case Command::CommandASIN:
|
||||||
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(Command::CommandINV));
|
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandINV));
|
||||||
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(Command::CommandSIN));
|
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandSIN));
|
||||||
break;
|
break;
|
||||||
case Command::CommandACOS:
|
case Command::CommandACOS:
|
||||||
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(Command::CommandINV));
|
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandINV));
|
||||||
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(Command::CommandCOS));
|
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandCOS));
|
||||||
break;
|
break;
|
||||||
case Command::CommandATAN:
|
case Command::CommandATAN:
|
||||||
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(Command::CommandINV));
|
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandINV));
|
||||||
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(Command::CommandTAN));
|
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandTAN));
|
||||||
break;
|
break;
|
||||||
case Command::CommandPOWE:
|
case Command::CommandPOWE:
|
||||||
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(Command::CommandINV));
|
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandINV));
|
||||||
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(Command::CommandLN));
|
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandLN));
|
||||||
break;
|
break;
|
||||||
case Command::CommandASINH:
|
case Command::CommandASINH:
|
||||||
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(Command::CommandINV));
|
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandINV));
|
||||||
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(Command::CommandSINH));
|
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandSINH));
|
||||||
break;
|
break;
|
||||||
case Command::CommandACOSH:
|
case Command::CommandACOSH:
|
||||||
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(Command::CommandINV));
|
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandINV));
|
||||||
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(Command::CommandCOSH));
|
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandCOSH));
|
||||||
break;
|
break;
|
||||||
case Command::CommandATANH:
|
case Command::CommandATANH:
|
||||||
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(Command::CommandINV));
|
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandINV));
|
||||||
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(Command::CommandTANH));
|
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(Command::CommandTANH));
|
||||||
break;
|
break;
|
||||||
case Command::CommandFE:
|
case Command::CommandFE:
|
||||||
m_isExponentialFormat = !m_isExponentialFormat;
|
m_isExponentialFormat = !m_isExponentialFormat;
|
||||||
// fall through
|
[[fallthrough]];
|
||||||
default:
|
default:
|
||||||
m_currentCalculatorEngine->ProcessCommand(static_cast<WPARAM>(command));
|
m_currentCalculatorEngine->ProcessCommand(static_cast<OpCode>(command));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -301,7 +308,10 @@ namespace CalculationManager
|
||||||
unsigned char CalculatorManager::MapCommandForSerialize(Command command)
|
unsigned char CalculatorManager::MapCommandForSerialize(Command command)
|
||||||
{
|
{
|
||||||
unsigned int commandToSave = static_cast<unsigned int>(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);
|
return static_cast<unsigned char>(commandToSave);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,7 +363,7 @@ namespace CalculationManager
|
||||||
/// <param name = "serializedPrimaryDisplay">Serialized Rational of primary display</param>
|
/// <param name = "serializedPrimaryDisplay">Serialized Rational of primary display</param>
|
||||||
void CalculatorManager::DeSerializePrimaryDisplay(const vector<long>& serializedPrimaryDisplay)
|
void CalculatorManager::DeSerializePrimaryDisplay(const vector<long>& serializedPrimaryDisplay)
|
||||||
{
|
{
|
||||||
if (serializedPrimaryDisplay.size() == 0)
|
if (serializedPrimaryDisplay.empty())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -425,8 +435,8 @@ namespace CalculationManager
|
||||||
|
|
||||||
for (auto commandItr = serializedData.begin(); commandItr != serializedData.end(); ++commandItr)
|
for (auto commandItr = serializedData.begin(); commandItr != serializedData.end(); ++commandItr)
|
||||||
{
|
{
|
||||||
if (*commandItr >= MEMORY_COMMAND_TO_UNSIGNED_CHAR(MemoryCommand::MemorizeNumber) &&
|
if (*commandItr >= MEMORY_COMMAND_TO_UNSIGNED_CHAR(MemoryCommand::MemorizeNumber)
|
||||||
*commandItr <= MEMORY_COMMAND_TO_UNSIGNED_CHAR(MemoryCommand::MemorizedNumberClearAll))
|
&& *commandItr <= MEMORY_COMMAND_TO_UNSIGNED_CHAR(MemoryCommand::MemorizedNumberClearAll))
|
||||||
{
|
{
|
||||||
// MemoryCommands(which have values above 255) are pushed on m_savedCommands upon casting to unsigned char.
|
// MemoryCommands(which have values above 255) are pushed on m_savedCommands upon casting to unsigned char.
|
||||||
// SerializeCommands uses m_savedCommands, which is then used in DeSerializeCommands.
|
// SerializeCommands uses m_savedCommands, which is then used in DeSerializeCommands.
|
||||||
|
@ -483,8 +493,12 @@ namespace CalculationManager
|
||||||
void CalculatorManager::MemorizeNumber()
|
void CalculatorManager::MemorizeNumber()
|
||||||
{
|
{
|
||||||
m_savedCommands.push_back(MEMORY_COMMAND_TO_UNSIGNED_CHAR(MemoryCommand::MemorizeNumber));
|
m_savedCommands.push_back(MEMORY_COMMAND_TO_UNSIGNED_CHAR(MemoryCommand::MemorizeNumber));
|
||||||
if (!(m_currentCalculatorEngine->FInErrorState()))
|
|
||||||
|
if (m_currentCalculatorEngine->FInErrorState())
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_currentCalculatorEngine->ProcessCommand(IDC_STORE);
|
m_currentCalculatorEngine->ProcessCommand(IDC_STORE);
|
||||||
|
|
||||||
auto memoryObjectPtr = m_currentCalculatorEngine->PersistedMemObject();
|
auto memoryObjectPtr = m_currentCalculatorEngine->PersistedMemObject();
|
||||||
|
@ -499,7 +513,6 @@ namespace CalculationManager
|
||||||
}
|
}
|
||||||
this->SetMemorizedNumbersString();
|
this->SetMemorizedNumbersString();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Recall the memorized number.
|
/// Recall the memorized number.
|
||||||
|
@ -509,12 +522,15 @@ namespace CalculationManager
|
||||||
void CalculatorManager::MemorizedNumberLoad(_In_ unsigned int indexOfMemory)
|
void CalculatorManager::MemorizedNumberLoad(_In_ unsigned int indexOfMemory)
|
||||||
{
|
{
|
||||||
SaveMemoryCommand(MemoryCommand::MemorizedNumberLoad, indexOfMemory);
|
SaveMemoryCommand(MemoryCommand::MemorizedNumberLoad, indexOfMemory);
|
||||||
if (!(m_currentCalculatorEngine->FInErrorState()))
|
|
||||||
|
if (m_currentCalculatorEngine->FInErrorState())
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this->MemorizedNumberSelect(indexOfMemory);
|
this->MemorizedNumberSelect(indexOfMemory);
|
||||||
m_currentCalculatorEngine->ProcessCommand(IDC_RECALL);
|
m_currentCalculatorEngine->ProcessCommand(IDC_RECALL);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Do the addition to the selected memory
|
/// Do the addition to the selected memory
|
||||||
|
@ -525,8 +541,12 @@ namespace CalculationManager
|
||||||
void CalculatorManager::MemorizedNumberAdd(_In_ unsigned int indexOfMemory)
|
void CalculatorManager::MemorizedNumberAdd(_In_ unsigned int indexOfMemory)
|
||||||
{
|
{
|
||||||
SaveMemoryCommand(MemoryCommand::MemorizedNumberAdd, indexOfMemory);
|
SaveMemoryCommand(MemoryCommand::MemorizedNumberAdd, indexOfMemory);
|
||||||
if (!(m_currentCalculatorEngine->FInErrorState()))
|
|
||||||
|
if (m_currentCalculatorEngine->FInErrorState())
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_memorizedNumbers.empty())
|
if (m_memorizedNumbers.empty())
|
||||||
{
|
{
|
||||||
this->MemorizeNumber();
|
this->MemorizeNumber();
|
||||||
|
@ -543,7 +563,6 @@ namespace CalculationManager
|
||||||
|
|
||||||
m_displayCallback->MemoryItemChanged(indexOfMemory);
|
m_displayCallback->MemoryItemChanged(indexOfMemory);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void CalculatorManager::MemorizedNumberClear(_In_ unsigned int indexOfMemory)
|
void CalculatorManager::MemorizedNumberClear(_In_ unsigned int indexOfMemory)
|
||||||
{
|
{
|
||||||
|
@ -563,8 +582,12 @@ namespace CalculationManager
|
||||||
void CalculatorManager::MemorizedNumberSubtract(_In_ unsigned int indexOfMemory)
|
void CalculatorManager::MemorizedNumberSubtract(_In_ unsigned int indexOfMemory)
|
||||||
{
|
{
|
||||||
SaveMemoryCommand(MemoryCommand::MemorizedNumberSubtract, indexOfMemory);
|
SaveMemoryCommand(MemoryCommand::MemorizedNumberSubtract, indexOfMemory);
|
||||||
if (!(m_currentCalculatorEngine->FInErrorState()))
|
|
||||||
|
if (m_currentCalculatorEngine->FInErrorState())
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// To add negative of the number on display to the memory -x = x - 2x
|
// To add negative of the number on display to the memory -x = x - 2x
|
||||||
if (m_memorizedNumbers.empty())
|
if (m_memorizedNumbers.empty())
|
||||||
{
|
{
|
||||||
|
@ -584,7 +607,6 @@ namespace CalculationManager
|
||||||
|
|
||||||
m_displayCallback->MemoryItemChanged(indexOfMemory);
|
m_displayCallback->MemoryItemChanged(indexOfMemory);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Clear all the memorized values
|
/// Clear all the memorized values
|
||||||
|
@ -606,12 +628,14 @@ namespace CalculationManager
|
||||||
/// <param name="indexOfMemory">Index of the target memory</param>
|
/// <param name="indexOfMemory">Index of the target memory</param>
|
||||||
void CalculatorManager::MemorizedNumberSelect(_In_ unsigned int indexOfMemory)
|
void CalculatorManager::MemorizedNumberSelect(_In_ unsigned int indexOfMemory)
|
||||||
{
|
{
|
||||||
if (!(m_currentCalculatorEngine->FInErrorState()))
|
if (m_currentCalculatorEngine->FInErrorState())
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto memoryObject = m_memorizedNumbers.at(indexOfMemory);
|
auto memoryObject = m_memorizedNumbers.at(indexOfMemory);
|
||||||
m_currentCalculatorEngine->PersistedMemObject(memoryObject);
|
m_currentCalculatorEngine->PersistedMemObject(memoryObject);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Helper function that needs to be executed when memory is modified
|
/// Helper function that needs to be executed when memory is modified
|
||||||
|
@ -620,15 +644,17 @@ namespace CalculationManager
|
||||||
/// <param name="indexOfMemory">Index of the target memory</param>
|
/// <param name="indexOfMemory">Index of the target memory</param>
|
||||||
void CalculatorManager::MemorizedNumberChanged(_In_ unsigned int indexOfMemory)
|
void CalculatorManager::MemorizedNumberChanged(_In_ unsigned int indexOfMemory)
|
||||||
{
|
{
|
||||||
if (!(m_currentCalculatorEngine->FInErrorState()))
|
if (m_currentCalculatorEngine->FInErrorState())
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto memoryObject = m_currentCalculatorEngine->PersistedMemObject();
|
auto memoryObject = m_currentCalculatorEngine->PersistedMemObject();
|
||||||
if (memoryObject != nullptr)
|
if (memoryObject != nullptr)
|
||||||
{
|
{
|
||||||
m_memorizedNumbers.at(indexOfMemory) = *memoryObject;
|
m_memorizedNumbers.at(indexOfMemory) = *memoryObject;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void CalculatorManager::SaveMemoryCommand(_In_ MemoryCommand command, _In_ unsigned int indexOfMemory)
|
void CalculatorManager::SaveMemoryCommand(_In_ MemoryCommand command, _In_ unsigned int indexOfMemory)
|
||||||
{
|
{
|
||||||
|
@ -647,9 +673,7 @@ namespace CalculationManager
|
||||||
|
|
||||||
vector<shared_ptr<HISTORYITEM>> const& CalculatorManager::GetHistoryItems(_In_ CALCULATOR_MODE mode)
|
vector<shared_ptr<HISTORYITEM>> const& CalculatorManager::GetHistoryItems(_In_ CALCULATOR_MODE mode)
|
||||||
{
|
{
|
||||||
return (mode == CM_STD) ?
|
return (mode == CM_STD) ? m_pStdHistory->GetHistory() : m_pSciHistory->GetHistory();
|
||||||
m_pStdHistory->GetHistory() :
|
|
||||||
m_pSciHistory->GetHistory();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_ptr<HISTORYITEM> const& CalculatorManager::GetHistoryItem(_In_ unsigned int uIdx)
|
shared_ptr<HISTORYITEM> const& CalculatorManager::GetHistoryItem(_In_ unsigned int uIdx)
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace CalculationManager
|
||||||
MemorizedNumberClear = 335
|
MemorizedNumberClear = 335
|
||||||
};
|
};
|
||||||
|
|
||||||
class CalculatorManager sealed : public virtual ICalcDisplay
|
class CalculatorManager final : public ICalcDisplay
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
ICalcDisplay* const m_displayCallback;
|
ICalcDisplay* const m_displayCallback;
|
||||||
|
@ -91,16 +91,18 @@ namespace CalculationManager
|
||||||
// ICalcDisplay
|
// ICalcDisplay
|
||||||
void SetPrimaryDisplay(_In_ const std::wstring& displayString, _In_ bool isError) override;
|
void SetPrimaryDisplay(_In_ const std::wstring& displayString, _In_ bool isError) override;
|
||||||
void SetIsInError(bool isError) override;
|
void SetIsInError(bool isError) override;
|
||||||
void SetExpressionDisplay(_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const &tokens, _Inout_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const &commands) override;
|
void SetExpressionDisplay(
|
||||||
|
_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const& tokens,
|
||||||
|
_Inout_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const& commands) override;
|
||||||
void SetMemorizedNumbers(_In_ const std::vector<std::wstring>& memorizedNumbers) override;
|
void SetMemorizedNumbers(_In_ const std::vector<std::wstring>& memorizedNumbers) override;
|
||||||
void OnHistoryItemAdded(_In_ unsigned int addedItemIndex) override;
|
void OnHistoryItemAdded(_In_ unsigned int addedItemIndex) override;
|
||||||
void SetParenDisplayText(const std::wstring& parenthesisCount);
|
void SetParenthesisNumber(_In_ unsigned int parenthesisCount) override;
|
||||||
|
void OnNoRightParenAdded() override;
|
||||||
void DisplayPasteError();
|
void DisplayPasteError();
|
||||||
void MaxDigitsReached() override;
|
void MaxDigitsReached() override;
|
||||||
void BinaryOperatorReceived() override;
|
void BinaryOperatorReceived() override;
|
||||||
void MemoryItemChanged(unsigned int indexOfMemory) override;
|
void MemoryItemChanged(unsigned int indexOfMemory) override;
|
||||||
|
|
||||||
|
|
||||||
CalculatorManager(ICalcDisplay* displayCallback, IResourceProvider* resourceProvider);
|
CalculatorManager(ICalcDisplay* displayCallback, IResourceProvider* resourceProvider);
|
||||||
~CalculatorManager();
|
~CalculatorManager();
|
||||||
|
|
||||||
|
@ -127,7 +129,10 @@ namespace CalculationManager
|
||||||
void MemorizedNumberClearAll();
|
void MemorizedNumberClearAll();
|
||||||
|
|
||||||
bool IsEngineRecording();
|
bool IsEngineRecording();
|
||||||
std::vector<unsigned char> GetSavedCommands(){ return m_savedCommands; }
|
std::vector<unsigned char> GetSavedCommands()
|
||||||
|
{
|
||||||
|
return m_savedCommands;
|
||||||
|
}
|
||||||
void SetRadix(RADIX_TYPE iRadixType);
|
void SetRadix(RADIX_TYPE iRadixType);
|
||||||
void SetMemorizedNumbersString();
|
void SetMemorizedNumbersString();
|
||||||
std::wstring GetResultForRadix(uint32_t radix, int32_t precision);
|
std::wstring GetResultForRadix(uint32_t radix, int32_t precision);
|
||||||
|
@ -140,7 +145,10 @@ namespace CalculationManager
|
||||||
std::shared_ptr<HISTORYITEM> const& GetHistoryItem(_In_ unsigned int uIdx);
|
std::shared_ptr<HISTORYITEM> const& GetHistoryItem(_In_ unsigned int uIdx);
|
||||||
bool RemoveHistoryItem(_In_ unsigned int uIdx);
|
bool RemoveHistoryItem(_In_ unsigned int uIdx);
|
||||||
void ClearHistory();
|
void ClearHistory();
|
||||||
const size_t MaxHistorySize() const { return m_pHistory->MaxHistorySize(); }
|
size_t MaxHistorySize() const
|
||||||
|
{
|
||||||
|
return m_pHistory->MaxHistorySize();
|
||||||
|
}
|
||||||
CalculationManager::Command GetCurrentDegreeMode();
|
CalculationManager::Command GetCurrentDegreeMode();
|
||||||
void SetHistory(_In_ CALCULATOR_MODE eMode, _In_ std::vector<std::shared_ptr<HISTORYITEM>> const& history);
|
void SetHistory(_In_ CALCULATOR_MODE eMode, _In_ std::vector<std::shared_ptr<HISTORYITEM>> const& history);
|
||||||
void SetInHistoryItemLoadMode(_In_ bool isHistoryItemLoadMode);
|
void SetInHistoryItemLoadMode(_In_ bool isHistoryItemLoadMode);
|
||||||
|
|
|
@ -8,7 +8,9 @@ namespace CalculationManager
|
||||||
class IResourceProvider
|
class IResourceProvider
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~IResourceProvider() { }
|
virtual ~IResourceProvider()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// Should return a string from the resource table for strings used
|
// Should return a string from the resource table for strings used
|
||||||
// by the calculation engine. The strings that must be defined
|
// by the calculation engine. The strings that must be defined
|
||||||
|
|
|
@ -1,15 +1,22 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <winerror.h>
|
||||||
|
#include "Ratpack/CalcErr.h"
|
||||||
|
#include <stdexcept> // for std::out_of_range
|
||||||
|
#include <sal.h> // for SAL
|
||||||
|
|
||||||
template <typename TType>
|
template <typename TType>
|
||||||
class CalculatorVector
|
class CalculatorVector
|
||||||
{
|
{
|
||||||
public:
|
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
|
try
|
||||||
{
|
{
|
||||||
*item = m_vector.at(index);
|
*item = m_vector.at(index);
|
||||||
|
@ -21,15 +28,15 @@ public:
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT GetSize(_Out_ unsigned int *size)
|
ResultCode GetSize(_Out_ unsigned int* size)
|
||||||
{
|
{
|
||||||
*size = static_cast<unsigned>(m_vector.size());
|
*size = static_cast<unsigned>(m_vector.size());
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
try
|
||||||
{
|
{
|
||||||
m_vector[index] = item;
|
m_vector[index] = item;
|
||||||
|
@ -41,9 +48,9 @@ public:
|
||||||
return hr;
|
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())
|
if (index < m_vector.size())
|
||||||
{
|
{
|
||||||
m_vector.erase(m_vector.begin() + index);
|
m_vector.erase(m_vector.begin() + index);
|
||||||
|
@ -55,9 +62,9 @@ public:
|
||||||
return hr;
|
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
|
try
|
||||||
{
|
{
|
||||||
auto iter = m_vector.begin() + index;
|
auto iter = m_vector.begin() + index;
|
||||||
|
@ -70,9 +77,9 @@ public:
|
||||||
return hr;
|
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())
|
if (index < m_vector.size())
|
||||||
{
|
{
|
||||||
auto startIter = m_vector.begin() + index;
|
auto startIter = m_vector.begin() + index;
|
||||||
|
@ -85,9 +92,9 @@ public:
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT Append(_In_opt_ TType item)
|
ResultCode Append(_In_opt_ TType item)
|
||||||
{
|
{
|
||||||
HRESULT hr = S_OK;
|
ResultCode hr = S_OK;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_vector.push_back(item);
|
m_vector.push_back(item);
|
||||||
|
@ -99,21 +106,21 @@ public:
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT RemoveAtEnd()
|
ResultCode RemoveAtEnd()
|
||||||
{
|
{
|
||||||
m_vector.erase(--(m_vector.end()));
|
m_vector.erase(--(m_vector.end()));
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT Clear()
|
ResultCode Clear()
|
||||||
{
|
{
|
||||||
m_vector.clear();
|
m_vector.clear();
|
||||||
return S_OK;
|
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;
|
unsigned int nTokens = 0;
|
||||||
std::pair<std::wstring, int> currentPair;
|
std::pair<std::wstring, int> currentPair;
|
||||||
hr = this->GetSize(&nTokens);
|
hr = this->GetSize(&nTokens);
|
||||||
|
@ -144,7 +151,7 @@ public:
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT GetExpressionSuffix(_Out_ std::wstring* suffix)
|
ResultCode GetExpressionSuffix(_Out_ std::wstring* suffix)
|
||||||
{
|
{
|
||||||
*suffix = L" =";
|
*suffix = L" =";
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
@ -7,9 +7,19 @@ namespace UnitConversionManager
|
||||||
{
|
{
|
||||||
enum class Command
|
enum class Command
|
||||||
{
|
{
|
||||||
Zero, One, Two, Three, Four, Five, Six, Seven, Eight, Nine,
|
Zero,
|
||||||
|
One,
|
||||||
|
Two,
|
||||||
|
Three,
|
||||||
|
Four,
|
||||||
|
Five,
|
||||||
|
Six,
|
||||||
|
Seven,
|
||||||
|
Eight,
|
||||||
|
Nine,
|
||||||
Decimal,
|
Decimal,
|
||||||
Negate, Backspace,
|
Negate,
|
||||||
|
Backspace,
|
||||||
Clear,
|
Clear,
|
||||||
Reset,
|
Reset,
|
||||||
None
|
None
|
||||||
|
@ -20,9 +30,19 @@ namespace CurrencyConversionManager
|
||||||
{
|
{
|
||||||
enum class Command
|
enum class Command
|
||||||
{
|
{
|
||||||
Zero, One, Two, Three, Four, Five, Six, Seven, Eight, Nine,
|
Zero,
|
||||||
|
One,
|
||||||
|
Two,
|
||||||
|
Three,
|
||||||
|
Four,
|
||||||
|
Five,
|
||||||
|
Six,
|
||||||
|
Seven,
|
||||||
|
Eight,
|
||||||
|
Nine,
|
||||||
Decimal,
|
Decimal,
|
||||||
Negate, Backspace,
|
Negate,
|
||||||
|
Backspace,
|
||||||
Clear,
|
Clear,
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -85,7 +105,6 @@ namespace CalculationManager
|
||||||
CommandCOSH = 106,
|
CommandCOSH = 106,
|
||||||
CommandTANH = 107,
|
CommandTANH = 107,
|
||||||
|
|
||||||
|
|
||||||
CommandLN = 108,
|
CommandLN = 108,
|
||||||
CommandLOG = 109,
|
CommandLOG = 109,
|
||||||
CommandSQRT = 110,
|
CommandSQRT = 110,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
#include "pch.h"
|
#include <string>
|
||||||
#include "Header Files/CCommand.h"
|
#include "Header Files/CCommand.h"
|
||||||
#include "CalculatorVector.h"
|
#include "CalculatorVector.h"
|
||||||
#include "ExpressionCommand.h"
|
#include "ExpressionCommand.h"
|
||||||
|
@ -13,8 +13,10 @@ constexpr wchar_t chNegate = L'-';
|
||||||
constexpr wchar_t chExp = L'e';
|
constexpr wchar_t chExp = L'e';
|
||||||
constexpr wchar_t chPlus = L'+';
|
constexpr wchar_t chPlus = L'+';
|
||||||
|
|
||||||
CParentheses::CParentheses(_In_ int command) :m_command(command)
|
CParentheses::CParentheses(_In_ int command)
|
||||||
{}
|
: m_command(command)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
int CParentheses::GetCommand() const
|
int CParentheses::GetCommand() const
|
||||||
{
|
{
|
||||||
|
@ -72,8 +74,10 @@ void CUnaryCommand::Accept(_In_ ISerializeCommandVisitor &commandVisitor)
|
||||||
commandVisitor.Visit(*this);
|
commandVisitor.Visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
CBinaryCommand::CBinaryCommand(int command) :m_command(command)
|
CBinaryCommand::CBinaryCommand(int command)
|
||||||
{}
|
: m_command(command)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void CBinaryCommand::SetCommand(int command)
|
void CBinaryCommand::SetCommand(int command)
|
||||||
{
|
{
|
||||||
|
@ -95,14 +99,15 @@ void CBinaryCommand::Accept(_In_ ISerializeCommandVisitor &commandVisitor)
|
||||||
commandVisitor.Visit(*this);
|
commandVisitor.Visit(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
COpndCommand::COpndCommand(shared_ptr<CalculatorVector<int>> const &commands, bool fNegative, bool fDecimal, bool fSciFmt) :
|
COpndCommand::COpndCommand(shared_ptr<CalculatorVector<int>> const& commands, bool fNegative, bool fDecimal, bool fSciFmt)
|
||||||
m_commands(commands),
|
: m_commands(commands)
|
||||||
m_fNegative(fNegative),
|
, m_fNegative(fNegative)
|
||||||
m_fDecimal(fDecimal),
|
, m_fSciFmt(fSciFmt)
|
||||||
m_fSciFmt(fSciFmt),
|
, m_fDecimal(fDecimal)
|
||||||
m_fInitialized(false),
|
, m_fInitialized(false)
|
||||||
m_value{}
|
, m_value{}
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void COpndCommand::Initialize(Rational const& rat)
|
void COpndCommand::Initialize(Rational const& rat)
|
||||||
{
|
{
|
||||||
|
|
|
@ -49,11 +49,7 @@ private:
|
||||||
class COpndCommand final : public IOpndCommand
|
class COpndCommand final : public IOpndCommand
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
COpndCommand(
|
COpndCommand(std::shared_ptr<CalculatorVector<int>> const& commands, bool fNegative, bool fDecimal, bool fSciFmt);
|
||||||
std::shared_ptr<CalculatorVector<int>> const &commands,
|
|
||||||
bool fNegative,
|
|
||||||
bool fDecimal,
|
|
||||||
bool fSciFmt);
|
|
||||||
void Initialize(CalcEngine::Rational const& rat);
|
void Initialize(CalcEngine::Rational const& rat);
|
||||||
|
|
||||||
const std::shared_ptr<CalculatorVector<int>>& GetCommands() const override;
|
const std::shared_ptr<CalculatorVector<int>>& GetCommands() const override;
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory> // for std::shared_ptr
|
||||||
#include "CalculatorVector.h"
|
#include "CalculatorVector.h"
|
||||||
#include "Command.h"
|
#include "Command.h"
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
*
|
*
|
||||||
\****************************************************************************/
|
\****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
// The following are the valid id's which can be passed to CCalcEngine::ProcessCommand
|
// The following are the valid id's which can be passed to CCalcEngine::ProcessCommand
|
||||||
|
|
||||||
#define IDM_HEX 313
|
#define IDM_HEX 313
|
||||||
|
@ -43,7 +45,6 @@
|
||||||
#define IDC_WORD IDM_WORD
|
#define IDC_WORD IDM_WORD
|
||||||
#define IDC_BYTE IDM_BYTE
|
#define IDC_BYTE IDM_BYTE
|
||||||
|
|
||||||
|
|
||||||
// Key IDs:
|
// Key IDs:
|
||||||
// These id's must be consecutive from IDC_FIRSTCONTROL to IDC_LASTCONTROL.
|
// These id's must be consecutive from IDC_FIRSTCONTROL to IDC_LASTCONTROL.
|
||||||
// The actual values don't matter but the order and sequence are very important.
|
// The actual values don't matter but the order and sequence are very important.
|
||||||
|
@ -75,7 +76,6 @@
|
||||||
#define IDC_ROOT 96
|
#define IDC_ROOT 96
|
||||||
#define IDC_PWR 97
|
#define IDC_PWR 97
|
||||||
|
|
||||||
|
|
||||||
#define IDC_UNARYFIRST IDC_CHOP
|
#define IDC_UNARYFIRST IDC_CHOP
|
||||||
#define IDC_CHOP 98 // Unary operators must be between IDC_CHOP and IDC_EQU
|
#define IDC_CHOP 98 // Unary operators must be between IDC_CHOP and IDC_EQU
|
||||||
#define IDC_ROL 99
|
#define IDC_ROL 99
|
||||||
|
@ -114,7 +114,6 @@
|
||||||
|
|
||||||
#define IDC_EXP 127
|
#define IDC_EXP 127
|
||||||
|
|
||||||
|
|
||||||
#define IDC_OPENP 128
|
#define IDC_OPENP 128
|
||||||
#define IDC_CLOSEP 129
|
#define IDC_CLOSEP 129
|
||||||
|
|
||||||
|
@ -206,9 +205,7 @@
|
||||||
#define IDC_BINPOS63 763
|
#define IDC_BINPOS63 763
|
||||||
#define IDC_BINEDITEND 763
|
#define IDC_BINEDITEND 763
|
||||||
|
|
||||||
|
|
||||||
// The strings in the following range IDS_ENGINESTR_FIRST ... IDS_ENGINESTR_MAX are strings allocated in the
|
// The strings in the following range IDS_ENGINESTR_FIRST ... IDS_ENGINESTR_MAX are strings allocated in the
|
||||||
// resource for the purpose internal to Engine and cant be used by the clients
|
// resource for the purpose internal to Engine and cant be used by the clients
|
||||||
#define IDS_ENGINESTR_FIRST 0
|
#define IDS_ENGINESTR_FIRST 0
|
||||||
#define IDS_ENGINESTR_MAX 200
|
#define IDS_ENGINESTR_MAX 200
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "RadixType.h"
|
#include "RadixType.h"
|
||||||
#include "History.h" // for History Collector
|
#include "History.h" // for History Collector
|
||||||
#include "CalcInput.h"
|
#include "CalcInput.h"
|
||||||
|
#include "CalcUtils.h"
|
||||||
#include "ICalcDisplay.h"
|
#include "ICalcDisplay.h"
|
||||||
#include "Rational.h"
|
#include "Rational.h"
|
||||||
#include "RationalMath.h"
|
#include "RationalMath.h"
|
||||||
|
@ -30,7 +31,8 @@
|
||||||
// The real exports follows later
|
// The real exports follows later
|
||||||
|
|
||||||
// This is expected to be in same order as IDM_QWORD, IDM_DWORD etc.
|
// This is expected to be in same order as IDM_QWORD, IDM_DWORD etc.
|
||||||
enum eNUM_WIDTH {
|
enum eNUM_WIDTH
|
||||||
|
{
|
||||||
QWORD_WIDTH, // Number width of 64 bits mode (default)
|
QWORD_WIDTH, // Number width of 64 bits mode (default)
|
||||||
DWORD_WIDTH, // Number width of 32 bits mode
|
DWORD_WIDTH, // Number width of 32 bits mode
|
||||||
WORD_WIDTH, // Number width of 16 bits mode
|
WORD_WIDTH, // Number width of 16 bits mode
|
||||||
|
@ -44,35 +46,62 @@ namespace CalculationManager
|
||||||
class IResourceProvider;
|
class IResourceProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace CalculatorUnitTests
|
namespace CalculatorEngineTests
|
||||||
{
|
{
|
||||||
class CalcEngineTests;
|
class CalcEngineTests;
|
||||||
}
|
}
|
||||||
|
|
||||||
class CCalcEngine {
|
class CCalcEngine
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
CCalcEngine(bool fPrecedence, bool fIntegerMode, CalculationManager::IResourceProvider* const pResourceProvider, __in_opt ICalcDisplay *pCalcDisplay, __in_opt std::shared_ptr<IHistoryDisplay> pHistoryDisplay);
|
CCalcEngine(
|
||||||
void ProcessCommand(WPARAM wID);
|
bool fPrecedence,
|
||||||
void DisplayError (DWORD nError);
|
bool fIntegerMode,
|
||||||
|
CalculationManager::IResourceProvider* const pResourceProvider,
|
||||||
|
__in_opt ICalcDisplay* pCalcDisplay,
|
||||||
|
__in_opt std::shared_ptr<IHistoryDisplay> pHistoryDisplay);
|
||||||
|
void ProcessCommand(OpCode wID);
|
||||||
|
void DisplayError(uint32_t nError);
|
||||||
std::unique_ptr<CalcEngine::Rational> PersistedMemObject();
|
std::unique_ptr<CalcEngine::Rational> PersistedMemObject();
|
||||||
void PersistedMemObject(CalcEngine::Rational const& memObject);
|
void PersistedMemObject(CalcEngine::Rational const& memObject);
|
||||||
bool FInErrorState() { return m_bError; }
|
bool FInErrorState()
|
||||||
bool FInRecordingState() { return m_bRecord; }
|
{
|
||||||
|
return m_bError;
|
||||||
|
}
|
||||||
|
bool FInRecordingState()
|
||||||
|
{
|
||||||
|
return m_bRecord;
|
||||||
|
}
|
||||||
void SettingsChanged();
|
void SettingsChanged();
|
||||||
bool IsCurrentTooBigForTrig();
|
bool IsCurrentTooBigForTrig();
|
||||||
int GetCurrentRadix();
|
int GetCurrentRadix();
|
||||||
std::wstring GetCurrentResultForRadix(uint32_t radix, int32_t precision);
|
std::wstring GetCurrentResultForRadix(uint32_t radix, int32_t precision);
|
||||||
void ChangePrecision(int32_t precision) { m_precision = precision; ChangeConstants(m_radix, precision); }
|
void ChangePrecision(int32_t precision)
|
||||||
|
{
|
||||||
|
m_precision = precision;
|
||||||
|
ChangeConstants(m_radix, precision);
|
||||||
|
}
|
||||||
std::wstring GroupDigitsPerRadix(std::wstring_view numberString, uint32_t radix);
|
std::wstring GroupDigitsPerRadix(std::wstring_view numberString, uint32_t radix);
|
||||||
std::wstring GetStringForDisplay(CalcEngine::Rational const& rat, uint32_t radix);
|
std::wstring GetStringForDisplay(CalcEngine::Rational const& rat, uint32_t radix);
|
||||||
void UpdateMaxIntDigits();
|
void UpdateMaxIntDigits();
|
||||||
wchar_t DecimalSeparator() const;
|
wchar_t DecimalSeparator() const;
|
||||||
|
|
||||||
// Static methods for the instance
|
// Static methods for the instance
|
||||||
static void InitialOneTimeOnlySetup(CalculationManager::IResourceProvider& resourceProvider); // Once per load time to call to initialize all shared global variables
|
static void
|
||||||
|
InitialOneTimeOnlySetup(CalculationManager::IResourceProvider& resourceProvider); // Once per load time to call to initialize all shared global variables
|
||||||
// returns the ptr to string representing the operator. Mostly same as the button, but few special cases for x^y etc.
|
// returns the ptr to string representing the operator. Mostly same as the button, but few special cases for x^y etc.
|
||||||
static std::wstring_view GetString(int ids) { return s_engineStrings[ids]; }
|
static std::wstring_view GetString(int ids)
|
||||||
static std::wstring_view OpCodeToString(int nOpCode) { return GetString(IdStrFromCmdId(nOpCode)); }
|
{
|
||||||
|
return s_engineStrings[std::to_wstring(ids)];
|
||||||
|
}
|
||||||
|
static std::wstring_view GetString(std::wstring ids)
|
||||||
|
{
|
||||||
|
return s_engineStrings[ids];
|
||||||
|
}
|
||||||
|
static std::wstring_view OpCodeToString(int nOpCode)
|
||||||
|
{
|
||||||
|
return GetString(IdStrFromCmdId(nOpCode));
|
||||||
|
}
|
||||||
static std::wstring_view OpCodeToUnaryString(int nOpCode, bool fInv, ANGLE_TYPE angletype);
|
static std::wstring_view OpCodeToUnaryString(int nOpCode, bool fInv, ANGLE_TYPE angletype);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -116,19 +145,20 @@ private:
|
||||||
int m_nLastCom; // Last command entered.
|
int m_nLastCom; // Last command entered.
|
||||||
ANGLE_TYPE m_angletype; // Current Angle type when in dec mode. one of deg, rad or grad
|
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.
|
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
|
CHistoryCollector m_HistoryCollector; // Accumulator of each line of history as various commands are processed
|
||||||
|
|
||||||
std::array<CalcEngine::Rational, NUM_WIDTH_LENGTH> m_chopNumbers; // word size enforcement
|
std::array<CalcEngine::Rational, NUM_WIDTH_LENGTH> m_chopNumbers; // word size enforcement
|
||||||
std::array<std::wstring, NUM_WIDTH_LENGTH> m_maxDecimalValueStrings; // maximum values represented by a given word width based off m_chopNumbers
|
std::array<std::wstring, NUM_WIDTH_LENGTH> m_maxDecimalValueStrings; // maximum values represented by a given word width based off m_chopNumbers
|
||||||
static std::array<std::wstring, CSTRINGSENGMAX> s_engineStrings; // the string table shared across all instances
|
static std::unordered_map<std::wstring, std::wstring> s_engineStrings; // the string table shared across all instances
|
||||||
wchar_t m_decimalSeparator;
|
wchar_t m_decimalSeparator;
|
||||||
wchar_t m_groupSeparator;
|
wchar_t m_groupSeparator;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ProcessCommandWorker(WPARAM wParam);
|
void ProcessCommandWorker(OpCode wParam);
|
||||||
void HandleErrorCommand(WPARAM idc);
|
void ResolveHighestPrecedenceOperation();
|
||||||
|
void HandleErrorCommand(OpCode idc);
|
||||||
void HandleMaxDigitsReached();
|
void HandleMaxDigitsReached();
|
||||||
void DisplayNum(void);
|
void DisplayNum(void);
|
||||||
int IsNumberInvalid(const std::wstring& numberString, int iMaxExp, int iMaxMantissa, uint32_t radix) const;
|
int IsNumberInvalid(const std::wstring& numberString, int iMaxExp, int iMaxMantissa, uint32_t radix) const;
|
||||||
|
@ -136,20 +166,22 @@ private:
|
||||||
void SetPrimaryDisplay(const std::wstring& szText, bool isError = false);
|
void SetPrimaryDisplay(const std::wstring& szText, bool isError = false);
|
||||||
void ClearTemporaryValues();
|
void ClearTemporaryValues();
|
||||||
CalcEngine::Rational TruncateNumForIntMath(CalcEngine::Rational const& rat);
|
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);
|
CalcEngine::Rational DoOperation(int operation, CalcEngine::Rational const& lhs, CalcEngine::Rational const& rhs);
|
||||||
void SetRadixTypeAndNumWidth(RADIX_TYPE radixtype, NUM_WIDTH numwidth);
|
void SetRadixTypeAndNumWidth(RADIX_TYPE radixtype, NUM_WIDTH numwidth);
|
||||||
LONG DwWordBitWidthFromeNumWidth(NUM_WIDTH numwidth);
|
int32_t DwWordBitWidthFromeNumWidth(NUM_WIDTH numwidth);
|
||||||
uint32_t NRadixFromRadixType(RADIX_TYPE radixtype);
|
uint32_t NRadixFromRadixType(RADIX_TYPE radixtype);
|
||||||
|
|
||||||
bool TryToggleBit(CalcEngine::Rational& rat, DWORD wbitno);
|
bool TryToggleBit(CalcEngine::Rational& rat, uint32_t wbitno);
|
||||||
void CheckAndAddLastBinOpToHistory(bool addToHistory = true);
|
void CheckAndAddLastBinOpToHistory(bool addToHistory = true);
|
||||||
int IdcSetAngleTypeDecMode(int idc);
|
|
||||||
|
|
||||||
void InitChopNumbers();
|
void InitChopNumbers();
|
||||||
|
|
||||||
static void LoadEngineStrings(CalculationManager::IResourceProvider& resourceProvider);
|
static void LoadEngineStrings(CalculationManager::IResourceProvider& resourceProvider);
|
||||||
static int IdStrFromCmdId(int id) { return id - IDC_FIRSTCONTROL + IDS_FIRSTENGSTR; }
|
static int IdStrFromCmdId(int id)
|
||||||
|
{
|
||||||
|
return id - IDC_FIRSTCONTROL + IDS_ENGINESTR_FIRST;
|
||||||
|
}
|
||||||
|
|
||||||
static std::vector<uint32_t> DigitGroupingStringToGroupingVector(std::wstring_view groupingString);
|
static std::vector<uint32_t> DigitGroupingStringToGroupingVector(std::wstring_view groupingString);
|
||||||
std::wstring GroupDigits(std::wstring_view delimiter, std::vector<uint32_t> const& grouping, std::wstring_view displayString, bool isNumNegative = false);
|
std::wstring GroupDigits(std::wstring_view delimiter, std::vector<uint32_t> const& grouping, std::wstring_view displayString, bool isNumNegative = false);
|
||||||
|
@ -158,5 +190,5 @@ private:
|
||||||
static void ChangeBaseConstants(uint32_t radix, int maxIntDigits, int32_t precision);
|
static void ChangeBaseConstants(uint32_t radix, int maxIntDigits, int32_t precision);
|
||||||
void BaseOrPrecisionChanged();
|
void BaseOrPrecisionChanged();
|
||||||
|
|
||||||
friend class CalculatorUnitTests::CalcEngineTests;
|
friend class CalculatorEngineTests::CalcEngineTests;
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,16 +13,26 @@ namespace CalcEngine
|
||||||
class CalcNumSec
|
class CalcNumSec
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CalcNumSec() :
|
CalcNumSec()
|
||||||
value(),
|
: value()
|
||||||
m_isNegative(false)
|
, m_isNegative(false)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
bool IsEmpty() { return value.empty(); }
|
bool IsEmpty()
|
||||||
|
{
|
||||||
|
return value.empty();
|
||||||
|
}
|
||||||
|
|
||||||
bool IsNegative() { return m_isNegative; }
|
bool IsNegative()
|
||||||
void IsNegative(bool isNegative) { m_isNegative = isNegative; }
|
{
|
||||||
|
return m_isNegative;
|
||||||
|
}
|
||||||
|
void IsNegative(bool isNegative)
|
||||||
|
{
|
||||||
|
m_isNegative = isNegative;
|
||||||
|
}
|
||||||
|
|
||||||
std::wstring value;
|
std::wstring value;
|
||||||
|
|
||||||
|
@ -33,21 +43,24 @@ namespace CalcEngine
|
||||||
class CalcInput
|
class CalcInput
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CalcInput() : CalcInput(L'.')
|
CalcInput()
|
||||||
{}
|
: CalcInput(L'.')
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
CalcInput(wchar_t decSymbol) :
|
CalcInput(wchar_t decSymbol)
|
||||||
m_hasExponent(false),
|
: m_hasExponent(false)
|
||||||
m_hasDecimal(false),
|
, m_hasDecimal(false)
|
||||||
m_decPtIndex(0),
|
, m_decPtIndex(0)
|
||||||
m_decSymbol(decSymbol),
|
, m_decSymbol(decSymbol)
|
||||||
m_base(),
|
, m_base()
|
||||||
m_exponent()
|
, m_exponent()
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
bool TryToggleSign(bool isIntegerMode, std::wstring_view maxNumStr);
|
bool TryToggleSign(bool isIntegerMode, std::wstring_view maxNumStr);
|
||||||
bool TryAddDigit(unsigned int value, uint32_t radix, bool isIntegerMode, std::wstring_view maxNumStr, 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 TryAddDecimalPt();
|
||||||
bool HasDecimalPt();
|
bool HasDecimalPt();
|
||||||
bool TryBeginExponent();
|
bool TryBeginExponent();
|
||||||
|
|
|
@ -3,11 +3,13 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
bool IsOpInRange(WPARAM op, uint32_t x, uint32_t y);
|
using OpCode = uintptr_t;
|
||||||
bool IsBinOpCode(WPARAM opCode);
|
|
||||||
|
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
|
// 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
|
// of it and catch it themselves or not needing this
|
||||||
bool IsUnaryOpCode(WPARAM opCode);
|
bool IsUnaryOpCode(OpCode opCode);
|
||||||
bool IsDigitOpCode(WPARAM opCode);
|
bool IsDigitOpCode(OpCode opCode);
|
||||||
bool IsGuiSettingOpCode(WPARAM opCode);
|
bool IsGuiSettingOpCode(OpCode opCode);
|
||||||
|
|
|
@ -13,327 +13,281 @@
|
||||||
* Created: 13-Feb-2008
|
* Created: 13-Feb-2008
|
||||||
*
|
*
|
||||||
\****************************************************************************/
|
\****************************************************************************/
|
||||||
#define IDS_FIRSTENGSTR IDS_ENGINESTR_FIRST
|
|
||||||
|
|
||||||
#define IDS_DECIMAL 4
|
#pragma once
|
||||||
|
|
||||||
// All unary op function names for easy history reading
|
#include <string>
|
||||||
// This is where the first string after all the commands in order have been placed, should be placed
|
|
||||||
// keeping in consecutive helps us to allocate 1 string table and index them
|
|
||||||
#define IDS_FNSZFIRST (IDC_F -IDC_FIRSTCONTROL)+1
|
|
||||||
|
|
||||||
#define IDS_FRAC IDS_FNSZFIRST
|
inline constexpr auto IDS_ERRORS_FIRST = 99;
|
||||||
|
|
||||||
#define IDS_SIND IDS_FNSZFIRST+1
|
|
||||||
#define IDS_COSD IDS_FNSZFIRST+2
|
|
||||||
#define IDS_TAND IDS_FNSZFIRST+3
|
|
||||||
#define IDS_ASIND IDS_FNSZFIRST+4
|
|
||||||
#define IDS_ACOSD IDS_FNSZFIRST+5
|
|
||||||
#define IDS_ATAND IDS_FNSZFIRST+6
|
|
||||||
|
|
||||||
#define IDS_SINR IDS_FNSZFIRST+7
|
|
||||||
#define IDS_COSR IDS_FNSZFIRST+8
|
|
||||||
#define IDS_TANR IDS_FNSZFIRST+9
|
|
||||||
#define IDS_ASINR IDS_FNSZFIRST+10
|
|
||||||
#define IDS_ACOSR IDS_FNSZFIRST+11
|
|
||||||
#define IDS_ATANR IDS_FNSZFIRST+12
|
|
||||||
|
|
||||||
#define IDS_SING IDS_FNSZFIRST+13
|
|
||||||
#define IDS_COSG IDS_FNSZFIRST+14
|
|
||||||
#define IDS_TANG IDS_FNSZFIRST+15
|
|
||||||
#define IDS_ASING IDS_FNSZFIRST+16
|
|
||||||
#define IDS_ACOSG IDS_FNSZFIRST+17
|
|
||||||
#define IDS_ATANG IDS_FNSZFIRST+18
|
|
||||||
|
|
||||||
#define IDS_ASINH IDS_FNSZFIRST+19
|
|
||||||
#define IDS_ACOSH IDS_FNSZFIRST+20
|
|
||||||
#define IDS_ATANH IDS_FNSZFIRST+21
|
|
||||||
#define IDS_POWE IDS_FNSZFIRST+22
|
|
||||||
#define IDS_POW10 IDS_FNSZFIRST+23
|
|
||||||
#define IDS_SQRT IDS_FNSZFIRST+24
|
|
||||||
#define IDS_SQR IDS_FNSZFIRST+25
|
|
||||||
#define IDS_CUBE IDS_FNSZFIRST+26
|
|
||||||
#define IDS_CUBERT IDS_FNSZFIRST+27
|
|
||||||
#define IDS_FACT IDS_FNSZFIRST+28
|
|
||||||
#define IDS_REC IDS_FNSZFIRST+29
|
|
||||||
#define IDS_DEGREES IDS_FNSZFIRST+30
|
|
||||||
#define IDS_NEGATE IDS_FNSZFIRST+31
|
|
||||||
#define IDS_RSH IDS_FNSZFIRST+32
|
|
||||||
|
|
||||||
#define IDS_FNSZLAST IDS_RSH
|
|
||||||
|
|
||||||
#define IDS_ERRORS_FIRST IDS_FNSZLAST+1
|
|
||||||
|
|
||||||
// This is the list of error strings corresponding to SCERR_DIVIDEZERO..
|
// This is the list of error strings corresponding to SCERR_DIVIDEZERO..
|
||||||
|
|
||||||
#define IDS_DIVBYZERO IDS_ERRORS_FIRST
|
inline constexpr auto IDS_DIVBYZERO = IDS_ERRORS_FIRST;
|
||||||
#define IDS_DOMAIN IDS_ERRORS_FIRST+1
|
inline constexpr auto IDS_DOMAIN = IDS_ERRORS_FIRST + 1;
|
||||||
#define IDS_UNDEFINED IDS_ERRORS_FIRST+2
|
inline constexpr auto IDS_UNDEFINED = IDS_ERRORS_FIRST + 2;
|
||||||
#define IDS_POS_INFINITY IDS_ERRORS_FIRST+3
|
inline constexpr auto IDS_POS_INFINITY = IDS_ERRORS_FIRST + 3;
|
||||||
#define IDS_NEG_INFINITY IDS_ERRORS_FIRST+4
|
inline constexpr auto IDS_NEG_INFINITY = IDS_ERRORS_FIRST + 4;
|
||||||
#define IDS_NOMEM IDS_ERRORS_FIRST+6
|
inline constexpr auto IDS_NOMEM = IDS_ERRORS_FIRST + 6;
|
||||||
#define IDS_TOOMANY IDS_ERRORS_FIRST+7
|
inline constexpr auto IDS_TOOMANY = IDS_ERRORS_FIRST + 7;
|
||||||
#define IDS_OVERFLOW IDS_ERRORS_FIRST+8
|
inline constexpr auto IDS_OVERFLOW = IDS_ERRORS_FIRST + 8;
|
||||||
#define IDS_NORESULT IDS_ERRORS_FIRST+9
|
inline constexpr auto IDS_NORESULT = IDS_ERRORS_FIRST + 9;
|
||||||
#define IDS_INSUFFICIENT_DATA IDS_ERRORS_FIRST+10
|
inline constexpr auto IDS_INSUFFICIENT_DATA = IDS_ERRORS_FIRST + 10;
|
||||||
|
|
||||||
#define CSTRINGSENGMAX IDS_INSUFFICIENT_DATA+1
|
inline constexpr auto CSTRINGSENGMAX = IDS_INSUFFICIENT_DATA + 1;
|
||||||
|
|
||||||
// Arithmetic expression evaluator error strings
|
// Arithmetic expression evaluator error strings
|
||||||
#define IDS_ERR_UNK_CH CSTRINGSENGMAX+1
|
inline constexpr auto IDS_ERR_UNK_CH = CSTRINGSENGMAX + 1;
|
||||||
#define IDS_ERR_UNK_FN CSTRINGSENGMAX+2
|
inline constexpr auto IDS_ERR_UNK_FN = CSTRINGSENGMAX + 2;
|
||||||
#define IDS_ERR_UNEX_NUM CSTRINGSENGMAX+3
|
inline constexpr auto IDS_ERR_UNEX_NUM = CSTRINGSENGMAX + 3;
|
||||||
#define IDS_ERR_UNEX_CH CSTRINGSENGMAX+4
|
inline constexpr auto IDS_ERR_UNEX_CH = CSTRINGSENGMAX + 4;
|
||||||
#define IDS_ERR_UNEX_SZ CSTRINGSENGMAX+5
|
inline constexpr auto IDS_ERR_UNEX_SZ = CSTRINGSENGMAX + 5;
|
||||||
#define IDS_ERR_MISMATCH_CLOSE CSTRINGSENGMAX+6
|
inline constexpr auto IDS_ERR_MISMATCH_CLOSE = CSTRINGSENGMAX + 6;
|
||||||
#define IDS_ERR_UNEX_END CSTRINGSENGMAX+7
|
inline constexpr auto IDS_ERR_UNEX_END = CSTRINGSENGMAX + 7;
|
||||||
#define IDS_ERR_SG_INV_ERROR CSTRINGSENGMAX+8
|
inline constexpr auto IDS_ERR_SG_INV_ERROR = CSTRINGSENGMAX + 8;
|
||||||
#define IDS_ERR_INPUT_OVERFLOW CSTRINGSENGMAX+9
|
inline constexpr auto IDS_ERR_INPUT_OVERFLOW = CSTRINGSENGMAX + 9;
|
||||||
#define IDS_ERR_OUTPUT_OVERFLOW CSTRINGSENGMAX+10
|
inline constexpr auto IDS_ERR_OUTPUT_OVERFLOW = CSTRINGSENGMAX + 10;
|
||||||
|
|
||||||
|
// Resource keys for CEngineStrings.resw
|
||||||
#define SIDS_PLUS_MINUS L"0"
|
inline constexpr auto SIDS_PLUS_MINUS = L"0";
|
||||||
#define SIDS_CLEAR L"1"
|
inline constexpr auto SIDS_CLEAR = L"1";
|
||||||
#define SIDS_CE L"2"
|
inline constexpr auto SIDS_CE = L"2";
|
||||||
#define SIDS_BACKSPACE L"3"
|
inline constexpr auto SIDS_BACKSPACE = L"3";
|
||||||
#define SIDS_DECIMAL_SEPARATOR L"4"
|
inline constexpr auto SIDS_DECIMAL_SEPARATOR = L"4";
|
||||||
#define SIDS_EMPTY_STRING L"5"
|
inline constexpr auto SIDS_EMPTY_STRING = L"5";
|
||||||
#define SIDS_AND L"6"
|
inline constexpr auto SIDS_AND = L"6";
|
||||||
#define SIDS_OR L"7"
|
inline constexpr auto SIDS_OR = L"7";
|
||||||
#define SIDS_XOR L"8"
|
inline constexpr auto SIDS_XOR = L"8";
|
||||||
#define SIDS_LSH L"9"
|
inline constexpr auto SIDS_LSH = L"9";
|
||||||
#define SIDS_RSH L"10"
|
inline constexpr auto SIDS_RSH = L"10";
|
||||||
#define SIDS_DIVIDE L"11"
|
inline constexpr auto SIDS_DIVIDE = L"11";
|
||||||
#define SIDS_MULTIPLY L"12"
|
inline constexpr auto SIDS_MULTIPLY = L"12";
|
||||||
#define SIDS_PLUS L"13"
|
inline constexpr auto SIDS_PLUS = L"13";
|
||||||
#define SIDS_MINUS L"14"
|
inline constexpr auto SIDS_MINUS = L"14";
|
||||||
#define SIDS_MOD L"15"
|
inline constexpr auto SIDS_MOD = L"15";
|
||||||
#define SIDS_YROOT L"16"
|
inline constexpr auto SIDS_YROOT = L"16";
|
||||||
#define SIDS_POW_HAT L"17"
|
inline constexpr auto SIDS_POW_HAT = L"17";
|
||||||
#define SIDS_INT L"18"
|
inline constexpr auto SIDS_INT = L"18";
|
||||||
#define SIDS_ROL L"19"
|
inline constexpr auto SIDS_ROL = L"19";
|
||||||
#define SIDS_ROR L"20"
|
inline constexpr auto SIDS_ROR = L"20";
|
||||||
#define SIDS_NOT L"21"
|
inline constexpr auto SIDS_NOT = L"21";
|
||||||
#define SIDS_SIN L"22"
|
inline constexpr auto SIDS_SIN = L"22";
|
||||||
#define SIDS_COS L"23"
|
inline constexpr auto SIDS_COS = L"23";
|
||||||
#define SIDS_TAN L"24"
|
inline constexpr auto SIDS_TAN = L"24";
|
||||||
#define SIDS_SINH L"25"
|
inline constexpr auto SIDS_SINH = L"25";
|
||||||
#define SIDS_COSH L"26"
|
inline constexpr auto SIDS_COSH = L"26";
|
||||||
#define SIDS_TANH L"27"
|
inline constexpr auto SIDS_TANH = L"27";
|
||||||
#define SIDS_LN L"28"
|
inline constexpr auto SIDS_LN = L"28";
|
||||||
#define SIDS_LOG L"29"
|
inline constexpr auto SIDS_LOG = L"29";
|
||||||
#define SIDS_SQRT L"30"
|
inline constexpr auto SIDS_SQRT = L"30";
|
||||||
#define SIDS_XPOW2 L"31"
|
inline constexpr auto SIDS_XPOW2 = L"31";
|
||||||
#define SIDS_XPOW3 L"32"
|
inline constexpr auto SIDS_XPOW3 = L"32";
|
||||||
#define SIDS_NFACTORIAL L"33"
|
inline constexpr auto SIDS_NFACTORIAL = L"33";
|
||||||
#define SIDS_RECIPROCAL L"34"
|
inline constexpr auto SIDS_RECIPROCAL = L"34";
|
||||||
#define SIDS_DMS L"35"
|
inline constexpr auto SIDS_DMS = L"35";
|
||||||
#define SIDS_CUBEROOT L"36"
|
inline constexpr auto SIDS_CUBEROOT = L"36";
|
||||||
#define SIDS_POWTEN L"37"
|
inline constexpr auto SIDS_POWTEN = L"37";
|
||||||
#define SIDS_PERCENT L"38"
|
inline constexpr auto SIDS_PERCENT = L"38";
|
||||||
#define SIDS_SCIENTIFIC_NOTATION L"39"
|
inline constexpr auto SIDS_SCIENTIFIC_NOTATION = L"39";
|
||||||
#define SIDS_PI L"40"
|
inline constexpr auto SIDS_PI = L"40";
|
||||||
#define SIDS_EQUAL L"41"
|
inline constexpr auto SIDS_EQUAL = L"41";
|
||||||
#define SIDS_MC L"42"
|
inline constexpr auto SIDS_MC = L"42";
|
||||||
#define SIDS_MR L"43"
|
inline constexpr auto SIDS_MR = L"43";
|
||||||
#define SIDS_MS L"44"
|
inline constexpr auto SIDS_MS = L"44";
|
||||||
#define SIDS_MPLUS L"45"
|
inline constexpr auto SIDS_MPLUS = L"45";
|
||||||
#define SIDS_MMINUS L"46"
|
inline constexpr auto SIDS_MMINUS = L"46";
|
||||||
#define SIDS_EXP L"47"
|
inline constexpr auto SIDS_EXP = L"47";
|
||||||
#define SIDS_OPEN_PAREN L"48"
|
inline constexpr auto SIDS_OPEN_PAREN = L"48";
|
||||||
#define SIDS_CLOSE_PAREN L"49"
|
inline constexpr auto SIDS_CLOSE_PAREN = L"49";
|
||||||
#define SIDS_0 L"50"
|
inline constexpr auto SIDS_0 = L"50";
|
||||||
#define SIDS_1 L"51"
|
inline constexpr auto SIDS_1 = L"51";
|
||||||
#define SIDS_2 L"52"
|
inline constexpr auto SIDS_2 = L"52";
|
||||||
#define SIDS_3 L"53"
|
inline constexpr auto SIDS_3 = L"53";
|
||||||
#define SIDS_4 L"54"
|
inline constexpr auto SIDS_4 = L"54";
|
||||||
#define SIDS_5 L"55"
|
inline constexpr auto SIDS_5 = L"55";
|
||||||
#define SIDS_6 L"56"
|
inline constexpr auto SIDS_6 = L"56";
|
||||||
#define SIDS_7 L"57"
|
inline constexpr auto SIDS_7 = L"57";
|
||||||
#define SIDS_8 L"58"
|
inline constexpr auto SIDS_8 = L"58";
|
||||||
#define SIDS_9 L"59"
|
inline constexpr auto SIDS_9 = L"59";
|
||||||
#define SIDS_A L"60"
|
inline constexpr auto SIDS_A = L"60";
|
||||||
#define SIDS_B L"61"
|
inline constexpr auto SIDS_B = L"61";
|
||||||
#define SIDS_C L"62"
|
inline constexpr auto SIDS_C = L"62";
|
||||||
#define SIDS_D L"63"
|
inline constexpr auto SIDS_D = L"63";
|
||||||
#define SIDS_E L"64"
|
inline constexpr auto SIDS_E = L"64";
|
||||||
#define SIDS_F L"65"
|
inline constexpr auto SIDS_F = L"65";
|
||||||
#define SIDS_FRAC L"66"
|
inline constexpr auto SIDS_FRAC = L"66";
|
||||||
#define SIDS_SIND L"67"
|
inline constexpr auto SIDS_SIND = L"67";
|
||||||
#define SIDS_COSD L"68"
|
inline constexpr auto SIDS_COSD = L"68";
|
||||||
#define SIDS_TAND L"69"
|
inline constexpr auto SIDS_TAND = L"69";
|
||||||
#define SIDS_ASIND L"70"
|
inline constexpr auto SIDS_ASIND = L"70";
|
||||||
#define SIDS_ACOSD L"71"
|
inline constexpr auto SIDS_ACOSD = L"71";
|
||||||
#define SIDS_ATAND L"72"
|
inline constexpr auto SIDS_ATAND = L"72";
|
||||||
#define SIDS_SINR L"73"
|
inline constexpr auto SIDS_SINR = L"73";
|
||||||
#define SIDS_COSR L"74"
|
inline constexpr auto SIDS_COSR = L"74";
|
||||||
#define SIDS_TANR L"75"
|
inline constexpr auto SIDS_TANR = L"75";
|
||||||
#define SIDS_ASINR L"76"
|
inline constexpr auto SIDS_ASINR = L"76";
|
||||||
#define SIDS_ACOSR L"77"
|
inline constexpr auto SIDS_ACOSR = L"77";
|
||||||
#define SIDS_ATANR L"78"
|
inline constexpr auto SIDS_ATANR = L"78";
|
||||||
#define SIDS_SING L"79"
|
inline constexpr auto SIDS_SING = L"79";
|
||||||
#define SIDS_COSG L"80"
|
inline constexpr auto SIDS_COSG = L"80";
|
||||||
#define SIDS_TANG L"81"
|
inline constexpr auto SIDS_TANG = L"81";
|
||||||
#define SIDS_ASING L"82"
|
inline constexpr auto SIDS_ASING = L"82";
|
||||||
#define SIDS_ACOSG L"83"
|
inline constexpr auto SIDS_ACOSG = L"83";
|
||||||
#define SIDS_ATANG L"84"
|
inline constexpr auto SIDS_ATANG = L"84";
|
||||||
#define SIDS_ASINH L"85"
|
inline constexpr auto SIDS_ASINH = L"85";
|
||||||
#define SIDS_ACOSH L"86"
|
inline constexpr auto SIDS_ACOSH = L"86";
|
||||||
#define SIDS_ATANH L"87"
|
inline constexpr auto SIDS_ATANH = L"87";
|
||||||
#define SIDS_POWE L"88"
|
inline constexpr auto SIDS_POWE = L"88";
|
||||||
#define SIDS_POWTEN2 L"89"
|
inline constexpr auto SIDS_POWTEN2 = L"89";
|
||||||
#define SIDS_SQRT2 L"90"
|
inline constexpr auto SIDS_SQRT2 = L"90";
|
||||||
#define SIDS_SQR L"91"
|
inline constexpr auto SIDS_SQR = L"91";
|
||||||
#define SIDS_CUBE L"92"
|
inline constexpr auto SIDS_CUBE = L"92";
|
||||||
#define SIDS_CUBERT L"93"
|
inline constexpr auto SIDS_CUBERT = L"93";
|
||||||
#define SIDS_FACT L"94"
|
inline constexpr auto SIDS_FACT = L"94";
|
||||||
#define SIDS_RECIPROC L"95"
|
inline constexpr auto SIDS_RECIPROC = L"95";
|
||||||
#define SIDS_DEGREES L"96"
|
inline constexpr auto SIDS_DEGREES = L"96";
|
||||||
#define SIDS_NEGATE L"97"
|
inline constexpr auto SIDS_NEGATE = L"97";
|
||||||
#define SIDS_RSH2 L"98"
|
inline constexpr auto SIDS_RSH2 = L"98";
|
||||||
#define SIDS_DIVIDEBYZERO L"99"
|
inline constexpr auto SIDS_DIVIDEBYZERO = L"99";
|
||||||
#define SIDS_DOMAIN L"100"
|
inline constexpr auto SIDS_DOMAIN = L"100";
|
||||||
#define SIDS_UNDEFINED L"101"
|
inline constexpr auto SIDS_UNDEFINED = L"101";
|
||||||
#define SIDS_POS_INFINITY L"102"
|
inline constexpr auto SIDS_POS_INFINITY = L"102";
|
||||||
#define SIDS_NEG_INFINITY L"103"
|
inline constexpr auto SIDS_NEG_INFINITY = L"103";
|
||||||
#define SIDS_ABORTED L"104"
|
inline constexpr auto SIDS_ABORTED = L"104";
|
||||||
#define SIDS_NOMEM L"105"
|
inline constexpr auto SIDS_NOMEM = L"105";
|
||||||
#define SIDS_TOOMANY L"106"
|
inline constexpr auto SIDS_TOOMANY = L"106";
|
||||||
#define SIDS_OVERFLOW L"107"
|
inline constexpr auto SIDS_OVERFLOW = L"107";
|
||||||
#define SIDS_NORESULT L"108"
|
inline constexpr auto SIDS_NORESULT = L"108";
|
||||||
#define SIDS_INSUFFICIENT_DATA L"109"
|
inline constexpr auto SIDS_INSUFFICIENT_DATA = L"109";
|
||||||
// 110 is skipped by CSTRINGSENGMAX
|
// 110 is skipped by CSTRINGSENGMAX
|
||||||
#define SIDS_ERR_UNK_CH L"111"
|
inline constexpr auto SIDS_ERR_UNK_CH = L"111";
|
||||||
#define SIDS_ERR_UNK_FN L"112"
|
inline constexpr auto SIDS_ERR_UNK_FN = L"112";
|
||||||
#define SIDS_ERR_UNEX_NUM L"113"
|
inline constexpr auto SIDS_ERR_UNEX_NUM = L"113";
|
||||||
#define SIDS_ERR_UNEX_CH L"114"
|
inline constexpr auto SIDS_ERR_UNEX_CH = L"114";
|
||||||
#define SIDS_ERR_UNEX_SZ L"115"
|
inline constexpr auto SIDS_ERR_UNEX_SZ = L"115";
|
||||||
#define SIDS_ERR_MISMATCH_CLOSE L"116"
|
inline constexpr auto SIDS_ERR_MISMATCH_CLOSE = L"116";
|
||||||
#define SIDS_ERR_UNEX_END L"117"
|
inline constexpr auto SIDS_ERR_UNEX_END = L"117";
|
||||||
#define SIDS_ERR_SG_INV_ERROR L"118"
|
inline constexpr auto SIDS_ERR_SG_INV_ERROR = L"118";
|
||||||
#define SIDS_ERR_INPUT_OVERFLOW L"119"
|
inline constexpr auto SIDS_ERR_INPUT_OVERFLOW = L"119";
|
||||||
#define SIDS_ERR_OUTPUT_OVERFLOW L"120"
|
inline constexpr auto SIDS_ERR_OUTPUT_OVERFLOW = L"120";
|
||||||
|
|
||||||
__declspec(selectany) std::wstring g_sids[] =
|
// Include the resource key ID from above into this vector to load it into memory for the engine to use
|
||||||
{
|
inline constexpr std::array<std::wstring_view, 120> g_sids = { SIDS_PLUS_MINUS,
|
||||||
std::wstring(SIDS_PLUS_MINUS),
|
SIDS_C,
|
||||||
std::wstring(SIDS_C),
|
SIDS_CE,
|
||||||
std::wstring(SIDS_CE),
|
SIDS_BACKSPACE,
|
||||||
std::wstring(SIDS_BACKSPACE),
|
SIDS_DECIMAL_SEPARATOR,
|
||||||
std::wstring(SIDS_DECIMAL_SEPARATOR),
|
SIDS_EMPTY_STRING,
|
||||||
std::wstring(SIDS_EMPTY_STRING),
|
SIDS_AND,
|
||||||
std::wstring(SIDS_AND),
|
SIDS_OR,
|
||||||
std::wstring(SIDS_OR),
|
SIDS_XOR,
|
||||||
std::wstring(SIDS_XOR),
|
SIDS_LSH,
|
||||||
std::wstring(SIDS_LSH),
|
SIDS_RSH,
|
||||||
std::wstring(SIDS_RSH),
|
SIDS_DIVIDE,
|
||||||
std::wstring(SIDS_DIVIDE),
|
SIDS_MULTIPLY,
|
||||||
std::wstring(SIDS_MULTIPLY),
|
SIDS_PLUS,
|
||||||
std::wstring(SIDS_PLUS),
|
SIDS_MINUS,
|
||||||
std::wstring(SIDS_MINUS),
|
SIDS_MOD,
|
||||||
std::wstring(SIDS_MOD),
|
SIDS_YROOT,
|
||||||
std::wstring(SIDS_YROOT),
|
SIDS_POW_HAT,
|
||||||
std::wstring(SIDS_POW_HAT),
|
SIDS_INT,
|
||||||
std::wstring(SIDS_INT),
|
SIDS_ROL,
|
||||||
std::wstring(SIDS_ROL),
|
SIDS_ROR,
|
||||||
std::wstring(SIDS_ROR),
|
SIDS_NOT,
|
||||||
std::wstring(SIDS_NOT),
|
SIDS_SIN,
|
||||||
std::wstring(SIDS_SIN),
|
SIDS_COS,
|
||||||
std::wstring(SIDS_COS),
|
SIDS_TAN,
|
||||||
std::wstring(SIDS_TAN),
|
SIDS_SINH,
|
||||||
std::wstring(SIDS_SINH),
|
SIDS_COSH,
|
||||||
std::wstring(SIDS_COSH),
|
SIDS_TANH,
|
||||||
std::wstring(SIDS_TANH),
|
SIDS_LN,
|
||||||
std::wstring(SIDS_LN),
|
SIDS_LOG,
|
||||||
std::wstring(SIDS_LOG),
|
SIDS_SQRT,
|
||||||
std::wstring(SIDS_SQRT),
|
SIDS_XPOW2,
|
||||||
std::wstring(SIDS_XPOW2),
|
SIDS_XPOW3,
|
||||||
std::wstring(SIDS_XPOW3),
|
SIDS_NFACTORIAL,
|
||||||
std::wstring(SIDS_NFACTORIAL),
|
SIDS_RECIPROCAL,
|
||||||
std::wstring(SIDS_RECIPROCAL),
|
SIDS_DMS,
|
||||||
std::wstring(SIDS_DMS),
|
SIDS_CUBEROOT,
|
||||||
std::wstring(SIDS_CUBEROOT),
|
SIDS_POWTEN,
|
||||||
std::wstring(SIDS_POWTEN),
|
SIDS_PERCENT,
|
||||||
std::wstring(SIDS_PERCENT),
|
SIDS_SCIENTIFIC_NOTATION,
|
||||||
std::wstring(SIDS_SCIENTIFIC_NOTATION),
|
SIDS_PI,
|
||||||
std::wstring(SIDS_PI),
|
SIDS_EQUAL,
|
||||||
std::wstring(SIDS_EQUAL),
|
SIDS_MC,
|
||||||
std::wstring(SIDS_MC),
|
SIDS_MR,
|
||||||
std::wstring(SIDS_MR),
|
SIDS_MS,
|
||||||
std::wstring(SIDS_MS),
|
SIDS_MPLUS,
|
||||||
std::wstring(SIDS_MPLUS),
|
SIDS_MMINUS,
|
||||||
std::wstring(SIDS_MMINUS),
|
SIDS_EXP,
|
||||||
std::wstring(SIDS_EXP),
|
SIDS_OPEN_PAREN,
|
||||||
std::wstring(SIDS_OPEN_PAREN),
|
SIDS_CLOSE_PAREN,
|
||||||
std::wstring(SIDS_CLOSE_PAREN),
|
SIDS_0,
|
||||||
std::wstring(SIDS_0),
|
SIDS_1,
|
||||||
std::wstring(SIDS_1),
|
SIDS_2,
|
||||||
std::wstring(SIDS_2),
|
SIDS_3,
|
||||||
std::wstring(SIDS_3),
|
SIDS_4,
|
||||||
std::wstring(SIDS_4),
|
SIDS_5,
|
||||||
std::wstring(SIDS_5),
|
SIDS_6,
|
||||||
std::wstring(SIDS_6),
|
SIDS_7,
|
||||||
std::wstring(SIDS_7),
|
SIDS_8,
|
||||||
std::wstring(SIDS_8),
|
SIDS_9,
|
||||||
std::wstring(SIDS_9),
|
SIDS_A,
|
||||||
std::wstring(SIDS_A),
|
SIDS_B,
|
||||||
std::wstring(SIDS_B),
|
SIDS_C,
|
||||||
std::wstring(SIDS_C),
|
SIDS_D,
|
||||||
std::wstring(SIDS_D),
|
SIDS_E,
|
||||||
std::wstring(SIDS_E),
|
SIDS_F,
|
||||||
std::wstring(SIDS_F),
|
SIDS_FRAC,
|
||||||
std::wstring(SIDS_FRAC),
|
SIDS_SIND,
|
||||||
std::wstring(SIDS_SIND),
|
SIDS_COSD,
|
||||||
std::wstring(SIDS_COSD),
|
SIDS_TAND,
|
||||||
std::wstring(SIDS_TAND),
|
SIDS_ASIND,
|
||||||
std::wstring(SIDS_ASIND),
|
SIDS_ACOSD,
|
||||||
std::wstring(SIDS_ACOSD),
|
SIDS_ATAND,
|
||||||
std::wstring(SIDS_ATAND),
|
SIDS_SINR,
|
||||||
std::wstring(SIDS_SINR),
|
SIDS_COSR,
|
||||||
std::wstring(SIDS_COSR),
|
SIDS_TANR,
|
||||||
std::wstring(SIDS_TANR),
|
SIDS_ASINR,
|
||||||
std::wstring(SIDS_ASINR),
|
SIDS_ACOSR,
|
||||||
std::wstring(SIDS_ACOSR),
|
SIDS_ATANR,
|
||||||
std::wstring(SIDS_ATANR),
|
SIDS_SING,
|
||||||
std::wstring(SIDS_SING),
|
SIDS_COSG,
|
||||||
std::wstring(SIDS_COSG),
|
SIDS_TANG,
|
||||||
std::wstring(SIDS_TANG),
|
SIDS_ASING,
|
||||||
std::wstring(SIDS_ASING),
|
SIDS_ACOSG,
|
||||||
std::wstring(SIDS_ACOSG),
|
SIDS_ATANG,
|
||||||
std::wstring(SIDS_ATANG),
|
SIDS_ASINH,
|
||||||
std::wstring(SIDS_ASINH),
|
SIDS_ACOSH,
|
||||||
std::wstring(SIDS_ACOSH),
|
SIDS_ATANH,
|
||||||
std::wstring(SIDS_ATANH),
|
SIDS_POWE,
|
||||||
std::wstring(SIDS_POWE),
|
SIDS_POWTEN2,
|
||||||
std::wstring(SIDS_POWTEN2),
|
SIDS_SQRT2,
|
||||||
std::wstring(SIDS_SQRT2),
|
SIDS_SQR,
|
||||||
std::wstring(SIDS_SQR),
|
SIDS_CUBE,
|
||||||
std::wstring(SIDS_CUBE),
|
SIDS_CUBERT,
|
||||||
std::wstring(SIDS_CUBERT),
|
SIDS_FACT,
|
||||||
std::wstring(SIDS_FACT),
|
SIDS_RECIPROC,
|
||||||
std::wstring(SIDS_RECIPROC),
|
SIDS_DEGREES,
|
||||||
std::wstring(SIDS_DEGREES),
|
SIDS_NEGATE,
|
||||||
std::wstring(SIDS_NEGATE),
|
SIDS_RSH,
|
||||||
std::wstring(SIDS_RSH),
|
SIDS_DIVIDEBYZERO,
|
||||||
std::wstring(SIDS_DIVIDEBYZERO),
|
SIDS_DOMAIN,
|
||||||
std::wstring(SIDS_DOMAIN),
|
SIDS_UNDEFINED,
|
||||||
std::wstring(SIDS_UNDEFINED),
|
SIDS_POS_INFINITY,
|
||||||
std::wstring(SIDS_POS_INFINITY),
|
SIDS_NEG_INFINITY,
|
||||||
std::wstring(SIDS_NEG_INFINITY),
|
SIDS_ABORTED,
|
||||||
std::wstring(SIDS_ABORTED),
|
SIDS_NOMEM,
|
||||||
std::wstring(SIDS_NOMEM),
|
SIDS_TOOMANY,
|
||||||
std::wstring(SIDS_TOOMANY),
|
SIDS_OVERFLOW,
|
||||||
std::wstring(SIDS_OVERFLOW),
|
SIDS_NORESULT,
|
||||||
std::wstring(SIDS_NORESULT),
|
SIDS_INSUFFICIENT_DATA,
|
||||||
std::wstring(SIDS_INSUFFICIENT_DATA),
|
SIDS_ERR_UNK_CH,
|
||||||
std::wstring(SIDS_ERR_UNK_CH),
|
SIDS_ERR_UNK_FN,
|
||||||
std::wstring(SIDS_ERR_UNK_FN),
|
SIDS_ERR_UNEX_NUM,
|
||||||
std::wstring(SIDS_ERR_UNEX_NUM),
|
SIDS_ERR_UNEX_CH,
|
||||||
std::wstring(SIDS_ERR_UNEX_CH),
|
SIDS_ERR_UNEX_SZ,
|
||||||
std::wstring(SIDS_ERR_UNEX_SZ),
|
SIDS_ERR_MISMATCH_CLOSE,
|
||||||
std::wstring(SIDS_ERR_MISMATCH_CLOSE),
|
SIDS_ERR_UNEX_END,
|
||||||
std::wstring(SIDS_ERR_UNEX_END),
|
SIDS_ERR_SG_INV_ERROR,
|
||||||
std::wstring(SIDS_ERR_SG_INV_ERROR),
|
SIDS_ERR_INPUT_OVERFLOW,
|
||||||
std::wstring(SIDS_ERR_INPUT_OVERFLOW),
|
SIDS_ERR_OUTPUT_OVERFLOW };
|
||||||
std::wstring(SIDS_ERR_OUTPUT_OVERFLOW)
|
|
||||||
};
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include "ICalcDisplay.h"
|
#include "ICalcDisplay.h"
|
||||||
#include "IHistoryDisplay.h"
|
#include "IHistoryDisplay.h"
|
||||||
#include "Rational.h"
|
#include "Rational.h"
|
||||||
|
@ -13,7 +14,8 @@ static constexpr size_t MAXPRECDEPTH = 25;
|
||||||
// Helper class really a internal class to CCalcEngine, to accumulate each history line of text by collecting the
|
// Helper class really a internal class to CCalcEngine, to accumulate each history line of text by collecting the
|
||||||
// operands, operator, unary operator etc. Since it is a separate entity, it can be unit tested on its own but does
|
// operands, operator, unary operator etc. Since it is a separate entity, it can be unit tested on its own but does
|
||||||
// rely on CCalcEngine calling it in appropriate order.
|
// rely on CCalcEngine calling it in appropriate order.
|
||||||
class CHistoryCollector {
|
class CHistoryCollector
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
CHistoryCollector(ICalcDisplay* pCalcDisplay, std::shared_ptr<IHistoryDisplay> pHistoryDisplay, wchar_t decimalSymbol); // Can throw errors
|
CHistoryCollector(ICalcDisplay* pCalcDisplay, std::shared_ptr<IHistoryDisplay> pHistoryDisplay, wchar_t decimalSymbol); // Can throw errors
|
||||||
~CHistoryCollector();
|
~CHistoryCollector();
|
||||||
|
@ -43,7 +45,8 @@ private:
|
||||||
// attaching the unary op around the last operand
|
// attaching the unary op around the last operand
|
||||||
int m_lastOpStartIndex; // index of the beginning of the last operand added to the history
|
int m_lastOpStartIndex; // index of the beginning of the last operand added to the history
|
||||||
int m_lastBinOpStartIndex; // index of the beginning of the last binary operator added to the history
|
int m_lastBinOpStartIndex; // index of the beginning of the last binary operator added to the history
|
||||||
std::array<int, MAXPRECDEPTH> m_operandIndices; // Stack of index of opnd's beginning for each '('. A parallel array to m_hnoParNum, but abstracted independently of that
|
std::array<int, MAXPRECDEPTH>
|
||||||
|
m_operandIndices; // Stack of index of opnd's beginning for each '('. A parallel array to m_hnoParNum, but abstracted independently of that
|
||||||
int m_curOperandIndex; // Stack index for the above stack
|
int m_curOperandIndex; // Stack index for the above stack
|
||||||
bool m_bLastOpndBrace; // iff the last opnd in history is already braced so we can avoid putting another one for unary operator
|
bool m_bLastOpndBrace; // iff the last opnd in history is already braced so we can avoid putting another one for unary operator
|
||||||
wchar_t m_decimalSymbol;
|
wchar_t m_decimalSymbol;
|
||||||
|
|
|
@ -7,12 +7,16 @@
|
||||||
#include "../ExpressionCommandInterface.h"
|
#include "../ExpressionCommandInterface.h"
|
||||||
|
|
||||||
// Callback interface to be implemented by the clients of CCalcEngine
|
// Callback interface to be implemented by the clients of CCalcEngine
|
||||||
class ICalcDisplay {
|
class ICalcDisplay
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
virtual void SetPrimaryDisplay(const std::wstring& pszText, bool isError) = 0;
|
virtual void SetPrimaryDisplay(const std::wstring& pszText, bool isError) = 0;
|
||||||
virtual void SetIsInError(bool isInError) = 0;
|
virtual void SetIsInError(bool isInError) = 0;
|
||||||
virtual void SetExpressionDisplay(_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const &tokens, _Inout_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const &commands) = 0;
|
virtual void SetExpressionDisplay(
|
||||||
virtual void SetParenDisplayText(const std::wstring& pszText) = 0;
|
_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const& tokens,
|
||||||
|
_Inout_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const& commands) = 0;
|
||||||
|
virtual void SetParenthesisNumber(_In_ unsigned int count) = 0;
|
||||||
|
virtual void OnNoRightParenAdded() = 0;
|
||||||
virtual void MaxDigitsReached() = 0; // not an error but still need to inform UI layer.
|
virtual void MaxDigitsReached() = 0; // not an error but still need to inform UI layer.
|
||||||
virtual void BinaryOperatorReceived() = 0;
|
virtual void BinaryOperatorReceived() = 0;
|
||||||
virtual void OnHistoryItemAdded(_In_ unsigned int addedItemIndex) = 0;
|
virtual void OnHistoryItemAdded(_In_ unsigned int addedItemIndex) = 0;
|
||||||
|
|
|
@ -4,8 +4,12 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// Callback interface to be implemented by the clients of CCalcEngine if they require equation history
|
// Callback interface to be implemented by the clients of CCalcEngine if they require equation history
|
||||||
class IHistoryDisplay {
|
class IHistoryDisplay
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~IHistoryDisplay(){};
|
virtual ~IHistoryDisplay(){};
|
||||||
virtual unsigned int AddToHistory(_In_ std::shared_ptr<CalculatorVector <std::pair<std::wstring, int>>> const &tokens, _In_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const &commands, _In_ std::wstring_view result) = 0;
|
virtual unsigned int AddToHistory(
|
||||||
|
_In_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const& tokens,
|
||||||
|
_In_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const& commands,
|
||||||
|
_In_ std::wstring_view result) = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
#include "Ratpack/ratpak.h"
|
#include "Ratpack/ratpak.h"
|
||||||
|
|
||||||
namespace CalcEngine
|
namespace CalcEngine
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// This is expected to be in same order as IDM_HEX, IDM_DEC, IDM_OCT, IDM_BIN
|
// This is expected to be in same order as IDM_HEX, IDM_DEC, IDM_OCT, IDM_BIN
|
||||||
enum eRADIX_TYPE {
|
enum eRADIX_TYPE
|
||||||
|
{
|
||||||
HEX_RADIX,
|
HEX_RADIX,
|
||||||
DEC_RADIX,
|
DEC_RADIX,
|
||||||
OCT_RADIX,
|
OCT_RADIX,
|
||||||
|
|
|
@ -13,6 +13,7 @@ namespace CalcEngine::RationalMath
|
||||||
Rational Pow(Rational const& base, Rational const& pow);
|
Rational Pow(Rational const& base, Rational const& pow);
|
||||||
Rational Root(Rational const& base, Rational const& root);
|
Rational Root(Rational const& base, Rational const& root);
|
||||||
Rational Fact(Rational const& rat);
|
Rational Fact(Rational const& rat);
|
||||||
|
Rational Mod(Rational const& a, Rational const& b);
|
||||||
|
|
||||||
Rational Exp(Rational const& rat);
|
Rational Exp(Rational const& rat);
|
||||||
Rational Log(Rational const& rat);
|
Rational Log(Rational const& rat);
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
// CalcErr.h
|
// CalcErr.h
|
||||||
//
|
//
|
||||||
// Defines the error codes thrown by ratpak and caught by Calculator
|
// Defines the error codes thrown by ratpak and caught by Calculator
|
||||||
|
@ -24,7 +26,7 @@
|
||||||
// R - Reserved - not currently used for anything
|
// R - Reserved - not currently used for anything
|
||||||
//
|
//
|
||||||
// r - reserved portion of the facility code. Reserved for internal
|
// 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.
|
// values, but are instead message ids for display strings.
|
||||||
//
|
//
|
||||||
// Facility - is the facility code
|
// Facility - is the facility code
|
||||||
|
@ -34,49 +36,50 @@
|
||||||
// This format is based loosely on an OLE HRESULT and is compatible with the
|
// This format is based loosely on an OLE HRESULT and is compatible with the
|
||||||
// SUCCEEDED and FAILED macros as well as the HRESULT_CODE macro
|
// SUCCEEDED and FAILED macros as well as the HRESULT_CODE macro
|
||||||
|
|
||||||
|
typedef int32_t ResultCode;
|
||||||
|
|
||||||
// CALC_E_DIVIDEBYZERO
|
// CALC_E_DIVIDEBYZERO
|
||||||
//
|
//
|
||||||
// The current operation would require a divide by zero to complete
|
// 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
|
// CALC_E_DOMAIN
|
||||||
//
|
//
|
||||||
// The given input is not within the domain of this function
|
// 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
|
// CALC_E_INDEFINITE
|
||||||
//
|
//
|
||||||
// The result of this function is undefined
|
// The result of this function is undefined
|
||||||
#define CALC_E_INDEFINITE ((DWORD)0x80000002)
|
#define CALC_E_INDEFINITE ((uint32_t)0x80000002)
|
||||||
|
|
||||||
// CALC_E_POSINFINITY
|
// CALC_E_POSINFINITY
|
||||||
//
|
//
|
||||||
// The result of this function is Positive Infinity.
|
// The result of this function is Positive Infinity.
|
||||||
#define CALC_E_POSINFINITY ((DWORD)0x80000003)
|
#define CALC_E_POSINFINITY ((uint32_t)0x80000003)
|
||||||
|
|
||||||
// CALC_E_NEGINFINITY
|
// CALC_E_NEGINFINITY
|
||||||
//
|
//
|
||||||
// The result of this function is Negative Infinity
|
// The result of this function is Negative Infinity
|
||||||
#define CALC_E_NEGINFINITY ((DWORD)0x80000004)
|
#define CALC_E_NEGINFINITY ((uint32_t)0x80000004)
|
||||||
|
|
||||||
// CALC_E_INVALIDRANGE
|
// CALC_E_INVALIDRANGE
|
||||||
//
|
//
|
||||||
// The given input is within the domain of the function but is beyond
|
// The given input is within the domain of the function but is beyond
|
||||||
// the range for which calc can successfully compute the answer
|
// 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
|
// CALC_E_OUTOFMEMORY
|
||||||
//
|
//
|
||||||
// There is not enough free memory to complete the requested function
|
// 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
|
// CALC_E_OVERFLOW
|
||||||
//
|
//
|
||||||
// The result of this operation is an 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
|
// CALC_E_NORESULT
|
||||||
//
|
//
|
||||||
// The result of this operation is undefined
|
// The result of this operation is undefined
|
||||||
#define CALC_E_NORESULT ((DWORD)0x80000009)
|
#define CALC_E_NORESULT ((uint32_t)0x80000009)
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,8 @@
|
||||||
// internal base is a power of 2.
|
// internal base is a power of 2.
|
||||||
//
|
//
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#include "pch.h"
|
|
||||||
#include "ratpak.h"
|
#include "ratpak.h"
|
||||||
|
#include <cstring> // for memmove
|
||||||
|
|
||||||
void _mulnumx(PNUMBER* pa, PNUMBER b);
|
void _mulnumx(PNUMBER* pa, PNUMBER b);
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ void __inline mulnumx( PNUMBER *pa, PNUMBER b )
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// if pa is one and b isn't just copy b. and adjust the sign.
|
// if pa is one and b isn't just copy b. and adjust the sign.
|
||||||
long sign = (*pa)->sign;
|
int32_t sign = (*pa)->sign;
|
||||||
DUPNUM(*pa, b);
|
DUPNUM(*pa, b);
|
||||||
(*pa)->sign *= sign;
|
(*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* ptrc; // ptrc is a pointer to the mantissa of c.
|
||||||
MANTTYPE* ptrcoffset; // ptrcoffset, is the anchor location of the next
|
MANTTYPE* ptrcoffset; // ptrcoffset, is the anchor location of the next
|
||||||
// single digit multiply partial result.
|
// single digit multiply partial result.
|
||||||
long iadigit=0; // Index of digit being used in the first number.
|
int32_t 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 ibdigit = 0; // Index of digit being used in the second number.
|
||||||
MANTTYPE da = 0; // da is the digit from the fist number.
|
MANTTYPE da = 0; // da is the digit from the fist number.
|
||||||
TWO_MANTTYPE cy = 0; // cy is the carry resulting from the addition of
|
TWO_MANTTYPE cy = 0; // cy is the carry resulting from the addition of
|
||||||
// a multiplied row into the result.
|
// a multiplied row into the result.
|
||||||
TWO_MANTTYPE mcy = 0; // mcy is the resultant from a single
|
TWO_MANTTYPE mcy = 0; // mcy is the resultant from a single
|
||||||
// multiply, AND the carry of that multiply.
|
// multiply, AND the carry of that multiply.
|
||||||
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;
|
a = *pa;
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ void _mulnumx( PNUMBER *pa, PNUMBER b )
|
||||||
for (ibdigit = b->cdigit; ibdigit > 0; ibdigit--)
|
for (ibdigit = b->cdigit; ibdigit > 0; ibdigit--)
|
||||||
{
|
{
|
||||||
cy = 0;
|
cy = 0;
|
||||||
mcy = (DWORDLONG)da * (*ptrb);
|
mcy = (uint64_t)da * (*ptrb);
|
||||||
if (mcy)
|
if (mcy)
|
||||||
{
|
{
|
||||||
icdigit = 0;
|
icdigit = 0;
|
||||||
|
@ -130,12 +130,11 @@ void _mulnumx( PNUMBER *pa, PNUMBER b )
|
||||||
// If result is nonzero, or while result of carry is nonzero...
|
// If result is nonzero, or while result of carry is nonzero...
|
||||||
while (mcy || cy)
|
while (mcy || cy)
|
||||||
{
|
{
|
||||||
|
|
||||||
// update carry from addition(s) and multiply.
|
// update carry from addition(s) and multiply.
|
||||||
cy += (TWO_MANTTYPE)ptrc[icdigit]+((DWORD)mcy&((DWORD)~BASEX));
|
cy += (TWO_MANTTYPE)ptrc[icdigit] + ((uint32_t)mcy & ((uint32_t)~BASEX));
|
||||||
|
|
||||||
// update result digit from
|
// update result digit from
|
||||||
ptrc[icdigit++]=(MANTTYPE)((DWORD)cy&((DWORD)~BASEX));
|
ptrc[icdigit++] = (MANTTYPE)((uint32_t)cy & ((uint32_t)~BASEX));
|
||||||
|
|
||||||
// update carries from
|
// update carries from
|
||||||
mcy >>= BASEXPWR;
|
mcy >>= BASEXPWR;
|
||||||
|
@ -144,7 +143,6 @@ void _mulnumx( PNUMBER *pa, PNUMBER b )
|
||||||
|
|
||||||
ptrb++;
|
ptrb++;
|
||||||
ptrc++;
|
ptrc++;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,9 +158,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.
|
// number.
|
||||||
//
|
//
|
||||||
// RETURN: None root is changed.
|
// RETURN: None root is changed.
|
||||||
|
@ -174,10 +172,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.
|
// Once the power remaining is zero we are done.
|
||||||
while (power > 0)
|
while (power > 0)
|
||||||
|
@ -198,7 +196,6 @@ void numpowlongx( _Inout_ PNUMBER *proot, _In_ long power )
|
||||||
}
|
}
|
||||||
destroynum(*proot);
|
destroynum(*proot);
|
||||||
*proot = lret;
|
*proot = lret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _divnumx(PNUMBER* pa, PNUMBER b, int32_t precision);
|
void _divnumx(PNUMBER* pa, PNUMBER b, int32_t precision);
|
||||||
|
@ -232,7 +229,7 @@ void __inline divnumx( PNUMBER *pa, PNUMBER b, int32_t precision)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// if pa is one and b is not one, just copy b, and adjust the sign.
|
// if pa is one and b is not one, just copy b, and adjust the sign.
|
||||||
long sign = (*pa)->sign;
|
int32_t sign = (*pa)->sign;
|
||||||
DUPNUM(*pa, b);
|
DUPNUM(*pa, b);
|
||||||
(*pa)->sign *= sign;
|
(*pa)->sign *= sign;
|
||||||
}
|
}
|
||||||
|
@ -266,10 +263,10 @@ void _divnumx( PNUMBER *pa, PNUMBER b, int32_t precision)
|
||||||
// guesses one bit too far.
|
// guesses one bit too far.
|
||||||
PNUMBER tmp = nullptr; // current guess being worked on for divide.
|
PNUMBER tmp = nullptr; // current guess being worked on for divide.
|
||||||
PNUMBER rem = nullptr; // remainder after applying guess.
|
PNUMBER rem = nullptr; // remainder after applying guess.
|
||||||
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.
|
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.
|
// to shoot for in the divide.
|
||||||
|
|
||||||
a = *pa;
|
a = *pa;
|
||||||
|
@ -301,14 +298,14 @@ void _divnumx( PNUMBER *pa, PNUMBER b, int32_t precision)
|
||||||
|
|
||||||
while (cdigits++ < thismax && !zernum(rem))
|
while (cdigits++ < thismax && !zernum(rem))
|
||||||
{
|
{
|
||||||
long digit = 0;
|
int32_t digit = 0;
|
||||||
*ptrc = 0;
|
*ptrc = 0;
|
||||||
while (!lessnum(rem, b))
|
while (!lessnum(rem, b))
|
||||||
{
|
{
|
||||||
digit = 1;
|
digit = 1;
|
||||||
DUPNUM(tmp, b);
|
DUPNUM(tmp, b);
|
||||||
destroynum(lasttmp);
|
destroynum(lasttmp);
|
||||||
lasttmp=longtonum( 0, BASEX );
|
lasttmp = i32tonum(0, BASEX);
|
||||||
while (lessnum(tmp, rem))
|
while (lessnum(tmp, rem))
|
||||||
{
|
{
|
||||||
destroynum(lasttmp);
|
destroynum(lasttmp);
|
||||||
|
@ -363,5 +360,3 @@ void _divnumx( PNUMBER *pa, PNUMBER b, int32_t precision)
|
||||||
destroynum(*pa);
|
destroynum(*pa);
|
||||||
*pa = c;
|
*pa = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -11,13 +11,16 @@
|
||||||
// Description
|
// Description
|
||||||
//
|
//
|
||||||
// Contains conversion, input and output routines for numbers rationals
|
// Contains conversion, input and output routines for numbers rationals
|
||||||
// and longs.
|
// and i32s.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "pch.h"
|
#include <algorithm>
|
||||||
|
#include <winerror.h>
|
||||||
|
#include <sstream>
|
||||||
|
#include <cstring> // for memmove, memcpy
|
||||||
#include "ratpak.h"
|
#include "ratpak.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -29,12 +32,76 @@ static constexpr wstring_view DIGITS = L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabc
|
||||||
|
|
||||||
// ratio of internal 'digits' to output 'digits'
|
// ratio of internal 'digits' to output 'digits'
|
||||||
// Calculated elsewhere as part of initialization and when base is changed
|
// 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
|
// Default decimal separator
|
||||||
wchar_t g_decimalSeparator = L'.';
|
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
|
// 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)
|
void SetDecimalSeparator(wchar_t decimalSeparator)
|
||||||
{
|
{
|
||||||
|
@ -61,7 +128,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))));
|
memcpy(dest, src, (int)(sizeof(NUMBER) + ((src)->cdigit) * (sizeof(MANTTYPE))));
|
||||||
}
|
}
|
||||||
|
@ -87,7 +154,6 @@ void _destroynum( _In_ PNUMBER pnum )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// FUNCTION: _destroyrat
|
// FUNCTION: _destroyrat
|
||||||
|
@ -112,7 +178,6 @@ void _destroyrat( _In_ PRAT prat )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// FUNCTION: _createnum
|
// FUNCTION: _createnum
|
||||||
|
@ -125,16 +190,15 @@ void _destroyrat( _In_ PRAT prat )
|
||||||
//
|
//
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
PNUMBER _createnum( _In_ ULONG size )
|
PNUMBER _createnum(_In_ uint32_t size)
|
||||||
|
|
||||||
{
|
{
|
||||||
PNUMBER pnumret = nullptr;
|
PNUMBER pnumret = nullptr;
|
||||||
ULONG cbAlloc;
|
uint32_t cbAlloc;
|
||||||
|
|
||||||
// sizeof( MANTTYPE ) is the size of a 'digit'
|
// sizeof( MANTTYPE ) is the size of a 'digit'
|
||||||
if (SUCCEEDED(ULongAdd(size, 1, &cbAlloc)) &&
|
if (SUCCEEDED(Calc_ULongAdd(size, 1, &cbAlloc)) && SUCCEEDED(Calc_ULongMult(cbAlloc, sizeof(MANTTYPE), &cbAlloc))
|
||||||
SUCCEEDED(ULongMult(cbAlloc, sizeof(MANTTYPE), &cbAlloc)) &&
|
&& SUCCEEDED(Calc_ULongAdd(cbAlloc, sizeof(NUMBER), &cbAlloc)))
|
||||||
SUCCEEDED(ULongAdd(cbAlloc, sizeof(NUMBER), &cbAlloc)))
|
|
||||||
{
|
{
|
||||||
pnumret = (PNUMBER)zmalloc(cbAlloc);
|
pnumret = (PNUMBER)zmalloc(cbAlloc);
|
||||||
if (pnumret == nullptr)
|
if (pnumret == nullptr)
|
||||||
|
@ -163,7 +227,6 @@ PNUMBER _createnum( _In_ ULONG size )
|
||||||
//
|
//
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
PRAT _createrat(void)
|
PRAT _createrat(void)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -180,8 +243,6 @@ PRAT _createrat( void )
|
||||||
return (prat);
|
return (prat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// FUNCTION: numtorat
|
// FUNCTION: numtorat
|
||||||
|
@ -203,7 +264,7 @@ PRAT numtorat( _In_ PNUMBER pin, uint32_t radix)
|
||||||
PNUMBER pnRadixn = nullptr;
|
PNUMBER pnRadixn = nullptr;
|
||||||
DUPNUM(pnRadixn, pin);
|
DUPNUM(pnRadixn, pin);
|
||||||
|
|
||||||
PNUMBER qnRadixn=longtonum( 1, radix);
|
PNUMBER qnRadixn = i32tonum(1, radix);
|
||||||
|
|
||||||
// Ensure p and q start out as integers.
|
// Ensure p and q start out as integers.
|
||||||
if (pnRadixn->exp < 0)
|
if (pnRadixn->exp < 0)
|
||||||
|
@ -219,15 +280,12 @@ PRAT numtorat( _In_ PNUMBER pin, uint32_t radix)
|
||||||
pout->pp = numtonRadixx(pnRadixn, radix);
|
pout->pp = numtonRadixx(pnRadixn, radix);
|
||||||
pout->pq = numtonRadixx(qnRadixn, radix);
|
pout->pq = numtonRadixx(qnRadixn, radix);
|
||||||
|
|
||||||
|
|
||||||
destroynum(pnRadixn);
|
destroynum(pnRadixn);
|
||||||
destroynum(qnRadixn);
|
destroynum(qnRadixn);
|
||||||
|
|
||||||
return (pout);
|
return (pout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// FUNCTION: nRadixxtonum
|
// FUNCTION: nRadixxtonum
|
||||||
|
@ -245,28 +303,27 @@ PRAT numtorat( _In_ PNUMBER pin, uint32_t radix)
|
||||||
PNUMBER nRadixxtonum(_In_ PNUMBER a, uint32_t radix, int32_t precision)
|
PNUMBER nRadixxtonum(_In_ PNUMBER a, uint32_t radix, int32_t precision)
|
||||||
|
|
||||||
{
|
{
|
||||||
unsigned long bitmask;
|
uint32_t bitmask;
|
||||||
unsigned long cdigits;
|
uint32_t cdigits;
|
||||||
MANTTYPE* ptr;
|
MANTTYPE* ptr;
|
||||||
|
|
||||||
PNUMBER sum = longtonum( 0, radix );
|
PNUMBER sum = i32tonum(0, radix);
|
||||||
PNUMBER powofnRadix = longtonum( BASEX, radix );
|
PNUMBER powofnRadix = i32tonum(BASEX, radix);
|
||||||
|
|
||||||
// A large penalty is paid for conversion of digits no one will see anyway.
|
// A large penalty is paid for conversion of digits no one will see anyway.
|
||||||
// limit the digits to the minimum of the existing precision or the
|
// limit the digits to the minimum of the existing precision or the
|
||||||
// requested precision.
|
// requested precision.
|
||||||
cdigits = precision + 1;
|
cdigits = precision + 1;
|
||||||
if ( cdigits > (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
|
// 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
|
// Loop over all the relative digits from MSD to LSD
|
||||||
for ( ptr = &(a->mant[a->cdigit-1]); cdigits > 0;
|
for (ptr = &(a->mant[a->cdigit - 1]); cdigits > 0; ptr--, cdigits--)
|
||||||
ptr--, cdigits-- )
|
|
||||||
{
|
{
|
||||||
// Loop over all the bits from MSB to LSB
|
// Loop over all the bits from MSB to LSB
|
||||||
for (bitmask = BASEX / 2; bitmask > 0; bitmask /= 2)
|
for (bitmask = BASEX / 2; bitmask > 0; bitmask /= 2)
|
||||||
|
@ -303,8 +360,8 @@ PNUMBER nRadixxtonum( _In_ PNUMBER a, uint32_t radix, int32_t precision)
|
||||||
|
|
||||||
PNUMBER numtonRadixx(_In_ PNUMBER a, uint32_t radix)
|
PNUMBER numtonRadixx(_In_ PNUMBER a, uint32_t radix)
|
||||||
{
|
{
|
||||||
PNUMBER pnumret = longtonum(0, BASEX); // pnumret is the number in internal form.
|
PNUMBER pnumret = i32tonum(0, BASEX); // pnumret is the number in internal form.
|
||||||
PNUMBER num_radix = longtonum(radix, BASEX);
|
PNUMBER num_radix = i32tonum(radix, BASEX);
|
||||||
MANTTYPE* ptrdigit = a->mant; // pointer to digit being worked on.
|
MANTTYPE* ptrdigit = a->mant; // pointer to digit being worked on.
|
||||||
|
|
||||||
// Digits are in reverse order, back over them LSD first.
|
// Digits are in reverse order, back over them LSD first.
|
||||||
|
@ -312,20 +369,20 @@ PNUMBER numtonRadixx(_In_ PNUMBER a, uint32_t radix)
|
||||||
|
|
||||||
PNUMBER thisdigit = nullptr; // thisdigit holds the current digit of a
|
PNUMBER thisdigit = nullptr; // thisdigit holds the current digit of a
|
||||||
// being summed into result.
|
// being summed into result.
|
||||||
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++)
|
for (idigit = 0; idigit < a->cdigit; idigit++)
|
||||||
{
|
{
|
||||||
mulnumx(&pnumret, num_radix);
|
mulnumx(&pnumret, num_radix);
|
||||||
// WARNING:
|
// WARNING:
|
||||||
// This should just smack in each digit into a 'special' thisdigit.
|
// This should just smack in each digit into a 'special' thisdigit.
|
||||||
// and not do the overhead of recreating the number type each time.
|
// and not do the overhead of recreating the number type each time.
|
||||||
thisdigit = longtonum( *ptrdigit--, BASEX );
|
thisdigit = i32tonum(*ptrdigit--, BASEX);
|
||||||
addnum(&pnumret, thisdigit, BASEX);
|
addnum(&pnumret, thisdigit, BASEX);
|
||||||
destroynum(thisdigit);
|
destroynum(thisdigit);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the exponent of the external base for scaling.
|
// Calculate the exponent of the external base for scaling.
|
||||||
numpowlongx( &num_radix, a->exp );
|
numpowi32x(&num_radix, a->exp);
|
||||||
|
|
||||||
// ... and scale the result.
|
// ... and scale the result.
|
||||||
mulnumx(&pnumret, num_radix);
|
mulnumx(&pnumret, num_radix);
|
||||||
|
@ -391,7 +448,7 @@ PRAT StringToRat(bool mantissaIsNegative, wstring_view mantissa, bool exponentIs
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deal with exponent
|
// Deal with exponent
|
||||||
long expt = 0;
|
int32_t expt = 0;
|
||||||
if (!exponent.empty())
|
if (!exponent.empty())
|
||||||
{
|
{
|
||||||
// Exponent specified, convert to number form.
|
// Exponent specified, convert to number form.
|
||||||
|
@ -404,18 +461,18 @@ PRAT StringToRat(bool mantissaIsNegative, wstring_view mantissa, bool exponentIs
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert exponent number form to native integral form, and cleanup.
|
// Convert exponent number form to native integral form, and cleanup.
|
||||||
expt = numtolong(numExp, radix);
|
expt = numtoi32(numExp, radix);
|
||||||
destroynum(numExp);
|
destroynum(numExp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert native integral exponent form to rational multiplier form.
|
// Convert native integral exponent form to rational multiplier form.
|
||||||
PNUMBER pnumexp = longtonum(radix, BASEX);
|
PNUMBER pnumexp = i32tonum(radix, BASEX);
|
||||||
numpowlongx(&pnumexp, abs(expt));
|
numpowi32x(&pnumexp, abs(expt));
|
||||||
|
|
||||||
PRAT pratexp = nullptr;
|
PRAT pratexp = nullptr;
|
||||||
createrat(pratexp);
|
createrat(pratexp);
|
||||||
DUPNUM(pratexp->pp, pnumexp);
|
DUPNUM(pratexp->pp, pnumexp);
|
||||||
pratexp->pq = longtonum(1, BASEX);
|
pratexp->pq = i32tonum(1, BASEX);
|
||||||
destroynum(pnumexp);
|
destroynum(pnumexp);
|
||||||
|
|
||||||
if (exponentIsNegative)
|
if (exponentIsNegative)
|
||||||
|
@ -507,21 +564,7 @@ static constexpr uint8_t ERR = 14;
|
||||||
|
|
||||||
#if defined(DEBUG)
|
#if defined(DEBUG)
|
||||||
char* statestr[] = {
|
char* statestr[] = {
|
||||||
"START",
|
"START", "MANTS", "LZ", "LZDP", "LD", "DZ", "DD", "DDP", "EXPB", "EXPS", "EXPD", "EXPBZ", "EXPSZ", "EXPDZ", "ERR",
|
||||||
"MANTS",
|
|
||||||
"LZ",
|
|
||||||
"LZDP",
|
|
||||||
"LD",
|
|
||||||
"DZ",
|
|
||||||
"DD",
|
|
||||||
"DDP",
|
|
||||||
"EXPB",
|
|
||||||
"EXPS",
|
|
||||||
"EXPD",
|
|
||||||
"EXPBZ",
|
|
||||||
"EXPSZ",
|
|
||||||
"EXPDZ",
|
|
||||||
"ERR",
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -574,11 +617,11 @@ wchar_t NormalizeCharDigit(wchar_t c, uint32_t radix)
|
||||||
|
|
||||||
PNUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precision)
|
PNUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precision)
|
||||||
{
|
{
|
||||||
long expSign = 1L; // expSign is exponent sign ( +/- 1 )
|
int32_t expSign = 1L; // expSign is exponent sign ( +/- 1 )
|
||||||
long expValue = 0L; // expValue is exponent mantissa, should be unsigned
|
int32_t expValue = 0L; // expValue is exponent mantissa, should be unsigned
|
||||||
|
|
||||||
PNUMBER pnumret = nullptr;
|
PNUMBER pnumret = nullptr;
|
||||||
createnum(pnumret, static_cast<ULONG>(numberString.length()));
|
createnum(pnumret, static_cast<uint32_t>(numberString.length()));
|
||||||
pnumret->sign = 1L;
|
pnumret->sign = 1L;
|
||||||
pnumret->cdigit = 0;
|
pnumret->cdigit = 0;
|
||||||
pnumret->exp = 0;
|
pnumret->exp = 0;
|
||||||
|
@ -612,6 +655,7 @@ PNUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precis
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Drop through in the 'e'-as-a-digit case
|
// Drop through in the 'e'-as-a-digit case
|
||||||
|
[[fallthrough]];
|
||||||
default:
|
default:
|
||||||
state = machine[state][NZ];
|
state = machine[state][NZ];
|
||||||
break;
|
break;
|
||||||
|
@ -636,7 +680,7 @@ PNUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precis
|
||||||
if (pos != wstring_view::npos)
|
if (pos != wstring_view::npos)
|
||||||
{
|
{
|
||||||
expValue *= radix;
|
expValue *= radix;
|
||||||
expValue += static_cast<long>(pos);
|
expValue += static_cast<int32_t>(pos);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -646,7 +690,7 @@ PNUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precis
|
||||||
break;
|
break;
|
||||||
case LD:
|
case LD:
|
||||||
pnumret->exp++;
|
pnumret->exp++;
|
||||||
// Fall through
|
[[fallthrough]];
|
||||||
case DD:
|
case DD:
|
||||||
{
|
{
|
||||||
curChar = NormalizeCharDigit(curChar, radix);
|
curChar = NormalizeCharDigit(curChar, radix);
|
||||||
|
@ -682,7 +726,7 @@ PNUMBER StringToNumber(wstring_view numberString, uint32_t radix, int32_t precis
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
while (pnumret->cdigit < static_cast<long>(numberString.length()))
|
while (pnumret->cdigit < static_cast<int32_t>(numberString.length()))
|
||||||
{
|
{
|
||||||
pnumret->cdigit++;
|
pnumret->cdigit++;
|
||||||
pnumret->exp--;
|
pnumret->exp--;
|
||||||
|
@ -705,65 +749,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)
|
// DESCRIPTION: Converts int32_t input to rational (p over q)
|
||||||
// form, where q is 1 and p is the long.
|
// 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;
|
PRAT pratret = nullptr;
|
||||||
createrat(pratret);
|
createrat(pratret);
|
||||||
pratret->pp = longtonum(inlong, BASEX );
|
pratret->pp = i32tonum(ini32, BASEX);
|
||||||
pratret->pq = longtonum(1L, BASEX );
|
pratret->pq = i32tonum(1L, BASEX);
|
||||||
return (pratret);
|
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)
|
// DESCRIPTION: Converts uint32_t input to rational (p over q)
|
||||||
// form, where q is 1 and p is the unsigned long. Being unsigned cant take negative
|
// form, where q is 1 and p is the uint32_t. Being unsigned cant take negative
|
||||||
// numbers, but the full range of unsigned numbers
|
// numbers, but the full range of unsigned numbers
|
||||||
//
|
//
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
PRAT Ulongtorat( _In_ unsigned long inulong )
|
PRAT Ui32torat(_In_ uint32_t inui32)
|
||||||
|
|
||||||
{
|
{
|
||||||
PRAT pratret = nullptr;
|
PRAT pratret = nullptr;
|
||||||
createrat(pratret);
|
createrat(pratret);
|
||||||
pratret->pp = Ulongtonum(inulong, BASEX );
|
pratret->pp = Ui32tonum(inui32, BASEX);
|
||||||
pratret->pq = longtonum(1L, BASEX );
|
pratret->pq = i32tonum(1L, BASEX);
|
||||||
return (pratret);
|
return (pratret);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// FUNCTION: longtonum
|
// FUNCTION: i32tonum
|
||||||
//
|
//
|
||||||
// ARGUMENTS: long input and radix requested.
|
// ARGUMENTS: int32_t input and radix requested.
|
||||||
//
|
//
|
||||||
// RETURN: number
|
// RETURN: number
|
||||||
//
|
//
|
||||||
// DESCRIPTION: Returns a number representation in the
|
// 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;
|
MANTTYPE* pmant;
|
||||||
|
@ -773,41 +817,41 @@ PNUMBER longtonum( long inlong, uint32_t radix)
|
||||||
pmant = pnumret->mant;
|
pmant = pnumret->mant;
|
||||||
pnumret->cdigit = 0;
|
pnumret->cdigit = 0;
|
||||||
pnumret->exp = 0;
|
pnumret->exp = 0;
|
||||||
if ( inlong < 0 )
|
if (ini32 < 0)
|
||||||
{
|
{
|
||||||
pnumret->sign = -1;
|
pnumret->sign = -1;
|
||||||
inlong *= -1;
|
ini32 *= -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pnumret->sign = 1;
|
pnumret->sign = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do
|
||||||
*pmant++ = (MANTTYPE)(inlong % radix);
|
{
|
||||||
inlong /= radix;
|
*pmant++ = (MANTTYPE)(ini32 % radix);
|
||||||
|
ini32 /= radix;
|
||||||
pnumret->cdigit++;
|
pnumret->cdigit++;
|
||||||
} while ( inlong );
|
} while (ini32);
|
||||||
|
|
||||||
return (pnumret);
|
return (pnumret);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// FUNCTION: Ulongtonum
|
// FUNCTION: Ui32tonum
|
||||||
//
|
//
|
||||||
// ARGUMENTS: ULONG input and radix requested.
|
// ARGUMENTS: uint32_t input and radix requested.
|
||||||
//
|
//
|
||||||
// RETURN: number
|
// RETURN: number
|
||||||
//
|
//
|
||||||
// DESCRIPTION: Returns a number representation in the
|
// 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
|
// negative number and takes the full range of unsigned number
|
||||||
//
|
//
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
PNUMBER Ui32tonum(uint32_t ini32, uint32_t radix)
|
||||||
PNUMBER Ulongtonum(unsigned long inlong, uint32_t radix)
|
|
||||||
{
|
{
|
||||||
MANTTYPE* pmant;
|
MANTTYPE* pmant;
|
||||||
PNUMBER pnumret = nullptr;
|
PNUMBER pnumret = nullptr;
|
||||||
|
@ -818,35 +862,35 @@ PNUMBER Ulongtonum(unsigned long inlong, uint32_t radix)
|
||||||
pnumret->exp = 0;
|
pnumret->exp = 0;
|
||||||
pnumret->sign = 1;
|
pnumret->sign = 1;
|
||||||
|
|
||||||
do {
|
do
|
||||||
*pmant++ = (MANTTYPE)(inlong % radix);
|
{
|
||||||
inlong /= radix;
|
*pmant++ = (MANTTYPE)(ini32 % radix);
|
||||||
|
ini32 /= radix;
|
||||||
pnumret->cdigit++;
|
pnumret->cdigit++;
|
||||||
} while ( inlong );
|
} while (ini32);
|
||||||
|
|
||||||
return (pnumret);
|
return (pnumret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// FUNCTION: rattolong
|
// FUNCTION: rattoi32
|
||||||
//
|
//
|
||||||
// ARGUMENTS: rational number in internal base, integer radix and int32_t precision.
|
// 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
|
// number input. Assumes that the number is in the internal
|
||||||
// base.
|
// 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);
|
throw(CALC_E_DOMAIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -857,7 +901,7 @@ long rattolong( _In_ PRAT prat , uint32_t radix, int32_t precision)
|
||||||
divnumx(&(pint->pp), pint->pq, precision);
|
divnumx(&(pint->pp), pint->pq, precision);
|
||||||
DUPNUM(pint->pq, num_one);
|
DUPNUM(pint->pq, num_one);
|
||||||
|
|
||||||
long lret = numtolong( pint->pp, BASEX );
|
int32_t lret = numtoi32(pint->pp, BASEX);
|
||||||
|
|
||||||
destroyrat(pint);
|
destroyrat(pint);
|
||||||
|
|
||||||
|
@ -866,22 +910,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.
|
// 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
|
// number input. Assumes that the number is in the internal
|
||||||
// base.
|
// 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))
|
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);
|
throw(CALC_E_DOMAIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -892,21 +936,20 @@ unsigned long rattoUlong( _In_ PRAT prat, uint32_t radix, int32_t precision)
|
||||||
divnumx(&(pint->pp), pint->pq, precision);
|
divnumx(&(pint->pp), pint->pq, precision);
|
||||||
DUPNUM(pint->pq, num_one);
|
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);
|
destroyrat(pint);
|
||||||
|
|
||||||
return (lret);
|
return (lret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// FUNCTION: rattoUlonglong
|
// FUNCTION: rattoUi64
|
||||||
//
|
//
|
||||||
// ARGUMENTS: rational number in internal base, integer radix and int32_t precision
|
// 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
|
// 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
|
// number input. Assumes that the number is in the internal
|
||||||
|
@ -915,50 +958,50 @@ unsigned long rattoUlong( _In_ PRAT prat, uint32_t radix, int32_t precision)
|
||||||
// internal base chosen happens to be 2^32, this is easier.
|
// internal base chosen happens to be 2^32, this is easier.
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
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;
|
PRAT pint = nullptr;
|
||||||
|
|
||||||
// first get the LO 32 bit word
|
// first get the LO 32 bit word
|
||||||
DUPRAT(pint, prat);
|
DUPRAT(pint, prat);
|
||||||
andrat(&pint, rat_dword, radix, precision); // & 0xFFFFFFFF (2 ^ 32 -1)
|
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
|
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);
|
rshrat(&pint, prat32, radix, precision);
|
||||||
intrat(&pint, radix, precision);
|
intrat(&pint, radix, precision);
|
||||||
andrat(&pint, rat_dword, radix, precision); // & 0xFFFFFFFF (2 ^ 32 -1)
|
andrat(&pint, rat_dword, radix, precision); // & 0xFFFFFFFF (2 ^ 32 -1)
|
||||||
unsigned long hi = rattoUlong(pint, radix, precision);
|
uint32_t hi = rattoUi32(pint, radix, precision);
|
||||||
|
|
||||||
destroyrat(prat32);
|
destroyrat(prat32);
|
||||||
destroyrat(pint);
|
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.
|
// 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
|
// number input. Assumes that the number is really in the
|
||||||
// base claimed.
|
// 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;
|
MANTTYPE* pmant = pnum->mant;
|
||||||
pmant += pnum->cdigit - 1;
|
pmant += pnum->cdigit - 1;
|
||||||
|
|
||||||
long expt = pnum->exp;
|
int32_t expt = pnum->exp;
|
||||||
for (long length = pnum->cdigit; length > 0 && length + expt > 0; length--)
|
for (int32_t length = pnum->cdigit; length > 0 && length + expt > 0; length--)
|
||||||
{
|
{
|
||||||
lret *= radix;
|
lret *= radix;
|
||||||
lret += *(pmant--);
|
lret += *(pmant--);
|
||||||
|
@ -985,10 +1028,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;
|
MANTTYPE* pmant;
|
||||||
long cdigits;
|
int32_t cdigits;
|
||||||
bool fstrip = false;
|
bool fstrip = false;
|
||||||
|
|
||||||
// point pmant to the LeastCalculatedDigit
|
// point pmant to the LeastCalculatedDigit
|
||||||
|
@ -1041,10 +1084,10 @@ bool stripzeroesnum(_Inout_ PNUMBER pnum, long starting)
|
||||||
wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_t precision)
|
wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_t precision)
|
||||||
{
|
{
|
||||||
stripzeroesnum(pnum, precision + 2);
|
stripzeroesnum(pnum, precision + 2);
|
||||||
long length = pnum->cdigit;
|
int32_t length = pnum->cdigit;
|
||||||
long exponent = pnum->exp + length; // Actual number of digits to the left of decimal
|
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)
|
if (exponent > precision && format == FMT_FLOAT)
|
||||||
{
|
{
|
||||||
// Force scientific mode to prevent user from assuming 33rd digit is exact.
|
// Force scientific mode to prevent user from assuming 33rd digit is exact.
|
||||||
|
@ -1064,7 +1107,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)))
|
if (!zernum(pnum) && (pnum->cdigit >= precision || (length - exponent > precision && exponent >= -MAX_ZEROS_AFTER_DECIMAL)))
|
||||||
{
|
{
|
||||||
// Otherwise round.
|
// Otherwise round.
|
||||||
round = longtonum(radix, radix);
|
round = i32tonum(radix, radix);
|
||||||
divnum(&round, num_two, radix, precision);
|
divnum(&round, num_two, radix, precision);
|
||||||
|
|
||||||
// Make round number exponent one below the LSD for the number.
|
// Make round number exponent one below the LSD for the number.
|
||||||
|
@ -1109,7 +1152,7 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_
|
||||||
if (round != nullptr)
|
if (round != nullptr)
|
||||||
{
|
{
|
||||||
addnum(&pnum, round, radix);
|
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);
|
destroynum(round);
|
||||||
if (stripzeroesnum(pnum, offset))
|
if (stripzeroesnum(pnum, offset))
|
||||||
{
|
{
|
||||||
|
@ -1125,7 +1168,7 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_
|
||||||
|
|
||||||
// Set up all the post rounding stuff.
|
// Set up all the post rounding stuff.
|
||||||
bool useSciForm = false;
|
bool useSciForm = false;
|
||||||
long eout = exponent - 1; // Displayed exponent.
|
int32_t eout = exponent - 1; // Displayed exponent.
|
||||||
MANTTYPE* pmant = pnum->mant + pnum->cdigit - 1;
|
MANTTYPE* pmant = pnum->mant + pnum->cdigit - 1;
|
||||||
// Case where too many digits are to the left of the decimal or
|
// Case where too many digits are to the left of the decimal or
|
||||||
// FMT_SCIENTIFIC or FMT_ENGINEERING was specified.
|
// FMT_SCIENTIFIC or FMT_ENGINEERING was specified.
|
||||||
|
@ -1239,7 +1282,7 @@ wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_
|
||||||
//
|
//
|
||||||
// ARGUMENTS:
|
// ARGUMENTS:
|
||||||
// PRAT *representation of a number.
|
// 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
|
// fmt, one of FMT_FLOAT FMT_SCIENTIFIC or FMT_ENGINEERING
|
||||||
// precision uint32_t
|
// precision uint32_t
|
||||||
//
|
//
|
||||||
|
@ -1269,8 +1312,8 @@ PNUMBER RatToNumber(_In_ PRAT prat, uint32_t radix, int32_t precision)
|
||||||
DUPRAT(temprat, prat);
|
DUPRAT(temprat, prat);
|
||||||
// Convert p and q of rational form from internal base to requested base.
|
// Convert p and q of rational form from internal base to requested base.
|
||||||
// Scale by largest power of BASEX possible.
|
// Scale by largest power of BASEX possible.
|
||||||
long scaleby = min(temprat->pp->exp, temprat->pq->exp);
|
int32_t scaleby = min(temprat->pp->exp, temprat->pq->exp);
|
||||||
scaleby = max(scaleby, 0);
|
scaleby = max<int32_t>(scaleby, 0);
|
||||||
|
|
||||||
temprat->pp->exp -= scaleby;
|
temprat->pp->exp -= scaleby;
|
||||||
temprat->pq->exp -= scaleby;
|
temprat->pq->exp -= scaleby;
|
||||||
|
@ -1358,12 +1401,12 @@ PNUMBER gcd( _In_ PNUMBER a, _In_ PNUMBER b)
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// FUNCTION: longfactnum
|
// FUNCTION: i32factnum
|
||||||
//
|
//
|
||||||
// ARGUMENTS:
|
// ARGUMENTS:
|
||||||
// long integer to factorialize.
|
// int32_t integer to factorialize.
|
||||||
// long integer representing base of answer.
|
// int32_t integer representing base of answer.
|
||||||
// unsigned long integer for radix
|
// uint32_t integer for radix
|
||||||
//
|
//
|
||||||
// RETURN: Factorial of input in radix PNUMBER form.
|
// RETURN: Factorial of input in radix PNUMBER form.
|
||||||
//
|
//
|
||||||
|
@ -1371,17 +1414,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 lret = nullptr;
|
||||||
PNUMBER tmp = 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);
|
mulnum(&lret, tmp, radix);
|
||||||
destroynum(tmp);
|
destroynum(tmp);
|
||||||
}
|
}
|
||||||
|
@ -1390,30 +1433,30 @@ PNUMBER longfactnum(long inlong, uint32_t radix)
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// FUNCTION: longprodnum
|
// FUNCTION: i32prodnum
|
||||||
//
|
//
|
||||||
// ARGUMENTS:
|
// ARGUMENTS:
|
||||||
// long integer to factorialize.
|
// int32_t integer to factorialize.
|
||||||
// long integer representing base of answer.
|
// int32_t integer representing base of answer.
|
||||||
// unsigned long integer for radix
|
// uint32_t integer for radix
|
||||||
//
|
//
|
||||||
// RETURN: Factorial of input in base PNUMBER form.
|
// 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 lret = nullptr;
|
||||||
PNUMBER tmp = nullptr;
|
PNUMBER tmp = nullptr;
|
||||||
|
|
||||||
lret = longtonum( 1, radix);
|
lret = i32tonum(1, radix);
|
||||||
|
|
||||||
while (start <= stop)
|
while (start <= stop)
|
||||||
{
|
{
|
||||||
if (start)
|
if (start)
|
||||||
{
|
{
|
||||||
tmp = longtonum( start, radix);
|
tmp = i32tonum(start, radix);
|
||||||
mulnum(&lret, tmp, radix);
|
mulnum(&lret, tmp, radix);
|
||||||
destroynum(tmp);
|
destroynum(tmp);
|
||||||
}
|
}
|
||||||
|
@ -1424,10 +1467,10 @@ PNUMBER longprodnum(long start, long stop, uint32_t radix)
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// FUNCTION: numpowlong
|
// FUNCTION: numpowi32
|
||||||
//
|
//
|
||||||
// ARGUMENTS: root as number power as long and radix of
|
// ARGUMENTS: root as number power as int32_t and radix of
|
||||||
// number along with the precision value in long.
|
// number along with the precision value in int32_t.
|
||||||
//
|
//
|
||||||
// RETURN: None root is changed.
|
// RETURN: None root is changed.
|
||||||
//
|
//
|
||||||
|
@ -1436,9 +1479,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)
|
while (power > 0)
|
||||||
{
|
{
|
||||||
|
@ -1452,14 +1495,13 @@ void numpowlong( _Inout_ PNUMBER *proot, long power, uint32_t radix, int32_t pre
|
||||||
}
|
}
|
||||||
destroynum(*proot);
|
destroynum(*proot);
|
||||||
*proot = lret;
|
*proot = lret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// 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.
|
// RETURN: None root is changed.
|
||||||
//
|
//
|
||||||
|
@ -1468,14 +1510,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)
|
if (power < 0)
|
||||||
{
|
{
|
||||||
// Take the positive power and invert answer.
|
// Take the positive power and invert answer.
|
||||||
PNUMBER pnumtemp = nullptr;
|
PNUMBER pnumtemp = nullptr;
|
||||||
ratpowlong( proot, -power, precision);
|
ratpowi32(proot, -power, precision);
|
||||||
pnumtemp = (*proot)->pp;
|
pnumtemp = (*proot)->pp;
|
||||||
(*proot)->pp = (*proot)->pq;
|
(*proot)->pp = (*proot)->pq;
|
||||||
(*proot)->pq = pnumtemp;
|
(*proot)->pq = pnumtemp;
|
||||||
|
@ -1484,7 +1526,7 @@ void ratpowlong( _Inout_ PRAT *proot, long power, int32_t precision)
|
||||||
{
|
{
|
||||||
PRAT lret = nullptr;
|
PRAT lret = nullptr;
|
||||||
|
|
||||||
lret = longtorat( 1 );
|
lret = i32torat(1);
|
||||||
|
|
||||||
while (power > 0)
|
while (power > 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -14,10 +14,8 @@
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#include "pch.h"
|
|
||||||
#include "ratpak.h"
|
#include "ratpak.h"
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// FUNCTION: exprat
|
// FUNCTION: exprat
|
||||||
|
@ -50,9 +48,10 @@ void _exprat( PRAT *px, int32_t precision)
|
||||||
addnum(&(pret->pq), num_one, BASEX);
|
addnum(&(pret->pq), num_one, BASEX);
|
||||||
DUPRAT(thisterm, pret);
|
DUPRAT(thisterm, pret);
|
||||||
|
|
||||||
n2=longtonum(0L, BASEX);
|
n2 = i32tonum(0L, BASEX);
|
||||||
|
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
NEXTTERM(*px, INC(n2) DIVNUM(n2), precision);
|
NEXTTERM(*px, INC(n2) DIVNUM(n2), precision);
|
||||||
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
||||||
|
|
||||||
|
@ -64,7 +63,7 @@ void exprat( PRAT *px, uint32_t radix, int32_t precision)
|
||||||
{
|
{
|
||||||
PRAT pwr = nullptr;
|
PRAT pwr = nullptr;
|
||||||
PRAT pint = nullptr;
|
PRAT pint = nullptr;
|
||||||
long intpwr;
|
int32_t intpwr;
|
||||||
|
|
||||||
if (rat_gt(*px, rat_max_exp, precision) || rat_lt(*px, rat_min_exp, precision))
|
if (rat_gt(*px, rat_max_exp, precision) || rat_lt(*px, rat_min_exp, precision))
|
||||||
{
|
{
|
||||||
|
@ -77,8 +76,8 @@ void exprat( PRAT *px, uint32_t radix, int32_t precision)
|
||||||
|
|
||||||
intrat(&pint, radix, precision);
|
intrat(&pint, radix, precision);
|
||||||
|
|
||||||
intpwr = rattolong(pint, radix, precision);
|
intpwr = rattoi32(pint, radix, precision);
|
||||||
ratpowlong( &pwr, intpwr, precision);
|
ratpowi32(&pwr, intpwr, precision);
|
||||||
|
|
||||||
subrat(px, pint, precision);
|
subrat(px, pint, precision);
|
||||||
|
|
||||||
|
@ -97,7 +96,6 @@ void exprat( PRAT *px, uint32_t radix, int32_t precision)
|
||||||
destroyrat(pint);
|
destroyrat(pint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// FUNCTION: lograt, _lograt
|
// FUNCTION: lograt, _lograt
|
||||||
|
@ -140,10 +138,11 @@ void _lograt( PRAT *px, int32_t precision)
|
||||||
DUPRAT(pret, *px);
|
DUPRAT(pret, *px);
|
||||||
DUPRAT(thisterm, *px);
|
DUPRAT(thisterm, *px);
|
||||||
|
|
||||||
n2=longtonum(1L, BASEX);
|
n2 = i32tonum(1L, BASEX);
|
||||||
(*px)->pp->sign *= -1;
|
(*px)->pp->sign *= -1;
|
||||||
|
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
NEXTTERM(*px, MULNUM(n2) INC(n2) DIVNUM(n2), precision);
|
NEXTTERM(*px, MULNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||||
TRIMTOP(*px, precision);
|
TRIMTOP(*px, precision);
|
||||||
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
||||||
|
@ -151,7 +150,6 @@ void _lograt( PRAT *px, int32_t precision)
|
||||||
DESTROYTAYLOR();
|
DESTROYTAYLOR();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void lograt(PRAT* px, int32_t precision)
|
void lograt(PRAT* px, int32_t precision)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -159,7 +157,6 @@ void lograt( PRAT *px, int32_t precision)
|
||||||
PRAT pwr = nullptr; // pwr is the large scaling factor.
|
PRAT pwr = nullptr; // pwr is the large scaling factor.
|
||||||
PRAT offset = nullptr; // offset is the incremental scaling factor.
|
PRAT offset = nullptr; // offset is the incremental scaling factor.
|
||||||
|
|
||||||
|
|
||||||
// Check for someone taking the log of zero or a negative number.
|
// Check for someone taking the log of zero or a negative number.
|
||||||
if (rat_le(*px, rat_zero, precision))
|
if (rat_le(*px, rat_zero, precision))
|
||||||
{
|
{
|
||||||
|
@ -183,10 +180,10 @@ void lograt( PRAT *px, int32_t precision)
|
||||||
{
|
{
|
||||||
// Take advantage of px's base BASEX to scale quickly down to
|
// Take advantage of px's base BASEX to scale quickly down to
|
||||||
// a reasonable range.
|
// a reasonable range.
|
||||||
long intpwr;
|
int32_t intpwr;
|
||||||
intpwr = LOGRAT2(*px) - 1;
|
intpwr = LOGRAT2(*px) - 1;
|
||||||
(*px)->pq->exp += intpwr;
|
(*px)->pq->exp += intpwr;
|
||||||
pwr=longtorat(intpwr*BASEXPWR);
|
pwr = i32torat(intpwr * BASEXPWR);
|
||||||
mulrat(&pwr, ln_two, precision);
|
mulrat(&pwr, ln_two, precision);
|
||||||
// ln(x+e)-ln(x) looks close to e when x is close to one using some
|
// ln(x+e)-ln(x) looks close to e when x is close to one using some
|
||||||
// expansions. This means we can trim past precision digits+1.
|
// expansions. This means we can trim past precision digits+1.
|
||||||
|
@ -309,7 +306,7 @@ void powratNumeratorDenominator(PRAT *px, PRAT y, uint32_t radix, int32_t precis
|
||||||
|
|
||||||
// Calculate the following use the Powers of Powers rule:
|
// Calculate the following use the Powers of Powers rule:
|
||||||
// px ^ (yNum/yDenom) == px ^ yNum ^ (1/yDenom)
|
// 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
|
// and store the result in pxPowNum
|
||||||
// 2. For pxPowNum ^ (1/yDenom), we call powratcomp
|
// 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
|
// 3. Validate the result of 2 by adding/subtracting 0.5, flooring and call powratcomp with yDenom
|
||||||
|
@ -408,7 +405,7 @@ void powratNumeratorDenominator(PRAT *px, PRAT y, uint32_t radix, int32_t precis
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
void powratcomp(PRAT* px, PRAT y, uint32_t radix, int32_t precision)
|
void powratcomp(PRAT* px, PRAT y, uint32_t radix, int32_t precision)
|
||||||
{
|
{
|
||||||
long sign = ((*px)->pp->sign * (*px)->pq->sign);
|
int32_t sign = SIGN(*px);
|
||||||
|
|
||||||
// Take the absolute value
|
// Take the absolute value
|
||||||
(*px)->pp->sign = 1;
|
(*px)->pp->sign = 1;
|
||||||
|
@ -434,8 +431,7 @@ void powratcomp(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
|
||||||
PRAT pxint = nullptr;
|
PRAT pxint = nullptr;
|
||||||
DUPRAT(pxint, *px);
|
DUPRAT(pxint, *px);
|
||||||
subrat(&pxint, rat_one, precision);
|
subrat(&pxint, rat_one, precision);
|
||||||
if ( rat_gt( pxint, rat_negsmallest, precision) &&
|
if (rat_gt(pxint, rat_negsmallest, precision) && rat_lt(pxint, rat_smallest, precision) && (sign == 1))
|
||||||
rat_lt( pxint, rat_smallest, precision) && ( sign == 1 ) )
|
|
||||||
{
|
{
|
||||||
// *px is one, special case a 1 return.
|
// *px is one, special case a 1 return.
|
||||||
DUPRAT(*px, rat_one);
|
DUPRAT(*px, rat_one);
|
||||||
|
@ -444,19 +440,18 @@ void powratcomp(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
// Only do the exp if the number isn't zero or one
|
// Only do the exp if the number isn't zero or one
|
||||||
PRAT podd = nullptr;
|
PRAT podd = nullptr;
|
||||||
DUPRAT(podd, y);
|
DUPRAT(podd, y);
|
||||||
fracrat(&podd, radix, precision);
|
fracrat(&podd, radix, precision);
|
||||||
if (rat_gt(podd, rat_negsmallest, precision) && rat_lt(podd, rat_smallest, precision))
|
if (rat_gt(podd, rat_negsmallest, precision) && rat_lt(podd, rat_smallest, precision))
|
||||||
{
|
{
|
||||||
// If power is an integer let ratpowlong deal with it.
|
// If power is an integer let ratpowi32 deal with it.
|
||||||
PRAT iy = nullptr;
|
PRAT iy = nullptr;
|
||||||
long inty;
|
int32_t inty;
|
||||||
DUPRAT(iy, y);
|
DUPRAT(iy, y);
|
||||||
subrat(&iy, podd, precision);
|
subrat(&iy, podd, precision);
|
||||||
inty = rattolong(iy, radix, precision);
|
inty = rattoi32(iy, radix, precision);
|
||||||
|
|
||||||
PRAT plnx = nullptr;
|
PRAT plnx = nullptr;
|
||||||
DUPRAT(plnx, *px);
|
DUPRAT(plnx, *px);
|
||||||
|
@ -472,7 +467,7 @@ void powratcomp(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
|
||||||
throw(CALC_E_DOMAIN);
|
throw(CALC_E_DOMAIN);
|
||||||
}
|
}
|
||||||
destroyrat(plnx);
|
destroyrat(plnx);
|
||||||
ratpowlong(px, inty, precision);
|
ratpowi32(px, inty, precision);
|
||||||
if ((inty & 1) == 0)
|
if ((inty & 1) == 0)
|
||||||
{
|
{
|
||||||
sign = 1;
|
sign = 1;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -13,10 +13,8 @@
|
||||||
// Contains fact(orial) and supporting _gamma functions.
|
// Contains fact(orial) and supporting _gamma functions.
|
||||||
//
|
//
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#include "pch.h"
|
|
||||||
#include "ratpak.h"
|
#include "ratpak.h"
|
||||||
|
|
||||||
|
|
||||||
#define ABSRAT(x) (((x)->pp->sign = 1), ((x)->pq->sign = 1))
|
#define ABSRAT(x) (((x)->pp->sign = 1), ((x)->pq->sign = 1))
|
||||||
#define NEGATE(x) ((x)->pp->sign *= -1)
|
#define NEGATE(x) ((x)->pp->sign *= -1)
|
||||||
|
|
||||||
|
@ -56,7 +54,6 @@
|
||||||
//
|
//
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
void _gamma(PRAT* pn, uint32_t radix, int32_t precision)
|
void _gamma(PRAT* pn, uint32_t radix, int32_t precision)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -72,14 +69,14 @@ void _gamma( PRAT *pn, uint32_t radix, int32_t precision)
|
||||||
PRAT mpy = nullptr;
|
PRAT mpy = nullptr;
|
||||||
PRAT ratprec = nullptr;
|
PRAT ratprec = nullptr;
|
||||||
PRAT ratRadix = nullptr;
|
PRAT ratRadix = nullptr;
|
||||||
long oldprec;
|
int32_t oldprec;
|
||||||
|
|
||||||
// Set up constants and initial conditions
|
// Set up constants and initial conditions
|
||||||
oldprec = precision;
|
oldprec = precision;
|
||||||
ratprec = longtorat( oldprec );
|
ratprec = i32torat(oldprec);
|
||||||
|
|
||||||
// Find the best 'A' for convergence to the required precision.
|
// Find the best 'A' for convergence to the required precision.
|
||||||
a=longtorat( radix );
|
a = i32torat(radix);
|
||||||
lograt(&a, precision);
|
lograt(&a, precision);
|
||||||
mulrat(&a, ratprec, precision);
|
mulrat(&a, ratprec, precision);
|
||||||
|
|
||||||
|
@ -96,7 +93,7 @@ void _gamma( PRAT *pn, uint32_t radix, int32_t precision)
|
||||||
// The following code is equivalent to
|
// The following code is equivalent to
|
||||||
// precision += ln(exp(a)*pow(a,n+1.5))-ln(radix));
|
// precision += ln(exp(a)*pow(a,n+1.5))-ln(radix));
|
||||||
DUPRAT(tmp, *pn);
|
DUPRAT(tmp, *pn);
|
||||||
one_pt_five=longtorat( 3L );
|
one_pt_five = i32torat(3L);
|
||||||
divrat(&one_pt_five, rat_two, precision);
|
divrat(&one_pt_five, rat_two, precision);
|
||||||
addrat(&tmp, one_pt_five, precision);
|
addrat(&tmp, one_pt_five, precision);
|
||||||
DUPRAT(term, a);
|
DUPRAT(term, a);
|
||||||
|
@ -105,15 +102,15 @@ void _gamma( PRAT *pn, uint32_t radix, int32_t precision)
|
||||||
exprat(&tmp, radix, precision);
|
exprat(&tmp, radix, precision);
|
||||||
mulrat(&term, tmp, precision);
|
mulrat(&term, tmp, precision);
|
||||||
lograt(&term, precision);
|
lograt(&term, precision);
|
||||||
ratRadix = longtorat(radix);
|
ratRadix = i32torat(radix);
|
||||||
DUPRAT(tmp, ratRadix);
|
DUPRAT(tmp, ratRadix);
|
||||||
lograt(&tmp, precision);
|
lograt(&tmp, precision);
|
||||||
subrat(&term, tmp, precision);
|
subrat(&term, tmp, precision);
|
||||||
precision += rattolong( term, radix, precision);
|
precision += rattoi32(term, radix, precision);
|
||||||
|
|
||||||
// Set up initial terms for series, refer to series in above comment block.
|
// Set up initial terms for series, refer to series in above comment block.
|
||||||
DUPRAT(factorial, rat_one); // Start factorial out with one
|
DUPRAT(factorial, rat_one); // Start factorial out with one
|
||||||
count = longtonum( 0L, BASEX );
|
count = i32tonum(0L, BASEX);
|
||||||
|
|
||||||
DUPRAT(mpy, a);
|
DUPRAT(mpy, a);
|
||||||
powratcomp(&mpy, *pn, radix, precision);
|
powratcomp(&mpy, *pn, radix, precision);
|
||||||
|
@ -215,13 +212,11 @@ void factrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||||
fracrat(&frac, radix, precision);
|
fracrat(&frac, radix, precision);
|
||||||
|
|
||||||
// Check for negative integers and throw an error.
|
// Check for negative integers and throw an error.
|
||||||
if ( ( zerrat(frac) || ( LOGRATRADIX(frac) <= -precision) ) &&
|
if ((zerrat(frac) || (LOGRATRADIX(frac) <= -precision)) && (SIGN(*px) == -1))
|
||||||
( (*px)->pp->sign * (*px)->pq->sign == -1 ) )
|
|
||||||
{
|
{
|
||||||
throw CALC_E_DOMAIN;
|
throw CALC_E_DOMAIN;
|
||||||
}
|
}
|
||||||
while ( rat_gt( *px, rat_zero, precision) &&
|
while (rat_gt(*px, rat_zero, precision) && (LOGRATRADIX(*px) > -precision))
|
||||||
( LOGRATRADIX(*px) > -precision) )
|
|
||||||
{
|
{
|
||||||
mulrat(&fact, *px, precision);
|
mulrat(&fact, *px, precision);
|
||||||
subrat(px, rat_one, precision);
|
subrat(px, rat_one, precision);
|
||||||
|
@ -255,4 +250,3 @@ void factrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||||
destroyrat(frac);
|
destroyrat(frac);
|
||||||
destroyrat(neg_rat_one);
|
destroyrat(neg_rat_one);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -15,11 +15,8 @@
|
||||||
// Special Information
|
// Special Information
|
||||||
//
|
//
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#include "pch.h"
|
|
||||||
#include "ratpak.h"
|
#include "ratpak.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void ascalerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, int32_t precision)
|
void ascalerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, int32_t precision)
|
||||||
{
|
{
|
||||||
switch (angletype)
|
switch (angletype)
|
||||||
|
@ -37,7 +34,6 @@ void ascalerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, int32_t precision)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// FUNCTION: asinrat, _asinrat
|
// FUNCTION: asinrat, _asinrat
|
||||||
|
@ -75,10 +71,8 @@ void _asinrat( PRAT *px, int32_t precision)
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
NEXTTERM(xx,MULNUM(n2) MULNUM(n2)
|
NEXTTERM(xx, MULNUM(n2) MULNUM(n2) INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||||
INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
||||||
}
|
|
||||||
while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
|
|
||||||
DESTROYTAYLOR();
|
DESTROYTAYLOR();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,11 +86,9 @@ void asinanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32
|
||||||
void asinrat(PRAT* px, uint32_t radix, int32_t precision)
|
void asinrat(PRAT* px, uint32_t radix, int32_t precision)
|
||||||
|
|
||||||
{
|
{
|
||||||
long sgn;
|
|
||||||
PRAT pret = nullptr;
|
PRAT pret = nullptr;
|
||||||
PRAT phack = nullptr;
|
PRAT phack = nullptr;
|
||||||
|
int32_t sgn = SIGN(*px);
|
||||||
sgn = (*px)->pp->sign* (*px)->pq->sign;
|
|
||||||
|
|
||||||
(*px)->pp->sign = 1;
|
(*px)->pp->sign = 1;
|
||||||
(*px)->pq->sign = 1;
|
(*px)->pq->sign = 1;
|
||||||
|
@ -146,7 +138,6 @@ void asinrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||||
(*px)->pq->sign = 1;
|
(*px)->pq->sign = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// FUNCTION: acosrat, _acosrat
|
// FUNCTION: acosrat, _acosrat
|
||||||
|
@ -186,17 +177,15 @@ void _acosrat( PRAT *px, int32_t precision)
|
||||||
CREATETAYLOR();
|
CREATETAYLOR();
|
||||||
|
|
||||||
createrat(thisterm);
|
createrat(thisterm);
|
||||||
thisterm->pp=longtonum( 1L, BASEX );
|
thisterm->pp = i32tonum(1L, BASEX);
|
||||||
thisterm->pq=longtonum( 1L, BASEX );
|
thisterm->pq = i32tonum(1L, BASEX);
|
||||||
|
|
||||||
DUPNUM(n2, num_one);
|
DUPNUM(n2, num_one);
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
NEXTTERM(xx,MULNUM(n2) MULNUM(n2)
|
NEXTTERM(xx, MULNUM(n2) MULNUM(n2) INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||||
INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
||||||
}
|
|
||||||
while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
|
|
||||||
|
|
||||||
DESTROYTAYLOR();
|
DESTROYTAYLOR();
|
||||||
}
|
}
|
||||||
|
@ -204,9 +193,7 @@ void _acosrat( PRAT *px, int32_t precision)
|
||||||
void acosrat(PRAT* px, uint32_t radix, int32_t precision)
|
void acosrat(PRAT* px, uint32_t radix, int32_t precision)
|
||||||
|
|
||||||
{
|
{
|
||||||
long sgn;
|
int32_t sgn = SIGN(*px);
|
||||||
|
|
||||||
sgn = (*px)->pp->sign*(*px)->pq->sign;
|
|
||||||
|
|
||||||
(*px)->pp->sign = 1;
|
(*px)->pp->sign = 1;
|
||||||
(*px)->pq->sign = 1;
|
(*px)->pq->sign = 1;
|
||||||
|
@ -281,7 +268,8 @@ void _atanrat( PRAT *px, int32_t precision)
|
||||||
|
|
||||||
xx->pp->sign *= -1;
|
xx->pp->sign *= -1;
|
||||||
|
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
NEXTTERM(xx, MULNUM(n2) INC(n2) INC(n2) DIVNUM(n2), precision);
|
NEXTTERM(xx, MULNUM(n2) INC(n2) INC(n2) DIVNUM(n2), precision);
|
||||||
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
||||||
|
|
||||||
|
@ -291,10 +279,8 @@ void _atanrat( PRAT *px, int32_t precision)
|
||||||
void atanrat(PRAT* px, uint32_t radix, int32_t precision)
|
void atanrat(PRAT* px, uint32_t radix, int32_t precision)
|
||||||
|
|
||||||
{
|
{
|
||||||
long sgn;
|
|
||||||
PRAT tmpx = nullptr;
|
PRAT tmpx = nullptr;
|
||||||
|
int32_t sgn = SIGN(*px);
|
||||||
sgn = (*px)->pp->sign * (*px)->pq->sign;
|
|
||||||
|
|
||||||
(*px)->pp->sign = 1;
|
(*px)->pp->sign = 1;
|
||||||
(*px)->pq->sign = 1;
|
(*px)->pq->sign = 1;
|
||||||
|
@ -339,4 +325,3 @@ void atanrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||||
subrat(px, pi, precision);
|
subrat(px, pi, precision);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,11 +16,8 @@
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#include "pch.h"
|
|
||||||
#include "ratpak.h"
|
#include "ratpak.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// FUNCTION: asinhrat
|
// FUNCTION: asinhrat
|
||||||
|
@ -80,17 +77,14 @@ void asinhrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
NEXTTERM(xx,MULNUM(n2) MULNUM(n2)
|
NEXTTERM(xx, MULNUM(n2) MULNUM(n2) INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||||
INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
||||||
}
|
|
||||||
while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
|
|
||||||
|
|
||||||
DESTROYTAYLOR();
|
DESTROYTAYLOR();
|
||||||
}
|
}
|
||||||
destroyrat(neg_pt_eight_five);
|
destroyrat(neg_pt_eight_five);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// FUNCTION: acoshrat
|
// FUNCTION: acoshrat
|
||||||
|
@ -157,4 +151,3 @@ void atanhrat( PRAT *px, int32_t precision)
|
||||||
divrat(px, rat_two, precision);
|
divrat(px, rat_two, precision);
|
||||||
destroyrat(ptmp);
|
destroyrat(ptmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
@ -13,16 +13,15 @@
|
||||||
// Contains routines for and, or, xor, not and other support
|
// Contains routines for and, or, xor, not and other support
|
||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
#include "pch.h"
|
|
||||||
#include "ratpak.h"
|
#include "ratpak.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
void lshrat(PRAT* pa, PRAT b, uint32_t radix, int32_t precision)
|
void lshrat(PRAT* pa, PRAT b, uint32_t radix, int32_t precision)
|
||||||
|
|
||||||
{
|
{
|
||||||
PRAT pwr = nullptr;
|
PRAT pwr = nullptr;
|
||||||
long intb;
|
int32_t intb;
|
||||||
|
|
||||||
intrat(pa, radix, precision);
|
intrat(pa, radix, precision);
|
||||||
if (!zernum((*pa)->pp))
|
if (!zernum((*pa)->pp))
|
||||||
|
@ -33,9 +32,9 @@ void lshrat( PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
|
||||||
// Don't attempt lsh of anything big
|
// Don't attempt lsh of anything big
|
||||||
throw(CALC_E_DOMAIN);
|
throw(CALC_E_DOMAIN);
|
||||||
}
|
}
|
||||||
intb = rattolong(b, radix, precision);
|
intb = rattoi32(b, radix, precision);
|
||||||
DUPRAT(pwr, rat_two);
|
DUPRAT(pwr, rat_two);
|
||||||
ratpowlong(&pwr, intb, precision);
|
ratpowi32(&pwr, intb, precision);
|
||||||
mulrat(pa, pwr, precision);
|
mulrat(pa, pwr, precision);
|
||||||
destroyrat(pwr);
|
destroyrat(pwr);
|
||||||
}
|
}
|
||||||
|
@ -45,7 +44,7 @@ void rshrat( PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
|
||||||
|
|
||||||
{
|
{
|
||||||
PRAT pwr = nullptr;
|
PRAT pwr = nullptr;
|
||||||
long intb;
|
int32_t intb;
|
||||||
|
|
||||||
intrat(pa, radix, precision);
|
intrat(pa, radix, precision);
|
||||||
if (!zernum((*pa)->pp))
|
if (!zernum((*pa)->pp))
|
||||||
|
@ -56,9 +55,9 @@ void rshrat( PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
|
||||||
// Don't attempt rsh of anything big and negative.
|
// Don't attempt rsh of anything big and negative.
|
||||||
throw(CALC_E_DOMAIN);
|
throw(CALC_E_DOMAIN);
|
||||||
}
|
}
|
||||||
intb = rattolong(b, radix, precision);
|
intb = rattoi32(b, radix, precision);
|
||||||
DUPRAT(pwr, rat_two);
|
DUPRAT(pwr, rat_two);
|
||||||
ratpowlong(&pwr, intb, precision);
|
ratpowi32(&pwr, intb, precision);
|
||||||
divrat(pa, pwr, precision);
|
divrat(pa, pwr, precision);
|
||||||
destroyrat(pwr);
|
destroyrat(pwr);
|
||||||
}
|
}
|
||||||
|
@ -67,8 +66,8 @@ void rshrat( PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
|
||||||
void boolrat(PRAT* pa, PRAT b, int func, uint32_t radix, int32_t precision);
|
void boolrat(PRAT* pa, PRAT b, int func, uint32_t radix, int32_t precision);
|
||||||
void boolnum(PNUMBER* pa, PNUMBER b, int func);
|
void boolnum(PNUMBER* pa, PNUMBER b, int func);
|
||||||
|
|
||||||
|
enum
|
||||||
enum {
|
{
|
||||||
FUNC_AND,
|
FUNC_AND,
|
||||||
FUNC_OR,
|
FUNC_OR,
|
||||||
FUNC_XOR
|
FUNC_XOR
|
||||||
|
@ -138,14 +137,13 @@ void boolnum( PNUMBER *pa, PNUMBER b, int func )
|
||||||
MANTTYPE* pcha;
|
MANTTYPE* pcha;
|
||||||
MANTTYPE* pchb;
|
MANTTYPE* pchb;
|
||||||
MANTTYPE* pchc;
|
MANTTYPE* pchc;
|
||||||
long cdigits;
|
int32_t cdigits;
|
||||||
long mexp;
|
int32_t mexp;
|
||||||
MANTTYPE da;
|
MANTTYPE da;
|
||||||
MANTTYPE db;
|
MANTTYPE db;
|
||||||
|
|
||||||
a = *pa;
|
a = *pa;
|
||||||
cdigits = max( a->cdigit+a->exp, b->cdigit+b->exp ) -
|
cdigits = max(a->cdigit + a->exp, b->cdigit + b->exp) - min(a->exp, b->exp);
|
||||||
min( a->exp, b->exp );
|
|
||||||
createnum(c, cdigits);
|
createnum(c, cdigits);
|
||||||
c->exp = min(a->exp, b->exp);
|
c->exp = min(a->exp, b->exp);
|
||||||
mexp = c->exp;
|
mexp = c->exp;
|
||||||
|
@ -155,12 +153,8 @@ void boolnum( PNUMBER *pa, PNUMBER b, int func )
|
||||||
pchc = c->mant;
|
pchc = c->mant;
|
||||||
for (; cdigits > 0; cdigits--, mexp++)
|
for (; cdigits > 0; cdigits--, mexp++)
|
||||||
{
|
{
|
||||||
da = ( ( ( mexp >= a->exp ) && ( cdigits + a->exp - c->exp >
|
da = (((mexp >= a->exp) && (cdigits + a->exp - c->exp > (c->cdigit - a->cdigit))) ? *pcha++ : 0);
|
||||||
(c->cdigit - a->cdigit) ) ) ?
|
db = (((mexp >= b->exp) && (cdigits + b->exp - c->exp > (c->cdigit - b->cdigit))) ? *pchb++ : 0);
|
||||||
*pcha++ : 0 );
|
|
||||||
db = ( ( ( mexp >= b->exp ) && ( cdigits + b->exp - c->exp >
|
|
||||||
(c->cdigit - b->cdigit) ) ) ?
|
|
||||||
*pchb++ : 0 );
|
|
||||||
switch (func)
|
switch (func)
|
||||||
{
|
{
|
||||||
case FUNC_AND:
|
case FUNC_AND:
|
||||||
|
@ -185,25 +179,27 @@ void boolnum( PNUMBER *pa, PNUMBER b, int func )
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// FUNCTION: modrat
|
// FUNCTION: remrat
|
||||||
//
|
//
|
||||||
// ARGUMENTS: pointer to a rational a second rational.
|
// ARGUMENTS: pointer to a rational a second rational.
|
||||||
//
|
//
|
||||||
// RETURN: None, changes pointer.
|
// RETURN: None, changes pointer.
|
||||||
//
|
//
|
||||||
// DESCRIPTION: Does the rational equivalent of frac(*pa);
|
// DESCRIPTION: Calculate the remainder of *pa / b,
|
||||||
|
// equivalent of 'pa % b' in C/C++ and produces a result
|
||||||
|
// that is either zero or has the same sign as the dividend.
|
||||||
//
|
//
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
void modrat( PRAT *pa, PRAT b )
|
void remrat(PRAT* pa, PRAT b)
|
||||||
|
|
||||||
{
|
{
|
||||||
PRAT tmp = nullptr;
|
|
||||||
|
|
||||||
if (zerrat(b))
|
if (zerrat(b))
|
||||||
{
|
{
|
||||||
throw CALC_E_INDEFINITE;
|
throw CALC_E_INDEFINITE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PRAT tmp = nullptr;
|
||||||
DUPRAT(tmp, b);
|
DUPRAT(tmp, b);
|
||||||
|
|
||||||
mulnumx(&((*pa)->pp), tmp->pq);
|
mulnumx(&((*pa)->pp), tmp->pq);
|
||||||
|
@ -217,3 +213,46 @@ void modrat( PRAT *pa, PRAT b )
|
||||||
destroyrat(tmp);
|
destroyrat(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// FUNCTION: modrat
|
||||||
|
//
|
||||||
|
// ARGUMENTS: pointer to a rational a second rational.
|
||||||
|
//
|
||||||
|
// RETURN: None, changes pointer.
|
||||||
|
//
|
||||||
|
// DESCRIPTION: Calculate the remainder of *pa / b, with the sign of the result
|
||||||
|
// either zero or has the same sign as the divisor.
|
||||||
|
// NOTE: When *pa or b are negative, the result won't be the same as
|
||||||
|
// the C/C++ operator %, use remrat if it's the behavior you expect.
|
||||||
|
//
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void modrat(PRAT* pa, PRAT b)
|
||||||
|
{
|
||||||
|
// contrary to remrat(X, 0) returning 0, modrat(X, 0) must return X
|
||||||
|
if (zerrat(b))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PRAT tmp = nullptr;
|
||||||
|
DUPRAT(tmp, b);
|
||||||
|
|
||||||
|
auto needAdjust = (SIGN(*pa) == -1 ? (SIGN(b) == 1) : (SIGN(b) == -1));
|
||||||
|
|
||||||
|
mulnumx(&((*pa)->pp), tmp->pq);
|
||||||
|
mulnumx(&(tmp->pp), (*pa)->pq);
|
||||||
|
remnum(&((*pa)->pp), tmp->pp, BASEX);
|
||||||
|
mulnumx(&((*pa)->pq), tmp->pq);
|
||||||
|
|
||||||
|
if (needAdjust && !zerrat(*pa))
|
||||||
|
{
|
||||||
|
addrat(pa, b, BASEX);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get *pa back in the integer over integer form.
|
||||||
|
RENORMALIZE(*pa);
|
||||||
|
|
||||||
|
destroyrat(tmp);
|
||||||
|
}
|
||||||
|
|
|
@ -17,7 +17,8 @@
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#include "pch.h"
|
#include <list>
|
||||||
|
#include <cstring> // for memmove
|
||||||
#include "ratpak.h"
|
#include "ratpak.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -66,22 +67,20 @@ void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
||||||
MANTTYPE* pcha; // pcha is a pointer to the mantissa of a.
|
MANTTYPE* pcha; // pcha is a pointer to the mantissa of a.
|
||||||
MANTTYPE* pchb; // pchb is a pointer to the mantissa of b.
|
MANTTYPE* pchb; // pchb is a pointer to the mantissa of b.
|
||||||
MANTTYPE* pchc; // pchc is a pointer to the mantissa of c.
|
MANTTYPE* pchc; // pchc is a pointer to the mantissa of c.
|
||||||
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.
|
// 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 da; // da is a single 'digit' after possible padding.
|
||||||
MANTTYPE db; // db is a single 'digit' after possible padding.
|
MANTTYPE db; // db is a single 'digit' after possible padding.
|
||||||
MANTTYPE cy = 0; // cy is the value of a carry after adding two 'digits'
|
MANTTYPE cy = 0; // cy is the value of a carry after adding two 'digits'
|
||||||
long fcompla = 0; // fcompla is a flag to signal a is negative.
|
int32_t 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 fcomplb = 0; // fcomplb is a flag to signal b is negative.
|
||||||
|
|
||||||
a = *pa;
|
a = *pa;
|
||||||
|
|
||||||
|
|
||||||
// Calculate the overlap of the numbers after alignment, this includes
|
// Calculate the overlap of the numbers after alignment, this includes
|
||||||
// necessary padding 0's
|
// necessary padding 0's
|
||||||
cdigits = max( a->cdigit+a->exp, b->cdigit+b->exp ) -
|
cdigits = max(a->cdigit + a->exp, b->cdigit + b->exp) - min(a->exp, b->exp);
|
||||||
min( a->exp, b->exp );
|
|
||||||
|
|
||||||
createnum(c, cdigits + 1);
|
createnum(c, cdigits + 1);
|
||||||
c->exp = min(a->exp, b->exp);
|
c->exp = min(a->exp, b->exp);
|
||||||
|
@ -103,15 +102,10 @@ void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
||||||
// aligned
|
// aligned
|
||||||
for (; cdigits > 0; cdigits--, mexp++)
|
for (; cdigits > 0; cdigits--, mexp++)
|
||||||
{
|
{
|
||||||
|
|
||||||
// Get digit from a, taking padding into account.
|
// Get digit from a, taking padding into account.
|
||||||
da = ( ( ( mexp >= a->exp ) && ( cdigits + a->exp - c->exp >
|
da = (((mexp >= a->exp) && (cdigits + a->exp - c->exp > (c->cdigit - a->cdigit))) ? *pcha++ : 0);
|
||||||
(c->cdigit - a->cdigit) ) ) ?
|
|
||||||
*pcha++ : 0 );
|
|
||||||
// Get digit from b, taking padding into account.
|
// Get digit from b, taking padding into account.
|
||||||
db = ( ( ( mexp >= b->exp ) && ( cdigits + b->exp - c->exp >
|
db = (((mexp >= b->exp) && (cdigits + b->exp - c->exp > (c->cdigit - b->cdigit))) ? *pchb++ : 0);
|
||||||
(c->cdigit - b->cdigit) ) ) ?
|
|
||||||
*pchb++ : 0 );
|
|
||||||
|
|
||||||
// Handle complementing for a and b digit. Might be a better way, but
|
// Handle complementing for a and b digit. Might be a better way, but
|
||||||
// haven't found it yet.
|
// haven't found it yet.
|
||||||
|
@ -156,9 +150,7 @@ void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
||||||
// slower on average.
|
// slower on average.
|
||||||
c->sign = -1;
|
c->sign = -1;
|
||||||
cy = 1;
|
cy = 1;
|
||||||
for ( ( cdigits = c->cdigit ), (pchc = c->mant);
|
for ((cdigits = c->cdigit), (pchc = c->mant); cdigits > 0; cdigits--)
|
||||||
cdigits > 0;
|
|
||||||
cdigits-- )
|
|
||||||
{
|
{
|
||||||
cy = (MANTTYPE)radix - (MANTTYPE)1 - *pchc + cy;
|
cy = (MANTTYPE)radix - (MANTTYPE)1 - *pchc + cy;
|
||||||
*pchc++ = (MANTTYPE)(cy % (MANTTYPE)radix);
|
*pchc++ = (MANTTYPE)(cy % (MANTTYPE)radix);
|
||||||
|
@ -205,7 +197,7 @@ void __inline mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ // if pa is one and b isn't just copy b, and adjust the sign.
|
{ // if pa is one and b isn't just copy b, and adjust the sign.
|
||||||
long sign = (*pa)->sign;
|
int32_t sign = (*pa)->sign;
|
||||||
DUPNUM(*pa, b);
|
DUPNUM(*pa, b);
|
||||||
(*pa)->sign *= sign;
|
(*pa)->sign *= sign;
|
||||||
}
|
}
|
||||||
|
@ -226,14 +218,14 @@ void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
||||||
MANTTYPE* pchc; // pchc is a pointer to the mantissa of c.
|
MANTTYPE* pchc; // pchc is a pointer to the mantissa of c.
|
||||||
MANTTYPE* pchcoffset; // pchcoffset, is the anchor location of the next
|
MANTTYPE* pchcoffset; // pchcoffset, is the anchor location of the next
|
||||||
// single digit multiply partial result.
|
// single digit multiply partial result.
|
||||||
long iadigit = 0; // Index of digit being used in the first number.
|
int32_t 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 ibdigit = 0; // Index of digit being used in the second number.
|
||||||
MANTTYPE da = 0; // da is the digit from the fist number.
|
MANTTYPE da = 0; // da is the digit from the fist number.
|
||||||
TWO_MANTTYPE cy = 0; // cy is the carry resulting from the addition of
|
TWO_MANTTYPE cy = 0; // cy is the carry resulting from the addition of
|
||||||
// a multiplied row into the result.
|
// a multiplied row into the result.
|
||||||
TWO_MANTTYPE mcy = 0; // mcy is the resultant from a single
|
TWO_MANTTYPE mcy = 0; // mcy is the resultant from a single
|
||||||
// multiply, AND the carry of that multiply.
|
// multiply, AND the carry of that multiply.
|
||||||
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;
|
a = *pa;
|
||||||
ibdigit = a->cdigit + b->cdigit - 1;
|
ibdigit = a->cdigit + b->cdigit - 1;
|
||||||
|
@ -268,7 +260,6 @@ void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
||||||
// If result is nonzero, or while result of carry is nonzero...
|
// If result is nonzero, or while result of carry is nonzero...
|
||||||
while (mcy || cy)
|
while (mcy || cy)
|
||||||
{
|
{
|
||||||
|
|
||||||
// update carry from addition(s) and multiply.
|
// update carry from addition(s) and multiply.
|
||||||
cy += (TWO_MANTTYPE)pchc[icdigit] + (mcy % (TWO_MANTTYPE)radix);
|
cy += (TWO_MANTTYPE)pchc[icdigit] + (mcy % (TWO_MANTTYPE)radix);
|
||||||
|
|
||||||
|
@ -296,7 +287,6 @@ void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
||||||
*pa = c;
|
*pa = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// FUNCTION: remnum
|
// FUNCTION: remnum
|
||||||
|
@ -334,7 +324,7 @@ void remnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
||||||
}
|
}
|
||||||
|
|
||||||
destroynum(lasttmp);
|
destroynum(lasttmp);
|
||||||
lasttmp=longtonum( 0, radix);
|
lasttmp = i32tonum(0, radix);
|
||||||
|
|
||||||
while (lessnum(tmp, *pa))
|
while (lessnum(tmp, *pa))
|
||||||
{
|
{
|
||||||
|
@ -356,11 +346,9 @@ void remnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
||||||
|
|
||||||
destroynum(tmp);
|
destroynum(tmp);
|
||||||
destroynum(lasttmp);
|
destroynum(lasttmp);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// FUNCTION: divnum
|
// FUNCTION: divnum
|
||||||
|
@ -394,7 +382,7 @@ void __inline divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
|
||||||
void _divnum(PNUMBER* pa, PNUMBER b, uint32_t radix, int32_t precision)
|
void _divnum(PNUMBER* pa, PNUMBER b, uint32_t radix, int32_t precision)
|
||||||
{
|
{
|
||||||
PNUMBER a = *pa;
|
PNUMBER a = *pa;
|
||||||
long thismax = precision + 2;
|
int32_t thismax = precision + 2;
|
||||||
if (thismax < a->cdigit)
|
if (thismax < a->cdigit)
|
||||||
{
|
{
|
||||||
thismax = a->cdigit;
|
thismax = a->cdigit;
|
||||||
|
@ -420,8 +408,8 @@ void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
|
||||||
|
|
||||||
// Build a table of multiplications of the divisor, this is quicker for
|
// Build a table of multiplications of the divisor, this is quicker for
|
||||||
// more than radix 'digits'
|
// more than radix 'digits'
|
||||||
list<PNUMBER> numberList{ longtonum(0L, radix) };
|
list<PNUMBER> numberList{ i32tonum(0L, radix) };
|
||||||
for (unsigned long i = 1; i < radix; i++)
|
for (uint32_t i = 1; i < radix; i++)
|
||||||
{
|
{
|
||||||
PNUMBER newValue = nullptr;
|
PNUMBER newValue = nullptr;
|
||||||
DUPNUM(newValue, numberList.front());
|
DUPNUM(newValue, numberList.front());
|
||||||
|
@ -431,8 +419,8 @@ void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
|
||||||
}
|
}
|
||||||
destroynum(tmp);
|
destroynum(tmp);
|
||||||
|
|
||||||
long digit;
|
int32_t digit;
|
||||||
long cdigits = 0;
|
int32_t cdigits = 0;
|
||||||
while (cdigits++ < thismax && !zernum(rem))
|
while (cdigits++ < thismax && !zernum(rem))
|
||||||
{
|
{
|
||||||
digit = radix - 1;
|
digit = radix - 1;
|
||||||
|
@ -488,7 +476,6 @@ void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
|
||||||
*pa = c;
|
*pa = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// FUNCTION: equnum
|
// FUNCTION: equnum
|
||||||
|
@ -505,11 +492,11 @@ void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
|
||||||
bool equnum(PNUMBER a, PNUMBER b)
|
bool equnum(PNUMBER a, PNUMBER b)
|
||||||
|
|
||||||
{
|
{
|
||||||
long diff;
|
int32_t diff;
|
||||||
MANTTYPE* pa;
|
MANTTYPE* pa;
|
||||||
MANTTYPE* pb;
|
MANTTYPE* pb;
|
||||||
long cdigits;
|
int32_t cdigits;
|
||||||
long ccdigits;
|
int32_t ccdigits;
|
||||||
MANTTYPE da;
|
MANTTYPE da;
|
||||||
MANTTYPE db;
|
MANTTYPE db;
|
||||||
|
|
||||||
|
@ -540,10 +527,8 @@ bool equnum( PNUMBER a, PNUMBER b )
|
||||||
// difference in the digits.
|
// difference in the digits.
|
||||||
for (; cdigits > 0; cdigits--)
|
for (; cdigits > 0; cdigits--)
|
||||||
{
|
{
|
||||||
da = ( (cdigits > (ccdigits - a->cdigit) ) ?
|
da = ((cdigits > (ccdigits - a->cdigit)) ? *pa-- : 0);
|
||||||
*pa-- : 0 );
|
db = ((cdigits > (ccdigits - b->cdigit)) ? *pb-- : 0);
|
||||||
db = ( (cdigits > (ccdigits - b->cdigit) ) ?
|
|
||||||
*pb-- : 0 );
|
|
||||||
if (da != db)
|
if (da != db)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -573,15 +558,14 @@ bool equnum( PNUMBER a, PNUMBER b )
|
||||||
bool lessnum(PNUMBER a, PNUMBER b)
|
bool lessnum(PNUMBER a, PNUMBER b)
|
||||||
|
|
||||||
{
|
{
|
||||||
long diff;
|
int32_t diff;
|
||||||
MANTTYPE* pa;
|
MANTTYPE* pa;
|
||||||
MANTTYPE* pb;
|
MANTTYPE* pb;
|
||||||
long cdigits;
|
int32_t cdigits;
|
||||||
long ccdigits;
|
int32_t ccdigits;
|
||||||
MANTTYPE da;
|
MANTTYPE da;
|
||||||
MANTTYPE db;
|
MANTTYPE db;
|
||||||
|
|
||||||
|
|
||||||
diff = (a->cdigit + a->exp) - (b->cdigit + b->exp);
|
diff = (a->cdigit + a->exp) - (b->cdigit + b->exp);
|
||||||
if (diff < 0)
|
if (diff < 0)
|
||||||
{
|
{
|
||||||
|
@ -604,10 +588,8 @@ bool lessnum( PNUMBER a, PNUMBER b )
|
||||||
ccdigits = cdigits;
|
ccdigits = cdigits;
|
||||||
for (; cdigits > 0; cdigits--)
|
for (; cdigits > 0; cdigits--)
|
||||||
{
|
{
|
||||||
da = ( (cdigits > (ccdigits - a->cdigit) ) ?
|
da = ((cdigits > (ccdigits - a->cdigit)) ? *pa-- : 0);
|
||||||
*pa-- : 0 );
|
db = ((cdigits > (ccdigits - b->cdigit)) ? *pb-- : 0);
|
||||||
db = ( (cdigits > (ccdigits - b->cdigit) ) ?
|
|
||||||
*pb-- : 0 );
|
|
||||||
diff = da - db;
|
diff = da - db;
|
||||||
if (diff)
|
if (diff)
|
||||||
{
|
{
|
||||||
|
@ -635,7 +617,7 @@ bool lessnum( PNUMBER a, PNUMBER b )
|
||||||
bool zernum(PNUMBER a)
|
bool zernum(PNUMBER a)
|
||||||
|
|
||||||
{
|
{
|
||||||
long length;
|
int32_t length;
|
||||||
MANTTYPE* pcha;
|
MANTTYPE* pcha;
|
||||||
length = a->cdigit;
|
length = a->cdigit;
|
||||||
pcha = a->mant;
|
pcha = a->mant;
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
//
|
//
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
#include "ratpak.h"
|
#include "ratpak.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -118,7 +117,6 @@ void mulrat( PRAT *pa, PRAT b, int32_t precision)
|
||||||
#ifdef MULGCD
|
#ifdef MULGCD
|
||||||
gcdrat(pa);
|
gcdrat(pa);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -134,11 +132,9 @@ void mulrat( PRAT *pa, PRAT b, int32_t precision)
|
||||||
//
|
//
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
void divrat(PRAT* pa, PRAT b, int32_t precision)
|
void divrat(PRAT* pa, PRAT b, int32_t precision)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!zernum((*pa)->pp))
|
if (!zernum((*pa)->pp))
|
||||||
{
|
{
|
||||||
// Only do the divide if the top isn't zero.
|
// Only do the divide if the top isn't zero.
|
||||||
|
@ -171,7 +167,6 @@ void divrat( PRAT *pa, PRAT b, int32_t precision)
|
||||||
#ifdef DIVGCD
|
#ifdef DIVGCD
|
||||||
gcdrat(pa);
|
gcdrat(pa);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -245,11 +240,8 @@ void addrat( PRAT *pa, PRAT b, int32_t precision)
|
||||||
#ifdef ADDGCD
|
#ifdef ADDGCD
|
||||||
gcdrat(pa);
|
gcdrat(pa);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// FUNCTION: rootrat
|
// FUNCTION: rootrat
|
||||||
|
@ -275,7 +267,6 @@ void rootrat( PRAT *py, PRAT n, uint32_t radix, int32_t precision)
|
||||||
destroyrat(oneovern);
|
destroyrat(oneovern);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// FUNCTION: zerrat
|
// FUNCTION: zerrat
|
||||||
|
@ -294,5 +285,3 @@ bool zerrat( PRAT a )
|
||||||
{
|
{
|
||||||
return (zernum(a->pp));
|
return (zernum(a->pp));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,482 +1,594 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
// Autogenerated by _dumprawrat in support.c
|
#pragma once
|
||||||
NUMBER init_num_one= {
|
|
||||||
1,
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
|
inline const NUMBER init_num_one = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 1,}
|
{
|
||||||
};
|
|
||||||
// Autogenerated by _dumprawrat in support.c
|
|
||||||
NUMBER init_num_two= {
|
|
||||||
1,
|
1,
|
||||||
|
} };
|
||||||
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
|
inline const NUMBER init_num_two = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 2,}
|
{
|
||||||
};
|
2,
|
||||||
// Autogenerated by _dumprawrat in support.c
|
} };
|
||||||
NUMBER init_num_five= {
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
1,
|
inline const NUMBER init_num_five = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 5,}
|
{
|
||||||
};
|
5,
|
||||||
// Autogenerated by _dumprawrat in support.c
|
} };
|
||||||
NUMBER init_num_six= {
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
1,
|
inline const NUMBER init_num_six = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 6,}
|
{
|
||||||
};
|
6,
|
||||||
// Autogenerated by _dumprawrat in support.c
|
} };
|
||||||
NUMBER init_num_ten= {
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
1,
|
inline const NUMBER init_num_ten = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 10,}
|
{
|
||||||
};
|
10,
|
||||||
// Autogenerated by _dumprawrat in support.c
|
} };
|
||||||
NUMBER init_p_rat_smallest = {
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
1,
|
inline const NUMBER init_p_rat_smallest = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 1,}
|
{
|
||||||
};
|
|
||||||
NUMBER init_q_rat_smallest = {
|
|
||||||
1,
|
1,
|
||||||
|
} };
|
||||||
|
inline const NUMBER init_q_rat_smallest = { 1,
|
||||||
4,
|
4,
|
||||||
0,
|
0,
|
||||||
{ 0, 190439170, 901055854, 10097,}
|
{
|
||||||
};
|
0,
|
||||||
// Autogenerated by _dumprawrat in support.c
|
190439170,
|
||||||
NUMBER init_p_rat_negsmallest = {
|
901055854,
|
||||||
-1,
|
10097,
|
||||||
|
} };
|
||||||
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
|
inline const NUMBER init_p_rat_negsmallest = { -1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 1,}
|
{
|
||||||
};
|
|
||||||
NUMBER init_q_rat_negsmallest = {
|
|
||||||
1,
|
1,
|
||||||
|
} };
|
||||||
|
inline const NUMBER init_q_rat_negsmallest = { 1,
|
||||||
4,
|
4,
|
||||||
0,
|
0,
|
||||||
{ 0, 190439170, 901055854, 10097,}
|
{
|
||||||
};
|
0,
|
||||||
// Autogenerated by _dumprawrat in support.c
|
190439170,
|
||||||
NUMBER init_p_pt_eight_five = {
|
901055854,
|
||||||
1,
|
10097,
|
||||||
|
} };
|
||||||
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
|
inline const NUMBER init_p_pt_eight_five = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 85,}
|
{
|
||||||
};
|
85,
|
||||||
NUMBER init_q_pt_eight_five = {
|
} };
|
||||||
1,
|
inline const NUMBER init_q_pt_eight_five = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 100,}
|
{
|
||||||
};
|
100,
|
||||||
// Autogenerated by _dumprawrat in support.c
|
} };
|
||||||
NUMBER init_p_rat_six = {
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
1,
|
inline const NUMBER init_p_rat_six = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 6,}
|
{
|
||||||
};
|
6,
|
||||||
NUMBER init_q_rat_six = {
|
} };
|
||||||
1,
|
inline const NUMBER init_q_rat_six = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 1,}
|
{
|
||||||
};
|
|
||||||
// Autogenerated by _dumprawrat in support.c
|
|
||||||
NUMBER init_p_rat_two = {
|
|
||||||
1,
|
1,
|
||||||
|
} };
|
||||||
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
|
inline const NUMBER init_p_rat_two = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 2,}
|
{
|
||||||
};
|
2,
|
||||||
NUMBER init_q_rat_two = {
|
} };
|
||||||
1,
|
inline const NUMBER init_q_rat_two = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 1,}
|
{
|
||||||
};
|
|
||||||
// Autogenerated by _dumprawrat in support.c
|
|
||||||
NUMBER init_p_rat_zero = {
|
|
||||||
1,
|
1,
|
||||||
|
} };
|
||||||
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
|
inline const NUMBER init_p_rat_zero = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 0,}
|
{
|
||||||
};
|
0,
|
||||||
NUMBER init_q_rat_zero = {
|
} };
|
||||||
1,
|
inline const NUMBER init_q_rat_zero = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 1,}
|
{
|
||||||
};
|
|
||||||
// Autogenerated by _dumprawrat in support.c
|
|
||||||
NUMBER init_p_rat_one = {
|
|
||||||
1,
|
1,
|
||||||
|
} };
|
||||||
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
|
inline const NUMBER init_p_rat_one = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 1,}
|
{
|
||||||
};
|
|
||||||
NUMBER init_q_rat_one = {
|
|
||||||
1,
|
1,
|
||||||
|
} };
|
||||||
|
inline const NUMBER init_q_rat_one = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 1,}
|
{
|
||||||
};
|
1,
|
||||||
// Autogenerated by _dumprawrat in support.c
|
} };
|
||||||
NUMBER init_p_rat_neg_one = {
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
-1,
|
inline const NUMBER init_p_rat_neg_one = { -1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 1,}
|
{
|
||||||
};
|
|
||||||
NUMBER init_q_rat_neg_one = {
|
|
||||||
1,
|
1,
|
||||||
|
} };
|
||||||
|
inline const NUMBER init_q_rat_neg_one = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 1,}
|
{
|
||||||
};
|
|
||||||
// Autogenerated by _dumprawrat in support.c
|
|
||||||
NUMBER init_p_rat_half = {
|
|
||||||
1,
|
1,
|
||||||
|
} };
|
||||||
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
|
inline const NUMBER init_p_rat_half = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 1,}
|
{
|
||||||
};
|
|
||||||
NUMBER init_q_rat_half = {
|
|
||||||
1,
|
1,
|
||||||
|
} };
|
||||||
|
inline const NUMBER init_q_rat_half = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 2,}
|
{
|
||||||
};
|
2,
|
||||||
// Autogenerated by _dumprawrat in support.c
|
} };
|
||||||
NUMBER init_p_rat_ten = {
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
1,
|
inline const NUMBER init_p_rat_ten = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 10,}
|
{
|
||||||
};
|
10,
|
||||||
NUMBER init_q_rat_ten = {
|
} };
|
||||||
1,
|
inline const NUMBER init_q_rat_ten = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 1,}
|
{
|
||||||
};
|
|
||||||
// Autogenerated by _dumprawrat in support.c
|
|
||||||
NUMBER init_p_pi = {
|
|
||||||
1,
|
1,
|
||||||
|
} };
|
||||||
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
|
inline const NUMBER init_p_pi = { 1,
|
||||||
6,
|
6,
|
||||||
0,
|
0,
|
||||||
{ 125527896, 283898350, 1960493936, 1672850762, 1288168272, 8,}
|
{
|
||||||
};
|
125527896,
|
||||||
NUMBER init_q_pi = {
|
283898350,
|
||||||
1,
|
1960493936,
|
||||||
|
1672850762,
|
||||||
|
1288168272,
|
||||||
|
8,
|
||||||
|
} };
|
||||||
|
inline const NUMBER init_q_pi = { 1,
|
||||||
6,
|
6,
|
||||||
0,
|
0,
|
||||||
{ 1288380402, 1120116153, 1860424692, 1944118326, 1583591604, 2,}
|
{
|
||||||
};
|
1288380402,
|
||||||
// Autogenerated by _dumprawrat in support.c
|
1120116153,
|
||||||
NUMBER init_p_two_pi = {
|
1860424692,
|
||||||
1,
|
1944118326,
|
||||||
|
1583591604,
|
||||||
|
2,
|
||||||
|
} };
|
||||||
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
|
inline const NUMBER init_p_two_pi = { 1,
|
||||||
6,
|
6,
|
||||||
0,
|
0,
|
||||||
{ 251055792, 567796700, 1773504224, 1198217877, 428852897, 17,}
|
{
|
||||||
};
|
251055792,
|
||||||
NUMBER init_q_two_pi = {
|
567796700,
|
||||||
1,
|
1773504224,
|
||||||
|
1198217877,
|
||||||
|
428852897,
|
||||||
|
17,
|
||||||
|
} };
|
||||||
|
inline const NUMBER init_q_two_pi = { 1,
|
||||||
6,
|
6,
|
||||||
0,
|
0,
|
||||||
{ 1288380402, 1120116153, 1860424692, 1944118326, 1583591604, 2,}
|
{
|
||||||
};
|
1288380402,
|
||||||
// Autogenerated by _dumprawrat in support.c
|
1120116153,
|
||||||
NUMBER init_p_pi_over_two = {
|
1860424692,
|
||||||
1,
|
1944118326,
|
||||||
|
1583591604,
|
||||||
|
2,
|
||||||
|
} };
|
||||||
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
|
inline const NUMBER init_p_pi_over_two = { 1,
|
||||||
6,
|
6,
|
||||||
0,
|
0,
|
||||||
{ 125527896, 283898350, 1960493936, 1672850762, 1288168272, 8,}
|
{
|
||||||
};
|
125527896,
|
||||||
NUMBER init_q_pi_over_two = {
|
283898350,
|
||||||
1,
|
1960493936,
|
||||||
|
1672850762,
|
||||||
|
1288168272,
|
||||||
|
8,
|
||||||
|
} };
|
||||||
|
inline const NUMBER init_q_pi_over_two = { 1,
|
||||||
6,
|
6,
|
||||||
0,
|
0,
|
||||||
{ 429277156, 92748659, 1573365737, 1740753005, 1019699561, 5,}
|
{
|
||||||
};
|
429277156,
|
||||||
// Autogenerated by _dumprawrat in support.c
|
92748659,
|
||||||
NUMBER init_p_one_pt_five_pi = {
|
1573365737,
|
||||||
1,
|
1740753005,
|
||||||
|
1019699561,
|
||||||
|
5,
|
||||||
|
} };
|
||||||
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
|
inline const NUMBER init_p_one_pt_five_pi = { 1,
|
||||||
6,
|
6,
|
||||||
0,
|
0,
|
||||||
{ 1241201312, 270061909, 1051574664, 1924965045, 1340320627, 70,}
|
{
|
||||||
};
|
1241201312,
|
||||||
NUMBER init_q_one_pt_five_pi = {
|
270061909,
|
||||||
1,
|
1051574664,
|
||||||
|
1924965045,
|
||||||
|
1340320627,
|
||||||
|
70,
|
||||||
|
} };
|
||||||
|
inline const NUMBER init_q_one_pt_five_pi = { 1,
|
||||||
6,
|
6,
|
||||||
0,
|
0,
|
||||||
{ 1579671539, 1837970263, 1067644340, 523549916, 2119366659, 14,}
|
{
|
||||||
};
|
1579671539,
|
||||||
// Autogenerated by _dumprawrat in support.c
|
1837970263,
|
||||||
NUMBER init_p_e_to_one_half = {
|
1067644340,
|
||||||
1,
|
523549916,
|
||||||
|
2119366659,
|
||||||
|
14,
|
||||||
|
} };
|
||||||
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
|
inline const NUMBER init_p_e_to_one_half = { 1,
|
||||||
6,
|
6,
|
||||||
0,
|
0,
|
||||||
{ 256945612, 216219427, 223516738, 477442596, 581063757, 23,}
|
{
|
||||||
};
|
256945612,
|
||||||
NUMBER init_q_e_to_one_half = {
|
216219427,
|
||||||
1,
|
223516738,
|
||||||
|
477442596,
|
||||||
|
581063757,
|
||||||
|
23,
|
||||||
|
} };
|
||||||
|
inline const NUMBER init_q_e_to_one_half = { 1,
|
||||||
6,
|
6,
|
||||||
0,
|
0,
|
||||||
{ 1536828363, 698484484, 1127331835, 224219346, 245499408, 14,}
|
{
|
||||||
};
|
1536828363,
|
||||||
// Autogenerated by _dumprawrat in support.c
|
698484484,
|
||||||
NUMBER init_p_rat_exp = {
|
1127331835,
|
||||||
1,
|
224219346,
|
||||||
|
245499408,
|
||||||
|
14,
|
||||||
|
} };
|
||||||
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
|
inline const NUMBER init_p_rat_exp = { 1,
|
||||||
6,
|
6,
|
||||||
0,
|
0,
|
||||||
{ 943665199, 1606559160, 1094967530, 1759391384, 1671799163, 1123581,}
|
{
|
||||||
};
|
943665199,
|
||||||
NUMBER init_q_rat_exp = {
|
1606559160,
|
||||||
1,
|
1094967530,
|
||||||
|
1759391384,
|
||||||
|
1671799163,
|
||||||
|
1123581,
|
||||||
|
} };
|
||||||
|
inline const NUMBER init_q_rat_exp = { 1,
|
||||||
6,
|
6,
|
||||||
0,
|
0,
|
||||||
{ 879242208, 2022880100, 617392930, 1374929092, 1367479163, 413342,}
|
{
|
||||||
};
|
879242208,
|
||||||
// Autogenerated by _dumprawrat in support.c
|
2022880100,
|
||||||
NUMBER init_p_ln_ten = {
|
617392930,
|
||||||
1,
|
1374929092,
|
||||||
|
1367479163,
|
||||||
|
413342,
|
||||||
|
} };
|
||||||
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
|
inline const NUMBER init_p_ln_ten = { 1,
|
||||||
6,
|
6,
|
||||||
0,
|
0,
|
||||||
{ 2086268922, 165794492, 1416063951, 1851428830, 1893239400, 65366841,}
|
{
|
||||||
};
|
2086268922,
|
||||||
NUMBER init_q_ln_ten = {
|
165794492,
|
||||||
1,
|
1416063951,
|
||||||
|
1851428830,
|
||||||
|
1893239400,
|
||||||
|
65366841,
|
||||||
|
} };
|
||||||
|
inline const NUMBER init_q_ln_ten = { 1,
|
||||||
6,
|
6,
|
||||||
0,
|
0,
|
||||||
{ 26790652, 564532679, 783998273, 216030448, 1564709968, 28388458,}
|
{
|
||||||
};
|
26790652,
|
||||||
// Autogenerated by _dumprawrat in support.c
|
564532679,
|
||||||
NUMBER init_p_ln_two = {
|
783998273,
|
||||||
1,
|
216030448,
|
||||||
|
1564709968,
|
||||||
|
28388458,
|
||||||
|
} };
|
||||||
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
|
inline const NUMBER init_p_ln_two = { 1,
|
||||||
6,
|
6,
|
||||||
0,
|
0,
|
||||||
{ 1789230241, 1057927868, 715399197, 908801241, 1411265331, 3,}
|
{
|
||||||
};
|
1789230241,
|
||||||
NUMBER init_q_ln_two = {
|
1057927868,
|
||||||
1,
|
715399197,
|
||||||
|
908801241,
|
||||||
|
1411265331,
|
||||||
|
3,
|
||||||
|
} };
|
||||||
|
inline const NUMBER init_q_ln_two = { 1,
|
||||||
6,
|
6,
|
||||||
0,
|
0,
|
||||||
{ 1559869847, 1930657510, 1228561531, 219003871, 593099283, 5,}
|
{
|
||||||
};
|
1559869847,
|
||||||
// Autogenerated by _dumprawrat in support.c
|
1930657510,
|
||||||
NUMBER init_p_rad_to_deg = {
|
1228561531,
|
||||||
1,
|
219003871,
|
||||||
|
593099283,
|
||||||
|
5,
|
||||||
|
} };
|
||||||
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
|
inline const NUMBER init_p_rad_to_deg = { 1,
|
||||||
6,
|
6,
|
||||||
0,
|
0,
|
||||||
{ 2127722024, 1904928383, 2016479213, 2048947859, 1578647346, 492,}
|
{
|
||||||
};
|
2127722024,
|
||||||
NUMBER init_q_rad_to_deg = {
|
1904928383,
|
||||||
1,
|
2016479213,
|
||||||
|
2048947859,
|
||||||
|
1578647346,
|
||||||
|
492,
|
||||||
|
} };
|
||||||
|
inline const NUMBER init_q_rad_to_deg = { 1,
|
||||||
6,
|
6,
|
||||||
0,
|
0,
|
||||||
{ 125527896, 283898350, 1960493936, 1672850762, 1288168272, 8,}
|
{
|
||||||
};
|
125527896,
|
||||||
// Autogenerated by _dumprawrat in support.c
|
283898350,
|
||||||
NUMBER init_p_rad_to_grad = {
|
1960493936,
|
||||||
1,
|
1672850762,
|
||||||
|
1288168272,
|
||||||
|
8,
|
||||||
|
} };
|
||||||
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
|
inline const NUMBER init_p_rad_to_grad = { 1,
|
||||||
6,
|
6,
|
||||||
0,
|
0,
|
||||||
{ 2125526288, 684931327, 570267400, 129125085, 1038224725, 547,}
|
{
|
||||||
};
|
2125526288,
|
||||||
NUMBER init_q_rad_to_grad = {
|
684931327,
|
||||||
1,
|
570267400,
|
||||||
|
129125085,
|
||||||
|
1038224725,
|
||||||
|
547,
|
||||||
|
} };
|
||||||
|
inline const NUMBER init_q_rad_to_grad = { 1,
|
||||||
6,
|
6,
|
||||||
0,
|
0,
|
||||||
{ 125527896, 283898350, 1960493936, 1672850762, 1288168272, 8,}
|
{
|
||||||
};
|
125527896,
|
||||||
// Autogenerated by _dumprawrat in support.c
|
283898350,
|
||||||
NUMBER init_p_rat_qword = {
|
1960493936,
|
||||||
1,
|
1672850762,
|
||||||
|
1288168272,
|
||||||
|
8,
|
||||||
|
} };
|
||||||
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
|
inline const NUMBER init_p_rat_qword = { 1,
|
||||||
3,
|
3,
|
||||||
0,
|
0,
|
||||||
{ 2147483647, 2147483647, 3,}
|
{
|
||||||
};
|
2147483647,
|
||||||
NUMBER init_q_rat_qword = {
|
2147483647,
|
||||||
1,
|
3,
|
||||||
|
} };
|
||||||
|
inline const NUMBER init_q_rat_qword = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 1,}
|
{
|
||||||
};
|
|
||||||
// Autogenerated by _dumprawrat in support.c
|
|
||||||
NUMBER init_p_rat_dword = {
|
|
||||||
1,
|
1,
|
||||||
|
} };
|
||||||
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
|
inline const NUMBER init_p_rat_dword = { 1,
|
||||||
2,
|
2,
|
||||||
0,
|
0,
|
||||||
{ 2147483647, 1,}
|
{
|
||||||
};
|
2147483647,
|
||||||
NUMBER init_q_rat_dword = {
|
|
||||||
1,
|
1,
|
||||||
|
} };
|
||||||
|
inline const NUMBER init_q_rat_dword = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 1,}
|
{
|
||||||
};
|
|
||||||
// Autogenerated by _dumprawrat in support.c
|
|
||||||
NUMBER init_p_rat_max_long = {
|
|
||||||
1,
|
1,
|
||||||
|
} };
|
||||||
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
|
inline const NUMBER init_p_rat_max_i32 = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 2147483647,}
|
{
|
||||||
};
|
2147483647,
|
||||||
NUMBER init_q_rat_max_long = {
|
} };
|
||||||
1,
|
inline const NUMBER init_q_rat_max_i32 = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 1,}
|
{
|
||||||
};
|
1,
|
||||||
// Autogenerated by _dumprawrat in support.c
|
} };
|
||||||
NUMBER init_p_rat_min_long = {
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
-1,
|
inline const NUMBER init_p_rat_min_i32 = { -1,
|
||||||
2,
|
2,
|
||||||
0,
|
0,
|
||||||
{ 0, 1,}
|
{
|
||||||
};
|
0,
|
||||||
NUMBER init_q_rat_min_long = {
|
|
||||||
1,
|
1,
|
||||||
|
} };
|
||||||
|
inline const NUMBER init_q_rat_min_i32 = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 1,}
|
{
|
||||||
};
|
|
||||||
// Autogenerated by _dumprawrat in support.c
|
|
||||||
NUMBER init_p_rat_word = {
|
|
||||||
1,
|
1,
|
||||||
|
} };
|
||||||
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
|
inline const NUMBER init_p_rat_word = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 65535,}
|
{
|
||||||
};
|
65535,
|
||||||
NUMBER init_q_rat_word = {
|
} };
|
||||||
1,
|
inline const NUMBER init_q_rat_word = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 1,}
|
{
|
||||||
};
|
|
||||||
// Autogenerated by _dumprawrat in support.c
|
|
||||||
NUMBER init_p_rat_byte = {
|
|
||||||
1,
|
1,
|
||||||
|
} };
|
||||||
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
|
inline const NUMBER init_p_rat_byte = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 255,}
|
{
|
||||||
};
|
255,
|
||||||
NUMBER init_q_rat_byte = {
|
} };
|
||||||
1,
|
inline const NUMBER init_q_rat_byte = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 1,}
|
{
|
||||||
};
|
|
||||||
// Autogenerated by _dumprawrat in support.c
|
|
||||||
NUMBER init_p_rat_400 = {
|
|
||||||
1,
|
1,
|
||||||
|
} };
|
||||||
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
|
inline const NUMBER init_p_rat_400 = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 400,}
|
{
|
||||||
};
|
400,
|
||||||
NUMBER init_q_rat_400 = {
|
} };
|
||||||
1,
|
inline const NUMBER init_q_rat_400 = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 1,}
|
{
|
||||||
};
|
|
||||||
// Autogenerated by _dumprawrat in support.c
|
|
||||||
NUMBER init_p_rat_360 = {
|
|
||||||
1,
|
1,
|
||||||
|
} };
|
||||||
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
|
inline const NUMBER init_p_rat_360 = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 360,}
|
{
|
||||||
};
|
360,
|
||||||
NUMBER init_q_rat_360 = {
|
} };
|
||||||
1,
|
inline const NUMBER init_q_rat_360 = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 1,}
|
{
|
||||||
};
|
|
||||||
// Autogenerated by _dumprawrat in support.c
|
|
||||||
NUMBER init_p_rat_200 = {
|
|
||||||
1,
|
1,
|
||||||
|
} };
|
||||||
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
|
inline const NUMBER init_p_rat_200 = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 200,}
|
{
|
||||||
};
|
200,
|
||||||
NUMBER init_q_rat_200 = {
|
} };
|
||||||
1,
|
inline const NUMBER init_q_rat_200 = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 1,}
|
{
|
||||||
};
|
|
||||||
// Autogenerated by _dumprawrat in support.c
|
|
||||||
NUMBER init_p_rat_180 = {
|
|
||||||
1,
|
1,
|
||||||
|
} };
|
||||||
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
|
inline const NUMBER init_p_rat_180 = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 180,}
|
{
|
||||||
};
|
180,
|
||||||
NUMBER init_q_rat_180 = {
|
} };
|
||||||
1,
|
inline const NUMBER init_q_rat_180 = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 1,}
|
{
|
||||||
};
|
|
||||||
// Autogenerated by _dumprawrat in support.c
|
|
||||||
NUMBER init_p_rat_max_exp = {
|
|
||||||
1,
|
1,
|
||||||
|
} };
|
||||||
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
|
inline const NUMBER init_p_rat_max_exp = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 100000,}
|
{
|
||||||
};
|
100000,
|
||||||
NUMBER init_q_rat_max_exp = {
|
} };
|
||||||
1,
|
inline const NUMBER init_q_rat_max_exp = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 1,}
|
{
|
||||||
};
|
1,
|
||||||
// Autogenerated by _dumprawrat in support.c
|
} };
|
||||||
NUMBER init_p_rat_min_exp = {
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
-1,
|
inline const NUMBER init_p_rat_min_exp = { -1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 100000,}
|
{
|
||||||
};
|
100000,
|
||||||
NUMBER init_q_rat_min_exp = {
|
} };
|
||||||
1,
|
inline const NUMBER init_q_rat_min_exp = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 1,}
|
{
|
||||||
};
|
1,
|
||||||
|
} };
|
||||||
|
|
||||||
// Autogenerated by _dumprawrat in support.c
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
NUMBER init_p_rat_max_fact = {
|
inline const NUMBER init_p_rat_max_fact = { 1,
|
||||||
1,
|
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 3249, }
|
{
|
||||||
};
|
3249,
|
||||||
NUMBER init_q_rat_max_fact = {
|
} };
|
||||||
1,
|
inline const NUMBER init_q_rat_max_fact = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 1, }
|
{
|
||||||
};
|
1,
|
||||||
|
} };
|
||||||
|
|
||||||
// Autogenerated by _dumprawrat in support.c
|
// Autogenerated by _dumprawrat in support.cpp
|
||||||
NUMBER init_p_rat_min_fact = {
|
inline const NUMBER init_p_rat_min_fact = { -1,
|
||||||
-1,
|
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 1000, }
|
{
|
||||||
};
|
1000,
|
||||||
NUMBER init_q_rat_min_fact = {
|
} };
|
||||||
1,
|
inline const NUMBER init_q_rat_min_fact = { 1,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
{ 1, }
|
{
|
||||||
};
|
1,
|
||||||
|
} };
|
||||||
|
|
|
@ -17,24 +17,30 @@
|
||||||
//
|
//
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <string>
|
||||||
#include "CalcErr.h"
|
#include "CalcErr.h"
|
||||||
|
#include <cstring> // for memmove
|
||||||
|
#include <sal.h> // for SAL
|
||||||
|
|
||||||
static constexpr uint32_t BASEXPWR = 31L; // Internal log2(BASEX)
|
static constexpr uint32_t BASEXPWR = 31L; // Internal log2(BASEX)
|
||||||
static constexpr uint32_t BASEX = 0x80000000; // Internal radix used in calculations, hope to raise
|
static constexpr uint32_t BASEX = 0x80000000; // Internal radix used in calculations, hope to raise
|
||||||
// this to 2^32 after solving scaling problems with
|
// this to 2^32 after solving scaling problems with
|
||||||
// overflow detection esp. in mul
|
// overflow detection esp. in mul
|
||||||
|
|
||||||
typedef unsigned long MANTTYPE;
|
typedef uint32_t MANTTYPE;
|
||||||
typedef unsigned __int64 TWO_MANTTYPE;
|
typedef uint64_t TWO_MANTTYPE;
|
||||||
|
|
||||||
enum eNUMOBJ_FMT {
|
enum eNUMOBJ_FMT
|
||||||
|
{
|
||||||
FMT_FLOAT, // returns floating point, or exponential if number is too big
|
FMT_FLOAT, // returns floating point, or exponential if number is too big
|
||||||
FMT_SCIENTIFIC, // always returns scientific notation
|
FMT_SCIENTIFIC, // always returns scientific notation
|
||||||
FMT_ENGINEERING // always returns engineering notation such that exponent is a multiple of 3
|
FMT_ENGINEERING // always returns engineering notation such that exponent is a multiple of 3
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum eANGLE_TYPE {
|
enum eANGLE_TYPE
|
||||||
|
{
|
||||||
ANGLE_DEG, // Calculate trig using 360 degrees per revolution
|
ANGLE_DEG, // Calculate trig using 360 degrees per revolution
|
||||||
ANGLE_RAD, // Calculate trig using 2 pi radians per revolution
|
ANGLE_RAD, // Calculate trig using 2 pi radians per revolution
|
||||||
ANGLE_GRAD // Calculate trig using 400 gradients per revolution
|
ANGLE_GRAD // Calculate trig using 400 gradients per revolution
|
||||||
|
@ -54,10 +60,10 @@ typedef enum eANGLE_TYPE ANGLE_TYPE;
|
||||||
#pragma warning(disable : 4200) // nonstandard extension used : zero-sized array in struct/union
|
#pragma warning(disable : 4200) // nonstandard extension used : zero-sized array in struct/union
|
||||||
typedef struct _number
|
typedef struct _number
|
||||||
{
|
{
|
||||||
long sign; // The sign of the mantissa, +1, or -1
|
int32_t sign; // The sign of the mantissa, +1, or -1
|
||||||
long cdigit; // The number of digits, or what passes for digits in the
|
int32_t cdigit; // The number of digits, or what passes for digits in the
|
||||||
// radix being used.
|
// 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)
|
// (decimal point in radix 10)
|
||||||
MANTTYPE mant[];
|
MANTTYPE mant[];
|
||||||
// This is actually allocated as a continuation of the
|
// This is actually allocated as a continuation of the
|
||||||
|
@ -65,7 +71,6 @@ typedef struct _number
|
||||||
} NUMBER, *PNUMBER, **PPNUMBER;
|
} NUMBER, *PNUMBER, **PPNUMBER;
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// RAT type is a representation radix on 2 NUMBER types.
|
// RAT type is a representation radix on 2 NUMBER types.
|
||||||
|
@ -127,14 +132,21 @@ extern PRAT rat_max_exp;
|
||||||
extern PRAT rat_min_exp;
|
extern PRAT rat_min_exp;
|
||||||
extern PRAT rat_max_fact;
|
extern PRAT rat_max_fact;
|
||||||
extern PRAT rat_min_fact;
|
extern PRAT rat_min_fact;
|
||||||
extern PRAT rat_max_long;
|
extern PRAT rat_max_i32;
|
||||||
extern PRAT rat_min_long;
|
extern PRAT rat_min_i32;
|
||||||
|
|
||||||
// DUPNUM Duplicates a number taking care of allocation and internals
|
// DUPNUM Duplicates a number taking care of allocation and internals
|
||||||
#define DUPNUM(a,b) destroynum(a);createnum( a, (b)->cdigit );_dupnum(a, b);
|
#define DUPNUM(a, b) \
|
||||||
|
destroynum(a); \
|
||||||
|
createnum(a, (b)->cdigit); \
|
||||||
|
_dupnum(a, b);
|
||||||
|
|
||||||
// DUPRAT Duplicates a rational taking care of allocation and internals
|
// DUPRAT Duplicates a rational taking care of allocation and internals
|
||||||
#define DUPRAT(a,b) destroyrat(a);createrat(a);DUPNUM((a)->pp,(b)->pp);DUPNUM((a)->pq,(b)->pq);
|
#define DUPRAT(a, b) \
|
||||||
|
destroyrat(a); \
|
||||||
|
createrat(a); \
|
||||||
|
DUPNUM((a)->pp, (b)->pp); \
|
||||||
|
DUPNUM((a)->pq, (b)->pq);
|
||||||
|
|
||||||
// LOG*RADIX calculates the integral portion of the log of a number in
|
// LOG*RADIX calculates the integral portion of the log of a number in
|
||||||
// the base currently being used, only accurate to within g_ratio
|
// the base currently being used, only accurate to within g_ratio
|
||||||
|
@ -148,6 +160,9 @@ extern PRAT rat_min_long;
|
||||||
#define LOGNUM2(pnum) ((pnum)->cdigit + (pnum)->exp)
|
#define LOGNUM2(pnum) ((pnum)->cdigit + (pnum)->exp)
|
||||||
#define LOGRAT2(prat) (LOGNUM2((prat)->pp) - LOGNUM2((prat)->pq))
|
#define LOGRAT2(prat) (LOGNUM2((prat)->pp) - LOGNUM2((prat)->pq))
|
||||||
|
|
||||||
|
// SIGN returns the sign of the rational
|
||||||
|
#define SIGN(prat) ((prat)->pp->sign * (prat)->pq->sign)
|
||||||
|
|
||||||
#if defined(DEBUG_RATPAK)
|
#if defined(DEBUG_RATPAK)
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
|
@ -156,7 +171,8 @@ extern PRAT rat_min_long;
|
||||||
//
|
//
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#define createrat(y) (y)=_createrat(); \
|
#define createrat(y) \
|
||||||
|
(y) = _createrat(); \
|
||||||
{ \
|
{ \
|
||||||
std::wstringstream outputString; \
|
std::wstringstream outputString; \
|
||||||
outputString << "createrat " << y << " " << #y << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
|
outputString << "createrat " << y << " " << #y << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
|
||||||
|
@ -169,7 +185,8 @@ extern PRAT rat_min_long;
|
||||||
OutputDebugString(outputString.str().c_str()); \
|
OutputDebugString(outputString.str().c_str()); \
|
||||||
} \
|
} \
|
||||||
_destroyrat(x), (x) = nullptr
|
_destroyrat(x), (x) = nullptr
|
||||||
#define createnum(y,x) (y)=_createnum(x); \
|
#define createnum(y, x) \
|
||||||
|
(y) = _createnum(x); \
|
||||||
{ \
|
{ \
|
||||||
std::wstringstream outputString; \
|
std::wstringstream outputString; \
|
||||||
outputString << "createnum " << y << " " << #y << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
|
outputString << "createnum " << y << " " << #y << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
|
||||||
|
@ -197,18 +214,23 @@ _destroynum(x),(x)=nullptr
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
// RENORMALIZE, gets the exponents non-negative.
|
// RENORMALIZE, gets the exponents non-negative.
|
||||||
#define RENORMALIZE(x) if ( (x)->pp->exp < 0 ) { \
|
#define RENORMALIZE(x) \
|
||||||
|
if ((x)->pp->exp < 0) \
|
||||||
|
{ \
|
||||||
(x)->pq->exp -= (x)->pp->exp; \
|
(x)->pq->exp -= (x)->pp->exp; \
|
||||||
(x)->pp->exp = 0; \
|
(x)->pp->exp = 0; \
|
||||||
} \
|
} \
|
||||||
if ( (x)->pq->exp < 0 ) { \
|
if ((x)->pq->exp < 0) \
|
||||||
|
{ \
|
||||||
(x)->pp->exp -= (x)->pq->exp; \
|
(x)->pp->exp -= (x)->pq->exp; \
|
||||||
(x)->pq->exp = 0; \
|
(x)->pq->exp = 0; \
|
||||||
}
|
}
|
||||||
|
|
||||||
// TRIMNUM ASSUMES the number is in radix form NOT INTERNAL BASEX!!!
|
// TRIMNUM ASSUMES the number is in radix form NOT INTERNAL BASEX!!!
|
||||||
#define TRIMNUM(x, precision) if ( !g_ftrueinfinite ) { \
|
#define TRIMNUM(x, precision) \
|
||||||
long trim = (x)->cdigit - precision-g_ratio;\
|
if (!g_ftrueinfinite) \
|
||||||
|
{ \
|
||||||
|
int32_t trim = (x)->cdigit - precision - g_ratio; \
|
||||||
if (trim > 1) \
|
if (trim > 1) \
|
||||||
{ \
|
{ \
|
||||||
memmove((x)->mant, &((x)->mant[trim]), sizeof(MANTTYPE) * ((x)->cdigit - trim)); \
|
memmove((x)->mant, &((x)->mant[trim]), sizeof(MANTTYPE) * ((x)->cdigit - trim)); \
|
||||||
|
@ -217,15 +239,17 @@ memmove( (x)->mant, &((x)->mant[trim]), sizeof(MANTTYPE)*((x)->cdigit-trim) ); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
// TRIMTOP ASSUMES the number is in INTERNAL BASEX!!!
|
// TRIMTOP ASSUMES the number is in INTERNAL BASEX!!!
|
||||||
#define TRIMTOP(x, precision) if ( !g_ftrueinfinite ) { \
|
#define TRIMTOP(x, precision) \
|
||||||
long trim = (x)->pp->cdigit - (precision/g_ratio) - 2;\
|
if (!g_ftrueinfinite) \
|
||||||
|
{ \
|
||||||
|
int32_t trim = (x)->pp->cdigit - (precision / g_ratio) - 2; \
|
||||||
if (trim > 1) \
|
if (trim > 1) \
|
||||||
{ \
|
{ \
|
||||||
memmove((x)->pp->mant, &((x)->pp->mant[trim]), sizeof(MANTTYPE) * ((x)->pp->cdigit - trim)); \
|
memmove((x)->pp->mant, &((x)->pp->mant[trim]), sizeof(MANTTYPE) * ((x)->pp->cdigit - trim)); \
|
||||||
(x)->pp->cdigit -= trim; \
|
(x)->pp->cdigit -= trim; \
|
||||||
(x)->pp->exp += trim; \
|
(x)->pp->exp += trim; \
|
||||||
} \
|
} \
|
||||||
trim = min((x)->pp->exp,(x)->pq->exp);\
|
trim = std::min((x)->pp->exp, (x)->pq->exp); \
|
||||||
(x)->pp->exp -= trim; \
|
(x)->pp->exp -= trim; \
|
||||||
(x)->pq->exp -= trim; \
|
(x)->pq->exp -= trim; \
|
||||||
}
|
}
|
||||||
|
@ -239,17 +263,19 @@ memmove( (x)->pp->mant, &((x)->pp->mant[trim]), sizeof(MANTTYPE)*((x)->pp->cdigi
|
||||||
//
|
//
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#define CREATETAYLOR() PRAT xx=nullptr;\
|
#define CREATETAYLOR() \
|
||||||
|
PRAT xx = nullptr; \
|
||||||
PNUMBER n2 = nullptr; \
|
PNUMBER n2 = nullptr; \
|
||||||
PRAT pret = nullptr; \
|
PRAT pret = nullptr; \
|
||||||
PRAT thisterm = nullptr; \
|
PRAT thisterm = nullptr; \
|
||||||
DUPRAT(xx, *px); \
|
DUPRAT(xx, *px); \
|
||||||
mulrat(&xx, *px, precision); \
|
mulrat(&xx, *px, precision); \
|
||||||
createrat(pret); \
|
createrat(pret); \
|
||||||
pret->pp=longtonum( 0L, BASEX ); \
|
pret->pp = i32tonum(0L, BASEX); \
|
||||||
pret->pq=longtonum( 0L, BASEX );
|
pret->pq = i32tonum(0L, BASEX);
|
||||||
|
|
||||||
#define DESTROYTAYLOR() destroynum( n2 ); \
|
#define DESTROYTAYLOR() \
|
||||||
|
destroynum(n2); \
|
||||||
destroyrat(xx); \
|
destroyrat(xx); \
|
||||||
destroyrat(thisterm); \
|
destroyrat(thisterm); \
|
||||||
destroyrat(*px); \
|
destroyrat(*px); \
|
||||||
|
@ -258,7 +284,8 @@ memmove( (x)->pp->mant, &((x)->pp->mant[trim]), sizeof(MANTTYPE)*((x)->pp->cdigi
|
||||||
|
|
||||||
// INC(a) is the rational equivalent of a++
|
// INC(a) is the rational equivalent of a++
|
||||||
// Check to see if we can avoid doing this the hard way.
|
// Check to see if we can avoid doing this the hard way.
|
||||||
#define INC(a) if ( (a)->mant[0] < BASEX - 1 ) \
|
#define INC(a) \
|
||||||
|
if ((a)->mant[0] < BASEX - 1) \
|
||||||
{ \
|
{ \
|
||||||
(a)->mant[0]++; \
|
(a)->mant[0]++; \
|
||||||
} \
|
} \
|
||||||
|
@ -282,7 +309,9 @@ memmove( (x)->pp->mant, &((x)->pp->mant[trim]), sizeof(MANTTYPE)*((x)->pp->cdigi
|
||||||
// thisterm *= p
|
// thisterm *= p
|
||||||
// d <d is usually an expansion of operations to get thisterm updated.>
|
// d <d is usually an expansion of operations to get thisterm updated.>
|
||||||
// pret += thisterm
|
// pret += thisterm
|
||||||
#define NEXTTERM(p,d,precision) mulrat(&thisterm,p,precision);d addrat( &pret, thisterm, precision )
|
#define NEXTTERM(p, d, precision) \
|
||||||
|
mulrat(&thisterm, p, precision); \
|
||||||
|
d addrat(&pret, thisterm, precision)
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
|
@ -294,7 +323,7 @@ extern bool g_ftrueinfinite; // set to true to allow infinite precision
|
||||||
// don't use unless you know what you are doing
|
// don't use unless you know what you are doing
|
||||||
// used to help decide when to stop calculating.
|
// 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,21 +350,25 @@ extern PNUMBER RatToNumber(_In_ PRAT prat, uint32_t radix, int32_t precision);
|
||||||
// flattens a PRAT by converting it to a PNUMBER and back to a PRAT
|
// flattens a PRAT by converting it to a PNUMBER and back to a PRAT
|
||||||
extern void flatrat(_Inout_ PRAT& prat, uint32_t radix, int32_t precision);
|
extern void flatrat(_Inout_ PRAT& prat, uint32_t radix, int32_t precision);
|
||||||
|
|
||||||
extern long numtolong(_In_ PNUMBER pnum, uint32_t radix );
|
extern int32_t numtoi32(_In_ PNUMBER pnum, uint32_t radix);
|
||||||
extern long rattolong(_In_ PRAT prat, uint32_t radix, int32_t precision);
|
extern int32_t rattoi32(_In_ PRAT prat, uint32_t radix, int32_t precision);
|
||||||
ULONGLONG rattoUlonglong(_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_ ULONG size ); // returns an empty number structure with size digits
|
extern PNUMBER _createnum(_In_ uint32_t size); // returns an empty number structure with size digits
|
||||||
extern PNUMBER nRadixxtonum(_In_ PNUMBER a, uint32_t radix, int32_t precision);
|
extern PNUMBER nRadixxtonum(_In_ PNUMBER a, uint32_t radix, int32_t precision);
|
||||||
extern PNUMBER gcd(_In_ PNUMBER a, _In_ PNUMBER b);
|
extern PNUMBER gcd(_In_ PNUMBER a, _In_ PNUMBER b);
|
||||||
extern PNUMBER StringToNumber(std::wstring_view numberString, uint32_t radix, int32_t precision); // takes a text representation of a number and returns a number.
|
extern PNUMBER StringToNumber(
|
||||||
|
std::wstring_view numberString,
|
||||||
|
uint32_t radix,
|
||||||
|
int32_t precision); // takes a text representation of a number and returns a number.
|
||||||
|
|
||||||
// takes a text representation of a number as a mantissa with sign and an exponent with sign.
|
// takes a text representation of a number as a mantissa with sign and an exponent with sign.
|
||||||
extern PRAT StringToRat(bool mantissaIsNegative, std::wstring_view mantissa, bool exponentIsNegative, std::wstring_view exponent, uint32_t radix, int32_t precision);
|
extern PRAT
|
||||||
|
StringToRat(bool mantissaIsNegative, std::wstring_view mantissa, bool exponentIsNegative, std::wstring_view exponent, uint32_t radix, int32_t precision);
|
||||||
|
|
||||||
extern PNUMBER longfactnum(long inlong, uint32_t radix);
|
extern PNUMBER i32factnum(int32_t ini32, uint32_t radix);
|
||||||
extern PNUMBER longprodnum(long start, long stop, uint32_t radix);
|
extern PNUMBER i32prodnum(int32_t start, int32_t stop, uint32_t radix);
|
||||||
extern PNUMBER longtonum(long inlong, uint32_t radix);
|
extern PNUMBER i32tonum(int32_t ini32, uint32_t radix);
|
||||||
extern PNUMBER Ulongtonum(unsigned long inlong, uint32_t radix);
|
extern PNUMBER Ui32tonum(uint32_t ini32, uint32_t radix);
|
||||||
extern PNUMBER numtonRadixx(PNUMBER a, uint32_t radix);
|
extern PNUMBER numtonRadixx(PNUMBER a, uint32_t radix);
|
||||||
|
|
||||||
// creates a empty/undefined rational representation (p/q)
|
// creates a empty/undefined rational representation (p/q)
|
||||||
|
@ -393,8 +426,8 @@ extern void log10rat( _Inout_ PRAT *px, int32_t precision);
|
||||||
// returns a new rat structure with the natural log of x->p/x->q
|
// returns a new rat structure with the natural log of x->p/x->q
|
||||||
extern void lograt(_Inout_ PRAT* px, int32_t precision);
|
extern void lograt(_Inout_ PRAT* px, int32_t precision);
|
||||||
|
|
||||||
extern PRAT longtorat( long inlong );
|
extern PRAT i32torat(int32_t ini32);
|
||||||
extern PRAT Ulongtorat( unsigned long inulong );
|
extern PRAT Ui32torat(uint32_t inui32);
|
||||||
extern PRAT numtorat(_In_ PNUMBER pin, uint32_t radix);
|
extern PRAT numtorat(_In_ PNUMBER pin, uint32_t radix);
|
||||||
|
|
||||||
extern void sinhrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
|
extern void sinhrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
|
||||||
|
@ -411,7 +444,7 @@ extern void tanrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
|
||||||
// angle type
|
// angle type
|
||||||
extern void tananglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
|
extern void tananglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
|
||||||
|
|
||||||
extern void _dupnum(_In_ PNUMBER dest, _In_ PNUMBER src);
|
extern void _dupnum(_In_ PNUMBER dest, _In_ const NUMBER* const src);
|
||||||
|
|
||||||
extern void _destroynum(_In_ PNUMBER pnum);
|
extern void _destroynum(_In_ PNUMBER pnum);
|
||||||
extern void _destroyrat(_In_ PRAT prat);
|
extern void _destroyrat(_In_ PRAT prat);
|
||||||
|
@ -423,19 +456,20 @@ extern void divnumx( _Inout_ PNUMBER *pa, _In_ PNUMBER b, int32_t precision);
|
||||||
extern void divrat(_Inout_ PRAT* pa, _In_ PRAT b, int32_t precision);
|
extern void divrat(_Inout_ PRAT* pa, _In_ PRAT b, int32_t precision);
|
||||||
extern void fracrat(_Inout_ PRAT* pa, uint32_t radix, int32_t precision);
|
extern void fracrat(_Inout_ PRAT* pa, uint32_t radix, int32_t precision);
|
||||||
extern void factrat(_Inout_ PRAT* pa, uint32_t radix, int32_t precision);
|
extern void factrat(_Inout_ PRAT* pa, uint32_t radix, int32_t precision);
|
||||||
|
extern void remrat(_Inout_ PRAT* pa, _In_ PRAT b);
|
||||||
extern void modrat(_Inout_ PRAT* pa, _In_ PRAT b);
|
extern void modrat(_Inout_ PRAT* pa, _In_ PRAT b);
|
||||||
extern void gcdrat(_Inout_ PRAT* pa, int32_t precision);
|
extern void gcdrat(_Inout_ PRAT* pa, int32_t precision);
|
||||||
extern void intrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
|
extern void intrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
|
||||||
extern void mulnum(_Inout_ PNUMBER* pa, _In_ PNUMBER b, uint32_t radix);
|
extern void mulnum(_Inout_ PNUMBER* pa, _In_ PNUMBER b, uint32_t radix);
|
||||||
extern void mulnumx(_Inout_ PNUMBER* pa, _In_ PNUMBER b);
|
extern void mulnumx(_Inout_ PNUMBER* pa, _In_ PNUMBER b);
|
||||||
extern void mulrat(_Inout_ PRAT* pa, _In_ PRAT b, int32_t precision);
|
extern void mulrat(_Inout_ PRAT* pa, _In_ PRAT b, int32_t precision);
|
||||||
extern void numpowlong( _Inout_ PNUMBER *proot, long power, uint32_t radix, int32_t precision);
|
extern void numpowi32(_Inout_ PNUMBER* proot, int32_t power, uint32_t radix, int32_t precision);
|
||||||
extern void numpowlongx( _Inout_ PNUMBER *proot, long power );
|
extern void numpowi32x(_Inout_ PNUMBER* proot, int32_t power);
|
||||||
extern void orrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
|
extern void orrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
|
||||||
extern void powrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
|
extern void powrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
|
||||||
extern void powratNumeratorDenominator(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
|
extern void powratNumeratorDenominator(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
|
||||||
extern void powratcomp(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
|
extern void powratcomp(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
|
||||||
extern void 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 remnum(_Inout_ PNUMBER* pa, _In_ PNUMBER b, uint32_t radix);
|
||||||
extern void rootrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
|
extern void rootrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
|
||||||
extern void scale2pi(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
|
extern void scale2pi(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
|
||||||
|
|
|
@ -18,7 +18,9 @@
|
||||||
//
|
//
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "pch.h"
|
#include <string>
|
||||||
|
#include <cstring> // for memmove
|
||||||
|
#include <iostream> // for wostream
|
||||||
#include "ratpak.h"
|
#include "ratpak.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -30,23 +32,34 @@ static int cbitsofprecision = 0;
|
||||||
#define READRAWRAT(v)
|
#define READRAWRAT(v)
|
||||||
#define READRAWNUM(v)
|
#define READRAWNUM(v)
|
||||||
#define DUMPRAWRAT(v) _dumprawrat(#v, v, wcout)
|
#define DUMPRAWRAT(v) _dumprawrat(#v, v, wcout)
|
||||||
#define DUMPRAWNUM(v) fprintf( stderr, \
|
#define DUMPRAWNUM(v) \
|
||||||
"// Autogenerated by _dumprawrat in support.c\n" ); \
|
fprintf(stderr, "// Autogenerated by _dumprawrat in support.cpp\n"); \
|
||||||
fprintf( stderr, "NUMBER init_" #v "= {\n" ); \
|
fprintf(stderr, "inline const NUMBER init_" #v "= {\n"); \
|
||||||
_dumprawnum(v, wcout); \
|
_dumprawnum(v, wcout); \
|
||||||
fprintf(stderr, "};\n")
|
fprintf(stderr, "};\n")
|
||||||
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define DUMPRAWRAT(v)
|
#define DUMPRAWRAT(v)
|
||||||
#define DUMPRAWNUM(v)
|
#define DUMPRAWNUM(v)
|
||||||
#define READRAWRAT(v) createrat(v); DUPNUM((v)->pp,(&(init_p_##v))); \
|
#define READRAWRAT(v) \
|
||||||
|
createrat(v); \
|
||||||
|
DUPNUM((v)->pp, (&(init_p_##v))); \
|
||||||
DUPNUM((v)->pq, (&(init_q_##v)));
|
DUPNUM((v)->pq, (&(init_q_##v)));
|
||||||
#define READRAWNUM(v) DUPNUM(v, (&(init_##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_NUM_IF_NULL(r, v) \
|
||||||
#define INIT_AND_DUMP_RAW_RAT_IF_NULL(r, v) if (r == nullptr) { r = longtorat(v); DUMPRAWRAT(v); }
|
if (r == nullptr) \
|
||||||
|
{ \
|
||||||
|
r = i32tonum(v, BASEX); \
|
||||||
|
DUMPRAWNUM(v); \
|
||||||
|
}
|
||||||
|
#define INIT_AND_DUMP_RAW_RAT_IF_NULL(r, v) \
|
||||||
|
if (r == nullptr) \
|
||||||
|
{ \
|
||||||
|
r = i32torat(v); \
|
||||||
|
DUMPRAWRAT(v); \
|
||||||
|
}
|
||||||
|
|
||||||
static constexpr int RATIO_FOR_DECIMAL = 9;
|
static constexpr int RATIO_FOR_DECIMAL = 9;
|
||||||
static constexpr int DECIMAL = 10;
|
static constexpr int DECIMAL = 10;
|
||||||
|
@ -87,7 +100,7 @@ PRAT rat_exp= nullptr;
|
||||||
PRAT rad_to_deg = nullptr;
|
PRAT rad_to_deg = nullptr;
|
||||||
PRAT rad_to_grad = nullptr;
|
PRAT rad_to_grad = nullptr;
|
||||||
PRAT rat_qword = nullptr;
|
PRAT rat_qword = nullptr;
|
||||||
PRAT rat_dword= nullptr; // unsigned max ulong
|
PRAT rat_dword = nullptr; // unsigned max ui32
|
||||||
PRAT rat_word = nullptr;
|
PRAT rat_word = nullptr;
|
||||||
PRAT rat_byte = nullptr;
|
PRAT rat_byte = nullptr;
|
||||||
PRAT rat_360 = nullptr;
|
PRAT rat_360 = nullptr;
|
||||||
|
@ -101,8 +114,8 @@ PRAT rat_max_exp= nullptr;
|
||||||
PRAT rat_min_exp = nullptr;
|
PRAT rat_min_exp = nullptr;
|
||||||
PRAT rat_max_fact = nullptr;
|
PRAT rat_max_fact = nullptr;
|
||||||
PRAT rat_min_fact = nullptr;
|
PRAT rat_min_fact = nullptr;
|
||||||
PRAT rat_min_long= nullptr; // min signed long
|
PRAT rat_min_i32 = nullptr; // min signed i32
|
||||||
PRAT rat_max_long= nullptr; // max signed long
|
PRAT rat_max_i32 = nullptr; // max signed i32
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
|
@ -132,7 +145,7 @@ void ChangeConstants(uint32_t radix, int32_t precision)
|
||||||
g_ratio += !g_ratio;
|
g_ratio += !g_ratio;
|
||||||
|
|
||||||
destroyrat(rat_nRadix);
|
destroyrat(rat_nRadix);
|
||||||
rat_nRadix=longtorat( radix );
|
rat_nRadix = i32torat(radix);
|
||||||
|
|
||||||
// Check to see what we have to recalculate and what we don't
|
// Check to see what we have to recalculate and what we don't
|
||||||
if (cbitsofprecision < (g_ratio * static_cast<int32_t>(radix) * precision))
|
if (cbitsofprecision < (g_ratio * static_cast<int32_t>(radix) * precision))
|
||||||
|
@ -166,7 +179,7 @@ void ChangeConstants(uint32_t radix, int32_t precision)
|
||||||
INIT_AND_DUMP_RAW_RAT_IF_NULL(rat_min_fact, -1000);
|
INIT_AND_DUMP_RAW_RAT_IF_NULL(rat_min_fact, -1000);
|
||||||
|
|
||||||
DUPRAT(rat_smallest, rat_nRadix);
|
DUPRAT(rat_smallest, rat_nRadix);
|
||||||
ratpowlong(&rat_smallest, -precision, precision);
|
ratpowi32(&rat_smallest, -precision, precision);
|
||||||
DUPRAT(rat_negsmallest, rat_smallest);
|
DUPRAT(rat_negsmallest, rat_smallest);
|
||||||
rat_negsmallest->pp->sign = -1;
|
rat_negsmallest->pp->sign = -1;
|
||||||
DUMPRAWRAT(rat_smallest);
|
DUMPRAWRAT(rat_smallest);
|
||||||
|
@ -183,29 +196,29 @@ void ChangeConstants(uint32_t radix, int32_t precision)
|
||||||
if (pt_eight_five == nullptr)
|
if (pt_eight_five == nullptr)
|
||||||
{
|
{
|
||||||
createrat(pt_eight_five);
|
createrat(pt_eight_five);
|
||||||
pt_eight_five->pp = longtonum(85L, BASEX);
|
pt_eight_five->pp = i32tonum(85L, BASEX);
|
||||||
pt_eight_five->pq = longtonum(100L, BASEX);
|
pt_eight_five->pq = i32tonum(100L, BASEX);
|
||||||
DUMPRAWRAT(pt_eight_five);
|
DUMPRAWRAT(pt_eight_five);
|
||||||
}
|
}
|
||||||
|
|
||||||
DUPRAT(rat_qword, rat_two);
|
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);
|
subrat(&rat_qword, rat_one, precision);
|
||||||
DUMPRAWRAT(rat_qword);
|
DUMPRAWRAT(rat_qword);
|
||||||
|
|
||||||
DUPRAT(rat_dword, rat_two);
|
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);
|
subrat(&rat_dword, rat_one, precision);
|
||||||
DUMPRAWRAT(rat_dword);
|
DUMPRAWRAT(rat_dword);
|
||||||
|
|
||||||
DUPRAT(rat_max_long, rat_two);
|
DUPRAT(rat_max_i32, rat_two);
|
||||||
numpowlong(&(rat_max_long->pp), 31, BASEX, precision);
|
numpowi32(&(rat_max_i32->pp), 31, BASEX, precision);
|
||||||
DUPRAT(rat_min_long, rat_max_long);
|
DUPRAT(rat_min_i32, rat_max_i32);
|
||||||
subrat(&rat_max_long, rat_one, precision); // rat_max_long = 2^31 -1
|
subrat(&rat_max_i32, rat_one, precision); // rat_max_i32 = 2^31 -1
|
||||||
DUMPRAWRAT(rat_max_long);
|
DUMPRAWRAT(rat_max_i32);
|
||||||
|
|
||||||
rat_min_long->pp->sign *= -1; // rat_min_long = -2^31
|
rat_min_i32->pp->sign *= -1; // rat_min_i32 = -2^31
|
||||||
DUMPRAWRAT(rat_min_long);
|
DUMPRAWRAT(rat_min_i32);
|
||||||
|
|
||||||
DUPRAT(rat_min_exp, rat_max_exp);
|
DUPRAT(rat_min_exp, rat_max_exp);
|
||||||
rat_min_exp->pp->sign *= -1;
|
rat_min_exp->pp->sign *= -1;
|
||||||
|
@ -215,7 +228,7 @@ void ChangeConstants(uint32_t radix, int32_t precision)
|
||||||
|
|
||||||
// Apparently when dividing 180 by pi, another (internal) digit of
|
// Apparently when dividing 180 by pi, another (internal) digit of
|
||||||
// precision is needed.
|
// precision is needed.
|
||||||
long extraPrecision = precision + g_ratio;
|
int32_t extraPrecision = precision + g_ratio;
|
||||||
DUPRAT(pi, rat_half);
|
DUPRAT(pi, rat_half);
|
||||||
asinrat(&pi, radix, extraPrecision);
|
asinrat(&pi, radix, extraPrecision);
|
||||||
mulrat(&pi, rat_six, extraPrecision);
|
mulrat(&pi, rat_six, extraPrecision);
|
||||||
|
@ -251,14 +264,13 @@ void ChangeConstants(uint32_t radix, int32_t precision)
|
||||||
lograt(&ln_two, extraPrecision);
|
lograt(&ln_two, extraPrecision);
|
||||||
DUMPRAWRAT(ln_two);
|
DUMPRAWRAT(ln_two);
|
||||||
|
|
||||||
|
|
||||||
destroyrat(rad_to_deg);
|
destroyrat(rad_to_deg);
|
||||||
rad_to_deg = longtorat(180L);
|
rad_to_deg = i32torat(180L);
|
||||||
divrat(&rad_to_deg, pi, extraPrecision);
|
divrat(&rad_to_deg, pi, extraPrecision);
|
||||||
DUMPRAWRAT(rad_to_deg);
|
DUMPRAWRAT(rad_to_deg);
|
||||||
|
|
||||||
destroyrat(rad_to_grad);
|
destroyrat(rad_to_grad);
|
||||||
rad_to_grad = longtorat(200L);
|
rad_to_grad = i32torat(200L);
|
||||||
divrat(&rad_to_grad, pi, extraPrecision);
|
divrat(&rad_to_grad, pi, extraPrecision);
|
||||||
DUMPRAWRAT(rad_to_grad);
|
DUMPRAWRAT(rad_to_grad);
|
||||||
}
|
}
|
||||||
|
@ -267,11 +279,10 @@ void ChangeConstants(uint32_t radix, int32_t precision)
|
||||||
_readconstants();
|
_readconstants();
|
||||||
|
|
||||||
DUPRAT(rat_smallest, rat_nRadix);
|
DUPRAT(rat_smallest, rat_nRadix);
|
||||||
ratpowlong(&rat_smallest, -precision, precision);
|
ratpowi32(&rat_smallest, -precision, precision);
|
||||||
DUPRAT(rat_negsmallest, rat_smallest);
|
DUPRAT(rat_negsmallest, rat_smallest);
|
||||||
rat_negsmallest->pp->sign = -1;
|
rat_negsmallest->pp->sign = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
@ -296,7 +307,7 @@ void intrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||||
// Subtract the fractional part of the rational
|
// Subtract the fractional part of the rational
|
||||||
PRAT pret = nullptr;
|
PRAT pret = nullptr;
|
||||||
DUPRAT(pret, *px);
|
DUPRAT(pret, *px);
|
||||||
modrat( &pret, rat_one );
|
remrat(&pret, rat_one);
|
||||||
|
|
||||||
subrat(px, pret, precision);
|
subrat(px, pret, precision);
|
||||||
destroyrat(pret);
|
destroyrat(pret);
|
||||||
|
@ -333,7 +344,7 @@ bool rat_equ( PRAT a, PRAT b, int32_t precision)
|
||||||
//
|
//
|
||||||
// FUNCTION: rat_ge
|
// 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
|
// RETURN: true if a is greater than or equal to b
|
||||||
//
|
//
|
||||||
|
@ -348,13 +359,11 @@ bool rat_ge( PRAT a, PRAT b, int32_t precision)
|
||||||
b->pp->sign *= -1;
|
b->pp->sign *= -1;
|
||||||
addrat(&rattmp, b, precision);
|
addrat(&rattmp, b, precision);
|
||||||
b->pp->sign *= -1;
|
b->pp->sign *= -1;
|
||||||
bool bret = ( zernum( rattmp->pp ) ||
|
bool bret = (zernum(rattmp->pp) || SIGN(rattmp) == 1);
|
||||||
rattmp->pp->sign * rattmp->pq->sign == 1 );
|
|
||||||
destroyrat(rattmp);
|
destroyrat(rattmp);
|
||||||
return (bret);
|
return (bret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// FUNCTION: rat_gt
|
// FUNCTION: rat_gt
|
||||||
|
@ -374,8 +383,7 @@ bool rat_gt( PRAT a, PRAT b, int32_t precision)
|
||||||
b->pp->sign *= -1;
|
b->pp->sign *= -1;
|
||||||
addrat(&rattmp, b, precision);
|
addrat(&rattmp, b, precision);
|
||||||
b->pp->sign *= -1;
|
b->pp->sign *= -1;
|
||||||
bool bret = ( !zernum( rattmp->pp ) &&
|
bool bret = (!zernum(rattmp->pp) && SIGN(rattmp) == 1);
|
||||||
rattmp->pp->sign * rattmp->pq->sign == 1 );
|
|
||||||
destroyrat(rattmp);
|
destroyrat(rattmp);
|
||||||
return (bret);
|
return (bret);
|
||||||
}
|
}
|
||||||
|
@ -384,7 +392,7 @@ bool rat_gt( PRAT a, PRAT b, int32_t precision)
|
||||||
//
|
//
|
||||||
// FUNCTION: rat_le
|
// 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
|
// RETURN: true if a is less than or equal to b
|
||||||
//
|
//
|
||||||
|
@ -394,24 +402,21 @@ bool rat_gt( PRAT a, PRAT b, int32_t precision)
|
||||||
bool rat_le(PRAT a, PRAT b, int32_t precision)
|
bool rat_le(PRAT a, PRAT b, int32_t precision)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
PRAT rattmp = nullptr;
|
PRAT rattmp = nullptr;
|
||||||
DUPRAT(rattmp, a);
|
DUPRAT(rattmp, a);
|
||||||
b->pp->sign *= -1;
|
b->pp->sign *= -1;
|
||||||
addrat(&rattmp, b, precision);
|
addrat(&rattmp, b, precision);
|
||||||
b->pp->sign *= -1;
|
b->pp->sign *= -1;
|
||||||
bool bret = ( zernum( rattmp->pp ) ||
|
bool bret = (zernum(rattmp->pp) || SIGN(rattmp) == -1);
|
||||||
rattmp->pp->sign * rattmp->pq->sign == -1 );
|
|
||||||
destroyrat(rattmp);
|
destroyrat(rattmp);
|
||||||
return (bret);
|
return (bret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// FUNCTION: rat_lt
|
// 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
|
// RETURN: true if a is less than b
|
||||||
//
|
//
|
||||||
|
@ -426,13 +431,11 @@ bool rat_lt( PRAT a, PRAT b, int32_t precision)
|
||||||
b->pp->sign *= -1;
|
b->pp->sign *= -1;
|
||||||
addrat(&rattmp, b, precision);
|
addrat(&rattmp, b, precision);
|
||||||
b->pp->sign *= -1;
|
b->pp->sign *= -1;
|
||||||
bool bret = ( !zernum( rattmp->pp ) &&
|
bool bret = (!zernum(rattmp->pp) && SIGN(rattmp) == -1);
|
||||||
rattmp->pp->sign * rattmp->pq->sign == -1 );
|
|
||||||
destroyrat(rattmp);
|
destroyrat(rattmp);
|
||||||
return (bret);
|
return (bret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// FUNCTION: rat_neq
|
// FUNCTION: rat_neq
|
||||||
|
@ -444,7 +447,6 @@ bool rat_lt( PRAT a, PRAT b, int32_t precision)
|
||||||
//
|
//
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
bool rat_neq(PRAT a, PRAT b, int32_t precision)
|
bool rat_neq(PRAT a, PRAT b, int32_t precision)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -475,8 +477,7 @@ void scale( PRAT *px, PRAT scalefact, uint32_t radix, int32_t precision )
|
||||||
|
|
||||||
// Logscale is a quick way to tell how much extra precision is needed for
|
// Logscale is a quick way to tell how much extra precision is needed for
|
||||||
// scaling by scalefact.
|
// 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));
|
||||||
(pret->pq->cdigit+pret->pq->exp) );
|
|
||||||
if (logscale > 0)
|
if (logscale > 0)
|
||||||
{
|
{
|
||||||
precision += logscale;
|
precision += logscale;
|
||||||
|
@ -510,8 +511,7 @@ void scale2pi( PRAT *px, uint32_t radix, int32_t precision )
|
||||||
|
|
||||||
// Logscale is a quick way to tell how much extra precision is needed for
|
// Logscale is a quick way to tell how much extra precision is needed for
|
||||||
// scaling by 2 pi.
|
// scaling by 2 pi.
|
||||||
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));
|
||||||
(pret->pq->cdigit+pret->pq->exp) );
|
|
||||||
if (logscale > 0)
|
if (logscale > 0)
|
||||||
{
|
{
|
||||||
precision += logscale;
|
precision += logscale;
|
||||||
|
@ -652,15 +652,15 @@ void _readconstants( void )
|
||||||
READRAWRAT(rat_min_exp);
|
READRAWRAT(rat_min_exp);
|
||||||
READRAWRAT(rat_max_fact);
|
READRAWRAT(rat_max_fact);
|
||||||
READRAWRAT(rat_min_fact);
|
READRAWRAT(rat_min_fact);
|
||||||
READRAWRAT(rat_min_long);
|
READRAWRAT(rat_min_i32);
|
||||||
READRAWRAT(rat_max_long);
|
READRAWRAT(rat_max_i32);
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// FUNCTION: trimit
|
// FUNCTION: trimit
|
||||||
//
|
//
|
||||||
// ARGUMENTS: PRAT *px, long precision
|
// ARGUMENTS: PRAT *px, int32_t precision
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// DESCRIPTION: Chops off digits from rational numbers to avoid time
|
// DESCRIPTION: Chops off digits from rational numbers to avoid time
|
||||||
|
@ -681,7 +681,7 @@ void trimit( PRAT *px, int32_t precision)
|
||||||
{
|
{
|
||||||
if (!g_ftrueinfinite)
|
if (!g_ftrueinfinite)
|
||||||
{
|
{
|
||||||
long trim;
|
int32_t trim;
|
||||||
PNUMBER pp = (*px)->pp;
|
PNUMBER pp = (*px)->pp;
|
||||||
PNUMBER pq = (*px)->pq;
|
PNUMBER pq = (*px)->pq;
|
||||||
trim = g_ratio * (min((pp->cdigit + pp->exp), (pq->cdigit + pq->exp)) - 1) - precision;
|
trim = g_ratio * (min((pp->cdigit + pp->exp), (pq->cdigit + pq->exp)) - 1) - precision;
|
||||||
|
|
|
@ -14,11 +14,8 @@
|
||||||
//
|
//
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "pch.h"
|
|
||||||
#include "ratpak.h"
|
#include "ratpak.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void scalerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
|
void scalerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
|
||||||
{
|
{
|
||||||
switch (angletype)
|
switch (angletype)
|
||||||
|
@ -35,7 +32,6 @@ void scalerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t p
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
// FUNCTION: sinrat, _sinrat
|
// FUNCTION: sinrat, _sinrat
|
||||||
|
@ -67,7 +63,6 @@ void scalerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t p
|
||||||
//
|
//
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
void _sinrat(PRAT* px, int32_t precision)
|
void _sinrat(PRAT* px, int32_t precision)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -79,7 +74,8 @@ void _sinrat( PRAT *px, int32_t precision)
|
||||||
DUPNUM(n2, num_one);
|
DUPNUM(n2, num_one);
|
||||||
xx->pp->sign *= -1;
|
xx->pp->sign *= -1;
|
||||||
|
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
NEXTTERM(xx, INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
NEXTTERM(xx, INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||||
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
||||||
|
|
||||||
|
@ -159,7 +155,6 @@ void sinanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_
|
||||||
//
|
//
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
void _cosrat(PRAT* px, uint32_t radix, int32_t precision)
|
void _cosrat(PRAT* px, uint32_t radix, int32_t precision)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -168,15 +163,16 @@ void _cosrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||||
destroynum(pret->pp);
|
destroynum(pret->pp);
|
||||||
destroynum(pret->pq);
|
destroynum(pret->pq);
|
||||||
|
|
||||||
pret->pp=longtonum( 1L, radix);
|
pret->pp = i32tonum(1L, radix);
|
||||||
pret->pq=longtonum( 1L, radix);
|
pret->pq = i32tonum(1L, radix);
|
||||||
|
|
||||||
DUPRAT(thisterm, pret)
|
DUPRAT(thisterm, pret)
|
||||||
|
|
||||||
n2=longtonum(0L, radix);
|
n2 = i32tonum(0L, radix);
|
||||||
xx->pp->sign *= -1;
|
xx->pp->sign *= -1;
|
||||||
|
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
NEXTTERM(xx, INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
NEXTTERM(xx, INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||||
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
||||||
|
|
||||||
|
@ -243,7 +239,6 @@ void cosanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_
|
||||||
//
|
//
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
void _tanrat(PRAT* px, uint32_t radix, int32_t precision)
|
void _tanrat(PRAT* px, uint32_t radix, int32_t precision)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -260,7 +255,6 @@ void _tanrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||||
divrat(px, ptmp, precision);
|
divrat(px, ptmp, precision);
|
||||||
|
|
||||||
destroyrat(ptmp);
|
destroyrat(ptmp);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void tanrat(PRAT* px, uint32_t radix, int32_t precision)
|
void tanrat(PRAT* px, uint32_t radix, int32_t precision)
|
||||||
|
@ -294,4 +288,3 @@ void tananglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_
|
||||||
}
|
}
|
||||||
_tanrat(pa, radix, precision);
|
_tanrat(pa, radix, precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,11 +14,8 @@
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#include "pch.h"
|
|
||||||
#include "ratpak.h"
|
#include "ratpak.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool IsValidForHypFunc(PRAT px, int32_t precision)
|
bool IsValidForHypFunc(PRAT px, int32_t precision)
|
||||||
{
|
{
|
||||||
PRAT ptmp = nullptr;
|
PRAT ptmp = nullptr;
|
||||||
|
@ -32,7 +29,6 @@ bool IsValidForHypFunc(PRAT px, int32_t precision)
|
||||||
}
|
}
|
||||||
destroyrat(ptmp);
|
destroyrat(ptmp);
|
||||||
return bRet;
|
return bRet;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -68,7 +64,6 @@ bool IsValidForHypFunc(PRAT px, int32_t precision)
|
||||||
//
|
//
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
void _sinhrat(PRAT* px, int32_t precision)
|
void _sinhrat(PRAT* px, int32_t precision)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -85,7 +80,8 @@ void _sinhrat( PRAT *px, int32_t precision)
|
||||||
|
|
||||||
DUPNUM(n2, num_one);
|
DUPNUM(n2, num_one);
|
||||||
|
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
NEXTTERM(xx, INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
NEXTTERM(xx, INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||||
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
||||||
|
|
||||||
|
@ -147,7 +143,6 @@ void sinhrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||||
//
|
//
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
void _coshrat(PRAT* px, uint32_t radix, int32_t precision)
|
void _coshrat(PRAT* px, uint32_t radix, int32_t precision)
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -159,14 +154,15 @@ void _coshrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||||
|
|
||||||
CREATETAYLOR();
|
CREATETAYLOR();
|
||||||
|
|
||||||
pret->pp=longtonum( 1L, radix);
|
pret->pp = i32tonum(1L, radix);
|
||||||
pret->pq=longtonum( 1L, radix);
|
pret->pq = i32tonum(1L, radix);
|
||||||
|
|
||||||
DUPRAT(thisterm, pret)
|
DUPRAT(thisterm, pret)
|
||||||
|
|
||||||
n2=longtonum(0L, radix);
|
n2 = i32tonum(0L, radix);
|
||||||
|
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
NEXTTERM(xx, INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
NEXTTERM(xx, INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||||
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
||||||
|
|
||||||
|
@ -227,5 +223,4 @@ void tanhrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||||
mulnumx(&((*px)->pq), ptmp->pp);
|
mulnumx(&((*px)->pq), ptmp->pp);
|
||||||
|
|
||||||
destroyrat(ptmp);
|
destroyrat(ptmp);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
#include "pch.h"
|
#include <cassert>
|
||||||
|
#include <sstream>
|
||||||
|
#include <algorithm> // for std::sort
|
||||||
#include "Command.h"
|
#include "Command.h"
|
||||||
#include "UnitConverter.h"
|
#include "UnitConverter.h"
|
||||||
|
|
||||||
|
@ -32,8 +34,8 @@ unordered_map<wstring, wchar_t> unquoteConversions;
|
||||||
/// Constructor, sets up all the variables and requires a configLoader
|
/// Constructor, sets up all the variables and requires a configLoader
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dataLoader">An instance of the IConverterDataLoader interface which we use to read in category/unit names and conversion data</param>
|
/// <param name="dataLoader">An instance of the IConverterDataLoader interface which we use to read in category/unit names and conversion data</param>
|
||||||
UnitConverter::UnitConverter(_In_ const shared_ptr<IConverterDataLoader>& dataLoader) :
|
UnitConverter::UnitConverter(_In_ const shared_ptr<IConverterDataLoader>& dataLoader)
|
||||||
UnitConverter::UnitConverter(dataLoader, nullptr)
|
: UnitConverter::UnitConverter(dataLoader, nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +65,8 @@ UnitConverter::UnitConverter(_In_ const shared_ptr<IConverterDataLoader>& dataLo
|
||||||
unquoteConversions[L"{sc}"] = L';';
|
unquoteConversions[L"{sc}"] = L';';
|
||||||
unquoteConversions[L"{lb}"] = LEFTESCAPECHAR;
|
unquoteConversions[L"{lb}"] = LEFTESCAPECHAR;
|
||||||
unquoteConversions[L"{rb}"] = RIGHTESCAPECHAR;
|
unquoteConversions[L"{rb}"] = RIGHTESCAPECHAR;
|
||||||
Reset();
|
ClearValues();
|
||||||
|
ResetCategoriesAndRatios();
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnitConverter::Initialize()
|
void UnitConverter::Initialize()
|
||||||
|
@ -75,7 +78,7 @@ bool UnitConverter::CheckLoad()
|
||||||
{
|
{
|
||||||
if (m_categories.empty())
|
if (m_categories.empty())
|
||||||
{
|
{
|
||||||
Reset();
|
ResetCategoriesAndRatios();
|
||||||
}
|
}
|
||||||
return !m_categories.empty();
|
return !m_categories.empty();
|
||||||
}
|
}
|
||||||
|
@ -109,22 +112,8 @@ CategorySelectionInitializer UnitConverter::SetCurrentCategory(const Category& i
|
||||||
vector<Unit>& unitVector = m_categoryToUnits[m_currentCategory];
|
vector<Unit>& unitVector = m_categoryToUnits[m_currentCategory];
|
||||||
for (unsigned int i = 0; i < unitVector.size(); i++)
|
for (unsigned int i = 0; i < unitVector.size(); i++)
|
||||||
{
|
{
|
||||||
if (unitVector[i].id == m_fromType.id)
|
unitVector[i].isConversionSource = (unitVector[i].id == m_fromType.id);
|
||||||
{
|
unitVector[i].isConversionTarget = (unitVector[i].id == m_toType.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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
m_currentCategory = input;
|
m_currentCategory = input;
|
||||||
if (!m_currentCategory.supportsNegative && m_currentDisplay.front() == L'-')
|
if (!m_currentCategory.supportsNegative && m_currentDisplay.front() == L'-')
|
||||||
|
@ -156,15 +145,16 @@ Category UnitConverter::GetCurrentCategory()
|
||||||
/// <param name="toType">Unit struct we are converting to</param>
|
/// <param name="toType">Unit struct we are converting to</param>
|
||||||
void UnitConverter::SetCurrentUnitTypes(const Unit& fromType, const Unit& toType)
|
void UnitConverter::SetCurrentUnitTypes(const Unit& fromType, const Unit& toType)
|
||||||
{
|
{
|
||||||
if (CheckLoad())
|
if (!CheckLoad())
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_fromType = fromType;
|
m_fromType = fromType;
|
||||||
m_toType = toType;
|
m_toType = toType;
|
||||||
Calculate();
|
Calculate();
|
||||||
|
|
||||||
UpdateCurrencySymbols();
|
UpdateCurrencySymbols();
|
||||||
UpdateViewModel();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -181,8 +171,11 @@ void UnitConverter::SetCurrentUnitTypes(const Unit& fromType, const Unit& toType
|
||||||
/// </param>
|
/// </param>
|
||||||
void UnitConverter::SwitchActive(const wstring& newValue)
|
void UnitConverter::SwitchActive(const wstring& newValue)
|
||||||
{
|
{
|
||||||
if (CheckLoad())
|
if (!CheckLoad())
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
swap(m_fromType, m_toType);
|
swap(m_fromType, m_toType);
|
||||||
swap(m_currentHasDecimal, m_returnHasDecimal);
|
swap(m_currentHasDecimal, m_returnHasDecimal);
|
||||||
m_returnDisplay = m_currentDisplay;
|
m_returnDisplay = m_currentDisplay;
|
||||||
|
@ -198,7 +191,6 @@ void UnitConverter::SwitchActive(const wstring& newValue)
|
||||||
m_vmCurrencyCallback->CurrencyRatiosCallback(currencyRatios.first, currencyRatios.second);
|
m_vmCurrencyCallback->CurrencyRatiosCallback(currencyRatios.first, currencyRatios.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
wstring UnitConverter::CategoryToString(const Category& c, const wchar_t* delimiter)
|
wstring UnitConverter::CategoryToString(const Category& c, const wchar_t* delimiter)
|
||||||
{
|
{
|
||||||
|
@ -240,7 +232,9 @@ Category UnitConverter::StringToCategory(const wstring& w)
|
||||||
wstring UnitConverter::UnitToString(const Unit& u, const wchar_t* delimiter)
|
wstring UnitConverter::UnitToString(const Unit& u, const wchar_t* delimiter)
|
||||||
{
|
{
|
||||||
wstringstream out(wstringstream::out);
|
wstringstream out(wstringstream::out);
|
||||||
out << Quote(std::to_wstring(u.id)) << delimiter << Quote(u.name) << delimiter << Quote(u.abbreviation) << delimiter << std::to_wstring(u.isConversionSource) << delimiter << std::to_wstring(u.isConversionTarget) << delimiter << std::to_wstring(u.isWhimsical) << delimiter;
|
out << Quote(std::to_wstring(u.id)) << delimiter << Quote(u.name) << delimiter << Quote(u.abbreviation) << delimiter
|
||||||
|
<< std::to_wstring(u.isConversionSource) << delimiter << std::to_wstring(u.isConversionTarget) << delimiter << std::to_wstring(u.isWhimsical)
|
||||||
|
<< delimiter;
|
||||||
return out.str();
|
return out.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,15 +285,19 @@ wstring UnitConverter::ConversionDataToString(ConversionData d, const wchar_t *
|
||||||
/// </summary>
|
/// </summary>
|
||||||
wstring UnitConverter::Serialize()
|
wstring UnitConverter::Serialize()
|
||||||
{
|
{
|
||||||
if (CheckLoad())
|
if (!CheckLoad())
|
||||||
{
|
{
|
||||||
|
return wstring();
|
||||||
|
}
|
||||||
|
|
||||||
wstringstream out(wstringstream::out);
|
wstringstream out(wstringstream::out);
|
||||||
const wchar_t* delimiter = L";";
|
const wchar_t* delimiter = L";";
|
||||||
|
|
||||||
out << UnitToString(m_fromType, delimiter) << "|";
|
out << UnitToString(m_fromType, delimiter) << "|";
|
||||||
out << UnitToString(m_toType, delimiter) << "|";
|
out << UnitToString(m_toType, delimiter) << "|";
|
||||||
out << CategoryToString(m_currentCategory, delimiter) << "|";
|
out << CategoryToString(m_currentCategory, delimiter) << "|";
|
||||||
out << std::to_wstring(m_currentHasDecimal) << delimiter << std::to_wstring(m_returnHasDecimal) << delimiter << std::to_wstring(m_switchedActive) << delimiter;
|
out << std::to_wstring(m_currentHasDecimal) << delimiter << std::to_wstring(m_returnHasDecimal) << delimiter << std::to_wstring(m_switchedActive)
|
||||||
|
<< delimiter;
|
||||||
out << m_currentDisplay << delimiter << m_returnDisplay << delimiter << "|";
|
out << m_currentDisplay << delimiter << m_returnDisplay << delimiter << "|";
|
||||||
wstringstream categoryString(wstringstream::out);
|
wstringstream categoryString(wstringstream::out);
|
||||||
wstringstream categoryToUnitString(wstringstream::out);
|
wstringstream categoryToUnitString(wstringstream::out);
|
||||||
|
@ -316,7 +314,8 @@ wstring UnitConverter::Serialize()
|
||||||
{
|
{
|
||||||
categoryToUnitString << UnitToString(u, delimiter) << ",";
|
categoryToUnitString << UnitToString(u, delimiter) << ",";
|
||||||
}
|
}
|
||||||
categoryToUnitString << "[" << "]";
|
categoryToUnitString << "["
|
||||||
|
<< "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& cur : m_ratioMap)
|
for (const auto& cur : m_ratioMap)
|
||||||
|
@ -327,7 +326,8 @@ wstring UnitConverter::Serialize()
|
||||||
unitToUnitToDoubleString << UnitToString(curConversion.first, delimiter) << ":";
|
unitToUnitToDoubleString << UnitToString(curConversion.first, delimiter) << ":";
|
||||||
unitToUnitToDoubleString << ConversionDataToString(curConversion.second, delimiter) << ":,";
|
unitToUnitToDoubleString << ConversionDataToString(curConversion.second, delimiter) << ":,";
|
||||||
}
|
}
|
||||||
unitToUnitToDoubleString << "[" << "]";
|
unitToUnitToDoubleString << "["
|
||||||
|
<< "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
out << categoryString.str() << "|";
|
out << categoryString.str() << "|";
|
||||||
|
@ -336,11 +336,6 @@ wstring UnitConverter::Serialize()
|
||||||
wstring test = out.str();
|
wstring test = out.str();
|
||||||
return test;
|
return test;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
return wstring();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// De-Serializes the data in the converter from a string
|
/// De-Serializes the data in the converter from a string
|
||||||
|
@ -348,9 +343,14 @@ wstring UnitConverter::Serialize()
|
||||||
/// <param name="serializedData">wstring holding the serialized data. If it does not have expected number of parameters, we will ignore it</param>
|
/// <param name="serializedData">wstring holding the serialized data. If it does not have expected number of parameters, we will ignore it</param>
|
||||||
void UnitConverter::DeSerialize(const wstring& serializedData)
|
void UnitConverter::DeSerialize(const wstring& serializedData)
|
||||||
{
|
{
|
||||||
Reset();
|
ClearValues();
|
||||||
if (!serializedData.empty())
|
ResetCategoriesAndRatios();
|
||||||
|
|
||||||
|
if (serializedData.empty())
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
vector<wstring> outerTokens = StringToVector(serializedData, L"|");
|
vector<wstring> outerTokens = StringToVector(serializedData, L"|");
|
||||||
assert(outerTokens.size() == EXPECTEDSERIALIZEDTOKENCOUNT);
|
assert(outerTokens.size() == EXPECTEDSERIALIZEDTOKENCOUNT);
|
||||||
m_fromType = StringToUnit(outerTokens[0]);
|
m_fromType = StringToUnit(outerTokens[0]);
|
||||||
|
@ -398,7 +398,6 @@ void UnitConverter::DeSerialize(const wstring& serializedData)
|
||||||
}
|
}
|
||||||
UpdateViewModel();
|
UpdateViewModel();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// De-Serializes the data in the converter from a string
|
/// De-Serializes the data in the converter from a string
|
||||||
|
@ -406,14 +405,33 @@ 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>
|
/// <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)
|
void UnitConverter::RestoreUserPreferences(const wstring& userPreferences)
|
||||||
{
|
{
|
||||||
if (!userPreferences.empty())
|
if (userPreferences.empty())
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
vector<wstring> outerTokens = StringToVector(userPreferences, L"|");
|
vector<wstring> outerTokens = StringToVector(userPreferences, L"|");
|
||||||
if (outerTokens.size() == 3)
|
if (outerTokens.size() != 3)
|
||||||
{
|
{
|
||||||
m_fromType = StringToUnit(outerTokens[0]);
|
return;
|
||||||
m_toType = StringToUnit(outerTokens[1]);
|
}
|
||||||
|
|
||||||
|
auto fromType = StringToUnit(outerTokens[0]);
|
||||||
|
auto toType = StringToUnit(outerTokens[1]);
|
||||||
m_currentCategory = StringToCategory(outerTokens[2]);
|
m_currentCategory = StringToCategory(outerTokens[2]);
|
||||||
|
|
||||||
|
// Only restore from the saved units if they are valid in the current available units.
|
||||||
|
auto itr = m_categoryToUnits.find(m_currentCategory);
|
||||||
|
if (itr != m_categoryToUnits.end())
|
||||||
|
{
|
||||||
|
const auto& curUnits = itr->second;
|
||||||
|
if (find(curUnits.begin(), curUnits.end(), fromType) != curUnits.end())
|
||||||
|
{
|
||||||
|
m_fromType = fromType;
|
||||||
|
}
|
||||||
|
if (find(curUnits.begin(), curUnits.end(), toType) != curUnits.end())
|
||||||
|
{
|
||||||
|
m_toType = toType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -479,7 +497,7 @@ wstring UnitConverter::Unquote(const wstring& s)
|
||||||
}
|
}
|
||||||
if (cursor == s.end())
|
if (cursor == s.end())
|
||||||
{
|
{
|
||||||
//badly formatted
|
// Badly formatted
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -503,8 +521,11 @@ wstring UnitConverter::Unquote(const wstring& s)
|
||||||
/// <param name="command">Command enum representing the command that was entered</param>
|
/// <param name="command">Command enum representing the command that was entered</param>
|
||||||
void UnitConverter::SendCommand(Command command)
|
void UnitConverter::SendCommand(Command command)
|
||||||
{
|
{
|
||||||
if (CheckLoad())
|
if (!CheckLoad())
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Localization of characters
|
// TODO: Localization of characters
|
||||||
bool clearFront = false;
|
bool clearFront = false;
|
||||||
if (m_currentDisplay == L"0")
|
if (m_currentDisplay == L"0")
|
||||||
|
@ -512,7 +533,8 @@ void UnitConverter::SendCommand(Command command)
|
||||||
clearFront = true;
|
clearFront = true;
|
||||||
}
|
}
|
||||||
bool clearBack = false;
|
bool clearBack = false;
|
||||||
if ((m_currentHasDecimal && m_currentDisplay.size() - 1 >= MAXIMUMDIGITSALLOWED) || (!m_currentHasDecimal && m_currentDisplay.size() >= MAXIMUMDIGITSALLOWED))
|
if ((m_currentHasDecimal && m_currentDisplay.size() - 1 >= MAXIMUMDIGITSALLOWED)
|
||||||
|
|| (!m_currentHasDecimal && m_currentDisplay.size() >= MAXIMUMDIGITSALLOWED))
|
||||||
{
|
{
|
||||||
clearBack = true;
|
clearBack = true;
|
||||||
}
|
}
|
||||||
|
@ -619,14 +641,13 @@ void UnitConverter::SendCommand(Command command)
|
||||||
clearFront = false;
|
clearFront = false;
|
||||||
clearBack = false;
|
clearBack = false;
|
||||||
ClearValues();
|
ClearValues();
|
||||||
Reset();
|
ResetCategoriesAndRatios();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (clearFront)
|
if (clearFront)
|
||||||
{
|
{
|
||||||
m_currentDisplay.erase(0, 1);
|
m_currentDisplay.erase(0, 1);
|
||||||
|
@ -638,9 +659,6 @@ void UnitConverter::SendCommand(Command command)
|
||||||
}
|
}
|
||||||
|
|
||||||
Calculate();
|
Calculate();
|
||||||
|
|
||||||
UpdateViewModel();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -670,8 +688,7 @@ void UnitConverter::SetViewModelCurrencyCallback(_In_ const shared_ptr<IViewMode
|
||||||
task<pair<bool, wstring>> UnitConverter::RefreshCurrencyRatios()
|
task<pair<bool, wstring>> UnitConverter::RefreshCurrencyRatios()
|
||||||
{
|
{
|
||||||
shared_ptr<ICurrencyConverterDataLoader> currencyDataLoader = GetCurrencyConverterDataLoader();
|
shared_ptr<ICurrencyConverterDataLoader> currencyDataLoader = GetCurrencyConverterDataLoader();
|
||||||
return create_task([this, currencyDataLoader]()
|
return create_task([this, currencyDataLoader]() {
|
||||||
{
|
|
||||||
if (currencyDataLoader != nullptr)
|
if (currencyDataLoader != nullptr)
|
||||||
{
|
{
|
||||||
return currencyDataLoader->TryLoadDataFromWebOverrideAsync();
|
return currencyDataLoader->TryLoadDataFromWebOverrideAsync();
|
||||||
|
@ -680,8 +697,9 @@ task<pair<bool, wstring>> UnitConverter::RefreshCurrencyRatios()
|
||||||
{
|
{
|
||||||
return task_from_result(false);
|
return task_from_result(false);
|
||||||
}
|
}
|
||||||
}).then([this, currencyDataLoader](bool didLoad)
|
})
|
||||||
{
|
.then(
|
||||||
|
[this, currencyDataLoader](bool didLoad) {
|
||||||
wstring timestamp = L"";
|
wstring timestamp = L"";
|
||||||
if (currencyDataLoader != nullptr)
|
if (currencyDataLoader != nullptr)
|
||||||
{
|
{
|
||||||
|
@ -689,7 +707,8 @@ task<pair<bool, wstring>> UnitConverter::RefreshCurrencyRatios()
|
||||||
}
|
}
|
||||||
|
|
||||||
return make_pair(didLoad, timestamp);
|
return make_pair(didLoad, timestamp);
|
||||||
}, task_continuation_context::use_default());
|
},
|
||||||
|
task_continuation_context::use_default());
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_ptr<ICurrencyConverterDataLoader> UnitConverter::GetCurrencyConverterDataLoader()
|
shared_ptr<ICurrencyConverterDataLoader> UnitConverter::GetCurrencyConverterDataLoader()
|
||||||
|
@ -746,9 +765,7 @@ vector<tuple<wstring, Unit>> UnitConverter::CalculateSuggested()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort the resulting list by absolute magnitude, breaking ties by choosing the positive value
|
// Sort the resulting list by absolute magnitude, breaking ties by choosing the positive value
|
||||||
sort(intermediateVector.begin(), intermediateVector.end(), []
|
sort(intermediateVector.begin(), intermediateVector.end(), [](SuggestedValueIntermediate first, SuggestedValueIntermediate second) {
|
||||||
(SuggestedValueIntermediate first, SuggestedValueIntermediate second)
|
|
||||||
{
|
|
||||||
if (abs(first.magnitude) == abs(second.magnitude))
|
if (abs(first.magnitude) == abs(second.magnitude))
|
||||||
{
|
{
|
||||||
return first.magnitude > second.magnitude;
|
return first.magnitude > second.magnitude;
|
||||||
|
@ -784,9 +801,7 @@ vector<tuple<wstring, Unit>> UnitConverter::CalculateSuggested()
|
||||||
|
|
||||||
// The Whimsicals are determined differently
|
// The Whimsicals are determined differently
|
||||||
// Sort the resulting list by absolute magnitude, breaking ties by choosing the positive value
|
// Sort the resulting list by absolute magnitude, breaking ties by choosing the positive value
|
||||||
sort(intermediateWhimsicalVector.begin(), intermediateWhimsicalVector.end(), []
|
sort(intermediateWhimsicalVector.begin(), intermediateWhimsicalVector.end(), [](SuggestedValueIntermediate first, SuggestedValueIntermediate second) {
|
||||||
(SuggestedValueIntermediate first, SuggestedValueIntermediate second)
|
|
||||||
{
|
|
||||||
if (abs(first.magnitude) == abs(second.magnitude))
|
if (abs(first.magnitude) == abs(second.magnitude))
|
||||||
{
|
{
|
||||||
return first.magnitude > second.magnitude;
|
return first.magnitude > second.magnitude;
|
||||||
|
@ -829,23 +844,23 @@ vector<tuple<wstring, Unit>> UnitConverter::CalculateSuggested()
|
||||||
returnVector.push_back(whimsicalReturnVector.at(0));
|
returnVector.push_back(whimsicalReturnVector.at(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
|
|
||||||
return returnVector;
|
return returnVector;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Resets the converter to its initial state
|
/// Resets categories and ratios
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void UnitConverter::Reset()
|
void UnitConverter::ResetCategoriesAndRatios()
|
||||||
{
|
{
|
||||||
m_categories = m_dataLoader->LoadOrderedCategories();
|
m_categories = m_dataLoader->LoadOrderedCategories();
|
||||||
|
|
||||||
ClearValues();
|
|
||||||
m_switchedActive = false;
|
m_switchedActive = false;
|
||||||
|
|
||||||
if (!m_categories.empty())
|
if (m_categories.empty())
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_currentCategory = m_categories[0];
|
m_currentCategory = m_categories[0];
|
||||||
|
|
||||||
m_categoryToUnits.clear();
|
m_categoryToUnits.clear();
|
||||||
|
@ -883,8 +898,6 @@ void UnitConverter::Reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
InitializeSelectedUnits();
|
InitializeSelectedUnits();
|
||||||
Calculate();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -910,7 +923,6 @@ shared_ptr<IConverterDataLoader> UnitConverter::GetDataLoaderForCategory(const C
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void UnitConverter::InitializeSelectedUnits()
|
void UnitConverter::InitializeSelectedUnits()
|
||||||
{
|
{
|
||||||
|
|
||||||
if (m_categoryToUnits.empty())
|
if (m_categoryToUnits.empty())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -975,11 +987,21 @@ bool UnitConverter::AnyUnitIsEmpty()
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void UnitConverter::Calculate()
|
void UnitConverter::Calculate()
|
||||||
{
|
{
|
||||||
unordered_map<Unit, ConversionData, UnitHash> conversionTable = m_ratioMap[m_fromType];
|
if (AnyUnitIsEmpty())
|
||||||
double returnValue = stod(m_currentDisplay);
|
|
||||||
if (AnyUnitIsEmpty() || (conversionTable[m_toType].ratio == 1.0 && conversionTable[m_toType].offset == 0.0))
|
|
||||||
{
|
{
|
||||||
m_returnDisplay = m_currentDisplay;
|
m_returnDisplay = m_currentDisplay;
|
||||||
|
m_returnHasDecimal = m_currentHasDecimal;
|
||||||
|
TrimString(m_returnDisplay);
|
||||||
|
UpdateViewModel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
unordered_map<Unit, ConversionData, UnitHash> conversionTable = m_ratioMap[m_fromType];
|
||||||
|
double returnValue = stod(m_currentDisplay);
|
||||||
|
if (conversionTable[m_toType].ratio == 1.0 && conversionTable[m_toType].offset == 0.0)
|
||||||
|
{
|
||||||
|
m_returnDisplay = m_currentDisplay;
|
||||||
|
m_returnHasDecimal = m_currentHasDecimal;
|
||||||
TrimString(m_returnDisplay);
|
TrimString(m_returnDisplay);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1018,10 +1040,10 @@ void UnitConverter::Calculate()
|
||||||
m_returnDisplay = returnString;
|
m_returnDisplay = returnString;
|
||||||
TrimString(m_returnDisplay);
|
TrimString(m_returnDisplay);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
m_returnHasDecimal = (m_returnDisplay.find(L'.') != m_returnDisplay.npos);
|
m_returnHasDecimal = (m_returnDisplay.find(L'.') != m_returnDisplay.npos);
|
||||||
}
|
}
|
||||||
|
UpdateViewModel();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Trims out any trailing zeros or decimals in the given input string
|
/// Trims out any trailing zeros or decimals in the given input string
|
||||||
|
@ -1029,8 +1051,11 @@ void UnitConverter::Calculate()
|
||||||
/// <param name="input">wstring to trim</param>
|
/// <param name="input">wstring to trim</param>
|
||||||
void UnitConverter::TrimString(wstring& returnString)
|
void UnitConverter::TrimString(wstring& returnString)
|
||||||
{
|
{
|
||||||
if (returnString.find(L'.') != m_returnDisplay.npos)
|
if (returnString.find(L'.') == m_returnDisplay.npos)
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
wstring::iterator iter;
|
wstring::iterator iter;
|
||||||
for (iter = returnString.end() - 1;; iter--)
|
for (iter = returnString.end() - 1;; iter--)
|
||||||
{
|
{
|
||||||
|
@ -1045,7 +1070,6 @@ void UnitConverter::TrimString(wstring& returnString)
|
||||||
returnString.erase(returnString.end() - 1, returnString.end());
|
returnString.erase(returnString.end() - 1, returnString.end());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Rounds the given double to the given number of significant digits
|
/// Rounds the given double to the given number of significant digits
|
||||||
|
|
|
@ -1,22 +1,47 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <ppltasks.h>
|
||||||
|
#include <sal.h> // for SAL
|
||||||
|
#include <memory> // for std::shared_ptr
|
||||||
|
|
||||||
namespace UnitConversionManager
|
namespace UnitConversionManager
|
||||||
{
|
{
|
||||||
enum class Command;
|
enum class Command;
|
||||||
|
|
||||||
struct Unit
|
struct Unit
|
||||||
{
|
{
|
||||||
Unit(){}
|
Unit()
|
||||||
|
{
|
||||||
|
}
|
||||||
Unit(int id, std::wstring name, std::wstring abbreviation, bool isConversionSource, bool isConversionTarget, bool isWhimsical)
|
Unit(int id, std::wstring name, std::wstring abbreviation, bool isConversionSource, bool isConversionTarget, bool isWhimsical)
|
||||||
: id(id), name(name), accessibleName(name), abbreviation(abbreviation), isConversionSource(isConversionSource), isConversionTarget(isConversionTarget), isWhimsical(isWhimsical)
|
: id(id)
|
||||||
|
, name(name)
|
||||||
|
, accessibleName(name)
|
||||||
|
, abbreviation(abbreviation)
|
||||||
|
, isConversionSource(isConversionSource)
|
||||||
|
, isConversionTarget(isConversionTarget)
|
||||||
|
, isWhimsical(isWhimsical)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Unit(int id, std::wstring currencyName, std::wstring countryName, std::wstring abbreviation, bool isRtlLanguage, bool isConversionSource, bool isConversionTarget)
|
Unit(
|
||||||
: id(id), abbreviation(abbreviation), isConversionSource(isConversionSource), isConversionTarget(isConversionTarget), isWhimsical(false)
|
int id,
|
||||||
|
std::wstring currencyName,
|
||||||
|
std::wstring countryName,
|
||||||
|
std::wstring abbreviation,
|
||||||
|
bool isRtlLanguage,
|
||||||
|
bool isConversionSource,
|
||||||
|
bool isConversionTarget)
|
||||||
|
: id(id)
|
||||||
|
, abbreviation(abbreviation)
|
||||||
|
, isConversionSource(isConversionSource)
|
||||||
|
, isConversionTarget(isConversionTarget)
|
||||||
|
, isWhimsical(false)
|
||||||
{
|
{
|
||||||
std::wstring nameValue1 = isRtlLanguage ? currencyName : countryName;
|
std::wstring nameValue1 = isRtlLanguage ? currencyName : countryName;
|
||||||
std::wstring nameValue2 = isRtlLanguage ? countryName : currencyName;
|
std::wstring nameValue2 = isRtlLanguage ? countryName : currencyName;
|
||||||
|
@ -25,7 +50,9 @@ namespace UnitConversionManager
|
||||||
accessibleName = nameValue1 + L" " + nameValue2;
|
accessibleName = nameValue1 + L" " + nameValue2;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~Unit() {}
|
virtual ~Unit()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
int id;
|
int id;
|
||||||
std::wstring name;
|
std::wstring name;
|
||||||
|
@ -55,9 +82,14 @@ namespace UnitConversionManager
|
||||||
|
|
||||||
struct Category
|
struct Category
|
||||||
{
|
{
|
||||||
Category(){}
|
Category()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
Category(int id, std::wstring name, bool supportsNegative) : id(id), name(name), supportsNegative(supportsNegative)
|
Category(int id, std::wstring name, bool supportsNegative)
|
||||||
|
: id(id)
|
||||||
|
, name(name)
|
||||||
|
, supportsNegative(supportsNegative)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +111,8 @@ namespace UnitConversionManager
|
||||||
class UnitHash
|
class UnitHash
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
size_t operator() (const Unit & x) const {
|
size_t operator()(const Unit& x) const
|
||||||
|
{
|
||||||
return x.id;
|
return x.id;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -87,7 +120,8 @@ namespace UnitConversionManager
|
||||||
class CategoryHash
|
class CategoryHash
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
size_t operator() (const Category & x) const {
|
size_t operator()(const Category& x) const
|
||||||
|
{
|
||||||
return x.id;
|
return x.id;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -101,12 +135,19 @@ namespace UnitConversionManager
|
||||||
|
|
||||||
struct ConversionData
|
struct ConversionData
|
||||||
{
|
{
|
||||||
ConversionData(){}
|
ConversionData()
|
||||||
ConversionData(double ratio, double offset, bool offsetFirst) : ratio(ratio), offset(offset), offsetFirst(offsetFirst)
|
{
|
||||||
|
}
|
||||||
|
ConversionData(double ratio, double offset, bool offsetFirst)
|
||||||
|
: ratio(ratio)
|
||||||
|
, offset(offset)
|
||||||
|
, offsetFirst(offsetFirst)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~ConversionData() {}
|
virtual ~ConversionData()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
double ratio;
|
double ratio;
|
||||||
double offset;
|
double offset;
|
||||||
|
@ -130,8 +171,13 @@ namespace UnitConversionManager
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::tuple<std::vector<UnitConversionManager::Unit>, UnitConversionManager::Unit, UnitConversionManager::Unit> CategorySelectionInitializer;
|
typedef std::tuple<std::vector<UnitConversionManager::Unit>, UnitConversionManager::Unit, UnitConversionManager::Unit> CategorySelectionInitializer;
|
||||||
typedef std::unordered_map<UnitConversionManager::Unit, std::unordered_map<UnitConversionManager::Unit, UnitConversionManager::ConversionData, UnitConversionManager::UnitHash>, UnitConversionManager::UnitHash> UnitToUnitToConversionDataMap;
|
typedef std::unordered_map<
|
||||||
typedef std::unordered_map<UnitConversionManager::Category, std::vector<UnitConversionManager::Unit>, UnitConversionManager::CategoryHash> CategoryToUnitVectorMap;
|
UnitConversionManager::Unit,
|
||||||
|
std::unordered_map<UnitConversionManager::Unit, UnitConversionManager::ConversionData, UnitConversionManager::UnitHash>,
|
||||||
|
UnitConversionManager::UnitHash>
|
||||||
|
UnitToUnitToConversionDataMap;
|
||||||
|
typedef std::unordered_map<UnitConversionManager::Category, std::vector<UnitConversionManager::Unit>, UnitConversionManager::CategoryHash>
|
||||||
|
CategoryToUnitVectorMap;
|
||||||
|
|
||||||
class IViewModelCurrencyCallback
|
class IViewModelCurrencyCallback
|
||||||
{
|
{
|
||||||
|
@ -159,8 +205,10 @@ namespace UnitConversionManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void SetViewModelCallback(const std::shared_ptr<UnitConversionManager::IViewModelCurrencyCallback>& callback) = 0;
|
virtual void SetViewModelCallback(const std::shared_ptr<UnitConversionManager::IViewModelCurrencyCallback>& callback) = 0;
|
||||||
virtual std::pair<std::wstring, std::wstring> GetCurrencySymbols(_In_ const UnitConversionManager::Unit& unit1, _In_ const UnitConversionManager::Unit& unit2) = 0;
|
virtual std::pair<std::wstring, std::wstring>
|
||||||
virtual std::pair<std::wstring, std::wstring> GetCurrencyRatioEquality(_In_ const UnitConversionManager::Unit& unit1, _In_ const UnitConversionManager::Unit& unit2) = 0;
|
GetCurrencySymbols(_In_ const UnitConversionManager::Unit& unit1, _In_ const UnitConversionManager::Unit& unit2) = 0;
|
||||||
|
virtual std::pair<std::wstring, std::wstring>
|
||||||
|
GetCurrencyRatioEquality(_In_ const UnitConversionManager::Unit& unit1, _In_ const UnitConversionManager::Unit& unit2) = 0;
|
||||||
virtual std::wstring GetCurrencyTimestamp() = 0;
|
virtual std::wstring GetCurrencyTimestamp() = 0;
|
||||||
|
|
||||||
virtual concurrency::task<bool> TryLoadDataFromCacheAsync() = 0;
|
virtual concurrency::task<bool> TryLoadDataFromCacheAsync() = 0;
|
||||||
|
@ -180,7 +228,9 @@ namespace UnitConversionManager
|
||||||
class IUnitConverter
|
class IUnitConverter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~IUnitConverter() { }
|
virtual ~IUnitConverter()
|
||||||
|
{
|
||||||
|
}
|
||||||
virtual void Initialize() = 0; // Use to initialize first time, use deserialize instead to rehydrate
|
virtual void Initialize() = 0; // Use to initialize first time, use deserialize instead to rehydrate
|
||||||
virtual std::vector<Category> GetCategories() = 0;
|
virtual std::vector<Category> GetCategories() = 0;
|
||||||
virtual CategorySelectionInitializer SetCurrentCategory(const Category& input) = 0;
|
virtual CategorySelectionInitializer SetCurrentCategory(const Category& input) = 0;
|
||||||
|
@ -195,6 +245,8 @@ namespace UnitConversionManager
|
||||||
virtual void SetViewModelCallback(_In_ const std::shared_ptr<IUnitConverterVMCallback>& newCallback) = 0;
|
virtual void SetViewModelCallback(_In_ const std::shared_ptr<IUnitConverterVMCallback>& newCallback) = 0;
|
||||||
virtual void SetViewModelCurrencyCallback(_In_ const std::shared_ptr<IViewModelCurrencyCallback>& newCallback) = 0;
|
virtual void SetViewModelCurrencyCallback(_In_ const std::shared_ptr<IViewModelCurrencyCallback>& newCallback) = 0;
|
||||||
virtual concurrency::task<std::pair<bool, std::wstring>> RefreshCurrencyRatios() = 0;
|
virtual concurrency::task<std::pair<bool, std::wstring>> RefreshCurrencyRatios() = 0;
|
||||||
|
virtual void Calculate() = 0;
|
||||||
|
virtual void ResetCategoriesAndRatios() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class UnitConverter : public IUnitConverter, public std::enable_shared_from_this<UnitConverter>
|
class UnitConverter : public IUnitConverter, public std::enable_shared_from_this<UnitConverter>
|
||||||
|
@ -218,6 +270,8 @@ namespace UnitConversionManager
|
||||||
void SetViewModelCallback(_In_ const std::shared_ptr<IUnitConverterVMCallback>& newCallback) override;
|
void SetViewModelCallback(_In_ const std::shared_ptr<IUnitConverterVMCallback>& newCallback) override;
|
||||||
void SetViewModelCurrencyCallback(_In_ const std::shared_ptr<IViewModelCurrencyCallback>& newCallback) override;
|
void SetViewModelCurrencyCallback(_In_ const std::shared_ptr<IViewModelCurrencyCallback>& newCallback) override;
|
||||||
concurrency::task<std::pair<bool, std::wstring>> RefreshCurrencyRatios() override;
|
concurrency::task<std::pair<bool, std::wstring>> RefreshCurrencyRatios() override;
|
||||||
|
void Calculate() override;
|
||||||
|
void ResetCategoriesAndRatios() override;
|
||||||
// IUnitConverter
|
// IUnitConverter
|
||||||
|
|
||||||
static std::vector<std::wstring> StringToVector(const std::wstring& w, const wchar_t* delimiter, bool addRemainder = false);
|
static std::vector<std::wstring> StringToVector(const std::wstring& w, const wchar_t* delimiter, bool addRemainder = false);
|
||||||
|
@ -228,9 +282,7 @@ namespace UnitConversionManager
|
||||||
bool CheckLoad();
|
bool CheckLoad();
|
||||||
double Convert(double value, ConversionData conversionData);
|
double Convert(double value, ConversionData conversionData);
|
||||||
std::vector<std::tuple<std::wstring, Unit>> CalculateSuggested();
|
std::vector<std::tuple<std::wstring, Unit>> CalculateSuggested();
|
||||||
void Reset();
|
|
||||||
void ClearValues();
|
void ClearValues();
|
||||||
void Calculate();
|
|
||||||
void TrimString(std::wstring& input);
|
void TrimString(std::wstring& input);
|
||||||
void InitializeSelectedUnits();
|
void InitializeSelectedUnits();
|
||||||
std::wstring RoundSignificant(double num, int numSignificant);
|
std::wstring RoundSignificant(double num, int numSignificant);
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
#include "pch.h"
|
// Intentionally do not include the pch.h here. For projects that don't
|
||||||
|
// use precompiled headers, including the header here would force unnecessary compilation.
|
||||||
|
// The pch will be included through forced include.
|
||||||
|
|
|
@ -1,23 +1,22 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifndef WIN32_LEAN_AND_MEAN
|
// The CalcManager project should be able to be compiled with or without a precompiled header
|
||||||
#define WIN32_LEAN_AND_MEAN
|
// in - order to support other toolchains besides MSVC. When adding new system headers, make sure
|
||||||
#endif
|
// that the relevant source file includes all headers it needs, but then also add the system headers
|
||||||
|
// here so that MSVC users see the performance benefit.
|
||||||
|
|
||||||
#include <assert.h>
|
#include <algorithm>
|
||||||
#include <windows.h>
|
|
||||||
#include <winerror.h>
|
|
||||||
#include <sstream>
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
#include <memory>
|
|
||||||
#include <vector>
|
|
||||||
#include <limits>
|
|
||||||
#include <regex>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <intsafe.h>
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <cassert>
|
||||||
|
#include <intsafe.h>
|
||||||
|
#include <list>
|
||||||
#include <ppltasks.h>
|
#include <ppltasks.h>
|
||||||
|
#include <regex>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
#include <winerror.h>
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
||||||
// Licensed under the MIT License.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
// Including SDKDDKVer.h defines the highest available Windows platform.
|
|
||||||
|
|
||||||
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
|
|
||||||
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
|
|
||||||
|
|
||||||
#include <SDKDDKVer.h>
|
|
|
@ -32,23 +32,19 @@ using namespace Windows::UI::Xaml::Data;
|
||||||
using namespace Windows::UI::Xaml::Input;
|
using namespace Windows::UI::Xaml::Input;
|
||||||
using namespace Windows::UI::Xaml::Media;
|
using namespace Windows::UI::Xaml::Media;
|
||||||
|
|
||||||
namespace CalculatorApp::ViewModel::ApplicationViewModelProperties
|
namespace
|
||||||
{
|
{
|
||||||
StringReference Mode(L"Mode");
|
StringReference CategoriesPropertyName(L"Categories");
|
||||||
StringReference PreviousMode(L"PreviousMode");
|
StringReference ClearMemoryVisibilityPropertyName(L"ClearMemoryVisibility");
|
||||||
StringReference ClearMemoryVisibility(L"ClearMemoryVisibility");
|
|
||||||
StringReference AppBarVisibility(L"AppBarVisibility");
|
|
||||||
StringReference CategoryName(L"CategoryName");
|
|
||||||
StringReference Categories(L"Categories");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ApplicationViewModel::ApplicationViewModel() :
|
ApplicationViewModel::ApplicationViewModel()
|
||||||
m_CalculatorViewModel(nullptr),
|
: m_CalculatorViewModel(nullptr)
|
||||||
m_DateCalcViewModel(nullptr),
|
, m_DateCalcViewModel(nullptr)
|
||||||
m_ConverterViewModel(nullptr),
|
, m_ConverterViewModel(nullptr)
|
||||||
m_PreviousMode(ViewMode::None),
|
, m_PreviousMode(ViewMode::None)
|
||||||
m_mode(ViewMode::None),
|
, m_mode(ViewMode::None)
|
||||||
m_categories(nullptr)
|
, m_categories(nullptr)
|
||||||
{
|
{
|
||||||
SetMenuCategories();
|
SetMenuCategories();
|
||||||
}
|
}
|
||||||
|
@ -60,7 +56,7 @@ void ApplicationViewModel::Mode::set(ViewMode value)
|
||||||
PreviousMode = m_mode;
|
PreviousMode = m_mode;
|
||||||
m_mode = value;
|
m_mode = value;
|
||||||
OnModeChanged();
|
OnModeChanged();
|
||||||
RaisePropertyChanged(ApplicationViewModelProperties::Mode);
|
RaisePropertyChanged(ModePropertyName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +65,7 @@ void ApplicationViewModel::Categories::set(IObservableVector<NavCategoryGroup^>^
|
||||||
if (m_categories != value)
|
if (m_categories != value)
|
||||||
{
|
{
|
||||||
m_categories = value;
|
m_categories = value;
|
||||||
RaisePropertyChanged(ApplicationViewModelProperties::Categories);
|
RaisePropertyChanged(CategoriesPropertyName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,11 +159,10 @@ void ApplicationViewModel::OnModeChanged()
|
||||||
//
|
//
|
||||||
// Save the changed mode, so that the new window launches in this mode.
|
// 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.
|
// 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()));
|
TraceLogger::GetInstance().LogModeChangeEnd(m_mode, ApplicationView::GetApplicationViewIdForWindow(CoreWindow::GetForCurrentThread()));
|
||||||
RaisePropertyChanged(ApplicationViewModelProperties::ClearMemoryVisibility);
|
RaisePropertyChanged(ClearMemoryVisibilityPropertyName);
|
||||||
RaisePropertyChanged(ApplicationViewModelProperties::AppBarVisibility);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplicationViewModel::OnCopyCommand(Object ^ parameter)
|
void ApplicationViewModel::OnCopyCommand(Object ^ parameter)
|
||||||
|
@ -192,7 +187,7 @@ void ApplicationViewModel::OnPasteCommand(Object^ parameter)
|
||||||
{
|
{
|
||||||
ConverterViewModel->OnPasteCommand(parameter);
|
ConverterViewModel->OnPasteCommand(parameter);
|
||||||
}
|
}
|
||||||
else
|
else if (NavCategory::IsCalculatorViewMode(m_mode))
|
||||||
{
|
{
|
||||||
CalculatorViewModel->OnPasteCommand(parameter);
|
CalculatorViewModel->OnPasteCommand(parameter);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
@ -11,18 +11,7 @@ namespace CalculatorApp
|
||||||
{
|
{
|
||||||
namespace ViewModel
|
namespace ViewModel
|
||||||
{
|
{
|
||||||
namespace ApplicationViewModelProperties
|
[Windows::UI::Xaml::Data::Bindable] public ref class ApplicationViewModel sealed : public Windows::UI::Xaml::Data::INotifyPropertyChanged
|
||||||
{
|
|
||||||
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
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ApplicationViewModel();
|
ApplicationViewModel();
|
||||||
|
@ -32,9 +21,9 @@ namespace CalculatorApp
|
||||||
OBSERVABLE_OBJECT();
|
OBSERVABLE_OBJECT();
|
||||||
OBSERVABLE_PROPERTY_RW(StandardCalculatorViewModel ^, CalculatorViewModel);
|
OBSERVABLE_PROPERTY_RW(StandardCalculatorViewModel ^, CalculatorViewModel);
|
||||||
OBSERVABLE_PROPERTY_RW(DateCalculatorViewModel ^, DateCalcViewModel);
|
OBSERVABLE_PROPERTY_RW(DateCalculatorViewModel ^, DateCalcViewModel);
|
||||||
OBSERVABLE_PROPERTY_RW(CalculatorApp::ViewModel::UnitConverterViewModel^, ConverterViewModel);
|
OBSERVABLE_PROPERTY_RW(UnitConverterViewModel ^, ConverterViewModel);
|
||||||
OBSERVABLE_PROPERTY_RW(CalculatorApp::Common::ViewMode, PreviousMode);
|
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(CopyCommand, ApplicationViewModel::OnCopyCommand);
|
||||||
COMMAND_FOR_METHOD(PasteCommand, ApplicationViewModel::OnPasteCommand);
|
COMMAND_FOR_METHOD(PasteCommand, ApplicationViewModel::OnPasteCommand);
|
||||||
|
@ -48,6 +37,13 @@ namespace CalculatorApp
|
||||||
|
|
||||||
void set(CalculatorApp::Common::ViewMode value);
|
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
|
property Windows::Foundation::Collections::IObservableVector<CalculatorApp::Common::NavCategoryGroup^>^ Categories
|
||||||
{
|
{
|
||||||
|
@ -63,18 +59,7 @@ namespace CalculatorApp
|
||||||
{
|
{
|
||||||
Windows::UI::Xaml::Visibility get()
|
Windows::UI::Xaml::Visibility get()
|
||||||
{
|
{
|
||||||
return CalculatorApp::Common::NavCategory::IsCalculatorViewMode(Mode)
|
return CalculatorApp::Common::NavCategory::IsCalculatorViewMode(Mode) ? Windows::UI::Xaml::Visibility::Visible
|
||||||
? Windows::UI::Xaml::Visibility::Visible
|
|
||||||
: Windows::UI::Xaml::Visibility::Collapsed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
property Windows::UI::Xaml::Visibility AppBarVisibility
|
|
||||||
{
|
|
||||||
Windows::UI::Xaml::Visibility get()
|
|
||||||
{
|
|
||||||
return CalculatorApp::Common::NavCategory::IsCalculatorViewMode(Mode)
|
|
||||||
? Windows::UI::Xaml::Visibility::Visible
|
|
||||||
: Windows::UI::Xaml::Visibility::Collapsed;
|
: Windows::UI::Xaml::Visibility::Collapsed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,30 +3,31 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace CalculatorApp { namespace Common
|
namespace CalculatorApp
|
||||||
{
|
{
|
||||||
ref class AlwaysSelectedCollectionView sealed:
|
namespace Common
|
||||||
public Windows::UI::Xaml::DependencyObject,
|
|
||||||
public Windows::UI::Xaml::Data::ICollectionView
|
|
||||||
{
|
{
|
||||||
internal:
|
ref class AlwaysSelectedCollectionView sealed : public Windows::UI::Xaml::DependencyObject, public Windows::UI::Xaml::Data::ICollectionView
|
||||||
AlwaysSelectedCollectionView(Windows::UI::Xaml::Interop::IBindableVector^ source):
|
{
|
||||||
m_currentPosition(-1)
|
internal : AlwaysSelectedCollectionView(Windows::UI::Xaml::Interop::IBindableVector ^ source)
|
||||||
|
: m_currentPosition(-1)
|
||||||
{
|
{
|
||||||
m_source = source;
|
m_source = source;
|
||||||
|
|
||||||
Windows::UI::Xaml::Interop::IBindableObservableVector^ observable = dynamic_cast<Windows::UI::Xaml::Interop::IBindableObservableVector^>(source);
|
Windows::UI::Xaml::Interop::IBindableObservableVector ^ observable =
|
||||||
|
dynamic_cast<Windows::UI::Xaml::Interop::IBindableObservableVector ^>(source);
|
||||||
if (observable)
|
if (observable)
|
||||||
{
|
{
|
||||||
observable->VectorChanged +=
|
observable->VectorChanged += ref new Windows::UI::Xaml::Interop::BindableVectorChangedEventHandler(
|
||||||
ref new Windows::UI::Xaml::Interop::BindableVectorChangedEventHandler(this, &AlwaysSelectedCollectionView::OnSourceBindableVectorChanged);
|
this, &AlwaysSelectedCollectionView::OnSourceBindableVectorChanged);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// ICollectionView
|
// ICollectionView
|
||||||
// Not implemented methods
|
// Not implemented methods
|
||||||
virtual WF::IAsyncOperation<Windows::UI::Xaml::Data::LoadMoreItemsResult>^ LoadMoreItemsAsync(unsigned int) = Windows::UI::Xaml::Data::ICollectionView::LoadMoreItemsAsync
|
virtual WF::IAsyncOperation<
|
||||||
|
Windows::UI::Xaml::Data::LoadMoreItemsResult> ^ LoadMoreItemsAsync(unsigned int) = Windows::UI::Xaml::Data::ICollectionView::LoadMoreItemsAsync
|
||||||
{
|
{
|
||||||
throw ref new Platform::NotImplementedException();
|
throw ref new Platform::NotImplementedException();
|
||||||
}
|
}
|
||||||
|
@ -46,14 +47,13 @@ namespace CalculatorApp { namespace Common
|
||||||
{
|
{
|
||||||
throw ref new Platform::NotImplementedException();
|
throw ref new Platform::NotImplementedException();
|
||||||
}
|
}
|
||||||
property Windows::Foundation::Collections::IObservableVector<Platform::Object^>^ CollectionGroups
|
property Windows::Foundation::Collections::IObservableVector<Platform::Object ^> ^ CollectionGroups {
|
||||||
{
|
virtual Windows::Foundation::Collections::IObservableVector<
|
||||||
virtual Windows::Foundation::Collections::IObservableVector<Platform::Object^>^ get() = Windows::UI::Xaml::Data::ICollectionView::CollectionGroups::get
|
Platform::Object ^> ^ get() = Windows::UI::Xaml::Data::ICollectionView::CollectionGroups::get
|
||||||
{
|
{
|
||||||
return ref new Platform::Collections::Vector<Platform::Object ^>();
|
return ref new Platform::Collections::Vector<Platform::Object ^>();
|
||||||
}
|
}
|
||||||
}
|
} property bool HasMoreItems
|
||||||
property bool HasMoreItems
|
|
||||||
{
|
{
|
||||||
virtual bool get() = Windows::UI::Xaml::Data::ICollectionView::HasMoreItems::get
|
virtual bool get() = Windows::UI::Xaml::Data::ICollectionView::HasMoreItems::get
|
||||||
{
|
{
|
||||||
|
@ -81,10 +81,7 @@ namespace CalculatorApp { namespace Common
|
||||||
// restore the selection to the way we wanted it to begin with
|
// restore the selection to the way we wanted it to begin with
|
||||||
if (m_currentPosition >= 0 && m_currentPosition < static_cast<int>(m_source->Size))
|
if (m_currentPosition >= 0 && m_currentPosition < static_cast<int>(m_source->Size))
|
||||||
{
|
{
|
||||||
this->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal,
|
this->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, ref new Windows::UI::Core::DispatchedHandler([this]() {
|
||||||
ref new Windows::UI::Core::DispatchedHandler(
|
|
||||||
[this]()
|
|
||||||
{
|
|
||||||
m_currentChanged(this, nullptr);
|
m_currentChanged(this, nullptr);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -172,11 +169,14 @@ namespace CalculatorApp { namespace Common
|
||||||
{
|
{
|
||||||
throw ref new Platform::NotImplementedException();
|
throw ref new Platform::NotImplementedException();
|
||||||
}
|
}
|
||||||
virtual unsigned int GetMany(unsigned int /*startIndex*/, Platform::WriteOnlyArray<Platform::Object^>^ /*items*/) = Windows::Foundation::Collections::IVector<Platform::Object^>::GetMany
|
virtual unsigned int GetMany(
|
||||||
|
unsigned int /*startIndex*/,
|
||||||
|
Platform::WriteOnlyArray<Platform::Object ^> ^ /*items*/) = Windows::Foundation::Collections::IVector<Platform::Object ^>::GetMany
|
||||||
{
|
{
|
||||||
throw ref new Platform::NotImplementedException();
|
throw ref new Platform::NotImplementedException();
|
||||||
}
|
}
|
||||||
virtual Windows::Foundation::Collections::IVectorView<Platform::Object^>^ GetView() = Windows::Foundation::Collections::IVector<Platform::Object^>::GetView
|
virtual Windows::Foundation::Collections::IVectorView<Platform::Object ^> ^ GetView() = Windows::Foundation::Collections::IVector<
|
||||||
|
Platform::Object ^>::GetView
|
||||||
{
|
{
|
||||||
throw ref new Platform::NotImplementedException();
|
throw ref new Platform::NotImplementedException();
|
||||||
}
|
}
|
||||||
|
@ -192,7 +192,8 @@ namespace CalculatorApp { namespace Common
|
||||||
{
|
{
|
||||||
throw ref new Platform::NotImplementedException();
|
throw ref new Platform::NotImplementedException();
|
||||||
}
|
}
|
||||||
virtual void ReplaceAll(const Platform::Array<Platform::Object^>^ /*items*/) = Windows::Foundation::Collections::IVector<Platform::Object^>::ReplaceAll
|
virtual void
|
||||||
|
ReplaceAll(const Platform::Array<Platform::Object ^> ^ /*items*/) = Windows::Foundation::Collections::IVector<Platform::Object ^>::ReplaceAll
|
||||||
{
|
{
|
||||||
throw ref new Platform::NotImplementedException();
|
throw ref new Platform::NotImplementedException();
|
||||||
}
|
}
|
||||||
|
@ -254,14 +255,17 @@ namespace CalculatorApp { namespace Common
|
||||||
event Windows::Foundation::Collections::VectorChangedEventHandler<Platform::Object ^> ^ m_vectorChanged;
|
event Windows::Foundation::Collections::VectorChangedEventHandler<Platform::Object ^> ^ m_vectorChanged;
|
||||||
};
|
};
|
||||||
|
|
||||||
public ref class AlwaysSelectedCollectionViewConverter sealed: public Windows::UI::Xaml::Data::IValueConverter
|
public
|
||||||
|
ref class AlwaysSelectedCollectionViewConverter sealed : public Windows::UI::Xaml::Data::IValueConverter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AlwaysSelectedCollectionViewConverter()
|
AlwaysSelectedCollectionViewConverter()
|
||||||
{ }
|
{
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual Platform::Object^ Convert(
|
virtual Platform::Object
|
||||||
|
^ Convert(
|
||||||
Platform::Object ^ value,
|
Platform::Object ^ value,
|
||||||
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
|
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
|
||||||
Platform::Object ^ /*parameter*/,
|
Platform::Object ^ /*parameter*/,
|
||||||
|
@ -275,7 +279,8 @@ namespace CalculatorApp { namespace Common
|
||||||
return Windows::UI::Xaml::DependencyProperty::UnsetValue; // Can't convert
|
return Windows::UI::Xaml::DependencyProperty::UnsetValue; // Can't convert
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual Platform::Object^ ConvertBack(
|
virtual Platform::Object
|
||||||
|
^ ConvertBack(
|
||||||
Platform::Object ^ /*value*/,
|
Platform::Object ^ /*value*/,
|
||||||
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
|
Windows::UI::Xaml::Interop::TypeName /*targetType*/,
|
||||||
Platform::Object ^ /*parameter*/,
|
Platform::Object ^ /*parameter*/,
|
||||||
|
@ -284,4 +289,5 @@ namespace CalculatorApp { namespace Common
|
||||||
return Windows::UI::Xaml::DependencyProperty::UnsetValue;
|
return Windows::UI::Xaml::DependencyProperty::UnsetValue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
#include "AppResourceProvider.h"
|
#include "AppResourceProvider.h"
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,8 @@
|
||||||
|
|
||||||
namespace CalculatorApp::Common::Automation
|
namespace CalculatorApp::Common::Automation
|
||||||
{
|
{
|
||||||
public interface class INarratorAnnouncementHost
|
public
|
||||||
|
interface class INarratorAnnouncementHost
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Is the host available on this OS.
|
// Is the host available on this OS.
|
||||||
|
|
|
@ -9,9 +9,10 @@ using namespace Windows::UI::Xaml::Automation;
|
||||||
using namespace Windows::UI::Xaml::Automation::Peers;
|
using namespace Windows::UI::Xaml::Automation::Peers;
|
||||||
using namespace Windows::UI::Xaml::Controls;
|
using namespace Windows::UI::Xaml::Controls;
|
||||||
|
|
||||||
LiveRegionHost::LiveRegionHost() :
|
LiveRegionHost::LiveRegionHost()
|
||||||
m_host(nullptr)
|
: m_host(nullptr)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
bool LiveRegionHost::IsHostAvailable()
|
bool LiveRegionHost::IsHostAvailable()
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,7 +16,8 @@ namespace CalculatorApp::Common::Automation
|
||||||
// When the app switches to min version RS3, this class can be removed
|
// When the app switches to min version RS3, this class can be removed
|
||||||
// and the app will switch to using the Notification API.
|
// and the app will switch to using the Notification API.
|
||||||
// TODO - MSFT 12735088
|
// TODO - MSFT 12735088
|
||||||
public ref class LiveRegionHost sealed : public INarratorAnnouncementHost
|
public
|
||||||
|
ref class LiveRegionHost sealed : public INarratorAnnouncementHost
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LiveRegionHost();
|
LiveRegionHost();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
#include "pch.h"
|
#include "pch.h"
|
||||||
|
@ -20,6 +20,8 @@ namespace CalculatorApp::Common::Automation
|
||||||
StringReference CategoryNameChanged(L"CategoryNameChanged");
|
StringReference CategoryNameChanged(L"CategoryNameChanged");
|
||||||
StringReference UpdateCurrencyRates(L"UpdateCurrencyRates");
|
StringReference UpdateCurrencyRates(L"UpdateCurrencyRates");
|
||||||
StringReference DisplayCopied(L"DisplayCopied");
|
StringReference DisplayCopied(L"DisplayCopied");
|
||||||
|
StringReference OpenParenthesisCountChanged(L"OpenParenthesisCountChanged");
|
||||||
|
StringReference NoParenthesisAdded(L"NoParenthesisAdded");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,12 +30,12 @@ NarratorAnnouncement::NarratorAnnouncement(
|
||||||
String ^ activityId,
|
String ^ activityId,
|
||||||
AutomationNotificationKind kind,
|
AutomationNotificationKind kind,
|
||||||
AutomationNotificationProcessing processing)
|
AutomationNotificationProcessing processing)
|
||||||
:
|
: m_announcement(announcement)
|
||||||
m_announcement(announcement),
|
, m_activityId(activityId)
|
||||||
m_activityId(activityId),
|
, m_kind(kind)
|
||||||
m_kind(kind),
|
, m_processing(processing)
|
||||||
m_processing(processing)
|
{
|
||||||
{}
|
}
|
||||||
|
|
||||||
String ^ NarratorAnnouncement::Announcement::get()
|
String ^ NarratorAnnouncement::Announcement::get()
|
||||||
{
|
{
|
||||||
|
@ -57,63 +59,43 @@ AutomationNotificationProcessing NarratorAnnouncement::Processing::get()
|
||||||
|
|
||||||
bool NarratorAnnouncement::IsValid(NarratorAnnouncement ^ announcement)
|
bool NarratorAnnouncement::IsValid(NarratorAnnouncement ^ announcement)
|
||||||
{
|
{
|
||||||
return announcement != nullptr
|
return announcement != nullptr && announcement->Announcement != nullptr && !announcement->Announcement->IsEmpty();
|
||||||
&& announcement->Announcement != nullptr
|
|
||||||
&& !announcement->Announcement->IsEmpty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NarratorAnnouncement ^ CalculatorAnnouncement::GetDisplayUpdatedAnnouncement(String ^ announcement)
|
NarratorAnnouncement ^ CalculatorAnnouncement::GetDisplayUpdatedAnnouncement(String ^ announcement)
|
||||||
{
|
{
|
||||||
return ref new NarratorAnnouncement(
|
return ref new NarratorAnnouncement(
|
||||||
announcement,
|
announcement, CalculatorActivityIds::DisplayUpdated, AutomationNotificationKind::Other, AutomationNotificationProcessing::ImportantMostRecent);
|
||||||
CalculatorActivityIds::DisplayUpdated,
|
|
||||||
AutomationNotificationKind::Other,
|
|
||||||
AutomationNotificationProcessing::ImportantMostRecent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NarratorAnnouncement ^ CalculatorAnnouncement::GetMaxDigitsReachedAnnouncement(String ^ announcement)
|
NarratorAnnouncement ^ CalculatorAnnouncement::GetMaxDigitsReachedAnnouncement(String ^ announcement)
|
||||||
{
|
{
|
||||||
return ref new NarratorAnnouncement(
|
return ref new NarratorAnnouncement(
|
||||||
announcement,
|
announcement, CalculatorActivityIds::MaxDigitsReached, AutomationNotificationKind::Other, AutomationNotificationProcessing::ImportantMostRecent);
|
||||||
CalculatorActivityIds::MaxDigitsReached,
|
|
||||||
AutomationNotificationKind::Other,
|
|
||||||
AutomationNotificationProcessing::ImportantMostRecent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NarratorAnnouncement ^ CalculatorAnnouncement::GetMemoryClearedAnnouncement(String ^ announcement)
|
NarratorAnnouncement ^ CalculatorAnnouncement::GetMemoryClearedAnnouncement(String ^ announcement)
|
||||||
{
|
{
|
||||||
return ref new NarratorAnnouncement(
|
return ref new NarratorAnnouncement(
|
||||||
announcement,
|
announcement, CalculatorActivityIds::MemoryCleared, AutomationNotificationKind::ItemRemoved, AutomationNotificationProcessing::ImportantMostRecent);
|
||||||
CalculatorActivityIds::MemoryCleared,
|
|
||||||
AutomationNotificationKind::ItemRemoved,
|
|
||||||
AutomationNotificationProcessing::ImportantMostRecent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NarratorAnnouncement ^ CalculatorAnnouncement::GetMemoryItemChangedAnnouncement(String ^ announcement)
|
NarratorAnnouncement ^ CalculatorAnnouncement::GetMemoryItemChangedAnnouncement(String ^ announcement)
|
||||||
{
|
{
|
||||||
return ref new NarratorAnnouncement(
|
return ref new NarratorAnnouncement(
|
||||||
announcement,
|
announcement, CalculatorActivityIds::MemoryItemChanged, AutomationNotificationKind::ActionCompleted, AutomationNotificationProcessing::MostRecent);
|
||||||
CalculatorActivityIds::MemoryItemChanged,
|
|
||||||
AutomationNotificationKind::ActionCompleted,
|
|
||||||
AutomationNotificationProcessing::MostRecent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NarratorAnnouncement ^ CalculatorAnnouncement::GetMemoryItemAddedAnnouncement(String ^ announcement)
|
NarratorAnnouncement ^ CalculatorAnnouncement::GetMemoryItemAddedAnnouncement(String ^ announcement)
|
||||||
{
|
{
|
||||||
return ref new NarratorAnnouncement(
|
return ref new NarratorAnnouncement(
|
||||||
announcement,
|
announcement, CalculatorActivityIds::MemoryItemAdded, AutomationNotificationKind::ItemAdded, AutomationNotificationProcessing::MostRecent);
|
||||||
CalculatorActivityIds::MemoryItemAdded,
|
|
||||||
AutomationNotificationKind::ItemAdded,
|
|
||||||
AutomationNotificationProcessing::MostRecent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NarratorAnnouncement ^ CalculatorAnnouncement::GetHistoryClearedAnnouncement(String ^ announcement)
|
NarratorAnnouncement ^ CalculatorAnnouncement::GetHistoryClearedAnnouncement(String ^ announcement)
|
||||||
{
|
{
|
||||||
return ref new NarratorAnnouncement(
|
return ref new NarratorAnnouncement(
|
||||||
announcement,
|
announcement, CalculatorActivityIds::HistoryCleared, AutomationNotificationKind::ItemRemoved, AutomationNotificationProcessing::MostRecent);
|
||||||
CalculatorActivityIds::HistoryCleared,
|
|
||||||
AutomationNotificationKind::ItemRemoved,
|
|
||||||
AutomationNotificationProcessing::MostRecent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NarratorAnnouncement ^ CalculatorAnnouncement::GetCategoryNameChangedAnnouncement(String ^ announcement)
|
NarratorAnnouncement ^ CalculatorAnnouncement::GetCategoryNameChangedAnnouncement(String ^ announcement)
|
||||||
|
@ -135,10 +117,25 @@ NarratorAnnouncement^ CalculatorAnnouncement::GetUpdateCurrencyRatesAnnouncement
|
||||||
}
|
}
|
||||||
|
|
||||||
NarratorAnnouncement ^ CalculatorAnnouncement::GetDisplayCopiedAnnouncement(String ^ announcement)
|
NarratorAnnouncement ^ CalculatorAnnouncement::GetDisplayCopiedAnnouncement(String ^ announcement)
|
||||||
|
{
|
||||||
|
return ref new NarratorAnnouncement(
|
||||||
|
announcement, CalculatorActivityIds::DisplayCopied, AutomationNotificationKind::ActionCompleted, AutomationNotificationProcessing::ImportantMostRecent);
|
||||||
|
}
|
||||||
|
|
||||||
|
NarratorAnnouncement ^ CalculatorAnnouncement::GetOpenParenthesisCountChangedAnnouncement(String ^ announcement)
|
||||||
{
|
{
|
||||||
return ref new NarratorAnnouncement(
|
return ref new NarratorAnnouncement(
|
||||||
announcement,
|
announcement,
|
||||||
CalculatorActivityIds::DisplayCopied,
|
CalculatorActivityIds::OpenParenthesisCountChanged,
|
||||||
|
AutomationNotificationKind::ActionCompleted,
|
||||||
|
AutomationNotificationProcessing::ImportantMostRecent);
|
||||||
|
}
|
||||||
|
|
||||||
|
NarratorAnnouncement ^ CalculatorAnnouncement::GetNoRightParenthesisAddedAnnouncement(String ^ announcement)
|
||||||
|
{
|
||||||
|
return ref new NarratorAnnouncement(
|
||||||
|
announcement,
|
||||||
|
CalculatorActivityIds::NoParenthesisAdded,
|
||||||
AutomationNotificationKind::ActionCompleted,
|
AutomationNotificationKind::ActionCompleted,
|
||||||
AutomationNotificationProcessing::ImportantMostRecent);
|
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.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
@ -11,7 +11,8 @@ namespace CalculatorApp::Common::Automation
|
||||||
// enums should be removed and the Windows types should be used
|
// enums should be removed and the Windows types should be used
|
||||||
// instead.
|
// instead.
|
||||||
// TODO - MSFT 12735088
|
// TODO - MSFT 12735088
|
||||||
public enum class AutomationNotificationKind
|
public
|
||||||
|
enum class AutomationNotificationKind
|
||||||
{
|
{
|
||||||
ItemAdded = 0,
|
ItemAdded = 0,
|
||||||
ItemRemoved = 1,
|
ItemRemoved = 1,
|
||||||
|
@ -20,7 +21,8 @@ namespace CalculatorApp::Common::Automation
|
||||||
Other = 4
|
Other = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
public enum class AutomationNotificationProcessing
|
public
|
||||||
|
enum class AutomationNotificationProcessing
|
||||||
{
|
{
|
||||||
ImportantAll = 0,
|
ImportantAll = 0,
|
||||||
ImportantMostRecent = 1,
|
ImportantMostRecent = 1,
|
||||||
|
@ -29,18 +31,15 @@ namespace CalculatorApp::Common::Automation
|
||||||
CurrentThenMostRecent = 4
|
CurrentThenMostRecent = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
public ref class NarratorAnnouncement sealed
|
public
|
||||||
|
ref class NarratorAnnouncement sealed
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
property Platform::String^ Announcement
|
property Platform::String
|
||||||
{
|
^ Announcement { Platform::String ^ get(); }
|
||||||
Platform::String^ get();
|
|
||||||
}
|
|
||||||
|
|
||||||
property Platform::String^ ActivityId
|
property Platform::String
|
||||||
{
|
^ ActivityId { Platform::String ^ get(); }
|
||||||
Platform::String^ get();
|
|
||||||
}
|
|
||||||
|
|
||||||
property AutomationNotificationKind Kind
|
property AutomationNotificationKind Kind
|
||||||
{
|
{
|
||||||
|
@ -90,5 +89,8 @@ namespace CalculatorApp::Common::Automation
|
||||||
static NarratorAnnouncement ^ GetUpdateCurrencyRatesAnnouncement(Platform::String ^ announcement);
|
static NarratorAnnouncement ^ GetUpdateCurrencyRatesAnnouncement(Platform::String ^ announcement);
|
||||||
|
|
||||||
static NarratorAnnouncement ^ GetDisplayCopiedAnnouncement(Platform::String ^ announcement);
|
static NarratorAnnouncement ^ GetDisplayCopiedAnnouncement(Platform::String ^ announcement);
|
||||||
|
|
||||||
|
static NarratorAnnouncement ^ GetOpenParenthesisCountChangedAnnouncement(Platform::String ^ announcement);
|
||||||
|
static NarratorAnnouncement ^ GetNoRightParenthesisAddedAnnouncement(Platform::String ^ announcement);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,10 +32,7 @@ void NarratorAnnouncementHostFactory::RegisterHosts()
|
||||||
{
|
{
|
||||||
// The host that will be used is the first available host,
|
// The host that will be used is the first available host,
|
||||||
// therefore, order of hosts is important here.
|
// therefore, order of hosts is important here.
|
||||||
NarratorAnnouncementHostFactory::s_hosts = {
|
NarratorAnnouncementHostFactory::s_hosts = { ref new NotificationHost(), ref new LiveRegionHost() };
|
||||||
ref new NotificationHost(),
|
|
||||||
ref new LiveRegionHost()
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
INarratorAnnouncementHost ^ NarratorAnnouncementHostFactory::GetHostProducer()
|
INarratorAnnouncementHost ^ NarratorAnnouncementHostFactory::GetHostProducer()
|
||||||
|
|
|
@ -17,7 +17,9 @@ namespace CalculatorApp::Common::Automation
|
||||||
static INarratorAnnouncementHost ^ MakeHost();
|
static INarratorAnnouncementHost ^ MakeHost();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NarratorAnnouncementHostFactory() {}
|
NarratorAnnouncementHostFactory()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
static int Initialize();
|
static int Initialize();
|
||||||
static void RegisterHosts();
|
static void RegisterHosts();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
// Licensed under the MIT License.
|
// Licensed under the MIT License.
|
||||||
|
|
||||||
// Implementation of the NarratorNotifier class.
|
// Implementation of the NarratorNotifier class.
|
||||||
|
@ -22,8 +22,7 @@ NarratorNotifier::NarratorNotifier()
|
||||||
|
|
||||||
void NarratorNotifier::Announce(NarratorAnnouncement ^ announcement)
|
void NarratorNotifier::Announce(NarratorAnnouncement ^ announcement)
|
||||||
{
|
{
|
||||||
if (NarratorAnnouncement::IsValid(announcement)
|
if (NarratorAnnouncement::IsValid(announcement) && m_announcementHost != nullptr)
|
||||||
&& m_announcementHost != nullptr)
|
|
||||||
{
|
{
|
||||||
m_announcementHost->Announce(announcement);
|
m_announcementHost->Announce(announcement);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,8 @@
|
||||||
|
|
||||||
namespace CalculatorApp::Common::Automation
|
namespace CalculatorApp::Common::Automation
|
||||||
{
|
{
|
||||||
public ref class NarratorNotifier sealed : public Windows::UI::Xaml::DependencyObject
|
public
|
||||||
|
ref class NarratorNotifier sealed : public Windows::UI::Xaml::DependencyObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NarratorNotifier();
|
NarratorNotifier();
|
||||||
|
@ -26,18 +27,12 @@ namespace CalculatorApp::Common::Automation
|
||||||
|
|
||||||
static void RegisterDependencyProperties();
|
static void RegisterDependencyProperties();
|
||||||
|
|
||||||
static property Windows::UI::Xaml::DependencyProperty^ AnnouncementProperty
|
static property Windows::UI::Xaml::DependencyProperty
|
||||||
{
|
^ AnnouncementProperty { Windows::UI::Xaml::DependencyProperty ^ get() { return s_announcementProperty; } }
|
||||||
Windows::UI::Xaml::DependencyProperty^ get()
|
|
||||||
{
|
|
||||||
return s_announcementProperty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static NarratorAnnouncement^ GetAnnouncement(Windows::UI::Xaml::DependencyObject^ element)
|
static NarratorAnnouncement
|
||||||
{
|
^ GetAnnouncement(
|
||||||
return safe_cast<NarratorAnnouncement^>(element->GetValue(s_announcementProperty));
|
Windows::UI::Xaml::DependencyObject ^ element) { return safe_cast<NarratorAnnouncement ^>(element->GetValue(s_announcementProperty)); }
|
||||||
}
|
|
||||||
|
|
||||||
static void SetAnnouncement(Windows::UI::Xaml::DependencyObject ^ element, NarratorAnnouncement ^ value)
|
static void SetAnnouncement(Windows::UI::Xaml::DependencyObject ^ element, NarratorAnnouncement ^ value)
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,15 +10,14 @@ using namespace Windows::UI::Xaml::Automation;
|
||||||
using namespace Windows::UI::Xaml::Automation::Peers;
|
using namespace Windows::UI::Xaml::Automation::Peers;
|
||||||
using namespace Windows::UI::Xaml::Controls;
|
using namespace Windows::UI::Xaml::Controls;
|
||||||
|
|
||||||
NotificationHost::NotificationHost() :
|
NotificationHost::NotificationHost()
|
||||||
m_host(nullptr)
|
: m_host(nullptr)
|
||||||
{}
|
{
|
||||||
|
}
|
||||||
|
|
||||||
bool NotificationHost::IsHostAvailable()
|
bool NotificationHost::IsHostAvailable()
|
||||||
{
|
{
|
||||||
return ApiInformation::IsMethodPresent(
|
return ApiInformation::IsMethodPresent(L"Windows.UI.Xaml.Automation.Peers.AutomationPeer", L"RaiseNotificationEvent");
|
||||||
L"Windows.UI.Xaml.Automation.Peers.AutomationPeer",
|
|
||||||
L"RaiseNotificationEvent");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
INarratorAnnouncementHost ^ NotificationHost::MakeHost()
|
INarratorAnnouncementHost ^ NotificationHost::MakeHost()
|
||||||
|
@ -44,8 +43,7 @@ void NotificationHost::Announce(NarratorAnnouncement^ announcement)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StandardPeers::AutomationNotificationKind NotificationHost::GetWindowsNotificationKind(
|
StandardPeers::AutomationNotificationKind NotificationHost::GetWindowsNotificationKind(CustomPeers::AutomationNotificationKind customKindType)
|
||||||
CustomPeers::AutomationNotificationKind customKindType)
|
|
||||||
{
|
{
|
||||||
switch (customKindType)
|
switch (customKindType)
|
||||||
{
|
{
|
||||||
|
@ -71,8 +69,8 @@ StandardPeers::AutomationNotificationKind NotificationHost::GetWindowsNotificati
|
||||||
return StandardPeers::AutomationNotificationKind::Other;
|
return StandardPeers::AutomationNotificationKind::Other;
|
||||||
}
|
}
|
||||||
|
|
||||||
StandardPeers::AutomationNotificationProcessing NotificationHost::GetWindowsNotificationProcessing(
|
StandardPeers::AutomationNotificationProcessing
|
||||||
CustomPeers::AutomationNotificationProcessing customProcessingType)
|
NotificationHost::GetWindowsNotificationProcessing(CustomPeers::AutomationNotificationProcessing customProcessingType)
|
||||||
{
|
{
|
||||||
switch (customProcessingType)
|
switch (customProcessingType)
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,7 +10,8 @@
|
||||||
|
|
||||||
namespace CalculatorApp::Common::Automation
|
namespace CalculatorApp::Common::Automation
|
||||||
{
|
{
|
||||||
public ref class NotificationHost sealed : public INarratorAnnouncementHost
|
public
|
||||||
|
ref class NotificationHost sealed : public INarratorAnnouncementHost
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NotificationHost();
|
NotificationHost();
|
||||||
|
@ -21,14 +22,13 @@ namespace CalculatorApp::Common::Automation
|
||||||
virtual void Announce(NarratorAnnouncement ^ announcement);
|
virtual void Announce(NarratorAnnouncement ^ announcement);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static Windows::UI::Xaml::Automation::Peers::AutomationNotificationKind GetWindowsNotificationKind(
|
static Windows::UI::Xaml::Automation::Peers::AutomationNotificationKind
|
||||||
CalculatorApp::Common::Automation::AutomationNotificationKind customKindType);
|
GetWindowsNotificationKind(CalculatorApp::Common::Automation::AutomationNotificationKind customKindType);
|
||||||
|
|
||||||
static Windows::UI::Xaml::Automation::Peers::AutomationNotificationProcessing GetWindowsNotificationProcessing(
|
static Windows::UI::Xaml::Automation::Peers::AutomationNotificationProcessing
|
||||||
CalculatorApp::Common::Automation::AutomationNotificationProcessing customProcessingType);
|
GetWindowsNotificationProcessing(CalculatorApp::Common::Automation::AutomationNotificationProcessing customProcessingType);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Windows::UI::Xaml::UIElement ^ m_host;
|
Windows::UI::Xaml::UIElement ^ m_host;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|