Searching...
No Matches
rational.h
Go to the documentation of this file.
1
6#ifndef SYMENGINE_RATIONAL_H
7#define SYMENGINE_RATIONAL_H
8
10#include <symengine/symengine_exception.h>
11
12namespace SymEngine
13{
15class Rational : public Number
16{
17private:
19 rational_class i;
20
21public:
24 Rational(rational_class &&_i) : i(std::move(_i))
25 {
26 SYMENGINE_ASSIGN_TYPEID()
27 }
31 static RCP<const Number> from_mpq(const rational_class &i);
32 static RCP<const Number> from_mpq(rational_class &&i);
34 hash_t __hash__() const override;
39 bool __eq__(const Basic &o) const override;
40 int compare(const Basic &o) const override;
42 bool is_canonical(const rational_class &i) const;
43
47 static RCP<const Number> from_two_ints(const Integer &n, const Integer &d);
48 static RCP<const Number> from_two_ints(const long n, const long d);
50 inline const rational_class &as_rational_class() const
51 {
52 return this->i;
53 }
55 bool is_zero() const override
56 {
57 return this->i == 0;
58 }
60 bool is_one() const override
61 {
62 return this->i == 1;
63 }
65 bool is_minus_one() const override
66 {
67 return this->i == -1;
68 }
70 inline bool is_int() const
71 {
72 return this->i == 1;
73 }
75 inline bool is_positive() const override
76 {
77 return i > 0;
78 }
80 inline bool is_negative() const override
81 {
82 return i < 0;
83 }
85 // False is returned because a rational cannot have an imaginary part
86 inline bool is_complex() const override
87 {
88 return false;
89 }
90
92 inline RCP<const Rational> neg() const
93 {
95 }
96
97 bool is_perfect_power(bool is_expected = false) const override;
98 // \return true if there is a exact nth root of self.
99 bool nth_root(const Ptr<RCP<const Number>> &,
100 unsigned long n) const override;
101
105 inline RCP<const Number> addrat(const Rational &other) const
106 {
107 return from_mpq(this->i + other.i);
108 }
112 inline RCP<const Number> addrat(const Integer &other) const
113 {
114 return from_mpq(this->i + other.as_integer_class());
115 }
119 inline RCP<const Number> subrat(const Rational &other) const
120 {
121 return from_mpq(this->i - other.i);
122 }
126 inline RCP<const Number> subrat(const Integer &other) const
127 {
128 return from_mpq(this->i - other.as_integer_class());
129 }
130 inline RCP<const Number> rsubrat(const Integer &other) const
131 {
132 return from_mpq(other.as_integer_class() - this->i);
133 }
137 inline RCP<const Number> mulrat(const Rational &other) const
138 {
139 return from_mpq(this->i * other.i);
140 }
144 inline RCP<const Number> mulrat(const Integer &other) const
145 {
146 return from_mpq(this->i * other.as_integer_class());
147 }
151 inline RCP<const Number> divrat(const Rational &other) const
152 {
153 if (other.i == 0) {
154 if (this->i == 0) {
155 return Nan;
156 } else {
157 return ComplexInf;
158 }
159 } else {
160 return from_mpq(this->i / other.i);
161 }
162 }
166 inline RCP<const Number> divrat(const Integer &other) const
167 {
168 if (other.as_integer_class() == 0) {
169 if (this->i == 0) {
170 return Nan;
171 } else {
172 return ComplexInf;
173 }
174 } else {
175 return from_mpq(this->i / other.as_integer_class());
176 }
177 }
178 inline RCP<const Number> rdivrat(const Integer &other) const
179 {
180 if (this->i == 0) {
181 if (other.is_zero()) {
182 return Nan;
183 } else {
184 return ComplexInf;
185 }
186 } else {
187 return from_mpq(other.as_integer_class() / this->i);
188 }
189 }
193 inline RCP<const Number> powrat(const Integer &other) const
194 {
195 bool neg = other.is_negative();
196 integer_class exp_ = other.as_integer_class();
197 if (neg)
198 exp_ = -exp_;
199 if (not mp_fits_ulong_p(exp_))
200 throw SymEngineException("powrat: 'exp' does not fit ulong.");
201 unsigned long exp = mp_get_ui(exp_);
202
203#if SYMENGINE_INTEGER_CLASS == SYMENGINE_BOOSTMP
204 // boost::multiprecision::cpp_rational doesn't provide
205 // non-const references to num and den
206 integer_class num;
207 integer_class den;
208 mp_pow_ui(num, SymEngine::get_num(i), exp);
209 mp_pow_ui(den, SymEngine::get_den(i), exp);
210 rational_class val(num, den);
211#else
212 rational_class val;
213 mp_pow_ui(SymEngine::get_num(val), SymEngine::get_num(i), exp);
214 mp_pow_ui(SymEngine::get_den(val), SymEngine::get_den(i), exp);
215#endif
216
217 // Since 'this' is in canonical form, so is this**other, so we simply
218 // pass val into the constructor directly without canonicalizing:
219 if (not neg) {
221 } else {
222 return Rational::from_mpq(1 / val);
223 }
224 }
228 RCP<const Basic> powrat(const Rational &other) const;
233 RCP<const Basic> rpowrat(const Integer &other) const;
234
236 RCP<const Number> add(const Number &other) const override
237 {
238 if (is_a<Rational>(other)) {
240 } else if (is_a<Integer>(other)) {
242 } else {
244 }
245 };
247 RCP<const Number> sub(const Number &other) const override
248 {
249 if (is_a<Rational>(other)) {
251 } else if (is_a<Integer>(other)) {
253 } else {
254 return other.rsub(*this);
255 }
256 };
258 RCP<const Number> rsub(const Number &other) const override
259 {
260 if (is_a<Integer>(other)) {
261 return rsubrat(down_cast<const Integer &>(other));
262 } else {
263 throw NotImplementedError("Not Implemented");
264 }
265 };
267 RCP<const Number> mul(const Number &other) const override
268 {
269 if (is_a<Rational>(other)) {
271 } else if (is_a<Integer>(other)) {
273 } else {
274 return other.mul(*this);
275 }
276 };
278 RCP<const Number> div(const Number &other) const override
279 {
280 if (is_a<Rational>(other)) {
282 } else if (is_a<Integer>(other)) {
284 } else {
285 return other.rdiv(*this);
286 }
287 };
289 RCP<const Number> rdiv(const Number &other) const override
290 {
291 if (is_a<Integer>(other)) {
292 return rdivrat(down_cast<const Integer &>(other));
293 } else {
294 throw NotImplementedError("Not Implemented");
295 }
296 };
298 RCP<const Number> pow(const Number &other) const override
299 {
300 if (is_a<Integer>(other)) {
302 } else {
303 return other.rpow(*this);
304 }
305 };
306
307 RCP<const Number> rpow(const Number &other) const override
308 {
309 throw NotImplementedError("Not Implemented");
310 };
311
312 RCP<const Integer> get_num() const
313 {
314 return integer(SymEngine::get_num(i));
315 }
316
317 RCP<const Integer> get_den() const
318 {
319 return integer(SymEngine::get_den(i));
320 }
321};
322
324void get_num_den(const Rational &rat, const Ptr<RCP<const Integer>> &num,
325 const Ptr<RCP<const Integer>> &den);
326
328inline RCP<const Number> rational(long n, long d)
329{
330 return Rational::from_two_ints(n, d);
331}
332} // namespace SymEngine
333
334#endif
#define IMPLEMENT_TYPEID(SYMENGINE_ID)
Inline members and functions.
Definition basic.h:340
The lowest unit of symbolic representation.
Definition basic.h:97
Integer Class.
Definition integer.h:19
Rational Class.
Definition rational.h:16
bool is_positive() const override
Definition rational.h:75
RCP< const Basic > rpowrat(const Integer &other) const
Definition rational.cpp:195
static RCP< const Number > from_mpq(const rational_class &i)
Definition rational.cpp:23
bool is_minus_one() const override
Definition rational.h:65
bool is_int() const
Definition rational.h:70
RCP< const Number > divrat(const Integer &other) const
Definition rational.h:166
RCP< const Number > addrat(const Integer &other) const
Definition rational.h:112
hash_t __hash__() const override
Definition rational.cpp:96
RCP< const Number > addrat(const Rational &other) const
Definition rational.h:105
RCP< const Number > mulrat(const Rational &other) const
Definition rational.h:137
int compare(const Basic &o) const override
Definition rational.cpp:115
RCP< const Number > div(const Number &other) const override
Converts the param other appropriately and then calls divrat
Definition rational.h:278
bool is_complex() const override
Definition rational.h:86
rational_class i
i : object of rational_class
Definition rational.h:19
RCP< const Number > mul(const Number &other) const override
Converts the param other appropriately and then calls mulrat
Definition rational.h:267
bool is_zero() const override
Definition rational.h:55
RCP< const Number > rsub(const Number &other) const override
Converts the param other appropriately and then calls rsubrat
Definition rational.h:258
RCP< const Number > powrat(const Integer &other) const
Definition rational.h:193
RCP< const Number > pow(const Number &other) const override
Converts the param other appropriately and then calls powrat
Definition rational.h:298
RCP< const Number > subrat(const Integer &other) const
Definition rational.h:126
const rational_class & as_rational_class() const
Convert to rational_class.
Definition rational.h:50
static RCP< const Number > from_two_ints(const Integer &n, const Integer &d)
Definition rational.cpp:44
RCP< const Number > add(const Number &other) const override
Converts the param other appropriately and then calls addrat
Definition rational.h:236
RCP< const Number > sub(const Number &other) const override
Converts the param other appropriately and then calls subrat
Definition rational.h:247
bool is_canonical(const rational_class &i) const
Definition rational.cpp:8
RCP< const Number > rdiv(const Number &other) const override
Converts the param other appropriately and then calls rdivrat
Definition rational.h:289
RCP< const Number > mulrat(const Integer &other) const
Definition rational.h:144
bool is_one() const override
Definition rational.h:60
RCP< const Rational > neg() const
Definition rational.h:92
bool __eq__(const Basic &o) const override
Definition rational.cpp:106
RCP< const Number > subrat(const Rational &other) const
Definition rational.h:119
bool is_negative() const override
Definition rational.h:80
RCP< const Number > divrat(const Rational &other) const
Definition rational.h:151
T move(T... args)
Main namespace for SymEngine package.
void hash_combine(hash_t &seed, const T &v)
Definition basic-inl.h:95
RCP< const Basic > exp(const RCP< const Basic > &x)
Returns the natural exponential function E**x = pow(E, x)
Definition pow.cpp:271
void get_num_den(const Rational &rat, const Ptr< RCP< const Integer > > &num, const Ptr< RCP< const Integer > > &den)
returns the num and den of rational rat as RCP<const Integer>
Definition rational.cpp:130
RCP< const Number > rational(long n, long d)
convenience creator from two longs
Definition rational.h:328
std::enable_if< std::is_integral< T >::value, RCP< constInteger > >::type integer(T i)
Definition integer.h:197
STL namespace.