Add deCtz32() to deInt32.h
authorPyry Haulos <phaulos@google.com>
Wed, 30 Sep 2015 17:56:36 +0000 (10:56 -0700)
committerPyry Haulos <phaulos@google.com>
Wed, 30 Sep 2015 17:56:36 +0000 (10:56 -0700)
deCtz32() computes number of trailing zeros.

Change-Id: I44707d92696af927d7464b75be789571338be479

framework/delibs/debase/deInt32.c
framework/delibs/debase/deInt32.h
framework/delibs/debase/deInt32Test.c

index 6905108..80dd150 100644 (file)
@@ -45,6 +45,26 @@ const deInt8 g_clzLUT[256] =
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 };
 
+const deInt8 g_ctzLUT[256] =
+{
+       8, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+       4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+       5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+       4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+       6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+       4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+       5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+       4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+       7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+       4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+       5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+       4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+       6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+       4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+       5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
+       4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
+};
+
 /*--------------------------------------------------------------------*//*!
  * \brief Compute the reciprocal of an integer.
  * \param a            Input value.
index 6e574e5..c1b4887 100644 (file)
@@ -254,13 +254,13 @@ DE_INLINE void* deAlignPtr (void* ptr, deUintptr align)
        return (void*)((val + align - 1) & ~(align - 1));
 }
 
+extern const deInt8 g_clzLUT[256];
+
 /*--------------------------------------------------------------------*//*!
  * \brief Compute number of leading zeros in an integer.
  * \param a    Input value.
  * \return The number of leading zero bits in the input.
  *//*--------------------------------------------------------------------*/
-extern const deInt8 g_clzLUT[256];
-
 DE_INLINE int deClz32 (deUint32 a)
 {
 #if (DE_COMPILER == DE_COMPILER_MSC)
@@ -285,6 +285,37 @@ DE_INLINE int deClz32 (deUint32 a)
 #endif
 }
 
+extern const deInt8 g_ctzLUT[256];
+
+/*--------------------------------------------------------------------*//*!
+ * \brief Compute number of trailing zeros in an integer.
+ * \param a    Input value.
+ * \return The number of trailing zero bits in the input.
+ *//*--------------------------------------------------------------------*/
+DE_INLINE int deCtz32 (deUint32 a)
+{
+#if (DE_COMPILER == DE_COMPILER_MSC)
+       unsigned long i;
+       if (_BitScanForward(&i, (unsigned long)a) == 0)
+               return 32;
+       else
+               return i;
+#elif (DE_COMPILER == DE_COMPILER_GCC) || (DE_COMPILER == DE_COMPILER_CLANG)
+       if (a == 0)
+               return 32;
+       else
+               return __builtin_ctz((unsigned int)a);
+#else
+       if ((a & 0x00FFFFFFu) == 0)
+               return (int)g_ctzLUT[a >> 24] + 24;
+       if ((a & 0x0000FFFFu) == 0)
+               return (int)g_ctzLUT[(a >> 16) & 0xffu] + 16;
+       if ((a & 0x000000FFu) == 0)
+               return (int)g_ctzLUT[(a >> 8) & 0xffu] + 8;
+       return (int)g_ctzLUT[a & 0xffu];
+#endif
+}
+
 /*--------------------------------------------------------------------*//*!
  * \brief Compute integer 'floor' of 'log2' for a positive integer.
  * \param a    Input value.
index 9d3d29a..d87aee7 100644 (file)
@@ -76,6 +76,15 @@ void deInt32_selfTest (void)
        deRandom_init(&rnd, 0xdeadbeefu-1);
 
        /* Test deClz32(). */
+       {
+               int i;
+               for (i = 0; i < 32; i++)
+               {
+                       DE_TEST_ASSERT(deClz32(1u << i) == 31-i);
+                       DE_TEST_ASSERT(deClz32((1u << i) | ((1u << i)-1u)) == 31-i);
+               }
+       }
+
        DE_TEST_ASSERT(deClz32(0) == 32);
        DE_TEST_ASSERT(deClz32(1) == 31);
        DE_TEST_ASSERT(deClz32(0xF1) == 24);
@@ -86,6 +95,22 @@ void deInt32_selfTest (void)
        DE_TEST_ASSERT(deClz32(0x40000000) == 1);
        DE_TEST_ASSERT(deClz32(0x80000000) == 0);
 
+       /* Test deCtz32(). */
+       {
+               int i;
+               for (i = 0; i < 32; i++)
+               {
+                       DE_TEST_ASSERT(deCtz32(1u << i) == i);
+                       DE_TEST_ASSERT(deCtz32(~((1u << i)-1u)) == i);
+               }
+       }
+
+       DE_TEST_ASSERT(deCtz32(0) == 32);
+       DE_TEST_ASSERT(deCtz32(1) == 0);
+       DE_TEST_ASSERT(deCtz32(0x3F4) == 2);
+       DE_TEST_ASSERT(deCtz32(0x3F40) == 6);
+       DE_TEST_ASSERT(deCtz32(0xFFFFFFFF) == 0);
+
        /* Test simple inputs for dePop32(). */
        DE_TEST_ASSERT(dePop32(0u) == 0);
        DE_TEST_ASSERT(dePop32(~0u) == 32);