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

Last change on this file since 1149 was 1149, checked in by gary, 11 years ago

math: minor compilation fixes for Visual Studio. Still does not link.

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