From 0ed24bc50e7b21c343bd3660373026d52fe22c58 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 16 Nov 2009 09:49:46 +0100 Subject: [PATCH] utils: API: Add multiplication and addition functions for fractions gst_util_fraction_add() gst_util_fraction_multiply() These work on plain integers instead of GValues to keep the overhead as low as possible. --- docs/gst/gstreamer-sections.txt | 2 + gst/gstutils.c | 93 +++++++++++++++++++++++++++++++++++++++++ gst/gstutils.h | 2 + gst/gstvalue.c | 34 ++++----------- win32/common/libgstreamer.def | 2 + 5 files changed, 108 insertions(+), 25 deletions(-) diff --git a/docs/gst/gstreamer-sections.txt b/docs/gst/gstreamer-sections.txt index 40c4069..6ee8dbc 100644 --- a/docs/gst/gstreamer-sections.txt +++ b/docs/gst/gstreamer-sections.txt @@ -2528,6 +2528,8 @@ gst_util_uint64_scale_int_ceil gst_util_greatest_common_divisor gst_util_fraction_to_double gst_util_double_to_fraction +gst_util_fraction_multiply +gst_util_fraction_add gst_util_seqnum_next gst_util_seqnum_compare gst_util_set_object_arg diff --git a/gst/gstutils.c b/gst/gstutils.c index d12aa9f..ef7b975 100644 --- a/gst/gstutils.c +++ b/gst/gstutils.c @@ -3950,3 +3950,96 @@ gst_util_double_to_fraction (gdouble src, gint * dest_n, gint * dest_d) *dest_n = N; *dest_d = D; } + +/** gst_util_fraction_multiply: + * @a_n: Numerator of first value + * @a_d: Denominator of first value + * @b_n: Numerator of second value + * @b_d: Denominator of second value + * @res_n: Pointer to #gint to hold the result numerator + * @res_d: Pointer to #gint to hold the result denominator + * + * Multiplies the fractions @a_n/@a_d and @b_n/@b_d and stores + * the result in @res_n and @res_d. + * + * Returns: %FALSE on overflow, %TRUE otherwise. + * + * Since: 0.10.26 + */ +gboolean +gst_util_fraction_multiply (gint a_n, gint a_d, gint b_n, gint b_d, + gint * res_n, gint * res_d) +{ + gint gcd; + + g_return_val_if_fail (res_n != NULL, FALSE); + g_return_val_if_fail (res_d != NULL, FALSE); + g_return_val_if_fail (a_d != 0, FALSE); + g_return_val_if_fail (b_d != 0, FALSE); + + gcd = gst_util_greatest_common_divisor (a_n, b_d); + a_n /= gcd; + b_d /= gcd; + gcd = gst_util_greatest_common_divisor (a_d, b_n); + a_d /= gcd; + b_n /= gcd; + + g_return_val_if_fail (a_n == 0 || G_MAXINT / ABS (a_n) >= ABS (b_n), FALSE); + g_return_val_if_fail (G_MAXINT / ABS (a_d) >= ABS (b_d), FALSE); + + *res_n = a_n * b_n; + *res_d = a_d * b_d; + + return TRUE; +} + +/** gst_util_fraction_add: + * @a_n: Numerator of first value + * @a_d: Denominator of first value + * @b_n: Numerator of second value + * @b_d: Denominator of second value + * @res_n: Pointer to #gint to hold the result numerator + * @res_d: Pointer to #gint to hold the result denominator + * + * Adds the fractions @a_n/@a_d and @b_n/@b_d and stores + * the result in @res_n and @res_d. + * + * Returns: %FALSE on overflow, %TRUE otherwise. + * + * Since: 0.10.26 + */ +gboolean +gst_util_fraction_add (gint a_n, gint a_d, gint b_n, gint b_d, gint * res_n, + gint * res_d) +{ + gint gcd; + + g_return_val_if_fail (res_n != NULL, FALSE); + g_return_val_if_fail (res_d != NULL, FALSE); + g_return_val_if_fail (a_d != 0, FALSE); + g_return_val_if_fail (b_d != 0, FALSE); + + if (a_n == 0) { + *res_n = b_n; + *res_d = b_d; + return TRUE; + } + if (b_n == 0) { + *res_n = a_n; + *res_d = a_d; + return TRUE; + } + + g_return_val_if_fail (a_n == 0 || G_MAXINT / ABS (a_n) >= ABS (b_n), FALSE); + g_return_val_if_fail (G_MAXINT / ABS (a_d) >= ABS (b_d), FALSE); + g_return_val_if_fail (G_MAXINT / ABS (a_d) >= ABS (b_d), FALSE); + + *res_n = (a_n * b_d) + (a_d * b_n); + *res_d = a_d * b_d; + + gcd = gst_util_greatest_common_divisor (*res_n, *res_d); + *res_n /= gcd; + *res_d /= gcd; + + return TRUE; +} diff --git a/gst/gstutils.h b/gst/gstutils.h index 4fa4c02..af4e33d 100644 --- a/gst/gstutils.h +++ b/gst/gstutils.h @@ -1169,6 +1169,8 @@ gpointer gst_util_array_binary_search (gpointer array, guint gint gst_util_greatest_common_divisor (gint a, gint b); void gst_util_fraction_to_double (gint src_n, gint src_d, gdouble *dest); void gst_util_double_to_fraction (gdouble src, gint *dest_n, gint *dest_d); +gboolean gst_util_fraction_multiply (gint a_n, gint a_d, gint b_n, gint b_d, gint *res_n, gint *res_d); +gboolean gst_util_fraction_add (gint a_n, gint a_d, gint b_n, gint b_d, gint *res_n, gint *res_d); G_END_DECLS diff --git a/gst/gstvalue.c b/gst/gstvalue.c index 257cff3..f307345 100644 --- a/gst/gstvalue.c +++ b/gst/gstvalue.c @@ -3606,7 +3606,8 @@ gboolean gst_value_fraction_multiply (GValue * product, const GValue * factor1, const GValue * factor2) { - gint gcd, n1, n2, d1, d2; + gint n1, n2, d1, d2; + gint res_n, res_d; g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (factor1), FALSE); g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (factor2), FALSE); @@ -3616,17 +3617,10 @@ gst_value_fraction_multiply (GValue * product, const GValue * factor1, d1 = factor1->data[1].v_int; d2 = factor2->data[1].v_int; - gcd = gst_util_greatest_common_divisor (n1, d2); - n1 /= gcd; - d2 /= gcd; - gcd = gst_util_greatest_common_divisor (n2, d1); - n2 /= gcd; - d1 /= gcd; - - g_return_val_if_fail (n1 == 0 || G_MAXINT / ABS (n1) >= ABS (n2), FALSE); - g_return_val_if_fail (G_MAXINT / ABS (d1) >= ABS (d2), FALSE); + if (!gst_util_fraction_multiply (n1, d1, n2, d2, &res_n, &res_d)) + return FALSE; - gst_value_set_fraction (product, n1 * n2, d1 * d2); + gst_value_set_fraction (product, res_n, res_d); return TRUE; } @@ -3646,6 +3640,7 @@ gst_value_fraction_subtract (GValue * dest, const GValue * minuend, const GValue * subtrahend) { gint n1, n2, d1, d2; + gint res_n, res_d; g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (minuend), FALSE); g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (subtrahend), FALSE); @@ -3655,20 +3650,9 @@ gst_value_fraction_subtract (GValue * dest, d1 = minuend->data[1].v_int; d2 = subtrahend->data[1].v_int; - if (n1 == 0) { - gst_value_set_fraction (dest, -n2, d2); - return TRUE; - } - if (n2 == 0) { - gst_value_set_fraction (dest, n1, d1); - return TRUE; - } - - g_return_val_if_fail (n1 == 0 || G_MAXINT / ABS (n1) >= ABS (d2), FALSE); - g_return_val_if_fail (G_MAXINT / ABS (d1) >= ABS (n2), FALSE); - g_return_val_if_fail (G_MAXINT / ABS (d1) >= ABS (d2), FALSE); - - gst_value_set_fraction (dest, (n1 * d2) - (n2 * d1), d1 * d2); + if (!gst_util_fraction_add (n1, d1, -n2, d2, &res_n, &res_d)) + return FALSE; + gst_value_set_fraction (dest, res_n, res_d); return TRUE; } diff --git a/win32/common/libgstreamer.def b/win32/common/libgstreamer.def index 6e8ede0..d03e866 100644 --- a/win32/common/libgstreamer.def +++ b/win32/common/libgstreamer.def @@ -1058,6 +1058,8 @@ EXPORTS gst_util_array_binary_search gst_util_double_to_fraction gst_util_dump_mem + gst_util_fraction_add + gst_util_fraction_multiply gst_util_fraction_to_double gst_util_gdouble_to_guint64 gst_util_get_timestamp -- 2.7.4