3#include "native/attributes.h"
7#include <native/detail/constexpr_float.h>
10namespace ftz {
namespace detail {
namespace math {
11 [[nodiscard]] native_constexpr native_inline native_const
float fp32_decode(
unsigned int bits) {
13 return std::bit_cast<float>(bits);
18 [[nodiscard]] native_constexpr native_inline native_const
unsigned int fp32_encode(
float value) {
20 return std::bit_cast<unsigned int>(value);
27 template <
bool Hardware = FTZ_FP32_HARDWARE_FTZ != 0>
28 native_constexpr
inline float fp32_ftz(
float value) {
30 if !
consteval {
if (Hardware)
return value; }
32 if (Hardware)
return value;
34 unsigned int bits = fp32_encode(value);
35 return fp32_decode((bits & 0x7f800000u) == 0u ? bits & 0x80000000u : bits);
39 template <
bool Flush = true,
bool Hardware = FTZ_FP32_HARDWARE_FTZ != 0>
40 [[nodiscard]] native_constexpr native_inline
float fp32_add(
float a,
float b) {
43 namespace fp = ::native::detail::constexpr_float;
44 auto const bits = fp::add_bits<fp::binary32>(fp32_encode(a), fp32_encode(b));
45 float result = fp32_decode(bits);
46 return Flush ? fp32_ftz<false>(result) : result;
50 precise
float result = a + b;
52 return Flush ? fp32_ftz<Hardware>(result) : result;
54 template <
bool Flush = true,
bool Hardware = FTZ_FP32_HARDWARE_FTZ != 0>
55 [[nodiscard]] native_constexpr native_inline
float fp32_mul(
float a,
float b) {
58 namespace fp = ::native::detail::constexpr_float;
59 auto const bits = fp::mul_bits<fp::binary32>(fp32_encode(a), fp32_encode(b));
60 float result = fp32_decode(bits);
61 return Flush ? fp32_ftz<false>(result) : result;
65 precise
float result = a * b;
67 return Flush ? fp32_ftz<Hardware>(result) : result;
69 template <
bool Flush = true,
bool Hardware = FTZ_FP32_HARDWARE_FTZ != 0>
70 [[nodiscard]] native_constexpr native_inline
float fp32_fma(
float a,
float b,
float c) {
73 namespace fp = ::native::detail::constexpr_float;
74 auto const bits = fp::fma_bits<fp::binary32>(fp32_encode(a), fp32_encode(b), fp32_encode(c));
75 float result = fp32_decode(bits);
76 return Flush ? fp32_ftz<false>(result) : result;
78 float result = std::fma(a, b, c);
80 precise
float result = mad(a, b, c);
82 return Flush ? fp32_ftz<Hardware>(result) : result;
85 native_constexpr
inline float2 fp32_ftz(float2 value) {
86#if FTZ_FP32_HARDWARE_FTZ
89 uint2 bits = asuint(value);
90 uint2 nonzero = uint2((bits & 0x7f800000u) != 0u);
91 return asfloat(bits & ((0u - nonzero) | 0x80000000u));
94 native_constexpr
inline float3 fp32_ftz(float3 value) {
95#if FTZ_FP32_HARDWARE_FTZ
98 uint3 bits = asuint(value);
99 uint3 nonzero = uint3((bits & 0x7f800000u) != 0u);
100 return asfloat(bits & ((0u - nonzero) | 0x80000000u));
103 native_constexpr
inline float4 fp32_ftz(float4 value) {
104#if FTZ_FP32_HARDWARE_FTZ
107 uint4 bits = asuint(value);
108 uint4 nonzero = uint4((bits & 0x7f800000u) != 0u);
109 return asfloat(bits & ((0u - nonzero) | 0x80000000u));