Branch data Line data Source code
1 : : // Copyright 2019-2026 David Robillard <d@drobilla.net> 2 : : // SPDX-License-Identifier: ISC 3 : : 4 : : #include "int_math.h" 5 : : 6 : : #include "attributes.h" 7 : : #include "exess_config.h" 8 : : 9 : : #include <assert.h> 10 : : 11 : : EXESS_I_NONBLOCKING unsigned 12 : 1583027 : exess_clz32(const uint32_t i) 13 : : { 14 [ - + ]: 1583027 : assert(i != 0); 15 : : 16 : : #if USE_BUILTIN_CLZ 17 : 1583027 : return (unsigned)__builtin_clz(i); 18 : : #else 19 : : unsigned n = 32U; 20 : : uint32_t bits = i; 21 : : for (unsigned s = 16; s > 0; s >>= 1) { 22 : : const uint32_t left = bits >> s; 23 : : if (left) { 24 : : n -= s; 25 : : bits = left; 26 : : } 27 : : } 28 : : return n - bits; 29 : : #endif 30 : : } 31 : : 32 : : EXESS_I_NONBLOCKING unsigned 33 : 321535 : exess_clz64(const uint64_t i) 34 : : { 35 [ - + ]: 321535 : assert(i != 0); 36 : : 37 : : #if USE_BUILTIN_CLZLL 38 : 321535 : return (unsigned)__builtin_clzll(i); 39 : : #else 40 : : return (i & 0xFFFFFFFF00000000) ? exess_clz32((uint32_t)(i >> 32U)) 41 : : : 32U + exess_clz32(i & 0xFFFFFFFF); 42 : : #endif 43 : : } 44 : : 45 : : EXESS_I_NONBLOCKING uint64_t 46 : 243608 : exess_ilog2(const uint64_t i) 47 : : { 48 [ - + ]: 243608 : assert(i != 0); 49 : 243608 : return (64U - exess_clz64(i | 1U)) - 1U; 50 : : } 51 : : 52 : : EXESS_I_NONBLOCKING uint64_t 53 : 243608 : exess_ilog10(const uint64_t i) 54 : : { 55 : : // See https://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10 56 : 243608 : const uint64_t log2 = exess_ilog2(i); 57 : 243608 : const uint64_t t = (log2 + 1U) * 1233U >> 12U; 58 : : 59 : 243608 : return t - (i < POW10[t]) + (i == 0); 60 : : } 61 : : 62 : : EXESS_I_NONBLOCKING uint8_t 63 : 244001 : exess_num_digits(const uint64_t i) 64 : : { 65 [ + + ]: 244001 : return i == 0U ? 1U : (uint8_t)(exess_ilog10(i) + 1U); 66 : : }