00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef PPL_checked_mpq_inlines_hh
00025 #define PPL_checked_mpq_inlines_hh 1
00026
00027 #include <sstream>
00028 #include <climits>
00029 #include <stdexcept>
00030
00031 namespace Parma_Polyhedra_Library {
00032
00033 namespace Checked {
00034
00035 template <typename Policy>
00036 inline Result
00037 classify_mpq(const mpq_class& v, bool nan, bool inf, bool sign) {
00038 if ((Policy::has_nan || Policy::has_infinity)
00039 && ::sgn(v.get_den()) == 0) {
00040 int s = ::sgn(v.get_num());
00041 if (Policy::has_nan && (nan || sign) && s == 0)
00042 return V_NAN;
00043 if (!inf && !sign)
00044 return V_LGE;
00045 if (Policy::has_infinity) {
00046 if (s < 0)
00047 return inf ? V_EQ_MINUS_INFINITY : V_LT;
00048 if (s > 0)
00049 return inf ? V_EQ_PLUS_INFINITY : V_GT;
00050 }
00051 }
00052 if (sign)
00053 return (Result) sgn<Policy>(v);
00054 return V_LGE;
00055 }
00056
00057 PPL_SPECIALIZE_CLASSIFY(classify_mpq, mpq_class)
00058
00059 template <typename Policy>
00060 inline bool
00061 is_nan_mpq(const mpq_class& v) {
00062 return Policy::has_nan
00063 && ::sgn(v.get_den()) == 0
00064 && ::sgn(v.get_num()) == 0;
00065 }
00066
00067 PPL_SPECIALIZE_IS_NAN(is_nan_mpq, mpq_class)
00068
00069 template <typename Policy>
00070 inline bool
00071 is_minf_mpq(const mpq_class& v) {
00072 return Policy::has_infinity
00073 && ::sgn(v.get_den()) == 0
00074 && ::sgn(v.get_num()) < 0;
00075 }
00076
00077 PPL_SPECIALIZE_IS_MINF(is_minf_mpq, mpq_class)
00078
00079 template <typename Policy>
00080 inline bool
00081 is_pinf_mpq(const mpq_class& v) {
00082 return Policy::has_infinity
00083 && ::sgn(v.get_den()) == 0
00084 && ::sgn(v.get_num()) > 0;
00085 }
00086
00087 PPL_SPECIALIZE_IS_PINF(is_pinf_mpq, mpq_class)
00088
00089 template <typename Policy>
00090 inline bool
00091 is_int_mpq(const mpq_class& v) {
00092 if ((Policy::has_infinity || Policy::has_nan)
00093 && ::sgn(v.get_den()) == 0)
00094 return !(Policy::has_nan && ::sgn(v.get_num()) == 0);
00095 else
00096 return v.get_den() == 1;
00097 }
00098
00099 PPL_SPECIALIZE_IS_INT(is_int_mpq, mpq_class)
00100
00101 template <typename Policy>
00102 inline Result
00103 assign_special_mpq(mpq_class& v, Result_Class c, Rounding_Dir) {
00104 switch (c) {
00105 case VC_NAN:
00106 if (Policy::has_nan) {
00107 v.get_num() = 0;
00108 v.get_den() = 0;
00109 return V_NAN | V_UNREPRESENTABLE;
00110 }
00111 return V_NAN;
00112 case VC_MINUS_INFINITY:
00113 if (Policy::has_infinity) {
00114 v.get_num() = -1;
00115 v.get_den() = 0;
00116 return V_EQ_MINUS_INFINITY;
00117 }
00118 return V_EQ_MINUS_INFINITY | V_UNREPRESENTABLE;
00119 case VC_PLUS_INFINITY:
00120 if (Policy::has_infinity) {
00121 v.get_num() = 1;
00122 v.get_den() = 0;
00123 return V_EQ_PLUS_INFINITY;
00124 }
00125 return V_EQ_PLUS_INFINITY | V_UNREPRESENTABLE;
00126 default:
00127 PPL_ASSERT(false);
00128 return V_NAN | V_UNREPRESENTABLE;
00129 }
00130 }
00131
00132 PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_mpq, mpq_class)
00133
00134 PPL_SPECIALIZE_COPY(copy_generic, mpq_class)
00135
00136 template <typename To_Policy, typename From_Policy, typename From>
00137 inline Result
00138 construct_mpq_base(mpq_class& to, const From& from, Rounding_Dir) {
00139 new (&to) mpq_class(from);
00140 return V_EQ;
00141 }
00142
00143 PPL_SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, mpz_class)
00144 PPL_SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, char)
00145 PPL_SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, signed char)
00146 PPL_SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, signed short)
00147 PPL_SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, signed int)
00148 PPL_SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, signed long)
00149 PPL_SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, unsigned char)
00150 PPL_SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, unsigned short)
00151 PPL_SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, unsigned int)
00152 PPL_SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, unsigned long)
00153
00154 template <typename To_Policy, typename From_Policy, typename From>
00155 inline Result
00156 construct_mpq_float(mpq_class& to, const From& from, Rounding_Dir dir) {
00157 if (is_nan<From_Policy>(from))
00158 return construct_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
00159 else if (is_minf<From_Policy>(from))
00160 return construct_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
00161 else if (is_pinf<From_Policy>(from))
00162 return construct_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
00163 new (&to) mpq_class(from);
00164 return V_EQ;
00165 }
00166
00167 PPL_SPECIALIZE_CONSTRUCT(construct_mpq_float, mpq_class, float)
00168 PPL_SPECIALIZE_CONSTRUCT(construct_mpq_float, mpq_class, double)
00169
00170 PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, mpq_class)
00171 PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, mpz_class)
00172 PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, char)
00173 PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, signed char)
00174 PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, signed short)
00175 PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, signed int)
00176 PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, signed long)
00177 PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, unsigned char)
00178 PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, unsigned short)
00179 PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, unsigned int)
00180 PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, unsigned long)
00181
00182 template <typename To_Policy, typename From_Policy, typename From>
00183 inline Result
00184 assign_mpq_float(mpq_class& to, const From& from, Rounding_Dir dir) {
00185 if (is_nan<From_Policy>(from))
00186 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
00187 else if (is_minf<From_Policy>(from))
00188 return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
00189 else if (is_pinf<From_Policy>(from))
00190 return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
00191 to = from;
00192 return V_EQ;
00193 }
00194
00195 PPL_SPECIALIZE_ASSIGN(assign_mpq_float, mpq_class, float)
00196 PPL_SPECIALIZE_ASSIGN(assign_mpq_float, mpq_class, double)
00197
00198 template <typename To_Policy, typename From_Policy, typename From>
00199 inline Result
00200 assign_mpq_signed_int(mpq_class& to, const From from, Rounding_Dir) {
00201 if (sizeof(From) <= sizeof(signed long))
00202 to = static_cast<signed long>(from);
00203 else {
00204 mpz_ptr m = to.get_num().get_mpz_t();
00205 if (from >= 0)
00206 mpz_import(m, 1, 1, sizeof(From), 0, 0, &from);
00207 else {
00208 From n = -from;
00209 mpz_import(m, 1, 1, sizeof(From), 0, 0, &n);
00210 mpz_neg(m, m);
00211 }
00212 to.get_den() = 1;
00213 }
00214 return V_EQ;
00215 }
00216
00217 PPL_SPECIALIZE_ASSIGN(assign_mpq_signed_int, mpq_class, signed long long)
00218
00219 template <typename To_Policy, typename From_Policy, typename From>
00220 inline Result
00221 assign_mpq_unsigned_int(mpq_class& to, const From from, Rounding_Dir) {
00222 if (sizeof(From) <= sizeof(unsigned long))
00223 to = static_cast<unsigned long>(from);
00224 else {
00225 mpz_import(to.get_num().get_mpz_t(), 1, 1, sizeof(From), 0, 0, &from);
00226 to.get_den() = 1;
00227 }
00228 return V_EQ;
00229 }
00230
00231 PPL_SPECIALIZE_ASSIGN(assign_mpq_unsigned_int, mpq_class, unsigned long long)
00232
00233 template <typename To_Policy, typename From_Policy>
00234 inline Result
00235 floor_mpq(mpq_class& to, const mpq_class& from, Rounding_Dir) {
00236 mpz_fdiv_q(to.get_num().get_mpz_t(),
00237 from.get_num().get_mpz_t(), from.get_den().get_mpz_t());
00238 to.get_den() = 1;
00239 return V_EQ;
00240 }
00241
00242 PPL_SPECIALIZE_FLOOR(floor_mpq, mpq_class, mpq_class)
00243
00244 template <typename To_Policy, typename From_Policy>
00245 inline Result
00246 ceil_mpq(mpq_class& to, const mpq_class& from, Rounding_Dir) {
00247 mpz_cdiv_q(to.get_num().get_mpz_t(),
00248 from.get_num().get_mpz_t(), from.get_den().get_mpz_t());
00249 to.get_den() = 1;
00250 return V_EQ;
00251 }
00252
00253 PPL_SPECIALIZE_CEIL(ceil_mpq, mpq_class, mpq_class)
00254
00255 template <typename To_Policy, typename From_Policy>
00256 inline Result
00257 trunc_mpq(mpq_class& to, const mpq_class& from, Rounding_Dir) {
00258 mpz_tdiv_q(to.get_num().get_mpz_t(),
00259 from.get_num().get_mpz_t(), from.get_den().get_mpz_t());
00260 to.get_den() = 1;
00261 return V_EQ;
00262 }
00263
00264 PPL_SPECIALIZE_TRUNC(trunc_mpq, mpq_class, mpq_class)
00265
00266 template <typename To_Policy, typename From_Policy>
00267 inline Result
00268 neg_mpq(mpq_class& to, const mpq_class& from, Rounding_Dir) {
00269 mpq_neg(to.get_mpq_t(), from.get_mpq_t());
00270 return V_EQ;
00271 }
00272
00273 PPL_SPECIALIZE_NEG(neg_mpq, mpq_class, mpq_class)
00274
00275 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
00276 inline Result
00277 add_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y, Rounding_Dir) {
00278 to = x + y;
00279 return V_EQ;
00280 }
00281
00282 PPL_SPECIALIZE_ADD(add_mpq, mpq_class, mpq_class, mpq_class)
00283
00284 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
00285 inline Result
00286 sub_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y, Rounding_Dir) {
00287 to = x - y;
00288 return V_EQ;
00289 }
00290
00291 PPL_SPECIALIZE_SUB(sub_mpq, mpq_class, mpq_class, mpq_class)
00292
00293 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
00294 inline Result
00295 mul_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y, Rounding_Dir) {
00296 to = x * y;
00297 return V_EQ;
00298 }
00299
00300 PPL_SPECIALIZE_MUL(mul_mpq, mpq_class, mpq_class, mpq_class)
00301
00302 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
00303 inline Result
00304 div_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y, Rounding_Dir) {
00305 if (CHECK_P(To_Policy::check_div_zero, sgn(y) == 0)) {
00306 return assign_nan<To_Policy>(to, V_DIV_ZERO);
00307 }
00308 to = x / y;
00309 return V_EQ;
00310 }
00311
00312 PPL_SPECIALIZE_DIV(div_mpq, mpq_class, mpq_class, mpq_class)
00313
00314 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
00315 inline Result
00316 idiv_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y, Rounding_Dir dir) {
00317 if (CHECK_P(To_Policy::check_div_zero, sgn(y) == 0)) {
00318 return assign_nan<To_Policy>(to, V_DIV_ZERO);
00319 }
00320 to = x / y;
00321 return trunc<To_Policy, To_Policy>(to, to, dir);
00322 }
00323
00324 PPL_SPECIALIZE_IDIV(idiv_mpq, mpq_class, mpq_class, mpq_class)
00325
00326 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
00327 inline Result
00328 rem_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y, Rounding_Dir) {
00329 if (CHECK_P(To_Policy::check_div_zero, sgn(y) == 0)) {
00330 return assign_nan<To_Policy>(to, V_MOD_ZERO);
00331 }
00332 PPL_DIRTY_TEMP(mpq_class, tmp);
00333 tmp = x / y;
00334 tmp.get_num() %= tmp.get_den();
00335 to = tmp * y;
00336 return V_EQ;
00337 }
00338
00339 PPL_SPECIALIZE_REM(rem_mpq, mpq_class, mpq_class, mpq_class)
00340
00341 template <typename To_Policy, typename From_Policy>
00342 inline Result
00343 add_2exp_mpq(mpq_class& to, const mpq_class& x, unsigned int exp,
00344 Rounding_Dir) {
00345 PPL_DIRTY_TEMP(mpz_class, v);
00346 v = 1;
00347 mpz_mul_2exp(v.get_mpz_t(), v.get_mpz_t(), exp);
00348 to = x + v;
00349 return V_EQ;
00350 }
00351
00352 PPL_SPECIALIZE_ADD_2EXP(add_2exp_mpq, mpq_class, mpq_class)
00353
00354 template <typename To_Policy, typename From_Policy>
00355 inline Result
00356 sub_2exp_mpq(mpq_class& to, const mpq_class& x, unsigned int exp,
00357 Rounding_Dir) {
00358 PPL_DIRTY_TEMP(mpz_class, v);
00359 v = 1;
00360 mpz_mul_2exp(v.get_mpz_t(), v.get_mpz_t(), exp);
00361 to = x - v;
00362 return V_EQ;
00363 }
00364
00365 PPL_SPECIALIZE_SUB_2EXP(sub_2exp_mpq, mpq_class, mpq_class)
00366
00367 template <typename To_Policy, typename From_Policy>
00368 inline Result
00369 mul_2exp_mpq(mpq_class& to, const mpq_class& x, unsigned int exp,
00370 Rounding_Dir) {
00371 mpz_mul_2exp(to.get_num().get_mpz_t(), x.get_num().get_mpz_t(), exp);
00372 to.get_den() = x.get_den();
00373 to.canonicalize();
00374 return V_EQ;
00375 }
00376
00377 PPL_SPECIALIZE_MUL_2EXP(mul_2exp_mpq, mpq_class, mpq_class)
00378
00379 template <typename To_Policy, typename From_Policy>
00380 inline Result
00381 div_2exp_mpq(mpq_class& to, const mpq_class& x, unsigned int exp,
00382 Rounding_Dir) {
00383 to.get_num() = x.get_num();
00384 mpz_mul_2exp(to.get_den().get_mpz_t(), x.get_den().get_mpz_t(), exp);
00385 to.canonicalize();
00386 return V_EQ;
00387 }
00388
00389 PPL_SPECIALIZE_DIV_2EXP(div_2exp_mpq, mpq_class, mpq_class)
00390
00391 template <typename To_Policy, typename From_Policy>
00392 inline Result
00393 smod_2exp_mpq(mpq_class& to, const mpq_class& x, unsigned int exp,
00394 Rounding_Dir) {
00395 mpz_mul_2exp(to.get_den().get_mpz_t(), x.get_den().get_mpz_t(), exp);
00396 mpz_fdiv_r(to.get_num().get_mpz_t(), x.get_num().get_mpz_t(), to.get_den().get_mpz_t());
00397 mpz_fdiv_q_2exp(to.get_den().get_mpz_t(), to.get_den().get_mpz_t(), 1);
00398 bool neg = to.get_num() >= to.get_den();
00399 mpz_mul_2exp(to.get_den().get_mpz_t(), to.get_den().get_mpz_t(), 1);
00400 if (neg)
00401 to.get_num() -= to.get_den();
00402 mpz_mul_2exp(to.get_num().get_mpz_t(), to.get_num().get_mpz_t(), exp);
00403 to.canonicalize();
00404 return V_EQ;
00405 }
00406
00407 PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_mpq, mpq_class, mpq_class)
00408
00409 template <typename To_Policy, typename From_Policy>
00410 inline Result
00411 umod_2exp_mpq(mpq_class& to, const mpq_class& x, unsigned int exp,
00412 Rounding_Dir) {
00413 mpz_mul_2exp(to.get_den().get_mpz_t(), x.get_den().get_mpz_t(), exp);
00414 mpz_fdiv_r(to.get_num().get_mpz_t(), x.get_num().get_mpz_t(), to.get_den().get_mpz_t());
00415 mpz_mul_2exp(to.get_num().get_mpz_t(), to.get_num().get_mpz_t(), exp);
00416 to.canonicalize();
00417 return V_EQ;
00418 }
00419
00420 PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_mpq, mpq_class, mpq_class)
00421
00422 template <typename To_Policy, typename From_Policy>
00423 inline Result
00424 abs_mpq(mpq_class& to, const mpq_class& from, Rounding_Dir) {
00425 to = abs(from);
00426 return V_EQ;
00427 }
00428
00429 PPL_SPECIALIZE_ABS(abs_mpq, mpq_class, mpq_class)
00430
00431 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
00432 inline Result
00433 add_mul_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y,
00434 Rounding_Dir) {
00435 to += x * y;
00436 return V_EQ;
00437 }
00438
00439 PPL_SPECIALIZE_ADD_MUL(add_mul_mpq, mpq_class, mpq_class, mpq_class)
00440
00441 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
00442 inline Result
00443 sub_mul_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y,
00444 Rounding_Dir) {
00445 to -= x * y;
00446 return V_EQ;
00447 }
00448
00449 PPL_SPECIALIZE_SUB_MUL(sub_mul_mpq, mpq_class, mpq_class, mpq_class)
00450
00451 extern unsigned irrational_precision;
00452
00453 template <typename To_Policy, typename From_Policy>
00454 inline Result
00455 sqrt_mpq(mpq_class& to, const mpq_class& from, Rounding_Dir dir) {
00456 if (CHECK_P(To_Policy::check_sqrt_neg, from < 0)) {
00457 return assign_nan<To_Policy>(to, V_SQRT_NEG);
00458 }
00459 if (from == 0) {
00460 to = 0;
00461 return V_EQ;
00462 }
00463 bool gt1 = from.get_num() > from.get_den();
00464 const mpz_class& from_a = gt1 ? from.get_num() : from.get_den();
00465 const mpz_class& from_b = gt1 ? from.get_den() : from.get_num();
00466 mpz_class& to_a = gt1 ? to.get_num() : to.get_den();
00467 mpz_class& to_b = gt1 ? to.get_den() : to.get_num();
00468 Rounding_Dir rdir = gt1 ? dir : inverse(dir);
00469 mul_2exp<To_Policy, From_Policy>(to_a, from_a,
00470 2*irrational_precision, ROUND_IGNORE);
00471 Result rdiv
00472 = div<To_Policy, To_Policy, To_Policy>(to_a, to_a, from_b, rdir);
00473 Result rsqrt = sqrt<To_Policy, To_Policy>(to_a, to_a, rdir);
00474 to_b = 1;
00475 mul_2exp<To_Policy, To_Policy>(to_b, to_b,
00476 irrational_precision, ROUND_IGNORE);
00477 to.canonicalize();
00478 return rdiv != V_EQ ? rdiv : rsqrt;
00479 }
00480
00481 PPL_SPECIALIZE_SQRT(sqrt_mpq, mpq_class, mpq_class)
00482
00483 template <typename Policy>
00484 inline Result
00485 input_mpq(mpq_class& to, std::istream& is, Rounding_Dir dir) {
00486 Result r = input_mpq(to, is);
00487 Result_Class c = result_class(r);
00488 switch (c) {
00489 case VC_MINUS_INFINITY:
00490 case VC_PLUS_INFINITY:
00491 return assign_special<Policy>(to, c, dir);
00492 case VC_NAN:
00493 return assign_nan<Policy>(to, r);
00494 default:
00495 return r;
00496 }
00497 }
00498
00499 PPL_SPECIALIZE_INPUT(input_mpq, mpq_class)
00500
00501 template <typename Policy>
00502 inline Result
00503 output_mpq(std::ostream& os,
00504 const mpq_class& from,
00505 const Numeric_Format&,
00506 Rounding_Dir) {
00507 os << from;
00508 return V_EQ;
00509 }
00510
00511 PPL_SPECIALIZE_OUTPUT(output_mpq, mpq_class)
00512
00513 template <typename To_Policy, typename From_Policy, typename From>
00514 inline Result
00515 assign_mpq_long_double(mpq_class& to, const From& from, Rounding_Dir dir) {
00516 if (is_nan<From_Policy>(from))
00517 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
00518 else if (is_minf<From_Policy>(from))
00519 return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
00520 else if (is_pinf<From_Policy>(from))
00521 return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
00522
00523 std::stringstream ss;
00524 output<From_Policy>(ss, from, Numeric_Format(), dir);
00525 return input_mpq(to, ss);
00526 }
00527
00528 PPL_SPECIALIZE_ASSIGN(assign_mpq_long_double, mpq_class, long double)
00529
00530 }
00531
00533 inline unsigned
00534 irrational_precision() {
00535 return Checked::irrational_precision;
00536 }
00537
00539
00547 inline void
00548 set_irrational_precision(const unsigned p) {
00549 if (p <= INT_MAX)
00550 Checked::irrational_precision = p;
00551 else
00552 throw std::invalid_argument("PPL::set_irrational_precision(p)"
00553 " with p > INT_MAX");
00554 }
00555
00556 }
00557
00558 #endif // !defined(PPL_checked_mpq_inlines_hh)