#include "float4_dispatch.h" #include // SSE2 intrinsics namespace { typedef __m128 f32x4; // Load 4 floats from memory into a SIMD register inline f32x4 v_load(const float* p) { return _mm_loadu_ps(p); } // Store 4 floats from SIMD register back to memory inline void v_store(float* dst, f32x4 v) { _mm_storeu_ps(dst, v); } // Broadcast a single float across all 4 lanes inline f32x4 v_set1(float s) { return _mm_set1_ps(s); } // Element-wise multiply inline f32x4 v_mul(f32x4 a, f32x4 b) { return _mm_mul_ps(a, b); } // Element-wise divide inline f32x4 v_div(f32x4 a, f32x4 b) { return _mm_div_ps(a, b); } // Element-wise add inline f32x4 v_add(f32x4 a, f32x4 b) { return _mm_add_ps(a, b); } // Element-wise subtract inline f32x4 v_sub(f32x4 a, f32x4 b) { return _mm_sub_ps(a, b); } // Horizontal sum of all 4 elements (for dot product, length, etc.) inline float v_hadd4(f32x4 a) { __m128 shuf = _mm_shuffle_ps(a, a, _MM_SHUFFLE(2, 3, 0, 1)); // swap pairs __m128 sums = _mm_add_ps(a, shuf); // sums: [a0+a1 a1+a0 a2+a3 a3+a2] shuf = _mm_shuffle_ps(sums, sums, _MM_SHUFFLE(1, 0, 3, 2)); // move high pair to low sums = _mm_add_ps(sums, shuf); // total sum in lower float return _mm_cvtss_f32(sums); } inline f32x4 v_cross(f32x4 a, f32x4 b) { f32x4 a_yzx = _mm_shuffle_ps(a, a, _MM_SHUFFLE(3, 0, 2, 1)); f32x4 b_yzx = _mm_shuffle_ps(b, b, _MM_SHUFFLE(3, 0, 2, 1)); f32x4 c = _mm_sub_ps( _mm_mul_ps(a, b_yzx), _mm_mul_ps(a_yzx, b) ); return _mm_shuffle_ps(c, c, _MM_SHUFFLE(3, 0, 2, 1)); } } #include "float4_impl.inl" namespace math_backend::float4::dispatch { // Install SSE2 backend void install_sse2() { gFloat4.add = float4_add_impl; gFloat4.sub = float4_sub_impl; gFloat4.mul = float4_mul_impl; gFloat4.mul_scalar = float4_mul_scalar_impl; gFloat4.div = float4_div_impl; gFloat4.div_scalar = float4_div_scalar_impl; gFloat4.dot = float4_dot_impl; gFloat4.length = float4_length_impl; gFloat4.lengthSquared = float4_length_squared_impl; gFloat4.normalize = float4_normalize_impl; gFloat4.normalize_mag = float4_normalize_mag_impl; gFloat4.lerp = float4_lerp_impl; gFloat4.cross = float4_cross_impl; } }