]> git.sesse.net Git - vlc/commitdiff
* include/vlc_common.h, src/extras/libc.c: added GCD() and vlc_reduce().
authorGildas Bazin <gbazin@videolan.org>
Thu, 9 Sep 2004 13:04:12 +0000 (13:04 +0000)
committerGildas Bazin <gbazin@videolan.org>
Thu, 9 Sep 2004 13:04:12 +0000 (13:04 +0000)
include/vlc_common.h
src/extras/libc.c

index c2f4a32b7e19c2364026fefc727c0da7d79ffdee..fd4972a30a810001537b4b014c55aa9c04b2f39e 100644 (file)
@@ -475,6 +475,12 @@ typedef int ( * vlc_callback_t ) ( vlc_object_t *,      /* variable's object */
 #   define __MIN(a, b)   ( ((a) < (b)) ? (a) : (b) )
 #endif
 
+static int64_t GCD( int64_t a, int64_t b )
+{
+    if( b ) return GCD( b, a % b );
+    else return a;
+}
+
 /* Dynamic array handling: realloc array, move data, increment position */
 #define INSERT_ELEM( p_ar, i_oldsize, i_pos, elem )                           \
     do                                                                        \
@@ -908,6 +914,8 @@ typedef __int64 off_t;
 #   define vlc_lseek NULL
 #endif
 
+VLC_EXPORT( vlc_bool_t, vlc_reduce, ( int *, int *, int64_t, int64_t, int64_t ) );
+
 /* vlc_wraptext (defined in src/extras/libc.c) */
 #define wraptext vlc_wraptext
 VLC_EXPORT( char *, vlc_wraptext, ( const char *, int, vlc_bool_t ) );
index 9ed82925015d6e73418dfcf813403d3227656f5c..42911036679b48ca2c92489b90ac1fe18b5ac202 100644 (file)
@@ -421,3 +421,68 @@ int vlc_iconv_close( vlc_iconv_t cd )
     return 0;
 #endif
 }
+
+/*****************************************************************************
+ * reduce a fraction
+ *   (adapted from libavcodec, author Michael Niedermayer <michaelni@gmx.at>)
+ *****************************************************************************/
+vlc_bool_t vlc_reduce( int *pi_dst_nom, int *pi_dst_den,
+                       int64_t i_nom, int64_t i_den, int64_t i_max )
+{
+    vlc_bool_t b_exact = 1, b_sign = 0;
+    int64_t i_gcd;
+
+    if( i_den == 0 )
+    {
+        i_nom = 0;
+        i_den = 1;
+        return 1;
+    }
+
+    if( i_den < 0 )
+    {
+        i_den = - i_den;
+        i_nom = - i_nom;
+    }
+
+    if( i_nom < 0 )
+    {
+        i_nom = - i_nom;
+        b_sign = 1;
+    }
+
+    i_gcd = GCD( i_nom, i_den );
+    i_nom /= i_gcd;
+    i_den /= i_gcd;
+
+    if( i_nom > i_max || i_den > i_max )
+    {
+        int i_a0_num = 0, i_a0_den = 1, i_a1_num = 1, i_a1_den = 0;
+        b_exact = 0;
+
+        for( ; ; )
+        {
+            int64_t i_x = i_nom / i_den;
+            int64_t i_a2n = i_x * i_a1_num + i_a0_num;
+            int64_t i_a2d = i_x * i_a1_den + i_a0_den;
+
+            if( i_a2n > i_max || i_a2d > i_max ) break;
+
+            i_nom %= i_den;
+
+            i_a0_num = i_a1_num; i_a0_den = i_a1_den;
+            i_a1_num = i_a2n; i_a1_den = i_a2d;
+            if( i_nom == 0 ) break;
+            i_x = i_nom; i_nom = i_den; i_den = i_x;
+        }
+        i_nom = i_a1_num;
+        i_den = i_a1_den;
+    }
+
+    if( b_sign ) i_nom = - i_nom;
+
+    *pi_dst_nom = i_nom;
+    *pi_dst_den = i_den;
+
+    return b_exact;
+}