24 #ifndef PPL_checked_float_inlines_hh
25 #define PPL_checked_float_inlines_hh 1
36 #if PPL_HAVE_DECL_FMAF && defined(FP_FAST_FMAF) \
37 && !defined(__alpha) && !defined(__FreeBSD__)
46 #if PPL_HAVE_DECL_FMA && defined(FP_FAST_FMA) \
47 && !defined(__alpha) && !defined(__FreeBSD__)
56 #if PPL_HAVE_DECL_FMAL && defined(FP_FAST_FMAL) \
57 && !defined(__alpha) && !defined(__FreeBSD__)
64 #if PPL_HAVE_DECL_RINTF
76 #if PPL_HAVE_DECL_RINTL
81 #elif !PPL_CXX_PROVIDES_PROPER_LONG_DOUBLE
88 #elif defined(__i386__) && (defined(__GNUC__) || defined(__INTEL_COMPILER))
94 __asm__ (
"frndint" :
"=t" (i) :
"0" (x));
147 template <
typename Policy,
typename T>
151 if ((nan || sign) &&
CHECK_P(Policy::has_nan, f.u.binary.is_nan())) {
155 if (Policy::has_infinity) {
156 int sign_inf = f.u.binary.inf_sign();
165 PPL_ASSERT(f.u.binary.inf_sign() == 0);
180 template <
typename Policy,
typename T>
184 return CHECK_P(Policy::has_nan, f.u.binary.is_nan());
187 template <
typename Policy,
typename T>
191 return CHECK_P(Policy::has_infinity, (f.u.binary.inf_sign() != 0));
193 template <
typename Policy,
typename T>
197 return CHECK_P(Policy::has_infinity, (f.u.binary.inf_sign() < 0));
200 template <
typename Policy,
typename T>
204 return CHECK_P(Policy::has_infinity, (f.u.binary.inf_sign() > 0));
208 template <
typename Policy,
typename T>
214 template <
typename Policy,
typename T>
234 template <
typename T>
238 PPL_ASSERT(!f.u.binary.is_nan());
239 PPL_ASSERT(f.u.binary.inf_sign() >= 0);
240 if (f.u.binary.zero_sign() > 0) {
244 else if (f.u.binary.sign_bit()) {
253 template <
typename T>
257 PPL_ASSERT(!f.u.binary.is_nan());
258 PPL_ASSERT(f.u.binary.inf_sign() <= 0);
259 if (f.u.binary.zero_sign() < 0) {
263 else if (!f.u.binary.sign_bit()) {
272 template <
typename Policy,
typename To>
282 template <
typename Policy,
typename To>
293 template <
typename Policy>
302 template <
typename Policy>
337 template <
typename To_Policy,
typename From_Policy,
typename To,
typename From>
340 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from)) {
347 template <
typename To_Policy,
typename From_Policy,
typename To,
typename From>
350 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from)) {
353 prepare_inexact<To_Policy>(dir);
371 return result_relation<To_Policy>(dir);
374 template <
typename To_Policy,
typename From_Policy,
typename To,
typename From>
377 if (
sizeof(
From) >
sizeof(
To)) {
378 return assign_float_float_inexact<To_Policy, From_Policy>(to, from, dir);
381 return assign_float_float_exact<To_Policy, From_Policy>(to, from, dir);
385 template <
typename To_Policy,
typename From_Policy,
typename Type>
388 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from)) {
410 template <
typename To_Policy,
typename From_Policy,
typename Type>
413 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from)) {
435 template <
typename To_Policy,
typename From_Policy,
typename Type>
438 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from)) {
442 return floor<To_Policy, From_Policy>(to, from, dir);
445 return ceil<To_Policy, From_Policy>(to, from, dir);
449 template <
typename To_Policy,
typename From_Policy,
typename Type>
452 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from)) {
459 template <
typename To_Policy,
typename From1_Policy,
typename From2_Policy,
463 if (To_Policy::check_inf_add_inf
464 && is_inf_float<From1_Policy>(x) && x == -y) {
467 prepare_inexact<To_Policy>(dir);
485 if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to)) {
488 return result_relation<To_Policy>(dir);
491 template <
typename To_Policy,
typename From1_Policy,
typename From2_Policy,
495 if (To_Policy::check_inf_sub_inf
496 && is_inf_float<From1_Policy>(x) && x == y) {
499 prepare_inexact<To_Policy>(dir);
517 if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to)) {
520 return result_relation<To_Policy>(dir);
523 template <
typename To_Policy,
typename From1_Policy,
typename From2_Policy,
527 if (To_Policy::check_inf_mul_zero
528 && ((x == 0 && is_inf_float<From2_Policy>(y))
530 (y == 0 && is_inf_float<From1_Policy>(x)))) {
533 prepare_inexact<To_Policy>(dir);
551 if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to)) {
554 return result_relation<To_Policy>(dir);
557 template <
typename To_Policy,
typename From1_Policy,
typename From2_Policy,
561 if (To_Policy::check_inf_div_inf
562 && is_inf_float<From1_Policy>(x) && is_inf_float<From2_Policy>(y)) {
565 if (To_Policy::check_div_zero && y == 0) {
568 prepare_inexact<To_Policy>(dir);
586 if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to)) {
589 return result_relation<To_Policy>(dir);
592 template <
typename To_Policy,
typename From1_Policy,
typename From2_Policy,
599 Result r = div<To_Policy, From1_Policy, From2_Policy>(temp, x, y, dir);
605 PPL_ASSERT(r1 ==
V_EQ);
606 if (r ==
V_EQ || to != temp) {
613 template <
typename To_Policy,
typename From1_Policy,
typename From2_Policy,
617 if (To_Policy::check_inf_mod && is_inf_float<From1_Policy>(x)) {
618 return assign_nan<To_Policy>(to,
V_INF_MOD);
620 if (To_Policy::check_div_zero && y == 0) {
623 to = std::fmod(x, y);
624 if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to)) {
635 template <
typename To_Policy,
typename From_Policy,
typename Type>
638 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(x)) {
643 add<To_Policy, From_Policy, Float_2exp>(to,
649 template <
typename To_Policy,
typename From_Policy,
typename Type>
652 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(x)) {
657 sub<To_Policy, From_Policy, Float_2exp>(to,
663 template <
typename To_Policy,
typename From_Policy,
typename Type>
666 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(x)) {
671 mul<To_Policy, From_Policy, Float_2exp>(to,
677 template <
typename To_Policy,
typename From_Policy,
typename Type>
680 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(x)) {
685 div<To_Policy, From_Policy, Float_2exp>(to,
691 template <
typename To_Policy,
typename From_Policy,
typename Type>
694 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(x)) {
697 if (To_Policy::check_inf_mod && is_inf_float<From_Policy>(x)) {
698 return assign_nan<To_Policy>(to,
V_INF_MOD);
701 Type m = 1ULL << exp;
702 rem_float<To_Policy, From_Policy, Float_2exp>(to, x, m,
ROUND_IGNORE);
705 return add_float<To_Policy, From_Policy, Float_2exp>(to, to, m, dir);
708 return sub_float<To_Policy, From_Policy, Float_2exp>(to, to, m, dir);
713 template <
typename To_Policy,
typename From_Policy,
typename Type>
716 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(x)) {
719 if (To_Policy::check_inf_mod && is_inf_float<From_Policy>(x)) {
720 return assign_nan<To_Policy>(to,
V_INF_MOD);
723 Type m = 1ULL << exp;
724 rem_float<To_Policy, From_Policy, Float_2exp>(to, x, m,
ROUND_IGNORE);
726 return add_float<To_Policy, From_Policy, Float_2exp>(to, to, m, dir);
731 template <
typename To_Policy,
typename From_Policy,
typename Type>
734 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from)) {
741 template <
typename To_Policy,
typename From_Policy,
typename Type>
744 if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from)) {
747 if (To_Policy::check_sqrt_neg && from < 0) {
750 prepare_inexact<To_Policy>(dir);
752 to = std::sqrt(from);
758 to = std::sqrt(from);
762 return result_relation<To_Policy>(dir);
765 template <
typename Policy,
typename Type>
780 template <
typename Policy1,
typename Policy2,
typename Type>
795 template <
typename To_Policy,
typename From_Policy,
typename To,
typename From>
798 prepare_inexact<To_Policy>(dir);
809 return result_relation<To_Policy>(dir);
812 template <
typename To_Policy,
typename From_Policy,
typename To,
typename From>
816 return assign_float_int_inexact<To_Policy, From_Policy>(to, from, dir);
819 return assign_exact<To_Policy, From_Policy>(to, from, dir);
823 template <
typename Policy,
typename T>
830 f.u.binary.set_max(
true);
844 template <
typename Policy,
typename T>
851 f.u.binary.set_max(
false);
865 template <
typename To_Policy,
typename From_Policy,
typename T>
868 int sign =
sgn(from);
873 mpz_srcptr from_z = from.get_mpz_t();
874 size_t exponent = mpz_sizeinbase(from_z, 2) - 1;
877 return set_neg_overflow_float<To_Policy>(to, dir);
880 return set_pos_overflow_float<To_Policy>(to, dir);
883 unsigned long zeroes = mpn_scan1(from_z->_mp_d, 0);
884 size_t meaningful_bits = exponent - zeroes;
888 mpz_tdiv_q_2exp(mantissa,
896 f.u.binary.build(sign < 0, mantissa, static_cast<long>(exponent));
901 return round_lt_float<To_Policy>(to, dir);
904 return round_gt_float<To_Policy>(to, dir);
910 template <
typename To_Policy,
typename From_Policy,
typename T>
913 const mpz_class& numer = from.get_num();
914 const mpz_class& denom = from.get_den();
916 return assign_float_mpz<To_Policy, From_Policy>(to, numer, dir);
918 mpz_srcptr numer_z = numer.get_mpz_t();
919 mpz_srcptr denom_z = denom.get_mpz_t();
920 int sign =
sgn(numer);
921 long exponent =
static_cast<long>(mpz_sizeinbase(numer_z, 2))
922 - static_cast<long>(mpz_sizeinbase(denom_z, 2));
927 return round_lt_float<To_Policy>(to, dir);
930 return round_gt_float<To_Policy>(to, dir);
936 return set_neg_overflow_float<To_Policy>(to, dir);
939 return set_pos_overflow_float<To_Policy>(to, dir);
945 needed_bits -=
static_cast<unsigned int>(diff);
950 long shift =
static_cast<long>(needed_bits) - exponent;
952 mpz_mul_2exp(mantissa, numer_z, static_cast<unsigned long>(shift));
955 else if (shift < 0) {
957 mpz_mul_2exp(mantissa, denom_z, static_cast<unsigned long>(shift));
963 mpz_tdiv_qr(mantissa, r, numer_z, denom_z);
964 size_t bits = mpz_sizeinbase(mantissa, 2);
965 bool inexact = (mpz_sgn(r) != 0);
967 if (bits == needed_bits + 1) {
968 inexact = (inexact || mpz_odd_p(mantissa));
969 mpz_tdiv_q_2exp(mantissa, mantissa, 1);
983 f.u.binary.build(sign < 0, mantissa, exponent);
992 template <
typename To_Policy,
typename From1_Policy,
typename From2_Policy,
996 if (To_Policy::check_inf_mul_zero
997 && ((x == 0 && is_inf_float<From2_Policy>(y))
999 (y == 0 && is_inf_float<From1_Policy>(x)))) {
1003 prepare_inexact<To_Policy>(dir);
1022 if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to)) {
1025 return result_relation<To_Policy>(dir);
1028 template <
typename To_Policy,
typename From1_Policy,
typename From2_Policy,
typename Type>
1031 if (To_Policy::check_inf_mul_zero
1032 && ((x == 0 && is_inf_float<From2_Policy>(y))
1034 (y == 0 && is_inf_float<From1_Policy>(x)))) {
1038 prepare_inexact<To_Policy>(dir);
1057 if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to)) {
1060 return result_relation<To_Policy>(dir);
1063 template <
typename From>
1076 mpz_class& num = to.get_num();
1077 mpz_class& den = to.get_den();
1079 long double n = std::frexp(from, &exp);
1085 const long double mult =
static_cast<long double>(ULONG_MAX) + 1.0L;
1086 const unsigned int bits =
sizeof(
unsigned long) * CHAR_BIT;
1090 const long double intpart = std::floor(n);
1091 num +=
static_cast<unsigned long>(intpart);
1110 template <
typename Policy,
typename Type>
1117 else if (is_minf<Policy>(from)) {
1120 else if (is_pinf<Policy>(from)) {
1123 else if (is_nan<Policy>(from)) {
1135 #if PPL_SUPPORTED_FLOAT
1137 #if PPL_SUPPORTED_DOUBLE
1141 #if PPL_SUPPORTED_LONG_DOUBLE
1147 #if PPL_SUPPORTED_DOUBLE
1149 #if PPL_SUPPORTED_LONG_DOUBLE
1155 #if PPL_SUPPORTED_LONG_DOUBLE
1159 #if PPL_SUPPORTED_FLOAT
1208 #if PPL_SUPPORTED_DOUBLE
1257 #if PPL_SUPPORTED_LONG_DOUBLE
1297 long double,
long double)
1311 #endif // !defined(PPL_checked_int_inlines_hh)
A positive integer overflow occurred (rounding down).
Rounding_Dir round_dir(Rounding_Dir dir)
Result add_2exp_float(Type &to, const Type x, unsigned int exp, Rounding_Dir dir)
Result sub_float(Type &to, const Type x, const Type y, Rounding_Dir dir)
#define PPL_SPECIALIZE_NEG(func, To, From)
const_bool_nodef(has_nan, false)
Result mul_float(Type &to, const Type x, const Type y, Rounding_Dir dir)
The computed result is exact.
Taking the square root of a negative number.
bool fpu_direct_rounding(Rounding_Dir dir)
Result assign_float_mpq(T &to, const mpq_class &from, Rounding_Dir dir)
Result floor_float(Type &to, const Type from, Rounding_Dir)
#define PPL_SPECIALIZE_ADD_MUL(func, To, From1, From2)
#define PPL_SPECIALIZE_IS_MINF(func, Type)
bool is_minf_float(const T v)
double round_to_integer(double x)
Rounding_Dir
Rounding directions for arithmetic computations.
#define PPL_SPECIALIZE_SQRT(func, To, From)
A positive integer overflow occurred (rounding up).
std::string float_mpq_to_string(mpq_class &q)
void assign_mpq_numeric_float(mpq_class &to, const From from)
Computing a remainder modulo zero.
#define PPL_SPECIALIZE_CLASSIFY(func, Type)
#define PPL_SPECIALIZE_ADD(func, To, From1, From2)
float multiply_add(float x, float y, float z)
bool is_int_float(const T v)
bool round_strict_relation(Rounding_Dir dir)
Result
Possible outcomes of a checked arithmetic computation.
From bool Type Type Rounding_Dir To
fpu_rounding_control_word_type fpu_save_rounding_direction(fpu_rounding_direction_type dir)
Sets the FPU rounding direction to dir and returns the rounding control word previously in use...
Result sub_2exp_float(Type &to, const Type x, unsigned int exp, Rounding_Dir dir)
Result neg_float(Type &to, const Type from, Rounding_Dir)
#define PPL_SPECIALIZE_REM(func, To, From1, From2)
int fpu_check_inexact()
Queries the inexact computation status.
Result classify_float(const T v, bool nan, bool inf, bool sign)
Negative infinity result class.
Not a number result class.
bool round_inverse(Rounding_Dir dir)
signed signed signed signed signed char signed signed signed signed signed int signed long long
Result gcdext_exact(To1 &to, To2 &s, To3 &t, const From1 &x, const From2 &y, Rounding_Dir dir)
#define PPL_SPECIALIZE_ABS(func, To, From)
Result trunc_float(Type &to, const Type from, Rounding_Dir dir)
Result input_generic(Type &to, std::istream &is, Rounding_Dir dir)
Result assign_float_int(To &to, const From from, Rounding_Dir dir)
#define PPL_SPECIALIZE_UMOD_2EXP(func, To, From)
Taking the modulus of an infinity.
PPL_SPECIALIZE_GCDEXT(gcdext_exact, char, char, char, char, char) PPL_SPECIALIZE_GCDEXT(gcdext_exact
The computed result is inexact and rounded down.
Result mul_2exp_float(Type &to, const Type x, unsigned int exp, Rounding_Dir dir)
#define PPL_SPECIALIZE_TRUNC(func, To, From)
Result assign_float_mpz(T &to, const mpz_class &from, Rounding_Dir dir)
#define PPL_SPECIALIZE_CMP(func, Type1, Type2)
#define PPL_SPECIALIZE_CEIL(func, To, From)
Result idiv_float(Type &to, const Type x, const Type y, Rounding_Dir dir)
#define PPL_SPECIALIZE_DIV(func, To, From1, From2)
#define PPL_SPECIALIZE_MUL_2EXP(func, To, From)
Positive infinity result class.
Result div_float(Type &to, const Type x, const Type y, Rounding_Dir dir)
fpu_rounding_direction_type round_fpu_dir(Rounding_Dir dir)
bool round_not_needed(Rounding_Dir dir)
Result_Class result_class(Result r)
The computed result is not representable.
Representable number result class.
#define PPL_SPECIALIZE_SUB(func, To, From1, From2)
#define PPL_SPECIALIZE_ASSIGN_SPECIAL(func, Type)
Negative infinity result.
#define sizeof_to_bits(size)
void limit_precision(const float &v)
Equal. This need to be accompanied by a value.
void fpu_reset_inexact()
Clears the inexact computation status.
Less than. This need to be accompanied by a value.
Result gcd_exact(To &to, const From1 &x, const From2 &y, Rounding_Dir dir)
The computed result is inexact.
bool round_up(Rounding_Dir dir)
#define PPL_SPECIALIZE_ADD_2EXP(func, To, From)
Result set_pos_overflow_float(T &to, Rounding_Dir dir)
#define PPL_SPECIALIZE_GCD(func, To, From1, From2)
Result assign_float_int_inexact(To &to, const From from, Rounding_Dir dir)
#define PPL_SPECIALIZE_SUB_MUL(func, To, From1, From2)
Result rem_float(Type &to, const Type x, const Type y, Rounding_Dir)
void PPL_CC_FLUSH(const T &x)
No-op function that force the compiler to store the argument and to reread it from memory if needed (...
Result assign_float_float_inexact(To &to, const From from, Rounding_Dir dir)
void fpu_restore_rounding_direction(fpu_rounding_control_word_type)
Restores the FPU rounding rounding control word to cw.
The computed result may be inexact and rounded up.
#define PPL_SPECIALIZE_IS_INT(func, Type)
#define PPL_SPECIALIZE_FLOOR(func, To, From)
Result output_float(std::ostream &os, const Type from, const Numeric_Format &, Rounding_Dir)
Result sqrt_float(Type &to, const Type from, Rounding_Dir dir)
The entire library is confined to this namespace.
Adding two infinities having opposite signs.
#define PPL_SPECIALIZE_DIV_2EXP(func, To, From)
Result div_2exp_float(Type &to, const Type x, unsigned int exp, Rounding_Dir dir)
Result umod_2exp_float(Type &to, const Type x, unsigned int exp, Rounding_Dir dir)
Result sub_mul_float(Type &to, const Type x, const Type y, Rounding_Dir dir)
Greater than. This need to be accompanied by a value.
Result_Relation cmp_float(const Type x, const Type y)
Enable_If< Is_Same< To_Policy, From_Policy >::value, void >::type copy_generic(Type &to, const Type &from)
Result add_float(Type &to, const Type x, const Type y, Rounding_Dir dir)
bool round_direct(Rounding_Dir dir)
bool is_nan_float(const T v)
The computed result may be inexact and rounded down.
Subtracting two infinities having the same sign.
bool is_pinf_float(const T v)
Result round_gt_float(To &to, Rounding_Dir dir)
Result round_lt_float(To &to, Rounding_Dir dir)
Result_Relation sgn_float(const Type x)
From bool Type Type Rounding_Dir From
bool fpu_inverse_rounding(Rounding_Dir dir)
#define PPL_SPECIALIZE_IS_NAN(func, Type)
No values satisfies the relation.
int sgn(Boundary_Type type, const T &x, const Info &info)
Result lcm_gcd_exact(To &to, const From1 &x, const From2 &y, Rounding_Dir dir)
#define PPL_SPECIALIZE_ASSIGN(func, To, From)
Positive infinity result.
Result assign_float_float_exact(To &to, const From from, Rounding_Dir)
Result ceil_float(Type &to, const Type from, Rounding_Dir)
Result abs_float(Type &to, const Type from, Rounding_Dir)
#define PPL_SPECIALIZE_SUB_2EXP(func, To, From)
Result smod_2exp_float(Type &to, const Type x, unsigned int exp, Rounding_Dir dir)
#define PPL_SPECIALIZE_COPY(func, Type)
Result assign_special_float(T &v, Result_Class c, Rounding_Dir)
A negative integer overflow occurred (rounding down).
bool is_inf_float(const T v)
#define PPL_SPECIALIZE_LCM(func, To, From1, From2)
Result assign_float_float(To &to, const From from, Rounding_Dir dir)
#define CHECK_P(cond, check)
#define PPL_SPECIALIZE_OUTPUT(func, Type)
The computed result is inexact and rounded up.
The computed result may be inexact.
Multiplying an infinity by zero.
void prepare_inexact(Rounding_Dir dir)
#define PPL_SPECIALIZE_INPUT(func, Type)
bool round_down(Rounding_Dir dir)
fpu_rounding_control_word_type
#define PPL_SPECIALIZE_SMOD_2EXP(func, To, From)
bool round_not_requested(Rounding_Dir dir)
A negative integer overflow occurred (rounding up).
#define PPL_SPECIALIZE_MUL(func, To, From1, From2)
#define PPL_SPECIALIZE_IS_PINF(func, Type)
#define PPL_SPECIALIZE_SGN(func, From)
Result set_neg_overflow_float(T &to, Rounding_Dir dir)
Result add_mul_float(Type &to, const Type x, const Type y, Rounding_Dir dir)
Result result_relation(Rounding_Dir dir)