FastLED 3.9.15
Loading...
Searching...
No Matches
simd_tests.cpp
Go to the documentation of this file.
1// examples/SIMD/simd_tests.cpp
2//
3// SIMD test implementations
4
5#include "simd_tests.h"
6#include "test_helpers.h"
7#include <FastLED.h>
8#include "fl/math/simd.h"
9
10using namespace fl::simd;
11
12namespace simd_test {
13
14// ============================================================================
15// Load/Store Tests
16// ============================================================================
17
19 uint8_t input[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
20 uint8_t output[16] = {0};
21
22 simd_u8x16 v = load_u8_16(input);
23 store_u8_16(output, v);
24
25 if (!compare_u8_arrays(input, output, 16)) {
26 result.fail("Load/store u8x16 data mismatch");
27 }
28}
29
31 uint32_t input[4] = {0x12345678, 0x9ABCDEF0, 0xFEDCBA98, 0x76543210};
32 uint32_t output[4] = {0};
33
34 simd_u32x4 v = load_u32_4(input);
35 store_u32_4(output, v);
36
37 for (int i = 0; i < 4; i++) {
38 if (input[i] != output[i]) {
39 result.fail("Load/store u32x4 data mismatch");
40 return;
41 }
42 }
43}
44
46 float input[4] = {1.5f, 2.5f, 3.5f, 4.5f};
47 float output[4] = {0.0f};
48
49 simd_f32x4 v = load_f32_4(input);
50 store_f32_4(output, v);
51
52 if (!compare_f32_arrays(input, output, 4)) {
53 result.fail("Load/store f32x4 data mismatch");
54 }
55}
56
57// ============================================================================
58// Arithmetic Tests
59// ============================================================================
60
62 uint8_t a_data[16] = {100, 150, 200, 250, 100, 150, 200, 250, 100, 150, 200, 250, 100, 150, 200, 250};
63 uint8_t b_data[16] = {50, 100, 50, 100, 50, 100, 50, 100, 50, 100, 50, 100, 50, 100, 50, 100};
64 uint8_t expected[16] = {150, 250, 250, 255, 150, 250, 250, 255, 150, 250, 250, 255, 150, 250, 250, 255};
65 uint8_t output[16] = {0};
66
67 simd_u8x16 a = load_u8_16(a_data);
68 simd_u8x16 b = load_u8_16(b_data);
69 simd_u8x16 c = add_sat_u8_16(a, b);
70 store_u8_16(output, c);
71
72 if (!compare_u8_arrays(expected, output, 16)) {
73 result.fail("Saturating add produced incorrect results");
74 }
75}
76
78 uint8_t a_data[16] = {100, 50, 200, 10, 100, 50, 200, 10, 100, 50, 200, 10, 100, 50, 200, 10};
79 uint8_t b_data[16] = {50, 100, 50, 100, 50, 100, 50, 100, 50, 100, 50, 100, 50, 100, 50, 100};
80 uint8_t expected[16] = {50, 0, 150, 0, 50, 0, 150, 0, 50, 0, 150, 0, 50, 0, 150, 0};
81 uint8_t output[16] = {0};
82
83 simd_u8x16 a = load_u8_16(a_data);
84 simd_u8x16 b = load_u8_16(b_data);
85 simd_u8x16 c = sub_sat_u8_16(a, b);
86 store_u8_16(output, c);
87
88 if (!compare_u8_arrays(expected, output, 16)) {
89 result.fail("Saturating subtract produced incorrect results");
90 }
91}
92
94 uint8_t input[16] = {255, 128, 64, 32, 255, 128, 64, 32, 255, 128, 64, 32, 255, 128, 64, 32};
95 uint8_t expected[16] = {127, 64, 32, 16, 127, 64, 32, 16, 127, 64, 32, 16, 127, 64, 32, 16};
96 uint8_t output[16] = {0};
97
98 simd_u8x16 v = load_u8_16(input);
99 simd_u8x16 scaled = scale_u8_16(v, 128); // Scale by 0.5
100 store_u8_16(output, scaled);
101
102 if (!compare_u8_arrays(expected, output, 16)) {
103 result.fail("Scale operation produced incorrect results");
104 }
105}
106
108 uint8_t a_data[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
109 uint8_t b_data[16] = {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255};
110 uint8_t expected[16] = {127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127};
111 uint8_t output[16] = {0};
112
113 simd_u8x16 a = load_u8_16(a_data);
114 simd_u8x16 b = load_u8_16(b_data);
115 simd_u8x16 c = blend_u8_16(a, b, 128); // 50% blend
116 store_u8_16(output, c);
117
118 if (!compare_u8_arrays(expected, output, 16)) {
119 result.fail("Blend operation produced incorrect results");
120 }
121}
122
123// ============================================================================
124// Comparison Tests
125// ============================================================================
126
128 uint8_t a_data[16] = {100, 50, 200, 10, 100, 50, 200, 10, 100, 50, 200, 10, 100, 50, 200, 10};
129 uint8_t b_data[16] = {50, 100, 150, 20, 50, 100, 150, 20, 50, 100, 150, 20, 50, 100, 150, 20};
130 uint8_t expected[16] = {50, 50, 150, 10, 50, 50, 150, 10, 50, 50, 150, 10, 50, 50, 150, 10};
131 uint8_t output[16] = {0};
132
133 simd_u8x16 a = load_u8_16(a_data);
134 simd_u8x16 b = load_u8_16(b_data);
135 simd_u8x16 c = min_u8_16(a, b);
136 store_u8_16(output, c);
137
138 if (!compare_u8_arrays(expected, output, 16)) {
139 result.fail("Min operation produced incorrect results");
140 }
141}
142
144 uint8_t a_data[16] = {100, 50, 200, 10, 100, 50, 200, 10, 100, 50, 200, 10, 100, 50, 200, 10};
145 uint8_t b_data[16] = {50, 100, 150, 20, 50, 100, 150, 20, 50, 100, 150, 20, 50, 100, 150, 20};
146 uint8_t expected[16] = {100, 100, 200, 20, 100, 100, 200, 20, 100, 100, 200, 20, 100, 100, 200, 20};
147 uint8_t output[16] = {0};
148
149 simd_u8x16 a = load_u8_16(a_data);
150 simd_u8x16 b = load_u8_16(b_data);
151 simd_u8x16 c = max_u8_16(a, b);
152 store_u8_16(output, c);
153
154 if (!compare_u8_arrays(expected, output, 16)) {
155 result.fail("Max operation produced incorrect results");
156 }
157}
158
160 uint8_t a_data[16] = {100, 50, 200, 10, 100, 50, 200, 10, 100, 50, 200, 10, 100, 50, 200, 10};
161 uint8_t b_data[16] = {50, 100, 150, 20, 50, 100, 150, 20, 50, 100, 150, 20, 50, 100, 150, 20};
162 uint8_t expected[16] = {75, 75, 175, 15, 75, 75, 175, 15, 75, 75, 175, 15, 75, 75, 175, 15};
163 uint8_t output[16] = {0};
164
165 simd_u8x16 a = load_u8_16(a_data);
166 simd_u8x16 b = load_u8_16(b_data);
167 simd_u8x16 c = avg_u8_16(a, b);
168 store_u8_16(output, c);
169
170 if (!compare_u8_arrays(expected, output, 16)) {
171 result.fail("Average operation produced incorrect results");
172 }
173}
174
176 uint8_t a_data[16] = {101, 51, 201, 11, 101, 51, 201, 11, 101, 51, 201, 11, 101, 51, 201, 11};
177 uint8_t b_data[16] = {50, 100, 150, 20, 50, 100, 150, 20, 50, 100, 150, 20, 50, 100, 150, 20};
178 uint8_t expected[16] = {76, 76, 176, 16, 76, 76, 176, 16, 76, 76, 176, 16, 76, 76, 176, 16};
179 uint8_t output[16] = {0};
180
181 simd_u8x16 a = load_u8_16(a_data);
182 simd_u8x16 b = load_u8_16(b_data);
183 simd_u8x16 c = avg_round_u8_16(a, b);
184 store_u8_16(output, c);
185
186 if (!compare_u8_arrays(expected, output, 16)) {
187 result.fail("Rounding average operation produced incorrect results");
188 }
189}
190
191// ============================================================================
192// Bitwise Tests
193// ============================================================================
194
196 uint8_t a_data[16] = {0xFF, 0xF0, 0x0F, 0xAA, 0xFF, 0xF0, 0x0F, 0xAA, 0xFF, 0xF0, 0x0F, 0xAA, 0xFF, 0xF0, 0x0F, 0xAA};
197 uint8_t b_data[16] = {0xF0, 0xFF, 0x0F, 0x55, 0xF0, 0xFF, 0x0F, 0x55, 0xF0, 0xFF, 0x0F, 0x55, 0xF0, 0xFF, 0x0F, 0x55};
198 uint8_t expected[16] = {0xF0, 0xF0, 0x0F, 0x00, 0xF0, 0xF0, 0x0F, 0x00, 0xF0, 0xF0, 0x0F, 0x00, 0xF0, 0xF0, 0x0F, 0x00};
199 uint8_t output[16] = {0};
200
201 simd_u8x16 a = load_u8_16(a_data);
202 simd_u8x16 b = load_u8_16(b_data);
203 simd_u8x16 c = and_u8_16(a, b);
204 store_u8_16(output, c);
205
206 if (!compare_u8_arrays(expected, output, 16)) {
207 result.fail("AND operation produced incorrect results");
208 }
209}
210
212 uint8_t a_data[16] = {0xF0, 0x0F, 0xAA, 0x55, 0xF0, 0x0F, 0xAA, 0x55, 0xF0, 0x0F, 0xAA, 0x55, 0xF0, 0x0F, 0xAA, 0x55};
213 uint8_t b_data[16] = {0x0F, 0xF0, 0x55, 0xAA, 0x0F, 0xF0, 0x55, 0xAA, 0x0F, 0xF0, 0x55, 0xAA, 0x0F, 0xF0, 0x55, 0xAA};
214 uint8_t expected[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
215 uint8_t output[16] = {0};
216
217 simd_u8x16 a = load_u8_16(a_data);
218 simd_u8x16 b = load_u8_16(b_data);
219 simd_u8x16 c = or_u8_16(a, b);
220 store_u8_16(output, c);
221
222 if (!compare_u8_arrays(expected, output, 16)) {
223 result.fail("OR operation produced incorrect results");
224 }
225}
226
228 uint8_t a_data[16] = {0xFF, 0xF0, 0xAA, 0x55, 0xFF, 0xF0, 0xAA, 0x55, 0xFF, 0xF0, 0xAA, 0x55, 0xFF, 0xF0, 0xAA, 0x55};
229 uint8_t b_data[16] = {0xF0, 0xFF, 0x55, 0xAA, 0xF0, 0xFF, 0x55, 0xAA, 0xF0, 0xFF, 0x55, 0xAA, 0xF0, 0xFF, 0x55, 0xAA};
230 uint8_t expected[16] = {0x0F, 0x0F, 0xFF, 0xFF, 0x0F, 0x0F, 0xFF, 0xFF, 0x0F, 0x0F, 0xFF, 0xFF, 0x0F, 0x0F, 0xFF, 0xFF};
231 uint8_t output[16] = {0};
232
233 simd_u8x16 a = load_u8_16(a_data);
234 simd_u8x16 b = load_u8_16(b_data);
235 simd_u8x16 c = xor_u8_16(a, b);
236 store_u8_16(output, c);
237
238 if (!compare_u8_arrays(expected, output, 16)) {
239 result.fail("XOR operation produced incorrect results");
240 }
241}
242
244 uint8_t a_data[16] = {0xF0, 0x0F, 0xAA, 0x55, 0xF0, 0x0F, 0xAA, 0x55, 0xF0, 0x0F, 0xAA, 0x55, 0xF0, 0x0F, 0xAA, 0x55};
245 uint8_t b_data[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
246 uint8_t expected[16] = {0x0F, 0xF0, 0x55, 0xAA, 0x0F, 0xF0, 0x55, 0xAA, 0x0F, 0xF0, 0x55, 0xAA, 0x0F, 0xF0, 0x55, 0xAA};
247 uint8_t output[16] = {0};
248
249 simd_u8x16 a = load_u8_16(a_data);
250 simd_u8x16 b = load_u8_16(b_data);
251 simd_u8x16 c = andnot_u8_16(a, b);
252 store_u8_16(output, c);
253
254 if (!compare_u8_arrays(expected, output, 16)) {
255 result.fail("AND-NOT operation produced incorrect results");
256 }
257}
258
259// ============================================================================
260// Broadcast Tests
261// ============================================================================
262
264 uint32_t value = 0xDEADBEEF;
265 uint32_t expected[4] = {0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF, 0xDEADBEEF};
266 uint32_t output[4] = {0};
267
268 simd_u32x4 v = set1_u32_4(value);
269 store_u32_4(output, v);
270
271 for (int i = 0; i < 4; i++) {
272 if (output[i] != expected[i]) {
273 result.fail("Set1 u32x4 operation produced incorrect results");
274 return;
275 }
276 }
277}
278
280 float value = 3.14159f;
281 float expected[4] = {3.14159f, 3.14159f, 3.14159f, 3.14159f};
282 float output[4] = {0.0f};
283
284 simd_f32x4 v = set1_f32_4(value);
285 store_f32_4(output, v);
286
287 if (!compare_f32_arrays(expected, output, 4)) {
288 result.fail("Set1 f32x4 operation produced incorrect results");
289 }
290}
291
292// ============================================================================
293// Floating Point Tests
294// ============================================================================
295
297 float a_data[4] = {1.0f, 2.0f, 3.0f, 4.0f};
298 float b_data[4] = {0.5f, 1.5f, 2.5f, 3.5f};
299 float expected[4] = {1.5f, 3.5f, 5.5f, 7.5f};
300 float output[4] = {0.0f};
301
302 simd_f32x4 a = load_f32_4(a_data);
303 simd_f32x4 b = load_f32_4(b_data);
304 simd_f32x4 c = add_f32_4(a, b);
305 store_f32_4(output, c);
306
307 if (!compare_f32_arrays(expected, output, 4)) {
308 result.fail("Float add operation produced incorrect results");
309 }
310}
311
313 float a_data[4] = {5.0f, 4.0f, 3.0f, 2.0f};
314 float b_data[4] = {1.5f, 1.5f, 1.5f, 1.5f};
315 float expected[4] = {3.5f, 2.5f, 1.5f, 0.5f};
316 float output[4] = {0.0f};
317
318 simd_f32x4 a = load_f32_4(a_data);
319 simd_f32x4 b = load_f32_4(b_data);
320 simd_f32x4 c = sub_f32_4(a, b);
321 store_f32_4(output, c);
322
323 if (!compare_f32_arrays(expected, output, 4)) {
324 result.fail("Float subtract operation produced incorrect results");
325 }
326}
327
329 float a_data[4] = {2.0f, 3.0f, 4.0f, 5.0f};
330 float b_data[4] = {0.5f, 2.0f, 0.25f, 1.0f};
331 float expected[4] = {1.0f, 6.0f, 1.0f, 5.0f};
332 float output[4] = {0.0f};
333
334 simd_f32x4 a = load_f32_4(a_data);
335 simd_f32x4 b = load_f32_4(b_data);
336 simd_f32x4 c = mul_f32_4(a, b);
337 store_f32_4(output, c);
338
339 if (!compare_f32_arrays(expected, output, 4)) {
340 result.fail("Float multiply operation produced incorrect results");
341 }
342}
343
345 float a_data[4] = {10.0f, 20.0f, 30.0f, 40.0f};
346 float b_data[4] = {2.0f, 4.0f, 5.0f, 8.0f};
347 float expected[4] = {5.0f, 5.0f, 6.0f, 5.0f};
348 float output[4] = {0.0f};
349
350 simd_f32x4 a = load_f32_4(a_data);
351 simd_f32x4 b = load_f32_4(b_data);
352 simd_f32x4 c = div_f32_4(a, b);
353 store_f32_4(output, c);
354
355 if (!compare_f32_arrays(expected, output, 4)) {
356 result.fail("Float divide operation produced incorrect results");
357 }
358}
359
361 float input[4] = {4.0f, 9.0f, 16.0f, 25.0f};
362 float expected[4] = {2.0f, 3.0f, 4.0f, 5.0f};
363 float output[4] = {0.0f};
364
365 simd_f32x4 v = load_f32_4(input);
366 simd_f32x4 result_v = sqrt_f32_4(v);
367 store_f32_4(output, result_v);
368
369 if (!compare_f32_arrays(expected, output, 4, 0.01f)) {
370 result.fail("Float sqrt operation produced incorrect results");
371 }
372}
373
375 float a_data[4] = {1.0f, 5.0f, 3.0f, 7.0f};
376 float b_data[4] = {2.0f, 4.0f, 6.0f, 1.0f};
377 float expected[4] = {1.0f, 4.0f, 3.0f, 1.0f};
378 float output[4] = {0.0f};
379
380 simd_f32x4 a = load_f32_4(a_data);
381 simd_f32x4 b = load_f32_4(b_data);
382 simd_f32x4 c = min_f32_4(a, b);
383 store_f32_4(output, c);
384
385 if (!compare_f32_arrays(expected, output, 4)) {
386 result.fail("Float min operation produced incorrect results");
387 }
388}
389
391 float a_data[4] = {1.0f, 5.0f, 3.0f, 7.0f};
392 float b_data[4] = {2.0f, 4.0f, 6.0f, 1.0f};
393 float expected[4] = {2.0f, 5.0f, 6.0f, 7.0f};
394 float output[4] = {0.0f};
395
396 simd_f32x4 a = load_f32_4(a_data);
397 simd_f32x4 b = load_f32_4(b_data);
398 simd_f32x4 c = max_f32_4(a, b);
399 store_f32_4(output, c);
400
401 if (!compare_f32_arrays(expected, output, 4)) {
402 result.fail("Float max operation produced incorrect results");
403 }
404}
405
406} // namespace simd_test
expected type for operations that can fail (C++23-style)
Definition expected.h:79
platforms::simd_u32x4 simd_u32x4
Definition types.h:26
platforms::simd_u8x16 simd_u8x16
Definition types.h:24
platforms::simd_f32x4 simd_f32x4
Definition types.h:27
constexpr int type_rank< T >::value
fl::u32 uint32_t
Definition s16x16x4.h:219
expected< T, E > result
Alias for expected (Rust-style naming)
Definition result.h:31
unsigned char uint8_t
Definition s16x16x4.h:209
void test_load_store_f32_4(TestResult &result)
void test_load_store_u8_16(TestResult &result)
void test_or_u8_16(TestResult &result)
void test_set1_u32_4(TestResult &result)
void test_add_sat_u8_16(TestResult &result)
void test_avg_u8_16(TestResult &result)
void test_load_store_u32_4(TestResult &result)
void test_min_f32_4(TestResult &result)
void test_and_u8_16(TestResult &result)
void test_max_f32_4(TestResult &result)
void test_set1_f32_4(TestResult &result)
void test_min_u8_16(TestResult &result)
void test_mul_f32_4(TestResult &result)
void test_sub_sat_u8_16(TestResult &result)
void test_add_f32_4(TestResult &result)
void test_div_f32_4(TestResult &result)
bool compare_u8_arrays(const uint8_t *a, const uint8_t *b, size_t count)
Compare two uint8_t arrays element-wise.
void test_xor_u8_16(TestResult &result)
void test_sub_f32_4(TestResult &result)
void test_scale_u8_16(TestResult &result)
void test_max_u8_16(TestResult &result)
void test_avg_round_u8_16(TestResult &result)
void test_blend_u8_16(TestResult &result)
bool compare_f32_arrays(const float *a, const float *b, size_t count, float epsilon)
Compare two float arrays element-wise with epsilon tolerance.
void test_andnot_u8_16(TestResult &result)
void test_sqrt_f32_4(TestResult &result)
Umbrella header for SIMD subsystem.
Stores the result of a single SIMD test.
Definition test_result.h:10