ffmpeg / libavutil / rational.c @ 5d6e4c16
History  View  Annotate  Download (4.44 KB)
1 
/*


2 
* rational numbers

3 
* Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>

4 
*

5 
* This file is part of FFmpeg.

6 
*

7 
* FFmpeg is free software; you can redistribute it and/or

8 
* modify it under the terms of the GNU Lesser General Public

9 
* License as published by the Free Software Foundation; either

10 
* version 2.1 of the License, or (at your option) any later version.

11 
*

12 
* FFmpeg is distributed in the hope that it will be useful,

13 
* but WITHOUT ANY WARRANTY; without even the implied warranty of

14 
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU

15 
* Lesser General Public License for more details.

16 
*

17 
* You should have received a copy of the GNU Lesser General Public

18 
* License along with FFmpeg; if not, write to the Free Software

19 
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 021101301 USA

20 
*/

21  
22 
/**

23 
* @file

24 
* rational numbers

25 
* @author Michael Niedermayer <michaelni@gmx.at>

26 
*/

27  
28 
#include "avassert.h" 
29 
//#include <math.h>

30 
#include <limits.h> 
31  
32 
#include "common.h" 
33 
#include "mathematics.h" 
34 
#include "rational.h" 
35  
36 
int av_reduce(int *dst_num, int *dst_den, int64_t num, int64_t den, int64_t max){ 
37 
AVRational a0={0,1}, a1={1,0}; 
38 
int sign= (num<0) ^ (den<0); 
39 
int64_t gcd= av_gcd(FFABS(num), FFABS(den)); 
40  
41 
if(gcd){

42 
num = FFABS(num)/gcd; 
43 
den = FFABS(den)/gcd; 
44 
} 
45 
if(num<=max && den<=max){

46 
a1= (AVRational){num, den}; 
47 
den=0;

48 
} 
49  
50 
while(den){

51 
uint64_t x = num / den; 
52 
int64_t next_den= num  den*x; 
53 
int64_t a2n= x*a1.num + a0.num; 
54 
int64_t a2d= x*a1.den + a0.den; 
55  
56 
if(a2n > max  a2d > max){

57 
if(a1.num) x= (max  a0.num) / a1.num;

58 
if(a1.den) x= FFMIN(x, (max  a0.den) / a1.den);

59  
60 
if (den*(2*x*a1.den + a0.den) > num*a1.den) 
61 
a1 = (AVRational){x*a1.num + a0.num, x*a1.den + a0.den}; 
62 
break;

63 
} 
64  
65 
a0= a1; 
66 
a1= (AVRational){a2n, a2d}; 
67 
num= den; 
68 
den= next_den; 
69 
} 
70 
av_assert2(av_gcd(a1.num, a1.den) <= 1U);

71  
72 
*dst_num = sign ? a1.num : a1.num; 
73 
*dst_den = a1.den; 
74  
75 
return den==0; 
76 
} 
77  
78 
AVRational av_mul_q(AVRational b, AVRational c){ 
79 
av_reduce(&b.num, &b.den, b.num * (int64_t)c.num, b.den * (int64_t)c.den, INT_MAX); 
80 
return b;

81 
} 
82  
83 
AVRational av_div_q(AVRational b, AVRational c){ 
84 
return av_mul_q(b, (AVRational){c.den, c.num});

85 
} 
86  
87 
AVRational av_add_q(AVRational b, AVRational c){ 
88 
av_reduce(&b.num, &b.den, b.num * (int64_t)c.den + c.num * (int64_t)b.den, b.den * (int64_t)c.den, INT_MAX); 
89 
return b;

90 
} 
91  
92 
AVRational av_sub_q(AVRational b, AVRational c){ 
93 
return av_add_q(b, (AVRational){c.num, c.den});

94 
} 
95  
96 
AVRational av_d2q(double d, int max){ 
97 
AVRational a; 
98 
#define LOG2 0.69314718055994530941723212145817656807550013436025 
99 
int exponent;

100 
int64_t den; 
101 
if (isnan(d))

102 
return (AVRational){0,0}; 
103 
if (isinf(d))

104 
return (AVRational){ d<0 ? 1:1, 0 }; 
105 
exponent = FFMAX( (int)(log(fabs(d) + 1e20)/LOG2), 0); 
106 
den = 1LL << (61  exponent); 
107 
av_reduce(&a.num, &a.den, (int64_t)(d * den + 0.5), den, max); 
108  
109 
return a;

110 
} 
111  
112 
int av_nearer_q(AVRational q, AVRational q1, AVRational q2)

113 
{ 
114 
/* n/d is q, a/b is the median between q1 and q2 */

115 
int64_t a = q1.num * (int64_t)q2.den + q2.num * (int64_t)q1.den; 
116 
int64_t b = 2 * (int64_t)q1.den * q2.den;

117  
118 
/* rnd_up(a*d/b) > n => a*d/b > n */

119 
int64_t x_up = av_rescale_rnd(a, q.den, b, AV_ROUND_UP); 
120  
121 
/* rnd_down(a*d/b) < n => a*d/b < n */

122 
int64_t x_down = av_rescale_rnd(a, q.den, b, AV_ROUND_DOWN); 
123  
124 
return ((x_up > q.num)  (x_down < q.num)) * av_cmp_q(q2, q1);

125 
} 
126  
127 
int av_find_nearest_q_idx(AVRational q, const AVRational* q_list) 
128 
{ 
129 
int i, nearest_q_idx = 0; 
130 
for(i=0; q_list[i].den; i++) 
131 
if (av_nearer_q(q, q_list[i], q_list[nearest_q_idx]) > 0) 
132 
nearest_q_idx = i; 
133  
134 
return nearest_q_idx;

135 
} 
136  
137 
#ifdef TEST

138 
main(){ 
139 
AVRational a,b; 
140 
for(a.num=2; a.num<=2; a.num++){ 
141 
for(a.den=2; a.den<=2; a.den++){ 
142 
for(b.num=2; b.num<=2; b.num++){ 
143 
for(b.den=2; b.den<=2; b.den++){ 
144 
int c= av_cmp_q(a,b);

145 
double d= av_q2d(a) == av_q2d(b) ? 0 : (av_q2d(a)  av_q2d(b)); 
146 
if(d>0) d=1; 
147 
else if(d<0) d=1; 
148 
else if(d != d) d= INT_MIN; 
149 
if(c!=d) av_log(0, AV_LOG_ERROR, "%d/%d %d/%d, %d %f\n", a.num, a.den, b.num, b.den, c,d); 
150 
} 
151 
} 
152 
} 
153 
} 
154 
} 
155 
#endif
