Преглед на файлове

math: put almost all quaternion/vector/matrix operators in ADL namespaces.

undefined
Sam Hocevar преди 10 години
родител
ревизия
11dc5eebcc
променени са 9 файла, в които са добавени 485 реда и са изтрити 342 реда
  1. +1
    -1
      src/Makefile.am
  2. +1
    -0
      src/lol/math/all.h
  3. +2
    -0
      src/lol/math/half.h
  4. +43
    -51
      src/lol/math/matrix.h
  5. +344
    -0
      src/lol/math/ops.h
  6. +24
    -4
      src/lol/math/transform.h
  7. +66
    -286
      src/lol/math/vector.h
  8. +1
    -0
      src/lolcore.vcxproj
  9. +3
    -0
      src/lolcore.vcxproj.filters

+ 1
- 1
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 \


+ 1
- 0
src/lol/math/all.h Целия файл

@@ -15,6 +15,7 @@
#include <lol/math/functions.h>
#include <lol/math/half.h>
#include <lol/math/real.h>
#include <lol/math/ops.h>
#include <lol/math/vector.h>
#include <lol/math/matrix.h>
#include <lol/math/transform.h>


+ 2
- 0
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)


+ 43
- 51
src/lol/math/matrix.h Целия файл

@@ -33,8 +33,11 @@ namespace lol
*/

