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

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

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

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

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

View File

@@ -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;
}

View File

@@ -33,9 +33,7 @@ bool IsDigitOpCode(OpCode opCode)
// was never inout, we need to revert the state changes made as a result of this test
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;
}

View File

@@ -11,7 +11,8 @@ constexpr int ASCII_0 = 48;
using namespace std;
using namespace CalcEngine;
namespace {
namespace
{
void IFT(ResultCode hr)
{
if (FAILED(hr))
@@ -38,11 +39,8 @@ 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();
}
@@ -302,7 +300,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)
@@ -323,14 +322,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)
@@ -392,14 +391,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)))

View File

@@ -7,20 +7,15 @@ 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 +28,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 +54,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; });
}
}

View File

@@ -7,10 +7,9 @@ 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 +23,9 @@ 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)
{
@@ -60,10 +58,9 @@ 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
{
@@ -353,7 +350,8 @@ namespace CalcEngine
/// 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.
/// 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)
{

View File

@@ -58,42 +58,43 @@ 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();

View File

@@ -20,16 +20,16 @@
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;
@@ -42,7 +42,6 @@ namespace {
iPrec = 0;
}
return rgbPrec[iPrec + 1];
}
}
@@ -90,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:
@@ -125,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
@@ -241,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;
@@ -272,7 +266,6 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
m_HistoryCollector.PopLastOpndStart();
goto DoPrecedenceCheckAgain;
}
}
}
@@ -337,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;
}
@@ -386,13 +377,13 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
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->SetParenthesisNumber(0);
m_pCalcDisplay->SetExpressionDisplay(make_shared<CalculatorVector<pair<wstring, int>>>(), make_shared<CalculatorVector<shared_ptr<IExpressionCommand>>>());
m_pCalcDisplay->SetExpressionDisplay(make_shared<CalculatorVector<pair<wstring, int>>>(),
make_shared<CalculatorVector<shared_ptr<IExpressionCommand>>>());
}
m_HistoryCollector.ClearHistoryLine(wstring());
@@ -435,7 +426,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
}
@@ -485,7 +476,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>>>());
}
}
@@ -749,7 +741,6 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
m_bInv = !m_bInv;
break;
}
}
// Helper function to resolve one item on the precedence stack.
@@ -758,8 +749,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)
{
@@ -814,7 +805,6 @@ void CCalcEngine::CheckAndAddLastBinOpToHistory(bool addToHistory)
// So erase the last operand
m_HistoryCollector.RemoveLastOpndFromHistory();
}
}
else if (m_HistoryCollector.FOpndAddedToHistory() && !m_bError)
{
@@ -823,8 +813,7 @@ void CCalcEngine::CheckAndAddLastBinOpToHistory(bool addToHistory)
// Let us make a current value =. So in case of 4 SQRT (or a equation under braces) and then a new equation is started, we can just form
// 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)
{
@@ -864,7 +853,7 @@ void CCalcEngine::DisplayAnnounceBinaryOperator()
// we have this separate table to get its localized name and for its Inv function if it exists.
struct FunctionNameElement
{
wstring degreeString; // Used by default if there are no rad or grad specific strings.
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;
@@ -877,9 +866,8 @@ struct FunctionNameElement
};
// Table for each unary operator
static const std::unordered_map<int, FunctionNameElement> unaryOperatorStringTable =
{
{ IDC_CHOP, { L"", SIDS_FRAC} },
static const std::unordered_map<int, FunctionNameElement> unaryOperatorStringTable = {
{ IDC_CHOP, { L"", SIDS_FRAC } },
{ 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 } },
@@ -889,7 +877,7 @@ static const std::unordered_map<int, FunctionNameElement> unaryOperatorStringTab
{ IDC_COSH, { L"", SIDS_ACOSH } },
{ IDC_TANH, { L"", SIDS_ATANH } },
{ IDC_LN , { L"", SIDS_POWE } },
{ IDC_LN, { L"", SIDS_POWE } },
{ IDC_SQR, { SIDS_SQR } },
{ IDC_CUB, { SIDS_CUBE } },
{ IDC_FAC, { SIDS_FACT } },

View File

@@ -25,7 +25,6 @@ constexpr uint32_t MAX_GROUPING_SIZE = 16;
constexpr wstring_view c_decPreSepStr = L"[+-]?(\\d*)[";
constexpr wstring_view c_decPostSepStr = L"]?(\\d*)(?:e[+-]?(\\d*))?$";
/****************************************************************************\
* void DisplayNum(void)
*
@@ -37,15 +36,16 @@ 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 };
@@ -66,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];
}
@@ -84,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;

View File

@@ -54,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;
@@ -168,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:
@@ -202,7 +202,7 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
}
break;
}
} // end switch( op )
} // end switch( op )
}
catch (uint32_t nErrCode)
{
@@ -226,4 +226,3 @@ void CCalcEngine::DisplayError(uint32_t nError)
m_HistoryCollector.ClearHistoryLine(errorString);
}

View File

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

View File

@@ -64,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

View File

@@ -7,11 +7,12 @@
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 +32,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)
{

View File

@@ -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,21 @@ 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);
size_t MaxHistorySize() const { return m_maxHistorySize; }
size_t MaxHistorySize() const
{
return m_maxHistorySize;
}
~CalculatorHistory(void);
private:

View File

@@ -14,25 +14,21 @@ static constexpr size_t SERIALIZED_NUMBER_MINSIZE = 3;
// 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 +85,8 @@ 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)
{
@@ -165,7 +162,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 +181,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 +197,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 +209,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 +219,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)
{
@@ -361,7 +360,7 @@ namespace CalculationManager
/// 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)
void CalculatorManager::DeSerializePrimaryDisplay(const vector<long>& serializedPrimaryDisplay)
{
if (serializedPrimaryDisplay.empty())
{
@@ -404,7 +403,7 @@ namespace CalculationManager
/// DeSerialize the Memory from vector of long
/// </summary>
/// <param name = "serializedMemory">Serialized Rational of memory</param>
void CalculatorManager::DeSerializeMemory(const vector<long> &serializedMemory)
void CalculatorManager::DeSerializeMemory(const vector<long>& serializedMemory)
{
vector<long>::const_iterator itr = serializedMemory.begin();
while (itr != serializedMemory.end())
@@ -435,8 +434,8 @@ namespace CalculationManager
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))
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.
@@ -622,10 +621,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 +672,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)

View File

@@ -91,7 +91,8 @@ 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 SetParenthesisNumber(_In_ unsigned int parenthesisCount) override;
@@ -101,7 +102,6 @@ namespace CalculationManager
void BinaryOperatorReceived() override;
void MemoryItemChanged(unsigned int indexOfMemory) override;
CalculatorManager(ICalcDisplay* displayCallback, IResourceProvider* resourceProvider);
~CalculatorManager();
@@ -114,10 +114,10 @@ namespace CalculationManager
void DeSerializeCommands(_In_ const std::vector<unsigned char>& serializedData);
void SerializeMemory();
std::vector<long> GetSerializedMemory();
void DeSerializeMemory(const std::vector<long> &serializedMemory);
void DeSerializeMemory(const std::vector<long>& serializedMemory);
void SerializePrimaryDisplay();
std::vector<long> GetSerializedPrimaryDisplay();
void DeSerializePrimaryDisplay(const std::vector<long> &serializedPrimaryDisplay);
void DeSerializePrimaryDisplay(const std::vector<long>& serializedPrimaryDisplay);
Command SerializeSavedDegreeMode();
void MemorizeNumber();
@@ -128,7 +128,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 +144,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);

View File

@@ -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

View File

@@ -8,13 +8,13 @@
#include <winerror.h>
#include "Ratpack/CalcErr.h"
#include <stdexcept> // for std::out_of_range
#include <sal.h> // for SAL
#include <sal.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
@@ -28,7 +28,7 @@ public:
return hr;
}
ResultCode GetSize(_Out_ unsigned int *size)
ResultCode GetSize(_Out_ unsigned int* size)
{
*size = static_cast<unsigned>(m_vector.size());
return S_OK;
@@ -122,7 +122,7 @@ public:
{
ResultCode hr = S_OK;
unsigned int nTokens = 0;
std::pair <std::wstring, int> currentPair;
std::pair<std::wstring, int> currentPair;
hr = this->GetSize(&nTokens);
if (SUCCEEDED(hr))
{

View File

@@ -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,

View File

@@ -13,8 +13,9 @@ 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 +27,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 +45,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 +68,14 @@ 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 +92,15 @@ 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 +108,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 +211,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 +297,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);
}

View File

@@ -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 &paraCmd) = 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;
};

View File

@@ -13,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
@@ -25,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;
};
@@ -39,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;
};

View File

@@ -17,34 +17,33 @@
// 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.
@@ -55,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

View File

@@ -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;
@@ -50,58 +51,80 @@ 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[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 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;
@@ -110,20 +133,20 @@ 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. */
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
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
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;
@@ -143,7 +166,7 @@ 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);
@@ -151,7 +174,10 @@ private:
void InitChopNumbers();
static void LoadEngineStrings(CalculationManager::IResourceProvider& resourceProvider);
static int IdStrFromCmdId(int id) { return id - IDC_FIRSTCONTROL + IDS_ENGINESTR_FIRST; }
static int IdStrFromCmdId(int id)
{
return id - IDC_FIRSTCONTROL + IDS_ENGINESTR_FIRST;
}
static std::vector<uint32_t> DigitGroupingStringToGroupingVector(std::wstring_view groupingString);
std::wstring GroupDigits(std::wstring_view delimiter, std::vector<uint32_t> const& grouping, std::wstring_view displayString, bool isNumNegative = false);

View File

@@ -13,16 +13,24 @@ namespace CalcEngine
class CalcNumSec
{
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;
@@ -34,16 +42,12 @@ namespace CalcEngine
{
public:
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);

View File

@@ -171,126 +171,123 @@ inline constexpr auto SIDS_ERR_INPUT_OVERFLOW = L"119";
inline constexpr auto SIDS_ERR_OUTPUT_OVERFLOW = L"120";
// Include the resource key ID from above into this vector to load it into memory for the engine to use
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
};
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 };

View File

@@ -14,9 +14,10 @@ static constexpr size_t MAXPRECDEPTH = 25;
// Helper class really a internal class to CCalcEngine, to accumulate each history line of text by collecting the
// 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();
@@ -31,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:

View File

@@ -7,11 +7,13 @@
#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 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.

View File

@@ -4,8 +4,11 @@
#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;
};

