2namespace NATIVE_BACKEND_NAMESPACE::native {
4 template<
class V>
struct fp32_bit_bridge;
5 template<std::
size_t N, ::native::isa<> Arch>
6 requires NATIVE_ARCH_REQUIRES(Arch) && ::NATIVE_BACKEND_NAMESPACE::float_shape<N>
7 struct fp32_bit_bridge<::native::simd<float,N,Arch>> {
8 using value_type=::native::simd<float,N,Arch>;
9 using bits_type=
typename value_type::bits_type;
10 static native_inline constexpr bits_type encode(value_type x)
noexcept {
return x.bits(); }
11 static native_inline constexpr value_type decode(bits_type x)
noexcept {
return value_type::from_bits(x); }
15 concept fp32_bits_register =
requires {
typename detail::fp32_bit_bridge<V>::bits_type; };
19namespace NATIVE_BACKEND_NAMESPACE::native {
21 template <
unsigned_register U>
native_inline constexpr U flush_clear_bits(U bits, U clear)
noexcept {
22 return bits & (clear ^ U(0xffffffffu));
25 native_inline constexpr uint32x8 flush_clear_bits(uint32x8 bits, uint32x8 clear)
noexcept {
26 if consteval {
return bits & (clear ^ uint32x8(0xffffffffu)); }
27 return uint32x8::from_native(_mm256_andnot_si256(clear.value, bits.value));
30#if NATIVE_HAS_AVX512F && NATIVE_HAS_AVX512DQ
31 native_inline constexpr uint32x16 flush_clear_bits(uint32x16 bits, uint32x16 clear)
noexcept {
32 if consteval {
return bits & (clear ^ uint32x16(0xffffffffu)); }
33 return uint32x16::from_native(_mm512_andnot_si512(clear.value, bits.value));
36#if NATIVE_HAS_ARM_NEON
37 native_inline constexpr uint32x4 flush_clear_bits(uint32x4 bits, uint32x4 clear)
noexcept {
38 if consteval {
return bits & (clear ^ uint32x4(0xffffffffu)); }
39 return uint32x4::from_native(vbicq_u8(bits.value, clear.value));
51 template <fp32_bits_register V, std::
size_t N>
54 std::array<V,N> result{};
55 for(std::size_t i=0;i<N;++i) result[i]=::native::detail::float_constant::map([](
auto bits) {
56 return (bits&0x7f800000u)?bits:(bits&0x80000000u);
60 if constexpr (N == 0)
return {};
62 auto const & [...value] = x;
63#if NATIVE_HAS_AVX512F && NATIVE_HAS_AVX512DQ
64 if constexpr (V::lanes == 16) {
66 auto const [...tiny] = std::array{_mm512_fpclass_ps_mask(value.value, 0x26)...};
67 auto const sign = _mm512_castsi512_ps(_mm512_set1_epi32(
68 std::bit_cast<std::int32_t>(0x80000000u)));
69 return {{V(_mm512_mask_and_ps(value.value, tiny, value.value, sign))...}};
73 using bridge = detail::fp32_bit_bridge<V>;
74 using U =
typename bridge::bits_type;
75 auto [...bits] = std::array{bridge::encode(value)...};
76 auto const [...exponent] = std::array{(bits & U(0x7f800000u))...};
78 auto const [...clear] = std::array{(zero & U(0x007fffffu))...};
79 ((bits = detail::flush_clear_bits(bits, clear)), ...);
80 return {{bridge::decode(bits)...}};
86 template <fp32_bits_register V>
native_inline constexpr V flush_to_zero(V x)
noexcept {
87 return flush_to_zero(std::array{x})[0];
92 using ::NATIVE_BACKEND_NAMESPACE::native::flush_to_zero;
#define native_inline
inline [[always_inline]]
constexpr auto mask_bits(simd< M, N, Arch > m) noexcept
Architecture-tagged vectors, register packs and supporting value types. Native arithmetic follows its...
constexpr std::array< V, N > flush_to_zero(std::array< V, N > const &x) noexcept
Replace binary32 subnormal lanes with signed zero. Both zero signs, normal values,...