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

Last change on this file since 1158 was 1158, checked in by sam, 10 years ago

math: make sure magic swizzling vectors don't actually store data, and
do the swizzling by using their address rather than their members.

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