Google OR-Tools v9.11
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-2024 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#include "ortools/base/macros.h"
28
29namespace operations_research {
30class MathUtil {
31 public:
32 // CeilOfRatio<IntegralType>
33 // FloorOfRatio<IntegralType>
34 // Returns the ceil (resp. floor) of the ratio of two integers.
35 //
36 // IntegralType: any integral type, whether signed or not.
37 // numerator: any integer: positive, negative, or zero.
38 // denominator: a non-zero integer, positive or negative.
39 template <typename IntegralType>
40 static IntegralType CeilOfRatio(IntegralType numerator,
41 IntegralType denominator) {
42 DCHECK_NE(0, denominator);
43 const IntegralType rounded_toward_zero = numerator / denominator;
44 const IntegralType intermediate_product = rounded_toward_zero * denominator;
45 const bool needs_adjustment =
46 (rounded_toward_zero >= 0) &&
47 ((denominator > 0 && numerator > intermediate_product) ||
48 (denominator < 0 && numerator < intermediate_product));
49 const IntegralType adjustment = static_cast<IntegralType>(needs_adjustment);
50 const IntegralType ceil_of_ratio = rounded_toward_zero + adjustment;
51 return ceil_of_ratio;
52 }
53 template <typename IntegralType>
54 static IntegralType FloorOfRatio(IntegralType numerator,
55 IntegralType denominator) {
56 DCHECK_NE(0, denominator);
57 const IntegralType rounded_toward_zero = numerator / denominator;
58 const IntegralType intermediate_product = rounded_toward_zero * denominator;
59 const bool needs_adjustment =
60 (rounded_toward_zero <= 0) &&
61 ((denominator > 0 && numerator < intermediate_product) ||
62 (denominator < 0 && numerator > intermediate_product));
63 const IntegralType adjustment = static_cast<IntegralType>(needs_adjustment);
64 const IntegralType floor_of_ratio = rounded_toward_zero - adjustment;
65 return floor_of_ratio;
66 }
67
68 // Returns the greatest common divisor of two unsigned integers x and y.
69 static unsigned int GCD(unsigned int x, unsigned int y) {
70 while (y != 0) {
71 unsigned int r = x % y;
72 x = y;
73 y = r;
74 }
75 return x;
76 }
77
78 // Returns the least common multiple of two unsigned integers. Returns zero
79 // if either is zero.
80 static unsigned int LeastCommonMultiple(unsigned int a, unsigned int b) {
81 if (a > b) {
82 return (a / MathUtil::GCD(a, b)) * b;
83 } else if (a < b) {
84 return (b / MathUtil::GCD(b, a)) * a;
85 } else {
86 return a;
87 }
88 }
89
90 // Absolute value of x.
91 // Works correctly for unsigned types and
92 // for special floating point values.
93 // Note: 0.0 and -0.0 are not differentiated by Abs (Abs(0.0) is -0.0),
94 // which should be OK: see the comment for Max above.
95 template <typename T>
96 static T Abs(const T x) {
97 return x > 0 ? x : -x;
98 }
99
100 // Returns the square of x.
101 template <typename T>
102 static T Square(const T x) {
103 return x * x;
104 }
105
106 // Euclid's Algorithm.
107 // Returns: the greatest common divisor of two unsigned integers x and y.
108 static int64_t GCD64(int64_t x, int64_t y) {
109 DCHECK_GE(x, 0);
110 DCHECK_GE(y, 0);
111 while (y != 0) {
112 int64_t r = x % y;
113 x = y;
114 y = r;
115 }
116 return x;
117 }
118
119 template <typename T>
120 static T IPow(T base, int exp) {
121 return pow(base, exp);
122 }
123
124 template <class IntOut, class FloatIn>
125 static IntOut Round(FloatIn x) {
126 // We don't use sgn(x) below because there is no need to distinguish the
127 // (x == 0) case. Also note that there are specialized faster versions
128 // of this function for Intel, ARM and PPC processors at the bottom
129 // of this file.
130 if (x > -0.5 && x < 0.5) {
131 // This case is special, because for largest floating point number
132 // below 0.5, the addition of 0.5 yields 1 and this would lead
133 // to incorrect result.
134 return static_cast<IntOut>(0);
135 }
136 return static_cast<IntOut>(x < 0 ? (x - 0.5) : (x + 0.5));
137 }
138
139 // Returns the minimum integer value which is a multiple of rounding_value,
140 // and greater than or equal to input_value.
141 // The input_value must be greater than or equal to zero, and the
142 // rounding_value must be greater than zero.
143 template <typename IntType>
144 static IntType RoundUpTo(IntType input_value, IntType rounding_value) {
145 static_assert(std::numeric_limits<IntType>::is_integer,
146 "RoundUpTo() operation type is not integer");
147 DCHECK_GE(input_value, 0);
148 DCHECK_GT(rounding_value, 0);
149 const IntType remainder = input_value % rounding_value;
150 return (remainder == 0) ? input_value
151 : (input_value - remainder + rounding_value);
152 }
153
154 // Convert a floating-point number to an integer. For all inputs x where
155 // static_cast<IntOut>(x) is legal according to the C++ standard, the result
156 // is identical to that cast (i.e. the result is x with its fractional part
157 // truncated whenever that is representable as IntOut).
158 //
159 // static_cast would cause undefined behavior for the following cases, which
160 // have well-defined behavior for this function:
161 //
162 // 1. If x is NaN, the result is zero.
163 //
164 // 2. If the truncated form of x is above the representable range of IntOut,
165 // the result is std::numeric_limits<IntOut>::max().
166 //
167 // 3. If the truncated form of x is below the representable range of IntOut,
168 // the result is std::numeric_limits<IntOut>::lowest().
169 //
170 // Note that cases #2 and #3 cover infinities as well as finite numbers.
171 //
172 // The range of FloatIn must include the range of IntOut, otherwise
173 // the results are undefined.
174 template <class IntOut, class FloatIn>
175 static IntOut SafeCast(FloatIn x) {
176 COMPILE_ASSERT(!std::numeric_limits<FloatIn>::is_integer,
177 FloatIn_is_integer);
178 COMPILE_ASSERT(std::numeric_limits<IntOut>::is_integer,
179 IntOut_is_not_integer);
180 COMPILE_ASSERT(std::numeric_limits<IntOut>::radix == 2, IntOut_is_base_2);
181
182 // Special case NaN, for which the logic below doesn't work.
183 if (std::isnan(x)) {
184 return 0;
185 }
186
187 // Negative values all clip to zero for unsigned results.
188 if (!std::numeric_limits<IntOut>::is_signed && x < 0) {
189 return 0;
190 }
191
192 // Handle infinities.
193 if (std::isinf(x)) {
194 return x < 0 ? std::numeric_limits<IntOut>::lowest()
195 : std::numeric_limits<IntOut>::max();
196 }
197
198 // Set exp such that x == f * 2^exp for some f with |f| in [0.5, 1.0),
199 // unless x is zero in which case exp == 0. Note that this implies that the
200 // magnitude of x is strictly less than 2^exp.
201 int exp = 0;
202 std::frexp(x, &exp);
203
204 // Let N be the number of non-sign bits in the representation of IntOut. If
205 // the magnitude of x is strictly less than 2^N, the truncated version of x
206 // is representable as IntOut. The only representable integer for which this
207 // is not the case is kMin for signed types (i.e. -2^N), but that is covered
208 // by the fall-through below.
209 if (exp <= std::numeric_limits<IntOut>::digits) {
210 return x;
211 }
212
213 // Handle numbers with magnitude >= 2^N.
214 return x < 0 ? std::numeric_limits<IntOut>::lowest()
215 : std::numeric_limits<IntOut>::max();
216 }
217
218 // --------------------------------------------------------------------
219 // SafeRound
220 // These functions round a floating-point number to an integer.
221 // Results are identical to Round, except in cases where
222 // the argument is NaN, or when the rounded value would overflow the
223 // return type. In those cases, Round has undefined
224 // behavior. SafeRound returns 0 when the argument is
225 // NaN, and returns the closest possible integer value otherwise (i.e.
226 // std::numeric_limits<IntOut>::max() for large positive values, and
227 // std::numeric_limits<IntOut>::lowest() for large negative values).
228 // The range of FloatIn must include the range of IntOut, otherwise
229 // the results are undefined.
230 // --------------------------------------------------------------------
231 template <class IntOut, class FloatIn>
232 static IntOut SafeRound(FloatIn x) {
233 COMPILE_ASSERT(!std::numeric_limits<FloatIn>::is_integer,
234 FloatIn_is_integer);
235 COMPILE_ASSERT(std::numeric_limits<IntOut>::is_integer,
236 IntOut_is_not_integer);
237
238 if (std::isnan(x)) {
239 return 0;
240 } else {
241 return SafeCast<IntOut>((x < 0.) ? (x - 0.5) : (x + 0.5));
242 }
243 }
244
245 // --------------------------------------------------------------------
246 // FastInt64Round
247 // Fast routines for converting floating-point numbers to integers.
248 //
249 // These routines are approximately 6 times faster than the default
250 // implementation of Round<int> on Intel processors (12 times faster on
251 // the Pentium 3). They are also more than 5 times faster than simply
252 // casting a "double" to an "int" using static_cast<int>. This is
253 // because casts are defined to truncate towards zero, which on Intel
254 // processors requires changing the rounding mode and flushing the
255 // floating-point pipeline (unless programs are compiled specifically
256 // for the Pentium 4, which has a new instruction to avoid this).
257 //
258 // Numbers that are halfway between two integers may be rounded up or
259 // down. This is because the conversion is done using the default
260 // rounding mode, which rounds towards the closest even number in case
261 // of ties. So for example, FastIntRound(0.5) == 0, but
262 // FastIntRound(1.5) == 2. These functions should only be used with
263 // applications that don't care about which way such half-integers are
264 // rounded.
265 //
266 // There are template specializations of Round() which call these
267 // functions (for "int" and "int64" only), but it's safer to call them
268 // directly.
269 static int64_t FastInt64Round(double x) { return Round<int64_t>(x); }
270
271 // Returns Stirling's Approximation for log(n!) which has an error
272 // of at worst 1/(1260*n^5).
273 static double Stirling(double n);
274
275 // Returns the log of the binomial coefficient C(n, k), known in the
276 // vernacular as "N choose K". Why log? Because the integer number
277 // for non-trivial N and K would overflow.
278 // Note that if k > 15, this uses Stirling's approximation of log(n!).
279 // The relative error is about 1/(1260*k^5) (which is 7.6e-10 when k=16).
280 static double LogCombinations(int n, int k);
281};
282} // namespace operations_research
283
284#endif // OR_TOOLS_BASE_MATHUTIL_H_
IntegerValue y
static double Stirling(double n)
Definition mathutil.cc:26
static T Square(const T x)
Returns the square of x.
Definition mathutil.h:102
static T IPow(T base, int exp)
Definition mathutil.h:120
static IntOut SafeRound(FloatIn x)
Definition mathutil.h:234
static IntType RoundUpTo(IntType input_value, IntType rounding_value)
Definition mathutil.h:144
static IntOut Round(FloatIn x)
Definition mathutil.h:125
static int64_t FastInt64Round(double x)
Definition mathutil.h:272
static unsigned int LeastCommonMultiple(unsigned int a, unsigned int b)
Definition mathutil.h:80
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:69
static double LogCombinations(int n, int k)
Definition mathutil.cc:33
static T Abs(const T x)
Definition mathutil.h:96
static int64_t GCD64(int64_t x, int64_t y)
Definition mathutil.h:108
static IntegralType CeilOfRatio(IntegralType numerator, IntegralType denominator)
Definition mathutil.h:40
static IntegralType FloorOfRatio(IntegralType numerator, IntegralType denominator)
Definition mathutil.h:54
static IntOut SafeCast(FloatIn x)
Definition mathutil.h:175
int64_t b
Definition table.cc:45
int64_t a
Definition table.cc:44
#define COMPILE_ASSERT(x, msg)
Definition macros.h:19
In SWIG mode, we don't want anything besides these top-level includes.
const Variable x
Definition qp_tests.cc:127