Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(252)

Side by Side Diff: third_party/WebKit/Source/wtf/MathExtras.h

Issue 2764243002: Move files in wtf/ to platform/wtf/ (Part 9). (Closed)
Patch Set: Rebase. Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/WebKit/Source/wtf/HexNumber.h ('k') | third_party/WebKit/Source/wtf/RetainPtr.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be
3 * 3 // found in the LICENSE file.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25 4
26 #ifndef WTF_MathExtras_h 5 #include "platform/wtf/MathExtras.h"
27 #define WTF_MathExtras_h
28 6
29 #include "wtf/Allocator.h" 7 // The contents of this header was moved to platform/wtf as part of
30 #include "wtf/Assertions.h" 8 // WTF migration project. See the following post for details:
31 #include "wtf/CPU.h" 9 // https://groups.google.com/a/chromium.org/d/msg/blink-dev/tLdAZCTlcAA/bYXVT8gY CAAJ
32 #include <cmath>
33 #include <cstddef>
34 #include <limits>
35
36 #if COMPILER(MSVC)
37 // Make math.h behave like other platforms.
38 #define _USE_MATH_DEFINES
39 // Even if math.h was already included, including math.h again with
40 // _USE_MATH_DEFINES adds the extra defines.
41 #include <math.h>
42 #include <stdint.h>
43 #endif
44
45 #if OS(OPENBSD)
46 #include <machine/ieee.h>
47 #include <sys/types.h>
48 #endif
49
50 const double piDouble = M_PI;
51 const float piFloat = static_cast<float>(M_PI);
52
53 const double piOverTwoDouble = M_PI_2;
54 const float piOverTwoFloat = static_cast<float>(M_PI_2);
55
56 const double piOverFourDouble = M_PI_4;
57 const float piOverFourFloat = static_cast<float>(M_PI_4);
58
59 const double twoPiDouble = piDouble * 2.0;
60 const float twoPiFloat = piFloat * 2.0f;
61
62 #if COMPILER(MSVC)
63
64 // VS2013 has most of the math functions now, but we still need to work
65 // around various differences in behavior of Inf.
66
67 // Work around a bug in Win, where atan2(+-infinity, +-infinity) yields NaN
68 // instead of specific values.
69 inline double wtf_atan2(double x, double y) {
70 double posInf = std::numeric_limits<double>::infinity();
71 double negInf = -std::numeric_limits<double>::infinity();
72 double nan = std::numeric_limits<double>::quiet_NaN();
73
74 double result = nan;
75
76 if (x == posInf && y == posInf)
77 result = piOverFourDouble;
78 else if (x == posInf && y == negInf)
79 result = 3 * piOverFourDouble;
80 else if (x == negInf && y == posInf)
81 result = -piOverFourDouble;
82 else if (x == negInf && y == negInf)
83 result = -3 * piOverFourDouble;
84 else
85 result = ::atan2(x, y);
86
87 return result;
88 }
89
90 // Work around a bug in the Microsoft CRT, where fmod(x, +-infinity) yields NaN
91 // instead of x.
92 inline double wtf_fmod(double x, double y) {
93 return (!std::isinf(x) && std::isinf(y)) ? x : fmod(x, y);
94 }
95
96 // Work around a bug in the Microsoft CRT, where pow(NaN, 0) yields NaN instead
97 // of 1.
98 inline double wtf_pow(double x, double y) {
99 return y == 0 ? 1 : pow(x, y);
100 }
101
102 #define atan2(x, y) wtf_atan2(x, y)
103 #define fmod(x, y) wtf_fmod(x, y)
104 #define pow(x, y) wtf_pow(x, y)
105
106 #endif // COMPILER(MSVC)
107
108 inline double deg2rad(double d) {
109 return d * piDouble / 180.0;
110 }
111 inline double rad2deg(double r) {
112 return r * 180.0 / piDouble;
113 }
114 inline double deg2grad(double d) {
115 return d * 400.0 / 360.0;
116 }
117 inline double grad2deg(double g) {
118 return g * 360.0 / 400.0;
119 }
120 inline double turn2deg(double t) {
121 return t * 360.0;
122 }
123 inline double deg2turn(double d) {
124 return d / 360.0;
125 }
126 inline double rad2grad(double r) {
127 return r * 200.0 / piDouble;
128 }
129 inline double grad2rad(double g) {
130 return g * piDouble / 200.0;
131 }
132 inline double turn2grad(double t) {
133 return t * 400;
134 }
135 inline double grad2turn(double g) {
136 return g / 400;
137 }
138
139 inline float deg2rad(float d) {
140 return d * piFloat / 180.0f;
141 }
142 inline float rad2deg(float r) {
143 return r * 180.0f / piFloat;
144 }
145 inline float deg2grad(float d) {
146 return d * 400.0f / 360.0f;
147 }
148 inline float grad2deg(float g) {
149 return g * 360.0f / 400.0f;
150 }
151 inline float turn2deg(float t) {
152 return t * 360.0f;
153 }
154 inline float deg2turn(float d) {
155 return d / 360.0f;
156 }
157 inline float rad2grad(float r) {
158 return r * 200.0f / piFloat;
159 }
160 inline float grad2rad(float g) {
161 return g * piFloat / 200.0f;
162 }
163 inline float turn2grad(float t) {
164 return t * 400;
165 }
166 inline float grad2turn(float g) {
167 return g / 400;
168 }
169
170 // clampTo() is implemented by templated helper classes (to allow for partial
171 // template specialization) as well as several helper functions.
172
173 // This helper function can be called when we know that:
174 // (1) The type signednesses match so the compiler will not produce signed vs.
175 // unsigned warnings
176 // (2) The default type promotions/conversions are sufficient to handle things
177 // correctly
178 template <typename LimitType, typename ValueType>
179 inline LimitType clampToDirectComparison(ValueType value,
180 LimitType min,
181 LimitType max) {
182 if (value >= max)
183 return max;
184 return (value <= min) ? min : static_cast<LimitType>(value);
185 }
186
187 // For any floating-point limits, or integral limits smaller than long long, we
188 // can cast the limits to double without losing precision; then the only cases
189 // where |value| can't be represented accurately as a double are the ones where
190 // it's outside the limit range anyway. So doing all comparisons as doubles
191 // will give correct results.
192 //
193 // In some cases, we can get better performance by using
194 // clampToDirectComparison(). We use a templated class to switch between these
195 // two cases (instead of simply using a conditional within one function) in
196 // order to only compile the clampToDirectComparison() code for cases where it
197 // will actually be used; this prevents the compiler from emitting warnings
198 // about unsafe code (even though we wouldn't actually be executing that code).
199 template <bool canUseDirectComparison, typename LimitType, typename ValueType>
200 class ClampToNonLongLongHelper;
201 template <typename LimitType, typename ValueType>
202 class ClampToNonLongLongHelper<true, LimitType, ValueType> {
203 STATIC_ONLY(ClampToNonLongLongHelper);
204
205 public:
206 static inline LimitType clampTo(ValueType value,
207 LimitType min,
208 LimitType max) {
209 return clampToDirectComparison(value, min, max);
210 }
211 };
212
213 template <typename LimitType, typename ValueType>
214 class ClampToNonLongLongHelper<false, LimitType, ValueType> {
215 STATIC_ONLY(ClampToNonLongLongHelper);
216
217 public:
218 static inline LimitType clampTo(ValueType value,
219 LimitType min,
220 LimitType max) {
221 const double doubleValue = static_cast<double>(value);
222 if (doubleValue >= static_cast<double>(max))
223 return max;
224 if (doubleValue <= static_cast<double>(min))
225 return min;
226 // If the limit type is integer, we might get better performance by
227 // casting |value| (as opposed to |doubleValue|) to the limit type.
228 return std::numeric_limits<LimitType>::is_integer
229 ? static_cast<LimitType>(value)
230 : static_cast<LimitType>(doubleValue);
231 }
232 };
233
234 // The unspecialized version of this templated class handles clamping to
235 // anything other than [unsigned] long long int limits. It simply uses the
236 // class above to toggle between the "fast" and "safe" clamp implementations.
237 template <typename LimitType, typename ValueType>
238 class ClampToHelper {
239 public:
240 static inline LimitType clampTo(ValueType value,
241 LimitType min,
242 LimitType max) {
243 // We only use clampToDirectComparison() when the integerness and
244 // signedness of the two types matches.
245 //
246 // If the integerness of the types doesn't match, then at best
247 // clampToDirectComparison() won't be much more efficient than the
248 // cast-everything-to-double method, since we'll need to convert to
249 // floating point anyway; at worst, we risk incorrect results when
250 // clamping a float to a 32-bit integral type due to potential precision
251 // loss.
252 //
253 // If the signedness doesn't match, clampToDirectComparison() will
254 // produce warnings about comparing signed vs. unsigned, which are apt
255 // since negative signed values will be converted to large unsigned ones
256 // and we'll get incorrect results.
257 return ClampToNonLongLongHelper <
258 std::numeric_limits<LimitType>::is_integer ==
259 std::numeric_limits<ValueType>::is_integer &&
260 std::numeric_limits<LimitType>::is_signed ==
261 std::numeric_limits<ValueType>::is_signed,
262 LimitType, ValueType > ::clampTo(value, min, max);
263 }
264 };
265
266 // Clamping to [unsigned] long long int limits requires more care. These may
267 // not be accurately representable as doubles, so instead we cast |value| to the
268 // limit type. But that cast is undefined if |value| is floating point and
269 // outside the representable range of the limit type, so we also have to check
270 // for that case explicitly.
271 template <typename ValueType>
272 class ClampToHelper<long long int, ValueType> {
273 STATIC_ONLY(ClampToHelper);
274
275 public:
276 static inline long long int clampTo(ValueType value,
277 long long int min,
278 long long int max) {
279 if (!std::numeric_limits<ValueType>::is_integer) {
280 if (value > 0) {
281 if (static_cast<double>(value) >=
282 static_cast<double>(std::numeric_limits<long long int>::max()))
283 return max;
284 } else if (static_cast<double>(value) <=
285 static_cast<double>(
286 std::numeric_limits<long long int>::min())) {
287 return min;
288 }
289 }
290 // Note: If |value| were unsigned long long int, it could be larger than
291 // the largest long long int, and this code would be wrong; we handle
292 // this case with a separate full specialization below.
293 return clampToDirectComparison(static_cast<long long int>(value), min, max);
294 }
295 };
296
297 // This specialization handles the case where the above partial specialization
298 // would be potentially incorrect.
299 template <>
300 class ClampToHelper<long long int, unsigned long long int> {
301 STATIC_ONLY(ClampToHelper);
302
303 public:
304 static inline long long int clampTo(unsigned long long int value,
305 long long int min,
306 long long int max) {
307 if (max <= 0 || value >= static_cast<unsigned long long int>(max))
308 return max;
309 const long long int longLongValue = static_cast<long long int>(value);
310 return (longLongValue <= min) ? min : longLongValue;
311 }
312 };
313
314 // This is similar to the partial specialization that clamps to long long int,
315 // but because the lower-bound check is done for integer value types as well, we
316 // don't need a <unsigned long long int, long long int> full specialization.
317 template <typename ValueType>
318 class ClampToHelper<unsigned long long int, ValueType> {
319 STATIC_ONLY(ClampToHelper);
320
321 public:
322 static inline unsigned long long int clampTo(ValueType value,
323 unsigned long long int min,
324 unsigned long long int max) {
325 if (value <= 0)
326 return min;
327 if (!std::numeric_limits<ValueType>::is_integer) {
328 if (static_cast<double>(value) >=
329 static_cast<double>(
330 std::numeric_limits<unsigned long long int>::max()))
331 return max;
332 }
333 return clampToDirectComparison(static_cast<unsigned long long int>(value),
334 min, max);
335 }
336 };
337
338 template <typename T>
339 inline T defaultMaximumForClamp() {
340 return std::numeric_limits<T>::max();
341 }
342 // This basically reimplements C++11's std::numeric_limits<T>::lowest().
343 template <typename T>
344 inline T defaultMinimumForClamp() {
345 return std::numeric_limits<T>::min();
346 }
347 template <>
348 inline float defaultMinimumForClamp<float>() {
349 return -std::numeric_limits<float>::max();
350 }
351 template <>
352 inline double defaultMinimumForClamp<double>() {
353 return -std::numeric_limits<double>::max();
354 }
355
356 // And, finally, the actual function for people to call.
357 template <typename LimitType, typename ValueType>
358 inline LimitType clampTo(ValueType value,
359 LimitType min = defaultMinimumForClamp<LimitType>(),
360 LimitType max = defaultMaximumForClamp<LimitType>()) {
361 DCHECK(!std::isnan(static_cast<double>(value)));
362 DCHECK_LE(min, max); // This also ensures |min| and |max| aren't NaN.
363 return ClampToHelper<LimitType, ValueType>::clampTo(value, min, max);
364 }
365
366 inline bool isWithinIntRange(float x) {
367 return x > static_cast<float>(std::numeric_limits<int>::min()) &&
368 x < static_cast<float>(std::numeric_limits<int>::max());
369 }
370
371 static size_t greatestCommonDivisor(size_t a, size_t b) {
372 return b ? greatestCommonDivisor(b, a % b) : a;
373 }
374
375 inline size_t lowestCommonMultiple(size_t a, size_t b) {
376 return a && b ? a / greatestCommonDivisor(a, b) * b : 0;
377 }
378
379 #ifndef UINT64_C
380 #if COMPILER(MSVC)
381 #define UINT64_C(c) c##ui64
382 #else
383 #define UINT64_C(c) c##ull
384 #endif
385 #endif
386
387 // Calculate d % 2^{64}.
388 inline void doubleToInteger(double d, unsigned long long& value) {
389 if (std::isnan(d) || std::isinf(d)) {
390 value = 0;
391 } else {
392 // -2^{64} < fmodValue < 2^{64}.
393 double fmodValue =
394 fmod(trunc(d), std::numeric_limits<unsigned long long>::max() + 1.0);
395 if (fmodValue >= 0) {
396 // 0 <= fmodValue < 2^{64}.
397 // 0 <= value < 2^{64}. This cast causes no loss.
398 value = static_cast<unsigned long long>(fmodValue);
399 } else {
400 // -2^{64} < fmodValue < 0.
401 // 0 < fmodValueInUnsignedLongLong < 2^{64}. This cast causes no loss.
402 unsigned long long fmodValueInUnsignedLongLong =
403 static_cast<unsigned long long>(-fmodValue);
404 // -1 < (std::numeric_limits<unsigned long long>::max() -
405 // fmodValueInUnsignedLongLong)
406 // < 2^{64} - 1.
407 // 0 < value < 2^{64}.
408 value = std::numeric_limits<unsigned long long>::max() -
409 fmodValueInUnsignedLongLong + 1;
410 }
411 }
412 }
413
414 namespace WTF {
415
416 inline unsigned fastLog2(unsigned i) {
417 unsigned log2 = 0;
418 if (i & (i - 1))
419 log2 += 1;
420 if (i >> 16)
421 log2 += 16, i >>= 16;
422 if (i >> 8)
423 log2 += 8, i >>= 8;
424 if (i >> 4)
425 log2 += 4, i >>= 4;
426 if (i >> 2)
427 log2 += 2, i >>= 2;
428 if (i >> 1)
429 log2 += 1;
430 return log2;
431 }
432
433 } // namespace WTF
434
435 #endif // #ifndef WTF_MathExtras_h
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/wtf/HexNumber.h ('k') | third_party/WebKit/Source/wtf/RetainPtr.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698