From 11dc5eebcc21fe619af566e6d5063c640f58bab0 Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Sat, 5 Jul 2014 09:22:18 +0000 Subject: [PATCH] math: put almost all quaternion/vector/matrix operators in ADL namespaces. --- src/Makefile.am | 2 +- src/lol/math/all.h | 1 + src/lol/math/half.h | 2 + src/lol/math/matrix.h | 94 +++++----- src/lol/math/ops.h | 344 +++++++++++++++++++++++++++++++++++ src/lol/math/transform.h | 28 ++- src/lol/math/vector.h | 352 +++++++----------------------------- src/lolcore.vcxproj | 1 + src/lolcore.vcxproj.filters | 3 + 9 files changed, 485 insertions(+), 342 deletions(-) create mode 100644 src/lol/math/ops.h diff --git a/src/Makefile.am b/src/Makefile.am index 6d2641d5..3bbe08e6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -43,7 +43,7 @@ liblolcore_headers = \ lol/math/all.h \ lol/math/functions.h lol/math/vector.h lol/math/half.h lol/math/real.h \ lol/math/geometry.h lol/math/interp.h lol/math/rand.h lol/math/array2d.h \ - lol/math/array3d.h lol/math/constants.h lol/math/matrix.h \ + lol/math/array3d.h lol/math/constants.h lol/math/matrix.h lol/math/ops.h \ lol/math/transform.h \ \ lol/algorithm/all.h \ diff --git a/src/lol/math/all.h b/src/lol/math/all.h index 69b72c14..4b29957e 100644 --- a/src/lol/math/all.h +++ b/src/lol/math/all.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include diff --git a/src/lol/math/half.h b/src/lol/math/half.h index 39cffab5..65a46eec 100644 --- a/src/lol/math/half.h +++ b/src/lol/math/half.h @@ -116,6 +116,8 @@ public: uint16_t bits; }; +static_assert(sizeof(half) == 2, "sizeof(half) == 2"); + static inline half min(half a, half b) { return a < b ? a : b; } static inline half max(half a, half b) { return a > b ? a : b; } static inline float fmod(half a, half b) diff --git a/src/lol/math/matrix.h b/src/lol/math/matrix.h index 12c85ef6..b0d47dbc 100644 --- a/src/lol/math/matrix.h +++ b/src/lol/math/matrix.h @@ -33,8 +33,11 @@ namespace lol */ template -struct mat_t : public linear_ops::base +struct mat_t + : public linear_ops::base> { + static int const count = COLS; + typedef vec_t element; typedef mat_t type; inline mat_t() {} @@ -59,8 +62,11 @@ private: */ template -struct mat_t : public linear_ops::base +struct mat_t + : public linear_ops::base> { + static int const count = 2; + typedef vec_t element; typedef mat_t type; inline mat_t() {} @@ -119,13 +125,25 @@ private: #endif }; +static_assert(sizeof(i8mat2) == 4, "sizeof(i8mat2) == 4"); +static_assert(sizeof(i16mat2) == 8, "sizeof(i16mat2) == 8"); +static_assert(sizeof(imat2) == 16, "sizeof(imat2) == 16"); +static_assert(sizeof(i64mat2) == 32, "sizeof(i64mat2) == 32"); + +static_assert(sizeof(f16mat2) == 8, "sizeof(f16mat2) == 8"); +static_assert(sizeof(mat2) == 16, "sizeof(mat2) == 16"); +static_assert(sizeof(dmat2) == 32, "sizeof(dmat2) == 32"); + /* * 3×3-element matrices */ template -struct mat_t : public linear_ops::base +struct mat_t + : public linear_ops::base> { + static int const count = 3; + typedef vec_t element; typedef mat_t type; inline mat_t() {} @@ -230,13 +248,25 @@ private: #endif }; +static_assert(sizeof(i8mat3) == 9, "sizeof(i8mat3) == 9"); +static_assert(sizeof(i16mat3) == 18, "sizeof(i16mat3) == 18"); +static_assert(sizeof(imat3) == 36, "sizeof(imat3) == 36"); +static_assert(sizeof(i64mat3) == 72, "sizeof(i64mat3) == 72"); + +static_assert(sizeof(f16mat3) == 18, "sizeof(f16mat3) == 18"); +static_assert(sizeof(mat3) == 36, "sizeof(mat3) == 36"); +static_assert(sizeof(dmat3) == 72, "sizeof(dmat3) == 72"); + /* * 4×4-element matrices */ template -struct mat_t : public linear_ops::base +struct mat_t + : public linear_ops::base> { + static int const count = 4; + typedef vec_t element; typedef mat_t type; inline mat_t() {} @@ -388,6 +418,15 @@ private: #endif }; +static_assert(sizeof(i8mat4) == 16, "sizeof(i8mat4) == 16"); +static_assert(sizeof(i16mat4) == 32, "sizeof(i16mat4) == 32"); +static_assert(sizeof(imat4) == 64, "sizeof(imat4) == 64"); +static_assert(sizeof(i64mat4) == 128, "sizeof(i64mat4) == 128"); + +static_assert(sizeof(f16mat4) == 32, "sizeof(f16mat4) == 32"); +static_assert(sizeof(mat4) == 64, "sizeof(mat4) == 64"); +static_assert(sizeof(dmat4) == 128, "sizeof(dmat4) == 128"); + template T determinant(mat_t const &); template T determinant(mat_t const &); template T determinant(mat_t const &); @@ -406,53 +445,6 @@ static inline mat_t transpose(mat_t const &m) return ret; } -/* - * Addition/subtraction/unary - */ - -template -static inline mat_t &operator +=(mat_t &a, - mat_t const &b) -{ - for (int i = 0; i < COLS; ++i) - a[i] += b[i]; - return a; -} - -template -static inline mat_t operator +(mat_t const &a, - mat_t const &b) -{ - mat_t ret = a; - return ret += b; -} - -template -static inline mat_t &operator -=(mat_t &a, - mat_t const &b) -{ - for (int i = 0; i < COLS; ++i) - a[i] -= b[i]; - return a; -} - -template -static inline mat_t operator -(mat_t const &a, - mat_t const &b) -{ - mat_t ret = a; - return ret -= b; -} - -template -static inline mat_t operator -(mat_t const &m) -{ - mat_t ret; - for (int i = 0; i < COLS; ++i) - ret[i] = -m[i]; - return ret; -} - /* * Matrix-vector and vector-matrix multiplication */ diff --git a/src/lol/math/ops.h b/src/lol/math/ops.h new file mode 100644 index 00000000..72f2379b --- /dev/null +++ b/src/lol/math/ops.h @@ -0,0 +1,344 @@ +// +// Lol Engine +// +// Copyright: (c) 2010-2014 Sam Hocevar +// This program is free software; you can redistribute it and/or +// modify it under the terms of the Do What The Fuck You Want To +// Public License, Version 2, as published by Sam Hocevar. See +// http://www.wtfpl.net/ for more details. +// + +// +// Operations for vector classes +// ----------------------------- +// + +#if !defined __LOL_MATH_OPS_H__ +#define __LOL_MATH_OPS_H__ + +#include +#include + +#include +#include + +/* + * Utility namespaces for traits -- this file uses a combination of + * ADL black magic and enable_if to ensure that only the expected type + * conversions are done. + */ + +namespace lol +{ + +/* + * Operators for swizzled vectors. Since template deduction cannot be + * done for two arbitrary vec_t<> values, we help the compiler understand + * the expected type. + */ + +namespace swizzle_ops +{ + +template +struct base {}; + + +template +static inline typename std::enable_if::type operator ==(vec_t const &a, + vec_t const &b) +{ + return vec_t(a) == vec_t(b); +} + +template +static inline typename std::enable_if::type operator !=(vec_t const &a, + vec_t const &b) +{ + return vec_t(a) != vec_t(b); +} + +#define LOL_SWIZZLE_V_VV_OP(op) \ + template \ + inline typename std::enable_if>::type \ + operator op(vec_t const &a, \ + vec_t const &b) \ + { \ + return vec_t(a) op vec_t(b); \ + } \ + \ + template \ + inline typename std::enable_if>::type & \ + operator op##=(vec_t &a, \ + vec_t const &b) \ + { \ + return a op##= vec_t(b); \ + } \ + \ + template \ + inline typename std::enable_if>::type \ + operator op(vec_t a, T const &b) \ + { \ + return vec_t(a) op b; \ + } + +LOL_SWIZZLE_V_VV_OP(+) +LOL_SWIZZLE_V_VV_OP(-) +LOL_SWIZZLE_V_VV_OP(*) +LOL_SWIZZLE_V_VV_OP(/) + +#undef LOL_SWIZZLE_V_VV_OP + +} /* namespace swizzle_ops */ + + +/* + * Linear operations: operators and functions that work on all types + * (vectors, matrices, quaternions...) such as addition or equality test. + * + * Others, e.g. multiplication, cannot be implemented here, since it should + * be implemented as per-component multiplication for vectors, and matrix + * product for matrices. + */ + +namespace linear_ops +{ + +template +struct base {}; + +/* + * Comparisons + */ + +template +static inline typename std::enable_if, V>::value, bool>::type +operator ==(V const &a, V const &b) +{ + for (int i = 0; i < V::count; ++i) + if (!(a[i] == b[i])) + return false; + return true; +} + +template +static inline typename std::enable_if, V>::value, bool>::type +operator !=(V const &a, V const &b) +{ + for (int i = 0; i < V::count; ++i) + if (a[i] != b[i]) + return true; + return false; +} + +/* + * Unary plus and minus + */ + +template +static inline typename std::enable_if, V>::value, typename V::type>::type +operator +(V const &v) +{ + return v; +} + +template +static inline typename std::enable_if, V>::value, typename V::type>::type +operator -(V const &v) +{ + typename V::type ret; + for (int i = 0; i < V::count; ++i) + ret[i] = -v[i]; + return ret; +} + +/* + * Addition and subtraction + */ + +template +static inline typename std::enable_if, V>::value, typename V::type>::type +operator +(V const &a, V const &b) +{ + typename V::type ret; + for (int i = 0; i < V::count; ++i) + ret[i] = a[i] + b[i]; + return ret; +} + +template +static inline typename std::enable_if, V>::value, typename V::type>::type +&operator +=(V &a, V const &b) +{ + return a = a + b; +} + +template +static inline typename std::enable_if, V>::value, typename V::type>::type +operator -(V const &a, V const &b) +{ + typename V::type ret; + for (int i = 0; i < V::count; ++i) + ret[i] = a[i] - b[i]; + return ret; +} + +template +static inline typename std::enable_if, V>::value, typename V::type>::type +&operator -=(V &a, V const &b) +{ + return a = a - b; +} + +/* + * Multiplication by scalar (left) + */ + +template +static inline typename std::enable_if, V>::value, typename V::type>::type +operator *(typename V::element const &val, V const &a) +{ + typename V::type ret; + for (int i = 0; i < V::count; ++i) + ret[i] = val * a[i]; + return ret; +} + +/* + * Multiplication/division by scalar (right) + */ + +template +static inline typename std::enable_if, V>::value, typename V::type>::type +operator *(V const &a, typename V::element const &val) +{ + typename V::type ret; + for (int i = 0; i < V::count; ++i) + ret[i] = a[i] * val; + return ret; +} + +template +static inline typename std::enable_if, V>::value, typename V::type>::type & +operator *=(V &a, typename V::element const &val) +{ + return a = a * val; +} + +template +static inline typename std::enable_if, V>::value, typename V::type>::type +operator /(V const &a, typename V::element const &val) +{ + typename V::type ret; + for (int i = 0; i < V::count; ++i) + ret[i] = a[i] / val; + return ret; +} + +template +static inline typename std::enable_if, V>::value, typename V::type>::type & +operator /=(V &a, typename V::element const &val) +{ + return a = a / val; +} + +} /* namespace linear_ops */ + + +/* + * Operations that work component-wise, such as comparisons or multiplication. + * This is only for vector types, as the other types (matrices, quaternions, + * complexes) have different meanings. + */ + +namespace componentwise_ops +{ + +template +struct base {}; + +template +static inline typename std::enable_if, V>::value, typename V::type>::type +operator *(V const &a, V const &b) +{ + typename V::type ret; + for (int i = 0; i < V::count; ++i) + ret[i] = a[i] * b[i]; + return ret; +} + +template +static inline typename std::enable_if, V>::value, typename V::type>::type +&operator *=(V &a, V const &b) +{ + return a = a * b; +} + +template +static inline typename std::enable_if, V>::value, typename V::type>::type +operator /(V const &a, V const &b) +{ + typename V::type ret; + for (int i = 0; i < V::count; ++i) + ret[i] = a[i] / b[i]; + return ret; +} + +template +static inline typename std::enable_if, V>::value, typename V::type>::type +&operator /=(V &a, V const &b) +{ + return a = a / b; +} + +/* + * Comparisons + */ + +template +static inline typename std::enable_if, V>::value, bool>::type +operator <(V const &a, V const &b) +{ + for (int i = 0; i < V::count; ++i) + if (!(a[i] < b[i])) + return false; + return true; +} + +template +static inline typename std::enable_if, V>::value, bool>::type +operator >(V const &a, V const &b) +{ + for (int i = 0; i < V::count; ++i) + if (!(a[i] > b[i])) + return false; + return true; +} + +template +static inline typename std::enable_if, V>::value, bool>::type +operator <=(V const &a, V const &b) +{ + for (int i = 0; i < V::count; ++i) + if (!(a[i] <= b[i])) + return false; + return true; +} + +template +static inline typename std::enable_if, V>::value, bool>::type +operator >=(V const &a, V const &b) +{ + for (int i = 0; i < V::count; ++i) + if (!(a[i] >= b[i])) + return false; + return true; +} + +} /* namespace componentwise_ops */ + +} /* namespace lol */ + +#endif // __LOL_MATH_OPS_H__ + diff --git a/src/lol/math/transform.h b/src/lol/math/transform.h index 0d191d88..33689fb2 100644 --- a/src/lol/math/transform.h +++ b/src/lol/math/transform.h @@ -30,8 +30,10 @@ namespace lol */ template -struct cmplx_t : public linear_ops::base +struct cmplx_t : public linear_ops::base { + static int const count = 2; + typedef T element; typedef cmplx_t type; inline constexpr cmplx_t() {} @@ -43,7 +45,6 @@ struct cmplx_t : public linear_ops::base : x(z.x), y(z.y) {} LOL_COMMON_MEMBER_OPS(x) - LOL_NONVECTOR_MEMBER_OPS() inline cmplx_t operator *(cmplx_t const &val) const { @@ -66,13 +67,24 @@ struct cmplx_t : public linear_ops::base T x, y; }; +static_assert(sizeof(i8cmplx) == 2, "sizeof(i8cmplx) == 2"); +static_assert(sizeof(i16cmplx) == 4, "sizeof(i16cmplx) == 4"); +static_assert(sizeof(icmplx) == 8, "sizeof(icmplx) == 8"); +static_assert(sizeof(i64cmplx) == 16, "sizeof(i64cmplx) == 16"); + +static_assert(sizeof(f16cmplx) == 4, "sizeof(f16cmplx) == 4"); +static_assert(sizeof(cmplx) == 8, "sizeof(cmplx) == 8"); +static_assert(sizeof(dcmplx) == 16, "sizeof(dcmplx) == 16"); + /* * 4-element transforms: quaternions */ template -struct quat_t : public linear_ops::base +struct quat_t : public linear_ops::base { + static int const count = 4; + typedef T element; typedef quat_t type; /* Default constructor and copy constructor */ @@ -95,7 +107,6 @@ struct quat_t : public linear_ops::base explicit quat_t(mat_t const &m); LOL_COMMON_MEMBER_OPS(w) - LOL_NONVECTOR_MEMBER_OPS() inline quat_t operator *(quat_t const &val) const { @@ -210,6 +221,15 @@ struct quat_t : public linear_ops::base T w, x, y, z; }; +static_assert(sizeof(i8quat) == 4, "sizeof(i8quat) == 4"); +static_assert(sizeof(i16quat) == 8, "sizeof(i16quat) == 8"); +static_assert(sizeof(iquat) == 16, "sizeof(iquat) == 16"); +static_assert(sizeof(i64quat) == 32, "sizeof(i64quat) == 32"); + +static_assert(sizeof(f16quat) == 8, "sizeof(f16quat) == 8"); +static_assert(sizeof(quat) == 16, "sizeof(quat) == 16"); +static_assert(sizeof(dquat) == 32, "sizeof(dquat) == 32"); + /* * Common operations on transforms */ diff --git a/src/lol/math/vector.h b/src/lol/math/vector.h index f953c025..18ec8259 100644 --- a/src/lol/math/vector.h +++ b/src/lol/math/vector.h @@ -17,10 +17,10 @@ #define __LOL_MATH_VECTOR_H__ #include -#include #include #include +#include namespace lol { @@ -35,169 +35,6 @@ namespace lol # define _____ /* */ #endif -/* - * Utility namespaces for traits - */ - -namespace swizzle_ops -{ - - - -} - - -namespace linear_ops -{ - -struct base {}; - -/* - * Unary plus and minus - */ - -template -static inline typename std::enable_if::value, V>::type -operator +(V const &v) -{ - return v; -} - -template -static inline typename std::enable_if::value, V>::type -operator -(V const &v) -{ - V ret; - for (size_t i = 0; i < sizeof(ret) / sizeof(ret[0]); ++i) - ret[i] = -v[i]; - return ret; -} - -/* - * Addition and subtraction - */ - -template -static inline typename std::enable_if::value, V>::type -operator +(V const &a, V const &b) -{ - V ret; - for (size_t i = 0; i < sizeof(ret) / sizeof(ret[0]); ++i) - ret[i] = a[i] + b[i]; - return ret; -} - -template -static inline typename std::enable_if::value, V>::type -&operator +=(V &a, V const &b) -{ - return a = a + b; -} - -template -static inline typename std::enable_if::value, V>::type -operator -(V const &a, V const &b) -{ - V ret; - for (size_t i = 0; i < sizeof(ret) / sizeof(ret[0]); ++i) - ret[i] = a[i] - b[i]; - return ret; -} - -template -static inline typename std::enable_if::value, V>::type -&operator -=(V &a, V const &b) -{ - return a = a - b; -} - -} /* namespace linear_ops */ - -namespace componentwise_ops -{ - -struct base {}; - -template -static inline typename std::enable_if::value, V>::type -operator *(V const &a, V const &b) -{ - V ret; - for (size_t i = 0; i < sizeof(ret) / sizeof(ret[0]); ++i) - ret[i] = a[i] * b[i]; - return ret; -} - -template -static inline typename std::enable_if::value, V>::type -&operator *=(V &a, V const &b) -{ - return a = a * b; -} - -template -static inline typename std::enable_if::value, V>::type -operator /(V const &a, V const &b) -{ - V ret; - for (size_t i = 0; i < sizeof(ret) / sizeof(ret[0]); ++i) - ret[i] = a[i] / b[i]; - return ret; -} - -template -static inline typename std::enable_if::value, V>::type -&operator /=(V &a, V const &b) -{ - return a = a / b; -} - -/* - * Comparisons - */ - -template -static inline typename std::enable_if::value, bool>::type -operator <(V const &a, V const &b) -{ - for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); ++i) - if (!(a[i] < b[i])) - return false; - return true; -} - -template -static inline typename std::enable_if::value, bool>::type -operator >(V const &a, V const &b) -{ - for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); ++i) - if (!(a[i] > b[i])) - return false; - return true; -} - -template -static inline typename std::enable_if::value, bool>::type -operator <=(V const &a, V const &b) -{ - for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); ++i) - if (!(a[i] <= b[i])) - return false; - return true; -} - -template -static inline typename std::enable_if::value, bool>::type -operator >=(V const &a, V const &b) -{ - for (size_t i = 0; i < sizeof(a) / sizeof(a[0]); ++i) - if (!(a[i] >= b[i])) - return false; - return true; -} - -} /* namespace componentwise_ops */ - /* * Magic vector swizzling (part 1/2) * These vectors are empty, but thanks to static_cast we can take their @@ -214,7 +51,13 @@ operator >=(V const &a, V const &b) template struct vec_t + /* MUST be a different base than e.g. vec_t otherwise the unions + * in vec_t with the same base will cause empty base optimisation + * failures. */ + : public swizzle_ops::base { + static int const count = N; + typedef T element; typedef vec_t type; inline vec_t& operator =(vec_t that); @@ -244,9 +87,11 @@ struct vec_t * swizzling. There's an override for N=2, N=3, N=4 that has swizzling. */ template struct vec_t - : public linear_ops::base, - public componentwise_ops::base + : public linear_ops::base, + public componentwise_ops::base { + static int const count = N; + typedef T element; typedef vec_t type; inline T& operator[](size_t n) { return m_data[n]; } @@ -260,30 +105,6 @@ private: * Helper macros for vector type member functions */ -#define LOL_V_VS_OP(op) \ - friend inline type operator op(type const &a, T const &val) \ - { \ - type ret; \ - for (size_t i = 0; i < sizeof(type) / sizeof(T); ++i) \ - ret[i] = a[i] op val; \ - return ret; \ - } - -#define LOL_V_VS_ASSIGN_OP(op) \ - friend inline type operator op##=(type &a, T const &val) \ - { \ - return a = a op val; \ - } - -#define LOL_B_VV_OP(op, op2, ret) \ - friend inline bool operator op(type const &a, type const &b) \ - { \ - for (size_t i = 0; i < sizeof(type) / sizeof(T); ++i) \ - if (!(a[i] op2 b[i])) \ - return !ret; \ - return ret; \ - } - #define LOL_COMMON_MEMBER_OPS(first) \ inline T& operator[](size_t n) { return (&this->first)[n]; } \ inline T const& operator[](size_t n) const { return (&this->first)[n]; } \ @@ -291,37 +112,13 @@ private: /* Visual Studio insists on having an assignment operator. */ \ inline type & operator =(type const &that) \ { \ - for (size_t i = 0; i < sizeof(type) / sizeof(T); ++i) \ + for (int i = 0; i < type::count; ++i) \ (*this)[i] = that[i]; \ return *this; \ } \ \ void printf() const; \ - String tostring() const; \ - \ - /* vec_t *(vec_t, scalar) - * vec_t /(vec_t, scalar) - * vec_t *=(vec_t, scalar) - * vec_t /=(vec_t, scalar) */ \ - LOL_V_VS_OP(*) \ - LOL_V_VS_OP(/) \ - LOL_V_VS_ASSIGN_OP(*) \ - LOL_V_VS_ASSIGN_OP(/) \ - \ - /* bool ==(vec_t, vec_t) - * bool !=(vec_t, vec_t) */ \ - LOL_B_VV_OP(==, ==, true) \ - LOL_B_VV_OP(!=, ==, false) - -#define LOL_NONVECTOR_MEMBER_OPS() \ - /* vec_t *(scalar, vec_t) (no division, it works differently) */ \ - friend inline type operator *(T const &val, type const &a) \ - { \ - type ret; \ - for (size_t i = 0; i < sizeof(type) / sizeof(T); ++i) \ - ret[i] = val * a[i]; \ - return ret; \ - } + String tostring() const; /* * 2-element vectors @@ -329,9 +126,12 @@ private: template struct vec_t - : public linear_ops::base, - public componentwise_ops::base + : public swizzle_ops::base, + public linear_ops::base, + public componentwise_ops::base { + static int const count = 2; + typedef T element; typedef vec_t type; /* Default constructor, copy constructor, and destructor */ @@ -405,15 +205,27 @@ struct vec_t }; }; +static_assert(sizeof(i8vec2) == 2, "sizeof(i8vec2) == 2"); +static_assert(sizeof(i16vec2) == 4, "sizeof(i16vec2) == 4"); +static_assert(sizeof(ivec2) == 8, "sizeof(ivec2) == 8"); +static_assert(sizeof(i64vec2) == 16, "sizeof(i64vec2) == 16"); + +static_assert(sizeof(f16vec2) == 4, "sizeof(f16vec2) == 4"); +static_assert(sizeof(vec2) == 8, "sizeof(vec2) == 8"); +static_assert(sizeof(dvec2) == 16, "sizeof(dvec2) == 16"); + /* * 3-element vectors */ template struct vec_t - : public linear_ops::base, - public componentwise_ops::base + : public swizzle_ops::base, + public linear_ops::base, + public componentwise_ops::base { + static int const count = 3; + typedef T element; typedef vec_t type; /* Default constructor, copy constructor, and destructor */ @@ -617,15 +429,27 @@ struct vec_t }; }; +static_assert(sizeof(i8vec3) == 3, "sizeof(i8vec3) == 3"); +static_assert(sizeof(i16vec3) == 6, "sizeof(i16vec3) == 6"); +static_assert(sizeof(ivec3) == 12, "sizeof(ivec3) == 12"); +static_assert(sizeof(i64vec3) == 24, "sizeof(i64vec3) == 24"); + +static_assert(sizeof(f16vec3) == 6, "sizeof(f16vec3) == 6"); +static_assert(sizeof(vec3) == 12, "sizeof(vec3) == 12"); +static_assert(sizeof(dvec3) == 24, "sizeof(dvec3) == 24"); + /* * 4-element vectors */ template struct vec_t - : public linear_ops::base, - public componentwise_ops::base + : public swizzle_ops::base, + public linear_ops::base, + public componentwise_ops::base { + static int const count = 4; + typedef T element; typedef vec_t type; /* Default constructor, copy constructor, and destructor */ @@ -1022,68 +846,24 @@ struct vec_t }; }; -/* - * Operators for swizzled vectors. Since template deduction cannot be - * done for two arbitrary vec_t<> values, we help the compiler understand - * the expected type. - */ +static_assert(sizeof(i8vec4) == 4, "sizeof(i8vec4) == 4"); +static_assert(sizeof(i16vec4) == 8, "sizeof(i16vec4) == 8"); +static_assert(sizeof(ivec4) == 16, "sizeof(ivec4) == 16"); +static_assert(sizeof(i64vec4) == 32, "sizeof(i64vec4) == 32"); -template -static inline bool operator ==(vec_t const &a, - vec_t const &b) -{ - for (size_t i = 0; i < N; ++i) - if (!(a[i] == b[i])) - return false; - return true; -} - -template -static inline bool operator !=(vec_t const &a, - vec_t const &b) -{ - for (size_t i = 0; i < N; ++i) - if (a[i] != b[i]) - return true; - return false; -} +static_assert(sizeof(f16vec4) == 8, "sizeof(f16vec4) == 8"); +static_assert(sizeof(vec4) == 16, "sizeof(vec4) == 16"); +static_assert(sizeof(dvec4) == 32, "sizeof(dvec4) == 32"); -#define LOL_SWIZZLE_V_VV_OP(op) \ - template \ - inline typename std::enable_if>::type \ - operator op(vec_t const &a, \ - vec_t const &b) \ - { \ - return vec_t(a) op vec_t(b); \ - } \ - \ - template \ - inline typename std::enable_if>::type & \ - operator op##=(vec_t &a, \ - vec_t const &b) \ - { \ - return a op##= vec_t(b); \ - } \ - \ - template \ - inline vec_t operator op(vec_t a, T const &b) \ - { \ - return vec_t(a) op b; \ - } - -LOL_SWIZZLE_V_VV_OP(+) -LOL_SWIZZLE_V_VV_OP(-) -LOL_SWIZZLE_V_VV_OP(*) -LOL_SWIZZLE_V_VV_OP(/) - -#undef LOL_SWIZZLE_V_VV_OP +/* + * vec_t *(scalar, vec_t) + */ template static inline vec_t operator *(T const &val, vec_t const &a) { vec_t ret; - for (size_t i = 0; i < N; ++i) + for (int i = 0; i < N; ++i) ret[i] = val * a[i]; return ret; } @@ -1100,7 +880,7 @@ static inline vec_t operator *(T const &val, vec_t const &a) { \ using lol::fun; \ vec_t ret; \ - for (size_t i = 0; i < N; ++i) \ + for (int i = 0; i < N; ++i) \ ret[i] = fun(a[i], b[i]); \ return ret; \ } \ @@ -1110,7 +890,7 @@ static inline vec_t operator *(T const &val, vec_t const &a) { \ using lol::fun; \ vec_t ret; \ - for (size_t i = 0; i < N; ++i) \ + for (int i = 0; i < N; ++i) \ ret[i] = fun(a[i], b); \ return ret; \ } \ @@ -1120,7 +900,7 @@ static inline vec_t operator *(T const &val, vec_t const &a) { \ using lol::fun; \ vec_t ret; \ - for (size_t i = 0; i < N; ++i) \ + for (int i = 0; i < N; ++i) \ ret[i] = fun(a, b[i]); \ return ret; \ } @@ -1200,7 +980,7 @@ static inline T dot(vec_t const &a, vec_t const &b) { T ret(0); - for (size_t i = 0; i < N; ++i) + for (int i = 0; i < N; ++i) ret += a[i] * b[i]; return ret; } @@ -1224,7 +1004,7 @@ static inline vec_t lerp(vec_t const &a, T const &s) { vec_t ret; - for (size_t i = 0; i < N; ++i) + for (int i = 0; i < N; ++i) ret[i] = a[i] + s * (b[i] - a[i]); return ret; } @@ -1240,7 +1020,7 @@ template static inline vec_t fract(vec_t const &a) { vec_t ret; - for (size_t i = 0; i < N; ++i) + for (int i = 0; i < N; ++i) ret[i] = fract(a[i]); return ret; } @@ -1256,7 +1036,7 @@ template static inline vec_t abs(vec_t const &a) { vec_t ret; - for (size_t i = 0; i < N; ++i) + for (int i = 0; i < N; ++i) ret[i] = lol::abs(a[i]); return ret; } @@ -1265,7 +1045,7 @@ template static inline vec_t degrees(vec_t const &a) { vec_t ret; - for (size_t i = 0; i < N; ++i) + for (int i = 0; i < N; ++i) ret[i] = lol::degrees(a[i]); return ret; } @@ -1274,7 +1054,7 @@ template static inline vec_t radians(vec_t const &a) { vec_t ret; - for (size_t i = 0; i < N; ++i) + for (int i = 0; i < N; ++i) ret[i] = lol::radians(a[i]); return ret; } diff --git a/src/lolcore.vcxproj b/src/lolcore.vcxproj index b02b0c0d..485e6133 100644 --- a/src/lolcore.vcxproj +++ b/src/lolcore.vcxproj @@ -327,6 +327,7 @@ + diff --git a/src/lolcore.vcxproj.filters b/src/lolcore.vcxproj.filters index 8185f8dc..3b8af4ce 100644 --- a/src/lolcore.vcxproj.filters +++ b/src/lolcore.vcxproj.filters @@ -441,6 +441,9 @@ lol\math + + lol\math + lol\math