Google OR-Tools: ortools/util/fp_utils.h Source File

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22#ifndef ORTOOLS_UTIL_FP_UTILS_H_

23#define ORTOOLS_UTIL_FP_UTILS_H_

24

25#include <algorithm>

26#include <cmath>

27#include <cstdint>

28#include <cstdlib>

29#include <limits>

30

31#include <numeric>

32

33#include "absl/log/check.h"

34#include "absl/types/span.h"

35

36#if defined(_MSC_VER)

37#pragma fenv_access(on)

38#else

39#include <cfenv>

40#endif

41

42#ifdef __SSE__

43#include <xmmintrin.h>

44#endif

45

46#if defined(_MSC_VER)

47static inline double isnan(double value) { return _isnan(value); }

48static inline double round(double value) { return floor(value + 0.5); }

49#elif defined(__APPLE__) || __GNUC__ >= 5

50using std::isnan;

51#endif

52

54

55

56

57

58

59

60

61

62

63

64

66 public:

68#if defined(_MSC_VER)

69

70#elif (defined(__GNUC__) || defined(__llvm__)) && defined(__x86_64__)

71 CHECK_EQ(0, fegetenv(&saved_fenv_));

72#endif

73 }

74

76#if defined(_MSC_VER)

77

78#elif defined(__x86_64__) && defined(__GLIBC__)

79 CHECK_EQ(0, fesetenv(&saved_fenv_));

80#endif

81 }

82

84#if defined(_MSC_VER)

85

86#elif (defined(__GNUC__) || defined(__llvm__)) && defined(__x86_64__) && \

87 !defined(__ANDROID__)

88 CHECK_EQ(0, fegetenv(&fenv_));

89 excepts &= FE_ALL_EXCEPT;

90#if defined(__APPLE__)

91 fenv_.__control &= ~excepts;

92#elif (defined(__FreeBSD__) || defined(__OpenBSD__))

93 fenv_.__x87.__control &= ~excepts;

94#elif defined(__NetBSD__)

95 fenv_.x87.control &= ~excepts;

96#else

97 fenv_.__control_word &= ~excepts;

98#endif

99#if defined(__NetBSD__)

100 fenv_.mxcsr &= ~(excepts << 7);

101#else

102 fenv_.__mxcsr &= ~(excepts << 7);

103#endif

104 CHECK_EQ(0, fesetenv(&fenv_));

105#endif

106 }

107

108 private:

109#if defined(_MSC_VER)

110

111#elif (defined(__GNUC__) || defined(__llvm__)) && defined(__x86_64__)

112 fenv_t fenv_;

113 mutable fenv_t saved_fenv_;

114#endif

115};

116

117template <typename FloatType>

119 return x == std::numeric_limits<FloatType>::infinity() ||

120 x == -std::numeric_limits<FloatType>::infinity();

121}

122

123

124

125

126

127

128

129

130template <typename FloatType>

132 FloatType relative_tolerance,

133 FloatType absolute_tolerance) {

134 DCHECK_LE(0.0, relative_tolerance);

135 DCHECK_LE(0.0, absolute_tolerance);

136 DCHECK_GT(1.0, relative_tolerance);

138 return x == y;

139 }

140 const FloatType difference = fabs(x - y);

141 if (difference <= absolute_tolerance) {

142 return true;

143 }

144 const FloatType largest_magnitude = std::max(fabs(x), fabs(y));

145 return difference <= largest_magnitude * relative_tolerance;

146}

147

148

149

150

151template <typename FloatType>

153 FloatType absolute_tolerance) {

154 DCHECK_LE(0.0, absolute_tolerance);

156 return x == y;

157 }

158 return fabs(x - y) <= absolute_tolerance;

159}

160

161

162

163template <typename FloatType>

166 return x <= y + tolerance * std::max(FloatType(1.0),

167 std::min(std::abs(x), std::abs(y)));

168}

169

170

171

172template <typename FloatType>

174 DCHECK_LE(0.0, tolerance);

176 return std::abs(x - std::round(x)) <= tolerance;

177}

178

179

180

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;

186

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;

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

217 int64_t max_absolute_sum,

218 double* scaling_factor,

219 double* max_relative_coeff_error);

220

221

222

223

224

226 absl::Span<const double> lb,

227 absl::Span<const double> ub,

228 int64_t max_absolute_sum);

229

230

231

232

233

234

235

236

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);

242

243

244

245

246

248 double scaling_factor);

249

250

251template <typename FloatType>

252inline FloatType Interpolate(FloatType x, FloatType y, FloatType alpha) {

253 return alpha * x + (1 - alpha) * y;

254}

255

256inline int fast_ilogb(double value) { return ilogb(value); }

257inline double fast_scalbn(double value, int exponent) {

258 return scalbn(value, exponent);

259}

260

261}

262

263#endif

void EnableExceptions(int excepts)

Definition fp_utils.h:83

~ScopedFloatingPointEnv()

Definition fp_utils.h:75

ScopedFloatingPointEnv()

Definition fp_utils.h:67

int fast_ilogb(double value)

Definition fp_utils.h:256

bool IsSmallerWithinTolerance(FloatType x, FloatType y, FloatType tolerance)

Definition fp_utils.h:164

bool IsIntegerWithinTolerance(FloatType x, FloatType tolerance)

Definition fp_utils.h:173

double fast_scalbn(double value, int exponent)

Definition fp_utils.h:257

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)

Definition fp_utils.h:252

bool AreWithinAbsoluteOrRelativeTolerances(FloatType x, FloatType y, FloatType relative_tolerance, FloatType absolute_tolerance)

Definition fp_utils.h:131

bool AreWithinAbsoluteTolerance(FloatType x, FloatType y, FloatType absolute_tolerance)

Definition fp_utils.h:152

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)

Definition fp_utils.h:118

static int input(yyscan_t yyscanner)