Ring Daemon 16.0.0
Loading...
Searching...
No Matches
rational.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2004-2025 Savoir-faire Linux Inc.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17#pragma once
18
19#include <utility> // std::swap
20#include <cstdlib> // std::abs
21#include <iostream>
22#include <cmath> // std::fmod
23#include <functional> // std::modulus
24#include <ciso646> // and, or ...
25
26extern "C" {
27#include <libavutil/rational.h> // specify conversions for AVRational
28}
29
30namespace jami {
31
36template<typename I>
38{
39public:
40 // Constructors
41 constexpr rational() {} // Zero
42 constexpr rational(I n)
43 : num_(n) {} // Equal to n/1
44 constexpr rational(I n, I d)
45 : num_(n)
46 , den_(d)
47 {
48 reduce();
49 } // General case (n/d)
50
51 // Define conversions to and from AVRational (equivalent)
52 constexpr rational(AVRational r)
53 : num_(r.num)
54 , den_(r.den) {};
55 constexpr operator AVRational() const { return AVRational {(int) num_, (int) den_}; }
56
57 // Normal copy constructors and assignment operators
58
59 // Assignment from I
61 {
62 num_ = n;
63 den_ = 1;
64 return *this;
65 }
66
67 // Assign in place
69 {
70 num_ = n;
71 den_ = d;
72 reduce();
73 return *this;
74 }
75
76 // Representation
77 constexpr I numerator() const { return num_; };
78 constexpr I denominator() const { return den_; };
79
80 template<typename R = double>
81 constexpr R real() const
82 {
83 return num_ / (R) den_;
84 }
85
86 // In addition to the following operators, all of the "obvious" derived
87 // operators are available - see operators.hpp
88
89 // Arithmetic operators
90 constexpr rational operator+(const rational& r) const
91 {
92 return {num_ * r.den_ + r.num_ * den_, den_ * r.den_};
93 }
94 constexpr rational operator-(const rational& r) const
95 {
96 return {num_ * r.den_ - r.num_ * den_, den_ * r.den_};
97 }
98 constexpr rational operator*(const rational& r) const { return {num_ * r.num_, den_ * r.den_}; }
99 constexpr rational operator/(const rational& r) const { return {num_ * r.den_, den_ * r.num_}; }
100
102 {
103 std::swap(*this, *this + r);
104 return *this;
105 }
107 {
108 std::swap(*this, *this - r);
109 return *this;
110 }
112 {
113 num_ *= r.num_;
114 den_ *= r.den_;
115 reduce();
116 return *this;
117 }
119 {
120 num_ *= r.den_;
121 den_ *= r.num_;
122 reduce();
123 return *this;
124 }
125
126 // Arithmetic with integers
128 {
129 num_ += i * den_;
130 return *this;
131 }
133 {
134 num_ -= i * den_;
135 return *this;
136 }
138 {
139 num_ *= i;
140 reduce();
141 return *this;
142 }
144 {
145 den_ *= i;
146 reduce();
147 return *this;
148 }
149
150 // Increment and decrement
152 {
153 num_ += den_;
154 return *this;
155 }
157 {
158 num_ -= den_;
159 return *this;
160 }
161
162 // Operator not
163 constexpr bool operator!() const { return !num_; };
164
165 // Boolean conversion
166 explicit constexpr operator bool() const { return num_; }
167
168 // Comparison operators
169 constexpr bool operator<(const rational& r) const
170 {
171 bool inv = (den_ > 0) != (r.den_ > 0);
172 return inv != (num_ * r.den_ < den_ * r.num_);
173 }
174 constexpr bool operator>(const rational& r) const
175 {
176 bool inv = (den_ > 0) != (r.den_ > 0);
177 return inv != (num_ * r.den_ > den_ * r.num_);
178 }
179 constexpr bool operator==(const rational& r) const { return num_ * r.den_ == den_ * r.num_; }
180 constexpr bool operator!=(const rational& r) const { return num_ * r.den_ != den_ * r.num_; }
181
182 // Comparison with integers
183 constexpr bool operator<(I i) const { return den_ < 0 ? (num_ > i * den_) : (num_ < i * den_); }
184 constexpr bool operator>(I i) const { return den_ < 0 ? (num_ < i * den_) : (num_ > i * den_); }
185 constexpr bool operator==(I i) const { return num_ == i * den_; }
186 constexpr bool operator!=(I i) const { return num_ != i * den_; }
187
188private:
189 I num_ {0};
190 I den_ {1};
191
192 static constexpr I gcd(I a, I b) { return b == (I) 0 ? a : gcd(b, std::modulus<I>()(a, b)); }
193 void reduce()
194 {
195 if (std::is_integral<I>::value) {
196 if (num_ and den_) {
197 auto g = gcd(num_ >= 0 ? num_ : -num_, den_ >= 0 ? den_ : -den_);
198 if (g > (I) 1) {
199 num_ /= g;
200 den_ /= g;
201 }
202 }
203 }
204 }
205};
206
207// Unary operators
208template<typename I>
211{
212 return r;
213}
214template<typename I>
217{
218 return {-r.numerator(), r.denominator()};
219};
220
221// Reversed order operators for - and / between (types convertible to) I and rational
222template<typename I, typename II>
224template<typename I, typename II>
225inline rational<I>
227{
228 return {i * r.denominator(), r.numerator()};
229}
230
231// Absolute value
232template<typename I>
235{
236 return {std::abs(r.numerator()), std::abs(r.denominator())};
237}
238
239// Input and output
240template<typename I>
241std::istream&
242operator>>(std::istream& is, rational<I>& r)
243{
244 char sep;
245 is >> r.num_ >> sep >> r.den_;
246 return is;
247}
248
249template<typename I>
250std::ostream&
251operator<<(std::ostream& os, const rational<I>& r)
252{
253 os << r.numerator() << '/' << r.denominator();
254 return os;
255}
256
257// Type conversion
258template<typename T, typename I>
260
261} // namespace jami
262
263namespace std {
264template<>
265struct modulus<double>
266{
267 double operator()(const double& lhs, const double& rhs) const { return std::fmod(lhs, rhs); }
268};
269} // namespace std
Naive implementation of the boost::rational interface, described here: http://www....
Definition rational.h:38
constexpr bool operator!() const
Definition rational.h:163
constexpr bool operator<(I i) const
Definition rational.h:183
constexpr bool operator>(const rational &r) const
Definition rational.h:174
rational & operator=(I n)
Definition rational.h:60
constexpr rational operator-(const rational &r) const
Definition rational.h:94
constexpr bool operator!=(I i) const
Definition rational.h:186
constexpr bool operator==(const rational &r) const
Definition rational.h:179
constexpr I denominator() const
Definition rational.h:78
constexpr R real() const
Definition rational.h:81
constexpr bool operator!=(const rational &r) const
Definition rational.h:180
constexpr bool operator==(I i) const
Definition rational.h:185
rational & operator*=(I i)
Definition rational.h:137
rational & operator*=(const rational &r)
Definition rational.h:111
constexpr rational operator/(const rational &r) const
Definition rational.h:99
constexpr I numerator() const
Definition rational.h:77
constexpr rational(AVRational r)
Definition rational.h:52
const rational & operator++()
Definition rational.h:151
constexpr bool operator<(const rational &r) const
Definition rational.h:169
constexpr rational()
Definition rational.h:41
rational & operator/=(const rational &r)
Definition rational.h:118
constexpr rational operator+(const rational &r) const
Definition rational.h:90
rational & operator+=(const rational &r)
Definition rational.h:101
constexpr bool operator>(I i) const
Definition rational.h:184
rational & operator/=(I i)
Definition rational.h:143
constexpr rational(I n)
Definition rational.h:42
rational & operator-=(I i)
Definition rational.h:132
const rational & operator--()
Definition rational.h:156
constexpr rational(I n, I d)
Definition rational.h:44
constexpr rational operator*(const rational &r) const
Definition rational.h:98
rational & assign(I n, I d)
Definition rational.h:68
rational & operator+=(I i)
Definition rational.h:127
rational & operator-=(const rational &r)
Definition rational.h:106
rational< I > abs(const rational< I > &r)
Definition rational.h:234
void emitSignal(Args... args)
Definition ring_signal.h:64
rational< I > operator+(const rational< I > &r)
Definition rational.h:210
std::istream & operator>>(std::istream &is, rational< I > &r)
Definition rational.h:242
T rational_cast(const rational< I > &r)
rational< I > operator-(const rational< I > &r)
Definition rational.h:216
rational< I > operator/(II i, const rational< I > &r)
Definition rational.h:226
static std::ostream & operator<<(std::ostream &os, const Account &acc)
Definition account.h:530