mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-18 22:36:33 +00:00
utils: gst_util_uint64_scale*() micro-optimisations
Sprinkle G_LIKELY/G_UNLIKELY; add inlined _scale_int_unchecked() so we don't do some checks twice when calling it from _scale().
This commit is contained in:
parent
998b2392d3
commit
f44204c8fa
1 changed files with 43 additions and 36 deletions
|
@ -264,7 +264,7 @@ gst_util_div128_64 (GstUInt64 c1, GstUInt64 c0, guint64 denom)
|
|||
}
|
||||
|
||||
static guint64
|
||||
gst_util_uint64_scale_int64 (guint64 val, guint64 num, guint64 denom)
|
||||
gst_util_uint64_scale_int64_unchecked (guint64 val, guint64 num, guint64 denom)
|
||||
{
|
||||
GstUInt64 a0, a1, b0, b1, c0, ct, c1, result;
|
||||
GstUInt64 v, n;
|
||||
|
@ -296,7 +296,7 @@ gst_util_uint64_scale_int64 (guint64 val, guint64 num, guint64 denom)
|
|||
c1.ll = (guint64) a1.l.high + b0.l.high + ct.l.high + b1.ll;
|
||||
|
||||
/* if high bits bigger than denom, we overflow */
|
||||
if (c1.ll >= denom)
|
||||
if (G_UNLIKELY (c1.ll >= denom))
|
||||
goto overflow;
|
||||
|
||||
/* shortcut for division by 1, c1.ll should be 0 because of the
|
||||
|
@ -326,6 +326,36 @@ overflow:
|
|||
}
|
||||
}
|
||||
|
||||
static inline guint64
|
||||
gst_util_uint64_scale_int_unchecked (guint64 val, gint num, gint denom)
|
||||
{
|
||||
GstUInt64 result;
|
||||
GstUInt64 low, high;
|
||||
|
||||
/* do 96 bits mult/div */
|
||||
low.ll = val;
|
||||
result.ll = ((guint64) low.l.low) * num;
|
||||
high.ll = ((guint64) low.l.high) * num + (result.l.high);
|
||||
|
||||
low.ll = high.ll / denom;
|
||||
result.l.high = high.ll % denom;
|
||||
result.ll /= denom;
|
||||
|
||||
/* avoid overflow */
|
||||
if (G_UNLIKELY (low.ll + result.l.high > G_MAXUINT32))
|
||||
goto overflow;
|
||||
|
||||
result.l.high += low.l.low;
|
||||
|
||||
return result.ll;
|
||||
|
||||
overflow:
|
||||
{
|
||||
return G_MAXUINT64;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_util_uint64_scale:
|
||||
* @val: the number to scale
|
||||
|
@ -344,33 +374,33 @@ gst_util_uint64_scale (guint64 val, guint64 num, guint64 denom)
|
|||
{
|
||||
g_return_val_if_fail (denom != 0, G_MAXUINT64);
|
||||
|
||||
if (num == 0)
|
||||
if (G_UNLIKELY (num == 0))
|
||||
return 0;
|
||||
|
||||
if (num == 1 && denom == 1)
|
||||
if (G_UNLIKELY (num == denom))
|
||||
return val;
|
||||
|
||||
/* if the denom is high, we need to do a 64 muldiv */
|
||||
if (denom > G_MAXINT32)
|
||||
if (G_UNLIKELY (denom > G_MAXINT32))
|
||||
goto do_int64;
|
||||
|
||||
/* if num and denom are low we can do a 32 bit muldiv */
|
||||
if (num <= G_MAXINT32)
|
||||
if (G_LIKELY (num <= G_MAXINT32))
|
||||
goto do_int32;
|
||||
|
||||
/* val and num are high, we need 64 muldiv */
|
||||
if (val > G_MAXINT32)
|
||||
if (G_UNLIKELY (val > G_MAXINT32))
|
||||
goto do_int64;
|
||||
|
||||
/* val is low and num is high, we can swap them and do 32 muldiv */
|
||||
return gst_util_uint64_scale_int (num, (gint) val, (gint) denom);
|
||||
return gst_util_uint64_scale_int_unchecked (num, (gint) val, (gint) denom);
|
||||
|
||||
do_int32:
|
||||
return gst_util_uint64_scale_int (val, (gint) num, (gint) denom);
|
||||
return gst_util_uint64_scale_int_unchecked (val, (gint) num, (gint) denom);
|
||||
|
||||
do_int64:
|
||||
/* to the more heavy implementations... */
|
||||
return gst_util_uint64_scale_int64 (val, num, denom);
|
||||
return gst_util_uint64_scale_int64_unchecked (val, num, denom);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -390,43 +420,20 @@ do_int64:
|
|||
guint64
|
||||
gst_util_uint64_scale_int (guint64 val, gint num, gint denom)
|
||||
{
|
||||
GstUInt64 result;
|
||||
GstUInt64 low, high;
|
||||
|
||||
g_return_val_if_fail (denom > 0, G_MAXUINT64);
|
||||
g_return_val_if_fail (num >= 0, G_MAXUINT64);
|
||||
|
||||
if (num == 0)
|
||||
if (G_UNLIKELY (num == 0))
|
||||
return 0;
|
||||
|
||||
if (num == 1 && denom == 1)
|
||||
if (G_UNLIKELY (num == denom))
|
||||
return val;
|
||||
|
||||
if (val <= G_MAXUINT32)
|
||||
/* simple case */
|
||||
return val * num / denom;
|
||||
|
||||
/* do 96 bits mult/div */
|
||||
low.ll = val;
|
||||
result.ll = ((guint64) low.l.low) * num;
|
||||
high.ll = ((guint64) low.l.high) * num + (result.l.high);
|
||||
|
||||
low.ll = high.ll / denom;
|
||||
result.l.high = high.ll % denom;
|
||||
result.ll /= denom;
|
||||
|
||||
/* avoid overflow */
|
||||
if (low.ll + result.l.high > G_MAXUINT32)
|
||||
goto overflow;
|
||||
|
||||
result.l.high += low.l.low;
|
||||
|
||||
return result.ll;
|
||||
|
||||
overflow:
|
||||
{
|
||||
return G_MAXUINT64;
|
||||
}
|
||||
return gst_util_uint64_scale_int_unchecked (val, num, denom);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue