HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
for_each.hpp
1
2
3#pragma once
4
5#include <concepts>
6
7hi_export_module(hikogui.DSP.apply)
8
9hi_export namespace hi { inline v1 {
10
28template<fixed_string Operation, typename T>
29struct dsp_op {
30};
31
32
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 *>;;
35
36template<typename Op>
37struct dps_op_traits {
38
39
40};
41
42
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
45{
46 if constexpr (not std::is_pointer_v<First>) {
47 std::get<I>(array) = first;
48 }
49 if constexpr (sizeof...(Rest) != 0) {
50 return _dsp_regs_init<I + 1>(array, rest...);
51 }
52}
53
54template<size_t I, typename Array, typename First, typename... Rest>
55[[nodiscard]] constexpr void dsp_load(Array &array, First &first, Rest &... rest) noexcept
56{
57 using reg_type = Array::value_type;
58
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++;
65
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);
69 first += 4;
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);
72 first += 2;
73#endif
74
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);
78 first += 4;
79#endif
80
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);
84 first += 8;
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);
87 first += 4;
88#endif
89
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);
93 first += 8;
94#endif
95
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);
99 first += 16;
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);
102 first += 8;
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);
105 first += 16;
106#endif
107 }
108
109 if constexpr (sizeof...(Rest) != 0) {
110 return dsp_load<I + 1>(array, rest...);
111 }
112}
113
114template<size_t I, typename Array, typename First, typename... Rest>
115[[nodiscard]] constexpr void dsp_init_scalar(Array &array, First first, Rest... rest) noexcept
116{
117 using reg_type = Array::value_type;
118
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;
125
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);
131#endif
132
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);
136#endif
137
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);
143#endif
144
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);
148#endif
149
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);
157#endif
158 }
159
160 if constexpr (sizeof...(Rest) != 0) {
161 return dsp_init_scalar<I + 1>(array, rest...);
162 }
163}
164
165template<typename T, typename... Args>
166[[nodiscard]] constexpr auto dsp_regs_init(Args... args) noexcept
167{
168 auto r = std::array<T, sizeof...(Args)>{};
169 dsp_init_scalar<0>(r, args...);
170 return r;
171}
172
175template<typename Operation, typename T, dsp_apply_argument<T>... Args>
176constexpr void dsp_for_each(T *r, T *r_last, Args... args) noexcept
177{
178 using traits = dsp_op_traits<Operation>;
179
180 auto T_regs = dsp_regs_init<T>(args...);
181
182 auto r_align = ceil(r, traits::best_alignment());
183 inplace_min(r_align, r_last);
184
185 while (r != r_align) {
186 *r++ = Operation{}();
187 }
188
189#if defined(HI_HAS_AVX512F)
190
191
192#elif defined(HI_HAS_AVX2)
193
194
195#elif defined(HI_HAS_SSE)
196
197#else
198#endif
199
200 while (r != sse_align) {
201 T_regs = dsp_regs_load_and_increment<T>(args...);
202 *r++ = Operation{}(T_regs);
203 }
204
205 if constexpr (traits{}::sse()) {
206 }
207#endif
208
209}
210
211
212template<>
213struct dsp_op<"+", float> {
214 constexpr float operator()(float a, float b) const noexcept
215 {
216 return a + b;
217 }
218
219#if HI_HAS_SSE
220 __m128 operator()(__m128 a, __m128 b) const noexcept
221 {
222 return _mm_add_ps(a, b);
223 }
224#endif
225
226#if HI_HAS_AVX
227 __m256 operator()(__m256 a, __m256 b) const noexcept
228 {
229 return _mm256_add_ps(a, b);
230 }
231#endif
232
233#if HI_HAS_AVX512F
234 __m512 operator()(__m512 a, __m512 b) const noexcept
235 {
236 return _mm512_add_ps(a, b);
237 }
238#endif
239};
240
241}}
The HikoGUI namespace.
Definition array_generic.hpp:20
DOXYGEN BUG.
Definition algorithm_misc.hpp:20
T ceil(T... args)