use continued fractions to approximate a fraction if its numerator or denominator is too large
Originally committed as revision 2405 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
@@ -684,7 +684,7 @@ char av_get_pict_type_char(int pict_type){
|
|||||||
|
|
||||||
int av_reduce(int *dst_nom, int *dst_den, int64_t nom, int64_t den, int64_t max){
|
int av_reduce(int *dst_nom, int *dst_den, int64_t nom, int64_t den, int64_t max){
|
||||||
int exact=1, sign=0;
|
int exact=1, sign=0;
|
||||||
int64_t gcd, larger;
|
int64_t gcd;
|
||||||
|
|
||||||
assert(den != 0);
|
assert(den != 0);
|
||||||
|
|
||||||
@@ -698,22 +698,34 @@ int av_reduce(int *dst_nom, int *dst_den, int64_t nom, int64_t den, int64_t max)
|
|||||||
sign= 1;
|
sign= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(;;){ //note is executed 1 or 2 times
|
gcd = ff_gcd(nom, den);
|
||||||
gcd = ff_gcd(nom, den);
|
nom /= gcd;
|
||||||
nom /= gcd;
|
den /= gcd;
|
||||||
den /= gcd;
|
|
||||||
|
|
||||||
larger= FFMAX(nom, den);
|
if(nom > max || den > max){
|
||||||
|
AVRational a0={0,1}, a1={1,0};
|
||||||
|
exact=0;
|
||||||
|
|
||||||
if(larger > max){
|
for(;;){
|
||||||
int64_t div= (larger + max - 1) / max;
|
int64_t x= nom / den;
|
||||||
nom = (nom + div/2)/div;
|
int64_t a2n= x*a1.num + a0.num;
|
||||||
den = (den + div/2)/div;
|
int64_t a2d= x*a1.den + a0.den;
|
||||||
exact=0;
|
|
||||||
}else
|
if(a2n > max || a2d > max) break;
|
||||||
break;
|
|
||||||
|
nom %= den;
|
||||||
|
|
||||||
|
a0= a1;
|
||||||
|
a1= (AVRational){a2n, a2d};
|
||||||
|
if(nom==0) break;
|
||||||
|
x= nom; nom=den; den=x;
|
||||||
|
}
|
||||||
|
nom= a1.num;
|
||||||
|
den= a1.den;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(ff_gcd(nom, den) == 1);
|
||||||
|
|
||||||
if(sign) nom= -nom;
|
if(sign) nom= -nom;
|
||||||
|
|
||||||
*dst_nom = nom;
|
*dst_nom = nom;
|
||||||
|
|||||||
Reference in New Issue
Block a user