aboutsummaryrefslogtreecommitdiffstats
path: root/src/int_math.c
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2019-10-13 11:20:42 +0200
committerDavid Robillard <d@drobilla.net>2020-10-27 13:13:58 +0100
commit39819593f45c29982182c740c5ba6669473ebfc3 (patch)
tree311b0fa20aff0afe115122875d1a469924bc276c /src/int_math.c
parent2901a3669de67025f4daa47e5c452a4ffbec1476 (diff)
downloadserd-39819593f45c29982182c740c5ba6669473ebfc3.tar.gz
serd-39819593f45c29982182c740c5ba6669473ebfc3.tar.bz2
serd-39819593f45c29982182c740c5ba6669473ebfc3.zip
Add integer and bit math utilities
Diffstat (limited to 'src/int_math.c')
-rw-r--r--src/int_math.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/src/int_math.c b/src/int_math.c
new file mode 100644
index 00000000..b20b14a6
--- /dev/null
+++ b/src/int_math.c
@@ -0,0 +1,70 @@
+/*
+ Copyright 2019-2020 David Robillard <http://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 <assert.h>
+
+unsigned
+serd_clz32(const uint32_t i)
+{
+ assert(i != 0);
+
+#ifdef HAVE_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
+serd_clz64(const uint64_t i)
+{
+ assert(i != 0);
+
+#ifdef HAVE_BUILTIN_CLZLL
+ return (unsigned)__builtin_clzll(i);
+#else
+ return i & 0xFFFFFFFF00000000 ? serd_clz32(i >> 32)
+ : 32 + serd_clz32(i & 0xFFFFFFFF);
+#endif
+}
+
+uint64_t
+serd_ilog2(const uint64_t i)
+{
+ assert(i != 0);
+ return (64 - serd_clz64(i | 1)) - 1;
+}
+
+uint64_t
+serd_ilog10(const uint64_t i)
+{
+ // See https://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
+ const uint64_t log2 = serd_ilog2(i);
+ const uint64_t t = (log2 + 1) * 1233 >> 12;
+
+ return t - (i < POW10[t]) + (i == 0);
+}