clock: Fix calculation for number of bits needed to store a 64 bit value

It was using log2(n) but what actually is needed is log2(n) + 1. Also add a
fast-path that uses __builtin_clzll() on gcc/clang.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7431>
This commit is contained in:
Sebastian Dröge 2024-08-26 19:13:11 +03:00 committed by Backport Bot
parent ff538e4adf
commit 49e14405cb

View file

@ -4454,10 +4454,15 @@ gst_util_group_id_next (void)
return ret;
}
/* Compute log2 of the passed 64-bit number by finding the highest set bit */
/* Compute the number of bits needed at least to store `in` */
static guint
gst_log2 (GstClockTime in)
gst_bit_storage_uint64 (guint64 in)
{
#if defined(__GNUC__) && __GNUC__ >= 4
return in ? 64 - __builtin_clzll (in) : 1;
#else
/* integer log2(v) from:
<http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog> */
const guint64 b[] =
{ 0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000, 0xFFFFFFFF00000000LL };
const guint64 S[] = { 1, 2, 4, 8, 16, 32 };
@ -4471,7 +4476,8 @@ gst_log2 (GstClockTime in)
}
}
return count;
return count + 1; // + 1 to get the number of storage bits needed
#endif
}
/**
@ -4649,7 +4655,7 @@ gst_calculate_linear_regression (const GstClockTime * xy,
* That means that each number must require at most (63 - 1) / 2 bits = 31
* bits of storage.
*/
max_bits = gst_log2 (MAX (1, MAX (xmax - xmin, ymax - ymin)));
max_bits = gst_bit_storage_uint64 (MAX (1, MAX (xmax - xmin, ymax - ymin)));
if (max_bits > 31)
pshift = max_bits - 31;