batmat 0.0.18
Batched linear algebra routines
Loading...
Searching...
No Matches
cneg.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <batmat/assume.hpp>
4#include <batmat/simd.hpp>
5#include <bit>
6#include <cmath>
7#include <cstdint>
8#include <limits>
9#include <type_traits>
10
11namespace batmat::ops {
12namespace detail {
13
14template <class T>
15struct floating_point_to_int; // deliberately undefined
16
17template <>
18struct floating_point_to_int<float> {
19 using type = std::uint32_t;
20 static_assert(sizeof(float) == sizeof(type));
21};
22
23template <>
24struct floating_point_to_int<double> {
25 using type = std::uint64_t;
26 static_assert(sizeof(double) == sizeof(type));
27};
28
29template <class T>
31
32/// @addtogroup topic-low-level-ops
33/// @{
34
35/// @name Conditional negation of floating point numbers
36/// @{
37
38/// Conditionally negates the sign bit of @p x, depending on @p signs, which
39/// should contain only ±0 (i.e. only the sign bit of an IEEE-754 floating point
40/// number).
41template <class T>
42T cneg(T x, T signs) {
43 using std::copysign;
44 return x * copysign(T{1}, signs);
45}
46
47/// @copydoc cneg(T,T)
48template <class T, class Abi>
49 requires(requires { typename floating_point_to_int_t<T>; } &&
50 std::numeric_limits<T>::is_iec559 && std::is_trivially_copyable_v<T>)
51[[gnu::always_inline]] inline T cneg(T x, T signs) {
52 BATMAT_ASSUME(signs == 0);
53 using int_type = floating_point_to_int_t<T>;
54 auto r = std::bit_cast<int_type>(x) ^ std::bit_cast<int_type>(signs);
55 return std::bit_cast<T>(r);
56}
57
58/// @copydoc cneg(T,T)
59template <class T, class Abi>
60 requires(requires {
62 } && std::numeric_limits<T>::is_iec559 && std::is_trivially_copyable_v<datapar::simd<T, Abi>>)
63[[gnu::always_inline]] inline datapar::simd<T, Abi> cneg(datapar::simd<T, Abi> x,
65#if !BATMAT_WITH_GSI_HPC_SIMD // TODO: enable once Clang supports operator==
66 BATMAT_ASSUME(all_of(signs == 0));
67#endif
68 using flt_simd = datapar::simd<T, Abi>;
69 using int_type = floating_point_to_int_t<T>;
70 using int_simd = datapar::deduced_simd<int_type, flt_simd::size()>;
71 auto r = std::bit_cast<int_simd>(x) ^ std::bit_cast<int_simd>(signs);
72 return std::bit_cast<flt_simd>(r);
73}
74
75/// @}
76
77/// @}
78
79} // namespace detail
80
81using detail::cneg;
82
83} // namespace batmat::ops
#define BATMAT_ASSUME(x)
Invokes undefined behavior if the expression x does not evaluate to true.
Definition assume.hpp:17
T cneg(T x, T signs)
Conditionally negates the sign bit of x, depending on signs, which should contain only ±0 (i....
Definition cneg.hpp:42
simd< Tp, deduced_abi< Tp, Np > > deduced_simd
Definition simd.hpp:103
stdx::simd< Tp, Abi > simd
Definition simd.hpp:99
typename floating_point_to_int< T >::type floating_point_to_int_t
Definition cneg.hpp:30