Vecmat 0.2.3
C math and linear algebra library for 2D/3D graphics, physics, and science.
Loading...
Searching...
No Matches
vector4_ptr.c
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2025-2026 Igal Alkon
2// SPDX-FileCopyrightText: 2026 ALKONTEK <git@alkontek.com>
3// SPDX-License-Identifier: BSD-3-Clause
4
5#include <arm_sve.h>
6#include <math.h>
7#include <vecmat.h>
8
9#if defined(VECMAT_USE_F64)
10
11static svbool_t pg4(void)
12{
13 return svwhilelt_b64((uint64_t)0, (uint64_t)4);
14}
15
16static svfloat64_t hadamard_div(svbool_t pg, svfloat64_t a, svfloat64_t b)
17{
18 const svfloat64_t zero = svdup_n_f64(0.0);
19 const svbool_t eqz = svcmpeq_f64(pg, b, zero);
20 const svfloat64_t safe = svsel_f64(eqz, svdup_n_f64(1.0), b);
21 return svsel_f64(eqz, zero, svdiv_f64_z(pg, a, safe));
22}
23
24static svfloat64_t sign4(svbool_t pg, svfloat64_t x)
25{
26 const svfloat64_t zero = svdup_n_f64(0.0);
27 const svfloat64_t one = svdup_n_f64(1.0);
28 svfloat64_t r = svsel_f64(svcmpgt_f64(pg, x, zero), one, zero);
29 return svsel_f64(svcmplt_f64(pg, x, zero), svneg_f64_z(pg, one), r);
30}
31
32void vec4_add_ptr_sve(vector4 *res, const vector4 *a, const vector4 *b)
33{
34 const svbool_t pg = pg4();
35 svst1_f64(pg, res->v, svadd_f64_z(pg, svld1_f64(pg, a->v), svld1_f64(pg, b->v)));
36}
37
38void vec4_sub_ptr_sve(vector4 *res, const vector4 *a, const vector4 *b)
39{
40 const svbool_t pg = pg4();
41 svst1_f64(pg, res->v, svsub_f64_z(pg, svld1_f64(pg, a->v), svld1_f64(pg, b->v)));
42}
43
44void vec4_mul_ptr_sve(vector4 *res, const vector4 *a, const vector4 *b)
45{
46 const svbool_t pg = pg4();
47 svst1_f64(pg, res->v, svmul_f64_z(pg, svld1_f64(pg, a->v), svld1_f64(pg, b->v)));
48}
49
51{
52 const svbool_t pg = pg4();
53 svst1_f64(pg, res->v, svmul_n_f64_z(pg, svld1_f64(pg, v->v), s));
54}
55
57{
58 const svbool_t pg = pg4();
59 if (s == 0.0) {
60 svst1_f64(pg, res->v, svdup_n_f64(0.0));
61 return;
62 }
63 svst1_f64(pg, res->v, svdiv_n_f64_z(pg, svld1_f64(pg, v->v), s));
64}
65
66void vec4_neg_ptr_sve(vector4 *res, const vector4 *v)
67{
68 const svbool_t pg = pg4();
69 svst1_f64(pg, res->v, svneg_f64_z(pg, svld1_f64(pg, v->v)));
70}
71
72void vec4_abs_ptr_sve(vector4 *res, const vector4 *v)
73{
74 const svbool_t pg = pg4();
75 svst1_f64(pg, res->v, svabs_f64_z(pg, svld1_f64(pg, v->v)));
76}
77
79{
80 const svbool_t pg = pg4();
81 const svfloat64_t x = svld1_f64(pg, v->v);
82 const double len2 = svaddv_f64(pg, svmul_f64_z(pg, x, x));
83 if (len2 == 0.0) {
84 *res = *v;
85 return;
86 }
87 const svfloat64_t s = svdup_n_f64(len2);
88 svfloat64_t e = svrsqrte_f64(s);
89 e = svmul_f64_z(pg, e, svrsqrts_f64(s, svmul_f64_z(pg, e, e)));
90 e = svmul_f64_z(pg, e, svrsqrts_f64(s, svmul_f64_z(pg, e, e)));
91 svst1_f64(pg, res->v, svmul_f64_z(pg, x, e));
92}
93
94void vec4_min_ptr_sve(vector4 *res, const vector4 *a, const vector4 *b)
95{
96 const svbool_t pg = pg4();
97 svst1_f64(pg, res->v, svmin_f64_z(pg, svld1_f64(pg, a->v), svld1_f64(pg, b->v)));
98}
99
100void vec4_max_ptr_sve(vector4 *res, const vector4 *a, const vector4 *b)
101{
102 const svbool_t pg = pg4();
103 svst1_f64(pg, res->v, svmax_f64_z(pg, svld1_f64(pg, a->v), svld1_f64(pg, b->v)));
104}
105
106void vec4_lerp_ptr_sve(vector4 *res, const vector4 *a, const vector4 *b, vm_float_t t)
107{
108 const svbool_t pg = pg4();
109 const svfloat64_t va = svld1_f64(pg, a->v);
110 const svfloat64_t d = svsub_f64_z(pg, svld1_f64(pg, b->v), va);
111 svst1_f64(pg, res->v, svmla_n_f64_z(pg, va, d, t));
112}
113
115 const vector4 *min, const vector4 *max)
116{
117 const svbool_t pg = pg4();
118 svfloat64_t x = svld1_f64(pg, v->v);
119 x = svmax_f64_z(pg, svld1_f64(pg, min->v), x);
120 x = svmin_f64_z(pg, svld1_f64(pg, max->v), x);
121 svst1_f64(pg, res->v, x);
122}
123
124void vec4_div_ptr_sve(vector4 *res, const vector4 *a, const vector4 *b)
125{
126 const svbool_t pg = pg4();
127 svst1_f64(pg, res->v, hadamard_div(pg, svld1_f64(pg, a->v), svld1_f64(pg, b->v)));
128}
129
131{
132 const svbool_t pg = pg4();
133 svst1_f64(pg, res->v, svadd_n_f64_z(pg, svld1_f64(pg, v->v), s));
134}
135
137{
138 const svbool_t pg = pg4();
139 svst1_f64(pg, res->v, svsub_n_f64_z(pg, svld1_f64(pg, v->v), s));
140}
141
143{
144 const svbool_t pg = pg4();
145 svfloat64_t x = svmax_n_f64_z(pg, svld1_f64(pg, v->v), min);
146 svst1_f64(pg, res->v, svmin_n_f64_z(pg, x, max));
147}
148
150{
151 const svbool_t pg = pg4();
152 svfloat64_t x = svmax_n_f64_z(pg, svld1_f64(pg, v->v), 0.0);
153 svst1_f64(pg, res->v, svmin_n_f64_z(pg, x, 1.0));
154}
155
157{
158 const svbool_t pg = pg4();
159 svst1_f64(pg, res->v, sign4(pg, svld1_f64(pg, v->v)));
160}
161
163{
164 const svbool_t pg = pg4();
165 svst1_f64(pg, res->v, svrintm_f64_z(pg, svld1_f64(pg, v->v)));
166}
167
169{
170 const svbool_t pg = pg4();
171 svst1_f64(pg, res->v, svrintp_f64_z(pg, svld1_f64(pg, v->v)));
172}
173
175{
176 const svbool_t pg = pg4();
177 svst1_f64(pg, res->v, svrinta_f64_z(pg, svld1_f64(pg, v->v)));
178}
179
181{
182 const svbool_t pg = pg4();
183 const svfloat64_t x = svld1_f64(pg, v->v);
184 svst1_f64(pg, res->v, svsub_f64_z(pg, x, svrintm_f64_z(pg, x)));
185}
186
188{
189 const svbool_t pg = pg4();
190 if (VECMAT_FABS(v->w) > VECMAT_EPSILON) {
191 svst1_f64(pg, res->v, svmul_n_f64_z(pg, svld1_f64(pg, v->v), 1.0 / v->w));
192 res->w = 1.0;
193 } else {
194 svst1_f64(pg, res->v, svdup_n_f64(0.0));
195 }
196}
197
198static svfloat64_t quat_mul4(svbool_t pg, svfloat64_t a, svfloat64_t b)
199{
200 const uint64_t i1[4] = {3, 2, 1, 0};
201 const uint64_t i2[4] = {2, 3, 0, 1};
202 const uint64_t i3[4] = {1, 0, 3, 2};
203 const svuint64_t lane = svindex_u64(0, 1);
204 const svbool_t n13 = svorr_z(pg, svcmpeq_n_u64(pg, lane, 1), svcmpeq_n_u64(pg, lane, 3));
205 const svbool_t n23 = svorr_z(pg, svcmpeq_n_u64(pg, lane, 2), svcmpeq_n_u64(pg, lane, 3));
206 const svbool_t n03 = svorr_z(pg, svcmpeq_n_u64(pg, lane, 0), svcmpeq_n_u64(pg, lane, 3));
207
208 svfloat64_t t1 = svtbl_f64(b, svld1_u64(pg, i1));
209 svfloat64_t t2 = svtbl_f64(b, svld1_u64(pg, i2));
210 svfloat64_t t3 = svtbl_f64(b, svld1_u64(pg, i3));
211 t1 = svneg_f64_m(t1, n13, t1);
212 t2 = svneg_f64_m(t2, n23, t2);
213 t3 = svneg_f64_m(t3, n03, t3);
214
215 double aa[4];
216 svst1_f64(pg, aa, a);
217 svfloat64_t r = svmul_n_f64_z(pg, b, aa[3]);
218 r = svmla_n_f64_z(pg, r, t1, aa[0]);
219 r = svmla_n_f64_z(pg, r, t2, aa[1]);
220 r = svmla_n_f64_z(pg, r, t3, aa[2]);
221 return r;
222}
223
224void quat_mul_ptr_sve(quaternion *res, const quaternion *a, const quaternion *b)
225{
226 const svbool_t pg = pg4();
227 svst1_f64(pg, res->v, quat_mul4(pg, svld1_f64(pg, a->v), svld1_f64(pg, b->v)));
228}
229
231{
232 vec4_normalize_ptr_sve((vector4 *)res, (const vector4 *)q);
233}
234
235#else /* float */
236
237static svbool_t pg4(void)
238{
239 return svwhilelt_b32((uint32_t)0, (uint32_t)4);
240}
241
242static svfloat32_t hadamard_div(svbool_t pg, svfloat32_t a, svfloat32_t b)
243{
244 const svfloat32_t zero = svdup_n_f32(0.0f);
245 const svbool_t eqz = svcmpeq_f32(pg, b, zero);
246 const svfloat32_t safe = svsel_f32(eqz, svdup_n_f32(1.0f), b);
247 return svsel_f32(eqz, zero, svdiv_f32_z(pg, a, safe));
248}
249
250static svfloat32_t sign4(svbool_t pg, svfloat32_t x)
251{
252 const svfloat32_t zero = svdup_n_f32(0.0f);
253 const svfloat32_t one = svdup_n_f32(1.0f);
254 svfloat32_t r = svsel_f32(svcmpgt_f32(pg, x, zero), one, zero);
255 return svsel_f32(svcmplt_f32(pg, x, zero), svneg_f32_z(pg, one), r);
256}
257
258void vec4_add_ptr_sve(vector4 *res, const vector4 *a, const vector4 *b)
259{
260 const svbool_t pg = pg4();
261 svst1_f32(pg, res->v, svadd_f32_z(pg, svld1_f32(pg, a->v), svld1_f32(pg, b->v)));
262}
263
264void vec4_sub_ptr_sve(vector4 *res, const vector4 *a, const vector4 *b)
265{
266 const svbool_t pg = pg4();
267 svst1_f32(pg, res->v, svsub_f32_z(pg, svld1_f32(pg, a->v), svld1_f32(pg, b->v)));
268}
269
270void vec4_mul_ptr_sve(vector4 *res, const vector4 *a, const vector4 *b)
271{
272 const svbool_t pg = pg4();
273 svst1_f32(pg, res->v, svmul_f32_z(pg, svld1_f32(pg, a->v), svld1_f32(pg, b->v)));
274}
275
277{
278 const svbool_t pg = pg4();
279 svst1_f32(pg, res->v, svmul_n_f32_z(pg, svld1_f32(pg, v->v), s));
280}
281
283{
284 const svbool_t pg = pg4();
285 if (s == 0.0f) {
286 svst1_f32(pg, res->v, svdup_n_f32(0.0f));
287 return;
288 }
289 svst1_f32(pg, res->v, svdiv_n_f32_z(pg, svld1_f32(pg, v->v), s));
290}
291
292void vec4_neg_ptr_sve(vector4 *res, const vector4 *v)
293{
294 const svbool_t pg = pg4();
295 svst1_f32(pg, res->v, svneg_f32_z(pg, svld1_f32(pg, v->v)));
296}
297
298void vec4_abs_ptr_sve(vector4 *res, const vector4 *v)
299{
300 const svbool_t pg = pg4();
301 svst1_f32(pg, res->v, svabs_f32_z(pg, svld1_f32(pg, v->v)));
302}
303
304void vec4_normalize_ptr_sve(vector4 *res, const vector4 *v)
305{
306 const svbool_t pg = pg4();
307 const svfloat32_t x = svld1_f32(pg, v->v);
308 const float len2 = svaddv_f32(pg, svmul_f32_z(pg, x, x));
309 if (len2 == 0.0f) {
310 *res = *v;
311 return;
312 }
313 const svfloat32_t s = svdup_n_f32(len2);
314 svfloat32_t e = svrsqrte_f32(s);
315 e = svmul_f32_z(pg, e, svrsqrts_f32(s, svmul_f32_z(pg, e, e)));
316 svst1_f32(pg, res->v, svmul_f32_z(pg, x, e));
317}
318
319void vec4_min_ptr_sve(vector4 *res, const vector4 *a, const vector4 *b)
320{
321 const svbool_t pg = pg4();
322 svst1_f32(pg, res->v, svmin_f32_z(pg, svld1_f32(pg, a->v), svld1_f32(pg, b->v)));
323}
324
325void vec4_max_ptr_sve(vector4 *res, const vector4 *a, const vector4 *b)
326{
327 const svbool_t pg = pg4();
328 svst1_f32(pg, res->v, svmax_f32_z(pg, svld1_f32(pg, a->v), svld1_f32(pg, b->v)));
329}
330
331void vec4_lerp_ptr_sve(vector4 *res, const vector4 *a, const vector4 *b, vm_float_t t)
332{
333 const svbool_t pg = pg4();
334 const svfloat32_t va = svld1_f32(pg, a->v);
335 const svfloat32_t d = svsub_f32_z(pg, svld1_f32(pg, b->v), va);
336 svst1_f32(pg, res->v, svmla_n_f32_z(pg, va, d, t));
337}
338
339void vec4_clamp_ptr_sve(vector4 *res, const vector4 *v, const vector4 *min, const vector4 *max)
340{
341 const svbool_t pg = pg4();
342 svfloat32_t x = svld1_f32(pg, v->v);
343 x = svmax_f32_z(pg, svld1_f32(pg, min->v), x);
344 x = svmin_f32_z(pg, svld1_f32(pg, max->v), x);
345 svst1_f32(pg, res->v, x);
346}
347
348void vec4_div_ptr_sve(vector4 *res, const vector4 *a, const vector4 *b)
349{
350 const svbool_t pg = pg4();
351 svst1_f32(pg, res->v, hadamard_div(pg, svld1_f32(pg, a->v), svld1_f32(pg, b->v)));
352}
353
355{
356 const svbool_t pg = pg4();
357 svst1_f32(pg, res->v, svadd_n_f32_z(pg, svld1_f32(pg, v->v), s));
358}
359
361{
362 const svbool_t pg = pg4();
363 svst1_f32(pg, res->v, svsub_n_f32_z(pg, svld1_f32(pg, v->v), s));
364}
365
367{
368 const svbool_t pg = pg4();
369 svfloat32_t x = svmax_n_f32_z(pg, svld1_f32(pg, v->v), min);
370 svst1_f32(pg, res->v, svmin_n_f32_z(pg, x, max));
371}
372
373void vec4_saturate_ptr_sve(vector4 *res, const vector4 *v)
374{
375 const svbool_t pg = pg4();
376 svfloat32_t x = svmax_n_f32_z(pg, svld1_f32(pg, v->v), 0.0f);
377 svst1_f32(pg, res->v, svmin_n_f32_z(pg, x, 1.0f));
378}
379
380void vec4_sign_ptr_sve(vector4 *res, const vector4 *v)
381{
382 const svbool_t pg = pg4();
383 svst1_f32(pg, res->v, sign4(pg, svld1_f32(pg, v->v)));
384}
385
386void vec4_floor_ptr_sve(vector4 *res, const vector4 *v)
387{
388 const svbool_t pg = pg4();
389 svst1_f32(pg, res->v, svrintm_f32_z(pg, svld1_f32(pg, v->v)));
390}
391
392void vec4_ceil_ptr_sve(vector4 *res, const vector4 *v)
393{
394 const svbool_t pg = pg4();
395 svst1_f32(pg, res->v, svrintp_f32_z(pg, svld1_f32(pg, v->v)));
396}
397
398void vec4_round_ptr_sve(vector4 *res, const vector4 *v)
399{
400 const svbool_t pg = pg4();
401 svst1_f32(pg, res->v, svrinta_f32_z(pg, svld1_f32(pg, v->v)));
402}
403
404void vec4_fract_ptr_sve(vector4 *res, const vector4 *v)
405{
406 const svbool_t pg = pg4();
407 const svfloat32_t x = svld1_f32(pg, v->v);
408 svst1_f32(pg, res->v, svsub_f32_z(pg, x, svrintm_f32_z(pg, x)));
409}
410
411void vec4_homogenize_ptr_sve(vector4 *res, const vector4 *v)
412{
413 const svbool_t pg = pg4();
414 if (VECMAT_FABS(v->w) > VECMAT_EPSILON) {
415 svst1_f32(pg, res->v, svmul_n_f32_z(pg, svld1_f32(pg, v->v), 1.0f / v->w));
416 res->w = 1.0f;
417 } else {
418 svst1_f32(pg, res->v, svdup_n_f32(0.0f));
419 }
420}
421
422static svfloat32_t quat_mul4(svbool_t pg, svfloat32_t a, svfloat32_t b)
423{
424 const uint32_t i1[4] = {3, 2, 1, 0};
425 const uint32_t i2[4] = {2, 3, 0, 1};
426 const uint32_t i3[4] = {1, 0, 3, 2};
427 const svuint32_t lane = svindex_u32(0, 1);
428 const svbool_t n13 = svorr_z(pg, svcmpeq_n_u32(pg, lane, 1), svcmpeq_n_u32(pg, lane, 3));
429 const svbool_t n23 = svorr_z(pg, svcmpeq_n_u32(pg, lane, 2), svcmpeq_n_u32(pg, lane, 3));
430 const svbool_t n03 = svorr_z(pg, svcmpeq_n_u32(pg, lane, 0), svcmpeq_n_u32(pg, lane, 3));
431
432 svfloat32_t t1 = svtbl_f32(b, svld1_u32(pg, i1));
433 svfloat32_t t2 = svtbl_f32(b, svld1_u32(pg, i2));
434 svfloat32_t t3 = svtbl_f32(b, svld1_u32(pg, i3));
435 t1 = svneg_f32_m(t1, n13, t1);
436 t2 = svneg_f32_m(t2, n23, t2);
437 t3 = svneg_f32_m(t3, n03, t3);
438
439 float aa[4];
440 svst1_f32(pg, aa, a);
441 svfloat32_t r = svmul_n_f32_z(pg, b, aa[3]);
442 r = svmla_n_f32_z(pg, r, t1, aa[0]);
443 r = svmla_n_f32_z(pg, r, t2, aa[1]);
444 r = svmla_n_f32_z(pg, r, t3, aa[2]);
445 return r;
446}
447
448void quat_mul_ptr_sve(quaternion *res, const quaternion *a, const quaternion *b)
449{
450 const svbool_t pg = pg4();
451 svst1_f32(pg, res->v, quat_mul4(pg, svld1_f32(pg, a->v), svld1_f32(pg, b->v)));
452}
453
455{
456 vec4_normalize_ptr_sve((vector4 *)res, (const vector4 *)q);
457}
458
459#endif
static __m256d hadamard_div(__m256d a, __m256d b)
Definition vector4_ptr.c:21
static __m256d sign4(__m256d x)
Definition vector4_ptr.c:29
void quat_normalize_ptr_sve(quaternion *res, const quaternion *q)
void vec4_homogenize_ptr_sve(vector4 *res, const vector4 *v)
static svbool_t pg4(void)
Definition vector4_ptr.c:11
void vec4_abs_ptr_sve(vector4 *res, const vector4 *v)
Definition vector4_ptr.c:72
void vec4_floor_ptr_sve(vector4 *res, const vector4 *v)
void vec4_div_scalar_ptr_sve(vector4 *res, const vector4 *v, vm_float_t s)
Definition vector4_ptr.c:56
void vec4_ceil_ptr_sve(vector4 *res, const vector4 *v)
void vec4_max_ptr_sve(vector4 *res, const vector4 *a, const vector4 *b)
void vec4_add_ptr_sve(vector4 *res, const vector4 *a, const vector4 *b)
Definition vector4_ptr.c:32
void vec4_saturate_ptr_sve(vector4 *res, const vector4 *v)
void vec4_mul_ptr_sve(vector4 *res, const vector4 *a, const vector4 *b)
Definition vector4_ptr.c:44
void vec4_clamp_scalar_ptr_sve(vector4 *res, const vector4 *v, vm_float_t min, vm_float_t max)
static svfloat64_t quat_mul4(svbool_t pg, svfloat64_t a, svfloat64_t b)
void vec4_sub_ptr_sve(vector4 *res, const vector4 *a, const vector4 *b)
Definition vector4_ptr.c:38
void vec4_normalize_ptr_sve(vector4 *res, const vector4 *v)
Definition vector4_ptr.c:78
void vec4_sign_ptr_sve(vector4 *res, const vector4 *v)
void vec4_mul_scalar_ptr_sve(vector4 *res, const vector4 *v, vm_float_t s)
Definition vector4_ptr.c:50
void vec4_add_scalar_ptr_sve(vector4 *res, const vector4 *v, vm_float_t s)
void vec4_round_ptr_sve(vector4 *res, const vector4 *v)
void vec4_div_ptr_sve(vector4 *res, const vector4 *a, const vector4 *b)
void vec4_sub_scalar_ptr_sve(vector4 *res, const vector4 *v, vm_float_t s)
void vec4_lerp_ptr_sve(vector4 *res, const vector4 *a, const vector4 *b, vm_float_t t)
void vec4_neg_ptr_sve(vector4 *res, const vector4 *v)
Definition vector4_ptr.c:66
void quat_mul_ptr_sve(quaternion *res, const quaternion *a, const quaternion *b)
void vec4_fract_ptr_sve(vector4 *res, const vector4 *v)
void vec4_clamp_ptr_sve(vector4 *res, const vector4 *v, const vector4 *min, const vector4 *max)
void vec4_min_ptr_sve(vector4 *res, const vector4 *a, const vector4 *b)
Definition vector4_ptr.c:94
vm_float_t v[VECMAT_QUAT_SIZE]
Definition vecmat.h:368
vm_float_t v[VECMAT_VEC4_SIZE]
Definition vecmat.h:153
vm_float_t w
Definition vecmat.h:151
#define VECMAT_EPSILON
Definition vecmat.h:377
double vm_float_t
Definition vecmat.h:79
#define VECMAT_FABS(x)
Definition vecmat.h:413