Bug 932076 - Add check for MediaExtractor creation failure. r=doublec
[gecko.git] / mfbt / MathAlgorithms.h
blob941ac812718dc797e0db99465dca5ab42026ff29
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /* mfbt maths algorithms. */
9 #ifndef mozilla_MathAlgorithms_h
10 #define mozilla_MathAlgorithms_h
12 #include "mozilla/Assertions.h"
13 #include "mozilla/TypeTraits.h"
15 #include <cmath>
16 #include <limits.h>
17 #include <stdint.h>
19 namespace mozilla {
21 // Greatest Common Divisor
22 template<typename IntegerType>
23 MOZ_ALWAYS_INLINE IntegerType
24 EuclidGCD(IntegerType a, IntegerType b)
26 // Euclid's algorithm; O(N) in the worst case. (There are better
27 // ways, but we don't need them for the current use of this algo.)
28 MOZ_ASSERT(a > 0);
29 MOZ_ASSERT(b > 0);
31 while (a != b) {
32 if (a > b) {
33 a = a - b;
34 } else {
35 b = b - a;
39 return a;
42 // Least Common Multiple
43 template<typename IntegerType>
44 MOZ_ALWAYS_INLINE IntegerType
45 EuclidLCM(IntegerType a, IntegerType b)
47 // Divide first to reduce overflow risk.
48 return (a / EuclidGCD(a, b)) * b;
51 namespace detail {
53 template<typename T>
54 struct AllowDeprecatedAbsFixed : FalseType {};
56 template<> struct AllowDeprecatedAbsFixed<int32_t> : TrueType {};
57 template<> struct AllowDeprecatedAbsFixed<int64_t> : TrueType {};
59 template<typename T>
60 struct AllowDeprecatedAbs : AllowDeprecatedAbsFixed<T> {};
62 template<> struct AllowDeprecatedAbs<int> : TrueType {};
63 template<> struct AllowDeprecatedAbs<long> : TrueType {};
65 } // namespace detail
67 // DO NOT USE DeprecatedAbs. It exists only until its callers can be converted
68 // to Abs below, and it will be removed when all callers have been changed.
69 template<typename T>
70 inline typename mozilla::EnableIf<detail::AllowDeprecatedAbs<T>::value, T>::Type
71 DeprecatedAbs(const T t)
73 // The absolute value of the smallest possible value of a signed-integer type
74 // won't fit in that type (on twos-complement systems -- and we're blithely
75 // assuming we're on such systems, for the non-<stdint.h> types listed above),
76 // so assert that the input isn't that value.
78 // This is the case if: the value is non-negative; or if adding one (giving a
79 // value in the range [-maxvalue, 0]), then negating (giving a value in the
80 // range [0, maxvalue]), doesn't produce maxvalue (because in twos-complement,
81 // (minvalue + 1) == -maxvalue).
82 MOZ_ASSERT(t >= 0 ||
83 -(t + 1) != T((1ULL << (CHAR_BIT * sizeof(T) - 1)) - 1),
84 "You can't negate the smallest possible negative integer!");
85 return t >= 0 ? t : -t;
88 namespace detail {
90 // For now mozilla::Abs only takes intN_T, the signed natural types, and
91 // float/double/long double. Feel free to add overloads for other standard,
92 // signed types if you need them.
94 template<typename T>
95 struct AbsReturnTypeFixed;
97 template<> struct AbsReturnTypeFixed<int8_t> { typedef uint8_t Type; };
98 template<> struct AbsReturnTypeFixed<int16_t> { typedef uint16_t Type; };
99 template<> struct AbsReturnTypeFixed<int32_t> { typedef uint32_t Type; };
100 template<> struct AbsReturnTypeFixed<int64_t> { typedef uint64_t Type; };
102 template<typename T>
103 struct AbsReturnType : AbsReturnTypeFixed<T> {};
105 template<> struct AbsReturnType<char> : EnableIf<char(-1) < char(0), unsigned char> {};
106 template<> struct AbsReturnType<signed char> { typedef unsigned char Type; };
107 template<> struct AbsReturnType<short> { typedef unsigned short Type; };
108 template<> struct AbsReturnType<int> { typedef unsigned int Type; };
109 template<> struct AbsReturnType<long> { typedef unsigned long Type; };
110 template<> struct AbsReturnType<long long> { typedef unsigned long long Type; };
111 template<> struct AbsReturnType<float> { typedef float Type; };
112 template<> struct AbsReturnType<double> { typedef double Type; };
113 template<> struct AbsReturnType<long double> { typedef long double Type; };
115 } // namespace detail
117 template<typename T>
118 inline typename detail::AbsReturnType<T>::Type
119 Abs(const T t)
121 typedef typename detail::AbsReturnType<T>::Type ReturnType;
122 return t >= 0 ? ReturnType(t) : ~ReturnType(t) + 1;
125 template<>
126 inline float
127 Abs<float>(const float f)
129 return std::fabs(f);
132 template<>
133 inline double
134 Abs<double>(const double d)
136 return std::fabs(d);
139 template<>
140 inline long double
141 Abs<long double>(const long double d)
143 return std::fabs(d);
146 } // namespace mozilla
148 #if defined(_WIN32) && (_MSC_VER >= 1300) && (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64))
149 # define MOZ_BITSCAN_WINDOWS
151 extern "C" {
152 unsigned char _BitScanForward(unsigned long* Index, unsigned long mask);
153 unsigned char _BitScanReverse(unsigned long* Index, unsigned long mask);
154 # pragma intrinsic(_BitScanForward, _BitScanReverse)
156 # if defined(_M_AMD64) || defined(_M_X64)
157 # define MOZ_BITSCAN_WINDOWS64
158 unsigned char _BitScanForward64(unsigned long* index, unsigned __int64 mask);
159 unsigned char _BitScanReverse64(unsigned long* index, unsigned __int64 mask);
160 # pragma intrinsic(_BitScanForward64, _BitScanReverse64)
161 # endif
162 } // extern "C"
164 #endif
166 namespace mozilla {
168 namespace detail {
170 #if defined(MOZ_BITSCAN_WINDOWS)
172 inline uint_fast8_t
173 CountLeadingZeroes32(uint32_t u)
175 unsigned long index;
176 _BitScanReverse(&index, static_cast<unsigned long>(u));
177 return uint_fast8_t(31 - index);
181 inline uint_fast8_t
182 CountTrailingZeroes32(uint32_t u)
184 unsigned long index;
185 _BitScanForward(&index, static_cast<unsigned long>(u));
186 return uint_fast8_t(index);
189 inline uint_fast8_t
190 CountPopulation32(uint32_t u)
192 uint32_t sum2 = (u & 0x55555555) + ((u & 0xaaaaaaaa) >> 1);
193 uint32_t sum4 = (sum2 & 0x33333333) + ((sum2 & 0xcccccccc) >> 2);
194 uint32_t sum8 = (sum4 & 0x0f0f0f0f) + ((sum4 & 0xf0f0f0f0) >> 4);
195 uint32_t sum16 = (sum8 & 0x00ff00ff) + ((sum8 & 0xff00ff00) >> 8);
196 return sum16;
199 inline uint_fast8_t
200 CountLeadingZeroes64(uint64_t u)
202 # if defined(MOZ_BITSCAN_WINDOWS64)
203 unsigned long index;
204 _BitScanReverse64(&index, static_cast<unsigned __int64>(u));
205 return uint_fast8_t(63 - index);
206 # else
207 uint32_t hi = uint32_t(u >> 32);
208 if (hi != 0)
209 return CountLeadingZeroes32(hi);
210 return 32 + CountLeadingZeroes32(uint32_t(u));
211 # endif
214 inline uint_fast8_t
215 CountTrailingZeroes64(uint64_t u)
217 # if defined(MOZ_BITSCAN_WINDOWS64)
218 unsigned long index;
219 _BitScanForward64(&index, static_cast<unsigned __int64>(u));
220 return uint_fast8_t(index);
221 # else
222 uint32_t lo = uint32_t(u);
223 if (lo != 0)
224 return CountTrailingZeroes32(lo);
225 return 32 + CountTrailingZeroes32(uint32_t(u >> 32));
226 # endif
229 # ifdef MOZ_HAVE_BITSCAN64
230 # undef MOZ_HAVE_BITSCAN64
231 # endif
233 #elif defined(__clang__) || defined(__GNUC__)
235 # if defined(__clang__)
236 # if !__has_builtin(__builtin_ctz) || !__has_builtin(__builtin_clz)
237 # error "A clang providing __builtin_c[lt]z is required to build"
238 # endif
239 # else
240 // gcc has had __builtin_clz and friends since 3.4: no need to check.
241 # endif
243 inline uint_fast8_t
244 CountLeadingZeroes32(uint32_t u)
246 return __builtin_clz(u);
249 inline uint_fast8_t
250 CountTrailingZeroes32(uint32_t u)
252 return __builtin_ctz(u);
255 inline uint_fast8_t
256 CountPopulation32(uint32_t u)
258 return __builtin_popcount(u);
261 inline uint_fast8_t
262 CountLeadingZeroes64(uint64_t u)
264 return __builtin_clzll(u);
267 inline uint_fast8_t
268 CountTrailingZeroes64(uint64_t u)
270 return __builtin_ctzll(u);
273 #else
274 # error "Implement these!"
275 inline uint_fast8_t CountLeadingZeroes32(uint32_t u) MOZ_DELETE;
276 inline uint_fast8_t CountTrailingZeroes32(uint32_t u) MOZ_DELETE;
277 inline uint_fast8_t CountPopulation32(uint32_t u) MOZ_DELETE;
278 inline uint_fast8_t CountLeadingZeroes64(uint64_t u) MOZ_DELETE;
279 inline uint_fast8_t CountTrailingZeroes64(uint64_t u) MOZ_DELETE;
280 #endif
282 } // namespace detail
285 * Compute the number of high-order zero bits in the NON-ZERO number |u|. That
286 * is, looking at the bitwise representation of the number, with the highest-
287 * valued bits at the start, return the number of zeroes before the first one
288 * is observed.
290 * CountLeadingZeroes32(0xF0FF1000) is 0;
291 * CountLeadingZeroes32(0x7F8F0001) is 1;
292 * CountLeadingZeroes32(0x3FFF0100) is 2;
293 * CountLeadingZeroes32(0x1FF50010) is 3; and so on.
295 inline uint_fast8_t
296 CountLeadingZeroes32(uint32_t u)
298 MOZ_ASSERT(u != 0);
299 return detail::CountLeadingZeroes32(u);
303 * Compute the number of low-order zero bits in the NON-ZERO number |u|. That
304 * is, looking at the bitwise representation of the number, with the lowest-
305 * valued bits at the start, return the number of zeroes before the first one
306 * is observed.
308 * CountTrailingZeroes32(0x0100FFFF) is 0;
309 * CountTrailingZeroes32(0x7000FFFE) is 1;
310 * CountTrailingZeroes32(0x0080FFFC) is 2;
311 * CountTrailingZeroes32(0x0080FFF8) is 3; and so on.
313 inline uint_fast8_t
314 CountTrailingZeroes32(uint32_t u)
316 MOZ_ASSERT(u != 0);
317 return detail::CountTrailingZeroes32(u);
321 * Compute the number of one bits in the number |u|,
323 inline uint_fast8_t
324 CountPopulation32(uint32_t u)
326 return detail::CountPopulation32(u);
329 /** Analogous to CountLeadingZeroes32, but for 64-bit numbers. */
330 inline uint_fast8_t
331 CountLeadingZeroes64(uint64_t u)
333 MOZ_ASSERT(u != 0);
334 return detail::CountLeadingZeroes64(u);
337 /** Analogous to CountTrailingZeroes32, but for 64-bit numbers. */
338 inline uint_fast8_t
339 CountTrailingZeroes64(uint64_t u)
341 MOZ_ASSERT(u != 0);
342 return detail::CountTrailingZeroes64(u);
345 namespace detail {
347 template<typename T, size_t Size = sizeof(T)>
348 class CeilingLog2;
350 template<typename T>
351 class CeilingLog2<T, 4>
353 public:
354 static uint_fast8_t compute(const T t) {
355 // Check for <= 1 to avoid the == 0 undefined case.
356 return t <= 1 ? 0 : 32 - CountLeadingZeroes32(t - 1);
360 template<typename T>
361 class CeilingLog2<T, 8>
363 public:
364 static uint_fast8_t compute(const T t) {
365 // Check for <= 1 to avoid the == 0 undefined case.
366 return t <= 1 ? 0 : 64 - CountLeadingZeroes64(t - 1);
370 } // namespace detail
373 * Compute the log of the least power of 2 greater than or equal to |t|.
375 * CeilingLog2(0..1) is 0;
376 * CeilingLog2(2) is 1;
377 * CeilingLog2(3..4) is 2;
378 * CeilingLog2(5..8) is 3;
379 * CeilingLog2(9..16) is 4; and so on.
381 template<typename T>
382 inline uint_fast8_t
383 CeilingLog2(const T t)
385 return detail::CeilingLog2<T>::compute(t);
388 /** A CeilingLog2 variant that accepts only size_t. */
389 inline uint_fast8_t
390 CeilingLog2Size(size_t n)
392 return CeilingLog2(n);
395 namespace detail {
397 template<typename T, size_t Size = sizeof(T)>
398 class FloorLog2;
400 template<typename T>
401 class FloorLog2<T, 4>
403 public:
404 static uint_fast8_t compute(const T t) {
405 return 31 - CountLeadingZeroes32(t | 1);
409 template<typename T>
410 class FloorLog2<T, 8>
412 public:
413 static uint_fast8_t compute(const T t) {
414 return 63 - CountLeadingZeroes64(t | 1);
418 } // namespace detail
421 * Compute the log of the greatest power of 2 less than or equal to |t|.
423 * FloorLog2(0..1) is 0;
424 * FloorLog2(2..3) is 1;
425 * FloorLog2(4..7) is 2;
426 * FloorLog2(8..15) is 3; and so on.
428 template<typename T>
429 inline uint_fast8_t
430 FloorLog2(const T t)
432 return detail::FloorLog2<T>::compute(t);
435 /** A FloorLog2 variant that accepts only size_t. */
436 inline uint_fast8_t
437 FloorLog2Size(size_t n)
439 return FloorLog2(n);
443 * Compute the smallest power of 2 greater than or equal to |x|. |x| must not
444 * be so great that the computed value would overflow |size_t|.
446 inline size_t
447 RoundUpPow2(size_t x)
449 MOZ_ASSERT(x <= (size_t(1) << (sizeof(size_t) * CHAR_BIT - 1)),
450 "can't round up -- will overflow!");
451 return size_t(1) << CeilingLog2(x);
454 } /* namespace mozilla */
456 #endif /* mozilla_MathAlgorithms_h */