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

Last change on this file since 2081 was 2081, checked in by sam, 7 years ago

math: prefix all convenience macros with "LOL_", make sure we #undef
them after use, and refactor them so that free functions such as
fmod() or clamp() are directly accessible in the lol namespace.

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