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_mpq_inlines_hh
00024 #define PPL_checked_mpq_inlines_hh 1
00025
00026 #include <sstream>
00027 #include <climits>
00028 #include <stdexcept>
00029
00030 namespace Parma_Polyhedra_Library {
00031
00032 namespace Checked {
00033
00034 template <typename Policy>
00035 inline Result
00036 classify_mpq(const mpq_class& v, bool nan, bool inf, bool sign) {
00037 if ((Policy::has_nan || Policy::has_infinity)
00038 && ::sgn(v.get_den()) == 0) {
00039 int s = ::sgn(v.get_num());
00040 if (Policy::has_nan && (nan || sign) && s == 0)
00041 return VC_NAN;
00042 if (!inf && !sign)
00043 return VC_NORMAL;
00044 if (Policy::has_infinity) {
00045 if (s < 0)
00046 return inf ? VC_MINUS_INFINITY : V_LT;
00047 if (s > 0)
00048 return inf ? VC_PLUS_INFINITY : V_GT;
00049 }
00050 }
00051 if (sign)
00052 return sgn<Policy>(v);
00053 return VC_NORMAL;
00054 }
00055
00056 SPECIALIZE_CLASSIFY(classify_mpq, mpq_class)
00057
00058 template <typename Policy>
00059 inline bool
00060 is_nan_mpq(const mpq_class& v) {
00061 return Policy::has_nan
00062 && ::sgn(v.get_den()) == 0
00063 && ::sgn(v.get_num()) == 0;
00064 }
00065
00066 SPECIALIZE_IS_NAN(is_nan_mpq, mpq_class)
00067
00068 template <typename Policy>
00069 inline bool
00070 is_minf_mpq(const mpq_class& v) {
00071 return Policy::has_infinity
00072 && ::sgn(v.get_den()) == 0
00073 && ::sgn(v.get_num()) < 0;
00074 }
00075
00076 SPECIALIZE_IS_MINF(is_minf_mpq, mpq_class)
00077
00078 template <typename Policy>
00079 inline bool
00080 is_pinf_mpq(const mpq_class& v) {
00081 return Policy::has_infinity
00082 && ::sgn(v.get_den()) == 0
00083 && ::sgn(v.get_num()) > 0;
00084 }
00085
00086 SPECIALIZE_IS_PINF(is_pinf_mpq, mpq_class)
00087
00088 template <typename Policy>
00089 inline bool
00090 is_int_mpq(const mpq_class& v) {
00091 if ((Policy::has_infinity || Policy::has_nan)
00092 && ::sgn(v.get_den()) == 0)
00093 return !(Policy::has_nan && ::sgn(v.get_num()) == 0);
00094 else
00095 return v.get_den() == 1;
00096 }
00097
00098 SPECIALIZE_IS_INT(is_int_mpq, mpq_class)
00099
00100 template <typename Policy>
00101 inline Result
00102 assign_special_mpq(mpq_class& v, Result r, Rounding_Dir) {
00103 Result c = classify(r);
00104 if (Policy::has_nan && c == VC_NAN) {
00105 v.get_num() = 0;
00106 v.get_den() = 0;
00107 }
00108 else if (Policy::has_infinity) {
00109 switch (c) {
00110 case VC_MINUS_INFINITY:
00111 v.get_num() = -1;
00112 v.get_den() = 0;
00113 return V_EQ;
00114 case VC_PLUS_INFINITY:
00115 v.get_num() = 1;
00116 v.get_den() = 0;
00117 return V_EQ;
00118 default:
00119 break;
00120 }
00121 }
00122 return r;
00123 }
00124
00125 SPECIALIZE_ASSIGN_SPECIAL(assign_special_mpq, mpq_class)
00126
00127 SPECIALIZE_COPY(copy_generic, mpq_class)
00128
00129 template <typename To_Policy, typename From_Policy, typename From>
00130 inline Result
00131 construct_mpq_base(mpq_class& to, const From& from, Rounding_Dir) {
00132 new (&to) mpq_class(from);
00133 return V_EQ;
00134 }
00135
00136 SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, mpz_class)
00137 SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, signed char)
00138 SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, signed short)
00139 SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, signed int)
00140 SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, signed long)
00141 SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, unsigned char)
00142 SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, unsigned short)
00143 SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, unsigned int)
00144 SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, unsigned long)
00145
00146 template <typename To_Policy, typename From_Policy, typename From>
00147 inline Result
00148 construct_mpq_float(mpq_class& to, const From& from, Rounding_Dir dir) {
00149 if (is_nan<From_Policy>(from))
00150 return construct_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
00151 else if (is_minf<From_Policy>(from))
00152 return construct_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
00153 else if (is_pinf<From_Policy>(from))
00154 return construct_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
00155 new (&to) mpq_class(from);
00156 return V_EQ;
00157 }
00158
00159 SPECIALIZE_CONSTRUCT(construct_mpq_float, mpq_class, float)
00160 SPECIALIZE_CONSTRUCT(construct_mpq_float, mpq_class, double)
00161
00162 SPECIALIZE_ASSIGN(assign_exact, mpq_class, mpq_class)
00163 SPECIALIZE_ASSIGN(assign_exact, mpq_class, mpz_class)
00164 SPECIALIZE_ASSIGN(assign_exact, mpq_class, signed char)
00165 SPECIALIZE_ASSIGN(assign_exact, mpq_class, signed short)
00166 SPECIALIZE_ASSIGN(assign_exact, mpq_class, signed int)
00167 SPECIALIZE_ASSIGN(assign_exact, mpq_class, signed long)
00168 SPECIALIZE_ASSIGN(assign_exact, mpq_class, unsigned char)
00169 SPECIALIZE_ASSIGN(assign_exact, mpq_class, unsigned short)
00170 SPECIALIZE_ASSIGN(assign_exact, mpq_class, unsigned int)
00171 SPECIALIZE_ASSIGN(assign_exact, mpq_class, unsigned long)
00172
00173 template <typename To_Policy, typename From_Policy, typename From>
00174 inline Result
00175 assign_mpq_float(mpq_class& to, const From& from, Rounding_Dir dir) {
00176 if (is_nan<From_Policy>(from))
00177 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
00178 else if (is_minf<From_Policy>(from))
00179 return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
00180 else if (is_pinf<From_Policy>(from))
00181 return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
00182 to = from;
00183 return V_EQ;
00184 }
00185
00186 SPECIALIZE_ASSIGN(assign_mpq_float, mpq_class, float)
00187 SPECIALIZE_ASSIGN(assign_mpq_float, mpq_class, double)
00188
00189 template <typename To_Policy, typename From_Policy, typename From>
00190 inline Result
00191 assign_mpq_signed_int(mpq_class& to, const From from, Rounding_Dir) {
00192 if (sizeof(From) <= sizeof(signed long))
00193 to = static_cast<signed long>(from);
00194 else {
00195 mpz_ptr m = to.get_num().get_mpz_t();
00196 if (from >= 0)
00197 mpz_import(m, 1, 1, sizeof(From), 0, 0, &from);
00198 else {
00199 From n = -from;
00200 mpz_import(m, 1, 1, sizeof(From), 0, 0, &n);
00201 mpz_neg(m, m);
00202 }
00203 to.get_den() = 1;
00204 }
00205 return V_EQ;
00206 }
00207
00208 SPECIALIZE_ASSIGN(assign_mpq_signed_int, mpq_class, signed long long)
00209
00210 template <typename To_Policy, typename From_Policy, typename From>
00211 inline Result
00212 assign_mpq_unsigned_int(mpq_class& to, const From from, Rounding_Dir) {
00213 if (sizeof(From) <= sizeof(unsigned long))
00214 to = static_cast<unsigned long>(from);
00215 else {
00216 mpz_import(to.get_num().get_mpz_t(), 1, 1, sizeof(From), 0, 0, &from);
00217 to.get_den() = 1;
00218 }
00219 return V_EQ;
00220 }
00221
00222 SPECIALIZE_ASSIGN(assign_mpq_unsigned_int, mpq_class, unsigned long long)
00223
00224 template <typename To_Policy, typename From_Policy>
00225 inline Result
00226 floor_mpq(mpq_class& to, const mpq_class& from, Rounding_Dir) {
00227 mpz_fdiv_q(to.get_num().get_mpz_t(),
00228 from.get_num().get_mpz_t(), from.get_den().get_mpz_t());
00229 to.get_den() = 1;
00230 return V_EQ;
00231 }
00232
00233 SPECIALIZE_FLOOR(floor_mpq, mpq_class, mpq_class)
00234
00235 template <typename To_Policy, typename From_Policy>
00236 inline Result
00237 ceil_mpq(mpq_class& to, const mpq_class& from, Rounding_Dir) {
00238 mpz_cdiv_q(to.get_num().get_mpz_t(),
00239 from.get_num().get_mpz_t(), from.get_den().get_mpz_t());
00240 to.get_den() = 1;
00241 return V_EQ;
00242 }
00243
00244 SPECIALIZE_CEIL(ceil_mpq, mpq_class, mpq_class)
00245
00246 template <typename To_Policy, typename From_Policy>
00247 inline Result
00248 trunc_mpq(mpq_class& to, const mpq_class& from, Rounding_Dir) {
00249 mpz_tdiv_q(to.get_num().get_mpz_t(),
00250 from.get_num().get_mpz_t(), from.get_den().get_mpz_t());
00251 to.get_den() = 1;
00252 return V_EQ;
00253 }
00254
00255 SPECIALIZE_TRUNC(trunc_mpq, mpq_class, mpq_class)
00256
00257 template <typename To_Policy, typename From_Policy>
00258 inline Result
00259 neg_mpq(mpq_class& to, const mpq_class& from, Rounding_Dir) {
00260 mpq_neg(to.get_mpq_t(), from.get_mpq_t());
00261 return V_EQ;
00262 }
00263
00264 SPECIALIZE_NEG(neg_mpq, mpq_class, mpq_class)
00265
00266 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
00267 inline Result
00268 add_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y, Rounding_Dir) {
00269 to = x + y;
00270 return V_EQ;
00271 }
00272
00273 SPECIALIZE_ADD(add_mpq, mpq_class, mpq_class, mpq_class)
00274
00275 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
00276 inline Result
00277 sub_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 SPECIALIZE_SUB(sub_mpq, mpq_class, mpq_class, mpq_class)
00283
00284 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
00285 inline Result
00286 mul_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 SPECIALIZE_MUL(mul_mpq, mpq_class, mpq_class, mpq_class)
00292
00293 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
00294 inline Result
00295 div_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y, Rounding_Dir) {
00296 if (CHECK_P(To_Policy::check_div_zero, sgn(y) == 0))
00297 return assign_special<To_Policy>(to, V_DIV_ZERO, ROUND_IGNORE);
00298 to = x / y;
00299 return V_EQ;
00300 }
00301
00302 SPECIALIZE_DIV(div_mpq, mpq_class, mpq_class, mpq_class)
00303
00304 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
00305 inline Result
00306 idiv_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y, Rounding_Dir dir) {
00307 if (CHECK_P(To_Policy::check_div_zero, sgn(y) == 0))
00308 return assign_special<To_Policy>(to, V_DIV_ZERO, ROUND_IGNORE);
00309 to = x / y;
00310 return trunc<To_Policy, To_Policy>(to, to, dir);
00311 }
00312
00313 SPECIALIZE_IDIV(idiv_mpq, mpq_class, mpq_class, mpq_class)
00314
00315 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
00316 inline Result
00317 rem_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y, Rounding_Dir) {
00318 if (CHECK_P(To_Policy::check_div_zero, sgn(y) == 0))
00319 return assign_special<To_Policy>(to, V_MOD_ZERO, ROUND_IGNORE);
00320 to = x / y;
00321 to.get_num() %= to.get_den();
00322 return V_EQ;
00323 }
00324
00325 SPECIALIZE_REM(rem_mpq, mpq_class, mpq_class, mpq_class)
00326
00327 template <typename To_Policy, typename From_Policy>
00328 inline Result
00329 mul2exp_mpq(mpq_class& to, const mpq_class& x, int exp, Rounding_Dir dir) {
00330 if (exp < 0)
00331 return div2exp<To_Policy, From_Policy>(to, x, -exp, dir);
00332 mpz_mul_2exp(to.get_num().get_mpz_t(), x.get_num().get_mpz_t(), exp);
00333 to.get_den() = x.get_den();
00334 to.canonicalize();
00335 return V_EQ;
00336 }
00337
00338 SPECIALIZE_MUL2EXP(mul2exp_mpq, mpq_class, mpq_class)
00339
00340 template <typename To_Policy, typename From_Policy>
00341 inline Result
00342 div2exp_mpq(mpq_class& to, const mpq_class& x, int exp, Rounding_Dir dir) {
00343 if (exp < 0)
00344 return mul2exp<To_Policy, From_Policy>(to, x, -exp, dir);
00345 to.get_num() = x.get_num();
00346 mpz_mul_2exp(to.get_den().get_mpz_t(), x.get_den().get_mpz_t(), exp);
00347 to.canonicalize();
00348 return V_EQ;
00349 }
00350
00351 SPECIALIZE_DIV2EXP(div2exp_mpq, mpq_class, mpq_class)
00352
00353 template <typename To_Policy, typename From_Policy>
00354 inline Result
00355 abs_mpq(mpq_class& to, const mpq_class& from, Rounding_Dir) {
00356 to = abs(from);
00357 return V_EQ;
00358 }
00359
00360 SPECIALIZE_ABS(abs_mpq, mpq_class, mpq_class)
00361
00362 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
00363 inline Result
00364 add_mul_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y,
00365 Rounding_Dir) {
00366 to += x * y;
00367 return V_EQ;
00368 }
00369
00370 SPECIALIZE_ADD_MUL(add_mul_mpq, mpq_class, mpq_class, mpq_class)
00371
00372 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
00373 inline Result
00374 sub_mul_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y,
00375 Rounding_Dir) {
00376 to -= x * y;
00377 return V_EQ;
00378 }
00379
00380 SPECIALIZE_SUB_MUL(sub_mul_mpq, mpq_class, mpq_class, mpq_class)
00381
00382 extern unsigned long rational_sqrt_precision_parameter;
00383
00384 template <typename To_Policy, typename From_Policy>
00385 inline Result
00386 sqrt_mpq(mpq_class& to, const mpq_class& from, Rounding_Dir dir) {
00387 if (CHECK_P(To_Policy::check_sqrt_neg, from < 0))
00388 return assign_special<To_Policy>(to, V_SQRT_NEG, ROUND_IGNORE);
00389 const unsigned long k = rational_sqrt_precision_parameter;
00390 mpz_class& to_num = to.get_num();
00391 mul2exp<To_Policy, From_Policy>(to_num, from.get_num(), 2*k, dir);
00392 Result rdiv
00393 = div<To_Policy, To_Policy, To_Policy>(to_num,
00394 to_num, from.get_den(), dir);
00395 Result rsqrt = sqrt<To_Policy, To_Policy>(to_num, to_num, dir);
00396 mpz_class& to_den = to.get_den();
00397 to_den = 1;
00398 mul2exp<To_Policy, To_Policy>(to_den, to_den, k, dir);
00399 to.canonicalize();
00400 return rdiv != V_EQ ? rdiv : rsqrt;
00401 }
00402
00403 SPECIALIZE_SQRT(sqrt_mpq, mpq_class, mpq_class)
00404
00405 template <typename Policy>
00406 inline Result
00407 input_mpq(mpq_class& to, std::istream& is, Rounding_Dir) {
00408 Result r = input_mpq(to, is);
00409 switch (classify(r)) {
00410 case VC_MINUS_INFINITY:
00411 case VC_PLUS_INFINITY:
00412 case VC_NAN:
00413 return assign_special<Policy>(to, r, ROUND_IGNORE);
00414 default:
00415 return r;
00416 }
00417 }
00418
00419 SPECIALIZE_INPUT(input_mpq, mpq_class)
00420
00421 template <typename Policy>
00422 inline Result
00423 output_mpq(std::ostream& os,
00424 const mpq_class& from,
00425 const Numeric_Format&,
00426 Rounding_Dir) {
00427 os << from;
00428 return V_EQ;
00429 }
00430
00431 SPECIALIZE_OUTPUT(output_mpq, mpq_class)
00432
00433 template <typename To_Policy, typename From_Policy, typename From>
00434 inline Result
00435 assign_mpq_long_double(mpq_class& to, const From& from, Rounding_Dir dir) {
00436 if (is_nan<From_Policy>(from))
00437 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
00438 else if (is_minf<From_Policy>(from))
00439 return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
00440 else if (is_pinf<From_Policy>(from))
00441 return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
00442
00443 std::stringstream ss;
00444 output<From_Policy>(ss, from, Numeric_Format(), dir);
00445 return input_mpq(to, ss);
00446 }
00447
00448 SPECIALIZE_ASSIGN(assign_mpq_long_double, mpq_class, long double)
00449
00450 }
00451
00453 inline unsigned
00454 rational_sqrt_precision_parameter() {
00455 return Checked::rational_sqrt_precision_parameter;
00456 }
00457
00459
00466 inline void
00467 set_rational_sqrt_precision_parameter(const unsigned p) {
00468 if (p <= INT_MAX)
00469 Checked::rational_sqrt_precision_parameter = p;
00470 else
00471 throw std::invalid_argument("PPL::set_rational_sqrt_precision_parameter(p)"
00472 " with p > INT_MAX");
00473 }
00474
00475 }
00476
00477 #endif // !defined(PPL_checked_mpq_inlines_hh)