Adding ffs and 64-bit prev/next pow2

Change-Id: Ie10731c16b65a4fd1f36fd4c9bbca9a6951583a1
This commit is contained in:
Chodor, Jaroslaw
2019-01-28 17:51:00 +01:00
committed by sys_ocldev
parent b11e0825c9
commit 22448ee265
4 changed files with 80 additions and 20 deletions

2
Jenkinsfile vendored
View File

@@ -1,5 +1,5 @@
#!groovy
dependenciesRevision='36a2a0d6a9da5e506439ffcb8dcf49d3e8f0e175-1185'
strategy='EQUAL'
allowedCD=272
allowedCD=270
allowedF=4

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017-2018 Intel Corporation
* Copyright (C) 2017-2019 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -20,7 +20,7 @@
namespace OCLRT {
namespace Math {
inline uint32_t nextPowerOfTwo(uint32_t value) {
constexpr uint32_t nextPowerOfTwo(uint32_t value) {
--value;
value |= value >> 1;
value |= value >> 2;
@@ -31,12 +31,34 @@ inline uint32_t nextPowerOfTwo(uint32_t value) {
return value;
}
inline uint32_t prevPowerOfTwo(uint32_t value) {
constexpr uint64_t nextPowerOfTwo(uint64_t value) {
--value;
value |= value >> 1;
value |= value >> 2;
value |= value >> 4;
value |= value >> 8;
value |= value >> 16;
value |= value >> 32;
++value;
return value;
}
constexpr uint32_t prevPowerOfTwo(uint32_t value) {
value |= value >> 1;
value |= value >> 2;
value |= value >> 4;
value |= value >> 8;
value |= value >> 16;
return (value - (value >> 1));
}
constexpr uint64_t prevPowerOfTwo(uint64_t value) {
value |= value >> 1;
value |= value >> 2;
value |= value >> 4;
value |= value >> 8;
value |= value >> 16;
value |= value >> 32;
return (value - (value >> 1));
}
@@ -49,7 +71,7 @@ inline uint32_t getMinLsbSet(uint32_t value) {
return multiplyDeBruijnBitPosition[static_cast<uint32_t>(value * 0x077CB531U) >> 27];
}
inline uint32_t log2(uint32_t value) {
constexpr uint32_t log2(uint32_t value) {
uint32_t exponent = 0u;
uint32_t startVal = value;
if (value == 0) {
@@ -65,7 +87,7 @@ inline uint32_t log2(uint32_t value) {
return exponent;
}
inline uint64_t log2(uint64_t value) {
constexpr uint64_t log2(uint64_t value) {
uint64_t exponent = 0;
uint64_t startVal = value;
if (value == 0) {
@@ -141,7 +163,7 @@ inline bool isDivisableByPowerOfTwoDivisor(uint32_t number, uint32_t divisor) {
return false;
}
inline size_t computeTotalElementsCount(const Vec3<size_t> &inputVector) {
constexpr size_t computeTotalElementsCount(const Vec3<size_t> &inputVector) {
size_t minElementCount = 1;
auto xDim = std::max(minElementCount, inputVector.x);
auto yDim = std::max(minElementCount, inputVector.y);
@@ -150,7 +172,7 @@ inline size_t computeTotalElementsCount(const Vec3<size_t> &inputVector) {
}
template <typename T>
bool isPow2(T val) {
constexpr bool isPow2(T val) {
if (val != 0) {
if ((val & (val - 1)) == 0) {
return true;
@@ -159,5 +181,20 @@ bool isPow2(T val) {
return false;
}
template <typename T>
constexpr T ffs(T v) {
if (v == 0) {
return std::numeric_limits<T>::max();
}
for (T i = 0; i < sizeof(T) * 8; ++i) {
if (0 != (v & (1ULL << i))) {
return i;
}
}
UNREACHABLE("Either v==0 or any of bits is set");
}
} // namespace Math
} // namespace OCLRT

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017-2018 Intel Corporation
* Copyright (C) 2017-2019 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -14,6 +14,8 @@
OCLRT::abortUnrecoverable(__LINE__, __FILE__); \
}
#define UNREACHABLE(...) std::abort()
#ifndef DEBUG_BREAK_IF
#ifdef _DEBUG
#define DEBUG_BREAK_IF(expression) \

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017-2018 Intel Corporation
* Copyright (C) 2017-2019 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -12,19 +12,22 @@ using namespace OCLRT::Math;
using namespace OCLRT;
TEST(NextPowerOfTwo, aFewCases) {
EXPECT_EQ(1u, nextPowerOfTwo(1));
EXPECT_EQ(2u, nextPowerOfTwo(2));
EXPECT_EQ(4u, nextPowerOfTwo(3));
EXPECT_EQ(32u, nextPowerOfTwo(31));
EXPECT_EQ(32u, nextPowerOfTwo(32));
EXPECT_EQ(64u, nextPowerOfTwo(33));
EXPECT_EQ(1u << 31, nextPowerOfTwo((1u << 30) + 1));
EXPECT_EQ(1u << 31, nextPowerOfTwo(1u << 31));
EXPECT_EQ(1u, nextPowerOfTwo(1U));
EXPECT_EQ(2u, nextPowerOfTwo(2U));
EXPECT_EQ(4u, nextPowerOfTwo(3U));
EXPECT_EQ(32u, nextPowerOfTwo(31U));
EXPECT_EQ(32u, nextPowerOfTwo(32U));
EXPECT_EQ(64u, nextPowerOfTwo(33U));
EXPECT_EQ(1u << 31, nextPowerOfTwo((1u << 30U) + 1));
EXPECT_EQ(1u << 31, nextPowerOfTwo(1u << 31U));
EXPECT_EQ(1ULL << 32, nextPowerOfTwo(static_cast<uint64_t>((1ULL << 31ULL) + 1)));
EXPECT_EQ(1ULL << 32, nextPowerOfTwo(static_cast<uint64_t>(1ULL << 32ULL)));
}
TEST(PrevPowerOfTwo, aroundPowers) {
EXPECT_EQ(0u, prevPowerOfTwo(0));
EXPECT_EQ(1u, prevPowerOfTwo(1));
EXPECT_EQ(0u, prevPowerOfTwo(0U));
EXPECT_EQ(1u, prevPowerOfTwo(1U));
for (uint32_t i = 1; i < 32; i++) {
uint32_t b = 1 << i;
@@ -32,6 +35,9 @@ TEST(PrevPowerOfTwo, aroundPowers) {
EXPECT_EQ(b, prevPowerOfTwo(b));
EXPECT_EQ(b, prevPowerOfTwo(b + 1));
}
EXPECT_EQ(1ULL << 32, prevPowerOfTwo(static_cast<uint64_t>(1ULL << 32ULL)));
EXPECT_EQ(1ULL << 32, prevPowerOfTwo(static_cast<uint64_t>((1ULL << 32ULL) + 7)));
}
TEST(getMinLsbSet, basicValues) {
@@ -193,3 +199,18 @@ TEST(isPow2Test, WhenArgPow2ThenReturnTrue) {
EXPECT_TRUE(isPow2(128u));
EXPECT_TRUE(isPow2(4096u));
}
TEST(ffs, givenZeroReturnMaxRange) {
EXPECT_EQ(std::numeric_limits<uint32_t>::max(), ffs(0U));
}
TEST(ffs, givenNonZeroReturnFirstSetBitIndex) {
EXPECT_EQ(0U, ffs(0b1U));
EXPECT_EQ(0U, ffs(0b11U));
EXPECT_EQ(1U, ffs(0b10U));
EXPECT_EQ(3U, ffs(0b1001000U));
EXPECT_EQ(31U, ffs(1U << 31U));
EXPECT_EQ(16U, ffs((1U << 31U) | (1U << 31U) | (1U << 16U)));
EXPECT_EQ(16ULL, ffs((1ULL << 63ULL) | (1ULL << 32ULL) | (1ULL << 16ULL)));
EXPECT_EQ(63ULL, ffs(1ULL << 63ULL));
}