22#ifndef OR_TOOLS_UTIL_FP_UTILS_H_
23#define OR_TOOLS_UTIL_FP_UTILS_H_
34#include "absl/log/check.h"
35#include "absl/types/span.h"
38#pragma fenv_access(on)
48static inline double isnan(
double value) {
return _isnan(value); }
49static inline double round(
double value) {
return floor(value + 0.5); }
50#elif defined(__APPLE__) || __GNUC__ >= 5
71#elif (defined(__GNUC__) || defined(__llvm__)) && defined(__x86_64__)
72 CHECK_EQ(0, fegetenv(&saved_fenv_));
79#elif defined(__x86_64__) && defined(__GLIBC__)
80 CHECK_EQ(0, fesetenv(&saved_fenv_));
87#elif (defined(__GNUC__) || defined(__llvm__)) && defined(__x86_64__) && \
89 CHECK_EQ(0, fegetenv(&fenv_));
90 excepts &= FE_ALL_EXCEPT;
92 fenv_.__control &= ~excepts;
93#elif (defined(__FreeBSD__) || defined(__OpenBSD__))
94 fenv_.__x87.__control &= ~excepts;
95#elif defined(__NetBSD__)
96 fenv_.x87.control &= ~excepts;
98 fenv_.__control_word &= ~excepts;
100#if defined(__NetBSD__)
101 fenv_.mxcsr &= ~(excepts << 7);
103 fenv_.__mxcsr &= ~(excepts << 7);
105 CHECK_EQ(0, fesetenv(&fenv_));
112#elif (defined(__GNUC__) || defined(__llvm__)) && defined(__x86_64__)
114 mutable fenv_t saved_fenv_;
118template <
typename FloatType>
120 return x == std::numeric_limits<FloatType>::infinity() ||
121 x == -std::numeric_limits<FloatType>::infinity();
131template <
typename FloatType>
133 FloatType relative_tolerance,
134 FloatType absolute_tolerance) {
135 DCHECK_LE(0.0, relative_tolerance);
136 DCHECK_LE(0.0, absolute_tolerance);
137 DCHECK_GT(1.0, relative_tolerance);
141 const FloatType difference = fabs(x - y);
142 if (difference <= absolute_tolerance) {
145 const FloatType largest_magnitude = std::max(fabs(x), fabs(y));
146 return difference <= largest_magnitude * relative_tolerance;
152template <
typename FloatType>
154 FloatType absolute_tolerance) {
155 DCHECK_LE(0.0, absolute_tolerance);
159 return fabs(x - y) <= absolute_tolerance;
164template <
typename FloatType>
167 return x <= y + tolerance * std::max(1.0, std::min(std::abs(x), std::abs(y)));
172template <
typename FloatType>
174 DCHECK_LE(0.0, tolerance);
176 return std::abs(x - std::round(x)) <= tolerance;
181#define EXPECT_COMPARABLE(expected, obtained, epsilon) \
182 EXPECT_TRUE(operations_research::AreWithinAbsoluteOrRelativeTolerances( \
183 expected, obtained, epsilon, epsilon)) \
184 << obtained << " != expected value " << expected \
185 << " within epsilon = " << epsilon;
187#define EXPECT_NOTCOMPARABLE(expected, obtained, epsilon) \
188 EXPECT_FALSE(operations_research::AreWithinAbsoluteOrRelativeTolerances( \
189 expected, obtained, epsilon, epsilon)) \
190 << obtained << " == expected value " << expected \
191 << " within epsilon = " << epsilon;
217 int64_t max_absolute_sum,
218 double* scaling_factor,
219 double* max_relative_coeff_error);
226 absl::Span<const double> lb,
227 absl::Span<const double> ub,
228 int64_t max_absolute_sum);
238 absl::Span<const double> lb,
239 absl::Span<const double> ub,
double scaling_factor,
240 double* max_relative_coeff_error,
241 double* max_scaled_sum_error);
248 double scaling_factor);
251template <
typename FloatType>
252inline FloatType
Interpolate(FloatType x, FloatType y, FloatType alpha) {
253 return alpha * x + (1 - alpha) * y;
void EnableExceptions(int excepts)
~ScopedFloatingPointEnv()
In SWIG mode, we don't want anything besides these top-level includes.
int fast_ilogb(double value)
bool IsSmallerWithinTolerance(FloatType x, FloatType y, FloatType tolerance)
bool IsIntegerWithinTolerance(FloatType x, FloatType tolerance)
double fast_scalbn(double value, int exponent)
double GetBestScalingOfDoublesToInt64(absl::Span< const double > input, absl::Span< const double > lb, absl::Span< const double > ub, int64_t max_absolute_sum)
FloatType Interpolate(FloatType x, FloatType y, FloatType alpha)
Returns alpha * x + (1 - alpha) * y.
bool AreWithinAbsoluteOrRelativeTolerances(FloatType x, FloatType y, FloatType relative_tolerance, FloatType absolute_tolerance)
bool AreWithinAbsoluteTolerance(FloatType x, FloatType y, FloatType absolute_tolerance)
void ComputeScalingErrors(absl::Span< const double > input, absl::Span< const double > lb, absl::Span< const double > ub, double scaling_factor, double *max_relative_coeff_error, double *max_scaled_sum_error)
int64_t ComputeGcdOfRoundedDoubles(absl::Span< const double > x, double scaling_factor)
bool IsPositiveOrNegativeInfinity(FloatType x)
void fast_scalbn_inplace(double &mutable_value, int exponent)
static int input(yyscan_t yyscanner)