View File

@@ -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,

View File

@@ -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)

View File

@@ -17,7 +17,7 @@
#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 __inline mulnumx(PNUMBER* pa, PNUMBER b)
{
if ( b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0 )
{
if (b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0)
{
// If b is not one we multiply
if ( (*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 __inline divnumx(PNUMBER* pa, PNUMBER b, int32_t precision)
{
if ( b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0 )
{
if (b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0)
{
// b is not one.
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

View File

@@ -16,7 +16,6 @@
//-----------------------------------------------------------------------------
#include "ratpak.h"
//-----------------------------------------------------------------------------
//
// FUNCTION: exprat
@@ -40,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
@@ -124,7 +123,7 @@ void exprat( PRAT *px, uint32_t radix, int32_t precision)
//
//-----------------------------------------------------------------------------
void _lograt( PRAT *px, int32_t precision)
void _lograt(PRAT* px, int32_t precision)
{
CREATETAYLOR();
@@ -133,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);
@@ -217,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);
@@ -246,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;
}
@@ -269,7 +267,7 @@ bool IsEven(PRAT x, uint32_t radix, int32_t precision)
//
//
//---------------------------------------------------------------------------
void powrat(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
void powrat(PRAT* px, PRAT y, uint32_t radix, int32_t precision)
{
// Handle cases where px or y is 0 by calling powratcomp directly
if (zerrat(*px) || zerrat(y))
@@ -296,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);
@@ -405,7 +403,7 @@ void powratNumeratorDenominator(PRAT *px, PRAT y, uint32_t radix, int32_t precis
//
//
//---------------------------------------------------------------------------
void powratcomp(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
void powratcomp(PRAT* px, PRAT y, uint32_t radix, int32_t precision)
{
int32_t sign = SIGN(*px);
@@ -413,76 +411,74 @@ void powratcomp(PRAT *px, PRAT y, uint32_t radix, int32_t precision)
(*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.
@@ -492,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);
@@ -501,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;
}

View File

@@ -15,8 +15,7 @@
//-----------------------------------------------------------------------------
#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)
//-----------------------------------------------------------------------------
@@ -55,37 +54,36 @@
//
//-----------------------------------------------------------------------------
void _gamma( PRAT *pn, uint32_t radix, int32_t precision)
void _gamma(PRAT* pn, uint32_t radix, int32_t precision)
{
PRAT factorial= nullptr;
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);
@@ -94,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;
@@ -188,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) ) &&
( SIGN(*px) == -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);
}

View File

@@ -17,26 +17,23 @@
//-----------------------------------------------------------------------------
#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
@@ -64,86 +61,83 @@ void ascalerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, int32_t precision)
//
//-----------------------------------------------------------------------------
void _asinrat( PRAT *px, int32_t precision)
void _asinrat(PRAT* px, int32_t precision)
{
CREATETAYLOR();
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)
{
PRAT pret= nullptr;
PRAT phack= nullptr;
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
@@ -170,35 +164,33 @@ void asinrat( PRAT *px, uint32_t radix, int32_t precision)
//
//-----------------------------------------------------------------------------
void acosanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
void acosanglerat(_Inout_ PRAT* pa, ANGLE_TYPE angletype, uint32_t radix, int32_t precision)
{
acosrat( pa, radix, precision);
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 = SIGN(*px);
@@ -206,24 +198,24 @@ void acosrat( PRAT *px, uint32_t radix, int32_t precision)
(*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);
}
}
}
//-----------------------------------------------------------------------------
@@ -257,79 +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)
{
PRAT tmpx= nullptr;
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);
}
}

View File

@@ -18,8 +18,6 @@
//-----------------------------------------------------------------------------
#include "ratpak.h"
//-----------------------------------------------------------------------------
//
// FUNCTION: asinhrat
@@ -49,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
@@ -106,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);
}
}
}
//-----------------------------------------------------------------------------
@@ -143,11 +138,11 @@ void acoshrat( PRAT *px, uint32_t radix, int32_t precision)
//
//-----------------------------------------------------------------------------
void atanhrat( PRAT *px, int32_t precision)
void atanhrat(PRAT* px, int32_t precision)
{
PRAT ptmp = nullptr;
DUPRAT(ptmp,(*px));
DUPRAT(ptmp, (*px));
subrat(&ptmp, rat_one, precision);
addrat(px, rat_one, precision);
divrat(px, ptmp, precision);
@@ -156,4 +151,3 @@ void atanhrat( PRAT *px, int32_t precision)
divrat(px, rat_two, precision);
destroyrat(ptmp);
}

