mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-07 07:58:51 +00:00
check/gst/gstutils.c: Updated check, add some scaling accuracy checking code.
Original commit message from CVS: * check/gst/gstutils.c: (GST_START_TEST): Updated check, add some scaling accuracy checking code. * gst/gstutils.c: (gst_util_div128_64), (gst_util_uint64_scale_int64), (gst_util_uint64_scale), (gst_util_uint64_scale_int): Fix 6 times faster division code. Optimize for common 1/1 and less common X/1 cases.
This commit is contained in:
parent
597335c574
commit
2dc0ef57fd
4 changed files with 65 additions and 42 deletions
11
ChangeLog
11
ChangeLog
|
@ -1,3 +1,14 @@
|
||||||
|
2005-11-28 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
|
* check/gst/gstutils.c: (GST_START_TEST):
|
||||||
|
Updated check, add some scaling accuracy checking code.
|
||||||
|
|
||||||
|
* gst/gstutils.c: (gst_util_div128_64),
|
||||||
|
(gst_util_uint64_scale_int64), (gst_util_uint64_scale),
|
||||||
|
(gst_util_uint64_scale_int):
|
||||||
|
Fix 6 times faster division code. Optimize for common
|
||||||
|
1/1 and less common X/1 cases.
|
||||||
|
|
||||||
2005-11-28 Wim Taymans <wim@fluendo.com>
|
2005-11-28 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
* check/gst/gstutils.c: (GST_START_TEST), (gst_utils_suite):
|
* check/gst/gstutils.c: (GST_START_TEST), (gst_utils_suite):
|
||||||
|
|
|
@ -236,19 +236,35 @@ GST_START_TEST (test_math_scale_uint64)
|
||||||
|
|
||||||
GST_START_TEST (test_math_scale_random)
|
GST_START_TEST (test_math_scale_random)
|
||||||
{
|
{
|
||||||
guint64 val, num, denom, res;;
|
guint64 val, num, denom, res;
|
||||||
GRand *rand;
|
GRand *rand;
|
||||||
gint i;
|
gint i;
|
||||||
|
|
||||||
rand = g_rand_new ();
|
rand = g_rand_new ();
|
||||||
|
|
||||||
i = 1000;
|
i = 1000000;
|
||||||
while (i--) {
|
while (i--) {
|
||||||
|
guint64 check, diff;
|
||||||
|
|
||||||
val = ((guint64) g_rand_int (rand)) << 32 | g_rand_int (rand);
|
val = ((guint64) g_rand_int (rand)) << 32 | g_rand_int (rand);
|
||||||
num = ((guint64) g_rand_int (rand)) << 32 | g_rand_int (rand);
|
num = ((guint64) g_rand_int (rand)) << 32 | g_rand_int (rand);
|
||||||
denom = ((guint64) g_rand_int (rand)) << 32 | g_rand_int (rand);
|
denom = ((guint64) g_rand_int (rand)) << 32 | g_rand_int (rand);
|
||||||
|
|
||||||
res = gst_util_uint64_scale (val, num, denom);
|
res = gst_util_uint64_scale (val, num, denom);
|
||||||
|
check = gst_gdouble_to_guint64 (gst_guint64_to_gdouble (val) *
|
||||||
|
gst_guint64_to_gdouble (num) / gst_guint64_to_gdouble (denom));
|
||||||
|
|
||||||
|
if (res < G_MAXUINT64 && check < G_MAXUINT64) {
|
||||||
|
if (res > check)
|
||||||
|
diff = res - check;
|
||||||
|
else
|
||||||
|
diff = check - res;
|
||||||
|
|
||||||
|
/* some arbitrary value, really.. someone do the proper math to get
|
||||||
|
* the upper bound */
|
||||||
|
if (diff > 20000)
|
||||||
|
fail_if (diff > 20000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
g_rand_free (rand);
|
g_rand_free (rand);
|
||||||
|
|
||||||
|
|
|
@ -356,36 +356,6 @@ typedef union
|
||||||
} l;
|
} l;
|
||||||
} GstUInt64;
|
} GstUInt64;
|
||||||
|
|
||||||
static guint64
|
|
||||||
gst_util_div128_64_iterate (GstUInt64 c1, GstUInt64 c0, guint64 denom)
|
|
||||||
{
|
|
||||||
gint i;
|
|
||||||
gint64 mask;
|
|
||||||
GstUInt64 a0;
|
|
||||||
|
|
||||||
/* full 128/64 case, very slow... */
|
|
||||||
/* quotient is c1, c0 */
|
|
||||||
a0.ll = 0; /* remainder a0 */
|
|
||||||
|
|
||||||
/* This can be done faster, inspiration in Hacker's Delight p152 */
|
|
||||||
for (i = 0; i < 128; i++) {
|
|
||||||
/* shift 192 bits remainder:quotient, we only need to
|
|
||||||
* check the top bit since denom is only 64 bits. */
|
|
||||||
/* sign extend top bit into mask */
|
|
||||||
mask = ((gint32) a0.l.high) >> 31;
|
|
||||||
mask |= (a0.ll = (a0.ll << 1) | (c1.l.high >> 31));
|
|
||||||
c1.ll = (c1.ll << 1) | (c0.l.high >> 31);
|
|
||||||
c0.ll <<= 1;
|
|
||||||
|
|
||||||
/* if remainder >= denom or top bit was set */
|
|
||||||
if (mask >= denom) {
|
|
||||||
a0.ll -= denom;
|
|
||||||
c0.ll += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return c0.ll;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* based on Hacker's Delight p152 */
|
/* based on Hacker's Delight p152 */
|
||||||
static guint64
|
static guint64
|
||||||
gst_util_div128_64 (GstUInt64 c1, GstUInt64 c0, guint64 denom)
|
gst_util_div128_64 (GstUInt64 c1, GstUInt64 c0, guint64 denom)
|
||||||
|
@ -409,10 +379,12 @@ gst_util_div128_64 (GstUInt64 c1, GstUInt64 c0, guint64 denom)
|
||||||
s += (s >> 8);
|
s += (s >> 8);
|
||||||
s = (s + (s >> 16)) & 0x3f;
|
s = (s + (s >> 16)) & 0x3f;
|
||||||
|
|
||||||
/* normalize divisor and dividend */
|
if (s > 0) {
|
||||||
v.ll <<= s;
|
/* normalize divisor and dividend */
|
||||||
c1.ll = (c1.ll << s) | ((c0.l.high >> (32 - s)) & (-s >> 31));
|
v.ll <<= s;
|
||||||
c0.ll <<= s;
|
c1.ll = (c1.ll << s) | (c0.l.high >> (32 - s));
|
||||||
|
c0.ll <<= s;
|
||||||
|
}
|
||||||
|
|
||||||
q1.ll = c1.ll / v.l.high;
|
q1.ll = c1.ll / v.l.high;
|
||||||
rhat.ll = c1.ll - q1.ll * v.l.high;
|
rhat.ll = c1.ll - q1.ll * v.l.high;
|
||||||
|
@ -489,6 +461,11 @@ gst_util_uint64_scale_int64 (guint64 val, guint64 num, guint64 denom)
|
||||||
if (c1.ll >= denom)
|
if (c1.ll >= denom)
|
||||||
goto overflow;
|
goto overflow;
|
||||||
|
|
||||||
|
/* shortcut for division by 1, c1.ll should be 0 because of the
|
||||||
|
* overflow check above. */
|
||||||
|
if (denom == 1)
|
||||||
|
return c0.ll;
|
||||||
|
|
||||||
/* and 128/64 bits division, result fits 64 bits */
|
/* and 128/64 bits division, result fits 64 bits */
|
||||||
if (denom <= G_MAXUINT32) {
|
if (denom <= G_MAXUINT32) {
|
||||||
guint32 den = (guint32) denom;
|
guint32 den = (guint32) denom;
|
||||||
|
@ -501,10 +478,7 @@ gst_util_uint64_scale_int64 (guint64 val, guint64 num, guint64 denom)
|
||||||
result.l.high = c1.ll / den;
|
result.l.high = c1.ll / den;
|
||||||
result.l.low = c0.ll / den;
|
result.l.low = c0.ll / den;
|
||||||
} else {
|
} else {
|
||||||
if (TRUE)
|
result.ll = gst_util_div128_64 (c1, c0, denom);
|
||||||
result.ll = gst_util_div128_64_iterate (c1, c0, denom);
|
|
||||||
else
|
|
||||||
result.ll = gst_util_div128_64 (c1, c0, denom);
|
|
||||||
}
|
}
|
||||||
return result.ll;
|
return result.ll;
|
||||||
|
|
||||||
|
@ -534,6 +508,9 @@ gst_util_uint64_scale (guint64 val, guint64 num, guint64 denom)
|
||||||
if (num == 0)
|
if (num == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (num == 1 && denom == 1)
|
||||||
|
return val;
|
||||||
|
|
||||||
/* if the denom is high, we need to do a 64 muldiv */
|
/* if the denom is high, we need to do a 64 muldiv */
|
||||||
if (denom > G_MAXINT32)
|
if (denom > G_MAXINT32)
|
||||||
goto do_int64;
|
goto do_int64;
|
||||||
|
@ -581,6 +558,9 @@ gst_util_uint64_scale_int (guint64 val, gint num, gint denom)
|
||||||
if (num == 0)
|
if (num == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (num == 1 && denom == 1)
|
||||||
|
return val;
|
||||||
|
|
||||||
if (val <= G_MAXUINT32) {
|
if (val <= G_MAXUINT32) {
|
||||||
/* simple case */
|
/* simple case */
|
||||||
result.ll = val * num / denom;
|
result.ll = val * num / denom;
|
||||||
|
|
|
@ -236,19 +236,35 @@ GST_START_TEST (test_math_scale_uint64)
|
||||||
|
|
||||||
GST_START_TEST (test_math_scale_random)
|
GST_START_TEST (test_math_scale_random)
|
||||||
{
|
{
|
||||||
guint64 val, num, denom, res;;
|
guint64 val, num, denom, res;
|
||||||
GRand *rand;
|
GRand *rand;
|
||||||
gint i;
|
gint i;
|
||||||
|
|
||||||
rand = g_rand_new ();
|
rand = g_rand_new ();
|
||||||
|
|
||||||
i = 1000;
|
i = 1000000;
|
||||||
while (i--) {
|
while (i--) {
|
||||||
|
guint64 check, diff;
|
||||||
|
|
||||||
val = ((guint64) g_rand_int (rand)) << 32 | g_rand_int (rand);
|
val = ((guint64) g_rand_int (rand)) << 32 | g_rand_int (rand);
|
||||||
num = ((guint64) g_rand_int (rand)) << 32 | g_rand_int (rand);
|
num = ((guint64) g_rand_int (rand)) << 32 | g_rand_int (rand);
|
||||||
denom = ((guint64) g_rand_int (rand)) << 32 | g_rand_int (rand);
|
denom = ((guint64) g_rand_int (rand)) << 32 | g_rand_int (rand);
|
||||||
|
|
||||||
res = gst_util_uint64_scale (val, num, denom);
|
res = gst_util_uint64_scale (val, num, denom);
|
||||||
|
check = gst_gdouble_to_guint64 (gst_guint64_to_gdouble (val) *
|
||||||
|
gst_guint64_to_gdouble (num) / gst_guint64_to_gdouble (denom));
|
||||||
|
|
||||||
|
if (res < G_MAXUINT64 && check < G_MAXUINT64) {
|
||||||
|
if (res > check)
|
||||||
|
diff = res - check;
|
||||||
|
else
|
||||||
|
diff = check - res;
|
||||||
|
|
||||||
|
/* some arbitrary value, really.. someone do the proper math to get
|
||||||
|
* the upper bound */
|
||||||
|
if (diff > 20000)
|
||||||
|
fail_if (diff > 20000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
g_rand_free (rand);
|
g_rand_free (rand);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue