Document the new DPF surfaces in one command set, and test the field, half-tree, and multipoint edges.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Ryan Henry 2026-09-24 23:18:10 -06:00
parent 0d8a5a8131
commit 0dff6df8ed
250 changed files with 12199 additions and 1981 deletions

View file

@ -13,6 +13,7 @@
#define LIBDPF_INCLUDE_DPF_MODINT_HPP__
#include <cstddef>
#include <cstring>
#include <cmath>
#include <type_traits>
#include <functional>
@ -32,6 +33,7 @@ namespace dpf
{
/// @brief represents an unsigned integer modulo `2^Nbits` for small values of `Nbits`
/// @tparam Nbits width in bits
template <std::size_t Nbits>
class modint
{
@ -40,6 +42,7 @@ class modint
using integral_type = dpf::utils::nonvoid_integral_type_from_bitlength_t<Nbits>;
static constexpr std::size_t num_bits = Nbits;
static constexpr bool dpf_modint = true;
/// @brief construct the `modint`
/// @{
@ -78,6 +81,7 @@ class modint
/// @}
/// @brief assign the `modint`
/// @return `*this`
/// @{
/// @brief value assignment
@ -110,10 +114,11 @@ class modint
~modint() = default;
/// @brief addition operator
/// @param rhs the other addend
/// @return the sum
/// @{
/// @details Performs addition with an `integral_type`.
/// @param rhs the other addend
HEDLEY_PURE
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
@ -123,7 +128,6 @@ class modint
}
/// @details Performs addition with another `modint`.
/// @param rhs the other addend
HEDLEY_PURE
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
@ -135,10 +139,11 @@ class modint
/// @}
/// @brief addition-assignment operator
/// @param rhs the other addend
/// @return `*this`
/// @{
/// @details Adds an `integral_type` to this `modint`.
/// @param rhs the other addend
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
constexpr modint & operator+=(integral_type rhs) noexcept
@ -148,7 +153,6 @@ class modint
}
/// @details Adds another `modint` to this one.
/// @param rhs the other addend
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
constexpr modint & operator+=(modint rhs) noexcept
@ -164,6 +168,7 @@ class modint
/// @brief pre-increment operator
/// @details Increments this `modint` and returns a reference to the
/// result.
/// @return `*this`
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
constexpr modint & operator++() noexcept
@ -174,6 +179,7 @@ class modint
/// @brief post-increment operator
/// @details Creates a copy of this `modint`, and then increments this
/// `modint` and returns the copy from before the increment.
/// @return `*this`
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
constexpr modint operator++(int) noexcept
@ -189,6 +195,7 @@ class modint
/// @details Returns the additive inverse modulo `2^Nbits` (two's
/// complement on the underlying word). Required by
/// `grotto::for_each_offset`, which computes `-offset`.
/// @return unary negation
HEDLEY_PURE
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
@ -198,10 +205,11 @@ class modint
}
/// @brief subtraction operator
/// @param rhs the subtrahend
/// @return the difference
/// @{
/// @details Performs subtraction by an `integral_type`.
/// @param rhs the subtrahend
HEDLEY_PURE
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
@ -211,7 +219,6 @@ class modint
}
/// @details Performs subtraction by another `modint`.
/// @param rhs the subtrahend
HEDLEY_PURE
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
@ -223,10 +230,11 @@ class modint
/// @}
/// @brief subtraction-assignment operator
/// @param rhs the subtrahend
/// @return `*this`
/// @{
/// @details Subtracts an `integral_type` from this `modint`.
/// @param rhs the subtrahend
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
constexpr modint & operator-=(integral_type rhs) noexcept
@ -236,7 +244,6 @@ class modint
}
/// @details Subtracts another `modint` from this one.
/// @param rhs the subtrahend
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
constexpr modint & operator-=(modint rhs) noexcept
@ -252,6 +259,7 @@ class modint
/// @brief pre-decrement operator
/// @details Decrements this `modint` and returns a reference to the
/// result.
/// @return `*this`
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
constexpr modint & operator--() noexcept
@ -262,6 +270,7 @@ class modint
/// @brief post-decrement operator
/// @details Creates a copy of this `modint`, and then decrements this
/// `modint` and returns the copy from before the decrement.
/// @return `*this`
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
constexpr modint operator--(int) noexcept
@ -278,6 +287,7 @@ class modint
/// one by `shift_amount` bits to the left. The value of `a<<b`
/// is therefore a `modint` congruent to `a * 2^b` modulo `2^Nbits`.
/// @param shift_amount the number of bits to shift by
/// @return bitwise-left-shift operator
HEDLEY_PURE
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
@ -295,6 +305,7 @@ class modint
/// and returns a reference to the result. Upon invoking `a<<=b`,
/// `a` is congruent to `a * 2^b` modulo `2^Nbits`.
/// @param shift_amount the number of bits to shift by
/// @return `*this`
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
constexpr modint & operator<<=(std::size_t shift_amount) noexcept
@ -311,6 +322,7 @@ class modint
/// one by `shift_amount` bits to the right. The value of `a>>b`
/// is therefore a `modint` equal to the integer part of `a/2^b`.
/// @param shift_amount the number of bits to shift by
/// @return bitwise-right-shift operator
HEDLEY_PURE
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
@ -338,6 +350,8 @@ class modint
}
/// @brief Integer division of the reduced values.
/// @param rhs the right-hand operand
/// @return Integer division of the reduced values
HEDLEY_PURE
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
@ -364,10 +378,11 @@ class modint
}
/// @brief multiplication operator
/// @param rhs the other multiplicand
/// @return the product
/// @{
/// @brief Multiplies this `modint` with an `integral_type`.
/// @param rhs the other multiplicand
HEDLEY_PURE
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
@ -377,7 +392,6 @@ class modint
}
/// @brief Multiplies another `modint` with this one.
/// @param rhs the other multiplicand
HEDLEY_PURE
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
@ -389,10 +403,11 @@ class modint
/// @}
/// @brief multiplication-assignment operator
/// @param rhs the other multiplicand
/// @return `*this`
/// @{
/// @details Multiplies an `integral_type` into this `modint`.
/// @param rhs the other multiplicand
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
constexpr modint & operator*=(integral_type rhs) noexcept
@ -402,7 +417,6 @@ class modint
}
/// @details Multiplies another `modint` into this one.
/// @param rhs the other multiplicand
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
constexpr modint & operator*=(modint rhs) noexcept
@ -532,6 +546,7 @@ class modint
}
/// @brief convert this `modint` to the equivalent `integeral_type`
/// @return the returned `operator`
HEDLEY_PURE
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
@ -572,7 +587,44 @@ class modint
operator<<(std::basic_ostream<CharT, Traits> & os,
const modint & i)
{
return os << i.reduced_value();
const auto raw = i.reduced_value();
using word = std::remove_cv_t<std::decay_t<decltype(raw)>>;
if constexpr (std::is_same_v<word, unsigned __int128>
|| std::is_same_v<word, __int128>)
{
if (raw == 0)
return os << CharT('0');
CharT buf[40];
int n = 0;
auto v = raw;
while (v != 0)
{
buf[n++] = static_cast<CharT>('0' + static_cast<int>(v % 10));
v /= 10;
}
while (n > 0)
os << buf[--n];
return os;
}
else if constexpr (std::is_integral_v<word>)
return os << raw;
else
{
unsigned char bytes[sizeof(word)];
std::memcpy(bytes, &raw, sizeof(word));
os << "0x";
bool started = false;
constexpr char hex[] = "0123456789abcdef";
for (int b = static_cast<int>(sizeof(word)) - 1; b >= 0; --b)
{
if (!started && bytes[static_cast<std::size_t>(b)] == 0 && b != 0)
continue;
started = true;
const auto byte = bytes[static_cast<std::size_t>(b)];
os << hex[byte >> 4] << hex[byte & 0x0f];
}
return os;
}
}
template <typename CharT,
@ -615,8 +667,10 @@ class modint
};
/// @brief Multiplies a `modint<Nbits>` with an `modint::integral_type`.
/// @tparam Nbits width in bits
/// @param lhs the `integral_type` multiplicand
/// @param rhs the `modint` multiplicand
/// @return Multiplies a `modint<Nbits>` with an `modint::integral_type`
template <std::size_t Nbits>
HEDLEY_CONST
HEDLEY_ALWAYS_INLINE
@ -628,9 +682,13 @@ constexpr modint<Nbits> operator*(typename modint<Nbits>::integral_type lhs,
}
/// @brief Compare two `modint<Nbits>`s as if they were regular integers
/// @tparam Nbits width in bits
/// @param lhs the left-hand operand
/// @param rhs the right-hand operand
/// @{
/// @brief less-than operator
/// @return `true` when `lhs < rhs`
template <std::size_t Nbits>
HEDLEY_CONST
HEDLEY_ALWAYS_INLINE
@ -642,6 +700,7 @@ constexpr bool operator<(modint<Nbits> lhs, modint<Nbits> rhs) noexcept
}
/// @brief less-than-or-equal-to operator
/// @return `true` when `lhs <= rhs`
template <std::size_t Nbits>
HEDLEY_CONST
HEDLEY_ALWAYS_INLINE
@ -653,6 +712,7 @@ constexpr bool operator<=(modint<Nbits> lhs, modint<Nbits> rhs) noexcept
}
/// @brief greater-than operator
/// @return `true` when `lhs > rhs`
template <std::size_t Nbits>
HEDLEY_CONST
HEDLEY_ALWAYS_INLINE
@ -664,6 +724,7 @@ constexpr bool operator>(modint<Nbits> lhs, modint<Nbits> rhs) noexcept
}
/// @brief greater-than-or-equal-to operator
/// @return `true` when `lhs >= rhs`
template <std::size_t Nbits>
HEDLEY_CONST
HEDLEY_ALWAYS_INLINE
@ -675,6 +736,7 @@ constexpr bool operator>=(modint<Nbits> lhs, modint<Nbits> rhs) noexcept
}
/// @brief equality operator
/// @return `true` when `lhs == rhs`
template <std::size_t Nbits>
HEDLEY_CONST
HEDLEY_ALWAYS_INLINE
@ -686,6 +748,7 @@ constexpr bool operator==(modint<Nbits> lhs, modint<Nbits> rhs) noexcept
}
/// @brief inequality operator
/// @return `true` when `lhs != rhs`
template <std::size_t Nbits>
HEDLEY_CONST
HEDLEY_ALWAYS_INLINE
@ -1358,6 +1421,7 @@ namespace std
/// @{
/// @details specializes `std::numeric_limits` for `dpf::modint<Nbits>`
/// @tparam Nbits width in bits
template<std::size_t Nbits>
class numeric_limits<dpf::modint<Nbits>>
{
@ -1409,18 +1473,21 @@ class numeric_limits<dpf::modint<Nbits>>
};
/// @details specializes `std::numeric_limits` for `dpf::modint<Nbits> const`
/// @tparam Nbits width in bits
template<std::size_t Nbits>
class numeric_limits<dpf::modint<Nbits> const>
: public numeric_limits<dpf::modint<Nbits>> {};
/// @details specializes `std::numeric_limits` for
/// `dpf::modint<Nbits> volatile`
/// @brief `dpf::modint<Nbits> volatile`
/// @tparam Nbits width in bits
template<std::size_t Nbits>
class numeric_limits<dpf::modint<Nbits> volatile>
: public numeric_limits<dpf::modint<Nbits>> {};
/// @details specializes `std::numeric_limits` for
/// `dpf::modint<Nbits> const volatile`
/// @brief `dpf::modint<Nbits> const volatile`
/// @tparam Nbits width in bits
template<std::size_t Nbits>
class numeric_limits<dpf::modint<Nbits> const volatile>
: public numeric_limits<dpf::modint<Nbits>> {};