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::handle_nan || Policy::handle_infinity)
00038 && ::sgn(v.get_den()) == 0) {
00039 int s = ::sgn(v.get_num());
00040 if (Policy::handle_nan && (nan || sign) && s == 0)
00041 return VC_NAN;
00042 if (!inf && !sign)
00043 return VC_NORMAL;
00044 if (Policy::handle_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(mpq, mpq_class)
00057
00058 template <typename Policy>
00059 inline bool
00060 is_nan_mpq(const mpq_class& v) {
00061 return Policy::handle_nan
00062 && ::sgn(v.get_den()) == 0
00063 && ::sgn(v.get_num()) == 0;
00064 }
00065
00066 SPECIALIZE_IS_NAN(mpq, mpq_class)
00067
00068 template <typename Policy>
00069 inline bool
00070 is_minf_mpq(const mpq_class& v) {
00071 return Policy::handle_infinity
00072 && ::sgn(v.get_den()) == 0
00073 && ::sgn(v.get_num()) < 0;
00074 }
00075
00076 SPECIALIZE_IS_MINF(mpq, mpq_class)
00077
00078 template <typename Policy>
00079 inline bool
00080 is_pinf_mpq(const mpq_class& v) {
00081 return Policy::handle_infinity
00082 && ::sgn(v.get_den()) == 0
00083 && ::sgn(v.get_num()) > 0;
00084 }
00085
00086 SPECIALIZE_IS_PINF(mpq, mpq_class)
00087
00088 template <typename Policy>
00089 inline bool
00090 is_int_mpq(const mpq_class& v) {
00091 return !is_nan<Policy>(v) && v.get_den() == 1;
00092 }
00093
00094 SPECIALIZE_IS_INT(mpq, mpq_class)
00095
00096 template <typename Policy>
00097 inline Result
00098 set_special_mpq(mpq_class& v, Result r) {
00099 Result c = classify(r);
00100 if (Policy::handle_nan && c == VC_NAN) {
00101 v.get_num() = 0;
00102 v.get_den() = 0;
00103 }
00104 else if (Policy::handle_infinity) {
00105 switch (c) {
00106 case VC_MINUS_INFINITY:
00107 v.get_num() = -1;
00108 v.get_den() = 0;
00109 break;
00110 case VC_PLUS_INFINITY:
00111 v.get_num() = 1;
00112 v.get_den() = 0;
00113 break;
00114 default:
00115 break;
00116 }
00117 }
00118 return r;
00119 }
00120
00121 SPECIALIZE_SET_SPECIAL(mpq, mpq_class)
00122
00123 SPECIALIZE_COPY(generic, mpq_class)
00124
00125 template <typename Policy, typename From>
00126 inline Result
00127 construct_mpq_base(mpq_class& to, const From& from, Rounding_Dir) {
00128 new (&to) mpq_class(from);
00129 return V_EQ;
00130 }
00131
00132 SPECIALIZE_CONSTRUCT(mpq_base, mpq_class, mpz_class)
00133 SPECIALIZE_CONSTRUCT(mpq_base, mpq_class, signed char)
00134 SPECIALIZE_CONSTRUCT(mpq_base, mpq_class, signed short)
00135 SPECIALIZE_CONSTRUCT(mpq_base, mpq_class, signed int)
00136 SPECIALIZE_CONSTRUCT(mpq_base, mpq_class, signed long)
00137 SPECIALIZE_CONSTRUCT(mpq_base, mpq_class, unsigned char)
00138 SPECIALIZE_CONSTRUCT(mpq_base, mpq_class, unsigned short)
00139 SPECIALIZE_CONSTRUCT(mpq_base, mpq_class, unsigned int)
00140 SPECIALIZE_CONSTRUCT(mpq_base, mpq_class, unsigned long)
00141 SPECIALIZE_CONSTRUCT(mpq_base, mpq_class, float)
00142 SPECIALIZE_CONSTRUCT(mpq_base, mpq_class, double)
00143
00144 template <typename Policy, typename From>
00145 inline Result
00146 construct_mpq_long_double(mpq_class& to, const From& from, Rounding_Dir dir) {
00147
00148 new (&to) mpq_class;
00149 std::stringstream ss;
00150 output_float<Policy, long double>(ss, from, Numeric_Format(), dir);
00151 return input_mpq(to, ss);
00152 }
00153
00154 SPECIALIZE_CONSTRUCT(mpq_long_double, mpq_class, long double)
00155
00156 template <typename Policy, typename From>
00157 inline Result
00158 assign_mpq_base(mpq_class& to, const From& from, Rounding_Dir) {
00159 to = from;
00160 return V_EQ;
00161 }
00162
00163 SPECIALIZE_ASSIGN(mpq_base, mpq_class, mpz_class)
00164 SPECIALIZE_ASSIGN(mpq_base, mpq_class, signed char)
00165 SPECIALIZE_ASSIGN(mpq_base, mpq_class, signed short)
00166 SPECIALIZE_ASSIGN(mpq_base, mpq_class, signed int)
00167 SPECIALIZE_ASSIGN(mpq_base, mpq_class, signed long)
00168 SPECIALIZE_ASSIGN(mpq_base, mpq_class, unsigned char)
00169 SPECIALIZE_ASSIGN(mpq_base, mpq_class, unsigned short)
00170 SPECIALIZE_ASSIGN(mpq_base, mpq_class, unsigned int)
00171 SPECIALIZE_ASSIGN(mpq_base, mpq_class, unsigned long)
00172 SPECIALIZE_ASSIGN(mpq_base, mpq_class, float)
00173 SPECIALIZE_ASSIGN(mpq_base, mpq_class, double)
00174
00175 template <typename Policy, typename From>
00176 inline Result
00177 assign_mpq_signed_int(mpq_class& to, const From from, Rounding_Dir) {
00178 if (sizeof(From) <= sizeof(signed long))
00179 to = static_cast<signed long>(from);
00180 else {
00181 mpz_ptr m = to.get_num().get_mpz_t();
00182 if (from >= 0)
00183 mpz_import(m, 1, 1, sizeof(From), 0, 0, &from);
00184 else {
00185 From n = -from;
00186 mpz_import(m, 1, 1, sizeof(From), 0, 0, &n);
00187 mpz_neg(m, m);
00188 }
00189 to.get_den() = 1;
00190 }
00191 return V_EQ;
00192 }
00193
00194 SPECIALIZE_ASSIGN(mpq_signed_int, mpq_class, signed long long)
00195
00196 template <typename Policy, typename From>
00197 inline Result
00198 assign_mpq_unsigned_int(mpq_class& to, const From from, Rounding_Dir) {
00199 if (sizeof(From) <= sizeof(unsigned long))
00200 to = static_cast<unsigned long>(from);
00201 else {
00202 mpz_import(to.get_num().get_mpz_t(), 1, 1, sizeof(From), 0, 0, &from);
00203 to.get_den() = 1;
00204 }
00205 return V_EQ;
00206 }
00207
00208 SPECIALIZE_ASSIGN(mpq_unsigned_int, mpq_class, unsigned long long)
00209
00210 template <typename Policy, typename From>
00211 inline Result
00212 assign_mpq_long_double(mpq_class& to, const From& from, Rounding_Dir dir) {
00213
00214 std::stringstream ss;
00215 output_float<Policy, long double>(ss, from, Numeric_Format(), dir);
00216 return input_mpq(to, ss);
00217 }
00218
00219 SPECIALIZE_ASSIGN(mpq_long_double, mpq_class, long double)
00220
00221 template <typename Policy>
00222 inline Result
00223 neg_mpq(mpq_class& to, const mpq_class& from, Rounding_Dir) {
00224 mpq_neg(to.get_mpq_t(), from.get_mpq_t());
00225 return V_EQ;
00226 }
00227
00228 SPECIALIZE_NEG(mpq, mpq_class, mpq_class)
00229
00230 template <typename Policy>
00231 inline Result
00232 add_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y, Rounding_Dir) {
00233 to = x + y;
00234 return V_EQ;
00235 }
00236
00237 SPECIALIZE_ADD(mpq, mpq_class, mpq_class, mpq_class)
00238
00239 template <typename Policy>
00240 inline Result
00241 sub_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y, Rounding_Dir) {
00242 to = x - y;
00243 return V_EQ;
00244 }
00245
00246 SPECIALIZE_SUB(mpq, mpq_class, mpq_class, mpq_class)
00247
00248 template <typename Policy>
00249 inline Result
00250 mul_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y, Rounding_Dir) {
00251 to = x * y;
00252 return V_EQ;
00253 }
00254
00255 SPECIALIZE_MUL(mpq, mpq_class, mpq_class, mpq_class)
00256
00257 template <typename Policy>
00258 inline Result
00259 div_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y, Rounding_Dir) {
00260 if (CHECK_P(Policy::check_div_zero, sgn(y) == 0))
00261 return set_special<Policy>(to, V_DIV_ZERO);
00262 to = x / y;
00263 return V_EQ;
00264 }
00265
00266 SPECIALIZE_DIV(mpq, mpq_class, mpq_class, mpq_class)
00267
00268 template <typename Policy>
00269 inline Result
00270 rem_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y, Rounding_Dir) {
00271 if (CHECK_P(Policy::check_div_zero, sgn(y) == 0))
00272 return set_special<Policy>(to, V_MOD_ZERO);
00273 to = x / y;
00274 to.get_num() %= to.get_den();
00275 return V_EQ;
00276 }
00277
00278 SPECIALIZE_REM(mpq, mpq_class, mpq_class, mpq_class)
00279
00280 template <typename Policy>
00281 inline Result
00282 mul2exp_mpq(mpq_class& to, const mpq_class& x, int exp, Rounding_Dir dir) {
00283 if (exp < 0)
00284 return div2exp<Policy>(to, x, -exp, dir);
00285 mpz_mul_2exp(to.get_num().get_mpz_t(), x.get_num().get_mpz_t(), exp);
00286 to.get_den() = x.get_den();
00287 to.canonicalize();
00288 return V_EQ;
00289 }
00290
00291 SPECIALIZE_MUL2EXP(mpq, mpq_class, mpq_class)
00292
00293 template <typename Policy>
00294 inline Result
00295 div2exp_mpq(mpq_class& to, const mpq_class& x, int exp, Rounding_Dir dir) {
00296 if (exp < 0)
00297 return mul2exp<Policy>(to, x, -exp, dir);
00298 to.get_num() = x.get_num();
00299 mpz_mul_2exp(to.get_den().get_mpz_t(), x.get_den().get_mpz_t(), exp);
00300 to.canonicalize();
00301 return V_EQ;
00302 }
00303
00304 SPECIALIZE_DIV2EXP(mpq, mpq_class, mpq_class)
00305
00306 template <typename Policy>
00307 inline Result
00308 abs_mpq(mpq_class& to, const mpq_class& from, Rounding_Dir) {
00309 to = abs(from);
00310 return V_EQ;
00311 }
00312
00313 SPECIALIZE_ABS(mpq, mpq_class, mpq_class)
00314
00315 template <typename Policy>
00316 inline Result
00317 add_mul_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y,
00318 Rounding_Dir) {
00319 to += x * y;
00320 return V_EQ;
00321 }
00322
00323 SPECIALIZE_ADD_MUL(mpq, mpq_class, mpq_class, mpq_class)
00324
00325 template <typename Policy>
00326 inline Result
00327 sub_mul_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y,
00328 Rounding_Dir) {
00329 to -= x * y;
00330 return V_EQ;
00331 }
00332
00333 SPECIALIZE_SUB_MUL(mpq, mpq_class, mpq_class, mpq_class)
00334
00335 extern unsigned long rational_sqrt_precision_parameter;
00336
00337 template <typename Policy>
00338 inline Result
00339 sqrt_mpq(mpq_class& to, const mpq_class& from, Rounding_Dir dir) {
00340 if (CHECK_P(Policy::check_sqrt_neg, from < 0))
00341 return set_special<Policy>(to, V_SQRT_NEG);
00342 const unsigned long k = rational_sqrt_precision_parameter;
00343 mpz_class& to_num = to.get_num();
00344 mul2exp<Policy>(to_num, from.get_num(), 2*k, dir);
00345 Result rdiv = div<Policy>(to_num, to_num, from.get_den(), dir);
00346 Result rsqrt = sqrt<Policy>(to_num, to_num, dir);
00347 mpz_class& to_den = to.get_den();
00348 to_den = 1;
00349 mul2exp<Policy>(to_den, to_den, k, dir);
00350 to.canonicalize();
00351 return rdiv != V_EQ ? rdiv : rsqrt;
00352 }
00353
00354 SPECIALIZE_SQRT(mpq, mpq_class, mpq_class)
00355
00356 template <typename Policy>
00357 inline Result
00358 input_mpq(mpq_class& to, std::istream& is, Rounding_Dir dir) {
00359 Result r = input_mpq(to, is);
00360 if (r == VC_MINUS_INFINITY)
00361 return assign<Policy>(to, MINUS_INFINITY, dir);
00362 if (r == VC_PLUS_INFINITY)
00363 return assign<Policy>(to, PLUS_INFINITY, dir);
00364 return set_special<Policy>(to, r);
00365 }
00366
00367 template <typename Policy>
00368 inline Result
00369 output_mpq(std::ostream& os,
00370 const mpq_class& from,
00371 const Numeric_Format&,
00372 Rounding_Dir) {
00373 os << from;
00374 return V_EQ;
00375 }
00376
00377 SPECIALIZE_INPUT(mpq, mpq_class)
00378 SPECIALIZE_OUTPUT(mpq, mpq_class)
00379
00380 inline memory_size_type
00381 external_memory_in_bytes(const mpq_class& x) {
00382 return external_memory_in_bytes(x.get_num())
00383 + external_memory_in_bytes(x.get_den());
00384 }
00385
00386 }
00387
00389 inline unsigned
00390 rational_sqrt_precision_parameter() {
00391 return Checked::rational_sqrt_precision_parameter;
00392 }
00393
00395
00402 inline void
00403 set_rational_sqrt_precision_parameter(const unsigned p) {
00404 if (p <= INT_MAX)
00405 Checked::rational_sqrt_precision_parameter = p;
00406 else
00407 throw std::invalid_argument("PPL::set_rational_sqrt_precision_parameter(p)"
00408 " with p > INT_MAX");
00409 }
00410
00411 }
00412
00413 #endif // !defined(PPL_checked_mpq_inlines_hh)