Merge master into feature/GraphingCalculator branch (#585)
* Merge master into feature/GraphingCalculator branch
This commit is contained in:
14
src/CalcManager/CEngine/CMakeLists.txt
Normal file
14
src/CalcManager/CEngine/CMakeLists.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
target_sources(CalcManager PRIVATE
|
||||
calc.cpp
|
||||
CalcInput.cpp
|
||||
CalcUtils.cpp
|
||||
History.cpp
|
||||
Number.cpp
|
||||
Rational.cpp
|
||||
RationalMath.cpp
|
||||
scicomm.cpp
|
||||
scidisp.cpp
|
||||
scifunc.cpp
|
||||
scioper.cpp
|
||||
sciset.cpp
|
||||
)
|
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include <sstream>
|
||||
#include "Header Files/CalcEngine.h"
|
||||
|
||||
using namespace std;
|
||||
@@ -124,15 +124,15 @@ bool CalcInput::TryAddDigit(unsigned int value, uint32_t radix, bool isIntegerMo
|
||||
else if (radix == 10)
|
||||
{
|
||||
// If value length is at least the max, we know we can't add another digit.
|
||||
if(pNumSec->value.size() < maxNumStr.size())
|
||||
if (pNumSec->value.size() < maxNumStr.size())
|
||||
{
|
||||
// Compare value to substring of maxNumStr of value.size() length.
|
||||
// If cmpResult > 0:
|
||||
// eg. max is "127", and the current number is "20". first digit itself says we are out.
|
||||
// eg. max is "127", and the current number is "20". first digit itself says we are out.
|
||||
// Additional digit is not possible
|
||||
|
||||
// If cmpResult < 0:
|
||||
// Success case. eg. max is "127", and current number is say "11". The second digit '1' being <
|
||||
// Success case. eg. max is "127", and current number is say "11". The second digit '1' being <
|
||||
// corresponding digit '2', means all digits are possible to append, like 119 will still be < 127
|
||||
|
||||
// If cmpResult == 0:
|
||||
@@ -151,7 +151,7 @@ bool CalcInput::TryAddDigit(unsigned int value, uint32_t radix, bool isIntegerMo
|
||||
}
|
||||
else if (pNumSec->IsNegative() && chDigit <= lastChar + 1)
|
||||
{
|
||||
// Negative value case, eg. max is "127", and current number is "-12". Then 8 is also valid, as the range
|
||||
// Negative value case, eg. max is "127", and current number is "-12". Then 8 is also valid, as the range
|
||||
// is always from -(max+1)...max in signed mode
|
||||
allowExtraDigit = true;
|
||||
}
|
||||
|
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include "Header Files/CalcEngine.h"
|
||||
#include "Header Files/CalcUtils.h"
|
||||
|
||||
@@ -34,9 +33,7 @@ bool IsDigitOpCode(OpCode opCode)
|
||||
// was never inout, we need to revert the state changes made as a result of this test
|
||||
bool IsGuiSettingOpCode(OpCode opCode)
|
||||
{
|
||||
if (IsOpInRange(opCode, IDM_HEX, IDM_BIN) ||
|
||||
IsOpInRange(opCode, IDM_QWORD, IDM_BYTE) ||
|
||||
IsOpInRange(opCode, IDM_DEG, IDM_GRAD))
|
||||
if (IsOpInRange(opCode, IDM_HEX, IDM_BIN) || IsOpInRange(opCode, IDM_QWORD, IDM_BYTE) || IsOpInRange(opCode, IDM_DEG, IDM_GRAD))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include "Header Files/CalcEngine.h"
|
||||
#include "Command.h"
|
||||
#include "CalculatorVector.h"
|
||||
@@ -12,7 +11,8 @@ constexpr int ASCII_0 = 48;
|
||||
using namespace std;
|
||||
using namespace CalcEngine;
|
||||
|
||||
namespace {
|
||||
namespace
|
||||
{
|
||||
void IFT(ResultCode hr)
|
||||
{
|
||||
if (FAILED(hr))
|
||||
@@ -39,11 +39,11 @@ void CHistoryCollector::ReinitHistory()
|
||||
|
||||
// Constructor
|
||||
// Can throw Out of memory error
|
||||
CHistoryCollector::CHistoryCollector(ICalcDisplay *pCalcDisplay, std::shared_ptr<IHistoryDisplay> pHistoryDisplay, wchar_t decimalSymbol) :
|
||||
m_pHistoryDisplay(pHistoryDisplay),
|
||||
m_pCalcDisplay(pCalcDisplay),
|
||||
m_iCurLineHistStart(-1),
|
||||
m_decimalSymbol(decimalSymbol)
|
||||
CHistoryCollector::CHistoryCollector(ICalcDisplay* pCalcDisplay, std::shared_ptr<IHistoryDisplay> pHistoryDisplay, wchar_t decimalSymbol)
|
||||
: m_pHistoryDisplay(pHistoryDisplay)
|
||||
, m_pCalcDisplay(pCalcDisplay)
|
||||
, m_iCurLineHistStart(-1)
|
||||
, m_decimalSymbol(decimalSymbol)
|
||||
{
|
||||
ReinitHistory();
|
||||
}
|
||||
@@ -303,7 +303,8 @@ void CHistoryCollector::CompleteHistoryLine(wstring_view numStr)
|
||||
{
|
||||
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)
|
||||
@@ -324,14 +325,14 @@ void CHistoryCollector::ClearHistoryLine(wstring_view errStr)
|
||||
{
|
||||
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
|
||||
ReinitHistory();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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
|
||||
int CHistoryCollector::IchAddSzToEquationSz(wstring_view str, int icommandIndex)
|
||||
@@ -393,14 +394,13 @@ void CHistoryCollector::SetExpressionDisplay()
|
||||
{
|
||||
m_pCalcDisplay->SetExpressionDisplay(m_spTokens, m_spCommands);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int CHistoryCollector::AddCommand(_In_ const std::shared_ptr<IExpressionCommand> & spCommand)
|
||||
int CHistoryCollector::AddCommand(_In_ const std::shared_ptr<IExpressionCommand>& spCommand)
|
||||
{
|
||||
if (m_spCommands == nullptr)
|
||||
{
|
||||
m_spCommands = std::make_shared <CalculatorVector<std::shared_ptr<IExpressionCommand>>>();
|
||||
m_spCommands = std::make_shared<CalculatorVector<std::shared_ptr<IExpressionCommand>>>();
|
||||
}
|
||||
|
||||
if (FAILED(m_spCommands->Append(spCommand)))
|
||||
|
@@ -1,26 +1,28 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
#include "pch.h"
|
||||
#include <algorithm>
|
||||
#include "Header Files/Number.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace CalcEngine
|
||||
{
|
||||
Number::Number() noexcept :
|
||||
Number(1, 0, { 0 })
|
||||
{}
|
||||
Number::Number() noexcept
|
||||
: Number(1, 0, { 0 })
|
||||
{
|
||||
}
|
||||
|
||||
Number::Number(int32_t sign, int32_t exp, vector<uint32_t> const& mantissa) noexcept :
|
||||
m_sign{ sign },
|
||||
m_exp{ exp },
|
||||
m_mantissa{ mantissa }
|
||||
{}
|
||||
Number::Number(int32_t sign, int32_t exp, vector<uint32_t> const& mantissa) noexcept
|
||||
: m_sign{ sign }
|
||||
, m_exp{ exp }
|
||||
, m_mantissa{ mantissa }
|
||||
{
|
||||
}
|
||||
|
||||
Number::Number(PNUMBER p) noexcept :
|
||||
m_sign{ p->sign },
|
||||
m_exp{ p->exp },
|
||||
m_mantissa{}
|
||||
Number::Number(PNUMBER p) noexcept
|
||||
: m_sign{ p->sign }
|
||||
, m_exp{ p->exp }
|
||||
, m_mantissa{}
|
||||
{
|
||||
m_mantissa.reserve(p->cdigit);
|
||||
copy(p->mant, p->mant + p->cdigit, back_inserter(m_mantissa));
|
||||
@@ -33,7 +35,7 @@ namespace CalcEngine
|
||||
ret->exp = this->Exp();
|
||||
ret->cdigit = static_cast<int32_t>(this->Mantissa().size());
|
||||
|
||||
MANTTYPE *ptrRet = ret->mant;
|
||||
MANTTYPE* ptrRet = ret->mant;
|
||||
for (auto const& digit : this->Mantissa())
|
||||
{
|
||||
*ptrRet++ = digit;
|
||||
@@ -59,6 +61,6 @@ namespace CalcEngine
|
||||
|
||||
bool Number::IsZero() const
|
||||
{
|
||||
return all_of(m_mantissa.begin(), m_mantissa.end(), [](auto &&i) { return i == 0; });
|
||||
return all_of(m_mantissa.begin(), m_mantissa.end(), [](auto&& i) { return i == 0; });
|
||||
}
|
||||
}
|
||||
|
@@ -1,16 +1,16 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
#include "pch.h"
|
||||
#include "Header Files/Rational.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace CalcEngine
|
||||
{
|
||||
Rational::Rational() noexcept :
|
||||
m_p{},
|
||||
m_q{ 1, 0, { 1 } }
|
||||
{}
|
||||
Rational::Rational() noexcept
|
||||
: m_p{}
|
||||
, m_q{ 1, 0, { 1 } }
|
||||
{
|
||||
}
|
||||
|
||||
Rational::Rational(Number const& n) noexcept
|
||||
{
|
||||
@@ -24,10 +24,11 @@ namespace CalcEngine
|
||||
m_q = Number(1, qExp, { 1 });
|
||||
}
|
||||
|
||||
Rational::Rational(Number const& p, Number const& q) noexcept :
|
||||
m_p{ p },
|
||||
m_q{ q }
|
||||
{}
|
||||
Rational::Rational(Number const& p, Number const& q) noexcept
|
||||
: m_p{ p }
|
||||
, m_q{ q }
|
||||
{
|
||||
}
|
||||
|
||||
Rational::Rational(int32_t i)
|
||||
{
|
||||
@@ -51,8 +52,8 @@ namespace CalcEngine
|
||||
|
||||
Rational::Rational(uint64_t ui)
|
||||
{
|
||||
uint32_t hi = HIDWORD(ui);
|
||||
uint32_t lo = LODWORD(ui);
|
||||
uint32_t hi = (uint32_t) (((ui) >> 32) & 0xffffffff);
|
||||
uint32_t lo = (uint32_t) ui;
|
||||
|
||||
Rational temp = (Rational{ hi } << 32) | lo;
|
||||
|
||||
@@ -60,10 +61,11 @@ namespace CalcEngine
|
||||
m_q = Number{ temp.Q() };
|
||||
}
|
||||
|
||||
Rational::Rational(PRAT prat) noexcept :
|
||||
m_p{ Number{prat->pp} },
|
||||
m_q{ Number{prat->pq} }
|
||||
{}
|
||||
Rational::Rational(PRAT prat) noexcept
|
||||
: m_p{ Number{ prat->pp } }
|
||||
, m_q{ Number{ prat->pq } }
|
||||
{
|
||||
}
|
||||
|
||||
PRAT Rational::ToPRAT() const
|
||||
{
|
||||
@@ -182,6 +184,13 @@ namespace CalcEngine
|
||||
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)
|
||||
{
|
||||
PRAT lhsRat = this->ToPRAT();
|
||||
@@ -189,7 +198,7 @@ namespace CalcEngine
|
||||
|
||||
try
|
||||
{
|
||||
modrat(&lhsRat, rhsRat);
|
||||
remrat(&lhsRat, rhsRat);
|
||||
destroyrat(rhsRat);
|
||||
}
|
||||
catch (uint32_t error)
|
||||
@@ -342,6 +351,13 @@ namespace CalcEngine
|
||||
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)
|
||||
{
|
||||
lhs %= rhs;
|
||||
|
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include "Header Files/RationalMath.h"
|
||||
|
||||
using namespace std;
|
||||
@@ -387,3 +386,33 @@ Rational RationalMath::ATanh(Rational const& rat)
|
||||
|
||||
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.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include <cassert>
|
||||
#include "Header Files/CalcEngine.h"
|
||||
|
||||
#include "CalculatorResource.h"
|
||||
|
||||
using namespace std;
|
||||
@@ -25,13 +24,18 @@ static constexpr wstring_view DEFAULT_NUMBER_STR = L"0";
|
||||
// Read strings for keys, errors, trig types, etc.
|
||||
// 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)
|
||||
{
|
||||
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(bool fPrecedence, bool fIntegerMode, CalculationManager::IResourceProvider* const pResourceProvider, __in_opt ICalcDisplay *pCalcDisplay, __in_opt shared_ptr<IHistoryDisplay> pHistoryDisplay) :
|
||||
m_fPrecedence(fPrecedence),
|
||||
m_fIntegerMode(fIntegerMode),
|
||||
m_pCalcDisplay(pCalcDisplay),
|
||||
m_resourceProvider(pResourceProvider),
|
||||
m_nOpCode(0),
|
||||
m_nPrevOpCode(0),
|
||||
m_bChangeOp(false),
|
||||
m_bRecord(false),
|
||||
m_bSetCalcState(false),
|
||||
m_input(DEFAULT_DEC_SEPARATOR),
|
||||
m_nFE(FMT_FLOAT),
|
||||
m_memoryValue{ make_unique<Rational>() },
|
||||
m_holdVal{},
|
||||
m_currentVal{},
|
||||
m_lastVal{},
|
||||
m_parenVals{},
|
||||
m_precedenceVals{},
|
||||
m_bError(false),
|
||||
m_bInv(false),
|
||||
m_bNoPrevEqu(true),
|
||||
m_radix(DEFAULT_RADIX),
|
||||
m_precision(DEFAULT_PRECISION),
|
||||
m_cIntDigitsSav(DEFAULT_MAX_DIGITS),
|
||||
m_decGrouping(),
|
||||
m_numberString(DEFAULT_NUMBER_STR),
|
||||
m_nTempCom(0),
|
||||
m_openParenCount(0),
|
||||
m_nOp(),
|
||||
m_nPrecOp(),
|
||||
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)
|
||||
CCalcEngine::CCalcEngine(
|
||||
bool fPrecedence,
|
||||
bool fIntegerMode,
|
||||
CalculationManager::IResourceProvider* const pResourceProvider,
|
||||
__in_opt ICalcDisplay* pCalcDisplay,
|
||||
__in_opt shared_ptr<IHistoryDisplay> pHistoryDisplay)
|
||||
: m_fPrecedence(fPrecedence)
|
||||
, m_fIntegerMode(fIntegerMode)
|
||||
, m_pCalcDisplay(pCalcDisplay)
|
||||
, m_resourceProvider(pResourceProvider)
|
||||
, m_nOpCode(0)
|
||||
, m_nPrevOpCode(0)
|
||||
, m_bChangeOp(false)
|
||||
, m_bRecord(false)
|
||||
, m_bSetCalcState(false)
|
||||
, m_input(DEFAULT_DEC_SEPARATOR)
|
||||
, m_nFE(FMT_FLOAT)
|
||||
, m_memoryValue{ make_unique<Rational>() }
|
||||
, m_holdVal{}
|
||||
, m_currentVal{}
|
||||
, m_lastVal{}
|
||||
, m_parenVals{}
|
||||
, m_precedenceVals{}
|
||||
, m_bError(false)
|
||||
, m_bInv(false)
|
||||
, m_bNoPrevEqu(true)
|
||||
, m_radix(DEFAULT_RADIX)
|
||||
, m_precision(DEFAULT_PRECISION)
|
||||
, m_cIntDigitsSav(DEFAULT_MAX_DIGITS)
|
||||
, m_decGrouping()
|
||||
, m_numberString(DEFAULT_NUMBER_STR)
|
||||
, m_nTempCom(0)
|
||||
, m_openParenCount(0)
|
||||
, m_nOp()
|
||||
, m_nPrecOp()
|
||||
, 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();
|
||||
|
||||
@@ -168,7 +177,7 @@ void CCalcEngine::SettingsChanged()
|
||||
m_HistoryCollector.SetDecimalSymbol(m_decimalSeparator);
|
||||
|
||||
// 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
|
||||
numChanged = true;
|
||||
|
@@ -12,30 +12,24 @@
|
||||
*
|
||||
* Author:
|
||||
\****************************************************************************/
|
||||
#include "pch.h"
|
||||
|
||||
#include <string>
|
||||
#include "Header Files/CalcEngine.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 CalcEngine;
|
||||
|
||||
namespace {
|
||||
namespace
|
||||
{
|
||||
// NPrecedenceOfOp
|
||||
//
|
||||
// returns a virtual number for precedence for the operator. We expect binary operator only, otherwise the lowest number
|
||||
// 0 is returned. Higher the number, higher the precedence of the operator.
|
||||
int NPrecedenceOfOp(int nopCode)
|
||||
{
|
||||
static uint8_t rgbPrec[] = { 0,0, IDC_OR,0, IDC_XOR,0, IDC_AND,1,
|
||||
IDC_ADD,2, IDC_SUB,2, IDC_RSHF,3, IDC_LSHF,3,
|
||||
IDC_MOD,3, IDC_DIV,3, IDC_MUL,3, IDC_PWR,4, IDC_ROOT, 4 };
|
||||
static uint8_t rgbPrec[] = { 0, 0, IDC_OR, 0, IDC_XOR, 0, IDC_AND, 1, IDC_ADD, 2, IDC_SUB, 2, IDC_RSHF,
|
||||
3, IDC_LSHF, 3, IDC_MOD, 3, IDC_DIV, 3, IDC_MUL, 3, IDC_PWR, 4, IDC_ROOT, 4 };
|
||||
unsigned int iPrec;
|
||||
|
||||
iPrec = 0;
|
||||
@@ -48,7 +42,6 @@ namespace {
|
||||
iPrec = 0;
|
||||
}
|
||||
return rgbPrec[iPrec + 1];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +89,7 @@ void CCalcEngine::ProcessCommand(OpCode wParam)
|
||||
|
||||
void CCalcEngine::ProcessCommandWorker(OpCode wParam)
|
||||
{
|
||||
int nx, ni;
|
||||
int nx, ni;
|
||||
|
||||
// Save the last command. Some commands are not saved in this manor, these
|
||||
// commands are:
|
||||
@@ -131,18 +124,13 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
|
||||
// Toggle Record/Display mode if appropriate.
|
||||
if (m_bRecord)
|
||||
{
|
||||
if (IsOpInRange(wParam, IDC_AND, IDC_MMINUS) ||
|
||||
IsOpInRange(wParam, IDC_OPENP, IDC_CLOSEP) ||
|
||||
IsOpInRange(wParam, IDM_HEX, IDM_BIN) ||
|
||||
IsOpInRange(wParam, IDM_QWORD, IDM_BYTE) ||
|
||||
IsOpInRange(wParam, IDM_DEG, IDM_GRAD) ||
|
||||
IsOpInRange(wParam, IDC_BINEDITSTART, IDC_BINEDITSTART + 63) ||
|
||||
(IDC_INV == wParam) ||
|
||||
(IDC_SIGN == wParam && 10 != m_radix))
|
||||
if (IsOpInRange(wParam, IDC_AND, IDC_MMINUS) || IsOpInRange(wParam, IDC_OPENP, IDC_CLOSEP) || IsOpInRange(wParam, IDM_HEX, IDM_BIN)
|
||||
|| IsOpInRange(wParam, IDM_QWORD, IDM_BYTE) || IsOpInRange(wParam, IDM_DEG, IDM_GRAD)
|
||||
|| IsOpInRange(wParam, IDC_BINEDITSTART, IDC_BINEDITSTART + 63) || (IDC_INV == wParam) || (IDC_SIGN == wParam && 10 != m_radix))
|
||||
{
|
||||
m_bRecord = false;
|
||||
m_currentVal = m_input.ToRational(m_radix, m_precision);
|
||||
DisplayNum(); // Causes 3.000 to shrink to 3. on first op.
|
||||
DisplayNum(); // Causes 3.000 to shrink to 3. on first op.
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -247,9 +235,9 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
|
||||
else
|
||||
{
|
||||
/* do the last operation and then if the precedence array is not
|
||||
* empty or the top is not the '(' demarcator then pop the top
|
||||
* of the array and recheck precedence against the new operator
|
||||
*/
|
||||
* empty or the top is not the '(' demarcator then pop the top
|
||||
* of the array and recheck precedence against the new operator
|
||||
*/
|
||||
m_currentVal = DoOperation(m_nOpCode, m_currentVal, m_lastVal);
|
||||
m_nPrevOpCode = m_nOpCode;
|
||||
|
||||
@@ -278,7 +266,6 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
|
||||
m_HistoryCollector.PopLastOpndStart();
|
||||
goto DoPrecedenceCheckAgain;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -343,11 +330,9 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
|
||||
/* reset the m_bInv flag and indicators if it is set
|
||||
and have been used */
|
||||
|
||||
if (m_bInv &&
|
||||
((wParam == IDC_CHOP) ||
|
||||
(wParam == IDC_SIN) || (wParam == IDC_COS) || (wParam == IDC_TAN) ||
|
||||
(wParam == IDC_LN) || (wParam == IDC_DMS) || (wParam == IDC_DEGREES) ||
|
||||
(wParam == IDC_SINH) || (wParam == IDC_COSH) || (wParam == IDC_TANH)))
|
||||
if (m_bInv
|
||||
&& ((wParam == IDC_CHOP) || (wParam == IDC_SIN) || (wParam == IDC_COS) || (wParam == IDC_TAN) || (wParam == IDC_LN) || (wParam == IDC_DMS)
|
||||
|| (wParam == IDC_DEGREES) || (wParam == IDC_SINH) || (wParam == IDC_COSH) || (wParam == IDC_TANH)))
|
||||
{
|
||||
m_bInv = false;
|
||||
}
|
||||
@@ -381,24 +366,25 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
|
||||
{
|
||||
if (!m_bChangeOp)
|
||||
{
|
||||
// A special goody we are doing to preserve the history, if all was done was serious of unary operations last
|
||||
// Preserve history, if everything done before was a series of unary operations.
|
||||
CheckAndAddLastBinOpToHistory(false);
|
||||
}
|
||||
|
||||
m_lastVal = 0;
|
||||
|
||||
m_bChangeOp = false;
|
||||
m_precedenceOpCount = m_nTempCom = m_nLastCom = m_nOpCode = m_openParenCount = 0;
|
||||
m_openParenCount = 0;
|
||||
m_precedenceOpCount = m_nTempCom = m_nLastCom = m_nOpCode = 0;
|
||||
m_nPrevOpCode = 0;
|
||||
m_bNoPrevEqu = true;
|
||||
|
||||
|
||||
/* clear the parenthesis status box indicator, this will not be
|
||||
cleared for CENTR */
|
||||
if (nullptr != m_pCalcDisplay)
|
||||
{
|
||||
m_pCalcDisplay->SetParenDisplayText(L"");
|
||||
m_pCalcDisplay->SetExpressionDisplay(make_shared<CalculatorVector<pair<wstring, int>>>(), make_shared<CalculatorVector<shared_ptr<IExpressionCommand>>>());
|
||||
m_pCalcDisplay->SetParenthesisNumber(0);
|
||||
m_pCalcDisplay->SetExpressionDisplay(
|
||||
make_shared<CalculatorVector<pair<wstring, int>>>(), make_shared<CalculatorVector<shared_ptr<IExpressionCommand>>>());
|
||||
}
|
||||
|
||||
m_HistoryCollector.ClearHistoryLine(wstring());
|
||||
@@ -441,7 +427,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
|
||||
// automatic closing of all the parenthesis to get a meaningful result as well as ensure data integrity
|
||||
m_nTempCom = m_nLastCom; // Put back this last saved command to the prev state so ) can be handled properly
|
||||
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
|
||||
}
|
||||
|
||||
@@ -491,7 +477,8 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
|
||||
m_HistoryCollector.CompleteHistoryLine(groupedString);
|
||||
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>>>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -601,7 +588,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
|
||||
// Set the "(=xx" indicator.
|
||||
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)
|
||||
@@ -755,7 +742,6 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
|
||||
m_bInv = !m_bInv;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Helper function to resolve one item on the precedence stack.
|
||||
@@ -764,8 +750,8 @@ 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
|
||||
// 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)
|
||||
{
|
||||
@@ -820,7 +806,6 @@ void CCalcEngine::CheckAndAddLastBinOpToHistory(bool addToHistory)
|
||||
// So erase the last operand
|
||||
m_HistoryCollector.RemoveLastOpndFromHistory();
|
||||
}
|
||||
|
||||
}
|
||||
else if (m_HistoryCollector.FOpndAddedToHistory() && !m_bError)
|
||||
{
|
||||
@@ -829,8 +814,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
|
||||
// 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.
|
||||
if ((IsUnaryOpCode(m_nLastCom) || IDC_SIGN == m_nLastCom || IDC_CLOSEP == m_nLastCom) &&
|
||||
0 == m_openParenCount)
|
||||
if ((IsUnaryOpCode(m_nLastCom) || IDC_SIGN == m_nLastCom || IDC_CLOSEP == m_nLastCom) && 0 == m_openParenCount)
|
||||
{
|
||||
if (addToHistory)
|
||||
{
|
||||
@@ -868,155 +852,93 @@ void CCalcEngine::DisplayAnnounceBinaryOperator()
|
||||
// Unary operator Function Name table Element
|
||||
// since unary operators button names aren't exactly friendly for history purpose,
|
||||
// we have this separate table to get its localized name and for its Inv function if it exists.
|
||||
typedef struct
|
||||
struct FunctionNameElement
|
||||
{
|
||||
int idsFunc; // index of string for the unary op function. Can be NULL, in which case it same as button name
|
||||
int idsFuncInv; // index of string for Inv of unary op. Can be NULL, in case it is same as idsFunc
|
||||
bool fDontUseInExpEval; // true if this cant be used in reverse direction as well, ie. during expression evaluation
|
||||
} UFNE;
|
||||
wstring degreeString; // Used by default if there are no rad or grad specific strings.
|
||||
wstring inverseDegreeString; // Will fall back to degreeString if empty
|
||||
|
||||
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
|
||||
static const UFNE rgUfne[] =
|
||||
{
|
||||
/* IDC_CHOP */{ 0, IDS_FRAC, false },
|
||||
/* IDC_ROL */{ 0, 0, true },
|
||||
/* IDC_ROR */{ 0, 0, true },
|
||||
static const std::unordered_map<int, FunctionNameElement> unaryOperatorStringTable = {
|
||||
{ IDC_CHOP, { L"", SIDS_FRAC } },
|
||||
|
||||
/* IDC_COM */{ 0, 0, true },
|
||||
/* IDC_SIN */{ IDS_SIND, IDS_ASIND, false }, // default in this table is degrees for sin,cos & tan
|
||||
/* IDC_COS */{ IDS_COSD, IDS_ACOSD, false },
|
||||
/* IDC_TAN */{ IDS_TAND, IDS_ATAND, false },
|
||||
{ IDC_SIN, { SIDS_SIND, SIDS_ASIND, SIDS_SINR, SIDS_ASINR, SIDS_SING, SIDS_ASING } },
|
||||
{ IDC_COS, { SIDS_COSD, SIDS_ACOSD, SIDS_COSR, SIDS_ACOSR, SIDS_COSG, SIDS_ACOSG } },
|
||||
{ IDC_TAN, { SIDS_TAND, SIDS_ATAND, SIDS_TANR, SIDS_ATANR, SIDS_TANG, SIDS_ATANG } },
|
||||
|
||||
/* IDC_SINH */{ 0, IDS_ASINH, false },
|
||||
/* IDC_COSH */{ 0, IDS_ACOSH, false },
|
||||
/* IDC_TANH */{ 0, IDS_ATANH, false },
|
||||
{ IDC_SINH, { L"", SIDS_ASINH } },
|
||||
{ IDC_COSH, { L"", SIDS_ACOSH } },
|
||||
{ IDC_TANH, { L"", SIDS_ATANH } },
|
||||
|
||||
/* IDC_LN */{ 0, IDS_POWE, false },
|
||||
/* IDC_LOG */{ 0, 0, false },
|
||||
/* IDC_SQRT */{ 0, 0, false },
|
||||
/* IDC_SQR */{ IDS_SQR, 0, false },
|
||||
/* IDC_CUB */{ IDS_CUBE, 0, false },
|
||||
/* IDC_FAC */{ IDS_FACT, 0, false },
|
||||
/* IDC_REC */{ IDS_REC, 0, false },
|
||||
/* IDC_DMS */{ 0, IDS_DEGREES, false },
|
||||
/* 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 },
|
||||
{ IDC_LN, { L"", SIDS_POWE } },
|
||||
{ IDC_SQR, { SIDS_SQR } },
|
||||
{ IDC_CUB, { SIDS_CUBE } },
|
||||
{ IDC_FAC, { SIDS_FACT } },
|
||||
{ IDC_REC, { SIDS_RECIPROC } },
|
||||
{ IDC_DMS, { L"", SIDS_DEGREES } },
|
||||
{ IDC_SIGN, { SIDS_NEGATE } },
|
||||
{ IDC_DEGREES, { SIDS_DEGREES } }
|
||||
};
|
||||
|
||||
wstring_view CCalcEngine::OpCodeToUnaryString(int nOpCode, bool fInv, ANGLE_TYPE angletype)
|
||||
{
|
||||
// Special cases for Sign and Degrees
|
||||
if (IDC_SIGN == nOpCode)
|
||||
{
|
||||
return GetString(IDS_NEGATE);
|
||||
}
|
||||
if (IDC_DEGREES == nOpCode)
|
||||
{
|
||||
return GetString(IDS_DEGREES);
|
||||
}
|
||||
|
||||
// Correct the trigonometric functions with type of angle argument they take
|
||||
if (ANGLE_RAD == angletype)
|
||||
{
|
||||
switch (nOpCode)
|
||||
{
|
||||
case IDC_SIN:
|
||||
nOpCode = IDC_RADSIN;
|
||||
break;
|
||||
case IDC_COS:
|
||||
nOpCode = IDC_RADCOS;
|
||||
break;
|
||||
case IDC_TAN:
|
||||
nOpCode = IDC_RADTAN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
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 && (size_t)iufne < size(rgUfne))
|
||||
wstring ids = L"";
|
||||
|
||||
if (auto pair = unaryOperatorStringTable.find(nOpCode); pair != unaryOperatorStringTable.end())
|
||||
{
|
||||
if (fInv)
|
||||
const FunctionNameElement& element = pair->second;
|
||||
if (!element.hasAngleStrings || ANGLE_DEG == angletype)
|
||||
{
|
||||
ids = rgUfne[iufne].idsFuncInv;
|
||||
if (fInv)
|
||||
{
|
||||
ids = element.inverseDegreeString;
|
||||
}
|
||||
|
||||
if (ids.empty())
|
||||
{
|
||||
ids = element.degreeString;
|
||||
}
|
||||
}
|
||||
if (0 == ids)
|
||||
else if (ANGLE_RAD == angletype)
|
||||
{
|
||||
ids = rgUfne[iufne].idsFunc;
|
||||
if (fInv)
|
||||
{
|
||||
ids = element.inverseRadString;
|
||||
}
|
||||
if (ids.empty())
|
||||
{
|
||||
ids = element.radString;
|
||||
}
|
||||
}
|
||||
else if (ANGLE_GRAD == angletype)
|
||||
{
|
||||
if (fInv)
|
||||
{
|
||||
ids = element.inverseGradString;
|
||||
}
|
||||
if (ids.empty())
|
||||
{
|
||||
ids = element.gradString;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!ids.empty())
|
||||
{
|
||||
return GetString(ids);
|
||||
}
|
||||
|
||||
// If we didn't find an ID in the table, use the op code.
|
||||
if (0 == ids)
|
||||
{
|
||||
ids = IdStrFromCmdId(nOpCode);
|
||||
}
|
||||
|
||||
return GetString(ids);
|
||||
}
|
||||
|
||||
//
|
||||
// Sets the Angle Mode for special unary op IDC's which are used to index to the table rgUfne
|
||||
// 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;
|
||||
|
||||
return OpCodeToString(nOpCode);
|
||||
}
|
||||
|
||||
bool CCalcEngine::IsCurrentTooBigForTrig()
|
||||
|
@@ -12,7 +12,9 @@
|
||||
*
|
||||
* Author:
|
||||
\****************************************************************************/
|
||||
#include "pch.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <regex>
|
||||
#include "Header Files/CalcEngine.h"
|
||||
|
||||
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_decPostSepStr = L"]?(\\d*)(?:e[+-]?(\\d*))?$";
|
||||
|
||||
|
||||
/****************************************************************************\
|
||||
* void DisplayNum(void)
|
||||
*
|
||||
@@ -35,18 +36,19 @@ constexpr wstring_view c_decPostSepStr = L"]?(\\d*)(?:e[+-]?(\\d*))?$";
|
||||
//
|
||||
// State of calc last time DisplayNum was called
|
||||
//
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
Rational value;
|
||||
int32_t precision;
|
||||
uint32_t radix;
|
||||
int nFE;
|
||||
NUM_WIDTH numwidth;
|
||||
bool fIntMath;
|
||||
bool bRecord;
|
||||
bool bUseSep;
|
||||
int nFE;
|
||||
NUM_WIDTH numwidth;
|
||||
bool fIntMath;
|
||||
bool bRecord;
|
||||
bool bUseSep;
|
||||
} LASTDISP;
|
||||
|
||||
LASTDISP gldPrevious = { 0, -1, 0, -1, (NUM_WIDTH)-1, false, false, false };
|
||||
static LASTDISP gldPrevious = { 0, -1, 0, -1, (NUM_WIDTH)-1, false, false, false };
|
||||
|
||||
// Truncates if too big, makes it a non negative - the number in rat. Doesn't do anything if not in INT mode
|
||||
CalcEngine::Rational CCalcEngine::TruncateNumForIntMath(CalcEngine::Rational const& rat)
|
||||
@@ -64,7 +66,7 @@ CalcEngine::Rational CCalcEngine::TruncateNumForIntMath(CalcEngine::Rational con
|
||||
if (result < 0)
|
||||
{
|
||||
// if negative make positive by doing a twos complement
|
||||
result = -(result) - 1;
|
||||
result = -(result)-1;
|
||||
result ^= m_chopNumbers[m_numwidth];
|
||||
}
|
||||
|
||||
@@ -82,15 +84,8 @@ void CCalcEngine::DisplayNum(void)
|
||||
// something important has changed since the last time DisplayNum was
|
||||
// called.
|
||||
//
|
||||
if (m_bRecord ||
|
||||
gldPrevious.value != m_currentVal ||
|
||||
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)
|
||||
if (m_bRecord || gldPrevious.value != m_currentVal || 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.radix = m_radix;
|
||||
|
@@ -16,7 +16,6 @@
|
||||
/*** ***/
|
||||
/*** ***/
|
||||
/**************************************************************************/
|
||||
#include "pch.h"
|
||||
#include "Header Files/CalcEngine.h"
|
||||
|
||||
using namespace std;
|
||||
@@ -55,7 +54,7 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
|
||||
|
||||
uint64_t w64Bits = result.ToUInt64_t();
|
||||
uint64_t msb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1;
|
||||
w64Bits <<= 1; // LShift by 1
|
||||
w64Bits <<= 1; // LShift by 1
|
||||
w64Bits |= msb; // Set the prev Msb as the current Lsb
|
||||
|
||||
result = w64Bits;
|
||||
@@ -169,9 +168,9 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
|
||||
|
||||
case IDC_DEGREES:
|
||||
ProcessCommand(IDC_INV);
|
||||
// This case falls through to IDC_DMS case because in the old Win32 Calc,
|
||||
// This case falls through to IDC_DMS case because in the old Win32 Calc,
|
||||
// the degrees functionality was achieved as 'Inv' of 'dms' operation,
|
||||
// so setting the IDC_INV command first and then performing 'dms' operation as global variables m_bInv, m_bRecord
|
||||
// so setting the IDC_INV command first and then performing 'dms' operation as global variables m_bInv, m_bRecord
|
||||
// are set properly through ProcessCommand(IDC_INV)
|
||||
[[fallthrough]];
|
||||
case IDC_DMS:
|
||||
@@ -203,7 +202,7 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
|
||||
}
|
||||
break;
|
||||
}
|
||||
} // end switch( op )
|
||||
} // end switch( op )
|
||||
}
|
||||
catch (uint32_t nErrCode)
|
||||
{
|
||||
@@ -227,4 +226,3 @@ void CCalcEngine::DisplayError(uint32_t nError)
|
||||
|
||||
m_HistoryCollector.ClearHistoryLine(errorString);
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include "Header Files/CalcEngine.h"
|
||||
|
||||
using namespace CalcEngine;
|
||||
@@ -78,7 +77,7 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa
|
||||
case IDC_DIV:
|
||||
case IDC_MOD:
|
||||
{
|
||||
int iNumeratorSign = 1, iDenominatorSign = 1, iFinalSign = 1;
|
||||
int iNumeratorSign = 1, iDenominatorSign = 1;
|
||||
auto temp = result;
|
||||
result = rhs;
|
||||
|
||||
@@ -107,20 +106,30 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa
|
||||
|
||||
if (operation == IDC_DIV)
|
||||
{
|
||||
iFinalSign = iNumeratorSign * iDenominatorSign;
|
||||
result /= temp;
|
||||
if (m_fIntegerMode && (iNumeratorSign * iDenominatorSign) == -1)
|
||||
{
|
||||
result = -(Integer(result));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
iFinalSign = iNumeratorSign;
|
||||
result %= temp;
|
||||
}
|
||||
if (m_fIntegerMode)
|
||||
{
|
||||
// Programmer mode, use remrat (remainder after division)
|
||||
result %= temp;
|
||||
|
||||
if (m_fIntegerMode && iFinalSign == -1)
|
||||
{
|
||||
result = -(Integer(result));
|
||||
if (iNumeratorSign == -1)
|
||||
{
|
||||
result = -(Integer(result));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// other modes, use modrat (modulus after division)
|
||||
result = Mod(result, temp);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include "Header Files/CalcEngine.h"
|
||||
|
||||
using namespace CalcEngine;
|
||||
@@ -65,7 +64,7 @@ int32_t CCalcEngine::DwWordBitWidthFromeNumWidth(NUM_WIDTH /*numwidth*/)
|
||||
|
||||
uint32_t CCalcEngine::NRadixFromRadixType(RADIX_TYPE radixtype)
|
||||
{
|
||||
static constexpr uint32_t rgnRadish[4] = { 16, 10, 8, 2 }; /* Number bases in the same order as radixtype */
|
||||
static constexpr uint32_t rgnRadish[4] = { 16, 10, 8, 2 }; /* Number bases in the same order as radixtype */
|
||||
uint32_t radix = 10;
|
||||
|
||||
// convert special bases into symbolic values
|
||||
|
11
src/CalcManager/CMakeLists.txt
Normal file
11
src/CalcManager/CMakeLists.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
add_library(CalcManager
|
||||
CalculatorHistory.cpp
|
||||
CalculatorManager.cpp
|
||||
ExpressionCommand.cpp
|
||||
pch.cpp
|
||||
UnitConverter.cpp
|
||||
)
|
||||
target_include_directories(CalcManager PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
add_subdirectory(Ratpack)
|
||||
add_subdirectory(CEngine)
|
@@ -45,8 +45,8 @@
|
||||
<AppContainerApplication>true</AppContainerApplication>
|
||||
<ApplicationType>Windows Store</ApplicationType>
|
||||
<ApplicationTypeRevision>10.0</ApplicationTypeRevision>
|
||||
<WindowsTargetPlatformVersion Condition="'$(WindowsTargetPlatformVersion)' == ''">10.0.17763.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformMinVersion>10.0.17134.0</WindowsTargetPlatformMinVersion>
|
||||
<WindowsTargetPlatformVersion Condition="'$(WindowsTargetPlatformVersion)' == ''">10.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformMinVersion>10.0.18362.0</WindowsTargetPlatformMinVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<!-- This has to be exactly in this place for this to work -->
|
||||
@@ -56,46 +56,46 @@
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
@@ -153,10 +153,11 @@
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalOptions>/Zm250 /await /std:c++17 /permissive- /Zc:twoPhase- %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalOptions>/Zm250 /await /std:c++17 /permissive- /Zc:twoPhase- /utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
@@ -169,10 +170,11 @@
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalOptions>/Zm250 /await /std:c++17 /permissive- /Zc:twoPhase- %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalOptions>/Zm250 /await /std:c++17 /permissive- /Zc:twoPhase- /utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
@@ -185,10 +187,11 @@
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalOptions>/Zm250 /await /std:c++17 /permissive- /Zc:twoPhase- %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalOptions>/Zm250 /await /std:c++17 /permissive- /Zc:twoPhase- /utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
@@ -201,10 +204,11 @@
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalOptions>/Zm250 /await /std:c++17 /permissive- /Zc:twoPhase- %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalOptions>/Zm250 /await /std:c++17 /permissive- /Zc:twoPhase- /utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
@@ -217,11 +221,12 @@
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalOptions>/Zm250 /await /std:c++17 /permissive- /Zc:twoPhase- %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalOptions>/Zm250 /await /std:c++17 /permissive- /Zc:twoPhase- /utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<PreprocessorDefinitions>_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
@@ -234,10 +239,11 @@
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalOptions>/Zm250 /await /std:c++17 /permissive- /Zc:twoPhase- %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalOptions>/Zm250 /await /std:c++17 /permissive- /Zc:twoPhase- /utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
@@ -250,10 +256,11 @@
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalOptions>/Zm250 /await /std:c++17 /permissive- /Zc:twoPhase- %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalOptions>/Zm250 /await /std:c++17 /permissive- /Zc:twoPhase- /utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
@@ -266,10 +273,11 @@
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<CompileAsWinRT>false</CompileAsWinRT>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<AdditionalOptions>/Zm250 /await /std:c++17 /permissive- /Zc:twoPhase- %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalOptions>/Zm250 /await /std:c++17 /permissive- /Zc:twoPhase- /utf-8 %(AdditionalOptions)</AdditionalOptions>
|
||||
<AdditionalIncludeDirectories>$(SolutionDir)..\src\;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<TreatWarningAsError>true</TreatWarningAsError>
|
||||
<ForcedIncludeFiles>pch.h</ForcedIncludeFiles>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
@@ -278,7 +286,6 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="CalcException.h" />
|
||||
<ClInclude Include="CalculatorHistory.h" />
|
||||
<ClInclude Include="CalculatorManager.h" />
|
||||
<ClInclude Include="CalculatorResource.h" />
|
||||
|
@@ -1,17 +1,21 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include <cassert>
|
||||
#include "CalculatorHistory.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace CalculationManager;
|
||||
|
||||
CalculatorHistory::CalculatorHistory(size_t maxSize) :
|
||||
m_maxHistorySize(maxSize)
|
||||
{}
|
||||
CalculatorHistory::CalculatorHistory(size_t 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;
|
||||
wstring generatedExpression;
|
||||
@@ -31,8 +35,7 @@ unsigned int CalculatorHistory::AddToHistory(_In_ shared_ptr<CalculatorVector <p
|
||||
return addedIndex;
|
||||
}
|
||||
|
||||
|
||||
unsigned int CalculatorHistory::AddItem(_In_ shared_ptr<HISTORYITEM> const &spHistoryItem)
|
||||
unsigned int CalculatorHistory::AddItem(_In_ shared_ptr<HISTORYITEM> const& spHistoryItem)
|
||||
{
|
||||
if (m_historyItems.size() >= m_maxHistorySize)
|
||||
{
|
||||
|
@@ -15,10 +15,10 @@ namespace CalculationManager
|
||||
|
||||
struct HISTORYITEMVECTOR
|
||||
{
|
||||
std::shared_ptr<CalculatorVector <std::pair<std::wstring, int>>> spTokens;
|
||||
std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> spTokens;
|
||||
std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> spCommands;
|
||||
std::wstring expression;
|
||||
std::wstring result;
|
||||
std::wstring expression;
|
||||
std::wstring result;
|
||||
};
|
||||
|
||||
struct HISTORYITEM
|
||||
@@ -26,19 +26,23 @@ namespace CalculationManager
|
||||
HISTORYITEMVECTOR historyItemVector;
|
||||
};
|
||||
|
||||
class CalculatorHistory :
|
||||
public IHistoryDisplay
|
||||
class CalculatorHistory : public IHistoryDisplay
|
||||
{
|
||||
|
||||
public:
|
||||
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::shared_ptr<HISTORYITEM> const& GetHistoryItem(unsigned int uIdx);
|
||||
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);
|
||||
const size_t MaxHistorySize() const { return m_maxHistorySize; }
|
||||
size_t MaxHistorySize() const
|
||||
{
|
||||
return m_maxHistorySize;
|
||||
}
|
||||
~CalculatorHistory(void);
|
||||
|
||||
private:
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include <climits> // for UCHAR_MAX
|
||||
#include "Header Files/CalcEngine.h"
|
||||
#include "CalculatorManager.h"
|
||||
#include "CalculatorResource.h"
|
||||
@@ -12,27 +12,27 @@ using namespace CalcEngine;
|
||||
static constexpr size_t MAX_HISTORY_ITEMS = 20;
|
||||
static constexpr size_t SERIALIZED_NUMBER_MINSIZE = 3;
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#define __pragma(x)
|
||||
#endif
|
||||
|
||||
// Converts Memory Command enum value to unsigned char,
|
||||
// while ignoring Warning C4309: 'conversion' : truncation of constant value
|
||||
#define MEMORY_COMMAND_TO_UNSIGNED_CHAR(c)\
|
||||
__pragma(warning(push))\
|
||||
__pragma(warning(disable: 4309))\
|
||||
static_cast<unsigned char>(c)\
|
||||
__pragma(warning(pop))
|
||||
#define MEMORY_COMMAND_TO_UNSIGNED_CHAR(c) __pragma(warning(push)) __pragma(warning(disable : 4309)) static_cast<unsigned char>(c) __pragma(warning(pop))
|
||||
|
||||
namespace CalculationManager
|
||||
{
|
||||
CalculatorManager::CalculatorManager(_In_ ICalcDisplay* displayCallback, _In_ IResourceProvider* resourceProvider) :
|
||||
m_displayCallback(displayCallback),
|
||||
m_currentCalculatorEngine(nullptr),
|
||||
m_resourceProvider(resourceProvider),
|
||||
m_inHistoryItemLoadMode(false),
|
||||
m_persistedPrimaryValue(),
|
||||
m_isExponentialFormat(false),
|
||||
m_currentDegreeMode(Command::CommandNULL),
|
||||
m_savedDegreeMode(Command::CommandDEG),
|
||||
m_pStdHistory(new CalculatorHistory(MAX_HISTORY_ITEMS)),
|
||||
m_pSciHistory(new CalculatorHistory(MAX_HISTORY_ITEMS))
|
||||
CalculatorManager::CalculatorManager(_In_ ICalcDisplay* displayCallback, _In_ IResourceProvider* resourceProvider)
|
||||
: m_displayCallback(displayCallback)
|
||||
, m_currentCalculatorEngine(nullptr)
|
||||
, m_resourceProvider(resourceProvider)
|
||||
, m_inHistoryItemLoadMode(false)
|
||||
, m_persistedPrimaryValue()
|
||||
, m_isExponentialFormat(false)
|
||||
, m_currentDegreeMode(Command::CommandNULL)
|
||||
, m_savedDegreeMode(Command::CommandDEG)
|
||||
, m_pStdHistory(new CalculatorHistory(MAX_HISTORY_ITEMS))
|
||||
, m_pSciHistory(new CalculatorHistory(MAX_HISTORY_ITEMS))
|
||||
{
|
||||
CCalcEngine::InitialOneTimeOnlySetup(*m_resourceProvider);
|
||||
}
|
||||
@@ -89,7 +89,9 @@ namespace CalculationManager
|
||||
/// Used to set the expression display value on ViewModel
|
||||
/// </summary>
|
||||
/// <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)
|
||||
{
|
||||
@@ -111,9 +113,9 @@ namespace CalculationManager
|
||||
/// Callback from the engine
|
||||
/// </summary>
|
||||
/// <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>
|
||||
@@ -165,7 +167,8 @@ namespace CalculationManager
|
||||
{
|
||||
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();
|
||||
@@ -183,7 +186,8 @@ namespace CalculationManager
|
||||
{
|
||||
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();
|
||||
@@ -198,9 +202,10 @@ namespace CalculationManager
|
||||
/// </summary>
|
||||
void CalculatorManager::SetProgrammerMode()
|
||||
{
|
||||
if(!m_programmerCalculatorEngine)
|
||||
if (!m_programmerCalculatorEngine)
|
||||
{
|
||||
m_programmerCalculatorEngine = make_unique<CCalcEngine>(true /* Respect Order of Operations */, true /* Set to Integer Mode */, m_resourceProvider, this, nullptr);
|
||||
m_programmerCalculatorEngine =
|
||||
make_unique<CCalcEngine>(true /* Respect Order of Operations */, true /* Set to Integer Mode */, m_resourceProvider, this, nullptr);
|
||||
}
|
||||
|
||||
m_currentCalculatorEngine = m_programmerCalculatorEngine.get();
|
||||
@@ -209,7 +214,6 @@ namespace CalculationManager
|
||||
m_currentCalculatorEngine->ChangePrecision(static_cast<int>(CalculatorPrecision::ProgrammerModePrecision));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Send command to the Calc Engine
|
||||
/// Cast Command Enum to OpCode.
|
||||
@@ -220,8 +224,8 @@ namespace CalculationManager
|
||||
{
|
||||
// When the expression line is cleared, we save the current state, which includes,
|
||||
// primary display, memory, and degree mode
|
||||
if (command == Command::CommandCLEAR || command == Command::CommandEQU
|
||||
|| command == Command::ModeBasic || command == Command::ModeScientific || command == Command::ModeProgrammer)
|
||||
if (command == Command::CommandCLEAR || command == Command::CommandEQU || command == Command::ModeBasic || command == Command::ModeScientific
|
||||
|| command == Command::ModeProgrammer)
|
||||
{
|
||||
switch (command)
|
||||
{
|
||||
@@ -244,8 +248,6 @@ namespace CalculationManager
|
||||
{
|
||||
m_savedCommands.push_back(MapCommandForSerialize(command));
|
||||
}
|
||||
this->SerializePrimaryDisplay();
|
||||
this->SerializeMemory();
|
||||
m_savedDegreeMode = m_currentDegreeMode;
|
||||
return;
|
||||
}
|
||||
@@ -330,47 +332,6 @@ namespace CalculationManager
|
||||
return commandToLoad;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return saved degree mode which is saved when last time the expression was cleared.
|
||||
/// </summary>
|
||||
Command CalculatorManager::SerializeSavedDegreeMode()
|
||||
{
|
||||
return m_savedDegreeMode;
|
||||
}
|
||||
|
||||
void CalculatorManager::SerializePrimaryDisplay()
|
||||
{
|
||||
m_savedPrimaryValue.clear();
|
||||
m_currentCalculatorEngine->ProcessCommand(IDC_STORE);
|
||||
auto memoryObject = m_currentCalculatorEngine->PersistedMemObject();
|
||||
if (memoryObject != nullptr)
|
||||
{
|
||||
m_savedPrimaryValue = SerializeRational(*memoryObject);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return serialized primary display that is saved when the expression line was cleared.
|
||||
/// </summary>
|
||||
vector<long> CalculatorManager::GetSerializedPrimaryDisplay()
|
||||
{
|
||||
return m_savedPrimaryValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DeSerialize the primary display from vector of long
|
||||
/// </summary>
|
||||
/// <param name = "serializedPrimaryDisplay">Serialized Rational of primary display</param>
|
||||
void CalculatorManager::DeSerializePrimaryDisplay(const vector<long> &serializedPrimaryDisplay)
|
||||
{
|
||||
if (serializedPrimaryDisplay.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
m_persistedPrimaryValue = DeSerializeRational(serializedPrimaryDisplay.begin());
|
||||
this->LoadPersistedPrimaryValue();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load the persisted value that is saved in memory of CalcEngine
|
||||
/// </summary>
|
||||
@@ -380,112 +341,6 @@ namespace CalculationManager
|
||||
m_currentCalculatorEngine->ProcessCommand(IDC_RECALL);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serialize the Memory to vector of long
|
||||
/// </summary>
|
||||
/// <return type = "std::vector<long>">Serialized Rational of memory</return>
|
||||
void CalculatorManager::SerializeMemory()
|
||||
{
|
||||
m_serializedMemory.clear();
|
||||
|
||||
for (auto const& memoryItem : m_memorizedNumbers)
|
||||
{
|
||||
auto serialMem = SerializeRational(memoryItem);
|
||||
m_serializedMemory.insert(m_serializedMemory.end(), serialMem.begin(), serialMem.end());
|
||||
}
|
||||
}
|
||||
|
||||
vector<long> CalculatorManager::GetSerializedMemory()
|
||||
{
|
||||
return m_serializedMemory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DeSerialize the Memory from vector of long
|
||||
/// </summary>
|
||||
/// <param name = "serializedMemory">Serialized Rational of memory</param>
|
||||
void CalculatorManager::DeSerializeMemory(const vector<long> &serializedMemory)
|
||||
{
|
||||
vector<long>::const_iterator itr = serializedMemory.begin();
|
||||
while (itr != serializedMemory.end())
|
||||
{
|
||||
Rational memoryItem = DeSerializeRational(itr);
|
||||
auto lengthMemoryItem = (2 * SERIALIZED_NUMBER_MINSIZE) + memoryItem.P().Mantissa().size() + memoryItem.Q().Mantissa().size();
|
||||
m_memorizedNumbers.push_back(memoryItem);
|
||||
itr += lengthMemoryItem;
|
||||
}
|
||||
this->SetMemorizedNumbersString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the commands saved since the expression has been cleared.
|
||||
/// </summary>
|
||||
vector<unsigned char> CalculatorManager::SerializeCommands()
|
||||
{
|
||||
return m_savedCommands;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replay the serialized commands
|
||||
/// </summary>
|
||||
/// <param name = "serializedData">Serialized commands</param>
|
||||
void CalculatorManager::DeSerializeCommands(_In_ const vector<unsigned char>& serializedData)
|
||||
{
|
||||
m_savedCommands.clear();
|
||||
|
||||
for (auto commandItr = serializedData.begin(); commandItr != serializedData.end(); ++commandItr)
|
||||
{
|
||||
if (*commandItr >= MEMORY_COMMAND_TO_UNSIGNED_CHAR(MemoryCommand::MemorizeNumber) &&
|
||||
*commandItr <= MEMORY_COMMAND_TO_UNSIGNED_CHAR(MemoryCommand::MemorizedNumberClearAll))
|
||||
{
|
||||
// MemoryCommands(which have values above 255) are pushed on m_savedCommands upon casting to unsigned char.
|
||||
// SerializeCommands uses m_savedCommands, which is then used in DeSerializeCommands.
|
||||
// Hence, a simple cast to MemoryCommand is not sufficient.
|
||||
MemoryCommand memoryCommand = static_cast<MemoryCommand>(*commandItr + UCHAR_MAX + 1);
|
||||
unsigned int indexOfMemory = 0;
|
||||
switch (memoryCommand)
|
||||
{
|
||||
case MemoryCommand::MemorizeNumber:
|
||||
this->MemorizeNumber();
|
||||
break;
|
||||
case MemoryCommand::MemorizedNumberLoad:
|
||||
if (commandItr + 1 == serializedData.end())
|
||||
{
|
||||
throw out_of_range("Expecting index of memory, data ended prematurely");
|
||||
}
|
||||
indexOfMemory = *(++commandItr);
|
||||
this->MemorizedNumberLoad(indexOfMemory);
|
||||
break;
|
||||
case MemoryCommand::MemorizedNumberAdd:
|
||||
if (commandItr + 1 == serializedData.end())
|
||||
{
|
||||
throw out_of_range("Expecting index of memory, data ended prematurely");
|
||||
}
|
||||
indexOfMemory = *(++commandItr);
|
||||
this->MemorizedNumberAdd(indexOfMemory);
|
||||
break;
|
||||
case MemoryCommand::MemorizedNumberSubtract:
|
||||
if (commandItr + 1 == serializedData.end())
|
||||
{
|
||||
throw out_of_range("Expecting index of memory, data ended prematurely");
|
||||
}
|
||||
indexOfMemory = *(++commandItr);
|
||||
this->MemorizedNumberSubtract(indexOfMemory);
|
||||
break;
|
||||
case MemoryCommand::MemorizedNumberClearAll:
|
||||
this->MemorizedNumberClearAll();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this->SendCommand(static_cast<Command>(MapCommandForDeSerialize(*commandItr)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Memorize the current displayed value
|
||||
/// Notify the client with new the new memorize value vector
|
||||
@@ -622,10 +477,10 @@ namespace CalculationManager
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper function that selects a memory from the vector and set it to CCalcEngine
|
||||
/// Saved RAT number needs to be copied and passed in, as CCalcEngine destroyed the passed in RAT
|
||||
/// </summary>
|
||||
/// <param name="indexOfMemory">Index of the target memory</param>
|
||||
/// Helper function that selects a memory from the vector and set it to CCalcEngine
|
||||
/// Saved RAT number needs to be copied and passed in, as CCalcEngine destroyed the passed in RAT
|
||||
/// </summary>
|
||||
/// <param name="indexOfMemory">Index of the target memory</param>
|
||||
void CalculatorManager::MemorizedNumberSelect(_In_ unsigned int indexOfMemory)
|
||||
{
|
||||
if (m_currentCalculatorEngine->FInErrorState())
|
||||
@@ -673,9 +528,7 @@ namespace CalculationManager
|
||||
|
||||
vector<shared_ptr<HISTORYITEM>> const& CalculatorManager::GetHistoryItems(_In_ CALCULATOR_MODE mode)
|
||||
{
|
||||
return (mode == CM_STD) ?
|
||||
m_pStdHistory->GetHistory() :
|
||||
m_pSciHistory->GetHistory();
|
||||
return (mode == CM_STD) ? m_pStdHistory->GetHistory() : m_pSciHistory->GetHistory();
|
||||
}
|
||||
|
||||
shared_ptr<HISTORYITEM> const& CalculatorManager::GetHistoryItem(_In_ unsigned int uIdx)
|
||||
|
@@ -63,7 +63,6 @@ namespace CalculationManager
|
||||
// For persistence
|
||||
std::vector<unsigned char> m_savedCommands;
|
||||
std::vector<long> m_savedPrimaryValue;
|
||||
std::vector<long> m_serializedMemory;
|
||||
std::vector<long> m_currentSerializedMemory;
|
||||
Command m_currentDegreeMode;
|
||||
Command m_savedDegreeMode;
|
||||
@@ -91,17 +90,18 @@ namespace CalculationManager
|
||||
// ICalcDisplay
|
||||
void SetPrimaryDisplay(_In_ const std::wstring& displayString, _In_ 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 OnHistoryItemAdded(_In_ unsigned int addedItemIndex) override;
|
||||
void SetParenDisplayText(const std::wstring& parenthesisCount) override;
|
||||
void SetParenthesisNumber(_In_ unsigned int parenthesisCount) override;
|
||||
void OnNoRightParenAdded() override;
|
||||
void DisplayPasteError();
|
||||
void MaxDigitsReached() override;
|
||||
void BinaryOperatorReceived() override;
|
||||
void MemoryItemChanged(unsigned int indexOfMemory) override;
|
||||
|
||||
|
||||
CalculatorManager(ICalcDisplay* displayCallback, IResourceProvider* resourceProvider);
|
||||
~CalculatorManager();
|
||||
|
||||
@@ -110,15 +110,6 @@ namespace CalculationManager
|
||||
void SetScientificMode();
|
||||
void SetProgrammerMode();
|
||||
void SendCommand(_In_ Command command);
|
||||
std::vector<unsigned char> SerializeCommands();
|
||||
void DeSerializeCommands(_In_ const std::vector<unsigned char>& serializedData);
|
||||
void SerializeMemory();
|
||||
std::vector<long> GetSerializedMemory();
|
||||
void DeSerializeMemory(const std::vector<long> &serializedMemory);
|
||||
void SerializePrimaryDisplay();
|
||||
std::vector<long> GetSerializedPrimaryDisplay();
|
||||
void DeSerializePrimaryDisplay(const std::vector<long> &serializedPrimaryDisplay);
|
||||
Command SerializeSavedDegreeMode();
|
||||
|
||||
void MemorizeNumber();
|
||||
void MemorizedNumberLoad(_In_ unsigned int);
|
||||
@@ -128,7 +119,10 @@ namespace CalculationManager
|
||||
void MemorizedNumberClearAll();
|
||||
|
||||
bool IsEngineRecording();
|
||||
std::vector<unsigned char> GetSavedCommands(){ return m_savedCommands; }
|
||||
std::vector<unsigned char> GetSavedCommands()
|
||||
{
|
||||
return m_savedCommands;
|
||||
}
|
||||
void SetRadix(RADIX_TYPE iRadixType);
|
||||
void SetMemorizedNumbersString();
|
||||
std::wstring GetResultForRadix(uint32_t radix, int32_t precision);
|
||||
@@ -141,7 +135,10 @@ namespace CalculationManager
|
||||
std::shared_ptr<HISTORYITEM> const& GetHistoryItem(_In_ unsigned int uIdx);
|
||||
bool RemoveHistoryItem(_In_ unsigned int uIdx);
|
||||
void ClearHistory();
|
||||
size_t MaxHistorySize() const { return m_pHistory->MaxHistorySize(); }
|
||||
size_t MaxHistorySize() const
|
||||
{
|
||||
return m_pHistory->MaxHistorySize();
|
||||
}
|
||||
CalculationManager::Command GetCurrentDegreeMode();
|
||||
void SetHistory(_In_ CALCULATOR_MODE eMode, _In_ std::vector<std::shared_ptr<HISTORYITEM>> const& history);
|
||||
void SetInHistoryItemLoadMode(_In_ bool isHistoryItemLoadMode);
|
||||
|
@@ -8,7 +8,9 @@ namespace CalculationManager
|
||||
class IResourceProvider
|
||||
{
|
||||
public:
|
||||
virtual ~IResourceProvider() { }
|
||||
virtual ~IResourceProvider()
|
||||
{
|
||||
}
|
||||
|
||||
// Should return a string from the resource table for strings used
|
||||
// by the calculation engine. The strings that must be defined
|
||||
|
@@ -1,29 +1,33 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "winerror_cross_platform.h"
|
||||
#include "Ratpack/CalcErr.h"
|
||||
#include <stdexcept> // for std::out_of_range
|
||||
#include "sal_cross_platform.h" // for SAL
|
||||
|
||||
template <typename TType>
|
||||
class CalculatorVector
|
||||
{
|
||||
public:
|
||||
ResultCode GetAt(_In_opt_ unsigned int index, _Out_ TType *item)
|
||||
ResultCode GetAt(_In_opt_ unsigned int index, _Out_ TType* item)
|
||||
{
|
||||
ResultCode hr = S_OK;
|
||||
try
|
||||
{
|
||||
*item = m_vector.at(index);
|
||||
}
|
||||
catch (const std::out_of_range& /*ex*/)
|
||||
{
|
||||
hr = E_BOUNDS;
|
||||
return E_BOUNDS;
|
||||
}
|
||||
return hr;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
ResultCode GetSize(_Out_ unsigned int *size)
|
||||
ResultCode GetSize(_Out_ unsigned int* size)
|
||||
{
|
||||
*size = static_cast<unsigned>(m_vector.size());
|
||||
return S_OK;
|
||||
@@ -31,35 +35,32 @@ public:
|
||||
|
||||
ResultCode SetAt(_In_ unsigned int index, _In_opt_ TType item)
|
||||
{
|
||||
ResultCode hr = S_OK;
|
||||
try
|
||||
{
|
||||
m_vector[index] = item;
|
||||
}
|
||||
catch (const std::out_of_range& /*ex*/)
|
||||
{
|
||||
hr = E_BOUNDS;
|
||||
return E_BOUNDS;
|
||||
}
|
||||
return hr;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
ResultCode RemoveAt(_In_ unsigned int index)
|
||||
{
|
||||
ResultCode hr = S_OK;
|
||||
if (index < m_vector.size())
|
||||
{
|
||||
m_vector.erase(m_vector.begin() + index);
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = E_BOUNDS;
|
||||
return E_BOUNDS;
|
||||
}
|
||||
return hr;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
ResultCode InsertAt(_In_ unsigned int index, _In_ TType item)
|
||||
{
|
||||
ResultCode hr = S_OK;
|
||||
try
|
||||
{
|
||||
auto iter = m_vector.begin() + index;
|
||||
@@ -67,14 +68,13 @@ public:
|
||||
}
|
||||
catch (const std::bad_alloc& /*ex*/)
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
return hr;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
ResultCode Truncate(_In_ unsigned int index)
|
||||
{
|
||||
ResultCode hr = S_OK;
|
||||
if (index < m_vector.size())
|
||||
{
|
||||
auto startIter = m_vector.begin() + index;
|
||||
@@ -82,23 +82,22 @@ public:
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = E_BOUNDS;
|
||||
return E_BOUNDS;
|
||||
}
|
||||
return hr;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
ResultCode Append(_In_opt_ TType item)
|
||||
{
|
||||
ResultCode hr = S_OK;
|
||||
try
|
||||
{
|
||||
m_vector.push_back(item);
|
||||
}
|
||||
catch (const std::bad_alloc& /*ex*/)
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
return hr;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
ResultCode RemoveAtEnd()
|
||||
@@ -115,12 +114,12 @@ public:
|
||||
|
||||
ResultCode GetString(_Out_ std::wstring* expression)
|
||||
{
|
||||
ResultCode hr = S_OK;
|
||||
unsigned int nTokens = 0;
|
||||
std::pair <std::wstring, int> currentPair;
|
||||
hr = this->GetSize(&nTokens);
|
||||
ResultCode hr = this->GetSize(&nTokens);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
|
||||
std::pair<std::wstring, int> currentPair;
|
||||
for (unsigned int i = 0; i < nTokens; i++)
|
||||
{
|
||||
hr = this->GetAt(i, ¤tPair);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
@@ -7,9 +7,19 @@ namespace UnitConversionManager
|
||||
{
|
||||
enum class Command
|
||||
{
|
||||
Zero, One, Two, Three, Four, Five, Six, Seven, Eight, Nine,
|
||||
Zero,
|
||||
One,
|
||||
Two,
|
||||
Three,
|
||||
Four,
|
||||
Five,
|
||||
Six,
|
||||
Seven,
|
||||
Eight,
|
||||
Nine,
|
||||
Decimal,
|
||||
Negate, Backspace,
|
||||
Negate,
|
||||
Backspace,
|
||||
Clear,
|
||||
Reset,
|
||||
None
|
||||
@@ -20,9 +30,19 @@ namespace CurrencyConversionManager
|
||||
{
|
||||
enum class Command
|
||||
{
|
||||
Zero, One, Two, Three, Four, Five, Six, Seven, Eight, Nine,
|
||||
Zero,
|
||||
One,
|
||||
Two,
|
||||
Three,
|
||||
Four,
|
||||
Five,
|
||||
Six,
|
||||
Seven,
|
||||
Eight,
|
||||
Nine,
|
||||
Decimal,
|
||||
Negate, Backspace,
|
||||
Negate,
|
||||
Backspace,
|
||||
Clear,
|
||||
None
|
||||
};
|
||||
@@ -73,7 +93,7 @@ namespace CalculationManager
|
||||
CommandROOT = 96,
|
||||
CommandPWR = 97,
|
||||
|
||||
CommandCHOP = 98, // Unary operators must be between CommandCHOP and CommandEQU
|
||||
CommandCHOP = 98, // Unary operators must be between CommandCHOP and CommandEQU
|
||||
CommandROL = 99,
|
||||
CommandROR = 100,
|
||||
CommandCOM = 101,
|
||||
@@ -85,7 +105,6 @@ namespace CalculationManager
|
||||
CommandCOSH = 106,
|
||||
CommandTANH = 107,
|
||||
|
||||
|
||||
CommandLN = 108,
|
||||
CommandLOG = 109,
|
||||
CommandSQRT = 110,
|
||||
@@ -94,8 +113,8 @@ namespace CalculationManager
|
||||
CommandFAC = 113,
|
||||
CommandREC = 114,
|
||||
CommandDMS = 115,
|
||||
CommandCUBEROOT = 116, // x ^ 1/3
|
||||
CommandPOW10 = 117, // 10 ^ x
|
||||
CommandCUBEROOT = 116, // x ^ 1/3
|
||||
CommandPOW10 = 117, // 10 ^ x
|
||||
CommandPERCENT = 118,
|
||||
|
||||
CommandFE = 119,
|
||||
@@ -113,7 +132,7 @@ namespace CalculationManager
|
||||
CommandOPENP = 128,
|
||||
CommandCLOSEP = 129,
|
||||
|
||||
Command0 = 130, // The controls for 0 through F must be consecutive and in order
|
||||
Command0 = 130, // The controls for 0 through F must be consecutive and in order
|
||||
Command1 = 131,
|
||||
Command2 = 132,
|
||||
Command3 = 133,
|
||||
@@ -128,7 +147,7 @@ namespace CalculationManager
|
||||
CommandC = 142,
|
||||
CommandD = 143,
|
||||
CommandE = 144,
|
||||
CommandF = 145, // this is last control ID which must match the string table
|
||||
CommandF = 145, // this is last control ID which must match the string table
|
||||
CommandINV = 146,
|
||||
CommandSET_RESULT = 147,
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include <string>
|
||||
#include "Header Files/CCommand.h"
|
||||
#include "CalculatorVector.h"
|
||||
#include "ExpressionCommand.h"
|
||||
@@ -13,8 +13,10 @@ constexpr wchar_t chNegate = L'-';
|
||||
constexpr wchar_t chExp = L'e';
|
||||
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
|
||||
{
|
||||
@@ -26,7 +28,7 @@ CalculationManager::CommandType CParentheses::GetCommandType() const
|
||||
return CalculationManager::CommandType::Parentheses;
|
||||
}
|
||||
|
||||
void CParentheses::Accept(_In_ ISerializeCommandVisitor &commandVisitor)
|
||||
void CParentheses::Accept(_In_ ISerializeCommandVisitor& commandVisitor)
|
||||
{
|
||||
commandVisitor.Visit(*this);
|
||||
}
|
||||
@@ -44,7 +46,7 @@ CUnaryCommand::CUnaryCommand(int command1, int command2)
|
||||
m_command->Append(command2);
|
||||
}
|
||||
|
||||
const shared_ptr<CalculatorVector<int>> & CUnaryCommand::GetCommands() const
|
||||
const shared_ptr<CalculatorVector<int>>& CUnaryCommand::GetCommands() const
|
||||
{
|
||||
return m_command;
|
||||
}
|
||||
@@ -67,13 +69,15 @@ void CUnaryCommand::SetCommands(int command1, int command2)
|
||||
m_command->Append(command2);
|
||||
}
|
||||
|
||||
void CUnaryCommand::Accept(_In_ ISerializeCommandVisitor &commandVisitor)
|
||||
void CUnaryCommand::Accept(_In_ ISerializeCommandVisitor& commandVisitor)
|
||||
{
|
||||
commandVisitor.Visit(*this);
|
||||
}
|
||||
|
||||
CBinaryCommand::CBinaryCommand(int command) :m_command(command)
|
||||
{}
|
||||
CBinaryCommand::CBinaryCommand(int command)
|
||||
: m_command(command)
|
||||
{
|
||||
}
|
||||
|
||||
void CBinaryCommand::SetCommand(int command)
|
||||
{
|
||||
@@ -90,19 +94,20 @@ CalculationManager::CommandType CBinaryCommand::GetCommandType() const
|
||||
return CalculationManager::CommandType::BinaryCommand;
|
||||
}
|
||||
|
||||
void CBinaryCommand::Accept(_In_ ISerializeCommandVisitor &commandVisitor)
|
||||
void CBinaryCommand::Accept(_In_ ISerializeCommandVisitor& commandVisitor)
|
||||
{
|
||||
commandVisitor.Visit(*this);
|
||||
}
|
||||
|
||||
COpndCommand::COpndCommand(shared_ptr<CalculatorVector<int>> const &commands, bool fNegative, bool fDecimal, bool fSciFmt) :
|
||||
m_commands(commands),
|
||||
m_fNegative(fNegative),
|
||||
m_fSciFmt(fSciFmt),
|
||||
m_fDecimal(fDecimal),
|
||||
m_fInitialized(false),
|
||||
m_value{}
|
||||
{}
|
||||
COpndCommand::COpndCommand(shared_ptr<CalculatorVector<int>> const& commands, bool fNegative, bool fDecimal, bool fSciFmt)
|
||||
: m_commands(commands)
|
||||
, m_fNegative(fNegative)
|
||||
, m_fSciFmt(fSciFmt)
|
||||
, m_fDecimal(fDecimal)
|
||||
, m_fInitialized(false)
|
||||
, m_value{}
|
||||
{
|
||||
}
|
||||
|
||||
void COpndCommand::Initialize(Rational const& rat)
|
||||
{
|
||||
@@ -110,7 +115,7 @@ void COpndCommand::Initialize(Rational const& rat)
|
||||
m_fInitialized = true;
|
||||
}
|
||||
|
||||
const shared_ptr<CalculatorVector<int>> & COpndCommand::GetCommands() const
|
||||
const shared_ptr<CalculatorVector<int>>& COpndCommand::GetCommands() const
|
||||
{
|
||||
return m_commands;
|
||||
}
|
||||
@@ -213,7 +218,7 @@ void COpndCommand::ClearAllAndAppendCommand(CalculationManager::Command command)
|
||||
m_fDecimal = false;
|
||||
}
|
||||
|
||||
const wstring & COpndCommand::GetToken(wchar_t decimalSymbol)
|
||||
const wstring& COpndCommand::GetToken(wchar_t decimalSymbol)
|
||||
{
|
||||
static const wchar_t chZero = L'0';
|
||||
|
||||
@@ -299,7 +304,7 @@ wstring COpndCommand::GetString(uint32_t radix, int32_t precision)
|
||||
return result;
|
||||
}
|
||||
|
||||
void COpndCommand::Accept(_In_ ISerializeCommandVisitor &commandVisitor)
|
||||
void COpndCommand::Accept(_In_ ISerializeCommandVisitor& commandVisitor)
|
||||
{
|
||||
commandVisitor.Visit(*this);
|
||||
}
|
||||
|
@@ -12,7 +12,7 @@ public:
|
||||
CParentheses(_In_ int command);
|
||||
int GetCommand() const override;
|
||||
CalculationManager::CommandType GetCommandType() const override;
|
||||
void Accept(_In_ ISerializeCommandVisitor &commandVisitor) override;
|
||||
void Accept(_In_ ISerializeCommandVisitor& commandVisitor) override;
|
||||
|
||||
private:
|
||||
int m_command;
|
||||
@@ -23,11 +23,11 @@ class CUnaryCommand final : public IUnaryCommand
|
||||
public:
|
||||
CUnaryCommand(int command);
|
||||
CUnaryCommand(int command1, int command2);
|
||||
const std::shared_ptr<CalculatorVector<int>> & GetCommands() const override;
|
||||
const std::shared_ptr<CalculatorVector<int>>& GetCommands() const override;
|
||||
CalculationManager::CommandType GetCommandType() const override;
|
||||
void SetCommand(int command) override;
|
||||
void SetCommands(int command1, int command2) override;
|
||||
void Accept(_In_ ISerializeCommandVisitor &commandVisitor) override;
|
||||
void Accept(_In_ ISerializeCommandVisitor& commandVisitor) override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<CalculatorVector<int>> m_command;
|
||||
@@ -40,7 +40,7 @@ public:
|
||||
void SetCommand(int command) override;
|
||||
int GetCommand() const override;
|
||||
CalculationManager::CommandType GetCommandType() const override;
|
||||
void Accept(_In_ ISerializeCommandVisitor &commandVisitor) override;
|
||||
void Accept(_In_ ISerializeCommandVisitor& commandVisitor) override;
|
||||
|
||||
private:
|
||||
int m_command;
|
||||
@@ -49,14 +49,10 @@ private:
|
||||
class COpndCommand final : public IOpndCommand
|
||||
{
|
||||
public:
|
||||
COpndCommand(
|
||||
std::shared_ptr<CalculatorVector<int>> const &commands,
|
||||
bool fNegative,
|
||||
bool fDecimal,
|
||||
bool fSciFmt);
|
||||
COpndCommand(std::shared_ptr<CalculatorVector<int>> const& commands, bool fNegative, bool fDecimal, bool fSciFmt);
|
||||
void Initialize(CalcEngine::Rational const& rat);
|
||||
|
||||
const std::shared_ptr<CalculatorVector<int>> & GetCommands() const override;
|
||||
const std::shared_ptr<CalculatorVector<int>>& GetCommands() const override;
|
||||
void SetCommands(std::shared_ptr<CalculatorVector<int>> const& commands) override;
|
||||
void AppendCommand(int command) override;
|
||||
void ToggleSign() override;
|
||||
@@ -64,9 +60,9 @@ public:
|
||||
bool IsNegative() const override;
|
||||
bool IsSciFmt() const override;
|
||||
bool IsDecimalPresent() const override;
|
||||
const std::wstring & GetToken(wchar_t decimalSymbol) override;
|
||||
const std::wstring& GetToken(wchar_t decimalSymbol) override;
|
||||
CalculationManager::CommandType GetCommandType() const override;
|
||||
void Accept(_In_ ISerializeCommandVisitor &commandVisitor) override;
|
||||
void Accept(_In_ ISerializeCommandVisitor& commandVisitor) override;
|
||||
std::wstring GetString(uint32_t radix, int32_t precision);
|
||||
|
||||
private:
|
||||
@@ -83,8 +79,8 @@ private:
|
||||
class ISerializeCommandVisitor
|
||||
{
|
||||
public:
|
||||
virtual void Visit(_In_ COpndCommand &opndCmd) = 0;
|
||||
virtual void Visit(_In_ CUnaryCommand &unaryCmd) = 0;
|
||||
virtual void Visit(_In_ CBinaryCommand &binaryCmd) = 0;
|
||||
virtual void Visit(_In_ CParentheses ¶Cmd) = 0;
|
||||
virtual void Visit(_In_ COpndCommand& opndCmd) = 0;
|
||||
virtual void Visit(_In_ CUnaryCommand& unaryCmd) = 0;
|
||||
virtual void Visit(_In_ CBinaryCommand& binaryCmd) = 0;
|
||||
virtual void Visit(_In_ CParentheses& paraCmd) = 0;
|
||||
};
|
||||
|
@@ -1,7 +1,9 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory> // for std::shared_ptr
|
||||
#include "CalculatorVector.h"
|
||||
#include "Command.h"
|
||||
|
||||
@@ -11,7 +13,7 @@ class IExpressionCommand
|
||||
{
|
||||
public:
|
||||
virtual CalculationManager::CommandType GetCommandType() const = 0;
|
||||
virtual void Accept(_In_ ISerializeCommandVisitor &commandVisitor) = 0;
|
||||
virtual void Accept(_In_ ISerializeCommandVisitor& commandVisitor) = 0;
|
||||
};
|
||||
|
||||
class IOperatorCommand : public IExpressionCommand
|
||||
@@ -23,7 +25,7 @@ public:
|
||||
class IUnaryCommand : public IOperatorCommand
|
||||
{
|
||||
public:
|
||||
virtual const std::shared_ptr<CalculatorVector<int>> & GetCommands() const = 0;
|
||||
virtual const std::shared_ptr<CalculatorVector<int>>& GetCommands() const = 0;
|
||||
virtual void SetCommands(int command1, int command2) = 0;
|
||||
};
|
||||
|
||||
@@ -37,14 +39,14 @@ public:
|
||||
class IOpndCommand : public IExpressionCommand
|
||||
{
|
||||
public:
|
||||
virtual const std::shared_ptr<CalculatorVector<int>> & GetCommands() const= 0;
|
||||
virtual const std::shared_ptr<CalculatorVector<int>>& GetCommands() const = 0;
|
||||
virtual void AppendCommand(int command) = 0;
|
||||
virtual void ToggleSign() = 0;
|
||||
virtual void RemoveFromEnd() = 0;
|
||||
virtual bool IsNegative() const = 0;
|
||||
virtual bool IsSciFmt() const = 0;
|
||||
virtual bool IsDecimalPresent() const = 0;
|
||||
virtual const std::wstring & GetToken(wchar_t decimalSymbol) = 0;
|
||||
virtual const std::wstring& GetToken(wchar_t decimalSymbol) = 0;
|
||||
virtual void SetCommands(std::shared_ptr<CalculatorVector<int>> const& commands) = 0;
|
||||
};
|
||||
|
||||
|
@@ -13,36 +13,37 @@
|
||||
*
|
||||
\****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
// The following are the valid id's which can be passed to CCalcEngine::ProcessCommand
|
||||
|
||||
#define IDM_HEX 313
|
||||
#define IDM_DEC 314
|
||||
#define IDM_OCT 315
|
||||
#define IDM_BIN 316
|
||||
#define IDM_QWORD 317
|
||||
#define IDM_DWORD 318
|
||||
#define IDM_WORD 319
|
||||
#define IDM_BYTE 320
|
||||
#define IDM_DEG 321
|
||||
#define IDM_RAD 322
|
||||
#define IDM_GRAD 323
|
||||
#define IDM_DEGREES 324
|
||||
#define IDM_HEX 313
|
||||
#define IDM_DEC 314
|
||||
#define IDM_OCT 315
|
||||
#define IDM_BIN 316
|
||||
#define IDM_QWORD 317
|
||||
#define IDM_DWORD 318
|
||||
#define IDM_WORD 319
|
||||
#define IDM_BYTE 320
|
||||
#define IDM_DEG 321
|
||||
#define IDM_RAD 322
|
||||
#define IDM_GRAD 323
|
||||
#define IDM_DEGREES 324
|
||||
|
||||
#define IDC_HEX IDM_HEX
|
||||
#define IDC_DEC IDM_DEC
|
||||
#define IDC_OCT IDM_OCT
|
||||
#define IDC_BIN IDM_BIN
|
||||
#define IDC_HEX IDM_HEX
|
||||
#define IDC_DEC IDM_DEC
|
||||
#define IDC_OCT IDM_OCT
|
||||
#define IDC_BIN IDM_BIN
|
||||
|
||||
#define IDC_DEG IDM_DEG
|
||||
#define IDC_RAD IDM_RAD
|
||||
#define IDC_GRAD IDM_GRAD
|
||||
#define IDC_DEGREES IDM_DEGREES
|
||||
|
||||
#define IDC_QWORD IDM_QWORD
|
||||
#define IDC_DWORD IDM_DWORD
|
||||
#define IDC_WORD IDM_WORD
|
||||
#define IDC_BYTE IDM_BYTE
|
||||
#define IDC_DEG IDM_DEG
|
||||
#define IDC_RAD IDM_RAD
|
||||
#define IDC_GRAD IDM_GRAD
|
||||
#define IDC_DEGREES IDM_DEGREES
|
||||
|
||||
#define IDC_QWORD IDM_QWORD
|
||||
#define IDC_DWORD IDM_DWORD
|
||||
#define IDC_WORD IDM_WORD
|
||||
#define IDC_BYTE IDM_BYTE
|
||||
|
||||
// Key IDs:
|
||||
// These id's must be consecutive from IDC_FIRSTCONTROL to IDC_LASTCONTROL.
|
||||
@@ -53,162 +54,158 @@
|
||||
// Find the string id for that control from the rc file
|
||||
// Now define the control's id as IDC_FRISTCONTROL+stringID(IDC_ST_AVE)
|
||||
#define IDC_FIRSTCONTROL IDC_SIGN
|
||||
#define IDC_SIGN 80
|
||||
#define IDC_CLEAR 81
|
||||
#define IDC_CENTR 82
|
||||
#define IDC_BACK 83
|
||||
#define IDC_SIGN 80
|
||||
#define IDC_CLEAR 81
|
||||
#define IDC_CENTR 82
|
||||
#define IDC_BACK 83
|
||||
|
||||
#define IDC_PNT 84
|
||||
#define IDC_PNT 84
|
||||
|
||||
// Hole 85
|
||||
|
||||
#define IDC_AND 86 // Binary operators must be between IDC_AND and IDC_PWR
|
||||
#define IDC_OR 87
|
||||
#define IDC_XOR 88
|
||||
#define IDC_LSHF 89
|
||||
#define IDC_RSHF 90
|
||||
#define IDC_DIV 91
|
||||
#define IDC_MUL 92
|
||||
#define IDC_ADD 93
|
||||
#define IDC_SUB 94
|
||||
#define IDC_MOD 95
|
||||
#define IDC_ROOT 96
|
||||
#define IDC_PWR 97
|
||||
#define IDC_AND 86 // Binary operators must be between IDC_AND and IDC_PWR
|
||||
#define IDC_OR 87
|
||||
#define IDC_XOR 88
|
||||
#define IDC_LSHF 89
|
||||
#define IDC_RSHF 90
|
||||
#define IDC_DIV 91
|
||||
#define IDC_MUL 92
|
||||
#define IDC_ADD 93
|
||||
#define IDC_SUB 94
|
||||
#define IDC_MOD 95
|
||||
#define IDC_ROOT 96
|
||||
#define IDC_PWR 97
|
||||
|
||||
#define IDC_UNARYFIRST IDC_CHOP
|
||||
#define IDC_CHOP 98 // Unary operators must be between IDC_CHOP and IDC_EQU
|
||||
#define IDC_ROL 99
|
||||
#define IDC_ROR 100
|
||||
#define IDC_COM 101
|
||||
#define IDC_SIN 102
|
||||
#define IDC_COS 103
|
||||
#define IDC_TAN 104
|
||||
|
||||
#define IDC_UNARYFIRST IDC_CHOP
|
||||
#define IDC_CHOP 98 // Unary operators must be between IDC_CHOP and IDC_EQU
|
||||
#define IDC_ROL 99
|
||||
#define IDC_ROR 100
|
||||
#define IDC_COM 101
|
||||
#define IDC_SIN 102
|
||||
#define IDC_COS 103
|
||||
#define IDC_TAN 104
|
||||
#define IDC_SINH 105
|
||||
#define IDC_COSH 106
|
||||
#define IDC_TANH 107
|
||||
|
||||
#define IDC_SINH 105
|
||||
#define IDC_COSH 106
|
||||
#define IDC_TANH 107
|
||||
|
||||
#define IDC_LN 108
|
||||
#define IDC_LOG 109
|
||||
#define IDC_SQRT 110
|
||||
#define IDC_SQR 111
|
||||
#define IDC_CUB 112
|
||||
#define IDC_FAC 113
|
||||
#define IDC_REC 114
|
||||
#define IDC_DMS 115
|
||||
#define IDC_CUBEROOT 116 // x ^ 1/3
|
||||
#define IDC_POW10 117 // 10 ^ x
|
||||
#define IDC_PERCENT 118
|
||||
#define IDC_LN 108
|
||||
#define IDC_LOG 109
|
||||
#define IDC_SQRT 110
|
||||
#define IDC_SQR 111
|
||||
#define IDC_CUB 112
|
||||
#define IDC_FAC 113
|
||||
#define IDC_REC 114
|
||||
#define IDC_DMS 115
|
||||
#define IDC_CUBEROOT 116 // x ^ 1/3
|
||||
#define IDC_POW10 117 // 10 ^ x
|
||||
#define IDC_PERCENT 118
|
||||
#define IDC_UNARYLAST IDC_PERCENT
|
||||
|
||||
#define IDC_FE 119
|
||||
#define IDC_PI 120
|
||||
#define IDC_EQU 121
|
||||
#define IDC_FE 119
|
||||
#define IDC_PI 120
|
||||
#define IDC_EQU 121
|
||||
|
||||
#define IDC_MCLEAR 122
|
||||
#define IDC_RECALL 123
|
||||
#define IDC_STORE 124
|
||||
#define IDC_MPLUS 125
|
||||
#define IDC_MMINUS 126
|
||||
#define IDC_MCLEAR 122
|
||||
#define IDC_RECALL 123
|
||||
#define IDC_STORE 124
|
||||
#define IDC_MPLUS 125
|
||||
#define IDC_MMINUS 126
|
||||
|
||||
#define IDC_EXP 127
|
||||
#define IDC_EXP 127
|
||||
|
||||
#define IDC_OPENP 128
|
||||
#define IDC_CLOSEP 129
|
||||
|
||||
#define IDC_OPENP 128
|
||||
#define IDC_CLOSEP 129
|
||||
|
||||
#define IDC_0 130 // The controls for 0 through F must be consecutive and in order
|
||||
#define IDC_1 131
|
||||
#define IDC_2 132
|
||||
#define IDC_3 133
|
||||
#define IDC_4 134
|
||||
#define IDC_5 135
|
||||
#define IDC_6 136
|
||||
#define IDC_7 137
|
||||
#define IDC_8 138
|
||||
#define IDC_9 139
|
||||
#define IDC_A 140
|
||||
#define IDC_B 141
|
||||
#define IDC_C 142
|
||||
#define IDC_D 143
|
||||
#define IDC_E 144
|
||||
#define IDC_F 145 // this is last control ID which must match the string table
|
||||
#define IDC_INV 146
|
||||
#define IDC_SET_RESULT 147
|
||||
#define IDC_0 130 // The controls for 0 through F must be consecutive and in order
|
||||
#define IDC_1 131
|
||||
#define IDC_2 132
|
||||
#define IDC_3 133
|
||||
#define IDC_4 134
|
||||
#define IDC_5 135
|
||||
#define IDC_6 136
|
||||
#define IDC_7 137
|
||||
#define IDC_8 138
|
||||
#define IDC_9 139
|
||||
#define IDC_A 140
|
||||
#define IDC_B 141
|
||||
#define IDC_C 142
|
||||
#define IDC_D 143
|
||||
#define IDC_E 144
|
||||
#define IDC_F 145 // this is last control ID which must match the string table
|
||||
#define IDC_INV 146
|
||||
#define IDC_SET_RESULT 147
|
||||
|
||||
#define IDC_LASTCONTROL IDC_SET_RESULT
|
||||
|
||||
#define IDC_BINEDITSTART 700
|
||||
#define IDC_BINPOS0 700
|
||||
#define IDC_BINPOS1 701
|
||||
#define IDC_BINPOS2 702
|
||||
#define IDC_BINPOS3 703
|
||||
#define IDC_BINPOS4 704
|
||||
#define IDC_BINPOS5 705
|
||||
#define IDC_BINPOS6 706
|
||||
#define IDC_BINPOS7 707
|
||||
#define IDC_BINPOS8 708
|
||||
#define IDC_BINPOS9 709
|
||||
#define IDC_BINPOS10 710
|
||||
#define IDC_BINPOS11 711
|
||||
#define IDC_BINPOS12 712
|
||||
#define IDC_BINPOS13 713
|
||||
#define IDC_BINPOS14 714
|
||||
#define IDC_BINPOS15 715
|
||||
#define IDC_BINPOS16 716
|
||||
#define IDC_BINPOS17 717
|
||||
#define IDC_BINPOS18 718
|
||||
#define IDC_BINPOS19 719
|
||||
#define IDC_BINPOS20 720
|
||||
#define IDC_BINPOS21 721
|
||||
#define IDC_BINPOS22 722
|
||||
#define IDC_BINPOS23 723
|
||||
#define IDC_BINPOS24 724
|
||||
#define IDC_BINPOS25 725
|
||||
#define IDC_BINPOS26 726
|
||||
#define IDC_BINPOS27 727
|
||||
#define IDC_BINPOS28 728
|
||||
#define IDC_BINPOS29 729
|
||||
#define IDC_BINPOS30 730
|
||||
#define IDC_BINPOS31 731
|
||||
#define IDC_BINPOS32 732
|
||||
#define IDC_BINPOS33 733
|
||||
#define IDC_BINPOS34 734
|
||||
#define IDC_BINPOS35 735
|
||||
#define IDC_BINPOS36 736
|
||||
#define IDC_BINPOS37 737
|
||||
#define IDC_BINPOS38 738
|
||||
#define IDC_BINPOS39 739
|
||||
#define IDC_BINPOS40 740
|
||||
#define IDC_BINPOS41 741
|
||||
#define IDC_BINPOS42 742
|
||||
#define IDC_BINPOS43 743
|
||||
#define IDC_BINPOS44 744
|
||||
#define IDC_BINPOS45 745
|
||||
#define IDC_BINPOS46 746
|
||||
#define IDC_BINPOS47 747
|
||||
#define IDC_BINPOS48 748
|
||||
#define IDC_BINPOS49 749
|
||||
#define IDC_BINPOS50 750
|
||||
#define IDC_BINPOS51 751
|
||||
#define IDC_BINPOS52 752
|
||||
#define IDC_BINPOS53 753
|
||||
#define IDC_BINPOS54 754
|
||||
#define IDC_BINPOS55 755
|
||||
#define IDC_BINPOS56 756
|
||||
#define IDC_BINPOS57 757
|
||||
#define IDC_BINPOS58 758
|
||||
#define IDC_BINPOS59 759
|
||||
#define IDC_BINPOS60 760
|
||||
#define IDC_BINPOS61 761
|
||||
#define IDC_BINPOS62 762
|
||||
#define IDC_BINPOS63 763
|
||||
#define IDC_BINEDITEND 763
|
||||
|
||||
#define IDC_BINEDITSTART 700
|
||||
#define IDC_BINPOS0 700
|
||||
#define IDC_BINPOS1 701
|
||||
#define IDC_BINPOS2 702
|
||||
#define IDC_BINPOS3 703
|
||||
#define IDC_BINPOS4 704
|
||||
#define IDC_BINPOS5 705
|
||||
#define IDC_BINPOS6 706
|
||||
#define IDC_BINPOS7 707
|
||||
#define IDC_BINPOS8 708
|
||||
#define IDC_BINPOS9 709
|
||||
#define IDC_BINPOS10 710
|
||||
#define IDC_BINPOS11 711
|
||||
#define IDC_BINPOS12 712
|
||||
#define IDC_BINPOS13 713
|
||||
#define IDC_BINPOS14 714
|
||||
#define IDC_BINPOS15 715
|
||||
#define IDC_BINPOS16 716
|
||||
#define IDC_BINPOS17 717
|
||||
#define IDC_BINPOS18 718
|
||||
#define IDC_BINPOS19 719
|
||||
#define IDC_BINPOS20 720
|
||||
#define IDC_BINPOS21 721
|
||||
#define IDC_BINPOS22 722
|
||||
#define IDC_BINPOS23 723
|
||||
#define IDC_BINPOS24 724
|
||||
#define IDC_BINPOS25 725
|
||||
#define IDC_BINPOS26 726
|
||||
#define IDC_BINPOS27 727
|
||||
#define IDC_BINPOS28 728
|
||||
#define IDC_BINPOS29 729
|
||||
#define IDC_BINPOS30 730
|
||||
#define IDC_BINPOS31 731
|
||||
#define IDC_BINPOS32 732
|
||||
#define IDC_BINPOS33 733
|
||||
#define IDC_BINPOS34 734
|
||||
#define IDC_BINPOS35 735
|
||||
#define IDC_BINPOS36 736
|
||||
#define IDC_BINPOS37 737
|
||||
#define IDC_BINPOS38 738
|
||||
#define IDC_BINPOS39 739
|
||||
#define IDC_BINPOS40 740
|
||||
#define IDC_BINPOS41 741
|
||||
#define IDC_BINPOS42 742
|
||||
#define IDC_BINPOS43 743
|
||||
#define IDC_BINPOS44 744
|
||||
#define IDC_BINPOS45 745
|
||||
#define IDC_BINPOS46 746
|
||||
#define IDC_BINPOS47 747
|
||||
#define IDC_BINPOS48 748
|
||||
#define IDC_BINPOS49 749
|
||||
#define IDC_BINPOS50 750
|
||||
#define IDC_BINPOS51 751
|
||||
#define IDC_BINPOS52 752
|
||||
#define IDC_BINPOS53 753
|
||||
#define IDC_BINPOS54 754
|
||||
#define IDC_BINPOS55 755
|
||||
#define IDC_BINPOS56 756
|
||||
#define IDC_BINPOS57 757
|
||||
#define IDC_BINPOS58 758
|
||||
#define IDC_BINPOS59 759
|
||||
#define IDC_BINPOS60 760
|
||||
#define IDC_BINPOS61 761
|
||||
#define IDC_BINPOS62 762
|
||||
#define IDC_BINPOS63 763
|
||||
#define IDC_BINEDITEND 763
|
||||
|
||||
// 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
|
||||
#define IDS_ENGINESTR_FIRST 0
|
||||
#define IDS_ENGINESTR_MAX 200
|
||||
|
||||
#define IDS_ENGINESTR_FIRST 0
|
||||
#define IDS_ENGINESTR_MAX 200
|
||||
|
@@ -20,7 +20,7 @@
|
||||
#include "../CalculatorVector.h"
|
||||
#include "../ExpressionCommand.h"
|
||||
#include "RadixType.h"
|
||||
#include "History.h" // for History Collector
|
||||
#include "History.h" // for History Collector
|
||||
#include "CalcInput.h"
|
||||
#include "CalcUtils.h"
|
||||
#include "ICalcDisplay.h"
|
||||
@@ -31,11 +31,12 @@
|
||||
// The real exports follows later
|
||||
|
||||
// This is expected to be in same order as IDM_QWORD, IDM_DWORD etc.
|
||||
enum eNUM_WIDTH {
|
||||
QWORD_WIDTH, // Number width of 64 bits mode (default)
|
||||
DWORD_WIDTH, // Number width of 32 bits mode
|
||||
WORD_WIDTH, // Number width of 16 bits mode
|
||||
BYTE_WIDTH // Number width of 16 bits mode
|
||||
enum eNUM_WIDTH
|
||||
{
|
||||
QWORD_WIDTH, // Number width of 64 bits mode (default)
|
||||
DWORD_WIDTH, // Number width of 32 bits mode
|
||||
WORD_WIDTH, // Number width of 16 bits mode
|
||||
BYTE_WIDTH // Number width of 16 bits mode
|
||||
};
|
||||
typedef enum eNUM_WIDTH NUM_WIDTH;
|
||||
static constexpr size_t NUM_WIDTH_LENGTH = 4;
|
||||
@@ -45,62 +46,89 @@ namespace CalculationManager
|
||||
class IResourceProvider;
|
||||
}
|
||||
|
||||
namespace CalculatorUnitTests
|
||||
namespace CalculatorEngineTests
|
||||
{
|
||||
class CalcEngineTests;
|
||||
}
|
||||
|
||||
class CCalcEngine {
|
||||
class CCalcEngine
|
||||
{
|
||||
public:
|
||||
CCalcEngine(bool fPrecedence, bool fIntegerMode, CalculationManager::IResourceProvider* const pResourceProvider, __in_opt ICalcDisplay *pCalcDisplay, __in_opt std::shared_ptr<IHistoryDisplay> pHistoryDisplay);
|
||||
CCalcEngine(
|
||||
bool fPrecedence,
|
||||
bool fIntegerMode,
|
||||
CalculationManager::IResourceProvider* const pResourceProvider,
|
||||
__in_opt ICalcDisplay* pCalcDisplay,
|
||||
__in_opt std::shared_ptr<IHistoryDisplay> pHistoryDisplay);
|
||||
void ProcessCommand(OpCode wID);
|
||||
void DisplayError (uint32_t nError);
|
||||
void DisplayError(uint32_t nError);
|
||||
std::unique_ptr<CalcEngine::Rational> PersistedMemObject();
|
||||
void PersistedMemObject(CalcEngine::Rational const& memObject);
|
||||
bool FInErrorState() { return m_bError; }
|
||||
bool FInRecordingState() { return m_bRecord; }
|
||||
bool FInErrorState()
|
||||
{
|
||||
return m_bError;
|
||||
}
|
||||
bool FInRecordingState()
|
||||
{
|
||||
return m_bRecord;
|
||||
}
|
||||
void SettingsChanged();
|
||||
bool IsCurrentTooBigForTrig();
|
||||
int GetCurrentRadix();
|
||||
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 GetStringForDisplay(CalcEngine::Rational const& rat, uint32_t radix);
|
||||
void UpdateMaxIntDigits();
|
||||
wchar_t DecimalSeparator() const;
|
||||
|
||||
// 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.
|
||||
static std::wstring_view GetString(int ids) { return s_engineStrings[ids]; }
|
||||
static std::wstring_view OpCodeToString(int nOpCode) { return GetString(IdStrFromCmdId(nOpCode)); }
|
||||
static std::wstring_view GetString(int ids)
|
||||
{
|
||||
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);
|
||||
|
||||
private:
|
||||
bool m_fPrecedence;
|
||||
bool m_fIntegerMode; /* This is true if engine is explicitly called to be in integer mode. All bases are restricted to be in integers only */
|
||||
ICalcDisplay *m_pCalcDisplay;
|
||||
ICalcDisplay* m_pCalcDisplay;
|
||||
CalculationManager::IResourceProvider* const m_resourceProvider;
|
||||
int m_nOpCode; /* ID value of operation. */
|
||||
int m_nOpCode; /* ID value of operation. */
|
||||
int m_nPrevOpCode; // opcode which computed the number in m_currentVal. 0 if it is already bracketed or plain number or
|
||||
// if it hasn't yet been computed
|
||||
bool m_bChangeOp; /* Flag for changing operation. */
|
||||
bool m_bRecord; // Global mode: recording or displaying
|
||||
bool m_bSetCalcState; // Flag for setting the engine result state
|
||||
bool m_bChangeOp; /* Flag for changing operation. */
|
||||
bool m_bRecord; // Global mode: recording or displaying
|
||||
bool m_bSetCalcState; // Flag for setting the engine result state
|
||||
CalcEngine::CalcInput m_input; // Global calc input object for decimal strings
|
||||
eNUMOBJ_FMT m_nFE; /* Scientific notation conversion flag. */
|
||||
eNUMOBJ_FMT m_nFE; /* Scientific notation conversion flag. */
|
||||
CalcEngine::Rational m_maxTrigonometricNum;
|
||||
std::unique_ptr<CalcEngine::Rational> m_memoryValue; // Current memory value.
|
||||
|
||||
CalcEngine::Rational m_holdVal; // For holding the second operand in repetitive calculations ( pressing "=" continuously)
|
||||
|
||||
CalcEngine::Rational m_currentVal; // Currently displayed number used everywhere.
|
||||
CalcEngine::Rational m_lastVal; // Number before operation (left operand).
|
||||
std::array<CalcEngine::Rational, MAXPRECDEPTH> m_parenVals; // Holding array for parenthesis values.
|
||||
CalcEngine::Rational m_currentVal; // Currently displayed number used everywhere.
|
||||
CalcEngine::Rational m_lastVal; // Number before operation (left operand).
|
||||
std::array<CalcEngine::Rational, MAXPRECDEPTH> m_parenVals; // Holding array for parenthesis values.
|
||||
std::array<CalcEngine::Rational, MAXPRECDEPTH> m_precedenceVals; // Holding array for precedence values.
|
||||
bool m_bError; // Error flag.
|
||||
bool m_bInv; // Inverse on/off flag.
|
||||
bool m_bNoPrevEqu; /* Flag for previous equals. */
|
||||
bool m_bError; // Error flag.
|
||||
bool m_bInv; // Inverse on/off flag.
|
||||
bool m_bNoPrevEqu; /* Flag for previous equals. */
|
||||
|
||||
uint32_t m_radix;
|
||||
int32_t m_precision;
|
||||
@@ -109,21 +137,21 @@ private:
|
||||
|
||||
std::wstring m_numberString;
|
||||
|
||||
int m_nTempCom; /* Holding place for the last command. */
|
||||
int m_openParenCount; // Number of open parentheses.
|
||||
std::array<int, MAXPRECDEPTH> m_nOp; /* Holding array for parenthesis operations. */
|
||||
std::array<int, MAXPRECDEPTH> m_nPrecOp; /* Holding array for precedence operations. */
|
||||
size_t m_precedenceOpCount; /* Current number of precedence ops in holding. */
|
||||
int m_nLastCom; // Last command entered.
|
||||
ANGLE_TYPE m_angletype; // Current Angle type when in dec mode. one of deg, rad or grad
|
||||
NUM_WIDTH m_numwidth; // one of qword, dword, word or byte mode.
|
||||
int32_t m_dwWordBitWidth; // # of bits in currently selected word size
|
||||
int m_nTempCom; /* Holding place for the last command. */
|
||||
size_t m_openParenCount; // Number of open parentheses.
|
||||
std::array<int, MAXPRECDEPTH> m_nOp; /* Holding array for parenthesis operations. */
|
||||
std::array<int, MAXPRECDEPTH> m_nPrecOp; /* Holding array for precedence operations. */
|
||||
size_t m_precedenceOpCount; /* Current number of precedence ops in holding. */
|
||||
int m_nLastCom; // Last command entered.
|
||||
ANGLE_TYPE m_angletype; // Current Angle type when in dec mode. one of deg, rad or grad
|
||||
NUM_WIDTH m_numwidth; // one of qword, dword, word or byte mode.
|
||||
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
|
||||
|
||||
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
|
||||
static std::array<std::wstring, CSTRINGSENGMAX> s_engineStrings; // the string table shared across all instances
|
||||
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
|
||||
static std::unordered_map<std::wstring, std::wstring> s_engineStrings; // the string table shared across all instances
|
||||
wchar_t m_decimalSeparator;
|
||||
wchar_t m_groupSeparator;
|
||||
|
||||
@@ -142,16 +170,18 @@ private:
|
||||
CalcEngine::Rational DoOperation(int operation, CalcEngine::Rational const& lhs, CalcEngine::Rational const& rhs);
|
||||
void SetRadixTypeAndNumWidth(RADIX_TYPE radixtype, NUM_WIDTH numwidth);
|
||||
int32_t DwWordBitWidthFromeNumWidth(NUM_WIDTH numwidth);
|
||||
uint32_t NRadixFromRadixType( RADIX_TYPE radixtype);
|
||||
uint32_t NRadixFromRadixType(RADIX_TYPE radixtype);
|
||||
|
||||
bool TryToggleBit(CalcEngine::Rational& rat, uint32_t wbitno);
|
||||
void CheckAndAddLastBinOpToHistory(bool addToHistory = true);
|
||||
int IdcSetAngleTypeDecMode(int idc);
|
||||
|
||||
void InitChopNumbers();
|
||||
|
||||
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);
|
||||
std::wstring GroupDigits(std::wstring_view delimiter, std::vector<uint32_t> const& grouping, std::wstring_view displayString, bool isNumNegative = false);
|
||||
@@ -160,5 +190,5 @@ private:
|
||||
static void ChangeBaseConstants(uint32_t radix, int maxIntDigits, int32_t precision);
|
||||
void BaseOrPrecisionChanged();
|
||||
|
||||
friend class CalculatorUnitTests::CalcEngineTests;
|
||||
friend class CalculatorEngineTests::CalcEngineTests;
|
||||
};
|
||||
|
@@ -13,16 +13,26 @@ namespace CalcEngine
|
||||
class CalcNumSec
|
||||
{
|
||||
public:
|
||||
CalcNumSec() :
|
||||
value(),
|
||||
m_isNegative(false)
|
||||
{}
|
||||
CalcNumSec()
|
||||
: value()
|
||||
, m_isNegative(false)
|
||||
{
|
||||
}
|
||||
|
||||
void Clear();
|
||||
bool IsEmpty() { return value.empty(); }
|
||||
bool IsEmpty()
|
||||
{
|
||||
return value.empty();
|
||||
}
|
||||
|
||||
bool IsNegative() { return m_isNegative; }
|
||||
void IsNegative(bool isNegative) { m_isNegative = isNegative; }
|
||||
bool IsNegative()
|
||||
{
|
||||
return m_isNegative;
|
||||
}
|
||||
void IsNegative(bool isNegative)
|
||||
{
|
||||
m_isNegative = isNegative;
|
||||
}
|
||||
|
||||
std::wstring value;
|
||||
|
||||
@@ -33,17 +43,20 @@ namespace CalcEngine
|
||||
class CalcInput
|
||||
{
|
||||
public:
|
||||
CalcInput() : CalcInput(L'.')
|
||||
{}
|
||||
CalcInput()
|
||||
: CalcInput(L'.')
|
||||
{
|
||||
}
|
||||
|
||||
CalcInput(wchar_t decSymbol) :
|
||||
m_hasExponent(false),
|
||||
m_hasDecimal(false),
|
||||
m_decPtIndex(0),
|
||||
m_decSymbol(decSymbol),
|
||||
m_base(),
|
||||
m_exponent()
|
||||
{}
|
||||
CalcInput(wchar_t decSymbol)
|
||||
: m_hasExponent(false)
|
||||
, m_hasDecimal(false)
|
||||
, m_decPtIndex(0)
|
||||
, m_decSymbol(decSymbol)
|
||||
, m_base()
|
||||
, m_exponent()
|
||||
{
|
||||
}
|
||||
|
||||
void Clear();
|
||||
bool TryToggleSign(bool isIntegerMode, std::wstring_view maxNumStr);
|
||||
|
@@ -13,327 +13,284 @@
|
||||
* 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
|
||||
// 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
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
|
||||
#define IDS_FRAC IDS_FNSZFIRST
|
||||
|
||||
#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
|
||||
inline constexpr auto IDS_ERRORS_FIRST = 99;
|
||||
|
||||
// This is the list of error strings corresponding to SCERR_DIVIDEZERO..
|
||||
|
||||
#define IDS_DIVBYZERO IDS_ERRORS_FIRST
|
||||
#define IDS_DOMAIN IDS_ERRORS_FIRST+1
|
||||
#define IDS_UNDEFINED IDS_ERRORS_FIRST+2
|
||||
#define IDS_POS_INFINITY IDS_ERRORS_FIRST+3
|
||||
#define IDS_NEG_INFINITY IDS_ERRORS_FIRST+4
|
||||
#define IDS_NOMEM IDS_ERRORS_FIRST+6
|
||||
#define IDS_TOOMANY IDS_ERRORS_FIRST+7
|
||||
#define IDS_OVERFLOW IDS_ERRORS_FIRST+8
|
||||
#define IDS_NORESULT IDS_ERRORS_FIRST+9
|
||||
#define IDS_INSUFFICIENT_DATA IDS_ERRORS_FIRST+10
|
||||
inline constexpr auto IDS_DIVBYZERO = IDS_ERRORS_FIRST;
|
||||
inline constexpr auto IDS_DOMAIN = IDS_ERRORS_FIRST + 1;
|
||||
inline constexpr auto IDS_UNDEFINED = IDS_ERRORS_FIRST + 2;
|
||||
inline constexpr auto IDS_POS_INFINITY = IDS_ERRORS_FIRST + 3;
|
||||
inline constexpr auto IDS_NEG_INFINITY = IDS_ERRORS_FIRST + 4;
|
||||
inline constexpr auto IDS_NOMEM = IDS_ERRORS_FIRST + 6;
|
||||
inline constexpr auto IDS_TOOMANY = IDS_ERRORS_FIRST + 7;
|
||||
inline constexpr auto IDS_OVERFLOW = IDS_ERRORS_FIRST + 8;
|
||||
inline constexpr auto IDS_NORESULT = IDS_ERRORS_FIRST + 9;
|
||||
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
|
||||
#define IDS_ERR_UNK_CH CSTRINGSENGMAX+1
|
||||
#define IDS_ERR_UNK_FN CSTRINGSENGMAX+2
|
||||
#define IDS_ERR_UNEX_NUM CSTRINGSENGMAX+3
|
||||
#define IDS_ERR_UNEX_CH CSTRINGSENGMAX+4
|
||||
#define IDS_ERR_UNEX_SZ CSTRINGSENGMAX+5
|
||||
#define IDS_ERR_MISMATCH_CLOSE CSTRINGSENGMAX+6
|
||||
#define IDS_ERR_UNEX_END CSTRINGSENGMAX+7
|
||||
#define IDS_ERR_SG_INV_ERROR CSTRINGSENGMAX+8
|
||||
#define IDS_ERR_INPUT_OVERFLOW CSTRINGSENGMAX+9
|
||||
#define IDS_ERR_OUTPUT_OVERFLOW CSTRINGSENGMAX+10
|
||||
inline constexpr auto IDS_ERR_UNK_CH = CSTRINGSENGMAX + 1;
|
||||
inline constexpr auto IDS_ERR_UNK_FN = CSTRINGSENGMAX + 2;
|
||||
inline constexpr auto IDS_ERR_UNEX_NUM = CSTRINGSENGMAX + 3;
|
||||
inline constexpr auto IDS_ERR_UNEX_CH = CSTRINGSENGMAX + 4;
|
||||
inline constexpr auto IDS_ERR_UNEX_SZ = CSTRINGSENGMAX + 5;
|
||||
inline constexpr auto IDS_ERR_MISMATCH_CLOSE = CSTRINGSENGMAX + 6;
|
||||
inline constexpr auto IDS_ERR_UNEX_END = CSTRINGSENGMAX + 7;
|
||||
inline constexpr auto IDS_ERR_SG_INV_ERROR = CSTRINGSENGMAX + 8;
|
||||
inline constexpr auto IDS_ERR_INPUT_OVERFLOW = CSTRINGSENGMAX + 9;
|
||||
inline constexpr auto IDS_ERR_OUTPUT_OVERFLOW = CSTRINGSENGMAX + 10;
|
||||
|
||||
|
||||
#define SIDS_PLUS_MINUS L"0"
|
||||
#define SIDS_CLEAR L"1"
|
||||
#define SIDS_CE L"2"
|
||||
#define SIDS_BACKSPACE L"3"
|
||||
#define SIDS_DECIMAL_SEPARATOR L"4"
|
||||
#define SIDS_EMPTY_STRING L"5"
|
||||
#define SIDS_AND L"6"
|
||||
#define SIDS_OR L"7"
|
||||
#define SIDS_XOR L"8"
|
||||
#define SIDS_LSH L"9"
|
||||
#define SIDS_RSH L"10"
|
||||
#define SIDS_DIVIDE L"11"
|
||||
#define SIDS_MULTIPLY L"12"
|
||||
#define SIDS_PLUS L"13"
|
||||
#define SIDS_MINUS L"14"
|
||||
#define SIDS_MOD L"15"
|
||||
#define SIDS_YROOT L"16"
|
||||
#define SIDS_POW_HAT L"17"
|
||||
#define SIDS_INT L"18"
|
||||
#define SIDS_ROL L"19"
|
||||
#define SIDS_ROR L"20"
|
||||
#define SIDS_NOT L"21"
|
||||
#define SIDS_SIN L"22"
|
||||
#define SIDS_COS L"23"
|
||||
#define SIDS_TAN L"24"
|
||||
#define SIDS_SINH L"25"
|
||||
#define SIDS_COSH L"26"
|
||||
#define SIDS_TANH L"27"
|
||||
#define SIDS_LN L"28"
|
||||
#define SIDS_LOG L"29"
|
||||
#define SIDS_SQRT L"30"
|
||||
#define SIDS_XPOW2 L"31"
|
||||
#define SIDS_XPOW3 L"32"
|
||||
#define SIDS_NFACTORIAL L"33"
|
||||
#define SIDS_RECIPROCAL L"34"
|
||||
#define SIDS_DMS L"35"
|
||||
#define SIDS_CUBEROOT L"36"
|
||||
#define SIDS_POWTEN L"37"
|
||||
#define SIDS_PERCENT L"38"
|
||||
#define SIDS_SCIENTIFIC_NOTATION L"39"
|
||||
#define SIDS_PI L"40"
|
||||
#define SIDS_EQUAL L"41"
|
||||
#define SIDS_MC L"42"
|
||||
#define SIDS_MR L"43"
|
||||
#define SIDS_MS L"44"
|
||||
#define SIDS_MPLUS L"45"
|
||||
#define SIDS_MMINUS L"46"
|
||||
#define SIDS_EXP L"47"
|
||||
#define SIDS_OPEN_PAREN L"48"
|
||||
#define SIDS_CLOSE_PAREN L"49"
|
||||
#define SIDS_0 L"50"
|
||||
#define SIDS_1 L"51"
|
||||
#define SIDS_2 L"52"
|
||||
#define SIDS_3 L"53"
|
||||
#define SIDS_4 L"54"
|
||||
#define SIDS_5 L"55"
|
||||
#define SIDS_6 L"56"
|
||||
#define SIDS_7 L"57"
|
||||
#define SIDS_8 L"58"
|
||||
#define SIDS_9 L"59"
|
||||
#define SIDS_A L"60"
|
||||
#define SIDS_B L"61"
|
||||
#define SIDS_C L"62"
|
||||
#define SIDS_D L"63"
|
||||
#define SIDS_E L"64"
|
||||
#define SIDS_F L"65"
|
||||
#define SIDS_FRAC L"66"
|
||||
#define SIDS_SIND L"67"
|
||||
#define SIDS_COSD L"68"
|
||||
#define SIDS_TAND L"69"
|
||||
#define SIDS_ASIND L"70"
|
||||
#define SIDS_ACOSD L"71"
|
||||
#define SIDS_ATAND L"72"
|
||||
#define SIDS_SINR L"73"
|
||||
#define SIDS_COSR L"74"
|
||||
#define SIDS_TANR L"75"
|
||||
#define SIDS_ASINR L"76"
|
||||
#define SIDS_ACOSR L"77"
|
||||
#define SIDS_ATANR L"78"
|
||||
#define SIDS_SING L"79"
|
||||
#define SIDS_COSG L"80"
|
||||
#define SIDS_TANG L"81"
|
||||
#define SIDS_ASING L"82"
|
||||
#define SIDS_ACOSG L"83"
|
||||
#define SIDS_ATANG L"84"
|
||||
#define SIDS_ASINH L"85"
|
||||
#define SIDS_ACOSH L"86"
|
||||
#define SIDS_ATANH L"87"
|
||||
#define SIDS_POWE L"88"
|
||||
#define SIDS_POWTEN2 L"89"
|
||||
#define SIDS_SQRT2 L"90"
|
||||
#define SIDS_SQR L"91"
|
||||
#define SIDS_CUBE L"92"
|
||||
#define SIDS_CUBERT L"93"
|
||||
#define SIDS_FACT L"94"
|
||||
#define SIDS_RECIPROC L"95"
|
||||
#define SIDS_DEGREES L"96"
|
||||
#define SIDS_NEGATE L"97"
|
||||
#define SIDS_RSH2 L"98"
|
||||
#define SIDS_DIVIDEBYZERO L"99"
|
||||
#define SIDS_DOMAIN L"100"
|
||||
#define SIDS_UNDEFINED L"101"
|
||||
#define SIDS_POS_INFINITY L"102"
|
||||
#define SIDS_NEG_INFINITY L"103"
|
||||
#define SIDS_ABORTED L"104"
|
||||
#define SIDS_NOMEM L"105"
|
||||
#define SIDS_TOOMANY L"106"
|
||||
#define SIDS_OVERFLOW L"107"
|
||||
#define SIDS_NORESULT L"108"
|
||||
#define SIDS_INSUFFICIENT_DATA L"109"
|
||||
// Resource keys for CEngineStrings.resw
|
||||
inline constexpr auto SIDS_PLUS_MINUS = L"0";
|
||||
inline constexpr auto SIDS_CLEAR = L"1";
|
||||
inline constexpr auto SIDS_CE = L"2";
|
||||
inline constexpr auto SIDS_BACKSPACE = L"3";
|
||||
inline constexpr auto SIDS_DECIMAL_SEPARATOR = L"4";
|
||||
inline constexpr auto SIDS_EMPTY_STRING = L"5";
|
||||
inline constexpr auto SIDS_AND = L"6";
|
||||
inline constexpr auto SIDS_OR = L"7";
|
||||
inline constexpr auto SIDS_XOR = L"8";
|
||||
inline constexpr auto SIDS_LSH = L"9";
|
||||
inline constexpr auto SIDS_RSH = L"10";
|
||||
inline constexpr auto SIDS_DIVIDE = L"11";
|
||||
inline constexpr auto SIDS_MULTIPLY = L"12";
|
||||
inline constexpr auto SIDS_PLUS = L"13";
|
||||
inline constexpr auto SIDS_MINUS = L"14";
|
||||
inline constexpr auto SIDS_MOD = L"15";
|
||||
inline constexpr auto SIDS_YROOT = L"16";
|
||||
inline constexpr auto SIDS_POW_HAT = L"17";
|
||||
inline constexpr auto SIDS_INT = L"18";
|
||||
inline constexpr auto SIDS_ROL = L"19";
|
||||
inline constexpr auto SIDS_ROR = L"20";
|
||||
inline constexpr auto SIDS_NOT = L"21";
|
||||
inline constexpr auto SIDS_SIN = L"22";
|
||||
inline constexpr auto SIDS_COS = L"23";
|
||||
inline constexpr auto SIDS_TAN = L"24";
|
||||
inline constexpr auto SIDS_SINH = L"25";
|
||||
inline constexpr auto SIDS_COSH = L"26";
|
||||
inline constexpr auto SIDS_TANH = L"27";
|
||||
inline constexpr auto SIDS_LN = L"28";
|
||||
inline constexpr auto SIDS_LOG = L"29";
|
||||
inline constexpr auto SIDS_SQRT = L"30";
|
||||
inline constexpr auto SIDS_XPOW2 = L"31";
|
||||
inline constexpr auto SIDS_XPOW3 = L"32";
|
||||
inline constexpr auto SIDS_NFACTORIAL = L"33";
|
||||
inline constexpr auto SIDS_RECIPROCAL = L"34";
|
||||
inline constexpr auto SIDS_DMS = L"35";
|
||||
inline constexpr auto SIDS_CUBEROOT = L"36";
|
||||
inline constexpr auto SIDS_POWTEN = L"37";
|
||||
inline constexpr auto SIDS_PERCENT = L"38";
|
||||
inline constexpr auto SIDS_SCIENTIFIC_NOTATION = L"39";
|
||||
inline constexpr auto SIDS_PI = L"40";
|
||||
inline constexpr auto SIDS_EQUAL = L"41";
|
||||
inline constexpr auto SIDS_MC = L"42";
|
||||
inline constexpr auto SIDS_MR = L"43";
|
||||
inline constexpr auto SIDS_MS = L"44";
|
||||
inline constexpr auto SIDS_MPLUS = L"45";
|
||||
inline constexpr auto SIDS_MMINUS = L"46";
|
||||
inline constexpr auto SIDS_EXP = L"47";
|
||||
inline constexpr auto SIDS_OPEN_PAREN = L"48";
|
||||
inline constexpr auto SIDS_CLOSE_PAREN = L"49";
|
||||
inline constexpr auto SIDS_0 = L"50";
|
||||
inline constexpr auto SIDS_1 = L"51";
|
||||
inline constexpr auto SIDS_2 = L"52";
|
||||
inline constexpr auto SIDS_3 = L"53";
|
||||
inline constexpr auto SIDS_4 = L"54";
|
||||
inline constexpr auto SIDS_5 = L"55";
|
||||
inline constexpr auto SIDS_6 = L"56";
|
||||
inline constexpr auto SIDS_7 = L"57";
|
||||
inline constexpr auto SIDS_8 = L"58";
|
||||
inline constexpr auto SIDS_9 = L"59";
|
||||
inline constexpr auto SIDS_A = L"60";
|
||||
inline constexpr auto SIDS_B = L"61";
|
||||
inline constexpr auto SIDS_C = L"62";
|
||||
inline constexpr auto SIDS_D = L"63";
|
||||
inline constexpr auto SIDS_E = L"64";
|
||||
inline constexpr auto SIDS_F = L"65";
|
||||
inline constexpr auto SIDS_FRAC = L"66";
|
||||
inline constexpr auto SIDS_SIND = L"67";
|
||||
inline constexpr auto SIDS_COSD = L"68";
|
||||
inline constexpr auto SIDS_TAND = L"69";
|
||||
inline constexpr auto SIDS_ASIND = L"70";
|
||||
inline constexpr auto SIDS_ACOSD = L"71";
|
||||
inline constexpr auto SIDS_ATAND = L"72";
|
||||
inline constexpr auto SIDS_SINR = L"73";
|
||||
inline constexpr auto SIDS_COSR = L"74";
|
||||
inline constexpr auto SIDS_TANR = L"75";
|
||||
inline constexpr auto SIDS_ASINR = L"76";
|
||||
inline constexpr auto SIDS_ACOSR = L"77";
|
||||
inline constexpr auto SIDS_ATANR = L"78";
|
||||
inline constexpr auto SIDS_SING = L"79";
|
||||
inline constexpr auto SIDS_COSG = L"80";
|
||||
inline constexpr auto SIDS_TANG = L"81";
|
||||
inline constexpr auto SIDS_ASING = L"82";
|
||||
inline constexpr auto SIDS_ACOSG = L"83";
|
||||
inline constexpr auto SIDS_ATANG = L"84";
|
||||
inline constexpr auto SIDS_ASINH = L"85";
|
||||
inline constexpr auto SIDS_ACOSH = L"86";
|
||||
inline constexpr auto SIDS_ATANH = L"87";
|
||||
inline constexpr auto SIDS_POWE = L"88";
|
||||
inline constexpr auto SIDS_POWTEN2 = L"89";
|
||||
inline constexpr auto SIDS_SQRT2 = L"90";
|
||||
inline constexpr auto SIDS_SQR = L"91";
|
||||
inline constexpr auto SIDS_CUBE = L"92";
|
||||
inline constexpr auto SIDS_CUBERT = L"93";
|
||||
inline constexpr auto SIDS_FACT = L"94";
|
||||
inline constexpr auto SIDS_RECIPROC = L"95";
|
||||
inline constexpr auto SIDS_DEGREES = L"96";
|
||||
inline constexpr auto SIDS_NEGATE = L"97";
|
||||
inline constexpr auto SIDS_RSH2 = L"98";
|
||||
inline constexpr auto SIDS_DIVIDEBYZERO = L"99";
|
||||
inline constexpr auto SIDS_DOMAIN = L"100";
|
||||
inline constexpr auto SIDS_UNDEFINED = L"101";
|
||||
inline constexpr auto SIDS_POS_INFINITY = L"102";
|
||||
inline constexpr auto SIDS_NEG_INFINITY = L"103";
|
||||
inline constexpr auto SIDS_ABORTED = L"104";
|
||||
inline constexpr auto SIDS_NOMEM = L"105";
|
||||
inline constexpr auto SIDS_TOOMANY = L"106";
|
||||
inline constexpr auto SIDS_OVERFLOW = L"107";
|
||||
inline constexpr auto SIDS_NORESULT = L"108";
|
||||
inline constexpr auto SIDS_INSUFFICIENT_DATA = L"109";
|
||||
// 110 is skipped by CSTRINGSENGMAX
|
||||
#define SIDS_ERR_UNK_CH L"111"
|
||||
#define SIDS_ERR_UNK_FN L"112"
|
||||
#define SIDS_ERR_UNEX_NUM L"113"
|
||||
#define SIDS_ERR_UNEX_CH L"114"
|
||||
#define SIDS_ERR_UNEX_SZ L"115"
|
||||
#define SIDS_ERR_MISMATCH_CLOSE L"116"
|
||||
#define SIDS_ERR_UNEX_END L"117"
|
||||
#define SIDS_ERR_SG_INV_ERROR L"118"
|
||||
#define SIDS_ERR_INPUT_OVERFLOW L"119"
|
||||
#define SIDS_ERR_OUTPUT_OVERFLOW L"120"
|
||||
inline constexpr auto SIDS_ERR_UNK_CH = L"111";
|
||||
inline constexpr auto SIDS_ERR_UNK_FN = L"112";
|
||||
inline constexpr auto SIDS_ERR_UNEX_NUM = L"113";
|
||||
inline constexpr auto SIDS_ERR_UNEX_CH = L"114";
|
||||
inline constexpr auto SIDS_ERR_UNEX_SZ = L"115";
|
||||
inline constexpr auto SIDS_ERR_MISMATCH_CLOSE = L"116";
|
||||
inline constexpr auto SIDS_ERR_UNEX_END = L"117";
|
||||
inline constexpr auto SIDS_ERR_SG_INV_ERROR = L"118";
|
||||
inline constexpr auto SIDS_ERR_INPUT_OVERFLOW = L"119";
|
||||
inline constexpr auto SIDS_ERR_OUTPUT_OVERFLOW = L"120";
|
||||
|
||||
__declspec(selectany) std::wstring g_sids[] =
|
||||
{
|
||||
std::wstring(SIDS_PLUS_MINUS),
|
||||
std::wstring(SIDS_C),
|
||||
std::wstring(SIDS_CE),
|
||||
std::wstring(SIDS_BACKSPACE),
|
||||
std::wstring(SIDS_DECIMAL_SEPARATOR),
|
||||
std::wstring(SIDS_EMPTY_STRING),
|
||||
std::wstring(SIDS_AND),
|
||||
std::wstring(SIDS_OR),
|
||||
std::wstring(SIDS_XOR),
|
||||
std::wstring(SIDS_LSH),
|
||||
std::wstring(SIDS_RSH),
|
||||
std::wstring(SIDS_DIVIDE),
|
||||
std::wstring(SIDS_MULTIPLY),
|
||||
std::wstring(SIDS_PLUS),
|
||||
std::wstring(SIDS_MINUS),
|
||||
std::wstring(SIDS_MOD),
|
||||
std::wstring(SIDS_YROOT),
|
||||
std::wstring(SIDS_POW_HAT),
|
||||
std::wstring(SIDS_INT),
|
||||
std::wstring(SIDS_ROL),
|
||||
std::wstring(SIDS_ROR),
|
||||
std::wstring(SIDS_NOT),
|
||||
std::wstring(SIDS_SIN),
|
||||
std::wstring(SIDS_COS),
|
||||
std::wstring(SIDS_TAN),
|
||||
std::wstring(SIDS_SINH),
|
||||
std::wstring(SIDS_COSH),
|
||||
std::wstring(SIDS_TANH),
|
||||
std::wstring(SIDS_LN),
|
||||
std::wstring(SIDS_LOG),
|
||||
std::wstring(SIDS_SQRT),
|
||||
std::wstring(SIDS_XPOW2),
|
||||
std::wstring(SIDS_XPOW3),
|
||||
std::wstring(SIDS_NFACTORIAL),
|
||||
std::wstring(SIDS_RECIPROCAL),
|
||||
std::wstring(SIDS_DMS),
|
||||
std::wstring(SIDS_CUBEROOT),
|
||||
std::wstring(SIDS_POWTEN),
|
||||
std::wstring(SIDS_PERCENT),
|
||||
std::wstring(SIDS_SCIENTIFIC_NOTATION),
|
||||
std::wstring(SIDS_PI),
|
||||
std::wstring(SIDS_EQUAL),
|
||||
std::wstring(SIDS_MC),
|
||||
std::wstring(SIDS_MR),
|
||||
std::wstring(SIDS_MS),
|
||||
std::wstring(SIDS_MPLUS),
|
||||
std::wstring(SIDS_MMINUS),
|
||||
std::wstring(SIDS_EXP),
|
||||
std::wstring(SIDS_OPEN_PAREN),
|
||||
std::wstring(SIDS_CLOSE_PAREN),
|
||||
std::wstring(SIDS_0),
|
||||
std::wstring(SIDS_1),
|
||||
std::wstring(SIDS_2),
|
||||
std::wstring(SIDS_3),
|
||||
std::wstring(SIDS_4),
|
||||
std::wstring(SIDS_5),
|
||||
std::wstring(SIDS_6),
|
||||
std::wstring(SIDS_7),
|
||||
std::wstring(SIDS_8),
|
||||
std::wstring(SIDS_9),
|
||||
std::wstring(SIDS_A),
|
||||
std::wstring(SIDS_B),
|
||||
std::wstring(SIDS_C),
|
||||
std::wstring(SIDS_D),
|
||||
std::wstring(SIDS_E),
|
||||
std::wstring(SIDS_F),
|
||||
std::wstring(SIDS_FRAC),
|
||||
std::wstring(SIDS_SIND),
|
||||
std::wstring(SIDS_COSD),
|
||||
std::wstring(SIDS_TAND),
|
||||
std::wstring(SIDS_ASIND),
|
||||
std::wstring(SIDS_ACOSD),
|
||||
std::wstring(SIDS_ATAND),
|
||||
std::wstring(SIDS_SINR),
|
||||
std::wstring(SIDS_COSR),
|
||||
std::wstring(SIDS_TANR),
|
||||
std::wstring(SIDS_ASINR),
|
||||
std::wstring(SIDS_ACOSR),
|
||||
std::wstring(SIDS_ATANR),
|
||||
std::wstring(SIDS_SING),
|
||||
std::wstring(SIDS_COSG),
|
||||
std::wstring(SIDS_TANG),
|
||||
std::wstring(SIDS_ASING),
|
||||
std::wstring(SIDS_ACOSG),
|
||||
std::wstring(SIDS_ATANG),
|
||||
std::wstring(SIDS_ASINH),
|
||||
std::wstring(SIDS_ACOSH),
|
||||
std::wstring(SIDS_ATANH),
|
||||
std::wstring(SIDS_POWE),
|
||||
std::wstring(SIDS_POWTEN2),
|
||||
std::wstring(SIDS_SQRT2),
|
||||
std::wstring(SIDS_SQR),
|
||||
std::wstring(SIDS_CUBE),
|
||||
std::wstring(SIDS_CUBERT),
|
||||
std::wstring(SIDS_FACT),
|
||||
std::wstring(SIDS_RECIPROC),
|
||||
std::wstring(SIDS_DEGREES),
|
||||
std::wstring(SIDS_NEGATE),
|
||||
std::wstring(SIDS_RSH),
|
||||
std::wstring(SIDS_DIVIDEBYZERO),
|
||||
std::wstring(SIDS_DOMAIN),
|
||||
std::wstring(SIDS_UNDEFINED),
|
||||
std::wstring(SIDS_POS_INFINITY),
|
||||
std::wstring(SIDS_NEG_INFINITY),
|
||||
std::wstring(SIDS_ABORTED),
|
||||
std::wstring(SIDS_NOMEM),
|
||||
std::wstring(SIDS_TOOMANY),
|
||||
std::wstring(SIDS_OVERFLOW),
|
||||
std::wstring(SIDS_NORESULT),
|
||||
std::wstring(SIDS_INSUFFICIENT_DATA),
|
||||
std::wstring(SIDS_ERR_UNK_CH),
|
||||
std::wstring(SIDS_ERR_UNK_FN),
|
||||
std::wstring(SIDS_ERR_UNEX_NUM),
|
||||
std::wstring(SIDS_ERR_UNEX_CH),
|
||||
std::wstring(SIDS_ERR_UNEX_SZ),
|
||||
std::wstring(SIDS_ERR_MISMATCH_CLOSE),
|
||||
std::wstring(SIDS_ERR_UNEX_END),
|
||||
std::wstring(SIDS_ERR_SG_INV_ERROR),
|
||||
std::wstring(SIDS_ERR_INPUT_OVERFLOW),
|
||||
std::wstring(SIDS_ERR_OUTPUT_OVERFLOW)
|
||||
};
|
||||
// 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,
|
||||
SIDS_C,
|
||||
SIDS_CE,
|
||||
SIDS_BACKSPACE,
|
||||
SIDS_DECIMAL_SEPARATOR,
|
||||
SIDS_EMPTY_STRING,
|
||||
SIDS_AND,
|
||||
SIDS_OR,
|
||||
SIDS_XOR,
|
||||
SIDS_LSH,
|
||||
SIDS_RSH,
|
||||
SIDS_DIVIDE,
|
||||
SIDS_MULTIPLY,
|
||||
SIDS_PLUS,
|
||||
SIDS_MINUS,
|
||||
SIDS_MOD,
|
||||
SIDS_YROOT,
|
||||
SIDS_POW_HAT,
|
||||
SIDS_INT,
|
||||
SIDS_ROL,
|
||||
SIDS_ROR,
|
||||
SIDS_NOT,
|
||||
SIDS_SIN,
|
||||
SIDS_COS,
|
||||
SIDS_TAN,
|
||||
SIDS_SINH,
|
||||
SIDS_COSH,
|
||||
SIDS_TANH,
|
||||
SIDS_LN,
|
||||
SIDS_LOG,
|
||||
SIDS_SQRT,
|
||||
SIDS_XPOW2,
|
||||
SIDS_XPOW3,
|
||||
SIDS_NFACTORIAL,
|
||||
SIDS_RECIPROCAL,
|
||||
SIDS_DMS,
|
||||
SIDS_CUBEROOT,
|
||||
SIDS_POWTEN,
|
||||
SIDS_PERCENT,
|
||||
SIDS_SCIENTIFIC_NOTATION,
|
||||
SIDS_PI,
|
||||
SIDS_EQUAL,
|
||||
SIDS_MC,
|
||||
SIDS_MR,
|
||||
SIDS_MS,
|
||||
SIDS_MPLUS,
|
||||
SIDS_MMINUS,
|
||||
SIDS_EXP,
|
||||
SIDS_OPEN_PAREN,
|
||||
SIDS_CLOSE_PAREN,
|
||||
SIDS_0,
|
||||
SIDS_1,
|
||||
SIDS_2,
|
||||
SIDS_3,
|
||||
SIDS_4,
|
||||
SIDS_5,
|
||||
SIDS_6,
|
||||
SIDS_7,
|
||||
SIDS_8,
|
||||
SIDS_9,
|
||||
SIDS_A,
|
||||
SIDS_B,
|
||||
SIDS_C,
|
||||
SIDS_D,
|
||||
SIDS_E,
|
||||
SIDS_F,
|
||||
SIDS_FRAC,
|
||||
SIDS_SIND,
|
||||
SIDS_COSD,
|
||||
SIDS_TAND,
|
||||
SIDS_ASIND,
|
||||
SIDS_ACOSD,
|
||||
SIDS_ATAND,
|
||||
SIDS_SINR,
|
||||
SIDS_COSR,
|
||||
SIDS_TANR,
|
||||
SIDS_ASINR,
|
||||
SIDS_ACOSR,
|
||||
SIDS_ATANR,
|
||||
SIDS_SING,
|
||||
SIDS_COSG,
|
||||
SIDS_TANG,
|
||||
SIDS_ASING,
|
||||
SIDS_ACOSG,
|
||||
SIDS_ATANG,
|
||||
SIDS_ASINH,
|
||||
SIDS_ACOSH,
|
||||
SIDS_ATANH,
|
||||
SIDS_POWE,
|
||||
SIDS_POWTEN2,
|
||||
SIDS_SQRT2,
|
||||
SIDS_SQR,
|
||||
SIDS_CUBE,
|
||||
SIDS_CUBERT,
|
||||
SIDS_FACT,
|
||||
SIDS_RECIPROC,
|
||||
SIDS_DEGREES,
|
||||
SIDS_NEGATE,
|
||||
SIDS_RSH,
|
||||
SIDS_DIVIDEBYZERO,
|
||||
SIDS_DOMAIN,
|
||||
SIDS_UNDEFINED,
|
||||
SIDS_POS_INFINITY,
|
||||
SIDS_NEG_INFINITY,
|
||||
SIDS_ABORTED,
|
||||
SIDS_NOMEM,
|
||||
SIDS_TOOMANY,
|
||||
SIDS_OVERFLOW,
|
||||
SIDS_NORESULT,
|
||||
SIDS_INSUFFICIENT_DATA,
|
||||
SIDS_ERR_UNK_CH,
|
||||
SIDS_ERR_UNK_FN,
|
||||
SIDS_ERR_UNEX_NUM,
|
||||
SIDS_ERR_UNEX_CH,
|
||||
SIDS_ERR_UNEX_SZ,
|
||||
SIDS_ERR_MISMATCH_CLOSE,
|
||||
SIDS_ERR_UNEX_END,
|
||||
SIDS_ERR_SG_INV_ERROR,
|
||||
SIDS_ERR_INPUT_OVERFLOW,
|
||||
SIDS_ERR_OUTPUT_OVERFLOW };
|
||||
|
@@ -3,6 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include "ICalcDisplay.h"
|
||||
#include "IHistoryDisplay.h"
|
||||
#include "Rational.h"
|
||||
@@ -13,9 +14,10 @@ static constexpr size_t MAXPRECDEPTH = 25;
|
||||
// Helper class really a internal class to CCalcEngine, to accumulate each history line of text by collecting the
|
||||
// operands, operator, unary operator etc. Since it is a separate entity, it can be unit tested on its own but does
|
||||
// rely on CCalcEngine calling it in appropriate order.
|
||||
class CHistoryCollector {
|
||||
class CHistoryCollector
|
||||
{
|
||||
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();
|
||||
void AddOpndToHistory(std::wstring_view numStr, CalcEngine::Rational const& rat, bool fRepetition = false);
|
||||
void RemoveLastOpndFromHistory();
|
||||
@@ -30,24 +32,25 @@ public:
|
||||
bool FOpndAddedToHistory();
|
||||
void CompleteHistoryLine(std::wstring_view numStr);
|
||||
void ClearHistoryLine(std::wstring_view errStr);
|
||||
int AddCommand(_In_ const std::shared_ptr<IExpressionCommand> & spCommand);
|
||||
int AddCommand(_In_ const std::shared_ptr<IExpressionCommand>& spCommand);
|
||||
void UpdateHistoryExpression(uint32_t radix, int32_t precision);
|
||||
void SetDecimalSymbol(wchar_t decimalSymbol);
|
||||
|
||||
private:
|
||||
std::shared_ptr<IHistoryDisplay> m_pHistoryDisplay;
|
||||
ICalcDisplay *m_pCalcDisplay;
|
||||
ICalcDisplay* m_pCalcDisplay;
|
||||
|
||||
int m_iCurLineHistStart; // index of the beginning of the current equation
|
||||
// a sort of state, set to the index before 2 after 2 in the expression 2 + 3 say. Useful for auto correct portion of history and for
|
||||
// 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
|
||||
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
|
||||
bool m_bLastOpndBrace; // iff the last opnd in history is already braced so we can avoid putting another one for unary operator
|
||||
bool m_bLastOpndBrace; // iff the last opnd in history is already braced so we can avoid putting another one for unary operator
|
||||
wchar_t m_decimalSymbol;
|
||||
std::shared_ptr<CalculatorVector <std::pair<std::wstring, int>>> m_spTokens;
|
||||
std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> m_spTokens;
|
||||
std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> m_spCommands;
|
||||
|
||||
private:
|
||||
|
@@ -7,12 +7,15 @@
|
||||
#include "../ExpressionCommandInterface.h"
|
||||
|
||||
// Callback interface to be implemented by the clients of CCalcEngine
|
||||
class ICalcDisplay {
|
||||
class ICalcDisplay
|
||||
{
|
||||
public:
|
||||
virtual void SetPrimaryDisplay(const std::wstring& pszText, bool isError) = 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 SetParenDisplayText(const std::wstring& pszText) = 0;
|
||||
virtual void SetExpressionDisplay(
|
||||
_Inout_ std::shared_ptr<CalculatorVector<std::pair<std::wstring, int>>> const& tokens,
|
||||
_Inout_ std::shared_ptr<CalculatorVector<std::shared_ptr<IExpressionCommand>>> const& commands) = 0;
|
||||
virtual void SetParenthesisNumber(_In_ unsigned int count) = 0;
|
||||
virtual void OnNoRightParenAdded() = 0;
|
||||
virtual void MaxDigitsReached() = 0; // not an error but still need to inform UI layer.
|
||||
virtual void BinaryOperatorReceived() = 0;
|
||||
|
@@ -4,8 +4,12 @@
|
||||
#pragma once
|
||||
|
||||
// Callback interface to be implemented by the clients of CCalcEngine if they require equation history
|
||||
class IHistoryDisplay {
|
||||
class IHistoryDisplay
|
||||
{
|
||||
public:
|
||||
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 ~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;
|
||||
};
|
||||
|
@@ -3,6 +3,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include "Ratpack/ratpak.h"
|
||||
|
||||
namespace CalcEngine
|
||||
|
@@ -4,7 +4,8 @@
|
||||
#pragma once
|
||||
|
||||
// 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,
|
||||
DEC_RADIX,
|
||||
OCT_RADIX,
|
||||
|
@@ -13,6 +13,7 @@ namespace CalcEngine::RationalMath
|
||||
Rational Pow(Rational const& base, Rational const& pow);
|
||||
Rational Root(Rational const& base, Rational const& root);
|
||||
Rational Fact(Rational const& rat);
|
||||
Rational Mod(Rational const& a, Rational const& b);
|
||||
|
||||
Rational Exp(Rational const& rat);
|
||||
Rational Log(Rational const& rat);
|
||||
|
14
src/CalcManager/Ratpack/CMakeLists.txt
Normal file
14
src/CalcManager/Ratpack/CMakeLists.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
target_sources(CalcManager PRIVATE
|
||||
basex.cpp
|
||||
conv.cpp
|
||||
exp.cpp
|
||||
fact.cpp
|
||||
itrans.cpp
|
||||
itransh.cpp
|
||||
logic.cpp
|
||||
num.cpp
|
||||
rat.cpp
|
||||
support.cpp
|
||||
trans.cpp
|
||||
transh.cpp
|
||||
)
|
@@ -41,46 +41,45 @@ typedef int32_t ResultCode;
|
||||
// CALC_E_DIVIDEBYZERO
|
||||
//
|
||||
// The current operation would require a divide by zero to complete
|
||||
#define CALC_E_DIVIDEBYZERO ((uint32_t)0x80000000)
|
||||
#define CALC_E_DIVIDEBYZERO ((uint32_t)0x80000000)
|
||||
|
||||
// CALC_E_DOMAIN
|
||||
//
|
||||
// The given input is not within the domain of this function
|
||||
#define CALC_E_DOMAIN ((uint32_t)0x80000001)
|
||||
#define CALC_E_DOMAIN ((uint32_t)0x80000001)
|
||||
|
||||
// CALC_E_INDEFINITE
|
||||
//
|
||||
// The result of this function is undefined
|
||||
#define CALC_E_INDEFINITE ((uint32_t)0x80000002)
|
||||
#define CALC_E_INDEFINITE ((uint32_t)0x80000002)
|
||||
|
||||
// CALC_E_POSINFINITY
|
||||
//
|
||||
// The result of this function is Positive Infinity.
|
||||
#define CALC_E_POSINFINITY ((uint32_t)0x80000003)
|
||||
#define CALC_E_POSINFINITY ((uint32_t)0x80000003)
|
||||
|
||||
// CALC_E_NEGINFINITY
|
||||
//
|
||||
// The result of this function is Negative Infinity
|
||||
#define CALC_E_NEGINFINITY ((uint32_t)0x80000004)
|
||||
#define CALC_E_NEGINFINITY ((uint32_t)0x80000004)
|
||||
|
||||
// CALC_E_INVALIDRANGE
|
||||
//
|
||||
// The given input is within the domain of the function but is beyond
|
||||
// the range for which calc can successfully compute the answer
|
||||
#define CALC_E_INVALIDRANGE ((uint32_t)0x80000006)
|
||||
#define CALC_E_INVALIDRANGE ((uint32_t)0x80000006)
|
||||
|
||||
// CALC_E_OUTOFMEMORY
|
||||
//
|
||||
// There is not enough free memory to complete the requested function
|
||||
#define CALC_E_OUTOFMEMORY ((uint32_t)0x80000007)
|
||||
#define CALC_E_OUTOFMEMORY ((uint32_t)0x80000007)
|
||||
|
||||
// CALC_E_OVERFLOW
|
||||
//
|
||||
// The result of this operation is an overflow
|
||||
#define CALC_E_OVERFLOW ((uint32_t)0x80000008)
|
||||
#define CALC_E_OVERFLOW ((uint32_t)0x80000008)
|
||||
|
||||
// CALC_E_NORESULT
|
||||
//
|
||||
// The result of this operation is undefined
|
||||
#define CALC_E_NORESULT ((uint32_t)0x80000009)
|
||||
|
||||
#define CALC_E_NORESULT ((uint32_t)0x80000009)
|
||||
|
@@ -14,10 +14,10 @@
|
||||
// internal base is a power of 2.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "pch.h"
|
||||
#include "ratpak.h"
|
||||
#include <cstring> // for memmove
|
||||
|
||||
void _mulnumx( PNUMBER *pa, PNUMBER b );
|
||||
void _mulnumx(PNUMBER* pa, PNUMBER b);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
@@ -34,30 +34,30 @@ void _mulnumx( PNUMBER *pa, PNUMBER b );
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void __inline mulnumx( PNUMBER *pa, PNUMBER b )
|
||||
void mulnumx(PNUMBER* pa, PNUMBER b)
|
||||
|
||||
{
|
||||
if ( b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0 )
|
||||
{
|
||||
if (b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0)
|
||||
{
|
||||
// If b is not one we multiply
|
||||
if ( (*pa)->cdigit > 1 || (*pa)->mant[0] != 1 || (*pa)->exp != 0 )
|
||||
{
|
||||
if ((*pa)->cdigit > 1 || (*pa)->mant[0] != 1 || (*pa)->exp != 0)
|
||||
{
|
||||
// pa and b are both non-one.
|
||||
_mulnumx( pa, b );
|
||||
}
|
||||
_mulnumx(pa, b);
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
// if pa is one and b isn't just copy b. and adjust the sign.
|
||||
int32_t sign = (*pa)->sign;
|
||||
DUPNUM(*pa,b);
|
||||
DUPNUM(*pa, b);
|
||||
(*pa)->sign *= sign;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
// B is +/- 1, But we do have to set the sign.
|
||||
(*pa)->sign *= b->sign;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -76,29 +76,29 @@ void __inline mulnumx( PNUMBER *pa, PNUMBER b )
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void _mulnumx( PNUMBER *pa, PNUMBER b )
|
||||
void _mulnumx(PNUMBER* pa, PNUMBER b)
|
||||
|
||||
{
|
||||
PNUMBER c= nullptr; // c will contain the result.
|
||||
PNUMBER a= nullptr; // a is the dereferenced number pointer from *pa
|
||||
MANTTYPE *ptra; // ptra is a pointer to the mantissa of a.
|
||||
MANTTYPE *ptrb; // ptrb is a pointer to the mantissa of b.
|
||||
MANTTYPE *ptrc; // ptrc is a pointer to the mantissa of c.
|
||||
MANTTYPE *ptrcoffset; // ptrcoffset, is the anchor location of the next
|
||||
// single digit multiply partial result.
|
||||
int32_t iadigit=0; // Index of digit being used in the first number.
|
||||
int32_t ibdigit=0; // Index of digit being used in the second number.
|
||||
MANTTYPE da=0; // da is the digit from the fist number.
|
||||
TWO_MANTTYPE cy=0; // cy is the carry resulting from the addition of
|
||||
// a multiplied row into the result.
|
||||
TWO_MANTTYPE mcy=0; // mcy is the resultant from a single
|
||||
// multiply, AND the carry of that multiply.
|
||||
int32_t icdigit=0; // Index of digit being calculated in final result.
|
||||
PNUMBER c = nullptr; // c will contain the result.
|
||||
PNUMBER a = nullptr; // a is the dereferenced number pointer from *pa
|
||||
MANTTYPE* ptra; // ptra is a pointer to the mantissa of a.
|
||||
MANTTYPE* ptrb; // ptrb is a pointer to the mantissa of b.
|
||||
MANTTYPE* ptrc; // ptrc is a pointer to the mantissa of c.
|
||||
MANTTYPE* ptrcoffset; // ptrcoffset, is the anchor location of the next
|
||||
// single digit multiply partial result.
|
||||
int32_t iadigit = 0; // Index of digit being used in the first number.
|
||||
int32_t ibdigit = 0; // Index of digit being used in the second number.
|
||||
MANTTYPE da = 0; // da is the digit from the fist number.
|
||||
TWO_MANTTYPE cy = 0; // cy is the carry resulting from the addition of
|
||||
// a multiplied row into the result.
|
||||
TWO_MANTTYPE mcy = 0; // mcy is the resultant from a single
|
||||
// multiply, AND the carry of that multiply.
|
||||
int32_t icdigit = 0; // Index of digit being calculated in final result.
|
||||
|
||||
a=*pa;
|
||||
a = *pa;
|
||||
|
||||
ibdigit = a->cdigit + b->cdigit - 1;
|
||||
createnum( c, ibdigit + 1 );
|
||||
createnum(c, ibdigit + 1);
|
||||
c->cdigit = ibdigit;
|
||||
c->sign = a->sign * b->sign;
|
||||
|
||||
@@ -106,36 +106,35 @@ void _mulnumx( PNUMBER *pa, PNUMBER b )
|
||||
ptra = a->mant;
|
||||
ptrcoffset = c->mant;
|
||||
|
||||
for ( iadigit = a->cdigit; iadigit > 0; iadigit-- )
|
||||
for (iadigit = a->cdigit; iadigit > 0; iadigit--)
|
||||
{
|
||||
da = *ptra++;
|
||||
da = *ptra++;
|
||||
ptrb = b->mant;
|
||||
|
||||
// Shift ptrc, and ptrcoffset, one for each digit
|
||||
ptrc = ptrcoffset++;
|
||||
|
||||
for ( ibdigit = b->cdigit; ibdigit > 0; ibdigit-- )
|
||||
for (ibdigit = b->cdigit; ibdigit > 0; ibdigit--)
|
||||
{
|
||||
cy = 0;
|
||||
mcy = (uint64_t)da * (*ptrb);
|
||||
if ( mcy )
|
||||
if (mcy)
|
||||
{
|
||||
icdigit = 0;
|
||||
if ( ibdigit == 1 && iadigit == 1 )
|
||||
if (ibdigit == 1 && iadigit == 1)
|
||||
{
|
||||
c->cdigit++;
|
||||
}
|
||||
}
|
||||
|
||||
// If result is nonzero, or while result of carry is nonzero...
|
||||
while ( mcy || cy )
|
||||
while (mcy || cy)
|
||||
{
|
||||
|
||||
// update carry from addition(s) and multiply.
|
||||
cy += (TWO_MANTTYPE)ptrc[icdigit]+((uint32_t)mcy&((uint32_t)~BASEX));
|
||||
cy += (TWO_MANTTYPE)ptrc[icdigit] + ((uint32_t)mcy & ((uint32_t)~BASEX));
|
||||
|
||||
// update result digit from
|
||||
ptrc[icdigit++]=(MANTTYPE)((uint32_t)cy&((uint32_t)~BASEX));
|
||||
ptrc[icdigit++] = (MANTTYPE)((uint32_t)cy & ((uint32_t)~BASEX));
|
||||
|
||||
// update carries from
|
||||
mcy >>= BASEXPWR;
|
||||
@@ -144,19 +143,18 @@ void _mulnumx( PNUMBER *pa, PNUMBER b )
|
||||
|
||||
ptrb++;
|
||||
ptrc++;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// prevent different kinds of zeros, by stripping leading duplicate zeros.
|
||||
// digits are in order of increasing significance.
|
||||
while ( c->cdigit > 1 && c->mant[c->cdigit-1] == 0 )
|
||||
{
|
||||
while (c->cdigit > 1 && c->mant[c->cdigit - 1] == 0)
|
||||
{
|
||||
c->cdigit--;
|
||||
}
|
||||
}
|
||||
|
||||
destroynum( *pa );
|
||||
*pa=c;
|
||||
destroynum(*pa);
|
||||
*pa = c;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
@@ -174,34 +172,33 @@ void _mulnumx( PNUMBER *pa, PNUMBER b )
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void numpowi32x( _Inout_ PNUMBER *proot, _In_ int32_t power )
|
||||
void numpowi32x(_Inout_ PNUMBER* proot, _In_ int32_t power)
|
||||
|
||||
{
|
||||
PNUMBER lret = i32tonum( 1, BASEX );
|
||||
PNUMBER lret = i32tonum(1, BASEX);
|
||||
|
||||
// Once the power remaining is zero we are done.
|
||||
while ( power > 0 )
|
||||
{
|
||||
while (power > 0)
|
||||
{
|
||||
// If this bit in the power decomposition is on, multiply the result
|
||||
// by the root number.
|
||||
if ( power & 1 )
|
||||
{
|
||||
mulnumx( &lret, *proot );
|
||||
}
|
||||
if (power & 1)
|
||||
{
|
||||
mulnumx(&lret, *proot);
|
||||
}
|
||||
|
||||
// multiply the root number by itself to scale for the next bit (i.e.
|
||||
// square it.
|
||||
mulnumx( proot, *proot );
|
||||
mulnumx(proot, *proot);
|
||||
|
||||
// move the next bit of the power into place.
|
||||
power >>= 1;
|
||||
}
|
||||
destroynum( *proot );
|
||||
*proot=lret;
|
||||
|
||||
}
|
||||
destroynum(*proot);
|
||||
*proot = lret;
|
||||
}
|
||||
|
||||
void _divnumx( PNUMBER *pa, PNUMBER b, int32_t precision);
|
||||
void _divnumx(PNUMBER* pa, PNUMBER b, int32_t precision);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
@@ -218,30 +215,30 @@ void _divnumx( PNUMBER *pa, PNUMBER b, int32_t precision);
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void __inline divnumx( PNUMBER *pa, PNUMBER b, int32_t precision)
|
||||
void divnumx(PNUMBER* pa, PNUMBER b, int32_t precision)
|
||||
|
||||
{
|
||||
if ( b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0 )
|
||||
{
|
||||
if (b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0)
|
||||
{
|
||||
// b is not one.
|
||||
if ( (*pa)->cdigit > 1 || (*pa)->mant[0] != 1 || (*pa)->exp != 0 )
|
||||
{
|
||||
if ((*pa)->cdigit > 1 || (*pa)->mant[0] != 1 || (*pa)->exp != 0)
|
||||
{
|
||||
// pa and b are both not one.
|
||||
_divnumx( pa, b, precision);
|
||||
}
|
||||
_divnumx(pa, b, precision);
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
// if pa is one and b is not one, just copy b, and adjust the sign.
|
||||
int32_t sign = (*pa)->sign;
|
||||
DUPNUM(*pa,b);
|
||||
DUPNUM(*pa, b);
|
||||
(*pa)->sign *= sign;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
// b is one so don't divide, but set the sign.
|
||||
(*pa)->sign *= b->sign;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -257,111 +254,109 @@ void __inline divnumx( PNUMBER *pa, PNUMBER b, int32_t precision)
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void _divnumx( PNUMBER *pa, PNUMBER b, int32_t precision)
|
||||
void _divnumx(PNUMBER* pa, PNUMBER b, int32_t precision)
|
||||
|
||||
{
|
||||
PNUMBER a= nullptr; // a is the dereferenced number pointer from *pa
|
||||
PNUMBER c= nullptr; // c will contain the result.
|
||||
PNUMBER a = nullptr; // a is the dereferenced number pointer from *pa
|
||||
PNUMBER c = nullptr; // c will contain the result.
|
||||
PNUMBER lasttmp = nullptr; // lasttmp allows a backup when the algorithm
|
||||
// guesses one bit too far.
|
||||
// guesses one bit too far.
|
||||
PNUMBER tmp = nullptr; // current guess being worked on for divide.
|
||||
PNUMBER rem = nullptr; // remainder after applying guess.
|
||||
int32_t cdigits; // count of digits for answer.
|
||||
MANTTYPE *ptrc; // ptrc is a pointer to the mantissa of c.
|
||||
MANTTYPE* ptrc; // ptrc is a pointer to the mantissa of c.
|
||||
|
||||
int32_t thismax = precision + g_ratio; // set a maximum number of internal digits
|
||||
// to shoot for in the divide.
|
||||
// to shoot for in the divide.
|
||||
|
||||
a=*pa;
|
||||
if ( thismax < a->cdigit )
|
||||
{
|
||||
a = *pa;
|
||||
if (thismax < a->cdigit)
|
||||
{
|
||||
// a has more digits than precision specified, bump up digits to shoot
|
||||
// for.
|
||||
thismax = a->cdigit;
|
||||
}
|
||||
}
|
||||
|
||||
if ( thismax < b->cdigit )
|
||||
{
|
||||
if (thismax < b->cdigit)
|
||||
{
|
||||
// b has more digits than precision specified, bump up digits to shoot
|
||||
// for.
|
||||
thismax = b->cdigit;
|
||||
}
|
||||
}
|
||||
|
||||
// Create c (the divide answer) and set up exponent and sign.
|
||||
createnum( c, thismax + 1 );
|
||||
c->exp = (a->cdigit+a->exp) - (b->cdigit+b->exp) + 1;
|
||||
createnum(c, thismax + 1);
|
||||
c->exp = (a->cdigit + a->exp) - (b->cdigit + b->exp) + 1;
|
||||
c->sign = a->sign * b->sign;
|
||||
|
||||
ptrc = c->mant + thismax;
|
||||
cdigits = 0;
|
||||
|
||||
DUPNUM( rem, a );
|
||||
DUPNUM(rem, a);
|
||||
rem->sign = b->sign;
|
||||
rem->exp = b->cdigit + b->exp - rem->cdigit;
|
||||
|
||||
while ( cdigits++ < thismax && !zernum(rem) )
|
||||
{
|
||||
while (cdigits++ < thismax && !zernum(rem))
|
||||
{
|
||||
int32_t digit = 0;
|
||||
*ptrc = 0;
|
||||
while ( !lessnum( rem, b ) )
|
||||
{
|
||||
while (!lessnum(rem, b))
|
||||
{
|
||||
digit = 1;
|
||||
DUPNUM( tmp, b );
|
||||
destroynum( lasttmp );
|
||||
lasttmp=i32tonum( 0, BASEX );
|
||||
while ( lessnum( tmp, rem ) )
|
||||
{
|
||||
destroynum( lasttmp );
|
||||
DUPNUM(lasttmp,tmp);
|
||||
addnum( &tmp, tmp, BASEX );
|
||||
DUPNUM(tmp, b);
|
||||
destroynum(lasttmp);
|
||||
lasttmp = i32tonum(0, BASEX);
|
||||
while (lessnum(tmp, rem))
|
||||
{
|
||||
destroynum(lasttmp);
|
||||
DUPNUM(lasttmp, tmp);
|
||||
addnum(&tmp, tmp, BASEX);
|
||||
digit *= 2;
|
||||
}
|
||||
if ( lessnum( rem, tmp ) )
|
||||
{
|
||||
}
|
||||
if (lessnum(rem, tmp))
|
||||
{
|
||||
// too far, back up...
|
||||
destroynum( tmp );
|
||||
destroynum(tmp);
|
||||
digit /= 2;
|
||||
tmp=lasttmp;
|
||||
lasttmp= nullptr;
|
||||
}
|
||||
tmp = lasttmp;
|
||||
lasttmp = nullptr;
|
||||
}
|
||||
|
||||
tmp->sign *= -1;
|
||||
addnum( &rem, tmp, BASEX );
|
||||
destroynum( tmp );
|
||||
destroynum( lasttmp );
|
||||
addnum(&rem, tmp, BASEX);
|
||||
destroynum(tmp);
|
||||
destroynum(lasttmp);
|
||||
*ptrc |= digit;
|
||||
}
|
||||
}
|
||||
rem->exp++;
|
||||
ptrc--;
|
||||
}
|
||||
}
|
||||
cdigits--;
|
||||
if ( c->mant != ++ptrc )
|
||||
{
|
||||
memmove( c->mant, ptrc, (int)(cdigits*sizeof(MANTTYPE)) );
|
||||
}
|
||||
if (c->mant != ++ptrc)
|
||||
{
|
||||
memmove(c->mant, ptrc, (int)(cdigits * sizeof(MANTTYPE)));
|
||||
}
|
||||
|
||||
if ( !cdigits )
|
||||
{
|
||||
if (!cdigits)
|
||||
{
|
||||
// A zero, make sure no weird exponents creep in
|
||||
c->exp = 0;
|
||||
c->cdigit = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
c->cdigit = cdigits;
|
||||
c->exp -= cdigits;
|
||||
// prevent different kinds of zeros, by stripping leading duplicate
|
||||
// zeros. digits are in order of increasing significance.
|
||||
while ( c->cdigit > 1 && c->mant[c->cdigit-1] == 0 )
|
||||
{
|
||||
while (c->cdigit > 1 && c->mant[c->cdigit - 1] == 0)
|
||||
{
|
||||
c->cdigit--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
destroynum( rem );
|
||||
destroynum(rem);
|
||||
|
||||
destroynum( *pa );
|
||||
*pa=c;
|
||||
destroynum(*pa);
|
||||
*pa = c;
|
||||
}
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -14,10 +14,8 @@
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "pch.h"
|
||||
#include "ratpak.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: exprat
|
||||
@@ -41,63 +39,63 @@
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void _exprat( PRAT *px, int32_t precision)
|
||||
void _exprat(PRAT* px, int32_t precision)
|
||||
|
||||
{
|
||||
CREATETAYLOR();
|
||||
|
||||
addnum(&(pret->pp),num_one, BASEX);
|
||||
addnum(&(pret->pq),num_one, BASEX);
|
||||
DUPRAT(thisterm,pret);
|
||||
addnum(&(pret->pp), num_one, BASEX);
|
||||
addnum(&(pret->pq), num_one, BASEX);
|
||||
DUPRAT(thisterm, pret);
|
||||
|
||||
n2=i32tonum(0L, BASEX);
|
||||
n2 = i32tonum(0L, BASEX);
|
||||
|
||||
do {
|
||||
do
|
||||
{
|
||||
NEXTTERM(*px, INC(n2) DIVNUM(n2), precision);
|
||||
} while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
|
||||
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
||||
|
||||
DESTROYTAYLOR();
|
||||
}
|
||||
|
||||
void exprat( PRAT *px, uint32_t radix, int32_t precision)
|
||||
void exprat(PRAT* px, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
PRAT pwr= nullptr;
|
||||
PRAT pint= nullptr;
|
||||
PRAT pwr = nullptr;
|
||||
PRAT pint = nullptr;
|
||||
int32_t intpwr;
|
||||
|
||||
if ( rat_gt( *px, rat_max_exp, precision) || rat_lt( *px, rat_min_exp, precision) )
|
||||
{
|
||||
if (rat_gt(*px, rat_max_exp, precision) || rat_lt(*px, rat_min_exp, precision))
|
||||
{
|
||||
// Don't attempt exp of anything large.
|
||||
throw( CALC_E_DOMAIN );
|
||||
}
|
||||
throw(CALC_E_DOMAIN);
|
||||
}
|
||||
|
||||
DUPRAT(pwr,rat_exp);
|
||||
DUPRAT(pint,*px);
|
||||
DUPRAT(pwr, rat_exp);
|
||||
DUPRAT(pint, *px);
|
||||
|
||||
intrat(&pint, radix, precision);
|
||||
|
||||
intpwr = rattoi32(pint, radix, precision);
|
||||
ratpowi32( &pwr, intpwr, precision);
|
||||
ratpowi32(&pwr, intpwr, precision);
|
||||
|
||||
subrat(px, pint, precision);
|
||||
|
||||
// It just so happens to be an integral power of e.
|
||||
if ( rat_gt( *px, rat_negsmallest, precision) && rat_lt( *px, rat_smallest, precision) )
|
||||
{
|
||||
DUPRAT(*px,pwr);
|
||||
}
|
||||
if (rat_gt(*px, rat_negsmallest, precision) && rat_lt(*px, rat_smallest, precision))
|
||||
{
|
||||
DUPRAT(*px, pwr);
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
_exprat(px, precision);
|
||||
mulrat(px, pwr, precision);
|
||||
}
|
||||
}
|
||||
|
||||
destroyrat( pwr );
|
||||
destroyrat( pint );
|
||||
destroyrat(pwr);
|
||||
destroyrat(pint);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: lograt, _lograt
|
||||
@@ -125,7 +123,7 @@ void exprat( PRAT *px, uint32_t radix, int32_t precision)
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void _lograt( PRAT *px, int32_t precision)
|
||||
void _lograt(PRAT* px, int32_t precision)
|
||||
|
||||
{
|
||||
CREATETAYLOR();
|
||||
@@ -134,76 +132,75 @@ void _lograt( PRAT *px, int32_t precision)
|
||||
|
||||
// sub one from x
|
||||
(*px)->pq->sign *= -1;
|
||||
addnum(&((*px)->pp),(*px)->pq, BASEX);
|
||||
addnum(&((*px)->pp), (*px)->pq, BASEX);
|
||||
(*px)->pq->sign *= -1;
|
||||
|
||||
DUPRAT(pret,*px);
|
||||
DUPRAT(thisterm,*px);
|
||||
DUPRAT(pret, *px);
|
||||
DUPRAT(thisterm, *px);
|
||||
|
||||
n2=i32tonum(1L, BASEX);
|
||||
n2 = i32tonum(1L, BASEX);
|
||||
(*px)->pp->sign *= -1;
|
||||
|
||||
do {
|
||||
do
|
||||
{
|
||||
NEXTTERM(*px, MULNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
TRIMTOP(*px, precision);
|
||||
} while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
|
||||
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
||||
|
||||
DESTROYTAYLOR();
|
||||
}
|
||||
|
||||
|
||||
void lograt( PRAT *px, int32_t precision)
|
||||
void lograt(PRAT* px, int32_t precision)
|
||||
|
||||
{
|
||||
bool fneglog;
|
||||
PRAT pwr = nullptr; // pwr is the large scaling factor.
|
||||
PRAT offset = nullptr; // offset is the incremental scaling factor.
|
||||
|
||||
PRAT pwr = nullptr; // pwr is the large scaling factor.
|
||||
PRAT offset = nullptr; // offset is the incremental scaling factor.
|
||||
|
||||
// Check for someone taking the log of zero or a negative number.
|
||||
if ( rat_le( *px, rat_zero, precision) )
|
||||
{
|
||||
throw( CALC_E_DOMAIN );
|
||||
}
|
||||
if (rat_le(*px, rat_zero, precision))
|
||||
{
|
||||
throw(CALC_E_DOMAIN);
|
||||
}
|
||||
|
||||
// Get number > 1, for scaling
|
||||
fneglog = rat_lt( *px, rat_one, precision);
|
||||
if ( fneglog )
|
||||
{
|
||||
fneglog = rat_lt(*px, rat_one, precision);
|
||||
if (fneglog)
|
||||
{
|
||||
// WARNING: This is equivalent to doing *px = 1 / *px
|
||||
PNUMBER pnumtemp= nullptr;
|
||||
PNUMBER pnumtemp = nullptr;
|
||||
pnumtemp = (*px)->pp;
|
||||
(*px)->pp = (*px)->pq;
|
||||
(*px)->pq = pnumtemp;
|
||||
}
|
||||
}
|
||||
|
||||
// Scale the number within BASEX factor of 1, for the large scale.
|
||||
// log(x*2^(BASEXPWR*k)) = BASEXPWR*k*log(2)+log(x)
|
||||
if ( LOGRAT2(*px) > 1 )
|
||||
{
|
||||
if (LOGRAT2(*px) > 1)
|
||||
{
|
||||
// Take advantage of px's base BASEX to scale quickly down to
|
||||
// a reasonable range.
|
||||
int32_t intpwr;
|
||||
intpwr=LOGRAT2(*px)-1;
|
||||
intpwr = LOGRAT2(*px) - 1;
|
||||
(*px)->pq->exp += intpwr;
|
||||
pwr=i32torat(intpwr*BASEXPWR);
|
||||
pwr = i32torat(intpwr * BASEXPWR);
|
||||
mulrat(&pwr, ln_two, precision);
|
||||
// ln(x+e)-ln(x) looks close to e when x is close to one using some
|
||||
// expansions. This means we can trim past precision digits+1.
|
||||
TRIMTOP(*px, precision);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DUPRAT(pwr,rat_zero);
|
||||
}
|
||||
{
|
||||
DUPRAT(pwr, rat_zero);
|
||||
}
|
||||
|
||||
DUPRAT(offset,rat_zero);
|
||||
DUPRAT(offset, rat_zero);
|
||||
// Scale the number between 1 and e_to_one_half, for the small scale.
|
||||
while ( rat_gt( *px, e_to_one_half, precision) )
|
||||
{
|
||||
divrat( px, e_to_one_half, precision);
|
||||
addrat( &offset, rat_one, precision);
|
||||
}
|
||||
while (rat_gt(*px, e_to_one_half, precision))
|
||||
{
|
||||
divrat(px, e_to_one_half, precision);
|
||||
addrat(&offset, rat_one, precision);
|
||||
}
|
||||
|
||||
_lograt(px, precision);
|
||||
|
||||
@@ -218,16 +215,16 @@ void lograt( PRAT *px, int32_t precision)
|
||||
trimit(px, precision);
|
||||
|
||||
// If number started out < 1 rescale answer to negative.
|
||||
if ( fneglog )
|
||||
{
|
||||
if (fneglog)
|
||||
{
|
||||
(*px)->pp->sign *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
destroyrat(offset);
|
||||
destroyrat(pwr);
|
||||
}
|
||||
|
||||
void log10rat( PRAT *px, int32_t precision)
|
||||
void log10rat(PRAT* px, int32_t precision)
|
||||
|
||||
{
|
||||
lograt(px, precision);
|
||||
@@ -247,7 +244,7 @@ bool IsEven(PRAT x, uint32_t radix, int32_t precision)
|
||||
fracrat(&tmp, radix, precision);
|
||||
addrat(&tmp, tmp, precision);
|
||||
subrat(&tmp, rat_one, precision);
|
||||
if ( rat_lt( tmp, rat_zero, precision))
|
||||
if (rat_lt(tmp, rat_zero, precision))
|
||||
{
|
||||
bRet = true;
|
||||
}
|
||||
@@ -270,7 +267,7 @@ bool IsEven(PRAT x, uint32_t radix, int32_t precision)
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void powrat(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
|
||||
void powrat(PRAT* px, PRAT y, uint32_t radix, int32_t precision)
|
||||
{
|
||||
// Handle cases where px or y is 0 by calling powratcomp directly
|
||||
if (zerrat(*px) || zerrat(y))
|
||||
@@ -297,12 +294,12 @@ void powrat(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
|
||||
}
|
||||
}
|
||||
|
||||
void powratNumeratorDenominator(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
|
||||
void powratNumeratorDenominator(PRAT* px, PRAT y, uint32_t radix, int32_t precision)
|
||||
{
|
||||
// Prepare rationals
|
||||
PRAT yNumerator = nullptr;
|
||||
PRAT yDenominator = nullptr;
|
||||
DUPRAT(yNumerator, rat_zero); // yNumerator->pq is 1 one
|
||||
DUPRAT(yNumerator, rat_zero); // yNumerator->pq is 1 one
|
||||
DUPRAT(yDenominator, rat_zero); // yDenominator->pq is 1 one
|
||||
DUPNUM(yNumerator->pp, y->pp);
|
||||
DUPNUM(yDenominator->pp, y->pq);
|
||||
@@ -406,84 +403,82 @@ void powratNumeratorDenominator(PRAT *px, PRAT y, uint32_t radix, int32_t precis
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void powratcomp(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
|
||||
void powratcomp(PRAT* px, PRAT y, uint32_t radix, int32_t precision)
|
||||
{
|
||||
int32_t sign = ((*px)->pp->sign * (*px)->pq->sign);
|
||||
int32_t sign = SIGN(*px);
|
||||
|
||||
// Take the absolute value
|
||||
(*px)->pp->sign = 1;
|
||||
(*px)->pq->sign = 1;
|
||||
|
||||
if ( zerrat( *px ) )
|
||||
{
|
||||
if (zerrat(*px))
|
||||
{
|
||||
// *px is zero.
|
||||
if ( rat_lt( y, rat_zero, precision) )
|
||||
{
|
||||
throw( CALC_E_DOMAIN );
|
||||
}
|
||||
else if ( zerrat( y ) )
|
||||
{
|
||||
// *px and y are both zero, special case a 1 return.
|
||||
DUPRAT(*px,rat_one);
|
||||
// Ensure sign is positive.
|
||||
sign = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (rat_lt(y, rat_zero, precision))
|
||||
{
|
||||
PRAT pxint= nullptr;
|
||||
DUPRAT(pxint,*px);
|
||||
subrat(&pxint, rat_one, precision);
|
||||
if ( rat_gt( pxint, rat_negsmallest, precision) &&
|
||||
rat_lt( pxint, rat_smallest, precision) && ( sign == 1 ) )
|
||||
{
|
||||
// *px is one, special case a 1 return.
|
||||
DUPRAT(*px,rat_one);
|
||||
throw(CALC_E_DOMAIN);
|
||||
}
|
||||
else if (zerrat(y))
|
||||
{
|
||||
// *px and y are both zero, special case a 1 return.
|
||||
DUPRAT(*px, rat_one);
|
||||
// Ensure sign is positive.
|
||||
sign = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PRAT pxint = nullptr;
|
||||
DUPRAT(pxint, *px);
|
||||
subrat(&pxint, rat_one, precision);
|
||||
if (rat_gt(pxint, rat_negsmallest, precision) && rat_lt(pxint, rat_smallest, precision) && (sign == 1))
|
||||
{
|
||||
// *px is one, special case a 1 return.
|
||||
DUPRAT(*px, rat_one);
|
||||
// Ensure sign is positive.
|
||||
sign = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
{
|
||||
// Only do the exp if the number isn't zero or one
|
||||
PRAT podd = nullptr;
|
||||
DUPRAT(podd,y);
|
||||
DUPRAT(podd, y);
|
||||
fracrat(&podd, radix, precision);
|
||||
if ( rat_gt( podd, rat_negsmallest, precision) && rat_lt( podd, rat_smallest, precision) )
|
||||
{
|
||||
if (rat_gt(podd, rat_negsmallest, precision) && rat_lt(podd, rat_smallest, precision))
|
||||
{
|
||||
// If power is an integer let ratpowi32 deal with it.
|
||||
PRAT iy = nullptr;
|
||||
int32_t inty;
|
||||
DUPRAT(iy,y);
|
||||
DUPRAT(iy, y);
|
||||
subrat(&iy, podd, precision);
|
||||
inty = rattoi32(iy, radix, precision);
|
||||
|
||||
PRAT plnx = nullptr;
|
||||
DUPRAT(plnx,*px);
|
||||
DUPRAT(plnx, *px);
|
||||
lograt(&plnx, precision);
|
||||
mulrat(&plnx, iy, precision);
|
||||
if ( rat_gt( plnx, rat_max_exp, precision) || rat_lt( plnx, rat_min_exp, precision) )
|
||||
{
|
||||
if (rat_gt(plnx, rat_max_exp, precision) || rat_lt(plnx, rat_min_exp, precision))
|
||||
{
|
||||
// Don't attempt exp of anything large or small.A
|
||||
destroyrat(plnx);
|
||||
destroyrat(iy);
|
||||
destroyrat(pxint);
|
||||
destroyrat(podd);
|
||||
throw( CALC_E_DOMAIN );
|
||||
}
|
||||
throw(CALC_E_DOMAIN);
|
||||
}
|
||||
destroyrat(plnx);
|
||||
ratpowi32(px, inty, precision);
|
||||
if ( ( inty & 1 ) == 0 )
|
||||
{
|
||||
sign=1;
|
||||
}
|
||||
destroyrat(iy);
|
||||
}
|
||||
else
|
||||
if ((inty & 1) == 0)
|
||||
{
|
||||
sign = 1;
|
||||
}
|
||||
destroyrat(iy);
|
||||
}
|
||||
else
|
||||
{
|
||||
// power is a fraction
|
||||
if ( sign == -1 )
|
||||
{
|
||||
if (sign == -1)
|
||||
{
|
||||
// Need to throw an error if the exponent has an even denominator.
|
||||
// As a first step, the numerator and denominator must be divided by 2 as many times as
|
||||
// possible, so that 2/6 is allowed.
|
||||
@@ -493,7 +488,7 @@ void powratcomp(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
|
||||
bool fBadExponent = false;
|
||||
|
||||
// Get the numbers in arbitrary precision rational number format
|
||||
DUPRAT(pNumerator, rat_zero); // pNumerator->pq is 1 one
|
||||
DUPRAT(pNumerator, rat_zero); // pNumerator->pq is 1 one
|
||||
DUPRAT(pDenominator, rat_zero); // pDenominator->pq is 1 one
|
||||
|
||||
DUPNUM(pNumerator->pp, y->pp);
|
||||
@@ -502,39 +497,39 @@ void powratcomp(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
|
||||
pDenominator->pp->sign = 1;
|
||||
|
||||
while (IsEven(pNumerator, radix, precision) && IsEven(pDenominator, radix, precision)) // both Numerator & denominator is even
|
||||
{
|
||||
{
|
||||
divrat(&pNumerator, rat_two, precision);
|
||||
divrat(&pDenominator, rat_two, precision);
|
||||
}
|
||||
}
|
||||
if (IsEven(pDenominator, radix, precision)) // denominator is still even
|
||||
{
|
||||
fBadExponent = true;
|
||||
}
|
||||
{
|
||||
fBadExponent = true;
|
||||
}
|
||||
if (IsEven(pNumerator, radix, precision)) // numerator is still even
|
||||
{
|
||||
{
|
||||
sign = 1;
|
||||
}
|
||||
}
|
||||
destroyrat(pNumerator);
|
||||
destroyrat(pDenominator);
|
||||
|
||||
if (fBadExponent)
|
||||
{
|
||||
throw( CALC_E_DOMAIN );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw(CALC_E_DOMAIN);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the exponent is not odd disregard the sign.
|
||||
sign = 1;
|
||||
}
|
||||
}
|
||||
|
||||
lograt(px, precision);
|
||||
mulrat(px, y, precision);
|
||||
exprat(px, radix, precision);
|
||||
}
|
||||
destroyrat(podd);
|
||||
}
|
||||
destroyrat(pxint);
|
||||
}
|
||||
destroyrat(podd);
|
||||
}
|
||||
destroyrat(pxint);
|
||||
}
|
||||
(*px)->pp->sign *= sign;
|
||||
}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -13,11 +13,9 @@
|
||||
// Contains fact(orial) and supporting _gamma functions.
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "pch.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)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -56,37 +54,36 @@
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
void _gamma( PRAT *pn, uint32_t radix, int32_t precision)
|
||||
void _gamma(PRAT* pn, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
PRAT factorial= nullptr;
|
||||
PNUMBER count= nullptr;
|
||||
PRAT tmp= nullptr;
|
||||
PRAT one_pt_five= nullptr;
|
||||
PRAT a= nullptr;
|
||||
PRAT a2= nullptr;
|
||||
PRAT term= nullptr;
|
||||
PRAT sum= nullptr;
|
||||
PRAT err= nullptr;
|
||||
PRAT mpy= nullptr;
|
||||
PRAT factorial = nullptr;
|
||||
PNUMBER count = nullptr;
|
||||
PRAT tmp = nullptr;
|
||||
PRAT one_pt_five = nullptr;
|
||||
PRAT a = nullptr;
|
||||
PRAT a2 = nullptr;
|
||||
PRAT term = nullptr;
|
||||
PRAT sum = nullptr;
|
||||
PRAT err = nullptr;
|
||||
PRAT mpy = nullptr;
|
||||
PRAT ratprec = nullptr;
|
||||
PRAT ratRadix = nullptr;
|
||||
int32_t oldprec;
|
||||
|
||||
// Set up constants and initial conditions
|
||||
oldprec = precision;
|
||||
ratprec = i32torat( oldprec );
|
||||
ratprec = i32torat(oldprec);
|
||||
|
||||
// Find the best 'A' for convergence to the required precision.
|
||||
a=i32torat( radix );
|
||||
a = i32torat(radix);
|
||||
lograt(&a, precision);
|
||||
mulrat(&a, ratprec, precision);
|
||||
|
||||
// Really is -ln(n)+1, but -ln(n) will be < 1
|
||||
// if we scale n between 0.5 and 1.5
|
||||
addrat(&a, rat_two, precision);
|
||||
DUPRAT(tmp,a);
|
||||
DUPRAT(tmp, a);
|
||||
lograt(&tmp, precision);
|
||||
mulrat(&tmp, *pn, precision);
|
||||
addrat(&a, tmp, precision);
|
||||
@@ -95,85 +92,85 @@ void _gamma( PRAT *pn, uint32_t radix, int32_t precision)
|
||||
// Calculate the necessary bump in precision and up the precision.
|
||||
// The following code is equivalent to
|
||||
// precision += ln(exp(a)*pow(a,n+1.5))-ln(radix));
|
||||
DUPRAT(tmp,*pn);
|
||||
one_pt_five=i32torat( 3L );
|
||||
divrat( &one_pt_five, rat_two, precision);
|
||||
addrat( &tmp, one_pt_five, precision);
|
||||
DUPRAT(term,a);
|
||||
powratcomp( &term, tmp, radix, precision);
|
||||
DUPRAT( tmp, a );
|
||||
exprat( &tmp, radix, precision);
|
||||
mulrat( &term, tmp, precision);
|
||||
lograt( &term, precision);
|
||||
DUPRAT(tmp, *pn);
|
||||
one_pt_five = i32torat(3L);
|
||||
divrat(&one_pt_five, rat_two, precision);
|
||||
addrat(&tmp, one_pt_five, precision);
|
||||
DUPRAT(term, a);
|
||||
powratcomp(&term, tmp, radix, precision);
|
||||
DUPRAT(tmp, a);
|
||||
exprat(&tmp, radix, precision);
|
||||
mulrat(&term, tmp, precision);
|
||||
lograt(&term, precision);
|
||||
ratRadix = i32torat(radix);
|
||||
DUPRAT(tmp,ratRadix);
|
||||
lograt( &tmp, precision);
|
||||
subrat( &term, tmp, precision);
|
||||
precision += rattoi32( term, radix, precision);
|
||||
DUPRAT(tmp, ratRadix);
|
||||
lograt(&tmp, precision);
|
||||
subrat(&term, tmp, precision);
|
||||
precision += rattoi32(term, radix, precision);
|
||||
|
||||
// Set up initial terms for series, refer to series in above comment block.
|
||||
DUPRAT(factorial,rat_one); // Start factorial out with one
|
||||
count = i32tonum( 0L, BASEX );
|
||||
DUPRAT(factorial, rat_one); // Start factorial out with one
|
||||
count = i32tonum(0L, BASEX);
|
||||
|
||||
DUPRAT(mpy,a);
|
||||
powratcomp(&mpy,*pn, radix, precision);
|
||||
DUPRAT(mpy, a);
|
||||
powratcomp(&mpy, *pn, radix, precision);
|
||||
// a2=a^2
|
||||
DUPRAT(a2,a);
|
||||
DUPRAT(a2, a);
|
||||
mulrat(&a2, a, precision);
|
||||
|
||||
// sum=(1/n)-(a/(n+1))
|
||||
DUPRAT(sum,rat_one);
|
||||
DUPRAT(sum, rat_one);
|
||||
divrat(&sum, *pn, precision);
|
||||
DUPRAT(tmp,*pn);
|
||||
DUPRAT(tmp, *pn);
|
||||
addrat(&tmp, rat_one, precision);
|
||||
DUPRAT(term,a);
|
||||
DUPRAT(term, a);
|
||||
divrat(&term, tmp, precision);
|
||||
subrat(&sum, term, precision);
|
||||
|
||||
DUPRAT(err,ratRadix);
|
||||
DUPRAT(err, ratRadix);
|
||||
NEGATE(ratprec);
|
||||
powratcomp(&err,ratprec, radix, precision);
|
||||
powratcomp(&err, ratprec, radix, precision);
|
||||
divrat(&err, ratRadix, precision);
|
||||
|
||||
// Just get something not tiny in term
|
||||
DUPRAT(term, rat_two );
|
||||
DUPRAT(term, rat_two);
|
||||
|
||||
// Loop until precision is reached, or asked to halt.
|
||||
while ( !zerrat( term ) && rat_gt( term, err, precision) )
|
||||
{
|
||||
while (!zerrat(term) && rat_gt(term, err, precision))
|
||||
{
|
||||
addrat(pn, rat_two, precision);
|
||||
|
||||
// WARNING: mixing numbers and rationals here.
|
||||
// for speed and efficiency.
|
||||
INC(count);
|
||||
mulnumx(&(factorial->pp),count);
|
||||
mulnumx(&(factorial->pp), count);
|
||||
INC(count)
|
||||
mulnumx(&(factorial->pp),count);
|
||||
mulnumx(&(factorial->pp), count);
|
||||
|
||||
divrat(&factorial, a2, precision);
|
||||
|
||||
DUPRAT(tmp,*pn);
|
||||
addrat( &tmp, rat_one, precision);
|
||||
DUPRAT(tmp, *pn);
|
||||
addrat(&tmp, rat_one, precision);
|
||||
destroyrat(term);
|
||||
createrat(term);
|
||||
DUPNUM(term->pp,count);
|
||||
DUPNUM(term->pq,num_one);
|
||||
addrat( &term, rat_one, precision);
|
||||
mulrat( &term, tmp, precision);
|
||||
DUPRAT(tmp,a);
|
||||
divrat( &tmp, term, precision);
|
||||
DUPNUM(term->pp, count);
|
||||
DUPNUM(term->pq, num_one);
|
||||
addrat(&term, rat_one, precision);
|
||||
mulrat(&term, tmp, precision);
|
||||
DUPRAT(tmp, a);
|
||||
divrat(&tmp, term, precision);
|
||||
|
||||
DUPRAT(term,rat_one);
|
||||
divrat( &term, *pn, precision);
|
||||
subrat( &term, tmp, precision);
|
||||
DUPRAT(term, rat_one);
|
||||
divrat(&term, *pn, precision);
|
||||
subrat(&term, tmp, precision);
|
||||
|
||||
divrat (&term, factorial, precision);
|
||||
addrat( &sum, term, precision);
|
||||
divrat(&term, factorial, precision);
|
||||
addrat(&sum, term, precision);
|
||||
ABSRAT(term);
|
||||
}
|
||||
}
|
||||
|
||||
// Multiply by factor.
|
||||
mulrat( &sum, mpy, precision);
|
||||
mulrat(&sum, mpy, precision);
|
||||
|
||||
// And cleanup
|
||||
precision = oldprec;
|
||||
@@ -189,70 +186,67 @@ void _gamma( PRAT *pn, uint32_t radix, int32_t precision)
|
||||
|
||||
destroyrat(factorial);
|
||||
destroyrat(*pn);
|
||||
DUPRAT(*pn,sum);
|
||||
DUPRAT(*pn, sum);
|
||||
destroyrat(sum);
|
||||
}
|
||||
|
||||
void factrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||
void factrat(PRAT* px, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
PRAT fact = nullptr;
|
||||
PRAT frac = nullptr;
|
||||
PRAT neg_rat_one = nullptr;
|
||||
|
||||
if ( rat_gt( *px, rat_max_fact, precision) || rat_lt( *px, rat_min_fact, precision) )
|
||||
{
|
||||
if (rat_gt(*px, rat_max_fact, precision) || rat_lt(*px, rat_min_fact, precision))
|
||||
{
|
||||
// Don't attempt factorial of anything too large or small.
|
||||
throw CALC_E_OVERFLOW;
|
||||
}
|
||||
}
|
||||
|
||||
DUPRAT(fact,rat_one);
|
||||
DUPRAT(fact, rat_one);
|
||||
|
||||
DUPRAT(neg_rat_one,rat_one);
|
||||
DUPRAT(neg_rat_one, rat_one);
|
||||
neg_rat_one->pp->sign *= -1;
|
||||
|
||||
DUPRAT( frac, *px );
|
||||
fracrat( &frac, radix, precision);
|
||||
DUPRAT(frac, *px);
|
||||
fracrat(&frac, radix, precision);
|
||||
|
||||
// Check for negative integers and throw an error.
|
||||
if ( ( zerrat(frac) || ( LOGRATRADIX(frac) <= -precision) ) &&
|
||||
( (*px)->pp->sign * (*px)->pq->sign == -1 ) )
|
||||
{
|
||||
if ((zerrat(frac) || (LOGRATRADIX(frac) <= -precision)) && (SIGN(*px) == -1))
|
||||
{
|
||||
throw CALC_E_DOMAIN;
|
||||
}
|
||||
while ( rat_gt( *px, rat_zero, precision) &&
|
||||
( LOGRATRADIX(*px) > -precision) )
|
||||
{
|
||||
mulrat( &fact, *px, precision);
|
||||
subrat( px, rat_one, precision);
|
||||
}
|
||||
}
|
||||
while (rat_gt(*px, rat_zero, precision) && (LOGRATRADIX(*px) > -precision))
|
||||
{
|
||||
mulrat(&fact, *px, precision);
|
||||
subrat(px, rat_one, precision);
|
||||
}
|
||||
|
||||
// Added to make numbers 'close enough' to integers use integer factorial.
|
||||
if ( LOGRATRADIX(*px) <= -precision)
|
||||
{
|
||||
DUPRAT((*px),rat_zero);
|
||||
if (LOGRATRADIX(*px) <= -precision)
|
||||
{
|
||||
DUPRAT((*px), rat_zero);
|
||||
intrat(&fact, radix, precision);
|
||||
}
|
||||
}
|
||||
|
||||
while ( rat_lt( *px, neg_rat_one, precision) )
|
||||
{
|
||||
addrat( px, rat_one, precision);
|
||||
divrat( &fact, *px, precision);
|
||||
}
|
||||
while (rat_lt(*px, neg_rat_one, precision))
|
||||
{
|
||||
addrat(px, rat_one, precision);
|
||||
divrat(&fact, *px, precision);
|
||||
}
|
||||
|
||||
if ( rat_neq( *px, rat_zero, precision) )
|
||||
{
|
||||
addrat( px, rat_one, precision);
|
||||
_gamma( px, radix, precision);
|
||||
mulrat( px, fact, precision);
|
||||
}
|
||||
if (rat_neq(*px, rat_zero, precision))
|
||||
{
|
||||
addrat(px, rat_one, precision);
|
||||
_gamma(px, radix, precision);
|
||||
mulrat(px, fact, precision);
|
||||
}
|
||||
else
|
||||
{
|
||||
DUPRAT(*px,fact);
|
||||
}
|
||||
{
|
||||
DUPRAT(*px, fact);
|
||||
}
|
||||
|
||||
destroyrat(fact);
|
||||
destroyrat(frac);
|
||||
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.
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -15,29 +15,25 @@
|
||||
// Special Information
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "pch.h"
|
||||
#include "ratpak.h"
|
||||
|
||||
|
||||
|
||||
void ascalerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, int32_t precision)
|
||||
void ascalerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, int32_t precision)
|
||||
{
|
||||
switch ( angletype )
|
||||
{
|
||||
switch (angletype)
|
||||
{
|
||||
case ANGLE_RAD:
|
||||
break;
|
||||
case ANGLE_DEG:
|
||||
divrat( pa, two_pi, precision);
|
||||
mulrat( pa, rat_360, precision);
|
||||
divrat(pa, two_pi, precision);
|
||||
mulrat(pa, rat_360, precision);
|
||||
break;
|
||||
case ANGLE_GRAD:
|
||||
divrat( pa, two_pi, precision);
|
||||
mulrat( pa, rat_400, precision);
|
||||
divrat(pa, two_pi, precision);
|
||||
mulrat(pa, rat_400, precision);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: asinrat, _asinrat
|
||||
@@ -65,88 +61,83 @@ void ascalerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, int32_t precision)
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void _asinrat( PRAT *px, int32_t precision)
|
||||
void _asinrat(PRAT* px, int32_t precision)
|
||||
|
||||
{
|
||||
CREATETAYLOR();
|
||||
DUPRAT(pret,*px);
|
||||
DUPRAT(thisterm,*px);
|
||||
DUPNUM(n2,num_one);
|
||||
DUPRAT(pret, *px);
|
||||
DUPRAT(thisterm, *px);
|
||||
DUPNUM(n2, num_one);
|
||||
|
||||
do
|
||||
{
|
||||
NEXTTERM(xx,MULNUM(n2) MULNUM(n2)
|
||||
INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
}
|
||||
while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
|
||||
{
|
||||
NEXTTERM(xx, MULNUM(n2) MULNUM(n2) INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
||||
DESTROYTAYLOR();
|
||||
}
|
||||
|
||||
void asinanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
|
||||
void asinanglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
asinrat( pa, radix, precision);
|
||||
ascalerat( pa, angletype, precision);
|
||||
asinrat(pa, radix, precision);
|
||||
ascalerat(pa, angletype, precision);
|
||||
}
|
||||
|
||||
void asinrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||
void asinrat(PRAT* px, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
int32_t sgn;
|
||||
PRAT pret= nullptr;
|
||||
PRAT phack= nullptr;
|
||||
|
||||
sgn = (*px)->pp->sign* (*px)->pq->sign;
|
||||
PRAT pret = nullptr;
|
||||
PRAT phack = nullptr;
|
||||
int32_t sgn = SIGN(*px);
|
||||
|
||||
(*px)->pp->sign = 1;
|
||||
(*px)->pq->sign = 1;
|
||||
|
||||
// Avoid the really bad part of the asin curve near +/-1.
|
||||
DUPRAT(phack,*px);
|
||||
DUPRAT(phack, *px);
|
||||
subrat(&phack, rat_one, precision);
|
||||
// Since *px might be epsilon near zero we must set it to zero.
|
||||
if ( rat_le(phack, rat_smallest, precision) && rat_ge(phack, rat_negsmallest, precision) )
|
||||
{
|
||||
if (rat_le(phack, rat_smallest, precision) && rat_ge(phack, rat_negsmallest, precision))
|
||||
{
|
||||
destroyrat(phack);
|
||||
DUPRAT( *px, pi_over_two );
|
||||
}
|
||||
DUPRAT(*px, pi_over_two);
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
destroyrat(phack);
|
||||
if ( rat_gt( *px, pt_eight_five, precision) )
|
||||
if (rat_gt(*px, pt_eight_five, precision))
|
||||
{
|
||||
if (rat_gt(*px, rat_one, precision))
|
||||
{
|
||||
if ( rat_gt( *px, rat_one, precision) )
|
||||
subrat(px, rat_one, precision);
|
||||
if (rat_gt(*px, rat_smallest, precision))
|
||||
{
|
||||
subrat( px, rat_one, precision);
|
||||
if ( rat_gt( *px, rat_smallest, precision) )
|
||||
{
|
||||
throw( CALC_E_DOMAIN );
|
||||
}
|
||||
else
|
||||
{
|
||||
DUPRAT(*px,rat_one);
|
||||
}
|
||||
throw(CALC_E_DOMAIN);
|
||||
}
|
||||
DUPRAT(pret,*px);
|
||||
mulrat( px, pret, precision);
|
||||
else
|
||||
{
|
||||
DUPRAT(*px, rat_one);
|
||||
}
|
||||
}
|
||||
DUPRAT(pret, *px);
|
||||
mulrat(px, pret, precision);
|
||||
(*px)->pp->sign *= -1;
|
||||
addrat( px, rat_one, precision);
|
||||
rootrat( px, rat_two, radix, precision);
|
||||
_asinrat( px, precision);
|
||||
addrat(px, rat_one, precision);
|
||||
rootrat(px, rat_two, radix, precision);
|
||||
_asinrat(px, precision);
|
||||
(*px)->pp->sign *= -1;
|
||||
addrat( px, pi_over_two, precision);
|
||||
addrat(px, pi_over_two, precision);
|
||||
destroyrat(pret);
|
||||
}
|
||||
else
|
||||
{
|
||||
_asinrat( px, precision);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_asinrat(px, precision);
|
||||
}
|
||||
}
|
||||
(*px)->pp->sign = sgn;
|
||||
(*px)->pq->sign = 1;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: acosrat, _acosrat
|
||||
@@ -173,62 +164,58 @@ void asinrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void acosanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
|
||||
void acosanglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
acosrat( pa, radix, precision);
|
||||
ascalerat( pa, angletype, precision);
|
||||
acosrat(pa, radix, precision);
|
||||
ascalerat(pa, angletype, precision);
|
||||
}
|
||||
|
||||
void _acosrat( PRAT *px, int32_t precision)
|
||||
void _acosrat(PRAT* px, int32_t precision)
|
||||
|
||||
{
|
||||
CREATETAYLOR();
|
||||
|
||||
createrat(thisterm);
|
||||
thisterm->pp=i32tonum( 1L, BASEX );
|
||||
thisterm->pq=i32tonum( 1L, BASEX );
|
||||
thisterm->pp = i32tonum(1L, BASEX);
|
||||
thisterm->pq = i32tonum(1L, BASEX);
|
||||
|
||||
DUPNUM(n2,num_one);
|
||||
DUPNUM(n2, num_one);
|
||||
|
||||
do
|
||||
{
|
||||
NEXTTERM(xx,MULNUM(n2) MULNUM(n2)
|
||||
INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
}
|
||||
while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
|
||||
{
|
||||
NEXTTERM(xx, MULNUM(n2) MULNUM(n2) INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
||||
|
||||
DESTROYTAYLOR();
|
||||
}
|
||||
|
||||
void acosrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||
void acosrat(PRAT* px, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
int32_t sgn;
|
||||
|
||||
sgn = (*px)->pp->sign*(*px)->pq->sign;
|
||||
int32_t sgn = SIGN(*px);
|
||||
|
||||
(*px)->pp->sign = 1;
|
||||
(*px)->pq->sign = 1;
|
||||
|
||||
if ( rat_equ( *px, rat_one, precision) )
|
||||
if (rat_equ(*px, rat_one, precision))
|
||||
{
|
||||
if (sgn == -1)
|
||||
{
|
||||
if ( sgn == -1 )
|
||||
{
|
||||
DUPRAT(*px,pi);
|
||||
}
|
||||
else
|
||||
{
|
||||
DUPRAT( *px, rat_zero );
|
||||
}
|
||||
DUPRAT(*px, pi);
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
DUPRAT(*px, rat_zero);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
(*px)->pp->sign = sgn;
|
||||
asinrat( px, radix, precision);
|
||||
asinrat(px, radix, precision);
|
||||
(*px)->pp->sign *= -1;
|
||||
addrat(px, pi_over_two, precision);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -262,81 +249,79 @@ void acosrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void atananglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
|
||||
void atananglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
atanrat( pa, radix, precision);
|
||||
ascalerat( pa, angletype, precision);
|
||||
atanrat(pa, radix, precision);
|
||||
ascalerat(pa, angletype, precision);
|
||||
}
|
||||
|
||||
void _atanrat( PRAT *px, int32_t precision)
|
||||
void _atanrat(PRAT* px, int32_t precision)
|
||||
|
||||
{
|
||||
CREATETAYLOR();
|
||||
|
||||
DUPRAT(pret,*px);
|
||||
DUPRAT(thisterm,*px);
|
||||
DUPRAT(pret, *px);
|
||||
DUPRAT(thisterm, *px);
|
||||
|
||||
DUPNUM(n2,num_one);
|
||||
DUPNUM(n2, num_one);
|
||||
|
||||
xx->pp->sign *= -1;
|
||||
|
||||
do {
|
||||
NEXTTERM(xx,MULNUM(n2) INC(n2) INC(n2) DIVNUM(n2), precision);
|
||||
} while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
|
||||
do
|
||||
{
|
||||
NEXTTERM(xx, MULNUM(n2) INC(n2) INC(n2) DIVNUM(n2), precision);
|
||||
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
||||
|
||||
DESTROYTAYLOR();
|
||||
}
|
||||
|
||||
void atanrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||
void atanrat(PRAT* px, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
int32_t sgn;
|
||||
PRAT tmpx= nullptr;
|
||||
|
||||
sgn = (*px)->pp->sign * (*px)->pq->sign;
|
||||
PRAT tmpx = nullptr;
|
||||
int32_t sgn = SIGN(*px);
|
||||
|
||||
(*px)->pp->sign = 1;
|
||||
(*px)->pq->sign = 1;
|
||||
|
||||
if ( rat_gt( (*px), pt_eight_five, precision) )
|
||||
if (rat_gt((*px), pt_eight_five, precision))
|
||||
{
|
||||
if (rat_gt((*px), rat_two, precision))
|
||||
{
|
||||
if ( rat_gt( (*px), rat_two, precision) )
|
||||
{
|
||||
(*px)->pp->sign = sgn;
|
||||
(*px)->pq->sign = 1;
|
||||
DUPRAT(tmpx,rat_one);
|
||||
DUPRAT(tmpx, rat_one);
|
||||
divrat(&tmpx, (*px), precision);
|
||||
_atanrat(&tmpx, precision);
|
||||
tmpx->pp->sign = sgn;
|
||||
tmpx->pq->sign = 1;
|
||||
DUPRAT(*px,pi_over_two);
|
||||
DUPRAT(*px, pi_over_two);
|
||||
subrat(px, tmpx, precision);
|
||||
destroyrat( tmpx );
|
||||
}
|
||||
destroyrat(tmpx);
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
(*px)->pp->sign = sgn;
|
||||
DUPRAT(tmpx,*px);
|
||||
mulrat( &tmpx, *px, precision);
|
||||
addrat( &tmpx, rat_one, precision);
|
||||
rootrat( &tmpx, rat_two, radix, precision);
|
||||
divrat( px, tmpx, precision);
|
||||
destroyrat( tmpx );
|
||||
asinrat( px, radix, precision);
|
||||
DUPRAT(tmpx, *px);
|
||||
mulrat(&tmpx, *px, precision);
|
||||
addrat(&tmpx, rat_one, precision);
|
||||
rootrat(&tmpx, rat_two, radix, precision);
|
||||
divrat(px, tmpx, precision);
|
||||
destroyrat(tmpx);
|
||||
asinrat(px, radix, precision);
|
||||
(*px)->pp->sign = sgn;
|
||||
(*px)->pq->sign = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
(*px)->pp->sign = sgn;
|
||||
(*px)->pq->sign = 1;
|
||||
_atanrat( px, precision);
|
||||
}
|
||||
if ( rat_gt( *px, pi_over_two, precision) )
|
||||
{
|
||||
subrat( px, pi, precision);
|
||||
}
|
||||
_atanrat(px, precision);
|
||||
}
|
||||
if (rat_gt(*px, pi_over_two, precision))
|
||||
{
|
||||
subrat(px, pi, precision);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -16,11 +16,8 @@
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "pch.h"
|
||||
#include "ratpak.h"
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: asinhrat
|
||||
@@ -50,47 +47,44 @@
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void asinhrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||
void asinhrat(PRAT* px, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
PRAT neg_pt_eight_five = nullptr;
|
||||
|
||||
DUPRAT(neg_pt_eight_five,pt_eight_five);
|
||||
DUPRAT(neg_pt_eight_five, pt_eight_five);
|
||||
neg_pt_eight_five->pp->sign *= -1;
|
||||
if ( rat_gt( *px, pt_eight_five, precision) || rat_lt( *px, neg_pt_eight_five, precision) )
|
||||
{
|
||||
if (rat_gt(*px, pt_eight_five, precision) || rat_lt(*px, neg_pt_eight_five, precision))
|
||||
{
|
||||
PRAT ptmp = nullptr;
|
||||
DUPRAT(ptmp,(*px));
|
||||
DUPRAT(ptmp, (*px));
|
||||
mulrat(&ptmp, *px, precision);
|
||||
addrat(&ptmp, rat_one, precision);
|
||||
rootrat(&ptmp, rat_two, radix, precision);
|
||||
addrat(px, ptmp, precision);
|
||||
lograt(px, precision);
|
||||
destroyrat(ptmp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
CREATETAYLOR();
|
||||
xx->pp->sign *= -1;
|
||||
|
||||
DUPRAT(pret,(*px));
|
||||
DUPRAT(thisterm,(*px));
|
||||
DUPRAT(pret, (*px));
|
||||
DUPRAT(thisterm, (*px));
|
||||
|
||||
DUPNUM(n2,num_one);
|
||||
DUPNUM(n2, num_one);
|
||||
|
||||
do
|
||||
{
|
||||
NEXTTERM(xx,MULNUM(n2) MULNUM(n2)
|
||||
INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
}
|
||||
while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
|
||||
{
|
||||
NEXTTERM(xx, MULNUM(n2) MULNUM(n2) INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
||||
|
||||
DESTROYTAYLOR();
|
||||
}
|
||||
}
|
||||
destroyrat(neg_pt_eight_five);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: acoshrat
|
||||
@@ -107,24 +101,24 @@ void asinhrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void acoshrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||
void acoshrat(PRAT* px, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
if ( rat_lt( *px, rat_one, precision) )
|
||||
{
|
||||
if (rat_lt(*px, rat_one, precision))
|
||||
{
|
||||
throw CALC_E_DOMAIN;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
PRAT ptmp = nullptr;
|
||||
DUPRAT(ptmp,(*px));
|
||||
DUPRAT(ptmp, (*px));
|
||||
mulrat(&ptmp, *px, precision);
|
||||
subrat(&ptmp, rat_one, precision);
|
||||
rootrat(&ptmp,rat_two, radix, precision);
|
||||
rootrat(&ptmp, rat_two, radix, precision);
|
||||
addrat(px, ptmp, precision);
|
||||
lograt(px, precision);
|
||||
destroyrat(ptmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -144,11 +138,11 @@ void acoshrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void atanhrat( PRAT *px, int32_t precision)
|
||||
void atanhrat(PRAT* px, int32_t precision)
|
||||
|
||||
{
|
||||
PRAT ptmp = nullptr;
|
||||
DUPRAT(ptmp,(*px));
|
||||
DUPRAT(ptmp, (*px));
|
||||
subrat(&ptmp, rat_one, precision);
|
||||
addrat(px, rat_one, precision);
|
||||
divrat(px, ptmp, precision);
|
||||
@@ -157,4 +151,3 @@ void atanhrat( PRAT *px, int32_t precision)
|
||||
divrat(px, rat_two, precision);
|
||||
destroyrat(ptmp);
|
||||
}
|
||||
|
||||
|
@@ -13,83 +13,82 @@
|
||||
// Contains routines for and, or, xor, not and other support
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
#include "pch.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;
|
||||
int32_t intb;
|
||||
|
||||
intrat(pa, radix, precision);
|
||||
if ( !zernum( (*pa)->pp ) )
|
||||
{
|
||||
if (!zernum((*pa)->pp))
|
||||
{
|
||||
// If input is zero we're done.
|
||||
if ( rat_gt( b, rat_max_exp, precision) )
|
||||
{
|
||||
if (rat_gt(b, rat_max_exp, precision))
|
||||
{
|
||||
// Don't attempt lsh of anything big
|
||||
throw( CALC_E_DOMAIN );
|
||||
}
|
||||
throw(CALC_E_DOMAIN);
|
||||
}
|
||||
intb = rattoi32(b, radix, precision);
|
||||
DUPRAT(pwr,rat_two);
|
||||
DUPRAT(pwr, rat_two);
|
||||
ratpowi32(&pwr, intb, precision);
|
||||
mulrat(pa, pwr, precision);
|
||||
destroyrat(pwr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void rshrat( PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
|
||||
void rshrat(PRAT* pa, PRAT b, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
PRAT pwr= nullptr;
|
||||
PRAT pwr = nullptr;
|
||||
int32_t intb;
|
||||
|
||||
intrat(pa, radix, precision);
|
||||
if ( !zernum( (*pa)->pp ) )
|
||||
{
|
||||
if (!zernum((*pa)->pp))
|
||||
{
|
||||
// If input is zero we're done.
|
||||
if ( rat_lt( b, rat_min_exp, precision) )
|
||||
{
|
||||
if (rat_lt(b, rat_min_exp, precision))
|
||||
{
|
||||
// Don't attempt rsh of anything big and negative.
|
||||
throw( CALC_E_DOMAIN );
|
||||
}
|
||||
throw(CALC_E_DOMAIN);
|
||||
}
|
||||
intb = rattoi32(b, radix, precision);
|
||||
DUPRAT(pwr,rat_two);
|
||||
DUPRAT(pwr, rat_two);
|
||||
ratpowi32(&pwr, intb, precision);
|
||||
divrat(pa, pwr, precision);
|
||||
destroyrat(pwr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void boolrat( PRAT *pa, PRAT b, int func, uint32_t radix, int32_t precision);
|
||||
void boolnum( PNUMBER *pa, PNUMBER b, int func );
|
||||
void boolrat(PRAT* pa, PRAT b, int func, uint32_t radix, int32_t precision);
|
||||
void boolnum(PNUMBER* pa, PNUMBER b, int func);
|
||||
|
||||
|
||||
enum {
|
||||
enum
|
||||
{
|
||||
FUNC_AND,
|
||||
FUNC_OR,
|
||||
FUNC_XOR
|
||||
} BOOL_FUNCS;
|
||||
|
||||
void andrat( PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
|
||||
void andrat(PRAT* pa, PRAT b, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
boolrat( pa, b, FUNC_AND, radix, precision);
|
||||
boolrat(pa, b, FUNC_AND, radix, precision);
|
||||
}
|
||||
|
||||
void orrat( PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
|
||||
void orrat(PRAT* pa, PRAT b, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
boolrat( pa, b, FUNC_OR, radix, precision);
|
||||
boolrat(pa, b, FUNC_OR, radix, precision);
|
||||
}
|
||||
|
||||
void xorrat( PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
|
||||
void xorrat(PRAT* pa, PRAT b, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
boolrat( pa, b, FUNC_XOR, radix, precision);
|
||||
boolrat(pa, b, FUNC_XOR, radix, precision);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
@@ -104,15 +103,15 @@ void xorrat( PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void boolrat( PRAT *pa, PRAT b, int func, uint32_t radix, int32_t precision)
|
||||
void boolrat(PRAT* pa, PRAT b, int func, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
PRAT tmp= nullptr;
|
||||
intrat( pa, radix, precision);
|
||||
DUPRAT(tmp,b);
|
||||
intrat( &tmp, radix, precision);
|
||||
PRAT tmp = nullptr;
|
||||
intrat(pa, radix, precision);
|
||||
DUPRAT(tmp, b);
|
||||
intrat(&tmp, radix, precision);
|
||||
|
||||
boolnum( &((*pa)->pp), tmp->pp, func );
|
||||
boolnum(&((*pa)->pp), tmp->pp, func);
|
||||
destroyrat(tmp);
|
||||
}
|
||||
|
||||
@@ -130,39 +129,34 @@ void boolrat( PRAT *pa, PRAT b, int func, uint32_t radix, int32_t precision)
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void boolnum( PNUMBER *pa, PNUMBER b, int func )
|
||||
void boolnum(PNUMBER* pa, PNUMBER b, int func)
|
||||
|
||||
{
|
||||
PNUMBER c= nullptr;
|
||||
PNUMBER a= nullptr;
|
||||
MANTTYPE *pcha;
|
||||
MANTTYPE *pchb;
|
||||
MANTTYPE *pchc;
|
||||
PNUMBER c = nullptr;
|
||||
PNUMBER a = nullptr;
|
||||
MANTTYPE* pcha;
|
||||
MANTTYPE* pchb;
|
||||
MANTTYPE* pchc;
|
||||
int32_t cdigits;
|
||||
int32_t mexp;
|
||||
MANTTYPE da;
|
||||
MANTTYPE db;
|
||||
|
||||
a=*pa;
|
||||
cdigits = max( a->cdigit+a->exp, b->cdigit+b->exp ) -
|
||||
min( a->exp, b->exp );
|
||||
createnum( c, cdigits );
|
||||
c->exp = min( a->exp, b->exp );
|
||||
a = *pa;
|
||||
cdigits = max(a->cdigit + a->exp, b->cdigit + b->exp) - min(a->exp, b->exp);
|
||||
createnum(c, cdigits);
|
||||
c->exp = min(a->exp, b->exp);
|
||||
mexp = c->exp;
|
||||
c->cdigit = cdigits;
|
||||
pcha = a->mant;
|
||||
pchb = b->mant;
|
||||
pchc = c->mant;
|
||||
for ( ;cdigits > 0; cdigits--, mexp++ )
|
||||
for (; cdigits > 0; cdigits--, mexp++)
|
||||
{
|
||||
da = (((mexp >= a->exp) && (cdigits + a->exp - c->exp > (c->cdigit - a->cdigit))) ? *pcha++ : 0);
|
||||
db = (((mexp >= b->exp) && (cdigits + b->exp - c->exp > (c->cdigit - b->cdigit))) ? *pchb++ : 0);
|
||||
switch (func)
|
||||
{
|
||||
da = ( ( ( mexp >= a->exp ) && ( cdigits + a->exp - c->exp >
|
||||
(c->cdigit - a->cdigit) ) ) ?
|
||||
*pcha++ : 0 );
|
||||
db = ( ( ( mexp >= b->exp ) && ( cdigits + b->exp - c->exp >
|
||||
(c->cdigit - b->cdigit) ) ) ?
|
||||
*pchb++ : 0 );
|
||||
switch ( func )
|
||||
{
|
||||
case FUNC_AND:
|
||||
*pchc++ = da & db;
|
||||
break;
|
||||
@@ -172,15 +166,51 @@ void boolnum( PNUMBER *pa, PNUMBER b, int func )
|
||||
case FUNC_XOR:
|
||||
*pchc++ = da ^ db;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
c->sign = a->sign;
|
||||
while ( c->cdigit > 1 && *(--pchc) == 0 )
|
||||
{
|
||||
while (c->cdigit > 1 && *(--pchc) == 0)
|
||||
{
|
||||
c->cdigit--;
|
||||
}
|
||||
destroynum( *pa );
|
||||
*pa=c;
|
||||
}
|
||||
destroynum(*pa);
|
||||
*pa = c;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: remrat
|
||||
//
|
||||
// ARGUMENTS: pointer to a rational a second rational.
|
||||
//
|
||||
// RETURN: None, changes pointer.
|
||||
//
|
||||
// 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 remrat(PRAT* pa, PRAT b)
|
||||
|
||||
{
|
||||
if (zerrat(b))
|
||||
{
|
||||
throw CALC_E_INDEFINITE;
|
||||
}
|
||||
|
||||
PRAT tmp = nullptr;
|
||||
DUPRAT(tmp, b);
|
||||
|
||||
mulnumx(&((*pa)->pp), tmp->pq);
|
||||
mulnumx(&(tmp->pp), (*pa)->pq);
|
||||
remnum(&((*pa)->pp), tmp->pp, BASEX);
|
||||
mulnumx(&((*pa)->pq), tmp->pq);
|
||||
|
||||
// Get *pa back in the integer over integer form.
|
||||
RENORMALIZE(*pa);
|
||||
|
||||
destroyrat(tmp);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -191,28 +221,38 @@ void boolnum( PNUMBER *pa, PNUMBER b, int func )
|
||||
//
|
||||
// RETURN: None, changes pointer.
|
||||
//
|
||||
// DESCRIPTION: Does the rational equivalent of frac(*pa);
|
||||
// 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 )
|
||||
|
||||
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);
|
||||
|
||||
if ( zerrat( b ) )
|
||||
{
|
||||
throw CALC_E_INDEFINITE;
|
||||
}
|
||||
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 );
|
||||
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 );
|
||||
destroyrat(tmp);
|
||||
}
|
||||
|
@@ -17,7 +17,8 @@
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "pch.h"
|
||||
#include <list>
|
||||
#include <cstring> // for memmove
|
||||
#include "ratpak.h"
|
||||
|
||||
using namespace std;
|
||||
@@ -40,51 +41,49 @@ using namespace std;
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix);
|
||||
void _addnum(PNUMBER* pa, PNUMBER b, uint32_t radix);
|
||||
|
||||
void __inline addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
||||
void addnum(PNUMBER* pa, PNUMBER b, uint32_t radix)
|
||||
|
||||
{
|
||||
if ( b->cdigit > 1 || b->mant[0] != 0 )
|
||||
{ // If b is zero we are done.
|
||||
if ( (*pa)->cdigit > 1 || (*pa)->mant[0] != 0 )
|
||||
{ // pa and b are both nonzero.
|
||||
_addnum( pa, b, radix);
|
||||
}
|
||||
else
|
||||
{ // if pa is zero and b isn't just copy b.
|
||||
DUPNUM(*pa,b);
|
||||
}
|
||||
if (b->cdigit > 1 || b->mant[0] != 0)
|
||||
{ // If b is zero we are done.
|
||||
if ((*pa)->cdigit > 1 || (*pa)->mant[0] != 0)
|
||||
{ // pa and b are both nonzero.
|
||||
_addnum(pa, b, radix);
|
||||
}
|
||||
else
|
||||
{ // if pa is zero and b isn't just copy b.
|
||||
DUPNUM(*pa, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
||||
void _addnum(PNUMBER* pa, PNUMBER b, uint32_t radix)
|
||||
|
||||
{
|
||||
PNUMBER c= nullptr; // c will contain the result.
|
||||
PNUMBER a= nullptr; // a is the dereferenced number pointer from *pa
|
||||
MANTTYPE *pcha; // pcha is a pointer to the mantissa of a.
|
||||
MANTTYPE *pchb; // pchb is a pointer to the mantissa of b.
|
||||
MANTTYPE *pchc; // pchc is a pointer to the mantissa of c.
|
||||
int32_t cdigits; // cdigits is the max count of the digits results
|
||||
// used as a counter.
|
||||
int32_t mexp; // mexp is the exponent of the result.
|
||||
MANTTYPE da; // da is a single 'digit' after possible padding.
|
||||
MANTTYPE db; // db is a single 'digit' after possible padding.
|
||||
MANTTYPE cy=0; // cy is the value of a carry after adding two 'digits'
|
||||
int32_t fcompla = 0; // fcompla is a flag to signal a is negative.
|
||||
int32_t fcomplb = 0; // fcomplb is a flag to signal b is negative.
|
||||
|
||||
a=*pa;
|
||||
PNUMBER c = nullptr; // c will contain the result.
|
||||
PNUMBER a = nullptr; // a is the dereferenced number pointer from *pa
|
||||
MANTTYPE* pcha; // pcha is a pointer to the mantissa of a.
|
||||
MANTTYPE* pchb; // pchb is a pointer to the mantissa of b.
|
||||
MANTTYPE* pchc; // pchc is a pointer to the mantissa of c.
|
||||
int32_t cdigits; // cdigits is the max count of the digits results
|
||||
// used as a counter.
|
||||
int32_t mexp; // mexp is the exponent of the result.
|
||||
MANTTYPE da; // da is a single 'digit' after possible padding.
|
||||
MANTTYPE db; // db is a single 'digit' after possible padding.
|
||||
MANTTYPE cy = 0; // cy is the value of a carry after adding two 'digits'
|
||||
int32_t fcompla = 0; // fcompla is a flag to signal a is negative.
|
||||
int32_t fcomplb = 0; // fcomplb is a flag to signal b is negative.
|
||||
|
||||
a = *pa;
|
||||
|
||||
// Calculate the overlap of the numbers after alignment, this includes
|
||||
// necessary padding 0's
|
||||
cdigits = max( a->cdigit+a->exp, b->cdigit+b->exp ) -
|
||||
min( a->exp, b->exp );
|
||||
cdigits = max(a->cdigit + a->exp, b->cdigit + b->exp) - min(a->exp, b->exp);
|
||||
|
||||
createnum( c, cdigits + 1 );
|
||||
c->exp = min( a->exp, b->exp );
|
||||
createnum(c, cdigits + 1);
|
||||
c->exp = min(a->exp, b->exp);
|
||||
mexp = c->exp;
|
||||
c->cdigit = cdigits;
|
||||
pcha = a->mant;
|
||||
@@ -92,89 +91,82 @@ void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
||||
pchc = c->mant;
|
||||
|
||||
// Figure out the sign of the numbers
|
||||
if ( a->sign != b->sign )
|
||||
{
|
||||
if (a->sign != b->sign)
|
||||
{
|
||||
cy = 1;
|
||||
fcompla = ( a->sign == -1 );
|
||||
fcomplb = ( b->sign == -1 );
|
||||
}
|
||||
fcompla = (a->sign == -1);
|
||||
fcomplb = (b->sign == -1);
|
||||
}
|
||||
|
||||
// Loop over all the digits, real and 0 padded. Here we know a and b are
|
||||
// aligned
|
||||
for ( ;cdigits > 0; cdigits--, mexp++ )
|
||||
{
|
||||
|
||||
for (; cdigits > 0; cdigits--, mexp++)
|
||||
{
|
||||
// Get digit from a, taking padding into account.
|
||||
da = ( ( ( mexp >= a->exp ) && ( cdigits + a->exp - c->exp >
|
||||
(c->cdigit - a->cdigit) ) ) ?
|
||||
*pcha++ : 0 );
|
||||
da = (((mexp >= a->exp) && (cdigits + a->exp - c->exp > (c->cdigit - a->cdigit))) ? *pcha++ : 0);
|
||||
// Get digit from b, taking padding into account.
|
||||
db = ( ( ( mexp >= b->exp ) && ( cdigits + b->exp - c->exp >
|
||||
(c->cdigit - b->cdigit) ) ) ?
|
||||
*pchb++ : 0 );
|
||||
db = (((mexp >= b->exp) && (cdigits + b->exp - c->exp > (c->cdigit - b->cdigit))) ? *pchb++ : 0);
|
||||
|
||||
// Handle complementing for a and b digit. Might be a better way, but
|
||||
// haven't found it yet.
|
||||
if ( fcompla )
|
||||
{
|
||||
da = (MANTTYPE)(radix) - 1 - da;
|
||||
}
|
||||
if ( fcomplb )
|
||||
{
|
||||
db = (MANTTYPE)(radix) - 1 - db;
|
||||
}
|
||||
if (fcompla)
|
||||
{
|
||||
da = (MANTTYPE)(radix)-1 - da;
|
||||
}
|
||||
if (fcomplb)
|
||||
{
|
||||
db = (MANTTYPE)(radix)-1 - db;
|
||||
}
|
||||
|
||||
// Update carry as necessary
|
||||
cy = da + db + cy;
|
||||
*pchc++ = (MANTTYPE)(cy % (MANTTYPE)radix);
|
||||
cy /= (MANTTYPE)radix;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle carry from last sum as extra digit
|
||||
if ( cy && !(fcompla || fcomplb) )
|
||||
{
|
||||
if (cy && !(fcompla || fcomplb))
|
||||
{
|
||||
*pchc++ = cy;
|
||||
c->cdigit++;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute sign of result
|
||||
if ( !(fcompla || fcomplb) )
|
||||
{
|
||||
if (!(fcompla || fcomplb))
|
||||
{
|
||||
c->sign = a->sign;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cy)
|
||||
{
|
||||
if ( cy )
|
||||
{
|
||||
c->sign = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
// In this particular case an overflow or underflow has occurred
|
||||
// and all the digits need to be complemented, at one time an
|
||||
// attempt to handle this above was made, it turned out to be much
|
||||
// slower on average.
|
||||
c->sign = -1;
|
||||
cy = 1;
|
||||
for ( ( cdigits = c->cdigit ), (pchc = c->mant);
|
||||
cdigits > 0;
|
||||
cdigits-- )
|
||||
{
|
||||
for ((cdigits = c->cdigit), (pchc = c->mant); cdigits > 0; cdigits--)
|
||||
{
|
||||
cy = (MANTTYPE)radix - (MANTTYPE)1 - *pchc + cy;
|
||||
*pchc++ = (MANTTYPE)( cy % (MANTTYPE)radix);
|
||||
*pchc++ = (MANTTYPE)(cy % (MANTTYPE)radix);
|
||||
cy /= (MANTTYPE)radix;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove leading zeros, remember digits are in order of
|
||||
// increasing significance. i.e. 100 would be 0,0,1
|
||||
while ( c->cdigit > 1 && *(--pchc) == 0 )
|
||||
{
|
||||
while (c->cdigit > 1 && *(--pchc) == 0)
|
||||
{
|
||||
c->cdigit--;
|
||||
}
|
||||
destroynum( *pa );
|
||||
*pa=c;
|
||||
}
|
||||
destroynum(*pa);
|
||||
*pa = c;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -192,52 +184,52 @@ void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix);
|
||||
void _mulnum(PNUMBER* pa, PNUMBER b, uint32_t radix);
|
||||
|
||||
void __inline mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
||||
void mulnum(PNUMBER* pa, PNUMBER b, uint32_t radix)
|
||||
|
||||
{
|
||||
if ( b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0 )
|
||||
{ // If b is one we don't multiply exactly.
|
||||
if ( (*pa)->cdigit > 1 || (*pa)->mant[0] != 1 || (*pa)->exp != 0 )
|
||||
{ // pa and b are both non-one.
|
||||
_mulnum( pa, b, radix);
|
||||
}
|
||||
if (b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0)
|
||||
{ // If b is one we don't multiply exactly.
|
||||
if ((*pa)->cdigit > 1 || (*pa)->mant[0] != 1 || (*pa)->exp != 0)
|
||||
{ // pa and b are both non-one.
|
||||
_mulnum(pa, b, radix);
|
||||
}
|
||||
else
|
||||
{ // if pa is one and b isn't just copy b, and adjust the sign.
|
||||
{ // if pa is one and b isn't just copy b, and adjust the sign.
|
||||
int32_t sign = (*pa)->sign;
|
||||
DUPNUM(*pa,b);
|
||||
DUPNUM(*pa, b);
|
||||
(*pa)->sign *= sign;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // But we do have to set the sign.
|
||||
{ // But we do have to set the sign.
|
||||
(*pa)->sign *= b->sign;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
||||
void _mulnum(PNUMBER* pa, PNUMBER b, uint32_t radix)
|
||||
|
||||
{
|
||||
PNUMBER c= nullptr; // c will contain the result.
|
||||
PNUMBER a= nullptr; // a is the dereferenced number pointer from *pa
|
||||
MANTTYPE *pcha; // pcha is a pointer to the mantissa of a.
|
||||
MANTTYPE *pchb; // pchb is a pointer to the mantissa of b.
|
||||
MANTTYPE *pchc; // pchc is a pointer to the mantissa of c.
|
||||
MANTTYPE *pchcoffset; // pchcoffset, is the anchor location of the next
|
||||
// single digit multiply partial result.
|
||||
int32_t iadigit = 0; // Index of digit being used in the first number.
|
||||
int32_t ibdigit = 0; // Index of digit being used in the second number.
|
||||
MANTTYPE da = 0; // da is the digit from the fist number.
|
||||
TWO_MANTTYPE cy = 0; // cy is the carry resulting from the addition of
|
||||
// a multiplied row into the result.
|
||||
TWO_MANTTYPE mcy = 0; // mcy is the resultant from a single
|
||||
// multiply, AND the carry of that multiply.
|
||||
int32_t icdigit = 0; // Index of digit being calculated in final result.
|
||||
PNUMBER c = nullptr; // c will contain the result.
|
||||
PNUMBER a = nullptr; // a is the dereferenced number pointer from *pa
|
||||
MANTTYPE* pcha; // pcha is a pointer to the mantissa of a.
|
||||
MANTTYPE* pchb; // pchb is a pointer to the mantissa of b.
|
||||
MANTTYPE* pchc; // pchc is a pointer to the mantissa of c.
|
||||
MANTTYPE* pchcoffset; // pchcoffset, is the anchor location of the next
|
||||
// single digit multiply partial result.
|
||||
int32_t iadigit = 0; // Index of digit being used in the first number.
|
||||
int32_t ibdigit = 0; // Index of digit being used in the second number.
|
||||
MANTTYPE da = 0; // da is the digit from the fist number.
|
||||
TWO_MANTTYPE cy = 0; // cy is the carry resulting from the addition of
|
||||
// a multiplied row into the result.
|
||||
TWO_MANTTYPE mcy = 0; // mcy is the resultant from a single
|
||||
// multiply, AND the carry of that multiply.
|
||||
int32_t icdigit = 0; // Index of digit being calculated in final result.
|
||||
|
||||
a=*pa;
|
||||
a = *pa;
|
||||
ibdigit = a->cdigit + b->cdigit - 1;
|
||||
createnum( c, ibdigit + 1 );
|
||||
createnum(c, ibdigit + 1);
|
||||
c->cdigit = ibdigit;
|
||||
c->sign = a->sign * b->sign;
|
||||
|
||||
@@ -245,58 +237,56 @@ void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
||||
pcha = a->mant;
|
||||
pchcoffset = c->mant;
|
||||
|
||||
for ( iadigit = a->cdigit; iadigit > 0; iadigit-- )
|
||||
{
|
||||
da = *pcha++;
|
||||
for (iadigit = a->cdigit; iadigit > 0; iadigit--)
|
||||
{
|
||||
da = *pcha++;
|
||||
pchb = b->mant;
|
||||
|
||||
// Shift pchc, and pchcoffset, one for each digit
|
||||
pchc = pchcoffset++;
|
||||
|
||||
for ( ibdigit = b->cdigit; ibdigit > 0; ibdigit-- )
|
||||
{
|
||||
for (ibdigit = b->cdigit; ibdigit > 0; ibdigit--)
|
||||
{
|
||||
cy = 0;
|
||||
mcy = (TWO_MANTTYPE)da * *pchb;
|
||||
if ( mcy )
|
||||
{
|
||||
if (mcy)
|
||||
{
|
||||
icdigit = 0;
|
||||
if ( ibdigit == 1 && iadigit == 1 )
|
||||
{
|
||||
c->cdigit++;
|
||||
}
|
||||
}
|
||||
// If result is nonzero, or while result of carry is nonzero...
|
||||
while ( mcy || cy )
|
||||
if (ibdigit == 1 && iadigit == 1)
|
||||
{
|
||||
|
||||
c->cdigit++;
|
||||
}
|
||||
}
|
||||
// If result is nonzero, or while result of carry is nonzero...
|
||||
while (mcy || cy)
|
||||
{
|
||||
// update carry from addition(s) and multiply.
|
||||
cy += (TWO_MANTTYPE)pchc[icdigit]+(mcy%(TWO_MANTTYPE)radix);
|
||||
cy += (TWO_MANTTYPE)pchc[icdigit] + (mcy % (TWO_MANTTYPE)radix);
|
||||
|
||||
// update result digit from
|
||||
pchc[icdigit++]=(MANTTYPE)(cy%(TWO_MANTTYPE)radix);
|
||||
pchc[icdigit++] = (MANTTYPE)(cy % (TWO_MANTTYPE)radix);
|
||||
|
||||
// update carries from
|
||||
mcy /= (TWO_MANTTYPE)radix;
|
||||
cy /= (TWO_MANTTYPE)radix;
|
||||
}
|
||||
}
|
||||
|
||||
pchb++;
|
||||
pchc++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// prevent different kinds of zeros, by stripping leading duplicate zeros.
|
||||
// digits are in order of increasing significance.
|
||||
while ( c->cdigit > 1 && c->mant[c->cdigit-1] == 0 )
|
||||
{
|
||||
while (c->cdigit > 1 && c->mant[c->cdigit - 1] == 0)
|
||||
{
|
||||
c->cdigit--;
|
||||
}
|
||||
}
|
||||
|
||||
destroynum( *pa );
|
||||
*pa=c;
|
||||
destroynum(*pa);
|
||||
*pa = c;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: remnum
|
||||
@@ -312,55 +302,53 @@ void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void remnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
||||
void remnum(PNUMBER* pa, PNUMBER b, uint32_t radix)
|
||||
|
||||
{
|
||||
PNUMBER tmp = nullptr; // tmp is the working remainder.
|
||||
PNUMBER lasttmp = nullptr; // lasttmp is the last remainder which worked.
|
||||
|
||||
// Once *pa is less than b, *pa is the remainder.
|
||||
while ( !lessnum( *pa, b ) )
|
||||
while (!lessnum(*pa, b))
|
||||
{
|
||||
DUPNUM(tmp, b);
|
||||
if (lessnum(tmp, *pa))
|
||||
{
|
||||
DUPNUM( tmp, b );
|
||||
if ( lessnum( tmp, *pa ) )
|
||||
{
|
||||
// Start off close to the right answer for subtraction.
|
||||
tmp->exp = (*pa)->cdigit+(*pa)->exp - tmp->cdigit;
|
||||
if ( MSD(*pa) <= MSD(tmp) )
|
||||
{
|
||||
tmp->exp = (*pa)->cdigit + (*pa)->exp - tmp->cdigit;
|
||||
if (MSD(*pa) <= MSD(tmp))
|
||||
{
|
||||
// Don't take the chance that the numbers are equal.
|
||||
tmp->exp--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
destroynum( lasttmp );
|
||||
lasttmp=i32tonum( 0, radix);
|
||||
destroynum(lasttmp);
|
||||
lasttmp = i32tonum(0, radix);
|
||||
|
||||
while ( lessnum( tmp, *pa ) )
|
||||
{
|
||||
DUPNUM( lasttmp, tmp );
|
||||
addnum( &tmp, tmp, radix);
|
||||
}
|
||||
while (lessnum(tmp, *pa))
|
||||
{
|
||||
DUPNUM(lasttmp, tmp);
|
||||
addnum(&tmp, tmp, radix);
|
||||
}
|
||||
|
||||
if ( lessnum( *pa, tmp ) )
|
||||
{
|
||||
if (lessnum(*pa, tmp))
|
||||
{
|
||||
// too far, back up...
|
||||
destroynum( tmp );
|
||||
tmp=lasttmp;
|
||||
lasttmp= nullptr;
|
||||
}
|
||||
destroynum(tmp);
|
||||
tmp = lasttmp;
|
||||
lasttmp = nullptr;
|
||||
}
|
||||
|
||||
// Subtract the working remainder from the remainder holder.
|
||||
tmp->sign = -1*(*pa)->sign;
|
||||
addnum( pa, tmp, radix);
|
||||
tmp->sign = -1 * (*pa)->sign;
|
||||
addnum(pa, tmp, radix);
|
||||
|
||||
destroynum( tmp );
|
||||
destroynum( lasttmp );
|
||||
|
||||
}
|
||||
destroynum(tmp);
|
||||
destroynum(lasttmp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: divnum
|
||||
@@ -375,23 +363,23 @@ void remnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision);
|
||||
void _divnum(PNUMBER* pa, PNUMBER b, uint32_t radix, int32_t precision);
|
||||
|
||||
void __inline divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
|
||||
void divnum(PNUMBER* pa, PNUMBER b, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
if ( b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0 )
|
||||
{
|
||||
if (b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0)
|
||||
{
|
||||
// b is not one
|
||||
_divnum( pa, b, radix, precision);
|
||||
}
|
||||
_divnum(pa, b, radix, precision);
|
||||
}
|
||||
else
|
||||
{ // But we do have to set the sign.
|
||||
{ // But we do have to set the sign.
|
||||
(*pa)->sign *= b->sign;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
int32_t thismax = precision + 2;
|
||||
@@ -410,7 +398,7 @@ void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
|
||||
c->exp = (a->cdigit + a->exp) - (b->cdigit + b->exp) + 1;
|
||||
c->sign = a->sign * b->sign;
|
||||
|
||||
MANTTYPE *ptrc = c->mant + thismax;
|
||||
MANTTYPE* ptrc = c->mant + thismax;
|
||||
PNUMBER rem = nullptr;
|
||||
PNUMBER tmp = nullptr;
|
||||
DUPNUM(rem, a);
|
||||
@@ -488,7 +476,6 @@ void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
|
||||
*pa = c;
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: equnum
|
||||
@@ -502,58 +489,56 @@ void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool equnum( PNUMBER a, PNUMBER b )
|
||||
bool equnum(PNUMBER a, PNUMBER b)
|
||||
|
||||
{
|
||||
int32_t diff;
|
||||
MANTTYPE *pa;
|
||||
MANTTYPE *pb;
|
||||
MANTTYPE* pa;
|
||||
MANTTYPE* pb;
|
||||
int32_t cdigits;
|
||||
int32_t ccdigits;
|
||||
MANTTYPE da;
|
||||
MANTTYPE db;
|
||||
MANTTYPE da;
|
||||
MANTTYPE db;
|
||||
|
||||
diff = ( a->cdigit + a->exp ) - ( b->cdigit + b->exp );
|
||||
if ( diff < 0 )
|
||||
{
|
||||
diff = (a->cdigit + a->exp) - (b->cdigit + b->exp);
|
||||
if (diff < 0)
|
||||
{
|
||||
// If the exponents are different, these are different numbers.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (diff > 0)
|
||||
{
|
||||
if ( diff > 0 )
|
||||
{
|
||||
// If the exponents are different, these are different numbers.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
// OK the exponents match.
|
||||
pa = a->mant;
|
||||
pb = b->mant;
|
||||
pa += a->cdigit - 1;
|
||||
pb += b->cdigit - 1;
|
||||
cdigits = max( a->cdigit, b->cdigit );
|
||||
cdigits = max(a->cdigit, b->cdigit);
|
||||
ccdigits = cdigits;
|
||||
|
||||
// Loop over all digits until we run out of digits or there is a
|
||||
// difference in the digits.
|
||||
for ( ;cdigits > 0; cdigits-- )
|
||||
for (; cdigits > 0; cdigits--)
|
||||
{
|
||||
da = ((cdigits > (ccdigits - a->cdigit)) ? *pa-- : 0);
|
||||
db = ((cdigits > (ccdigits - b->cdigit)) ? *pb-- : 0);
|
||||
if (da != db)
|
||||
{
|
||||
da = ( (cdigits > (ccdigits - a->cdigit) ) ?
|
||||
*pa-- : 0 );
|
||||
db = ( (cdigits > (ccdigits - b->cdigit) ) ?
|
||||
*pb-- : 0 );
|
||||
if ( da != db )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// In this case, they are equal.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
@@ -570,54 +555,51 @@ bool equnum( PNUMBER a, PNUMBER b )
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool lessnum( PNUMBER a, PNUMBER b )
|
||||
bool lessnum(PNUMBER a, PNUMBER b)
|
||||
|
||||
{
|
||||
int32_t diff;
|
||||
MANTTYPE *pa;
|
||||
MANTTYPE *pb;
|
||||
MANTTYPE* pa;
|
||||
MANTTYPE* pb;
|
||||
int32_t cdigits;
|
||||
int32_t ccdigits;
|
||||
MANTTYPE da;
|
||||
MANTTYPE db;
|
||||
MANTTYPE da;
|
||||
MANTTYPE db;
|
||||
|
||||
|
||||
diff = ( a->cdigit + a->exp ) - ( b->cdigit + b->exp );
|
||||
if ( diff < 0 )
|
||||
{
|
||||
diff = (a->cdigit + a->exp) - (b->cdigit + b->exp);
|
||||
if (diff < 0)
|
||||
{
|
||||
// The exponent of a is less than b
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (diff > 0)
|
||||
{
|
||||
if ( diff > 0 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
pa = a->mant;
|
||||
pb = b->mant;
|
||||
pa += a->cdigit - 1;
|
||||
pb += b->cdigit - 1;
|
||||
cdigits = max( a->cdigit, b->cdigit );
|
||||
cdigits = max(a->cdigit, b->cdigit);
|
||||
ccdigits = cdigits;
|
||||
for ( ;cdigits > 0; cdigits-- )
|
||||
for (; cdigits > 0; cdigits--)
|
||||
{
|
||||
da = ((cdigits > (ccdigits - a->cdigit)) ? *pa-- : 0);
|
||||
db = ((cdigits > (ccdigits - b->cdigit)) ? *pb-- : 0);
|
||||
diff = da - db;
|
||||
if (diff)
|
||||
{
|
||||
da = ( (cdigits > (ccdigits - a->cdigit) ) ?
|
||||
*pa-- : 0 );
|
||||
db = ( (cdigits > (ccdigits - b->cdigit) ) ?
|
||||
*pb-- : 0 );
|
||||
diff = da-db;
|
||||
if ( diff )
|
||||
{
|
||||
return( diff < 0 );
|
||||
}
|
||||
return (diff < 0);
|
||||
}
|
||||
}
|
||||
// In this case, they are equal.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -632,24 +614,24 @@ bool lessnum( PNUMBER a, PNUMBER b )
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
bool zernum( PNUMBER a )
|
||||
bool zernum(PNUMBER a)
|
||||
|
||||
{
|
||||
int32_t length;
|
||||
MANTTYPE *pcha;
|
||||
MANTTYPE* pcha;
|
||||
length = a->cdigit;
|
||||
pcha = a->mant;
|
||||
|
||||
// loop over all the digits until you find a nonzero or until you run
|
||||
// out of digits
|
||||
while ( length-- > 0 )
|
||||
while (length-- > 0)
|
||||
{
|
||||
if (*pcha++)
|
||||
{
|
||||
if ( *pcha++ )
|
||||
{
|
||||
// One of the digits isn't zero, therefore the number isn't zero
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// All of the digits are zero, therefore the number is zero
|
||||
return true;
|
||||
}
|
||||
|
@@ -16,7 +16,6 @@
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "pch.h"
|
||||
#include "ratpak.h"
|
||||
|
||||
using namespace std;
|
||||
@@ -38,23 +37,23 @@ using namespace std;
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void gcdrat( PRAT *pa, int32_t precision)
|
||||
void gcdrat(PRAT* pa, int32_t precision)
|
||||
|
||||
{
|
||||
PNUMBER pgcd= nullptr;
|
||||
PRAT a= nullptr;
|
||||
PNUMBER pgcd = nullptr;
|
||||
PRAT a = nullptr;
|
||||
|
||||
a=*pa;
|
||||
pgcd = gcd( a->pp, a->pq );
|
||||
a = *pa;
|
||||
pgcd = gcd(a->pp, a->pq);
|
||||
|
||||
if ( !zernum( pgcd ) )
|
||||
{
|
||||
divnumx( &(a->pp), pgcd, precision);
|
||||
divnumx( &(a->pq), pgcd, precision);
|
||||
}
|
||||
if (!zernum(pgcd))
|
||||
{
|
||||
divnumx(&(a->pp), pgcd, precision);
|
||||
divnumx(&(a->pq), pgcd, precision);
|
||||
}
|
||||
|
||||
destroynum( pgcd );
|
||||
*pa=a;
|
||||
destroynum(pgcd);
|
||||
*pa = a;
|
||||
|
||||
RENORMALIZE(*pa);
|
||||
}
|
||||
@@ -71,16 +70,16 @@ void gcdrat( PRAT *pa, int32_t precision)
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void fracrat( PRAT *pa , uint32_t radix, int32_t precision)
|
||||
void fracrat(PRAT* pa, uint32_t radix, int32_t precision)
|
||||
{
|
||||
// Only do the flatrat operation if number is nonzero.
|
||||
// and only if the bottom part is not one.
|
||||
if ( !zernum( (*pa)->pp ) && !equnum( (*pa)->pq, num_one ) )
|
||||
if (!zernum((*pa)->pp) && !equnum((*pa)->pq, num_one))
|
||||
{
|
||||
flatrat(*pa, radix, precision);
|
||||
}
|
||||
|
||||
remnum( &((*pa)->pp), (*pa)->pq, BASEX );
|
||||
remnum(&((*pa)->pp), (*pa)->pq, BASEX);
|
||||
|
||||
// Get *pa back in the integer over integer form.
|
||||
RENORMALIZE(*pa);
|
||||
@@ -99,26 +98,25 @@ void fracrat( PRAT *pa , uint32_t radix, int32_t precision)
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void mulrat( PRAT *pa, PRAT b, int32_t precision)
|
||||
void mulrat(PRAT* pa, PRAT b, int32_t precision)
|
||||
|
||||
{
|
||||
{
|
||||
// Only do the multiply if it isn't zero.
|
||||
if ( !zernum( (*pa)->pp ) )
|
||||
{
|
||||
mulnumx( &((*pa)->pp), b->pp );
|
||||
mulnumx( &((*pa)->pq), b->pq );
|
||||
if (!zernum((*pa)->pp))
|
||||
{
|
||||
mulnumx(&((*pa)->pp), b->pp);
|
||||
mulnumx(&((*pa)->pq), b->pq);
|
||||
trimit(pa, precision);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
// If it is zero, blast a one in the denominator.
|
||||
DUPNUM( ((*pa)->pq), num_one );
|
||||
}
|
||||
DUPNUM(((*pa)->pq), num_one);
|
||||
}
|
||||
|
||||
#ifdef MULGCD
|
||||
gcdrat( pa );
|
||||
gcdrat(pa);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -134,44 +132,41 @@ void mulrat( PRAT *pa, PRAT b, int32_t precision)
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
void divrat( PRAT *pa, PRAT b, int32_t precision)
|
||||
void divrat(PRAT* pa, PRAT b, int32_t precision)
|
||||
|
||||
{
|
||||
|
||||
if ( !zernum( (*pa)->pp ) )
|
||||
{
|
||||
if (!zernum((*pa)->pp))
|
||||
{
|
||||
// Only do the divide if the top isn't zero.
|
||||
mulnumx( &((*pa)->pp), b->pq );
|
||||
mulnumx( &((*pa)->pq), b->pp );
|
||||
mulnumx(&((*pa)->pp), b->pq);
|
||||
mulnumx(&((*pa)->pq), b->pp);
|
||||
|
||||
if ( zernum( (*pa)->pq ) )
|
||||
{
|
||||
// raise an exception if the bottom is 0.
|
||||
throw( CALC_E_DIVIDEBYZERO );
|
||||
}
|
||||
trimit(pa, precision);
|
||||
}
|
||||
else
|
||||
if (zernum((*pa)->pq))
|
||||
{
|
||||
// raise an exception if the bottom is 0.
|
||||
throw(CALC_E_DIVIDEBYZERO);
|
||||
}
|
||||
trimit(pa, precision);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Top is zero.
|
||||
if ( zerrat( b ) )
|
||||
{
|
||||
if (zerrat(b))
|
||||
{
|
||||
// If bottom is zero
|
||||
// 0 / 0 is indefinite, raise an exception.
|
||||
throw( CALC_E_INDEFINITE );
|
||||
}
|
||||
else
|
||||
{
|
||||
// 0/x make a unique 0.
|
||||
DUPNUM( ((*pa)->pq), num_one );
|
||||
}
|
||||
throw(CALC_E_INDEFINITE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 0/x make a unique 0.
|
||||
DUPNUM(((*pa)->pq), num_one);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DIVGCD
|
||||
gcdrat( pa );
|
||||
gcdrat(pa);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -187,11 +182,11 @@ void divrat( PRAT *pa, PRAT b, int32_t precision)
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void subrat( PRAT *pa, PRAT b, int32_t precision)
|
||||
void subrat(PRAT* pa, PRAT b, int32_t precision)
|
||||
|
||||
{
|
||||
b->pp->sign *= -1;
|
||||
addrat( pa, b, precision);
|
||||
addrat(pa, b, precision);
|
||||
b->pp->sign *= -1;
|
||||
}
|
||||
|
||||
@@ -208,13 +203,13 @@ void subrat( PRAT *pa, PRAT b, int32_t precision)
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void addrat( PRAT *pa, PRAT b, int32_t precision)
|
||||
void addrat(PRAT* pa, PRAT b, int32_t precision)
|
||||
|
||||
{
|
||||
PNUMBER bot= nullptr;
|
||||
PNUMBER bot = nullptr;
|
||||
|
||||
if ( equnum( (*pa)->pq, b->pq ) )
|
||||
{
|
||||
if (equnum((*pa)->pq, b->pq))
|
||||
{
|
||||
// Very special case, q's match.,
|
||||
// make sure signs are involved in the calculation
|
||||
// we have to do this since the optimization here is only
|
||||
@@ -223,33 +218,30 @@ void addrat( PRAT *pa, PRAT b, int32_t precision)
|
||||
(*pa)->pq->sign = 1;
|
||||
b->pp->sign *= b->pq->sign;
|
||||
b->pq->sign = 1;
|
||||
addnum( &((*pa)->pp), b->pp, BASEX );
|
||||
}
|
||||
addnum(&((*pa)->pp), b->pp, BASEX);
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
// Usual case q's aren't the same.
|
||||
DUPNUM( bot, (*pa)->pq );
|
||||
mulnumx( &bot, b->pq );
|
||||
mulnumx( &((*pa)->pp), b->pq );
|
||||
mulnumx( &((*pa)->pq), b->pp );
|
||||
addnum( &((*pa)->pp), (*pa)->pq, BASEX );
|
||||
destroynum( (*pa)->pq );
|
||||
DUPNUM(bot, (*pa)->pq);
|
||||
mulnumx(&bot, b->pq);
|
||||
mulnumx(&((*pa)->pp), b->pq);
|
||||
mulnumx(&((*pa)->pq), b->pp);
|
||||
addnum(&((*pa)->pp), (*pa)->pq, BASEX);
|
||||
destroynum((*pa)->pq);
|
||||
(*pa)->pq = bot;
|
||||
trimit(pa, precision);
|
||||
|
||||
// Get rid of negative zeros here.
|
||||
(*pa)->pp->sign *= (*pa)->pq->sign;
|
||||
(*pa)->pq->sign = 1;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ADDGCD
|
||||
gcdrat( pa );
|
||||
gcdrat(pa);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: rootrat
|
||||
@@ -263,11 +255,11 @@ void addrat( PRAT *pa, PRAT b, int32_t precision)
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void rootrat( PRAT *py, PRAT n, uint32_t radix, int32_t precision)
|
||||
void rootrat(PRAT* py, PRAT n, uint32_t radix, int32_t precision)
|
||||
{
|
||||
// Initialize 1/n
|
||||
PRAT oneovern= nullptr;
|
||||
DUPRAT(oneovern,rat_one);
|
||||
PRAT oneovern = nullptr;
|
||||
DUPRAT(oneovern, rat_one);
|
||||
divrat(&oneovern, n, precision);
|
||||
|
||||
powrat(py, oneovern, radix, precision);
|
||||
@@ -275,7 +267,6 @@ void rootrat( PRAT *py, PRAT n, uint32_t radix, int32_t precision)
|
||||
destroyrat(oneovern);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: zerrat
|
||||
@@ -289,10 +280,8 @@ void rootrat( PRAT *py, PRAT n, uint32_t radix, int32_t precision)
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool zerrat( PRAT a )
|
||||
bool zerrat(PRAT a)
|
||||
|
||||
{
|
||||
return( zernum(a->pp) );
|
||||
return (zernum(a->pp));
|
||||
}
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -17,27 +17,33 @@
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include "CalcErr.h"
|
||||
#include <cstring> // for memmove
|
||||
#include "sal_cross_platform.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
|
||||
// this to 2^32 after solving scaling problems with
|
||||
// overflow detection esp. in mul
|
||||
// this to 2^32 after solving scaling problems with
|
||||
// overflow detection esp. in mul
|
||||
|
||||
typedef uint32_t MANTTYPE;
|
||||
typedef uint64_t TWO_MANTTYPE;
|
||||
|
||||
enum eNUMOBJ_FMT {
|
||||
FMT_FLOAT, // returns floating point, or exponential if number is too big
|
||||
FMT_SCIENTIFIC, // always returns scientific notation
|
||||
FMT_ENGINEERING // always returns engineering notation such that exponent is a multiple of 3
|
||||
enum eNUMOBJ_FMT
|
||||
{
|
||||
FMT_FLOAT, // returns floating point, or exponential if number is too big
|
||||
FMT_SCIENTIFIC, // always returns scientific notation
|
||||
FMT_ENGINEERING // always returns engineering notation such that exponent is a multiple of 3
|
||||
|
||||
};
|
||||
|
||||
enum eANGLE_TYPE {
|
||||
ANGLE_DEG, // Calculate trig using 360 degrees per revolution
|
||||
ANGLE_RAD, // Calculate trig using 2 pi radians per revolution
|
||||
ANGLE_GRAD // Calculate trig using 400 gradients per revolution
|
||||
enum eANGLE_TYPE
|
||||
{
|
||||
ANGLE_DEG, // Calculate trig using 360 degrees per revolution
|
||||
ANGLE_RAD, // Calculate trig using 2 pi radians per revolution
|
||||
ANGLE_GRAD // Calculate trig using 400 gradients per revolution
|
||||
|
||||
};
|
||||
|
||||
@@ -51,21 +57,20 @@ typedef enum eANGLE_TYPE ANGLE_TYPE;
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4200) // nonstandard extension used : zero-sized array in struct/union
|
||||
#pragma warning(disable : 4200) // nonstandard extension used : zero-sized array in struct/union
|
||||
typedef struct _number
|
||||
{
|
||||
int32_t sign; // The sign of the mantissa, +1, or -1
|
||||
int32_t cdigit; // The number of digits, or what passes for digits in the
|
||||
int32_t sign; // The sign of the mantissa, +1, or -1
|
||||
int32_t cdigit; // The number of digits, or what passes for digits in the
|
||||
// radix being used.
|
||||
int32_t exp; // The offset of digits from the radix point
|
||||
int32_t exp; // The offset of digits from the radix point
|
||||
// (decimal point in radix 10)
|
||||
MANTTYPE mant[];
|
||||
// This is actually allocated as a continuation of the
|
||||
// NUMBER structure.
|
||||
// This is actually allocated as a continuation of the
|
||||
// NUMBER structure.
|
||||
} NUMBER, *PNUMBER, **PPNUMBER;
|
||||
#pragma warning(pop)
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// RAT type is a representation radix on 2 NUMBER types.
|
||||
@@ -74,10 +79,10 @@ typedef struct _number
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
typedef struct _rat
|
||||
{
|
||||
{
|
||||
PNUMBER pp;
|
||||
PNUMBER pq;
|
||||
} RAT, *PRAT;
|
||||
} RAT, *PRAT;
|
||||
|
||||
static constexpr uint32_t MAX_LONG_SIZE = 33; // Base 2 requires 32 'digits'
|
||||
|
||||
@@ -131,24 +136,34 @@ extern PRAT rat_max_i32;
|
||||
extern PRAT rat_min_i32;
|
||||
|
||||
// DUPNUM Duplicates a number taking care of allocation and internals
|
||||
#define DUPNUM(a,b) destroynum(a);createnum( a, (b)->cdigit );_dupnum(a, b);
|
||||
#define DUPNUM(a, b) \
|
||||
destroynum(a); \
|
||||
createnum(a, (b)->cdigit); \
|
||||
_dupnum(a, b);
|
||||
|
||||
// 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
|
||||
// the base currently being used, only accurate to within g_ratio
|
||||
|
||||
#define LOGNUMRADIX(pnum) (((pnum)->cdigit+(pnum)->exp)*g_ratio)
|
||||
#define LOGRATRADIX(prat) (LOGNUMRADIX((prat)->pp)-LOGNUMRADIX((prat)->pq))
|
||||
#define LOGNUMRADIX(pnum) (((pnum)->cdigit + (pnum)->exp) * g_ratio)
|
||||
#define LOGRATRADIX(prat) (LOGNUMRADIX((prat)->pp) - LOGNUMRADIX((prat)->pq))
|
||||
|
||||
// LOG*2 calculates the integral portion of the log of a number in
|
||||
// the internal base being used, only accurate to within g_ratio
|
||||
|
||||
#define LOGNUM2(pnum) ((pnum)->cdigit+(pnum)->exp)
|
||||
#define LOGRAT2(prat) (LOGNUM2((prat)->pp)-LOGNUM2((prat)->pq))
|
||||
#define LOGNUM2(pnum) ((pnum)->cdigit + (pnum)->exp)
|
||||
#define LOGRAT2(prat) (LOGNUM2((prat)->pp) - LOGNUM2((prat)->pq))
|
||||
|
||||
#if defined( DEBUG_RATPAK )
|
||||
// SIGN returns the sign of the rational
|
||||
#define SIGN(prat) ((prat)->pp->sign * (prat)->pq->sign)
|
||||
|
||||
#if defined(DEBUG_RATPAK)
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// Debug versions of rational number creation and destruction routines.
|
||||
@@ -156,37 +171,39 @@ extern PRAT rat_min_i32;
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define createrat(y) (y)=_createrat(); \
|
||||
{ \
|
||||
std::wstringstream outputString; \
|
||||
outputString << "createrat " << y << " " << # y << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
|
||||
OutputDebugString(outputString.str().c_str()); \
|
||||
}
|
||||
#define destroyrat(x) \
|
||||
{ \
|
||||
std::wstringstream outputString; \
|
||||
outputString << "destroyrat " << x << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
|
||||
OutputDebugString(outputString.str().c_str()); \
|
||||
} \
|
||||
_destroyrat(x),(x)=nullptr
|
||||
#define createnum(y,x) (y)=_createnum(x); \
|
||||
{ \
|
||||
std::wstringstream outputString; \
|
||||
outputString << "createnum " << y << " " << # y << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
|
||||
OutputDebugString(outputString.str().c_str()); \
|
||||
}
|
||||
#define destroynum(x) \
|
||||
{ \
|
||||
std::wstringstream outputString; \
|
||||
outputString << "destroynum " << x << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
|
||||
OutputDebugString(outputString.str().c_str()); \
|
||||
} \
|
||||
_destroynum(x),(x)=nullptr
|
||||
#define createrat(y) \
|
||||
(y) = _createrat(); \
|
||||
{ \
|
||||
std::wstringstream outputString; \
|
||||
outputString << "createrat " << y << " " << #y << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
|
||||
OutputDebugString(outputString.str().c_str()); \
|
||||
}
|
||||
#define destroyrat(x) \
|
||||
{ \
|
||||
std::wstringstream outputString; \
|
||||
outputString << "destroyrat " << x << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
|
||||
OutputDebugString(outputString.str().c_str()); \
|
||||
} \
|
||||
_destroyrat(x), (x) = nullptr
|
||||
#define createnum(y, x) \
|
||||
(y) = _createnum(x); \
|
||||
{ \
|
||||
std::wstringstream outputString; \
|
||||
outputString << "createnum " << y << " " << #y << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
|
||||
OutputDebugString(outputString.str().c_str()); \
|
||||
}
|
||||
#define destroynum(x) \
|
||||
{ \
|
||||
std::wstringstream outputString; \
|
||||
outputString << "destroynum " << x << " file= " << __FILE__ << ", line= " << __LINE__ << "\n"; \
|
||||
OutputDebugString(outputString.str().c_str()); \
|
||||
} \
|
||||
_destroynum(x), (x) = nullptr
|
||||
#else
|
||||
#define createrat(y) (y)=_createrat()
|
||||
#define destroyrat(x) _destroyrat(x),(x)=nullptr
|
||||
#define createnum(y,x) (y)=_createnum(x)
|
||||
#define destroynum(x) _destroynum(x),(x)=nullptr
|
||||
#define createrat(y) (y) = _createrat()
|
||||
#define destroyrat(x) _destroyrat(x), (x) = nullptr
|
||||
#define createnum(y, x) (y) = _createnum(x)
|
||||
#define destroynum(x) _destroynum(x), (x) = nullptr
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -197,40 +214,47 @@ _destroynum(x),(x)=nullptr
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// RENORMALIZE, gets the exponents non-negative.
|
||||
#define RENORMALIZE(x) if ( (x)->pp->exp < 0 ) { \
|
||||
(x)->pq->exp -= (x)->pp->exp; \
|
||||
(x)->pp->exp = 0; \
|
||||
} \
|
||||
if ( (x)->pq->exp < 0 ) { \
|
||||
(x)->pp->exp -= (x)->pq->exp; \
|
||||
(x)->pq->exp = 0; \
|
||||
#define RENORMALIZE(x) \
|
||||
if ((x)->pp->exp < 0) \
|
||||
{ \
|
||||
(x)->pq->exp -= (x)->pp->exp; \
|
||||
(x)->pp->exp = 0; \
|
||||
} \
|
||||
if ((x)->pq->exp < 0) \
|
||||
{ \
|
||||
(x)->pp->exp -= (x)->pq->exp; \
|
||||
(x)->pq->exp = 0; \
|
||||
}
|
||||
|
||||
// TRIMNUM ASSUMES the number is in radix form NOT INTERNAL BASEX!!!
|
||||
#define TRIMNUM(x, precision) if ( !g_ftrueinfinite ) { \
|
||||
int32_t trim = (x)->cdigit - precision-g_ratio;\
|
||||
if ( trim > 1 ) \
|
||||
{ \
|
||||
memmove( (x)->mant, &((x)->mant[trim]), sizeof(MANTTYPE)*((x)->cdigit-trim) ); \
|
||||
(x)->cdigit -= trim; \
|
||||
(x)->exp += trim; \
|
||||
} \
|
||||
}
|
||||
#define TRIMNUM(x, precision) \
|
||||
if (!g_ftrueinfinite) \
|
||||
{ \
|
||||
int32_t trim = (x)->cdigit - precision - g_ratio; \
|
||||
if (trim > 1) \
|
||||
{ \
|
||||
memmove((x)->mant, &((x)->mant[trim]), sizeof(MANTTYPE) * ((x)->cdigit - trim)); \
|
||||
(x)->cdigit -= trim; \
|
||||
(x)->exp += trim; \
|
||||
} \
|
||||
}
|
||||
// TRIMTOP ASSUMES the number is in INTERNAL BASEX!!!
|
||||
#define TRIMTOP(x, precision) if ( !g_ftrueinfinite ) { \
|
||||
int32_t trim = (x)->pp->cdigit - (precision/g_ratio) - 2;\
|
||||
if ( trim > 1 ) \
|
||||
{ \
|
||||
memmove( (x)->pp->mant, &((x)->pp->mant[trim]), sizeof(MANTTYPE)*((x)->pp->cdigit-trim) ); \
|
||||
(x)->pp->cdigit -= trim; \
|
||||
(x)->pp->exp += trim; \
|
||||
} \
|
||||
trim = std::min((x)->pp->exp,(x)->pq->exp);\
|
||||
(x)->pp->exp -= trim;\
|
||||
(x)->pq->exp -= trim;\
|
||||
}
|
||||
#define TRIMTOP(x, precision) \
|
||||
if (!g_ftrueinfinite) \
|
||||
{ \
|
||||
int32_t trim = (x)->pp->cdigit - (precision / g_ratio) - 2; \
|
||||
if (trim > 1) \
|
||||
{ \
|
||||
memmove((x)->pp->mant, &((x)->pp->mant[trim]), sizeof(MANTTYPE) * ((x)->pp->cdigit - trim)); \
|
||||
(x)->pp->cdigit -= trim; \
|
||||
(x)->pp->exp += trim; \
|
||||
} \
|
||||
trim = std::min((x)->pp->exp, (x)->pq->exp); \
|
||||
(x)->pp->exp -= trim; \
|
||||
(x)->pq->exp -= trim; \
|
||||
}
|
||||
|
||||
#define SMALL_ENOUGH_RAT(a, precision) (zernum((a)->pp) || ( ( ( (a)->pq->cdigit + (a)->pq->exp ) - ( (a)->pp->cdigit + (a)->pp->exp ) - 1 ) * g_ratio > precision ) )
|
||||
#define SMALL_ENOUGH_RAT(a, precision) (zernum((a)->pp) || ((((a)->pq->cdigit + (a)->pq->exp) - ((a)->pp->cdigit + (a)->pp->exp) - 1) * g_ratio > precision))
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
@@ -239,50 +263,55 @@ memmove( (x)->pp->mant, &((x)->pp->mant[trim]), sizeof(MANTTYPE)*((x)->pp->cdigi
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define CREATETAYLOR() PRAT xx=nullptr;\
|
||||
PNUMBER n2=nullptr; \
|
||||
PRAT pret=nullptr; \
|
||||
PRAT thisterm=nullptr; \
|
||||
DUPRAT(xx,*px); \
|
||||
mulrat(&xx,*px, precision); \
|
||||
createrat(pret); \
|
||||
pret->pp=i32tonum( 0L, BASEX ); \
|
||||
pret->pq=i32tonum( 0L, BASEX );
|
||||
#define CREATETAYLOR() \
|
||||
PRAT xx = nullptr; \
|
||||
PNUMBER n2 = nullptr; \
|
||||
PRAT pret = nullptr; \
|
||||
PRAT thisterm = nullptr; \
|
||||
DUPRAT(xx, *px); \
|
||||
mulrat(&xx, *px, precision); \
|
||||
createrat(pret); \
|
||||
pret->pp = i32tonum(0L, BASEX); \
|
||||
pret->pq = i32tonum(0L, BASEX);
|
||||
|
||||
#define DESTROYTAYLOR() destroynum( n2 ); \
|
||||
destroyrat( xx );\
|
||||
destroyrat( thisterm );\
|
||||
destroyrat( *px );\
|
||||
trimit(&pret, precision);\
|
||||
*px=pret;
|
||||
#define DESTROYTAYLOR() \
|
||||
destroynum(n2); \
|
||||
destroyrat(xx); \
|
||||
destroyrat(thisterm); \
|
||||
destroyrat(*px); \
|
||||
trimit(&pret, precision); \
|
||||
*px = pret;
|
||||
|
||||
// INC(a) is the rational equivalent of a++
|
||||
// Check to see if we can avoid doing this the hard way.
|
||||
#define INC(a) if ( (a)->mant[0] < BASEX - 1 ) \
|
||||
{ \
|
||||
(a)->mant[0]++; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
addnum( &(a), num_one, BASEX); \
|
||||
#define INC(a) \
|
||||
if ((a)->mant[0] < BASEX - 1) \
|
||||
{ \
|
||||
(a)->mant[0]++; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
addnum(&(a), num_one, BASEX); \
|
||||
}
|
||||
|
||||
#define MSD(x) ((x)->mant[(x)->cdigit-1])
|
||||
#define MSD(x) ((x)->mant[(x)->cdigit - 1])
|
||||
// MULNUM(b) is the rational equivalent of thisterm *= b where thisterm is
|
||||
// a rational and b is a number, NOTE this is a mixed type operation for
|
||||
// efficiency reasons.
|
||||
#define MULNUM(b) mulnumx( &(thisterm->pp), b);
|
||||
#define MULNUM(b) mulnumx(&(thisterm->pp), b);
|
||||
|
||||
// DIVNUM(b) is the rational equivalent of thisterm /= b where thisterm is
|
||||
// a rational and b is a number, NOTE this is a mixed type operation for
|
||||
// efficiency reasons.
|
||||
#define DIVNUM(b) mulnumx( &(thisterm->pq), b);
|
||||
#define DIVNUM(b) mulnumx(&(thisterm->pq), b);
|
||||
|
||||
// NEXTTERM(p,d) is the rational equivalent of
|
||||
// thisterm *= p
|
||||
// d <d is usually an expansion of operations to get thisterm updated.>
|
||||
// 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)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
@@ -292,9 +321,9 @@ memmove( (x)->pp->mant, &((x)->pp->mant[trim]), sizeof(MANTTYPE)*((x)->pp->cdigi
|
||||
|
||||
extern bool g_ftrueinfinite; // set to true to allow infinite precision
|
||||
// don't use unless you know what you are doing
|
||||
// used to help decide when to stop calculating.
|
||||
// used to help decide when to stop calculating.
|
||||
|
||||
extern int32_t g_ratio; // Internally calculated ratio of internal radix
|
||||
extern int32_t g_ratio; // Internally calculated ratio of internal radix
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
@@ -308,10 +337,10 @@ extern void SetDecimalSeparator(wchar_t decimalSeparator);
|
||||
// Call whenever either radix or precision changes, is smarter about recalculating constants.
|
||||
extern void ChangeConstants(uint32_t radix, int32_t precision);
|
||||
|
||||
extern bool equnum(_In_ PNUMBER a, _In_ PNUMBER b ); // returns true of a == b
|
||||
extern bool lessnum(_In_ PNUMBER a, _In_ PNUMBER b ); // returns true of a < b
|
||||
extern bool zernum(_In_ PNUMBER a ); // returns true of a == 0
|
||||
extern bool zerrat(_In_ PRAT a ); // returns true if a == 0/q
|
||||
extern bool equnum(_In_ PNUMBER a, _In_ PNUMBER b); // returns true of a == b
|
||||
extern bool lessnum(_In_ PNUMBER a, _In_ PNUMBER b); // returns true of a < b
|
||||
extern bool zernum(_In_ PNUMBER a); // returns true of a == 0
|
||||
extern bool zerrat(_In_ PRAT a); // returns true if a == 0/q
|
||||
extern std::wstring NumberToString(_Inout_ PNUMBER& pnum, int format, uint32_t radix, int32_t precision);
|
||||
|
||||
// returns a text representation of a PRAT
|
||||
@@ -321,16 +350,20 @@ extern PNUMBER RatToNumber(_In_ PRAT prat, uint32_t radix, int32_t precision);
|
||||
// flattens a PRAT by converting it to a PNUMBER and back to a PRAT
|
||||
extern void flatrat(_Inout_ PRAT& prat, uint32_t radix, int32_t precision);
|
||||
|
||||
extern int32_t numtoi32(_In_ PNUMBER pnum, uint32_t radix );
|
||||
extern int32_t numtoi32(_In_ PNUMBER pnum, uint32_t radix);
|
||||
extern int32_t rattoi32(_In_ PRAT prat, uint32_t radix, int32_t precision);
|
||||
uint64_t rattoUi64(_In_ PRAT prat, uint32_t radix, int32_t precision);
|
||||
extern PNUMBER _createnum(_In_ uint32_t size ); // returns an empty number structure with size digits
|
||||
extern PNUMBER _createnum(_In_ uint32_t size); // returns an empty number structure with size digits
|
||||
extern PNUMBER nRadixxtonum(_In_ PNUMBER a, uint32_t radix, int32_t precision);
|
||||
extern PNUMBER 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 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.
|
||||
|
||||
// takes a text representation of a number as a mantissa with sign and an exponent with sign.
|
||||
extern PRAT StringToRat(bool mantissaIsNegative, std::wstring_view mantissa, bool exponentIsNegative, std::wstring_view exponent, uint32_t radix, int32_t precision);
|
||||
extern PRAT
|
||||
StringToRat(bool mantissaIsNegative, std::wstring_view mantissa, bool exponentIsNegative, std::wstring_view exponent, uint32_t radix, int32_t precision);
|
||||
|
||||
extern PNUMBER i32factnum(int32_t ini32, uint32_t radix);
|
||||
extern PNUMBER i32prodnum(int32_t start, int32_t stop, uint32_t radix);
|
||||
@@ -339,118 +372,119 @@ extern PNUMBER Ui32tonum(uint32_t ini32, uint32_t radix);
|
||||
extern PNUMBER numtonRadixx(PNUMBER a, uint32_t radix);
|
||||
|
||||
// creates a empty/undefined rational representation (p/q)
|
||||
extern PRAT _createrat( void );
|
||||
extern PRAT _createrat(void);
|
||||
|
||||
// returns a new rat structure with the acos of x->p/x->q taking into account
|
||||
// angle type
|
||||
extern void acosanglerat( _Inout_ PRAT *px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
|
||||
extern void acosanglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
|
||||
|
||||
// returns a new rat structure with the acosh of x->p/x->q
|
||||
extern void acoshrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
|
||||
extern void acoshrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
|
||||
|
||||
// returns a new rat structure with the acos of x->p/x->q
|
||||
extern void acosrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
|
||||
extern void acosrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
|
||||
|
||||
// returns a new rat structure with the asin of x->p/x->q taking into account
|
||||
// angle type
|
||||
extern void asinanglerat( _Inout_ PRAT *px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
|
||||
extern void asinanglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
|
||||
|
||||
extern void asinhrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
|
||||
extern void asinhrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
|
||||
// returns a new rat structure with the asinh of x->p/x->q
|
||||
|
||||
// returns a new rat structure with the asin of x->p/x->q
|
||||
extern void asinrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
|
||||
extern void asinrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
|
||||
|
||||
// returns a new rat structure with the atan of x->p/x->q taking into account
|
||||
// angle type
|
||||
extern void atananglerat( _Inout_ PRAT *px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
|
||||
extern void atananglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
|
||||
|
||||
// returns a new rat structure with the atanh of x->p/x->q
|
||||
extern void atanhrat( _Inout_ PRAT *px, int32_t precision);
|
||||
extern void atanhrat(_Inout_ PRAT* px, int32_t precision);
|
||||
|
||||
// returns a new rat structure with the atan of x->p/x->q
|
||||
extern void atanrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
|
||||
extern void atanrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
|
||||
|
||||
// returns a new rat structure with the cosh of x->p/x->q
|
||||
extern void coshrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
|
||||
extern void coshrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
|
||||
|
||||
// returns a new rat structure with the cos of x->p/x->q
|
||||
extern void cosrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
|
||||
extern void cosrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
|
||||
|
||||
// returns a new rat structure with the cos of x->p/x->q taking into account
|
||||
// angle type
|
||||
extern void cosanglerat( _Inout_ PRAT *px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
|
||||
extern void cosanglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
|
||||
|
||||
// returns a new rat structure with the exp of x->p/x->q this should not be called explicitly.
|
||||
extern void _exprat( _Inout_ PRAT *px, int32_t precision);
|
||||
extern void _exprat(_Inout_ PRAT* px, int32_t precision);
|
||||
|
||||
// returns a new rat structure with the exp of x->p/x->q
|
||||
extern void exprat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
|
||||
extern void exprat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
|
||||
|
||||
// returns a new rat structure with the log base 10 of x->p/x->q
|
||||
extern void log10rat( _Inout_ PRAT *px, int32_t precision);
|
||||
extern void log10rat(_Inout_ PRAT* px, int32_t precision);
|
||||
|
||||
// returns a new rat structure with the natural log of x->p/x->q
|
||||
extern void lograt( _Inout_ PRAT *px, int32_t precision);
|
||||
extern void lograt(_Inout_ PRAT* px, int32_t precision);
|
||||
|
||||
extern PRAT i32torat( int32_t ini32 );
|
||||
extern PRAT Ui32torat( uint32_t inui32 );
|
||||
extern PRAT numtorat( _In_ PNUMBER pin, uint32_t radix);
|
||||
extern PRAT i32torat(int32_t ini32);
|
||||
extern PRAT Ui32torat(uint32_t inui32);
|
||||
extern PRAT numtorat(_In_ PNUMBER pin, uint32_t radix);
|
||||
|
||||
extern void sinhrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
|
||||
extern void sinrat( _Inout_ PRAT *px );
|
||||
extern void sinhrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
|
||||
extern void sinrat(_Inout_ PRAT* px);
|
||||
|
||||
// returns a new rat structure with the sin of x->p/x->q taking into account
|
||||
// angle type
|
||||
extern void sinanglerat( _Inout_ PRAT *px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
|
||||
extern void sinanglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
|
||||
|
||||
extern void tanhrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
|
||||
extern void tanrat( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
|
||||
extern void tanhrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
|
||||
extern void tanrat(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
|
||||
|
||||
// returns a new rat structure with the tan of x->p/x->q taking into account
|
||||
// angle type
|
||||
extern void tananglerat( _Inout_ PRAT *px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
|
||||
extern void tananglerat(_Inout_ PRAT* px, ANGLE_TYPE angletype, uint32_t radix, int32_t precision);
|
||||
|
||||
extern void _dupnum(_In_ PNUMBER dest, _In_ const NUMBER * const src);
|
||||
extern void _dupnum(_In_ PNUMBER dest, _In_ const NUMBER* const src);
|
||||
|
||||
extern void _destroynum( _In_ PNUMBER pnum );
|
||||
extern void _destroyrat( _In_ PRAT prat );
|
||||
extern void addnum( _Inout_ PNUMBER *pa, _In_ PNUMBER b, uint32_t radix);
|
||||
extern void addrat( _Inout_ PRAT *pa, _In_ PRAT b, int32_t precision);
|
||||
extern void andrat( _Inout_ PRAT *pa, _In_ PRAT b, uint32_t radix, int32_t precision);
|
||||
extern void divnum( _Inout_ PNUMBER *pa, _In_ PNUMBER b, uint32_t radix, int32_t precision);
|
||||
extern void divnumx( _Inout_ PNUMBER *pa, _In_ PNUMBER 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 factrat( _Inout_ PRAT *pa, uint32_t radix, int32_t precision);
|
||||
extern void modrat( _Inout_ PRAT *pa, _In_ PRAT b );
|
||||
extern void gcdrat( _Inout_ PRAT *pa, 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 mulnumx( _Inout_ PNUMBER *pa, _In_ PNUMBER b );
|
||||
extern void mulrat( _Inout_ PRAT *pa, _In_ PRAT b, int32_t precision);
|
||||
extern void numpowi32( _Inout_ PNUMBER *proot, int32_t power, uint32_t radix, int32_t precision);
|
||||
extern void numpowi32x( _Inout_ PNUMBER *proot, int32_t power );
|
||||
extern void orrat( _Inout_ PRAT *pa, _In_ PRAT b, uint32_t radix, int32_t precision);
|
||||
extern void powrat( _Inout_ PRAT *pa, _In_ PRAT b , uint32_t radix, int32_t precision);
|
||||
extern void powratNumeratorDenominator(_Inout_ PRAT *pa, _In_ PRAT b, uint32_t radix, int32_t precision);
|
||||
extern void powratcomp(_Inout_ PRAT *pa, _In_ PRAT b, uint32_t radix, int32_t precision);
|
||||
extern void ratpowi32( _Inout_ PRAT *proot, int32_t power, int32_t precision);
|
||||
extern void remnum( _Inout_ PNUMBER *pa, _In_ PNUMBER b, uint32_t radix);
|
||||
extern void rootrat( _Inout_ PRAT *pa, _In_ PRAT b , uint32_t radix, int32_t precision);
|
||||
extern void scale2pi( _Inout_ PRAT *px, uint32_t radix, int32_t precision);
|
||||
extern void scale( _Inout_ PRAT *px, _In_ PRAT scalefact, uint32_t radix, int32_t precision);
|
||||
extern void subrat( _Inout_ PRAT *pa, _In_ PRAT b, int32_t precision);
|
||||
extern void xorrat( _Inout_ PRAT *pa, _In_ PRAT b, uint32_t radix, int32_t precision);
|
||||
extern void lshrat( _Inout_ PRAT *pa, _In_ PRAT b , uint32_t radix, int32_t precision);
|
||||
extern void rshrat( _Inout_ PRAT *pa, _In_ PRAT b, uint32_t radix, int32_t precision);
|
||||
extern bool rat_equ( _In_ PRAT a, _In_ PRAT b, int32_t precision);
|
||||
extern bool rat_neq( _In_ PRAT a, _In_ PRAT b, int32_t precision);
|
||||
extern bool rat_gt( _In_ PRAT a, _In_ PRAT b, int32_t precision);
|
||||
extern bool rat_ge( _In_ PRAT a, _In_ PRAT b, int32_t precision);
|
||||
extern bool rat_lt( _In_ PRAT a, _In_ PRAT b, int32_t precision);
|
||||
extern bool rat_le( _In_ PRAT a, _In_ PRAT b, int32_t precision);
|
||||
extern void inbetween( _In_ PRAT *px, _In_ PRAT range, int32_t precision);
|
||||
extern void trimit( _Inout_ PRAT *px, int32_t precision);
|
||||
extern void _dumprawrat(_In_ const wchar_t *varname, _In_ PRAT rat, std::wostream& out);
|
||||
extern void _dumprawnum(_In_ const wchar_t *varname, _In_ PNUMBER num, std::wostream& out);
|
||||
extern void _destroynum(_In_ PNUMBER pnum);
|
||||
extern void _destroyrat(_In_ PRAT prat);
|
||||
extern void addnum(_Inout_ PNUMBER* pa, _In_ PNUMBER b, uint32_t radix);
|
||||
extern void addrat(_Inout_ PRAT* pa, _In_ PRAT b, int32_t precision);
|
||||
extern void andrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
|
||||
extern void divnum(_Inout_ PNUMBER* pa, _In_ PNUMBER b, uint32_t radix, int32_t precision);
|
||||
extern void divnumx(_Inout_ PNUMBER* pa, _In_ PNUMBER 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 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 gcdrat(_Inout_ PRAT* pa, 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 mulnumx(_Inout_ PNUMBER* pa, _In_ PNUMBER b);
|
||||
extern void mulrat(_Inout_ PRAT* pa, _In_ PRAT b, int32_t precision);
|
||||
extern void numpowi32(_Inout_ PNUMBER* proot, int32_t power, uint32_t radix, int32_t precision);
|
||||
extern void numpowi32x(_Inout_ PNUMBER* proot, int32_t power);
|
||||
extern void orrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
|
||||
extern void powrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
|
||||
extern void powratNumeratorDenominator(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
|
||||
extern void powratcomp(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
|
||||
extern void ratpowi32(_Inout_ PRAT* proot, int32_t power, int32_t precision);
|
||||
extern void remnum(_Inout_ PNUMBER* pa, _In_ PNUMBER b, uint32_t radix);
|
||||
extern void rootrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
|
||||
extern void scale2pi(_Inout_ PRAT* px, uint32_t radix, int32_t precision);
|
||||
extern void scale(_Inout_ PRAT* px, _In_ PRAT scalefact, uint32_t radix, int32_t precision);
|
||||
extern void subrat(_Inout_ PRAT* pa, _In_ PRAT b, int32_t precision);
|
||||
extern void xorrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
|
||||
extern void lshrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
|
||||
extern void rshrat(_Inout_ PRAT* pa, _In_ PRAT b, uint32_t radix, int32_t precision);
|
||||
extern bool rat_equ(_In_ PRAT a, _In_ PRAT b, int32_t precision);
|
||||
extern bool rat_neq(_In_ PRAT a, _In_ PRAT b, int32_t precision);
|
||||
extern bool rat_gt(_In_ PRAT a, _In_ PRAT b, int32_t precision);
|
||||
extern bool rat_ge(_In_ PRAT a, _In_ PRAT b, int32_t precision);
|
||||
extern bool rat_lt(_In_ PRAT a, _In_ PRAT b, int32_t precision);
|
||||
extern bool rat_le(_In_ PRAT a, _In_ PRAT b, int32_t precision);
|
||||
extern void inbetween(_In_ PRAT* px, _In_ PRAT range, int32_t precision);
|
||||
extern void trimit(_Inout_ PRAT* px, int32_t precision);
|
||||
extern void _dumprawrat(_In_ const wchar_t* varname, _In_ PRAT rat, std::wostream& out);
|
||||
extern void _dumprawnum(_In_ const wchar_t* varname, _In_ PNUMBER num, std::wostream& out);
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -18,35 +18,48 @@
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include "pch.h"
|
||||
#include <string>
|
||||
#include <cstring> // for memmove
|
||||
#include <iostream> // for wostream
|
||||
#include "ratpak.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
void _readconstants( void );
|
||||
void _readconstants(void);
|
||||
|
||||
#if defined( GEN_CONST )
|
||||
#if defined(GEN_CONST)
|
||||
static int cbitsofprecision = 0;
|
||||
#define READRAWRAT(v)
|
||||
#define READRAWNUM(v)
|
||||
#define DUMPRAWRAT(v) _dumprawrat(#v,v, wcout)
|
||||
#define DUMPRAWNUM(v) fprintf( stderr, \
|
||||
"// Autogenerated by _dumprawrat in support.cpp\n" ); \
|
||||
fprintf( stderr, "inline const NUMBER init_" #v "= {\n" ); \
|
||||
_dumprawnum(v, wcout); \
|
||||
fprintf( stderr, "};\n" )
|
||||
|
||||
#define DUMPRAWRAT(v) _dumprawrat(#v, v, wcout)
|
||||
#define DUMPRAWNUM(v) \
|
||||
fprintf(stderr, "// Autogenerated by _dumprawrat in support.cpp\n"); \
|
||||
fprintf(stderr, "inline const NUMBER init_" #v "= {\n"); \
|
||||
_dumprawnum(v, wcout); \
|
||||
fprintf(stderr, "};\n")
|
||||
|
||||
#else
|
||||
|
||||
#define DUMPRAWRAT(v)
|
||||
#define DUMPRAWNUM(v)
|
||||
#define READRAWRAT(v) createrat(v); DUPNUM((v)->pp,(&(init_p_##v))); \
|
||||
DUPNUM((v)->pq,(&(init_q_##v)));
|
||||
#define READRAWNUM(v) DUPNUM(v,(&(init_##v)))
|
||||
#define READRAWRAT(v) \
|
||||
createrat(v); \
|
||||
DUPNUM((v)->pp, (&(init_p_##v))); \
|
||||
DUPNUM((v)->pq, (&(init_q_##v)));
|
||||
#define READRAWNUM(v) DUPNUM(v, (&(init_##v)))
|
||||
|
||||
#define INIT_AND_DUMP_RAW_NUM_IF_NULL(r, v) if (r == nullptr) { r = i32tonum(v, BASEX); DUMPRAWNUM(v); }
|
||||
#define INIT_AND_DUMP_RAW_RAT_IF_NULL(r, v) if (r == nullptr) { r = i32torat(v); DUMPRAWRAT(v); }
|
||||
#define INIT_AND_DUMP_RAW_NUM_IF_NULL(r, v) \
|
||||
if (r == nullptr) \
|
||||
{ \
|
||||
r = i32tonum(v, BASEX); \
|
||||
DUMPRAWNUM(v); \
|
||||
}
|
||||
#define INIT_AND_DUMP_RAW_RAT_IF_NULL(r, v) \
|
||||
if (r == nullptr) \
|
||||
{ \
|
||||
r = i32torat(v); \
|
||||
DUMPRAWRAT(v); \
|
||||
}
|
||||
|
||||
static constexpr int RATIO_FOR_DECIMAL = 9;
|
||||
static constexpr int DECIMAL = 10;
|
||||
@@ -58,51 +71,51 @@ static int cbitsofprecision = RATIO_FOR_DECIMAL * DECIMAL * CALC_DECIMAL_DIGITS_
|
||||
|
||||
#endif
|
||||
|
||||
bool g_ftrueinfinite = false; // Set to true if you don't want
|
||||
// chopping internally
|
||||
// precision used internally
|
||||
bool g_ftrueinfinite = false; // Set to true if you don't want
|
||||
// chopping internally
|
||||
// precision used internally
|
||||
|
||||
PNUMBER num_one= nullptr;
|
||||
PNUMBER num_two= nullptr;
|
||||
PNUMBER num_five= nullptr;
|
||||
PNUMBER num_six= nullptr;
|
||||
PNUMBER num_ten= nullptr;
|
||||
PNUMBER num_one = nullptr;
|
||||
PNUMBER num_two = nullptr;
|
||||
PNUMBER num_five = nullptr;
|
||||
PNUMBER num_six = nullptr;
|
||||
PNUMBER num_ten = nullptr;
|
||||
|
||||
PRAT ln_ten= nullptr;
|
||||
PRAT ln_two= nullptr;
|
||||
PRAT rat_zero= nullptr;
|
||||
PRAT rat_one= nullptr;
|
||||
PRAT rat_neg_one= nullptr;
|
||||
PRAT rat_two= nullptr;
|
||||
PRAT rat_six= nullptr;
|
||||
PRAT rat_half= nullptr;
|
||||
PRAT rat_ten= nullptr;
|
||||
PRAT pt_eight_five= nullptr;
|
||||
PRAT pi= nullptr;
|
||||
PRAT pi_over_two= nullptr;
|
||||
PRAT two_pi= nullptr;
|
||||
PRAT one_pt_five_pi= nullptr;
|
||||
PRAT e_to_one_half= nullptr;
|
||||
PRAT rat_exp= nullptr;
|
||||
PRAT rad_to_deg= nullptr;
|
||||
PRAT rad_to_grad= nullptr;
|
||||
PRAT rat_qword= nullptr;
|
||||
PRAT rat_dword= nullptr; // unsigned max ui32
|
||||
PRAT rat_word= nullptr;
|
||||
PRAT rat_byte= nullptr;
|
||||
PRAT rat_360= nullptr;
|
||||
PRAT rat_400= nullptr;
|
||||
PRAT rat_180= nullptr;
|
||||
PRAT rat_200= nullptr;
|
||||
PRAT rat_nRadix= nullptr;
|
||||
PRAT rat_smallest= nullptr;
|
||||
PRAT rat_negsmallest= nullptr;
|
||||
PRAT rat_max_exp= nullptr;
|
||||
PRAT rat_min_exp= nullptr;
|
||||
PRAT ln_ten = nullptr;
|
||||
PRAT ln_two = nullptr;
|
||||
PRAT rat_zero = nullptr;
|
||||
PRAT rat_one = nullptr;
|
||||
PRAT rat_neg_one = nullptr;
|
||||
PRAT rat_two = nullptr;
|
||||
PRAT rat_six = nullptr;
|
||||
PRAT rat_half = nullptr;
|
||||
PRAT rat_ten = nullptr;
|
||||
PRAT pt_eight_five = nullptr;
|
||||
PRAT pi = nullptr;
|
||||
PRAT pi_over_two = nullptr;
|
||||
PRAT two_pi = nullptr;
|
||||
PRAT one_pt_five_pi = nullptr;
|
||||
PRAT e_to_one_half = nullptr;
|
||||
PRAT rat_exp = nullptr;
|
||||
PRAT rad_to_deg = nullptr;
|
||||
PRAT rad_to_grad = nullptr;
|
||||
PRAT rat_qword = nullptr;
|
||||
PRAT rat_dword = nullptr; // unsigned max ui32
|
||||
PRAT rat_word = nullptr;
|
||||
PRAT rat_byte = nullptr;
|
||||
PRAT rat_360 = nullptr;
|
||||
PRAT rat_400 = nullptr;
|
||||
PRAT rat_180 = nullptr;
|
||||
PRAT rat_200 = nullptr;
|
||||
PRAT rat_nRadix = nullptr;
|
||||
PRAT rat_smallest = nullptr;
|
||||
PRAT rat_negsmallest = nullptr;
|
||||
PRAT rat_max_exp = nullptr;
|
||||
PRAT rat_min_exp = nullptr;
|
||||
PRAT rat_max_fact = nullptr;
|
||||
PRAT rat_min_fact = nullptr;
|
||||
PRAT rat_min_i32= nullptr; // min signed i32
|
||||
PRAT rat_max_i32= nullptr; // max signed i32
|
||||
PRAT rat_min_i32 = nullptr; // min signed i32
|
||||
PRAT rat_max_i32 = nullptr; // max signed i32
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
@@ -125,14 +138,14 @@ void ChangeConstants(uint32_t radix, int32_t precision)
|
||||
|
||||
uint64_t limit = static_cast<uint64_t>(BASEX) / static_cast<uint64_t>(radix);
|
||||
g_ratio = 0;
|
||||
for (uint32_t digit = 1; digit < limit; digit *= radix )
|
||||
for (uint32_t digit = 1; digit < limit; digit *= radix)
|
||||
{
|
||||
g_ratio++;
|
||||
}
|
||||
g_ratio += !g_ratio;
|
||||
|
||||
destroyrat(rat_nRadix);
|
||||
rat_nRadix=i32torat( radix );
|
||||
rat_nRadix = i32torat(radix);
|
||||
|
||||
// Check to see what we have to recalculate and what we don't
|
||||
if (cbitsofprecision < (g_ratio * static_cast<int32_t>(radix) * precision))
|
||||
@@ -251,7 +264,6 @@ void ChangeConstants(uint32_t radix, int32_t precision)
|
||||
lograt(&ln_two, extraPrecision);
|
||||
DUMPRAWRAT(ln_two);
|
||||
|
||||
|
||||
destroyrat(rad_to_deg);
|
||||
rad_to_deg = i32torat(180L);
|
||||
divrat(&rad_to_deg, pi, extraPrecision);
|
||||
@@ -271,7 +283,6 @@ void ChangeConstants(uint32_t radix, int32_t precision)
|
||||
DUPRAT(rat_negsmallest, rat_smallest);
|
||||
rat_negsmallest->pp->sign = -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -285,21 +296,21 @@ void ChangeConstants(uint32_t radix, int32_t precision)
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
void intrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||
void intrat(PRAT* px, uint32_t radix, int32_t precision)
|
||||
{
|
||||
// Only do the intrat operation if number is nonzero.
|
||||
// and only if the bottom part is not one.
|
||||
if ( !zernum( (*px)->pp ) && !equnum( (*px)->pq, num_one ) )
|
||||
if (!zernum((*px)->pp) && !equnum((*px)->pq, num_one))
|
||||
{
|
||||
flatrat(*px, radix, precision);
|
||||
|
||||
// Subtract the fractional part of the rational
|
||||
PRAT pret = nullptr;
|
||||
DUPRAT(pret,*px);
|
||||
modrat( &pret, rat_one );
|
||||
DUPRAT(pret, *px);
|
||||
remrat(&pret, rat_one);
|
||||
|
||||
subrat( px, pret, precision);
|
||||
destroyrat( pret );
|
||||
subrat(px, pret, precision);
|
||||
destroyrat(pret);
|
||||
|
||||
// Simplify the value if possible to resolve rounding errors
|
||||
flatrat(*px, radix, precision);
|
||||
@@ -317,16 +328,16 @@ void intrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool rat_equ( PRAT a, PRAT b, int32_t precision)
|
||||
bool rat_equ(PRAT a, PRAT b, int32_t precision)
|
||||
|
||||
{
|
||||
PRAT rattmp= nullptr;
|
||||
DUPRAT(rattmp,a);
|
||||
PRAT rattmp = nullptr;
|
||||
DUPRAT(rattmp, a);
|
||||
rattmp->pp->sign *= -1;
|
||||
addrat( &rattmp, b, precision);
|
||||
bool bret = zernum( rattmp->pp );
|
||||
destroyrat( rattmp );
|
||||
return( bret );
|
||||
addrat(&rattmp, b, precision);
|
||||
bool bret = zernum(rattmp->pp);
|
||||
destroyrat(rattmp);
|
||||
return (bret);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
@@ -340,21 +351,19 @@ bool rat_equ( PRAT a, PRAT b, int32_t precision)
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool rat_ge( PRAT a, PRAT b, int32_t precision)
|
||||
bool rat_ge(PRAT a, PRAT b, int32_t precision)
|
||||
|
||||
{
|
||||
PRAT rattmp= nullptr;
|
||||
DUPRAT(rattmp,a);
|
||||
PRAT rattmp = nullptr;
|
||||
DUPRAT(rattmp, a);
|
||||
b->pp->sign *= -1;
|
||||
addrat( &rattmp, b, precision);
|
||||
addrat(&rattmp, b, precision);
|
||||
b->pp->sign *= -1;
|
||||
bool bret = ( zernum( rattmp->pp ) ||
|
||||
rattmp->pp->sign * rattmp->pq->sign == 1 );
|
||||
destroyrat( rattmp );
|
||||
return( bret );
|
||||
bool bret = (zernum(rattmp->pp) || SIGN(rattmp) == 1);
|
||||
destroyrat(rattmp);
|
||||
return (bret);
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: rat_gt
|
||||
@@ -366,18 +375,17 @@ bool rat_ge( PRAT a, PRAT b, int32_t precision)
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool rat_gt( PRAT a, PRAT b, int32_t precision)
|
||||
bool rat_gt(PRAT a, PRAT b, int32_t precision)
|
||||
|
||||
{
|
||||
PRAT rattmp= nullptr;
|
||||
DUPRAT(rattmp,a);
|
||||
PRAT rattmp = nullptr;
|
||||
DUPRAT(rattmp, a);
|
||||
b->pp->sign *= -1;
|
||||
addrat( &rattmp, b, precision);
|
||||
addrat(&rattmp, b, precision);
|
||||
b->pp->sign *= -1;
|
||||
bool bret = ( !zernum( rattmp->pp ) &&
|
||||
rattmp->pp->sign * rattmp->pq->sign == 1 );
|
||||
destroyrat( rattmp );
|
||||
return( bret );
|
||||
bool bret = (!zernum(rattmp->pp) && SIGN(rattmp) == 1);
|
||||
destroyrat(rattmp);
|
||||
return (bret);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
@@ -391,22 +399,19 @@ bool rat_gt( PRAT a, PRAT b, int32_t precision)
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool rat_le( PRAT a, PRAT b, int32_t precision)
|
||||
bool rat_le(PRAT a, PRAT b, int32_t precision)
|
||||
|
||||
{
|
||||
|
||||
PRAT rattmp= nullptr;
|
||||
DUPRAT(rattmp,a);
|
||||
PRAT rattmp = nullptr;
|
||||
DUPRAT(rattmp, a);
|
||||
b->pp->sign *= -1;
|
||||
addrat( &rattmp, b, precision);
|
||||
addrat(&rattmp, b, precision);
|
||||
b->pp->sign *= -1;
|
||||
bool bret = ( zernum( rattmp->pp ) ||
|
||||
rattmp->pp->sign * rattmp->pq->sign == -1 );
|
||||
destroyrat( rattmp );
|
||||
return( bret );
|
||||
bool bret = (zernum(rattmp->pp) || SIGN(rattmp) == -1);
|
||||
destroyrat(rattmp);
|
||||
return (bret);
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: rat_lt
|
||||
@@ -418,21 +423,19 @@ bool rat_le( PRAT a, PRAT b, int32_t precision)
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
bool rat_lt( PRAT a, PRAT b, int32_t precision)
|
||||
bool rat_lt(PRAT a, PRAT b, int32_t precision)
|
||||
|
||||
{
|
||||
PRAT rattmp= nullptr;
|
||||
DUPRAT(rattmp,a);
|
||||
PRAT rattmp = nullptr;
|
||||
DUPRAT(rattmp, a);
|
||||
b->pp->sign *= -1;
|
||||
addrat( &rattmp, b, precision);
|
||||
addrat(&rattmp, b, precision);
|
||||
b->pp->sign *= -1;
|
||||
bool bret = ( !zernum( rattmp->pp ) &&
|
||||
rattmp->pp->sign * rattmp->pq->sign == -1 );
|
||||
destroyrat( rattmp );
|
||||
return( bret );
|
||||
bool bret = (!zernum(rattmp->pp) && SIGN(rattmp) == -1);
|
||||
destroyrat(rattmp);
|
||||
return (bret);
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: rat_neq
|
||||
@@ -444,17 +447,16 @@ bool rat_lt( PRAT a, PRAT b, int32_t precision)
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
|
||||
bool rat_neq( PRAT a, PRAT b, int32_t precision)
|
||||
bool rat_neq(PRAT a, PRAT b, int32_t precision)
|
||||
|
||||
{
|
||||
PRAT rattmp= nullptr;
|
||||
DUPRAT(rattmp,a);
|
||||
PRAT rattmp = nullptr;
|
||||
DUPRAT(rattmp, a);
|
||||
rattmp->pp->sign *= -1;
|
||||
addrat( &rattmp, b, precision);
|
||||
bool bret = !( zernum( rattmp->pp ) );
|
||||
destroyrat( rattmp );
|
||||
return( bret );
|
||||
addrat(&rattmp, b, precision);
|
||||
bool bret = !(zernum(rattmp->pp));
|
||||
destroyrat(rattmp);
|
||||
return (bret);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
@@ -468,27 +470,26 @@ bool rat_neq( PRAT a, PRAT b, int32_t precision)
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void scale( PRAT *px, PRAT scalefact, uint32_t radix, int32_t precision )
|
||||
void scale(PRAT* px, PRAT scalefact, uint32_t radix, int32_t precision)
|
||||
{
|
||||
PRAT pret = nullptr;
|
||||
DUPRAT(pret,*px);
|
||||
DUPRAT(pret, *px);
|
||||
|
||||
// Logscale is a quick way to tell how much extra precision is needed for
|
||||
// scaling by scalefact.
|
||||
int32_t logscale = g_ratio * ( (pret->pp->cdigit+pret->pp->exp) -
|
||||
(pret->pq->cdigit+pret->pq->exp) );
|
||||
if ( logscale > 0 )
|
||||
int32_t logscale = g_ratio * ((pret->pp->cdigit + pret->pp->exp) - (pret->pq->cdigit + pret->pq->exp));
|
||||
if (logscale > 0)
|
||||
{
|
||||
precision += logscale;
|
||||
}
|
||||
|
||||
divrat( &pret, scalefact, precision);
|
||||
divrat(&pret, scalefact, precision);
|
||||
intrat(&pret, radix, precision);
|
||||
mulrat( &pret, scalefact, precision);
|
||||
mulrat(&pret, scalefact, precision);
|
||||
pret->pp->sign *= -1;
|
||||
addrat( px, pret, precision);
|
||||
addrat(px, pret, precision);
|
||||
|
||||
destroyrat( pret );
|
||||
destroyrat(pret);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
@@ -502,38 +503,37 @@ void scale( PRAT *px, PRAT scalefact, uint32_t radix, int32_t precision )
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void scale2pi( PRAT *px, uint32_t radix, int32_t precision )
|
||||
void scale2pi(PRAT* px, uint32_t radix, int32_t precision)
|
||||
{
|
||||
PRAT pret = nullptr;
|
||||
PRAT my_two_pi = nullptr;
|
||||
DUPRAT(pret,*px);
|
||||
DUPRAT(pret, *px);
|
||||
|
||||
// Logscale is a quick way to tell how much extra precision is needed for
|
||||
// scaling by 2 pi.
|
||||
int32_t logscale = g_ratio * ( (pret->pp->cdigit+pret->pp->exp) -
|
||||
(pret->pq->cdigit+pret->pq->exp) );
|
||||
if ( logscale > 0 )
|
||||
int32_t logscale = g_ratio * ((pret->pp->cdigit + pret->pp->exp) - (pret->pq->cdigit + pret->pq->exp));
|
||||
if (logscale > 0)
|
||||
{
|
||||
precision += logscale;
|
||||
DUPRAT(my_two_pi,rat_half);
|
||||
asinrat( &my_two_pi, radix, precision);
|
||||
mulrat( &my_two_pi, rat_six, precision);
|
||||
mulrat( &my_two_pi, rat_two, precision);
|
||||
DUPRAT(my_two_pi, rat_half);
|
||||
asinrat(&my_two_pi, radix, precision);
|
||||
mulrat(&my_two_pi, rat_six, precision);
|
||||
mulrat(&my_two_pi, rat_two, precision);
|
||||
}
|
||||
else
|
||||
{
|
||||
DUPRAT(my_two_pi,two_pi);
|
||||
DUPRAT(my_two_pi, two_pi);
|
||||
logscale = 0;
|
||||
}
|
||||
|
||||
divrat( &pret, my_two_pi, precision);
|
||||
divrat(&pret, my_two_pi, precision);
|
||||
intrat(&pret, radix, precision);
|
||||
mulrat( &pret, my_two_pi, precision);
|
||||
mulrat(&pret, my_two_pi, precision);
|
||||
pret->pp->sign *= -1;
|
||||
addrat( px, pret, precision);
|
||||
addrat(px, pret, precision);
|
||||
|
||||
destroyrat( my_two_pi );
|
||||
destroyrat( pret );
|
||||
destroyrat(my_two_pi);
|
||||
destroyrat(pret);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
@@ -546,22 +546,22 @@ void scale2pi( PRAT *px, uint32_t radix, int32_t precision )
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void inbetween( PRAT *px, PRAT range, int32_t precision)
|
||||
void inbetween(PRAT* px, PRAT range, int32_t precision)
|
||||
|
||||
{
|
||||
if ( rat_gt(*px,range, precision) )
|
||||
{
|
||||
DUPRAT(*px,range);
|
||||
}
|
||||
if (rat_gt(*px, range, precision))
|
||||
{
|
||||
DUPRAT(*px, range);
|
||||
}
|
||||
else
|
||||
{
|
||||
range->pp->sign *= -1;
|
||||
if (rat_lt(*px, range, precision))
|
||||
{
|
||||
range->pp->sign *= -1;
|
||||
if ( rat_lt(*px, range, precision) )
|
||||
{
|
||||
DUPRAT(*px,range);
|
||||
}
|
||||
range->pp->sign *= -1;
|
||||
DUPRAT(*px, range);
|
||||
}
|
||||
range->pp->sign *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
@@ -575,11 +575,11 @@ void inbetween( PRAT *px, PRAT range, int32_t precision)
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void _dumprawrat( const wchar_t *varname, PRAT rat, wostream& out)
|
||||
void _dumprawrat(const wchar_t* varname, PRAT rat, wostream& out)
|
||||
|
||||
{
|
||||
_dumprawnum(varname, rat->pp, out );
|
||||
_dumprawnum(varname, rat->pq, out );
|
||||
_dumprawnum(varname, rat->pp, out);
|
||||
_dumprawnum(varname, rat->pq, out);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
@@ -593,26 +593,26 @@ void _dumprawrat( const wchar_t *varname, PRAT rat, wostream& out)
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void _dumprawnum(const wchar_t *varname, PNUMBER num, wostream& out)
|
||||
void _dumprawnum(const wchar_t* varname, PNUMBER num, wostream& out)
|
||||
|
||||
{
|
||||
int i;
|
||||
|
||||
out << L"NUMBER " << varname << L" = {\n";
|
||||
out << L"\t"<< num->sign << L",\n";
|
||||
out << L"\t" << num->sign << L",\n";
|
||||
out << L"\t" << num->cdigit << L",\n";
|
||||
out << L"\t" << num->exp << L",\n";
|
||||
out << L"\t{ ";
|
||||
|
||||
for ( i = 0; i < num->cdigit; i++ )
|
||||
{
|
||||
out << L" "<< num->mant[i] << L",";
|
||||
}
|
||||
for (i = 0; i < num->cdigit; i++)
|
||||
{
|
||||
out << L" " << num->mant[i] << L",";
|
||||
}
|
||||
out << L"}\n";
|
||||
out << L"};\n";
|
||||
}
|
||||
|
||||
void _readconstants( void )
|
||||
void _readconstants(void)
|
||||
|
||||
{
|
||||
READRAWNUM(num_one);
|
||||
@@ -676,43 +676,43 @@ void _readconstants( void )
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void trimit( PRAT *px, int32_t precision)
|
||||
void trimit(PRAT* px, int32_t precision)
|
||||
|
||||
{
|
||||
if ( !g_ftrueinfinite )
|
||||
{
|
||||
if (!g_ftrueinfinite)
|
||||
{
|
||||
int32_t trim;
|
||||
PNUMBER pp=(*px)->pp;
|
||||
PNUMBER pq=(*px)->pq;
|
||||
trim = g_ratio * (min((pp->cdigit+pp->exp),(pq->cdigit+pq->exp))-1) - precision;
|
||||
if ( trim > g_ratio )
|
||||
{
|
||||
PNUMBER pp = (*px)->pp;
|
||||
PNUMBER pq = (*px)->pq;
|
||||
trim = g_ratio * (min((pp->cdigit + pp->exp), (pq->cdigit + pq->exp)) - 1) - precision;
|
||||
if (trim > g_ratio)
|
||||
{
|
||||
trim /= g_ratio;
|
||||
|
||||
if ( trim <= pp->exp )
|
||||
{
|
||||
if (trim <= pp->exp)
|
||||
{
|
||||
pp->exp -= trim;
|
||||
}
|
||||
else
|
||||
{
|
||||
memmove( pp->mant, &(pp->mant[trim-pp->exp]), sizeof(MANTTYPE)*(pp->cdigit-trim+pp->exp) );
|
||||
pp->cdigit -= trim-pp->exp;
|
||||
pp->exp = 0;
|
||||
}
|
||||
|
||||
if ( trim <= pq->exp )
|
||||
{
|
||||
pq->exp -= trim;
|
||||
}
|
||||
else
|
||||
{
|
||||
memmove( pq->mant, &(pq->mant[trim-pq->exp]), sizeof(MANTTYPE)*(pq->cdigit-trim+pq->exp) );
|
||||
pq->cdigit -= trim-pq->exp;
|
||||
pq->exp = 0;
|
||||
}
|
||||
}
|
||||
trim = min(pp->exp,pq->exp);
|
||||
else
|
||||
{
|
||||
memmove(pp->mant, &(pp->mant[trim - pp->exp]), sizeof(MANTTYPE) * (pp->cdigit - trim + pp->exp));
|
||||
pp->cdigit -= trim - pp->exp;
|
||||
pp->exp = 0;
|
||||
}
|
||||
|
||||
if (trim <= pq->exp)
|
||||
{
|
||||
pq->exp -= trim;
|
||||
}
|
||||
else
|
||||
{
|
||||
memmove(pq->mant, &(pq->mant[trim - pq->exp]), sizeof(MANTTYPE) * (pq->cdigit - trim + pq->exp));
|
||||
pq->cdigit -= trim - pq->exp;
|
||||
pq->exp = 0;
|
||||
}
|
||||
}
|
||||
trim = min(pp->exp, pq->exp);
|
||||
pp->exp -= trim;
|
||||
pq->exp -= trim;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -14,28 +14,24 @@
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include "pch.h"
|
||||
#include "ratpak.h"
|
||||
|
||||
|
||||
|
||||
void scalerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision )
|
||||
void scalerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
|
||||
{
|
||||
switch ( angletype )
|
||||
switch (angletype)
|
||||
{
|
||||
case ANGLE_RAD:
|
||||
scale2pi( pa, radix, precision);
|
||||
scale2pi(pa, radix, precision);
|
||||
break;
|
||||
case ANGLE_DEG:
|
||||
scale( pa, rat_360, radix, precision);
|
||||
scale(pa, rat_360, radix, precision);
|
||||
break;
|
||||
case ANGLE_GRAD:
|
||||
scale( pa, rat_400, radix, precision);
|
||||
scale(pa, rat_400, radix, precision);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNCTION: sinrat, _sinrat
|
||||
@@ -67,21 +63,21 @@ void scalerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t p
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
void _sinrat( PRAT *px, int32_t precision)
|
||||
void _sinrat(PRAT* px, int32_t precision)
|
||||
|
||||
{
|
||||
CREATETAYLOR();
|
||||
|
||||
DUPRAT(pret,*px);
|
||||
DUPRAT(thisterm,*px);
|
||||
DUPRAT(pret, *px);
|
||||
DUPRAT(thisterm, *px);
|
||||
|
||||
DUPNUM(n2,num_one);
|
||||
DUPNUM(n2, num_one);
|
||||
xx->pp->sign *= -1;
|
||||
|
||||
do {
|
||||
NEXTTERM(xx,INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
} while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
|
||||
do
|
||||
{
|
||||
NEXTTERM(xx, INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
||||
|
||||
DESTROYTAYLOR();
|
||||
|
||||
@@ -90,42 +86,42 @@ void _sinrat( PRAT *px, int32_t precision)
|
||||
inbetween(px, rat_one, precision);
|
||||
|
||||
// Since *px might be epsilon near zero we must set it to zero.
|
||||
if ( rat_le(*px, rat_smallest, precision) && rat_ge(*px, rat_negsmallest, precision) )
|
||||
{
|
||||
DUPRAT(*px,rat_zero);
|
||||
}
|
||||
if (rat_le(*px, rat_smallest, precision) && rat_ge(*px, rat_negsmallest, precision))
|
||||
{
|
||||
DUPRAT(*px, rat_zero);
|
||||
}
|
||||
}
|
||||
|
||||
void sinrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||
void sinrat(PRAT* px, uint32_t radix, int32_t precision)
|
||||
{
|
||||
scale2pi(px, radix, precision);
|
||||
_sinrat(px, precision);
|
||||
}
|
||||
|
||||
void sinanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
|
||||
void sinanglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
scalerat( pa, angletype, radix, precision);
|
||||
switch ( angletype )
|
||||
{
|
||||
scalerat(pa, angletype, radix, precision);
|
||||
switch (angletype)
|
||||
{
|
||||
case ANGLE_DEG:
|
||||
if ( rat_gt( *pa, rat_180, precision) )
|
||||
{
|
||||
if (rat_gt(*pa, rat_180, precision))
|
||||
{
|
||||
subrat(pa, rat_360, precision);
|
||||
}
|
||||
divrat( pa, rat_180, precision);
|
||||
mulrat( pa, pi, precision);
|
||||
}
|
||||
divrat(pa, rat_180, precision);
|
||||
mulrat(pa, pi, precision);
|
||||
break;
|
||||
case ANGLE_GRAD:
|
||||
if ( rat_gt( *pa, rat_200, precision) )
|
||||
{
|
||||
subrat(pa,rat_400, precision);
|
||||
}
|
||||
divrat( pa, rat_200, precision);
|
||||
mulrat( pa, pi, precision);
|
||||
break;
|
||||
if (rat_gt(*pa, rat_200, precision))
|
||||
{
|
||||
subrat(pa, rat_400, precision);
|
||||
}
|
||||
_sinrat( pa, precision);
|
||||
divrat(pa, rat_200, precision);
|
||||
mulrat(pa, pi, precision);
|
||||
break;
|
||||
}
|
||||
_sinrat(pa, precision);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -159,8 +155,7 @@ void sinanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
void _cosrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||
void _cosrat(PRAT* px, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
CREATETAYLOR();
|
||||
@@ -168,67 +163,68 @@ void _cosrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||
destroynum(pret->pp);
|
||||
destroynum(pret->pq);
|
||||
|
||||
pret->pp=i32tonum( 1L, radix);
|
||||
pret->pq=i32tonum( 1L, radix);
|
||||
pret->pp = i32tonum(1L, radix);
|
||||
pret->pq = i32tonum(1L, radix);
|
||||
|
||||
DUPRAT(thisterm,pret)
|
||||
DUPRAT(thisterm, pret)
|
||||
|
||||
n2=i32tonum(0L, radix);
|
||||
n2 = i32tonum(0L, radix);
|
||||
xx->pp->sign *= -1;
|
||||
|
||||
do {
|
||||
NEXTTERM(xx,INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
} while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
|
||||
do
|
||||
{
|
||||
NEXTTERM(xx, INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
||||
|
||||
DESTROYTAYLOR();
|
||||
// Since *px might be epsilon above 1 or below -1, due to TRIMIT we need
|
||||
// this trick here.
|
||||
inbetween(px, rat_one, precision);
|
||||
// Since *px might be epsilon near zero we must set it to zero.
|
||||
if ( rat_le(*px, rat_smallest, precision) && rat_ge(*px, rat_negsmallest, precision) )
|
||||
{
|
||||
DUPRAT(*px,rat_zero);
|
||||
}
|
||||
if (rat_le(*px, rat_smallest, precision) && rat_ge(*px, rat_negsmallest, precision))
|
||||
{
|
||||
DUPRAT(*px, rat_zero);
|
||||
}
|
||||
}
|
||||
|
||||
void cosrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||
void cosrat(PRAT* px, uint32_t radix, int32_t precision)
|
||||
{
|
||||
scale2pi(px, radix, precision);
|
||||
_cosrat(px, radix, precision);
|
||||
}
|
||||
|
||||
void cosanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
|
||||
void cosanglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
scalerat( pa, angletype, radix, precision);
|
||||
switch ( angletype )
|
||||
{
|
||||
scalerat(pa, angletype, radix, precision);
|
||||
switch (angletype)
|
||||
{
|
||||
case ANGLE_DEG:
|
||||
if ( rat_gt( *pa, rat_180, precision) )
|
||||
{
|
||||
PRAT ptmp= nullptr;
|
||||
DUPRAT(ptmp,rat_360);
|
||||
if (rat_gt(*pa, rat_180, precision))
|
||||
{
|
||||
PRAT ptmp = nullptr;
|
||||
DUPRAT(ptmp, rat_360);
|
||||
subrat(&ptmp, *pa, precision);
|
||||
destroyrat(*pa);
|
||||
*pa=ptmp;
|
||||
}
|
||||
divrat( pa, rat_180, precision);
|
||||
mulrat( pa, pi, precision);
|
||||
*pa = ptmp;
|
||||
}
|
||||
divrat(pa, rat_180, precision);
|
||||
mulrat(pa, pi, precision);
|
||||
break;
|
||||
case ANGLE_GRAD:
|
||||
if ( rat_gt( *pa, rat_200, precision) )
|
||||
{
|
||||
PRAT ptmp= nullptr;
|
||||
DUPRAT(ptmp,rat_400);
|
||||
if (rat_gt(*pa, rat_200, precision))
|
||||
{
|
||||
PRAT ptmp = nullptr;
|
||||
DUPRAT(ptmp, rat_400);
|
||||
subrat(&ptmp, *pa, precision);
|
||||
destroyrat(*pa);
|
||||
*pa=ptmp;
|
||||
}
|
||||
divrat( pa, rat_200, precision);
|
||||
mulrat( pa, pi, precision);
|
||||
break;
|
||||
*pa = ptmp;
|
||||
}
|
||||
_cosrat( pa, radix, precision);
|
||||
divrat(pa, rat_200, precision);
|
||||
mulrat(pa, pi, precision);
|
||||
break;
|
||||
}
|
||||
_cosrat(pa, radix, precision);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -243,55 +239,52 @@ void cosanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
void _tanrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||
void _tanrat(PRAT* px, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
PRAT ptmp= nullptr;
|
||||
PRAT ptmp = nullptr;
|
||||
|
||||
DUPRAT(ptmp,*px);
|
||||
DUPRAT(ptmp, *px);
|
||||
_sinrat(px, precision);
|
||||
_cosrat(&ptmp, radix, precision);
|
||||
if ( zerrat( ptmp ) )
|
||||
{
|
||||
if (zerrat(ptmp))
|
||||
{
|
||||
destroyrat(ptmp);
|
||||
throw( CALC_E_DOMAIN );
|
||||
}
|
||||
throw(CALC_E_DOMAIN);
|
||||
}
|
||||
divrat(px, ptmp, precision);
|
||||
|
||||
destroyrat(ptmp);
|
||||
|
||||
}
|
||||
|
||||
void tanrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||
void tanrat(PRAT* px, uint32_t radix, int32_t precision)
|
||||
{
|
||||
scale2pi(px, radix, precision);
|
||||
_tanrat(px, radix, precision);
|
||||
}
|
||||
|
||||
void tananglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
|
||||
void tananglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
scalerat( pa, angletype, radix, precision);
|
||||
switch ( angletype )
|
||||
{
|
||||
scalerat(pa, angletype, radix, precision);
|
||||
switch (angletype)
|
||||
{
|
||||
case ANGLE_DEG:
|
||||
if ( rat_gt( *pa, rat_180, precision) )
|
||||
{
|
||||
if (rat_gt(*pa, rat_180, precision))
|
||||
{
|
||||
subrat(pa, rat_180, precision);
|
||||
}
|
||||
divrat( pa, rat_180, precision);
|
||||
mulrat( pa, pi, precision);
|
||||
}
|
||||
divrat(pa, rat_180, precision);
|
||||
mulrat(pa, pi, precision);
|
||||
break;
|
||||
case ANGLE_GRAD:
|
||||
if ( rat_gt( *pa, rat_200, precision) )
|
||||
{
|
||||
if (rat_gt(*pa, rat_200, precision))
|
||||
{
|
||||
subrat(pa, rat_200, precision);
|
||||
}
|
||||
divrat( pa, rat_200, precision);
|
||||
mulrat( pa, pi, precision);
|
||||
break;
|
||||
}
|
||||
_tanrat( pa, radix, precision);
|
||||
divrat(pa, rat_200, precision);
|
||||
mulrat(pa, pi, precision);
|
||||
break;
|
||||
}
|
||||
_tanrat(pa, radix, precision);
|
||||
}
|
||||
|
||||
|
@@ -14,25 +14,21 @@
|
||||
//
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "pch.h"
|
||||
#include "ratpak.h"
|
||||
|
||||
|
||||
|
||||
bool IsValidForHypFunc(PRAT px, int32_t precision)
|
||||
{
|
||||
PRAT ptmp = nullptr;
|
||||
bool bRet = true;
|
||||
|
||||
DUPRAT(ptmp,rat_min_exp);
|
||||
DUPRAT(ptmp, rat_min_exp);
|
||||
divrat(&ptmp, rat_ten, precision);
|
||||
if ( rat_lt( px, ptmp, precision) )
|
||||
if (rat_lt(px, ptmp, precision))
|
||||
{
|
||||
bRet = false;
|
||||
}
|
||||
destroyrat( ptmp );
|
||||
destroyrat(ptmp);
|
||||
return bRet;
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -68,49 +64,49 @@ bool IsValidForHypFunc(PRAT px, int32_t precision)
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
void _sinhrat( PRAT *px, int32_t precision)
|
||||
void _sinhrat(PRAT* px, int32_t precision)
|
||||
|
||||
{
|
||||
if ( !IsValidForHypFunc(*px, precision))
|
||||
{
|
||||
if (!IsValidForHypFunc(*px, precision))
|
||||
{
|
||||
// Don't attempt exp of anything large or small
|
||||
throw( CALC_E_DOMAIN );
|
||||
}
|
||||
throw(CALC_E_DOMAIN);
|
||||
}
|
||||
|
||||
CREATETAYLOR();
|
||||
|
||||
DUPRAT(pret,*px);
|
||||
DUPRAT(thisterm,pret);
|
||||
DUPRAT(pret, *px);
|
||||
DUPRAT(thisterm, pret);
|
||||
|
||||
DUPNUM(n2,num_one);
|
||||
DUPNUM(n2, num_one);
|
||||
|
||||
do {
|
||||
NEXTTERM(xx,INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
} while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
|
||||
do
|
||||
{
|
||||
NEXTTERM(xx, INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
||||
|
||||
DESTROYTAYLOR();
|
||||
}
|
||||
|
||||
void sinhrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||
void sinhrat(PRAT* px, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
PRAT tmpx= nullptr;
|
||||
PRAT tmpx = nullptr;
|
||||
|
||||
if ( rat_ge( *px, rat_one, precision) )
|
||||
{
|
||||
DUPRAT(tmpx,*px);
|
||||
if (rat_ge(*px, rat_one, precision))
|
||||
{
|
||||
DUPRAT(tmpx, *px);
|
||||
exprat(px, radix, precision);
|
||||
tmpx->pp->sign *= -1;
|
||||
exprat(&tmpx, radix, precision);
|
||||
subrat( px, tmpx, precision);
|
||||
divrat( px, rat_two, precision);
|
||||
destroyrat( tmpx );
|
||||
}
|
||||
subrat(px, tmpx, precision);
|
||||
divrat(px, rat_two, precision);
|
||||
destroyrat(tmpx);
|
||||
}
|
||||
else
|
||||
{
|
||||
_sinhrat( px, precision);
|
||||
}
|
||||
{
|
||||
_sinhrat(px, precision);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -147,59 +143,59 @@ void sinhrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
void _coshrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||
void _coshrat(PRAT* px, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
if ( !IsValidForHypFunc(*px, precision))
|
||||
{
|
||||
if (!IsValidForHypFunc(*px, precision))
|
||||
{
|
||||
// Don't attempt exp of anything large or small
|
||||
throw( CALC_E_DOMAIN );
|
||||
}
|
||||
throw(CALC_E_DOMAIN);
|
||||
}
|
||||
|
||||
CREATETAYLOR();
|
||||
|
||||
pret->pp=i32tonum( 1L, radix);
|
||||
pret->pq=i32tonum( 1L, radix);
|
||||
pret->pp = i32tonum(1L, radix);
|
||||
pret->pq = i32tonum(1L, radix);
|
||||
|
||||
DUPRAT(thisterm,pret)
|
||||
DUPRAT(thisterm, pret)
|
||||
|
||||
n2=i32tonum(0L, radix);
|
||||
n2 = i32tonum(0L, radix);
|
||||
|
||||
do {
|
||||
NEXTTERM(xx,INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
} while ( !SMALL_ENOUGH_RAT( thisterm, precision) );
|
||||
do
|
||||
{
|
||||
NEXTTERM(xx, INC(n2) DIVNUM(n2) INC(n2) DIVNUM(n2), precision);
|
||||
} while (!SMALL_ENOUGH_RAT(thisterm, precision));
|
||||
|
||||
DESTROYTAYLOR();
|
||||
}
|
||||
|
||||
void coshrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||
void coshrat(PRAT* px, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
PRAT tmpx= nullptr;
|
||||
PRAT tmpx = nullptr;
|
||||
|
||||
(*px)->pp->sign = 1;
|
||||
(*px)->pq->sign = 1;
|
||||
if ( rat_ge( *px, rat_one, precision) )
|
||||
{
|
||||
DUPRAT(tmpx,*px);
|
||||
if (rat_ge(*px, rat_one, precision))
|
||||
{
|
||||
DUPRAT(tmpx, *px);
|
||||
exprat(px, radix, precision);
|
||||
tmpx->pp->sign *= -1;
|
||||
exprat(&tmpx, radix, precision);
|
||||
addrat( px, tmpx, precision);
|
||||
divrat( px, rat_two, precision);
|
||||
destroyrat( tmpx );
|
||||
}
|
||||
addrat(px, tmpx, precision);
|
||||
divrat(px, rat_two, precision);
|
||||
destroyrat(tmpx);
|
||||
}
|
||||
else
|
||||
{
|
||||
_coshrat( px, radix, precision);
|
||||
}
|
||||
{
|
||||
_coshrat(px, radix, precision);
|
||||
}
|
||||
// Since *px might be epsilon below 1 due to TRIMIT
|
||||
// we need this trick here.
|
||||
if ( rat_lt(*px, rat_one, precision) )
|
||||
{
|
||||
DUPRAT(*px,rat_one);
|
||||
}
|
||||
if (rat_lt(*px, rat_one, precision))
|
||||
{
|
||||
DUPRAT(*px, rat_one);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -215,17 +211,16 @@ void coshrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void tanhrat( PRAT *px, uint32_t radix, int32_t precision)
|
||||
void tanhrat(PRAT* px, uint32_t radix, int32_t precision)
|
||||
|
||||
{
|
||||
PRAT ptmp= nullptr;
|
||||
PRAT ptmp = nullptr;
|
||||
|
||||
DUPRAT(ptmp,*px);
|
||||
DUPRAT(ptmp, *px);
|
||||
sinhrat(px, radix, precision);
|
||||
coshrat(&ptmp, radix, precision);
|
||||
mulnumx(&((*px)->pp),ptmp->pq);
|
||||
mulnumx(&((*px)->pq),ptmp->pp);
|
||||
mulnumx(&((*px)->pp), ptmp->pq);
|
||||
mulnumx(&((*px)->pq), ptmp->pp);
|
||||
|
||||
destroyrat(ptmp);
|
||||
|
||||
}
|
||||
|
@@ -1,16 +1,16 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#include "pch.h"
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <sstream>
|
||||
#include <algorithm> // for std::sort
|
||||
#include "Command.h"
|
||||
#include "UnitConverter.h"
|
||||
|
||||
using namespace concurrency;
|
||||
using namespace std;
|
||||
using namespace UnitConversionManager;
|
||||
|
||||
static constexpr uint32_t EXPECTEDSERIALIZEDTOKENCOUNT = 7;
|
||||
static constexpr uint32_t EXPECTEDSERIALIZEDCONVERSIONDATATOKENCOUNT = 3;
|
||||
static constexpr uint32_t EXPECTEDSERIALIZEDCATEGORYTOKENCOUNT = 3;
|
||||
static constexpr uint32_t EXPECTEDSERIALIZEDUNITTOKENCOUNT = 6;
|
||||
static constexpr uint32_t EXPECTEDSTATEDATATOKENCOUNT = 5;
|
||||
@@ -32,8 +32,8 @@ unordered_map<wstring, wchar_t> unquoteConversions;
|
||||
/// Constructor, sets up all the variables and requires a configLoader
|
||||
/// </summary>
|
||||
/// <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(dataLoader, nullptr)
|
||||
UnitConverter::UnitConverter(_In_ const shared_ptr<IConverterDataLoader>& dataLoader)
|
||||
: UnitConverter::UnitConverter(dataLoader, nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -63,7 +63,8 @@ UnitConverter::UnitConverter(_In_ const shared_ptr<IConverterDataLoader>& dataLo
|
||||
unquoteConversions[L"{sc}"] = L';';
|
||||
unquoteConversions[L"{lb}"] = LEFTESCAPECHAR;
|
||||
unquoteConversions[L"{rb}"] = RIGHTESCAPECHAR;
|
||||
Reset();
|
||||
ClearValues();
|
||||
ResetCategoriesAndRatios();
|
||||
}
|
||||
|
||||
void UnitConverter::Initialize()
|
||||
@@ -75,7 +76,7 @@ bool UnitConverter::CheckLoad()
|
||||
{
|
||||
if (m_categories.empty())
|
||||
{
|
||||
Reset();
|
||||
ResetCategoriesAndRatios();
|
||||
}
|
||||
return !m_categories.empty();
|
||||
}
|
||||
@@ -152,7 +153,6 @@ void UnitConverter::SetCurrentUnitTypes(const Unit& fromType, const Unit& toType
|
||||
Calculate();
|
||||
|
||||
UpdateCurrencySymbols();
|
||||
UpdateViewModel();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -190,14 +190,14 @@ void UnitConverter::SwitchActive(const wstring& newValue)
|
||||
}
|
||||
}
|
||||
|
||||
wstring UnitConverter::CategoryToString(const Category& c, const wchar_t * delimiter)
|
||||
wstring UnitConverter::CategoryToString(const Category& c, const wchar_t* delimiter)
|
||||
{
|
||||
wstringstream out(wstringstream::out);
|
||||
out << Quote(std::to_wstring(c.id)) << delimiter << Quote(std::to_wstring(c.supportsNegative)) << delimiter << Quote(c.name) << delimiter;
|
||||
return out.str();
|
||||
}
|
||||
|
||||
vector<wstring> UnitConverter::StringToVector(const wstring& w, const wchar_t * delimiter, bool addRemainder)
|
||||
vector<wstring> UnitConverter::StringToVector(const wstring& w, const wchar_t* delimiter, bool addRemainder)
|
||||
{
|
||||
size_t delimiterIndex = w.find(delimiter);
|
||||
size_t startIndex = 0;
|
||||
@@ -215,22 +215,12 @@ vector<wstring> UnitConverter::StringToVector(const wstring& w, const wchar_t *
|
||||
}
|
||||
return serializedTokens;
|
||||
}
|
||||
|
||||
Category UnitConverter::StringToCategory(const wstring& w)
|
||||
{
|
||||
vector<wstring> tokenList = StringToVector(w, L";");
|
||||
assert(tokenList.size() == EXPECTEDSERIALIZEDCATEGORYTOKENCOUNT);
|
||||
Category serializedCategory;
|
||||
serializedCategory.id = _wtoi(Unquote(tokenList[0]).c_str());
|
||||
serializedCategory.supportsNegative = (tokenList[1].compare(L"1") == 0);
|
||||
serializedCategory.name = Unquote(tokenList[2]);
|
||||
return serializedCategory;
|
||||
}
|
||||
|
||||
wstring UnitConverter::UnitToString(const Unit& u, const wchar_t * delimiter)
|
||||
wstring UnitConverter::UnitToString(const Unit& u, const wchar_t* delimiter)
|
||||
{
|
||||
wstringstream out(wstringstream::out);
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -239,7 +229,7 @@ Unit UnitConverter::StringToUnit(const wstring& w)
|
||||
vector<wstring> tokenList = StringToVector(w, L";");
|
||||
assert(tokenList.size() == EXPECTEDSERIALIZEDUNITTOKENCOUNT);
|
||||
Unit serializedUnit;
|
||||
serializedUnit.id = _wtoi(Unquote(tokenList[0]).c_str());
|
||||
serializedUnit.id = wcstol(Unquote(tokenList[0]).c_str(), nullptr, 10);
|
||||
serializedUnit.name = Unquote(tokenList[1]);
|
||||
serializedUnit.accessibleName = serializedUnit.name;
|
||||
serializedUnit.abbreviation = Unquote(tokenList[2]);
|
||||
@@ -249,146 +239,15 @@ Unit UnitConverter::StringToUnit(const wstring& w)
|
||||
return serializedUnit;
|
||||
}
|
||||
|
||||
ConversionData UnitConverter::StringToConversionData(const wstring& w)
|
||||
Category UnitConverter::StringToCategory(const wstring& w)
|
||||
{
|
||||
vector<wstring> tokenList = StringToVector(w, L";");
|
||||
assert(tokenList.size() == EXPECTEDSERIALIZEDCONVERSIONDATATOKENCOUNT);
|
||||
ConversionData serializedConversionData;
|
||||
serializedConversionData.ratio = stod(Unquote(tokenList[0]).c_str());
|
||||
serializedConversionData.offset = stod(Unquote(tokenList[1]).c_str());
|
||||
serializedConversionData.offsetFirst = (tokenList[2].compare(L"1") == 0);
|
||||
return serializedConversionData;
|
||||
}
|
||||
|
||||
wstring UnitConverter::ConversionDataToString(ConversionData d, const wchar_t * delimiter)
|
||||
{
|
||||
wstringstream out(wstringstream::out);
|
||||
out.precision(32);
|
||||
out << fixed << d.ratio;
|
||||
wstring ratio = out.str();
|
||||
out.str(L"");
|
||||
out << fixed << d.offset;
|
||||
wstring offset = out.str();
|
||||
out.str(L"");
|
||||
TrimString(ratio);
|
||||
TrimString(offset);
|
||||
out << Quote(ratio) << delimiter << Quote(offset) << delimiter << std::to_wstring(d.offsetFirst) << delimiter;
|
||||
return out.str();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serializes the data in the converter and returns it as a string
|
||||
/// </summary>
|
||||
wstring UnitConverter::Serialize()
|
||||
{
|
||||
if (!CheckLoad())
|
||||
{
|
||||
return wstring();
|
||||
}
|
||||
|
||||
wstringstream out(wstringstream::out);
|
||||
const wchar_t * delimiter = L";";
|
||||
|
||||
out << UnitToString(m_fromType, delimiter) << "|";
|
||||
out << UnitToString(m_toType, delimiter) << "|";
|
||||
out << CategoryToString(m_currentCategory, delimiter) << "|";
|
||||
out << std::to_wstring(m_currentHasDecimal) << delimiter << std::to_wstring(m_returnHasDecimal) << delimiter << std::to_wstring(m_switchedActive) << delimiter;
|
||||
out << m_currentDisplay << delimiter << m_returnDisplay << delimiter << "|";
|
||||
wstringstream categoryString(wstringstream::out);
|
||||
wstringstream categoryToUnitString(wstringstream::out);
|
||||
wstringstream unitToUnitToDoubleString(wstringstream::out);
|
||||
for (const Category& c : m_categories)
|
||||
{
|
||||
categoryString << CategoryToString(c, delimiter) << ",";
|
||||
}
|
||||
|
||||
for (const auto& cur : m_categoryToUnits)
|
||||
{
|
||||
categoryToUnitString << CategoryToString(cur.first, delimiter) << "[";
|
||||
for (const Unit& u : cur.second)
|
||||
{
|
||||
categoryToUnitString << UnitToString(u, delimiter) << ",";
|
||||
}
|
||||
categoryToUnitString << "[" << "]";
|
||||
}
|
||||
|
||||
for (const auto& cur : m_ratioMap)
|
||||
{
|
||||
unitToUnitToDoubleString << UnitToString(cur.first, delimiter) << "[";
|
||||
for (const auto& curConversion : cur.second)
|
||||
{
|
||||
unitToUnitToDoubleString << UnitToString(curConversion.first, delimiter) << ":";
|
||||
unitToUnitToDoubleString << ConversionDataToString(curConversion.second, delimiter) << ":,";
|
||||
}
|
||||
unitToUnitToDoubleString << "[" << "]";
|
||||
}
|
||||
|
||||
out << categoryString.str() << "|";
|
||||
out << categoryToUnitString.str() << "|";
|
||||
out << unitToUnitToDoubleString.str() << "|";
|
||||
wstring test = out.str();
|
||||
return test;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// De-Serializes the data in the converter from a string
|
||||
/// </summary>
|
||||
/// <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)
|
||||
{
|
||||
Reset();
|
||||
|
||||
if (serializedData.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
vector<wstring> outerTokens = StringToVector(serializedData, L"|");
|
||||
assert(outerTokens.size() == EXPECTEDSERIALIZEDTOKENCOUNT);
|
||||
m_fromType = StringToUnit(outerTokens[0]);
|
||||
m_toType = StringToUnit(outerTokens[1]);
|
||||
m_currentCategory = StringToCategory(outerTokens[2]);
|
||||
vector<wstring> stateDataTokens = StringToVector(outerTokens[3], L";");
|
||||
assert(stateDataTokens.size() == EXPECTEDSTATEDATATOKENCOUNT);
|
||||
m_currentHasDecimal = (stateDataTokens[0].compare(L"1") == 0);
|
||||
m_returnHasDecimal = (stateDataTokens[1].compare(L"1") == 0);
|
||||
m_switchedActive = (stateDataTokens[2].compare(L"1") == 0);
|
||||
m_currentDisplay = stateDataTokens[3];
|
||||
m_returnDisplay = stateDataTokens[4];
|
||||
vector<wstring> categoryListTokens = StringToVector(outerTokens[4], L",");
|
||||
for (wstring token : categoryListTokens)
|
||||
{
|
||||
m_categories.push_back(StringToCategory(token));
|
||||
}
|
||||
vector<wstring> unitVectorTokens = StringToVector(outerTokens[5], L"]");
|
||||
for (wstring unitVector : unitVectorTokens)
|
||||
{
|
||||
vector<wstring> mapcomponents = StringToVector(unitVector, L"[");
|
||||
assert(mapcomponents.size() == EXPECTEDMAPCOMPONENTTOKENCOUNT);
|
||||
Category key = StringToCategory(mapcomponents[0]);
|
||||
vector<wstring> units = StringToVector(mapcomponents[1], L",");
|
||||
for (wstring unit : units)
|
||||
{
|
||||
m_categoryToUnits[key].push_back(StringToUnit(unit));
|
||||
}
|
||||
}
|
||||
vector<wstring> ratioMapTokens = StringToVector(outerTokens[6], L"]");
|
||||
for (wstring token : ratioMapTokens)
|
||||
{
|
||||
vector<wstring> ratioMapComponentTokens = StringToVector(token, L"[");
|
||||
assert(ratioMapComponentTokens.size() == EXPECTEDMAPCOMPONENTTOKENCOUNT);
|
||||
Unit key = StringToUnit(ratioMapComponentTokens[0]);
|
||||
vector<wstring> ratioMapList = StringToVector(ratioMapComponentTokens[1], L",");
|
||||
for (wstring subtoken : ratioMapList)
|
||||
{
|
||||
vector<wstring> ratioMapSubComponentTokens = StringToVector(subtoken, L":");
|
||||
assert(ratioMapSubComponentTokens.size() == EXPECTEDMAPCOMPONENTTOKENCOUNT);
|
||||
Unit subkey = StringToUnit(ratioMapSubComponentTokens[0]);
|
||||
ConversionData conversion = StringToConversionData(ratioMapSubComponentTokens[1]);
|
||||
m_ratioMap[key][subkey] = conversion;
|
||||
}
|
||||
}
|
||||
UpdateViewModel();
|
||||
assert(tokenList.size() == EXPECTEDSERIALIZEDCATEGORYTOKENCOUNT);
|
||||
Category serializedCategory;
|
||||
serializedCategory.id = wcstol(Unquote(tokenList[0]).c_str(), nullptr, 10);
|
||||
serializedCategory.supportsNegative = (tokenList[1].compare(L"1") == 0);
|
||||
serializedCategory.name = Unquote(tokenList[2]);
|
||||
return serializedCategory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -403,11 +262,28 @@ void UnitConverter::RestoreUserPreferences(const wstring& userPreferences)
|
||||
}
|
||||
|
||||
vector<wstring> outerTokens = StringToVector(userPreferences, L"|");
|
||||
if (outerTokens.size() == 3)
|
||||
if (outerTokens.size() != 3)
|
||||
{
|
||||
m_fromType = StringToUnit(outerTokens[0]);
|
||||
m_toType = StringToUnit(outerTokens[1]);
|
||||
m_currentCategory = StringToCategory(outerTokens[2]);
|
||||
return;
|
||||
}
|
||||
|
||||
auto fromType = StringToUnit(outerTokens[0]);
|
||||
auto toType = StringToUnit(outerTokens[1]);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -417,7 +293,7 @@ void UnitConverter::RestoreUserPreferences(const wstring& userPreferences)
|
||||
wstring UnitConverter::SaveUserPreferences()
|
||||
{
|
||||
wstringstream out(wstringstream::out);
|
||||
const wchar_t * delimiter = L";";
|
||||
const wchar_t* delimiter = L";";
|
||||
|
||||
out << UnitToString(m_fromType, delimiter) << "|";
|
||||
out << UnitToString(m_toType, delimiter) << "|";
|
||||
@@ -436,7 +312,7 @@ wstring UnitConverter::Quote(const wstring& s)
|
||||
|
||||
// Iterate over the delimiter characters we need to quote
|
||||
wstring::const_iterator cursor = s.begin();
|
||||
while(cursor != s.end())
|
||||
while (cursor != s.end())
|
||||
{
|
||||
if (quoteConversions.find(*cursor) != quoteConversions.end())
|
||||
{
|
||||
@@ -460,9 +336,9 @@ wstring UnitConverter::Unquote(const wstring& s)
|
||||
wstringstream quotedSubString(wstringstream::out);
|
||||
wstringstream unquotedString(wstringstream::out);
|
||||
wstring::const_iterator cursor = s.begin();
|
||||
while(cursor != s.end())
|
||||
while (cursor != s.end())
|
||||
{
|
||||
if(*cursor == LEFTESCAPECHAR)
|
||||
if (*cursor == LEFTESCAPECHAR)
|
||||
{
|
||||
quotedSubString.str(L"");
|
||||
while (cursor != s.end() && *cursor != RIGHTESCAPECHAR)
|
||||
@@ -508,7 +384,8 @@ void UnitConverter::SendCommand(Command command)
|
||||
clearFront = true;
|
||||
}
|
||||
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;
|
||||
}
|
||||
@@ -615,14 +492,13 @@ void UnitConverter::SendCommand(Command command)
|
||||
clearFront = false;
|
||||
clearBack = false;
|
||||
ClearValues();
|
||||
Reset();
|
||||
ResetCategoriesAndRatios();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (clearFront)
|
||||
{
|
||||
m_currentDisplay.erase(0, 1);
|
||||
@@ -634,8 +510,6 @@ void UnitConverter::SendCommand(Command command)
|
||||
}
|
||||
|
||||
Calculate();
|
||||
|
||||
UpdateViewModel();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -662,21 +536,23 @@ void UnitConverter::SetViewModelCurrencyCallback(_In_ const shared_ptr<IViewMode
|
||||
}
|
||||
}
|
||||
|
||||
task<pair<bool, wstring>> UnitConverter::RefreshCurrencyRatios()
|
||||
future<pair<bool, wstring>> UnitConverter::RefreshCurrencyRatios()
|
||||
{
|
||||
shared_ptr<ICurrencyConverterDataLoader> currencyDataLoader = GetCurrencyConverterDataLoader();
|
||||
return create_task([this, currencyDataLoader]()
|
||||
future<bool> loadDataResult;
|
||||
if (currencyDataLoader != nullptr)
|
||||
{
|
||||
if (currencyDataLoader != nullptr)
|
||||
{
|
||||
return currencyDataLoader->TryLoadDataFromWebOverrideAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
return task_from_result(false);
|
||||
}
|
||||
}).then([this, currencyDataLoader](bool didLoad)
|
||||
loadDataResult = currencyDataLoader->TryLoadDataFromWebOverrideAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
loadDataResult = async([] { return false; });
|
||||
}
|
||||
|
||||
shared_future<bool> sharedLoadResult = loadDataResult.share();
|
||||
return async([this, currencyDataLoader, sharedLoadResult]() {
|
||||
sharedLoadResult.wait();
|
||||
bool didLoad = sharedLoadResult.get();
|
||||
wstring timestamp = L"";
|
||||
if (currencyDataLoader != nullptr)
|
||||
{
|
||||
@@ -684,7 +560,7 @@ task<pair<bool, wstring>> UnitConverter::RefreshCurrencyRatios()
|
||||
}
|
||||
|
||||
return make_pair(didLoad, timestamp);
|
||||
}, task_continuation_context::use_default());
|
||||
});
|
||||
}
|
||||
|
||||
shared_ptr<ICurrencyConverterDataLoader> UnitConverter::GetCurrencyConverterDataLoader()
|
||||
@@ -733,7 +609,7 @@ vector<tuple<wstring, Unit>> UnitConverter::CalculateSuggested()
|
||||
newEntry.magnitude = log10(convertedValue);
|
||||
newEntry.value = convertedValue;
|
||||
newEntry.type = cur.first;
|
||||
if(newEntry.type.isWhimsical == false)
|
||||
if (newEntry.type.isWhimsical == false)
|
||||
intermediateVector.push_back(newEntry);
|
||||
else
|
||||
intermediateWhimsicalVector.push_back(newEntry);
|
||||
@@ -741,9 +617,7 @@ vector<tuple<wstring, Unit>> UnitConverter::CalculateSuggested()
|
||||
}
|
||||
|
||||
// Sort the resulting list by absolute magnitude, breaking ties by choosing the positive value
|
||||
sort(intermediateVector.begin(), intermediateVector.end(), []
|
||||
(SuggestedValueIntermediate first, SuggestedValueIntermediate second)
|
||||
{
|
||||
sort(intermediateVector.begin(), intermediateVector.end(), [](SuggestedValueIntermediate first, SuggestedValueIntermediate second) {
|
||||
if (abs(first.magnitude) == abs(second.magnitude))
|
||||
{
|
||||
return first.magnitude > second.magnitude;
|
||||
@@ -764,7 +638,7 @@ vector<tuple<wstring, Unit>> UnitConverter::CalculateSuggested()
|
||||
}
|
||||
else if (abs(entry.value) < 1000)
|
||||
{
|
||||
roundedString = RoundSignificant(entry.value, 1);
|
||||
roundedString = RoundSignificant(entry.value, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -779,9 +653,7 @@ vector<tuple<wstring, Unit>> UnitConverter::CalculateSuggested()
|
||||
|
||||
// The Whimsicals are determined differently
|
||||
// Sort the resulting list by absolute magnitude, breaking ties by choosing the positive value
|
||||
sort(intermediateWhimsicalVector.begin(), intermediateWhimsicalVector.end(), []
|
||||
(SuggestedValueIntermediate first, SuggestedValueIntermediate second)
|
||||
{
|
||||
sort(intermediateWhimsicalVector.begin(), intermediateWhimsicalVector.end(), [](SuggestedValueIntermediate first, SuggestedValueIntermediate second) {
|
||||
if (abs(first.magnitude) == abs(second.magnitude))
|
||||
{
|
||||
return first.magnitude > second.magnitude;
|
||||
@@ -824,19 +696,16 @@ vector<tuple<wstring, Unit>> UnitConverter::CalculateSuggested()
|
||||
returnVector.push_back(whimsicalReturnVector.at(0));
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
return returnVector;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets the converter to its initial state
|
||||
/// Resets categories and ratios
|
||||
/// </summary>
|
||||
void UnitConverter::Reset()
|
||||
void UnitConverter::ResetCategoriesAndRatios()
|
||||
{
|
||||
m_categories = m_dataLoader->LoadOrderedCategories();
|
||||
|
||||
ClearValues();
|
||||
m_switchedActive = false;
|
||||
|
||||
if (m_categories.empty())
|
||||
@@ -881,7 +750,6 @@ void UnitConverter::Reset()
|
||||
}
|
||||
|
||||
InitializeSelectedUnits();
|
||||
Calculate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -907,7 +775,6 @@ shared_ptr<IConverterDataLoader> UnitConverter::GetDataLoaderForCategory(const C
|
||||
/// </summary>
|
||||
void UnitConverter::InitializeSelectedUnits()
|
||||
{
|
||||
|
||||
if (m_categoryToUnits.empty())
|
||||
{
|
||||
return;
|
||||
@@ -972,11 +839,21 @@ bool UnitConverter::AnyUnitIsEmpty()
|
||||
/// </summary>
|
||||
void UnitConverter::Calculate()
|
||||
{
|
||||
unordered_map<Unit, ConversionData, UnitHash> conversionTable = m_ratioMap[m_fromType];
|
||||
double returnValue = stod(m_currentDisplay);
|
||||
if (AnyUnitIsEmpty() || (conversionTable[m_toType].ratio == 1.0 && conversionTable[m_toType].offset == 0.0))
|
||||
if (AnyUnitIsEmpty())
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
@@ -1015,9 +892,9 @@ void UnitConverter::Calculate()
|
||||
m_returnDisplay = returnString;
|
||||
TrimString(m_returnDisplay);
|
||||
}
|
||||
m_returnHasDecimal = (m_returnDisplay.find(L'.') != m_returnDisplay.npos);
|
||||
}
|
||||
|
||||
m_returnHasDecimal = (m_returnDisplay.find(L'.') != m_returnDisplay.npos);
|
||||
UpdateViewModel();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1032,7 +909,7 @@ void UnitConverter::TrimString(wstring& returnString)
|
||||
}
|
||||
|
||||
wstring::iterator iter;
|
||||
for (iter = returnString.end() - 1; ;iter--)
|
||||
for (iter = returnString.end() - 1;; iter--)
|
||||
{
|
||||
if (*iter != L'0')
|
||||
{
|
||||
@@ -1040,9 +917,9 @@ void UnitConverter::TrimString(wstring& returnString)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (*(returnString.end()-1) == L'.')
|
||||
if (*(returnString.end() - 1) == L'.')
|
||||
{
|
||||
returnString.erase(returnString.end()-1, returnString.end());
|
||||
returnString.erase(returnString.end() - 1, returnString.end());
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,22 +1,47 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <future>
|
||||
#include "sal_cross_platform.h" // for SAL
|
||||
#include <memory> // for std::shared_ptr
|
||||
|
||||
namespace UnitConversionManager
|
||||
{
|
||||
enum class Command;
|
||||
|
||||
struct Unit
|
||||
{
|
||||
Unit(){}
|
||||
Unit()
|
||||
{
|
||||
}
|
||||
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)
|
||||
: id(id), abbreviation(abbreviation), isConversionSource(isConversionSource), isConversionTarget(isConversionTarget), isWhimsical(false)
|
||||
Unit(
|
||||
int id,
|
||||
std::wstring currencyName,
|
||||
std::wstring countryName,
|
||||
std::wstring abbreviation,
|
||||
bool isRtlLanguage,
|
||||
bool isConversionSource,
|
||||
bool isConversionTarget)
|
||||
: id(id)
|
||||
, abbreviation(abbreviation)
|
||||
, isConversionSource(isConversionSource)
|
||||
, isConversionTarget(isConversionTarget)
|
||||
, isWhimsical(false)
|
||||
{
|
||||
std::wstring nameValue1 = isRtlLanguage ? currencyName : countryName;
|
||||
std::wstring nameValue2 = isRtlLanguage ? countryName : currencyName;
|
||||
@@ -25,7 +50,9 @@ namespace UnitConversionManager
|
||||
accessibleName = nameValue1 + L" " + nameValue2;
|
||||
}
|
||||
|
||||
virtual ~Unit() {}
|
||||
virtual ~Unit()
|
||||
{
|
||||
}
|
||||
|
||||
int id;
|
||||
std::wstring name;
|
||||
@@ -35,12 +62,12 @@ namespace UnitConversionManager
|
||||
bool isConversionTarget;
|
||||
bool isWhimsical;
|
||||
|
||||
bool operator!= (const Unit& that) const
|
||||
bool operator!=(const Unit& that) const
|
||||
{
|
||||
return that.id != id;
|
||||
}
|
||||
|
||||
bool operator== (const Unit& that) const
|
||||
bool operator==(const Unit& that) const
|
||||
{
|
||||
return that.id == id;
|
||||
}
|
||||
@@ -55,9 +82,14 @@ namespace UnitConversionManager
|
||||
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -65,12 +97,12 @@ namespace UnitConversionManager
|
||||
std::wstring name;
|
||||
bool supportsNegative;
|
||||
|
||||
bool operator!= (const Category& that) const
|
||||
bool operator!=(const Category& that) const
|
||||
{
|
||||
return that.id != id;
|
||||
}
|
||||
|
||||
bool operator== (const Category& that) const
|
||||
bool operator==(const Category& that) const
|
||||
{
|
||||
return that.id == id;
|
||||
}
|
||||
@@ -79,7 +111,8 @@ namespace UnitConversionManager
|
||||
class UnitHash
|
||||
{
|
||||
public:
|
||||
size_t operator() (const Unit & x) const {
|
||||
size_t operator()(const Unit& x) const
|
||||
{
|
||||
return x.id;
|
||||
}
|
||||
};
|
||||
@@ -87,7 +120,8 @@ namespace UnitConversionManager
|
||||
class CategoryHash
|
||||
{
|
||||
public:
|
||||
size_t operator() (const Category & x) const {
|
||||
size_t operator()(const Category& x) const
|
||||
{
|
||||
return x.id;
|
||||
}
|
||||
};
|
||||
@@ -101,12 +135,19 @@ namespace UnitConversionManager
|
||||
|
||||
struct ConversionData
|
||||
{
|
||||
ConversionData(){}
|
||||
ConversionData(double ratio, double offset, bool offsetFirst) : ratio(ratio), offset(offset), offsetFirst(offsetFirst)
|
||||
ConversionData()
|
||||
{
|
||||
}
|
||||
ConversionData(double ratio, double offset, bool offsetFirst)
|
||||
: ratio(ratio)
|
||||
, offset(offset)
|
||||
, offsetFirst(offsetFirst)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~ConversionData() {}
|
||||
virtual ~ConversionData()
|
||||
{
|
||||
}
|
||||
|
||||
double ratio;
|
||||
double offset;
|
||||
@@ -130,13 +171,18 @@ namespace UnitConversionManager
|
||||
};
|
||||
|
||||
typedef std::tuple<std::vector<UnitConversionManager::Unit>, UnitConversionManager::Unit, UnitConversionManager::Unit> CategorySelectionInitializer;
|
||||
typedef std::unordered_map<UnitConversionManager::Unit, std::unordered_map<UnitConversionManager::Unit, UnitConversionManager::ConversionData, UnitConversionManager::UnitHash>, UnitConversionManager::UnitHash> UnitToUnitToConversionDataMap;
|
||||
typedef std::unordered_map<UnitConversionManager::Category, std::vector<UnitConversionManager::Unit>, UnitConversionManager::CategoryHash> CategoryToUnitVectorMap;
|
||||
typedef std::unordered_map<
|
||||
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
|
||||
{
|
||||
public:
|
||||
virtual ~IViewModelCurrencyCallback() { };
|
||||
virtual ~IViewModelCurrencyCallback(){};
|
||||
virtual void CurrencyDataLoadFinished(bool didLoad) = 0;
|
||||
virtual void CurrencySymbolsCallback(_In_ const std::wstring& fromSymbol, _In_ const std::wstring& toSymbol) = 0;
|
||||
virtual void CurrencyRatiosCallback(_In_ const std::wstring& ratioEquality, _In_ const std::wstring& accRatioEquality) = 0;
|
||||
@@ -147,8 +193,8 @@ namespace UnitConversionManager
|
||||
class IConverterDataLoader
|
||||
{
|
||||
public:
|
||||
virtual ~IConverterDataLoader() { };
|
||||
virtual void LoadData() = 0; // prepare data if necessary before calling other functions
|
||||
virtual ~IConverterDataLoader(){};
|
||||
virtual void LoadData() = 0; // prepare data if necessary before calling other functions
|
||||
virtual std::vector<Category> LoadOrderedCategories() = 0;
|
||||
virtual std::vector<Unit> LoadOrderedUnits(const Category& c) = 0;
|
||||
virtual std::unordered_map<Unit, ConversionData, UnitHash> LoadOrderedRatios(const Unit& u) = 0;
|
||||
@@ -159,19 +205,21 @@ namespace UnitConversionManager
|
||||
{
|
||||
public:
|
||||
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> GetCurrencyRatioEquality(_In_ const UnitConversionManager::Unit& unit1, _In_ const UnitConversionManager::Unit& unit2) = 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>
|
||||
GetCurrencyRatioEquality(_In_ const UnitConversionManager::Unit& unit1, _In_ const UnitConversionManager::Unit& unit2) = 0;
|
||||
virtual std::wstring GetCurrencyTimestamp() = 0;
|
||||
|
||||
virtual concurrency::task<bool> TryLoadDataFromCacheAsync() = 0;
|
||||
virtual concurrency::task<bool> TryLoadDataFromWebAsync() = 0;
|
||||
virtual concurrency::task<bool> TryLoadDataFromWebOverrideAsync() = 0;
|
||||
virtual std::future<bool> TryLoadDataFromCacheAsync() = 0;
|
||||
virtual std::future<bool> TryLoadDataFromWebAsync() = 0;
|
||||
virtual std::future<bool> TryLoadDataFromWebOverrideAsync() = 0;
|
||||
};
|
||||
|
||||
class IUnitConverterVMCallback
|
||||
{
|
||||
public:
|
||||
virtual ~IUnitConverterVMCallback() { };
|
||||
virtual ~IUnitConverterVMCallback(){};
|
||||
virtual void DisplayCallback(const std::wstring& from, const std::wstring& to) = 0;
|
||||
virtual void SuggestedValueCallback(const std::vector<std::tuple<std::wstring, Unit>>& suggestedValues) = 0;
|
||||
virtual void MaxDigitsReached() = 0;
|
||||
@@ -180,21 +228,23 @@ namespace UnitConversionManager
|
||||
class IUnitConverter
|
||||
{
|
||||
public:
|
||||
virtual ~IUnitConverter() { }
|
||||
virtual void Initialize() = 0; // Use to initialize first time, use deserialize instead to rehydrate
|
||||
virtual ~IUnitConverter()
|
||||
{
|
||||
}
|
||||
virtual void Initialize() = 0; // Use to initialize first time, use deserialize instead to rehydrate
|
||||
virtual std::vector<Category> GetCategories() = 0;
|
||||
virtual CategorySelectionInitializer SetCurrentCategory(const Category& input) = 0;
|
||||
virtual Category GetCurrentCategory() = 0;
|
||||
virtual void SetCurrentUnitTypes(const Unit& fromType, const Unit& toType) = 0;
|
||||
virtual void SwitchActive(const std::wstring& newValue) = 0;
|
||||
virtual std::wstring Serialize() = 0;
|
||||
virtual void DeSerialize(const std::wstring& serializedData) = 0;
|
||||
virtual std::wstring SaveUserPreferences() = 0;
|
||||
virtual void RestoreUserPreferences(_In_ const std::wstring& userPreferences) = 0;
|
||||
virtual void SendCommand(Command command) = 0;
|
||||
virtual void SetViewModelCallback(_In_ const std::shared_ptr<IUnitConverterVMCallback>& newCallback) = 0;
|
||||
virtual void SetViewModelCurrencyCallback(_In_ const std::shared_ptr<IViewModelCurrencyCallback>& newCallback) = 0;
|
||||
virtual concurrency::task<std::pair<bool, std::wstring>> RefreshCurrencyRatios() = 0;
|
||||
virtual std::future<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>
|
||||
@@ -210,17 +260,17 @@ namespace UnitConversionManager
|
||||
Category GetCurrentCategory() override;
|
||||
void SetCurrentUnitTypes(const Unit& fromType, const Unit& toType) override;
|
||||
void SwitchActive(const std::wstring& newValue) override;
|
||||
std::wstring Serialize() override;
|
||||
void DeSerialize(const std::wstring& serializedData) override;
|
||||
std::wstring SaveUserPreferences() override;
|
||||
void RestoreUserPreferences(const std::wstring& userPreference) override;
|
||||
void SendCommand(Command command) override;
|
||||
void SetViewModelCallback(_In_ const std::shared_ptr<IUnitConverterVMCallback>& newCallback) override;
|
||||
void SetViewModelCurrencyCallback(_In_ const std::shared_ptr<IViewModelCurrencyCallback>& newCallback) override;
|
||||
concurrency::task<std::pair<bool, std::wstring>> RefreshCurrencyRatios() override;
|
||||
std::future<std::pair<bool, std::wstring>> RefreshCurrencyRatios() override;
|
||||
void Calculate() override;
|
||||
void ResetCategoriesAndRatios() override;
|
||||
// IUnitConverter
|
||||
|
||||
static std::vector<std::wstring> StringToVector(const std::wstring& w, const wchar_t * delimiter, bool addRemainder = false);
|
||||
static std::vector<std::wstring> StringToVector(const std::wstring& w, const wchar_t* delimiter, bool addRemainder = false);
|
||||
static std::wstring Quote(const std::wstring& s);
|
||||
static std::wstring Unquote(const std::wstring& s);
|
||||
|
||||
@@ -228,18 +278,14 @@ namespace UnitConversionManager
|
||||
bool CheckLoad();
|
||||
double Convert(double value, ConversionData conversionData);
|
||||
std::vector<std::tuple<std::wstring, Unit>> CalculateSuggested();
|
||||
void Reset();
|
||||
void ClearValues();
|
||||
void Calculate();
|
||||
void TrimString(std::wstring& input);
|
||||
void InitializeSelectedUnits();
|
||||
std::wstring RoundSignificant(double num, int numSignificant);
|
||||
Category StringToCategory(const std::wstring& w);
|
||||
std::wstring CategoryToString(const Category& c, const wchar_t * delimiter);
|
||||
std::wstring UnitToString(const Unit& u, const wchar_t * delimiter);
|
||||
std::wstring CategoryToString(const Category& c, const wchar_t* delimiter);
|
||||
std::wstring UnitToString(const Unit& u, const wchar_t* delimiter);
|
||||
Unit StringToUnit(const std::wstring& w);
|
||||
ConversionData StringToConversionData(const std::wstring& w);
|
||||
std::wstring ConversionDataToString(ConversionData d, const wchar_t * delimiter);
|
||||
void UpdateCurrencySymbols();
|
||||
void UpdateViewModel();
|
||||
bool AnyUnitIsEmpty();
|
||||
|
@@ -1,4 +1,6 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// 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.
|
||||
|
@@ -3,27 +3,20 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
// The CalcManager project should be able to be compiled with or without a precompiled header
|
||||
// in - order to support other toolchains besides MSVC. When adding new system headers, make sure
|
||||
// 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.
|
||||
|
||||
// Windows headers define min/max macros.
|
||||
// Disable it for project code.
|
||||
#define NOMINMAX
|
||||
|
||||
#include <assert.h>
|
||||
#include <windows.h>
|
||||
#include <winerror.h>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
#include <list>
|
||||
#include <regex>
|
||||
#include <unordered_map>
|
||||
#include <intsafe.h>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <ppltasks.h>
|
||||
#include <cassert>
|
||||
#include <intsafe.h>
|
||||
#include <list>
|
||||
#include <future>
|
||||
#include <regex>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <winerror.h>
|
||||
|
19
src/CalcManager/sal_cross_platform.h
Normal file
19
src/CalcManager/sal_cross_platform.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(_WIN32) && defined(_MSC_VER)
|
||||
|
||||
#include <sal.h>
|
||||
|
||||
#else
|
||||
|
||||
// Empty macro definitions for source annotations
|
||||
|
||||
#define _In_opt_
|
||||
#define _Out_opt_
|
||||
#define _In_
|
||||
#define _Out_
|
||||
#define _Inout_
|
||||
#define __in_opt
|
||||
#define _Frees_ptr_opt_
|
||||
|
||||
#endif
|
@@ -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>
|
25
src/CalcManager/winerror_cross_platform.h
Normal file
25
src/CalcManager/winerror_cross_platform.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(_WIN32) && defined(_MSC_VER)
|
||||
|
||||
#include <winerror.h>
|
||||
|
||||
#else
|
||||
|
||||
#include "Ratpack/CalcErr.h"
|
||||
|
||||
#define E_ACCESSDENIED 0x80070005
|
||||
#define E_FAIL 0x80004005
|
||||
#define E_INVALIDARG 0x80070057
|
||||
#define E_OUTOFMEMORY 0x8007000E
|
||||
#define E_POINTER 0x80004003
|
||||
#define E_UNEXPECTED 0x8000FFFF
|
||||
#define E_BOUNDS 0x8000000B
|
||||
#define S_OK 0x0
|
||||
#define S_FALSE 0x1
|
||||
|
||||
#define SUCCEEDED(hr) (((ResultCode)(hr)) >= 0)
|
||||
#define FAILED(hr) (((ResultCode)(hr)) < 0)
|
||||
#define SCODE_CODE(sc) ((sc) & 0xFFFF)
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user