7hi_export_module(hikogui.DSP.apply)
9hi_export namespace
hi {
inline v1 {
28template<fixed_
string Operation,
typename T>
33template<
typename Context,
typename T>
34concept dsp_apply_argument = std::same_as<Context, T> or std::same_as<Context, T const *> or std::same_as<Context, T *>;;
43template<
size_t I,
typename Array,
typename First,
typename... Rest>
44[[nodiscard]]
constexpr void _dsp_regs_init_float(Array &array, First first, Rest... rest)
noexcept
46 if constexpr (not std::is_pointer_v<First>) {
47 std::get<I>(array) = first;
49 if constexpr (
sizeof...(Rest) != 0) {
50 return _dsp_regs_init<I + 1>(array, rest...);
54template<
size_t I,
typename Array,
typename First,
typename... Rest>
55[[nodiscard]]
constexpr void dsp_load(Array &array, First &first, Rest &... rest)
noexcept
57 using reg_type = Array::value_type;
59 if constexpr (std::same_as<reg_type, float> and std::same_as<First, float const *>) {
60 std::get<I>(array) = *first++;
61 }
else if constexpr (std::same_as<reg_type, double> and std::same_as<First, double const *>) {
62 std::get<I>(array) = *first++;
63 }
else if constexpr (std::same_as<reg_type, int> and std::same_as<First, int const *>) {
64 std::get<I>(array) = *first++;
66#if defined(HI_HAS_SSE)
67 }
else if constexpr (std::same_as<reg_type, __m128> and std::same_as<First, float const *>) {
68 std::get<I>(array) = _mm_loadu_ps(first);
70 }
else if constexpr (std::same_as<reg_type, __m128> and std::same_as<First, double const *>) {
71 std::get<I>(array) = _mm_loadu_pd(first);
75#if defined(HI_HAS_SSE2)
76 }
else if constexpr (std::same_as<reg_type, __m128i> and std::same_as<First, int const *>) {
77 std::get<I>(array) = _mm_loadu_epi32(first);
81#if defined(HI_HAS_AVX)
82 }
else if constexpr (std::same_as<reg_type, __m256> and std::same_as<First, float const *>) {
83 std::get<I>(array) = _mm256_loadu_ps(first);
85 }
else if constexpr (std::same_as<reg_type, __m256> and std::same_as<First, double const *>) {
86 std::get<I>(array) = _mm256_loadu_pd(first);
90#if defined(HI_HAS_AVX2)
91 }
else if constexpr (std::same_as<reg_type, __m256i> and std::same_as<First, int const *>) {
92 std::get<I>(array) = _mm256_loadu_epi32(first);
96#if defined(HI_HAS_AVX512F)
97 }
else if constexpr (std::same_as<reg_type, __m512> and std::same_as<First, float const *>) {
98 std::get<I>(array) = _mm512_loadu_ps(first);
100 }
else if constexpr (std::same_as<reg_type, __m512> and std::same_as<First, double const *>) {
101 std::get<I>(array) = _mm512_loadu_pd(first);
103 }
else if constexpr (std::same_as<reg_type, __m512i> and std::same_as<First, int const *>) {
104 std::get<I>(array) = _mm512_loadu_epi32(first);
109 if constexpr (
sizeof...(Rest) != 0) {
110 return dsp_load<I + 1>(array, rest...);
114template<
size_t I,
typename Array,
typename First,
typename... Rest>
115[[nodiscard]]
constexpr void dsp_init_scalar(Array &array, First first, Rest... rest)
noexcept
117 using reg_type = Array::value_type;
119 if constexpr (std::same_as<reg_type, float> and std::same_as<First, float>) {
120 std::get<I>(array) = first;
121 }
else if constexpr (std::same_as<reg_type, double> and std::same_as<First, double>) {
122 std::get<I>(array) = first;
123 }
else if constexpr (std::same_as<reg_type, int> and std::same_as<First, int>) {
124 std::get<I>(array) = first;
126#if defined(HI_HAS_SSE)
127 }
else if constexpr (std::same_as<reg_type, __m128> and std::same_as<First, float>) {
128 std::get<I>(array) = _mm_set1_ps(first);
129 }
else if constexpr (std::same_as<reg_type, __m128> and std::same_as<First, double>) {
130 std::get<I>(array) = _mm_set1_pd(first);
133#if defined(HI_HAS_SSE2)
134 }
else if constexpr (std::same_as<reg_type, __m128i> and std::same_as<First, int>) {
135 std::get<I>(array) = _mm_set1_epi32(first);
138#if defined(HI_HAS_AVX)
139 }
else if constexpr (std::same_as<reg_type, __m256> and std::same_as<First, float>) {
140 std::get<I>(array) = _mm256_set1_ps(first);
141 }
else if constexpr (std::same_as<reg_type, __m256> and std::same_as<First, double>) {
142 std::get<I>(array) = _mm256_set1_pd(first);
145#if defined(HI_HAS_AVX2)
146 }
else if constexpr (std::same_as<reg_type, __m256i> and std::same_as<First, int>) {
147 std::get<I>(array) = _mm256_set1_epi32(first);
150#if defined(HI_HAS_AVX512F)
151 }
else if constexpr (std::same_as<reg_type, __m512> and std::same_as<First, float>) {
152 std::get<I>(array) = _mm512_set1_ps(first);
153 }
else if constexpr (std::same_as<reg_type, __m512> and std::same_as<First, double>) {
154 std::get<I>(array) = _mm512_set1_pd(first);
155 }
else if constexpr (std::same_as<reg_type, __m512i> and std::same_as<First, int>) {
156 std::get<I>(array) = _mm512_set1_epi32(first);
160 if constexpr (
sizeof...(Rest) != 0) {
161 return dsp_init_scalar<I + 1>(array, rest...);
165template<
typename T,
typename... Args>
166[[nodiscard]]
constexpr auto dsp_regs_init(Args... args)
noexcept
169 dsp_init_scalar<0>(r, args...);
175template<
typename Operation,
typename T, dsp_apply_argument<T>... Args>
176constexpr void dsp_for_each(T *r, T *r_last, Args... args)
noexcept
178 using traits = dsp_op_traits<Operation>;
180 auto T_regs = dsp_regs_init<T>(args...);
182 auto r_align =
ceil(r, traits::best_alignment());
183 inplace_min(r_align, r_last);
185 while (r != r_align) {
186 *r++ = Operation{}();
189#if defined(HI_HAS_AVX512F)
192#elif defined(HI_HAS_AVX2)
195#elif defined(HI_HAS_SSE)
200 while (r != sse_align) {
201 T_regs = dsp_regs_load_and_increment<T>(args...);
202 *r++ = Operation{}(T_regs);
205 if constexpr (traits{}::sse()) {
213struct dsp_op<
"+", float> {
214 constexpr float operator()(
float a,
float b)
const noexcept
220 __m128 operator()(__m128 a, __m128 b)
const noexcept
222 return _mm_add_ps(a, b);
227 __m256 operator()(__m256 a, __m256 b)
const noexcept
229 return _mm256_add_ps(a, b);
234 __m512 operator()(__m512 a, __m512 b)
const noexcept
236 return _mm512_add_ps(a, b);
The HikoGUI namespace.
Definition array_generic.hpp:20
DOXYGEN BUG.
Definition algorithm_misc.hpp:20