Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/mozilla/MathAlgorithms.h
Line
Count
Source (jump to first uncovered line)
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/. */
6
7
/* mfbt maths algorithms. */
8
9
#ifndef mozilla_MathAlgorithms_h
10
#define mozilla_MathAlgorithms_h
11
12
#include "mozilla/Assertions.h"
13
#include "mozilla/TypeTraits.h"
14
15
#include <cmath>
16
#include <limits.h>
17
#include <stdint.h>
18
19
namespace mozilla {
20
21
// Greatest Common Divisor
22
template<typename IntegerType>
23
MOZ_ALWAYS_INLINE IntegerType
24
EuclidGCD(IntegerType aA, IntegerType aB)
25
{
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(aA > IntegerType(0));
29
  MOZ_ASSERT(aB > IntegerType(0));
30
31
  while (aA != aB) {
32
    if (aA > aB) {
33
      aA = aA - aB;
34
    } else {
35
      aB = aB - aA;
36
    }
37
  }
38
39
  return aA;
40
}
41
42
// Least Common Multiple
43
template<typename IntegerType>
44
MOZ_ALWAYS_INLINE IntegerType
45
EuclidLCM(IntegerType aA, IntegerType aB)
46
{
47
  // Divide first to reduce overflow risk.
48
  return (aA / EuclidGCD(aA, aB)) * aB;
49
}
50
51
namespace detail {
52
53
template<typename T>
54
struct AllowDeprecatedAbsFixed : FalseType {};
55
56
template<> struct AllowDeprecatedAbsFixed<int32_t> : TrueType {};
57
template<> struct AllowDeprecatedAbsFixed<int64_t> : TrueType {};
58
59
template<typename T>
60
struct AllowDeprecatedAbs : AllowDeprecatedAbsFixed<T> {};
61
62
template<> struct AllowDeprecatedAbs<int> : TrueType {};
63
template<> struct AllowDeprecatedAbs<long> : TrueType {};
64
65
} // namespace detail
66
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 aValue)
72
0
{
73
0
  // The absolute value of the smallest possible value of a signed-integer type
74
0
  // won't fit in that type (on twos-complement systems -- and we're blithely
75
0
  // assuming we're on such systems, for the non-<stdint.h> types listed above),
76
0
  // so assert that the input isn't that value.
77
0
  //
78
0
  // This is the case if: the value is non-negative; or if adding one (giving a
79
0
  // value in the range [-maxvalue, 0]), then negating (giving a value in the
80
0
  // range [0, maxvalue]), doesn't produce maxvalue (because in twos-complement,
81
0
  // (minvalue + 1) == -maxvalue).
82
0
  MOZ_ASSERT(aValue >= 0 ||
83
0
             -(aValue + 1) != T((1ULL << (CHAR_BIT * sizeof(T) - 1)) - 1),
84
0
             "You can't negate the smallest possible negative integer!");
85
0
  return aValue >= 0 ? aValue : -aValue;
86
0
}
Unexecuted instantiation: _ZN7mozilla13DeprecatedAbsIlEENS_8EnableIfIXsr6detail18AllowDeprecatedAbsIT_EE5valueES2_E4TypeES2_
Unexecuted instantiation: _ZN7mozilla13DeprecatedAbsIiEENS_8EnableIfIXsr6detail18AllowDeprecatedAbsIT_EE5valueES2_E4TypeES2_
87
88
namespace detail {
89
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.
93
94
template<typename T>
95
struct AbsReturnTypeFixed;
96
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; };
101
102
template<typename T>
103
struct AbsReturnType : AbsReturnTypeFixed<T> {};
104
105
template<> struct AbsReturnType<char> :
106
  EnableIf<char(-1) < char(0), unsigned char> {};
