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