template<typename T, int COLS, int ROWS>
struct mat_t : public linear_ops::base
struct mat_t
: public linear_ops::base<vec_t<T,ROWS>>
{
static int const count = COLS;
typedef vec_t<T,ROWS> element;
typedef mat_t<T,COLS,ROWS> type;

inline mat_t() {}
@@ -59,8 +62,11 @@ private:
*/

template <typename T>
struct mat_t<T, 2, 2> : public linear_ops::base
struct mat_t<T, 2, 2>
: public linear_ops::base<vec_t<T,2>>
{
static int const count = 2;
typedef vec_t<T,2> element;
typedef mat_t<T,2,2> 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 <typename T>
struct mat_t<T, 3, 3> : public linear_ops::base
struct mat_t<T, 3, 3>
: public linear_ops::base<vec_t<T,3>>
{
static int const count = 3;
typedef vec_t<T,3> element;
typedef mat_t<T,3,3> 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 <typename T>
struct mat_t<T, 4, 4> : public linear_ops::base
struct mat_t<T, 4, 4>
: public linear_ops::base<vec_t<T,4>>
{
static int const count = 4;
typedef vec_t<T,4> element;
typedef mat_t<T,4,4> 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<typename T> T determinant(mat_t<T,2,2> const &);
template<typename T> T determinant(mat_t<T,3,3> const &);
template<typename T> T determinant(mat_t<T,4,4> const &);
@@ -406,53 +445,6 @@ static inline mat_t<T, ROWS, COLS> transpose(mat_t<T, COLS, ROWS> const &m)
return ret;
}

/*
* Addition/subtraction/unary
*/

template<typename T, int COLS, int ROWS>
static inline mat_t<T, COLS, ROWS> &operator +=(mat_t<T, COLS, ROWS> &a,
mat_t<T, COLS, ROWS> const &b)
{
for (int i = 0; i < COLS; ++i)
a[i] += b[i];
return a;
}

template<typename T, int COLS, int ROWS>
static inline mat_t<T, COLS, ROWS> operator +(mat_t<T, COLS, ROWS> const &a,
mat_t<T, COLS, ROWS> const &b)
{
mat_t<T, COLS, ROWS> ret = a;
return ret += b;
}

template<typename T, int COLS, int ROWS>
static inline mat_t<T, COLS, ROWS> &operator -=(mat_t<T, COLS, ROWS> &a,
mat_t<T, COLS, ROWS> const &b)
{
for (int i = 0; i < COLS; ++i)
a[i] -= b[i];
return a;
}

template<typename T, int COLS, int ROWS>
static inline mat_t<T, COLS, ROWS> operator -(mat_t<T, COLS, ROWS> const &a,
mat_t<T, COLS, ROWS> const &b)
{
mat_t<T, COLS, ROWS> ret = a;
return ret -= b;
}

template<typename T, int COLS, int ROWS>
static inline mat_t<T, COLS, ROWS> operator -(mat_t<T, COLS, ROWS> const &m)
{
mat_t<T, COLS, ROWS> ret;
for (int i = 0; i < COLS; ++i)
ret[i] = -m[i];
return ret;
}

/*
* Matrix-vector and vector-matrix multiplication
*/


+ 344
- 0
src/lol/math/ops.h Целия файл

@@ -0,0 +1,344 @@
//
// Lol Engine
//
// Copyright: (c) 2010-2014 Sam Hocevar <sam@hocevar.net>
// 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 <ostream>
#include <type_traits>

#include <lol/math/half.h>
#include <lol/math/real.h>

/*
* 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<typename T, int SWIZZLE = FULL_SWIZZLE>
struct base {};


template<typename T, int N, int SWIZZLE1, int SWIZZLE2>
static inline typename std::enable_if<SWIZZLE1 != FULL_SWIZZLE || SWIZZLE2 != FULL_SWIZZLE, bool>::type operator ==(vec_t<T,N,SWIZZLE1> const &a,
vec_t<T,N,SWIZZLE2> const &b)
{
return vec_t<T,N>(a) == vec_t<T,N>(b);
}

template<typename T, int N, int SWIZZLE1, int SWIZZLE2>
static inline typename std::enable_if<SWIZZLE1 != FULL_SWIZZLE || SWIZZLE2 != FULL_SWIZZLE, bool>::type operator !=(vec_t<T,N,SWIZZLE1> const &a,
vec_t<T,N,SWIZZLE2> const &b)
{
return vec_t<T,N>(a) != vec_t<T,N>(b);
}

#define LOL_SWIZZLE_V_VV_OP(op) \
template<typename T, int N, int SWIZZLE1, int SWIZZLE2> \
inline typename std::enable_if<SWIZZLE1 != FULL_SWIZZLE \
|| SWIZZLE2 != FULL_SWIZZLE,vec_t<T,N>>::type \
operator op(vec_t<T,N,SWIZZLE1> const &a, \
vec_t<T,N,SWIZZLE2> const &b) \
{ \
return vec_t<T,N>(a) op vec_t<T,N>(b); \
} \
\
template<typename T, int N, int SWIZZLE> \
inline typename std::enable_if<SWIZZLE != FULL_SWIZZLE,vec_t<T,N>>::type & \
operator op##=(vec_t<T,N> &a, \
vec_t<T,N,SWIZZLE> const &b) \
{ \
return a op##= vec_t<T,N>(b); \
} \
\
template<typename T, int N, int SWIZZLE> \
inline typename std::enable_if<SWIZZLE != FULL_SWIZZLE,vec_t<T,N>>::type \
operator op(vec_t<T,N,SWIZZLE> a, T const &b) \
{ \
return vec_t<T,N>(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<typename T>
struct base {};

/*
* Comparisons
*/

template<typename V>
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, 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<typename V>
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, 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<typename V>
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, V>::value, typename V::type>::type
operator +(V const &v)
{
return v;
}

template<typename V>
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, 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<typename V>
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, 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<typename V>
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, V>::value, typename V::type>::type
&operator +=(V &a, V const &b)
{
return a = a + b;
}

template<typename V>
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, 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<typename V>
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, V>::value, typename V::type>::type
&operator -=(V &a, V const &b)
{
return a = a - b;
}

/*
* Multiplication by scalar (left)
*/

template<typename V>
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, 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<typename V>
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, 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<typename V>
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, V>::value, typename V::type>::type &
operator *=(V &a, typename V::element const &val)
{
return a = a * val;
}

template<typename V>
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, 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<typename V>
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, 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<typename T>
struct base {};

template<typename V>
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, 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<typename V>
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, V>::value, typename V::type>::type
&operator *=(V &a, V const &b)
{
return a = a * b;
}

template<typename V>
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, 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<typename V>
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, V>::value, typename V::type>::type
&operator /=(V &a, V const &b)
{
return a = a / b;
}

/*
* Comparisons
*/

template<typename V>
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, 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<typename V>
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, 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<typename V>
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, 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<typename V>
static inline typename std::enable_if<std::is_base_of<base<typename V::element>, 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__


+ 24
- 4
src/lol/math/transform.h Целия файл

@@ -30,8 +30,10 @@ namespace lol
*/

template<typename T>
struct cmplx_t : public linear_ops::base
struct cmplx_t : public linear_ops::base<T>
{
static int const count = 2;
typedef T element;
typedef cmplx_t<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<T> operator *(cmplx_t<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<typename T>
struct quat_t : public linear_ops::base
struct quat_t : public linear_ops::base<T>
{
static int const count = 4;
typedef T element;
typedef quat_t<T> type;

/* Default constructor and copy constructor */
@@ -95,7 +107,6 @@ struct quat_t : public linear_ops::base
explicit quat_t(mat_t<T,4,4> 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
*/


+ 66
- 286
src/lol/math/vector.h Целия файл

@@ -17,10 +17,10 @@
#define __LOL_MATH_VECTOR_H__

#include <ostream>
#include <type_traits>

#include <lol/math/half.h>
#include <lol/math/real.h>
#include <lol/math/ops.h>

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<typename V>
static inline typename std::enable_if<std::is_base_of<base, V>::value, V>::type
operator +(V const &v)
{
return v;
}

template<typename V>
static inline typename std::enable_if<std::is_base_of<base, V>::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<typename V>
static inline typename std::enable_if<std::is_base_of<base, V>::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<typename V>
static inline typename std::enable_if<std::is_base_of<base, V>::value, V>::type
&operator +=(V &a, V const &b)
{
return a = a + b;
}

template<typename V>
static inline typename std::enable_if<std::is_base_of<base, V>::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<typename V>
static inline typename std::enable_if<std::is_base_of<base, V>::value, V>::type
&operator -=(V &a, V const &b)
{
return a = a - b;
}

} /* namespace linear_ops */

namespace componentwise_ops
{

struct base {};

template<typename V>
static inline typename std::enable_if<std::is_base_of<base, V>::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<typename V>
static inline typename std::enable_if<std::is_base_of<base, V>::value, V>::type
&operator *=(V &a, V const &b)
{
return a = a * b;
}

template<typename V>
static inline typename std::enable_if<std::is_base_of<base, V>::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<typename V>
static inline typename std::enable_if<std::is_base_of<base, V>::value, V>::type
&operator /=(V &a, V const &b)
{
return a = a / b;
}

/*
* Comparisons
*/

template<typename V>
static inline typename std::enable_if<std::is_base_of<base, V>::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<typename V>
static inline typename std::enable_if<std::is_base_of<base, V>::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<typename V>
static inline typename std::enable_if<std::is_base_of<base, V>::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<typename V>
static inline typename std::enable_if<std::is_base_of<base, V>::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<typename T, int N, int SWIZZLE>
struct vec_t
/* MUST be a different base than e.g. vec_t<T,2> otherwise the unions
* in vec_t<T,2> with the same base will cause empty base optimisation
* failures. */
: public swizzle_ops::base<T, SWIZZLE>
{
static int const count = N;
typedef T element;
typedef vec_t<T,N> type;

inline vec_t<T, N, SWIZZLE>& operator =(vec_t<T, N> that);
@@ -244,9 +87,11 @@ struct vec_t
* swizzling. There's an override for N=2, N=3, N=4 that has swizzling. */
template<typename T, int N>
struct vec_t<T, N, FULL_SWIZZLE>
: public linear_ops::base,
public componentwise_ops::base
: public linear_ops::base<T>,
public componentwise_ops::base<T>
{
static int const count = N;
typedef T element;
typedef vec_t<T,N> 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 <typename T>
struct vec_t<T,2>
: public linear_ops::base,
public componentwise_ops::base
: public swizzle_ops::base<T>,
public linear_ops::base<T>,
public componentwise_ops::base<T>
{
static int const count = 2;
typedef T element;
typedef vec_t<T,2> type;

/* Default constructor, copy constructor, and destructor */
@@ -405,15 +205,27 @@ struct vec_t<T,2>
};
};

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 <typename T>
struct vec_t<T,3>
: public linear_ops::base,
public componentwise_ops::base
: public swizzle_ops::base<T>,
public linear_ops::base<T>,
public componentwise_ops::base<T>
{
static int const count = 3;
typedef T element;
typedef vec_t<T,3> type;

/* Default constructor, copy constructor, and destructor */
@@ -617,15 +429,27 @@ struct vec_t<T,3>
};
};

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 <typename T>
struct vec_t<T,4>
: public linear_ops::base,
public componentwise_ops::base
: public swizzle_ops::base<T>,
public linear_ops::base<T>,
public componentwise_ops::base<T>
{
static int const count = 4;
typedef T element;
typedef vec_t<T,4> type;

/* Default constructor, copy constructor, and destructor */
@@ -1022,68 +846,24 @@ struct vec_t<T,4>
};
};

/*
* 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<typename T, int N, int SWIZZLE1, int SWIZZLE2>
static inline bool operator ==(vec_t<T,N,SWIZZLE1> const &a,
vec_t<T,N,SWIZZLE2> const &b)
{
for (size_t i = 0; i < N; ++i)
if (!(a[i] == b[i]))
return false;
return true;
}

template<typename T, int N, int SWIZZLE1, int SWIZZLE2>
static inline bool operator !=(vec_t<T,N,SWIZZLE1> const &a,
vec_t<T,N,SWIZZLE2> 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<typename T, int N, int SWIZZLE1, int SWIZZLE2> \
inline typename std::enable_if<SWIZZLE1 != FULL_SWIZZLE \
|| SWIZZLE2 != FULL_SWIZZLE,vec_t<T,N>>::type \
operator op(vec_t<T,N,SWIZZLE1> const &a, \
vec_t<T,N,SWIZZLE2> const &b) \
{ \
return vec_t<T,N>(a) op vec_t<T,N>(b); \
} \
\
template<typename T, int N, int SWIZZLE> \
inline typename std::enable_if<SWIZZLE != FULL_SWIZZLE,vec_t<T,N>>::type & \
operator op##=(vec_t<T,N> &a, \
vec_t<T,N,SWIZZLE> const &b) \
{ \
return a op##= vec_t<T,N>(b); \
} \
\
template<typename T, int N, int SWIZZLE> \
inline vec_t<T,N> operator op(vec_t<T,N,SWIZZLE> a, T const &b) \
{ \
return vec_t<T,N>(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<typename T, int N, int SWIZZLE>
static inline vec_t<T,N> operator *(T const &val, vec_t<T,N,SWIZZLE> const &a)
{
vec_t<T,N> 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<T,N> operator *(T const &val, vec_t<T,N,SWIZZLE> const &a)
{ \
using lol::fun; \
vec_t<T,N> 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<T,N> operator *(T const &val, vec_t<T,N,SWIZZLE> const &a)
{ \
using lol::fun; \
vec_t<T,N> 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<T,N> operator *(T const &val, vec_t<T,N,SWIZZLE> const &a)
{ \
using lol::fun; \
vec_t<T,N> 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<T,N,SWIZZLE1> const &a,
vec_t<T,N,SWIZZLE2> 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<T,N> lerp(vec_t<T,N,SWIZZLE1> const &a,
T const &s)
{
vec_t<T,N> 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<typename T, int N, int SWIZZLE>
static inline vec_t<T,N> fract(vec_t<T,N,SWIZZLE> const &a)
{
vec_t<T,N> 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<typename T, int N, int SWIZZLE>
static inline vec_t<T,N> abs(vec_t<T,N,SWIZZLE> const &a)
{
vec_t<T,N> 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<typename T, int N, int SWIZZLE>
static inline vec_t<T,N> degrees(vec_t<T,N,SWIZZLE> const &a)
{
vec_t<T,N> 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<typename T, int N, int SWIZZLE>
static inline vec_t<T,N> radians(vec_t<T,N,SWIZZLE> const &a)
{
vec_t<T,N> ret;
for (size_t i = 0; i < N; ++i)
for (int i = 0; i < N; ++i)
ret[i] = lol::radians(a[i]);
return ret;
}


+ 1
- 0
src/lolcore.vcxproj Целия файл

@@ -327,6 +327,7 @@
<ClInclude Include="lol\math\half.h" />
<ClInclude Include="lol\math\interp.h" />
<ClInclude Include="lol\math\matrix.h" />
<ClInclude Include="lol\math\ops.h" />
<ClInclude Include="lol\math\rand.h" />
<ClInclude Include="lol\math\real.h" />
<ClInclude Include="lol\math\remez.h" />


+ 3
- 0
src/lolcore.vcxproj.filters Целия файл

@@ -441,6 +441,9 @@
<ClInclude Include="lol\math\matrix.h">
<Filter>lol\math</Filter>
</ClInclude>
<ClInclude Include="lol\math\ops.h">
<Filter>lol\math</Filter>
</ClInclude>
<ClInclude Include="lol\math\rand.h">
<Filter>lol\math</Filter>
</ClInclude>


Зареждане…
Отказ
Запис