107
template<> struct AbsReturnType<signed char> { typedef unsigned char Type; };
108
template<> struct AbsReturnType<short> { typedef unsigned short Type; };
109
template<> struct AbsReturnType<int> { typedef unsigned int Type; };
110
template<> struct AbsReturnType<long> { typedef unsigned long Type; };
111
template<> struct AbsReturnType<long long> { typedef unsigned long long Type; };
112
template<> struct AbsReturnType<float> { typedef float Type; };
113
template<> struct AbsReturnType<double> { typedef double Type; };
114
template<> struct AbsReturnType<long double> { typedef long double Type; };
115
116
} // namespace detail
117
118
template<typename T>
119
inline constexpr typename detail::AbsReturnType<T>::Type
120
Abs(const T aValue)
121
0
{
122
0
  using ReturnType = typename detail::AbsReturnType<T>::Type;
123
0
  return aValue >= 0 ? ReturnType(aValue) : ~ReturnType(aValue) + 1;
124
0
}
125
126
template<>
127
inline float
128
Abs<float>(const float aFloat)
129
0
{
130
0
  return std::fabs(aFloat);
131
0
}
132
133
template<>
134
inline double
135
Abs<double>(const double aDouble)
136
0
{
137
0
  return std::fabs(aDouble);
138
0
}
139
140
template<>
141
inline long double
142
Abs<long double>(const long double aLongDouble)
143
0
{
144
0
  return std::fabs(aLongDouble);
145
0
}
146
147
} // namespace mozilla
148
149
#if defined(_MSC_VER) && \
150
    (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64) || defined(_M_ARM64))
