Add bit library
This commit is contained in:
@ -11,6 +11,7 @@ cc_library(
|
||||
hdrs = [
|
||||
"annotations.hpp",
|
||||
"assert.hpp",
|
||||
"bit.hpp",
|
||||
"config.hpp",
|
||||
"defer.hpp",
|
||||
"float.hpp",
|
||||
@ -37,6 +38,7 @@ cc_library(
|
||||
"//asl/types:box",
|
||||
],
|
||||
) for name in [
|
||||
"bit",
|
||||
"defer",
|
||||
"float",
|
||||
"functional",
|
||||
|
174
asl/base/bit.hpp
Normal file
174
asl/base/bit.hpp
Normal file
@ -0,0 +1,174 @@
|
||||
// Copyright 2025 Steven Le Rouzic
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "asl/base/integers.hpp"
|
||||
#include "asl/base/meta.hpp"
|
||||
|
||||
namespace asl
|
||||
{
|
||||
|
||||
constexpr bool has_single_bit(is_unsigned_integer auto x)
|
||||
{
|
||||
return x != 0 && ((x - 1) & x) == 0;
|
||||
}
|
||||
|
||||
// @Todo Move this to numeric library
|
||||
template<is_integer T>
|
||||
constexpr bool is_pow2(T x)
|
||||
{
|
||||
using unsigned_type = select_t<is_unsigned_integer<T>, T, as_unsigned_integer<T>>;
|
||||
return x > 0 && has_single_bit(static_cast<unsigned_type>(x));
|
||||
}
|
||||
|
||||
constexpr int popcount(uint8_t v)
|
||||
{
|
||||
v = v - ((v >> 1) & 0x55);
|
||||
v = (v & 0x33) + ((v >> 2) & 0x33);
|
||||
return (v + (v >> 4)) & 0x0F;
|
||||
}
|
||||
|
||||
constexpr int popcount(uint16_t v)
|
||||
{
|
||||
v = v - ((v >> 1) & 0x5555);
|
||||
v = (v & 0x3333) + ((v >> 2) & 0x3333);
|
||||
return static_cast<uint16_t>((v + (v >> 4) & 0x0F0F) * uint16_t{0x0101}) >> 8;
|
||||
}
|
||||
|
||||
constexpr int popcount(uint32_t v)
|
||||
{
|
||||
v = v - ((v >> 1) & 0x5555'5555);
|
||||
v = (v & 0x3333'3333) + ((v >> 2) & 0x3333'3333);
|
||||
return static_cast<int>(((v + (v >> 4) & 0x0F0F'0F0F) * 0x0101'0101) >> 24);
|
||||
}
|
||||
|
||||
constexpr int popcount(uint64_t v)
|
||||
{
|
||||
v = v - ((v >> 1) & 0x5555'5555'5555'5555);
|
||||
v = (v & 0x3333'3333'3333'3333) + ((v >> 2) & 0x3333'3333'3333'3333);
|
||||
return static_cast<int>(((v + (v >> 4) & 0x0F0F'0F0F'0F0F'0F0F) * 0x0101'0101'0101'0101) >> 56);
|
||||
}
|
||||
|
||||
constexpr uint8_t propagate_right_one(uint8_t v)
|
||||
{
|
||||
v = v | (v >> 1);
|
||||
v = v | (v >> 2);
|
||||
v = v | (v >> 4);
|
||||
return v;
|
||||
}
|
||||
|
||||
constexpr uint16_t propagate_right_one(uint16_t v)
|
||||
{
|
||||
v = v | (v >> 1);
|
||||
v = v | (v >> 2);
|
||||
v = v | (v >> 4);
|
||||
v = v | (v >> 8);
|
||||
return v;
|
||||
}
|
||||
|
||||
constexpr uint32_t propagate_right_one(uint32_t v)
|
||||
{
|
||||
v = v | (v >> 1);
|
||||
v = v | (v >> 2);
|
||||
v = v | (v >> 4);
|
||||
v = v | (v >> 8);
|
||||
v = v | (v >> 16);
|
||||
return v;
|
||||
}
|
||||
|
||||
constexpr uint64_t propagate_right_one(uint64_t v)
|
||||
{
|
||||
v = v | (v >> 1);
|
||||
v = v | (v >> 2);
|
||||
v = v | (v >> 4);
|
||||
v = v | (v >> 8);
|
||||
v = v | (v >> 16);
|
||||
v = v | (v >> 32);
|
||||
return v;
|
||||
}
|
||||
|
||||
constexpr int countr_zero(is_unsigned_integer auto v)
|
||||
{
|
||||
v = ~v & (v - 1);
|
||||
return popcount(v);
|
||||
}
|
||||
|
||||
constexpr int countr_one(is_unsigned_integer auto v)
|
||||
{
|
||||
v = v & (~v - 1);
|
||||
return popcount(v);
|
||||
}
|
||||
|
||||
constexpr int countl_zero(is_unsigned_integer auto v)
|
||||
{
|
||||
v = ~propagate_right_one(v);
|
||||
return popcount(v);
|
||||
}
|
||||
|
||||
constexpr int countl_one(is_unsigned_integer auto v)
|
||||
{
|
||||
v = ~v;
|
||||
v = ~propagate_right_one(v);
|
||||
return popcount(v);
|
||||
}
|
||||
|
||||
template<is_unsigned_integer T>
|
||||
constexpr T rotr(T v, int s);
|
||||
|
||||
template<is_unsigned_integer T>
|
||||
constexpr T rotl(T v, int s) // NOLINT(*-no-recursion)
|
||||
{
|
||||
static constexpr int N = sizeof(decltype(v)) * 8;
|
||||
s = s % N;
|
||||
return (s >= 0) ? (v << s) | (v >> (N - s)) : rotr(v, -s);
|
||||
}
|
||||
|
||||
template<is_unsigned_integer T>
|
||||
constexpr T rotr(T v, int s) // NOLINT(*-no-recursion)
|
||||
{
|
||||
static constexpr int N = sizeof(decltype(v)) * 8;
|
||||
s = s % N;
|
||||
return (s >= 0) ? (v >> s) | (v << (N - s)) : rotl(v, -s);
|
||||
}
|
||||
|
||||
constexpr uint16_t byteswap(uint16_t v)
|
||||
{
|
||||
return static_cast<uint16_t>((v << 8U) | (v >> 8U));
|
||||
}
|
||||
|
||||
constexpr uint32_t byteswap(uint32_t v)
|
||||
{
|
||||
return rotr(v & 0x00ff'00ff, 8) | rotl(v & 0xff00'ff00, 8);
|
||||
}
|
||||
|
||||
constexpr uint64_t byteswap(uint64_t v)
|
||||
{
|
||||
return (uint64_t{byteswap(static_cast<uint32_t>(v))} << 32)
|
||||
| uint64_t{byteswap(static_cast<uint32_t>(v >> 32))};
|
||||
}
|
||||
|
||||
constexpr auto bit_ceil(is_unsigned_integer auto v)
|
||||
{
|
||||
v -= 1;
|
||||
v = propagate_right_one(v);
|
||||
v += 1;
|
||||
return v;
|
||||
}
|
||||
|
||||
constexpr auto bit_floor(is_unsigned_integer auto v)
|
||||
{
|
||||
v = propagate_right_one(v);
|
||||
v = v - (v >> 1);
|
||||
return v;
|
||||
}
|
||||
|
||||
constexpr int bit_width(is_unsigned_integer auto v)
|
||||
{
|
||||
static constexpr int N = sizeof(decltype(v)) * 8;
|
||||
return N - countl_zero(v);
|
||||
}
|
||||
|
||||
} // namespace asl
|
||||
|
203
asl/base/bit_tests.cpp
Normal file
203
asl/base/bit_tests.cpp
Normal file
@ -0,0 +1,203 @@
|
||||
// Copyright 2025 Steven Le Rouzic
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
#include "asl/base/bit.hpp"
|
||||
|
||||
#include "asl/testing/testing.hpp"
|
||||
|
||||
ASL_TEST(has_single_bit)
|
||||
{
|
||||
ASL_TEST_EXPECT(asl::has_single_bit(4U));
|
||||
ASL_TEST_EXPECT(asl::has_single_bit(1024U));
|
||||
ASL_TEST_EXPECT(asl::has_single_bit(0x8000'0000U));
|
||||
ASL_TEST_EXPECT(asl::has_single_bit(0x0000'8000'0000'0000ULL));
|
||||
ASL_TEST_EXPECT(!asl::has_single_bit(0U));
|
||||
ASL_TEST_EXPECT(!asl::has_single_bit(3U));
|
||||
ASL_TEST_EXPECT(!asl::has_single_bit(341U));
|
||||
}
|
||||
|
||||
ASL_TEST(is_pow2)
|
||||
{
|
||||
ASL_TEST_EXPECT(asl::is_pow2(4));
|
||||
ASL_TEST_EXPECT(asl::is_pow2(65536));
|
||||
ASL_TEST_EXPECT(!asl::is_pow2(6));
|
||||
ASL_TEST_EXPECT(!asl::is_pow2(1978));
|
||||
ASL_TEST_EXPECT(!asl::is_pow2(0));
|
||||
}
|
||||
|
||||
ASL_TEST(popcount) // NOLINT(*-cognitive-complexity)
|
||||
{
|
||||
ASL_TEST_EXPECT(asl::popcount(uint8_t{0}) == 0);
|
||||
ASL_TEST_EXPECT(asl::popcount(uint8_t{255}) == 8);
|
||||
ASL_TEST_EXPECT(asl::popcount(uint8_t{46}) == 4);
|
||||
ASL_TEST_EXPECT(asl::popcount(uint16_t{0}) == 0);
|
||||
ASL_TEST_EXPECT(asl::popcount(uint16_t{255}) == 8);
|
||||
ASL_TEST_EXPECT(asl::popcount(uint16_t{65535}) == 16);
|
||||
ASL_TEST_EXPECT(asl::popcount(uint16_t{46}) == 4);
|
||||
ASL_TEST_EXPECT(asl::popcount(uint32_t{0}) == 0);
|
||||
ASL_TEST_EXPECT(asl::popcount(uint32_t{255}) == 8);
|
||||
ASL_TEST_EXPECT(asl::popcount(uint32_t{65535}) == 16);
|
||||
ASL_TEST_EXPECT(asl::popcount(uint32_t{65536}) == 1);
|
||||
ASL_TEST_EXPECT(asl::popcount(uint32_t{46}) == 4);
|
||||
ASL_TEST_EXPECT(asl::popcount(uint32_t{0xffff'ffff}) == 32);
|
||||
ASL_TEST_EXPECT(asl::popcount(0x8421'1248'8421'1248) == 16);
|
||||
ASL_TEST_EXPECT(asl::popcount(0xffff'ffff'ffff'ffff) == 64);
|
||||
}
|
||||
|
||||
ASL_TEST(countr_zero)
|
||||
{
|
||||
ASL_TEST_EXPECT(asl::countr_zero(uint8_t{0}) == 8);
|
||||
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);
|
||||
ASL_TEST_EXPECT(asl::countr_zero(uint8_t{0b10101001}) == 0);
|
||||
}
|
||||
|
||||
ASL_TEST(countr_one)
|
||||
{
|
||||
ASL_TEST_EXPECT(asl::countr_one(uint8_t{0}) == 0);
|
||||
ASL_TEST_EXPECT(asl::countr_one(uint8_t{255}) == 8);
|
||||
ASL_TEST_EXPECT(asl::countr_one(uint8_t{0b00011100}) == 0);
|
||||
ASL_TEST_EXPECT(asl::countr_one(uint8_t{0b10101011}) == 2);
|
||||
ASL_TEST_EXPECT(asl::countr_one(uint8_t{0b10101001}) == 1);
|
||||
}
|
||||
|
||||
ASL_TEST(countl_zero)
|
||||
{
|
||||
ASL_TEST_EXPECT(asl::countl_zero(uint8_t{0}) == 8);
|
||||
ASL_TEST_EXPECT(asl::countl_zero(uint8_t{255}) == 0);
|
||||
ASL_TEST_EXPECT(asl::countl_zero(uint8_t{0b00011100}) == 3);
|
||||
ASL_TEST_EXPECT(asl::countl_zero(uint8_t{0b10101010}) == 0);
|
||||
ASL_TEST_EXPECT(asl::countl_zero(uint8_t{0b00001001}) == 4);
|
||||
}
|
||||
|
||||
ASL_TEST(countl_one)
|
||||
{
|
||||
ASL_TEST_EXPECT(asl::countl_one(uint8_t{0}) == 0);
|
||||
ASL_TEST_EXPECT(asl::countl_one(uint8_t{255}) == 8);
|
||||
ASL_TEST_EXPECT(asl::countl_one(uint8_t{0b00011100}) == 0);
|
||||
ASL_TEST_EXPECT(asl::countl_one(uint8_t{0b10101010}) == 1);
|
||||
ASL_TEST_EXPECT(asl::countl_one(uint8_t{0b11101001}) == 3);
|
||||
}
|
||||
|
||||
ASL_TEST(rotl)
|
||||
{
|
||||
ASL_TEST_EXPECT(asl::rotl(uint32_t{0x4000'0100}, 1) == 0x8000'0200);
|
||||
ASL_TEST_EXPECT(asl::rotl(uint32_t{0x4000'0100}, 3) == 0x0000'0802);
|
||||
ASL_TEST_EXPECT(asl::rotl(uint32_t{0x4000'0100}, 0) == 0x4000'0100);
|
||||
ASL_TEST_EXPECT(asl::rotl(uint32_t{0x4000'0100}, -1) == 0x2000'0080);
|
||||
ASL_TEST_EXPECT(asl::rotl(uint32_t{0x4000'0100}, -12) == 0x1004'0000);
|
||||
}
|
||||
|
||||
ASL_TEST(rotr)
|
||||
{
|
||||
ASL_TEST_EXPECT(asl::rotr(uint32_t{0x4000'0100}, -1) == 0x8000'0200);
|
||||
ASL_TEST_EXPECT(asl::rotr(uint32_t{0x4000'0100}, -3) == 0x0000'0802);
|
||||
ASL_TEST_EXPECT(asl::rotr(uint32_t{0x4000'0100}, 0) == 0x4000'0100);
|
||||
ASL_TEST_EXPECT(asl::rotr(uint32_t{0x4000'0100}, 1) == 0x2000'0080);
|
||||
ASL_TEST_EXPECT(asl::rotr(uint32_t{0x4000'0100}, 12) == 0x1004'0000);
|
||||
}
|
||||
|
||||
ASL_TEST(byteswap)
|
||||
{
|
||||
ASL_TEST_EXPECT(asl::byteswap(uint32_t{0x1234'5678}) == 0x7856'3412);
|
||||
ASL_TEST_EXPECT(asl::byteswap(uint16_t{0x1234}) == 0x3412);
|
||||
ASL_TEST_EXPECT(asl::byteswap(uint64_t{0x0123'4567'89ab'cdef}) == 0xefcd'ab89'6745'2301);
|
||||
}
|
||||
|
||||
ASL_TEST(bit_ceil) // NOLINT(*-cognitive-complexity)
|
||||
{
|
||||
ASL_TEST_EXPECT(asl::bit_ceil(uint8_t{0}) == 0);
|
||||
ASL_TEST_EXPECT(asl::bit_ceil(uint8_t{1}) == 1);
|
||||
ASL_TEST_EXPECT(asl::bit_ceil(uint8_t{2}) == 2);
|
||||
ASL_TEST_EXPECT(asl::bit_ceil(uint8_t{3}) == 4);
|
||||
ASL_TEST_EXPECT(asl::bit_ceil(uint8_t{4}) == 4);
|
||||
ASL_TEST_EXPECT(asl::bit_ceil(uint8_t{5}) == 8);
|
||||
ASL_TEST_EXPECT(asl::bit_ceil(uint8_t{6}) == 8);
|
||||
ASL_TEST_EXPECT(asl::bit_ceil(uint8_t{127}) == 128);
|
||||
ASL_TEST_EXPECT(asl::bit_ceil(uint8_t{128}) == 128);
|
||||
ASL_TEST_EXPECT(asl::bit_ceil(uint8_t{254}) == 0);
|
||||
ASL_TEST_EXPECT(asl::bit_ceil(uint8_t{255}) == 0);
|
||||
|
||||
ASL_TEST_EXPECT(asl::bit_ceil(uint16_t{0}) == 0);
|
||||
ASL_TEST_EXPECT(asl::bit_ceil(uint16_t{1}) == 1);
|
||||
ASL_TEST_EXPECT(asl::bit_ceil(uint16_t{2}) == 2);
|
||||
ASL_TEST_EXPECT(asl::bit_ceil(uint16_t{3}) == 4);
|
||||
ASL_TEST_EXPECT(asl::bit_ceil(uint16_t{4}) == 4);
|
||||
ASL_TEST_EXPECT(asl::bit_ceil(uint16_t{5}) == 8);
|
||||
ASL_TEST_EXPECT(asl::bit_ceil(uint16_t{6}) == 8);
|
||||
ASL_TEST_EXPECT(asl::bit_ceil(uint16_t{32000}) == 32768);
|
||||
ASL_TEST_EXPECT(asl::bit_ceil(uint16_t{32768}) == 32768);
|
||||
ASL_TEST_EXPECT(asl::bit_ceil(uint16_t{35000}) == 0);
|
||||
ASL_TEST_EXPECT(asl::bit_ceil(uint16_t{65535}) == 0);
|
||||
}
|
||||
|
||||
ASL_TEST(bit_floor) // NOLINT(*-cognitive-complexity)
|
||||
{
|
||||
ASL_TEST_EXPECT(asl::bit_floor(uint8_t{0}) == 0);
|
||||
ASL_TEST_EXPECT(asl::bit_floor(uint8_t{1}) == 1);
|
||||
ASL_TEST_EXPECT(asl::bit_floor(uint8_t{2}) == 2);
|
||||
ASL_TEST_EXPECT(asl::bit_floor(uint8_t{3}) == 2);
|
||||
ASL_TEST_EXPECT(asl::bit_floor(uint8_t{4}) == 4);
|
||||
ASL_TEST_EXPECT(asl::bit_floor(uint8_t{5}) == 4);
|
||||
ASL_TEST_EXPECT(asl::bit_floor(uint8_t{6}) == 4);
|
||||
ASL_TEST_EXPECT(asl::bit_floor(uint8_t{127}) == 64);
|
||||
ASL_TEST_EXPECT(asl::bit_floor(uint8_t{128}) == 128);
|
||||
ASL_TEST_EXPECT(asl::bit_floor(uint8_t{254}) == 128);
|
||||
ASL_TEST_EXPECT(asl::bit_floor(uint8_t{255}) == 128);
|
||||
|
||||
ASL_TEST_EXPECT(asl::bit_floor(uint16_t{0}) == 0);
|
||||
ASL_TEST_EXPECT(asl::bit_floor(uint16_t{1}) == 1);
|
||||
ASL_TEST_EXPECT(asl::bit_floor(uint16_t{2}) == 2);
|
||||
ASL_TEST_EXPECT(asl::bit_floor(uint16_t{3}) == 2);
|
||||
ASL_TEST_EXPECT(asl::bit_floor(uint16_t{4}) == 4);
|
||||
ASL_TEST_EXPECT(asl::bit_floor(uint16_t{5}) == 4);
|
||||
ASL_TEST_EXPECT(asl::bit_floor(uint16_t{6}) == 4);
|
||||
ASL_TEST_EXPECT(asl::bit_floor(uint16_t{32000}) == 16384);
|
||||
ASL_TEST_EXPECT(asl::bit_floor(uint16_t{32768}) == 32768);
|
||||
ASL_TEST_EXPECT(asl::bit_floor(uint16_t{35000}) == 32768);
|
||||
ASL_TEST_EXPECT(asl::bit_floor(uint16_t{65535}) == 32768);
|
||||
}
|
||||
|
||||
ASL_TEST(bit_width) // NOLINT(*-cognitive-complexity)
|
||||
{
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint8_t{0}) == 0);
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint8_t{1}) == 1);
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint8_t{2}) == 2);
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint8_t{3}) == 2);
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint8_t{4}) == 3);
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint8_t{5}) == 3);
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint8_t{6}) == 3);
|
||||
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint16_t{0}) == 0);
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint16_t{1}) == 1);
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint16_t{2}) == 2);
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint16_t{3}) == 2);
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint16_t{4}) == 3);
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint16_t{5}) == 3);
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint16_t{6}) == 3);
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint16_t{65535}) == 16);
|
||||
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint32_t{0}) == 0);
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint32_t{1}) == 1);
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint32_t{2}) == 2);
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint32_t{3}) == 2);
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint32_t{4}) == 3);
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint32_t{5}) == 3);
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint32_t{6}) == 3);
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint32_t{65535}) == 16);
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint32_t{65536}) == 17);
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint32_t{0xffff'ffff}) == 32);
|
||||
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint64_t{0}) == 0);
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint64_t{1}) == 1);
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint64_t{2}) == 2);
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint64_t{3}) == 2);
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint64_t{4}) == 3);
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint64_t{5}) == 3);
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint64_t{6}) == 3);
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint64_t{65535}) == 16);
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint64_t{65536}) == 17);
|
||||
ASL_TEST_EXPECT(asl::bit_width(uint64_t{0xffff'ffff}) == 32);
|
||||
}
|
@ -25,6 +25,9 @@ struct empty {};
|
||||
|
||||
template<typename T> struct id { using type = T; };
|
||||
|
||||
struct in_place_t {};
|
||||
static constexpr in_place_t in_place{};
|
||||
|
||||
template<typename... Args> static constexpr isize_t types_count = sizeof...(Args);
|
||||
|
||||
template<typename T, T kValue> struct integral_constant { static constexpr T value = kValue; };
|
||||
@ -234,17 +237,75 @@ template<> struct _is_floating_point_helper<double> : true_type {};
|
||||
|
||||
template<typename T> concept is_floating_point = _is_floating_point_helper<un_cv_t<T>>::value;
|
||||
|
||||
template<typename T> struct _is_integer_helper : false_type {};
|
||||
template<> struct _is_integer_helper<int8_t> : true_type {};
|
||||
template<> struct _is_integer_helper<int16_t> : true_type {};
|
||||
template<> struct _is_integer_helper<int32_t> : true_type {};
|
||||
template<> struct _is_integer_helper<int64_t> : true_type {};
|
||||
template<> struct _is_integer_helper<uint8_t> : true_type {};
|
||||
template<> struct _is_integer_helper<uint16_t> : true_type {};
|
||||
template<> struct _is_integer_helper<uint32_t> : true_type {};
|
||||
template<> struct _is_integer_helper<uint64_t> : true_type {};
|
||||
template<typename T> struct _integer_traits
|
||||
{
|
||||
static constexpr bool kSigned = false;
|
||||
static constexpr bool kUnsigned = false;
|
||||
};
|
||||
|
||||
template<typename T> concept is_integer = _is_integer_helper<un_cv_t<T>>::value;
|
||||
template<> struct _integer_traits<uint8_t>
|
||||
{
|
||||
static constexpr bool kSigned = false;
|
||||
static constexpr bool kUnsigned = true;
|
||||
using as_signed = int8_t;
|
||||
};
|
||||
|
||||
template<> struct _integer_traits<uint16_t>
|
||||
{
|
||||
static constexpr bool kSigned = false;
|
||||
static constexpr bool kUnsigned = true;
|
||||
using as_signed = int16_t;
|
||||
};
|
||||
|
||||
template<> struct _integer_traits<uint32_t>
|
||||
{
|
||||
static constexpr bool kSigned = false;
|
||||
static constexpr bool kUnsigned = true;
|
||||
using as_signed = int32_t;
|
||||
};
|
||||
|
||||
template<> struct _integer_traits<uint64_t>
|
||||
{
|
||||
static constexpr bool kSigned = false;
|
||||
static constexpr bool kUnsigned = true;
|
||||
using as_signed = int64_t;
|
||||
};
|
||||
|
||||
template<> struct _integer_traits<int8_t>
|
||||
{
|
||||
static constexpr bool kSigned = true;
|
||||
static constexpr bool kUnsigned = false;
|
||||
using as_unsigned = uint8_t;
|
||||
};
|
||||
|
||||
template<> struct _integer_traits<int16_t>
|
||||
{
|
||||
static constexpr bool kSigned = true;
|
||||
static constexpr bool kUnsigned = false;
|
||||
using as_unsigned = uint16_t;
|
||||
};
|
||||
|
||||
template<> struct _integer_traits<int32_t>
|
||||
{
|
||||
static constexpr bool kSigned = true;
|
||||
static constexpr bool kUnsigned = false;
|
||||
using as_unsigned = uint32_t;
|
||||
};
|
||||
|
||||
template<> struct _integer_traits<int64_t>
|
||||
{
|
||||
static constexpr bool kSigned = true;
|
||||
static constexpr bool kUnsigned = false;
|
||||
using as_unsigned = uint64_t;
|
||||
};
|
||||
|
||||
template<typename T> concept is_signed_integer = _integer_traits<T>::kSigned;
|
||||
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<typename T> concept is_enum = __is_enum(T);
|
||||
|
||||
|
@ -47,9 +47,6 @@ template<typename T>
|
||||
namespace asl
|
||||
{
|
||||
|
||||
struct in_place_t {};
|
||||
static constexpr in_place_t in_place{};
|
||||
|
||||
template<moveable T>
|
||||
constexpr void swap(T& a, T& b)
|
||||
{
|
||||
@ -84,27 +81,6 @@ constexpr T max(T a, T b)
|
||||
return (a >= b) ? a : b;
|
||||
}
|
||||
|
||||
constexpr uint64_t round_up_pow2(uint64_t v)
|
||||
{
|
||||
ASL_ASSERT(v <= 0x8000'0000'0000'0000);
|
||||
|
||||
v -= 1;
|
||||
|
||||
v |= v >> 1U;
|
||||
v |= v >> 2U;
|
||||
v |= v >> 4U;
|
||||
v |= v >> 8U;
|
||||
v |= v >> 16U;
|
||||
v |= v >> 32U;
|
||||
|
||||
return v + 1;
|
||||
}
|
||||
|
||||
constexpr bool is_pow2(isize_t v)
|
||||
{
|
||||
return v > 0 && ((v - 1) & v) == 0; // NOLINT
|
||||
}
|
||||
|
||||
// NOLINTBEGIN(*-macro-parentheses)
|
||||
#define ASL_DELETE_COPY(T) \
|
||||
T(const T&) = delete; \
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "asl/memory/memory.hpp"
|
||||
#include "asl/base/annotations.hpp"
|
||||
#include "asl/base/assert.hpp"
|
||||
#include "asl/base/bit.hpp"
|
||||
#include "asl/types/span.hpp"
|
||||
#include "asl/hashing/hash.hpp"
|
||||
|
||||
@ -320,7 +321,7 @@ public:
|
||||
if (new_capacity <= capacity()) { return; }
|
||||
ASL_ASSERT(new_capacity > kInlineCapacity);
|
||||
|
||||
new_capacity = static_cast<isize_t>(round_up_pow2(static_cast<uint64_t>(new_capacity)));
|
||||
new_capacity = static_cast<isize_t>(bit_ceil(static_cast<uint64_t>(new_capacity)));
|
||||
|
||||
T* old_data = data();
|
||||
const isize_t old_capacity = capacity();
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "asl/base/annotations.hpp"
|
||||
#include "asl/base/utility.hpp"
|
||||
#include "asl/base/meta.hpp"
|
||||
#include "asl/base/bit.hpp"
|
||||
#include "asl/memory/allocator.hpp"
|
||||
#include "asl/memory/memory.hpp"
|
||||
#include "asl/types/maybe_uninit.hpp"
|
||||
@ -83,7 +84,7 @@ protected:
|
||||
ASL_ASSERT(size > 0);
|
||||
return max<isize_t>(
|
||||
kMinCapacity,
|
||||
static_cast<isize_t>(round_up_pow2((static_cast<uint64_t>(size) * 4 + 2) / 3)));
|
||||
static_cast<isize_t>(bit_ceil((static_cast<uint64_t>(size) * 4 + 2) / 3)));
|
||||
}
|
||||
|
||||
static void insert_inner(
|
||||
|
Reference in New Issue
Block a user