24 #ifndef PPL_checked_mpz_inlines_hh
25 #define PPL_checked_mpz_inlines_hh 1
33 template <
typename Policy>
43 template <
typename Policy>
53 #if __cplusplus >= 201103L
57 typedef typeof(__mpz_struct()._mp_size) mp_size_field_t;
64 inline mp_size_field_t
66 return v.get_mpz_t()->_mp_size;
71 v.get_mpz_t()->_mp_size = size;
74 template <
typename Policy>
77 if (Policy::has_nan || Policy::has_infinity) {
87 if (Policy::has_infinity) {
97 return static_cast<Result>(sgn<Policy>(v));
104 template <typename Policy>
107 return Policy::has_nan
113 template <typename Policy>
116 return Policy::has_infinity
122 template <typename Policy>
125 return Policy::has_infinity
131 template <typename Policy>
134 return !is_nan<Policy>(v);
139 template <typename Policy>
144 if (Policy::has_nan) {
149 if (Policy::has_infinity) {
155 if (Policy::has_infinity) {
168 template <typename To_Policy, typename From_Policy>
171 if (is_nan_mpz<From_Policy>(from)) {
172 PPL_ASSERT(To_Policy::has_nan);
174 else if (is_minf_mpz<From_Policy>(from) || is_pinf_mpz<From_Policy>(from)) {
175 PPL_ASSERT(To_Policy::has_infinity);
186 template <typename To_Policy, typename From_Policy, typename
From>
189 new(&to) mpz_class(from);
203 template <typename To_Policy, typename From_Policy, typename
From>
206 if (is_nan<From_Policy>(from)) {
209 else if (is_minf<From_Policy>(from)) {
212 else if (is_pinf<From_Policy>(from)) {
216 new(&to) mpz_class(from);
220 new(&to) mpz_class(n);
225 return round_lt_mpz<To_Policy>(to, dir);
228 return round_gt_mpz<To_Policy>(to, dir);
246 template <typename To_Policy, typename From_Policy, typename
From>
249 if (
sizeof(
From) <=
sizeof(
signed long)) {
250 to =
static_cast<signed long>(from);
253 mpz_ptr m = to.get_mpz_t();
255 mpz_import(m, 1, 1,
sizeof(
From), 0, 0, &from);
259 mpz_import(m, 1, 1,
sizeof(
From), 0, 0, &n);
268 template <
typename To_Policy,
typename From_Policy,
typename From>
271 if (
sizeof(
From) <=
sizeof(
unsigned long)) {
272 to =
static_cast<unsigned long>(from);
275 mpz_import(to.get_mpz_t(), 1, 1,
sizeof(
From), 0, 0, &from);
282 template <
typename To_Policy,
typename From_Policy,
typename From>
285 if (is_nan<From_Policy>(from)) {
288 else if (is_minf<From_Policy>(from)) {
291 else if (is_pinf<From_Policy>(from)) {
298 From i_from = rint(from);
300 if (from == i_from) {
304 return round_lt_mpz<To_Policy>(to, dir);
307 return round_gt_mpz<To_Policy>(to, dir);
310 return round_lt_mpz<To_Policy>(to, dir);
313 return round_gt_mpz<To_Policy>(to, dir);
322 template <typename To_Policy, typename From_Policy, typename
From>
325 if (is_nan<From_Policy>(from)) {
328 else if (is_minf<From_Policy>(from)) {
331 else if (is_pinf<From_Policy>(from)) {
335 std::stringstream ss;
342 PPL_ASSERT(r ==
V_EQ);
343 return assign<To_Policy, From_Policy>(to, tmp, dir);
348 template <
typename To_Policy,
typename From_Policy>
359 const mpz_srcptr n = from.get_num().get_mpz_t();
360 const mpz_srcptr d = from.get_den().get_mpz_t();
362 mpz_fdiv_q(to.get_mpz_t(), n, d);
364 return (mpz_divisible_p(n, d) != 0) ?
V_EQ :
V_GT;
370 mpz_cdiv_q(to.get_mpz_t(), n, d);
372 return (mpz_divisible_p(n, d) != 0) ?
V_EQ :
V_LT;
384 template <typename To_Policy, typename From_Policy>
387 mpz_neg(to.get_mpz_t(), from.get_mpz_t());
393 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
402 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
411 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
420 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
424 if (
CHECK_P(To_Policy::check_div_zero, ::
sgn(y) == 0)) {
427 const mpz_srcptr n = x.get_mpz_t();
428 const mpz_srcptr d = y.get_mpz_t();
430 mpz_divexact(to.get_mpz_t(), n, d);
434 mpz_cdiv_q(to.get_mpz_t(), n, d);
438 mpz_fdiv_q(to.get_mpz_t(), n, d);
440 return (mpz_divisible_p(n, d) != 0) ?
V_EQ :
V_GT;
446 mpz_cdiv_q(to.get_mpz_t(), n, d);
448 return (mpz_divisible_p(n, d) != 0) ?
V_EQ :
V_LT;
456 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
460 if (
CHECK_P(To_Policy::check_div_zero, ::
sgn(y) == 0)) {
463 mpz_srcptr n = x.get_mpz_t();
464 mpz_srcptr d = y.get_mpz_t();
465 mpz_tdiv_q(to.get_mpz_t(), n, d);
471 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
474 if (
CHECK_P(To_Policy::check_div_zero, ::
sgn(y) == 0)) {
483 template <typename To_Policy, typename From_Policy>
489 mpz_mul_2exp(v.get_mpz_t(), v.get_mpz_t(), exp);
496 template <typename To_Policy, typename From_Policy>
502 mpz_mul_2exp(v.get_mpz_t(), v.get_mpz_t(), exp);
509 template <typename To_Policy, typename From_Policy>
513 mpz_mul_2exp(to.get_mpz_t(), x.get_mpz_t(), exp);
519 template <typename To_Policy, typename From_Policy>
523 const mpz_srcptr n = x.get_mpz_t();
525 mpz_tdiv_q_2exp(to.get_mpz_t(), x.get_mpz_t(), exp);
529 mpz_fdiv_q_2exp(to.get_mpz_t(), n, exp);
531 return (mpz_divisible_2exp_p(n, exp) != 0) ?
V_EQ :
V_GT;
537 mpz_cdiv_q_2exp(to.get_mpz_t(), n, exp);
539 return (mpz_divisible_2exp_p(n, exp) != 0) ?
V_EQ :
V_LT;
547 template <typename To_Policy, typename From_Policy>
551 if (mpz_tstbit(x.get_mpz_t(), exp - 1) != 0) {
552 mpz_cdiv_r_2exp(to.get_mpz_t(), x.get_mpz_t(), exp);
555 mpz_fdiv_r_2exp(to.get_mpz_t(), x.get_mpz_t(), exp);
562 template <typename To_Policy, typename From_Policy>
566 mpz_fdiv_r_2exp(to.get_mpz_t(), x.get_mpz_t(), exp);
572 template <typename To_Policy, typename From_Policy>
581 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
585 mpz_addmul(to.get_mpz_t(), x.get_mpz_t(), y.get_mpz_t());
591 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
595 mpz_submul(to.get_mpz_t(), x.get_mpz_t(), y.get_mpz_t());
601 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
604 mpz_gcd(to.get_mpz_t(), x.get_mpz_t(), y.get_mpz_t());
610 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
615 mpz_gcdext(to.get_mpz_t(), s.get_mpz_t(), t.get_mpz_t(),
616 x.get_mpz_t(), y.get_mpz_t());
622 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
625 mpz_lcm(to.get_mpz_t(), x.get_mpz_t(), y.get_mpz_t());
631 template <typename To_Policy, typename From_Policy>
634 if (
CHECK_P(To_Policy::check_sqrt_neg, from < 0)) {
642 mpz_sqrtrem(to.get_mpz_t(), r.get_mpz_t(), from.get_mpz_t());
646 return round_gt_mpz<To_Policy>(to, dir);
651 template <typename Policy, typename
Type>
654 const int sign =
::sgn(x);
661 template <typename Policy1, typename Policy2, typename
Type>
671 template <typename Policy>
686 #endif // !defined(PPL_checked_mpz_inlines_hh)
#define PPL_SPECIALIZE_NEG(func, To, From)
Result lcm_mpz(mpz_class &to, const mpz_class &x, const mpz_class &y, Rounding_Dir)
The computed result is exact.
Result assign_mpz_unsigned_int(mpz_class &to, const From from, Rounding_Dir)
Taking the square root of a negative number.
Result sqrt_mpz(mpz_class &to, const mpz_class &from, Rounding_Dir dir)
Result neg_mpz(mpz_class &to, const mpz_class &from, Rounding_Dir)
#define PPL_SPECIALIZE_ADD_MUL(func, To, From1, From2)
#define PPL_SPECIALIZE_IS_MINF(func, Type)
mp_size_field_t get_mp_size(const mpz_class &v)
Result mul_mpz(mpz_class &to, const mpz_class &x, const mpz_class &y, Rounding_Dir)
Rounding_Dir
Rounding directions for arithmetic computations.
#define PPL_SPECIALIZE_SQRT(func, To, From)
Result add_2exp_mpz(mpz_class &to, const mpz_class &x, unsigned int exp, Rounding_Dir)
Result assign_mpz_float(mpz_class &to, const From from, Rounding_Dir dir)
Computing a remainder modulo zero.
void set_mp_size(mpz_class &v, mp_size_field_t size)
#define PPL_SPECIALIZE_CLASSIFY(func, Type)
bool round_ignore(Rounding_Dir dir)
#define PPL_SPECIALIZE_ADD(func, To, From1, From2)
bool round_strict_relation(Rounding_Dir dir)
int mp_size_field_t
This is assumed to be the type of the _mp_size field of GMP's __mpz_struct.
Result
Possible outcomes of a checked arithmetic computation.
Result construct_mpz_base(mpz_class &to, const From from, Rounding_Dir)
The standard C++ namespace.
#define PPL_SPECIALIZE_REM(func, To, From1, From2)
Negative infinity result class.
Not a number result class.
Result classify_mpz(const mpz_class &v, bool nan, bool inf, bool sign)
bool is_nan_mpz(const mpz_class &v)
#define PPL_SPECIALIZE_ABS(func, To, From)
Result input_generic(Type &to, std::istream &is, Rounding_Dir dir)
Result idiv_mpz(mpz_class &to, const mpz_class &x, const mpz_class &y, Rounding_Dir)
#define PPL_SPECIALIZE_UMOD_2EXP(func, To, From)
PPL_SPECIALIZE_GCDEXT(gcdext_exact, char, char, char, char, char) PPL_SPECIALIZE_GCDEXT(gcdext_exact
Result construct_mpz_float(mpz_class &to, const From &from, Rounding_Dir dir)
The computed result is inexact and rounded down.
Result round_gt_mpz(mpz_class &to, Rounding_Dir dir)
#define PPL_SPECIALIZE_TRUNC(func, To, From)
#define PPL_SPECIALIZE_CMP(func, Type1, Type2)
#define PPL_SPECIALIZE_CEIL(func, To, From)
#define PPL_SPECIALIZE_DIV(func, To, From1, From2)
void copy_mpz(mpz_class &to, const mpz_class &from)
Result add_mpz(mpz_class &to, const mpz_class &x, const mpz_class &y, Rounding_Dir)
Result div_2exp_mpz(mpz_class &to, const mpz_class &x, unsigned int exp, Rounding_Dir dir)
#define PPL_SPECIALIZE_IDIV(func, To, From1, From2)
Result mul_2exp_mpz(mpz_class &to, const mpz_class &x, unsigned int exp, Rounding_Dir)
Result sub_mul_mpz(mpz_class &to, const mpz_class &x, const mpz_class &y, Rounding_Dir)
#define PPL_SPECIALIZE_MUL_2EXP(func, To, From)
Result umod_2exp_mpz(mpz_class &to, const mpz_class &x, unsigned int exp, Rounding_Dir)
Positive infinity result class.
Result gcdext_mpz(mpz_class &to, mpz_class &s, mpz_class &t, const mpz_class &x, const mpz_class &y, Rounding_Dir)
Result assign_mpz_long_double(mpz_class &to, const From &from, Rounding_Dir dir)
bool is_pinf_mpz(const mpz_class &v)
bool round_not_needed(Rounding_Dir dir)
The computed result is not representable.
bool is_minf_mpz(const mpz_class &v)
Result add_mul_mpz(mpz_class &to, const mpz_class &x, const mpz_class &y, Rounding_Dir)
#define PPL_SPECIALIZE_SUB(func, To, From1, From2)
#define PPL_SPECIALIZE_ASSIGN_SPECIAL(func, Type)
Negative infinity result.
bool is_int_mpz(const mpz_class &v)
Equal. This need to be accompanied by a value.
Less than. This need to be accompanied by a value.
Result sub_mpz(mpz_class &to, const mpz_class &x, const mpz_class &y, Rounding_Dir)
bool round_up(Rounding_Dir dir)
#define PPL_SPECIALIZE_ADD_2EXP(func, To, From)
Result round_lt_mpz(mpz_class &to, Rounding_Dir dir)
#define PPL_SPECIALIZE_GCD(func, To, From1, From2)
#define PPL_SPECIALIZE_SUB_MUL(func, To, From1, From2)
Result abs_mpz(mpz_class &to, const mpz_class &from, Rounding_Dir)
The computed result may be inexact and rounded up.
Result assign_mpz_mpq(mpz_class &to, const mpq_class &from, Rounding_Dir dir)
#define PPL_DIRTY_TEMP(T, id)
#define PPL_SPECIALIZE_IS_INT(func, Type)
#define PPL_SPECIALIZE_FLOOR(func, To, From)
Result gcd_mpz(mpz_class &to, const mpz_class &x, const mpz_class &y, Rounding_Dir)
#define PPL_SPECIALIZE_CONSTRUCT(func, To, From)
Result sub_2exp_mpz(mpz_class &to, const mpz_class &x, unsigned int exp, Rounding_Dir)
Result assign_exact(To &to, const From &from, Rounding_Dir)
Result_Relation cmp_mp(const Type &x, const Type &y)
Result assign_mpz_signed_int(mpz_class &to, const From from, Rounding_Dir)
The entire library is confined to this namespace.
#define PPL_SPECIALIZE_DIV_2EXP(func, To, From)
Result_Relation sgn_mp(const Type &x)
Greater than. This need to be accompanied by a value.
bool round_direct(Rounding_Dir dir)
int cmp(const GMP_Integer &x, const GMP_Integer &y)
The computed result may be inexact and rounded down.
From bool Type Type Rounding_Dir From
Result input_mpq(mpq_class &to, std::istream &is)
Result output_mpz(std::ostream &os, const mpz_class &from, const Numeric_Format &, Rounding_Dir)
#define PPL_SPECIALIZE_IS_NAN(func, Type)
int sgn(Boundary_Type type, const T &x, const Info &info)
#define PPL_SPECIALIZE_ASSIGN(func, To, From)
Positive infinity result.
#define PPL_SPECIALIZE_SUB_2EXP(func, To, From)
Result rem_mpz(mpz_class &to, const mpz_class &x, const mpz_class &y, Rounding_Dir)
#define PPL_SPECIALIZE_COPY(func, Type)
Result assign_special_mpz(mpz_class &v, Result_Class c, Rounding_Dir)
#define PPL_SPECIALIZE_LCM(func, To, From1, From2)
#define CHECK_P(cond, check)
#define PPL_SPECIALIZE_OUTPUT(func, Type)
The computed result is inexact and rounded up.
The computed result may be inexact.
#define PPL_SPECIALIZE_INPUT(func, Type)
bool round_down(Rounding_Dir dir)
#define PPL_SPECIALIZE_SMOD_2EXP(func, To, From)
bool round_not_requested(Rounding_Dir dir)
#define PPL_SPECIALIZE_MUL(func, To, From1, From2)
#define PPL_SPECIALIZE_IS_PINF(func, Type)
#define PPL_SPECIALIZE_SGN(func, From)
Result smod_2exp_mpz(mpz_class &to, const mpz_class &x, unsigned int exp, Rounding_Dir)
Result div_mpz(mpz_class &to, const mpz_class &x, const mpz_class &y, Rounding_Dir dir)