diff options
author | Anas Nashif <anas.nashif@intel.com> | 2012-11-06 07:10:54 -0800 |
---|---|---|
committer | Anas Nashif <anas.nashif@intel.com> | 2012-11-06 07:10:54 -0800 |
commit | ede95f2eabeab645352a36af072ee998c400bca1 (patch) | |
tree | fcd5dc9c73c1bdc0444deee28a9b329f62a2ed7b /src/checked_int.inlines.hh | |
download | ppl-upstream.tar.gz ppl-upstream.tar.bz2 ppl-upstream.zip |
Imported Upstream version 0.11.2upstream/0.11.2upstream
Diffstat (limited to 'src/checked_int.inlines.hh')
-rw-r--r-- | src/checked_int.inlines.hh | 1933 |
1 files changed, 1933 insertions, 0 deletions
diff --git a/src/checked_int.inlines.hh b/src/checked_int.inlines.hh new file mode 100644 index 000000000..496e3731c --- /dev/null +++ b/src/checked_int.inlines.hh @@ -0,0 +1,1933 @@ +/* Specialized "checked" functions for native integer numbers. + Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it> + Copyright (C) 2010-2011 BUGSENG srl (http://bugseng.com) + +This file is part of the Parma Polyhedra Library (PPL). + +The PPL is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The PPL is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software Foundation, +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA. + +For the most up-to-date information see the Parma Polyhedra Library +site: http://www.cs.unipr.it/ppl/ . */ + +#ifndef PPL_checked_int_inlines_hh +#define PPL_checked_int_inlines_hh 1 + +#include "C_Integer.hh" +#include <cerrno> +#include <cstdlib> +#include <climits> +#include <string> + +#if !PPL_HAVE_DECL_STRTOLL +signed long long +strtoll(const char* nptr, char** endptr, int base); +#endif + +#if !PPL_HAVE_DECL_STRTOULL +unsigned long long +strtoull(const char* nptr, char** endptr, int base); +#endif + +namespace Parma_Polyhedra_Library { + +namespace Checked { + +#ifndef PPL_HAVE_INT_FAST16_T +typedef int16_t int_fast16_t; +#endif + +#ifndef PPL_HAVE_INT_FAST32_T +typedef int32_t int_fast32_t; +#endif + +#ifndef PPL_HAVE_INT_FAST64_T +typedef int64_t int_fast64_t; +#endif + +#ifndef PPL_HAVE_UINT_FAST16_T +typedef uint16_t uint_fast16_t; +#endif + +#ifndef PPL_HAVE_UINT_FAST32_T +typedef uint32_t uint_fast32_t; +#endif + +#ifndef PPL_HAVE_UINT_FAST64_T +typedef uint64_t uint_fast64_t; +#endif + +template <typename Policy, typename Type> +struct Extended_Int { + static const Type plus_infinity = C_Integer<Type>::max; + static const Type minus_infinity = (C_Integer<Type>::min >= 0 + ? C_Integer<Type>::max - 1 + : C_Integer<Type>::min); + static const Type not_a_number = (C_Integer<Type>::min >= 0 + ? C_Integer<Type>::max - Policy::has_infinity * 2 + : C_Integer<Type>::min + Policy::has_infinity); + static const Type min = (C_Integer<Type>::min + + (C_Integer<Type>::min >= 0 ? 0 + : (Policy::has_infinity + Policy::has_nan))); + static const Type max = (C_Integer<Type>::max + - (C_Integer<Type>::min >= 0 + ? (2 * Policy::has_infinity + Policy::has_nan) + : Policy::has_infinity)); +}; + +template <typename Policy, typename To> +inline Result +set_neg_overflow_int(To& to, Rounding_Dir dir) { + if (round_up(dir)) { + to = Extended_Int<Policy, To>::min; + return V_LT_INF; + } + else { + if (Policy::has_infinity) { + to = Extended_Int<Policy, To>::minus_infinity; + return V_GT_MINUS_INFINITY; + } + return V_GT_MINUS_INFINITY | V_UNREPRESENTABLE; + } +} + +template <typename Policy, typename To> +inline Result +set_pos_overflow_int(To& to, Rounding_Dir dir) { + if (round_down(dir)) { + to = Extended_Int<Policy, To>::max; + return V_GT_SUP; + } + else { + if (Policy::has_infinity) { + to = Extended_Int<Policy, To>::plus_infinity; + return V_LT_PLUS_INFINITY; + } + return V_LT_PLUS_INFINITY | V_UNREPRESENTABLE; + } +} + +template <typename Policy, typename To> +inline Result +round_lt_int_no_overflow(To& to, Rounding_Dir dir) { + if (round_down(dir)) { + --to; + return V_GT; + } + return V_LT; +} + +template <typename Policy, typename To> +inline Result +round_gt_int_no_overflow(To& to, Rounding_Dir dir) { + if (round_up(dir)) { + ++to; + return V_LT; + } + return V_GT; +} + +template <typename Policy, typename To> +inline Result +round_lt_int(To& to, Rounding_Dir dir) { + if (round_down(dir)) { + if (to == Extended_Int<Policy, To>::min) { + if (Policy::has_infinity) { + to = Extended_Int<Policy, To>::minus_infinity; + return V_GT_MINUS_INFINITY; + } + return V_GT_MINUS_INFINITY | V_UNREPRESENTABLE; + } + else { + --to; + return V_GT; + } + } + return V_LT; +} + +template <typename Policy, typename To> +inline Result +round_gt_int(To& to, Rounding_Dir dir) { + if (round_up(dir)) { + if (to == Extended_Int<Policy, To>::max) { + if (Policy::has_infinity) { + to = Extended_Int<Policy, To>::plus_infinity; + return V_LT_PLUS_INFINITY; + } + return V_LT_PLUS_INFINITY | V_UNREPRESENTABLE; + } + else { + ++to; + return V_LT; + } + } + return V_GT; +} + +PPL_SPECIALIZE_COPY(copy_generic, char) +PPL_SPECIALIZE_COPY(copy_generic, signed char) +PPL_SPECIALIZE_COPY(copy_generic, signed short) +PPL_SPECIALIZE_COPY(copy_generic, signed int) +PPL_SPECIALIZE_COPY(copy_generic, signed long) +PPL_SPECIALIZE_COPY(copy_generic, signed long long) +PPL_SPECIALIZE_COPY(copy_generic, unsigned char) +PPL_SPECIALIZE_COPY(copy_generic, unsigned short) +PPL_SPECIALIZE_COPY(copy_generic, unsigned int) +PPL_SPECIALIZE_COPY(copy_generic, unsigned long) +PPL_SPECIALIZE_COPY(copy_generic, unsigned long long) + +template <typename Policy, typename Type> +inline Result +classify_int(const Type v, bool nan, bool inf, bool sign) { + if (Policy::has_nan + && (nan || sign) + && v == Extended_Int<Policy, Type>::not_a_number) + return V_NAN; + if (!inf && !sign) + return V_LGE; + if (Policy::has_infinity) { + if (v == Extended_Int<Policy, Type>::minus_infinity) + return inf ? V_EQ_MINUS_INFINITY : V_LT; + if (v == Extended_Int<Policy, Type>::plus_infinity) + return inf ? V_EQ_PLUS_INFINITY : V_GT; + } + if (sign) { + if (v < 0) + return V_LT; + if (v > 0) + return V_GT; + return V_EQ; + } + return V_LGE; +} + +PPL_SPECIALIZE_CLASSIFY(classify_int, char) +PPL_SPECIALIZE_CLASSIFY(classify_int, signed char) +PPL_SPECIALIZE_CLASSIFY(classify_int, signed short) +PPL_SPECIALIZE_CLASSIFY(classify_int, signed int) +PPL_SPECIALIZE_CLASSIFY(classify_int, signed long) +PPL_SPECIALIZE_CLASSIFY(classify_int, signed long long) +PPL_SPECIALIZE_CLASSIFY(classify_int, unsigned char) +PPL_SPECIALIZE_CLASSIFY(classify_int, unsigned short) +PPL_SPECIALIZE_CLASSIFY(classify_int, unsigned int) +PPL_SPECIALIZE_CLASSIFY(classify_int, unsigned long) +PPL_SPECIALIZE_CLASSIFY(classify_int, unsigned long long) + +template <typename Policy, typename Type> +inline bool +is_nan_int(const Type v) { + return Policy::has_nan && v == Extended_Int<Policy, Type>::not_a_number; +} + +PPL_SPECIALIZE_IS_NAN(is_nan_int, char) +PPL_SPECIALIZE_IS_NAN(is_nan_int, signed char) +PPL_SPECIALIZE_IS_NAN(is_nan_int, signed short) +PPL_SPECIALIZE_IS_NAN(is_nan_int, signed int) +PPL_SPECIALIZE_IS_NAN(is_nan_int, signed long) +PPL_SPECIALIZE_IS_NAN(is_nan_int, signed long long) +PPL_SPECIALIZE_IS_NAN(is_nan_int, unsigned char) +PPL_SPECIALIZE_IS_NAN(is_nan_int, unsigned short) +PPL_SPECIALIZE_IS_NAN(is_nan_int, unsigned int) +PPL_SPECIALIZE_IS_NAN(is_nan_int, unsigned long) +PPL_SPECIALIZE_IS_NAN(is_nan_int, unsigned long long) + +template <typename Policy, typename Type> +inline bool +is_minf_int(const Type v) { + return Policy::has_infinity + && v == Extended_Int<Policy, Type>::minus_infinity; +} + +PPL_SPECIALIZE_IS_MINF(is_minf_int, char) +PPL_SPECIALIZE_IS_MINF(is_minf_int, signed char) +PPL_SPECIALIZE_IS_MINF(is_minf_int, signed short) +PPL_SPECIALIZE_IS_MINF(is_minf_int, signed int) +PPL_SPECIALIZE_IS_MINF(is_minf_int, signed long) +PPL_SPECIALIZE_IS_MINF(is_minf_int, signed long long) +PPL_SPECIALIZE_IS_MINF(is_minf_int, unsigned char) +PPL_SPECIALIZE_IS_MINF(is_minf_int, unsigned short) +PPL_SPECIALIZE_IS_MINF(is_minf_int, unsigned int) +PPL_SPECIALIZE_IS_MINF(is_minf_int, unsigned long) +PPL_SPECIALIZE_IS_MINF(is_minf_int, unsigned long long) + +template <typename Policy, typename Type> +inline bool +is_pinf_int(const Type v) { + return Policy::has_infinity + && v == Extended_Int<Policy, Type>::plus_infinity; +} + +PPL_SPECIALIZE_IS_PINF(is_pinf_int, char) +PPL_SPECIALIZE_IS_PINF(is_pinf_int, signed char) +PPL_SPECIALIZE_IS_PINF(is_pinf_int, signed short) +PPL_SPECIALIZE_IS_PINF(is_pinf_int, signed int) +PPL_SPECIALIZE_IS_PINF(is_pinf_int, signed long) +PPL_SPECIALIZE_IS_PINF(is_pinf_int, signed long long) +PPL_SPECIALIZE_IS_PINF(is_pinf_int, unsigned char) +PPL_SPECIALIZE_IS_PINF(is_pinf_int, unsigned short) +PPL_SPECIALIZE_IS_PINF(is_pinf_int, unsigned int) +PPL_SPECIALIZE_IS_PINF(is_pinf_int, unsigned long) +PPL_SPECIALIZE_IS_PINF(is_pinf_int, unsigned long long) + +template <typename Policy, typename Type> +inline bool +is_int_int(const Type v) { + return !is_nan<Policy>(v); +} + +PPL_SPECIALIZE_IS_INT(is_int_int, char) +PPL_SPECIALIZE_IS_INT(is_int_int, signed char) +PPL_SPECIALIZE_IS_INT(is_int_int, signed short) +PPL_SPECIALIZE_IS_INT(is_int_int, signed int) +PPL_SPECIALIZE_IS_INT(is_int_int, signed long) +PPL_SPECIALIZE_IS_INT(is_int_int, signed long long) +PPL_SPECIALIZE_IS_INT(is_int_int, unsigned char) +PPL_SPECIALIZE_IS_INT(is_int_int, unsigned short) +PPL_SPECIALIZE_IS_INT(is_int_int, unsigned int) +PPL_SPECIALIZE_IS_INT(is_int_int, unsigned long) +PPL_SPECIALIZE_IS_INT(is_int_int, unsigned long long) + +template <typename Policy, typename Type> +inline Result +assign_special_int(Type& v, Result_Class c, Rounding_Dir dir) { + switch (c) { + case VC_NAN: + if (Policy::has_nan) { + v = Extended_Int<Policy, Type>::not_a_number; + return V_NAN; + } + return V_NAN | V_UNREPRESENTABLE; + case VC_MINUS_INFINITY: + if (Policy::has_infinity) { + v = Extended_Int<Policy, Type>::minus_infinity; + return V_EQ_MINUS_INFINITY; + } + if (round_up(dir)) { + v = Extended_Int<Policy, Type>::min; + return V_LT_INF; + } + return V_EQ_MINUS_INFINITY | V_UNREPRESENTABLE; + case VC_PLUS_INFINITY: + if (Policy::has_infinity) { + v = Extended_Int<Policy, Type>::plus_infinity; + return V_EQ_PLUS_INFINITY; + } + if (round_down(dir)) { + v = Extended_Int<Policy, Type>::max; + return V_GT_SUP; + } + return V_EQ_PLUS_INFINITY | V_UNREPRESENTABLE; + default: + PPL_ASSERT(0); + return V_NAN | V_UNREPRESENTABLE; + } +} + +PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_int, char) +PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_int, signed char) +PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_int, signed short) +PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_int, signed int) +PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_int, signed long) +PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_int, signed long long) +PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_int, unsigned char) +PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_int, unsigned short) +PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_int, unsigned int) +PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_int, unsigned long) +PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_int, unsigned long long) + +template <typename To_Policy, typename From_Policy, typename To, typename From> +inline Result +assign_signed_int_signed_int(To& to, const From from, Rounding_Dir dir) { + if (sizeof(To) < sizeof(From) + || (sizeof(To) == sizeof(From) + && (Extended_Int<To_Policy, To>::min > Extended_Int<From_Policy, From>::min + || Extended_Int<To_Policy, To>::max < Extended_Int<From_Policy, From>::max))) { + if (CHECK_P(To_Policy::check_overflow, + PPL_LT_SILENT(from, From(Extended_Int<To_Policy, To>::min)))) + return set_neg_overflow_int<To_Policy>(to, dir); + if (CHECK_P(To_Policy::check_overflow, + PPL_GT_SILENT(from, From(Extended_Int<To_Policy, To>::max)))) + return set_pos_overflow_int<To_Policy>(to, dir); + } + to = To(from); + return V_EQ; +} + +template <typename To_Policy, typename From_Policy, typename To, typename From> +inline Result +assign_signed_int_unsigned_int(To& to, const From from, Rounding_Dir dir) { + if (sizeof(To) <= sizeof(From)) { + if (CHECK_P(To_Policy::check_overflow, + from > From(Extended_Int<To_Policy, To>::max))) + return set_pos_overflow_int<To_Policy>(to, dir); + } + to = To(from); + return V_EQ; +} + +template <typename To_Policy, typename From_Policy, typename To, typename From> +inline Result +assign_unsigned_int_signed_int(To& to, const From from, Rounding_Dir dir) { + if (CHECK_P(To_Policy::check_overflow, from < 0)) + return set_neg_overflow_int<To_Policy>(to, dir); + if (sizeof(To) < sizeof(From)) { + if (CHECK_P(To_Policy::check_overflow, + from > From(Extended_Int<To_Policy, To>::max))) + return set_pos_overflow_int<To_Policy>(to, dir); + } + to = To(from); + return V_EQ; +} + +template <typename To_Policy, typename From_Policy, typename To, typename From> +inline Result +assign_unsigned_int_unsigned_int(To& to, const From from, Rounding_Dir dir) { + if (sizeof(To) < sizeof(From) + || (sizeof(To) == sizeof(From) + && Extended_Int<To_Policy, To>::max < Extended_Int<From_Policy, From>::max)) { + if (CHECK_P(To_Policy::check_overflow, + PPL_GT_SILENT(from, From(Extended_Int<To_Policy, To>::max)))) + return set_pos_overflow_int<To_Policy>(to, dir); + } + to = To(from); + return V_EQ; +} + + +#define PPL_ASSIGN2_SIGNED_SIGNED(Smaller, Larger) \ +PPL_SPECIALIZE_ASSIGN(assign_signed_int_signed_int, Smaller, Larger) \ +PPL_SPECIALIZE_ASSIGN(assign_signed_int_signed_int, Larger, Smaller) + +#define PPL_ASSIGN2_UNSIGNED_UNSIGNED(Smaller, Larger) \ +PPL_SPECIALIZE_ASSIGN(assign_unsigned_int_unsigned_int, Smaller, Larger) \ +PPL_SPECIALIZE_ASSIGN(assign_unsigned_int_unsigned_int, Larger, Smaller) + +#define PPL_ASSIGN2_UNSIGNED_SIGNED(Smaller, Larger) \ +PPL_SPECIALIZE_ASSIGN(assign_unsigned_int_signed_int, Smaller, Larger) \ +PPL_SPECIALIZE_ASSIGN(assign_signed_int_unsigned_int, Larger, Smaller) + +#define PPL_ASSIGN2_SIGNED_UNSIGNED(Smaller, Larger) \ +PPL_SPECIALIZE_ASSIGN(assign_signed_int_unsigned_int, Smaller, Larger) \ +PPL_SPECIALIZE_ASSIGN(assign_unsigned_int_signed_int, Larger, Smaller) + +#define PPL_ASSIGN_SIGNED(Type) \ +PPL_SPECIALIZE_ASSIGN(assign_signed_int_signed_int, Type, Type) +#define PPL_ASSIGN_UNSIGNED(Type) \ +PPL_SPECIALIZE_ASSIGN(assign_unsigned_int_unsigned_int, Type, Type) + +#if PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_ASSIGN_SIGNED(char) +#endif +PPL_ASSIGN_SIGNED(signed char) +PPL_ASSIGN_SIGNED(signed short) +PPL_ASSIGN_SIGNED(signed int) +PPL_ASSIGN_SIGNED(signed long) +PPL_ASSIGN_SIGNED(signed long long) +#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_ASSIGN_UNSIGNED(char) +#endif +PPL_ASSIGN_UNSIGNED(unsigned char) +PPL_ASSIGN_UNSIGNED(unsigned short) +PPL_ASSIGN_UNSIGNED(unsigned int) +PPL_ASSIGN_UNSIGNED(unsigned long) +PPL_ASSIGN_UNSIGNED(unsigned long long) + +#if PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_ASSIGN2_SIGNED_SIGNED(char, signed short) +PPL_ASSIGN2_SIGNED_SIGNED(char, signed int) +PPL_ASSIGN2_SIGNED_SIGNED(char, signed long) +PPL_ASSIGN2_SIGNED_SIGNED(char, signed long long) +#endif +PPL_ASSIGN2_SIGNED_SIGNED(signed char, signed short) +PPL_ASSIGN2_SIGNED_SIGNED(signed char, signed int) +PPL_ASSIGN2_SIGNED_SIGNED(signed char, signed long) +PPL_ASSIGN2_SIGNED_SIGNED(signed char, signed long long) +PPL_ASSIGN2_SIGNED_SIGNED(signed short, signed int) +PPL_ASSIGN2_SIGNED_SIGNED(signed short, signed long) +PPL_ASSIGN2_SIGNED_SIGNED(signed short, signed long long) +PPL_ASSIGN2_SIGNED_SIGNED(signed int, signed long) +PPL_ASSIGN2_SIGNED_SIGNED(signed int, signed long long) +PPL_ASSIGN2_SIGNED_SIGNED(signed long, signed long long) +#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_ASSIGN2_UNSIGNED_UNSIGNED(char, unsigned short) +PPL_ASSIGN2_UNSIGNED_UNSIGNED(char, unsigned int) +PPL_ASSIGN2_UNSIGNED_UNSIGNED(char, unsigned long) +PPL_ASSIGN2_UNSIGNED_UNSIGNED(char, unsigned long long) +#endif +PPL_ASSIGN2_UNSIGNED_UNSIGNED(unsigned char, unsigned short) +PPL_ASSIGN2_UNSIGNED_UNSIGNED(unsigned char, unsigned int) +PPL_ASSIGN2_UNSIGNED_UNSIGNED(unsigned char, unsigned long) +PPL_ASSIGN2_UNSIGNED_UNSIGNED(unsigned char, unsigned long long) +PPL_ASSIGN2_UNSIGNED_UNSIGNED(unsigned short, unsigned int) +PPL_ASSIGN2_UNSIGNED_UNSIGNED(unsigned short, unsigned long) +PPL_ASSIGN2_UNSIGNED_UNSIGNED(unsigned short, unsigned long long) +PPL_ASSIGN2_UNSIGNED_UNSIGNED(unsigned int, unsigned long) +PPL_ASSIGN2_UNSIGNED_UNSIGNED(unsigned int, unsigned long long) +PPL_ASSIGN2_UNSIGNED_UNSIGNED(unsigned long, unsigned long long) +#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_ASSIGN2_UNSIGNED_SIGNED(char, signed short) +PPL_ASSIGN2_UNSIGNED_SIGNED(char, signed int) +PPL_ASSIGN2_UNSIGNED_SIGNED(char, signed long) +PPL_ASSIGN2_UNSIGNED_SIGNED(char, signed long long) +#endif +PPL_ASSIGN2_UNSIGNED_SIGNED(unsigned char, signed short) +PPL_ASSIGN2_UNSIGNED_SIGNED(unsigned char, signed int) +PPL_ASSIGN2_UNSIGNED_SIGNED(unsigned char, signed long) +PPL_ASSIGN2_UNSIGNED_SIGNED(unsigned char, signed long long) +PPL_ASSIGN2_UNSIGNED_SIGNED(unsigned short, signed int) +PPL_ASSIGN2_UNSIGNED_SIGNED(unsigned short, signed long) +PPL_ASSIGN2_UNSIGNED_SIGNED(unsigned short, signed long long) +PPL_ASSIGN2_UNSIGNED_SIGNED(unsigned int, signed long) +PPL_ASSIGN2_UNSIGNED_SIGNED(unsigned int, signed long long) +PPL_ASSIGN2_UNSIGNED_SIGNED(unsigned long, signed long long) +#if PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_ASSIGN2_SIGNED_UNSIGNED(char, unsigned char) +PPL_ASSIGN2_SIGNED_UNSIGNED(char, unsigned short) +PPL_ASSIGN2_SIGNED_UNSIGNED(char, unsigned int) +PPL_ASSIGN2_SIGNED_UNSIGNED(char, unsigned long) +PPL_ASSIGN2_SIGNED_UNSIGNED(char, unsigned long long) +#else +PPL_ASSIGN2_SIGNED_UNSIGNED(signed char, char) +#endif +PPL_ASSIGN2_SIGNED_UNSIGNED(signed char, unsigned char) +PPL_ASSIGN2_SIGNED_UNSIGNED(signed char, unsigned short) +PPL_ASSIGN2_SIGNED_UNSIGNED(signed char, unsigned int) +PPL_ASSIGN2_SIGNED_UNSIGNED(signed char, unsigned long) +PPL_ASSIGN2_SIGNED_UNSIGNED(signed char, unsigned long long) +PPL_ASSIGN2_SIGNED_UNSIGNED(signed short, unsigned short) +PPL_ASSIGN2_SIGNED_UNSIGNED(signed short, unsigned int) +PPL_ASSIGN2_SIGNED_UNSIGNED(signed short, unsigned long) +PPL_ASSIGN2_SIGNED_UNSIGNED(signed short, unsigned long long) +PPL_ASSIGN2_SIGNED_UNSIGNED(signed int, unsigned int) +PPL_ASSIGN2_SIGNED_UNSIGNED(signed int, unsigned long) +PPL_ASSIGN2_SIGNED_UNSIGNED(signed int, unsigned long long) +PPL_ASSIGN2_SIGNED_UNSIGNED(signed long, unsigned long) +PPL_ASSIGN2_SIGNED_UNSIGNED(signed long, unsigned long long) +PPL_ASSIGN2_SIGNED_UNSIGNED(signed long long, unsigned long long) + +template <typename To_Policy, typename From_Policy, typename To, typename From> +inline Result +assign_int_float(To& to, const From from, Rounding_Dir dir) { + if (is_nan<From_Policy>(from)) + return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE); + else if (is_minf<From_Policy>(from)) + return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir); + else if (is_pinf<From_Policy>(from)) + return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir); +#if 0 + // FIXME: this is correct but it is inefficient and breaks the build + // for the missing definition of static const members (a problem present + // also in other areas of the PPL). + if (CHECK_P(To_Policy::check_overflow, lt(from, Extended_Int<To_Policy, To>::min))) + return set_neg_overflow_int<To_Policy>(to, dir); + if (CHECK_P(To_Policy::check_overflow, !le(from, Extended_Int<To_Policy, To>::max))) + return set_pos_overflow_int<To_Policy>(to, dir); +#else + if (CHECK_P(To_Policy::check_overflow, (from < Extended_Int<To_Policy, To>::min))) + return set_neg_overflow_int<To_Policy>(to, dir); + if (CHECK_P(To_Policy::check_overflow, (from > Extended_Int<To_Policy, To>::max))) + return set_pos_overflow_int<To_Policy>(to, dir); +#endif + if (round_not_requested(dir)) { + to = from; + return V_LGE; + } + From i_from = rint(from); + to = i_from; + if (from == i_from) + return V_EQ; + if (round_direct(ROUND_UP)) + return round_lt_int<To_Policy>(to, dir); + if (round_direct(ROUND_DOWN)) + return round_gt_int<To_Policy>(to, dir); + if (from < i_from) + return round_lt_int<To_Policy>(to, dir); + if (from > i_from) + return round_gt_int<To_Policy>(to, dir); + PPL_ASSERT(false); + return V_NAN; +} + +PPL_SPECIALIZE_ASSIGN(assign_int_float, char, float) +PPL_SPECIALIZE_ASSIGN(assign_int_float, signed char, float) +PPL_SPECIALIZE_ASSIGN(assign_int_float, signed short, float) +PPL_SPECIALIZE_ASSIGN(assign_int_float, signed int, float) +PPL_SPECIALIZE_ASSIGN(assign_int_float, signed long, float) +PPL_SPECIALIZE_ASSIGN(assign_int_float, signed long long, float) +PPL_SPECIALIZE_ASSIGN(assign_int_float, unsigned char, float) +PPL_SPECIALIZE_ASSIGN(assign_int_float, unsigned short, float) +PPL_SPECIALIZE_ASSIGN(assign_int_float, unsigned int, float) +PPL_SPECIALIZE_ASSIGN(assign_int_float, unsigned long, float) +PPL_SPECIALIZE_ASSIGN(assign_int_float, unsigned long long, float) + +PPL_SPECIALIZE_ASSIGN(assign_int_float, char, double) +PPL_SPECIALIZE_ASSIGN(assign_int_float, signed char, double) +PPL_SPECIALIZE_ASSIGN(assign_int_float, signed short, double) +PPL_SPECIALIZE_ASSIGN(assign_int_float, signed int, double) +PPL_SPECIALIZE_ASSIGN(assign_int_float, signed long, double) +PPL_SPECIALIZE_ASSIGN(assign_int_float, signed long long, double) +PPL_SPECIALIZE_ASSIGN(assign_int_float, unsigned char, double) +PPL_SPECIALIZE_ASSIGN(assign_int_float, unsigned short, double) +PPL_SPECIALIZE_ASSIGN(assign_int_float, unsigned int, double) +PPL_SPECIALIZE_ASSIGN(assign_int_float, unsigned long, double) +PPL_SPECIALIZE_ASSIGN(assign_int_float, unsigned long long, double) + +PPL_SPECIALIZE_ASSIGN(assign_int_float, char, long double) +PPL_SPECIALIZE_ASSIGN(assign_int_float, signed char, long double) +PPL_SPECIALIZE_ASSIGN(assign_int_float, signed short, long double) +PPL_SPECIALIZE_ASSIGN(assign_int_float, signed int, long double) +PPL_SPECIALIZE_ASSIGN(assign_int_float, signed long, long double) +PPL_SPECIALIZE_ASSIGN(assign_int_float, signed long long, long double) +PPL_SPECIALIZE_ASSIGN(assign_int_float, unsigned char, long double) +PPL_SPECIALIZE_ASSIGN(assign_int_float, unsigned short, long double) +PPL_SPECIALIZE_ASSIGN(assign_int_float, unsigned int, long double) +PPL_SPECIALIZE_ASSIGN(assign_int_float, unsigned long, long double) +PPL_SPECIALIZE_ASSIGN(assign_int_float, unsigned long long, long double) + +#undef PPL_ASSIGN_SIGNED +#undef PPL_ASSIGN_UNSIGNED +#undef PPL_ASSIGN2_SIGNED_SIGNED +#undef PPL_ASSIGN2_UNSIGNED_UNSIGNED +#undef PPL_ASSIGN2_UNSIGNED_SIGNED +#undef PPL_ASSIGN2_SIGNED_UNSIGNED + +template <typename To_Policy, typename From_Policy, typename To> +inline Result +assign_signed_int_mpz(To& to, const mpz_class& from, Rounding_Dir dir) { + if (sizeof(To) <= sizeof(signed long)) { + if (!To_Policy::check_overflow) { + to = from.get_si(); + return V_EQ; + } + if (from.fits_slong_p()) { + signed long v = from.get_si(); + if (PPL_LT_SILENT(v, (Extended_Int<To_Policy, To>::min))) + return set_neg_overflow_int<To_Policy>(to, dir); + if (PPL_GT_SILENT(v, (Extended_Int<To_Policy, To>::max))) + return set_pos_overflow_int<To_Policy>(to, dir); + to = v; + return V_EQ; + } + } + else { + mpz_srcptr m = from.get_mpz_t(); + size_t sz = mpz_size(m); + if (sz <= sizeof(To) / sizeof(mp_limb_t)) { + if (sz == 0) { + to = 0; + return V_EQ; + } + To v; + mpz_export(&v, 0, -1, sizeof(To), 0, 0, m); + if (v >= 0) { + if (::sgn(from) < 0) + return neg<To_Policy, To_Policy>(to, v, dir); + to = v; + return V_EQ; + } + } + } + return ::sgn(from) < 0 + ? set_neg_overflow_int<To_Policy>(to, dir) + : set_pos_overflow_int<To_Policy>(to, dir); +} + +#if PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_ASSIGN(assign_signed_int_mpz, char, mpz_class) +#endif +PPL_SPECIALIZE_ASSIGN(assign_signed_int_mpz, signed char, mpz_class) +PPL_SPECIALIZE_ASSIGN(assign_signed_int_mpz, signed short, mpz_class) +PPL_SPECIALIZE_ASSIGN(assign_signed_int_mpz, signed int, mpz_class) +PPL_SPECIALIZE_ASSIGN(assign_signed_int_mpz, signed long, mpz_class) +PPL_SPECIALIZE_ASSIGN(assign_signed_int_mpz, signed long long, mpz_class) + +template <typename To_Policy, typename From_Policy, typename To> +inline Result +assign_unsigned_int_mpz(To& to, const mpz_class& from, Rounding_Dir dir) { + if (CHECK_P(To_Policy::check_overflow, ::sgn(from) < 0)) + return set_neg_overflow_int<To_Policy>(to, dir); + if (sizeof(To) <= sizeof(unsigned long)) { + if (!To_Policy::check_overflow) { + to = from.get_ui(); + return V_EQ; + } + if (from.fits_ulong_p()) { + unsigned long v = from.get_ui(); + if (PPL_GT_SILENT(v, (Extended_Int<To_Policy, To>::max))) + return set_pos_overflow_int<To_Policy>(to, dir); + to = v; + return V_EQ; + } + } + else { + mpz_srcptr m = from.get_mpz_t(); + size_t sz = mpz_size(m); + if (sz <= sizeof(To) / sizeof(mp_limb_t)) { + if (sz == 0) + to = 0; + else + mpz_export(&to, 0, -1, sizeof(To), 0, 0, m); + return V_EQ; + } + } + return set_pos_overflow_int<To_Policy>(to, dir); +} + +#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_ASSIGN(assign_unsigned_int_mpz, char, mpz_class) +#endif +PPL_SPECIALIZE_ASSIGN(assign_unsigned_int_mpz, unsigned char, mpz_class) +PPL_SPECIALIZE_ASSIGN(assign_unsigned_int_mpz, unsigned short, mpz_class) +PPL_SPECIALIZE_ASSIGN(assign_unsigned_int_mpz, unsigned int, mpz_class) +PPL_SPECIALIZE_ASSIGN(assign_unsigned_int_mpz, unsigned long, mpz_class) +PPL_SPECIALIZE_ASSIGN(assign_unsigned_int_mpz, unsigned long long, mpz_class) + +template <typename To_Policy, typename From_Policy, typename To> +inline Result +assign_int_mpq(To& to, const mpq_class& from, Rounding_Dir dir) { + mpz_srcptr n = from.get_num().get_mpz_t(); + mpz_srcptr d = from.get_den().get_mpz_t(); + PPL_DIRTY_TEMP0(mpz_class, q); + mpz_ptr _q = q.get_mpz_t(); + if (round_not_requested(dir)) { + mpz_tdiv_q(_q, n, d); + Result r = assign<To_Policy, void>(to, q, dir); + if (r != V_EQ) + return r; + return V_LGE; + } + mpz_t rem; + int sign; + mpz_init(rem); + mpz_tdiv_qr(_q, rem, n, d); + sign = mpz_sgn(rem); + mpz_clear(rem); + Result r = assign<To_Policy, void>(to, q, dir); + if (r != V_EQ) + return r; + switch (sign) { + case -1: + return round_lt_int<To_Policy>(to, dir); + case 1: + return round_gt_int<To_Policy>(to, dir); + default: + return V_EQ; + } +} + +PPL_SPECIALIZE_ASSIGN(assign_int_mpq, char, mpq_class) +PPL_SPECIALIZE_ASSIGN(assign_int_mpq, signed char, mpq_class) +PPL_SPECIALIZE_ASSIGN(assign_int_mpq, signed short, mpq_class) +PPL_SPECIALIZE_ASSIGN(assign_int_mpq, signed int, mpq_class) +PPL_SPECIALIZE_ASSIGN(assign_int_mpq, signed long, mpq_class) +PPL_SPECIALIZE_ASSIGN(assign_int_mpq, signed long long, mpq_class) +PPL_SPECIALIZE_ASSIGN(assign_int_mpq, unsigned char, mpq_class) +PPL_SPECIALIZE_ASSIGN(assign_int_mpq, unsigned short, mpq_class) +PPL_SPECIALIZE_ASSIGN(assign_int_mpq, unsigned int, mpq_class) +PPL_SPECIALIZE_ASSIGN(assign_int_mpq, unsigned long, mpq_class) +PPL_SPECIALIZE_ASSIGN(assign_int_mpq, unsigned long long, mpq_class) + +#if ~0 != -1 +#error "Only two's complement is supported" +#endif + +#if UCHAR_MAX == 0xff +#define CHAR_BITS 8 +#else +#error "Unexpected max for unsigned char" +#endif + +#if USHRT_MAX == 0xffff +#define SHRT_BITS 16 +#else +#error "Unexpected max for unsigned short" +#endif + +#if UINT_MAX == 0xffffffff +#define INT_BITS 32 +#else +#error "Unexpected max for unsigned int" +#endif + +#if ULONG_MAX == 0xffffffffUL +#define LONG_BITS 32 +#elif ULONG_MAX == 0xffffffffffffffffULL +#define LONG_BITS 64 +#else +#error "Unexpected max for unsigned long" +#endif + +#if ULLONG_MAX == 0xffffffffffffffffULL +#define LONG_LONG_BITS 64 +#else +#error "Unexpected max for unsigned long long" +#endif + + +template <typename T> +struct Larger; + +// The following may be tuned for performance on specific architectures. +// +// Current guidelines: +// - avoid division where possible (larger type variant for mul) +// - use larger type variant for types smaller than architecture bit size + +template <> +struct Larger<char> { + const_bool_nodef(use_for_neg, true); + const_bool_nodef(use_for_add, true); + const_bool_nodef(use_for_sub, true); + const_bool_nodef(use_for_mul, true); + typedef int_fast16_t type_for_neg; + typedef int_fast16_t type_for_add; + typedef int_fast16_t type_for_sub; + typedef int_fast16_t type_for_mul; +}; + +template <> +struct Larger<signed char> { + const_bool_nodef(use_for_neg, true); + const_bool_nodef(use_for_add, true); + const_bool_nodef(use_for_sub, true); + const_bool_nodef(use_for_mul, true); + typedef int_fast16_t type_for_neg; + typedef int_fast16_t type_for_add; + typedef int_fast16_t type_for_sub; + typedef int_fast16_t type_for_mul; +}; + +template <> +struct Larger<unsigned char> { + const_bool_nodef(use_for_neg, true); + const_bool_nodef(use_for_add, true); + const_bool_nodef(use_for_sub, true); + const_bool_nodef(use_for_mul, true); + typedef int_fast16_t type_for_neg; + typedef uint_fast16_t type_for_add; + typedef int_fast16_t type_for_sub; + typedef uint_fast16_t type_for_mul; +}; + +template <> +struct Larger<signed short> { + const_bool_nodef(use_for_neg, true); + const_bool_nodef(use_for_add, true); + const_bool_nodef(use_for_sub, true); + const_bool_nodef(use_for_mul, true); + typedef int_fast32_t type_for_neg; + typedef int_fast32_t type_for_add; + typedef int_fast32_t type_for_sub; + typedef int_fast32_t type_for_mul; +}; + +template <> +struct Larger<unsigned short> { + const_bool_nodef(use_for_neg, true); + const_bool_nodef(use_for_add, true); + const_bool_nodef(use_for_sub, true); + const_bool_nodef(use_for_mul, true); + typedef int_fast32_t type_for_neg; + typedef uint_fast32_t type_for_add; + typedef int_fast32_t type_for_sub; + typedef uint_fast32_t type_for_mul; +}; + +template <> +struct Larger<signed int> { + const_bool_nodef(use_for_neg, (LONG_BITS == 64)); + const_bool_nodef(use_for_add, (LONG_BITS == 64)); + const_bool_nodef(use_for_sub, (LONG_BITS == 64)); + const_bool_nodef(use_for_mul, true); + typedef int_fast64_t type_for_neg; + typedef int_fast64_t type_for_add; + typedef int_fast64_t type_for_sub; + typedef int_fast64_t type_for_mul; +}; + +template <> +struct Larger<unsigned int> { + const_bool_nodef(use_for_neg, (LONG_BITS == 64)); + const_bool_nodef(use_for_add, (LONG_BITS == 64)); + const_bool_nodef(use_for_sub, (LONG_BITS == 64)); + const_bool_nodef(use_for_mul, true); + typedef int_fast64_t type_for_neg; + typedef uint_fast64_t type_for_add; + typedef int_fast64_t type_for_sub; + typedef uint_fast64_t type_for_mul; +}; + +template <> +struct Larger<signed long> { + const_bool_nodef(use_for_neg, false); + const_bool_nodef(use_for_add, false); + const_bool_nodef(use_for_sub, false); + const_bool_nodef(use_for_mul, (LONG_BITS == 32)); + typedef int_fast64_t type_for_neg; + typedef int_fast64_t type_for_add; + typedef int_fast64_t type_for_sub; + typedef int_fast64_t type_for_mul; +}; + +template <> +struct Larger<unsigned long> { + const_bool_nodef(use_for_neg, false); + const_bool_nodef(use_for_add, false); + const_bool_nodef(use_for_sub, false); + const_bool_nodef(use_for_mul, (LONG_BITS == 32)); + typedef int_fast64_t type_for_neg; + typedef uint_fast64_t type_for_add; + typedef int_fast64_t type_for_sub; + typedef uint_fast64_t type_for_mul; +}; + +template <> +struct Larger<signed long long> { + const_bool_nodef(use_for_neg, false); + const_bool_nodef(use_for_add, false); + const_bool_nodef(use_for_sub, false); + const_bool_nodef(use_for_mul, false); + typedef int_fast64_t type_for_neg; + typedef int_fast64_t type_for_add; + typedef int_fast64_t type_for_sub; + typedef int_fast64_t type_for_mul; +}; + +template <> +struct Larger<unsigned long long> { + const_bool_nodef(use_for_neg, false); + const_bool_nodef(use_for_add, false); + const_bool_nodef(use_for_sub, false); + const_bool_nodef(use_for_mul, false); + typedef int_fast64_t type_for_neg; + typedef uint_fast64_t type_for_add; + typedef int_fast64_t type_for_sub; + typedef uint_fast64_t type_for_mul; +}; + +template <typename To_Policy, typename From_Policy, typename Type> +inline Result +neg_int_larger(Type& to, const Type x, Rounding_Dir dir) { + typename Larger<Type>::type_for_neg l = x; + l = -l; + return assign<To_Policy, To_Policy>(to, l, dir); +} + +template <typename To_Policy, typename From1_Policy, typename From2_Policy, typename Type> +inline Result +add_int_larger(Type& to, const Type x, const Type y, Rounding_Dir dir) { + typename Larger<Type>::type_for_add l = x; + l += y; + return assign<To_Policy, To_Policy>(to, l, dir); +} + +template <typename To_Policy, typename From1_Policy, typename From2_Policy, typename Type> +inline Result +sub_int_larger(Type& to, const Type x, const Type y, Rounding_Dir dir) { + typename Larger<Type>::type_for_sub l = x; + l -= y; + return assign<To_Policy, To_Policy>(to, l, dir); +} + +template <typename To_Policy, typename From1_Policy, typename From2_Policy, typename Type> +inline Result +mul_int_larger(Type& to, const Type x, const Type y, Rounding_Dir dir) { + typename Larger<Type>::type_for_mul l = x; + l *= y; + return assign<To_Policy, To_Policy>(to, l, dir); +} + +template <typename To_Policy, typename From_Policy, typename Type> +inline Result +neg_signed_int(Type& to, const Type from, Rounding_Dir dir) { + if (To_Policy::check_overflow && Larger<Type>::use_for_neg) + return neg_int_larger<To_Policy, From_Policy>(to, from, dir); + if (CHECK_P(To_Policy::check_overflow, + (from < -Extended_Int<To_Policy, Type>::max))) + return set_pos_overflow_int<To_Policy>(to, dir); + to = -from; + return V_EQ; +} + +template <typename To_Policy, typename From_Policy, typename Type> +inline Result +neg_unsigned_int(Type& to, const Type from, Rounding_Dir dir) { + if (To_Policy::check_overflow && Larger<Type>::use_for_neg) + return neg_int_larger<To_Policy, From_Policy>(to, from, dir); + if (CHECK_P(To_Policy::check_overflow, from != 0)) + return set_neg_overflow_int<To_Policy>(to, dir); + to = from; + return V_EQ; +} + +template <typename To_Policy, typename From1_Policy, typename From2_Policy, typename Type> +inline Result +add_signed_int(Type& to, const Type x, const Type y, Rounding_Dir dir) { + if (To_Policy::check_overflow && Larger<Type>::use_for_add) + return add_int_larger<To_Policy, From1_Policy, From2_Policy>(to, x, y, dir); + if (To_Policy::check_overflow) { + if (y >= 0) { + if (x > Extended_Int<To_Policy, Type>::max - y) + return set_pos_overflow_int<To_Policy>(to, dir); + } + else if (x < Extended_Int<To_Policy, Type>::min - y) + return set_neg_overflow_int<To_Policy>(to, dir); + } + to = x + y; + return V_EQ; +} + +template <typename To_Policy, typename From1_Policy, typename From2_Policy, typename Type> +inline Result +add_unsigned_int(Type& to, const Type x, const Type y, Rounding_Dir dir) { + if (To_Policy::check_overflow && Larger<Type>::use_for_add) + return add_int_larger<To_Policy, From1_Policy, From2_Policy>(to, x, y, dir); + if (CHECK_P(To_Policy::check_overflow, + (x > Extended_Int<To_Policy, Type>::max - y))) + return set_pos_overflow_int<To_Policy>(to, dir); + to = x + y; + return V_EQ; +} + +template <typename To_Policy, typename From1_Policy, typename From2_Policy, typename Type> +inline Result +sub_signed_int(Type& to, const Type x, const Type y, Rounding_Dir dir) { + if (To_Policy::check_overflow && Larger<Type>::use_for_sub) + return sub_int_larger<To_Policy, From1_Policy, From2_Policy>(to, x, y, dir); + if (To_Policy::check_overflow) { + if (y >= 0) { + if (x < Extended_Int<To_Policy, Type>::min + y) + return set_neg_overflow_int<To_Policy>(to, dir); + } + else if (x > Extended_Int<To_Policy, Type>::max + y) + return set_pos_overflow_int<To_Policy>(to, dir); + } + to = x - y; + return V_EQ; +} + +template <typename To_Policy, typename From1_Policy, typename From2_Policy, typename Type> +inline Result +sub_unsigned_int(Type& to, const Type x, const Type y, Rounding_Dir dir) { + if (To_Policy::check_overflow && Larger<Type>::use_for_sub) + return sub_int_larger<To_Policy, From1_Policy, From2_Policy>(to, x, y, dir); + if (CHECK_P(To_Policy::check_overflow, + (x < Extended_Int<To_Policy, Type>::min + y))) + return set_neg_overflow_int<To_Policy>(to, dir); + to = x - y; + return V_EQ; +} + +template <typename To_Policy, typename From1_Policy, typename From2_Policy, typename Type> +inline Result +mul_signed_int(Type& to, const Type x, const Type y, Rounding_Dir dir) { + if (To_Policy::check_overflow && Larger<Type>::use_for_mul) + return mul_int_larger<To_Policy, From1_Policy, From2_Policy>(to, x, y, dir); + if (!To_Policy::check_overflow) { + to = x * y; + return V_EQ; + } + if (y == 0) { + to = 0; + return V_EQ; + } + if (y == -1) + return neg_signed_int<To_Policy, From1_Policy>(to, x, dir); + if (x >= 0) { + if (y > 0) { + if (x > Extended_Int<To_Policy, Type>::max / y) + return set_pos_overflow_int<To_Policy>(to, dir); + } + else { + if (x > Extended_Int<To_Policy, Type>::min / y) + return set_neg_overflow_int<To_Policy>(to, dir); + } + } + else { + if (y < 0) { + if (x < Extended_Int<To_Policy, Type>::max / y) + return set_pos_overflow_int<To_Policy>(to, dir); + } + else { + if (x < Extended_Int<To_Policy, Type>::min / y) + return set_neg_overflow_int<To_Policy>(to, dir); + } + } + to = x * y; + return V_EQ; +} + +template <typename To_Policy, typename From1_Policy, typename From2_Policy, typename Type> +inline Result +mul_unsigned_int(Type& to, const Type x, const Type y, Rounding_Dir dir) { + if (To_Policy::check_overflow && Larger<Type>::use_for_mul) + return mul_int_larger<To_Policy, From1_Policy, From2_Policy>(to, x, y, dir); + if (!To_Policy::check_overflow) { + to = x * y; + return V_EQ; + } + if (y == 0) { + to = 0; + return V_EQ; + } + if (x > Extended_Int<To_Policy, Type>::max / y) + return set_pos_overflow_int<To_Policy>(to, dir); + to = x * y; + return V_EQ; +} + +template <typename To_Policy, typename From1_Policy, typename From2_Policy, typename Type> +inline Result +div_signed_int(Type& to, const Type x, const Type y, Rounding_Dir dir) { + if (CHECK_P(To_Policy::check_div_zero, y == 0)) { + return assign_nan<To_Policy>(to, V_DIV_ZERO); + } + if (To_Policy::check_overflow && y == -1) + return neg_signed_int<To_Policy, From1_Policy>(to, x, dir); + to = x / y; + if (round_not_requested(dir)) + return V_LGE; + Type m = x % y; + if (m < 0) + return round_lt_int_no_overflow<To_Policy>(to, dir); + else if (m > 0) + return round_gt_int_no_overflow<To_Policy>(to, dir); + else + return V_EQ; +} + +template <typename To_Policy, typename From1_Policy, typename From2_Policy, typename Type> +inline Result +div_unsigned_int(Type& to, const Type x, const Type y, Rounding_Dir dir) { + if (CHECK_P(To_Policy::check_div_zero, y == 0)) { + return assign_nan<To_Policy>(to, V_DIV_ZERO); + } + to = x / y; + if (round_not_requested(dir)) + return V_GE; + Type m = x % y; + if (m == 0) + return V_EQ; + return round_gt_int<To_Policy>(to, dir); +} + +template <typename To_Policy, typename From1_Policy, typename From2_Policy, typename Type> +inline Result +idiv_signed_int(Type& to, const Type x, const Type y, Rounding_Dir dir) { + if (CHECK_P(To_Policy::check_div_zero, y == 0)) { + return assign_nan<To_Policy>(to, V_DIV_ZERO); + } + if (To_Policy::check_overflow && y == -1) + return neg_signed_int<To_Policy, From1_Policy>(to, x, dir); + to = x / y; + return V_EQ; +} + +template <typename To_Policy, typename From1_Policy, typename From2_Policy, typename Type> +inline Result +idiv_unsigned_int(Type& to, const Type x, const Type y, Rounding_Dir) { + if (CHECK_P(To_Policy::check_div_zero, y == 0)) { + return assign_nan<To_Policy>(to, V_DIV_ZERO); + } + to = x / y; + return V_EQ; +} + +template <typename To_Policy, typename From1_Policy, typename From2_Policy, typename Type> +inline Result +rem_signed_int(Type& to, const Type x, const Type y, Rounding_Dir) { + if (CHECK_P(To_Policy::check_div_zero, y == 0)) { + return assign_nan<To_Policy>(to, V_MOD_ZERO); + } + to = x % y; + return V_EQ; +} + +template <typename To_Policy, typename From1_Policy, typename From2_Policy, typename Type> +inline Result +rem_unsigned_int(Type& to, const Type x, const Type y, Rounding_Dir) { + if (CHECK_P(To_Policy::check_div_zero, y == 0)) { + return assign_nan<To_Policy>(to, V_MOD_ZERO); + } + to = x % y; + return V_EQ; +} + +template <typename To_Policy, typename From_Policy, typename Type> +inline Result +div_2exp_unsigned_int(Type& to, const Type x, unsigned int exp, + Rounding_Dir dir) { + if (exp >= sizeof(Type) * CHAR_BIT) { + to = 0; + if (round_not_requested(dir)) + return V_GE; + if (x == 0) + return V_EQ; + return round_gt_int_no_overflow<To_Policy>(to, dir); + } + to = x >> exp; + if (round_not_requested(dir)) + return V_GE; + if (x & ((Type(1) << exp) - 1)) + return round_gt_int_no_overflow<To_Policy>(to, dir); + else + return V_EQ; +} + +template <typename To_Policy, typename From_Policy, typename Type> +inline Result +div_2exp_signed_int(Type& to, const Type x, unsigned int exp, + Rounding_Dir dir) { + if (exp > sizeof(Type) * CHAR_BIT - 1) { + zero: + to = 0; + if (round_not_requested(dir)) + return V_LGE; + if (x < 0) + return round_lt_int_no_overflow<To_Policy>(to, dir); + else if (x > 0) + return round_gt_int_no_overflow<To_Policy>(to, dir); + else + return V_EQ; + } + if (exp == sizeof(Type) * CHAR_BIT - 1) { + if (x == C_Integer<Type>::min) { + to = -1; + return V_EQ; + } + goto zero; + } +#if 0 + to = x / (Type(1) << exp); + if (round_not_requested(dir)) + return V_GE; + Type r = x % (Type(1) << exp); + if (r < 0) + return round_lt_int_no_overflow<To_Policy>(to, dir); + else if (r > 0) + return round_gt_int_no_overflow<To_Policy>(to, dir); + else + return V_EQ; +#else + // Faster but compiler implementation dependent (see C++98 5.8.3) + to = x >> exp; + if (round_not_requested(dir)) + return V_GE; + if (x & ((Type(1) << exp) - 1)) + return round_gt_int_no_overflow<To_Policy>(to, dir); + return V_EQ; +#endif +} + +template <typename To_Policy, typename From_Policy, typename Type> +inline Result +add_2exp_unsigned_int(Type& to, const Type x, unsigned int exp, + Rounding_Dir dir) { + if (!To_Policy::check_overflow) { + to = x + (Type(1) << exp); + return V_EQ; + } + if (exp >= sizeof(Type) * CHAR_BIT) + return set_pos_overflow_int<To_Policy>(to, dir); + Type n = Type(1) << exp; + return add_unsigned_int<To_Policy, From_Policy, void>(to, x, n, dir); +} + +template <typename To_Policy, typename From_Policy, typename Type> +inline Result +add_2exp_signed_int(Type& to, const Type x, unsigned int exp, + Rounding_Dir dir) { + if (!To_Policy::check_overflow) { + to = x + (Type(1) << exp); + return V_EQ; + } + if (exp >= sizeof(Type) * CHAR_BIT) + return set_pos_overflow_int<To_Policy>(to, dir); + if (exp == sizeof(Type) * CHAR_BIT - 1) { + Type n = -2 * (Type(1) << (exp - 1)); + return sub_signed_int<To_Policy, From_Policy, void>(to, x, n, dir); + } + else { + Type n = Type(1) << exp; + return add_signed_int<To_Policy, From_Policy, void>(to, x, n, dir); + } +} + +template <typename To_Policy, typename From_Policy, typename Type> +inline Result +sub_2exp_unsigned_int(Type& to, const Type x, unsigned int exp, + Rounding_Dir dir) { + if (!To_Policy::check_overflow) { + to = x - (Type(1) << exp); + return V_EQ; + } + if (exp >= sizeof(Type) * CHAR_BIT) + return set_neg_overflow_int<To_Policy>(to, dir); + Type n = Type(1) << exp; + return sub_unsigned_int<To_Policy, From_Policy, void>(to, x, n, dir); +} + +template <typename To_Policy, typename From_Policy, typename Type> +inline Result +sub_2exp_signed_int(Type& to, const Type x, unsigned int exp, + Rounding_Dir dir) { + if (!To_Policy::check_overflow) { + to = x - (Type(1) << exp); + return V_EQ; + } + if (exp >= sizeof(Type) * CHAR_BIT) + return set_neg_overflow_int<To_Policy>(to, dir); + if (exp == sizeof(Type) * CHAR_BIT - 1) { + Type n = -2 * (Type(1) << (exp - 1)); + return add_signed_int<To_Policy, From_Policy, void>(to, x, n, dir); + } + else { + Type n = Type(1) << exp; + return sub_signed_int<To_Policy, From_Policy, void>(to, x, n, dir); + } +} + +template <typename To_Policy, typename From_Policy, typename Type> +inline Result +mul_2exp_unsigned_int(Type& to, const Type x, unsigned int exp, + Rounding_Dir dir) { + if (!To_Policy::check_overflow) { + to = x << exp; + return V_EQ; + } + if (exp >= sizeof(Type) * CHAR_BIT) { + if (x == 0) { + to = 0; + return V_EQ; + } + return set_pos_overflow_int<To_Policy>(to, dir); + } + if (x & (((Type(1) << exp) - 1) << (sizeof(Type) * CHAR_BIT - exp))) + return set_pos_overflow_int<To_Policy>(to, dir); + Type n = x << exp; + if (PPL_GT_SILENT(n, (Extended_Int<To_Policy, Type>::max))) + return set_pos_overflow_int<To_Policy>(to, dir); + to = n; + return V_EQ; +} + +template <typename To_Policy, typename From_Policy, typename Type> +inline Result +mul_2exp_signed_int(Type& to, const Type x, unsigned int exp, + Rounding_Dir dir) { + if (!To_Policy::check_overflow) { + to = x << exp; + return V_EQ; + } + if (exp >= sizeof(Type) * CHAR_BIT - 1) { + if (x < 0) + return set_neg_overflow_int<To_Policy>(to, dir); + else if (x > 0) + return set_pos_overflow_int<To_Policy>(to, dir); + else { + to = 0; + return V_EQ; + } + } + Type mask = ((Type(1) << exp) - 1) + << (sizeof(Type) * CHAR_BIT - 1 - exp); + Type n; + if (x < 0) { + if ((x & mask) != mask) + return set_neg_overflow_int<To_Policy>(to, dir); + n = x << exp; + if (PPL_LT_SILENT(n, (Extended_Int<To_Policy, Type>::min))) + return set_neg_overflow_int<To_Policy>(to, dir); + } + else { + if (x & mask) + return set_pos_overflow_int<To_Policy>(to, dir); + n = x << exp; + if (PPL_GT_SILENT(n, (Extended_Int<To_Policy, Type>::max))) + return set_pos_overflow_int<To_Policy>(to, dir); + } + to = n; + return V_EQ; +} + +template <typename To_Policy, typename From_Policy, typename Type> +inline Result +smod_2exp_unsigned_int(Type& to, const Type x, unsigned int exp, + Rounding_Dir dir) { + if (exp > sizeof(Type) * CHAR_BIT) + to = x; + else { + Type v = exp == sizeof(Type) * CHAR_BIT ? x : (x & ((Type(1) << exp) - 1)); + if (v >= Type(1) << (exp - 1)) + return set_neg_overflow_int<To_Policy>(to, dir); + else + to = v; + } + return V_EQ; +} + +template <typename To_Policy, typename From_Policy, typename Type> +inline Result +smod_2exp_signed_int(Type& to, const Type x, unsigned int exp, + Rounding_Dir) { + if (exp >= sizeof(Type) * CHAR_BIT) + to = x; + else { + Type m = Type(1) << (exp - 1); + to = (x & (m - 1)) - (x & m); + } + return V_EQ; +} + +template <typename To_Policy, typename From_Policy, typename Type> +inline Result +umod_2exp_unsigned_int(Type& to, const Type x, unsigned int exp, + Rounding_Dir) { + if (exp >= sizeof(Type) * CHAR_BIT) + to = x; + else + to = x & ((Type(1) << exp) - 1); + return V_EQ; +} + +template <typename To_Policy, typename From_Policy, typename Type> +inline Result +umod_2exp_signed_int(Type& to, const Type x, unsigned int exp, + Rounding_Dir dir) { + if (exp >= sizeof(Type) * CHAR_BIT) { + if (x < 0) + return set_pos_overflow_int<To_Policy>(to, dir); + to = x; + } + else + to = x & ((Type(1) << exp) - 1); + return V_EQ; +} + +template <typename Type> +inline void +isqrtrem(Type& q, Type& r, const Type from) { + q = 0; + r = from; + Type t(1); + for (t <<= CHAR_BIT * sizeof(Type) - 2; t != 0; t >>= 2) { + Type s = q + t; + if (s <= r) { + r -= s; + q = s + t; + } + q >>= 1; + } +} + +template <typename To_Policy, typename From_Policy, typename Type> +inline Result +sqrt_unsigned_int(Type& to, const Type from, Rounding_Dir dir) { + Type rem; + isqrtrem(to, rem, from); + if (round_not_requested(dir)) + return V_GE; + if (rem == 0) + return V_EQ; + return round_gt_int<To_Policy>(to, dir); +} + +template <typename To_Policy, typename From_Policy, typename Type> +inline Result +sqrt_signed_int(Type& to, const Type from, Rounding_Dir dir) { + if (CHECK_P(To_Policy::check_sqrt_neg, from < 0)) { + return assign_nan<To_Policy>(to, V_SQRT_NEG); + } + return sqrt_unsigned_int<To_Policy, From_Policy>(to, from, dir); +} + +template <typename To_Policy, typename From1_Policy, typename From2_Policy, typename Type> +inline Result +add_mul_int(Type& to, const Type x, const Type y, Rounding_Dir dir) { + Type z; + Result r = mul<To_Policy, From1_Policy, From2_Policy>(z, x, y, dir); + switch (result_overflow(r)) { + case 0: + return add<To_Policy, To_Policy, To_Policy>(to, to, z, dir); + case -1: + if (to <= 0) + return set_neg_overflow_int<To_Policy>(to, dir); + return assign_nan<To_Policy>(to, V_UNKNOWN_NEG_OVERFLOW); + case 1: + if (to >= 0) + return set_pos_overflow_int<To_Policy>(to, dir); + return assign_nan<To_Policy>(to, V_UNKNOWN_POS_OVERFLOW); + default: + PPL_ASSERT(false); + return V_NAN; + } +} + +template <typename To_Policy, typename From1_Policy, typename From2_Policy, typename Type> +inline Result +sub_mul_int(Type& to, const Type x, const Type y, Rounding_Dir dir) { + Type z; + Result r = mul<To_Policy, From1_Policy, From2_Policy>(z, x, y, dir); + switch (result_overflow(r)) { + case 0: + return sub<To_Policy, To_Policy, To_Policy>(to, to, z, dir); + case -1: + if (to >= 0) + return set_pos_overflow_int<To_Policy>(to, dir); + return assign_nan<To_Policy>(to, V_UNKNOWN_NEG_OVERFLOW); + case 1: + if (to <= 0) + return set_neg_overflow_int<To_Policy>(to, dir); + return assign_nan<To_Policy>(to, V_UNKNOWN_POS_OVERFLOW); + default: + PPL_ASSERT(false); + return V_NAN; + } +} + +template <typename Policy, typename Type> +inline Result +output_char(std::ostream& os, Type& from, + const Numeric_Format&, Rounding_Dir) { + os << int(from); + return V_EQ; +} + +template <typename Policy, typename Type> +inline Result +output_int(std::ostream& os, Type& from, const Numeric_Format&, Rounding_Dir) { + os << from; + return V_EQ; +} + +#if PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_FLOOR(assign_signed_int_signed_int, char, char) +#endif +PPL_SPECIALIZE_FLOOR(assign_signed_int_signed_int, signed char, signed char) +PPL_SPECIALIZE_FLOOR(assign_signed_int_signed_int, signed short, signed short) +PPL_SPECIALIZE_FLOOR(assign_signed_int_signed_int, signed int, signed int) +PPL_SPECIALIZE_FLOOR(assign_signed_int_signed_int, signed long, signed long) +PPL_SPECIALIZE_FLOOR(assign_signed_int_signed_int, signed long long, signed long long) +#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_FLOOR(assign_unsigned_int_unsigned_int, char, char) +#endif +PPL_SPECIALIZE_FLOOR(assign_unsigned_int_unsigned_int, unsigned char, unsigned char) +PPL_SPECIALIZE_FLOOR(assign_unsigned_int_unsigned_int, unsigned short, unsigned short) +PPL_SPECIALIZE_FLOOR(assign_unsigned_int_unsigned_int, unsigned int, unsigned int) +PPL_SPECIALIZE_FLOOR(assign_unsigned_int_unsigned_int, unsigned long, unsigned long) +PPL_SPECIALIZE_FLOOR(assign_unsigned_int_unsigned_int, unsigned long long, unsigned long long) + +#if PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_CEIL(assign_signed_int_signed_int, char, char) +#endif +PPL_SPECIALIZE_CEIL(assign_signed_int_signed_int, signed char, signed char) +PPL_SPECIALIZE_CEIL(assign_signed_int_signed_int, signed short, signed short) +PPL_SPECIALIZE_CEIL(assign_signed_int_signed_int, signed int, signed int) +PPL_SPECIALIZE_CEIL(assign_signed_int_signed_int, signed long, signed long) +PPL_SPECIALIZE_CEIL(assign_signed_int_signed_int, signed long long, signed long long) +#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_CEIL(assign_unsigned_int_unsigned_int, char, char) +#endif +PPL_SPECIALIZE_CEIL(assign_unsigned_int_unsigned_int, unsigned char, unsigned char) +PPL_SPECIALIZE_CEIL(assign_unsigned_int_unsigned_int, unsigned short, unsigned short) +PPL_SPECIALIZE_CEIL(assign_unsigned_int_unsigned_int, unsigned int, unsigned int) +PPL_SPECIALIZE_CEIL(assign_unsigned_int_unsigned_int, unsigned long, unsigned long) +PPL_SPECIALIZE_CEIL(assign_unsigned_int_unsigned_int, unsigned long long, unsigned long long) + +#if PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_TRUNC(assign_signed_int_signed_int, char, char) +#endif +PPL_SPECIALIZE_TRUNC(assign_signed_int_signed_int, signed char, signed char) +PPL_SPECIALIZE_TRUNC(assign_signed_int_signed_int, signed short, signed short) +PPL_SPECIALIZE_TRUNC(assign_signed_int_signed_int, signed int, signed int) +PPL_SPECIALIZE_TRUNC(assign_signed_int_signed_int, signed long, signed long) +PPL_SPECIALIZE_TRUNC(assign_signed_int_signed_int, signed long long, signed long long) +#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_TRUNC(assign_unsigned_int_unsigned_int, char, char) +#endif +PPL_SPECIALIZE_TRUNC(assign_unsigned_int_unsigned_int, unsigned char, unsigned char) +PPL_SPECIALIZE_TRUNC(assign_unsigned_int_unsigned_int, unsigned short, unsigned short) +PPL_SPECIALIZE_TRUNC(assign_unsigned_int_unsigned_int, unsigned int, unsigned int) +PPL_SPECIALIZE_TRUNC(assign_unsigned_int_unsigned_int, unsigned long, unsigned long) +PPL_SPECIALIZE_TRUNC(assign_unsigned_int_unsigned_int, unsigned long long, unsigned long long) + +#if PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_NEG(neg_signed_int, char, char) +#endif +PPL_SPECIALIZE_NEG(neg_signed_int, signed char, signed char) +PPL_SPECIALIZE_NEG(neg_signed_int, signed short, signed short) +PPL_SPECIALIZE_NEG(neg_signed_int, signed int, signed int) +PPL_SPECIALIZE_NEG(neg_signed_int, signed long, signed long) +PPL_SPECIALIZE_NEG(neg_signed_int, signed long long, signed long long) +#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_NEG(neg_unsigned_int, char, char) +#endif +PPL_SPECIALIZE_NEG(neg_unsigned_int, unsigned char, unsigned char) +PPL_SPECIALIZE_NEG(neg_unsigned_int, unsigned short, unsigned short) +PPL_SPECIALIZE_NEG(neg_unsigned_int, unsigned int, unsigned int) +PPL_SPECIALIZE_NEG(neg_unsigned_int, unsigned long, unsigned long) +PPL_SPECIALIZE_NEG(neg_unsigned_int, unsigned long long, unsigned long long) + +#if PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_ADD(add_signed_int, char, char, char) +#endif +PPL_SPECIALIZE_ADD(add_signed_int, signed char, signed char, signed char) +PPL_SPECIALIZE_ADD(add_signed_int, signed short, signed short, signed short) +PPL_SPECIALIZE_ADD(add_signed_int, signed int, signed int, signed int) +PPL_SPECIALIZE_ADD(add_signed_int, signed long, signed long, signed long) +PPL_SPECIALIZE_ADD(add_signed_int, signed long long, signed long long, signed long long) +#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_ADD(add_unsigned_int, char, char, char) +#endif +PPL_SPECIALIZE_ADD(add_unsigned_int, unsigned char, unsigned char, unsigned char) +PPL_SPECIALIZE_ADD(add_unsigned_int, unsigned short, unsigned short, unsigned short) +PPL_SPECIALIZE_ADD(add_unsigned_int, unsigned int, unsigned int, unsigned int) +PPL_SPECIALIZE_ADD(add_unsigned_int, unsigned long, unsigned long, unsigned long) +PPL_SPECIALIZE_ADD(add_unsigned_int, unsigned long long, unsigned long long, unsigned long long) + +#if PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_SUB(sub_signed_int, char, char, char) +#endif +PPL_SPECIALIZE_SUB(sub_signed_int, signed char, signed char, signed char) +PPL_SPECIALIZE_SUB(sub_signed_int, signed short, signed short, signed short) +PPL_SPECIALIZE_SUB(sub_signed_int, signed int, signed int, signed int) +PPL_SPECIALIZE_SUB(sub_signed_int, signed long, signed long, signed long) +PPL_SPECIALIZE_SUB(sub_signed_int, signed long long, signed long long, signed long long) +#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_SUB(sub_unsigned_int, char, char, char) +#endif +PPL_SPECIALIZE_SUB(sub_unsigned_int, unsigned char, unsigned char, unsigned char) +PPL_SPECIALIZE_SUB(sub_unsigned_int, unsigned short, unsigned short, unsigned short) +PPL_SPECIALIZE_SUB(sub_unsigned_int, unsigned int, unsigned int, unsigned int) +PPL_SPECIALIZE_SUB(sub_unsigned_int, unsigned long, unsigned long, unsigned long) +PPL_SPECIALIZE_SUB(sub_unsigned_int, unsigned long long, unsigned long long, unsigned long long) + +#if PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_MUL(mul_signed_int, char, char, char) +#endif +PPL_SPECIALIZE_MUL(mul_signed_int, signed char, signed char, signed char) +PPL_SPECIALIZE_MUL(mul_signed_int, signed short, signed short, signed short) +PPL_SPECIALIZE_MUL(mul_signed_int, signed int, signed int, signed int) +PPL_SPECIALIZE_MUL(mul_signed_int, signed long, signed long, signed long) +PPL_SPECIALIZE_MUL(mul_signed_int, signed long long, signed long long, signed long long) +#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_MUL(mul_unsigned_int, char, char, char) +#endif +PPL_SPECIALIZE_MUL(mul_unsigned_int, unsigned char, unsigned char, unsigned char) +PPL_SPECIALIZE_MUL(mul_unsigned_int, unsigned short, unsigned short, unsigned short) +PPL_SPECIALIZE_MUL(mul_unsigned_int, unsigned int, unsigned int, unsigned int) +PPL_SPECIALIZE_MUL(mul_unsigned_int, unsigned long, unsigned long, unsigned long) +PPL_SPECIALIZE_MUL(mul_unsigned_int, unsigned long long, unsigned long long, unsigned long long) + +#if PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_DIV(div_signed_int, char, char, char) +#endif +PPL_SPECIALIZE_DIV(div_signed_int, signed char, signed char, signed char) +PPL_SPECIALIZE_DIV(div_signed_int, signed short, signed short, signed short) +PPL_SPECIALIZE_DIV(div_signed_int, signed int, signed int, signed int) +PPL_SPECIALIZE_DIV(div_signed_int, signed long, signed long, signed long) +PPL_SPECIALIZE_DIV(div_signed_int, signed long long, signed long long, signed long long) +#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_DIV(div_unsigned_int, char, char, char) +#endif +PPL_SPECIALIZE_DIV(div_unsigned_int, unsigned char, unsigned char, unsigned char) +PPL_SPECIALIZE_DIV(div_unsigned_int, unsigned short, unsigned short, unsigned short) +PPL_SPECIALIZE_DIV(div_unsigned_int, unsigned int, unsigned int, unsigned int) +PPL_SPECIALIZE_DIV(div_unsigned_int, unsigned long, unsigned long, unsigned long) +PPL_SPECIALIZE_DIV(div_unsigned_int, unsigned long long, unsigned long long, unsigned long long) + +#if PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_IDIV(idiv_signed_int, char, char, char) +#endif +PPL_SPECIALIZE_IDIV(idiv_signed_int, signed char, signed char, signed char) +PPL_SPECIALIZE_IDIV(idiv_signed_int, signed short, signed short, signed short) +PPL_SPECIALIZE_IDIV(idiv_signed_int, signed int, signed int, signed int) +PPL_SPECIALIZE_IDIV(idiv_signed_int, signed long, signed long, signed long) +PPL_SPECIALIZE_IDIV(idiv_signed_int, signed long long, signed long long, signed long long) +#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_IDIV(idiv_unsigned_int, char, char, char) +#endif +PPL_SPECIALIZE_IDIV(idiv_unsigned_int, unsigned char, unsigned char, unsigned char) +PPL_SPECIALIZE_IDIV(idiv_unsigned_int, unsigned short, unsigned short, unsigned short) +PPL_SPECIALIZE_IDIV(idiv_unsigned_int, unsigned int, unsigned int, unsigned int) +PPL_SPECIALIZE_IDIV(idiv_unsigned_int, unsigned long, unsigned long, unsigned long) +PPL_SPECIALIZE_IDIV(idiv_unsigned_int, unsigned long long, unsigned long long, unsigned long long) + +#if PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_REM(rem_signed_int, char, char, char) +#endif +PPL_SPECIALIZE_REM(rem_signed_int, signed char, signed char, signed char) +PPL_SPECIALIZE_REM(rem_signed_int, signed short, signed short, signed short) +PPL_SPECIALIZE_REM(rem_signed_int, signed int, signed int, signed int) +PPL_SPECIALIZE_REM(rem_signed_int, signed long, signed long, signed long) +PPL_SPECIALIZE_REM(rem_signed_int, signed long long, signed long long, signed long long) +#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_REM(rem_unsigned_int, char, char, char) +#endif +PPL_SPECIALIZE_REM(rem_unsigned_int, unsigned char, unsigned char, unsigned char) +PPL_SPECIALIZE_REM(rem_unsigned_int, unsigned short, unsigned short, unsigned short) +PPL_SPECIALIZE_REM(rem_unsigned_int, unsigned int, unsigned int, unsigned int) +PPL_SPECIALIZE_REM(rem_unsigned_int, unsigned long, unsigned long, unsigned long) +PPL_SPECIALIZE_REM(rem_unsigned_int, unsigned long long, unsigned long long, unsigned long long) + +#if PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_ADD_2EXP(add_2exp_signed_int, char, char) +#endif +PPL_SPECIALIZE_ADD_2EXP(add_2exp_signed_int, signed char, signed char) +PPL_SPECIALIZE_ADD_2EXP(add_2exp_signed_int, signed short, signed short) +PPL_SPECIALIZE_ADD_2EXP(add_2exp_signed_int, signed int, signed int) +PPL_SPECIALIZE_ADD_2EXP(add_2exp_signed_int, signed long, signed long) +PPL_SPECIALIZE_ADD_2EXP(add_2exp_signed_int, signed long long, signed long long) +#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_ADD_2EXP(add_2exp_unsigned_int, char, char) +#endif +PPL_SPECIALIZE_ADD_2EXP(add_2exp_unsigned_int, unsigned char, unsigned char) +PPL_SPECIALIZE_ADD_2EXP(add_2exp_unsigned_int, unsigned short, unsigned short) +PPL_SPECIALIZE_ADD_2EXP(add_2exp_unsigned_int, unsigned int, unsigned int) +PPL_SPECIALIZE_ADD_2EXP(add_2exp_unsigned_int, unsigned long, unsigned long) +PPL_SPECIALIZE_ADD_2EXP(add_2exp_unsigned_int, unsigned long long, unsigned long long) + +#if PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_SUB_2EXP(sub_2exp_signed_int, char, char) +#endif +PPL_SPECIALIZE_SUB_2EXP(sub_2exp_signed_int, signed char, signed char) +PPL_SPECIALIZE_SUB_2EXP(sub_2exp_signed_int, signed short, signed short) +PPL_SPECIALIZE_SUB_2EXP(sub_2exp_signed_int, signed int, signed int) +PPL_SPECIALIZE_SUB_2EXP(sub_2exp_signed_int, signed long, signed long) +PPL_SPECIALIZE_SUB_2EXP(sub_2exp_signed_int, signed long long, signed long long) +#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_SUB_2EXP(sub_2exp_unsigned_int, char, char) +#endif +PPL_SPECIALIZE_SUB_2EXP(sub_2exp_unsigned_int, unsigned char, unsigned char) +PPL_SPECIALIZE_SUB_2EXP(sub_2exp_unsigned_int, unsigned short, unsigned short) +PPL_SPECIALIZE_SUB_2EXP(sub_2exp_unsigned_int, unsigned int, unsigned int) +PPL_SPECIALIZE_SUB_2EXP(sub_2exp_unsigned_int, unsigned long, unsigned long) +PPL_SPECIALIZE_SUB_2EXP(sub_2exp_unsigned_int, unsigned long long, unsigned long long) + +#if PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_MUL_2EXP(mul_2exp_signed_int, char, char) +#endif +PPL_SPECIALIZE_MUL_2EXP(mul_2exp_signed_int, signed char, signed char) +PPL_SPECIALIZE_MUL_2EXP(mul_2exp_signed_int, signed short, signed short) +PPL_SPECIALIZE_MUL_2EXP(mul_2exp_signed_int, signed int, signed int) +PPL_SPECIALIZE_MUL_2EXP(mul_2exp_signed_int, signed long, signed long) +PPL_SPECIALIZE_MUL_2EXP(mul_2exp_signed_int, signed long long, signed long long) +#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_MUL_2EXP(mul_2exp_unsigned_int, char, char) +#endif +PPL_SPECIALIZE_MUL_2EXP(mul_2exp_unsigned_int, unsigned char, unsigned char) +PPL_SPECIALIZE_MUL_2EXP(mul_2exp_unsigned_int, unsigned short, unsigned short) +PPL_SPECIALIZE_MUL_2EXP(mul_2exp_unsigned_int, unsigned int, unsigned int) +PPL_SPECIALIZE_MUL_2EXP(mul_2exp_unsigned_int, unsigned long, unsigned long) +PPL_SPECIALIZE_MUL_2EXP(mul_2exp_unsigned_int, unsigned long long, unsigned long long) + +#if PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_DIV_2EXP(div_2exp_signed_int, char, char) +#endif +PPL_SPECIALIZE_DIV_2EXP(div_2exp_signed_int, signed char, signed char) +PPL_SPECIALIZE_DIV_2EXP(div_2exp_signed_int, signed short, signed short) +PPL_SPECIALIZE_DIV_2EXP(div_2exp_signed_int, signed int, signed int) +PPL_SPECIALIZE_DIV_2EXP(div_2exp_signed_int, signed long, signed long) +PPL_SPECIALIZE_DIV_2EXP(div_2exp_signed_int, signed long long, signed long long) +#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_DIV_2EXP(div_2exp_unsigned_int, char, char) +#endif +PPL_SPECIALIZE_DIV_2EXP(div_2exp_unsigned_int, unsigned char, unsigned char) +PPL_SPECIALIZE_DIV_2EXP(div_2exp_unsigned_int, unsigned short, unsigned short) +PPL_SPECIALIZE_DIV_2EXP(div_2exp_unsigned_int, unsigned int, unsigned int) +PPL_SPECIALIZE_DIV_2EXP(div_2exp_unsigned_int, unsigned long, unsigned long) +PPL_SPECIALIZE_DIV_2EXP(div_2exp_unsigned_int, unsigned long long, unsigned long long) + +#if PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_signed_int, char, char) +#endif +PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_signed_int, signed char, signed char) +PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_signed_int, signed short, signed short) +PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_signed_int, signed int, signed int) +PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_signed_int, signed long, signed long) +PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_signed_int, signed long long, signed long long) +#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_unsigned_int, char, char) +#endif +PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_unsigned_int, unsigned char, unsigned char) +PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_unsigned_int, unsigned short, unsigned short) +PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_unsigned_int, unsigned int, unsigned int) +PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_unsigned_int, unsigned long, unsigned long) +PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_unsigned_int, unsigned long long, unsigned long long) + +#if PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_signed_int, char, char) +#endif +PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_signed_int, signed char, signed char) +PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_signed_int, signed short, signed short) +PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_signed_int, signed int, signed int) +PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_signed_int, signed long, signed long) +PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_signed_int, signed long long, signed long long) +#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_unsigned_int, char, char) +#endif +PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_unsigned_int, unsigned char, unsigned char) +PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_unsigned_int, unsigned short, unsigned short) +PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_unsigned_int, unsigned int, unsigned int) +PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_unsigned_int, unsigned long, unsigned long) +PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_unsigned_int, unsigned long long, unsigned long long) + +#if PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_SQRT(sqrt_signed_int, char, char) +#endif +PPL_SPECIALIZE_SQRT(sqrt_signed_int, signed char, signed char) +PPL_SPECIALIZE_SQRT(sqrt_signed_int, signed short, signed short) +PPL_SPECIALIZE_SQRT(sqrt_signed_int, signed int, signed int) +PPL_SPECIALIZE_SQRT(sqrt_signed_int, signed long, signed long) +PPL_SPECIALIZE_SQRT(sqrt_signed_int, signed long long, signed long long) +#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_SQRT(sqrt_unsigned_int, char, char) +#endif +PPL_SPECIALIZE_SQRT(sqrt_unsigned_int, unsigned char, unsigned char) +PPL_SPECIALIZE_SQRT(sqrt_unsigned_int, unsigned short, unsigned short) +PPL_SPECIALIZE_SQRT(sqrt_unsigned_int, unsigned int, unsigned int) +PPL_SPECIALIZE_SQRT(sqrt_unsigned_int, unsigned long, unsigned long) +PPL_SPECIALIZE_SQRT(sqrt_unsigned_int, unsigned long long, unsigned long long) + +#if PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_ABS(abs_generic, char, char) +#endif +PPL_SPECIALIZE_ABS(abs_generic, signed char, signed char) +PPL_SPECIALIZE_ABS(abs_generic, signed short, signed short) +PPL_SPECIALIZE_ABS(abs_generic, signed int, signed int) +PPL_SPECIALIZE_ABS(abs_generic, signed long, signed long) +PPL_SPECIALIZE_ABS(abs_generic, signed long long, signed long long) +#if !PPL_CXX_PLAIN_CHAR_IS_SIGNED +PPL_SPECIALIZE_ABS(assign_unsigned_int_unsigned_int, char, char) +#endif +PPL_SPECIALIZE_ABS(assign_unsigned_int_unsigned_int, unsigned char, unsigned char) +PPL_SPECIALIZE_ABS(assign_unsigned_int_unsigned_int, unsigned short, unsigned short) +PPL_SPECIALIZE_ABS(assign_unsigned_int_unsigned_int, unsigned int, unsigned int) +PPL_SPECIALIZE_ABS(assign_unsigned_int_unsigned_int, unsigned long, unsigned long) +PPL_SPECIALIZE_ABS(assign_unsigned_int_unsigned_int, unsigned long long, unsigned long long) + +PPL_SPECIALIZE_GCD(gcd_exact, char, char, char) +PPL_SPECIALIZE_GCD(gcd_exact, signed char, signed char, signed char) +PPL_SPECIALIZE_GCD(gcd_exact, signed short, signed short, signed short) +PPL_SPECIALIZE_GCD(gcd_exact, signed int, signed int, signed int) +PPL_SPECIALIZE_GCD(gcd_exact, signed long, signed long, signed long) +PPL_SPECIALIZE_GCD(gcd_exact, signed long long, signed long long, signed long long) +PPL_SPECIALIZE_GCD(gcd_exact, unsigned char, unsigned char, unsigned char) +PPL_SPECIALIZE_GCD(gcd_exact, unsigned short, unsigned short, unsigned short) +PPL_SPECIALIZE_GCD(gcd_exact, unsigned int, unsigned int, unsigned int) +PPL_SPECIALIZE_GCD(gcd_exact, unsigned long, unsigned long, unsigned long) +PPL_SPECIALIZE_GCD(gcd_exact, unsigned long long, unsigned long long, unsigned long long) + +PPL_SPECIALIZE_GCDEXT(gcdext_exact, char, char, char, char, char) +PPL_SPECIALIZE_GCDEXT(gcdext_exact, signed char, signed char, signed char, signed char, signed char) +PPL_SPECIALIZE_GCDEXT(gcdext_exact, signed short, signed short, signed short, signed short, signed short) +PPL_SPECIALIZE_GCDEXT(gcdext_exact, signed int, signed int, signed int, signed int, signed int) +PPL_SPECIALIZE_GCDEXT(gcdext_exact, signed long, signed long, signed long, signed long, signed long) +PPL_SPECIALIZE_GCDEXT(gcdext_exact, signed long long, signed long long, signed long long, signed long long, signed long long) +PPL_SPECIALIZE_GCDEXT(gcdext_exact, unsigned char, unsigned char, unsigned char, unsigned char, unsigned char) +PPL_SPECIALIZE_GCDEXT(gcdext_exact, unsigned short, unsigned short, unsigned short, unsigned short, unsigned short) +PPL_SPECIALIZE_GCDEXT(gcdext_exact, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int) +PPL_SPECIALIZE_GCDEXT(gcdext_exact, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) +PPL_SPECIALIZE_GCDEXT(gcdext_exact, unsigned long long, unsigned long long, unsigned long long, unsigned long long, unsigned long long) + +PPL_SPECIALIZE_LCM(lcm_gcd_exact, char, char, char) +PPL_SPECIALIZE_LCM(lcm_gcd_exact, signed char, signed char, signed char) +PPL_SPECIALIZE_LCM(lcm_gcd_exact, signed short, signed short, signed short) +PPL_SPECIALIZE_LCM(lcm_gcd_exact, signed int, signed int, signed int) +PPL_SPECIALIZE_LCM(lcm_gcd_exact, signed long, signed long, signed long) +PPL_SPECIALIZE_LCM(lcm_gcd_exact, signed long long, signed long long, signed long long) +PPL_SPECIALIZE_LCM(lcm_gcd_exact, unsigned char, unsigned char, unsigned char) +PPL_SPECIALIZE_LCM(lcm_gcd_exact, unsigned short, unsigned short, unsigned short) +PPL_SPECIALIZE_LCM(lcm_gcd_exact, unsigned int, unsigned int, unsigned int) +PPL_SPECIALIZE_LCM(lcm_gcd_exact, unsigned long, unsigned long, unsigned long) +PPL_SPECIALIZE_LCM(lcm_gcd_exact, unsigned long long, unsigned long long, unsigned long long) + +PPL_SPECIALIZE_SGN(sgn_generic, char) +PPL_SPECIALIZE_SGN(sgn_generic, signed char) +PPL_SPECIALIZE_SGN(sgn_generic, signed short) +PPL_SPECIALIZE_SGN(sgn_generic, signed int) +PPL_SPECIALIZE_SGN(sgn_generic, signed long) +PPL_SPECIALIZE_SGN(sgn_generic, signed long long) +PPL_SPECIALIZE_SGN(sgn_generic, unsigned char) +PPL_SPECIALIZE_SGN(sgn_generic, unsigned short) +PPL_SPECIALIZE_SGN(sgn_generic, unsigned int) +PPL_SPECIALIZE_SGN(sgn_generic, unsigned long) +PPL_SPECIALIZE_SGN(sgn_generic, unsigned long long) + +PPL_SPECIALIZE_CMP(cmp_generic, char, char) +PPL_SPECIALIZE_CMP(cmp_generic, signed char, signed char) +PPL_SPECIALIZE_CMP(cmp_generic, signed short, signed short) +PPL_SPECIALIZE_CMP(cmp_generic, signed int, signed int) +PPL_SPECIALIZE_CMP(cmp_generic, signed long, signed long) +PPL_SPECIALIZE_CMP(cmp_generic, signed long long, signed long long) +PPL_SPECIALIZE_CMP(cmp_generic, unsigned char, unsigned char) +PPL_SPECIALIZE_CMP(cmp_generic, unsigned short, unsigned short) +PPL_SPECIALIZE_CMP(cmp_generic, unsigned int, unsigned int) +PPL_SPECIALIZE_CMP(cmp_generic, unsigned long, unsigned long) +PPL_SPECIALIZE_CMP(cmp_generic, unsigned long long, unsigned long long) + +PPL_SPECIALIZE_ADD_MUL(add_mul_int, char, char, char) +PPL_SPECIALIZE_ADD_MUL(add_mul_int, signed char, signed char, signed char) +PPL_SPECIALIZE_ADD_MUL(add_mul_int, signed short, signed short, signed short) +PPL_SPECIALIZE_ADD_MUL(add_mul_int, signed int, signed int, signed int) +PPL_SPECIALIZE_ADD_MUL(add_mul_int, signed long, signed long, signed long) +PPL_SPECIALIZE_ADD_MUL(add_mul_int, signed long long, signed long long, signed long long) +PPL_SPECIALIZE_ADD_MUL(add_mul_int, unsigned char, unsigned char, unsigned char) +PPL_SPECIALIZE_ADD_MUL(add_mul_int, unsigned short, unsigned short, unsigned short) +PPL_SPECIALIZE_ADD_MUL(add_mul_int, unsigned int, unsigned int, unsigned int) +PPL_SPECIALIZE_ADD_MUL(add_mul_int, unsigned long, unsigned long, unsigned long) +PPL_SPECIALIZE_ADD_MUL(add_mul_int, unsigned long long, unsigned long long, unsigned long long) + +PPL_SPECIALIZE_SUB_MUL(sub_mul_int, char, char, char) +PPL_SPECIALIZE_SUB_MUL(sub_mul_int, signed char, signed char, signed char) +PPL_SPECIALIZE_SUB_MUL(sub_mul_int, signed short, signed short, signed short) +PPL_SPECIALIZE_SUB_MUL(sub_mul_int, signed int, signed int, signed int) +PPL_SPECIALIZE_SUB_MUL(sub_mul_int, signed long, signed long, signed long) +PPL_SPECIALIZE_SUB_MUL(sub_mul_int, signed long long, signed long long, signed long long) +PPL_SPECIALIZE_SUB_MUL(sub_mul_int, unsigned char, unsigned char, unsigned char) +PPL_SPECIALIZE_SUB_MUL(sub_mul_int, unsigned short, unsigned short, unsigned short) +PPL_SPECIALIZE_SUB_MUL(sub_mul_int, unsigned int, unsigned int, unsigned int) +PPL_SPECIALIZE_SUB_MUL(sub_mul_int, unsigned long, unsigned long, unsigned long) +PPL_SPECIALIZE_SUB_MUL(sub_mul_int, unsigned long long, unsigned long long, unsigned long long) + +PPL_SPECIALIZE_INPUT(input_generic, char) +PPL_SPECIALIZE_INPUT(input_generic, signed char) +PPL_SPECIALIZE_INPUT(input_generic, signed short) +PPL_SPECIALIZE_INPUT(input_generic, signed int) +PPL_SPECIALIZE_INPUT(input_generic, signed long) +PPL_SPECIALIZE_INPUT(input_generic, signed long long) +PPL_SPECIALIZE_INPUT(input_generic, unsigned char) +PPL_SPECIALIZE_INPUT(input_generic, unsigned short) +PPL_SPECIALIZE_INPUT(input_generic, unsigned int) +PPL_SPECIALIZE_INPUT(input_generic, unsigned long) +PPL_SPECIALIZE_INPUT(input_generic, unsigned long long) + +PPL_SPECIALIZE_OUTPUT(output_char, char) +PPL_SPECIALIZE_OUTPUT(output_char, signed char) +PPL_SPECIALIZE_OUTPUT(output_int, signed short) +PPL_SPECIALIZE_OUTPUT(output_int, signed int) +PPL_SPECIALIZE_OUTPUT(output_int, signed long) +PPL_SPECIALIZE_OUTPUT(output_int, signed long long) +PPL_SPECIALIZE_OUTPUT(output_char, unsigned char) +PPL_SPECIALIZE_OUTPUT(output_int, unsigned short) +PPL_SPECIALIZE_OUTPUT(output_int, unsigned int) +PPL_SPECIALIZE_OUTPUT(output_int, unsigned long) +PPL_SPECIALIZE_OUTPUT(output_int, unsigned long long) + +} // namespace Checked + +} // namespace Parma_Polyhedra_Library + +#endif // !defined(PPL_checked_int_inlines_hh) |