diff --git a/girs/Gst-1.0.gir b/girs/Gst-1.0.gir index f82f08d4cf..0b7860104c 100644 --- a/girs/Gst-1.0.gir +++ b/girs/Gst-1.0.gir @@ -53907,6 +53907,35 @@ if the conversion worked or not. + + 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. + + + + + + + + + + + + + non-significative terms (typical value: 8) + + + + + + + Scale @val by the rational number @num / @denom, avoiding overflows and underflows and without loss of precision. diff --git a/subprojects/gstreamer/gst/gstutils.c b/subprojects/gstreamer/gst/gstutils.c index 83c3f485e3..07dd4633d6 100644 --- a/subprojects/gstreamer/gst/gstutils.c +++ b/subprojects/gstreamer/gst/gstutils.c @@ -3669,6 +3669,74 @@ gst_util_greatest_common_divisor_int64 (gint64 a, gint64 b) 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: diff --git a/subprojects/gstreamer/gst/gstutils.h b/subprojects/gstreamer/gst/gstutils.h index 2147b0d080..ee1b91d89f 100644 --- a/subprojects/gstreamer/gst/gstutils.h +++ b/subprojects/gstreamer/gst/gstutils.h @@ -1208,6 +1208,10 @@ gint gst_util_greatest_common_divisor (gint a, gint b); GST_API 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 void gst_util_fraction_to_double (gint src_n, gint src_d, gdouble *dest);