summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2019-10-31 13:16:58 +0100
committerwm4 <wm4@nowhere>2019-10-31 13:16:58 +0100
commit7510ed6f684041db643c051cb17b13abf663b3b2 (patch)
treee99355085b8f9ccb13d883d08dc22dca1a58ff50
parent6d92e5550203b04b7254eb8ffe31734e57070d79 (diff)
downloadmpv-7510ed6f684041db643c051cb17b13abf663b3b2.tar.bz2
mpv-7510ed6f684041db643c051cb17b13abf663b3b2.tar.xz
common: add mp_log2()
To be used in the next commit. According to compiler explorer, __builtin_clz is very widely available, and it barely makes sense to provide a fallback. clang also eats this (and identifies at least as GCC 4). Actually, there's doubt that a fast log2 implementation is needed at all (I guess UTF-8 parsing needs it, but something UTF-8-specific would probably make it faster than using log2). So the fallback is just something naive.
-rw-r--r--common/common.c18
-rw-r--r--common/common.h2
2 files changed, 20 insertions, 0 deletions
diff --git a/common/common.c b/common/common.c
index d0b2382b78..967ab961c0 100644
--- a/common/common.c
+++ b/common/common.c
@@ -318,3 +318,21 @@ char **mp_dup_str_array(void *tctx, char **s)
MP_TARRAY_APPEND(tctx, r, num_r, NULL);
return r;
}
+
+// Return rounded down integer log 2 of v, i.e. position of highest set bit.
+// mp_log2(0) == 0
+// mp_log2(1) == 0
+// mp_log2(31) == 4
+// mp_log2(32) == 5
+unsigned int mp_log2(uint32_t v)
+{
+#if defined(__GNUC__) && __GNUC__ >= 4
+ return v ? 31 - __builtin_clz(v) : 0;
+#else
+ for (int x = 31; x >= 0; x--) {
+ if (v & (((uint32_t)1) << x))
+ return x;
+ }
+ return 0;
+#endif
+}
diff --git a/common/common.h b/common/common.h
index 16e1ec4cfd..5e6950c931 100644
--- a/common/common.h
+++ b/common/common.h
@@ -88,6 +88,8 @@ bool mp_rect_intersection(struct mp_rect *rc, const struct mp_rect *rc2);
bool mp_rect_contains(struct mp_rect *rc, int x, int y);
bool mp_rect_equals(struct mp_rect *rc1, struct mp_rect *rc2);
+unsigned int mp_log2(uint32_t v);
+
int mp_snprintf_cat(char *str, size_t size, const char *format, ...)
PRINTF_ATTRIBUTE(3, 4);