summaryrefslogtreecommitdiff
path: root/asl/base
diff options
context:
space:
mode:
Diffstat (limited to 'asl/base')
-rw-r--r--asl/base/bit_tests.cpp4
-rw-r--r--asl/base/meta.hpp20
-rw-r--r--asl/base/numeric.hpp17
-rw-r--r--asl/base/numeric_tests.cpp52
4 files changed, 86 insertions, 7 deletions
diff --git a/asl/base/bit_tests.cpp b/asl/base/bit_tests.cpp
index fa05fab..972bc72 100644
--- a/asl/base/bit_tests.cpp
+++ b/asl/base/bit_tests.cpp
@@ -39,6 +39,10 @@ ASL_TEST(popcount) // NOLINT(*-cognitive-complexity)
ASL_TEST(countr_zero)
{
ASL_TEST_EXPECT(asl::countr_zero(uint8_t{0}) == 8);
+ ASL_TEST_EXPECT(asl::countr_zero(uint8_t{1}) == 0);
+ ASL_TEST_EXPECT(asl::countr_zero(uint8_t{2}) == 1);
+ ASL_TEST_EXPECT(asl::countr_zero(uint8_t{4}) == 2);
+ ASL_TEST_EXPECT(asl::countr_zero(uint8_t{8}) == 3);
ASL_TEST_EXPECT(asl::countr_zero(uint8_t{255}) == 0);
ASL_TEST_EXPECT(asl::countr_zero(uint8_t{0b00011100}) == 2);
ASL_TEST_EXPECT(asl::countr_zero(uint8_t{0b10101010}) == 1);
diff --git a/asl/base/meta.hpp b/asl/base/meta.hpp
index e050e69..b17d761 100644
--- a/asl/base/meta.hpp
+++ b/asl/base/meta.hpp
@@ -249,28 +249,32 @@ template<> struct _integer_traits<uint8_t>
{
static constexpr bool kSigned = false;
static constexpr bool kUnsigned = true;
- using as_signed = int8_t;
+ using as_signed = int8_t;
+ using as_unsigned = uint8_t;
};
template<> struct _integer_traits<uint16_t>
{
static constexpr bool kSigned = false;
static constexpr bool kUnsigned = true;
- using as_signed = int16_t;
+ using as_signed = int16_t;
+ using as_unsigned = uint16_t;
};
template<> struct _integer_traits<uint32_t>
{
static constexpr bool kSigned = false;
static constexpr bool kUnsigned = true;
- using as_signed = int32_t;
+ using as_signed = int32_t;
+ using as_unsigned = uint32_t;
};
template<> struct _integer_traits<uint64_t>
{
static constexpr bool kSigned = false;
static constexpr bool kUnsigned = true;
- using as_signed = int64_t;
+ using as_signed = int64_t;
+ using as_unsigned = uint64_t;
};
template<> struct _integer_traits<int8_t>
@@ -278,6 +282,7 @@ template<> struct _integer_traits<int8_t>
static constexpr bool kSigned = true;
static constexpr bool kUnsigned = false;
using as_unsigned = uint8_t;
+ using as_signed = int8_t;
};
template<> struct _integer_traits<int16_t>
@@ -285,6 +290,7 @@ template<> struct _integer_traits<int16_t>
static constexpr bool kSigned = true;
static constexpr bool kUnsigned = false;
using as_unsigned = uint16_t;
+ using as_signed = int16_t;
};
template<> struct _integer_traits<int32_t>
@@ -292,6 +298,7 @@ template<> struct _integer_traits<int32_t>
static constexpr bool kSigned = true;
static constexpr bool kUnsigned = false;
using as_unsigned = uint32_t;
+ using as_signed = int32_t;
};
template<> struct _integer_traits<int64_t>
@@ -299,6 +306,7 @@ template<> struct _integer_traits<int64_t>
static constexpr bool kSigned = true;
static constexpr bool kUnsigned = false;
using as_unsigned = uint64_t;
+ using as_signed = int64_t;
};
template<typename T> concept is_signed_integer = _integer_traits<T>::kSigned;
@@ -306,8 +314,8 @@ template<typename T> concept is_unsigned_integer = _integer_traits<T>::kUnsigned
template<typename T> concept is_integer = is_signed_integer<T> || is_unsigned_integer<T>;
-template<is_signed_integer T> using as_unsigned_integer = _integer_traits<T>::as_unsigned;
-template<is_unsigned_integer T> using as_signed_integer = _integer_traits<T>::as_signed;
+template<is_integer T> using as_unsigned_integer = _integer_traits<T>::as_unsigned;
+template<is_integer T> using as_signed_integer = _integer_traits<T>::as_signed;
template<typename T> concept is_enum = __is_enum(T);
diff --git a/asl/base/numeric.hpp b/asl/base/numeric.hpp
index bbd229d..8d3b8ef 100644
--- a/asl/base/numeric.hpp
+++ b/asl/base/numeric.hpp
@@ -7,6 +7,7 @@
#include "asl/base/integers.hpp"
#include "asl/base/bit.hpp"
#include "asl/base/meta.hpp"
+#include "asl/base/assert.hpp"
namespace asl
{
@@ -14,10 +15,24 @@ namespace asl
template<is_integer T>
constexpr bool is_pow2(T x)
{
- using unsigned_type = select_t<is_unsigned_integer<T>, T, as_unsigned_integer<T>>;
+ using unsigned_type = as_unsigned_integer<T>;
return x > 0 && has_single_bit(static_cast<unsigned_type>(x));
}
+template<is_integer T>
+constexpr T round_down_pow2(T x, T div)
+{
+ ASL_ASSERT(is_pow2(div));
+ return x & (-div);
+}
+
+template<is_integer T>
+constexpr T round_up_pow2(T x, T div)
+{
+ ASL_ASSERT(is_pow2(div));
+ return (x + (div - 1)) & (-div);
+}
+
template<typename T>
concept is_numeric = is_integer<T> || is_floating_point<T>;
diff --git a/asl/base/numeric_tests.cpp b/asl/base/numeric_tests.cpp
index cfbc1ac..afcc12a 100644
--- a/asl/base/numeric_tests.cpp
+++ b/asl/base/numeric_tests.cpp
@@ -13,4 +13,56 @@ ASL_TEST(is_pow2)
ASL_TEST_EXPECT(!asl::is_pow2(6));
ASL_TEST_EXPECT(!asl::is_pow2(1978));
ASL_TEST_EXPECT(!asl::is_pow2(0));
+ ASL_TEST_EXPECT(asl::is_pow2(4U));
+ ASL_TEST_EXPECT(asl::is_pow2(uint64_t{65536}));
+}
+
+ASL_TEST(round_down_pow2) // NOLINT
+{
+ ASL_TEST_EXPECT(asl::round_down_pow2(0, 1) == 0);
+ ASL_TEST_EXPECT(asl::round_down_pow2(1, 1) == 1);
+ ASL_TEST_EXPECT(asl::round_down_pow2(2, 1) == 2);
+ ASL_TEST_EXPECT(asl::round_down_pow2(3, 1) == 3);
+ ASL_TEST_EXPECT(asl::round_down_pow2(-1, 1) == -1);
+ ASL_TEST_EXPECT(asl::round_down_pow2(-2, 1) == -2);
+ ASL_TEST_EXPECT(asl::round_down_pow2(-3, 1) == -3);
+
+ ASL_TEST_EXPECT(asl::round_down_pow2(0U, 1U) == 0U);
+ ASL_TEST_EXPECT(asl::round_down_pow2(1U, 1U) == 1U);
+ ASL_TEST_EXPECT(asl::round_down_pow2(2U, 1U) == 2U);
+ ASL_TEST_EXPECT(asl::round_down_pow2(3U, 1U) == 3U);
+
+ ASL_TEST_EXPECT(asl::round_down_pow2(0, 16) == 0);
+ ASL_TEST_EXPECT(asl::round_down_pow2(1, 16) == 0);
+ ASL_TEST_EXPECT(asl::round_down_pow2(8, 16) == 0);
+ ASL_TEST_EXPECT(asl::round_down_pow2(15, 16) == 0);
+ ASL_TEST_EXPECT(asl::round_down_pow2(16, 16) == 16);
+ ASL_TEST_EXPECT(asl::round_down_pow2(17, 16) == 16);
+ ASL_TEST_EXPECT(asl::round_down_pow2(255, 16) == 240);
+ ASL_TEST_EXPECT(asl::round_down_pow2(-255, 16) == -256);
+}
+
+ASL_TEST(round_up_pow2) // NOLINT
+{
+ ASL_TEST_EXPECT(asl::round_up_pow2(0, 1) == 0);
+ ASL_TEST_EXPECT(asl::round_up_pow2(1, 1) == 1);
+ ASL_TEST_EXPECT(asl::round_up_pow2(2, 1) == 2);
+ ASL_TEST_EXPECT(asl::round_up_pow2(3, 1) == 3);
+ ASL_TEST_EXPECT(asl::round_up_pow2(-1, 1) == -1);
+ ASL_TEST_EXPECT(asl::round_up_pow2(-2, 1) == -2);
+ ASL_TEST_EXPECT(asl::round_up_pow2(-3, 1) == -3);
+
+ ASL_TEST_EXPECT(asl::round_up_pow2(0U, 1U) == 0U);
+ ASL_TEST_EXPECT(asl::round_up_pow2(1U, 1U) == 1U);
+ ASL_TEST_EXPECT(asl::round_up_pow2(2U, 1U) == 2U);
+ ASL_TEST_EXPECT(asl::round_up_pow2(3U, 1U) == 3U);
+
+ ASL_TEST_EXPECT(asl::round_up_pow2(0, 16) == 0);
+ ASL_TEST_EXPECT(asl::round_up_pow2(1, 16) == 16);
+ ASL_TEST_EXPECT(asl::round_up_pow2(8, 16) == 16);
+ ASL_TEST_EXPECT(asl::round_up_pow2(15, 16) == 16);
+ ASL_TEST_EXPECT(asl::round_up_pow2(16, 16) == 16);
+ ASL_TEST_EXPECT(asl::round_up_pow2(17, 16) == 32);
+ ASL_TEST_EXPECT(asl::round_up_pow2(255, 16) == 256);
+ ASL_TEST_EXPECT(asl::round_up_pow2(-255, 16) == -240);
}