-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Also refactor IntegralReference into common header.
- Loading branch information
1 parent
293b0ec
commit 75cb6fb
Showing
5 changed files
with
437 additions
and
136 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
#pragma once | ||
|
||
#include <climits> | ||
#include <type_traits> | ||
|
||
namespace internal | ||
{ | ||
/// A proxy type representing a reference to an integral value, stored in a buffer at a specified bit offset. | ||
/// @tparam Integral Integral data type which can be loaded and store through this reference. | ||
/// @tparam StoredIntegralPointer Pointer to integral type used for storing the bits. | ||
template<typename Integral, typename StoredIntegralPointer> | ||
struct IntegralReference | ||
{ | ||
using StoredIntegral = std::remove_const_t<std::remove_pointer_t<StoredIntegralPointer>>; | ||
|
||
static_assert(std::is_integral_v<Integral>); | ||
static_assert(std::is_integral_v<StoredIntegral>); | ||
static_assert( | ||
sizeof(StoredIntegral) >= sizeof(Integral), | ||
"The integral type used for the storage must be at least as big as the type of the values to retrieve"); | ||
|
||
StoredIntegralPointer ptr; | ||
std::size_t bitOffset; | ||
unsigned bits; | ||
|
||
static constexpr auto registerBits = sizeof(StoredIntegral) * CHAR_BIT; | ||
|
||
// NOLINTNEXTLINE(google-explicit-constructor,hicpp-explicit-conversions) | ||
operator Integral() const | ||
{ | ||
auto* p = ptr + bitOffset / registerBits; | ||
const auto innerBitOffset = bitOffset % registerBits; | ||
auto v = p[0] >> innerBitOffset; | ||
|
||
const auto innerBitEndOffset = innerBitOffset + bits; | ||
if(innerBitEndOffset <= registerBits) | ||
{ | ||
const auto mask = (StoredIntegral{1} << bits) - 1u; | ||
v &= mask; | ||
} | ||
else | ||
{ | ||
const auto excessBits = innerBitEndOffset - registerBits; | ||
const auto bitsLoaded = registerBits - innerBitOffset; | ||
const auto mask = (StoredIntegral{1} << excessBits) - 1u; | ||
v |= (p[1] & mask) << bitsLoaded; | ||
} | ||
if constexpr(std::is_signed_v<Integral>) | ||
if((v & (StoredIntegral{1} << (bits - 1))) != 0) | ||
{ | ||
// sign extend | ||
v |= static_cast<StoredIntegral>(-1) << bits; | ||
} | ||
return static_cast<Integral>(v); | ||
} | ||
|
||
auto operator=(Integral v) -> IntegralReference& | ||
{ | ||
const auto mask = (StoredIntegral{1} << bits) - 1u; | ||
const auto vBits = (static_cast<StoredIntegral>(v) & mask); | ||
|
||
auto* p = ptr + bitOffset / registerBits; | ||
const auto innerBitOffset = bitOffset % registerBits; | ||
const auto clearMask = ~(mask << innerBitOffset); | ||
auto m = p[0] & clearMask; // clear previous bits | ||
m |= vBits << innerBitOffset; // write new bits | ||
p[0] = m; | ||
|
||
const auto innerBitEndOffset = innerBitOffset + bits; | ||
if(innerBitEndOffset > registerBits) | ||
{ | ||
const auto excessBits = innerBitEndOffset - registerBits; | ||
const auto bitsWritten = registerBits - innerBitOffset; | ||
const auto clearMask = ~((StoredIntegral{1} << excessBits) - 1u); | ||
auto m = p[1] & clearMask; // clear previous bits | ||
m |= vBits >> bitsWritten; // write new bits | ||
p[1] = m; | ||
} | ||
|
||
return *this; | ||
} | ||
}; | ||
} // namespace internal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
cmake_minimum_required (VERSION 3.15) | ||
project(llama-floatpack CXX) | ||
|
||
if (NOT TARGET llama::llama) | ||
find_package(llama REQUIRED) | ||
endif() | ||
add_executable(${PROJECT_NAME} floatpack.cpp) | ||
target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_17) | ||
target_link_libraries(${PROJECT_NAME} PRIVATE llama::llama) |
Oops, something went wrong.