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

Last change on this file since 1315 was 1315, checked in by sam, 9 years ago

math: add methods to convert from a quaternion to Euler angles and from
Euler angles to a rotation matrix. Also fix quat::rotate() which was not
building the correct quaternion.

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