View File

@@ -17,7 +17,7 @@
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;
@@ -40,7 +40,7 @@ void lshrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
}
}
void rshrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
void rshrat(PRAT* pa, PRAT b, uint32_t radix, int32_t precision)
{
PRAT pwr = nullptr;
@@ -63,29 +63,29 @@ void rshrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
}
}
void boolrat(PRAT *pa, PRAT b, int func, uint32_t radix, int32_t precision);
void 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);
}
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);
}
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);
@@ -103,7 +103,7 @@ void xorrat(PRAT *pa, PRAT b, uint32_t radix, int32_t precision)
//
//---------------------------------------------------------------------------
void boolrat(PRAT *pa, PRAT b, int func, uint32_t radix, int32_t precision)
void boolrat(PRAT* pa, PRAT b, int func, uint32_t radix, int32_t precision)
{
PRAT tmp = nullptr;
@@ -129,22 +129,21 @@ void boolrat(PRAT *pa, PRAT b, int func, uint32_t radix, int32_t precision)
//
//---------------------------------------------------------------------------
void boolnum(PNUMBER *pa, PNUMBER b, int func)
void boolnum(PNUMBER* pa, PNUMBER b, int func)
{
PNUMBER c = nullptr;
PNUMBER a = nullptr;
MANTTYPE *pcha;
MANTTYPE *pchb;
MANTTYPE *pchc;
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);
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;
@@ -154,12 +153,8 @@ void boolnum(PNUMBER *pa, PNUMBER b, int func)
pchc = c->mant;
for (; cdigits > 0; cdigits--, mexp++)
{
da = (((mexp >= a->exp) && (cdigits + a->exp - c->exp >
(c->cdigit - a->cdigit))) ?
*pcha++ : 0);
db = (((mexp >= b->exp) && (cdigits + b->exp - c->exp >
(c->cdigit - b->cdigit))) ?
*pchb++ : 0);
da = (((mexp >= a->exp) && (cdigits + a->exp - c->exp > (c->cdigit - a->cdigit))) ? *pcha++ : 0);
db = (((mexp >= b->exp) && (cdigits + b->exp - c->exp > (c->cdigit - b->cdigit))) ? *pchb++ : 0);
switch (func)
{
case FUNC_AND:
@@ -196,7 +191,7 @@ void boolnum(PNUMBER *pa, PNUMBER b, int func)
//
//-----------------------------------------------------------------------------
void remrat(PRAT *pa, PRAT b)
void remrat(PRAT* pa, PRAT b)
{
if (zerrat(b))
@@ -227,15 +222,15 @@ void remrat(PRAT *pa, PRAT b)
// RETURN: None, changes pointer.
//
// DESCRIPTION: Calculate the remainder of *pa / b, with the sign of the result
// either zero or has the same sign as the divisor.
// 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.
// 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
// contrary to remrat(X, 0) returning 0, modrat(X, 0) must return X
if (zerrat(b))
{
return;

View File

@@ -41,51 +41,49 @@ using namespace std;
//
//----------------------------------------------------------------------------
void _addnum( PNUMBER *pa, PNUMBER b, uint32_t radix);
void _addnum(PNUMBER* pa, PNUMBER b, uint32_t radix);
void __inline addnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
void __inline addnum(PNUMBER* pa, PNUMBER b, uint32_t radix)
{
if ( b->cdigit > 1 || b->mant[0] != 0 )
{ // If b 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;
@@ -93,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;
}
//----------------------------------------------------------------------------
@@ -193,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 __inline 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;
@@ -246,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
@@ -313,55 +302,53 @@ void _mulnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
//
//----------------------------------------------------------------------------
void remnum( PNUMBER *pa, PNUMBER b, uint32_t radix)
void remnum(PNUMBER* pa, PNUMBER b, uint32_t radix)
{
PNUMBER tmp = nullptr; // tmp is the working remainder.
PNUMBER 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
@@ -376,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 __inline divnum(PNUMBER* pa, PNUMBER b, uint32_t radix, int32_t precision)
{
if ( b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0 )
{
if (b->cdigit > 1 || b->mant[0] != 1 || b->exp != 0)
{
// b is not one
_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;
@@ -411,7 +398,7 @@ void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
c->exp = (a->cdigit + a->exp) - (b->cdigit + b->exp) + 1;
c->sign = a->sign * b->sign;
MANTTYPE *ptrc = c->mant + thismax;
MANTTYPE* ptrc = c->mant + thismax;
PNUMBER rem = nullptr;
PNUMBER tmp = nullptr;
DUPNUM(rem, a);
@@ -489,7 +476,6 @@ void _divnum( PNUMBER *pa, PNUMBER b, uint32_t radix, int32_t precision)
*pa = c;
}
//---------------------------------------------------------------------------
//
// FUNCTION: equnum
@@ -503,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;
}
}
}
}
//---------------------------------------------------------------------------
@@ -571,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;
}
}
}
}
//----------------------------------------------------------------------------
@@ -633,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;
}

