103typedef union ALIGN(16) SimdVec2 {
124typedef union ALIGN(16) SimdVec3 {
150typedef union ALIGN(16) SimdVec4 {
170static inline void vec2_print(
const Vec2 v,
const char* name) {
172 printf(
"%s: ", name);
174 printf(
"Vec2(%f, %f)\n", v.
x, v.
y);
182static inline void vec3_print(
const Vec3 v,
const char* name) {
184 printf(
"%s: ", name);
186 printf(
"Vec3(%.4f, %.4f, %.4f)\n", v.
x, v.
y, v.
z);
194static inline void vec3_print_ex(
const Vec3 v,
const char* name) {
196 printf(
"%s: ", name);
198 printf(
"Vec3(%f, %f, %f)\n", v.
x, v.
y, v.
z);
206static inline void vec4_print(
const Vec4 v,
const char* name) {
208 printf(
"%s: ", name);
210 printf(
"Vec4(%.4f, %.4f, %.4f, %.4f)\n", v.
x, v.
y, v.
z, v.
w);
225static inline SimdVec2 vec2_load(
Vec2 v) {
229 res.v = simd_set(v.
x, v.
y, 0.0f, 0.0f);
244static inline Vec2 vec2_store(SimdVec2 v) {
246 return (
Vec2){v.
x, v.y};
260static inline SimdVec2 vec2_add(SimdVec2 a, SimdVec2 b) {
return (SimdVec2){.v = simd_add(a.v, b.v)}; }
271static inline SimdVec2 vec2_sub(SimdVec2 a, SimdVec2 b) {
return (SimdVec2){.v = simd_sub(a.v, b.v)}; }
284static inline SimdVec2 vec2_mul(SimdVec2 a,
float s) {
return (SimdVec2){.v = simd_mul(a.v, simd_set1(s))}; }
299static inline float vec2_dot(SimdVec2 a, SimdVec2 b) {
305 return (a.x * b.x) + (a.y * b.y);
319static inline float vec2_length_sq(SimdVec2 v) {
return vec2_dot(v, v); }
332static inline float vec2_length(SimdVec2 v) {
return sqrtf(vec2_length_sq(v)); }
348static inline SimdVec2 vec2_normalize(SimdVec2 v) {
351 return (SimdVec2){.v = simd_normalize3(v.v)};
375static inline SimdVec2 vec2_rotate(SimdVec2 v,
float angle) {
376 float c = cosf(angle);
377 float s = sinf(angle);
380 simd_vec_t x = simd_splat_x(v.v);
381 simd_vec_t y = simd_splat_y(v.v);
386 simd_vec_t c0 = simd_set(c, s, 0.0f, 0.0f);
387 simd_vec_t c1 = simd_set(-s, c, 0.0f, 0.0f);
390 return (SimdVec2){.v = simd_add(simd_mul(x, c0), simd_mul(y, c1))};
403static inline float vec2_distance_sq(SimdVec2 a, SimdVec2 b) {
return vec2_length_sq(vec2_sub(b, a)); }
412static inline float vec2_distance(SimdVec2 a, SimdVec2 b) {
return sqrtf(vec2_distance_sq(a, b)); }
424static inline SimdVec2 vec2_lerp(SimdVec2 a, SimdVec2 b,
float t) {
426 SimdVec2 diff = vec2_sub(b, a);
427 SimdVec2 part = vec2_mul(diff, t);
428 return vec2_add(a, part);
435static inline SimdVec2 vec2_project(SimdVec2 a, SimdVec2 b) {
436 float b_len_sq = vec2_length_sq(b);
437 if (b_len_sq < 1e-6f)
return (SimdVec2){{0}};
439 float scale = vec2_dot(a, b) / b_len_sq;
440 return vec2_mul(b, scale);
447static inline SimdVec2 vec2_reject(SimdVec2 a, SimdVec2 b) {
return vec2_sub(a, vec2_project(a, b)); }
453static inline SimdVec2 vec2_perpendicular(SimdVec2 v) {
457 return (SimdVec2){.v = simd_set(-v.y, v.x, 0.0f, 0.0f)};
473static inline SimdVec3 vec3_load(
Vec3 v) {
476 res.v = simd_set(v.
x, v.
y, v.
z, 0.0f);
488static inline Vec3 vec3_store(SimdVec3 v) {
return (
Vec3){v.
x, v.y, v.z}; }
499static inline SimdVec3 vec3_add(SimdVec3 a, SimdVec3 b) {
return (SimdVec3){.v = simd_add(a.v, b.v)}; }
510static inline SimdVec3 vec3_sub(SimdVec3 a, SimdVec3 b) {
return (SimdVec3){.v = simd_sub(a.v, b.v)}; }
521static inline SimdVec3 vec3_mul(SimdVec3 a,
float s) {
return (SimdVec3){.v = simd_mul(a.v, simd_set1(s))}; }
536static inline SimdVec3 vec3_scale(SimdVec3 a, SimdVec3 b) {
return (SimdVec3){.v = simd_mul(a.v, b.v)}; }
553static inline float vec3_dot(SimdVec3 a, SimdVec3 b) {
return simd_dot3(a.v, b.v); }
578static inline SimdVec3 vec3_cross(SimdVec3 a, SimdVec3 b) {
return (SimdVec3){.v = simd_cross(a.v, b.v)}; }
592static inline float vec3_length_sq(SimdVec3 v) {
return simd_length_sq3(v.v); }
602static inline float vec3_length(SimdVec3 v) {
return simd_length3(v.v); }
617static inline SimdVec3 vec3_normalize(SimdVec3 v) {
return (SimdVec3){.v = simd_normalize3(v.v)}; }
640static inline SimdVec3 vec3_normalize_fast(SimdVec3 v) {
return (SimdVec3){.v = simd_normalize3_fast(v.v)}; }
649static inline float vec3_distance_sq(SimdVec3 a, SimdVec3 b) {
return vec3_length_sq(vec3_sub(b, a)); }
658static inline float vec3_distance(SimdVec3 a, SimdVec3 b) {
return sqrtf(vec3_distance_sq(a, b)); }
670static inline SimdVec3 vec3_lerp(SimdVec3 a, SimdVec3 b,
float t) {
671 SimdVec3 diff = vec3_sub(b, a);
672 return vec3_add(a, vec3_mul(diff, t));
684static inline SimdVec3 vec3_project(SimdVec3 a, SimdVec3 b) {
685 float b_len_sq = vec3_length_sq(b);
686 if (b_len_sq < 1e-6f)
return (SimdVec3){{0}};
688 float scale = vec3_dot(a, b) / b_len_sq;
689 return vec3_mul(b, scale);
701static inline SimdVec3 vec3_reject(SimdVec3 a, SimdVec3 b) {
return vec3_sub(a, vec3_project(a, b)); }
715static inline SimdVec3 vec3_perpendicular(SimdVec3 v) {
723 if (fabsf(v.y) < 0.99f) {
724 axis = vec3_load((
Vec3){0.0f, 1.0f, 0.0f});
726 axis = vec3_load((
Vec3){1.0f, 0.0f, 0.0f});
729 return vec3_normalize(vec3_cross(v, axis));
745static inline SimdVec4 vec4_load(
Vec4 v) {
747 res.v = simd_set(v.
x, v.
y, v.
z, v.
w);
757static inline Vec4 vec4_store(SimdVec4 v) {
return (
Vec4){v.
x, v.y, v.z, v.w}; }
767static inline float vec4_length(SimdVec4 v) {
return simd_length4(v.v); }
777static inline float vec4_length_sq(SimdVec4 v) {
return simd_length_sq4(v.v); }
786static inline SimdVec4 vec4_add(SimdVec4 a, SimdVec4 b) {
return (SimdVec4){.v = simd_add(a.v, b.v)}; }
795static inline SimdVec4 vec4_sub(SimdVec4 a, SimdVec4 b) {
return (SimdVec4){.v = simd_sub(a.v, b.v)}; }
804static inline SimdVec4 vec4_mul(SimdVec4 a,
float s) {
return (SimdVec4){.v = simd_mul(a.v, simd_set1(s))}; }
816static inline SimdVec4 vec4_div(SimdVec4 a,
float s) {
818 if (fabsf(s) < 1e-8f) {
819 return (SimdVec4){.v = simd_set_zero()};
823 return vec4_mul(a, 1.0f / s);
838static inline float vec4_dot(SimdVec4 a, SimdVec4 b) {
return simd_dot4(a.v, b.v); }
849static inline SimdVec4 vec4_scale(SimdVec4 a, SimdVec4 b) {
return (SimdVec4){.v = simd_mul(a.v, b.v)}; }
859static inline SimdVec4 vec4_normalize(SimdVec4 a) {
return (SimdVec4){.v = simd_normalize4(a.v)}; }
891static inline SimdVec4 vec4_rotate_x(SimdVec4 v,
float angle) {
892 float c = cosf(angle);
893 float s = sinf(angle);
897 float ny = v.y * c - v.z * s;
898 float nz = v.y * s + v.z * c;
900 return (SimdVec4){.v = simd_set(v.x, ny, nz, v.w)};
924static inline SimdVec4 vec4_rotate_y(SimdVec4 v,
float angle) {
925 float c = cosf(angle);
926 float s = sinf(angle);
930 float nx = v.x * c + v.z * s;
931 float nz = -v.x * s + v.z * c;
933 return (SimdVec4){.v = simd_set(nx, v.y, nz, v.w)};
959static inline SimdVec4 vec4_rotate_z(SimdVec4 v,
float angle) {
960 float c = cosf(angle);
961 float s = sinf(angle);
965 float nx = v.x * c - v.y * s;
966 float ny = v.x * s + v.y * c;
968 return (SimdVec4){.v = simd_set(nx, ny, v.z, v.w)};
993static inline bool vec3_equals(
Vec3 a,
Vec3 b,
float epsilon) {
995 SimdVec3 sa = vec3_load(a);
996 SimdVec3 sb = vec3_load(b);
997 return simd_equals_eps(sa.v, sb.v, epsilon);
1013static inline bool vec4_equals(
Vec4 a,
Vec4 b,
float epsilon) {
1014 SimdVec4 sa = vec4_load(a);
1015 SimdVec4 sb = vec4_load(b);
1016 return simd_equals_eps(sa.v, sb.v, epsilon);
1026static inline float vec4_distance_sq(SimdVec4 a, SimdVec4 b) {
return vec4_length_sq(vec4_sub(b, a)); }
1035static inline float vec4_distance(SimdVec4 a, SimdVec4 b) {
return sqrtf(vec4_distance_sq(a, b)); }
1047static inline SimdVec4 vec4_lerp(SimdVec4 a, SimdVec4 b,
float t) {
1048 SimdVec4 diff = vec4_sub(b, a);
1049 return vec4_add(a, vec4_mul(diff, t));
1061static inline SimdVec4 vec4_project(SimdVec4 a, SimdVec4 b) {
1062 float b_len_sq = vec4_length_sq(b);
1063 if (b_len_sq < 1e-6f)
return (SimdVec4){{0}};
1065 float scale = vec4_dot(a, b) / b_len_sq;
1066 return vec4_mul(b, scale);
1078static inline SimdVec4 vec4_reject(SimdVec4 a, SimdVec4 b) {
return vec4_sub(a, vec4_project(a, b)); }
1083static inline SimdVec4 vec4_min(SimdVec4 a, SimdVec4 b) {
return (SimdVec4){.v = simd_min(a.v, b.v)}; }
1088static inline SimdVec4 vec4_max(SimdVec4 a, SimdVec4 b) {
return (SimdVec4){.v = simd_max(a.v, b.v)}; }
1093static inline SimdVec4 vec4_abs(SimdVec4 v) {
return (SimdVec4){.v = simd_abs(v.v)}; }
1098static inline float vec4_sum(SimdVec4 v) {
return simd_hadd(v.v); }
Portable Single Instruction Multiple Data (SIMD) Intrinsics Wrapper.
2D vector storage type (8 bytes, unaligned).
3D vector storage type (12 bytes, unaligned).
4D vector storage type (16 bytes, naturally aligned).
float w
W component (also used for homogeneous coordinates)