diff --git a/src/base/intmath.hh b/src/base/intmath.hh index acf7681af8..ba2017782a 100644 --- a/src/base/intmath.hh +++ b/src/base/intmath.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2021 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2001, 2003-2005 The Regents of The University of Michigan * All rights reserved. * @@ -33,6 +45,7 @@ #include #include +#include "base/bitfield.hh" #include "base/logging.hh" #include "base/types.hh" @@ -154,4 +167,19 @@ roundDown(const T& val, const U& align) return val & ~mask; } +/** + * Calculate the log2 of a power of 2 integer + * + * @param An input value + * @return The base 2 log of value + * + * @ingroup api_base_utils + */ +inline int +log2i(int value) +{ + assert(isPowerOf2(value) && value > 0); + return ctz32(value); +} + #endif // __BASE_INTMATH_HH__ diff --git a/src/base/intmath.test.cc b/src/base/intmath.test.cc index e985a1b5d7..e953a7e735 100644 --- a/src/base/intmath.test.cc +++ b/src/base/intmath.test.cc @@ -1,4 +1,15 @@ /* + * Copyright (c) 2021 ARM Limited + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2019 The Regents of the University of California * All rights reserved * @@ -123,3 +134,47 @@ TEST(IntmathTest, roundDown) EXPECT_EQ(4096, roundDown(4101, 16)); EXPECT_EQ(7936, roundDown(7991, 256)); } + +/** This is testing if log2i actually works. + * at every iteration value is multiplied by 2 (left shift) and expected + * is incremented by one. This until value reaches becomes negative (by + * left shifting) which is when expected points to the MSB + */ +TEST(IntmathTest, Log2i) +{ + int expected = 0; + for (int value = 1; value > 0; expected++, value <<= 1) { + EXPECT_EQ(expected, log2i(value)); + } + + // Just as a sanity check for expected to point to the MSB + EXPECT_EQ(expected, sizeof(int) * 8 - 1); +} + +/** This is testing the assertions: what if invalid arguments are + * provided to log2i: + * + * 1) value = 0 + * 2) value < 0 + * 3) value is not a power of 2 + */ +TEST(IntmathDeathTest, Log2iDeath) +{ + // 1) value = 0 + EXPECT_DEATH({ + const int value = 0; + log2i(value); + }, "value > 0.*failed"); + + // 2) value < 0 + EXPECT_DEATH({ + const int value = -1; + log2i(value); + }, "value > 0.*failed"); + + // 3) value is not a power of 2 + EXPECT_DEATH({ + const int value = 5; + log2i(value); + }, "isPowerOf2"); +}