View File

@@ -37,23 +37,23 @@ using namespace std;
//
//-----------------------------------------------------------------------------
void gcdrat( PRAT *pa, int32_t precision)
void gcdrat(PRAT* pa, int32_t precision)
{
PNUMBER pgcd= nullptr;
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);
}
@@ -70,16 +70,16 @@ void gcdrat( PRAT *pa, int32_t precision)
//
//-----------------------------------------------------------------------------
void fracrat( PRAT *pa , uint32_t radix, int32_t precision)
void fracrat(PRAT* pa, uint32_t radix, int32_t precision)
{
// Only do the flatrat operation if number is nonzero.
// 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);
@@ -98,26 +98,25 @@ void fracrat( PRAT *pa , uint32_t radix, int32_t precision)
//
//-----------------------------------------------------------------------------
void mulrat( PRAT *pa, PRAT b, int32_t precision)
void mulrat(PRAT* pa, PRAT b, int32_t precision)
{
{
// Only do the multiply if it isn't zero.
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
}
//-----------------------------------------------------------------------------
@@ -133,44 +132,41 @@ void mulrat( PRAT *pa, PRAT b, int32_t precision)
//
//-----------------------------------------------------------------------------
void divrat( PRAT *pa, PRAT b, int32_t precision)
void divrat(PRAT* pa, PRAT b, int32_t precision)
{
if ( !zernum( (*pa)->pp ) )
{
if (!zernum((*pa)->pp))
{
// Only do the divide if the top isn't zero.
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
}
//-----------------------------------------------------------------------------
@@ -186,11 +182,11 @@ void divrat( PRAT *pa, PRAT b, int32_t precision)
//
//-----------------------------------------------------------------------------
void subrat( PRAT *pa, PRAT b, int32_t precision)
void subrat(PRAT* pa, PRAT b, int32_t precision)
{
b->pp->sign *= -1;
addrat( pa, b, precision);
addrat(pa, b, precision);
b->pp->sign *= -1;
}
@@ -207,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
@@ -222,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
@@ -262,11 +255,11 @@ void addrat( PRAT *pa, PRAT b, int32_t precision)
//
//-----------------------------------------------------------------------------
void rootrat( PRAT *py, PRAT n, uint32_t radix, int32_t precision)
void rootrat(PRAT* py, PRAT n, uint32_t radix, int32_t precision)
{
// Initialize 1/n
PRAT oneovern= nullptr;
DUPRAT(oneovern,rat_one);
PRAT oneovern = nullptr;
DUPRAT(oneovern, rat_one);
divrat(&oneovern, n, precision);
powrat(py, oneovern, radix, precision);
@@ -274,7 +267,6 @@ void rootrat( PRAT *py, PRAT n, uint32_t radix, int32_t precision)
destroyrat(oneovern);
}
//-----------------------------------------------------------------------------
//
// FUNCTION: zerrat
@@ -288,10 +280,8 @@ void rootrat( PRAT *py, PRAT n, uint32_t radix, int32_t precision)
//
//-----------------------------------------------------------------------------
bool zerrat( PRAT a )
bool zerrat(PRAT a)
{
return( zernum(a->pp) );
return (zernum(a->pp));
}

File diff suppressed because it is too large Load Diff

View File

@@ -21,27 +21,29 @@
#include <string>
#include "CalcErr.h"
#include <cstring> // for memmove
#include <sal.h> // for SAL
#include <sal.h> // for SAL
static constexpr uint32_t BASEXPWR = 31L;// Internal log2(BASEX)
static constexpr uint32_t BASEXPWR = 31L; // Internal log2(BASEX)
static constexpr uint32_t BASEX = 0x80000000; // Internal radix used in calculations, hope to raise
// 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
};
@@ -55,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.
@@ -78,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'
@@ -135,27 +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))
// SIGN returns the sign of the rational
#define SIGN(prat) ((prat)->pp->sign*(prat)->pq->sign)
#define SIGN(prat) ((prat)->pp->sign * (prat)->pq->sign)
#if defined( DEBUG_RATPAK )
#if defined(DEBUG_RATPAK)
//-----------------------------------------------------------------------------
//
// Debug versions of rational number creation and destruction routines.
@@ -163,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
//-----------------------------------------------------------------------------
@@ -204,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))
//-----------------------------------------------------------------------------
//
@@ -246,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)
//-----------------------------------------------------------------------------
//
@@ -299,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
//-----------------------------------------------------------------------------
//
@@ -315,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
@@ -328,16 +350,18 @@ extern PNUMBER RatToNumber(_In_ PRAT prat, uint32_t radix, int32_t precision);
// flattens a PRAT by converting it to a PNUMBER and back to a PRAT
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);
@@ -346,119 +370,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 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);
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);

