Simplify calculations of the nearest power of 2

Use compiler intrinsics to find the nearest power of 2 as quickly as possible.

In addition, handle the 0 case, so that the program does not become stuck in an infinite loop if iNum is 0.
This commit is contained in:
Rose 2023-09-27 16:32:34 -04:00
commit dd8509fb3f
2 changed files with 10 additions and 25 deletions

View file

@ -50,7 +50,7 @@ void CCalcEngine::SetRadixTypeAndNumWidth(RadixType radixtype, NUM_WIDTH numwidt
DisplayNum();
}
int32_t CCalcEngine::DwWordBitWidthFromNumWidth(NUM_WIDTH numwidth)
uint32_t CCalcEngine::DwWordBitWidthFromNumWidth(NUM_WIDTH numwidth)
{
switch (numwidth)
{
@ -103,30 +103,15 @@ bool CCalcEngine::TryToggleBit(CalcEngine::Rational& rat, uint32_t wbitno)
}
// Returns the nearest power of two
int CCalcEngine::QuickLog2(int iNum)
unsigned int CCalcEngine::QuickLog2(unsigned int iNum)
{
int iRes = 0;
// Nearest power of 2 to 0 is 1
if (!iNum)
return 1;
// 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;
// Count the number of leading 0's of iNum - 1,
// and then shift 1 by that amount
return 1U << (32 - __builtin_clz(iNum - 1));
}
////////////////////////////////////////////////////////////////////////

View file

@ -179,7 +179,7 @@ private:
CalcEngine::Rational SciCalcFunctions(CalcEngine::Rational const& rat, uint32_t op);
CalcEngine::Rational DoOperation(int operation, CalcEngine::Rational const& lhs, CalcEngine::Rational const& rhs);
void SetRadixTypeAndNumWidth(RadixType radixtype, NUM_WIDTH numwidth);
int32_t DwWordBitWidthFromNumWidth(NUM_WIDTH numwidth);
uint32_t DwWordBitWidthFromNumWidth(NUM_WIDTH numwidth);
uint32_t NRadixFromRadixType(RadixType radixtype);
double GenerateRandomNumber();
@ -199,7 +199,7 @@ private:
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);
static int QuickLog2(int iNum);
static unsigned int QuickLog2(unsigned int iNum);
static void ChangeBaseConstants(uint32_t radix, int maxIntDigits, int32_t precision);
void BaseOrPrecisionChanged();