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

Last change on this file since 1401 was 1401, checked in by sam, 11 years ago

core: no longer deactivate std::ostream features on Android.

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