11#include <native/attributes.h>
12#include <ftz/config.h>
28#if defined(__FAST_MATH__)
29#error Reproducible ftz32 requires ordinary expression contraction and fast math disabled
63 template <
bool Hardware>
65 static constexpr bool hardware = Hardware;
70 : bits_(detail::ftz32_canonical(std::bit_cast<
unsigned int>(value))) {}
72 [[nodiscard]]
constexpr native_inline native_pure
operator float() const noexcept {
return to_float(); }
79 return canonical(std::bit_cast<unsigned int>(value));
82 [[nodiscard]]
static constexpr native_inline native_const
basic_ftz32 from_bits(
unsigned int bits)
noexcept {
83 return canonical(detail::ftz32_canonical(bits));
86 [[nodiscard]]
constexpr native_inline native_pure
float to_float() const noexcept {
return std::bit_cast<float>(bits_); }
88 [[nodiscard]]
constexpr native_inline native_pure
unsigned int to_bits() const noexcept {
return bits_; }
92 return canonical(detail::ftz32_add<Hardware>(a.bits_, b.bits_));
97 return canonical(detail::ftz32_sub<Hardware>(a.bits_, b.bits_));
102 return canonical(detail::ftz32_mul(a.bits_, b.bits_));
107 return canonical(detail::ftz32_div<Hardware>(a.bits_, b.bits_));
134 unsigned int bits_ = 0u;
135 [[nodiscard]]
static constexpr native_inline native_const
basic_ftz32 canonical(
unsigned int bits)
noexcept {
136 basic_ftz32 result; result.bits_ = bits;
return result;
149 static_assert(
sizeof(
m32)==
sizeof(float) &&
sizeof(
h32)==
sizeof(float));
150 static_assert(std::is_trivially_copyable_v<m32> && std::is_trivially_copyable_v<h32>);
153 template <
class T>
inline constexpr bool is_ftz32 =
false;
159 template <
class T>
struct policy_of {
static constexpr int value = -1; };
160 template <
bool H>
struct policy_of<
basic_ftz32<H>> {
static constexpr int value = H; };
161 template <
class T>
requires requires {
typename T::value_type; }
162 struct policy_of<T> : policy_of<typename T::value_type> {};
163 template <
class A,
class B>
concept mixed_policy =
164 policy_of<std::remove_cvref_t<A>>::value >= 0 && policy_of<std::remove_cvref_t<B>>::value >= 0 &&
165 policy_of<std::remove_cvref_t<A>>::value != policy_of<std::remove_cvref_t<B>>::value;
171 template <
class A,
class B>
requires detail::mixed_policy<A,B>
void operator+(A,B) =
delete;
173 template <
class A,
class B>
requires detail::mixed_policy<A,B>
void operator-(A,B) =
delete;
175 template <
class A,
class B>
requires detail::mixed_policy<A,B>
void operator*(A,B) =
delete;
177 template <
class A,
class B>
requires detail::mixed_policy<A,B>
void operator/(A,B) =
delete;
179 template <
class A,
class B>
requires detail::mixed_policy<A,B>
void operator==(A,B) =
delete;
181 template <
class A,
class B>
requires detail::mixed_policy<A,B>
void operator!=(A,B) =
delete;
183 template <
class A,
class B>
requires detail::mixed_policy<A,B>
void operator<(A,B) =
delete;
185 template <
class A,
class B>
requires detail::mixed_policy<A,B>
void operator>(A,B) =
delete;
187 template <
class A,
class B>
requires detail::mixed_policy<A,B>
void operator<=(A,B) =
delete;
189 template <
class A,
class B>
requires detail::mixed_policy<A,B>
void operator>=(A,B) =
delete;
191 template <
class A,
class B>
requires detail::mixed_policy<A,B>
void operator<=>(A,B) =
delete;
193 template <
class A,
class B>
requires detail::mixed_policy<A,B>
void operator+=(A &,B) =
delete;
195 template <
class A,
class B>
requires detail::mixed_policy<A,B>
void operator-=(A &,B) =
delete;
197 template <
class A,
class B>
requires detail::mixed_policy<A,B>
void operator*=(A &,B) =
delete;
199 template <
class A,
class B>
requires detail::mixed_policy<A,B>
void operator/=(A &,B) =
delete;
202 template <
class A,
class B>
requires detail::mixed_policy<A,B>
void atan2(A,B) =
delete;
205 template <
class A,
class B>
requires detail::mixed_policy<A,B>
void copysign(A,B) =
delete;
208 template <
class A,
class B>
requires detail::mixed_policy<A,B>
void min(A,B) =
delete;
211 template <
class A,
class B>
requires detail::mixed_policy<A,B>
void max(A,B) =
delete;
214 template <
class A,
class B>
requires detail::mixed_policy<A,B>
void scaleb(A,B) =
delete;
217 template <
class A,
class B,
class C>
requires (detail::mixed_policy<A,B> || detail::mixed_policy<A,C> || detail::mixed_policy<B,C>)
218 void fma(A,B,C) =
delete;
221 template <
class M,
class A,
class B>
requires detail::mixed_policy<A,B>
void select(M,A,B) =
delete;
224 template <
class M,
class A,
class B,
class E>
requires (detail::mixed_policy<A,B> || detail::mixed_policy<A,E> || detail::mixed_policy<B,E>)
225 void masked_scaleb(M,A,B,E) =
delete;
228 template <
class M,
class A,
class E>
requires detail::mixed_policy<A,E>
void masked_scaleb_zero(M,A,E) =
delete;
259 template <
bool Hardware, ftz32_scalar T> [[nodiscard]]
constexpr native_inline native_const
bool operator<(
basic_ftz32<Hardware> a, T b)
noexcept {
return a < basic_ftz32<Hardware>(
static_cast<float>(b)); }
267 template <
bool Hardware, ftz32_scalar T> [[nodiscard]]
constexpr native_inline native_const
bool operator<=(
basic_ftz32<Hardware> a, T b)
noexcept {
return a <= basic_ftz32<Hardware>(
static_cast<float>(b)); }
278 template <
bool Hardware>
286 template <
bool Hardware>
292 template <
bool Hardware>
298 template <
bool Hardware>
304 template <
bool Hardware>
310 template <
bool Hardware>
317 template <
unsigned int Degree = 6,
bool Hardware>
requires (Degree >= 1 && Degree <= 7)
323 template <
bool Hardware,
bool Flush,
unsigned int Degree>
requires (!Flush && Degree >= 1 && Degree <= 7)
328 template <
bool Hardware>
334 template <
bool Hardware>
340 template <
bool Hardware>
348 template <
bool Hardware>
354 template <
bool Hardware>
357 namespace fp = ::native::detail::constexpr_float;
359 a.
to_bits(), fp::rounding::downward));
367 template <
bool Hardware>
370 namespace fp = ::native::detail::constexpr_float;
372 a.
to_bits(), fp::rounding::upward));
380 template <
bool Hardware>
383 namespace fp = ::native::detail::constexpr_float;
385 a.
to_bits(), fp::rounding::toward_zero));
392 template <
bool Hardware>
397 template <
bool Hardware>
402 template <
bool Hardware>
407 template <
bool Hardware>
412 template <
bool Hardware>
417 template <
bool Hardware>
423 template <
bool Hardware>
431 template <
class T>
concept scalar_argument = !ftz32_type<T> &&
432 (std::is_arithmetic_v<std::remove_cvref_t<T>> ||
433 (std::convertible_to<T,m32> != std::convertible_to<T,h32>));
434 template <
class T>
using scalar_argument_t = std::conditional_t<
435 std::is_arithmetic_v<std::remove_cvref_t<T>>,
ftz32,
436 std::conditional_t<std::convertible_to<T,m32>,
m32,
h32>>;
442 template <
class T>
requires detail::scalar_argument<T &&>
443 [[nodiscard]]
constexpr native_inline
auto sin(T && a)
444 noexcept(
noexcept(
sin(detail::scalar_argument_t<T &&>(std::forward<T>(a))))) {
445 return sin(detail::scalar_argument_t<T &&>(std::forward<T>(a)));
451 template <
class T>
requires detail::scalar_argument<T &&>
452 [[nodiscard]]
constexpr native_inline
auto cos(T && a)
453 noexcept(
noexcept(
cos(detail::scalar_argument_t<T &&>(std::forward<T>(a))))) {
454 return cos(detail::scalar_argument_t<T &&>(std::forward<T>(a)));
460 template <
class T>
requires detail::scalar_argument<T &&>
461 [[nodiscard]]
constexpr native_inline
auto sincos(T && a)
462 noexcept(
noexcept(
sincos(detail::scalar_argument_t<T &&>(std::forward<T>(a))))) {
463 return sincos(detail::scalar_argument_t<T &&>(std::forward<T>(a)));
469 template <
class T>
requires detail::scalar_argument<T &&>
470 [[nodiscard]]
constexpr native_inline
auto tanh(T && a)
471 noexcept(
noexcept(
tanh(detail::scalar_argument_t<T &&>(std::forward<T>(a))))) {
472 return tanh(detail::scalar_argument_t<T &&>(std::forward<T>(a)));
478 template <
class T>
requires detail::scalar_argument<T &&>
479 [[nodiscard]]
constexpr native_inline
auto log(T && a)
480 noexcept(
noexcept(
log(detail::scalar_argument_t<T &&>(std::forward<T>(a))))) {
481 return log(detail::scalar_argument_t<T &&>(std::forward<T>(a)));
487 template <
class T>
requires detail::scalar_argument<T &&>
488 [[nodiscard]]
constexpr native_inline
auto log1p(T && a)
489 noexcept(
noexcept(
log1p(detail::scalar_argument_t<T &&>(std::forward<T>(a))))) {
490 return log1p(detail::scalar_argument_t<T &&>(std::forward<T>(a)));
496 template <
unsigned int Degree = 6,
class T>
requires (detail::scalar_argument<T &&> && Degree >= 1 && Degree <= 7)
497 [[nodiscard]]
constexpr native_inline
auto exp(T && a)
498 noexcept(
noexcept(
exp<Degree>(detail::scalar_argument_t<T &&>(std::forward<T>(a))))) {
499 return exp<Degree>(detail::scalar_argument_t<T &&>(std::forward<T>(a)));
504 template <
class T>
requires detail::scalar_argument<T &&>
505 [[nodiscard]]
constexpr native_inline
auto expm1(T && a)
506 noexcept(
noexcept(
expm1(detail::scalar_argument_t<T &&>(std::forward<T>(a))))) {
507 return expm1(detail::scalar_argument_t<T &&>(std::forward<T>(a)));
513 template <
class T>
requires detail::scalar_argument<T &&>
514 [[nodiscard]]
constexpr native_inline
auto sqrt(T && a)
515 noexcept(
noexcept(
sqrt(detail::scalar_argument_t<T &&>(std::forward<T>(a))))) {
516 return sqrt(detail::scalar_argument_t<T &&>(std::forward<T>(a)));
522 template <
class T>
requires detail::scalar_argument<T &&>
523 [[nodiscard]]
constexpr native_inline
auto floor(T && a)
524 noexcept(
noexcept(
floor(detail::scalar_argument_t<T &&>(std::forward<T>(a))))) {
525 return floor(detail::scalar_argument_t<T &&>(std::forward<T>(a)));
531 template <
class T>
requires detail::scalar_argument<T &&>
532 [[nodiscard]]
constexpr native_inline
auto ceil(T && a)
533 noexcept(
noexcept(
ceil(detail::scalar_argument_t<T &&>(std::forward<T>(a))))) {
534 return ceil(detail::scalar_argument_t<T &&>(std::forward<T>(a)));
540 template <
class T>
requires detail::scalar_argument<T &&>
541 [[nodiscard]]
constexpr native_inline
auto trunc(T && a)
542 noexcept(
noexcept(
trunc(detail::scalar_argument_t<T &&>(std::forward<T>(a))))) {
543 return trunc(detail::scalar_argument_t<T &&>(std::forward<T>(a)));
548 template <
class T>
requires detail::scalar_argument<T &&>
549 [[nodiscard]]
constexpr native_inline
auto abs(T && a)
550 noexcept(
noexcept(
abs(detail::scalar_argument_t<T &&>(std::forward<T>(a))))) {
551 return abs(detail::scalar_argument_t<T &&>(std::forward<T>(a)));
556 template <
class T>
requires detail::scalar_argument<T &&>
557 [[nodiscard]]
constexpr native_inline
auto neg(T && a)
558 noexcept(
noexcept(
neg(detail::scalar_argument_t<T &&>(std::forward<T>(a))))) {
559 return neg(detail::scalar_argument_t<T &&>(std::forward<T>(a)));
564 template <
class T>
requires detail::scalar_argument<T &&>
565 [[nodiscard]]
constexpr native_inline
auto isnan(T && a)
566 noexcept(
noexcept(
isnan(detail::scalar_argument_t<T &&>(std::forward<T>(a))))) {
567 return isnan(detail::scalar_argument_t<T &&>(std::forward<T>(a)));
572 template <
class T>
requires detail::scalar_argument<T &&>
573 [[nodiscard]]
constexpr native_inline
auto isinf(T && a)
574 noexcept(
noexcept(
isinf(detail::scalar_argument_t<T &&>(std::forward<T>(a))))) {
575 return isinf(detail::scalar_argument_t<T &&>(std::forward<T>(a)));
580 template <
class T>
requires detail::scalar_argument<T &&>
581 [[nodiscard]]
constexpr native_inline
auto isfinite(T && a)
582 noexcept(
noexcept(
isfinite(detail::scalar_argument_t<T &&>(std::forward<T>(a))))) {
583 return isfinite(detail::scalar_argument_t<T &&>(std::forward<T>(a)));
588 template <
class T>
requires detail::scalar_argument<T &&>
589 [[nodiscard]]
constexpr native_inline
auto signbit(T && a)
590 noexcept(
noexcept(
signbit(detail::scalar_argument_t<T &&>(std::forward<T>(a))))) {
591 return signbit(detail::scalar_argument_t<T &&>(std::forward<T>(a)));
595 template <
class T>
inline constexpr int scalar_policy = [] {
596 if constexpr (ftz32_type<T>)
return int(std::remove_cvref_t<T>::hardware);
597 else if constexpr (std::is_arithmetic_v<std::remove_cvref_t<T>>)
return -1;
598 else if constexpr (std::convertible_to<T,m32> != std::convertible_to<T,h32>)
599 return int(std::convertible_to<T,h32>);
602 template <
class... T>
concept scalar_arguments = ((scalar_policy<T> >= -1) && ...) &&
603 !(((scalar_policy<T> == 0) || ...) && ((scalar_policy<T> == 1) || ...));
604 template <
class... T>
using scalar_arguments_t = std::conditional_t<
605 ((scalar_policy<T> == 0) || ...),
m32,
606 std::conditional_t<((scalar_policy<T> == 1) || ...),
h32,
ftz32>>;
611 template <
class A,
class B,
class C>
requires detail::scalar_arguments<A &&,B &&,C &&> &&
613 [[nodiscard]]
constexpr native_inline
auto fma(A && a,B && b,C && c)
614 noexcept(
noexcept(
fma(detail::scalar_arguments_t<A &&,B &&,C &&>(std::forward<A>(a)),
615 detail::scalar_arguments_t<A &&,B &&,C &&>(std::forward<B>(b)),
616 detail::scalar_arguments_t<A &&,B &&,C &&>(std::forward<C>(c))))) {
617 using F=detail::scalar_arguments_t<A &&,B &&,C &&>;
618 return fma(F(std::forward<A>(a)),F(std::forward<B>(b)),F(std::forward<C>(c)));
624 template <
class A,
class B>
requires detail::scalar_arguments<A &&,B &&> &&
625 (!(ftz32_type<A> && ftz32_type<B>))
626 [[nodiscard]]
constexpr native_inline
auto atan2(A && a,B && b)
627 noexcept(
noexcept(
atan2(detail::scalar_arguments_t<A &&,B &&>(std::forward<A>(a)),
628 detail::scalar_arguments_t<A &&,B &&>(std::forward<B>(b))))) {
629 using F=detail::scalar_arguments_t<A &&,B &&>;
630 return atan2(F(std::forward<A>(a)),F(std::forward<B>(b)));
636 template <
class A,
class B>
requires detail::scalar_arguments<A &&,B &&> &&
637 (!(ftz32_type<A> && ftz32_type<B>))
638 [[nodiscard]]
constexpr native_inline
auto copysign(A && a,B && b)
639 noexcept(
noexcept(
copysign(detail::scalar_arguments_t<A &&,B &&>(std::forward<A>(a)),
640 detail::scalar_arguments_t<A &&,B &&>(std::forward<B>(b))))) {
641 using F=detail::scalar_arguments_t<A &&,B &&>;
642 return copysign(F(std::forward<A>(a)),F(std::forward<B>(b)));
649namespace ftz::detail {
650 using ::ftz::detail::ftz32_cpu_witness;
651 using ::ftz::detail::ftz32_cpu_path;
654 template <
bool Hardware>
657#elif defined(__GNUC__) || defined(__clang__)
658 __attribute__((noinline))
660 inline unsigned int ftz32_cpu_evaluate(ftz32_cpu_witness row, ftz32_cpu_path path) {
661 volatile unsigned int a_word = row.a, b_word = row.b, c_word = row.c;
662 unsigned int a = a_word, b = b_word, c = c_word;
663 if (path != ftz32_cpu_path::raw) {
667 auto add = [path](
unsigned int x,
unsigned int y) {
668 return path == ftz32_cpu_path::explicit_core ? ftz32_add_policy<false>(x,y) : ftz32_add<Hardware>(x,y);
670 switch (row.operation) {
671 case 0:
return add(a,b);
672 case 1:
return ftz32_mul(a,b);
673 case 2:
return ftz32_fma(a,b,c);
674 case 3:
return add(ftz32_mul(a,b),c);
675 default:
return ftz32_canonical(a);
678 float x = std::bit_cast<float>(a), y = std::bit_cast<float>(b), z = std::bit_cast<float>(c);
679 switch (row.operation) {
680 case 0:
return std::bit_cast<unsigned int>(x+y);
681 case 1:
return std::bit_cast<unsigned int>(x*y);
682 case 2:
return std::bit_cast<unsigned int>(std::fma(x,y,z));
685 return std::bit_cast<unsigned int>(product+z);
691export namespace ftz {
705 template <ftz32_type T = ftz32>
707 return ::ftz::detail::ftz32_cpu_probe(detail::ftz32_cpu_evaluate<T::hardware>, T::hardware);
Accepts built-in arithmetic operands for conversion into a chosen FTZ policy.
Accepts either scalar policy after removing cv/ref qualifiers.
Shared FTZ scalar operators and math, including special values and full-range trig reduction.
ftz32_cpu_admission probe_ftz32_cpu()
Observes whether this compiled scalar profile meets the requested policy.
constexpr basic_ftz32< Hardware > neg(basic_ftz32< Hardware > a) noexcept
Flips the sign bit without floating-point arithmetic.
constexpr basic_ftz32< Hardware > abs(basic_ftz32< Hardware > a) noexcept
Clears the sign bit without floating-point arithmetic.
constexpr basic_ftz32< Hardware > sqrt(basic_ftz32< Hardware > a) noexcept
Returns the reciprocal-refined square-root approximation; signed zero and positive infinity are prese...
constexpr std::array< R, N > log1p(std::array< R, N > const &input) noexcept
Computes log(1+x), preserving signed zero; -1 gives negative infinity and x < -1 gives NaN....
constexpr std::array< R, N > add(std::array< R, N > const &a, std::array< R, N > const &b) noexcept
Adds matching register arrays; a non-array operand is converted once and broadcast,...
constexpr std::array< R, N > log(std::array< R, N > const &input) noexcept
Computes natural logarithms; either zero gives negative infinity, negative nonzero values give NaN....
constexpr std::array< R, N > atan2(std::array< R, N > const &y, std::array< R, N > const &x) noexcept
Computes atan2(y,x) in radians with the scalar FTZ signed-axis and infinity rules....
constexpr std::array< R, N > tanh(std::array< R, N > const &input) noexcept
Computes hyperbolic tangent with the scalar FTZ graph, preserving signed zero and saturating infiniti...
basic_ftz32< true > h32
Hardware-normalization value; arithmetic requires a qualified flush region.
basic_ftz32< false > m32
Explicit-normalization value; arithmetic supports gradual and admitted flush regions.
constexpr bool is_ftz32
Identifies the two unqualified FTZ scalar types. Use ftz32_type to ignore cv/ref.
basic_ftz32< FTZ_FP32_HARDWARE_FTZ !=0 > ftz32
Compatibility alias selected by the installed FTZ_FP32_HARDWARE_FTZ package setting....
constexpr R trunc(R value) noexcept
Rounds toward zero, independently of ambient rounding mode; signed zero and infinities survive....
constexpr R::mask isfinite(R value) noexcept
Returns R::mask for finite lanes by inspecting words, without changing FP status.
constexpr R::mask isinf(R value) noexcept
Returns R::mask for either infinity by inspecting lane words.
constexpr auto operator!=(V a, basic_ftz32< Hardware > b) noexcept
Imports the raw register into the scalar operand's FTZ policy and returns the native comparison mask.
constexpr R floor(R value) noexcept
Rounds toward negative infinity, independently of ambient rounding mode; signed zero and infinities s...
constexpr R cos(R input) noexcept
Computes cosine in radians with dedicated output reconstruction and the scalar FTZ special-value rule...
constexpr V & operator+=(V &a, basic_ftz32< Hardware > b) noexcept
Evaluates FTZ arithmetic before assigning to the existing raw-register destination.
constexpr auto operator>=(V a, basic_ftz32< Hardware > b) noexcept
Imports the raw register into the scalar operand's FTZ policy and returns the native comparison mask.
constexpr R::mask signbit(R value) noexcept
Returns R::mask for set sign bits, including negative zero and signed NaNs.
constexpr auto operator==(V a, basic_ftz32< Hardware > b) noexcept
Imports the raw register into the scalar operand's FTZ policy and returns the native comparison mask.
constexpr V & operator-=(V &a, basic_ftz32< Hardware > b) noexcept
Evaluates FTZ arithmetic before assigning to the existing raw-register destination.
constexpr auto operator>(V a, basic_ftz32< Hardware > b) noexcept
Imports the raw register into the scalar operand's FTZ policy and returns the native comparison mask.
constexpr auto operator/(V a, basic_ftz32< Hardware > b) noexcept
Imports the raw register into the scalar operand's FTZ policy and returns its FTZ vector rebind.
constexpr R expm1(R input) noexcept
Computes exp(x)-1 with the scalar FTZ graph, preserving signed zero. Returns R.
constexpr auto operator*(V a, basic_ftz32< Hardware > b) noexcept
Imports the raw register into the scalar operand's FTZ policy and returns its FTZ vector rebind.
constexpr auto sincos(R input) noexcept
Computes sine and cosine in radians with the scalar special-value rules; returns a pair in that order...
constexpr R exp(R input) noexcept
Computes the exponential with the scalar FTZ underflow, overflow and special-value rules....
constexpr R ceil(R value) noexcept
Rounds toward positive infinity, independently of ambient rounding mode; signed zero and infinities s...
constexpr V & operator*=(V &a, basic_ftz32< Hardware > b) noexcept
Evaluates FTZ arithmetic before assigning to the existing raw-register destination.
constexpr R::mask isnan(R value) noexcept
Returns R::mask for NaN lanes by inspecting words; no FP evaluation or NaN quieting occurs.
constexpr auto fma(A a, B b, C c) noexcept(std::is_nothrow_constructible_v< detail::ftz32_simd< detail::raw_family_t< A, B, C >, detail::scalar_family_t< A, B, C > >, A & > &&std::is_nothrow_constructible_v< detail::ftz32_simd< detail::raw_family_t< A, B, C >, detail::scalar_family_t< A, B, C > >, B & > &&std::is_nothrow_constructible_v< detail::ftz32_simd< detail::raw_family_t< A, B, C >, detail::scalar_family_t< A, B, C > >, C & >)
Imports raw SIMD operands into the FTZ scalar operand's policy and evaluates fused a*b+c....
constexpr R sin(R input) noexcept
Computes sine in radians with dedicated output reconstruction and the scalar FTZ special-value rules....
constexpr auto operator<(V a, basic_ftz32< Hardware > b) noexcept
Imports the raw register into the scalar operand's FTZ policy and returns the native comparison mask.
constexpr auto operator-(V a, basic_ftz32< Hardware > b) noexcept
Imports the raw register into the scalar operand's FTZ policy and returns its FTZ vector rebind.
constexpr auto operator<=(V a, basic_ftz32< Hardware > b) noexcept
Imports the raw register into the scalar operand's FTZ policy and returns the native comparison mask.
constexpr auto operator+(V a, basic_ftz32< Hardware > b) noexcept
Imports the raw register into the scalar operand's FTZ policy and returns its FTZ vector rebind.
constexpr V & operator/=(V &a, basic_ftz32< Hardware > b) noexcept
Evaluates FTZ arithmetic before assigning to the existing raw-register destination.
constexpr R copysign(R magnitude, R sign) noexcept
Returns magnitude with the sign bits of sign; all other words, including NaN payloads,...
Binary32 value with a compile-time signed-FTZ policy.
static constexpr basic_ftz32 from_float(float value) noexcept
Imports and normalizes a float, as the converting constructor does.
constexpr basic_ftz32 & operator+=(basic_ftz32 b) noexcept
Assigns the corresponding FTZ result and returns this value by reference.
friend constexpr bool operator<=(basic_ftz32 a, basic_ftz32 b) noexcept
Compares values; NaN is unordered (only != is true), and the two zero signs compare equal.
friend constexpr bool operator>(basic_ftz32 a, basic_ftz32 b) noexcept
Compares values; NaN is unordered (only != is true), and the two zero signs compare equal.
constexpr unsigned int to_bits() const noexcept
Exports the exact stored word, including zero sign and NaN payload.
constexpr basic_ftz32() noexcept=default
Constructs positive zero.
friend constexpr bool operator==(basic_ftz32 a, basic_ftz32 b) noexcept
Compares values; NaN is unordered (only != is true), and the two zero signs compare equal.
constexpr basic_ftz32 & operator-=(basic_ftz32 b) noexcept
Assigns the corresponding FTZ result and returns this value by reference.
constexpr basic_ftz32 & operator/=(basic_ftz32 b) noexcept
Assigns the corresponding FTZ result and returns this value by reference.
friend constexpr basic_ftz32 operator+(basic_ftz32 a) noexcept
Returns the value unchanged.
friend constexpr bool operator!=(basic_ftz32 a, basic_ftz32 b) noexcept
Compares values; NaN is unordered (only != is true), and the two zero signs compare equal.
friend constexpr bool operator>=(basic_ftz32 a, basic_ftz32 b) noexcept
Compares values; NaN is unordered (only != is true), and the two zero signs compare equal.
static constexpr basic_ftz32 unsafe_from_float32(float value) noexcept
Wraps float bits without classification or normalization.
constexpr float to_float() const noexcept
friend constexpr basic_ftz32 operator-(basic_ftz32 a) noexcept
Flips only the sign bit, preserving signed zero and NaN payloads.
friend constexpr basic_ftz32 operator/(basic_ftz32 a, basic_ftz32 b) noexcept
Divides using the reproducible reciprocal-refinement graph, with signed IEEE-like zero/infinity cases...
constexpr basic_ftz32 & operator*=(basic_ftz32 b) noexcept
Assigns the corresponding FTZ result and returns this value by reference.
friend constexpr basic_ftz32 operator-(basic_ftz32 a, basic_ftz32 b) noexcept
Applies the FTZ arithmetic/sign operation, preserving this policy and signed-zero semantics.
static constexpr basic_ftz32 from_bits(unsigned int bits) noexcept
Imports binary32 bits, flushing only subnormal magnitudes to signed zero.
friend constexpr basic_ftz32 operator+(basic_ftz32 a, basic_ftz32 b) noexcept
Applies the FTZ arithmetic/sign operation, preserving this policy and signed-zero semantics.
friend constexpr bool operator<(basic_ftz32 a, basic_ftz32 b) noexcept
Compares values; NaN is unordered (only != is true), and the two zero signs compare equal.
friend constexpr basic_ftz32 operator*(basic_ftz32 a, basic_ftz32 b) noexcept
Applies the FTZ arithmetic/sign operation, preserving this policy and signed-zero semantics.
Results of finite startup witnesses for this scalar compilation and calling thread....