mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 00:36:51 +00:00
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:
parent
395e0c3925
commit
1528ab2e7a
3 changed files with 101 additions and 0 deletions
|
@ -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.
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue