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:
parent
0d8a5a8131
commit
0dff6df8ed
250 changed files with 12199 additions and 1981 deletions
|
|
@ -1,6 +1,5 @@
|
|||
/// @file grotto/fixedpoint.hpp
|
||||
/// @brief
|
||||
/// @details
|
||||
/// @brief Fixed-point values stored in an integer backend.
|
||||
/// @author Ryan Henry <ryan.henry@ucalgary.ca>
|
||||
/// @copyright Copyright (c) 2019-2023 Ryan Henry and others
|
||||
/// @license Released under a GNU General Public v2.0 (GPLv2) license;
|
||||
|
|
@ -40,6 +39,8 @@ namespace detail
|
|||
|
||||
/// @brief Integer value of an already-rounded finite double, as a 256-bit word.
|
||||
/// Values that do not fit saturate to all-ones.
|
||||
/// @param rounded the `rounded`
|
||||
/// @return Integer value of an already-rounded finite double, as a 256-bit word
|
||||
HEDLEY_NO_THROW
|
||||
inline uint256_t uint256_from_rounded_double(double rounded) noexcept
|
||||
{
|
||||
|
|
@ -98,7 +99,11 @@ struct is_static_castable<To, From,
|
|||
std::void_t<decltype(static_cast<To>(std::declval<From>()))>>
|
||||
: std::true_type {};
|
||||
|
||||
/// Low `bits` of `wide`, saturated to all-ones when `wide` does not fit.
|
||||
/// @brief Low `bits` of `wide`, saturated to all-ones when `wide` does not fit.
|
||||
/// @tparam Raw underlying representation
|
||||
/// @tparam Bits bits
|
||||
/// @param wide the `wide`
|
||||
/// @return Low `bits` of `wide`, saturated to all-ones when `wide` does not fit
|
||||
template <typename Raw, std::size_t Bits>
|
||||
HEDLEY_NO_THROW
|
||||
Raw saturate_low_bits(uint256_t wide) noexcept
|
||||
|
|
@ -202,8 +207,13 @@ inline IntegralType rounded_double_to_integral(double rounded) noexcept
|
|||
}
|
||||
}
|
||||
|
||||
/// Shift an integer into fixed-point raw form: `value * 2^FractionalBits`,
|
||||
/// @brief Shift an integer into fixed-point raw form: `value * 2^FractionalBits`,
|
||||
/// wrapping in the backend's two's-complement encoding. One shift; no `double`.
|
||||
/// @tparam IntegralType underlying integral type
|
||||
/// @tparam FractionalBits number of fractional bits
|
||||
/// @tparam T value type
|
||||
/// @param integer_value the `integer_value`
|
||||
/// @return the returned `IntegralType`
|
||||
template <typename IntegralType,
|
||||
unsigned FractionalBits,
|
||||
typename T>
|
||||
|
|
@ -227,8 +237,11 @@ inline constexpr bool is_signed_rep_v =
|
|||
std::is_signed_v<IntegralType>
|
||||
|| std::is_same_v<IntegralType, simde_int128>;
|
||||
|
||||
/// Two's-complement negate via the unsigned width. Defined for the
|
||||
/// @brief Two's-complement negate via the unsigned width. Defined for the
|
||||
/// most-negative value (wraps); signed `-x` would be UB there.
|
||||
/// @tparam IntegralType underlying integral type
|
||||
/// @param x the `x`
|
||||
/// @return Two's-complement negate via the unsigned width
|
||||
template <typename IntegralType>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_CONST
|
||||
|
|
@ -253,8 +266,12 @@ constexpr IntegralType raw_abs(IntegralType x) noexcept
|
|||
return x;
|
||||
}
|
||||
|
||||
/// Remainder with the sign of `a` and magnitude `< |b|` (C++ `%` /
|
||||
/// @brief Remainder with the sign of `a` and magnitude `< |b|` (C++ `%` /
|
||||
/// `std::fmod`). Zero divisor → 0; this type has no NaN.
|
||||
/// @tparam IntegralType underlying integral type
|
||||
/// @param a the `a`
|
||||
/// @param b the `b`
|
||||
/// @return Remainder with the sign of `a` and magnitude `< |b|` (C++ `%` / `std::fmod`)
|
||||
template <typename IntegralType>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_CONST
|
||||
|
|
@ -276,7 +293,7 @@ HEDLEY_NO_THROW
|
|||
auto constexpr make_fixed_from_integral_type(IntegralType value) noexcept;
|
||||
|
||||
/// @tparam FractionalBits Number of fractional bits used in the fixed-point
|
||||
/// representation.
|
||||
/// @brief representation.
|
||||
/// @tparam IntegralType The underlying integral type used for the fixed-point
|
||||
/// representation.
|
||||
template <unsigned FractionalBits,
|
||||
|
|
@ -310,18 +327,21 @@ public:
|
|||
|
||||
/// @brief Copy c'tor
|
||||
/// @details Constructs a fixed-point with the value copied from `other`.
|
||||
/// @param other the value to compare or copy
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr fixedpoint(const fixedpoint & other) noexcept = default;
|
||||
|
||||
/// @brief Move c'tor
|
||||
/// @details Constructs a fixed-point with the value copied from `other` using move semantics.
|
||||
/// @param other the value to compare or copy
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr fixedpoint(fixedpoint && other) noexcept = default;
|
||||
|
||||
/// @brief Value c'tor
|
||||
/// @details Initializes the fixed-point with the value determined by `desired`, using the <a href="https://en.cppreference.com/w/cpp/numeric/fenv/FE_round">current rounding mode</a> for the least-significant bit.
|
||||
/// @param desired the `desired`
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr fixedpoint(double desired) noexcept // NOLINT (implicit c'tor)
|
||||
|
|
@ -333,6 +353,9 @@ public:
|
|||
/// @details `fixedpoint(3)` is the mathematical value 3 (raw encoding
|
||||
/// `3 << fractional_bits`), not a raw word. One shift; no `double`.
|
||||
/// Use `from_raw` for a bit-exact encoding.
|
||||
/// @tparam T value type
|
||||
/// @tparam T value type
|
||||
/// @param integer_value the `integer_value`
|
||||
template <typename T,
|
||||
std::enable_if_t<
|
||||
std::is_integral_v<T>
|
||||
|
|
@ -345,6 +368,8 @@ public:
|
|||
{ }
|
||||
|
||||
/// @brief Bit-exact construction from the backend integer encoding.
|
||||
/// @param raw the underlying integer
|
||||
/// @return Bit-exact construction from the backend integer encoding
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr fixedpoint from_raw(integral_type raw) noexcept
|
||||
|
|
@ -354,24 +379,30 @@ public:
|
|||
|
||||
/// @}
|
||||
|
||||
/// @name Assignment operators
|
||||
/// @brief Assign a new value to a fixed-point number
|
||||
/// {@
|
||||
/// @name Assignment operators
|
||||
/// @brief Assign a new value to a fixed-point number
|
||||
/// @{
|
||||
|
||||
/// @brief Copy assignment
|
||||
/// @details Assigns the fixed-point with a copy of `other`
|
||||
/// @param other the value to compare or copy
|
||||
/// @return `*this`
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr fixedpoint & operator=(const fixedpoint & other) noexcept = default;
|
||||
|
||||
/// @brief Move assignment
|
||||
/// @details Assigns the fixed-point with a copy of `other` using move semantics.
|
||||
/// @param other the value to compare or copy
|
||||
/// @return `*this`
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr fixedpoint & operator=(fixedpoint && other) noexcept = default;
|
||||
|
||||
/// @brief Value assignment
|
||||
/// @details Assigns the fixed-point with a value determined by `desired`, using the <a href="https://en.cppreference.com/w/cpp/numeric/fenv/FE_round">current rounding mode</a> for the least-significant bit..
|
||||
/// @param desired the `desired`
|
||||
/// @return `*this`
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr fixedpoint & operator=(const double & desired) noexcept
|
||||
|
|
@ -386,6 +417,7 @@ public:
|
|||
~fixedpoint() = default;
|
||||
|
||||
/// @brief Cast to `double`
|
||||
/// @return Cast to `double`
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_PURE
|
||||
|
|
@ -402,8 +434,11 @@ public:
|
|||
return static_cast<bool>(this->integral_representation() & mask);
|
||||
}
|
||||
|
||||
/// Bit test against another encoding (DPF writes `mask & x` with both
|
||||
/// @brief Bit test against another encoding (DPF writes `mask & x` with both
|
||||
/// sides the input type when `msb_mask` is a `fixedpoint`).
|
||||
/// @param mask the bit mask
|
||||
/// @return Bit test against another encoding (DPF writes `mask & x` with both sides the input
|
||||
/// type when `msb_mask` is a `fixedpoint`)
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_PURE
|
||||
|
|
@ -412,7 +447,8 @@ public:
|
|||
return static_cast<bool>(value & mask.value);
|
||||
}
|
||||
|
||||
/// Bitwise complement of the encoding. `std::bit_not` uses this.
|
||||
/// @brief Bitwise complement of the encoding. `std::bit_not` uses this.
|
||||
/// @return Bitwise complement of the encoding
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_PURE
|
||||
|
|
@ -423,7 +459,8 @@ public:
|
|||
~static_cast<unsigned_type>(value)));
|
||||
}
|
||||
|
||||
/// Next / previous representable encoding (one ULP).
|
||||
/// @brief Next / previous representable encoding (one ULP).
|
||||
/// @return `*this`
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr fixedpoint & operator++() noexcept
|
||||
|
|
@ -458,7 +495,7 @@ public:
|
|||
return tmp;
|
||||
}
|
||||
|
||||
/// Logical shift of the encoding. DPF walks `msb_mask` with `>>`; a
|
||||
/// @brief Logical shift of the encoding. DPF walks `msb_mask` with `>>`; a
|
||||
/// signed arithmetic shift would sign-extend the MSB and break that.
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
|
|
@ -497,6 +534,7 @@ public:
|
|||
/// @brief Access underlying integral representation
|
||||
/// @details If the represented fixed-point number is `x`, then this
|
||||
/// function returns an `integral_type` whose value is `x*2**fractional_bits`.
|
||||
/// @return Access underlying integral representation
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_PURE
|
||||
|
|
@ -506,6 +544,7 @@ public:
|
|||
}
|
||||
|
||||
/// @brief Unary negation operator
|
||||
/// @return Unary negation operator
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_PURE
|
||||
|
|
@ -516,6 +555,8 @@ public:
|
|||
|
||||
/// @brief Binary addition operator
|
||||
/// @details Computes the sum of two fixed-point numbers
|
||||
/// @param rhs the right-hand operand
|
||||
/// @return Binary addition operator
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_PURE
|
||||
|
|
@ -525,6 +566,8 @@ public:
|
|||
}
|
||||
|
||||
/// @brief Binary addition assignment operator
|
||||
/// @param rhs the right-hand operand
|
||||
/// @return `*this`
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr fixedpoint & operator+=(fixedpoint rhs) noexcept
|
||||
|
|
@ -534,6 +577,8 @@ public:
|
|||
}
|
||||
|
||||
/// @brief Binary subtraction operator
|
||||
/// @param rhs the right-hand operand
|
||||
/// @return Binary subtraction operator
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
HEDLEY_PURE
|
||||
|
|
@ -543,6 +588,8 @@ public:
|
|||
}
|
||||
|
||||
/// @brief Binary addition assignment operator
|
||||
/// @param rhs the right-hand operand
|
||||
/// @return `*this`
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
constexpr fixedpoint & operator-=(fixedpoint rhs) noexcept
|
||||
|
|
@ -552,6 +599,9 @@ public:
|
|||
}
|
||||
|
||||
/// @brief Binary multiplication operator
|
||||
/// @tparam FractionalBits1 fractional bits1
|
||||
/// @param rhs the right-hand operand
|
||||
/// @return Binary multiplication operator
|
||||
template <unsigned FractionalBits1>
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
|
|
@ -701,6 +751,8 @@ public:
|
|||
// struct make_fixed_from_integral_type_tag {};
|
||||
|
||||
/// @brief Determine if a floating-point is within range
|
||||
/// @param d the `d`
|
||||
/// @return Determine if a floating-point is within range
|
||||
HEDLEY_ALWAYS_INLINE
|
||||
HEDLEY_NO_THROW
|
||||
static constexpr bool is_in_range(double d) noexcept
|
||||
|
|
@ -734,6 +786,12 @@ public:
|
|||
|
||||
/// @brief Bit test with the mask on the left. DPF key generation and
|
||||
/// evaluation write `mask & x`.
|
||||
/// @tparam FractionalBits number of fractional bits
|
||||
/// @tparam IntegralType underlying integral type
|
||||
/// @tparam Mask mask
|
||||
/// @param mask the bit mask
|
||||
/// @param x the `x`
|
||||
/// @return Bit test with the mask on the left
|
||||
template <unsigned FractionalBits,
|
||||
typename IntegralType,
|
||||
typename Mask>
|
||||
|
|
@ -797,7 +855,11 @@ static constexpr auto make_fixed(double d)
|
|||
}
|
||||
|
||||
/// @brief Creates a fixed-point number from a double with bounds checking.
|
||||
/// @throws std::range_error If the input double is outside the representable
|
||||
/// @tparam FractionalBits number of fractional bits
|
||||
/// @tparam IntegralType underlying integral type
|
||||
/// @param d the `d`
|
||||
/// @return Creates a fixed-point number from a double with bounds checking
|
||||
/// @throws std::range_error if the input double is outside the representable
|
||||
/// range of the fixed-point number.
|
||||
template <unsigned FractionalBits,
|
||||
typename IntegralType = GROTTO_FIXED_DEFAULT_INTEGRAL_REPRESENTATION>
|
||||
|
|
@ -1562,6 +1624,8 @@ struct flip_msb_for_input<grotto::fixedpoint<FractionalBits, IntegralType>>
|
|||
namespace dpf::leaf_arithmetic
|
||||
{
|
||||
|
||||
HEDLEY_PRAGMA(GCC diagnostic push)
|
||||
HEDLEY_PRAGMA(GCC diagnostic ignored "-Wignored-attributes")
|
||||
template <unsigned FractionalBits, typename IntegralType>
|
||||
struct add_t<grotto::fixedpoint<FractionalBits, IntegralType>, simde__m128i>
|
||||
{
|
||||
|
|
@ -1617,6 +1681,7 @@ struct multiply_t<grotto::fixedpoint<FractionalBits, IntegralType>, simde__m256i
|
|||
return multiply_t<IntegralType, simde__m256i>{}(a, b.integral_representation());
|
||||
}
|
||||
};
|
||||
HEDLEY_PRAGMA(GCC diagnostic pop)
|
||||
|
||||
} // namespace dpf::leaf_arithmetic
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue