diff options
-rw-r--r-- | sal/rtl/math.cxx | 29 | ||||
-rw-r--r-- | tools/source/generic/fract.cxx | 24 | ||||
-rw-r--r-- | tools/source/misc/fix16.cxx | 31 |
3 files changed, 12 insertions, 72 deletions
diff --git a/sal/rtl/math.cxx b/sal/rtl/math.cxx index fe45b90a8297..5b6c780b5001 100644 --- a/sal/rtl/math.cxx +++ b/sal/rtl/math.cxx @@ -24,6 +24,7 @@ #include <rtl/math.hxx> #include <algorithm> +#include <bit> #include <cassert> #include <cfenv> #include <cmath> @@ -118,18 +119,6 @@ bool isRepresentableInteger(double fAbsValue) return nInt == fAbsValue; } -// Returns 1-based index of least significant bit in a number, or zero if number is zero -int findFirstSetBit(unsigned n) -{ -#if defined _WIN32 - unsigned long pos; - unsigned char bNonZero = _BitScanForward(&pos, n); - return (bNonZero == 0) ? 0 : pos + 1; -#else - return __builtin_ffs(n); -#endif -} - /** Returns number of binary bits for fractional part of the number Expects a proper non-negative double value, not +-INF, not NAN */ @@ -138,19 +127,13 @@ int getBitsInFracPart(double fAbsValue) assert(std::isfinite(fAbsValue) && fAbsValue >= 0.0); if (fAbsValue == 0.0) return 0; - auto pValParts = reinterpret_cast<const sal_math_Double*>(&fAbsValue); - int nExponent = pValParts->inf_parts.exponent - 1023; + auto& rValParts = reinterpret_cast<const sal_math_Double*>(&fAbsValue)->parts; + int nExponent = rValParts.exponent - 1023; if (nExponent >= 52) return 0; // All bits in fraction are in integer part of the number - int nLeastSignificant = findFirstSetBit(pValParts->inf_parts.fraction_lo); - if (nLeastSignificant == 0) - { - nLeastSignificant = findFirstSetBit(pValParts->inf_parts.fraction_hi); - if (nLeastSignificant == 0) - nLeastSignificant = 53; // the implied leading 1 is the least significant - else - nLeastSignificant += 32; - } + int nLeastSignificant = rValParts.fraction + ? std::countr_zero(rValParts.fraction) + 1 + : 53; // the implied leading 1 is the least significant int nFracSignificant = 53 - nLeastSignificant; int nBitsInFracPart = nFracSignificant - nExponent; diff --git a/tools/source/generic/fract.cxx b/tools/source/generic/fract.cxx index abe8ee41b206..7dfddf50a880 100644 --- a/tools/source/generic/fract.cxx +++ b/tools/source/generic/fract.cxx @@ -25,18 +25,16 @@ #include <osl/diagnose.h> #include <algorithm> +#include <bit> #include <cmath> #include <numeric> #include <boost/rational.hpp> -#ifdef _MSC_VER -#include <intrin.h> -#endif - static boost::rational<sal_Int32> rational_FromDouble(double dVal); static void rational_ReduceInaccurate(boost::rational<sal_Int32>& rRational, unsigned nSignificantBits); -static int impl_NumberOfBits( sal_uInt32 nNum ); +// Find the number of bits required to represent this number +static int impl_NumberOfBits(sal_uInt32 nNum) { return 32 - std::countl_zero(nNum); } static boost::rational<sal_Int32> toRational(sal_Int32 n, sal_Int32 d) { @@ -406,22 +404,6 @@ static boost::rational<sal_Int32> rational_FromDouble(double dVal) return boost::rational<sal_Int32>( sal_Int32(dVal), nDen ); } -/** - * Find the number of bits required to represent this number, using the CLZ intrinsic - */ -static int impl_NumberOfBits( sal_uInt32 nNum ) -{ - if (nNum == 0) - return 0; -#ifdef _MSC_VER - unsigned long r = 0; - _BitScanReverse(&r, nNum); - return r + 1; -#else - return 32 - __builtin_clz(nNum); -#endif -} - /** Inaccurate cancellation for a fraction. Clip both nominator and denominator to said number of bits. If diff --git a/tools/source/misc/fix16.cxx b/tools/source/misc/fix16.cxx index 978f77291dce..58c40704d931 100644 --- a/tools/source/misc/fix16.cxx +++ b/tools/source/misc/fix16.cxx @@ -24,6 +24,8 @@ #include <tools/fix16.hxx> +#include <bit> + const fix16_t fix16_minimum = 0x80000000; /*!< the minimum value of fix16_t */ const fix16_t fix16_overflow = 0x80000000; /*!< the value used to indicate overflows */ @@ -74,33 +76,6 @@ fix16_t fix16_mul(fix16_t inArg0, fix16_t inArg1) return result; } -/* 32-bit implementation of fix16_div. Fastest version for e.g. ARM Cortex M3. - * Performs 32-bit divisions repeatedly to reduce the remainder. For this to - * be efficient, the processor has to have 32-bit hardware division. - */ -#ifdef __GNUC__ -// Count leading zeros, using processor-specific instruction if available. -#define clz(x) (__builtin_clzl(x) - (8 * sizeof(long) - 32)) -#else -static uint8_t clz(uint32_t x) -{ - uint8_t result = 0; - if (x == 0) - return 32; - while (!(x & 0xF0000000)) - { - result += 4; - x <<= 4; - } - while (!(x & 0x80000000)) - { - result += 1; - x <<= 1; - } - return result; -} -#endif - fix16_t fix16_div(fix16_t a, fix16_t b) { // This uses a hardware 32/32 bit division multiple times, until we have @@ -135,7 +110,7 @@ fix16_t fix16_div(fix16_t a, fix16_t b) while (remainder && bit_pos >= 0) { // Shift remainder as much as we can without overflowing - int shift = clz(remainder); + int shift = std::countl_zero(remainder); if (shift > bit_pos) shift = bit_pos; remainder <<= shift; |