Loading...
Searching...
No Matches
mp_class.h
1#ifndef SYMENGINE_INTEGER_CLASS_H
2#define SYMENGINE_INTEGER_CLASS_H
3
4#include <symengine/symengine_config.h>
5#include <symengine/symengine_casts.h>
6#include <cstring>
7#if SYMENGINE_INTEGER_CLASS != SYMENGINE_BOOSTMP
8#include <symengine/mp_wrapper.h>
9#endif
10
11#if SYMENGINE_INTEGER_CLASS == SYMENGINE_BOOSTMP
12#include <boost/multiprecision/cpp_int.hpp>
13#include <boost/random/mersenne_twister.hpp>
14#include <boost/random/uniform_int.hpp>
15#include <symengine/symengine_rcp.h>
16#include <ios>
17#elif SYMENGINE_INTEGER_CLASS == SYMENGINE_PIRANHA
18#include <piranha/mp_integer.hpp>
19#include <piranha/mp_rational.hpp>
20#elif SYMENGINE_INTEGER_CLASS == SYMENGINE_GMPXX
21#define __GMPXX_USE_CXX11 1
22#include <gmpxx.h>
23#endif
24
25namespace SymEngine
26{
27/*
28 * integer_class and rational_class are the storage classes for
29 * SymEngine::Integer
30 * and SymEngine::Rational respectively. There are 4 choices for the
31 * integer_class.
32 * mpz_class from libgmpxx, piranha::integer from piranha, mpz_wrapper which
33 * wraps
34 * mpz_t from libgmp and fmpz_wrapper which wraps fmpz_t from libflint. This
35 * choice
36 * is made at compile time with SYMENGINE_INTEGER_CLASS.
37 *
38 * Each of these classes has to have all the arithmetic operators overloaded
39 * with
40 * operands of these classes and C++ integer types except long long. Also, shift
41 * operators, move operators, string, integer and mpz_t constructors are also
42 * required.
43 *
44 * To add a new type, several non-member functions need to be defined for the
45 * new
46 * type. See mpz_wrapper implementation for all the non-member functions that
47 * need
48 * to be defined.
49 */
50
51#if SYMENGINE_INTEGER_CLASS == SYMENGINE_BOOSTMP
52typedef boost::multiprecision::number<boost::multiprecision::cpp_int_backend<>,
53 boost::multiprecision::et_off>
54 integer_class;
55typedef boost::multiprecision::number<
56 boost::multiprecision::cpp_rational_backend, boost::multiprecision::et_off>
57 rational_class;
58#elif SYMENGINE_INTEGER_CLASS == SYMENGINE_PIRANHA
59typedef piranha::integer integer_class;
60typedef piranha::rational rational_class;
61#elif SYMENGINE_INTEGER_CLASS == SYMENGINE_FLINT
62typedef fmpz_wrapper integer_class;
63typedef fmpq_wrapper rational_class;
64#elif SYMENGINE_INTEGER_CLASS == SYMENGINE_GMP
65typedef mpz_wrapper integer_class;
66typedef mpq_wrapper rational_class;
67#elif SYMENGINE_INTEGER_CLASS == SYMENGINE_GMPXX
68typedef mpz_class integer_class;
69typedef mpq_class rational_class;
70#endif
71
72// needs to be in a separate namespace to import the literals.
73// eg: using namespace SymEngine::literals;
74inline namespace literals
75{
77inline integer_class operator"" _z(const char *str)
78{
79 return integer_class(str);
80}
81
82inline rational_class operator"" _q(const char *str)
83{
84 return rational_class(integer_class(str));
85}
86} // namespace literals
87
88#if SYMENGINE_INTEGER_CLASS == SYMENGINE_GMPXX \
89 || SYMENGINE_INTEGER_CLASS == SYMENGINE_GMP
90// Helper functions for mpz
91inline integer_class mp_abs(const integer_class &i)
92{
93 integer_class res;
94 mpz_abs(res.get_mpz_t(), i.get_mpz_t());
95 return res;
96}
97
98inline int mp_sign(const integer_class &i)
99{
100 return mpz_sgn(i.get_mpz_t());
101}
102
103inline integer_class mp_sqrt(const integer_class &i)
104{
105 integer_class res;
106 mpz_sqrt(res.get_mpz_t(), i.get_mpz_t());
107 return res;
108}
109
110inline double mp_get_d(const integer_class &i)
111{
112 return static_cast<double>(i.get_d());
113}
114
115inline void mp_set_d(integer_class &i, double a)
116{
117 mpz_set_d(i.get_mpz_t(), a);
118}
119
120inline void mp_set_str(integer_class &i, const std::string &a)
121{
122 mpz_set_str(i.get_mpz_t(), a.c_str(), 0);
123}
124
125inline std::string mp_get_hex_str(const integer_class &i)
126{
127 void (*freefunc)(void *, size_t);
128 mp_get_memory_functions(NULL, NULL, &freefunc);
129 char *c = mpz_get_str(NULL, 16, i.get_mpz_t());
131 freefunc(c, strlen(c) + 1);
132 return r;
133}
134
135inline void mp_demote(integer_class &i) {}
136
137inline bool mp_fits_ulong_p(const integer_class &i)
138{
139 return i.fits_ulong_p() != 0;
140}
141
142inline bool mp_fits_slong_p(const integer_class &i)
143{
144 return i.fits_slong_p() != 0;
145}
146
147inline unsigned long mp_get_ui(const integer_class &i)
148{
149 return i.get_ui();
150}
151
152inline long mp_get_si(const integer_class &i)
153{
154 return i.get_si();
155}
156
157inline mpz_srcptr get_mpz_t(const integer_class &i)
158{
159 return i.get_mpz_t();
160}
161
162inline mpz_ptr get_mpz_t(integer_class &i)
163{
164 return i.get_mpz_t();
165}
166
167inline void mp_pow_ui(integer_class &res, const integer_class &i,
168 unsigned long n)
169{
170 mpz_pow_ui(res.get_mpz_t(), i.get_mpz_t(), n);
171}
172
173inline void mp_pow_ui(rational_class &res, const rational_class &i,
174 unsigned long n)
175{
176 mpz_pow_ui(res.get_num().get_mpz_t(), i.get_num().get_mpz_t(), n);
177 mpz_pow_ui(res.get_den().get_mpz_t(), i.get_den().get_mpz_t(), n);
178}
179
180inline void mp_powm(integer_class &res, const integer_class &a,
181 const integer_class &b, const integer_class &m)
182{
183 mpz_powm(res.get_mpz_t(), a.get_mpz_t(), b.get_mpz_t(), m.get_mpz_t());
184}
185
186inline bool mp_invert(integer_class &res, const integer_class &a,
187 const integer_class &m)
188{
189 return mpz_invert(res.get_mpz_t(), a.get_mpz_t(), m.get_mpz_t()) != 0;
190}
191
192inline void mp_gcd(integer_class &res, const integer_class &a,
193 const integer_class &b)
194{
195 mpz_gcd(res.get_mpz_t(), a.get_mpz_t(), b.get_mpz_t());
196}
197
198inline void mp_gcdext(integer_class &res, integer_class &r, integer_class &s,
199 const integer_class &a, const integer_class &b)
200{
201 mpz_gcdext(res.get_mpz_t(), r.get_mpz_t(), s.get_mpz_t(), a.get_mpz_t(),
202 b.get_mpz_t());
203}
204
205inline void mp_and(integer_class &res, const integer_class &a,
206 const integer_class &b)
207{
208 mpz_and(res.get_mpz_t(), a.get_mpz_t(), b.get_mpz_t());
209}
210
211inline void mp_fdiv_r(integer_class &res, const integer_class &a,
212 const integer_class &b)
213{
214 mpz_fdiv_r(res.get_mpz_t(), a.get_mpz_t(), b.get_mpz_t());
215}
216
217inline void mp_fdiv_q(integer_class &res, const integer_class &a,
218 const integer_class &b)
219{
220 mpz_fdiv_q(res.get_mpz_t(), a.get_mpz_t(), b.get_mpz_t());
221}
222
223inline void mp_cdiv_q(integer_class &res, const integer_class &a,
224 const integer_class &b)
225{
226 mpz_cdiv_q(res.get_mpz_t(), a.get_mpz_t(), b.get_mpz_t());
227}
228
229inline void mp_tdiv_q(integer_class &res, const integer_class &a,
230 const integer_class &b)
231{
232 mpz_tdiv_q(res.get_mpz_t(), a.get_mpz_t(), b.get_mpz_t());
233}
234
235inline void mp_fdiv_qr(integer_class &q, integer_class &r,
236 const integer_class &a, const integer_class &b)
237{
238 mpz_fdiv_qr(q.get_mpz_t(), r.get_mpz_t(), a.get_mpz_t(), b.get_mpz_t());
239}
240
241inline void mp_divexact(integer_class &q, const integer_class &a,
242 const integer_class &b)
243{
244 mpz_divexact(q.get_mpz_t(), a.get_mpz_t(), b.get_mpz_t());
245}
246
247inline void mp_lcm(integer_class &q, const integer_class &a,
248 const integer_class &b)
249{
250 mpz_lcm(q.get_mpz_t(), a.get_mpz_t(), b.get_mpz_t());
251}
252
253inline void mp_tdiv_qr(integer_class &q, integer_class &r,
254 const integer_class &a, const integer_class &b)
255{
256 mpz_tdiv_qr(q.get_mpz_t(), r.get_mpz_t(), a.get_mpz_t(), b.get_mpz_t());
257}
258
259inline void mp_addmul(integer_class &r, const integer_class &a,
260 const integer_class &b)
261{
262 mpz_addmul(r.get_mpz_t(), a.get_mpz_t(), b.get_mpz_t());
263}
264
265// Helper functions for mpq
266inline const integer_class &get_den(const rational_class &i)
267{
268 return i.get_den();
269}
270
271inline const integer_class &get_num(const rational_class &i)
272{
273 return i.get_num();
274}
275
276inline integer_class &get_den(rational_class &i)
277{
278 return i.get_den();
279}
280
281inline integer_class &get_num(rational_class &i)
282{
283 return i.get_num();
284}
285
286inline mpq_srcptr get_mpq_t(const rational_class &i)
287{
288 return i.get_mpq_t();
289}
290
291inline void canonicalize(rational_class &i)
292{
293 i.canonicalize();
294}
295
296inline double mp_get_d(const rational_class &i)
297{
298 return i.get_d();
299}
300
301inline int mp_sign(const rational_class &i)
302{
303 return mpq_sgn(i.get_mpq_t());
304}
305
306inline rational_class mp_abs(const rational_class &i)
307{
308 rational_class res;
309 mpq_abs(res.get_mpq_t(), i.get_mpq_t());
310 return res;
311}
312
313inline integer_class mp_primorial(unsigned long n)
314{
315 integer_class res;
316 mpz_primorial_ui(res.get_mpz_t(), n);
317 return res;
318}
319
320#elif SYMENGINE_INTEGER_CLASS == SYMENGINE_PIRANHA
321// Helper functions for piranha::integer
322inline piranha::integer mp_abs(const piranha::integer &i)
323{
324 return i.abs();
325}
326
327inline piranha::integer mp_sqrt(const piranha::integer &i)
328{
329 return i.sqrt();
330}
331
332inline void mp_demote(piranha::integer &i) {}
333
334inline mpz_ptr get_mpz_t(piranha::integer &i)
335{
336 return i._get_mpz_ptr();
337}
338
339inline auto get_mpz_t(const piranha::integer &i) -> decltype(i.get_mpz_view())
340{
341 return i.get_mpz_view();
342}
343
344inline void mp_pow_ui(piranha::integer &res, const piranha::integer &i,
345 unsigned long n)
346{
347 res = i.pow(n);
348}
349
350inline void mp_pow_ui(piranha::rational &res, const piranha::rational &i,
351 unsigned long n)
352{
353 res = i.pow(n);
354}
355
356inline void mp_powm(piranha::integer &res, const piranha::integer &a,
357 const piranha::integer &b, const piranha::integer &m)
358{
359 auto _res = get_mpz_t(res);
360 mpz_powm(_res, get_mpz_t(a), get_mpz_t(b), get_mpz_t(m));
361}
362
363inline bool mp_invert(piranha::integer &res, const piranha::integer &a,
364 const piranha::integer &m)
365{
366 auto _res = get_mpz_t(res);
367 return mpz_invert(_res, get_mpz_t(a), get_mpz_t(m)) != 0;
368}
369
370inline void mp_gcd(piranha::integer &g, const piranha::integer &a,
371 const piranha::integer &b)
372{
373 piranha::integer::gcd(g, a, b);
374}
375
376inline void mp_gcdext(piranha::integer &g, piranha::integer &r,
377 piranha::integer &s, const piranha::integer &a,
378 const piranha::integer &b)
379{
380 auto _g = get_mpz_t(g);
381 auto _r = get_mpz_t(r);
382 auto _s = get_mpz_t(s);
383 mpz_gcdext(_g, _r, _s, get_mpz_t(a), get_mpz_t(b));
384}
385
386inline void mp_and(piranha::integer &res, const piranha::integer &a,
387 const piranha::integer &b)
388{
389 auto _res = get_mpz_t(res);
390 mpz_and(_res, get_mpz_t(a), get_mpz_t(b));
391}
392
393inline void mp_fdiv_r(piranha::integer &res, const piranha::integer &a,
394 const piranha::integer &b)
395{
396 auto _res = get_mpz_t(res);
397 mpz_fdiv_r(_res, get_mpz_t(a), get_mpz_t(b));
398}
399
400inline void mp_fdiv_q(piranha::integer &res, const piranha::integer &a,
401 const piranha::integer &b)
402{
403 auto _res = get_mpz_t(res);
404 mpz_fdiv_q(_res, get_mpz_t(a), get_mpz_t(b));
405}
406
407inline void mp_cdiv_q(piranha::integer &res, const piranha::integer &a,
408 const piranha::integer &b)
409{
410 auto _res = get_mpz_t(res);
411 mpz_cdiv_q(_res, get_mpz_t(a), get_mpz_t(b));
412}
413
414inline void mp_tdiv_q(piranha::integer &res, const piranha::integer &a,
415 const piranha::integer &b)
416{
417 auto _res = get_mpz_t(res);
418 mpz_tdiv_q(_res, get_mpz_t(a), get_mpz_t(b));
419}
420
421inline void mp_fdiv_qr(piranha::integer &q, piranha::integer &r,
422 const piranha::integer &a, const piranha::integer &b)
423{
424 auto _q = get_mpz_t(q);
425 mpz_fdiv_qr(_q, get_mpz_t(r), get_mpz_t(a), get_mpz_t(b));
426}
427
428inline void mp_divexact(piranha::integer &q, const piranha::integer &a,
429 const piranha::integer &b)
430{
431 piranha::integer::_divexact(q, a, b);
432}
433
434inline void mp_lcm(piranha::integer &q, const piranha::integer &a,
435 const piranha::integer &b)
436{
437 auto _q = get_mpz_t(q);
438 mpz_lcm(_q, get_mpz_t(a), get_mpz_t(b));
439}
440
441inline void mp_tdiv_qr(piranha::integer &q, piranha::integer &r,
442 const piranha::integer &a, const piranha::integer &b)
443{
444 piranha::integer::divrem(q, r, a, b);
445}
446
447inline int mp_sign(const piranha::integer &i)
448{
449 return i.sign();
450}
451
452inline long mp_get_si(const piranha::integer &i)
453{
454 return mpz_get_si(i.get_mpz_view());
455}
456
457inline unsigned long mp_get_ui(const piranha::integer &i)
458{
459 return mpz_get_ui(i.get_mpz_view());
460}
461
462inline double mp_get_d(const piranha::integer &i)
463{
464 return mpz_get_d(i.get_mpz_view());
465}
466
467inline void mp_set_d(piranha::integer &i, double a)
468{
469 i = a;
470}
471
472inline void mp_set_str(integer_class &i, const std::string &a)
473{
474 mpz_t m;
475 mpz_init(m);
476 mpz_set_str(m, a.c_str(), 0);
477 i = integer_class(m);
478}
479
480inline std::string mp_get_hex_str(const integer_class &i)
481{
482
483 void (*freefunc)(void *, size_t);
484 mp_get_memory_functions(NULL, NULL, &freefunc);
485 char *c = mpz_get_str(NULL, 16, i.get_mpz_view());
487 freefunc(c, strlen(c) + 1);
488 return r;
489}
490
491inline bool mp_fits_ulong_p(const piranha::integer &i)
492{
493 return mpz_fits_ulong_p(i.get_mpz_view()) != 0;
494}
495
496inline bool mp_fits_slong_p(const piranha::integer &i)
497{
498 return mpz_fits_slong_p(i.get_mpz_view()) != 0;
499}
500
501inline void mp_addmul(integer_class &r, const integer_class &a,
502 const integer_class &b)
503{
504 piranha::math::multiply_accumulate(r, a, b);
505}
506
507inline integer_class mp_primorial(unsigned long n)
508{
509 integer_class res;
510 mpz_primorial_ui(get_mpz_t(res), n);
511 return res;
512}
513
514// Helper functions for piranha::rational
515
516inline piranha::rational mp_abs(const piranha::rational &i)
517{
518 return i.abs();
519}
520
521inline const piranha::integer &get_den(const piranha::rational &i)
522{
523 return i.den();
524}
525
526inline const piranha::integer &get_num(const piranha::rational &i)
527{
528 return i.num();
529}
530
531inline piranha::integer &get_den(piranha::rational &i)
532{
533 return i._den();
534}
535
536inline piranha::integer &get_num(piranha::rational &i)
537{
538 return i._num();
539}
540
541inline void canonicalize(piranha::rational &i)
542{
543 i.canonicalise();
544}
545
546inline double mp_get_d(const piranha::rational &i)
547{
548 return mpq_get_d(i.get_mpq_view().get());
549}
550
551inline auto get_mpq_t(const piranha::rational &i) -> decltype(i.get_mpq_view())
552{
553 return i.get_mpq_view();
554}
555
556inline int mp_sign(const piranha::rational &i)
557{
558 return i.num().sign();
559}
560#elif SYMENGINE_INTEGER_CLASS == SYMENGINE_FLINT
561
562// helper functions for fmpz
563
564inline mpz_view_flint get_mpz_t(const fmpz_wrapper &i)
565{
566 return mpz_view_flint(i);
567}
568
569inline mpz_ptr get_mpz_t(fmpz_wrapper &i)
570{
571 return _fmpz_promote_val(i.get_fmpz_t());
572}
573
574inline void mp_demote(fmpz_wrapper &i)
575{
576 _fmpz_demote_val(i.get_fmpz_t());
577}
578
579inline int mp_sign(const fmpz_wrapper &i)
580{
581 return fmpz_sgn(i.get_fmpz_t());
582}
583
584inline long mp_get_si(const fmpz_wrapper &i)
585{
586 return fmpz_get_si(i.get_fmpz_t());
587}
588
589inline unsigned long mp_get_ui(const fmpz_wrapper &i)
590{
591 return fmpz_get_ui(i.get_fmpz_t());
592}
593
594inline bool mp_fits_slong_p(const fmpz_wrapper &i)
595{
596 return fmpz_fits_si(i.get_fmpz_t());
597}
598
599inline bool mp_fits_ulong_p(const fmpz_wrapper &i)
600{
601 return fmpz_sgn(i.get_fmpz_t()) >= 0 && fmpz_abs_fits_ui(i.get_fmpz_t());
602}
603
604inline double mp_get_d(const fmpz_wrapper &i)
605{
606 return fmpz_get_d(i.get_fmpz_t());
607}
608
609inline void mp_set_d(fmpz_wrapper &i, double a)
610{
611 return fmpz_set_d(i.get_fmpz_t(), a);
612}
613
614inline void mp_set_str(fmpz_wrapper &i, const std::string &a)
615{
616 fmpz_set_str(i.get_fmpz_t(), a.c_str(), 0);
617}
618
619inline std::string mp_get_hex_str(const fmpz_wrapper &i)
620{
621 void (*freefunc)(void *, size_t);
622 mp_get_memory_functions(NULL, NULL, &freefunc);
623 char *c = fmpz_get_str(NULL, 16, i.get_fmpz_t());
625 freefunc(c, strlen(c) + 1);
626 return r;
627}
628
629inline fmpz_wrapper mp_abs(const fmpz_wrapper &i)
630{
631 fmpz_wrapper res;
632 fmpz_abs(res.get_fmpz_t(), i.get_fmpz_t());
633 return res;
634}
635
636inline fmpz_wrapper mp_sqrt(const fmpz_wrapper &i)
637{
638 fmpz_wrapper res;
639 fmpz_sqrt(res.get_fmpz_t(), i.get_fmpz_t());
640 return res;
641}
642
643inline void mp_pow_ui(fmpz_wrapper &res, const fmpz_wrapper &i, unsigned long n)
644{
645 fmpz_pow_ui(res.get_fmpz_t(), i.get_fmpz_t(), n);
646}
647
648inline void mp_pow_ui(fmpq_wrapper &res, const fmpq_wrapper &i, unsigned long n)
649{
650 fmpq_pow_si(res.get_fmpq_t(), i.get_fmpq_t(), n);
651}
652
653inline void mp_powm(fmpz_wrapper &res, const fmpz_wrapper &a,
654 const fmpz_wrapper &b, const fmpz_wrapper &m)
655{
656 if (b >= 0) {
657 fmpz_powm(res.get_fmpz_t(), a.get_fmpz_t(), b.get_fmpz_t(),
658 m.get_fmpz_t());
659 } else {
660 fmpz_neg(res.get_fmpz_t(), b.get_fmpz_t());
661 fmpz_powm(res.get_fmpz_t(), a.get_fmpz_t(), res.get_fmpz_t(),
662 m.get_fmpz_t());
663 fmpz_invmod(res.get_fmpz_t(), res.get_fmpz_t(), m.get_fmpz_t());
664 }
665}
666
667inline bool mp_invert(fmpz_wrapper &res, const fmpz_wrapper &a,
668 const fmpz_wrapper &m)
669{
670 return fmpz_invmod(res.get_fmpz_t(), a.get_fmpz_t(), m.get_fmpz_t()) != 0;
671}
672
673inline void mp_gcd(fmpz_wrapper &res, const fmpz_wrapper &a,
674 const fmpz_wrapper &b)
675{
676 fmpz_gcd(res.get_fmpz_t(), a.get_fmpz_t(), b.get_fmpz_t());
677}
678
679inline void mp_gcdext(fmpz_wrapper &g, fmpz_wrapper &r, fmpz_wrapper &s,
680 const fmpz_wrapper &a, const fmpz_wrapper &b)
681{
682 fmpz_xgcd(g.get_fmpz_t(), r.get_fmpz_t(), s.get_fmpz_t(), a.get_fmpz_t(),
683 b.get_fmpz_t());
684}
685
686inline void mp_and(fmpz_wrapper &res, const fmpz_wrapper &a,
687 const fmpz_wrapper &b)
688{
689 fmpz_and(res.get_fmpz_t(), a.get_fmpz_t(), b.get_fmpz_t());
690}
691
692inline void mp_fdiv_r(fmpz_wrapper &res, const fmpz_wrapper &a,
693 const fmpz_wrapper &b)
694{
695 fmpz_fdiv_r(res.get_fmpz_t(), a.get_fmpz_t(), b.get_fmpz_t());
696}
697
698inline void mp_fdiv_q(fmpz_wrapper &res, const fmpz_wrapper &a,
699 const fmpz_wrapper &b)
700{
701 fmpz_fdiv_q(res.get_fmpz_t(), a.get_fmpz_t(), b.get_fmpz_t());
702}
703
704inline void mp_cdiv_q(fmpz_wrapper &res, const fmpz_wrapper &a,
705 const fmpz_wrapper &b)
706{
707 fmpz_cdiv_q(res.get_fmpz_t(), a.get_fmpz_t(), b.get_fmpz_t());
708}
709
710inline void mp_tdiv_q(fmpz_wrapper &res, const fmpz_wrapper &a,
711 const fmpz_wrapper &b)
712{
713 fmpz_tdiv_q(res.get_fmpz_t(), a.get_fmpz_t(), b.get_fmpz_t());
714}
715
716inline void mp_fdiv_qr(fmpz_wrapper &q, fmpz_wrapper &r, const fmpz_wrapper &a,
717 const fmpz_wrapper &b)
718{
719 fmpz_fdiv_qr(q.get_fmpz_t(), r.get_fmpz_t(), a.get_fmpz_t(),
720 b.get_fmpz_t());
721}
722
723inline void mp_divexact(fmpz_wrapper &q, const fmpz_wrapper &a,
724 const fmpz_wrapper &b)
725{
726 fmpz_divexact(q.get_fmpz_t(), a.get_fmpz_t(), b.get_fmpz_t());
727}
728
729inline void mp_lcm(fmpz_wrapper &q, const fmpz_wrapper &a,
730 const fmpz_wrapper &b)
731{
732 fmpz_lcm(q.get_fmpz_t(), a.get_fmpz_t(), b.get_fmpz_t());
733}
734
735inline void mp_tdiv_qr(fmpz_wrapper &q, fmpz_wrapper &r, const fmpz_wrapper &a,
736 const fmpz_wrapper &b)
737{
738 fmpz_tdiv_qr(q.get_fmpz_t(), r.get_fmpz_t(), a.get_fmpz_t(),
739 b.get_fmpz_t());
740}
741
742inline void mp_addmul(fmpz_wrapper &r, const fmpz_wrapper &a,
743 const fmpz_wrapper &b)
744{
745 fmpz_addmul(r.get_fmpz_t(), a.get_fmpz_t(), b.get_fmpz_t());
746}
747
748inline integer_class mp_primorial(unsigned long n)
749{
750 fmpz_wrapper res;
751 fmpz_primorial(res.get_fmpz_t(), n);
752 return res;
753}
754
755// helper functions for fmpq
756
757inline const fmpz_wrapper &get_den(const fmpq_wrapper &i)
758{
759 return i.get_den();
760}
761
762inline const fmpz_wrapper &get_num(const fmpq_wrapper &i)
763{
764 return i.get_num();
765}
766
767inline fmpz_wrapper &get_den(fmpq_wrapper &i)
768{
769 return i.get_den();
770}
771
772inline fmpz_wrapper &get_num(fmpq_wrapper &i)
773{
774 return i.get_num();
775}
776
777inline mpq_view_flint get_mpq_t(const fmpq_wrapper &i)
778{
779 return mpq_view_flint(i);
780}
781
782inline void canonicalize(fmpq_wrapper &i)
783{
784 fmpq_canonicalise(i.get_fmpq_t());
785}
786
787inline double mp_get_d(const fmpq_wrapper &i)
788{
789 return mp_get_d(i.get_num()) / mp_get_d(i.get_den());
790}
791
792inline int mp_sign(const fmpq_wrapper &i)
793{
794 return fmpq_sgn(i.get_fmpq_t());
795}
796
797inline fmpq_wrapper mp_abs(const fmpq_wrapper &i)
798{
799 fmpq_wrapper res;
800 fmpq_abs(res.get_fmpq_t(), i.get_fmpq_t());
801 return res;
802}
803
804#elif SYMENGINE_INTEGER_CLASS == SYMENGINE_BOOSTMP
805
806inline integer_class mp_abs(const integer_class &i)
807{
808 // boost::multiprecision::abs(i) returns
809 // an expression template, not a cpp_int
810 // but it's ok: cpp_int is constructible from an expression template
811 return boost::multiprecision::abs(i);
812}
813
814inline int mp_cmpabs(const integer_class &a, const integer_class &b)
815{
816 if (mp_abs(a) > mp_abs(b)) {
817 return 1;
818 }
819 if (mp_abs(a) == mp_abs(b)) {
820 return 0;
821 }
822 return -1;
823}
824
825inline int mp_sign(const integer_class &i)
826{
827 return boost::math::sign(i);
828}
829
830inline double mp_get_d(const integer_class &i)
831{
832 return i.convert_to<double>();
833}
834
835inline void mp_set_d(integer_class &i, double a)
836{
837 i.assign(a);
838}
839
840inline void mp_set_str(integer_class &i, const std::string &a)
841{
842 i = integer_class(a.c_str());
843}
844
845inline std::string mp_get_hex_str(const integer_class &i)
846{
847 if (mp_sign(i) >= 0) {
848 return i.str(0, std::ios_base::hex);
849 } else {
850 return std::string("-") + (-i).str(0, std::ios_base::hex);
851 }
852}
853
854inline unsigned long mp_get_ui(const integer_class &i)
855{
856 return mp_abs(i).convert_to<unsigned long>();
857}
858
859inline long mp_get_si(const integer_class &i)
860{
861 return i.convert_to<long>();
862}
863
864inline bool mp_fits_ulong_p(const integer_class &i)
865{
866 return (i >= 0) && (i <= ULONG_MAX);
867}
868
869inline bool mp_fits_slong_p(const integer_class &i)
870{
871 return (i >= LONG_MIN) && (i <= LONG_MAX);
872}
873
874// bitwise and
875inline void mp_and(integer_class &res, const integer_class &a,
876 const integer_class &b)
877{
878 res = boost::multiprecision::operator&(a, b);
879}
880
881inline void mp_pow_ui(integer_class &res, const integer_class &i,
882 unsigned long n)
883{
884 res = boost::multiprecision::pow(i, numeric_cast<unsigned>(n));
885}
886
887inline void mp_gcd(integer_class &res, const integer_class &a,
888 const integer_class &b)
889{
890 res = boost::multiprecision::gcd(a, b);
891}
892
893void mp_fdiv_qr(integer_class &q, integer_class &r, const integer_class &a,
894 const integer_class &b);
895
896void mp_cdiv_qr(integer_class &q, integer_class &r, const integer_class &a,
897 const integer_class &b);
898
899inline void mp_fdiv_r(integer_class &res, const integer_class &a,
900 const integer_class &b)
901{
902 // TODO: benchmark this speed
903 integer_class quo;
904 mp_fdiv_qr(quo, res, a, b);
905}
906
907inline void mp_fdiv_q(integer_class &res, const integer_class &a,
908 const integer_class &b)
909{
910 // TODO: benchmark this speed
911 integer_class rem;
912 mp_fdiv_qr(res, rem, a, b);
913}
914
915inline void mp_cdiv_q(integer_class &res, const integer_class &a,
916 const integer_class &b)
917{
918 // TODO: benchmark this speed
919 integer_class rem;
920 mp_cdiv_qr(res, rem, a, b);
921}
922
923inline void mp_tdiv_qr(integer_class &q, integer_class &r,
924 const integer_class &a, const integer_class &b)
925{
926 boost::multiprecision::divide_qr(a, b, q, r);
927}
928
929inline void mp_tdiv_q(integer_class &res, const integer_class &a,
930 const integer_class &b)
931{
932 integer_class rem;
933 mp_tdiv_qr(res, rem, a, b);
934}
935
936inline void mp_divexact(integer_class &q, const integer_class &a,
937 const integer_class &b)
938{
939 // TODO: make faster
940 q = a / b;
941}
942
943inline void mp_lcm(integer_class &q, const integer_class &a,
944 const integer_class &b)
945{
946 q = boost::multiprecision::lcm(a, b);
947}
948
949inline void mp_addmul(integer_class &r, const integer_class &a,
950 const integer_class &b)
951{
952 // boost::multiprecision::default_ops::eval_multiply_add(r,a,b);
953 // //segfaults.
954 r += a * b;
955}
956
957// Helper functions for cpp_rational
958inline const integer_class get_den(const rational_class &i)
959{
960 return boost::multiprecision::denominator(i);
961}
962
963inline const integer_class get_num(const rational_class &i)
964{
965 return boost::multiprecision::numerator(i);
966}
967
968inline void canonicalize(rational_class &i)
969{
970 // do nothing; boost::multiprecision::cpp_int
971 // is always stored in canonical form
972 // numerator and denominator share no common factors
973 // denominator is positive.
974}
975
976inline double mp_get_d(const rational_class &i)
977{
978 return i.convert_to<double>();
979}
980
981inline int mp_sign(const rational_class &i)
982{
983 return i.sign();
984}
985
986inline rational_class mp_abs(const rational_class &i)
987{
988 return boost::multiprecision::abs(i);
989}
990
991inline bool mp_divisible_p(const integer_class &a, const integer_class &b)
992{
993 if (b == 0) {
994 return (a == 0);
995 }
996 return a % b == 0;
997}
998
999void mp_pow_ui(rational_class &res, const rational_class &i, unsigned long n);
1000
1001void mp_powm(integer_class &res, const integer_class &a, const integer_class &b,
1002 const integer_class &m);
1003
1004/* Extended Euclidean algorithm in Z
1005 * inargs: integers a, b
1006 * outargs: gcd, the greatest common divisor of a and b
1007 * s, t such that sa + tb = gcd
1008 */
1009void mp_gcdext(integer_class &gcd, integer_class &s, integer_class &t,
1010 const integer_class &a, const integer_class &b);
1011
1012bool mp_invert(integer_class &res, const integer_class &a,
1013 const integer_class &m);
1014
1015bool mp_root(integer_class &res, const integer_class &i, unsigned long n);
1016
1017integer_class mp_sqrt(const integer_class &i);
1018
1019void mp_rootrem(integer_class &a, integer_class &b, const integer_class &i,
1020 unsigned long n);
1021
1022void mp_sqrtrem(integer_class &a, integer_class &b, const integer_class &i);
1023
1024int mp_probab_prime_p(const integer_class &i, unsigned retries);
1025
1026void mp_nextprime(integer_class &res, const integer_class &i);
1027
1028unsigned long mp_scan1(const integer_class &i);
1029
1030void mp_fib_ui(integer_class &res, unsigned long n);
1031
1032void mp_fib2_ui(integer_class &a, integer_class &b, unsigned long n);
1033
1034void mp_lucnum_ui(integer_class &res, unsigned long n);
1035
1036void mp_lucnum2_ui(integer_class &a, integer_class &b, unsigned long n);
1037
1038void mp_fac_ui(integer_class &res, unsigned long n);
1039
1040void mp_bin_ui(integer_class &res, const integer_class &n, unsigned long r);
1041
1042bool mp_perfect_power_p(const integer_class &i);
1043
1044bool mp_perfect_square_p(const integer_class &i);
1045
1046int mp_legendre(const integer_class &a, const integer_class &n);
1047
1048int mp_jacobi(const integer_class &a, const integer_class &n);
1049
1050int mp_kronecker(const integer_class &a, const integer_class &n);
1051
1052integer_class mp_primorial(unsigned long n);
1053
1054class mp_randstate
1055{
1056public:
1057 // returns a uniformly distributed random integer between 0 and a-1,
1058 // inclusive
1059 void urandomint(integer_class &res, const integer_class &a)
1060 {
1061 boost::random::uniform_int_distribution<integer_class> ui(0, a);
1062 res = ui(_twister);
1063 }
1064
1065 void seed(const uint32_t &i)
1066 {
1067 _twister.seed(i);
1068 }
1069
1070private:
1071 boost::random::mt19937 _twister;
1072};
1073
1074#endif // SYMENGINE_INTEGER_CLASS == SYMENGINE_BOOSTMP
1075
1076// The implementation of each of the following
1077// requires only get_mpz_t(integer_class), mp_demote
1078// and functions from GMP. They don't depend on
1079// any members of the backend class mpz, fmpz, or piranha::integer.
1080// These functions will all need to be implemented separately
1081// for a GMP-free build (with boost::multiprecision, for instance)
1082#if SYMENGINE_INTEGER_CLASS == SYMENGINE_PIRANHA \
1083 || SYMENGINE_INTEGER_CLASS == SYMENGINE_FLINT \
1084 || SYMENGINE_INTEGER_CLASS == SYMENGINE_GMP \
1085 || SYMENGINE_INTEGER_CLASS == SYMENGINE_GMPXX
1086
1087inline bool mp_root(integer_class &res, const integer_class &i, unsigned long n)
1088{
1089 auto _res = get_mpz_t(res);
1090 int ret = mpz_root(_res, get_mpz_t(i), n);
1091 mp_demote(res);
1092 return ret != 0;
1093}
1094
1095inline void mp_nextprime(integer_class &res, const integer_class &i)
1096{
1097 auto _res = get_mpz_t(res);
1098 mpz_nextprime(_res, get_mpz_t(i));
1099 mp_demote(res);
1100}
1101
1102inline void mp_sqrtrem(integer_class &a, integer_class &b,
1103 const integer_class &i)
1104{
1105 auto _a = get_mpz_t(a);
1106 auto _b = get_mpz_t(b);
1107 mpz_sqrtrem(_a, _b, get_mpz_t(i));
1108 mp_demote(a);
1109 mp_demote(b);
1110}
1111
1112inline void mp_rootrem(integer_class &a, integer_class &b,
1113 const integer_class &i, unsigned long n)
1114{
1115 auto _a = get_mpz_t(a);
1116 auto _b = get_mpz_t(b);
1117 mpz_rootrem(_a, _b, get_mpz_t(i), n);
1118 mp_demote(a);
1119 mp_demote(b);
1120}
1121
1122inline unsigned long mp_scan1(const integer_class &i)
1123{
1124 return mpz_scan1(get_mpz_t(i), 0);
1125}
1126
1127inline void mp_fib_ui(integer_class &res, unsigned long n)
1128{
1129 mpz_fib_ui(get_mpz_t(res), n);
1130 mp_demote(res);
1131}
1132
1133inline void mp_fib2_ui(integer_class &a, integer_class &b, unsigned long n)
1134{
1135 mpz_fib2_ui(get_mpz_t(a), get_mpz_t(b), n);
1136 mp_demote(a);
1137 mp_demote(b);
1138}
1139
1140inline void mp_lucnum_ui(integer_class &res, unsigned long n)
1141{
1142 mpz_lucnum_ui(get_mpz_t(res), n);
1143 mp_demote(res);
1144}
1145
1146inline void mp_lucnum2_ui(integer_class &a, integer_class &b, unsigned long n)
1147{
1148 mpz_lucnum2_ui(get_mpz_t(a), get_mpz_t(b), n);
1149 mp_demote(a);
1150 mp_demote(b);
1151}
1152
1153inline void mp_bin_ui(integer_class &res, const integer_class &n,
1154 unsigned long r)
1155{
1156 auto _res = get_mpz_t(res);
1157 mpz_bin_ui(_res, get_mpz_t(n), r);
1158 mp_demote(res);
1159}
1160
1161inline void mp_fac_ui(integer_class &res, unsigned long n)
1162{
1163 mpz_fac_ui(get_mpz_t(res), n);
1164 mp_demote(res);
1165}
1166
1167inline int mp_legendre(const integer_class &a, const integer_class &n)
1168{
1169 return mpz_legendre(get_mpz_t(a), get_mpz_t(n));
1170}
1171
1172inline int mp_kronecker(const integer_class &a, const integer_class &n)
1173{
1174 return mpz_kronecker(get_mpz_t(a), get_mpz_t(n));
1175}
1176
1177inline int mp_jacobi(const integer_class &a, const integer_class &n)
1178{
1179 return mpz_jacobi(get_mpz_t(a), get_mpz_t(n));
1180}
1181
1182inline bool mp_perfect_power_p(const integer_class &i)
1183{
1184 return mpz_perfect_power_p(get_mpz_t(i)) != 0;
1185}
1186
1187inline bool mp_perfect_square_p(const integer_class &i)
1188{
1189 return mpz_perfect_square_p(get_mpz_t(i)) != 0;
1190}
1191
1192inline int mp_probab_prime_p(const integer_class &i, unsigned retries)
1193{
1194 return mpz_probab_prime_p(get_mpz_t(i), retries);
1195}
1196
1197inline bool mp_divisible_p(const integer_class &a, const integer_class &b)
1198{
1199 return mpz_divisible_p(get_mpz_t(a), get_mpz_t(b)) != 0;
1200}
1201
1202inline void mp_urandomm(integer_class &a, gmp_randstate_t &t,
1203 const integer_class &b)
1204{
1205 auto _a = get_mpz_t(a);
1206 mpz_urandomm(_a, t, get_mpz_t(b));
1207 mp_demote(a);
1208}
1209
1210inline auto get_mp_t(const integer_class &x) -> decltype(get_mpz_t(x))
1211{
1212 return get_mpz_t(x);
1213}
1214
1215inline auto get_mp_t(const rational_class &x) -> decltype(get_mpq_t(x))
1216{
1217 return get_mpq_t(x);
1218}
1219
1220inline int mp_cmpabs(const integer_class &a, const integer_class &b)
1221{
1222 return mpz_cmpabs(get_mpz_t(a), get_mpz_t(b));
1223}
1224
1226{
1227public:
1228 // returns a uniformly distributed random integer between 0 and a-1,
1229 // inclusive
1230 void urandomint(integer_class &res, const integer_class &a)
1231 {
1232 mpz_urandomm(get_mpz_t(res), _state, get_mpz_t(a));
1233 mp_demote(res);
1234 }
1235
1236 void seed(const integer_class &i)
1237 {
1238 gmp_randseed(_state, get_mpz_t(i));
1239 }
1240
1241 mp_randstate()
1242 {
1243 gmp_randinit_default(_state);
1244 gmp_randseed_ui(_state, std::rand());
1245 }
1246
1248 {
1249 gmp_randclear(_state);
1250 }
1251
1252private:
1253 gmp_randstate_t _state;
1254};
1255
1256#endif // SYMENGINE_INTEGER_CLASS == Piranha or Flint or GMP or GMPXX
1257
1258} // namespace SymEngine
1259
1260#if !defined(HAVE_SYMENGINE_GMP) && defined(HAVE_SYMENGINE_BOOST) \
1261 && BOOST_VERSION < 105900
1262namespace boost
1263{
1264namespace detail
1265{
1266template <>
1267struct make_unsigned_imp<SymEngine::integer_class> {
1268 typedef SymEngine::integer_class type;
1269};
1270} // namespace detail
1271} // namespace boost
1272#endif
1273
1274#endif // SYMENGINE_INTEGER_CLASS_H
T c_str(T... args)
Main namespace for SymEngine package.
Definition: add.cpp:19
RCP< const Integer > gcd(const Integer &a, const Integer &b)
Greatest Common Divisor.
Definition: ntheory.cpp:31
T rand(T... args)
T strlen(T... args)