Commit fbf5f16d authored by Wim Taymans's avatar Wim Taymans

check/gst/gstutils.c: Added test for scaling.

Original commit message from CVS:
* check/gst/gstutils.c: (GST_START_TEST), (gst_utils_suite):
Added test for scaling.

* gst/gstclock.h:
Small doc fix.

* gst/gstutils.c: (gst_util_uint64_scale_int):
Implemented high precision scaling code.
parent 9cd16433
2005-11-24 Wim Taymans <wim@fluendo.com>
* check/gst/gstutils.c: (GST_START_TEST), (gst_utils_suite):
Added test for scaling.
* gst/gstclock.h:
Small doc fix.
* gst/gstutils.c: (gst_util_uint64_scale_int):
Implemented high precision scaling code.
2005-11-24 Stefan Kost <ensonic@users.sf.net>
* gst/gstinfo.h:
......
......@@ -167,6 +167,37 @@ GST_START_TEST (test_buffer_probe_once)
g_assert (n_data_probes_once == 1); /* let's hit it and quit!!! */
} GST_END_TEST;
GST_START_TEST (test_math_scale)
{
fail_if (gst_util_uint64_scale_int (1, 1, 1) != 1);
fail_if (gst_util_uint64_scale_int (10, 10, 1) != 100);
fail_if (gst_util_uint64_scale_int (10, 10, 2) != 50);
fail_if (gst_util_uint64_scale_int (0, 10, 2) != 0);
fail_if (gst_util_uint64_scale_int (0, 0, 2) != 0);
fail_if (gst_util_uint64_scale_int (G_MAXUINT32, 5, 1) != G_MAXUINT32 * 5LL);
fail_if (gst_util_uint64_scale_int (G_MAXUINT32, 10, 2) != G_MAXUINT32 * 5LL);
fail_if (gst_util_uint64_scale_int (G_MAXUINT32, 1, 5) != G_MAXUINT32 / 5LL);
fail_if (gst_util_uint64_scale_int (G_MAXUINT32, 2, 10) != G_MAXUINT32 / 5LL);
/* not quite overflow */
fail_if (gst_util_uint64_scale_int (G_MAXUINT64 - 1, 10,
10) != G_MAXUINT64 - 1);
fail_if (gst_util_uint64_scale_int (G_MAXUINT64 - 1, G_MAXINT32,
G_MAXINT32) != G_MAXUINT64 - 1);
fail_if (gst_util_uint64_scale_int (G_MAXUINT64 - 100, G_MAXINT32,
G_MAXINT32) != G_MAXUINT64 - 100);
/* overflow */
fail_if (gst_util_uint64_scale_int (G_MAXUINT64 - 1, 10, 1) != G_MAXUINT64);
fail_if (gst_util_uint64_scale_int (G_MAXUINT64 - 1, G_MAXINT32,
1) != G_MAXUINT64);
} GST_END_TEST;
Suite *
gst_utils_suite (void)
{
......@@ -176,6 +207,7 @@ gst_utils_suite (void)
suite_add_tcase (s, tc_chain);
tcase_add_test (tc_chain, test_buffer_probe_n_times);
tcase_add_test (tc_chain, test_buffer_probe_once);
tcase_add_test (tc_chain, test_math_scale);
return s;
}
......
......@@ -63,7 +63,7 @@ typedef gint64 GstClockTimeDiff;
/**
* GstClockID:
*
* A datatype to hold the handle to an outstanding async clock callback.
* A datatype to hold the handle to an outstanding sync or async clock callback.
*/
typedef gpointer GstClockID;
......
......@@ -340,6 +340,22 @@ gst_gdouble_to_guint64 (gdouble value)
}
#endif
/* convenience struct for getting high an low uint32 parts of
* a guint64 */
typedef union
{
guint64 ll;
struct
{
#if G_BYTE_ORDER == G_BIG_ENDIAN
guint32 high, low;
#else
guint32 low, high;
#endif
} l;
} GstUInt64;
/**
* gst_util_uint64_scale:
* @val: the number to scale
......@@ -360,19 +376,54 @@ gst_util_uint64_scale (guint64 val, guint64 num, guint64 denom)
/**
* gst_util_uint64_scale_int:
* @val: GstClockTime to scale.
* @val: guint64 (such as a #GstClockTime) to scale.
* @num: numerator of the scale factor.
* @denom: denominator of the scale factor.
*
* Scale a clocktime by a factor expressed as a fraction (num/denom), avoiding
* Scale a guint64 by a factor expressed as a fraction (num/denom), avoiding
* overflows and loss of precision.
*
* @num and @denom must be positive integers. @denom cannot be 0.
*
* Returns: @val * @num / @denom, avoiding overflow and loss of precision
*/
guint64
gst_util_uint64_scale_int (guint64 val, gint num, gint denom)
{
return val * num / denom;
GstUInt64 result;
g_return_val_if_fail (denom > 0, G_MAXUINT64);
g_return_val_if_fail (num >= 0, G_MAXUINT64);
if (val <= G_MAXUINT32) {
/* simple case */
result.ll = val * num / denom;
} else {
GstUInt64 gval, low, high, temp;
/* do 96 bits mult/div */
gval.ll = val;
low.ll = ((guint64) gval.l.low) * num;
high.ll = ((guint64) gval.l.high) * num + (low.l.high);
result.ll = (high.ll / denom);
temp.l.high = (high.ll % denom);
temp.l.low = (low.l.low);
temp.ll /= denom;
/* avoid overflow */
if (result.ll + temp.l.high > G_MAXUINT32)
goto overflow;
result.l.high = result.l.low;
result.l.low = 0;
result.ll += temp.ll;
}
return result.ll;
overflow:
{
return G_MAXUINT64;
}
}
/* -----------------------------------------------------
......
......@@ -167,6 +167,37 @@ GST_START_TEST (test_buffer_probe_once)
g_assert (n_data_probes_once == 1); /* let's hit it and quit!!! */
} GST_END_TEST;
GST_START_TEST (test_math_scale)
{
fail_if (gst_util_uint64_scale_int (1, 1, 1) != 1);
fail_if (gst_util_uint64_scale_int (10, 10, 1) != 100);
fail_if (gst_util_uint64_scale_int (10, 10, 2) != 50);
fail_if (gst_util_uint64_scale_int (0, 10, 2) != 0);
fail_if (gst_util_uint64_scale_int (0, 0, 2) != 0);
fail_if (gst_util_uint64_scale_int (G_MAXUINT32, 5, 1) != G_MAXUINT32 * 5LL);
fail_if (gst_util_uint64_scale_int (G_MAXUINT32, 10, 2) != G_MAXUINT32 * 5LL);
fail_if (gst_util_uint64_scale_int (G_MAXUINT32, 1, 5) != G_MAXUINT32 / 5LL);
fail_if (gst_util_uint64_scale_int (G_MAXUINT32, 2, 10) != G_MAXUINT32 / 5LL);
/* not quite overflow */
fail_if (gst_util_uint64_scale_int (G_MAXUINT64 - 1, 10,
10) != G_MAXUINT64 - 1);
fail_if (gst_util_uint64_scale_int (G_MAXUINT64 - 1, G_MAXINT32,
G_MAXINT32) != G_MAXUINT64 - 1);
fail_if (gst_util_uint64_scale_int (G_MAXUINT64 - 100, G_MAXINT32,
G_MAXINT32) != G_MAXUINT64 - 100);
/* overflow */
fail_if (gst_util_uint64_scale_int (G_MAXUINT64 - 1, 10, 1) != G_MAXUINT64);
fail_if (gst_util_uint64_scale_int (G_MAXUINT64 - 1, G_MAXINT32,
1) != G_MAXUINT64);
} GST_END_TEST;
Suite *
gst_utils_suite (void)
{
......@@ -176,6 +207,7 @@ gst_utils_suite (void)
suite_add_tcase (s, tc_chain);
tcase_add_test (tc_chain, test_buffer_probe_n_times);
tcase_add_test (tc_chain, test_buffer_probe_once);
tcase_add_test (tc_chain, test_math_scale);
return s;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment