gstreamer: gst-utils: add gst_util_simplify_fraction

We add the gst_util_simplify_fraction function to be able to convert
fractions such as 333333/10000000 to 1/30.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1304>
This commit is contained in:
Michael Grzeschik 2023-03-08 01:09:42 +01:00 committed by GStreamer Marge Bot
parent 395e0c3925
commit 1528ab2e7a
3 changed files with 101 additions and 0 deletions

View file

@ -53907,6 +53907,35 @@ if the conversion worked or not.</doc>
</parameter> </parameter>
</parameters> </parameters>
</function> </function>
<function name="util_simplify_fraction" c:identifier="gst_util_simplify_fraction" version="1.24">
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstutils.c">Calculates the simpler representation of @a and @b.
Simplify a fraction using a simple continued fraction decomposition.
The idea here is to convert fractions such as 333333/10000000 to 1/30
using 32 bit arithmetic only. The algorithm is not perfect and relies
upon two arbitrary parameters to remove non-significative terms from
the simple continued fraction decomposition. Using 8 and 333 for
n_terms and threshold respectively seems to give nice results.</doc>
<source-position filename="../subprojects/gstreamer/gst/gstutils.h"/>
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
</return-value>
<parameters>
<parameter name="numerator" transfer-ownership="none">
<type name="gint" c:type="gint*"/>
</parameter>
<parameter name="denominator" transfer-ownership="none">
<type name="gint" c:type="gint*"/>
</parameter>
<parameter name="n_terms" transfer-ownership="none">
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstutils.c">non-significative terms (typical value: 8)</doc>
<type name="guint" c:type="guint"/>
</parameter>
<parameter name="threshold" transfer-ownership="none">
<type name="guint" c:type="guint"/>
</parameter>
</parameters>
</function>
<function name="util_uint64_scale" c:identifier="gst_util_uint64_scale"> <function name="util_uint64_scale" c:identifier="gst_util_uint64_scale">
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstutils.c">Scale @val by the rational number @num / @denom, avoiding overflows and <doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstutils.c">Scale @val by the rational number @num / @denom, avoiding overflows and
underflows and without loss of precision. underflows and without loss of precision.

View file

@ -3669,6 +3669,74 @@ gst_util_greatest_common_divisor_int64 (gint64 a, gint64 b)
return ABS (a); return ABS (a);
} }
/**
* gst_util_simplify_fraction:
* @a: First value as #gint
* @b: Second value as #gint
* @n_terms: non-significative terms (typical value: 8)
* @threashold: threshold (typical value: 333)
*
* Calculates the simpler representation of @a and @b.
*
* Simplify a fraction using a simple continued fraction decomposition.
* The idea here is to convert fractions such as 333333/10000000 to 1/30
* using 32 bit arithmetic only. The algorithm is not perfect and relies
* upon two arbitrary parameters to remove non-significative terms from
* the simple continued fraction decomposition. Using 8 and 333 for
* n_terms and threshold respectively seems to give nice results.
*
* Returns: simple representation of @a and @b
*
* Since: 1.24
*/
void
gst_util_simplify_fraction (gint * numerator, gint * denominator,
guint n_terms, guint threshold)
{
guint *an;
guint x, y, r;
guint i, n;
an = g_malloc_n (n_terms, sizeof (*an));
if (an == NULL)
return;
/*
* Convert the fraction to a simple continued fraction. See
* https://en.wikipedia.org/wiki/Continued_fraction
* Stop if the current term is bigger than or equal to the given
* threshold.
*/
x = *numerator;
y = *denominator;
for (n = 0; n < n_terms && y != 0; ++n) {
an[n] = x / y;
if (an[n] >= threshold) {
if (n < 2)
n++;
break;
}
r = x - an[n] * y;
x = y;
y = r;
}
/* Expand the simple continued fraction back to an integer fraction. */
x = 0;
y = 1;
for (i = n; i > 0; --i) {
r = y;
y = an[i - 1] * y + x;
x = r;
}
*numerator = y;
*denominator = x;
g_free (an);
}
/** /**
* gst_util_fraction_to_double: * gst_util_fraction_to_double:

View file

@ -1208,6 +1208,10 @@ gint gst_util_greatest_common_divisor (gint a, gint b);
GST_API GST_API
gint64 gst_util_greatest_common_divisor_int64 (gint64 a, gint64 b); gint64 gst_util_greatest_common_divisor_int64 (gint64 a, gint64 b);
GST_API
void gst_util_simplify_fraction (gint *numerator, gint *denominator,
guint n_terms, guint threshold);
GST_API GST_API
void gst_util_fraction_to_double (gint src_n, gint src_d, gdouble *dest); void gst_util_fraction_to_double (gint src_n, gint src_d, gdouble *dest);