151
#  define MOZ_BITSCAN_WINDOWS
152
153
#  include <intrin.h>
154
#  pragma intrinsic(_BitScanForward, _BitScanReverse)
155
156
#  if defined(_M_AMD64) || defined(_M_X64) || defined(_M_ARM64)
157
#    define MOZ_BITSCAN_WINDOWS64
158
#   pragma intrinsic(_BitScanForward64, _BitScanReverse64)
159
#  endif
160
161
#endif
162
163
namespace mozilla {
164
165
namespace detail {
166
167
#if defined(MOZ_BITSCAN_WINDOWS)
168
169
inline uint_fast8_t
170
CountLeadingZeroes32(uint32_t aValue)
171
{
172
  unsigned long index;
173
  if (!_BitScanReverse(&index, static_cast<unsigned long>(aValue)))
174
      return 32;
175
  return uint_fast8_t(31 - index);
176
}
177
178
179
inline uint_fast8_t
180
CountTrailingZeroes32(uint32_t aValue)
181
{
182
  unsigned long index;
183
  if (!_BitScanForward(&index, static_cast<unsigned long>(aValue)))
184
      return 32;
185
  return uint_fast8_t(index);
186
}
187
188
inline uint_fast8_t
189
CountPopulation32(uint32_t aValue)
190
{
191
  uint32_t x = aValue - ((aValue >> 1) & 0x55555555);
192
  x = (x & 0x33333333) + ((x >> 2) & 0x33333333);
193
  return (((x + (x >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24;
194
}
195
inline uint_fast8_t
196
CountPopulation64(uint64_t aValue)
197
{
198
  return uint_fast8_t(CountPopulation32(aValue & 0xffffffff) +
199
                      CountPopulation32(aValue >> 32));
200
}
201
202
inline uint_fast8_t
203
CountLeadingZeroes64(uint64_t aValue)
204
{
205
#if defined(MOZ_BITSCAN_WINDOWS64)
206
  unsigned long index;
207
  if (!_BitScanReverse64(&index, static_cast<unsigned __int64>(aValue)))
208
      return 64;
209
  return uint_fast8_t(63 - index);
210
#else
211
  uint32_t hi = uint32_t(aValue >> 32);
212
  if (hi != 0) {
213
    return CountLeadingZeroes32(hi);
214
  }
215
  return 32u + CountLeadingZeroes32(uint32_t(aValue));
216
#endif
217
}
218
219
inline uint_fast8_t
220
CountTrailingZeroes64(uint64_t aValue)
221
{
222
#if defined(MOZ_BITSCAN_WINDOWS64)
223
  unsigned long index;
224
  if (!_BitScanForward64(&index, static_cast<unsigned __int64>(aValue)))
225
      return 64;
226
  return uint_fast8_t(index);
227
#else
228
  uint32_t lo = uint32_t(aValue);
229
  if (lo != 0) {
230
    return CountTrailingZeroes32(lo);
231
  }
232
  return 32u + CountTrailingZeroes32(uint32_t(aValue >> 32));
233
#endif
234
}
235
236
#  ifdef MOZ_HAVE_BITSCAN64
237
#    undef MOZ_HAVE_BITSCAN64
238
#  endif
239
240
#elif defined(__clang__) || defined(__GNUC__)
241
242
#  if defined(__clang__)
243
#    if !__has_builtin(__builtin_ctz) || !__has_builtin(__builtin_clz)
244
#      error "A clang providing __builtin_c[lt]z is required to build"
245
#    endif
246
#  else
247
     // gcc has had __builtin_clz and friends since 3.4: no need to check.
248
#  endif
249
250
inline uint_fast8_t
251
CountLeadingZeroes32(uint32_t aValue)
252
{
253
  return __builtin_clz(aValue);
254
}
255
256
inline uint_fast8_t
257
CountTrailingZeroes32(uint32_t aValue)
258
{
259
  return __builtin_ctz(aValue);
260
}
261
262
inline uint_fast8_t
263
CountPopulation32(uint32_t aValue)
264
{
265
  return __builtin_popcount(aValue);
266
}
267
268
inline uint_fast8_t
269
CountPopulation64(uint64_t aValue)
270
0
{
271
0
  return __builtin_popcountll(aValue);
272
0
}
273
274
inline uint_fast8_t
275
CountLeadingZeroes64(uint64_t aValue)
276
23.4M
{
277
23.4M
  return __builtin_clzll(aValue);
278
23.4M
}
279
280
inline uint_fast8_t
281
CountTrailingZeroes64(uint64_t aValue)
282
{
283
  return __builtin_ctzll(aValue);
284
}
285
286
#else
287
#  error "Implement these!"
288
inline uint_fast8_t CountLeadingZeroes32(uint32_t aValue) = delete;
289
inline uint_fast8_t CountTrailingZeroes32(uint32_t aValue) = delete;
290
inline uint_fast8_t CountPopulation32(uint32_t aValue) = delete;
291
inline uint_fast8_t CountPopulation64(uint64_t aValue) = delete;
292
inline uint_fast8_t CountLeadingZeroes64(uint64_t aValue) = delete;
293
inline uint_fast8_t CountTrailingZeroes64(uint64_t aValue) = delete;
294
#endif
295
296
} // namespace detail
297
298
/**
299
 * Compute the number of high-order zero bits in the NON-ZERO number |aValue|.
300
 * That is, looking at the bitwise representation of the number, with the
301
 * highest- valued bits at the start, return the number of zeroes before the
302
 * first one is observed.
303
 *
304
 * CountLeadingZeroes32(0xF0FF1000) is 0;
305
 * CountLeadingZeroes32(0x7F8F0001) is 1;
306
 * CountLeadingZeroes32(0x3FFF0100) is 2;
307
 * CountLeadingZeroes32(0x1FF50010) is 3; and so on.
308
 */
309
inline uint_fast8_t
310
CountLeadingZeroes32(uint32_t aValue)
311
1.85k
{
312
1.85k
  MOZ_ASSERT(aValue != 0);
313
1.85k
  return detail::CountLeadingZeroes32(aValue);
314
1.85k
}
315
316
/**
317
 * Compute the number of low-order zero bits in the NON-ZERO number |aValue|.
318
 * That is, looking at the bitwise representation of the number, with the
319
 * lowest- valued bits at the start, return the number of zeroes before the
320
 * first one is observed.
321
 *
322
 * CountTrailingZeroes32(0x0100FFFF) is 0;
323
 * CountTrailingZeroes32(0x7000FFFE) is 1;
324
 * CountTrailingZeroes32(0x0080FFFC) is 2;
325
 * CountTrailingZeroes32(0x0080FFF8) is 3; and so on.
326
 */
327
inline uint_fast8_t
328
CountTrailingZeroes32(uint32_t aValue)
329
6.02k
{
330
6.02k
  MOZ_ASSERT(aValue != 0);
331
6.02k
  return detail::CountTrailingZeroes32(aValue);
332
6.02k
}
333
334
/**
335
 * Compute the number of one bits in the number |aValue|,
336
 */
337
inline uint_fast8_t
338
CountPopulation32(uint32_t aValue)
339
{
340
  return detail::CountPopulation32(aValue);
341
}
342
343
/** Analogous to CountPopulation32, but for 64-bit numbers */
344
inline uint_fast8_t
345
CountPopulation64(uint64_t aValue)
346
0
{
347
0
  return detail::CountPopulation64(aValue);
348
0
}
349
350
/** Analogous to CountLeadingZeroes32, but for 64-bit numbers. */
351
inline uint_fast8_t
352
CountLeadingZeroes64(uint64_t aValue)
353
2.35k
{
354
2.35k
  MOZ_ASSERT(aValue != 0);
355
2.35k
  return detail::CountLeadingZeroes64(aValue);
356
2.35k
}
357
358
/** Analogous to CountTrailingZeroes32, but for 64-bit numbers. */
359
inline uint_fast8_t
360
CountTrailingZeroes64(uint64_t aValue)
361
10.7k
{
362
10.7k
  MOZ_ASSERT(aValue != 0);
363
10.7k
  return detail::CountTrailingZeroes64(aValue);
364
10.7k
}
365
366
namespace detail {
367
368
template<typename T, size_t Size = sizeof(T)>
369
class CeilingLog2;
370
371
template<typename T>
372
class CeilingLog2<T, 4>
373
{
374
public:
375
  static uint_fast8_t compute(const T aValue)
376
3.75k
  {
377
3.75k
    // Check for <= 1 to avoid the == 0 undefined case.
378
3.75k
    return aValue <= 1 ? 0u : 32u - CountLeadingZeroes32(aValue - 1);
379
3.75k
  }
380
};
381
382
template<typename T>
383
class CeilingLog2<T, 8>
384
{
385
public:
386
  static uint_fast8_t compute(const T aValue)
387
23.4M
  {
388
23.4M
    // Check for <= 1 to avoid the == 0 undefined case.
389
23.4M
    return aValue <= 1 ? 0u : 64u - CountLeadingZeroes64(aValue - 1);
390
23.4M
  }
391
};
392
393
} // namespace detail
394
395
/**
396
 * Compute the log of the least power of 2 greater than or equal to |aValue|.
397
 *
398
 * CeilingLog2(0..1) is 0;
399
 * CeilingLog2(2) is 1;
400
 * CeilingLog2(3..4) is 2;
401
 * CeilingLog2(5..8) is 3;
402
 * CeilingLog2(9..16) is 4; and so on.
403
 */
404
template<typename T>
405
inline uint_fast8_t
406
CeilingLog2(const T aValue)
407
23.4M
{
408
23.4M
  return detail::CeilingLog2<T>::compute(aValue);
409
23.4M
}
unsigned char mozilla::CeilingLog2<unsigned long>(unsigned long)
Line
Count
Source
407
23.4M
{
408
23.4M
  return detail::CeilingLog2<T>::compute(aValue);
409
23.4M
}
unsigned char mozilla::CeilingLog2<unsigned int>(unsigned int)
Line
Count
Source
407
3.75k
{
408
3.75k
  return detail::CeilingLog2<T>::compute(aValue);
409
3.75k
}
410
411
/** A CeilingLog2 variant that accepts only size_t. */
412
inline uint_fast8_t
413
CeilingLog2Size(size_t aValue)
414
{
415
  return CeilingLog2(aValue);
416
}
417
418
namespace detail {
419
420
template<typename T, size_t Size = sizeof(T)>
421
class FloorLog2;
422
423
template<typename T>
424
class FloorLog2<T, 4>
425
{
426
public:
427
  static uint_fast8_t compute(const T aValue)
428
280
  {
429
280
    return 31u - CountLeadingZeroes32(aValue | 1);
430
280
  }
mozilla::detail::FloorLog2<unsigned int, 4ul>::compute(unsigned int)
Line
Count
Source
428
280
  {
429
280
    return 31u - CountLeadingZeroes32(aValue | 1);
430
280
  }
Unexecuted instantiation: mozilla::detail::FloorLog2<int, 4ul>::compute(int)
Unexecuted instantiation: mozilla::detail::FloorLog2<JSFunction::Flags, 4ul>::compute(JSFunction::Flags)
431
};
432
433
template<typename T>
434
class FloorLog2<T, 8>
435
{
436
public:
437
  static uint_fast8_t compute(const T aValue)
438
0
  {
439
0
    return 63u - CountLeadingZeroes64(aValue | 1);
440
0
  }
Unexecuted instantiation: mozilla::detail::FloorLog2<unsigned long, 8ul>::compute(unsigned long)
Unexecuted instantiation: mozilla::detail::FloorLog2<long, 8ul>::compute(long)
441
};
442
443
} // namespace detail
444
445
/**
446
 * Compute the log of the greatest power of 2 less than or equal to |aValue|.
447
 *
448
 * FloorLog2(0..1) is 0;
449
 * FloorLog2(2..3) is 1;
450
 * FloorLog2(4..7) is 2;
451
 * FloorLog2(8..15) is 3; and so on.
452
 */
453
template<typename T>
454
inline uint_fast8_t
455
FloorLog2(const T aValue)
456
280
{
457
280
  return detail::FloorLog2<T>::compute(aValue);
458
280
}
Unexecuted instantiation: unsigned char mozilla::FloorLog2<unsigned long>(unsigned long)
unsigned char mozilla::FloorLog2<unsigned int>(unsigned int)
Line
Count
Source
456
280
{
457
280
  return detail::FloorLog2<T>::compute(aValue);
458
280
}
Unexecuted instantiation: unsigned char mozilla::FloorLog2<int>(int)
Unexecuted instantiation: unsigned char mozilla::FloorLog2<JSFunction::Flags>(JSFunction::Flags)
Unexecuted instantiation: unsigned char mozilla::FloorLog2<long>(long)
459
460
/** A FloorLog2 variant that accepts only size_t. */
461
inline uint_fast8_t
462
FloorLog2Size(size_t aValue)
463
0
{
464
0
  return FloorLog2(aValue);
465
0
}
466
467
/*
468
 * Compute the smallest power of 2 greater than or equal to |x|.  |x| must not
469
 * be so great that the computed value would overflow |size_t|.
470
 */
471
inline size_t
472
RoundUpPow2(size_t aValue)
473
23.4M
{
474
23.4M
  MOZ_ASSERT(aValue <= (size_t(1) << (sizeof(size_t) * CHAR_BIT - 1)),
475
23.4M
             "can't round up -- will overflow!");
476
23.4M
  return size_t(1) << CeilingLog2(aValue);
477
23.4M
}
478
479
/**
480
 * Rotates the bits of the given value left by the amount of the shift width.
481
 */
482
template<typename T>
483
MOZ_NO_SANITIZE_UNSIGNED_OVERFLOW
484
inline T
485
RotateLeft(const T aValue, uint_fast8_t aShift)
486
54
{
487
54
  static_assert(IsUnsigned<T>::value, "Rotates require unsigned values");
488
54
489
54
  MOZ_ASSERT(aShift < sizeof(T) * CHAR_BIT, "Shift value is too large!");
490
54
  MOZ_ASSERT(aShift > 0,
491
54
             "Rotation by value length is undefined behavior, but compilers "
492
54
             "do not currently fold a test into the rotate instruction. "
493
54
             "Please remove this restriction when compilers optimize the "
494
54
             "zero case (http://blog.regehr.org/archives/1063).");
495
54
496
54
  return (aValue << aShift) | (aValue >> (sizeof(T) * CHAR_BIT - aShift));
497
54
}
Unexecuted instantiation: unsigned long mozilla::RotateLeft<unsigned long>(unsigned long, unsigned char)
Unexecuted instantiation: unsigned long mozilla::RotateLeft<unsigned long>(unsigned long, unsigned char)
unsigned int mozilla::RotateLeft<unsigned int>(unsigned int, unsigned char)
Line
Count
Source
486
54
{
487
54
  static_assert(IsUnsigned<T>::value, "Rotates require unsigned values");
488
54
489
54
  MOZ_ASSERT(aShift < sizeof(T) * CHAR_BIT, "Shift value is too large!");
490
54
  MOZ_ASSERT(aShift > 0,
491
54
             "Rotation by value length is undefined behavior, but compilers "
492
54
             "do not currently fold a test into the rotate instruction. "
493
54
             "Please remove this restriction when compilers optimize the "
494
54
             "zero case (http://blog.regehr.org/archives/1063).");
495
54
496
54
  return (aValue << aShift) | (aValue >> (sizeof(T) * CHAR_BIT - aShift));
497
54
}
498
499
/**
500
 * Rotates the bits of the given value right by the amount of the shift width.
501
 */
502
template<typename T>
503
MOZ_NO_SANITIZE_UNSIGNED_OVERFLOW
504
inline T
505
RotateRight(const T aValue, uint_fast8_t aShift)
506
{
507
  static_assert(IsUnsigned<T>::value, "Rotates require unsigned values");
508
509
  MOZ_ASSERT(aShift < sizeof(T) * CHAR_BIT, "Shift value is too large!");
510
  MOZ_ASSERT(aShift > 0,
511
             "Rotation by value length is undefined behavior, but compilers "
512
             "do not currently fold a test into the rotate instruction. "
513
             "Please remove this restriction when compilers optimize the "
514
             "zero case (http://blog.regehr.org/archives/1063).");
515
516
  return (aValue >> aShift) | (aValue << (sizeof(T) * CHAR_BIT - aShift));
517
}
518
519
/**
520
 * Returns true if |x| is a power of two.
521
 * Zero is not an integer power of two. (-Inf is not an integer)
522
 */
523
template<typename T>
524
constexpr bool
525
IsPowerOfTwo(T x)
526
0
{
527
0
    static_assert(IsUnsigned<T>::value,
528
0
                  "IsPowerOfTwo requires unsigned values");
529
0
    return x && (x & (x - 1)) == 0;
530
0
}
Unexecuted instantiation: bool mozilla::IsPowerOfTwo<unsigned int>(unsigned int)
Unexecuted instantiation: bool mozilla::IsPowerOfTwo<unsigned long>(unsigned long)
531
532
template<typename T>
533
inline T
534
Clamp(const T aValue, const T aMin, const T aMax)
535
0
{
536
0
    static_assert(IsIntegral<T>::value,
537
0
                  "Clamp accepts only integral types, so that it doesn't have"
538
0
                  " to distinguish differently-signed zeroes (which users may"
539
0
                  " or may not care to distinguish, likely at a perf cost) or"
540
0
                  " to decide how to clamp NaN or a range with a NaN"
541
0
                  " endpoint.");
542
0
    MOZ_ASSERT(aMin <= aMax);
543
0
544
0
    if (aValue <= aMin)
545
0
        return aMin;
546
0
    if (aValue >= aMax)
547
0
        return aMax;
548
0
    return aValue;
549
0
}
Unexecuted instantiation: unsigned int mozilla::Clamp<unsigned int>(unsigned int, unsigned int, unsigned int)
Unexecuted instantiation: int mozilla::Clamp<int>(int, int, int)
550
551
} /* namespace mozilla */
552
553
#endif /* mozilla_MathAlgorithms_h */