#ifndef CORE_GENERIC_H #define CORE_GENERIC_H #include "core/Matrix.h" // clang-format off #define GENERIC_PAIR(type, name) type: name, const type : name // clang-format on #define GENERIC_FLOAT_VECTOR(a, name) \ _Generic((a), \ GENERIC_PAIR(Vector2*, name##V2), \ GENERIC_PAIR(Vector3*, name##V3), \ GENERIC_PAIR(Vector4*, name##V4)) #define GENERIC_VECTOR(a, name) \ _Generic((a), \ GENERIC_PAIR(Vector2*, name##V2), \ GENERIC_PAIR(Vector3*, name##V3), \ GENERIC_PAIR(Vector4*, name##V4), \ GENERIC_PAIR(IntVector2*, name##IV2), \ GENERIC_PAIR(IntVector3*, name##IV3), \ GENERIC_PAIR(IntVector4*, name##IV4)) #define ZERO_VECTOR(a) \ _Generic((a), \ GENERIC_PAIR(Matrix*, &(Vector3){0}), \ GENERIC_PAIR(Vector2*, &(Vector2){0}), \ GENERIC_PAIR(Vector3*, &(Vector3){0}), \ GENERIC_PAIR(Vector4*, &(Vector4){0}), \ GENERIC_PAIR(IntVector2*, &(IntVector2){0}), \ GENERIC_PAIR(IntVector3*, &(IntVector3){0}), \ GENERIC_PAIR(IntVector4*, &(IntVector4){0})) #define GENERIC_FACTOR(b, type, base, factor) \ type: \ _Generic((b), GENERIC_PAIR(type, base), default: factor) #define SELECT_OP(_1, _2, _3, name, ...) name #define addSet(a, b) GENERIC_VECTOR(a, addSet)(a, b) #define add3(a, b, c) GENERIC_VECTOR(a, add)(a, b, c) #define add2(a, b) add3(ZERO_VECTOR(a), a, b) #define add(...) SELECT_OP(__VA_ARGS__, add3, add2, 0)(__VA_ARGS__) #define subSet(a, b) GENERIC_VECTOR(a, subSet)(a, b) #define sub3(a, b, c) GENERIC_VECTOR(a, sub)(a, b, c) #define sub2(a, b) sub3(ZERO_VECTOR(a), a, b) #define sub(...) SELECT_OP(__VA_ARGS__, sub3, sub2, 0)(__VA_ARGS__) #define mulSet(a, b) \ _Generic((a), \ Matrix *: mulSetMatrix, \ Quaternion *: mulSetQ, \ GENERIC_FACTOR(b, Vector2*, mulSetV2, mulSetV2F), \ GENERIC_FACTOR(b, Vector3*, mulSetV3, mulSetV3F), \ GENERIC_FACTOR(b, Vector4*, mulSetV4, mulSetV4F), \ GENERIC_FACTOR(b, IntVector2*, mulSetIV2, mulSetIV2F), \ GENERIC_FACTOR(b, IntVector3*, mulSetIV3, mulSetIV3F), \ GENERIC_FACTOR(b, IntVector4*, mulSetIV4, mulSetIV4F))(a, b) #define mul3(a, b, c) \ _Generic((a), \ Matrix *: mulMatrix, \ Quaternion *: mulQ, \ GENERIC_FACTOR(c, Vector2*, mulV2, mulV2F), \ Vector3 *: _Generic((c), \ Vector3 *: _Generic((b), \ GENERIC_PAIR(Quaternion*, mulQV3), \ GENERIC_PAIR(Matrix*, mulMatrixV3), \ default: mulV3), \ default: mulV3F), \ GENERIC_FACTOR(c, Vector4*, mulV4, mulV4F), \ GENERIC_FACTOR(c, IntVector2*, mulIV2, mulIV2F), \ GENERIC_FACTOR(c, IntVector3*, mulIV3, mulIV3F), \ GENERIC_FACTOR(c, IntVector4*, mulIV4, mulIV4F))(a, b, c) #define mul2(a, b) mul3(ZERO_VECTOR(a), a, b) #define mul(...) SELECT_OP(__VA_ARGS__, mul3, mul2, 0)(__VA_ARGS__) #define divSet(a, b) \ _Generic((a), \ GENERIC_FACTOR(b, Vector2*, divSetV2, divSetV2F), \ GENERIC_FACTOR(b, Vector3*, divSetV3, divSetV3F), \ GENERIC_FACTOR(b, Vector4*, divSetV4, divSetV4F), \ GENERIC_FACTOR(b, IntVector2*, divSetIV2, divSetIV2F), \ GENERIC_FACTOR(b, IntVector3*, divSetIV3, divSetIV3F), \ GENERIC_FACTOR(b, IntVector4*, divSetIV4, divSetIV4F))(a, b) #define div3(a, b, c) \ _Generic((a), \ GENERIC_FACTOR(c, Vector2*, divV2, divV2F), \ GENERIC_FACTOR(c, Vector3*, divV3, divV3F), \ GENERIC_FACTOR(c, Vector4*, divV4, divV4F), \ GENERIC_FACTOR(c, IntVector2*, divIV2, divIV2F), \ GENERIC_FACTOR(c, IntVector3*, divIV3, divIV3F), \ GENERIC_FACTOR(c, IntVector4*, divIV4, divIV4F))(a, b, c) #define div2(a, b) div3(ZERO_VECTOR(a), a, b) #define div(...) SELECT_OP(__VA_ARGS__, div3, div2, 0)(__VA_ARGS__) #define invertSet(a) GENERIC_VECTOR(a, invertSet)(a) #define invert2(a, b) GENERIC_VECTOR(a, invert)(a, b) #define invert1(a) invert2(ZERO_VECTOR(a), a) #define invert(...) SELECT_OP(0, __VA_ARGS__, invert2, invert1, 0)(__VA_ARGS__) #define dot(a, b) GENERIC_FLOAT_VECTOR(a, dot)(a, b) #define squareLength(a) GENERIC_FLOAT_VECTOR(a, squareLength)(a) #define length(a) GENERIC_FLOAT_VECTOR(a, length)(a) #define normalize(a) GENERIC_FLOAT_VECTOR(a, normalize)(a) #undef cross #define SELECT_OP(_1, _2, _3, name, ...) name #define cross3(a, b, c) cross(a, b, c) #define cross2(a, b) cross(&(Vector3){0}, a, b) #define cross(...) SELECT_OP(__VA_ARGS__, cross3, cross2, 0)(__VA_ARGS__) #define convert(a, b) \ _Generic((a), \ Vector2 *: convertIV2, \ Vector3 *: convertIV3, \ Vector4 *: convertIV4, \ IntVector2 *: convertV2, \ IntVector3 *: convertV3, \ IntVector4 *: convertV4)(a, b) #endif