mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 12:11:13 +00:00
utils: Add gst_util_fraction_compare() to compare fractions
And use it for the fraction comparisons in gstvalue.c instead of using comparisons by first converting the fractions to double. Should fix bug #628174. API: gst_util_fraction_compare()
This commit is contained in:
parent
8a20878535
commit
8ca48752fb
3 changed files with 70 additions and 22 deletions
|
@ -4196,3 +4196,51 @@ gst_util_fraction_add (gint a_n, gint a_d, gint b_n, gint b_d, gint * res_n,
|
|||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_util_fraction_compare:
|
||||
* @a_n: Numerator of first value
|
||||
* @a_d: Denominator of first value
|
||||
* @b_n: Numerator of second value
|
||||
* @b_d: Denominator of second value
|
||||
*
|
||||
* Compares the fractions @a_n/@a_d and @b_n/@b_d and returns
|
||||
* -1 if a < b, 0 if a = b and 1 if a > b.
|
||||
*
|
||||
* Returns: -1 if a < b; 0 if a = b; 1 if a > b.
|
||||
*
|
||||
* Since: 0.10.31
|
||||
*/
|
||||
gint
|
||||
gst_util_fraction_compare (gint a_n, gint a_d, gint b_n, gint b_d)
|
||||
{
|
||||
gint64 new_num_1;
|
||||
gint64 new_num_2;
|
||||
gint gcd;
|
||||
|
||||
g_return_val_if_fail (a_d == 0 || b_d == 0, 0);
|
||||
|
||||
/* Simplify */
|
||||
gcd = gst_util_greatest_common_divisor (a_n, a_d);
|
||||
a_n /= gcd;
|
||||
a_d /= gcd;
|
||||
|
||||
gcd = gst_util_greatest_common_divisor (b_n, b_d);
|
||||
b_n /= gcd;
|
||||
b_d /= gcd;
|
||||
|
||||
/* fractions are reduced when set, so we can quickly see if they're equal */
|
||||
if (a_n == b_n && a_d == b_d)
|
||||
return 0;
|
||||
|
||||
/* extend to 64 bits */
|
||||
new_num_1 = ((gint64) a_n) * b_d;
|
||||
new_num_2 = ((gint64) b_n) * a_d;
|
||||
if (new_num_1 < new_num_2)
|
||||
return -1;
|
||||
if (new_num_1 > new_num_2)
|
||||
return 1;
|
||||
|
||||
/* Should not happen because a_d and b_d are not 0 */
|
||||
g_return_val_if_reached (0);
|
||||
}
|
||||
|
|
|
@ -1172,6 +1172,7 @@ 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);
|
||||
gint gst_util_fraction_compare (gint a_n, gint a_d, gint b_n, gint b_d);
|
||||
|
||||
|
||||
/* sink message event
|
||||
|
|
|
@ -1106,10 +1106,9 @@ gst_value_collect_fraction_range (GValue * value, guint n_collect_values,
|
|||
if (collect_values[3].v_int == 0)
|
||||
return g_strdup_printf ("passed '0' as second denominator for `%s'",
|
||||
G_VALUE_TYPE_NAME (value));
|
||||
if ((((gdouble) collect_values[0].v_int) /
|
||||
((gdouble) collect_values[1].v_int)) >=
|
||||
(((gdouble) collect_values[2].v_int) /
|
||||
((gdouble) collect_values[3].v_int)))
|
||||
if (gst_util_fraction_compare (collect_values[0].v_int,
|
||||
collect_values[1].v_int, collect_values[2].v_int,
|
||||
collect_values[3].v_int) >= 0)
|
||||
return g_strdup_printf ("range start is not smaller than end for `%s'",
|
||||
G_VALUE_TYPE_NAME (value));
|
||||
|
||||
|
@ -1175,9 +1174,8 @@ gst_value_set_fraction_range (GValue * value, const GValue * start,
|
|||
g_return_if_fail (GST_VALUE_HOLDS_FRACTION_RANGE (value));
|
||||
g_return_if_fail (GST_VALUE_HOLDS_FRACTION (start));
|
||||
g_return_if_fail (GST_VALUE_HOLDS_FRACTION (end));
|
||||
g_return_if_fail (((gdouble) start->data[0].v_int) /
|
||||
((gdouble) start->data[1].v_int) <
|
||||
((gdouble) end->data[0].v_int) / ((gdouble) end->data[1].v_int));
|
||||
g_return_if_fail (gst_util_fraction_compare (start->data[0].v_int,
|
||||
start->data[1].v_int, end->data[0].v_int, end->data[1].v_int) < 0);
|
||||
|
||||
vals = (GValue *) value->data[0].v_pointer;
|
||||
if (vals == NULL) {
|
||||
|
@ -1210,9 +1208,8 @@ gst_value_set_fraction_range_full (GValue * value,
|
|||
g_return_if_fail (value != NULL);
|
||||
g_return_if_fail (denominator_start != 0);
|
||||
g_return_if_fail (denominator_end != 0);
|
||||
g_return_if_fail (((gdouble) numerator_start) /
|
||||
((gdouble) denominator_start) <
|
||||
((gdouble) numerator_end) / ((gdouble) denominator_end));
|
||||
g_return_if_fail (gst_util_fraction_compare (numerator_start,
|
||||
denominator_start, numerator_end, denominator_end) < 0);
|
||||
|
||||
g_value_init (&start, GST_TYPE_FRACTION);
|
||||
g_value_init (&end, GST_TYPE_FRACTION);
|
||||
|
@ -3910,9 +3907,7 @@ gst_value_compare_fraction (const GValue * value1, const GValue * value2)
|
|||
{
|
||||
gint n1, n2;
|
||||
gint d1, d2;
|
||||
|
||||
gint64 new_num_1;
|
||||
gint64 new_num_2;
|
||||
gint ret;
|
||||
|
||||
n1 = value1->data[0].v_int;
|
||||
n2 = value2->data[0].v_int;
|
||||
|
@ -3923,18 +3918,22 @@ gst_value_compare_fraction (const GValue * value1, const GValue * value2)
|
|||
if (n1 == n2 && d1 == d2)
|
||||
return GST_VALUE_EQUAL;
|
||||
|
||||
/* extend to 64 bits */
|
||||
new_num_1 = ((gint64) n1) * d2;
|
||||
new_num_2 = ((gint64) n2) * d1;
|
||||
if (new_num_1 < new_num_2)
|
||||
if (d1 == 0 && d2 == 0)
|
||||
return GST_VALUE_UNORDERED;
|
||||
else if (d1 == 0)
|
||||
return GST_VALUE_GREATER_THAN;
|
||||
else if (d2 == 0)
|
||||
return GST_VALUE_LESS_THAN;
|
||||
if (new_num_1 > new_num_2)
|
||||
|
||||
ret = gst_util_fraction_compare (n1, d1, n2, d2);
|
||||
if (ret == -1)
|
||||
return GST_VALUE_LESS_THAN;
|
||||
else if (ret == 1)
|
||||
return GST_VALUE_GREATER_THAN;
|
||||
|
||||
/* new_num_1 == new_num_2 implies that both denominators must have
|
||||
* been 0, beause otherwise simplification would have caught the
|
||||
* equivalence */
|
||||
return GST_VALUE_UNORDERED;
|
||||
/* Equality can't happen here because we check for that
|
||||
* first already */
|
||||
g_return_val_if_reached (GST_VALUE_UNORDERED);
|
||||
}
|
||||
|
||||
/*********
|
||||
|
|
Loading…
Reference in a new issue