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_int_inlines_hh
00024 #define PPL_checked_int_inlines_hh 1
00025
00026 #include "Limits.hh"
00027 #include <cerrno>
00028 #include <cstdlib>
00029 #include <climits>
00030 #include <string>
00031 #ifdef HAVE_STDINT_H
00032 #include <stdint.h>
00033 #endif
00034 #ifdef HAVE_INTTYPES_H
00035 #include <inttypes.h>
00036 #endif
00037
00038 #if !HAVE_DECL_STRTOLL
00039 signed long long
00040 strtoll(const char* nptr, char** endptr, int base);
00041 #endif
00042
00043 #if !HAVE_DECL_STRTOULL
00044 unsigned long long
00045 strtoull(const char* nptr, char** endptr, int base);
00046 #endif
00047
00048 namespace Parma_Polyhedra_Library {
00049
00050 namespace Checked {
00051
00052 #ifndef HAVE_INT_FAST16_T
00053 typedef int16_t int_fast16_t;
00054 #endif
00055
00056 #ifndef HAVE_INT_FAST32_T
00057 typedef int32_t int_fast32_t;
00058 #endif
00059
00060 #ifndef HAVE_INT_FAST64_T
00061 typedef int64_t int_fast64_t;
00062 #endif
00063
00064 #ifndef HAVE_UINT_FAST16_T
00065 typedef uint16_t uint_fast16_t;
00066 #endif
00067
00068 #ifndef HAVE_UINT_FAST32_T
00069 typedef uint32_t uint_fast32_t;
00070 #endif
00071
00072 #ifndef HAVE_UINT_FAST64_T
00073 typedef uint64_t uint_fast64_t;
00074 #endif
00075
00076 template <typename Policy, typename Type>
00077 struct Extended_Int {
00078 static const Type plus_infinity = Limits<Type>::max;
00079 static const Type minus_infinity = (Limits<Type>::min >= 0
00080 ? Limits<Type>::max - 1
00081 : Limits<Type>::min);
00082 static const Type not_a_number = (Limits<Type>::min >= 0
00083 ? Limits<Type>::max - Policy::handle_infinity * 2
00084 : Limits<Type>::min + Policy::handle_infinity);
00085 static const Type min = (Limits<Type>::min
00086 + (Limits<Type>::min >= 0 ? 0
00087 : (Policy::handle_infinity + Policy::handle_nan)));
00088 static const Type max = (Limits<Type>::max
00089 - (Limits<Type>::min >= 0
00090 ? (2 * Policy::handle_infinity + Policy::handle_nan)
00091 : Policy::handle_infinity));
00092 };
00093
00094 template <typename Policy, typename To>
00095 inline Result
00096 set_neg_overflow_int(To& to, Rounding_Dir dir) {
00097 if (dir == ROUND_UP) {
00098 to = Extended_Int<Policy, To>::min;
00099 return V_LT;
00100 }
00101 else {
00102 if (Policy::handle_infinity) {
00103 to = Extended_Int<Policy, To>::minus_infinity;
00104 return V_GT;
00105 }
00106 return V_NEG_OVERFLOW;
00107 }
00108 }
00109
00110 template <typename Policy, typename To>
00111 inline Result
00112 set_pos_overflow_int(To& to, Rounding_Dir dir) {
00113 if (dir == ROUND_DOWN) {
00114 to = Extended_Int<Policy, To>::max;
00115 return V_GT;
00116 }
00117 else {
00118 if (Policy::handle_infinity) {
00119 to = Extended_Int<Policy, To>::plus_infinity;
00120 return V_LT;
00121 }
00122 return V_POS_OVERFLOW;
00123 }
00124 }
00125
00126 template <typename Policy, typename To>
00127 inline Result
00128 round_lt_int_no_overflow(To& to, Rounding_Dir dir) {
00129 if (dir == ROUND_DOWN) {
00130 to--;
00131 return V_GT;
00132 }
00133 return V_LT;
00134 }
00135
00136 template <typename Policy, typename To>
00137 inline Result
00138 round_gt_int_no_overflow(To& to, Rounding_Dir dir) {
00139 if (dir == ROUND_UP) {
00140 to++;
00141 return V_LT;
00142 }
00143 return V_GT;
00144 }
00145
00146 template <typename Policy, typename To>
00147 inline Result
00148 round_lt_int(To& to, Rounding_Dir dir) {
00149 if (dir == ROUND_DOWN) {
00150 if (to == Extended_Int<Policy, To>::min) {
00151 if (Policy::handle_infinity) {
00152 to = Extended_Int<Policy, To>::minus_infinity;
00153 return V_GT;
00154 }
00155 return V_NEG_OVERFLOW;
00156 } else {
00157 to--;
00158 return V_GT;
00159 }
00160 }
00161 return V_LT;
00162 }
00163
00164 template <typename Policy, typename To>
00165 inline Result
00166 round_gt_int(To& to, Rounding_Dir dir) {
00167 if (dir == ROUND_UP) {
00168 if (to == Extended_Int<Policy, To>::max) {
00169 if (Policy::handle_infinity) {
00170 to = Extended_Int<Policy, To>::plus_infinity;
00171 return V_LT;
00172 }
00173 return V_POS_OVERFLOW;
00174 } else {
00175 to++;
00176 return V_LT;
00177 }
00178 }
00179 return V_GT;
00180 }
00181
00182 SPECIALIZE_COPY(generic, signed char)
00183 SPECIALIZE_COPY(generic, signed short)
00184 SPECIALIZE_COPY(generic, signed int)
00185 SPECIALIZE_COPY(generic, signed long)
00186 SPECIALIZE_COPY(generic, signed long long)
00187 SPECIALIZE_COPY(generic, unsigned char)
00188 SPECIALIZE_COPY(generic, unsigned short)
00189 SPECIALIZE_COPY(generic, unsigned int)
00190 SPECIALIZE_COPY(generic, unsigned long)
00191 SPECIALIZE_COPY(generic, unsigned long long)
00192
00193 template <typename Policy, typename Type>
00194 inline Result
00195 classify_int(const Type v, bool nan, bool inf, bool sign) {
00196 if (Policy::handle_nan
00197 && (nan || sign)
00198 && v == Extended_Int<Policy, Type>::not_a_number)
00199 return VC_NAN;
00200 if (!inf & !sign)
00201 return VC_NORMAL;
00202 if (Policy::handle_infinity) {
00203 if (v == Extended_Int<Policy, Type>::minus_infinity)
00204 return inf ? VC_MINUS_INFINITY : V_LT;
00205 if (v == Extended_Int<Policy, Type>::plus_infinity)
00206 return inf ? VC_PLUS_INFINITY : V_GT;
00207 }
00208 if (sign) {
00209 if (v < 0)
00210 return V_LT;
00211 if (v > 0)
00212 return V_GT;
00213 return V_EQ;
00214 }
00215 return VC_NORMAL;
00216 }
00217
00218 SPECIALIZE_CLASSIFY(int, signed char)
00219 SPECIALIZE_CLASSIFY(int, signed short)
00220 SPECIALIZE_CLASSIFY(int, signed int)
00221 SPECIALIZE_CLASSIFY(int, signed long)
00222 SPECIALIZE_CLASSIFY(int, signed long long)
00223 SPECIALIZE_CLASSIFY(int, unsigned char)
00224 SPECIALIZE_CLASSIFY(int, unsigned short)
00225 SPECIALIZE_CLASSIFY(int, unsigned int)
00226 SPECIALIZE_CLASSIFY(int, unsigned long)
00227 SPECIALIZE_CLASSIFY(int, unsigned long long)
00228
00229 template <typename Policy, typename Type>
00230 inline bool
00231 is_nan_int(const Type v) {
00232 return Policy::handle_nan && v == Extended_Int<Policy, Type>::not_a_number;
00233 }
00234
00235 SPECIALIZE_IS_NAN(int, signed char)
00236 SPECIALIZE_IS_NAN(int, signed short)
00237 SPECIALIZE_IS_NAN(int, signed int)
00238 SPECIALIZE_IS_NAN(int, signed long)
00239 SPECIALIZE_IS_NAN(int, signed long long)
00240 SPECIALIZE_IS_NAN(int, unsigned char)
00241 SPECIALIZE_IS_NAN(int, unsigned short)
00242 SPECIALIZE_IS_NAN(int, unsigned int)
00243 SPECIALIZE_IS_NAN(int, unsigned long)
00244 SPECIALIZE_IS_NAN(int, unsigned long long)
00245
00246 template <typename Policy, typename Type>
00247 inline bool
00248 is_minf_int(const Type v) {
00249 return Policy::handle_infinity
00250 && v == Extended_Int<Policy, Type>::minus_infinity;
00251 }
00252
00253 SPECIALIZE_IS_MINF(int, signed char)
00254 SPECIALIZE_IS_MINF(int, signed short)
00255 SPECIALIZE_IS_MINF(int, signed int)
00256 SPECIALIZE_IS_MINF(int, signed long)
00257 SPECIALIZE_IS_MINF(int, signed long long)
00258 SPECIALIZE_IS_MINF(int, unsigned char)
00259 SPECIALIZE_IS_MINF(int, unsigned short)
00260 SPECIALIZE_IS_MINF(int, unsigned int)
00261 SPECIALIZE_IS_MINF(int, unsigned long)
00262 SPECIALIZE_IS_MINF(int, unsigned long long)
00263
00264 template <typename Policy, typename Type>
00265 inline bool
00266 is_pinf_int(const Type v) {
00267 return Policy::handle_infinity
00268 && v == Extended_Int<Policy, Type>::plus_infinity;
00269 }
00270
00271 SPECIALIZE_IS_PINF(int, signed char)
00272 SPECIALIZE_IS_PINF(int, signed short)
00273 SPECIALIZE_IS_PINF(int, signed int)
00274 SPECIALIZE_IS_PINF(int, signed long)
00275 SPECIALIZE_IS_PINF(int, signed long long)
00276 SPECIALIZE_IS_PINF(int, unsigned char)
00277 SPECIALIZE_IS_PINF(int, unsigned short)
00278 SPECIALIZE_IS_PINF(int, unsigned int)
00279 SPECIALIZE_IS_PINF(int, unsigned long)
00280 SPECIALIZE_IS_PINF(int, unsigned long long)
00281
00282 template <typename Policy, typename Type>
00283 inline bool
00284 is_int_int(const Type v) {
00285 return !is_nan<Policy>(v);
00286 }
00287
00288 SPECIALIZE_IS_INT(int, signed char)
00289 SPECIALIZE_IS_INT(int, signed short)
00290 SPECIALIZE_IS_INT(int, signed int)
00291 SPECIALIZE_IS_INT(int, signed long)
00292 SPECIALIZE_IS_INT(int, signed long long)
00293 SPECIALIZE_IS_INT(int, unsigned char)
00294 SPECIALIZE_IS_INT(int, unsigned short)
00295 SPECIALIZE_IS_INT(int, unsigned int)
00296 SPECIALIZE_IS_INT(int, unsigned long)
00297 SPECIALIZE_IS_INT(int, unsigned long long)
00298
00299 template <typename Policy, typename Type>
00300 inline Result
00301 set_special_int(Type& v, Result r) {
00302 Result t = classify(r);
00303 if (Policy::handle_nan && t == VC_NAN)
00304 v = Extended_Int<Policy, Type>::not_a_number;
00305 else if (Policy::handle_infinity) {
00306 switch (t) {
00307 case VC_MINUS_INFINITY:
00308 v = Extended_Int<Policy, Type>::minus_infinity;
00309 break;
00310 case VC_PLUS_INFINITY:
00311 v = Extended_Int<Policy, Type>::plus_infinity;
00312 break;
00313 default:
00314 break;
00315 }
00316 }
00317 return r;
00318 }
00319
00320 SPECIALIZE_SET_SPECIAL(int, signed char)
00321 SPECIALIZE_SET_SPECIAL(int, signed short)
00322 SPECIALIZE_SET_SPECIAL(int, signed int)
00323 SPECIALIZE_SET_SPECIAL(int, signed long)
00324 SPECIALIZE_SET_SPECIAL(int, signed long long)
00325 SPECIALIZE_SET_SPECIAL(int, unsigned char)
00326 SPECIALIZE_SET_SPECIAL(int, unsigned short)
00327 SPECIALIZE_SET_SPECIAL(int, unsigned int)
00328 SPECIALIZE_SET_SPECIAL(int, unsigned long)
00329 SPECIALIZE_SET_SPECIAL(int, unsigned long long)
00330
00331 template <typename Policy, typename To, typename From>
00332 inline Result
00333 assign_signed_int_signed_int(To& to, const From from, Rounding_Dir dir) {
00334 if (sizeof(To) <= sizeof(From)) {
00335 if (CHECK_P(Policy::check_overflow,
00336 from < static_cast<From>(Extended_Int<Policy, To>::min)))
00337 return set_neg_overflow_int<Policy>(to, dir);
00338 if (CHECK_P(Policy::check_overflow,
00339 from > static_cast<From>(Extended_Int<Policy, To>::max)))
00340 return set_pos_overflow_int<Policy>(to, dir);
00341 }
00342 to = To(from);
00343 return V_EQ;
00344 }
00345
00346 template <typename Policy, typename To, typename From>
00347 inline Result
00348 assign_signed_int_unsigned_int(To& to, const From from, Rounding_Dir dir) {
00349 if (sizeof(To) <= sizeof(From)) {
00350 if (CHECK_P(Policy::check_overflow,
00351 from > static_cast<From>(Extended_Int<Policy, To>::max)))
00352 return set_pos_overflow_int<Policy>(to, dir);
00353 }
00354 to = To(from);
00355 return V_EQ;
00356 }
00357
00358 template <typename Policy, typename To, typename From>
00359 inline Result
00360 assign_unsigned_int_signed_int(To& to, const From from, Rounding_Dir dir) {
00361 if (CHECK_P(Policy::check_overflow, from < 0))
00362 return set_neg_overflow_int<Policy>(to, dir);
00363 if (sizeof(To) < sizeof(From)) {
00364 if (CHECK_P(Policy::check_overflow,
00365 from > static_cast<From>(Extended_Int<Policy, To>::max)))
00366 return set_pos_overflow_int<Policy>(to, dir);
00367 }
00368 to = To(from);
00369 return V_EQ;
00370 }
00371
00372 template <typename Policy, typename To, typename From>
00373 inline Result
00374 assign_unsigned_int_unsigned_int(To& to, const From from, Rounding_Dir dir) {
00375 if (sizeof(To) <= sizeof(From)) {
00376 if (CHECK_P(Policy::check_overflow,
00377 from > static_cast<From>(Extended_Int<Policy, To>::max)))
00378 return set_pos_overflow_int<Policy>(to, dir);
00379 }
00380 to = To(from);
00381 return V_EQ;
00382 }
00383
00384
00385 #define ASSIGN2_SIGNED_SIGNED(Smaller, Larger) \
00386 SPECIALIZE_ASSIGN(signed_int_signed_int, Smaller, Larger) \
00387 SPECIALIZE_ASSIGN(signed_int_signed_int, Larger, Smaller)
00388
00389 #define ASSIGN2_UNSIGNED_UNSIGNED(Smaller, Larger) \
00390 SPECIALIZE_ASSIGN(unsigned_int_unsigned_int, Smaller, Larger) \
00391 SPECIALIZE_ASSIGN(unsigned_int_unsigned_int, Larger, Smaller)
00392
00393 #define ASSIGN2_UNSIGNED_SIGNED(Smaller, Larger) \
00394 SPECIALIZE_ASSIGN(unsigned_int_signed_int, Smaller, Larger) \
00395 SPECIALIZE_ASSIGN(signed_int_unsigned_int, Larger, Smaller)
00396
00397 #define ASSIGN2_SIGNED_UNSIGNED(Smaller, Larger) \
00398 SPECIALIZE_ASSIGN(signed_int_unsigned_int, Smaller, Larger) \
00399 SPECIALIZE_ASSIGN(unsigned_int_signed_int, Larger, Smaller)
00400
00401 #define ASSIGN_SIGNED(Type) \
00402 SPECIALIZE_ASSIGN(signed_int_signed_int, Type, Type)
00403 #define ASSIGN_UNSIGNED(Type) \
00404 SPECIALIZE_ASSIGN(unsigned_int_unsigned_int, Type, Type)
00405
00406 ASSIGN_SIGNED(signed char)
00407 ASSIGN_SIGNED(signed short)
00408 ASSIGN_SIGNED(signed int)
00409 ASSIGN_SIGNED(signed long)
00410 ASSIGN_SIGNED(signed long long)
00411 ASSIGN_UNSIGNED(unsigned char)
00412 ASSIGN_UNSIGNED(unsigned short)
00413 ASSIGN_UNSIGNED(unsigned int)
00414 ASSIGN_UNSIGNED(unsigned long)
00415 ASSIGN_UNSIGNED(unsigned long long)
00416
00417 ASSIGN2_SIGNED_SIGNED(signed char, signed short)
00418 ASSIGN2_SIGNED_SIGNED(signed char, signed int)
00419 ASSIGN2_SIGNED_SIGNED(signed char, signed long)
00420 ASSIGN2_SIGNED_SIGNED(signed char, signed long long)
00421 ASSIGN2_SIGNED_SIGNED(signed short, signed int)
00422 ASSIGN2_SIGNED_SIGNED(signed short, signed long)
00423 ASSIGN2_SIGNED_SIGNED(signed short, signed long long)
00424 ASSIGN2_SIGNED_SIGNED(signed int, signed long)
00425 ASSIGN2_SIGNED_SIGNED(signed int, signed long long)
00426 ASSIGN2_SIGNED_SIGNED(signed long, signed long long)
00427 ASSIGN2_UNSIGNED_UNSIGNED(unsigned char, unsigned short)
00428 ASSIGN2_UNSIGNED_UNSIGNED(unsigned char, unsigned int)
00429 ASSIGN2_UNSIGNED_UNSIGNED(unsigned char, unsigned long)
00430 ASSIGN2_UNSIGNED_UNSIGNED(unsigned char, unsigned long long)
00431 ASSIGN2_UNSIGNED_UNSIGNED(unsigned short, unsigned int)
00432 ASSIGN2_UNSIGNED_UNSIGNED(unsigned short, unsigned long)
00433 ASSIGN2_UNSIGNED_UNSIGNED(unsigned short, unsigned long long)
00434 ASSIGN2_UNSIGNED_UNSIGNED(unsigned int, unsigned long)
00435 ASSIGN2_UNSIGNED_UNSIGNED(unsigned int, unsigned long long)
00436 ASSIGN2_UNSIGNED_UNSIGNED(unsigned long, unsigned long long)
00437 ASSIGN2_UNSIGNED_SIGNED(unsigned char, signed short)
00438 ASSIGN2_UNSIGNED_SIGNED(unsigned char, signed int)
00439 ASSIGN2_UNSIGNED_SIGNED(unsigned char, signed long)
00440 ASSIGN2_UNSIGNED_SIGNED(unsigned char, signed long long)
00441 ASSIGN2_UNSIGNED_SIGNED(unsigned short, signed int)
00442 ASSIGN2_UNSIGNED_SIGNED(unsigned short, signed long)
00443 ASSIGN2_UNSIGNED_SIGNED(unsigned short, signed long long)
00444 ASSIGN2_UNSIGNED_SIGNED(unsigned int, signed long)
00445 ASSIGN2_UNSIGNED_SIGNED(unsigned int, signed long long)
00446 ASSIGN2_UNSIGNED_SIGNED(unsigned long, signed long long)
00447 ASSIGN2_SIGNED_UNSIGNED(signed char, unsigned char)
00448 ASSIGN2_SIGNED_UNSIGNED(signed char, unsigned short)
00449 ASSIGN2_SIGNED_UNSIGNED(signed char, unsigned int)
00450 ASSIGN2_SIGNED_UNSIGNED(signed char, unsigned long)
00451 ASSIGN2_SIGNED_UNSIGNED(signed char, unsigned long long)
00452 ASSIGN2_SIGNED_UNSIGNED(signed short, unsigned short)
00453 ASSIGN2_SIGNED_UNSIGNED(signed short, unsigned int)
00454 ASSIGN2_SIGNED_UNSIGNED(signed short, unsigned long)
00455 ASSIGN2_SIGNED_UNSIGNED(signed short, unsigned long long)
00456 ASSIGN2_SIGNED_UNSIGNED(signed int, unsigned int)
00457 ASSIGN2_SIGNED_UNSIGNED(signed int, unsigned long)
00458 ASSIGN2_SIGNED_UNSIGNED(signed int, unsigned long long)
00459 ASSIGN2_SIGNED_UNSIGNED(signed long, unsigned long)
00460 ASSIGN2_SIGNED_UNSIGNED(signed long, unsigned long long)
00461 ASSIGN2_SIGNED_UNSIGNED(signed long long, unsigned long long)
00462
00463 template <typename Policy, typename To, typename From>
00464 inline Result
00465 assign_int_float(To& to, const From from, Rounding_Dir dir) {
00466 if (CHECK_P(Policy::check_overflow, (from < Extended_Int<Policy, To>::min)))
00467 return set_neg_overflow_int<Policy>(to, dir);
00468 if (CHECK_P(Policy::check_overflow, (from > Extended_Int<Policy, To>::max)))
00469 return set_pos_overflow_int<Policy>(to, dir);
00470 to = static_cast<To>(from);
00471 if (dir == ROUND_IGNORE)
00472 return V_LGE;
00473 if (from < to)
00474 return round_lt_int<Policy>(to, dir);
00475 else if (from > to)
00476 return round_gt_int<Policy>(to, dir);
00477 else
00478 return V_EQ;
00479 }
00480
00481 SPECIALIZE_ASSIGN(int_float, signed char, float)
00482 SPECIALIZE_ASSIGN(int_float, signed short, float)
00483 SPECIALIZE_ASSIGN(int_float, signed int, float)
00484 SPECIALIZE_ASSIGN(int_float, signed long, float)
00485 SPECIALIZE_ASSIGN(int_float, signed long long, float)
00486 SPECIALIZE_ASSIGN(int_float, unsigned char, float)
00487 SPECIALIZE_ASSIGN(int_float, unsigned short, float)
00488 SPECIALIZE_ASSIGN(int_float, unsigned int, float)
00489 SPECIALIZE_ASSIGN(int_float, unsigned long, float)
00490 SPECIALIZE_ASSIGN(int_float, unsigned long long, float)
00491
00492 SPECIALIZE_ASSIGN(int_float, signed char, double)
00493 SPECIALIZE_ASSIGN(int_float, signed short, double)
00494 SPECIALIZE_ASSIGN(int_float, signed int, double)
00495 SPECIALIZE_ASSIGN(int_float, signed long, double)
00496 SPECIALIZE_ASSIGN(int_float, signed long long, double)
00497 SPECIALIZE_ASSIGN(int_float, unsigned char, double)
00498 SPECIALIZE_ASSIGN(int_float, unsigned short, double)
00499 SPECIALIZE_ASSIGN(int_float, unsigned int, double)
00500 SPECIALIZE_ASSIGN(int_float, unsigned long, double)
00501 SPECIALIZE_ASSIGN(int_float, unsigned long long, double)
00502
00503 SPECIALIZE_ASSIGN(int_float, signed char, long double)
00504 SPECIALIZE_ASSIGN(int_float, signed short, long double)
00505 SPECIALIZE_ASSIGN(int_float, signed int, long double)
00506 SPECIALIZE_ASSIGN(int_float, signed long, long double)
00507 SPECIALIZE_ASSIGN(int_float, signed long long, long double)
00508 SPECIALIZE_ASSIGN(int_float, unsigned char, long double)
00509 SPECIALIZE_ASSIGN(int_float, unsigned short, long double)
00510 SPECIALIZE_ASSIGN(int_float, unsigned int, long double)
00511 SPECIALIZE_ASSIGN(int_float, unsigned long, long double)
00512 SPECIALIZE_ASSIGN(int_float, unsigned long long, long double)
00513
00514 #undef ASSIGN2_SIGNED_SIGNED
00515 #undef ASSIGN2_UNSIGNED_UNSIGNED
00516 #undef ASSIGN2_UNSIGNED_SIGNED
00517 #undef ASSIGN2_SIGNED_UNSIGNED
00518
00519 template <typename Policy, typename To>
00520 inline Result
00521 assign_signed_int_mpz(To& to, const mpz_class& from, Rounding_Dir dir) {
00522 if (sizeof(To) <= sizeof(signed long)) {
00523 if (!Policy::check_overflow) {
00524 to = from.get_si();
00525 return V_EQ;
00526 }
00527 if (from.fits_slong_p()) {
00528 signed long v = from.get_si();
00529 if (v < Limits<To>::min)
00530 return set_neg_overflow_int<Policy>(to, dir);
00531 if (v > Limits<To>::max)
00532 return set_pos_overflow_int<Policy>(to, dir);
00533 to = v;
00534 return V_EQ;
00535 }
00536 }
00537 else {
00538 mpz_srcptr m = from.get_mpz_t();
00539 size_t sz = mpz_size(m);
00540 if (sz <= sizeof(To) / sizeof(mp_limb_t)) {
00541 if (sz == 0) {
00542 to = 0;
00543 return V_EQ;
00544 }
00545 To v;
00546 mpz_export(&v, 0, -1, sizeof(To), 0, 0, m);
00547 if (v >= 0) {
00548 if (::sgn(from) < 0)
00549 return neg<Policy>(to, v, dir);
00550 to = v;
00551 return V_EQ;
00552 }
00553 }
00554 }
00555 return ::sgn(from) < 0
00556 ? set_neg_overflow_int<Policy>(to, dir)
00557 : set_pos_overflow_int<Policy>(to, dir);
00558 }
00559
00560 SPECIALIZE_ASSIGN(signed_int_mpz, signed char, mpz_class)
00561 SPECIALIZE_ASSIGN(signed_int_mpz, signed short, mpz_class)
00562 SPECIALIZE_ASSIGN(signed_int_mpz, signed int, mpz_class)
00563 SPECIALIZE_ASSIGN(signed_int_mpz, signed long, mpz_class)
00564 SPECIALIZE_ASSIGN(signed_int_mpz, signed long long, mpz_class)
00565
00566 template <typename Policy, typename To>
00567 inline Result
00568 assign_unsigned_int_mpz(To& to, const mpz_class& from, Rounding_Dir dir) {
00569 if (CHECK_P(Policy::check_overflow, ::sgn(from) < 0))
00570 return set_neg_overflow_int<Policy>(to, dir);
00571 if (sizeof(To) <= sizeof(unsigned long)) {
00572 if (!Policy::check_overflow) {
00573 to = from.get_ui();
00574 return V_EQ;
00575 }
00576 if (from.fits_ulong_p()) {
00577 unsigned long v = from.get_ui();
00578 if (v > Limits<To>::max)
00579 return set_pos_overflow_int<Policy>(to, dir);
00580 to = v;
00581 return V_EQ;
00582 }
00583 }
00584 else {
00585 mpz_srcptr m = from.get_mpz_t();
00586 size_t sz = mpz_size(m);
00587 if (sz <= sizeof(To) / sizeof(mp_limb_t)) {
00588 if (sz == 0)
00589 to = 0;
00590 else
00591 mpz_export(&to, 0, -1, sizeof(To), 0, 0, m);
00592 return V_EQ;
00593 }
00594 }
00595 return set_pos_overflow_int<Policy>(to, dir);
00596 }
00597
00598 SPECIALIZE_ASSIGN(unsigned_int_mpz, unsigned char, mpz_class)
00599 SPECIALIZE_ASSIGN(unsigned_int_mpz, unsigned short, mpz_class)
00600 SPECIALIZE_ASSIGN(unsigned_int_mpz, unsigned int, mpz_class)
00601 SPECIALIZE_ASSIGN(unsigned_int_mpz, unsigned long, mpz_class)
00602 SPECIALIZE_ASSIGN(unsigned_int_mpz, unsigned long long, mpz_class)
00603
00604 template <typename Policy, typename To>
00605 inline Result
00606 assign_int_mpq(To& to, const mpq_class& from, Rounding_Dir dir) {
00607 mpz_srcptr n = from.get_num().get_mpz_t();
00608 mpz_srcptr d = from.get_den().get_mpz_t();
00609 mpz_class q;
00610 mpz_ptr _q = q.get_mpz_t();
00611 if (dir == ROUND_IGNORE) {
00612 mpz_tdiv_q(_q, n, d);
00613 Result r = assign<Policy>(to, q, dir);
00614 if (r != V_EQ)
00615 return r;
00616 return V_LGE;
00617 }
00618 mpz_t rem;
00619 int sign;
00620 mpz_init(rem);
00621 mpz_tdiv_qr(_q, rem, n, d);
00622 sign = mpz_sgn(rem);
00623 mpz_clear(rem);
00624 Result r = assign<Policy>(to, q, dir);
00625 if (r != V_EQ)
00626 return r;
00627 switch (sign) {
00628 case -1:
00629 return round_lt_int<Policy>(to, dir);
00630 case 1:
00631 return round_gt_int<Policy>(to, dir);
00632 default:
00633 return V_EQ;
00634 }
00635 }
00636
00637 SPECIALIZE_ASSIGN(int_mpq, signed char, mpq_class)
00638 SPECIALIZE_ASSIGN(int_mpq, signed short, mpq_class)
00639 SPECIALIZE_ASSIGN(int_mpq, signed int, mpq_class)
00640 SPECIALIZE_ASSIGN(int_mpq, signed long, mpq_class)
00641 SPECIALIZE_ASSIGN(int_mpq, signed long long, mpq_class)
00642 SPECIALIZE_ASSIGN(int_mpq, unsigned char, mpq_class)
00643 SPECIALIZE_ASSIGN(int_mpq, unsigned short, mpq_class)
00644 SPECIALIZE_ASSIGN(int_mpq, unsigned int, mpq_class)
00645 SPECIALIZE_ASSIGN(int_mpq, unsigned long, mpq_class)
00646 SPECIALIZE_ASSIGN(int_mpq, unsigned long long, mpq_class)
00647
00648 template <typename Policy, typename To>
00649 inline Result
00650 assign_int_minf(To& to, const Minus_Infinity&, Rounding_Dir dir) {
00651 if (Policy::handle_infinity) {
00652 to = Extended_Int<Policy, To>::minus_infinity;
00653 return V_EQ;
00654 }
00655 if (dir == ROUND_UP) {
00656 to = Extended_Int<Policy, To>::min;
00657 return V_LT;
00658 }
00659 return VC_MINUS_INFINITY;
00660 }
00661
00662 template <typename Policy, typename To>
00663 inline Result
00664 assign_int_pinf(To& to, const Plus_Infinity&, Rounding_Dir dir) {
00665 if (Policy::handle_infinity) {
00666 to = Extended_Int<Policy, To>::plus_infinity;
00667 return V_EQ;
00668 }
00669 if (dir == ROUND_DOWN) {
00670 to = Extended_Int<Policy, To>::max;
00671 return V_GT;
00672 }
00673 return VC_PLUS_INFINITY;
00674 }
00675
00676 template <typename Policy, typename To>
00677 inline Result
00678 assign_int_nan(To& to, const Not_A_Number&, Rounding_Dir) {
00679 if (Policy::handle_nan) {
00680 to = Extended_Int<Policy, To>::not_a_number;
00681 return V_EQ;
00682 }
00683 return VC_NAN;
00684 }
00685
00686 SPECIALIZE_ASSIGN(int_minf, signed char, Minus_Infinity)
00687 SPECIALIZE_ASSIGN(int_minf, signed short, Minus_Infinity)
00688 SPECIALIZE_ASSIGN(int_minf, signed int, Minus_Infinity)
00689 SPECIALIZE_ASSIGN(int_minf, signed long, Minus_Infinity)
00690 SPECIALIZE_ASSIGN(int_minf, signed long long, Minus_Infinity)
00691 SPECIALIZE_ASSIGN(int_minf, unsigned char, Minus_Infinity)
00692 SPECIALIZE_ASSIGN(int_minf, unsigned short, Minus_Infinity)
00693 SPECIALIZE_ASSIGN(int_minf, unsigned int, Minus_Infinity)
00694 SPECIALIZE_ASSIGN(int_minf, unsigned long, Minus_Infinity)
00695 SPECIALIZE_ASSIGN(int_minf, unsigned long long, Minus_Infinity)
00696
00697 SPECIALIZE_ASSIGN(int_pinf, signed char, Plus_Infinity)
00698 SPECIALIZE_ASSIGN(int_pinf, signed short, Plus_Infinity)
00699 SPECIALIZE_ASSIGN(int_pinf, signed int, Plus_Infinity)
00700 SPECIALIZE_ASSIGN(int_pinf, signed long, Plus_Infinity)
00701 SPECIALIZE_ASSIGN(int_pinf, signed long long, Plus_Infinity)
00702 SPECIALIZE_ASSIGN(int_pinf, unsigned char, Plus_Infinity)
00703 SPECIALIZE_ASSIGN(int_pinf, unsigned short, Plus_Infinity)
00704 SPECIALIZE_ASSIGN(int_pinf, unsigned int, Plus_Infinity)
00705 SPECIALIZE_ASSIGN(int_pinf, unsigned long, Plus_Infinity)
00706 SPECIALIZE_ASSIGN(int_pinf, unsigned long long, Plus_Infinity)
00707
00708 SPECIALIZE_ASSIGN(int_nan, signed char, Not_A_Number)
00709 SPECIALIZE_ASSIGN(int_nan, signed short, Not_A_Number)
00710 SPECIALIZE_ASSIGN(int_nan, signed int, Not_A_Number)
00711 SPECIALIZE_ASSIGN(int_nan, signed long, Not_A_Number)
00712 SPECIALIZE_ASSIGN(int_nan, signed long long, Not_A_Number)
00713 SPECIALIZE_ASSIGN(int_nan, unsigned char, Not_A_Number)
00714 SPECIALIZE_ASSIGN(int_nan, unsigned short, Not_A_Number)
00715 SPECIALIZE_ASSIGN(int_nan, unsigned int, Not_A_Number)
00716 SPECIALIZE_ASSIGN(int_nan, unsigned long, Not_A_Number)
00717 SPECIALIZE_ASSIGN(int_nan, unsigned long long, Not_A_Number)
00718
00719 #if UCHAR_MAX == 0xff
00720 #define CHAR_BITS 8
00721 #else
00722 #error "Unexpected max for unsigned char"
00723 #endif
00724
00725 #if USHRT_MAX == 0xffff
00726 #define SHRT_BITS 16
00727 #else
00728 #error "Unexpected max for unsigned short"
00729 #endif
00730
00731 #if UINT_MAX == 0xffffffff
00732 #define INT_BITS 32
00733 #else
00734 #error "Unexpected max for unsigned int"
00735 #endif
00736
00737 #if ULONG_MAX == 0xffffffffUL
00738 #define LONG_BITS 32
00739 #elif ULONG_MAX == 0xffffffffffffffffULL
00740 #define LONG_BITS 64
00741 #else
00742 #error "Unexpected max for unsigned long"
00743 #endif
00744
00745 #if ULLONG_MAX == 0xffffffffffffffffULL
00746 #define LONG_LONG_BITS 64
00747 #else
00748 #error "Unexpected max for unsigned long long"
00749 #endif
00750
00751
00752 template <typename T>
00753 struct Larger;
00754
00755
00756
00757
00758
00759
00760
00761 template <>
00762 struct Larger<signed char> {
00763 static const bool use_for_neg = true;
00764 static const bool use_for_add = true;
00765 static const bool use_for_sub = true;
00766 static const bool use_for_mul = true;
00767 typedef int_fast16_t Type_For_Neg;
00768 typedef int_fast16_t Type_For_Add;
00769 typedef int_fast16_t Type_For_Sub;
00770 typedef int_fast16_t Type_For_Mul;
00771 };
00772
00773 template <>
00774 struct Larger<unsigned char> {
00775 static const bool use_for_neg = true;
00776 static const bool use_for_add = true;
00777 static const bool use_for_sub = true;
00778 static const bool use_for_mul = true;
00779 typedef int_fast16_t Type_For_Neg;
00780 typedef uint_fast16_t Type_For_Add;
00781 typedef int_fast16_t Type_For_Sub;
00782 typedef uint_fast16_t Type_For_Mul;
00783 };
00784
00785 template <>
00786 struct Larger<signed short> {
00787 static const bool use_for_neg = true;
00788 static const bool use_for_add = true;
00789 static const bool use_for_sub = true;
00790 static const bool use_for_mul = true;
00791 typedef int_fast32_t Type_For_Neg;
00792 typedef int_fast32_t Type_For_Add;
00793 typedef int_fast32_t Type_For_Sub;
00794 typedef int_fast32_t Type_For_Mul;
00795 };
00796
00797 template <>
00798 struct Larger<unsigned short> {
00799 static const bool use_for_neg = true;
00800 static const bool use_for_add = true;
00801 static const bool use_for_sub = true;
00802 static const bool use_for_mul = true;
00803 typedef int_fast32_t Type_For_Neg;
00804 typedef uint_fast32_t Type_For_Add;
00805 typedef int_fast32_t Type_For_Sub;
00806 typedef uint_fast32_t Type_For_Mul;
00807 };
00808
00809 template <>
00810 struct Larger<signed int> {
00811 static const bool use_for_neg = (LONG_BITS == 64);
00812 static const bool use_for_add = (LONG_BITS == 64);
00813 static const bool use_for_sub = (LONG_BITS == 64);
00814 static const bool use_for_mul = true;
00815 typedef int_fast64_t Type_For_Neg;
00816 typedef int_fast64_t Type_For_Add;
00817 typedef int_fast64_t Type_For_Sub;
00818 typedef int_fast64_t Type_For_Mul;
00819 };
00820
00821 template <>
00822 struct Larger<unsigned int> {
00823 static const bool use_for_neg = (LONG_BITS == 64);
00824 static const bool use_for_add = (LONG_BITS == 64);
00825 static const bool use_for_sub = (LONG_BITS == 64);
00826 static const bool use_for_mul = true;
00827 typedef int_fast64_t Type_For_Neg;
00828 typedef uint_fast64_t Type_For_Add;
00829 typedef int_fast64_t Type_For_Sub;
00830 typedef uint_fast64_t Type_For_Mul;
00831 };
00832
00833 template <>
00834 struct Larger<signed long> {
00835 static const bool use_for_neg = false;
00836 static const bool use_for_add = false;
00837 static const bool use_for_sub = false;
00838 static const bool use_for_mul = (LONG_BITS == 32);
00839 typedef int_fast64_t Type_For_Neg;
00840 typedef int_fast64_t Type_For_Add;
00841 typedef int_fast64_t Type_For_Sub;
00842 typedef int_fast64_t Type_For_Mul;
00843 };
00844
00845 template <>
00846 struct Larger<unsigned long> {
00847 static const bool use_for_neg = false;
00848 static const bool use_for_add = false;
00849 static const bool use_for_sub = false;
00850 static const bool use_for_mul = (LONG_BITS == 32);
00851 typedef int_fast64_t Type_For_Neg;
00852 typedef uint_fast64_t Type_For_Add;
00853 typedef int_fast64_t Type_For_Sub;
00854 typedef uint_fast64_t Type_For_Mul;
00855 };
00856
00857 template <>
00858 struct Larger<signed long long> {
00859 static const bool use_for_neg = false;
00860 static const bool use_for_add = false;
00861 static const bool use_for_sub = false;
00862 static const bool use_for_mul = false;
00863 typedef int_fast64_t Type_For_Neg;
00864 typedef int_fast64_t Type_For_Add;
00865 typedef int_fast64_t Type_For_Sub;
00866 typedef int_fast64_t Type_For_Mul;
00867 };
00868
00869 template <>
00870 struct Larger<unsigned long long> {
00871 static const bool use_for_neg = false;
00872 static const bool use_for_add = false;
00873 static const bool use_for_sub = false;
00874 static const bool use_for_mul = false;
00875 typedef int_fast64_t Type_For_Neg;
00876 typedef uint_fast64_t Type_For_Add;
00877 typedef int_fast64_t Type_For_Sub;
00878 typedef uint_fast64_t Type_For_Mul;
00879 };
00880
00881 template <typename Policy, typename Type>
00882 inline Result
00883 neg_int_larger(Type& to, const Type x, Rounding_Dir dir) {
00884 typename Larger<Type>::Type_For_Neg l = x;
00885 l = -l;
00886 return assign<Policy>(to, l, dir);
00887 }
00888
00889 template <typename Policy, typename Type>
00890 inline Result
00891 add_int_larger(Type& to, const Type x, const Type y, Rounding_Dir dir) {
00892 typename Larger<Type>::Type_For_Add l = x;
00893 l += y;
00894 return assign<Policy>(to, l, dir);
00895 }
00896
00897 template <typename Policy, typename Type>
00898 inline Result
00899 sub_int_larger(Type& to, const Type x, const Type y, Rounding_Dir dir) {
00900 typename Larger<Type>::Type_For_Sub l = x;
00901 l -= y;
00902 return assign<Policy>(to, l, dir);
00903 }
00904
00905 template <typename Policy, typename Type>
00906 inline Result
00907 mul_int_larger(Type& to, const Type x, const Type y, Rounding_Dir dir) {
00908 typename Larger<Type>::Type_For_Mul l = x;
00909 l *= y;
00910 return assign<Policy>(to, l, dir);
00911 }
00912
00913 template <typename Policy, typename Type>
00914 inline Result
00915 neg_signed_int(Type& to, const Type from, Rounding_Dir dir) {
00916 if (Policy::check_overflow && Larger<Type>::use_for_neg)
00917 return neg_int_larger<Policy>(to, from, dir);
00918 if (CHECK_P(Policy::check_overflow,
00919 (from < -Extended_Int<Policy, Type>::max)))
00920 return set_pos_overflow_int<Policy>(to, dir);
00921 to = -from;
00922 return V_EQ;
00923 }
00924
00925 template <typename Policy, typename Type>
00926 inline Result
00927 neg_unsigned_int(Type& to, const Type from, Rounding_Dir dir) {
00928 if (Policy::check_overflow && Larger<Type>::use_for_neg)
00929 return neg_int_larger<Policy>(to, from, dir);
00930 if (CHECK_P(Policy::check_overflow, from != 0))
00931 return set_neg_overflow_int<Policy>(to, dir);
00932 to = from;
00933 return V_EQ;
00934 }
00935
00936 template <typename Policy, typename Type>
00937 inline Result
00938 add_signed_int(Type& to, const Type x, const Type y, Rounding_Dir dir) {
00939 if (Policy::check_overflow && Larger<Type>::use_for_add)
00940 return add_int_larger<Policy>(to, x, y, dir);
00941 if (Policy::check_overflow) {
00942 if (y >= 0) {
00943 if (x > Extended_Int<Policy, Type>::max - y)
00944 return set_pos_overflow_int<Policy>(to, dir);
00945 }
00946 else if (x < Extended_Int<Policy, Type>::min - y)
00947 return set_neg_overflow_int<Policy>(to, dir);
00948 }
00949 to = x + y;
00950 return V_EQ;
00951 }
00952
00953 template <typename Policy, typename Type>
00954 inline Result
00955 add_unsigned_int(Type& to, const Type x, const Type y, Rounding_Dir dir) {
00956 if (Policy::check_overflow && Larger<Type>::use_for_add)
00957 return add_int_larger<Policy>(to, x, y, dir);
00958 if (CHECK_P(Policy::check_overflow,
00959 (x > Extended_Int<Policy, Type>::max - y)))
00960 return set_pos_overflow_int<Policy>(to, dir);
00961 to = x + y;
00962 return V_EQ;
00963 }
00964
00965 template <typename Policy, typename Type>
00966 inline Result
00967 sub_signed_int(Type& to, const Type x, const Type y, Rounding_Dir dir) {
00968 if (Policy::check_overflow && Larger<Type>::use_for_sub)
00969 return sub_int_larger<Policy>(to, x, y, dir);
00970 if (Policy::check_overflow) {
00971 if (y >= 0) {
00972 if (x < Extended_Int<Policy, Type>::min + y)
00973 return set_neg_overflow_int<Policy>(to, dir);
00974 }
00975 else if (x > Extended_Int<Policy, Type>::max + y)
00976 return set_pos_overflow_int<Policy>(to, dir);
00977 }
00978 to = x - y;
00979 return V_EQ;
00980 }
00981
00982 template <typename Policy, typename Type>
00983 inline Result
00984 sub_unsigned_int(Type& to, const Type x, const Type y, Rounding_Dir dir) {
00985 if (Policy::check_overflow && Larger<Type>::use_for_sub)
00986 return sub_int_larger<Policy>(to, x, y, dir);
00987 if (CHECK_P(Policy::check_overflow,
00988 (x < Extended_Int<Policy, Type>::min + y)))
00989 return set_neg_overflow_int<Policy>(to, dir);
00990 to = x - y;
00991 return V_EQ;
00992 }
00993
00994 template <typename Policy, typename Type>
00995 inline Result
00996 mul_signed_int(Type& to, const Type x, const Type y, Rounding_Dir dir) {
00997 if (Policy::check_overflow && Larger<Type>::use_for_mul)
00998 return mul_int_larger<Policy>(to, x, y, dir);
00999 if (!Policy::check_overflow) {
01000 to = x * y;
01001 return V_EQ;
01002 }
01003 if (y == 0) {
01004 to = 0;
01005 return V_EQ;
01006 }
01007 if (y == -1)
01008 return neg_signed_int<Policy>(to, x, dir);
01009 if (x >= 0) {
01010 if (y > 0) {
01011 if (x > Extended_Int<Policy, Type>::max / y)
01012 return set_pos_overflow_int<Policy>(to, dir);
01013 }
01014 else {
01015 if (x > Extended_Int<Policy, Type>::min / y)
01016 return set_neg_overflow_int<Policy>(to, dir);
01017 }
01018 }
01019 else {
01020 if (y < 0) {
01021 if (x < Extended_Int<Policy, Type>::max / y)
01022 return set_pos_overflow_int<Policy>(to, dir);
01023 }
01024 else {
01025 if (x < Extended_Int<Policy, Type>::min / y)
01026 return set_neg_overflow_int<Policy>(to, dir);
01027 }
01028 }
01029 to = x * y;
01030 return V_EQ;
01031 }
01032
01033 template <typename Policy, typename Type>
01034 inline Result
01035 mul_unsigned_int(Type& to, const Type x, const Type y, Rounding_Dir dir) {
01036 if (Policy::check_overflow && Larger<Type>::use_for_mul)
01037 return mul_int_larger<Policy>(to, x, y, dir);
01038 if (!Policy::check_overflow) {
01039 to = x * y;
01040 return V_EQ;
01041 }
01042 if (y == 0) {
01043 to = 0;
01044 return V_EQ;
01045 }
01046 if (x > Extended_Int<Policy, Type>::max / y)
01047 return set_pos_overflow_int<Policy>(to, dir);
01048 to = x * y;
01049 return V_EQ;
01050 }
01051
01052 template <typename Policy, typename Type>
01053 inline Result
01054 div_signed_int(Type& to, const Type x, const Type y, Rounding_Dir dir) {
01055 if (CHECK_P(Policy::check_div_zero, y == 0))
01056 return set_special<Policy>(to, V_DIV_ZERO);
01057 if (Policy::check_overflow && y == -1)
01058 return neg_signed_int<Policy>(to, x, dir);
01059 to = x / y;
01060 if (dir == ROUND_IGNORE)
01061 return V_LGE;
01062 Type m = x % y;
01063 if (m < 0)
01064 return round_lt_int_no_overflow<Policy>(to, dir);
01065 else if (m > 0)
01066 return round_gt_int_no_overflow<Policy>(to, dir);
01067 else
01068 return V_EQ;
01069 }
01070
01071 template <typename Policy, typename Type>
01072 inline Result
01073 div_unsigned_int(Type& to, const Type x, const Type y, Rounding_Dir dir) {
01074 if (CHECK_P(Policy::check_div_zero, y == 0))
01075 return set_special<Policy>(to, V_DIV_ZERO);
01076 to = x / y;
01077 if (dir == ROUND_IGNORE)
01078 return V_GE;
01079 Type m = x % y;
01080 if (m == 0)
01081 return V_EQ;
01082 return round_gt_int<Policy>(to, dir);
01083 }
01084
01085 template <typename Policy, typename Type>
01086 inline Result
01087 rem_int(Type& to, const Type x, const Type y, Rounding_Dir) {
01088 if (CHECK_P(Policy::check_div_zero, y == 0))
01089 return set_special<Policy>(to, V_MOD_ZERO);
01090 to = x % y;
01091 return V_EQ;
01092 }
01093
01094 template <typename Policy, typename Type>
01095 inline Result
01096 div2exp_unsigned_int(Type& to, const Type x, int exp, Rounding_Dir dir) {
01097 if (exp < 0)
01098 return mul2exp<Policy>(to, x, -exp, dir);
01099 if (static_cast<unsigned int>(exp) >= sizeof(Type) * 8) {
01100 to = 0;
01101 if (dir == ROUND_IGNORE)
01102 return V_GE;
01103 if (x == 0)
01104 return V_EQ;
01105 return round_gt_int_no_overflow<Policy>(to, dir);
01106 }
01107 to = x >> exp;
01108 if (dir == ROUND_IGNORE)
01109 return V_GE;
01110 if (x & ((static_cast<Type>(1) << exp) - 1))
01111 return round_gt_int_no_overflow<Policy>(to, dir);
01112 else
01113 return V_EQ;
01114 }
01115
01116 template <typename Policy, typename Type>
01117 inline Result
01118 div2exp_signed_int(Type& to, const Type x, int exp, Rounding_Dir dir) {
01119 if (exp < 0)
01120 return mul2exp<Policy>(to, x, -exp, dir);
01121 if (static_cast<unsigned int>(exp) >= sizeof(Type) * 8) {
01122 zero:
01123 to = 0;
01124 if (dir == ROUND_IGNORE)
01125 return V_LGE;
01126 if (x < 0)
01127 return round_lt_int_no_overflow<Policy>(to, dir);
01128 else if (x > 0)
01129 return round_gt_int_no_overflow<Policy>(to, dir);
01130 else
01131 return V_EQ;
01132 }
01133 if (static_cast<unsigned int>(exp) >= sizeof(Type) * 8 - 1) {
01134 if (x == Limits<Type>::min) {
01135 to = -1;
01136 return V_EQ;
01137 }
01138 goto zero;
01139 }
01140 #if 0
01141 to = x / (static_cast<Type>(1) << exp);
01142 if (dir == ROUND_IGNORE)
01143 return V_GE;
01144 Type r = x % (static_cast<Type>(1) << exp);
01145 if (r < 0)
01146 return round_lt_int_no_overflow<Policy>(to, dir);
01147 else if (r > 0)
01148 return round_gt_int_no_overflow<Policy>(to, dir);
01149 else
01150 return V_EQ;
01151 #else
01152
01153 to = x >> exp;
01154 if (dir == ROUND_IGNORE)
01155 return V_GE;
01156 if (x & ((static_cast<Type>(1) << exp) - 1))
01157 return round_gt_int_no_overflow<Policy>(to, dir);
01158 return V_EQ;
01159 #endif
01160 }
01161
01162 template <typename Policy, typename Type>
01163 inline Result
01164 mul2exp_unsigned_int(Type& to, const Type x, int exp, Rounding_Dir dir) {
01165 if (exp < 0)
01166 return div2exp<Policy>(to, x, -exp, dir);
01167 if (!Policy::check_overflow) {
01168 to = x << exp;
01169 return V_EQ;
01170 }
01171 if (static_cast<unsigned int>(exp) >= sizeof(Type) * 8) {
01172 if (x == 0) {
01173 to = 0;
01174 return V_EQ;
01175 }
01176 return set_pos_overflow_int<Policy>(to, dir);
01177 }
01178 if (x & (((static_cast<Type>(1) << exp) - 1) << (sizeof(Type) * 8 - exp)))
01179 return set_pos_overflow_int<Policy>(to, dir);
01180 Type n = x << exp;
01181 if (n > Extended_Int<Policy, Type>::max)
01182 return set_pos_overflow_int<Policy>(to, dir);
01183 to = n;
01184 return V_EQ;
01185 }
01186
01187 template <typename Policy, typename Type>
01188 inline Result
01189 mul2exp_signed_int(Type& to, const Type x, int exp, Rounding_Dir dir) {
01190 if (exp < 0)
01191 return div2exp<Policy>(to, x, -exp, dir);
01192 if (!Policy::check_overflow) {
01193 to = x << exp;
01194 return V_EQ;
01195 }
01196 if (static_cast<unsigned int>(exp) >= sizeof(Type) * 8 - 1) {
01197 if (x < 0)
01198 return set_neg_overflow_int<Policy>(to, dir);
01199 else if (x > 0)
01200 return set_pos_overflow_int<Policy>(to, dir);
01201 else {
01202 to = 0;
01203 return V_EQ;
01204 }
01205 }
01206 Type mask = ((static_cast<Type>(1) << exp) - 1)
01207 << (sizeof(Type) * 8 - 1 - exp);
01208 Type n;
01209 if (x < 0) {
01210 if ((x & mask) != mask)
01211 return set_neg_overflow_int<Policy>(to, dir);
01212 n = x << exp;
01213 if (n < Extended_Int<Policy, Type>::min)
01214 return set_neg_overflow_int<Policy>(to, dir);
01215 }
01216 else {
01217 if (x & mask)
01218 return set_pos_overflow_int<Policy>(to, dir);
01219 n = x << exp;
01220 if (n > Extended_Int<Policy, Type>::max)
01221 return set_pos_overflow_int<Policy>(to, dir);
01222 }
01223 to = n;
01224 return V_EQ;
01225 }
01226
01227 template <typename Type>
01228 inline void
01229 isqrtrem_(Type& q, Type& r, const Type from) {
01230 q = 0;
01231 r = from;
01232 Type t(1);
01233 for (t <<= 8 * sizeof(Type) - 2; t != 0; t >>= 2) {
01234 Type s = q + t;
01235 if (s <= r) {
01236 r -= s;
01237 q = s + t;
01238 }
01239 q >>= 1;
01240 }
01241 }
01242
01243 template <typename Policy, typename Type>
01244 inline Result
01245 sqrt_unsigned_int(Type& to, const Type from, Rounding_Dir dir) {
01246 Type rem;
01247 isqrtrem_(to, rem, from);
01248 if (dir == ROUND_IGNORE)
01249 return V_GE;
01250 if (rem == 0)
01251 return V_EQ;
01252 return round_gt_int<Policy>(to, dir);
01253 }
01254
01255 template <typename Policy, typename Type>
01256 inline Result
01257 sqrt_signed_int(Type& to, const Type from, Rounding_Dir dir) {
01258 if (CHECK_P(Policy::check_sqrt_neg, from < 0))
01259 return set_special<Policy>(to, V_SQRT_NEG);
01260 return sqrt_unsigned_int<Policy>(to, from, dir);
01261 }
01262
01263 template <typename Policy, typename Type>
01264 inline Result
01265 add_mul_int(Type& to, const Type x, const Type y, Rounding_Dir dir) {
01266 Type z;
01267 Result r = mul<Policy>(z, x, y, dir);
01268 switch (r) {
01269 case V_NEG_OVERFLOW:
01270 case V_LT:
01271 if (to <= 0) {
01272 to = z;
01273 return r;
01274 }
01275 return set_special<Policy>(to, V_UNKNOWN_NEG_OVERFLOW);
01276 case V_POS_OVERFLOW:
01277 case V_GT:
01278 if (to >= 0) {
01279 to = z;
01280 return r;
01281 }
01282 return set_special<Policy>(to, V_UNKNOWN_POS_OVERFLOW);
01283 default:
01284 return add<Policy>(to, to, z, dir);
01285 }
01286 }
01287
01288 template <typename Policy, typename Type>
01289 inline Result
01290 sub_mul_int(Type& to, const Type x, const Type y, Rounding_Dir dir) {
01291 Type z;
01292 Result r = mul<Policy>(z, x, y, dir);
01293 switch (r) {
01294 case V_NEG_OVERFLOW:
01295 case V_LT:
01296 if (to >= 0)
01297 return set_pos_overflow_int<Policy>(to, dir);
01298 return V_UNKNOWN_NEG_OVERFLOW;
01299 case V_POS_OVERFLOW:
01300 case V_GT:
01301 if (to <= 0)
01302 return set_neg_overflow_int<Policy>(to, dir);
01303 return V_UNKNOWN_POS_OVERFLOW;
01304 default:
01305 return sub<Policy>(to, to, z, dir);
01306 }
01307 }
01308
01309 template <typename Policy, typename Type>
01310 inline Result
01311 output_char(std::ostream& os, Type& from,
01312 const Numeric_Format&, Rounding_Dir) {
01313 os << (int) from;
01314 return V_EQ;
01315 }
01316
01317 template <typename Policy, typename Type>
01318 inline Result
01319 output_int(std::ostream& os, Type& from, const Numeric_Format&, Rounding_Dir) {
01320 os << from;
01321 return V_EQ;
01322 }
01323
01324 SPECIALIZE_NEG(signed_int, signed char, signed char)
01325 SPECIALIZE_NEG(signed_int, signed short, signed short)
01326 SPECIALIZE_NEG(signed_int, signed int, signed int)
01327 SPECIALIZE_NEG(signed_int, signed long, signed long)
01328 SPECIALIZE_NEG(signed_int, signed long long, signed long long)
01329 SPECIALIZE_NEG(unsigned_int, unsigned char, unsigned char)
01330 SPECIALIZE_NEG(unsigned_int, unsigned short, unsigned short)
01331 SPECIALIZE_NEG(unsigned_int, unsigned int, unsigned int)
01332 SPECIALIZE_NEG(unsigned_int, unsigned long, unsigned long)
01333 SPECIALIZE_NEG(unsigned_int, unsigned long long, unsigned long long)
01334
01335 SPECIALIZE_ADD(signed_int, signed char, signed char, signed char)
01336 SPECIALIZE_ADD(signed_int, signed short, signed short, signed short)
01337 SPECIALIZE_ADD(signed_int, signed int, signed int, signed int)
01338 SPECIALIZE_ADD(signed_int, signed long, signed long, signed long)
01339 SPECIALIZE_ADD(signed_int, signed long long, signed long long, signed long long)
01340 SPECIALIZE_ADD(unsigned_int, unsigned char, unsigned char, unsigned char)
01341 SPECIALIZE_ADD(unsigned_int, unsigned short, unsigned short, unsigned short)
01342 SPECIALIZE_ADD(unsigned_int, unsigned int, unsigned int, unsigned int)
01343 SPECIALIZE_ADD(unsigned_int, unsigned long, unsigned long, unsigned long)
01344 SPECIALIZE_ADD(unsigned_int, unsigned long long, unsigned long long, unsigned long long)
01345
01346 SPECIALIZE_SUB(signed_int, signed char, signed char, signed char)
01347 SPECIALIZE_SUB(signed_int, signed short, signed short, signed short)
01348 SPECIALIZE_SUB(signed_int, signed int, signed int, signed int)
01349 SPECIALIZE_SUB(signed_int, signed long, signed long, signed long)
01350 SPECIALIZE_SUB(signed_int, signed long long, signed long long, signed long long)
01351 SPECIALIZE_SUB(unsigned_int, unsigned char, unsigned char, unsigned char)
01352 SPECIALIZE_SUB(unsigned_int, unsigned short, unsigned short, unsigned short)
01353 SPECIALIZE_SUB(unsigned_int, unsigned int, unsigned int, unsigned int)
01354 SPECIALIZE_SUB(unsigned_int, unsigned long, unsigned long, unsigned long)
01355 SPECIALIZE_SUB(unsigned_int, unsigned long long, unsigned long long, unsigned long long)
01356
01357 SPECIALIZE_MUL(signed_int, signed char, signed char, signed char)
01358 SPECIALIZE_MUL(signed_int, signed short, signed short, signed short)
01359 SPECIALIZE_MUL(signed_int, signed int, signed int, signed int)
01360 SPECIALIZE_MUL(signed_int, signed long, signed long, signed long)
01361 SPECIALIZE_MUL(signed_int, signed long long, signed long long, signed long long)
01362 SPECIALIZE_MUL(unsigned_int, unsigned char, unsigned char, unsigned char)
01363 SPECIALIZE_MUL(unsigned_int, unsigned short, unsigned short, unsigned short)
01364 SPECIALIZE_MUL(unsigned_int, unsigned int, unsigned int, unsigned int)
01365 SPECIALIZE_MUL(unsigned_int, unsigned long, unsigned long, unsigned long)
01366 SPECIALIZE_MUL(unsigned_int, unsigned long long, unsigned long long, unsigned long long)
01367
01368 SPECIALIZE_DIV(signed_int, signed char, signed char, signed char)
01369 SPECIALIZE_DIV(signed_int, signed short, signed short, signed short)
01370 SPECIALIZE_DIV(signed_int, signed int, signed int, signed int)
01371 SPECIALIZE_DIV(signed_int, signed long, signed long, signed long)
01372 SPECIALIZE_DIV(signed_int, signed long long, signed long long, signed long long)
01373 SPECIALIZE_DIV(unsigned_int, unsigned char, unsigned char, unsigned char)
01374 SPECIALIZE_DIV(unsigned_int, unsigned short, unsigned short, unsigned short)
01375 SPECIALIZE_DIV(unsigned_int, unsigned int, unsigned int, unsigned int)
01376 SPECIALIZE_DIV(unsigned_int, unsigned long, unsigned long, unsigned long)
01377 SPECIALIZE_DIV(unsigned_int, unsigned long long, unsigned long long, unsigned long long)
01378
01379 SPECIALIZE_REM(int, signed char, signed char, signed char)
01380 SPECIALIZE_REM(int, signed short, signed short, signed short)
01381 SPECIALIZE_REM(int, signed int, signed int, signed int)
01382 SPECIALIZE_REM(int, signed long, signed long, signed long)
01383 SPECIALIZE_REM(int, signed long long, signed long long, signed long long)
01384 SPECIALIZE_REM(int, unsigned char, unsigned char, unsigned char)
01385 SPECIALIZE_REM(int, unsigned short, unsigned short, unsigned short)
01386 SPECIALIZE_REM(int, unsigned int, unsigned int, unsigned int)
01387 SPECIALIZE_REM(int, unsigned long, unsigned long, unsigned long)
01388 SPECIALIZE_REM(int, unsigned long long, unsigned long long, unsigned long long)
01389
01390 SPECIALIZE_MUL2EXP(signed_int, signed char, signed char)
01391 SPECIALIZE_MUL2EXP(signed_int, signed short, signed short)
01392 SPECIALIZE_MUL2EXP(signed_int, signed int, signed int)
01393 SPECIALIZE_MUL2EXP(signed_int, signed long, signed long)
01394 SPECIALIZE_MUL2EXP(signed_int, signed long long, signed long long)
01395 SPECIALIZE_MUL2EXP(unsigned_int, unsigned char, unsigned char)
01396 SPECIALIZE_MUL2EXP(unsigned_int, unsigned short, unsigned short)
01397 SPECIALIZE_MUL2EXP(unsigned_int, unsigned int, unsigned int)
01398 SPECIALIZE_MUL2EXP(unsigned_int, unsigned long, unsigned long)
01399 SPECIALIZE_MUL2EXP(unsigned_int, unsigned long long, unsigned long long)
01400
01401 SPECIALIZE_DIV2EXP(signed_int, signed char, signed char)
01402 SPECIALIZE_DIV2EXP(signed_int, signed short, signed short)
01403 SPECIALIZE_DIV2EXP(signed_int, signed int, signed int)
01404 SPECIALIZE_DIV2EXP(signed_int, signed long, signed long)
01405 SPECIALIZE_DIV2EXP(signed_int, signed long long, signed long long)
01406 SPECIALIZE_DIV2EXP(unsigned_int, unsigned char, unsigned char)
01407 SPECIALIZE_DIV2EXP(unsigned_int, unsigned short, unsigned short)
01408 SPECIALIZE_DIV2EXP(unsigned_int, unsigned int, unsigned int)
01409 SPECIALIZE_DIV2EXP(unsigned_int, unsigned long, unsigned long)
01410 SPECIALIZE_DIV2EXP(unsigned_int, unsigned long long, unsigned long long)
01411
01412 SPECIALIZE_SQRT(signed_int, signed char, signed char)
01413 SPECIALIZE_SQRT(signed_int, signed short, signed short)
01414 SPECIALIZE_SQRT(signed_int, signed int, signed int)
01415 SPECIALIZE_SQRT(signed_int, signed long, signed long)
01416 SPECIALIZE_SQRT(signed_int, signed long long, signed long long)
01417 SPECIALIZE_SQRT(unsigned_int, unsigned char, unsigned char)
01418 SPECIALIZE_SQRT(unsigned_int, unsigned short, unsigned short)
01419 SPECIALIZE_SQRT(unsigned_int, unsigned int, unsigned int)
01420 SPECIALIZE_SQRT(unsigned_int, unsigned long, unsigned long)
01421 SPECIALIZE_SQRT(unsigned_int, unsigned long long, unsigned long long)
01422
01423 SPECIALIZE_ABS(generic, signed char, signed char)
01424 SPECIALIZE_ABS(generic, signed short, signed short)
01425 SPECIALIZE_ABS(generic, signed int, signed int)
01426 SPECIALIZE_ABS(generic, signed long, signed long)
01427 SPECIALIZE_ABS(generic, signed long long, signed long long)
01428 SPECIALIZE_ABS(generic, unsigned char, unsigned char)
01429 SPECIALIZE_ABS(generic, unsigned short, unsigned short)
01430 SPECIALIZE_ABS(generic, unsigned int, unsigned int)
01431 SPECIALIZE_ABS(generic, unsigned long, unsigned long)
01432 SPECIALIZE_ABS(generic, unsigned long long, unsigned long long)
01433
01434 SPECIALIZE_GCD(exact, signed char, signed char, signed char)
01435 SPECIALIZE_GCD(exact, signed short, signed short, signed short)
01436 SPECIALIZE_GCD(exact, signed int, signed int, signed int)
01437 SPECIALIZE_GCD(exact, signed long, signed long, signed long)
01438 SPECIALIZE_GCD(exact, signed long long, signed long long, signed long long)
01439 SPECIALIZE_GCD(exact, unsigned char, unsigned char, unsigned char)
01440 SPECIALIZE_GCD(exact, unsigned short, unsigned short, unsigned short)
01441 SPECIALIZE_GCD(exact, unsigned int, unsigned int, unsigned int)
01442 SPECIALIZE_GCD(exact, unsigned long, unsigned long, unsigned long)
01443 SPECIALIZE_GCD(exact, unsigned long long, unsigned long long, unsigned long long)
01444
01445 SPECIALIZE_GCDEXT(exact, signed char, signed char, signed char, signed char, signed char)
01446 SPECIALIZE_GCDEXT(exact, signed short, signed short, signed short, signed short, signed short)
01447 SPECIALIZE_GCDEXT(exact, signed int, signed int, signed int, signed int, signed int)
01448 SPECIALIZE_GCDEXT(exact, signed long, signed long, signed long, signed long, signed long)
01449 SPECIALIZE_GCDEXT(exact, signed long long, signed long long, signed long long, signed long long, signed long long)
01450 SPECIALIZE_GCDEXT(exact, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char)
01451 SPECIALIZE_GCDEXT(exact, unsigned short, unsigned short, unsigned short, unsigned short, unsigned short)
01452 SPECIALIZE_GCDEXT(exact, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int)
01453 SPECIALIZE_GCDEXT(exact, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long)
01454 SPECIALIZE_GCDEXT(exact, unsigned long long, unsigned long long, unsigned long long, unsigned long long, unsigned long long)
01455
01456 SPECIALIZE_LCM(gcd_exact, signed char, signed char, signed char)
01457 SPECIALIZE_LCM(gcd_exact, signed short, signed short, signed short)
01458 SPECIALIZE_LCM(gcd_exact, signed int, signed int, signed int)
01459 SPECIALIZE_LCM(gcd_exact, signed long, signed long, signed long)
01460 SPECIALIZE_LCM(gcd_exact, signed long long, signed long long, signed long long)
01461 SPECIALIZE_LCM(gcd_exact, unsigned char, unsigned char, unsigned char)
01462 SPECIALIZE_LCM(gcd_exact, unsigned short, unsigned short, unsigned short)
01463 SPECIALIZE_LCM(gcd_exact, unsigned int, unsigned int, unsigned int)
01464 SPECIALIZE_LCM(gcd_exact, unsigned long, unsigned long, unsigned long)
01465 SPECIALIZE_LCM(gcd_exact, unsigned long long, unsigned long long, unsigned long long)
01466
01467 SPECIALIZE_SGN(generic, signed char)
01468 SPECIALIZE_SGN(generic, signed short)
01469 SPECIALIZE_SGN(generic, signed int)
01470 SPECIALIZE_SGN(generic, signed long)
01471 SPECIALIZE_SGN(generic, signed long long)
01472 SPECIALIZE_SGN(generic, unsigned char)
01473 SPECIALIZE_SGN(generic, unsigned short)
01474 SPECIALIZE_SGN(generic, unsigned int)
01475 SPECIALIZE_SGN(generic, unsigned long)
01476 SPECIALIZE_SGN(generic, unsigned long long)
01477
01478 SPECIALIZE_CMP(generic, signed char, signed char)
01479 SPECIALIZE_CMP(generic, signed short, signed short)
01480 SPECIALIZE_CMP(generic, signed int, signed int)
01481 SPECIALIZE_CMP(generic, signed long, signed long)
01482 SPECIALIZE_CMP(generic, signed long long, signed long long)
01483 SPECIALIZE_CMP(generic, unsigned char, unsigned char)
01484 SPECIALIZE_CMP(generic, unsigned short, unsigned short)
01485 SPECIALIZE_CMP(generic, unsigned int, unsigned int)
01486 SPECIALIZE_CMP(generic, unsigned long, unsigned long)
01487 SPECIALIZE_CMP(generic, unsigned long long, unsigned long long)
01488
01489 SPECIALIZE_ADD_MUL(int, signed char, signed char, signed char)
01490 SPECIALIZE_ADD_MUL(int, signed short, signed short, signed short)
01491 SPECIALIZE_ADD_MUL(int, signed int, signed int, signed int)
01492 SPECIALIZE_ADD_MUL(int, signed long, signed long, signed long)
01493 SPECIALIZE_ADD_MUL(int, signed long long, signed long long, signed long long)
01494 SPECIALIZE_ADD_MUL(int, unsigned char, unsigned char, unsigned char)
01495 SPECIALIZE_ADD_MUL(int, unsigned short, unsigned short, unsigned short)
01496 SPECIALIZE_ADD_MUL(int, unsigned int, unsigned int, unsigned int)
01497 SPECIALIZE_ADD_MUL(int, unsigned long, unsigned long, unsigned long)
01498 SPECIALIZE_ADD_MUL(int, unsigned long long, unsigned long long, unsigned long long)
01499
01500 SPECIALIZE_SUB_MUL(int, signed char, signed char, signed char)
01501 SPECIALIZE_SUB_MUL(int, signed short, signed short, signed short)
01502 SPECIALIZE_SUB_MUL(int, signed int, signed int, signed int)
01503 SPECIALIZE_SUB_MUL(int, signed long, signed long, signed long)
01504 SPECIALIZE_SUB_MUL(int, signed long long, signed long long, signed long long)
01505 SPECIALIZE_SUB_MUL(int, unsigned char, unsigned char, unsigned char)
01506 SPECIALIZE_SUB_MUL(int, unsigned short, unsigned short, unsigned short)
01507 SPECIALIZE_SUB_MUL(int, unsigned int, unsigned int, unsigned int)
01508 SPECIALIZE_SUB_MUL(int, unsigned long, unsigned long, unsigned long)
01509 SPECIALIZE_SUB_MUL(int, unsigned long long, unsigned long long, unsigned long long)
01510
01511 SPECIALIZE_INPUT(generic, signed char)
01512 SPECIALIZE_INPUT(generic, signed short)
01513 SPECIALIZE_INPUT(generic, signed int)
01514 SPECIALIZE_INPUT(generic, signed long)
01515 SPECIALIZE_INPUT(generic, signed long long)
01516 SPECIALIZE_INPUT(generic, unsigned char)
01517 SPECIALIZE_INPUT(generic, unsigned short)
01518 SPECIALIZE_INPUT(generic, unsigned int)
01519 SPECIALIZE_INPUT(generic, unsigned long)
01520 SPECIALIZE_INPUT(generic, unsigned long long)
01521
01522 SPECIALIZE_OUTPUT(char, signed char)
01523 SPECIALIZE_OUTPUT(int, signed short)
01524 SPECIALIZE_OUTPUT(int, signed int)
01525 SPECIALIZE_OUTPUT(int, signed long)
01526 SPECIALIZE_OUTPUT(int, signed long long)
01527 SPECIALIZE_OUTPUT(char, unsigned char)
01528 SPECIALIZE_OUTPUT(int, unsigned short)
01529 SPECIALIZE_OUTPUT(int, unsigned int)
01530 SPECIALIZE_OUTPUT(int, unsigned long)
01531 SPECIALIZE_OUTPUT(int, unsigned long long)
01532
01533 }
01534
01535 }
01536
01537 #endif // !defined(PPL_checked_int_inlines_hh)