comparison utils.c @ 1549:5e643dd7e889 libavcodec

use continued fractions to approximate a fraction if its numerator or denominator is too large
author michael
date Mon, 20 Oct 2003 22:33:53 +0000
parents dd544554ed42
children ece0ad14a35d
comparison
equal deleted inserted replaced
1548:dd544554ed42 1549:5e643dd7e889
682 } 682 }
683 } 683 }
684 684
685 int av_reduce(int *dst_nom, int *dst_den, int64_t nom, int64_t den, int64_t max){ 685 int av_reduce(int *dst_nom, int *dst_den, int64_t nom, int64_t den, int64_t max){
686 int exact=1, sign=0; 686 int exact=1, sign=0;
687 int64_t gcd, larger; 687 int64_t gcd;
688 688
689 assert(den != 0); 689 assert(den != 0);
690 690
691 if(den < 0){ 691 if(den < 0){
692 den= -den; 692 den= -den;
696 if(nom < 0){ 696 if(nom < 0){
697 nom= -nom; 697 nom= -nom;
698 sign= 1; 698 sign= 1;
699 } 699 }
700 700
701 for(;;){ //note is executed 1 or 2 times 701 gcd = ff_gcd(nom, den);
702 gcd = ff_gcd(nom, den); 702 nom /= gcd;
703 nom /= gcd; 703 den /= gcd;
704 den /= gcd; 704
705 705 if(nom > max || den > max){
706 larger= FFMAX(nom, den); 706 AVRational a0={0,1}, a1={1,0};
707 707 exact=0;
708 if(larger > max){ 708
709 int64_t div= (larger + max - 1) / max; 709 for(;;){
710 nom = (nom + div/2)/div; 710 int64_t x= nom / den;
711 den = (den + div/2)/div; 711 int64_t a2n= x*a1.num + a0.num;
712 exact=0; 712 int64_t a2d= x*a1.den + a0.den;
713 }else 713
714 break; 714 if(a2n > max || a2d > max) break;
715 } 715
716 nom %= den;
717
718 a0= a1;
719 a1= (AVRational){a2n, a2d};
720 if(nom==0) break;
721 x= nom; nom=den; den=x;
722 }
723 nom= a1.num;
724 den= a1.den;
725 }
726
727 assert(ff_gcd(nom, den) == 1);
716 728
717 if(sign) nom= -nom; 729 if(sign) nom= -nom;
718 730
719 *dst_nom = nom; 731 *dst_nom = nom;
720 *dst_den = den; 732 *dst_den = den;