source: trunk/src/lol/math/vector.h @ 2806

Last change on this file since 2806 was 2806, checked in by lolbot, 8 years ago

fixed 7 files out of 2745:

  • removed 0 CR characters
  • removed 21 trailing whitespaces
  • replaced 42 tabs with spaces
  • Property svn:keywords set to Id
File size: 62.7 KB
RevLine 
[1139]1//
2// Lol Engine
3//
[2216]4// Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
[1139]5//   This program is free software; you can redistribute it and/or
6//   modify it under the terms of the Do What The Fuck You Want To
7//   Public License, Version 2, as published by Sam Hocevar. See
[2183]8//   http://www.wtfpl.net/ for more details.
[1139]9//
10
11//
12// The vector, complex, quaternion and matrix classes
13// --------------------------------------------------
14//
15
16#if !defined __LOL_MATH_VECTOR_H__
17#define __LOL_MATH_VECTOR_H__
18
19#include <stdint.h>
[1401]20#include <ostream>
[1139]21
[2318]22#include <lol/math/half.h>
23#include <lol/math/real.h>
[1148]24
[1139]25namespace lol
26{
27
[1154]28/* Some compilers do not support const members in anonymous unions. So
29 * far, GCC (>= 4.6), CLang (3.0) and Visual Studio (>= 2010) appear to
30 * work properly. */
31#undef LOL_NO_CONST_MEMBERS_IN_ANONYMOUS_UNIONS
32#if defined __GNUC__ && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6))
33#   define LOL_NO_CONST_MEMBERS_IN_ANONYMOUS_UNIONS 1
34#endif
35
[2081]36#define LOL_VECTOR_TYPEDEFS(tname, suffix) \
[1139]37    template <typename T> struct tname; \
38    typedef tname<half> f16##suffix; \
39    typedef tname<float> suffix; \
[1426]40    typedef tname<double> d##suffix; \
[2056]41    typedef tname<ldouble> f128##suffix; \
[1139]42    typedef tname<int8_t> i8##suffix; \
43    typedef tname<uint8_t> u8##suffix; \
44    typedef tname<int16_t> i16##suffix; \
45    typedef tname<uint16_t> u16##suffix; \
46    typedef tname<int32_t> i##suffix; \
47    typedef tname<uint32_t> u##suffix; \
48    typedef tname<int64_t> i64##suffix; \
[1148]49    typedef tname<uint64_t> u64##suffix; \
50    typedef tname<real> r##suffix; \
[1139]51
[2081]52LOL_VECTOR_TYPEDEFS(Vec2, vec2)
53LOL_VECTOR_TYPEDEFS(Cmplx, cmplx)
54LOL_VECTOR_TYPEDEFS(Vec3, vec3)
55LOL_VECTOR_TYPEDEFS(Vec4, vec4)
56LOL_VECTOR_TYPEDEFS(Quat, quat)
57LOL_VECTOR_TYPEDEFS(Mat2, mat2)
58LOL_VECTOR_TYPEDEFS(Mat3, mat3)
59LOL_VECTOR_TYPEDEFS(Mat4, mat4)
[1139]60
[2081]61#undef LOL_VECTOR_TYPEDEFS
62
[1139]63/*
[1405]64 * HLSL/Cg-compliant type names.
65 */
66
67typedef vec2 float2;
68typedef vec3 float3;
69typedef vec4 float4;
70typedef mat2 float2x2;
71typedef mat3 float3x3;
72typedef mat4 float4x4;
73
74typedef ivec2 int2;
75typedef ivec3 int3;
76typedef ivec4 int4;
77typedef imat2 int2x2;
78typedef imat3 int3x3;
79typedef imat4 int4x4;
80
81/*
[1139]82 * Magic vector swizzling (part 1/2)
[1158]83 * These vectors are empty, but thanks to static_cast we can take their
84 * address and access the vector of T's that they are union'ed with. We
85 * use static_cast instead of reinterpret_cast because there is a stronger
86 * guarantee (by the standard) that the address will stay the same across
87 * casts.
[1139]88 */
89
90template<typename T, int N> struct XVec2
91{
[1142]92    inline Vec2<T> operator =(Vec2<T> const &that);
[1139]93
[1209]94    inline T& operator[](size_t n)
[1158]95    {
96        int i = (N >> (4 * (1 - n))) & 3;
97        return static_cast<T*>(static_cast<void*>(this))[i];
98    }
[1209]99    inline T const& operator[](size_t n) const
[1158]100    {
101        int i = (N >> (4 * (1 - n))) & 3;
102        return static_cast<T const*>(static_cast<void const *>(this))[i];
103    }
[1139]104};
105
106template<typename T, int N> struct XVec3
107{
[1142]108    inline Vec3<T> operator =(Vec3<T> const &that);
[1139]109
[1209]110    inline T& operator[](size_t n)
[1158]111    {
112        int i = (N >> (4 * (2 - n))) & 3;
113        return static_cast<T*>(static_cast<void*>(this))[i];
114    }
[1209]115    inline T const& operator[](size_t n) const
[1158]116    {
117        int i = (N >> (4 * (2 - n))) & 3;
118        return static_cast<T const*>(static_cast<void const *>(this))[i];
119    }
[1139]120};
121
122template<typename T, int N> struct XVec4
123{
[1142]124    inline Vec4<T> operator =(Vec4<T> const &that);
[1139]125
[1209]126    inline T& operator[](size_t n)
[1158]127    {
128        int i = (N >> (4 * (3 - n))) & 3;
129        return static_cast<T*>(static_cast<void*>(this))[i];
130    }
[1209]131    inline T const& operator[](size_t n) const
[1158]132    {
133        int i = (N >> (4 * (3 - n))) & 3;
134        return static_cast<T const*>(static_cast<void const *>(this))[i];
135    }
[1139]136};
137
138/*
139 * Helper macro for vector type member functions
140 */
141
[2081]142#define LOL_MEMBER_OPS(tname, first) \
[1351]143    inline T& operator[](size_t n) { return *(&this->first + n); } \
144    inline T const& operator[](size_t n) const { return *(&this->first + n); } \
[1139]145    \
[1149]146    /* Visual Studio insists on having an assignment operator. */ \
147    inline tname<T> const & operator =(tname<T> const &that) \
148    { \
149        for (size_t n = 0; n < sizeof(*this) / sizeof(T); n++) \
150            (*this)[n] = that[n]; \
151        return *this; \
152    } \
[1139]153    \
154    template<typename U> \
155    inline operator tname<U>() const \
156    { \
157        tname<U> ret; \
158        for (size_t n = 0; n < sizeof(*this) / sizeof(T); n++) \
159            ret[n] = static_cast<U>((*this)[n]); \
160        return ret; \
[1149]161    } \
162    \
163    void printf() const;
[1139]164
165/*
166 * 2-element vectors
167 */
168
[1148]169template <typename T> struct BVec2
[1139]170{
[1148]171    explicit inline BVec2() {}
172    explicit inline BVec2(T X, T Y) : x(X), y(Y) {}
[1139]173
174    union
175    {
176        struct { T x, y; };
177        struct { T r, g; };
178        struct { T s, t; };
179
[1154]180#if LOL_NO_CONST_MEMBERS_IN_ANONYMOUS_UNIONS
181#   define const /* disabled */
182#endif
[2179]183#if !_DOXYGEN_SKIP_ME
[1141]184        XVec2<T,0x00> const xx, rr, ss;
[1143]185        XVec2<T,0x01> const xy, rg, st; /* lvalue */
186        XVec2<T,0x10> const yx, gr, ts; /* lvalue */
[1141]187        XVec2<T,0x11> const yy, gg, tt;
[1139]188
[1141]189        XVec3<T,0x000> const xxx, rrr, sss;
190        XVec3<T,0x001> const xxy, rrg, sst;
191        XVec3<T,0x010> const xyx, rgr, sts;
192        XVec3<T,0x011> const xyy, rgg, stt;
193        XVec3<T,0x100> const yxx, grr, tss;
194        XVec3<T,0x101> const yxy, grg, tst;
195        XVec3<T,0x110> const yyx, ggr, tts;
196        XVec3<T,0x111> const yyy, ggg, ttt;
[1139]197
[1141]198        XVec4<T,0x0000> const xxxx, rrrr, ssss;
199        XVec4<T,0x0001> const xxxy, rrrg, ssst;
200        XVec4<T,0x0010> const xxyx, rrgr, ssts;
201        XVec4<T,0x0011> const xxyy, rrgg, sstt;
202        XVec4<T,0x0100> const xyxx, rgrr, stss;
203        XVec4<T,0x0101> const xyxy, rgrg, stst;
204        XVec4<T,0x0110> const xyyx, rggr, stts;
205        XVec4<T,0x0111> const xyyy, rggg, sttt;
206        XVec4<T,0x1000> const yxxx, grrr, tsss;
207        XVec4<T,0x1001> const yxxy, grrg, tsst;
208        XVec4<T,0x1010> const yxyx, grgr, tsts;
209        XVec4<T,0x1011> const yxyy, grgg, tstt;
210        XVec4<T,0x1100> const yyxx, ggrr, ttss;
211        XVec4<T,0x1101> const yyxy, ggrg, ttst;
212        XVec4<T,0x1110> const yyyx, gggr, ttts;
213        XVec4<T,0x1111> const yyyy, gggg, tttt;
[2179]214#endif
[1154]215#if LOL_NO_CONST_MEMBERS_IN_ANONYMOUS_UNIONS
216#   undef const
217#endif
[1139]218    };
219};
220
[1148]221template <> struct BVec2<half>
222{
223    explicit inline BVec2() {}
224    explicit inline BVec2(half X, half Y) : x(X), y(Y) {}
225
226    half x, y;
227};
228
229template <> struct BVec2<real>
230{
231    explicit inline BVec2() {}
232    explicit inline BVec2(real X, real Y) : x(X), y(Y) {}
233
234    real x, y;
235};
236
237template <typename T> struct Vec2 : BVec2<T>
238{
239    inline Vec2() {}
240    inline Vec2(T X, T Y) : BVec2<T>(X, Y) {}
241
242    explicit inline Vec2(T X) : BVec2<T>(X, X) {}
243
244    template<int N>
245    inline Vec2(XVec2<T, N> const &v)
[1158]246      : BVec2<T>(v[0], v[1]) {}
[1148]247
248    template<typename U, int N>
249    explicit inline Vec2(XVec2<U, N> const &v)
[1158]250      : BVec2<T>(v[0], v[1]) {}
[1148]251
[2081]252    LOL_MEMBER_OPS(Vec2, x)
[1148]253
254    template<typename U>
255    friend std::ostream &operator<<(std::ostream &stream, Vec2<U> const &v);
256};
257
[1139]258/*
259 * 2-element complexes
260 */
261
262template <typename T> struct Cmplx
263{
264    inline Cmplx() {}
265    inline Cmplx(T X) : x(X), y(0) {}
266    inline Cmplx(T X, T Y) : x(X), y(Y) {}
267
[2081]268    LOL_MEMBER_OPS(Cmplx, x)
[1139]269
270    inline Cmplx<T> operator *(Cmplx<T> const &val) const
271    {
272        return Cmplx<T>(x * val.x - y * val.y, x * val.y + y * val.x);
273    }
274
275    inline Cmplx<T> operator *=(Cmplx<T> const &val)
276    {
277        return *this = (*this) * val;
278    }
279
280    inline Cmplx<T> operator ~() const
281    {
282        return Cmplx<T>(x, -y);
283    }
284
[1369]285    inline T norm() const { return length(*this); }
[1139]286    template<typename U>
287    friend std::ostream &operator<<(std::ostream &stream, Cmplx<U> const &v);
288
289    T x, y;
290};
291
292template<typename T>
293static inline Cmplx<T> re(Cmplx<T> const &val)
294{
[1369]295    return ~val / sqlength(val);
[1139]296}
297
298template<typename T>
299static inline Cmplx<T> operator /(T a, Cmplx<T> const &b)
300{
301    return a * re(b);
302}
303
304template<typename T>
305static inline Cmplx<T> operator /(Cmplx<T> a, Cmplx<T> const &b)
306{
307    return a * re(b);
308}
309
310template<typename T>
311static inline bool operator ==(Cmplx<T> const &a, T b)
312{
313    return (a.x == b) && !a.y;
314}
315
316template<typename T>
317static inline bool operator !=(Cmplx<T> const &a, T b)
318{
319    return (a.x != b) || a.y;
320}
321
322template<typename T>
323static inline bool operator ==(T a, Cmplx<T> const &b) { return b == a; }
324
325template<typename T>
326static inline bool operator !=(T a, Cmplx<T> const &b) { return b != a; }
327
328/*
329 * 3-element vectors
330 */
331
[1148]332template <typename T> struct BVec3
[1139]333{
[1148]334    explicit inline BVec3() {}
335    explicit inline BVec3(T X, T Y, T Z) : x(X), y(Y), z(Z) {}
[1139]336
337    union
338    {
339        struct { T x, y, z; };
340        struct { T r, g, b; };
341        struct { T s, t, p; };
342
[1154]343#if LOL_NO_CONST_MEMBERS_IN_ANONYMOUS_UNIONS
344#   define const /* disabled */
345#endif
[2179]346#if !_DOXYGEN_SKIP_ME
[1141]347        XVec2<T,0x00> const xx, rr, ss;
[1143]348        XVec2<T,0x01> const xy, rg, st; /* lvalue */
349        XVec2<T,0x02> const xz, rb, sp; /* lvalue */
350        XVec2<T,0x10> const yx, gr, ts; /* lvalue */
[1141]351        XVec2<T,0x11> const yy, gg, tt;
[1143]352        XVec2<T,0x12> const yz, gb, tp; /* lvalue */
353        XVec2<T,0x20> const zx, br, ps; /* lvalue */
354        XVec2<T,0x21> const zy, bg, pt; /* lvalue */
[1141]355        XVec2<T,0x22> const zz, bb, pp;
[1139]356
[1141]357        XVec3<T,0x000> const xxx, rrr, sss;
358        XVec3<T,0x001> const xxy, rrg, sst;
359        XVec3<T,0x002> const xxz, rrb, ssp;
360        XVec3<T,0x010> const xyx, rgr, sts;
361        XVec3<T,0x011> const xyy, rgg, stt;
[1143]362        XVec3<T,0x012> const xyz, rgb, stp; /* lvalue */
[1141]363        XVec3<T,0x020> const xzx, rbr, sps;
[1143]364        XVec3<T,0x021> const xzy, rbg, spt; /* lvalue */
[1141]365        XVec3<T,0x022> const xzz, rbb, spp;
366        XVec3<T,0x100> const yxx, grr, tss;
367        XVec3<T,0x101> const yxy, grg, tst;
[1143]368        XVec3<T,0x102> const yxz, grb, tsp; /* lvalue */
[1141]369        XVec3<T,0x110> const yyx, ggr, tts;
370        XVec3<T,0x111> const yyy, ggg, ttt;
371        XVec3<T,0x112> const yyz, ggb, ttp;
[1143]372        XVec3<T,0x120> const yzx, gbr, tps; /* lvalue */
[1141]373        XVec3<T,0x121> const yzy, gbg, tpt;
374        XVec3<T,0x122> const yzz, gbb, tpp;
375        XVec3<T,0x200> const zxx, brr, pss;
[1143]376        XVec3<T,0x201> const zxy, brg, pst; /* lvalue */
[1141]377        XVec3<T,0x202> const zxz, brb, psp;
[1143]378        XVec3<T,0x210> const zyx, bgr, pts; /* lvalue */
[1141]379        XVec3<T,0x211> const zyy, bgg, ptt;
380        XVec3<T,0x212> const zyz, bgb, ptp;
381        XVec3<T,0x220> const zzx, bbr, pps;
382        XVec3<T,0x221> const zzy, bbg, ppt;
383        XVec3<T,0x222> const zzz, bbb, ppp;
[1139]384
[1141]385        XVec4<T,0x0000> const xxxx, rrrr, ssss;
386        XVec4<T,0x0001> const xxxy, rrrg, ssst;
387        XVec4<T,0x0002> const xxxz, rrrb, sssp;
388        XVec4<T,0x0010> const xxyx, rrgr, ssts;
389        XVec4<T,0x0011> const xxyy, rrgg, sstt;
390        XVec4<T,0x0012> const xxyz, rrgb, sstp;
391        XVec4<T,0x0020> const xxzx, rrbr, ssps;
392        XVec4<T,0x0021> const xxzy, rrbg, sspt;
393        XVec4<T,0x0022> const xxzz, rrbb, sspp;
394        XVec4<T,0x0100> const xyxx, rgrr, stss;
395        XVec4<T,0x0101> const xyxy, rgrg, stst;
396        XVec4<T,0x0102> const xyxz, rgrb, stsp;
397        XVec4<T,0x0110> const xyyx, rggr, stts;
398        XVec4<T,0x0111> const xyyy, rggg, sttt;
399        XVec4<T,0x0112> const xyyz, rggb, sttp;
400        XVec4<T,0x0120> const xyzx, rgbr, stps;
401        XVec4<T,0x0121> const xyzy, rgbg, stpt;
402        XVec4<T,0x0122> const xyzz, rgbb, stpp;
403        XVec4<T,0x0200> const xzxx, rbrr, spss;
404        XVec4<T,0x0201> const xzxy, rbrg, spst;
405        XVec4<T,0x0202> const xzxz, rbrb, spsp;
406        XVec4<T,0x0210> const xzyx, rbgr, spts;
407        XVec4<T,0x0211> const xzyy, rbgg, sptt;
408        XVec4<T,0x0212> const xzyz, rbgb, sptp;
409        XVec4<T,0x0220> const xzzx, rbbr, spps;
410        XVec4<T,0x0221> const xzzy, rbbg, sppt;
411        XVec4<T,0x0222> const xzzz, rbbb, sppp;
412        XVec4<T,0x1000> const yxxx, grrr, tsss;
413        XVec4<T,0x1001> const yxxy, grrg, tsst;
414        XVec4<T,0x1002> const yxxz, grrb, tssp;
415        XVec4<T,0x1010> const yxyx, grgr, tsts;
416        XVec4<T,0x1011> const yxyy, grgg, tstt;
417        XVec4<T,0x1012> const yxyz, grgb, tstp;
418        XVec4<T,0x1020> const yxzx, grbr, tsps;
419        XVec4<T,0x1021> const yxzy, grbg, tspt;
420        XVec4<T,0x1022> const yxzz, grbb, tspp;
421        XVec4<T,0x1100> const yyxx, ggrr, ttss;
422        XVec4<T,0x1101> const yyxy, ggrg, ttst;
423        XVec4<T,0x1102> const yyxz, ggrb, ttsp;
424        XVec4<T,0x1110> const yyyx, gggr, ttts;
425        XVec4<T,0x1111> const yyyy, gggg, tttt;
426        XVec4<T,0x1112> const yyyz, gggb, tttp;
427        XVec4<T,0x1120> const yyzx, ggbr, ttps;
428        XVec4<T,0x1121> const yyzy, ggbg, ttpt;
429        XVec4<T,0x1122> const yyzz, ggbb, ttpp;
430        XVec4<T,0x1200> const yzxx, gbrr, tpss;
431        XVec4<T,0x1201> const yzxy, gbrg, tpst;
432        XVec4<T,0x1202> const yzxz, gbrb, tpsp;
433        XVec4<T,0x1210> const yzyx, gbgr, tpts;
434        XVec4<T,0x1211> const yzyy, gbgg, tptt;
435        XVec4<T,0x1212> const yzyz, gbgb, tptp;
436        XVec4<T,0x1220> const yzzx, gbbr, tpps;
437        XVec4<T,0x1221> const yzzy, gbbg, tppt;
438        XVec4<T,0x1222> const yzzz, gbbb, tppp;
439        XVec4<T,0x2000> const zxxx, brrr, psss;
440        XVec4<T,0x2001> const zxxy, brrg, psst;
441        XVec4<T,0x2002> const zxxz, brrb, pssp;
442        XVec4<T,0x2010> const zxyx, brgr, psts;
443        XVec4<T,0x2011> const zxyy, brgg, pstt;
444        XVec4<T,0x2012> const zxyz, brgb, pstp;
445        XVec4<T,0x2020> const zxzx, brbr, psps;
446        XVec4<T,0x2021> const zxzy, brbg, pspt;
447        XVec4<T,0x2022> const zxzz, brbb, pspp;
448        XVec4<T,0x2100> const zyxx, bgrr, ptss;
449        XVec4<T,0x2101> const zyxy, bgrg, ptst;
450        XVec4<T,0x2102> const zyxz, bgrb, ptsp;
451        XVec4<T,0x2110> const zyyx, bggr, ptts;
452        XVec4<T,0x2111> const zyyy, bggg, pttt;
453        XVec4<T,0x2112> const zyyz, bggb, pttp;
454        XVec4<T,0x2120> const zyzx, bgbr, ptps;
455        XVec4<T,0x2121> const zyzy, bgbg, ptpt;
456        XVec4<T,0x2122> const zyzz, bgbb, ptpp;
457        XVec4<T,0x2200> const zzxx, bbrr, ppss;
458        XVec4<T,0x2201> const zzxy, bbrg, ppst;
459        XVec4<T,0x2202> const zzxz, bbrb, ppsp;
460        XVec4<T,0x2210> const zzyx, bbgr, ppts;
461        XVec4<T,0x2211> const zzyy, bbgg, pptt;
462        XVec4<T,0x2212> const zzyz, bbgb, pptp;
463        XVec4<T,0x2220> const zzzx, bbbr, ppps;
464        XVec4<T,0x2221> const zzzy, bbbg, pppt;
465        XVec4<T,0x2222> const zzzz, bbbb, pppp;
[2179]466#endif
[1154]467#if LOL_NO_CONST_MEMBERS_IN_ANONYMOUS_UNIONS
468#   undef const
469#endif
[1139]470    };
471};
472
[1148]473template <> struct BVec3<half>
474{
475    explicit inline BVec3() {}
476    explicit inline BVec3(half X, half Y, half Z) : x(X), y(Y), z(Z) {}
[1139]477
[1148]478    half x, y, z;
479};
480
481template <> struct BVec3<real>
[1139]482{
[1148]483    explicit inline BVec3() {}
484    explicit inline BVec3(real X, real Y, real Z) : x(X), y(Y), z(Z) {}
[1139]485
[1148]486    real x, y, z;
487};
[1139]488
[1148]489template <typename T> struct Vec3 : BVec3<T>
490{
491    inline Vec3() {}
492    inline Vec3(T X, T Y, T Z) : BVec3<T>(X, Y, Z) {}
493    inline Vec3(Vec2<T> XY, T Z) : BVec3<T>(XY.x, XY.y, Z) {}
494    inline Vec3(T X, Vec2<T> YZ) : BVec3<T>(X, YZ.x, YZ.y) {}
495
496    explicit inline Vec3(T X) : BVec3<T>(X, X, X) {}
497
[1139]498    template<int N>
[1148]499    inline Vec3(XVec3<T, N> const &v)
[1158]500      : BVec3<T>(v[0], v[1], v[2]) {}
[1139]501
502    template<typename U, int N>
[1148]503    explicit inline Vec3(XVec3<U, N> const &v)
[1158]504      : BVec3<T>(v[0], v[1], v[2]) {}
[1139]505
[1315]506    static Vec3<T> toeuler(Quat<T> const &q);
507
[2081]508    LOL_MEMBER_OPS(Vec3, x)
[1139]509
510    template<typename U>
[1148]511    friend std::ostream &operator<<(std::ostream &stream, Vec3<U> const &v);
512};
[1139]513
[1148]514/*
515 * 4-element vectors
516 */
517
518template <typename T> struct BVec4
519{
520    explicit inline BVec4() {}
521    explicit inline BVec4(T X, T Y, T Z, T W) : x(X), y(Y), z(Z), w(W) {}
522
[1139]523    union
524    {
525        struct { T x, y, z, w; };
526        struct { T r, g, b, a; };
527        struct { T s, t, p, q; };
528
[1154]529#if LOL_NO_CONST_MEMBERS_IN_ANONYMOUS_UNIONS
530#   define const /* disabled */
531#endif
[2179]532#if !_DOXYGEN_SKIP_ME
[1141]533        XVec2<T,0x00> const xx, rr, ss;
[1143]534        XVec2<T,0x01> const xy, rg, st; /* lvalue */
535        XVec2<T,0x02> const xz, rb, sp; /* lvalue */
536        XVec2<T,0x03> const xw, ra, sq; /* lvalue */
537        XVec2<T,0x10> const yx, gr, ts; /* lvalue */
[1141]538        XVec2<T,0x11> const yy, gg, tt;
[1143]539        XVec2<T,0x12> const yz, gb, tp; /* lvalue */
540        XVec2<T,0x13> const yw, ga, tq; /* lvalue */
541        XVec2<T,0x20> const zx, br, ps; /* lvalue */
542        XVec2<T,0x21> const zy, bg, pt; /* lvalue */
[1141]543        XVec2<T,0x22> const zz, bb, pp;
[1143]544        XVec2<T,0x23> const zw, ba, pq; /* lvalue */
545        XVec2<T,0x30> const wx, ar, qs; /* lvalue */
546        XVec2<T,0x31> const wy, ag, qt; /* lvalue */
547        XVec2<T,0x32> const wz, ab, qp; /* lvalue */
[1141]548        XVec2<T,0x33> const ww, aa, qq;
[1139]549
[1141]550        XVec3<T,0x000> const xxx, rrr, sss;
551        XVec3<T,0x001> const xxy, rrg, sst;
552        XVec3<T,0x002> const xxz, rrb, ssp;
553        XVec3<T,0x003> const xxw, rra, ssq;
554        XVec3<T,0x010> const xyx, rgr, sts;
555        XVec3<T,0x011> const xyy, rgg, stt;
[1143]556        XVec3<T,0x012> const xyz, rgb, stp; /* lvalue */
557        XVec3<T,0x013> const xyw, rga, stq; /* lvalue */
[1141]558        XVec3<T,0x020> const xzx, rbr, sps;
[1143]559        XVec3<T,0x021> const xzy, rbg, spt; /* lvalue */
[1141]560        XVec3<T,0x022> const xzz, rbb, spp;
[1143]561        XVec3<T,0x023> const xzw, rba, spq; /* lvalue */
[1141]562        XVec3<T,0x030> const xwx, rar, sqs;
[1143]563        XVec3<T,0x031> const xwy, rag, sqt; /* lvalue */
564        XVec3<T,0x032> const xwz, rab, sqp; /* lvalue */
[1141]565        XVec3<T,0x033> const xww, raa, sqq;
566        XVec3<T,0x100> const yxx, grr, tss;
567        XVec3<T,0x101> const yxy, grg, tst;
[1143]568        XVec3<T,0x102> const yxz, grb, tsp; /* lvalue */
569        XVec3<T,0x103> const yxw, gra, tsq; /* lvalue */
[1141]570        XVec3<T,0x110> const yyx, ggr, tts;
571        XVec3<T,0x111> const yyy, ggg, ttt;
572        XVec3<T,0x112> const yyz, ggb, ttp;
573        XVec3<T,0x113> const yyw, gga, ttq;
[1143]574        XVec3<T,0x120> const yzx, gbr, tps; /* lvalue */
[1141]575        XVec3<T,0x121> const yzy, gbg, tpt;
576        XVec3<T,0x122> const yzz, gbb, tpp;
[1143]577        XVec3<T,0x123> const yzw, gba, tpq; /* lvalue */
578        XVec3<T,0x130> const ywx, gar, tqs; /* lvalue */
[1141]579        XVec3<T,0x131> const ywy, gag, tqt;
[1143]580        XVec3<T,0x132> const ywz, gab, tqp; /* lvalue */
[1141]581        XVec3<T,0x133> const yww, gaa, tqq;
582        XVec3<T,0x200> const zxx, brr, pss;
[1143]583        XVec3<T,0x201> const zxy, brg, pst; /* lvalue */
[1141]584        XVec3<T,0x202> const zxz, brb, psp;
[1143]585        XVec3<T,0x203> const zxw, bra, psq; /* lvalue */
586        XVec3<T,0x210> const zyx, bgr, pts; /* lvalue */
[1141]587        XVec3<T,0x211> const zyy, bgg, ptt;
588        XVec3<T,0x212> const zyz, bgb, ptp;
[1143]589        XVec3<T,0x213> const zyw, bga, ptq; /* lvalue */
[1141]590        XVec3<T,0x220> const zzx, bbr, pps;
591        XVec3<T,0x221> const zzy, bbg, ppt;
592        XVec3<T,0x222> const zzz, bbb, ppp;
593        XVec3<T,0x223> const zzw, bba, ppq;
[1143]594        XVec3<T,0x230> const zwx, bar, pqs; /* lvalue */
595        XVec3<T,0x231> const zwy, bag, pqt; /* lvalue */
[1141]596        XVec3<T,0x232> const zwz, bab, pqp;
597        XVec3<T,0x233> const zww, baa, pqq;
598        XVec3<T,0x300> const wxx, arr, qss;
[1143]599        XVec3<T,0x301> const wxy, arg, qst; /* lvalue */
600        XVec3<T,0x302> const wxz, arb, qsp; /* lvalue */
[1141]601        XVec3<T,0x303> const wxw, ara, qsq;
[1143]602        XVec3<T,0x310> const wyx, agr, qts; /* lvalue */
[1141]603        XVec3<T,0x311> const wyy, agg, qtt;
[1143]604        XVec3<T,0x312> const wyz, agb, qtp; /* lvalue */
[1141]605        XVec3<T,0x313> const wyw, aga, qtq;
[1143]606        XVec3<T,0x320> const wzx, abr, qps; /* lvalue */
607        XVec3<T,0x321> const wzy, abg, qpt; /* lvalue */
[1141]608        XVec3<T,0x322> const wzz, abb, qpp;
609        XVec3<T,0x323> const wzw, aba, qpq;
610        XVec3<T,0x330> const wwx, aar, qqs;
611        XVec3<T,0x331> const wwy, aag, qqt;
612        XVec3<T,0x332> const wwz, aab, qqp;
613        XVec3<T,0x333> const www, aaa, qqq;
[1139]614
[1141]615        XVec4<T,0x0000> const xxxx, rrrr, ssss;
616        XVec4<T,0x0001> const xxxy, rrrg, ssst;
617        XVec4<T,0x0002> const xxxz, rrrb, sssp;
618        XVec4<T,0x0003> const xxxw, rrra, sssq;
619        XVec4<T,0x0010> const xxyx, rrgr, ssts;
620        XVec4<T,0x0011> const xxyy, rrgg, sstt;
621        XVec4<T,0x0012> const xxyz, rrgb, sstp;
622        XVec4<T,0x0013> const xxyw, rrga, sstq;
623        XVec4<T,0x0020> const xxzx, rrbr, ssps;
624        XVec4<T,0x0021> const xxzy, rrbg, sspt;
625        XVec4<T,0x0022> const xxzz, rrbb, sspp;
626        XVec4<T,0x0023> const xxzw, rrba, sspq;
627        XVec4<T,0x0030> const xxwx, rrar, ssqs;
628        XVec4<T,0x0031> const xxwy, rrag, ssqt;
629        XVec4<T,0x0032> const xxwz, rrab, ssqp;
630        XVec4<T,0x0033> const xxww, rraa, ssqq;
631        XVec4<T,0x0100> const xyxx, rgrr, stss;
632        XVec4<T,0x0101> const xyxy, rgrg, stst;
633        XVec4<T,0x0102> const xyxz, rgrb, stsp;
634        XVec4<T,0x0103> const xyxw, rgra, stsq;
635        XVec4<T,0x0110> const xyyx, rggr, stts;
636        XVec4<T,0x0111> const xyyy, rggg, sttt;
637        XVec4<T,0x0112> const xyyz, rggb, sttp;
638        XVec4<T,0x0113> const xyyw, rgga, sttq;
639        XVec4<T,0x0120> const xyzx, rgbr, stps;
640        XVec4<T,0x0121> const xyzy, rgbg, stpt;
641        XVec4<T,0x0122> const xyzz, rgbb, stpp;
[1143]642        XVec4<T,0x0123> const xyzw, rgba, stpq; /* lvalue */
[1141]643        XVec4<T,0x0130> const xywx, rgar, stqs;
644        XVec4<T,0x0131> const xywy, rgag, stqt;
[1143]645        XVec4<T,0x0132> const xywz, rgab, stqp; /* lvalue */
[1141]646        XVec4<T,0x0133> const xyww, rgaa, stqq;
647        XVec4<T,0x0200> const xzxx, rbrr, spss;
648        XVec4<T,0x0201> const xzxy, rbrg, spst;
649        XVec4<T,0x0202> const xzxz, rbrb, spsp;
650        XVec4<T,0x0203> const xzxw, rbra, spsq;
651        XVec4<T,0x0210> const xzyx, rbgr, spts;
652        XVec4<T,0x0211> const xzyy, rbgg, sptt;
653        XVec4<T,0x0212> const xzyz, rbgb, sptp;
[1143]654        XVec4<T,0x0213> const xzyw, rbga, sptq; /* lvalue */
[1141]655        XVec4<T,0x0220> const xzzx, rbbr, spps;
656        XVec4<T,0x0221> const xzzy, rbbg, sppt;
657        XVec4<T,0x0222> const xzzz, rbbb, sppp;
658        XVec4<T,0x0223> const xzzw, rbba, sppq;
659        XVec4<T,0x0230> const xzwx, rbar, spqs;
[1143]660        XVec4<T,0x0231> const xzwy, rbag, spqt; /* lvalue */
[1141]661        XVec4<T,0x0232> const xzwz, rbab, spqp;
662        XVec4<T,0x0233> const xzww, rbaa, spqq;
663        XVec4<T,0x0300> const xwxx, rarr, sqss;
664        XVec4<T,0x0301> const xwxy, rarg, sqst;
665        XVec4<T,0x0302> const xwxz, rarb, sqsp;
666        XVec4<T,0x0303> const xwxw, rara, sqsq;
667        XVec4<T,0x0310> const xwyx, ragr, sqts;
668        XVec4<T,0x0311> const xwyy, ragg, sqtt;
[1143]669        XVec4<T,0x0312> const xwyz, ragb, sqtp; /* lvalue */
[1141]670        XVec4<T,0x0313> const xwyw, raga, sqtq;
671        XVec4<T,0x0320> const xwzx, rabr, sqps;
[1143]672        XVec4<T,0x0321> const xwzy, rabg, sqpt; /* lvalue */
[1141]673        XVec4<T,0x0322> const xwzz, rabb, sqpp;
674        XVec4<T,0x0323> const xwzw, raba, sqpq;
675        XVec4<T,0x0330> const xwwx, raar, sqqs;
676        XVec4<T,0x0331> const xwwy, raag, sqqt;
677        XVec4<T,0x0332> const xwwz, raab, sqqp;
678        XVec4<T,0x0333> const xwww, raaa, sqqq;
679        XVec4<T,0x1000> const yxxx, grrr, tsss;
680        XVec4<T,0x1001> const yxxy, grrg, tsst;
681        XVec4<T,0x1002> const yxxz, grrb, tssp;
682        XVec4<T,0x1003> const yxxw, grra, tssq;
683        XVec4<T,0x1010> const yxyx, grgr, tsts;
684        XVec4<T,0x1011> const yxyy, grgg, tstt;
685        XVec4<T,0x1012> const yxyz, grgb, tstp;
686        XVec4<T,0x1013> const yxyw, grga, tstq;
687        XVec4<T,0x1020> const yxzx, grbr, tsps;
688        XVec4<T,0x1021> const yxzy, grbg, tspt;
689        XVec4<T,0x1022> const yxzz, grbb, tspp;
[1143]690        XVec4<T,0x1023> const yxzw, grba, tspq; /* lvalue */
[1141]691        XVec4<T,0x1030> const yxwx, grar, tsqs;
692        XVec4<T,0x1031> const yxwy, grag, tsqt;
[1143]693        XVec4<T,0x1032> const yxwz, grab, tsqp; /* lvalue */
[1141]694        XVec4<T,0x1033> const yxww, graa, tsqq;
695        XVec4<T,0x1100> const yyxx, ggrr, ttss;
696        XVec4<T,0x1101> const yyxy, ggrg, ttst;
697        XVec4<T,0x1102> const yyxz, ggrb, ttsp;
698        XVec4<T,0x1103> const yyxw, ggra, ttsq;
699        XVec4<T,0x1110> const yyyx, gggr, ttts;
700        XVec4<T,0x1111> const yyyy, gggg, tttt;
701        XVec4<T,0x1112> const yyyz, gggb, tttp;
702        XVec4<T,0x1113> const yyyw, ggga, tttq;
703        XVec4<T,0x1120> const yyzx, ggbr, ttps;
704        XVec4<T,0x1121> const yyzy, ggbg, ttpt;
705        XVec4<T,0x1122> const yyzz, ggbb, ttpp;
706        XVec4<T,0x1123> const yyzw, ggba, ttpq;
707        XVec4<T,0x1130> const yywx, ggar, ttqs;
708        XVec4<T,0x1131> const yywy, ggag, ttqt;
709        XVec4<T,0x1132> const yywz, ggab, ttqp;
710        XVec4<T,0x1133> const yyww, ggaa, ttqq;
711        XVec4<T,0x1200> const yzxx, gbrr, tpss;
712        XVec4<T,0x1201> const yzxy, gbrg, tpst;
713        XVec4<T,0x1202> const yzxz, gbrb, tpsp;
[1143]714        XVec4<T,0x1203> const yzxw, gbra, tpsq; /* lvalue */
[1141]715        XVec4<T,0x1210> const yzyx, gbgr, tpts;
716        XVec4<T,0x1211> const yzyy, gbgg, tptt;
717        XVec4<T,0x1212> const yzyz, gbgb, tptp;
718        XVec4<T,0x1213> const yzyw, gbga, tptq;
719        XVec4<T,0x1220> const yzzx, gbbr, tpps;
720        XVec4<T,0x1221> const yzzy, gbbg, tppt;
721        XVec4<T,0x1222> const yzzz, gbbb, tppp;
722        XVec4<T,0x1223> const yzzw, gbba, tppq;
[1143]723        XVec4<T,0x1230> const yzwx, gbar, tpqs; /* lvalue */
[1141]724        XVec4<T,0x1231> const yzwy, gbag, tpqt;
725        XVec4<T,0x1232> const yzwz, gbab, tpqp;
726        XVec4<T,0x1233> const yzww, gbaa, tpqq;
727        XVec4<T,0x1300> const ywxx, garr, tqss;
728        XVec4<T,0x1301> const ywxy, garg, tqst;
[1143]729        XVec4<T,0x1302> const ywxz, garb, tqsp; /* lvalue */
[1141]730        XVec4<T,0x1303> const ywxw, gara, tqsq;
731        XVec4<T,0x1310> const ywyx, gagr, tqts;
732        XVec4<T,0x1311> const ywyy, gagg, tqtt;
733        XVec4<T,0x1312> const ywyz, gagb, tqtp;
734        XVec4<T,0x1313> const ywyw, gaga, tqtq;
[1143]735        XVec4<T,0x1320> const ywzx, gabr, tqps; /* lvalue */
[1141]736        XVec4<T,0x1321> const ywzy, gabg, tqpt;
737        XVec4<T,0x1322> const ywzz, gabb, tqpp;
738        XVec4<T,0x1323> const ywzw, gaba, tqpq;
739        XVec4<T,0x1330> const ywwx, gaar, tqqs;
740        XVec4<T,0x1331> const ywwy, gaag, tqqt;
741        XVec4<T,0x1332> const ywwz, gaab, tqqp;
742        XVec4<T,0x1333> const ywww, gaaa, tqqq;
743        XVec4<T,0x2000> const zxxx, brrr, psss;
744        XVec4<T,0x2001> const zxxy, brrg, psst;
745        XVec4<T,0x2002> const zxxz, brrb, pssp;
746        XVec4<T,0x2003> const zxxw, brra, pssq;
747        XVec4<T,0x2010> const zxyx, brgr, psts;
748        XVec4<T,0x2011> const zxyy, brgg, pstt;
749        XVec4<T,0x2012> const zxyz, brgb, pstp;
[1143]750        XVec4<T,0x2013> const zxyw, brga, pstq; /* lvalue */
[1141]751        XVec4<T,0x2020> const zxzx, brbr, psps;
752        XVec4<T,0x2021> const zxzy, brbg, pspt;
753        XVec4<T,0x2022> const zxzz, brbb, pspp;
754        XVec4<T,0x2023> const zxzw, brba, pspq;
755        XVec4<T,0x2030> const zxwx, brar, psqs;
[1143]756        XVec4<T,0x2031> const zxwy, brag, psqt; /* lvalue */
[1141]757        XVec4<T,0x2032> const zxwz, brab, psqp;
758        XVec4<T,0x2033> const zxww, braa, psqq;
759        XVec4<T,0x2100> const zyxx, bgrr, ptss;
760        XVec4<T,0x2101> const zyxy, bgrg, ptst;
761        XVec4<T,0x2102> const zyxz, bgrb, ptsp;
[1143]762        XVec4<T,0x2103> const zyxw, bgra, ptsq; /* lvalue */
[1141]763        XVec4<T,0x2110> const zyyx, bggr, ptts;
764        XVec4<T,0x2111> const zyyy, bggg, pttt;
765        XVec4<T,0x2112> const zyyz, bggb, pttp;
766        XVec4<T,0x2113> const zyyw, bgga, pttq;
767        XVec4<T,0x2120> const zyzx, bgbr, ptps;
768        XVec4<T,0x2121> const zyzy, bgbg, ptpt;
769        XVec4<T,0x2122> const zyzz, bgbb, ptpp;
770        XVec4<T,0x2123> const zyzw, bgba, ptpq;
[1143]771        XVec4<T,0x2130> const zywx, bgar, ptqs; /* lvalue */
[1141]772        XVec4<T,0x2131> const zywy, bgag, ptqt;
773        XVec4<T,0x2132> const zywz, bgab, ptqp;
774        XVec4<T,0x2133> const zyww, bgaa, ptqq;
775        XVec4<T,0x2200> const zzxx, bbrr, ppss;
776        XVec4<T,0x2201> const zzxy, bbrg, ppst;
777        XVec4<T,0x2202> const zzxz, bbrb, ppsp;
778        XVec4<T,0x2203> const zzxw, bbra, ppsq;
779        XVec4<T,0x2210> const zzyx, bbgr, ppts;
780        XVec4<T,0x2211> const zzyy, bbgg, pptt;
781        XVec4<T,0x2212> const zzyz, bbgb, pptp;
782        XVec4<T,0x2213> const zzyw, bbga, pptq;
783        XVec4<T,0x2220> const zzzx, bbbr, ppps;
784        XVec4<T,0x2221> const zzzy, bbbg, pppt;
785        XVec4<T,0x2222> const zzzz, bbbb, pppp;
786        XVec4<T,0x2223> const zzzw, bbba, pppq;
787        XVec4<T,0x2230> const zzwx, bbar, ppqs;
788        XVec4<T,0x2231> const zzwy, bbag, ppqt;
789        XVec4<T,0x2232> const zzwz, bbab, ppqp;
790        XVec4<T,0x2233> const zzww, bbaa, ppqq;
791        XVec4<T,0x2300> const zwxx, barr, pqss;
[1143]792        XVec4<T,0x2301> const zwxy, barg, pqst; /* lvalue */
[1141]793        XVec4<T,0x2302> const zwxz, barb, pqsp;
794        XVec4<T,0x2303> const zwxw, bara, pqsq;
[1143]795        XVec4<T,0x2310> const zwyx, bagr, pqts; /* lvalue */
[1141]796        XVec4<T,0x2311> const zwyy, bagg, pqtt;
797        XVec4<T,0x2312> const zwyz, bagb, pqtp;
798        XVec4<T,0x2313> const zwyw, baga, pqtq;
799        XVec4<T,0x2320> const zwzx, babr, pqps;
800        XVec4<T,0x2321> const zwzy, babg, pqpt;
801        XVec4<T,0x2322> const zwzz, babb, pqpp;
802        XVec4<T,0x2323> const zwzw, baba, pqpq;
803        XVec4<T,0x2330> const zwwx, baar, pqqs;
804        XVec4<T,0x2331> const zwwy, baag, pqqt;
805        XVec4<T,0x2332> const zwwz, baab, pqqp;
806        XVec4<T,0x2333> const zwww, baaa, pqqq;
807        XVec4<T,0x3000> const wxxx, arrr, qsss;
808        XVec4<T,0x3001> const wxxy, arrg, qsst;
809        XVec4<T,0x3002> const wxxz, arrb, qssp;
810        XVec4<T,0x3003> const wxxw, arra, qssq;
811        XVec4<T,0x3010> const wxyx, argr, qsts;
812        XVec4<T,0x3011> const wxyy, argg, qstt;
[1143]813        XVec4<T,0x3012> const wxyz, argb, qstp; /* lvalue */
[1141]814        XVec4<T,0x3013> const wxyw, arga, qstq;
815        XVec4<T,0x3020> const wxzx, arbr, qsps;
[1143]816        XVec4<T,0x3021> const wxzy, arbg, qspt; /* lvalue */
[1141]817        XVec4<T,0x3022> const wxzz, arbb, qspp;
818        XVec4<T,0x3023> const wxzw, arba, qspq;
819        XVec4<T,0x3030> const wxwx, arar, qsqs;
820        XVec4<T,0x3031> const wxwy, arag, qsqt;
821        XVec4<T,0x3032> const wxwz, arab, qsqp;
822        XVec4<T,0x3033> const wxww, araa, qsqq;
823        XVec4<T,0x3100> const wyxx, agrr, qtss;
824        XVec4<T,0x3101> const wyxy, agrg, qtst;
[1143]825        XVec4<T,0x3102> const wyxz, agrb, qtsp; /* lvalue */
[1141]826        XVec4<T,0x3103> const wyxw, agra, qtsq;
827        XVec4<T,0x3110> const wyyx, aggr, qtts;
828        XVec4<T,0x3111> const wyyy, aggg, qttt;
829        XVec4<T,0x3112> const wyyz, aggb, qttp;
830        XVec4<T,0x3113> const wyyw, agga, qttq;
[1143]831        XVec4<T,0x3120> const wyzx, agbr, qtps; /* lvalue */
[1141]832        XVec4<T,0x3121> const wyzy, agbg, qtpt;
833        XVec4<T,0x3122> const wyzz, agbb, qtpp;
834        XVec4<T,0x3123> const wyzw, agba, qtpq;
835        XVec4<T,0x3130> const wywx, agar, qtqs;
836        XVec4<T,0x3131> const wywy, agag, qtqt;
837        XVec4<T,0x3132> const wywz, agab, qtqp;
838        XVec4<T,0x3133> const wyww, agaa, qtqq;
839        XVec4<T,0x3200> const wzxx, abrr, qpss;
[1143]840        XVec4<T,0x3201> const wzxy, abrg, qpst; /* lvalue */
[1141]841        XVec4<T,0x3202> const wzxz, abrb, qpsp;
842        XVec4<T,0x3203> const wzxw, abra, qpsq;
[1143]843        XVec4<T,0x3210> const wzyx, abgr, qpts; /* lvalue */
[1141]844        XVec4<T,0x3211> const wzyy, abgg, qptt;
845        XVec4<T,0x3212> const wzyz, abgb, qptp;
846        XVec4<T,0x3213> const wzyw, abga, qptq;
847        XVec4<T,0x3220> const wzzx, abbr, qpps;
848        XVec4<T,0x3221> const wzzy, abbg, qppt;
849        XVec4<T,0x3222> const wzzz, abbb, qppp;
850        XVec4<T,0x3223> const wzzw, abba, qppq;
851        XVec4<T,0x3230> const wzwx, abar, qpqs;
852        XVec4<T,0x3231> const wzwy, abag, qpqt;
853        XVec4<T,0x3232> const wzwz, abab, qpqp;
854        XVec4<T,0x3233> const wzww, abaa, qpqq;
855        XVec4<T,0x3300> const wwxx, aarr, qqss;
856        XVec4<T,0x3301> const wwxy, aarg, qqst;
857        XVec4<T,0x3302> const wwxz, aarb, qqsp;
858        XVec4<T,0x3303> const wwxw, aara, qqsq;
859        XVec4<T,0x3310> const wwyx, aagr, qqts;
860        XVec4<T,0x3311> const wwyy, aagg, qqtt;
861        XVec4<T,0x3312> const wwyz, aagb, qqtp;
862        XVec4<T,0x3313> const wwyw, aaga, qqtq;
863        XVec4<T,0x3320> const wwzx, aabr, qqps;
864        XVec4<T,0x3321> const wwzy, aabg, qqpt;
865        XVec4<T,0x3322> const wwzz, aabb, qqpp;
866        XVec4<T,0x3323> const wwzw, aaba, qqpq;
867        XVec4<T,0x3330> const wwwx, aaar, qqqs;
868        XVec4<T,0x3331> const wwwy, aaag, qqqt;
869        XVec4<T,0x3332> const wwwz, aaab, qqqp;
870        XVec4<T,0x3333> const wwww, aaaa, qqqq;
[2179]871#endif
[1154]872#if LOL_NO_CONST_MEMBERS_IN_ANONYMOUS_UNIONS
873#   undef const
874#endif
[1139]875    };
876};
877
[1148]878template <> struct BVec4<half>
879{
880    explicit inline BVec4() {}
881    explicit inline BVec4(half X, half Y, half Z, half W)
882     : x(X), y(Y), z(Z), w(W) {}
883
884    half x, y, z, w;
885};
886
887template <> struct BVec4<real>
888{
889    explicit inline BVec4() {}
890    explicit inline BVec4(real X, real Y, real Z, real W)
891     : x(X), y(Y), z(Z), w(W) {}
892
893    real x, y, z, w;
894};
895
896template <typename T> struct Vec4 : BVec4<T>
897{
898    inline Vec4() {}
899    inline Vec4(T X, T Y, T Z, T W) : BVec4<T>(X, Y, Z, W) {}
900    inline Vec4(Vec2<T> XY, T Z, T W) : BVec4<T>(XY.x, XY.y, Z, W) {}
901    inline Vec4(T X, Vec2<T> YZ, T W) : BVec4<T>(X, YZ.x, YZ.y, W) {}
902    inline Vec4(T X, T Y, Vec2<T> ZW) : BVec4<T>(X, Y, ZW.x, ZW.y) {}
903    inline Vec4(Vec2<T> XY, Vec2<T> ZW) : BVec4<T>(XY.x, XY.y, ZW.x, ZW.y) {}
904    inline Vec4(Vec3<T> XYZ, T W) : BVec4<T>(XYZ.x, XYZ.y, XYZ.z, W) {}
905    inline Vec4(T X, Vec3<T> YZW) : BVec4<T>(X, YZW.x, YZW.y, YZW.z) {}
906
907    explicit inline Vec4(T X) : BVec4<T>(X, X, X, X) {}
908
909    template<int N>
910    inline Vec4(XVec4<T, N> const &v)
[1158]911      : BVec4<T>(v[0], v[1], v[2], v[3]) {}
[1148]912
913    template<typename U, int N>
914    explicit inline Vec4(XVec4<U, N> const &v)
[1158]915      : BVec4<T>(v[0], v[1], v[2], v[3]) {}
[1148]916
[2081]917    LOL_MEMBER_OPS(Vec4, x)
[1148]918
919    template<typename U>
920    friend std::ostream &operator<<(std::ostream &stream, Vec4<U> const &v);
921};
922
[1139]923/*
924 * 4-element quaternions
925 */
926
927template <typename T> struct Quat
928{
929    inline Quat() {}
[1351]930    inline Quat(T W) : w(W),  x(0), y(0), z(0) {}
931    inline Quat(T W, T X, T Y, T Z) : w(W), x(X), y(Y), z(Z) {}
[1139]932
[1232]933    Quat(Mat3<T> const &m);
[1139]934    Quat(Mat4<T> const &m);
935
[2081]936    LOL_MEMBER_OPS(Quat, w)
[1139]937
[2348]938    /* Create a unit quaternion representing a rotation around an axis. */
939    static Quat<T> rotate(T degrees, T x, T y, T z);
940    static Quat<T> rotate(T degrees, Vec3<T> const &v);
[1305]941
[1351]942    /* Convert from Euler angles. The axes in fromeuler_xyx are
943     * x, then y', then x", ie. the axes are attached to the model.
944     * If you want to rotate around static axes, just reverse the order
[2348]945     * of the arguments. Angle values are in degrees. */
[1351]946    static Quat<T> fromeuler_xyx(Vec3<T> const &v);
947    static Quat<T> fromeuler_xzx(Vec3<T> const &v);
948    static Quat<T> fromeuler_yxy(Vec3<T> const &v);
949    static Quat<T> fromeuler_yzy(Vec3<T> const &v);
950    static Quat<T> fromeuler_zxz(Vec3<T> const &v);
951    static Quat<T> fromeuler_zyz(Vec3<T> const &v);
952    static Quat<T> fromeuler_xyx(T phi, T theta, T psi);
953    static Quat<T> fromeuler_xzx(T phi, T theta, T psi);
954    static Quat<T> fromeuler_yxy(T phi, T theta, T psi);
955    static Quat<T> fromeuler_yzy(T phi, T theta, T psi);
956    static Quat<T> fromeuler_zxz(T phi, T theta, T psi);
957    static Quat<T> fromeuler_zyz(T phi, T theta, T psi);
958
[1349]959    /* Convert from Tait-Bryan angles (incorrectly called Euler angles,
960     * but since everyone does it…). The axes in fromeuler_xyz are
961     * x, then y', then z", ie. the axes are attached to the model.
962     * If you want to apply yaw around x, pitch around y, and roll
[2348]963     * around z, use fromeuler_xyz. Angle values are in degrees.
[1349]964     * If you want to rotate around static axes, reverse the order in
965     * the function name (_zyx instead of _xyz) AND reverse the order
966     * of the arguments. */
967    static Quat<T> fromeuler_xyz(Vec3<T> const &v);
968    static Quat<T> fromeuler_xzy(Vec3<T> const &v);
969    static Quat<T> fromeuler_yxz(Vec3<T> const &v);
970    static Quat<T> fromeuler_yzx(Vec3<T> const &v);
971    static Quat<T> fromeuler_zxy(Vec3<T> const &v);
972    static Quat<T> fromeuler_zyx(Vec3<T> const &v);
973    static Quat<T> fromeuler_xyz(T phi, T theta, T psi);
974    static Quat<T> fromeuler_xzy(T phi, T theta, T psi);
975    static Quat<T> fromeuler_yxz(T phi, T theta, T psi);
976    static Quat<T> fromeuler_yzx(T phi, T theta, T psi);
977    static Quat<T> fromeuler_zxy(T phi, T theta, T psi);
978    static Quat<T> fromeuler_zyx(T phi, T theta, T psi);
979
[1381]980    inline Quat<T> operator *(Quat<T> const &val) const;
[1139]981
982    inline Quat<T> operator *=(Quat<T> const &val)
983    {
984        return *this = (*this) * val;
985    }
986
987    inline Quat<T> operator ~() const
988    {
[1305]989        return Quat<T>(w, -x, -y, -z);
[1139]990    }
991
[1317]992    inline Vec3<T> transform(Vec3<T> const &v)
993    {
994        Quat<T> p = Quat<T>(0, v.x, v.y, v.z);
995        Quat<T> q = *this * p / *this;
996        return Vec3<T>(q.x, q.y, q.z);
997    }
998
[1139]999    template<typename U>
1000    friend std::ostream &operator<<(std::ostream &stream, Quat<U> const &v);
1001
[1351]1002    /* XXX: storage order is wxyz, unlike vectors! */
1003    T w, x, y, z;
[1139]1004};
1005
1006template<typename T>
1007inline T norm(Quat<T> const &val)
1008{
[1369]1009    return sqlength(val);
[1139]1010}
1011
1012template<typename T>
1013static inline Quat<T> re(Quat<T> const &val)
1014{
1015    return ~val / norm(val);
1016}
1017
1018template<typename T>
1019static inline Quat<T> operator /(T x, Quat<T> const &y)
1020{
1021    return x * re(y);
1022}
1023
1024template<typename T>
[1807]1025static inline Quat<T> operator /(Quat<T> const &x, Quat<T> const &y)
[1139]1026{
1027    return x * re(y);
1028}
1029
[1807]1030template<typename T>
1031extern Quat<T> slerp(Quat<T> const &qa, Quat<T> const &qb, T f);
1032
[1139]1033/*
1034 * Common operators for all vector types, including quaternions
1035 */
1036
[1311]1037/*
1038 * vec +(vec, vec)   (also complex & quaternion)
1039 * vec -(vec, vec)   (also complex & quaternion)
1040 * vec *(vec, vec)
1041 * vec /(vec, vec)
1042 */
[2317]1043#define LOL_VECTOR_VECTOR_OP(tname, op, tprefix, type) \
[1139]1044    tprefix \
[2317]1045    inline tname<type> operator op(tname<type> const &a, tname<type> const &b) \
[1139]1046    { \
[2317]1047        tname<type> ret; \
1048        for (size_t n = 0; n < sizeof(a) / sizeof(type); n++) \
[1139]1049            ret[n] = a[n] op b[n]; \
1050        return ret; \
[1153]1051    }
1052
[1311]1053/*
1054 * vec +=(vec, vec)   (also complex & quaternion)
1055 * vec -=(vec, vec)   (also complex & quaternion)
1056 * vec *=(vec, vec)
1057 * vec /=(vec, vec)
1058 */
[2317]1059#define LOL_VECTOR_VECTOR_NONCONST_OP(tname, op, tprefix, type) \
[1139]1060    tprefix \
[1157]1061    inline tname<type> operator op##=(tname<type> &a, tname<type> const &b) \
[1139]1062    { \
1063        return a = a op b; \
1064    }
1065
[1311]1066/*
[2054]1067 * vec min(vec, vec)     (also max, fmod)
1068 * vec min(vec, scalar)  (also max, fmod)
1069 * vec min(scalar, vec)  (also max, fmod)
[1311]1070 */
[2081]1071#define LOL_VECTOR_MINMAX_FUN(tname, op, tprefix, type) \
[1311]1072    tprefix \
1073    inline tname<type> op(tname<type> const &a, tname<type> const &b) \
1074    { \
[2056]1075        using lol::op; \
[1311]1076        tname<type> ret; \
1077        for (size_t n = 0; n < sizeof(a) / sizeof(type); n++) \
1078            ret[n] = op(a[n], b[n]); \
1079        return ret; \
1080    } \
1081    \
1082    tprefix \
1083    inline tname<type> op(tname<type> const &a, type const &b) \
1084    { \
[2056]1085        using lol::op; \
[1311]1086        tname<type> ret; \
1087        for (size_t n = 0; n < sizeof(a) / sizeof(type); n++) \
1088            ret[n] = op(a[n], b); \
1089        return ret; \
1090    } \
1091    \
1092    tprefix \
1093    inline tname<type> op(type const &a, tname<type> const &b) \
1094    { \
[2056]1095        using lol::op; \
[1311]1096        tname<type> ret; \
1097        for (size_t n = 0; n < sizeof(b) / sizeof(type); n++) \
1098            ret[n] = op(a, b[n]); \
1099        return ret; \
1100    }
1101
1102/*
1103 * vec clamp(vec, vec, vec)
1104 * vec clamp(vec, vec, scalar)
1105 * vec clamp(vec, scalar, vec)
[2054]1106 * vec clamp(vec, scalar, scalar)
[1311]1107 */
[2081]1108#define LOL_VECTOR_CLAMP_FUN(tname, tprefix, type) \
[1311]1109    tprefix \
1110    inline tname<type> clamp(tname<type> const &x, \
1111                             tname<type> const &a, tname<type> const &b) \
1112    { \
1113        return max(min(x, b), a); \
1114    } \
1115    \
1116    tprefix \
1117    inline tname<type> clamp(tname<type> const &x, \
1118                             type const &a, tname<type> const &b) \
1119    { \
1120        return max(min(x, b), a); \
1121    } \
1122    \
1123    tprefix \
1124    inline tname<type> clamp(tname<type> const &x, \
1125                             tname<type> const &a, type const &b) \
1126    { \
1127        return max(min(x, b), a); \
[2054]1128    } \
1129    \
1130    tprefix \
1131    inline tname<type> clamp(tname<type> const &x, \
1132                             type const &a, type const &b) \
1133    { \
1134        return max(min(x, b), a); \
[1311]1135    }
1136
1137/*
[2192]1138 * vec mix(vec, vec, vec)
1139 * vec mix(vec, vec, scalar)
1140 */
1141#define LOL_VECTOR_MIX_FUN(tname, tprefix, type) \
1142    tprefix \
1143    inline tname<type> mix(tname<type> const &x, \
1144                           tname<type> const &y, tname<type> const &a) \
1145    { \
1146        return x + a * (y - x); \
1147    } \
1148    \
1149    tprefix \
1150    inline tname<type> mix(tname<type> const &x, \
1151                           tname<type> const &y, type const &a) \
1152    { \
1153        return x + a * (y - x); \
1154    }
1155
1156/*
[1311]1157 * bool ==(vec, vec)   (also complex & quaternion)
1158 * bool !=(vec, vec)   (also complex & quaternion)
1159 * bool >=(vec, vec)
1160 * bool <=(vec, vec)
1161 * bool >(vec, vec)
1162 * bool <(vec, vec)
1163 */
[2317]1164#define LOL_VECTOR_VECTOR_BOOL_OP(tname, op, op2, ret, tprefix, type) \
[1139]1165    tprefix \
[2317]1166    inline bool operator op(tname<type> const &a, tname<type> const &b) \
[1139]1167    { \
[2317]1168        for (size_t n = 0; n < sizeof(a) / sizeof(type); n++) \
[1139]1169            if (!(a[n] op2 b[n])) \
1170                return !ret; \
1171        return ret; \
1172    }
1173
[1311]1174/*
1175 * vec *(vec, scalar)   (also complex & quaternion)
1176 * vec /(vec, scalar)   (also complex & quaternion)
1177 */
[2317]1178#define LOL_VECTOR_SCALAR_OP(tname, op, tprefix, type) \
[1139]1179    tprefix \
[2317]1180    inline tname<type> operator op(tname<type> const &a, type const &val) \
[1139]1181    { \
[2317]1182        tname<type> ret; \
1183        for (size_t n = 0; n < sizeof(a) / sizeof(type); n++) \
[1139]1184            ret[n] = a[n] op val; \
1185        return ret; \
[1341]1186    }
1187
1188/*
1189 * vec *(scalar, vec)   (also complex & quaternion)
1190 * vec /(scalar, vec)   (NOT for complex & quaternion!)
1191 */
[2317]1192#define LOL_SCALAR_VECTOR_OP(tname, op, tprefix, type) \
[1139]1193    tprefix \
[2317]1194    inline tname<type> operator op(type const &val, tname<type> const &a) \
[1139]1195    { \
[2317]1196        tname<type> ret; \
1197        for (size_t n = 0; n < sizeof(a) / sizeof(type); n++) \
[1139]1198            ret[n] = a[n] op val; \
1199        return ret; \
[1153]1200    }
1201
[1311]1202/*
1203 * vec *=(vec, scalar)   (also complex & quaternion)
1204 * vec /=(vec, scalar)   (also complex & quaternion)
1205 */
[2317]1206#define LOL_VECTOR_SCALAR_NONCONST_OP(tname, op, tprefix, type) \
[1139]1207    tprefix \
[1157]1208    inline tname<type> operator op##=(tname<type> &a, type const &val) \
[1139]1209    { \
1210        return a = a op val; \
1211    }
1212
[2081]1213#define LOL_UNARY_OPS(tname, tprefix, type) \
[1139]1214    tprefix \
[1157]1215    inline tname<type> operator -(tname<type> const &a) \
[1139]1216    { \
[1151]1217        tname<type> ret; \
1218        for (size_t n = 0; n < sizeof(a) / sizeof(type); n++) \
[1139]1219            ret[n] = -a[n]; \
1220        return ret; \
[2081]1221    }
1222
1223#define LOL_UNARY_FUNS(tname, tprefix, type) \
[1139]1224    tprefix \
[1369]1225    inline type sqlength(tname<type> const &a) \
[1139]1226    { \
[1151]1227        type acc = 0; \
1228        for (size_t n = 0; n < sizeof(a) / sizeof(type); n++) \
[1139]1229            acc += a[n] * a[n]; \
1230        return acc; \
1231    } \
1232    \
1233    tprefix \
[2057]1234    inline type length(tname<type> const &a) \
[1139]1235    { \
[2057]1236        return (type)sqrt((double)sqlength(a)); \
[1139]1237    } \
1238    \
1239    tprefix \
[2192]1240    inline tname<type> fract(tname<type> const &a) \
1241    { \
1242        tname<type> ret; \
1243        for (size_t n = 0; n < sizeof(a) / sizeof(type); n++) \
1244            ret[n] = fract(a[n]); \
1245        return ret; \
1246    } \
1247    \
1248    tprefix \
[2054]1249    inline tname<type> normalize(tname<type> const &a) \
[1139]1250    { \
[2054]1251        type norm = (type)length(a); \
1252        return norm ? a / norm : a * (type)0; \
1253    } \
1254    \
1255    tprefix \
1256    inline tname<type> abs(tname<type> const &a) \
1257    { \
1258        tname<type> ret; \
1259        for (size_t n = 0; n < sizeof(a) / sizeof(type); n++) \
[2056]1260            ret[n] = lol::abs(a[n]); \
[2054]1261        return ret; \
[1151]1262    }
1263
[2317]1264#define LOL_BINARY_NONVECTOR_FUNS(tname, tprefix, type) \
[1139]1265    tprefix \
[2317]1266    inline type dot(tname<type> const &a, tname<type> const &b) \
[1139]1267    { \
[2317]1268        type ret = 0; \
1269        for (size_t n = 0; n < sizeof(a) / sizeof(type); n++) \
[1151]1270            ret += a[n] * b[n]; \
1271        return ret; \
[1833]1272    } \
[2317]1273    \
[1833]1274    tprefix \
[2317]1275    inline tname<type> lerp(tname<type> const &a, \
1276                            tname<type> const &b, type x) \
[1833]1277    { \
[2317]1278        tname<type> ret; \
1279        for (size_t n = 0; n < sizeof(a) / sizeof(type); n++) \
[2279]1280            ret[n] = a[n] + (b[n] - a[n]) * x; \
[1833]1281        return ret; \
[1139]1282    }
1283
[2317]1284#define LOL_VEC_3_FUNS(tname, tprefix, type) \
[1175]1285    tprefix \
[2317]1286    inline tname<type> cross(tname<type> const &a, tname<type> const &b) \
[1175]1287    { \
[2317]1288        return tname<type>((type)(a.y * b.z - a.z * b.y), \
1289                           (type)(a.z * b.x - a.x * b.z), \
1290                           (type)(a.x * b.y - a.y * b.x)); \
[1175]1291    }
1292
[2081]1293#define LOL_BINARY_NONVECTOR_OPS(tname, tprefix, type) \
1294    LOL_VECTOR_VECTOR_OP(tname, -, tprefix, type) \
1295    LOL_VECTOR_VECTOR_OP(tname, +, tprefix, type) \
[2317]1296    LOL_VECTOR_SCALAR_OP(tname, *, tprefix, type) \
1297    LOL_VECTOR_SCALAR_OP(tname, /, tprefix, type) \
1298    LOL_SCALAR_VECTOR_OP(tname, *, tprefix, type) \
[1311]1299    \
[2317]1300    LOL_VECTOR_VECTOR_NONCONST_OP(tname, -, tprefix, type) \
1301    LOL_VECTOR_VECTOR_NONCONST_OP(tname, +, tprefix, type) \
1302    LOL_VECTOR_SCALAR_NONCONST_OP(tname, *, tprefix, type) \
1303    LOL_VECTOR_SCALAR_NONCONST_OP(tname, /, tprefix, type) \
1304    \
1305    LOL_VECTOR_VECTOR_BOOL_OP(tname, ==, ==, true, tprefix, type) \
1306    LOL_VECTOR_VECTOR_BOOL_OP(tname, !=, ==, false, tprefix, type)
[1341]1307
[2081]1308#define LOL_BINARY_VECTOR_OPS(tname, tprefix, type) \
[2317]1309    LOL_SCALAR_VECTOR_OP(tname, /, tprefix, type)
[2081]1310
1311#define LOL_BINARY_VECTOR_FUNS(tname, tprefix, type) \
1312    LOL_VECTOR_MINMAX_FUN(tname, min, tprefix, type) \
1313    LOL_VECTOR_MINMAX_FUN(tname, max, tprefix, type) \
1314    LOL_VECTOR_MINMAX_FUN(tname, fmod, tprefix, type) \
[2192]1315    LOL_VECTOR_CLAMP_FUN(tname, tprefix, type) \
[2317]1316    LOL_VECTOR_MIX_FUN(tname, tprefix, type) \
[1153]1317    \
[2317]1318    LOL_VECTOR_VECTOR_BOOL_OP(tname, <=, <=, true, tprefix, type) \
1319    LOL_VECTOR_VECTOR_BOOL_OP(tname, >=, >=, true, tprefix, type) \
1320    LOL_VECTOR_VECTOR_BOOL_OP(tname, <, <, true, tprefix, type) \
1321    LOL_VECTOR_VECTOR_BOOL_OP(tname, >, >, true, tprefix, type)
[1153]1322
[2081]1323#define LOL_VECTOR_OPS(tname, tprefix, type) \
[2317]1324    LOL_VECTOR_VECTOR_OP(tname, *, tprefix, type) \
1325    LOL_VECTOR_VECTOR_OP(tname, /, tprefix, type) \
[1153]1326    \
[2317]1327    LOL_VECTOR_VECTOR_NONCONST_OP(tname, *, tprefix, type) \
1328    LOL_VECTOR_VECTOR_NONCONST_OP(tname, /, tprefix, type)
[1139]1329
[2081]1330#define LOL_ALL_NONVECTOR_OPS_AND_FUNS(tname) \
1331    LOL_BINARY_NONVECTOR_OPS(tname, template<typename T> static, T) \
1332    LOL_BINARY_NONVECTOR_FUNS(tname, template<typename T> static, T) \
1333    LOL_UNARY_OPS(tname, template<typename T> static, T) \
1334    LOL_UNARY_FUNS(tname, template<typename T> static, T)
[1139]1335
[2081]1336#define LOL_ALL_VECTOR_OPS_INNER(tname, type) \
1337    LOL_BINARY_VECTOR_OPS(tname, static, type) \
1338    LOL_BINARY_NONVECTOR_OPS(tname, static, type) \
1339    LOL_UNARY_OPS(tname, static, type) \
1340    LOL_VECTOR_OPS(tname, static, type)
[1139]1341
[2081]1342#define LOL_ALL_VECTOR_FUNS_INNER(tname, type) \
1343    LOL_BINARY_VECTOR_FUNS(tname, static, type) \
1344    LOL_BINARY_NONVECTOR_FUNS(tname, static, type) \
1345    LOL_UNARY_FUNS(tname, static, type)
1346
[2532]1347/* HACK: This trick fails with Apple’s clang++, which sometimes fails to deduce
1348 * the arguments for simple stuff such as vec3 + vec3. Disable it for now.
1349 * Note that llvm-g++ doesn’t have the problem. */
1350#if defined __clang__
1351#   define LOL_OPEN_NAMESPACE(x)
1352#   define LOL_CLOSE_NAMESPACE(x)
1353#else
1354#   define LOL_OPEN_NAMESPACE(x) namespace x {
1355#   define LOL_CLOSE_NAMESPACE(x) } using namespace x;
1356#endif
1357
[2081]1358#define LOL_ALL_VECTOR_OPS_AND_FUNS(type) \
[2532]1359    LOL_OPEN_NAMESPACE(x##type) \
[2081]1360        LOL_ALL_VECTOR_OPS_INNER(Vec2, type) \
1361        LOL_ALL_VECTOR_OPS_INNER(Vec3, type) \
1362        LOL_ALL_VECTOR_OPS_INNER(Vec4, type) \
[2532]1363    LOL_CLOSE_NAMESPACE(x##type) \
[2081]1364    LOL_ALL_VECTOR_FUNS_INNER(Vec2, type) \
1365    LOL_ALL_VECTOR_FUNS_INNER(Vec3, type) \
1366    LOL_ALL_VECTOR_FUNS_INNER(Vec4, type) \
[2317]1367    LOL_VEC_3_FUNS(Vec3, static, type)
[1139]1368
[2081]1369LOL_ALL_NONVECTOR_OPS_AND_FUNS(Cmplx)
1370LOL_ALL_NONVECTOR_OPS_AND_FUNS(Quat)
[1176]1371
[1161]1372/* Disable warning about unary operator applied to unsigned type */
1373#if defined _MSC_VER
1374#   pragma warning(push)
1375#   pragma warning(disable: 4146)
1376#endif
1377
[2081]1378LOL_ALL_VECTOR_OPS_AND_FUNS(half)
1379LOL_ALL_VECTOR_OPS_AND_FUNS(float)
1380LOL_ALL_VECTOR_OPS_AND_FUNS(double)
1381LOL_ALL_VECTOR_OPS_AND_FUNS(ldouble)
[2318]1382LOL_ALL_VECTOR_OPS_AND_FUNS(real)
1383
[2081]1384LOL_ALL_VECTOR_OPS_AND_FUNS(int8_t)
1385LOL_ALL_VECTOR_OPS_AND_FUNS(uint8_t)
1386LOL_ALL_VECTOR_OPS_AND_FUNS(int16_t)
1387LOL_ALL_VECTOR_OPS_AND_FUNS(uint16_t)
1388LOL_ALL_VECTOR_OPS_AND_FUNS(int32_t)
1389LOL_ALL_VECTOR_OPS_AND_FUNS(uint32_t)
1390LOL_ALL_VECTOR_OPS_AND_FUNS(int64_t)
1391LOL_ALL_VECTOR_OPS_AND_FUNS(uint64_t)
[1151]1392
[2317]1393#if defined _MSC_VER
[1159]1394#   pragma warning(pop)
1395#endif
1396
[2081]1397#undef LOL_MEMBER_OPS
[1139]1398
[2081]1399#undef LOL_VECTOR_VECTOR_OP
[2317]1400#undef LOL_VECTOR_VECTOR_NONCONST_OP
[2081]1401#undef LOL_VECTOR_MINMAX_FUN
1402#undef LOL_VECTOR_CLAMP_FUN
[2192]1403#undef LOL_VECTOR_MIX_FUN
[2081]1404#undef LOL_VECTOR_VECTOR_BOOL_OP
1405#undef LOL_VECTOR_SCALAR_OP
[2317]1406#undef LOL_SCALAR_VECTOR_OP
1407#undef LOL_VECTOR_SCALAR_OP
[2081]1408
1409#undef LOL_BINARY_VECTOR_OPS
1410#undef LOL_BINARY_VECTOR_FUNS
1411#undef LOL_BINARY_NONVECTOR_OPS
1412#undef LOL_BINARY_NONVECTOR_FUNS
1413#undef LOL_UNARY_OPS
1414#undef LOL_UNARY_FUNS
[2317]1415#undef LOL_VEC_3_FUNS
[2081]1416#undef LOL_VECTOR_OPS
1417
1418#undef LOL_ALL_NONVECTOR_OPS_AND_FUNS
1419#undef LOL_ALL_VECTOR_OPS_INNER
1420#undef LOL_ALL_VECTOR_FUNS_INNER
1421#undef LOL_ALL_VECTOR_OPS_AND_FUNS
1422
[2532]1423#undef LOL_OPEN_NAMESPACE
1424#undef LOL_CLOSE_NAMESPACE
1425
[1139]1426/*
[1381]1427 * Definition of additional functions requiring vector functions
1428 */
1429
1430template<typename T>
1431inline Quat<T> Quat<T>::operator *(Quat<T> const &val) const
1432{
1433    Quat<T> ret;
1434    Vec3<T> v1(x, y, z);
1435    Vec3<T> v2(val.x, val.y, val.z);
1436    Vec3<T> v3 = cross(v1, v2) + w * v2 + val.w * v1;
1437    return Quat<T>(w * val.w - dot(v1, v2), v3.x, v3.y, v3.z);
1438}
1439
1440/*
[1139]1441 * Magic vector swizzling (part 2/2)
[1143]1442 * Unfortunately these assignment operators cannot be used for now, because
1443 * we would also need to override the default copy assignment operator, and
1444 * in C++98 unions cannot contain such objects. This is why all the swizzling
1445 * magic objects are marked 'const' even those that could be lvalues.
[1139]1446 */
1447
1448template<typename T, int N>
[1142]1449inline Vec2<T> XVec2<T, N>::operator =(Vec2<T> const &that)
[1139]1450{
[1158]1451    for (int i = 0; i < 2; i++)
1452        *this[i] = that[i];
[1139]1453    return *this;
1454}
1455
1456template<typename T, int N>
[1142]1457inline Vec3<T> XVec3<T, N>::operator =(Vec3<T> const &that)
[1139]1458{
[1158]1459    for (int i = 0; i < 3; i++)
1460        *this[i] = that[i];
[1139]1461    return *this;
1462}
1463
1464template<typename T, int N>
[1142]1465inline Vec4<T> XVec4<T, N>::operator =(Vec4<T> const &that)
[1139]1466{
[1158]1467    for (int i = 0; i < 4; i++)
1468        *this[i] = that[i];
[1139]1469    return *this;
1470}
1471
1472/*
[1232]1473 * 2×2-element matrices
1474 */
1475
1476template <typename T> struct Mat2
1477{
1478    inline Mat2() {}
1479    inline Mat2(Vec2<T> V0, Vec2<T> V1)
1480      : v0(V0), v1(V1) {}
1481
1482    explicit inline Mat2(T val)
1483      : v0(val, (T)0),
1484        v1((T)0, val) {}
1485
[1258]1486    explicit inline Mat2(Mat4<T> const &mat)
1487      : v0(mat[0].xy),
1488        v1(mat[1].xy) {}
1489
[1232]1490    inline Vec2<T>& operator[](size_t n) { return (&v0)[n]; }
1491    inline Vec2<T> const& operator[](size_t n) const { return (&v0)[n]; }
1492
1493    /* Helpers for transformation matrices */
[2348]1494    static Mat2<T> rotate(T degrees);
1495    static inline Mat2<T> rotate(Mat2<T> mat, T degrees)
[1232]1496    {
[2348]1497        return rotate(degrees) * mat;
[1232]1498    }
1499
1500    void printf() const;
1501
1502    template<class U>
1503    friend std::ostream &operator<<(std::ostream &stream, Mat2<U> const &m);
1504
1505    inline Mat2<T> operator +(Mat2<T> const m) const
1506    {
1507        return Mat2<T>(v0 + m[0], v1 + m[1]);
1508    }
1509
1510    inline Mat2<T> operator +=(Mat2<T> const m)
1511    {
1512        return *this = *this + m;
1513    }
1514
1515    inline Mat2<T> operator -(Mat2<T> const m) const
1516    {
1517        return Mat2<T>(v0 - m[0], v1 - m[1]);
1518    }
1519
1520    inline Mat2<T> operator -=(Mat2<T> const m)
1521    {
1522        return *this = *this - m;
1523    }
1524
1525    inline Mat2<T> operator *(Mat2<T> const m) const
1526    {
1527        return Mat2<T>(*this * m[0], *this * m[1]);
1528    }
1529
1530    inline Mat2<T> operator *=(Mat2<T> const m)
1531    {
1532        return *this = *this * m;
1533    }
1534
1535    inline Vec2<T> operator *(Vec2<T> const m) const
1536    {
1537        Vec2<T> ret;
1538        for (int j = 0; j < 2; j++)
1539        {
1540            T tmp = 0;
1541            for (int k = 0; k < 2; k++)
1542                tmp += (*this)[k][j] * m[k];
1543            ret[j] = tmp;
1544        }
1545        return ret;
1546    }
1547
1548    Vec2<T> v0, v1;
1549};
1550
1551/*
1552 * 3×3-element matrices
1553 */
1554
1555template <typename T> struct Mat3
1556{
1557    inline Mat3() {}
1558    inline Mat3(Vec3<T> V0, Vec3<T> V1, Vec3<T> V2)
1559      : v0(V0), v1(V1), v2(V2) {}
1560
1561    explicit inline Mat3(T val)
1562      : v0(val, (T)0, (T)0),
1563        v1((T)0, val, (T)0),
1564        v2((T)0, (T)0, val) {}
1565
[1264]1566    explicit inline Mat3(Mat2<T> mat)
1567      : v0(mat[0], (T)0),
1568        v1(mat[1], (T)0),
1569        v2((T)0, (T)0, (T)0) {}
1570
1571    explicit inline Mat3(Mat2<T> mat, T val)
1572      : v0(Vec3<T>(mat[0], (T)0)),
1573        v1(Vec3<T>(mat[1], (T)0)),
1574        v2((T)0, (T)0, val) {}
1575
[1258]1576    explicit inline Mat3(Mat4<T> const &mat)
1577      : v0(mat[0].xyz),
1578        v1(mat[1].xyz),
1579        v2(mat[2].xyz) {}
1580
[1320]1581    explicit Mat3(Quat<T> const &q);
1582
[1232]1583    inline Vec3<T>& operator[](size_t n) { return (&v0)[n]; }
1584    inline Vec3<T> const& operator[](size_t n) const { return (&v0)[n]; }
1585
1586    /* Helpers for transformation matrices */
[1947]1587    static Mat3<T> scale(T x);
[1272]1588    static Mat3<T> scale(T x, T y, T z);
1589    static Mat3<T> scale(Vec3<T> v);
[2348]1590    static Mat3<T> rotate(T degrees, T x, T y, T z);
1591    static Mat3<T> rotate(T degrees, Vec3<T> v);
[1232]1592
[1352]1593    static Mat3<T> fromeuler_xyz(Vec3<T> const &v);
1594    static Mat3<T> fromeuler_xzy(Vec3<T> const &v);
1595    static Mat3<T> fromeuler_yxz(Vec3<T> const &v);
1596    static Mat3<T> fromeuler_yzx(Vec3<T> const &v);
1597    static Mat3<T> fromeuler_zxy(Vec3<T> const &v);
1598    static Mat3<T> fromeuler_zyx(Vec3<T> const &v);
1599    static Mat3<T> fromeuler_xyz(T phi, T theta, T psi);
1600    static Mat3<T> fromeuler_xzy(T phi, T theta, T psi);
1601    static Mat3<T> fromeuler_yxz(T phi, T theta, T psi);
1602    static Mat3<T> fromeuler_yzx(T phi, T theta, T psi);
1603    static Mat3<T> fromeuler_zxy(T phi, T theta, T psi);
1604    static Mat3<T> fromeuler_zyx(T phi, T theta, T psi);
1605
1606    static Mat3<T> fromeuler_xyx(Vec3<T> const &v);
1607    static Mat3<T> fromeuler_xzx(Vec3<T> const &v);
1608    static Mat3<T> fromeuler_yxy(Vec3<T> const &v);
1609    static Mat3<T> fromeuler_yzy(Vec3<T> const &v);
1610    static Mat3<T> fromeuler_zxz(Vec3<T> const &v);
1611    static Mat3<T> fromeuler_zyz(Vec3<T> const &v);
1612    static Mat3<T> fromeuler_xyx(T phi, T theta, T psi);
1613    static Mat3<T> fromeuler_xzx(T phi, T theta, T psi);
1614    static Mat3<T> fromeuler_yxy(T phi, T theta, T psi);
1615    static Mat3<T> fromeuler_yzy(T phi, T theta, T psi);
1616    static Mat3<T> fromeuler_zxz(T phi, T theta, T psi);
1617    static Mat3<T> fromeuler_zyz(T phi, T theta, T psi);
1618
[2348]1619    static inline Mat3<T> rotate(Mat3<T> mat, T degrees, Vec3<T> v)
[1232]1620    {
[2348]1621        return rotate(degrees, v) * mat;
[1232]1622    }
1623
1624    void printf() const;
1625
1626    template<class U>
1627    friend std::ostream &operator<<(std::ostream &stream, Mat3<U> const &m);
1628
1629    inline Mat3<T> operator +(Mat3<T> const m) const
1630    {
1631        return Mat3<T>(v0 + m[0], v1 + m[1], v2 + m[2]);
1632    }
1633
1634    inline Mat3<T> operator +=(Mat3<T> const m)
1635    {
1636        return *this = *this + m;
1637    }
1638
1639    inline Mat3<T> operator -(Mat3<T> const m) const
1640    {
1641        return Mat3<T>(v0 - m[0], v1 - m[1], v2 - m[2]);
1642    }
1643
1644    inline Mat3<T> operator -=(Mat3<T> const m)
1645    {
1646        return *this = *this - m;
1647    }
1648
1649    inline Mat3<T> operator *(Mat3<T> const m) const
1650    {
1651        return Mat3<T>(*this * m[0], *this * m[1], *this * m[2]);
1652    }
1653
1654    inline Mat3<T> operator *=(Mat3<T> const m)
1655    {
1656        return *this = *this * m;
1657    }
1658
1659    inline Vec3<T> operator *(Vec3<T> const m) const
1660    {
1661        Vec3<T> ret;
1662        for (int j = 0; j < 3; j++)
1663        {
1664            T tmp = 0;
1665            for (int k = 0; k < 3; k++)
1666                tmp += (*this)[k][j] * m[k];
1667            ret[j] = tmp;
1668        }
1669        return ret;
1670    }
1671
1672    Vec3<T> v0, v1, v2;
1673};
1674
1675/*
[1139]1676 * 4×4-element matrices
1677 */
1678
1679template <typename T> struct Mat4
1680{
1681    inline Mat4() {}
1682    inline Mat4(Vec4<T> V0, Vec4<T> V1, Vec4<T> V2, Vec4<T> V3)
1683      : v0(V0), v1(V1), v2(V2), v3(V3) {}
1684
1685    explicit inline Mat4(T val)
1686      : v0(val, (T)0, (T)0, (T)0),
1687        v1((T)0, val, (T)0, (T)0),
1688        v2((T)0, (T)0, val, (T)0),
1689        v3((T)0, (T)0, (T)0, val) {}
1690
[1264]1691    explicit inline Mat4(Mat2<T> mat)
1692      : v0(mat[0], (T)0, (T)0),
1693        v1(mat[1], (T)0, (T)0),
1694        v2((T)0, (T)0, (T)0, (T)0),
1695        v3((T)0, (T)0, (T)0, (T)0) {}
1696
1697    explicit inline Mat4(Mat2<T> mat, T val1, T val2)
1698      : v0(mat[0], (T)0, (T)0),
1699        v1(mat[1], (T)0, (T)0),
1700        v2((T)0, (T)0, val1, (T)0),
1701        v3((T)0, (T)0, (T)0, val2) {}
1702
1703    explicit inline Mat4(Mat3<T> mat)
1704      : v0(mat[0], (T)0),
1705        v1(mat[1], (T)0),
1706        v2(mat[2], (T)0),
1707        v3((T)0, (T)0, (T)0, (T)0) {}
1708
1709    explicit inline Mat4(Mat3<T> mat, T val)
1710      : v0(mat[0], (T)0),
1711        v1(mat[1], (T)0),
1712        v2(mat[2], (T)0),
1713        v3((T)0, (T)0, (T)0, val) {}
1714
[1320]1715    explicit Mat4(Quat<T> const &q);
1716
[1209]1717    inline Vec4<T>& operator[](size_t n) { return (&v0)[n]; }
1718    inline Vec4<T> const& operator[](size_t n) const { return (&v0)[n]; }
[1139]1719
1720    /* Helpers for transformation matrices */
1721    static Mat4<T> translate(T x, T y, T z);
1722    static Mat4<T> translate(Vec3<T> v);
1723
[1947]1724    static inline Mat4<T> scale(T x)
1725    {
1726        return Mat4<T>(Mat3<T>::scale(x), (T)1);
1727    }
1728
[1272]1729    static inline Mat4<T> scale(T x, T y, T z)
1730    {
1731        return Mat4<T>(Mat3<T>::scale(x, y, z), (T)1);
1732    }
1733
1734    static inline Mat4<T> scale(Vec3<T> v)
1735    {
1736        return Mat4<T>(Mat3<T>::scale(v), (T)1);
1737    }
1738
[1257]1739    static inline Mat4<T> translate(Mat4<T> const &mat, Vec3<T> v)
[1139]1740    {
1741        return translate(v) * mat;
1742    }
1743
[2348]1744    static inline Mat4<T> rotate(T degrees, T x, T y, T z)
[1270]1745    {
[2348]1746        return Mat4<T>(Mat3<T>::rotate(degrees, x, y, z), (T)1);
[1270]1747    }
1748
[2348]1749    static inline Mat4<T> rotate(T degrees, Vec3<T> v)
[1270]1750    {
[2348]1751        return Mat4<T>(Mat3<T>::rotate(degrees, v), (T)1);
[1270]1752    }
1753
[2348]1754    static inline Mat4<T> rotate(Mat4<T> &mat, T degrees, Vec3<T> v)
[1139]1755    {
[2348]1756        return rotate(degrees, v) * mat;
[1139]1757    }
1758
[1352]1759    static Mat4<T> fromeuler_xyz(Vec3<T> const &v);
1760    static Mat4<T> fromeuler_xzy(Vec3<T> const &v);
1761    static Mat4<T> fromeuler_yxz(Vec3<T> const &v);
1762    static Mat4<T> fromeuler_yzx(Vec3<T> const &v);
1763    static Mat4<T> fromeuler_zxy(Vec3<T> const &v);
1764    static Mat4<T> fromeuler_zyx(Vec3<T> const &v);
1765    static Mat4<T> fromeuler_xyz(T phi, T theta, T psi);
1766    static Mat4<T> fromeuler_xzy(T phi, T theta, T psi);
1767    static Mat4<T> fromeuler_yxz(T phi, T theta, T psi);
1768    static Mat4<T> fromeuler_yzx(T phi, T theta, T psi);
1769    static Mat4<T> fromeuler_zxy(T phi, T theta, T psi);
1770    static Mat4<T> fromeuler_zyx(T phi, T theta, T psi);
[1315]1771
[1352]1772    static Mat4<T> fromeuler_xyx(Vec3<T> const &v);
1773    static Mat4<T> fromeuler_xzx(Vec3<T> const &v);
1774    static Mat4<T> fromeuler_yxy(Vec3<T> const &v);
1775    static Mat4<T> fromeuler_yzy(Vec3<T> const &v);
1776    static Mat4<T> fromeuler_zxz(Vec3<T> const &v);
1777    static Mat4<T> fromeuler_zyz(Vec3<T> const &v);
1778    static Mat4<T> fromeuler_xyx(T phi, T theta, T psi);
1779    static Mat4<T> fromeuler_xzx(T phi, T theta, T psi);
1780    static Mat4<T> fromeuler_yxy(T phi, T theta, T psi);
1781    static Mat4<T> fromeuler_yzy(T phi, T theta, T psi);
1782    static Mat4<T> fromeuler_zxz(T phi, T theta, T psi);
1783    static Mat4<T> fromeuler_zyz(T phi, T theta, T psi);
[1315]1784
[1139]1785    /* Helpers for view matrices */
1786    static Mat4<T> lookat(Vec3<T> eye, Vec3<T> center, Vec3<T> up);
1787
1788    /* Helpers for projection matrices */
1789    static Mat4<T> ortho(T left, T right, T bottom, T top, T near, T far);
[1350]1790    static Mat4<T> ortho(T width, T height, T near, T far);
[2749]1791    static Mat4<T> ortho(T screen_size, T screen_ratio_xy, T draw_distance);
[1139]1792    static Mat4<T> frustum(T left, T right, T bottom, T top, T near, T far);
1793    static Mat4<T> perspective(T fov_y, T width, T height, T near, T far);
[2749]1794    static Mat4<T> shifted_perspective(T fov_y, T screen_size, T screen_ratio_xy, T draw_distance);
[2806]1795
[1139]1796    void printf() const;
1797
1798    template<class U>
1799    friend std::ostream &operator<<(std::ostream &stream, Mat4<U> const &m);
1800
[1257]1801    inline Mat4<T> operator +(Mat4<T> const &m) const
[1139]1802    {
1803        return Mat4<T>(v0 + m[0], v1 + m[1], v2 + m[2], v3 + m[3]);
1804    }
1805
[1257]1806    inline Mat4<T> operator +=(Mat4<T> const &m)
[1139]1807    {
1808        return *this = *this + m;
1809    }
1810
[1257]1811    inline Mat4<T> operator -(Mat4<T> const &m) const
[1139]1812    {
1813        return Mat4<T>(v0 - m[0], v1 - m[1], v2 - m[2], v3 - m[3]);
1814    }
1815
[1257]1816    inline Mat4<T> operator -=(Mat4<T> const &m)
[1139]1817    {
1818        return *this = *this - m;
1819    }
1820
[1257]1821    inline Mat4<T> operator *(Mat4<T> const &m) const
[1139]1822    {
1823        return Mat4<T>(*this * m[0], *this * m[1], *this * m[2], *this * m[3]);
1824    }
1825
[1257]1826    inline Mat4<T> operator *=(Mat4<T> const &m)
[1139]1827    {
1828        return *this = *this * m;
1829    }
1830
[1257]1831    inline Vec4<T> operator *(Vec4<T> const &m) const
[1139]1832    {
1833        Vec4<T> ret;
1834        for (int j = 0; j < 4; j++)
1835        {
1836            T tmp = 0;
1837            for (int k = 0; k < 4; k++)
1838                tmp += (*this)[k][j] * m[k];
1839            ret[j] = tmp;
1840        }
1841        return ret;
1842    }
1843
1844    Vec4<T> v0, v1, v2, v3;
1845};
1846
[1257]1847template<typename T> T determinant(Mat2<T> const &);
1848template<typename T> T determinant(Mat3<T> const &);
1849template<typename T> T determinant(Mat4<T> const &);
1850
1851template<typename T> Mat2<T> transpose(Mat2<T> const &);
1852template<typename T> Mat3<T> transpose(Mat3<T> const &);
1853template<typename T> Mat4<T> transpose(Mat4<T> const &);
1854
1855template<typename T> Mat2<T> inverse(Mat2<T> const &);
1856template<typename T> Mat3<T> inverse(Mat3<T> const &);
1857template<typename T> Mat4<T> inverse(Mat4<T> const &);
1858
[1139]1859/*
1860 * Arbitrarily-sized square matrices; for now this only supports
1861 * naive inversion and is used for the Remez inversion method.
1862 */
1863
1864template<int N, typename T> struct Mat
1865{
1866    inline Mat<N, T>() {}
1867
1868    Mat(T x)
1869    {
1870        for (int j = 0; j < N; j++)
1871            for (int i = 0; i < N; i++)
1872                if (i == j)
1873                    m[i][j] = x;
1874                else
1875                    m[i][j] = 0;
1876    }
1877
1878    /* Naive matrix inversion */
1879    Mat<N, T> inv() const
1880    {
1881        Mat a = *this, b((T)1);
1882
1883        /* Inversion method: iterate through all columns and make sure
1884         * all the terms are 1 on the diagonal and 0 everywhere else */
1885        for (int i = 0; i < N; i++)
1886        {
1887            /* If the expected coefficient is zero, add one of
1888             * the other lines. The first we meet will do. */
1889            if (!a.m[i][i])
1890            {
1891                for (int j = i + 1; j < N; j++)
1892                {
1893                    if (!a.m[i][j])
1894                        continue;
1895                    /* Add row j to row i */
1896                    for (int n = 0; n < N; n++)
1897                    {
1898                        a.m[n][i] += a.m[n][j];
1899                        b.m[n][i] += b.m[n][j];
1900                    }
1901                    break;
1902                }
1903            }
1904
1905            /* Now we know the diagonal term is non-zero. Get its inverse
1906             * and use that to nullify all other terms in the column */
1907            T x = (T)1 / a.m[i][i];
1908            for (int j = 0; j < N; j++)
1909            {
1910                if (j == i)
1911                    continue;
1912                T mul = x * a.m[i][j];
1913                for (int n = 0; n < N; n++)
1914                {
1915                    a.m[n][j] -= mul * a.m[n][i];
1916                    b.m[n][j] -= mul * b.m[n][i];
1917                }
1918            }
1919
1920            /* Finally, ensure the diagonal term is 1 */
1921            for (int n = 0; n < N; n++)
1922            {
1923                a.m[n][i] *= x;
1924                b.m[n][i] *= x;
1925            }
1926        }
1927
1928        return b;
1929    }
1930
1931    T m[N][N];
1932};
1933
1934} /* namespace lol */
1935
1936#endif // __LOL_MATH_VECTOR_H__
1937
Note: See TracBrowser for help on using the repository browser.