00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef PPL_checked_mpz_inlines_hh
00024 #define PPL_checked_mpz_inlines_hh 1
00025
00026 #include <sstream>
00027
00028 namespace Parma_Polyhedra_Library {
00029
00030 namespace Checked {
00031
00032 template <typename Policy>
00033 inline Result
00034 round_lt_mpz(mpz_class& to, Rounding_Dir dir) {
00035 if (round_down(dir)) {
00036 --to;
00037 return V_GT;
00038 }
00039 return V_LT;
00040 }
00041
00042 template <typename Policy>
00043 inline Result
00044 round_gt_mpz(mpz_class& to, Rounding_Dir dir) {
00045 if (round_up(dir)) {
00046 ++to;
00047 return V_LT;
00048 }
00049 return V_GT;
00050 }
00051
00052 #ifdef PPL_HAVE_TYPEOF
00054 typedef typeof(__mpz_struct()._mp_size) mp_size_field_t;
00055 #else
00057 typedef int mp_size_field_t;
00058 #endif
00059
00060 inline mp_size_field_t
00061 get_mp_size(const mpz_class &v) {
00062 return v.get_mpz_t()->_mp_size;
00063 }
00064
00065 inline void
00066 set_mp_size(mpz_class &v, mp_size_field_t size) {
00067 v.get_mpz_t()->_mp_size = size;
00068 }
00069
00070 template <typename Policy>
00071 inline Result
00072 classify_mpz(const mpz_class& v, bool nan, bool inf, bool sign) {
00073 if (Policy::has_nan || Policy::has_infinity) {
00074 mp_size_field_t s = get_mp_size(v);
00075 if (Policy::has_nan
00076 && (nan || sign)
00077 && s == C_Integer<mp_size_field_t>::min + 1)
00078 return VC_NAN;
00079 if (!inf && !sign)
00080 return VC_NORMAL;
00081 if (Policy::has_infinity) {
00082 if (s == C_Integer<mp_size_field_t>::min)
00083 return inf ? VC_MINUS_INFINITY : V_LT;
00084 if (s == C_Integer<mp_size_field_t>::max)
00085 return inf ? VC_PLUS_INFINITY : V_GT;
00086 }
00087 }
00088 if (sign)
00089 return sgn<Policy>(v);
00090 return VC_NORMAL;
00091 }
00092
00093 SPECIALIZE_CLASSIFY(classify_mpz, mpz_class)
00094
00095 template <typename Policy>
00096 inline bool
00097 is_nan_mpz(const mpz_class& v) {
00098 return Policy::has_nan
00099 && get_mp_size(v) == C_Integer<mp_size_field_t>::min + 1;
00100 }
00101
00102 SPECIALIZE_IS_NAN(is_nan_mpz, mpz_class)
00103
00104 template <typename Policy>
00105 inline bool
00106 is_minf_mpz(const mpz_class& v) {
00107 return Policy::has_infinity
00108 && get_mp_size(v) == C_Integer<mp_size_field_t>::min;
00109 }
00110
00111 SPECIALIZE_IS_MINF(is_minf_mpz, mpz_class)
00112
00113 template <typename Policy>
00114 inline bool
00115 is_pinf_mpz(const mpz_class& v) {
00116 return Policy::has_infinity
00117 && get_mp_size(v) == C_Integer<mp_size_field_t>::max;
00118 }
00119
00120 SPECIALIZE_IS_PINF(is_pinf_mpz, mpz_class)
00121
00122 template <typename Policy>
00123 inline bool
00124 is_int_mpz(const mpz_class& v) {
00125 return !is_nan<Policy>(v);
00126 }
00127
00128 SPECIALIZE_IS_INT(is_int_mpz, mpz_class)
00129
00130 template <typename Policy>
00131 inline Result
00132 assign_special_mpz(mpz_class& v, Result r, Rounding_Dir) {
00133 Result c = classify(r);
00134 if (Policy::has_nan && c == VC_NAN)
00135 set_mp_size(v, C_Integer<mp_size_field_t>::min + 1);
00136 else if (Policy::has_infinity) {
00137 switch (c) {
00138 case VC_MINUS_INFINITY:
00139 set_mp_size(v, C_Integer<mp_size_field_t>::min);
00140 return V_EQ;
00141 case VC_PLUS_INFINITY:
00142 set_mp_size(v, C_Integer<mp_size_field_t>::max);
00143 return V_EQ;
00144 default:
00145 break;
00146 }
00147 }
00148 return r;
00149 }
00150
00151 SPECIALIZE_ASSIGN_SPECIAL(assign_special_mpz, mpz_class)
00152
00153 template <typename To_Policy, typename From_Policy>
00154 inline void
00155 copy_mpz(mpz_class& to, const mpz_class& from) {
00156 if (is_nan_mpz<From_Policy>(from))
00157 assert(To_Policy::has_nan);
00158 else if (is_minf_mpz<From_Policy>(from) || is_pinf_mpz<From_Policy>(from))
00159 assert(To_Policy::has_infinity);
00160 else {
00161 to = from;
00162 return;
00163 }
00164 set_mp_size(to, get_mp_size(from));
00165 }
00166
00167 SPECIALIZE_COPY(copy_mpz, mpz_class)
00168
00169 template <typename To_Policy, typename From_Policy, typename From>
00170 inline Result
00171 construct_mpz_base(mpz_class& to, const From from, Rounding_Dir) {
00172 new (&to) mpz_class(from);
00173 return V_EQ;
00174 }
00175
00176 SPECIALIZE_CONSTRUCT(construct_mpz_base, mpz_class, signed char)
00177 SPECIALIZE_CONSTRUCT(construct_mpz_base, mpz_class, signed short)
00178 SPECIALIZE_CONSTRUCT(construct_mpz_base, mpz_class, signed int)
00179 SPECIALIZE_CONSTRUCT(construct_mpz_base, mpz_class, signed long)
00180 SPECIALIZE_CONSTRUCT(construct_mpz_base, mpz_class, unsigned char)
00181 SPECIALIZE_CONSTRUCT(construct_mpz_base, mpz_class, unsigned short)
00182 SPECIALIZE_CONSTRUCT(construct_mpz_base, mpz_class, unsigned int)
00183 SPECIALIZE_CONSTRUCT(construct_mpz_base, mpz_class, unsigned long)
00184
00185 template <typename To_Policy, typename From_Policy, typename From>
00186 inline Result
00187 construct_mpz_float(mpz_class& to, const From& from, Rounding_Dir dir) {
00188 if (is_nan<From_Policy>(from))
00189 return construct_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
00190 else if (is_minf<From_Policy>(from))
00191 return construct_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
00192 else if (is_pinf<From_Policy>(from))
00193 return construct_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
00194 if (round_ignore(dir)) {
00195 new (&to) mpz_class(from);
00196 return V_LGE;
00197 }
00198 From n = rint(from);
00199 new (&to) mpz_class(n);
00200 if (from < n)
00201 return round_lt_mpz<To_Policy>(to, dir);
00202 else if (from > n)
00203 return round_gt_mpz<To_Policy>(to, dir);
00204 else
00205 return V_EQ;
00206 }
00207
00208 SPECIALIZE_CONSTRUCT(construct_mpz_float, mpz_class, float)
00209 SPECIALIZE_CONSTRUCT(construct_mpz_float, mpz_class, double)
00210
00211 SPECIALIZE_ASSIGN(assign_exact, mpz_class, mpz_class)
00212 SPECIALIZE_ASSIGN(assign_exact, mpz_class, signed char)
00213 SPECIALIZE_ASSIGN(assign_exact, mpz_class, signed short)
00214 SPECIALIZE_ASSIGN(assign_exact, mpz_class, signed int)
00215 SPECIALIZE_ASSIGN(assign_exact, mpz_class, signed long)
00216 SPECIALIZE_ASSIGN(assign_exact, mpz_class, unsigned char)
00217 SPECIALIZE_ASSIGN(assign_exact, mpz_class, unsigned short)
00218 SPECIALIZE_ASSIGN(assign_exact, mpz_class, unsigned int)
00219 SPECIALIZE_ASSIGN(assign_exact, mpz_class, unsigned long)
00220
00221 template <typename To_Policy, typename From_Policy, typename From>
00222 inline Result
00223 assign_mpz_signed_int(mpz_class& to, const From from, Rounding_Dir) {
00224 if (sizeof(From) <= sizeof(signed long))
00225 to = static_cast<signed long>(from);
00226 else {
00227 mpz_ptr m = to.get_mpz_t();
00228 if (from >= 0)
00229 mpz_import(m, 1, 1, sizeof(From), 0, 0, &from);
00230 else {
00231 From n = -from;
00232 mpz_import(m, 1, 1, sizeof(From), 0, 0, &n);
00233 mpz_neg(m, m);
00234 }
00235 }
00236 return V_EQ;
00237 }
00238
00239 SPECIALIZE_ASSIGN(assign_mpz_signed_int, mpz_class, signed long long)
00240
00241 template <typename To_Policy, typename From_Policy, typename From>
00242 inline Result
00243 assign_mpz_unsigned_int(mpz_class& to, const From from, Rounding_Dir) {
00244 if (sizeof(From) <= sizeof(unsigned long))
00245 to = static_cast<unsigned long>(from);
00246 else
00247 mpz_import(to.get_mpz_t(), 1, 1, sizeof(From), 0, 0, &from);
00248 return V_EQ;
00249 }
00250
00251 SPECIALIZE_ASSIGN(assign_mpz_unsigned_int, mpz_class, unsigned long long)
00252
00253 template <typename To_Policy, typename From_Policy, typename From>
00254 inline Result
00255 assign_mpz_float(mpz_class& to, const From from, Rounding_Dir dir) {
00256 if (is_nan<From_Policy>(from))
00257 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
00258 else if (is_minf<From_Policy>(from))
00259 return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
00260 else if (is_pinf<From_Policy>(from))
00261 return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
00262 if (round_ignore(dir)) {
00263 to = from;
00264 return V_LGE;
00265 }
00266 From n = rint(from);
00267 to = n;
00268 if (from < n)
00269 return round_lt_mpz<To_Policy>(to, dir);
00270 else if (from > n)
00271 return round_gt_mpz<To_Policy>(to, dir);
00272 else
00273 return V_EQ;
00274 }
00275
00276 SPECIALIZE_ASSIGN(assign_mpz_float, mpz_class, float)
00277 SPECIALIZE_ASSIGN(assign_mpz_float, mpz_class, double)
00278
00279 template <typename To_Policy, typename From_Policy, typename From>
00280 inline Result
00281 assign_mpz_long_double(mpz_class& to, const From& from, Rounding_Dir dir) {
00282 if (is_nan<From_Policy>(from))
00283 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
00284 else if (is_minf<From_Policy>(from))
00285 return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
00286 else if (is_pinf<From_Policy>(from))
00287 return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
00288
00289 std::stringstream ss;
00290 output<From_Policy>(ss, from, Numeric_Format(), dir);
00291 DIRTY_TEMP0(mpq_class, tmp);
00292 #ifndef NDEBUG
00293 Result r =
00294 #endif
00295 input_mpq(tmp, ss);
00296 assert(r == V_EQ);
00297 return assign<To_Policy, From_Policy>(to, tmp, dir);
00298 }
00299
00300 SPECIALIZE_ASSIGN(assign_mpz_long_double, mpz_class, long double)
00301
00302 template <typename To_Policy, typename From_Policy>
00303 inline Result
00304 assign_mpz_mpq(mpz_class& to, const mpq_class& from, Rounding_Dir dir) {
00305 if (round_ignore(dir)) {
00306 to = from;
00307 return V_LGE;
00308 }
00309 mpz_srcptr n = from.get_num().get_mpz_t();
00310 mpz_srcptr d = from.get_den().get_mpz_t();
00311 if (round_down(dir)) {
00312 mpz_fdiv_q(to.get_mpz_t(), n, d);
00313 return mpz_divisible_p(n, d) ? V_EQ : V_GT;
00314 }
00315 else {
00316 assert(round_up(dir));
00317 mpz_cdiv_q(to.get_mpz_t(), n, d);
00318 return mpz_divisible_p(n, d) ? V_EQ : V_LT;
00319 }
00320 }
00321
00322 SPECIALIZE_ASSIGN(assign_mpz_mpq, mpz_class, mpq_class)
00323
00324 SPECIALIZE_FLOOR(assign_exact, mpz_class, mpz_class)
00325 SPECIALIZE_CEIL(assign_exact, mpz_class, mpz_class)
00326 SPECIALIZE_TRUNC(assign_exact, mpz_class, mpz_class)
00327
00328 template <typename To_Policy, typename From_Policy>
00329 inline Result
00330 neg_mpz(mpz_class& to, const mpz_class& from, Rounding_Dir) {
00331 mpz_neg(to.get_mpz_t(), from.get_mpz_t());
00332 return V_EQ;
00333 }
00334
00335 SPECIALIZE_NEG(neg_mpz, mpz_class, mpz_class)
00336
00337 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
00338 inline Result
00339 add_mpz(mpz_class& to, const mpz_class& x, const mpz_class& y, Rounding_Dir) {
00340 to = x + y;
00341 return V_EQ;
00342 }
00343
00344 SPECIALIZE_ADD(add_mpz, mpz_class, mpz_class, mpz_class)
00345
00346 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
00347 inline Result
00348 sub_mpz(mpz_class& to, const mpz_class& x, const mpz_class& y, Rounding_Dir) {
00349 to = x - y;
00350 return V_EQ;
00351 }
00352
00353 SPECIALIZE_SUB(sub_mpz, mpz_class, mpz_class, mpz_class)
00354
00355 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
00356 inline Result
00357 mul_mpz(mpz_class& to, const mpz_class& x, const mpz_class& y, Rounding_Dir) {
00358 to = x * y;
00359 return V_EQ;
00360 }
00361
00362 SPECIALIZE_MUL(mul_mpz, mpz_class, mpz_class, mpz_class)
00363
00364 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
00365 inline Result
00366 div_mpz(mpz_class& to, const mpz_class& x, const mpz_class& y,
00367 Rounding_Dir dir) {
00368 if (CHECK_P(To_Policy::check_div_zero, ::sgn(y) == 0))
00369 return assign_special<To_Policy>(to, V_DIV_ZERO, ROUND_IGNORE);
00370 mpz_srcptr n = x.get_mpz_t();
00371 mpz_srcptr d = y.get_mpz_t();
00372 if (round_ignore(dir)) {
00373
00374 mpz_divexact(to.get_mpz_t(), n, d);
00375 return V_LGE;
00376 }
00377 if (round_down(dir)) {
00378 mpz_fdiv_q(to.get_mpz_t(), n, d);
00379 return mpz_divisible_p(n, d) ? V_EQ : V_GT;
00380 }
00381 else {
00382 assert(round_up(dir));
00383 mpz_cdiv_q(to.get_mpz_t(), n, d);
00384 return mpz_divisible_p(n, d) ? V_EQ : V_LT;
00385 }
00386 }
00387
00388 SPECIALIZE_DIV(div_mpz, mpz_class, mpz_class, mpz_class)
00389
00390 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
00391 inline Result
00392 idiv_mpz(mpz_class& to, const mpz_class& x, const mpz_class& y,
00393 Rounding_Dir) {
00394 if (CHECK_P(To_Policy::check_div_zero, ::sgn(y) == 0))
00395 return assign_special<To_Policy>(to, V_DIV_ZERO, ROUND_IGNORE);
00396 mpz_srcptr n = x.get_mpz_t();
00397 mpz_srcptr d = y.get_mpz_t();
00398 mpz_tdiv_q(to.get_mpz_t(), n, d);
00399 return V_EQ;
00400 }
00401
00402 SPECIALIZE_IDIV(idiv_mpz, mpz_class, mpz_class, mpz_class)
00403
00404 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
00405 inline Result
00406 rem_mpz(mpz_class& to, const mpz_class& x, const mpz_class& y, Rounding_Dir) {
00407 if (CHECK_P(To_Policy::check_div_zero, ::sgn(y) == 0))
00408 return assign_special<To_Policy>(to, V_MOD_ZERO, ROUND_IGNORE);
00409 to = x % y;
00410 return V_EQ;
00411 }
00412
00413 SPECIALIZE_REM(rem_mpz, mpz_class, mpz_class, mpz_class)
00414
00415 template <typename To_Policy, typename From_Policy>
00416 inline Result
00417 mul2exp_mpz(mpz_class& to, const mpz_class& x, int exp, Rounding_Dir dir) {
00418 if (exp < 0)
00419 return div2exp<To_Policy, From_Policy>(to, x, -exp, dir);
00420 mpz_mul_2exp(to.get_mpz_t(), x.get_mpz_t(), exp);
00421 return V_EQ;
00422 }
00423
00424 SPECIALIZE_MUL2EXP(mul2exp_mpz, mpz_class, mpz_class)
00425
00426 template <typename To_Policy, typename From_Policy>
00427 inline Result
00428 div2exp_mpz(mpz_class& to, const mpz_class& x, int exp, Rounding_Dir dir) {
00429 if (exp < 0)
00430 return mul2exp<To_Policy, From_Policy>(to, x, -exp, dir);
00431 mpz_srcptr n = x.get_mpz_t();
00432 if (round_ignore(dir)) {
00433 mpz_tdiv_q_2exp(to.get_mpz_t(), x.get_mpz_t(), exp);
00434 return V_LGE;
00435 }
00436 if (round_down(dir)) {
00437 mpz_fdiv_q_2exp(to.get_mpz_t(), n, exp);
00438 return mpz_divisible_2exp_p(n, exp) ? V_EQ : V_GT;
00439 }
00440 else {
00441 assert(round_up(dir));
00442 mpz_cdiv_q_2exp(to.get_mpz_t(), n, exp);
00443 return mpz_divisible_2exp_p(n, exp) ? V_EQ : V_LT;
00444 }
00445 }
00446
00447 SPECIALIZE_DIV2EXP(div2exp_mpz, mpz_class, mpz_class)
00448
00449 template <typename To_Policy, typename From_Policy>
00450 inline Result
00451 abs_mpz(mpz_class& to, const mpz_class& from, Rounding_Dir) {
00452 to = abs(from);
00453 return V_EQ;
00454 }
00455
00456 SPECIALIZE_ABS(abs_mpz, mpz_class, mpz_class)
00457
00458 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
00459 inline Result
00460 add_mul_mpz(mpz_class& to, const mpz_class& x, const mpz_class& y,
00461 Rounding_Dir) {
00462 mpz_addmul(to.get_mpz_t(), x.get_mpz_t(), y.get_mpz_t());
00463 return V_EQ;
00464 }
00465
00466 SPECIALIZE_ADD_MUL(add_mul_mpz, mpz_class, mpz_class, mpz_class)
00467
00468 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
00469 inline Result
00470 sub_mul_mpz(mpz_class& to, const mpz_class& x, const mpz_class& y,
00471 Rounding_Dir) {
00472 mpz_submul(to.get_mpz_t(), x.get_mpz_t(), y.get_mpz_t());
00473 return V_EQ;
00474 }
00475
00476 SPECIALIZE_SUB_MUL(sub_mul_mpz, mpz_class, mpz_class, mpz_class)
00477
00478 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
00479 inline Result
00480 gcd_mpz(mpz_class& to, const mpz_class& x, const mpz_class& y, Rounding_Dir) {
00481 mpz_gcd(to.get_mpz_t(), x.get_mpz_t(), y.get_mpz_t());
00482 return V_EQ;
00483 }
00484
00485 SPECIALIZE_GCD(gcd_mpz, mpz_class, mpz_class, mpz_class)
00486
00487 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
00488 inline Result
00489 gcdext_mpz(mpz_class& to, mpz_class& s, mpz_class& t,
00490 const mpz_class& x, const mpz_class& y,
00491 Rounding_Dir) {
00492 mpz_gcdext(to.get_mpz_t(), s.get_mpz_t(), t.get_mpz_t(),
00493 x.get_mpz_t(), y.get_mpz_t());
00494 return V_EQ;
00495 }
00496
00497 SPECIALIZE_GCDEXT(gcdext_mpz, mpz_class, mpz_class, mpz_class, mpz_class, mpz_class)
00498
00499 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
00500 inline Result
00501 lcm_mpz(mpz_class& to, const mpz_class& x, const mpz_class& y, Rounding_Dir) {
00502 mpz_lcm(to.get_mpz_t(), x.get_mpz_t(), y.get_mpz_t());
00503 return V_EQ;
00504 }
00505
00506 SPECIALIZE_LCM(lcm_mpz, mpz_class, mpz_class, mpz_class)
00507
00508 template <typename To_Policy, typename From_Policy>
00509 inline Result
00510 sqrt_mpz(mpz_class& to, const mpz_class& from, Rounding_Dir dir) {
00511 if (CHECK_P(To_Policy::check_sqrt_neg, from < 0))
00512 return assign_special<To_Policy>(to, V_SQRT_NEG, ROUND_IGNORE);
00513 if (round_ignore(dir)) {
00514 to = sqrt(from);
00515 return V_GE;
00516 }
00517 DIRTY_TEMP0(mpz_class, r);
00518 mpz_sqrtrem(to.get_mpz_t(), r.get_mpz_t(), from.get_mpz_t());
00519 if (r == 0)
00520 return V_EQ;
00521 return round_gt_mpz<To_Policy>(to, dir);
00522 }
00523
00524 SPECIALIZE_SQRT(sqrt_mpz, mpz_class, mpz_class)
00525
00526 template <typename Policy, typename Type>
00527 inline Result
00528 sgn_mp(const Type& x) {
00529 int i = ::sgn(x);
00530 return i > 0 ? V_GT : i == 0 ? V_EQ : V_LT;
00531 }
00532
00533 SPECIALIZE_SGN(sgn_mp, mpz_class)
00534 SPECIALIZE_SGN(sgn_mp, mpq_class)
00535
00536 template <typename Policy1, typename Policy2, typename Type>
00537 inline Result
00538 cmp_mp(const Type& x, const Type& y) {
00539 int i = ::cmp(x, y);
00540 return i > 0 ? V_GT : i == 0 ? V_EQ : V_LT;
00541 }
00542
00543 SPECIALIZE_CMP(cmp_mp, mpz_class, mpz_class)
00544 SPECIALIZE_CMP(cmp_mp, mpq_class, mpq_class)
00545
00546 template <typename Policy>
00547 inline Result
00548 output_mpz(std::ostream& os, const mpz_class& from, const Numeric_Format&,
00549 Rounding_Dir) {
00550 os << from;
00551 return V_EQ;
00552 }
00553
00554 SPECIALIZE_INPUT(input_generic, mpz_class)
00555 SPECIALIZE_OUTPUT(output_mpz, mpz_class)
00556
00557 }
00558
00559 }
00560
00561 #endif // !defined(PPL_checked_mpz_inlines_hh)