real_mpfr.h
1 
6 #ifndef SYMENGINE_REAL_MPFR_H
7 #define SYMENGINE_REAL_MPFR_H
8 
9 #include <symengine/complex_double.h>
10 #include <symengine/symengine_exception.h>
11 
12 #ifdef HAVE_SYMENGINE_MPFR
13 #include <mpfr.h>
14 
15 namespace SymEngine
16 {
17 
18 class mpfr_class
19 {
20 private:
21  mpfr_t mp;
22 
23 public:
24  mpfr_ptr get_mpfr_t()
25  {
26  return mp;
27  }
28  mpfr_srcptr get_mpfr_t() const
29  {
30  return mp;
31  }
32  explicit mpfr_class(mpfr_srcptr m)
33  {
34  mpfr_init2(mp, mpfr_get_prec(m));
35  mpfr_set(mp, m, MPFR_RNDN);
36  }
37  explicit mpfr_class(mpfr_prec_t prec = 53)
38  {
39  mpfr_init2(mp, prec);
40  }
41  mpfr_class(std::string s, mpfr_prec_t prec = 53, unsigned base = 10)
42  {
43  mpfr_init2(mp, prec);
44  mpfr_set_str(mp, s.c_str(), base, MPFR_RNDN);
45  }
46  mpfr_class(const mpfr_class &other)
47  {
48  mpfr_init2(mp, mpfr_get_prec(other.get_mpfr_t()));
49  mpfr_set(mp, other.get_mpfr_t(), MPFR_RNDN);
50  }
51  mpfr_class(mpfr_class &&other)
52  {
53  mp->_mpfr_d = nullptr;
54  mpfr_swap(mp, other.get_mpfr_t());
55  }
56  mpfr_class &operator=(const mpfr_class &other)
57  {
58  mpfr_set_prec(mp, mpfr_get_prec(other.get_mpfr_t()));
59  mpfr_set(mp, other.get_mpfr_t(), MPFR_RNDN);
60  return *this;
61  }
62  mpfr_class &operator=(mpfr_class &&other)
63  {
64  mpfr_swap(mp, other.get_mpfr_t());
65  return *this;
66  }
67  ~mpfr_class()
68  {
69  if (mp->_mpfr_d != nullptr) {
70  mpfr_clear(mp);
71  }
72  }
73  mpfr_prec_t get_prec() const
74  {
75  return mpfr_get_prec(mp);
76  }
77 };
78 
79 void hash_combine_impl(hash_t &, mpfr_srcptr);
80 
81 RCP<const Number> number(mpfr_ptr x);
82 
84 class RealMPFR : public Number
85 {
86 public:
87  mpfr_class i;
88 
89 public:
90  IMPLEMENT_TYPEID(SYMENGINE_REAL_MPFR)
92  RealMPFR(mpfr_class i);
93  inline const mpfr_class &as_mpfr() const
94  {
95  return i;
96  }
97  inline mpfr_prec_t get_prec() const
98  {
99  return mpfr_get_prec(i.get_mpfr_t());
100  }
102  hash_t __hash__() const override;
107  bool __eq__(const Basic &o) const override;
108  int compare(const Basic &o) const override;
110  inline bool is_positive() const override
111  {
112  return mpfr_cmp_si(i.get_mpfr_t(), 0) > 0;
113  }
115  inline bool is_negative() const override
116  {
117  return mpfr_cmp_si(i.get_mpfr_t(), 0) < 0;
118  }
120  inline bool is_exact() const override
121  {
122  return false;
123  }
125  Evaluate &get_eval() const override;
126 
128  bool is_zero() const override
129  {
130  return mpfr_cmp_si(i.get_mpfr_t(), 0) == 0;
131  }
133  // A mpfr_t is not exactly equal to `1`
134  bool is_one() const override
135  {
136  return false;
137  }
139  // A mpfr_t is not exactly equal to `-1`
140  bool is_minus_one() const override
141  {
142  return false;
143  }
145  // False is returned because an 'mpfr' cannot have an imaginary part
146  bool is_complex() const override
147  {
148  return false;
149  }
150 
154  RCP<const Number> addreal(const Integer &other) const;
155  RCP<const Number> addreal(const Rational &other) const;
156  RCP<const Number> addreal(const Complex &other) const;
157  RCP<const Number> addreal(const RealDouble &other) const;
158  RCP<const Number> addreal(const ComplexDouble &other) const;
159  RCP<const Number> addreal(const RealMPFR &other) const;
160 
162  RCP<const Number> add(const Number &other) const override
163  {
164  if (is_a<Rational>(other)) {
165  return addreal(down_cast<const Rational &>(other));
166  } else if (is_a<Integer>(other)) {
167  return addreal(down_cast<const Integer &>(other));
168  } else if (is_a<Complex>(other)) {
169  return addreal(down_cast<const Complex &>(other));
170  } else if (is_a<RealDouble>(other)) {
171  return addreal(down_cast<const RealDouble &>(other));
172  } else if (is_a<ComplexDouble>(other)) {
173  return addreal(down_cast<const ComplexDouble &>(other));
174  } else if (is_a<RealMPFR>(other)) {
175  return addreal(down_cast<const RealMPFR &>(other));
176  } else {
177  return other.add(*this);
178  }
179  }
180 
181  RCP<const Number> subreal(const Integer &other) const;
182  RCP<const Number> subreal(const Rational &other) const;
183  RCP<const Number> subreal(const Complex &other) const;
184  RCP<const Number> subreal(const RealDouble &other) const;
185  RCP<const Number> subreal(const ComplexDouble &other) const;
186  RCP<const Number> subreal(const RealMPFR &other) const;
187 
189  RCP<const Number> sub(const Number &other) const override
190  {
191  if (is_a<Rational>(other)) {
192  return subreal(down_cast<const Rational &>(other));
193  } else if (is_a<Integer>(other)) {
194  return subreal(down_cast<const Integer &>(other));
195  } else if (is_a<Complex>(other)) {
196  return subreal(down_cast<const Complex &>(other));
197  } else if (is_a<RealDouble>(other)) {
198  return subreal(down_cast<const RealDouble &>(other));
199  } else if (is_a<ComplexDouble>(other)) {
200  return subreal(down_cast<const ComplexDouble &>(other));
201  } else if (is_a<RealMPFR>(other)) {
202  return subreal(down_cast<const RealMPFR &>(other));
203  } else {
204  return other.rsub(*this);
205  }
206  }
207 
208  RCP<const Number> rsubreal(const Integer &other) const;
209  RCP<const Number> rsubreal(const Rational &other) const;
210  RCP<const Number> rsubreal(const Complex &other) const;
211  RCP<const Number> rsubreal(const RealDouble &other) const;
212  RCP<const Number> rsubreal(const ComplexDouble &other) const;
213 
215  RCP<const Number> rsub(const Number &other) const override
216  {
217  if (is_a<Rational>(other)) {
218  return rsubreal(down_cast<const Rational &>(other));
219  } else if (is_a<Integer>(other)) {
220  return rsubreal(down_cast<const Integer &>(other));
221  } else if (is_a<Complex>(other)) {
222  return rsubreal(down_cast<const Complex &>(other));
223  } else if (is_a<RealDouble>(other)) {
224  return rsubreal(down_cast<const RealDouble &>(other));
225  } else if (is_a<ComplexDouble>(other)) {
226  return rsubreal(down_cast<const ComplexDouble &>(other));
227  } else {
228  throw NotImplementedError("Not Implemented");
229  }
230  }
231 
232  RCP<const Number> mulreal(const Integer &other) const;
233  RCP<const Number> mulreal(const Rational &other) const;
234  RCP<const Number> mulreal(const Complex &other) const;
235  RCP<const Number> mulreal(const RealDouble &other) const;
236  RCP<const Number> mulreal(const ComplexDouble &other) const;
237  RCP<const Number> mulreal(const RealMPFR &other) const;
238 
240  RCP<const Number> mul(const Number &other) const override
241  {
242  if (is_a<Rational>(other)) {
243  return mulreal(down_cast<const Rational &>(other));
244  } else if (is_a<Integer>(other)) {
245  return mulreal(down_cast<const Integer &>(other));
246  } else if (is_a<Complex>(other)) {
247  return mulreal(down_cast<const Complex &>(other));
248  } else if (is_a<RealDouble>(other)) {
249  return mulreal(down_cast<const RealDouble &>(other));
250  } else if (is_a<ComplexDouble>(other)) {
251  return mulreal(down_cast<const ComplexDouble &>(other));
252  } else if (is_a<RealMPFR>(other)) {
253  return mulreal(down_cast<const RealMPFR &>(other));
254  } else {
255  return other.mul(*this);
256  }
257  }
258 
259  RCP<const Number> divreal(const Integer &other) const;
260  RCP<const Number> divreal(const Rational &other) const;
261  RCP<const Number> divreal(const Complex &other) const;
262  RCP<const Number> divreal(const RealDouble &other) const;
263  RCP<const Number> divreal(const ComplexDouble &other) const;
264  RCP<const Number> divreal(const RealMPFR &other) const;
265 
267  RCP<const Number> div(const Number &other) const override
268  {
269  if (is_a<Rational>(other)) {
270  return divreal(down_cast<const Rational &>(other));
271  } else if (is_a<Integer>(other)) {
272  return divreal(down_cast<const Integer &>(other));
273  } else if (is_a<Complex>(other)) {
274  return divreal(down_cast<const Complex &>(other));
275  } else if (is_a<RealDouble>(other)) {
276  return divreal(down_cast<const RealDouble &>(other));
277  } else if (is_a<ComplexDouble>(other)) {
278  return divreal(down_cast<const ComplexDouble &>(other));
279  } else if (is_a<RealMPFR>(other)) {
280  return divreal(down_cast<const RealMPFR &>(other));
281  } else {
282  return other.rdiv(*this);
283  }
284  }
285 
286  RCP<const Number> rdivreal(const Integer &other) const;
287  RCP<const Number> rdivreal(const Rational &other) const;
288  RCP<const Number> rdivreal(const Complex &other) const;
289  RCP<const Number> rdivreal(const RealDouble &other) const;
290  RCP<const Number> rdivreal(const ComplexDouble &other) const;
291 
293  RCP<const Number> rdiv(const Number &other) const override
294  {
295  if (is_a<Rational>(other)) {
296  return rdivreal(down_cast<const Rational &>(other));
297  } else if (is_a<Integer>(other)) {
298  return rdivreal(down_cast<const Integer &>(other));
299  } else if (is_a<Complex>(other)) {
300  return rdivreal(down_cast<const Complex &>(other));
301  } else if (is_a<RealDouble>(other)) {
302  return rdivreal(down_cast<const RealDouble &>(other));
303  } else if (is_a<ComplexDouble>(other)) {
304  return rdivreal(down_cast<const ComplexDouble &>(other));
305  } else {
306  throw NotImplementedError("Not Implemented");
307  }
308  }
309 
310  RCP<const Number> powreal(const Integer &other) const;
311  RCP<const Number> powreal(const Rational &other) const;
312  RCP<const Number> powreal(const Complex &other) const;
313  RCP<const Number> powreal(const RealDouble &other) const;
314  RCP<const Number> powreal(const ComplexDouble &other) const;
315  RCP<const Number> powreal(const RealMPFR &other) const;
316 
318  RCP<const Number> pow(const Number &other) const override
319  {
320  if (is_a<Rational>(other)) {
321  return powreal(down_cast<const Rational &>(other));
322  } else if (is_a<Integer>(other)) {
323  return powreal(down_cast<const Integer &>(other));
324  } else if (is_a<Complex>(other)) {
325  return powreal(down_cast<const Complex &>(other));
326  } else if (is_a<RealDouble>(other)) {
327  return powreal(down_cast<const RealDouble &>(other));
328  } else if (is_a<ComplexDouble>(other)) {
329  return powreal(down_cast<const ComplexDouble &>(other));
330  } else if (is_a<RealMPFR>(other)) {
331  return powreal(down_cast<const RealMPFR &>(other));
332  } else {
333  return other.rpow(*this);
334  }
335  }
336 
337  RCP<const Number> rpowreal(const Integer &other) const;
338  RCP<const Number> rpowreal(const Rational &other) const;
339  RCP<const Number> rpowreal(const Complex &other) const;
340  RCP<const Number> rpowreal(const RealDouble &other) const;
341  RCP<const Number> rpowreal(const ComplexDouble &other) const;
342 
344  RCP<const Number> rpow(const Number &other) const override
345  {
346  if (is_a<Rational>(other)) {
347  return rpowreal(down_cast<const Rational &>(other));
348  } else if (is_a<Integer>(other)) {
349  return rpowreal(down_cast<const Integer &>(other));
350  } else if (is_a<Complex>(other)) {
351  return rpowreal(down_cast<const Complex &>(other));
352  } else if (is_a<RealDouble>(other)) {
353  return rpowreal(down_cast<const RealDouble &>(other));
354  } else if (is_a<ComplexDouble>(other)) {
355  return rpowreal(down_cast<const ComplexDouble &>(other));
356  } else {
357  throw NotImplementedError("Not Implemented");
358  }
359  }
360 };
361 
362 inline RCP<const RealMPFR> real_mpfr(mpfr_class x)
363 {
364  return rcp(new RealMPFR(std::move(x)));
365 }
366 } // namespace SymEngine
367 #else
368 
369 namespace SymEngine
370 {
371 class RealMPFR : public Number
372 {
373 public:
374  IMPLEMENT_TYPEID(SYMENGINE_REAL_MPFR)
375 };
376 } // namespace SymEngine
377 
378 #endif // HAVE_SYMENGINE_MPFR
379 #endif // SymEngine
#define IMPLEMENT_TYPEID(SYMENGINE_ID)
Inline members and functions.
Definition: basic.h:340
T c_str(T... args)
Basic()
Constructor.
Definition: basic.h:120
virtual bool __eq__(const Basic &o) const =0
Test equality.
virtual hash_t __hash__() const =0
virtual int compare(const Basic &o) const =0
virtual Evaluate & get_eval() const
Get Evaluate singleton to evaluate numerically.
Definition: number.h:47
virtual RCP< const Number > mul(const Number &other) const =0
Multiplication.
virtual bool is_one() const =0
virtual bool is_complex() const =0
virtual bool is_exact() const
return true if the number is an exact representation
Definition: number.h:37
virtual RCP< const Number > add(const Number &other) const =0
Addition.
virtual RCP< const Number > pow(const Number &other) const =0
Power.
virtual bool is_negative() const =0
virtual bool is_positive() const =0
virtual RCP< const Number > div(const Number &other) const
Division.
Definition: number.cpp:26
virtual RCP< const Number > sub(const Number &other) const
Subtraction.
Definition: number.cpp:16
virtual bool is_zero() const =0
virtual bool is_minus_one() const =0
T move(T... args)
Main namespace for SymEngine package.
Definition: add.cpp:19
void hash_combine_impl(hash_t &seed, const T &v, typename std::enable_if< std::is_base_of< Basic, T >::value >::type *=nullptr)
Templatised version to combine hash.
Definition: basic-inl.h:61