Update Calc Engine for new functions needed for keyboard refresh (#662)
* Update Calc Engine to Support New Functionality * Address PR comments * Address PR comments
This commit is contained in:
@@ -261,6 +261,11 @@ void CalcInput::SetDecimalSymbol(wchar_t decSymbol)
|
||||
}
|
||||
}
|
||||
|
||||
bool CalcInput::IsEmpty()
|
||||
{
|
||||
return m_base.IsEmpty() && !m_hasExponent && m_exponent.IsEmpty() && !m_hasDecimal;
|
||||
}
|
||||
|
||||
wstring CalcInput::ToString(uint32_t radix)
|
||||
{
|
||||
// In theory both the base and exponent could be C_NUM_MAX_DIGITS long.
|
||||
|
||||
@@ -11,14 +11,14 @@ bool IsOpInRange(OpCode op, uint32_t x, uint32_t y)
|
||||
|
||||
bool IsBinOpCode(OpCode opCode)
|
||||
{
|
||||
return IsOpInRange(opCode, IDC_AND, IDC_PWR);
|
||||
return IsOpInRange(opCode, IDC_AND, IDC_PWR) || IsOpInRange(opCode, IDC_BINARYEXTENDEDFIRST, IDC_BINARYEXTENDEDLAST);
|
||||
}
|
||||
|
||||
// WARNING: IDC_SIGN is a special unary op but still this doesn't catch this. Caller has to be aware
|
||||
// of it and catch it themselves or not needing this
|
||||
bool IsUnaryOpCode(OpCode opCode)
|
||||
{
|
||||
return IsOpInRange(opCode, IDC_UNARYFIRST, IDC_UNARYLAST);
|
||||
return (IsOpInRange(opCode, IDC_UNARYFIRST, IDC_UNARYLAST) || IsOpInRange(opCode, IDC_UNARYEXTENDEDFIRST, IDC_UNARYEXTENDEDLAST));
|
||||
}
|
||||
|
||||
bool IsDigitOpCode(OpCode opCode)
|
||||
|
||||
@@ -120,12 +120,12 @@ void CHistoryCollector::RemoveLastOpndFromHistory()
|
||||
// This will not restore the m_lastBinOpStartIndex, as it isn't possible to remove that also later
|
||||
}
|
||||
|
||||
void CHistoryCollector::AddBinOpToHistory(int nOpCode, bool fNoRepetition)
|
||||
void CHistoryCollector::AddBinOpToHistory(int nOpCode, bool isIntegerMode, bool fNoRepetition)
|
||||
{
|
||||
int iCommandEnd = AddCommand(std::make_shared<CBinaryCommand>(nOpCode));
|
||||
m_lastBinOpStartIndex = IchAddSzToEquationSz(L" ", -1);
|
||||
|
||||
IchAddSzToEquationSz(CCalcEngine::OpCodeToString(nOpCode), iCommandEnd);
|
||||
IchAddSzToEquationSz(CCalcEngine::OpCodeToBinaryString(nOpCode, isIntegerMode), iCommandEnd);
|
||||
IchAddSzToEquationSz(L" ", -1);
|
||||
|
||||
if (fNoRepetition)
|
||||
@@ -138,14 +138,14 @@ void CHistoryCollector::AddBinOpToHistory(int nOpCode, bool fNoRepetition)
|
||||
// This is expected to be called when a binary op in the last say 1+2+ is changing to another one say 1+2* (+ changed to *)
|
||||
// It needs to know by this change a Precedence inversion happened. i.e. previous op was lower or equal to its previous op, but the new
|
||||
// one isn't. (Eg. 1*2* to 1*2^). It can add explicit brackets to ensure the precedence is inverted. (Eg. (1*2) ^)
|
||||
void CHistoryCollector::ChangeLastBinOp(int nOpCode, bool fPrecInvToHigher)
|
||||
void CHistoryCollector::ChangeLastBinOp(int nOpCode, bool fPrecInvToHigher, bool isIntgerMode)
|
||||
{
|
||||
TruncateEquationSzFromIch(m_lastBinOpStartIndex);
|
||||
if (fPrecInvToHigher)
|
||||
{
|
||||
EnclosePrecInversionBrackets();
|
||||
}
|
||||
AddBinOpToHistory(nOpCode);
|
||||
AddBinOpToHistory(nOpCode, isIntgerMode);
|
||||
}
|
||||
|
||||
void CHistoryCollector::PushLastOpndStart(int ichOpndStart)
|
||||
@@ -266,6 +266,30 @@ void CHistoryCollector::AddUnaryOpToHistory(int nOpCode, bool fInv, ANGLE_TYPE a
|
||||
command = fInv ? static_cast<int>(CalculationManager::Command::CommandATANH) : IDC_TANH;
|
||||
spExpressionCommand = std::make_shared<CUnaryCommand>(command);
|
||||
break;
|
||||
case IDC_SEC:
|
||||
command = fInv ? static_cast<int>(CalculationManager::Command::CommandASEC) : IDC_SEC;
|
||||
spExpressionCommand = std::make_shared<CUnaryCommand>(static_cast<int>(angleOpCode), command);
|
||||
break;
|
||||
case IDC_CSC:
|
||||
command = fInv ? static_cast<int>(CalculationManager::Command::CommandACSC) : IDC_CSC;
|
||||
spExpressionCommand = std::make_shared<CUnaryCommand>(static_cast<int>(angleOpCode), command);
|
||||
break;
|
||||
case IDC_COT:
|
||||
command = fInv ? static_cast<int>(CalculationManager::Command::CommandACOT) : IDC_COT;
|
||||
spExpressionCommand = std::make_shared<CUnaryCommand>(static_cast<int>(angleOpCode), command);
|
||||
break;
|
||||
case IDC_SECH:
|
||||
command = fInv ? static_cast<int>(CalculationManager::Command::CommandASECH) : IDC_SECH;
|
||||
spExpressionCommand = std::make_shared<CUnaryCommand>(command);
|
||||
break;
|
||||
case IDC_CSCH:
|
||||
command = fInv ? static_cast<int>(CalculationManager::Command::CommandACSCH) : IDC_CSCH;
|
||||
spExpressionCommand = std::make_shared<CUnaryCommand>(command);
|
||||
break;
|
||||
case IDC_COTH:
|
||||
command = fInv ? static_cast<int>(CalculationManager::Command::CommandACOTH) : IDC_COTH;
|
||||
spExpressionCommand = std::make_shared<CUnaryCommand>(command);
|
||||
break;
|
||||
case IDC_LN:
|
||||
command = fInv ? static_cast<int>(CalculationManager::Command::CommandPOWE) : IDC_LN;
|
||||
spExpressionCommand = std::make_shared<CUnaryCommand>(command);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <string>
|
||||
#include "Header Files/CalcEngine.h"
|
||||
#include "Header Files/CalcUtils.h"
|
||||
#include "NumberFormattingUtils.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace CalcEngine;
|
||||
@@ -28,8 +29,13 @@ namespace
|
||||
// 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 uint16_t rgbPrec[] = {
|
||||
0,0, IDC_OR,0, IDC_XOR,0,
|
||||
IDC_AND,1, IDC_NAND,1, IDC_NOR,1,
|
||||
IDC_ADD,2, IDC_SUB,2,
|
||||
IDC_RSHF,3, IDC_LSHF,3, IDC_RSHFL,3,
|
||||
IDC_MOD,3, IDC_DIV,3, IDC_MUL,3,
|
||||
IDC_PWR,4, IDC_ROOT,4, IDC_LOGBASEX,4 };
|
||||
unsigned int iPrec;
|
||||
|
||||
iPrec = 0;
|
||||
@@ -124,9 +130,18 @@ 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 (IsBinOpCode(wParam) ||
|
||||
IsUnaryOpCode(wParam) ||
|
||||
IsOpInRange(wParam, IDC_FE, 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_BINEDITEND) ||
|
||||
(IDC_INV == wParam) ||
|
||||
(IDC_SIGN == wParam && 10 != m_radix) ||
|
||||
(IDC_RAND == wParam) ||
|
||||
(IDC_EULER == wParam))
|
||||
{
|
||||
m_bRecord = false;
|
||||
m_currentVal = m_input.ToRational(m_radix, m_precision);
|
||||
@@ -193,7 +208,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
|
||||
m_nPrevOpCode = 0; // Once the precedence inversion has put additional brackets, its no longer required
|
||||
}
|
||||
}
|
||||
m_HistoryCollector.ChangeLastBinOp(m_nOpCode, fPrecInvToHigher);
|
||||
m_HistoryCollector.ChangeLastBinOp(m_nOpCode, fPrecInvToHigher, m_fIntegerMode);
|
||||
DisplayAnnounceBinaryOperator();
|
||||
return;
|
||||
}
|
||||
@@ -270,10 +285,9 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
|
||||
}
|
||||
|
||||
DisplayAnnounceBinaryOperator();
|
||||
|
||||
m_lastVal = m_currentVal;
|
||||
m_nOpCode = (int)wParam;
|
||||
m_HistoryCollector.AddBinOpToHistory(m_nOpCode);
|
||||
m_HistoryCollector.AddBinOpToHistory(m_nOpCode, m_fIntegerMode);
|
||||
m_bNoPrevEqu = m_bChangeOp = true;
|
||||
return;
|
||||
}
|
||||
@@ -303,7 +317,8 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
|
||||
m_HistoryCollector.AddUnaryOpToHistory((int)wParam, m_bInv, m_angletype);
|
||||
}
|
||||
|
||||
if ((wParam == IDC_SIN) || (wParam == IDC_COS) || (wParam == IDC_TAN) || (wParam == IDC_SINH) || (wParam == IDC_COSH) || (wParam == IDC_TANH))
|
||||
if ((wParam == IDC_SIN) || (wParam == IDC_COS) || (wParam == IDC_TAN) || (wParam == IDC_SINH) || (wParam == IDC_COSH) || (wParam == IDC_TANH)
|
||||
|| (wParam == IDC_SEC) || (wParam == IDC_CSC) || (wParam == IDC_COT) || (wParam == IDC_SECH) || (wParam == IDC_CSCH) || (wParam == IDC_COTH))
|
||||
{
|
||||
if (IsCurrentTooBigForTrig())
|
||||
{
|
||||
@@ -330,9 +345,13 @@ 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) || (wParam == IDC_SEC) || (wParam == IDC_CSC) ||
|
||||
(wParam == IDC_COT) || (wParam == IDC_SECH) || (wParam == IDC_CSCH) ||
|
||||
(wParam == IDC_COTH)))
|
||||
{
|
||||
m_bInv = false;
|
||||
}
|
||||
@@ -341,10 +360,10 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
|
||||
}
|
||||
|
||||
// Tiny binary edit windows clicked. Toggle that bit and update display
|
||||
if (IsOpInRange(wParam, IDC_BINEDITSTART, IDC_BINEDITSTART + 63))
|
||||
if (IsOpInRange(wParam, IDC_BINEDITSTART, IDC_BINEDITEND))
|
||||
{
|
||||
// Same reasoning as for unary operators. We need to seed it previous number
|
||||
if (m_nLastCom >= IDC_AND && m_nLastCom <= IDC_PWR)
|
||||
if (IsBinOpCode(m_nLastCom))
|
||||
{
|
||||
m_currentVal = m_lastVal;
|
||||
}
|
||||
@@ -377,6 +396,7 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
|
||||
m_precedenceOpCount = m_nTempCom = m_nLastCom = m_nOpCode = 0;
|
||||
m_nPrevOpCode = 0;
|
||||
m_bNoPrevEqu = true;
|
||||
m_carryBit = 0;
|
||||
|
||||
/* clear the parenthesis status box indicator, this will not be
|
||||
cleared for CENTR */
|
||||
@@ -700,7 +720,6 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
|
||||
case IDC_MCLEAR:
|
||||
m_memoryValue = make_unique<Rational>(wParam == IDC_STORE ? TruncateNumForIntMath(m_currentVal) : 0);
|
||||
break;
|
||||
|
||||
case IDC_PI:
|
||||
if (!m_fIntegerMode)
|
||||
{
|
||||
@@ -713,7 +732,43 @@ void CCalcEngine::ProcessCommandWorker(OpCode wParam)
|
||||
}
|
||||
HandleErrorCommand(wParam);
|
||||
break;
|
||||
case IDC_RAND:
|
||||
if (!m_fIntegerMode)
|
||||
{
|
||||
CheckAndAddLastBinOpToHistory(); // rand is like entering the number
|
||||
|
||||
wstringstream str;
|
||||
str << fixed << setprecision(m_precision) << GenerateRandomNumber();
|
||||
|
||||
auto rat = StringToRat(false, str.str(), false, L"", m_radix, m_precision);
|
||||
if (rat != nullptr)
|
||||
{
|
||||
m_currentVal = Rational{ rat };
|
||||
}
|
||||
else
|
||||
{
|
||||
m_currentVal = Rational{ 0 };
|
||||
}
|
||||
destroyrat(rat);
|
||||
|
||||
DisplayNum();
|
||||
m_bInv = false;
|
||||
break;
|
||||
}
|
||||
HandleErrorCommand(wParam);
|
||||
break;
|
||||
case IDC_EULER:
|
||||
if (!m_fIntegerMode)
|
||||
{
|
||||
CheckAndAddLastBinOpToHistory(); // e is like entering the number
|
||||
m_currentVal = Rational{ rat_exp };
|
||||
|
||||
DisplayNum();
|
||||
m_bInv = false;
|
||||
break;
|
||||
}
|
||||
HandleErrorCommand(wParam);
|
||||
break;
|
||||
case IDC_FE:
|
||||
// Toggle exponential notation display.
|
||||
m_nFE = NUMOBJ_FMT(!(int)m_nFE);
|
||||
@@ -761,7 +816,7 @@ void CCalcEngine::ResolveHighestPrecedenceOperation()
|
||||
{
|
||||
m_currentVal = m_holdVal;
|
||||
DisplayNum(); // to update the m_numberString
|
||||
m_HistoryCollector.AddBinOpToHistory(m_nOpCode, false);
|
||||
m_HistoryCollector.AddBinOpToHistory(m_nOpCode, m_fIntegerMode, false);
|
||||
m_HistoryCollector.AddOpndToHistory(m_numberString, m_currentVal); // Adding the repeated last op to history
|
||||
}
|
||||
|
||||
@@ -863,11 +918,14 @@ struct FunctionNameElement
|
||||
wstring gradString;
|
||||
wstring inverseGradString; // Will fall back to gradString if empty
|
||||
|
||||
wstring programmerModeString;
|
||||
|
||||
bool hasAngleStrings = ((!radString.empty()) || (!inverseRadString.empty()) || (!gradString.empty()) || (!inverseGradString.empty()));
|
||||
};
|
||||
|
||||
// Table for each unary operator
|
||||
static const std::unordered_map<int, FunctionNameElement> unaryOperatorStringTable = {
|
||||
static const std::unordered_map<int, FunctionNameElement> operatorStringTable =
|
||||
{
|
||||
{ IDC_CHOP, { L"", SIDS_FRAC } },
|
||||
|
||||
{ IDC_SIN, { SIDS_SIND, SIDS_ASIND, SIDS_SINR, SIDS_ASINR, SIDS_SING, SIDS_ASING } },
|
||||
@@ -878,6 +936,14 @@ static const std::unordered_map<int, FunctionNameElement> unaryOperatorStringTab
|
||||
{ IDC_COSH, { L"", SIDS_ACOSH } },
|
||||
{ IDC_TANH, { L"", SIDS_ATANH } },
|
||||
|
||||
{ IDC_SEC, { SIDS_SECD, SIDS_ASECD, SIDS_SECR, SIDS_ASECR, SIDS_SECG, SIDS_ASECG } },
|
||||
{ IDC_CSC, { SIDS_CSCD, SIDS_ACSCD, SIDS_CSCR, SIDS_ACSCR, SIDS_CSCG, SIDS_ACSCG } },
|
||||
{ IDC_COT, { SIDS_COTD, SIDS_ACOTD, SIDS_COTR, SIDS_ACOTR, SIDS_COTG, SIDS_ACOTG } },
|
||||
|
||||
{ IDC_SECH, { SIDS_SECH, SIDS_ASECH } },
|
||||
{ IDC_CSCH, { SIDS_CSCH, SIDS_ACSCH } },
|
||||
{ IDC_COTH, { SIDS_COTH, SIDS_ACOTH } },
|
||||
|
||||
{ IDC_LN, { L"", SIDS_POWE } },
|
||||
{ IDC_SQR, { SIDS_SQR } },
|
||||
{ IDC_CUB, { SIDS_CUBE } },
|
||||
@@ -885,7 +951,19 @@ static const std::unordered_map<int, FunctionNameElement> unaryOperatorStringTab
|
||||
{ IDC_REC, { SIDS_RECIPROC } },
|
||||
{ IDC_DMS, { L"", SIDS_DEGREES } },
|
||||
{ IDC_SIGN, { SIDS_NEGATE } },
|
||||
{ IDC_DEGREES, { SIDS_DEGREES } }
|
||||
{ IDC_DEGREES, { SIDS_DEGREES } },
|
||||
{ IDC_POW2, { SIDS_TWOPOWX } },
|
||||
{ IDC_LOGBASEX, { SIDS_LOGBASEX } },
|
||||
{ IDC_ABS, { SIDS_ABS } },
|
||||
{ IDC_CEIL, { SIDS_CEIL } },
|
||||
{ IDC_FLOOR, { SIDS_FLOOR } },
|
||||
{ IDC_NAND, { SIDS_NAND } },
|
||||
{ IDC_NOR, { SIDS_NOR } },
|
||||
{ IDC_RSHFL, { SIDS_RSH } },
|
||||
{ IDC_RORC, { SIDS_ROR } },
|
||||
{ IDC_ROLC, { SIDS_ROL } },
|
||||
{ IDC_CUBEROOT, {SIDS_CUBEROOT} },
|
||||
{ IDC_MOD, {SIDS_MOD, L"", L"", L"", L"", L"", SIDS_PROGRAMMER_MOD} },
|
||||
};
|
||||
|
||||
wstring_view CCalcEngine::OpCodeToUnaryString(int nOpCode, bool fInv, ANGLE_TYPE angletype)
|
||||
@@ -893,7 +971,7 @@ wstring_view CCalcEngine::OpCodeToUnaryString(int nOpCode, bool fInv, ANGLE_TYPE
|
||||
// Try to lookup the ID in the UFNE table
|
||||
wstring ids = L"";
|
||||
|
||||
if (auto pair = unaryOperatorStringTable.find(nOpCode); pair != unaryOperatorStringTable.end())
|
||||
if (auto pair = operatorStringTable.find(nOpCode); pair != operatorStringTable.end())
|
||||
{
|
||||
const FunctionNameElement& element = pair->second;
|
||||
if (!element.hasAngleStrings || ANGLE_DEG == angletype)
|
||||
@@ -941,6 +1019,32 @@ wstring_view CCalcEngine::OpCodeToUnaryString(int nOpCode, bool fInv, ANGLE_TYPE
|
||||
return OpCodeToString(nOpCode);
|
||||
}
|
||||
|
||||
wstring_view CCalcEngine::OpCodeToBinaryString(int nOpCode, bool isIntegerMode)
|
||||
{
|
||||
// Try to lookup the ID in the UFNE table
|
||||
wstring ids = L"";
|
||||
|
||||
if (auto pair = operatorStringTable.find(nOpCode); pair != operatorStringTable.end())
|
||||
{
|
||||
if (isIntegerMode && !pair->second.programmerModeString.empty())
|
||||
{
|
||||
ids = pair->second.programmerModeString;
|
||||
}
|
||||
else
|
||||
{
|
||||
ids = pair->second.degreeString;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ids.empty())
|
||||
{
|
||||
return GetString(ids);
|
||||
}
|
||||
|
||||
// If we didn't find an ID in the table, use the op code.
|
||||
return OpCodeToString(nOpCode);
|
||||
}
|
||||
|
||||
bool CCalcEngine::IsCurrentTooBigForTrig()
|
||||
{
|
||||
return m_currentVal >= m_maxTrigonometricNum;
|
||||
@@ -1007,3 +1111,14 @@ wstring CCalcEngine::GetStringForDisplay(Rational const& rat, uint32_t radix)
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
double CCalcEngine::GenerateRandomNumber()
|
||||
{
|
||||
if (m_randomGeneratorEngine == nullptr)
|
||||
{
|
||||
random_device rd;
|
||||
m_randomGeneratorEngine = std::make_unique<std::mt19937>(rd());
|
||||
m_distr = std::make_unique<std::uniform_real_distribution<>>(0, 1);
|
||||
}
|
||||
return (*m_distr.get())(*m_randomGeneratorEngine.get());
|
||||
}
|
||||
|
||||
@@ -46,8 +46,8 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
|
||||
}
|
||||
break;
|
||||
|
||||
// Rotate Left with hi bit wrapped over to lo bit
|
||||
case IDC_ROL:
|
||||
case IDC_ROLC:
|
||||
if (m_fIntegerMode)
|
||||
{
|
||||
result = Integer(rat);
|
||||
@@ -55,14 +55,23 @@ 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 |= msb; // Set the prev Msb as the current Lsb
|
||||
|
||||
if (op == IDC_ROL)
|
||||
{
|
||||
w64Bits |= msb; // Set the prev Msb as the current Lsb
|
||||
}
|
||||
else
|
||||
{
|
||||
w64Bits |= m_carryBit; // Set the carry bit as the LSB
|
||||
m_carryBit = msb; // Store the msb as the next carry bit
|
||||
}
|
||||
|
||||
result = w64Bits;
|
||||
}
|
||||
break;
|
||||
|
||||
// Rotate right with lo bit wrapped over to hi bit
|
||||
case IDC_ROR:
|
||||
case IDC_RORC:
|
||||
if (m_fIntegerMode)
|
||||
{
|
||||
result = Integer(rat);
|
||||
@@ -70,7 +79,16 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
|
||||
uint64_t w64Bits = result.ToUInt64_t();
|
||||
uint64_t lsb = ((w64Bits & 0x01) == 1) ? 1 : 0;
|
||||
w64Bits >>= 1; // RShift by 1
|
||||
w64Bits |= (lsb << (m_dwWordBitWidth - 1));
|
||||
|
||||
if (op == IDC_ROR)
|
||||
{
|
||||
w64Bits |= (lsb << (m_dwWordBitWidth - 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
w64Bits |= (m_carryBit << (m_dwWordBitWidth - 1));
|
||||
m_carryBit = lsb;
|
||||
}
|
||||
|
||||
result = w64Bits;
|
||||
}
|
||||
@@ -133,6 +151,48 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
|
||||
}
|
||||
break;
|
||||
|
||||
case IDC_SEC:
|
||||
if (!m_fIntegerMode)
|
||||
{
|
||||
result = m_bInv ? ACos(Invert(rat), m_angletype) : Invert(Cos(rat, m_angletype));
|
||||
}
|
||||
break;
|
||||
|
||||
case IDC_CSC:
|
||||
if (!m_fIntegerMode)
|
||||
{
|
||||
result = m_bInv ? ASin(Invert(rat), m_angletype) : Invert(Sin(rat, m_angletype));
|
||||
}
|
||||
break;
|
||||
|
||||
case IDC_COT:
|
||||
if (!m_fIntegerMode)
|
||||
{
|
||||
result = m_bInv ? ATan(Invert(rat), m_angletype) : Invert(Tan(rat, m_angletype));
|
||||
}
|
||||
break;
|
||||
|
||||
case IDC_SECH:
|
||||
if (!m_fIntegerMode)
|
||||
{
|
||||
result = m_bInv ? ACosh(Invert(rat)) : Invert(Cosh(rat));
|
||||
}
|
||||
break;
|
||||
|
||||
case IDC_CSCH:
|
||||
if (!m_fIntegerMode)
|
||||
{
|
||||
result = m_bInv ? ASinh(Invert(rat)) : Invert(Sinh(rat));
|
||||
}
|
||||
break;
|
||||
|
||||
case IDC_COTH:
|
||||
if (!m_fIntegerMode)
|
||||
{
|
||||
result = m_bInv ? ATanh(Invert(rat)) : Invert(Tanh(rat));
|
||||
}
|
||||
break;
|
||||
|
||||
case IDC_REC: /* Reciprocal. */
|
||||
result = Invert(rat);
|
||||
break;
|
||||
@@ -158,6 +218,10 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
|
||||
result = Pow(10, rat);
|
||||
break;
|
||||
|
||||
case IDC_POW2:
|
||||
result = Pow(2, rat);
|
||||
break;
|
||||
|
||||
case IDC_LN: /* Functions for natural log. */
|
||||
result = m_bInv ? Exp(rat) : Log(rat);
|
||||
break;
|
||||
@@ -202,6 +266,18 @@ CalcEngine::Rational CCalcEngine::SciCalcFunctions(CalcEngine::Rational const& r
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IDC_CEIL:
|
||||
result = (Frac(rat) > 0) ? Integer(rat + 1) : Integer(rat);
|
||||
break;
|
||||
|
||||
case IDC_FLOOR:
|
||||
result = (Frac(rat) < 0) ? Integer(rat - 1 ) : Integer(rat);
|
||||
break;
|
||||
|
||||
case IDC_ABS:
|
||||
result = Abs(rat);
|
||||
break;
|
||||
|
||||
} // end switch( op )
|
||||
}
|
||||
catch (uint32_t nErrCode)
|
||||
|
||||
@@ -28,6 +28,14 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa
|
||||
result ^= rhs;
|
||||
break;
|
||||
|
||||
case IDC_NAND:
|
||||
result = (result & rhs) ^ m_chopNumbers[m_numwidth];
|
||||
break;
|
||||
|
||||
case IDC_NOR:
|
||||
result = (result | rhs) ^ m_chopNumbers[m_numwidth];
|
||||
break;
|
||||
|
||||
case IDC_RSHF:
|
||||
{
|
||||
if (m_fIntegerMode && result >= m_dwWordBitWidth) // Lsh/Rsh >= than current word size is always 0
|
||||
@@ -52,7 +60,16 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IDC_RSHFL:
|
||||
{
|
||||
if (m_fIntegerMode && result >= m_dwWordBitWidth) // Lsh/Rsh >= than current word size is always 0
|
||||
{
|
||||
throw CALC_E_NORESULT;
|
||||
}
|
||||
|
||||
result = rhs >> result;
|
||||
break;
|
||||
}
|
||||
case IDC_LSHF:
|
||||
if (m_fIntegerMode && result >= m_dwWordBitWidth) // Lsh/Rsh >= than current word size is always 0
|
||||
{
|
||||
@@ -140,6 +157,10 @@ CalcEngine::Rational CCalcEngine::DoOperation(int operation, CalcEngine::Rationa
|
||||
case IDC_ROOT: // Calculates rhs to the result(th) root.
|
||||
result = Root(rhs, result);
|
||||
break;
|
||||
|
||||
case IDC_LOGBASEX:
|
||||
result = (Log(result) / Log(rhs));
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (uint32_t dwErrCode)
|
||||
|
||||
Reference in New Issue
Block a user