aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/exess/src/int_math.c
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/exess/src/int_math.c')
-rw-r--r--subprojects/exess/src/int_math.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/subprojects/exess/src/int_math.c b/subprojects/exess/src/int_math.c
new file mode 100644
index 00000000..ce263b43
--- /dev/null
+++ b/subprojects/exess/src/int_math.c
@@ -0,0 +1,78 @@
+/*
+ Copyright 2019-2021 David Robillard <d@drobilla.net>
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+#include "int_math.h"
+
+#include "exess_config.h"
+
+#include <assert.h>
+
+unsigned
+exess_clz32(const uint32_t i)
+{
+ assert(i != 0);
+
+#if USE_BUILTIN_CLZ
+ return (unsigned)__builtin_clz(i);
+#else
+ unsigned n = 32u;
+ uint32_t bits = i;
+ for (unsigned s = 16; s > 0; s >>= 1) {
+ const uint32_t left = bits >> s;
+ if (left) {
+ n -= s;
+ bits = left;
+ }
+ }
+ return n - bits;
+#endif
+}
+
+unsigned
+exess_clz64(const uint64_t i)
+{
+ assert(i != 0);
+
+#if USE_BUILTIN_CLZLL
+ return (unsigned)__builtin_clzll(i);
+#else
+ return i & 0xFFFFFFFF00000000 ? exess_clz32((uint32_t)(i >> 32u))
+ : 32u + exess_clz32(i & 0xFFFFFFFF);
+#endif
+}
+
+uint64_t
+exess_ilog2(const uint64_t i)
+{
+ assert(i != 0);
+ return (64u - exess_clz64(i | 1u)) - 1u;
+}
+
+uint64_t
+exess_ilog10(const uint64_t i)
+{
+ // See https://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
+ const uint64_t log2 = exess_ilog2(i);
+ const uint64_t t = (log2 + 1u) * 1233u >> 12u;
+
+ return t - (i < POW10[t]) + (i == 0);
+}
+
+uint8_t
+exess_num_digits(const uint64_t i)
+{
+ return i == 0u ? 1u : (uint8_t)(exess_ilog10(i) + 1u);
+}