Google OR-Tools v9.14
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
mathutil.h
Go to the documentation of this file.
1// Copyright 2010-2025 Google LLC
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14#ifndef OR_TOOLS_BASE_MATHUTIL_H_
15#define OR_TOOLS_BASE_MATHUTIL_H_
16
17#include <math.h>
18
19#include <algorithm>
20#include <cmath>
21#include <cstdint>
22#include <limits>
23#include <vector>
24
25#include "absl/base/casts.h"
27
28namespace operations_research {
29class MathUtil {
30 public:
31 // CeilOfRatio<IntegralType>
32 // FloorOfRatio<IntegralType>
33 // Returns the ceil (resp. floor) of the ratio of two integers.
34 //
35 // IntegralType: any integral type, whether signed or not.
36 // numerator: any integer: positive, negative, or zero.
37 // denominator: a non-zero integer, positive or negative.
38 template <typename IntegralType>
39 static IntegralType CeilOfRatio(IntegralType numerator,
40 IntegralType denominator) {
41 DCHECK_NE(0, denominator);
42 const IntegralType rounded_toward_zero = numerator / denominator;
43 const IntegralType intermediate_product = rounded_toward_zero * denominator;
44 const bool needs_adjustment =
45 (rounded_toward_zero >= 0) &&
46 ((denominator > 0 && numerator > intermediate_product) ||
47 (denominator < 0 && numerator < intermediate_product));
48 const IntegralType adjustment = static_cast<IntegralType>(needs_adjustment);
49 const IntegralType ceil_of_ratio = rounded_toward_zero + adjustment;
50 return ceil_of_ratio;
51 }
52 template <typename IntegralType>
53 static IntegralType FloorOfRatio(IntegralType numerator,
54 IntegralType denominator) {
55 DCHECK_NE(0, denominator);
56 const IntegralType rounded_toward_zero = numerator / denominator;
57 const IntegralType intermediate_product = rounded_toward_zero * denominator;
58 const bool needs_adjustment =
59 (rounded_toward_zero <= 0) &&
60 ((denominator > 0 && numerator < intermediate_product) ||
61 (denominator < 0 && numerator > intermediate_product));
62 const IntegralType adjustment = static_cast<IntegralType>(needs_adjustment);
63 const IntegralType floor_of_ratio = rounded_toward_zero - adjustment;
64 return floor_of_ratio;
65 }
66
67 // Returns the greatest common divisor of two unsigned integers x and y.
68 static unsigned int GCD(unsigned int x, unsigned int y) {
69 while (y != 0) {
70 unsigned int r = x % y;
71 x = y;
72 y = r;
73 }
74 return x;
75 }
76
77 // Returns the least common multiple of two unsigned integers. Returns zero
78 // if either is zero.
79 static unsigned int LeastCommonMultiple(unsigned int a, unsigned int b) {
80 if (a > b) {
81 return (a / MathUtil::GCD(a, b)) * b;
82 } else if (a < b) {
83 return (b / MathUtil::GCD(b, a)) * a;
84 } else {
85 return a;
86 }
87 }
88
89 // Absolute value of x.
90 // Works correctly for unsigned types and
91 // for special floating point values.
92 // Note: 0.0 and -0.0 are not differentiated by Abs (Abs(0.0) is -0.0),
93 // which should be OK: see the comment for Max above.
94 template <typename T>
95 static T Abs(const T x) {
96 return x > 0 ? x : -x;
97 }
98
99 // Returns the square of x.
100 template <typename T>
101 static T Square(const T x) {
102 return x * x;
103 }
104
105 // Euclid's Algorithm.
106 // Returns: the greatest common divisor of two unsigned integers x and y.
107 static int64_t GCD64(int64_t x, int64_t y) {
108 DCHECK_GE(x, 0);
109 DCHECK_GE(y, 0);
110 while (y != 0) {
111 int64_t r = x % y;
112 x = y;
113 y = r;
114 }
115 return x;
116 }
117
118 template <typename T>
119 static T IPow(T base, int exp) {
120 return pow(base, exp);
121 }
122
123 template <class IntOut, class FloatIn>
124 static IntOut Round(FloatIn x) {
125 // We don't use sgn(x) below because there is no need to distinguish the
126 // (x == 0) case. Also note that there are specialized faster versions
127 // of this function for Intel, ARM and PPC processors at the bottom
128 // of this file.
129 if (x > -0.5 && x < 0.5) {
130 // This case is special, because for largest floating point number
131 // below 0.5, the addition of 0.5 yields 1 and this would lead
132 // to incorrect result.
133 return static_cast<IntOut>(0);
134 }
135 return static_cast<IntOut>(x < 0 ? (x - 0.5) : (x + 0.5));
136 }
137
138 // Returns the minimum integer value which is a multiple of rounding_value,
139 // and greater than or equal to input_value.
140 // The input_value must be greater than or equal to zero, and the
141 // rounding_value must be greater than zero.
142 template <typename IntType>
143 static IntType RoundUpTo(IntType input_value, IntType rounding_value) {
144 static_assert(std::numeric_limits<IntType>::is_integer,
145 "RoundUpTo() operation type is not integer");
146 DCHECK_GE(input_value, 0);
147 DCHECK_GT(rounding_value, 0);
148 const IntType remainder = input_value % rounding_value;
149 return (remainder == 0) ? input_value
150 : (input_value - remainder + rounding_value);
151 }
152
153 // Convert a floating-point number to an integer. For all inputs x where
154 // static_cast<IntOut>(x) is legal according to the C++ standard, the result
155 // is identical to that cast (i.e. the result is x with its fractional part
156 // truncated whenever that is representable as IntOut).
157 //
158 // static_cast would cause undefined behavior for the following cases, which
159 // have well-defined behavior for this function:
160 //
161 // 1. If x is NaN, the result is zero.
162 //
163 // 2. If the truncated form of x is above the representable range of IntOut,
164 // the result is std::numeric_limits<IntOut>::max().
165 //
166 // 3. If the truncated form of x is below the representable range of IntOut,
167 // the result is std::numeric_limits<IntOut>::lowest().
168 //
169 // Note that cases #2 and #3 cover infinities as well as finite numbers.
170 //
171 // The range of FloatIn must include the range of IntOut, otherwise
172 // the results are undefined.
173 template <class IntOut, class FloatIn>
174 static IntOut SafeCast(FloatIn x) {
175 // Special case NaN, for which the logic below doesn't work.
176 if (std::isnan(x)) {
177 return 0;
178 }
179
180 // Negative values all clip to zero for unsigned results.
181 if (!std::numeric_limits<IntOut>::is_signed && x < 0) {
182 return 0;
183 }
184
185 // Handle infinities.
186 if (std::isinf(x)) {
187 return x < 0 ? std::numeric_limits<IntOut>::lowest()
188 : std::numeric_limits<IntOut>::max();
189 }
190
191 // Set exp such that x == f * 2^exp for some f with |f| in [0.5, 1.0),
192 // unless x is zero in which case exp == 0. Note that this implies that the
193 // magnitude of x is strictly less than 2^exp.
194 int exp = 0;
195 std::frexp(x, &exp);
196
197 // Let N be the number of non-sign bits in the representation of IntOut. If
198 // the magnitude of x is strictly less than 2^N, the truncated version of x
199 // is representable as IntOut. The only representable integer for which this
200 // is not the case is kMin for signed types (i.e. -2^N), but that is covered
201 // by the fall-through below.
202 if (exp <= std::numeric_limits<IntOut>::digits) {
203 return x;
204 }
205
206 // Handle numbers with magnitude >= 2^N.
207 return x < 0 ? std::numeric_limits<IntOut>::lowest()
208 : std::numeric_limits<IntOut>::max();
209 }
210
211 // --------------------------------------------------------------------
212 // SafeRound
213 // These functions round a floating-point number to an integer.
214 // Results are identical to Round, except in cases where
215 // the argument is NaN, or when the rounded value would overflow the
216 // return type. In those cases, Round has undefined
217 // behavior. SafeRound returns 0 when the argument is
218 // NaN, and returns the closest possible integer value otherwise (i.e.
219 // std::numeric_limits<IntOut>::max() for large positive values, and
220 // std::numeric_limits<IntOut>::lowest() for large negative values).
221 // The range of FloatIn must include the range of IntOut, otherwise
222 // the results are undefined.
223 // --------------------------------------------------------------------
224 template <class IntOut, class FloatIn>
225 static IntOut SafeRound(FloatIn x) {
226 if (std::isnan(x)) {
227 return 0;
228 } else {
229 return SafeCast<IntOut>((x < 0.) ? (x - 0.5) : (x + 0.5));
230 }
231 }
232
233 // --------------------------------------------------------------------
234 // FastInt64Round
235 // Fast routines for converting floating-point numbers to integers.
236 //
237 // These routines are approximately 6 times faster than the default
238 // implementation of Round<int> on Intel processors (12 times faster on
239 // the Pentium 3). They are also more than 5 times faster than simply
240 // casting a "double" to an "int" using static_cast<int>. This is
241 // because casts are defined to truncate towards zero, which on Intel
242 // processors requires changing the rounding mode and flushing the
243 // floating-point pipeline (unless programs are compiled specifically
244 // for the Pentium 4, which has a new instruction to avoid this).
245 //
246 // Numbers that are halfway between two integers may be rounded up or
247 // down. This is because the conversion is done using the default
248 // rounding mode, which rounds towards the closest even number in case
249 // of ties. So for example, FastIntRound(0.5) == 0, but
250 // FastIntRound(1.5) == 2. These functions should only be used with
251 // applications that don't care about which way such half-integers are
252 // rounded.
253 //
254 // There are template specializations of Round() which call these
255 // functions (for "int" and "int64" only), but it's safer to call them
256 // directly.
257 static int64_t FastInt64Round(double x) { return Round<int64_t>(x); }
258
259 // Returns Stirling's Approximation for log(n!) which has an error
260 // of at worst 1/(1260*n^5).
261 static double Stirling(double n);
262
263 // Returns the log of the binomial coefficient C(n, k), known in the
264 // vernacular as "N choose K". Why log? Because the integer number
265 // for non-trivial N and K would overflow.
266 // Note that if k > 15, this uses Stirling's approximation of log(n!).
267 // The relative error is about 1/(1260*k^5) (which is 7.6e-10 when k=16).
268 static double LogCombinations(int n, int k);
269
270 // Tests whether two values are close enough to each other to be considered
271 // equal. This function is intended to be used mainly as a replacement for
272 // equality tests of floating point values in CHECK()s, and as a replacement
273 // for equality comparison against golden files. It is the same as == for
274 // integer types. The purpose of AlmostEquals() is to avoid false positive
275 // error reports in unit tests and regression tests due to minute differences
276 // in floating point arithmetic (for example, due to a different compiler).
277 //
278 // We cannot use simple equality to compare floating point values
279 // because floating point expressions often accumulate inaccuracies, and
280 // new compilers may introduce further variations in the values.
281 //
282 // Two values x and y are considered "almost equals" if:
283 // (a) Both values are very close to zero: x and y are in the range
284 // [-standard_error, standard_error]
285 // Normal calculations producing these values are likely to be dealing
286 // with meaningless residual values.
287 // -or-
288 // (b) The difference between the values is small:
289 // abs(x - y) <= standard_error
290 // -or-
291 // (c) The values are finite and the relative difference between them is
292 // small:
293 // abs (x - y) <= standard_error * max(abs(x), abs(y))
294 // -or-
295 // (d) The values are both positive infinity or both negative infinity.
296 //
297 // Cases (b) and (c) are the same as MathUtils::NearByFractionOrMargin(x, y).
298 //
299 // standard_error is the corresponding MathLimits<T>::kStdError constant.
300 // It is equivalent to 5 bits of mantissa error. See util/math/mathlimits.cc.
301 //
302 // Caveat:
303 // AlmostEquals() is not appropriate for checking long sequences of
304 // operations where errors may cascade (like extended sums or matrix
305 // computations), or where significant cancellation may occur
306 // (e.g., the expression (x+y)-x, where x is much larger than y).
307 // Both cases may produce errors in excess of standard_error.
308 // In any case, you should not test the results of calculations which have
309 // not been vetted for possible cancellation errors and the like.
310 template <typename T>
311 static bool AlmostEquals(const T x, const T y) {
312 static_assert(std::is_arithmetic_v<T>);
313 if constexpr (std::numeric_limits<T>::is_integer) {
314 return x == y;
315 } else {
316 if (x == y) // Covers +inf and -inf, and is a shortcut for finite values.
317 return true;
318
319 if (std::abs(x) <= 1e-6 && std::abs(y) <= 1e-6) return true;
320 if (std::abs(x - y) <= 1e-6) return true;
321 return std::abs(x - y) / std::max(std::abs(x), std::abs(y)) <= 1e-6;
322 }
323 }
324};
325} // namespace operations_research
326
327#endif // OR_TOOLS_BASE_MATHUTIL_H_
static double Stirling(double n)
Definition mathutil.cc:26
static T Square(const T x)
Returns the square of x.
Definition mathutil.h:101
static T IPow(T base, int exp)
Definition mathutil.h:119
static IntOut SafeRound(FloatIn x)
Definition mathutil.h:227
static IntType RoundUpTo(IntType input_value, IntType rounding_value)
Definition mathutil.h:143
static IntOut Round(FloatIn x)
Definition mathutil.h:124
static int64_t FastInt64Round(double x)
Definition mathutil.h:260
static unsigned int LeastCommonMultiple(unsigned int a, unsigned int b)
Definition mathutil.h:79
static unsigned int GCD(unsigned int x, unsigned int y)
Returns the greatest common divisor of two unsigned integers x and y.
Definition mathutil.h:68
static double LogCombinations(int n, int k)
Definition mathutil.cc:33
static T Abs(const T x)
Definition mathutil.h:95
static int64_t GCD64(int64_t x, int64_t y)
Definition mathutil.h:107
static IntegralType CeilOfRatio(IntegralType numerator, IntegralType denominator)
Definition mathutil.h:39
static IntegralType FloorOfRatio(IntegralType numerator, IntegralType denominator)
Definition mathutil.h:53
static IntOut SafeCast(FloatIn x)
Definition mathutil.h:174
static bool AlmostEquals(const T x, const T y)
Definition mathutil.h:314
In SWIG mode, we don't want anything besides these top-level includes.