author | Jeff Gilbert <jgilbert@mozilla.com> |
Fri, 04 Sep 2015 13:33:10 -0700 | |
changeset 261046 | dff32fe11db99341fa0f1fb95ab04feee3dc112e |
parent 261045 | 065f00e9b2fde1b7f0811687bd5994c9add07f69 |
child 261047 | a677282b7646114eaa0493834b83eb74801b3f0e |
push id | 29333 |
push user | philringnalda@gmail.com |
push date | Sun, 06 Sep 2015 03:20:00 +0000 |
treeherder | mozilla-central@56f5ffd44b7f [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | waldo |
bugs | 1193600 |
milestone | 43.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/mfbt/MathAlgorithms.h +++ b/mfbt/MathAlgorithms.h @@ -495,11 +495,43 @@ template<typename T> inline T RotateRight(const T aValue, uint_fast8_t aShift) { MOZ_ASSERT(aShift < sizeof(T) * CHAR_BIT, "Shift value is too large!"); static_assert(IsUnsigned<T>::value, "Rotates require unsigned values"); return (aValue >> aShift) | (aValue << (sizeof(T) * CHAR_BIT - aShift)); } +/** + * Returns true if |x| is a power of two. + * Zero is not an integer power of two. (-Inf is not an integer) + */ +template<typename T> +inline bool +IsPowerOfTwo(T x) +{ + static_assert(IsUnsigned<T>::value, + "IsPowerOfTwo requires unsigned values"); + return x && (x & (x - 1)) == 0; +} + +template<typename T> +inline T +Clamp(const T aValue, const T aMin, const T aMax) +{ + static_assert(IsIntegral<T>::value, + "Clamp accepts only integral types, so that it doesn't have" + " to distinguish differently-signed zeroes (which users may" + " or may not care to distinguish, likely at a perf cost) or" + " to decide how to clamp NaN or a range with a NaN" + " endpoint."); + MOZ_ASSERT(aMin <= aMax); + + if (aValue <= aMin) + return aMin; + if (aValue >= aMax) + return aMax; + return aValue; +} + } /* namespace mozilla */ #endif /* mozilla_MathAlgorithms_h */
new file mode 100644 --- /dev/null +++ b/mfbt/tests/TestMathAlgorithms.cpp @@ -0,0 +1,87 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/MathAlgorithms.h" + +using mozilla::Clamp; +using mozilla::IsPowerOfTwo; + +static void +TestClamp() +{ + MOZ_RELEASE_ASSERT(Clamp(0, 0, 0) == 0); + MOZ_RELEASE_ASSERT(Clamp(1, 0, 0) == 0); + MOZ_RELEASE_ASSERT(Clamp(-1, 0, 0) == 0); + + MOZ_RELEASE_ASSERT(Clamp(0, 1, 1) == 1); + MOZ_RELEASE_ASSERT(Clamp(0, 1, 2) == 1); + + MOZ_RELEASE_ASSERT(Clamp(0, -1, -1) == -1); + MOZ_RELEASE_ASSERT(Clamp(0, -2, -1) == -1); + + MOZ_RELEASE_ASSERT(Clamp(0, 1, 3) == 1); + MOZ_RELEASE_ASSERT(Clamp(1, 1, 3) == 1); + MOZ_RELEASE_ASSERT(Clamp(2, 1, 3) == 2); + MOZ_RELEASE_ASSERT(Clamp(3, 1, 3) == 3); + MOZ_RELEASE_ASSERT(Clamp(4, 1, 3) == 3); + MOZ_RELEASE_ASSERT(Clamp(5, 1, 3) == 3); + + MOZ_RELEASE_ASSERT(Clamp<uint8_t>(UINT8_MAX, 0, UINT8_MAX) == UINT8_MAX); + MOZ_RELEASE_ASSERT(Clamp<uint8_t>(0, 0, UINT8_MAX) == 0); + + MOZ_RELEASE_ASSERT(Clamp<int8_t>(INT8_MIN, INT8_MIN, INT8_MAX) == INT8_MIN); + MOZ_RELEASE_ASSERT(Clamp<int8_t>(INT8_MIN, 0, INT8_MAX) == 0); + MOZ_RELEASE_ASSERT(Clamp<int8_t>(INT8_MAX, INT8_MIN, INT8_MAX) == INT8_MAX); + MOZ_RELEASE_ASSERT(Clamp<int8_t>(INT8_MAX, INT8_MIN, 0) == 0); +} + +static void +TestIsPowerOfTwo() +{ + MOZ_RELEASE_ASSERT(!IsPowerOfTwo(0u)); + MOZ_RELEASE_ASSERT( IsPowerOfTwo(1u)); + MOZ_RELEASE_ASSERT( IsPowerOfTwo(2u)); + MOZ_RELEASE_ASSERT(!IsPowerOfTwo(3u)); + MOZ_RELEASE_ASSERT( IsPowerOfTwo(4u)); + MOZ_RELEASE_ASSERT(!IsPowerOfTwo(5u)); + MOZ_RELEASE_ASSERT(!IsPowerOfTwo(6u)); + MOZ_RELEASE_ASSERT(!IsPowerOfTwo(7u)); + MOZ_RELEASE_ASSERT( IsPowerOfTwo(8u)); + MOZ_RELEASE_ASSERT(!IsPowerOfTwo(9u)); + + MOZ_RELEASE_ASSERT(!IsPowerOfTwo(uint8_t(UINT8_MAX/2))); // 127, 0x7f + MOZ_RELEASE_ASSERT( IsPowerOfTwo(uint8_t(UINT8_MAX/2 + 1))); // 128, 0x80 + MOZ_RELEASE_ASSERT(!IsPowerOfTwo(uint8_t(UINT8_MAX/2 + 2))); // 129, 0x81 + MOZ_RELEASE_ASSERT(!IsPowerOfTwo(uint8_t(UINT8_MAX - 1))); // 254, 0xfe + MOZ_RELEASE_ASSERT(!IsPowerOfTwo(uint8_t(UINT8_MAX))); // 255, 0xff + + MOZ_RELEASE_ASSERT(!IsPowerOfTwo(uint16_t(UINT16_MAX/2))); // 0x7fff + MOZ_RELEASE_ASSERT( IsPowerOfTwo(uint16_t(UINT16_MAX/2 + 1))); // 0x8000 + MOZ_RELEASE_ASSERT(!IsPowerOfTwo(uint16_t(UINT16_MAX/2 + 2))); // 0x8001 + MOZ_RELEASE_ASSERT(!IsPowerOfTwo(uint16_t(UINT16_MAX - 1))); // 0xfffe + MOZ_RELEASE_ASSERT(!IsPowerOfTwo(uint16_t(UINT16_MAX))); // 0xffff + + MOZ_RELEASE_ASSERT(!IsPowerOfTwo(uint32_t(UINT32_MAX/2))); + MOZ_RELEASE_ASSERT( IsPowerOfTwo(uint32_t(UINT32_MAX/2 + 1))); + MOZ_RELEASE_ASSERT(!IsPowerOfTwo(uint32_t(UINT32_MAX/2 + 2))); + MOZ_RELEASE_ASSERT(!IsPowerOfTwo(uint32_t(UINT32_MAX - 1))); + MOZ_RELEASE_ASSERT(!IsPowerOfTwo(uint32_t(UINT32_MAX))); + + MOZ_RELEASE_ASSERT(!IsPowerOfTwo(uint64_t(UINT64_MAX/2))); + MOZ_RELEASE_ASSERT( IsPowerOfTwo(uint64_t(UINT64_MAX/2 + 1))); + MOZ_RELEASE_ASSERT(!IsPowerOfTwo(uint64_t(UINT64_MAX/2 + 2))); + MOZ_RELEASE_ASSERT(!IsPowerOfTwo(uint64_t(UINT64_MAX - 1))); + MOZ_RELEASE_ASSERT(!IsPowerOfTwo(uint64_t(UINT64_MAX))); +} + +int +main() +{ + TestIsPowerOfTwo(); + TestClamp(); + + return 0; +}
--- a/mfbt/tests/moz.build +++ b/mfbt/tests/moz.build @@ -17,16 +17,17 @@ CppUnitTests([ 'TestEndian', 'TestEnumSet', 'TestFloatingPoint', 'TestIntegerPrintfMacros', 'TestIntegerRange', 'TestJSONWriter', 'TestMacroArgs', 'TestMacroForEach', + 'TestMathAlgorithms', 'TestMaybe', 'TestPair', 'TestRefPtr', 'TestRollingMean', 'TestScopeExit', 'TestSegmentedVector', 'TestSHA1', 'TestSplayTree',