mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 18:21:04 +00:00
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.
This commit is contained in:
parent
e4257e8d5f
commit
0ed24bc50e
5 changed files with 108 additions and 25 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
if (!gst_util_fraction_multiply (n1, d1, n2, d2, &res_n, &res_d))
|
||||
return FALSE;
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue