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.
180 lines
5.9 KiB
C++
180 lines
5.9 KiB
C++
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
|
|
#include "Header Files/CalcEngine.h"
|
|
|
|
using namespace CalcEngine;
|
|
using namespace CalcEngine::RationalMath;
|
|
using namespace std;
|
|
|
|
// To be called when either the radix or num width changes. You can use -1 in either of these values to mean
|
|
// dont change that.
|
|
void CCalcEngine::SetRadixTypeAndNumWidth(RADIX_TYPE radixtype, NUM_WIDTH numwidth)
|
|
{
|
|
// When in integer mode, the number is represented in 2's complement form. When a bit width is changing, we can
|
|
// change the number representation back to sign, abs num form in ratpak. Soon when display sees this, it will
|
|
// convert to 2's complement form, but this time all high bits will be propagated. Eg. -127, in byte mode is
|
|
// represented as 1000,0001. This puts it back as sign=-1, 01111111 . But DisplayNum will see this and convert it
|
|
// back to 1111,1111,1000,0001 when in Word mode.
|
|
if (m_fIntegerMode)
|
|
{
|
|
uint64_t w64Bits = m_currentVal.ToUInt64_t();
|
|
bool fMsb = (w64Bits >> (m_dwWordBitWidth - 1)) & 1; // make sure you use the old width
|
|
|
|
if (fMsb)
|
|
{
|
|
// If high bit is set, then get the decimal number in -ve 2'scompl form.
|
|
auto tempResult = m_currentVal ^ m_chopNumbers[m_numwidth];
|
|
|
|
m_currentVal = -(tempResult + 1);
|
|
}
|
|
}
|
|
|
|
if (radixtype >= HEX_RADIX && radixtype <= BIN_RADIX)
|
|
{
|
|
m_radix = NRadixFromRadixType(radixtype);
|
|
// radixtype is not even saved
|
|
}
|
|
|
|
if (numwidth >= QWORD_WIDTH && numwidth <= BYTE_WIDTH)
|
|
{
|
|
m_numwidth = numwidth;
|
|
m_dwWordBitWidth = DwWordBitWidthFromeNumWidth(numwidth);
|
|
}
|
|
|
|
// inform ratpak that a change in base or precision has occurred
|
|
BaseOrPrecisionChanged();
|
|
|
|
// display the correct number for the new state (ie convert displayed
|
|
// number to correct base)
|
|
DisplayNum();
|
|
}
|
|
|
|
int32_t CCalcEngine::DwWordBitWidthFromeNumWidth(NUM_WIDTH /*numwidth*/)
|
|
{
|
|
static constexpr int nBitMax[] = { 64, 32, 16, 8 };
|
|
int32_t wmax = nBitMax[0];
|
|
|
|
if (m_numwidth >= 0 && (size_t)m_numwidth < size(nBitMax))
|
|
{
|
|
wmax = nBitMax[m_numwidth];
|
|
}
|
|
return wmax;
|
|
}
|
|
|
|
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 */
|
|
uint32_t radix = 10;
|
|
|
|
// convert special bases into symbolic values
|
|
if (radixtype >= 0 && (size_t)radixtype < size(rgnRadish))
|
|
{
|
|
radix = rgnRadish[radixtype];
|
|
}
|
|
return radix;
|
|
}
|
|
|
|
// Toggles a given bit into the number representation. returns true if it changed it actually.
|
|
bool CCalcEngine::TryToggleBit(CalcEngine::Rational& rat, uint32_t wbitno)
|
|
{
|
|
uint32_t wmax = DwWordBitWidthFromeNumWidth(m_numwidth);
|
|
if (wbitno >= wmax)
|
|
{
|
|
return false; // ignore error cant happen
|
|
}
|
|
|
|
Rational result = Integer(rat);
|
|
|
|
// Remove any variance in how 0 could be represented in rat e.g. -0, 0/n, etc.
|
|
result = (result != 0 ? result : 0);
|
|
|
|
// XOR the result with 2^wbitno power
|
|
rat = result ^ Pow(2, static_cast<int32_t>(wbitno));
|
|
|
|
return true;
|
|
}
|
|
|
|
// Returns the nearest power of two
|
|
int CCalcEngine::QuickLog2(int iNum)
|
|
{
|
|
int iRes = 0;
|
|
|
|
// while first digit is a zero
|
|
while (!(iNum & 1))
|
|
{
|
|
iRes++;
|
|
iNum >>= 1;
|
|
}
|
|
|
|
// if our number isn't a perfect square
|
|
iNum = iNum >> 1;
|
|
if (iNum)
|
|
{
|
|
// find the largest digit
|
|
for (iNum = iNum >> 1; iNum; iNum = iNum >> 1)
|
|
++iRes;
|
|
|
|
// and then add two
|
|
iRes += 2;
|
|
}
|
|
|
|
return iRes;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// UpdateMaxIntDigits
|
|
//
|
|
// determine the maximum number of digits needed for the current precision,
|
|
// word size, and base. This number is conservative towards the small side
|
|
// such that there may be some extra bits left over. For example, base 8 requires 3 bits per digit.
|
|
// A word size of 32 bits allows for 10 digits with a remainder of two bits. Bases
|
|
// that require variable number of bits (non-power-of-two bases) are approximated
|
|
// by the next highest power-of-two base (again, to be conservative and guarantee
|
|
// there will be no over flow verse the current word size for numbers entered).
|
|
// Base 10 is a special case and always uses the base 10 precision (m_nPrecisionSav).
|
|
void CCalcEngine::UpdateMaxIntDigits()
|
|
{
|
|
if (m_radix == 10)
|
|
{
|
|
// if in integer mode you still have to honor the max digits you can enter based on bit width
|
|
if (m_fIntegerMode)
|
|
{
|
|
m_cIntDigitsSav = static_cast<int>(m_maxDecimalValueStrings[m_numwidth].length()) - 1;
|
|
// This is the max digits you can enter a decimal in fixed width mode aka integer mode -1. The last digit
|
|
// has to be checked separately
|
|
}
|
|
else
|
|
{
|
|
m_cIntDigitsSav = m_precision;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_cIntDigitsSav = m_dwWordBitWidth / CCalcEngine::QuickLog2(m_radix);
|
|
}
|
|
}
|
|
|
|
void CCalcEngine::ChangeBaseConstants(uint32_t radix, int maxIntDigits, int32_t precision)
|
|
{
|
|
if (10 == radix)
|
|
{
|
|
ChangeConstants(radix, precision); // Base 10 precision for internal computing still needs to be 32, to
|
|
// take care of decimals precisely. For eg. to get the HI word of a qword, we do a rsh, which depends on getting
|
|
// 18446744073709551615 / 4294967296 = 4294967295.9999917... This is important it works this and doesn't reduce
|
|
// the precision to number of digits allowed to enter. In other words, precision and # of allowed digits to be
|
|
// entered are different.
|
|
}
|
|
else
|
|
{
|
|
ChangeConstants(radix, maxIntDigits + 1);
|
|
}
|
|
}
|
|
|
|
void CCalcEngine::BaseOrPrecisionChanged()
|
|
{
|
|
UpdateMaxIntDigits();
|
|
CCalcEngine::ChangeBaseConstants(m_radix, m_cIntDigitsSav, m_precision);
|
|
}
|