AVPKit
Rational.cpp
1 /*******************************************************************************
2  * Copyright (c) 2024, 2026, Olivier Ayache. All rights reserved.
3  *
4  * This file is part of AVPKit.
5  *
6  * AVPKit is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * AVPKit is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with AVPKit. If not, see <http://www.gnu.org/licenses/>.
18  *******************************************************************************/
19 
20 // for std::numeric_limits
21 #include <limits>
22 
23 #include <com/avpkit/core/Rational.h>
24 
25 namespace com { namespace avpkit { namespace core
26 {
27 
28  Rational :: Rational()
29  {
30  // default to 0 for the value.
31  mRational.den = 1;
32  mRational.num = 0;
33  mInitialized = false;
34  }
35 
36  Rational :: ~Rational()
37  {
38  }
39 
40  void
42  {
43  if (!mInitialized) {
44  (void) reduce(mRational.num,
45  mRational.den,
46  FFMAX(mRational.den, mRational.num));
47  }
48  mInitialized = true;
49  }
50 
51  Rational *
52  Rational :: make(double d)
53  {
54  Rational *result=0;
55  result = Rational::make();
56  if (result) {
57  result->setValue(d);
58  result->init();
59  }
60  return result;
61  }
62 
63  void
65  {
66  if (!mInitialized)
67  mRational = av_d2q(d, 0x7fffffff);
68  }
69 
70  double
72  {
73  return getDouble();
74  }
75 
76  Rational *
77  Rational :: make(AVRational *src)
78  {
79  Rational *result=0;
80  if (src)
81  {
82  result = Rational::make();
83  if (result) {
84  result->mRational = *src;
85  result->init();
86  }
87  }
88  return result;
89  }
90 
91  IRational *
93  {
94  return Rational::make(this);
95  }
96 
97  Rational *
99  {
100  Rational *result=0;
101  if (src)
102  {
103  result = Rational::make();
104  if (result) {
105  result->mRational = src->mRational;
106  result->init();
107  }
108  }
109  return result;
110  }
111  void
113  {
114  if (!mInitialized)
115  mRational.num = num;
116  }
117  void
119  {
120  if (!mInitialized)
121  mRational.den = den;
122  }
123  bool
125  {
126  return mInitialized;
127  }
128  Rational *
129  Rational :: make(int32_t num, int32_t den)
130  {
131  Rational *result=0;
132  result = Rational::make();
133  if (result) {
134  result->setNumerator(num);
135  result->setDenominator(den);
136  result->init();
137  }
138  return result;
139  }
140  int32_t
142  {
143  int32_t result = 0;
144  Rational *arg=dynamic_cast<Rational*>(other);
145  if (arg)
146  result = av_cmp_q(mRational, arg->mRational);
147  return result;
148  }
149 
150  double
152  {
153  double result = 0;
154  // On some runs in Linux calling av_q2d will raise
155  // a FPE instead of returning back NaN or infinity,
156  // so we try to short-circuit that here.
157  if (mRational.den == 0)
158  if (mRational.num == 0)
159  result = std::numeric_limits<double>::quiet_NaN();
160  else
161  result = std::numeric_limits<double>::infinity();
162  else
163  result = av_q2d(mRational);
164  return result;
165  }
166 
167  int32_t
168  Rational :: reduce(int64_t num, int64_t den, int64_t max)
169  {
170  int32_t result = 0;
171  result = av_reduce(&mRational.num, &mRational.den,
172  num, den, max);
173  return result;
174  }
175 
176  IRational *
178  {
179  Rational *result = 0;
180  Rational *arg=dynamic_cast<Rational*>(other);
181  if (arg)
182  {
183  result = Rational::make();
184  if (result)
185  {
186  result->mRational = av_mul_q(this->mRational,
187  arg->mRational);
188  }
189  }
190  return result;
191  }
192 
193  IRational *
195  {
196  Rational *result = 0;
197  Rational *arg=dynamic_cast<Rational*>(other);
198  if (arg)
199  {
200  result = Rational::make();
201  if (result)
202  {
203  result->mRational = av_div_q(this->mRational,
204  arg->mRational);
205  }
206  }
207  return result;
208  }
209 
210  IRational *
212  {
213  Rational *result = 0;
214  Rational *arg=dynamic_cast<Rational*>(other);
215  if (arg)
216  {
217  result = Rational::make();
218  if (result)
219  {
220  result->mRational = av_sub_q(this->mRational,
221  arg->mRational);
222  }
223  }
224  return result;
225  }
226  IRational *
228  {
229  Rational *result = 0;
230  Rational *arg=dynamic_cast<Rational*>(other);
231  if (arg)
232  {
233  result = Rational::make();
234  if (result)
235  {
236  result->mRational = av_add_q(this->mRational,
237  arg->mRational);
238  }
239  }
240  return result;
241  }
242 
243  int64_t
244  Rational :: rescale(int64_t origValue, IRational *origBase)
245  {
246  int64_t retval=origValue;
247  Rational *arg=dynamic_cast<Rational*>(origBase);
248 
249  if (arg)
250  {
251  retval = av_rescale_q(origValue, arg->mRational, this->mRational);
252  }
253  return retval;
254  }
255 
256  int64_t
257  Rational :: rescale(int64_t origValue, IRational *origBase,
258  Rounding rounding)
259  {
260  int64_t retval=origValue;
261  Rational *arg=dynamic_cast<Rational*>(origBase);
262 
263  if (arg)
264  {
265  int64_t b = arg->mRational.num * (int64_t)this->mRational.den;
266  int64_t c = this->mRational.num * (int64_t)arg->mRational.den;
267 
268  retval = av_rescale_rnd(origValue, b,
269  c, (enum AVRounding)rounding);
270  }
271  return retval;
272  }
273 
274  int64_t
275  Rational :: rescale(int64_t srcValue,
276  int32_t dstNumerator,
277  int32_t dstDenominator,
278  int32_t srcNumerator,
279  int32_t srcDenominator,
280  Rounding rounding)
281  {
282  int64_t retval = srcValue;
283  if (!dstNumerator || !dstDenominator ||
284  !srcNumerator || !srcDenominator)
285  return 0;
286 
287  int64_t b = srcNumerator * (int64_t)dstDenominator;
288  int64_t c = dstNumerator * (int64_t)srcDenominator;
289 
290  retval = av_rescale_rnd(srcValue, b,
291  c, (enum AVRounding)rounding);
292 
293  return retval;
294  }
295 
296 }}}
This class wraps represents a Rational number for the AVPKit.
Definition: IRational.h:43
static IRational * make()
Get a new rational that will be set to 0/0.
Definition: IRational.cpp:79
virtual void init()
Marks this object as finalized and immutable.
Definition: Rational.cpp:41
virtual IRational * multiply(IRational *arg)
Multiplies this number by arg.
Definition: Rational.cpp:177
virtual void setDenominator(int32_t value)
Sets the denominator on this object.
Definition: Rational.cpp:118
virtual double getValue()
An alias for getDouble() but matching JavaBean conventions.
Definition: Rational.cpp:71
virtual double getDouble()
Rational to double conversion.
Definition: Rational.cpp:151
virtual int32_t reduce(int64_t num, int64_t den, int64_t max)
Reduce a fraction to it's lowest common denominators.
Definition: Rational.cpp:168
virtual void setValue(double value)
Sets the numerator and denominator on this object by reducing the double to the closest integer numer...
Definition: Rational.cpp:64
virtual IRational * divide(IRational *arg)
Divides this rational by arg.
Definition: Rational.cpp:194
virtual int64_t rescale(int64_t origValue, IRational *origBase)
Takes a value scaled in increments of origBase and gives the equivalent value scaled in terms of this...
Definition: Rational.cpp:244
virtual void setNumerator(int32_t value)
Sets the numerator on this object.
Definition: Rational.cpp:112
virtual IRational * add(IRational *arg)
Adds arg to this rational.
Definition: Rational.cpp:227
virtual int32_t compareTo(IRational *other)
Compare a rational to this rational.
Definition: Rational.cpp:141
virtual bool isFinalized()
Returns true if init() has been called and this object is now considered finalized and immutable.
Definition: Rational.cpp:124
virtual IRational * subtract(IRational *arg)
Subtracts arg from this rational.
Definition: Rational.cpp:211
virtual IRational * copy()
Creates a new IRational object by copying (by value) this object.
Definition: Rational.cpp:92
WARNING: Do not use logging in this class, and do not set any static file variables to values other t...