Initial import of libdpf.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
commit
e4e666f459
4563 changed files with 1690372 additions and 0 deletions
204
include/dpf/twobit.hpp
Normal file
204
include/dpf/twobit.hpp
Normal file
|
|
@ -0,0 +1,204 @@
|
|||
/// @file dpf/twobit.hpp
|
||||
/// @brief `dpf::twobit`, a 2-bit output lane in the ring Z/4Z.
|
||||
/// @details Values are `0..3`. Scalar `+` and `-` wrap mod 4. A leaf node
|
||||
/// packs one lane every two bits, low lane in the low bits of the
|
||||
/// first byte, matching `dpf::bit`. Leaf addition is not XOR: a
|
||||
/// carry stays inside the 2-bit lane. See `packed_lane_arithmetic.hpp`.
|
||||
|
||||
#ifndef LIBDPF_INCLUDE_DPF_TWOBIT_HPP__
|
||||
#define LIBDPF_INCLUDE_DPF_TWOBIT_HPP__
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <istream>
|
||||
#include <limits>
|
||||
#include <ostream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include "hedley/hedley.h"
|
||||
|
||||
#include "dpf/utils.hpp"
|
||||
|
||||
namespace dpf
|
||||
{
|
||||
|
||||
/// @brief 2-bit unsigned ring element, packed two bits per lane
|
||||
enum class twobit : std::uint8_t
|
||||
{
|
||||
zero = 0,
|
||||
one = 1,
|
||||
two = 2,
|
||||
three = 3
|
||||
};
|
||||
|
||||
HEDLEY_CONST
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
static constexpr dpf::twobit to_twobit(unsigned value) noexcept
|
||||
{
|
||||
return static_cast<dpf::twobit>(value & 3u);
|
||||
}
|
||||
|
||||
HEDLEY_CONST
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
static constexpr dpf::twobit to_twobit(unsigned long long value) noexcept
|
||||
{
|
||||
return static_cast<dpf::twobit>(value & 3ull);
|
||||
}
|
||||
|
||||
/// @brief parse one character as a 2-bit digit
|
||||
/// @param zero character for 0 (default `'0'`)
|
||||
/// @throws std::domain_error if `value` is not one of the four digits
|
||||
template <typename CharT>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
static constexpr dpf::twobit to_twobit(CharT value, CharT zero = CharT('0'))
|
||||
{
|
||||
auto delta = static_cast<unsigned>(value) - static_cast<unsigned>(zero);
|
||||
if (delta > 3u)
|
||||
{
|
||||
throw std::domain_error("Unrecognized twobit character");
|
||||
}
|
||||
return static_cast<dpf::twobit>(delta);
|
||||
}
|
||||
|
||||
inline std::string to_string(dpf::twobit value)
|
||||
{
|
||||
return std::string(1, static_cast<char>('0' + static_cast<unsigned>(value)));
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
std::basic_ostream<CharT, Traits> &
|
||||
operator<<(std::basic_ostream<CharT, Traits> & os, dpf::twobit value)
|
||||
{
|
||||
return os << static_cast<char>('0' + static_cast<unsigned>(value));
|
||||
}
|
||||
|
||||
template <typename CharT, typename Traits>
|
||||
std::basic_istream<CharT, Traits> &
|
||||
operator>>(std::basic_istream<CharT, Traits> & is, dpf::twobit & value)
|
||||
{
|
||||
try
|
||||
{
|
||||
value = to_twobit<CharT>(is.get(), is.widen('0'));
|
||||
}
|
||||
catch (const std::exception &)
|
||||
{
|
||||
is.setstate(std::ios::failbit);
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
/// @brief addition in Z/4Z
|
||||
HEDLEY_CONST
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr dpf::twobit operator+(dpf::twobit lhs, dpf::twobit rhs) noexcept
|
||||
{
|
||||
return static_cast<dpf::twobit>(
|
||||
(static_cast<unsigned>(lhs) + static_cast<unsigned>(rhs)) & 3u);
|
||||
}
|
||||
|
||||
/// @brief subtraction in Z/4Z
|
||||
HEDLEY_CONST
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr dpf::twobit operator-(dpf::twobit lhs, dpf::twobit rhs) noexcept
|
||||
{
|
||||
return static_cast<dpf::twobit>(
|
||||
(static_cast<unsigned>(lhs) - static_cast<unsigned>(rhs)) & 3u);
|
||||
}
|
||||
|
||||
/// @brief additive inverse in Z/4Z
|
||||
HEDLEY_CONST
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr dpf::twobit operator-(dpf::twobit value) noexcept
|
||||
{
|
||||
return static_cast<dpf::twobit>((0u - static_cast<unsigned>(value)) & 3u);
|
||||
}
|
||||
|
||||
/// @brief multiplication in Z/4Z
|
||||
HEDLEY_CONST
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
constexpr dpf::twobit operator*(dpf::twobit lhs, dpf::twobit rhs) noexcept
|
||||
{
|
||||
return static_cast<dpf::twobit>(
|
||||
(static_cast<unsigned>(lhs) * static_cast<unsigned>(rhs)) & 3u);
|
||||
}
|
||||
|
||||
namespace utils
|
||||
{
|
||||
|
||||
template <>
|
||||
struct bitlength_of<dpf::twobit>
|
||||
: public std::integral_constant<std::size_t, 2> {};
|
||||
|
||||
template <typename NodeT>
|
||||
struct bitlength_of_output<dpf::twobit, NodeT>
|
||||
: public std::integral_constant<std::size_t, 2> {};
|
||||
|
||||
template <>
|
||||
struct is_packed_subbyte<dpf::twobit> : std::true_type {};
|
||||
|
||||
template <>
|
||||
struct packed_lane_bits<dpf::twobit>
|
||||
: public std::integral_constant<std::size_t, 2> {};
|
||||
|
||||
template <>
|
||||
struct make_from_integral_value<dpf::twobit>
|
||||
{
|
||||
using integral_type = std::uint8_t;
|
||||
constexpr dpf::twobit operator()(integral_type val) const noexcept
|
||||
{
|
||||
return dpf::to_twobit(val);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace utils
|
||||
|
||||
namespace literals
|
||||
{
|
||||
namespace twobit
|
||||
{
|
||||
|
||||
constexpr dpf::twobit operator""_twobit(unsigned long long x)
|
||||
{
|
||||
return dpf::to_twobit(x);
|
||||
}
|
||||
|
||||
} // namespace twobit
|
||||
} // namespace literals
|
||||
|
||||
} // namespace dpf
|
||||
|
||||
namespace std
|
||||
{
|
||||
|
||||
template <>
|
||||
class numeric_limits<dpf::twobit> : public numeric_limits<std::uint8_t>
|
||||
{
|
||||
public:
|
||||
static constexpr int digits = 2;
|
||||
static constexpr int digits10 = 0;
|
||||
static constexpr dpf::twobit min() noexcept { return dpf::twobit::zero; }
|
||||
static constexpr dpf::twobit max() noexcept { return dpf::twobit::three; }
|
||||
static constexpr dpf::twobit lowest() noexcept { return min(); }
|
||||
};
|
||||
|
||||
template <>
|
||||
class numeric_limits<dpf::twobit const> : public numeric_limits<dpf::twobit> {};
|
||||
|
||||
template <>
|
||||
class numeric_limits<dpf::twobit volatile> : public numeric_limits<dpf::twobit> {};
|
||||
|
||||
template <>
|
||||
class numeric_limits<dpf::twobit const volatile>
|
||||
: public numeric_limits<dpf::twobit> {};
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif // LIBDPF_INCLUDE_DPF_TWOBIT_HPP__
|
||||
Loading…
Add table
Add a link
Reference in a new issue