View File

@@ -19,36 +19,47 @@
//----------------------------------------------------------------------------
#include <string>
#include <cstring> // for memmove
#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;
@@ -60,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
//----------------------------------------------------------------------------
//
@@ -127,14 +138,14 @@ void ChangeConstants(uint32_t radix, int32_t precision)
uint64_t limit = static_cast<uint64_t>(BASEX) / static_cast<uint64_t>(radix);
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))
@@ -253,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);
@@ -273,7 +283,6 @@ void ChangeConstants(uint32_t radix, int32_t precision)
DUPRAT(rat_negsmallest, rat_smallest);
rat_negsmallest->pp->sign = -1;
}
}
//----------------------------------------------------------------------------
@@ -287,21 +296,21 @@ void ChangeConstants(uint32_t radix, int32_t precision)
//
//----------------------------------------------------------------------------
void intrat( PRAT *px, uint32_t radix, int32_t precision)
void intrat(PRAT* px, uint32_t radix, int32_t precision)
{
// Only do the intrat operation if number is nonzero.
// 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);
remrat( &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);
@@ -319,16 +328,16 @@ void intrat( PRAT *px, uint32_t radix, int32_t precision)
//
//---------------------------------------------------------------------------
bool rat_equ( PRAT a, PRAT b, int32_t precision)
bool rat_equ(PRAT a, PRAT b, int32_t precision)
{
PRAT rattmp= nullptr;
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);
}
//---------------------------------------------------------------------------
@@ -342,20 +351,19 @@ bool rat_equ( PRAT a, PRAT b, int32_t precision)
//
//---------------------------------------------------------------------------
bool rat_ge( PRAT a, PRAT b, int32_t precision)
bool rat_ge(PRAT a, PRAT b, int32_t precision)
{
PRAT rattmp= nullptr;
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 ) || SIGN(rattmp) == 1 );
destroyrat( rattmp );
return( bret );
bool bret = (zernum(rattmp->pp) || SIGN(rattmp) == 1);
destroyrat(rattmp);
return (bret);
}
//---------------------------------------------------------------------------
//
// FUNCTION: rat_gt
@@ -367,17 +375,17 @@ bool rat_ge( PRAT a, PRAT b, int32_t precision)
//
//---------------------------------------------------------------------------
bool rat_gt( PRAT a, PRAT b, int32_t precision)
bool rat_gt(PRAT a, PRAT b, int32_t precision)
{
PRAT rattmp= nullptr;
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 ) && SIGN(rattmp) == 1 );
destroyrat( rattmp );
return( bret );
bool bret = (!zernum(rattmp->pp) && SIGN(rattmp) == 1);
destroyrat(rattmp);
return (bret);
}
//---------------------------------------------------------------------------
@@ -391,21 +399,19 @@ bool rat_gt( PRAT a, PRAT b, int32_t precision)
//
//---------------------------------------------------------------------------
bool rat_le( PRAT a, PRAT b, int32_t precision)
bool rat_le(PRAT a, PRAT b, int32_t precision)
{
PRAT rattmp= nullptr;
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 ) || SIGN(rattmp) == -1 );
destroyrat( rattmp );
return( bret );
bool bret = (zernum(rattmp->pp) || SIGN(rattmp) == -1);
destroyrat(rattmp);
return (bret);
}
//---------------------------------------------------------------------------
//
// FUNCTION: rat_lt
@@ -417,20 +423,19 @@ bool rat_le( PRAT a, PRAT b, int32_t precision)
//
//---------------------------------------------------------------------------
bool rat_lt( PRAT a, PRAT b, int32_t precision)
bool rat_lt(PRAT a, PRAT b, int32_t precision)
{
PRAT rattmp= nullptr;
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 ) && SIGN(rattmp) == -1 );
destroyrat( rattmp );
return( bret );
bool bret = (!zernum(rattmp->pp) && SIGN(rattmp) == -1);
destroyrat(rattmp);
return (bret);
}
//---------------------------------------------------------------------------
//
// FUNCTION: rat_neq
@@ -442,17 +447,16 @@ bool rat_lt( PRAT a, PRAT b, int32_t precision)
//
//---------------------------------------------------------------------------
bool rat_neq( PRAT a, PRAT b, int32_t precision)
bool rat_neq(PRAT a, PRAT b, int32_t precision)
{
PRAT rattmp= nullptr;
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);
}
//---------------------------------------------------------------------------
@@ -466,27 +470,26 @@ bool rat_neq( PRAT a, PRAT b, int32_t precision)
//
//---------------------------------------------------------------------------
void scale( PRAT *px, PRAT scalefact, uint32_t radix, int32_t precision )
void scale(PRAT* px, PRAT scalefact, uint32_t radix, int32_t precision)
{
PRAT pret = nullptr;
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);
}
//---------------------------------------------------------------------------
@@ -500,38 +503,37 @@ void scale( PRAT *px, PRAT scalefact, uint32_t radix, int32_t precision )
//
//---------------------------------------------------------------------------
void scale2pi( PRAT *px, uint32_t radix, int32_t precision )
void scale2pi(PRAT* px, uint32_t radix, int32_t precision)
{
PRAT pret = nullptr;
PRAT 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);
}
//---------------------------------------------------------------------------
@@ -544,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;
}
}
//---------------------------------------------------------------------------
@@ -573,11 +575,11 @@ void inbetween( PRAT *px, PRAT range, int32_t precision)
//
//---------------------------------------------------------------------------
void _dumprawrat( const wchar_t *varname, PRAT rat, wostream& out)
void _dumprawrat(const wchar_t* varname, PRAT rat, wostream& out)
{
_dumprawnum(varname, rat->pp, out );
_dumprawnum(varname, rat->pq, out );
_dumprawnum(varname, rat->pp, out);
_dumprawnum(varname, rat->pq, out);
}
//---------------------------------------------------------------------------
@@ -591,26 +593,26 @@ void _dumprawrat( const wchar_t *varname, PRAT rat, wostream& out)
//
//---------------------------------------------------------------------------
void _dumprawnum(const wchar_t *varname, PNUMBER num, wostream& out)
void _dumprawnum(const wchar_t* varname, PNUMBER num, wostream& out)
{
int i;
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);
@@ -674,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;
}
}
}

