Bug 1193600 - Add Clamp and IsPowerOfTwo to MFBT. - r=waldo
authorJeff Gilbert <jgilbert@mozilla.com>
Fri, 04 Sep 2015 13:33:10 -0700
changeset 261046 dff32fe11db99341fa0f1fb95ab04feee3dc112e
parent 261045 065f00e9b2fde1b7f0811687bd5994c9add07f69
child 261047 a677282b7646114eaa0493834b83eb74801b3f0e
push id29333
push userphilringnalda@gmail.com
push dateSun, 06 Sep 2015 03:20:00 +0000
treeherdermozilla-central@56f5ffd44b7f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerswaldo
bugs1193600
milestone43.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
Bug 1193600 - Add Clamp and IsPowerOfTwo to MFBT. - r=waldo
mfbt/MathAlgorithms.h
mfbt/tests/TestMathAlgorithms.cpp
mfbt/tests/moz.build
--- 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',