瀏覽代碼

math: use a combination of ADL and enable_if black magic to get rid of macros.

undefined
Sam Hocevar 11 年之前
父節點
當前提交
f6dd334c1a
共有 3 個文件被更改,包括 191 次插入76 次删除
  1. +4
    -10
      src/lol/math/matrix.h
  2. +2
    -2
      src/lol/math/transform.h
  3. +185
    -64
      src/lol/math/vector.h

+ 4
- 10
src/lol/math/matrix.h 查看文件

@@ -33,7 +33,7 @@ namespace lol
*/ */


template<typename T, int COLS, int ROWS> template<typename T, int COLS, int ROWS>
struct mat_t
struct mat_t : public linear_ops::base
{ {
typedef mat_t<T,COLS,ROWS> type; typedef mat_t<T,COLS,ROWS> type;


@@ -59,7 +59,7 @@ private:
*/ */


template <typename T> template <typename T>
struct mat_t<T, 2, 2>
struct mat_t<T, 2, 2> : public linear_ops::base
{ {
typedef mat_t<T,2,2> type; typedef mat_t<T,2,2> type;


@@ -124,7 +124,7 @@ private:
*/ */


template <typename T> template <typename T>
struct mat_t<T, 3, 3>
struct mat_t<T, 3, 3> : public linear_ops::base
{ {
typedef mat_t<T,3,3> type; typedef mat_t<T,3,3> type;


@@ -235,7 +235,7 @@ private:
*/ */


template <typename T> template <typename T>
struct mat_t<T, 4, 4>
struct mat_t<T, 4, 4> : public linear_ops::base
{ {
typedef mat_t<T,4,4> type; typedef mat_t<T,4,4> type;


@@ -427,12 +427,6 @@ static inline mat_t<T, COLS, ROWS> operator +(mat_t<T, COLS, ROWS> const &a,
return ret += b; 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)
{
return m;
}

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


+ 2
- 2
src/lol/math/transform.h 查看文件

@@ -30,7 +30,7 @@ namespace lol
*/ */


template<typename T> template<typename T>
struct cmplx_t
struct cmplx_t : public linear_ops::base
{ {
typedef cmplx_t<T> type; typedef cmplx_t<T> type;


@@ -71,7 +71,7 @@ struct cmplx_t
*/ */


template<typename T> template<typename T>
struct quat_t
struct quat_t : public linear_ops::base
{ {
typedef quat_t<T> type; typedef quat_t<T> type;




+ 185
- 64
src/lol/math/vector.h 查看文件

@@ -17,6 +17,7 @@
#define __LOL_MATH_VECTOR_H__ #define __LOL_MATH_VECTOR_H__


#include <ostream> #include <ostream>
#include <type_traits>


#include <lol/math/half.h> #include <lol/math/half.h>
#include <lol/math/real.h> #include <lol/math/real.h>
@@ -34,6 +35,169 @@ namespace lol
# define _____ /* */ # define _____ /* */
#endif #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) * Magic vector swizzling (part 1/2)
* These vectors are empty, but thanks to static_cast we can take their * These vectors are empty, but thanks to static_cast we can take their
@@ -79,7 +243,9 @@ struct vec_t
/* The generic “vec_t” type, which is a fixed-size vector with no /* The generic “vec_t” type, which is a fixed-size vector with no
* swizzling. There's an override for N=2, N=3, N=4 that has swizzling. */ * swizzling. There's an override for N=2, N=3, N=4 that has swizzling. */
template<typename T, int N> template<typename T, int N>
struct vec_t<T, N, -1>
struct vec_t<T, N, FULL_SWIZZLE>
: public linear_ops::base,
public componentwise_ops::base
{ {
typedef vec_t<T,N> type; typedef vec_t<T,N> type;


@@ -94,21 +260,6 @@ private:
* Helper macros for vector type member functions * Helper macros for vector type member functions
*/ */


#define LOL_V_VV_OP(op) \
friend inline type operator op(type const &a, type const &b) \
{ \
type ret; \
for (size_t i = 0; i < sizeof(type) / sizeof(T); ++i) \
ret[i] = a[i] op b[i]; \
return ret; \
}

#define LOL_V_VV_ASSIGN_OP(op) \
friend inline type &operator op##=(type &a, type const &b) \
{ \
return a = a op b; \
}

#define LOL_V_VS_OP(op) \ #define LOL_V_VS_OP(op) \
friend inline type operator op(type const &a, T const &val) \ friend inline type operator op(type const &a, T const &val) \
{ \ { \
@@ -148,30 +299,6 @@ private:
void printf() const; \ void printf() const; \
String tostring() const; \ String tostring() const; \
\ \
/* vec_t -(vec_t)
* vec_t +(vec_t) */ \
friend inline type operator -(type const &a) \
{ \
type ret; \
for (size_t i = 0; i < sizeof(type) / sizeof(T); ++i) \
ret[i] = -a[i]; \
return ret; \
} \
\
friend inline type operator +(type const &a) \
{ \
return a; \
} \
\
/* vec_t +(vec_t, vec_t)
* vec_t -(vec_t, vec_t)
* vec_t +=(vec_t, vec_t)
* vec_t -=(vec_t, vec_t) */ \
LOL_V_VV_OP(+); \
LOL_V_VV_OP(-); \
LOL_V_VV_ASSIGN_OP(+); \
LOL_V_VV_ASSIGN_OP(-); \
\
/* vec_t *(vec_t, scalar) /* vec_t *(vec_t, scalar)
* vec_t /(vec_t, scalar) * vec_t /(vec_t, scalar)
* vec_t *=(vec_t, scalar) * vec_t *=(vec_t, scalar)
@@ -186,25 +313,6 @@ private:
LOL_B_VV_OP(==, ==, true) \ LOL_B_VV_OP(==, ==, true) \
LOL_B_VV_OP(!=, ==, false) LOL_B_VV_OP(!=, ==, false)


#define LOL_VECTOR_MEMBER_OPS() \
/* vec_t *(vec_t, vec_t)
* vec_t /(vec_t, vec_t)
* vec_t *=(vec_t, vec_t)
* vec_t /=(vec_t, vec_t) */ \
LOL_V_VV_OP(*); \
LOL_V_VV_OP(/); \
LOL_V_VV_ASSIGN_OP(*); \
LOL_V_VV_ASSIGN_OP(/); \
\
/* bool >=(vec_t, vec_t)
* bool <=(vec_t, vec_t)
* bool >(vec_t, vec_t)
* bool <(vec_t, vec_t) */ \
LOL_B_VV_OP(<=, <=, true) \
LOL_B_VV_OP(>=, >=, true) \
LOL_B_VV_OP(<, <, true) \
LOL_B_VV_OP(>, >, true)

#define LOL_NONVECTOR_MEMBER_OPS() \ #define LOL_NONVECTOR_MEMBER_OPS() \
/* vec_t *(scalar, vec_t) (no division, it works differently) */ \ /* vec_t *(scalar, vec_t) (no division, it works differently) */ \
friend inline type operator *(T const &val, type const &a) \ friend inline type operator *(T const &val, type const &a) \
@@ -221,6 +329,8 @@ private:


template <typename T> template <typename T>
struct vec_t<T,2> struct vec_t<T,2>
: public linear_ops::base,
public componentwise_ops::base
{ {
typedef vec_t<T,2> type; typedef vec_t<T,2> type;


@@ -246,7 +356,6 @@ struct vec_t<T,2>
: x(X), y(X) {} : x(X), y(X) {}


LOL_COMMON_MEMBER_OPS(x) LOL_COMMON_MEMBER_OPS(x)
LOL_VECTOR_MEMBER_OPS()


static const vec_t<T,2> zero; static const vec_t<T,2> zero;
static const vec_t<T,2> axis_x; static const vec_t<T,2> axis_x;
@@ -302,6 +411,8 @@ struct vec_t<T,2>


template <typename T> template <typename T>
struct vec_t<T,3> struct vec_t<T,3>
: public linear_ops::base,
public componentwise_ops::base
{ {
typedef vec_t<T,3> type; typedef vec_t<T,3> type;


@@ -331,7 +442,6 @@ struct vec_t<T,3>
: x(X), y(YZ.x), z(YZ.y) {} : x(X), y(YZ.x), z(YZ.y) {}


LOL_COMMON_MEMBER_OPS(x) LOL_COMMON_MEMBER_OPS(x)
LOL_VECTOR_MEMBER_OPS()


static vec_t<T,3> toeuler_xyx(quat_t<T> const &q); static vec_t<T,3> toeuler_xyx(quat_t<T> const &q);
static vec_t<T,3> toeuler_xzx(quat_t<T> const &q); static vec_t<T,3> toeuler_xzx(quat_t<T> const &q);
@@ -513,6 +623,8 @@ struct vec_t<T,3>


template <typename T> template <typename T>
struct vec_t<T,4> struct vec_t<T,4>
: public linear_ops::base,
public componentwise_ops::base
{ {
typedef vec_t<T,4> type; typedef vec_t<T,4> type;


@@ -551,7 +663,6 @@ struct vec_t<T,4>
: x(X), y(YZW.x), z(YZW.y), w(YZW.z) {} : x(X), y(YZW.x), z(YZW.y), w(YZW.z) {}


LOL_COMMON_MEMBER_OPS(x) LOL_COMMON_MEMBER_OPS(x)
LOL_VECTOR_MEMBER_OPS()


static const vec_t<T,4> zero; static const vec_t<T,4> zero;
static const vec_t<T,4> axis_x; static const vec_t<T,4> axis_x;
@@ -939,13 +1050,23 @@ static inline bool operator !=(vec_t<T,N,SWIZZLE1> const &a,


#define LOL_SWIZZLE_V_VV_OP(op) \ #define LOL_SWIZZLE_V_VV_OP(op) \
template<typename T, int N, int SWIZZLE1, int SWIZZLE2> \ template<typename T, int N, int SWIZZLE1, int SWIZZLE2> \
inline vec_t<T,N> operator op(vec_t<T,N,SWIZZLE1> const &a, \
vec_t<T,N,SWIZZLE2> const &b) \
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); \ return vec_t<T,N>(a) op vec_t<T,N>(b); \
} \ } \
\ \
template<typename T, int N, int SWIZZLE> \ 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) \ inline vec_t<T,N> operator op(vec_t<T,N,SWIZZLE> a, T const &b) \
{ \ { \
return vec_t<T,N>(a) op b; \ return vec_t<T,N>(a) op b; \


Loading…
取消
儲存