// Copyright 2023 alexevier // licensed under the zlib license #ifndef lexlib_math_vec4_h #define lexlib_math_vec4_h #include #include"../common.h" #include"../simd.h" /* NOTE s if SIMD is enabled memory should be aligned. */ struct LEXLIB_ALIGN(16) LexlibVec4 { float x; float y; float z; float w; }; #define LEXL_VEC4_ZERO ((struct LexlibVec4){0.0f, 0.0f, 0.0f, 0.0f}) // adds b to a // result.xyzw = a.xyzw + b.xyzw LEXLIB_INLINE void lexlibVec4Add(struct LexlibVec4 *result, const struct LexlibVec4 *a, const struct LexlibVec4 *b){ #if LEXLIB_SIMD_MATH && defined(LEXLIB_SSE) lexlibSimd128fStore( (float*)result, lexlibSimd128fAdd( lexlibSimd128fLoad((const float*)a), lexlibSimd128fLoad((const float*)b) ) ); #else result->x = a->x + b->x; result->y = a->y + b->y; result->z = a->z + b->z; result->w = a->w + b->w; #endif } // subtracts b from a // result.xyzw = a.xyzw - b.xyzw LEXLIB_INLINE void lexlibVec4Sub(struct LexlibVec4 *result, const struct LexlibVec4 *a, const struct LexlibVec4 *b){ #if LEXLIB_SIMD_MATH && defined(LEXLIB_SSE) lexlibSimd128fStore( (float*)result, lexlibSimd128fSub( lexlibSimd128fLoad((const float*)a), lexlibSimd128fLoad((const float*)b) ) ); #else result->x = a->x - b->x; result->y = a->y - b->y; result->z = a->z - b->z; result->w = a->w - b->w; #endif } // multiplies a with b // result.xyzw = a.xyzw * b.xyzw LEXLIB_INLINE void lexlibVec4Mul(struct LexlibVec4 *result, const struct LexlibVec4 *a, const struct LexlibVec4 *b){ #if LEXLIB_SIMD_MATH && defined(LEXLIB_SSE) lexlibSimd128fStore( (float*)result, lexlibSimd128fMul( lexlibSimd128fLoad((const float*)a), lexlibSimd128fLoad((const float*)b) ) ); #else result->x = a->x * b->x; result->y = a->y * b->y; result->z = a->z * b->z; result->w = a->w * b->w; #endif } // divides a with b // result.xyzw = a.xyzw / b.xyzw LEXLIB_INLINE void lexlibVec4Div(struct LexlibVec4 *result, const struct LexlibVec4 *a, const struct LexlibVec4 *b){ #if LEXLIB_SIMD_MATH && defined(LEXLIB_SSE) lexlibSimd128fStore( (float*)result, lexlibSimd128fDiv( lexlibSimd128fLoad((const float*)a), lexlibSimd128fLoad((const float*)b) ) ); #else result->x = a->x / b->x; result->y = a->y / b->y; result->z = a->z / b->z; result->w = a->w / b->w; #endif } // adds scalar b to a // result.xyzw = a.xyzw + b LEXLIB_INLINE void lexlibVec4Adds(struct LexlibVec4 *result, const struct LexlibVec4 *a, float b){ #if LEXLIB_SIMD_MATH && defined(LEXLIB_SSE) lexlibSimd128fStore( (float*)result, lexlibSimd128fAdd( lexlibSimd128fLoad((const float*)a), lexlibSimd128fSet1(b) ) ); #else result->x = a->x + b; result->y = a->y + b; result->z = a->z + b; result->w = a->w + b; #endif } // subtracts scalar b from a // result.xyzw = a.xyzw - b LEXLIB_INLINE void lexlibVec4Subs(struct LexlibVec4 *result, const struct LexlibVec4 *a, float b){ #if LEXLIB_SIMD_MATH && defined(LEXLIB_SSE) lexlibSimd128fStore( (float*)result, lexlibSimd128fSub( lexlibSimd128fLoad((const float*)a), lexlibSimd128fSet1(b) ) ); #else result->x = a->x - b; result->y = a->y - b; result->z = a->z - b; result->w = a->w - b; #endif } // multiplies a with scalar b (does the same as lexlibVec4Scale) // result.xyzw = a.xyzw * b.xyzw LEXLIB_INLINE void lexlibVec4Muls(struct LexlibVec4 *result, const struct LexlibVec4 *a, float b){ #if LEXLIB_SIMD_MATH && defined(LEXLIB_SSE) lexlibSimd128fStore( (float*)result, lexlibSimd128fMul( lexlibSimd128fLoad((const float*)a), lexlibSimd128fSet1(b) ) ); #else result->x = a->x * b; result->y = a->y * b; result->z = a->z * b; result->w = a->w * b; #endif } // divides a with scalar b // result.xyzw = a.xyzw / b LEXLIB_INLINE void lexlibVec4Divs(struct LexlibVec4 *result, const struct LexlibVec4 *a, float b){ #if LEXLIB_SIMD_MATH && defined(LEXLIB_SSE) lexlibSimd128fStore( (float*)result, lexlibSimd128fDiv( lexlibSimd128fLoad((const float*)a), lexlibSimd128fSet1(b) ) ); #else result->x = a->x / b; result->y = a->y / b; result->z = a->z / b; result->w = a->w / b; #endif } // scales a vector with a scalar value // result.xyzw = vector.xyzw * scalar LEXLIB_INLINE void lexlibVec4Scale(struct LexlibVec4 *result, const struct LexlibVec4 *vector, float scalar){ #if LEXLIB_SIMD_MATH && defined(LEXLIB_SSE) lexlibSimd128fStore( (float*)result, lexlibSimd128fDiv( lexlibSimd128fLoad((const float*)vector), lexlibSimd128fSet1(scalar) ) ); #else result->x = vector->x * scalar; result->y = vector->y * scalar; result->z = vector->z * scalar; result->w = vector->w * scalar; #endif } // calculates the dot product // result = (a.x * b.x) + (a.y * b.y) + (a.z * b.z) + (a.w * b.w) LEXLIB_INLINE float lexlibVec4Dot(const struct LexlibVec4 *a, const struct LexlibVec4 *b){ #if LEXLIB_SIMD_MATH && defined(LEXLIB_SSE) LexlibSimd128f tmp = lexlibSimd128fMul( lexlibSimd128fLoad((const float*)a), lexlibSimd128fLoad((const float*)b) ); return tmp[0] + tmp[1] + tmp[2] + tmp[3]; #else return (a->x * b->x) + (a->y * b->y) + (a->z * b->z) + (a->w * b->w); #endif } // calculates the magnitude of a vector LEXLIB_INLINE float lexlibVec4Mag(const struct LexlibVec4 *vector){ return sqrtf(lexlibVec4Dot(vector, vector)); } // normalizes a vector LEXLIB_INLINE void lexlibVec4Norm(struct LexlibVec4 *result, const struct LexlibVec4 *vec){ float mag = lexlibVec4Mag(vec); if(mag == 0.0f){ #if LEXLIB_SIMD_MATH && defined(LEXLIB_SSE) lexlibSimd128fStore( (float*)result, lexlibSimd128fSet1(0.0f) ); #else result->x = 0.0f; result->y = 0.0f; result->z = 0.0f; result->w = 0.0f; #endif return; } lexlibVec4Divs(result, vec, mag); } // negates a vector LEXLIB_INLINE void lexlibVec4Neg(struct LexlibVec4 *result, const struct LexlibVec4 *vec){ result->x = -vec->x; result->y = -vec->y; result->z = -vec->z; result->w = -vec->w; } #endif