View File

@@ -16,25 +16,22 @@
#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
@@ -66,21 +63,21 @@ void scalerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_t p
//
//-----------------------------------------------------------------------------
void _sinrat( PRAT *px, int32_t precision)
void _sinrat(PRAT* px, int32_t precision)
{
CREATETAYLOR();
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();
@@ -89,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);
}
//-----------------------------------------------------------------------------
@@ -158,8 +155,7 @@ void sinanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_
//
//-----------------------------------------------------------------------------
void _cosrat( PRAT *px, uint32_t radix, int32_t precision)
void _cosrat(PRAT* px, uint32_t radix, int32_t precision)
{
CREATETAYLOR();
@@ -167,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);
}
//-----------------------------------------------------------------------------
@@ -242,55 +239,52 @@ void cosanglerat( _Inout_ PRAT *pa, ANGLE_TYPE angletype, uint32_t radix, int32_
//
//-----------------------------------------------------------------------------
void _tanrat( PRAT *px, uint32_t radix, int32_t precision)
void _tanrat(PRAT* px, uint32_t radix, int32_t precision)
{
PRAT ptmp= nullptr;
PRAT ptmp = nullptr;
DUPRAT(ptmp,*px);
DUPRAT(ptmp, *px);
_sinrat(px, precision);
_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);
}

