Ship the TLS mesh, composer, Beaver/Yao/leaf MPC, prep/online paths, apps, and docs so the tree is pushable before elevating share_expr, security_mode, and prep resume. Co-authored-by: Cursor <cursoragent@cursor.com>
235 lines
6.2 KiB
C++
235 lines
6.2 KiB
C++
/// @file dpf/nyble.hpp
|
|
/// @brief `dpf::nyble`, a 4-bit output lane in the ring Z/16Z.
|
|
/// @details Values are `0..15`. Scalar `+` and `-` wrap mod 16. A leaf node
|
|
/// packs one lane every four bits, low nibble first. Leaf addition
|
|
/// is not XOR and is not `add_epi8`: a carry must not cross into
|
|
/// the neighbouring nibble. See `packed_lane_arithmetic.hpp`.
|
|
/// @see packed_lane_arithmetic.hpp
|
|
|
|
#ifndef LIBDPF_INCLUDE_DPF_NYBLE_HPP__
|
|
#define LIBDPF_INCLUDE_DPF_NYBLE_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 4-bit unsigned ring element, packed one nibble per lane
|
|
/// @note Not a DPF domain. A 4-bit index is `dpf::modint<4>` or `dpf::xint<4>`.
|
|
/// Scalar `+` and `-` wrap mod 16. A carry must not cross into the next
|
|
/// nibble.
|
|
/// @see dpf::bit
|
|
/// @see dpf::twobit
|
|
/// @see dpf::modint
|
|
/// @see dpf::packed
|
|
enum class nyble : std::uint8_t
|
|
{
|
|
zero = 0
|
|
};
|
|
|
|
HEDLEY_CONST
|
|
HEDLEY_NO_THROW
|
|
HEDLEY_ALWAYS_INLINE
|
|
static constexpr dpf::nyble to_nyble(unsigned value) noexcept
|
|
{
|
|
return static_cast<dpf::nyble>(value & 0x0fu);
|
|
}
|
|
|
|
HEDLEY_CONST
|
|
HEDLEY_NO_THROW
|
|
HEDLEY_ALWAYS_INLINE
|
|
static constexpr dpf::nyble to_nyble(unsigned long long value) noexcept
|
|
{
|
|
return static_cast<dpf::nyble>(value & 0x0full);
|
|
}
|
|
|
|
/// @brief parse one hex digit as a nibble
|
|
/// @tparam CharT character type
|
|
/// @param value the value to convert or store
|
|
/// @return the returned `dpf::nyble`
|
|
/// @throws std::domain_error if `value` is not `0-9`, `a-f`, or `A-F`
|
|
template <typename CharT>
|
|
static constexpr dpf::nyble to_nyble(CharT value)
|
|
{
|
|
auto u = static_cast<unsigned>(value);
|
|
if (u >= static_cast<unsigned>(CharT('0')) && u <= static_cast<unsigned>(CharT('9')))
|
|
{
|
|
return static_cast<dpf::nyble>(u - static_cast<unsigned>(CharT('0')));
|
|
}
|
|
if (u >= static_cast<unsigned>(CharT('a')) && u <= static_cast<unsigned>(CharT('f')))
|
|
{
|
|
return static_cast<dpf::nyble>(10u + u - static_cast<unsigned>(CharT('a')));
|
|
}
|
|
if (u >= static_cast<unsigned>(CharT('A')) && u <= static_cast<unsigned>(CharT('F')))
|
|
{
|
|
return static_cast<dpf::nyble>(10u + u - static_cast<unsigned>(CharT('A')));
|
|
}
|
|
throw std::domain_error("Unrecognized nyble character");
|
|
}
|
|
|
|
inline std::string to_string(dpf::nyble value)
|
|
{
|
|
constexpr char digits[] = "0123456789abcdef";
|
|
return std::string(1, digits[static_cast<unsigned>(value) & 0x0fu]);
|
|
}
|
|
|
|
template <typename CharT, typename Traits>
|
|
std::basic_ostream<CharT, Traits> &
|
|
operator<<(std::basic_ostream<CharT, Traits> & os, dpf::nyble value)
|
|
{
|
|
constexpr char digits[] = "0123456789abcdef";
|
|
return os << digits[static_cast<unsigned>(value) & 0x0fu];
|
|
}
|
|
|
|
template <typename CharT, typename Traits>
|
|
std::basic_istream<CharT, Traits> &
|
|
operator>>(std::basic_istream<CharT, Traits> & is, dpf::nyble & value)
|
|
{
|
|
try
|
|
{
|
|
value = to_nyble<CharT>(is.get());
|
|
}
|
|
catch (const std::exception &)
|
|
{
|
|
is.setstate(std::ios::failbit);
|
|
}
|
|
return is;
|
|
}
|
|
|
|
/// @brief addition in Z/16Z
|
|
/// @param lhs the left-hand operand
|
|
/// @param rhs the right-hand operand
|
|
/// @return addition in Z/16Z
|
|
HEDLEY_CONST
|
|
HEDLEY_NO_THROW
|
|
HEDLEY_ALWAYS_INLINE
|
|
constexpr dpf::nyble operator+(dpf::nyble lhs, dpf::nyble rhs) noexcept
|
|
{
|
|
return static_cast<dpf::nyble>(
|
|
(static_cast<unsigned>(lhs) + static_cast<unsigned>(rhs)) & 0x0fu);
|
|
}
|
|
|
|
/// @brief subtraction in Z/16Z
|
|
/// @param lhs the left-hand operand
|
|
/// @param rhs the right-hand operand
|
|
/// @return subtraction in Z/16Z
|
|
HEDLEY_CONST
|
|
HEDLEY_NO_THROW
|
|
HEDLEY_ALWAYS_INLINE
|
|
constexpr dpf::nyble operator-(dpf::nyble lhs, dpf::nyble rhs) noexcept
|
|
{
|
|
return static_cast<dpf::nyble>(
|
|
(static_cast<unsigned>(lhs) - static_cast<unsigned>(rhs)) & 0x0fu);
|
|
}
|
|
|
|
/// @brief additive inverse in Z/16Z
|
|
/// @param value the value to convert or store
|
|
/// @return additive inverse in Z/16Z
|
|
HEDLEY_CONST
|
|
HEDLEY_NO_THROW
|
|
HEDLEY_ALWAYS_INLINE
|
|
constexpr dpf::nyble operator-(dpf::nyble value) noexcept
|
|
{
|
|
return static_cast<dpf::nyble>((0u - static_cast<unsigned>(value)) & 0x0fu);
|
|
}
|
|
|
|
/// @brief multiplication in Z/16Z
|
|
/// @param lhs the left-hand operand
|
|
/// @param rhs the right-hand operand
|
|
/// @return multiplication in Z/16Z
|
|
HEDLEY_CONST
|
|
HEDLEY_NO_THROW
|
|
HEDLEY_ALWAYS_INLINE
|
|
constexpr dpf::nyble operator*(dpf::nyble lhs, dpf::nyble rhs) noexcept
|
|
{
|
|
return static_cast<dpf::nyble>(
|
|
(static_cast<unsigned>(lhs) * static_cast<unsigned>(rhs)) & 0x0fu);
|
|
}
|
|
|
|
namespace utils
|
|
{
|
|
|
|
template <>
|
|
struct bitlength_of<dpf::nyble>
|
|
: public std::integral_constant<std::size_t, 4> {};
|
|
|
|
template <typename NodeT>
|
|
struct bitlength_of_output<dpf::nyble, NodeT>
|
|
: public std::integral_constant<std::size_t, 4> {};
|
|
|
|
template <>
|
|
struct is_packed_subbyte<dpf::nyble> : std::true_type {};
|
|
|
|
template <>
|
|
struct packed_lane_bits<dpf::nyble>
|
|
: public std::integral_constant<std::size_t, 4> {};
|
|
|
|
template <>
|
|
struct make_from_integral_value<dpf::nyble>
|
|
{
|
|
using integral_type = std::uint8_t;
|
|
HEDLEY_NO_THROW
|
|
constexpr dpf::nyble operator()(integral_type val) const noexcept
|
|
{
|
|
return dpf::to_nyble(val);
|
|
}
|
|
};
|
|
|
|
} // namespace utils
|
|
|
|
namespace literals
|
|
{
|
|
namespace nyble
|
|
{
|
|
|
|
constexpr dpf::nyble operator""_nyble(unsigned long long x)
|
|
{
|
|
return dpf::to_nyble(x);
|
|
}
|
|
|
|
} // namespace nyble
|
|
} // namespace literals
|
|
|
|
} // namespace dpf
|
|
|
|
namespace std
|
|
{
|
|
|
|
template <>
|
|
class numeric_limits<dpf::nyble> : public numeric_limits<std::uint8_t>
|
|
{
|
|
public:
|
|
static constexpr int digits = 4;
|
|
static constexpr int digits10 = 1;
|
|
HEDLEY_NO_THROW
|
|
static constexpr dpf::nyble min() noexcept { return dpf::nyble::zero; }
|
|
HEDLEY_NO_THROW
|
|
static constexpr dpf::nyble max() noexcept { return dpf::nyble{15}; }
|
|
HEDLEY_NO_THROW
|
|
static constexpr dpf::nyble lowest() noexcept { return min(); }
|
|
};
|
|
|
|
template <>
|
|
class numeric_limits<dpf::nyble const> : public numeric_limits<dpf::nyble> {};
|
|
|
|
template <>
|
|
class numeric_limits<dpf::nyble volatile> : public numeric_limits<dpf::nyble> {};
|
|
|
|
template <>
|
|
class numeric_limits<dpf::nyble const volatile>
|
|
: public numeric_limits<dpf::nyble> {};
|
|
|
|
} // namespace std
|
|
|
|
#endif // LIBDPF_INCLUDE_DPF_NYBLE_HPP__
|