View File

@@ -16,22 +16,19 @@
//-----------------------------------------------------------------------------
#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;
}
//-----------------------------------------------------------------------------
@@ -67,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);
}
}
//-----------------------------------------------------------------------------
@@ -146,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);
}
}
//-----------------------------------------------------------------------------
@@ -214,17 +211,16 @@ void coshrat( PRAT *px, uint32_t radix, int32_t precision)
//
//-----------------------------------------------------------------------------
void tanhrat( PRAT *px, uint32_t radix, int32_t precision)
void tanhrat(PRAT* px, uint32_t radix, int32_t precision)
{
PRAT ptmp= nullptr;
PRAT ptmp = nullptr;
DUPRAT(ptmp,*px);
DUPRAT(ptmp, *px);
sinhrat(px, radix, precision);
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);
}

View File

@@ -34,8 +34,7 @@ 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)
{
}
@@ -192,14 +191,14 @@ void UnitConverter::SwitchActive(const wstring& newValue)
}
}
wstring UnitConverter::CategoryToString(const Category& c, const wchar_t * delimiter)
wstring UnitConverter::CategoryToString(const Category& c, const wchar_t* delimiter)
{
wstringstream out(wstringstream::out);
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;
@@ -229,10 +228,12 @@ Category UnitConverter::StringToCategory(const wstring& w)
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();
}
@@ -262,7 +263,7 @@ ConversionData UnitConverter::StringToConversionData(const wstring& w)
return serializedConversionData;
}
wstring UnitConverter::ConversionDataToString(ConversionData d, const wchar_t * delimiter)
wstring UnitConverter::ConversionDataToString(ConversionData d, const wchar_t* delimiter)
{
wstringstream out(wstringstream::out);
out.precision(32);
@@ -289,12 +290,13 @@ wstring UnitConverter::Serialize()
}
wstringstream out(wstringstream::out);
const wchar_t * delimiter = L";";
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 << 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);
@@ -311,7 +313,8 @@ wstring UnitConverter::Serialize()
{
categoryToUnitString << UnitToString(u, delimiter) << ",";
}
categoryToUnitString << "[" << "]";
categoryToUnitString << "["
<< "]";
}
for (const auto& cur : m_ratioMap)
@@ -322,7 +325,8 @@ wstring UnitConverter::Serialize()
unitToUnitToDoubleString << UnitToString(curConversion.first, delimiter) << ":";
unitToUnitToDoubleString << ConversionDataToString(curConversion.second, delimiter) << ":,";
}
unitToUnitToDoubleString << "[" << "]";
unitToUnitToDoubleString << "["
<< "]";
}
out << categoryString.str() << "|";
@@ -429,7 +433,6 @@ void UnitConverter::RestoreUserPreferences(const wstring& userPreferences)
m_toType = toType;
}
}
}
/// <summary>
@@ -438,7 +441,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) << "|";
@@ -457,7 +460,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())
{
@@ -481,9 +484,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)
@@ -529,7 +532,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;
}
@@ -643,7 +647,6 @@ void UnitConverter::SendCommand(Command command)
break;
}
if (clearFront)
{
m_currentDisplay.erase(0, 1);
@@ -684,26 +687,27 @@ void UnitConverter::SetViewModelCurrencyCallback(_In_ const shared_ptr<IViewMode
task<pair<bool, wstring>> UnitConverter::RefreshCurrencyRatios()
{
shared_ptr<ICurrencyConverterDataLoader> currencyDataLoader = GetCurrencyConverterDataLoader();
return create_task([this, currencyDataLoader]()
{
if (currencyDataLoader != nullptr)
{
return currencyDataLoader->TryLoadDataFromWebOverrideAsync();
}
else
{
return task_from_result(false);
}
}).then([this, currencyDataLoader](bool didLoad)
{
wstring timestamp = L"";
if (currencyDataLoader != nullptr)
{
timestamp = currencyDataLoader->GetCurrencyTimestamp();
}
return create_task([this, currencyDataLoader]() {
if (currencyDataLoader != nullptr)
{
return currencyDataLoader->TryLoadDataFromWebOverrideAsync();
}
else
{
return task_from_result(false);
}
})
.then(
[this, currencyDataLoader](bool didLoad) {
wstring timestamp = L"";
if (currencyDataLoader != nullptr)
{
timestamp = currencyDataLoader->GetCurrencyTimestamp();
}
return make_pair(didLoad, timestamp);
}, task_continuation_context::use_default());
return make_pair(didLoad, timestamp);
},
task_continuation_context::use_default());
}
shared_ptr<ICurrencyConverterDataLoader> UnitConverter::GetCurrencyConverterDataLoader()
@@ -752,7 +756,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);
@@ -760,9 +764,7 @@ vector<tuple<wstring, Unit>> UnitConverter::CalculateSuggested()
}
// Sort the resulting list by absolute magnitude, breaking ties by choosing the positive value
sort(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;
@@ -783,7 +785,7 @@ vector<tuple<wstring, Unit>> UnitConverter::CalculateSuggested()
}
else if (abs(entry.value) < 1000)
{
roundedString = RoundSignificant(entry.value, 1);
roundedString = RoundSignificant(entry.value, 1);
}
else
{
@@ -798,9 +800,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;
@@ -922,7 +922,6 @@ shared_ptr<IConverterDataLoader> UnitConverter::GetDataLoaderForCategory(const C
/// </summary>
void UnitConverter::InitializeSelectedUnits()
{
if (m_categoryToUnits.empty())
{
return;
@@ -1057,7 +1056,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')
{
@@ -1065,9 +1064,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());
}
}

View File

@@ -6,7 +6,7 @@
#include <vector>
#include <unordered_map>
#include <ppltasks.h>
#include <sal.h> // for SAL
#include <sal.h> // for SAL
#include <memory> // for std::shared_ptr
namespace UnitConversionManager
@@ -15,13 +15,22 @@ namespace UnitConversionManager
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)
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;
@@ -31,7 +40,9 @@ namespace UnitConversionManager
accessibleName = nameValue1 + L" " + nameValue2;
}
virtual ~Unit() {}
virtual ~Unit()
{
}
int id;
std::wstring name;
@@ -41,12 +52,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;
}
@@ -61,7 +72,9 @@ namespace UnitConversionManager
struct Category
{
Category(){}
Category()
{
}
Category(int id, std::wstring name, bool supportsNegative) : id(id), name(name), supportsNegative(supportsNegative)
{
@@ -71,12 +84,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;
}
@@ -85,7 +98,8 @@ namespace UnitConversionManager
class UnitHash
{
public:
size_t operator() (const Unit & x) const {
size_t operator()(const Unit& x) const
{
return x.id;
}
};
@@ -93,7 +107,8 @@ namespace UnitConversionManager
class CategoryHash
{
public:
size_t operator() (const Category & x) const {
size_t operator()(const Category& x) const
{
return x.id;
}
};
@@ -107,12 +122,16 @@ namespace UnitConversionManager
struct ConversionData
{
ConversionData(){}
ConversionData()
{
}
ConversionData(double ratio, double offset, bool offsetFirst) : ratio(ratio), offset(offset), offsetFirst(offsetFirst)
{
}
virtual ~ConversionData() {}
virtual ~ConversionData()
{
}
double ratio;
double offset;
@@ -136,13 +155,17 @@ 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;
@@ -153,8 +176,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;
@@ -165,8 +188,10 @@ 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;
@@ -177,7 +202,7 @@ namespace UnitConversionManager
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;
@@ -186,8 +211,10 @@ 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;
@@ -230,7 +257,7 @@ namespace UnitConversionManager
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);
@@ -243,11 +270,11 @@ namespace UnitConversionManager
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);
std::wstring ConversionDataToString(ConversionData d, const wchar_t* delimiter);
void UpdateCurrencySymbols();
void UpdateViewModel();
bool AnyUnitIsEmpty();