]> git.cworth.org Git - vogl/blob - src/voglcore/vogl_vec.h
Initial vogl checkin
[vogl] / src / voglcore / vogl_vec.h
1 /**************************************************************************
2  *
3  * Copyright 2013-2014 RAD Game Tools and Valve Software
4  * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  *
25  **************************************************************************/
26
27 // File: vogl_vec.h
28 #pragma once
29
30 #include "vogl_core.h"
31 #include "vogl_rand.h"
32
33 namespace vogl
34 {
35     template <uint N, typename T>
36     class vec : public helpers::rel_ops<vec<N, T> >
37     {
38     public:
39         typedef T scalar_type;
40         enum
41         {
42             num_elements = N
43         };
44
45         inline vec()
46         {
47         }
48
49         inline vec(eClear)
50         {
51             clear();
52         }
53
54         inline vec(const vec &other)
55         {
56             for (uint i = 0; i < N; i++)
57                 m_s[i] = other.m_s[i];
58         }
59
60         template <uint O, typename U>
61         inline vec(const vec<O, U> &other)
62         {
63             set(other);
64         }
65
66         template <uint O, typename U>
67         inline vec(const vec<O, U> &other, T w)
68         {
69             *this = other;
70             m_s[N - 1] = w;
71         }
72
73         explicit inline vec(T val)
74         {
75             set(val);
76         }
77
78         inline vec(T val0, T val1)
79         {
80             set(val0, val1);
81         }
82
83         inline vec(T val0, T val1, T val2)
84         {
85             set(val0, val1, val2);
86         }
87
88         inline vec(T val0, T val1, T val2, T val3)
89         {
90             set(val0, val1, val2, val3);
91         }
92
93         inline vec(
94             T val0, T val1, T val2, T val3,
95             T val4, T val5, T val6, T val7,
96             T val8, T val9, T val10, T val11,
97             T val12, T val13, T val14, T val15)
98         {
99             set(val0, val1, val2, val3,
100                 val4, val5, val6, val7,
101                 val8, val9, val10, val11,
102                 val12, val13, val14, val15);
103         }
104
105         inline vec(
106             T val0, T val1, T val2, T val3,
107             T val4, T val5, T val6, T val7,
108             T val8, T val9, T val10, T val11,
109             T val12, T val13, T val14, T val15,
110             T val16, T val17, T val18, T val19)
111         {
112             set(val0, val1, val2, val3,
113                 val4, val5, val6, val7,
114                 val8, val9, val10, val11,
115                 val12, val13, val14, val15,
116                 val16, val17, val18, val19);
117         }
118
119         inline vec(
120             T val0, T val1, T val2, T val3,
121             T val4, T val5, T val6, T val7,
122             T val8, T val9, T val10, T val11,
123             T val12, T val13, T val14, T val15,
124             T val16, T val17, T val18, T val19,
125             T val20, T val21, T val22, T val23,
126             T val24)
127         {
128             set(val0, val1, val2, val3,
129                 val4, val5, val6, val7,
130                 val8, val9, val10, val11,
131                 val12, val13, val14, val15,
132                 val16, val17, val18, val19,
133                 val20, val21, val22, val23,
134                 val24);
135         }
136
137         inline void clear()
138         {
139             if (N > 4)
140                 memset(m_s, 0, sizeof(m_s));
141             else
142             {
143                 for (uint i = 0; i < N; i++)
144                     m_s[i] = 0;
145             }
146         }
147
148         template <uint ON, typename OT>
149         inline vec &set(const vec<ON, OT> &other)
150         {
151             if ((void *)this == (void *)&other)
152                 return *this;
153             const uint m = math::minimum(N, ON);
154             uint i;
155             for (i = 0; i < m; i++)
156                 m_s[i] = static_cast<T>(other[i]);
157             for (; i < N; i++)
158                 m_s[i] = 0;
159             return *this;
160         }
161
162         inline vec &set_component(uint index, T val)
163         {
164             VOGL_ASSERT(index < N);
165             m_s[index] = val;
166             return *this;
167         }
168
169         inline vec &set(T val)
170         {
171             for (uint i = 0; i < N; i++)
172                 m_s[i] = val;
173             return *this;
174         }
175
176         inline vec &set(T val0, T val1)
177         {
178             m_s[0] = val0;
179             if (N >= 2)
180             {
181                 m_s[1] = val1;
182
183                 for (uint i = 2; i < N; i++)
184                     m_s[i] = 0;
185             }
186             return *this;
187         }
188
189         inline vec &set(T val0, T val1, T val2)
190         {
191             m_s[0] = val0;
192             if (N >= 2)
193             {
194                 m_s[1] = val1;
195
196                 if (N >= 3)
197                 {
198                     m_s[2] = val2;
199
200                     for (uint i = 3; i < N; i++)
201                         m_s[i] = 0;
202                 }
203             }
204             return *this;
205         }
206
207         inline vec &set(T val0, T val1, T val2, T val3)
208         {
209             m_s[0] = val0;
210             if (N >= 2)
211             {
212                 m_s[1] = val1;
213
214                 if (N >= 3)
215                 {
216                     m_s[2] = val2;
217
218                     if (N >= 4)
219                     {
220                         m_s[3] = val3;
221
222                         for (uint i = 4; i < N; i++)
223                             m_s[i] = 0;
224                     }
225                 }
226             }
227             return *this;
228         }
229
230         inline vec &set(
231             T val0, T val1, T val2, T val3,
232             T val4, T val5, T val6, T val7,
233             T val8, T val9, T val10, T val11,
234             T val12, T val13, T val14, T val15)
235         {
236             m_s[0] = val0;
237             if (N >= 2)
238                 m_s[1] = val1;
239             if (N >= 3)
240                 m_s[2] = val2;
241             if (N >= 4)
242                 m_s[3] = val3;
243
244             if (N >= 5)
245                 m_s[4] = val4;
246             if (N >= 6)
247                 m_s[5] = val5;
248             if (N >= 7)
249                 m_s[6] = val6;
250             if (N >= 8)
251                 m_s[7] = val7;
252
253             if (N >= 9)
254                 m_s[8] = val8;
255             if (N >= 10)
256                 m_s[9] = val9;
257             if (N >= 11)
258                 m_s[10] = val10;
259             if (N >= 12)
260                 m_s[11] = val11;
261
262             if (N >= 13)
263                 m_s[12] = val12;
264             if (N >= 14)
265                 m_s[13] = val13;
266             if (N >= 15)
267                 m_s[14] = val14;
268             if (N >= 16)
269                 m_s[15] = val15;
270
271             for (uint i = 16; i < N; i++)
272                 m_s[i] = 0;
273
274             return *this;
275         }
276
277         inline vec &set(
278             T val0, T val1, T val2, T val3,
279             T val4, T val5, T val6, T val7,
280             T val8, T val9, T val10, T val11,
281             T val12, T val13, T val14, T val15,
282             T val16, T val17, T val18, T val19)
283         {
284             m_s[0] = val0;
285             if (N >= 2)
286                 m_s[1] = val1;
287             if (N >= 3)
288                 m_s[2] = val2;
289             if (N >= 4)
290                 m_s[3] = val3;
291
292             if (N >= 5)
293                 m_s[4] = val4;
294             if (N >= 6)
295                 m_s[5] = val5;
296             if (N >= 7)
297                 m_s[6] = val6;
298             if (N >= 8)
299                 m_s[7] = val7;
300
301             if (N >= 9)
302                 m_s[8] = val8;
303             if (N >= 10)
304                 m_s[9] = val9;
305             if (N >= 11)
306                 m_s[10] = val10;
307             if (N >= 12)
308                 m_s[11] = val11;
309
310             if (N >= 13)
311                 m_s[12] = val12;
312             if (N >= 14)
313                 m_s[13] = val13;
314             if (N >= 15)
315                 m_s[14] = val14;
316             if (N >= 16)
317                 m_s[15] = val15;
318
319             if (N >= 17)
320                 m_s[16] = val16;
321             if (N >= 18)
322                 m_s[17] = val17;
323             if (N >= 19)
324                 m_s[18] = val18;
325             if (N >= 20)
326                 m_s[19] = val19;
327
328             for (uint i = 20; i < N; i++)
329                 m_s[i] = 0;
330
331             return *this;
332         }
333
334         inline vec &set(
335             T val0, T val1, T val2, T val3,
336             T val4, T val5, T val6, T val7,
337             T val8, T val9, T val10, T val11,
338             T val12, T val13, T val14, T val15,
339             T val16, T val17, T val18, T val19,
340             T val20, T val21, T val22, T val23,
341             T val24)
342         {
343             m_s[0] = val0;
344             if (N >= 2)
345                 m_s[1] = val1;
346             if (N >= 3)
347                 m_s[2] = val2;
348             if (N >= 4)
349                 m_s[3] = val3;
350
351             if (N >= 5)
352                 m_s[4] = val4;
353             if (N >= 6)
354                 m_s[5] = val5;
355             if (N >= 7)
356                 m_s[6] = val6;
357             if (N >= 8)
358                 m_s[7] = val7;
359
360             if (N >= 9)
361                 m_s[8] = val8;
362             if (N >= 10)
363                 m_s[9] = val9;
364             if (N >= 11)
365                 m_s[10] = val10;
366             if (N >= 12)
367                 m_s[11] = val11;
368
369             if (N >= 13)
370                 m_s[12] = val12;
371             if (N >= 14)
372                 m_s[13] = val13;
373             if (N >= 15)
374                 m_s[14] = val14;
375             if (N >= 16)
376                 m_s[15] = val15;
377
378             if (N >= 17)
379                 m_s[16] = val16;
380             if (N >= 18)
381                 m_s[17] = val17;
382             if (N >= 19)
383                 m_s[18] = val18;
384             if (N >= 20)
385                 m_s[19] = val19;
386
387             if (N >= 21)
388                 m_s[20] = val20;
389             if (N >= 22)
390                 m_s[21] = val21;
391             if (N >= 23)
392                 m_s[22] = val22;
393             if (N >= 24)
394                 m_s[23] = val23;
395
396             if (N >= 25)
397                 m_s[24] = val24;
398
399             for (uint i = 25; i < N; i++)
400                 m_s[i] = 0;
401
402             return *this;
403         }
404
405         inline vec &set(const T *pValues)
406         {
407             for (uint i = 0; i < N; i++)
408                 m_s[i] = pValues[i];
409             return *this;
410         }
411
412         template <uint ON, typename OT>
413         inline vec &swizzle_set(const vec<ON, OT> &other, uint i)
414         {
415             return set(static_cast<T>(other[i]));
416         }
417
418         template <uint ON, typename OT>
419         inline vec &swizzle_set(const vec<ON, OT> &other, uint i, uint j)
420         {
421             return set(static_cast<T>(other[i]), static_cast<T>(other[j]));
422         }
423
424         template <uint ON, typename OT>
425         inline vec &swizzle_set(const vec<ON, OT> &other, uint i, uint j, uint k)
426         {
427             return set(static_cast<T>(other[i]), static_cast<T>(other[j]), static_cast<T>(other[k]));
428         }
429
430         template <uint ON, typename OT>
431         inline vec &swizzle_set(const vec<ON, OT> &other, uint i, uint j, uint k, uint l)
432         {
433             return set(static_cast<T>(other[i]), static_cast<T>(other[j]), static_cast<T>(other[k]), static_cast<T>(other[l]));
434         }
435
436         inline vec &operator=(const vec &rhs)
437         {
438             if (this != &rhs)
439             {
440                 for (uint i = 0; i < N; i++)
441                     m_s[i] = rhs.m_s[i];
442             }
443             return *this;
444         }
445
446         template <uint O, typename U>
447         inline vec &operator=(const vec<O, U> &other)
448         {
449             if ((void *)this == (void *)&other)
450                 return *this;
451
452             uint s = math::minimum(N, O);
453
454             uint i;
455             for (i = 0; i < s; i++)
456                 m_s[i] = static_cast<T>(other[i]);
457
458             for (; i < N; i++)
459                 m_s[i] = 0;
460
461             return *this;
462         }
463
464         inline bool operator==(const vec &rhs) const
465         {
466             for (uint i = 0; i < N; i++)
467                 if (!(m_s[i] == rhs.m_s[i]))
468                     return false;
469             return true;
470         }
471
472         inline bool operator<(const vec &rhs) const
473         {
474             for (uint i = 0; i < N; i++)
475             {
476                 if (m_s[i] < rhs.m_s[i])
477                     return true;
478                 else if (!(m_s[i] == rhs.m_s[i]))
479                     return false;
480             }
481
482             return false;
483         }
484
485         inline T operator[](uint i) const
486         {
487             VOGL_ASSERT(i < N);
488             return m_s[i];
489         }
490
491         inline T &operator[](uint i)
492         {
493             VOGL_ASSERT(i < N);
494             return m_s[i];
495         }
496
497         template <uint index>
498         inline uint64_t get_component_as_uint() const
499         {
500             VOGL_ASSUME(index < N);
501             if (sizeof(T) == sizeof(float))
502                 return *reinterpret_cast<const uint32 *>(&m_s[index]);
503             else
504                 return *reinterpret_cast<const uint64_t *>(&m_s[index]);
505         }
506
507         inline T get_x(void) const
508         {
509             return m_s[0];
510         }
511         inline T get_y(void) const
512         {
513             VOGL_ASSUME(N >= 2);
514             return m_s[1];
515         }
516         inline T get_z(void) const
517         {
518             VOGL_ASSUME(N >= 3);
519             return m_s[2];
520         }
521         inline T get_w(void) const
522         {
523             VOGL_ASSUME(N >= 4);
524             return m_s[3];
525         }
526
527         inline vec get_x_vector() const
528         {
529             return broadcast<0>();
530         }
531         inline vec get_y_vector() const
532         {
533             return broadcast<1>();
534         }
535         inline vec get_z_vector() const
536         {
537             return broadcast<2>();
538         }
539         inline vec get_w_vector() const
540         {
541             return broadcast<3>();
542         }
543
544         inline T get_component(uint i) const
545         {
546             return (*this)[i];
547         }
548
549         inline vec &set_x(T v)
550         {
551             m_s[0] = v;
552             return *this;
553         }
554         inline vec &set_y(T v)
555         {
556             VOGL_ASSUME(N >= 2);
557             m_s[1] = v;
558             return *this;
559         }
560         inline vec &set_z(T v)
561         {
562             VOGL_ASSUME(N >= 3);
563             m_s[2] = v;
564             return *this;
565         }
566         inline vec &set_w(T v)
567         {
568             VOGL_ASSUME(N >= 4);
569             m_s[3] = v;
570             return *this;
571         }
572
573         inline const T *get_ptr() const
574         {
575             return reinterpret_cast<const T *>(&m_s[0]);
576         }
577         inline T *get_ptr()
578         {
579             return reinterpret_cast<T *>(&m_s[0]);
580         }
581
582         inline vec as_point() const
583         {
584             vec result(*this);
585             result[N - 1] = 1;
586             return result;
587         }
588
589         inline vec as_dir() const
590         {
591             vec result(*this);
592             result[N - 1] = 0;
593             return result;
594         }
595
596         inline vec<2, T> select2(uint i, uint j) const
597         {
598             VOGL_ASSERT((i < N) && (j < N));
599             return vec<2, T>(m_s[i], m_s[j]);
600         }
601
602         inline vec<3, T> select3(uint i, uint j, uint k) const
603         {
604             VOGL_ASSERT((i < N) && (j < N) && (k < N));
605             return vec<3, T>(m_s[i], m_s[j], m_s[k]);
606         }
607
608         inline vec<4, T> select4(uint i, uint j, uint k, uint l) const
609         {
610             VOGL_ASSERT((i < N) && (j < N) && (k < N) && (l < N));
611             return vec<4, T>(m_s[i], m_s[j], m_s[k], m_s[l]);
612         }
613
614         inline bool is_dir() const
615         {
616             return m_s[N - 1] == 0;
617         }
618         inline bool is_vector() const
619         {
620             return is_dir();
621         }
622         inline bool is_point() const
623         {
624             return m_s[N - 1] == 1;
625         }
626
627         inline vec project() const
628         {
629             vec result(*this);
630             if (result[N - 1])
631                 result /= result[N - 1];
632             return result;
633         }
634
635         inline vec broadcast(unsigned i) const
636         {
637             return vec((*this)[i]);
638         }
639
640         template <uint i>
641         inline vec broadcast() const
642         {
643             return vec((*this)[i]);
644         }
645
646         inline vec swizzle(uint i, uint j) const
647         {
648             return vec((*this)[i], (*this)[j]);
649         }
650
651         inline vec swizzle(uint i, uint j, uint k) const
652         {
653             return vec((*this)[i], (*this)[j], (*this)[k]);
654         }
655
656         inline vec swizzle(uint i, uint j, uint k, uint l) const
657         {
658             return vec((*this)[i], (*this)[j], (*this)[k], (*this)[l]);
659         }
660
661         inline vec operator-() const
662         {
663             vec result;
664             for (uint i = 0; i < N; i++)
665                 result.m_s[i] = -m_s[i];
666             return result;
667         }
668
669         inline vec operator+() const
670         {
671             return *this;
672         }
673
674         inline vec &operator+=(const vec &other)
675         {
676             for (uint i = 0; i < N; i++)
677                 m_s[i] += other.m_s[i];
678             return *this;
679         }
680
681         inline vec &operator-=(const vec &other)
682         {
683             for (uint i = 0; i < N; i++)
684                 m_s[i] -= other.m_s[i];
685             return *this;
686         }
687
688         inline vec &operator*=(const vec &other)
689         {
690             for (uint i = 0; i < N; i++)
691                 m_s[i] *= other.m_s[i];
692             return *this;
693         }
694
695         inline vec &operator/=(const vec &other)
696         {
697             for (uint i = 0; i < N; i++)
698                 m_s[i] /= other.m_s[i];
699             return *this;
700         }
701
702         inline vec &operator*=(T s)
703         {
704             for (uint i = 0; i < N; i++)
705                 m_s[i] *= s;
706             return *this;
707         }
708
709         inline vec &operator/=(T s)
710         {
711             for (uint i = 0; i < N; i++)
712                 m_s[i] /= s;
713             return *this;
714         }
715
716         // component-wise multiply (not a dot product like in previous versions)
717         friend inline vec operator*(const vec &lhs, const vec &rhs)
718         {
719             return vec::mul_components(lhs, rhs);
720         }
721
722         friend inline vec operator*(const vec &lhs, T val)
723         {
724             vec result;
725             for (uint i = 0; i < N; i++)
726                 result.m_s[i] = lhs.m_s[i] * val;
727             return result;
728         }
729
730         friend inline vec operator*(T val, const vec &rhs)
731         {
732             vec result;
733             for (uint i = 0; i < N; i++)
734                 result.m_s[i] = val * rhs.m_s[i];
735             return result;
736         }
737
738         friend inline vec operator/(const vec &lhs, const vec &rhs)
739         {
740             vec result;
741             for (uint i = 0; i < N; i++)
742                 result.m_s[i] = lhs.m_s[i] / rhs.m_s[i];
743             return result;
744         }
745
746         friend inline vec operator/(const vec &lhs, T val)
747         {
748             vec result;
749             for (uint i = 0; i < N; i++)
750                 result.m_s[i] = lhs.m_s[i] / val;
751             return result;
752         }
753
754         friend inline vec operator+(const vec &lhs, const vec &rhs)
755         {
756             vec result;
757             for (uint i = 0; i < N; i++)
758                 result.m_s[i] = lhs.m_s[i] + rhs.m_s[i];
759             return result;
760         }
761
762         friend inline vec operator-(const vec &lhs, const vec &rhs)
763         {
764             vec result;
765             for (uint i = 0; i < N; i++)
766                 result.m_s[i] = lhs.m_s[i] - rhs.m_s[i];
767             return result;
768         }
769
770         static inline vec<3, T> cross2(const vec &a, const vec &b)
771         {
772             VOGL_ASSUME(N >= 2);
773             return vec<3, T>(0, 0, a[0] * b[1] - a[1] * b[0]);
774         }
775
776         inline vec<3, T> cross2(const vec &b) const
777         {
778             return cross2(*this, b);
779         }
780
781         static inline vec<3, T> cross3(const vec &a, const vec &b)
782         {
783             VOGL_ASSUME(N >= 3);
784             return vec<3, T>(a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]);
785         }
786
787         inline vec<3, T> cross3(const vec &b) const
788         {
789             return cross3(*this, b);
790         }
791
792         static inline vec<3, T> cross(const vec &a, const vec &b)
793         {
794             VOGL_ASSUME(N >= 2);
795
796             if (N == 2)
797                 return cross2(a, b);
798             else
799                 return cross3(a, b);
800         }
801
802         inline vec<3, T> cross(const vec &b) const
803         {
804             VOGL_ASSUME(N >= 2);
805             return cross(*this, b);
806         }
807
808         inline T dot(const vec &rhs) const
809         {
810             return dot(*this, rhs);
811         }
812
813         inline vec dot_vector(const vec &rhs) const
814         {
815             return vec(dot(*this, rhs));
816         }
817
818         static inline T dot(const vec &lhs, const vec &rhs)
819         {
820             T result = lhs.m_s[0] * rhs.m_s[0];
821             for (uint i = 1; i < N; i++)
822                 result += lhs.m_s[i] * rhs.m_s[i];
823             return result;
824         }
825
826         inline T dot2(const vec &rhs) const
827         {
828             VOGL_ASSUME(N >= 2);
829             return m_s[0] * rhs.m_s[0] + m_s[1] * rhs.m_s[1];
830         }
831
832         inline T dot3(const vec &rhs) const
833         {
834             VOGL_ASSUME(N >= 3);
835             return m_s[0] * rhs.m_s[0] + m_s[1] * rhs.m_s[1] + m_s[2] * rhs.m_s[2];
836         }
837
838         inline T dot4(const vec &rhs) const
839         {
840             VOGL_ASSUME(N >= 4);
841             return m_s[0] * rhs.m_s[0] + m_s[1] * rhs.m_s[1] + m_s[2] * rhs.m_s[2] + m_s[3] * rhs.m_s[3];
842         }
843
844         inline T norm(void) const
845         {
846             T sum = m_s[0] * m_s[0];
847             for (uint i = 1; i < N; i++)
848                 sum += m_s[i] * m_s[i];
849             return sum;
850         }
851
852         inline T length(void) const
853         {
854             return sqrt(norm());
855         }
856
857         inline T squared_distance(const vec &rhs) const
858         {
859             T dist2 = 0;
860             for (uint i = 0; i < N; i++)
861             {
862                 T d = m_s[i] - rhs.m_s[i];
863                 dist2 += d * d;
864             }
865             return dist2;
866         }
867
868         inline T squared_distance(const vec &rhs, T early_out) const
869         {
870             T dist2 = 0;
871             for (uint i = 0; i < N; i++)
872             {
873                 T d = m_s[i] - rhs.m_s[i];
874                 dist2 += d * d;
875                 if (dist2 > early_out)
876                     break;
877             }
878             return dist2;
879         }
880
881         inline T distance(const vec &rhs) const
882         {
883             T dist2 = 0;
884             for (uint i = 0; i < N; i++)
885             {
886                 T d = m_s[i] - rhs.m_s[i];
887                 dist2 += d * d;
888             }
889             return sqrt(dist2);
890         }
891
892         inline vec inverse() const
893         {
894             vec result;
895             for (uint i = 0; i < N; i++)
896                 result[i] = m_s[i] ? (1.0f / m_s[i]) : 0;
897             return result;
898         }
899
900         // returns squared length (norm)
901         inline double normalize(const vec *pDefaultVec = NULL)
902         {
903             double n = m_s[0] * m_s[0];
904             for (uint i = 1; i < N; i++)
905                 n += m_s[i] * m_s[i];
906
907             if (n != 0)
908                 *this *= static_cast<T>(1.0f / sqrt(n));
909             else if (pDefaultVec)
910                 *this = *pDefaultVec;
911             return n;
912         }
913
914         inline double normalize3(const vec *pDefaultVec = NULL)
915         {
916             VOGL_ASSUME(N >= 3);
917
918             double n = m_s[0] * m_s[0] + m_s[1] * m_s[1] + m_s[2] * m_s[2];
919
920             if (n != 0)
921                 *this *= static_cast<T>((1.0f / sqrt(n)));
922             else if (pDefaultVec)
923                 *this = *pDefaultVec;
924             return n;
925         }
926
927         inline vec &normalize_in_place(const vec *pDefaultVec = NULL)
928         {
929             normalize(pDefaultVec);
930             return *this;
931         }
932
933         inline vec &normalize3_in_place(const vec *pDefaultVec = NULL)
934         {
935             normalize3(pDefaultVec);
936             return *this;
937         }
938
939         inline vec get_normalized(const vec *pDefaultVec = NULL) const
940         {
941             vec result(*this);
942             result.normalize(pDefaultVec);
943             return result;
944         }
945
946         inline vec get_normalized3(const vec *pDefaultVec = NULL) const
947         {
948             vec result(*this);
949             result.normalize3(pDefaultVec);
950             return result;
951         }
952
953         inline vec &clamp(T l, T h)
954         {
955             for (uint i = 0; i < N; i++)
956                 m_s[i] = static_cast<T>(math::clamp(m_s[i], l, h));
957             return *this;
958         }
959
960         inline vec &clamp(const vec &l, const vec &h)
961         {
962             for (uint i = 0; i < N; i++)
963                 m_s[i] = static_cast<T>(math::clamp(m_s[i], l[i], h[i]));
964             return *this;
965         }
966
967         inline bool is_within_bounds(const vec &l, const vec &h) const
968         {
969             for (uint i = 0; i < N; i++)
970                 if ((m_s[i] < l[i]) || (m_s[i] > h[i]))
971                     return false;
972
973             return true;
974         }
975
976         inline bool is_within_bounds(T l, T h) const
977         {
978             for (uint i = 0; i < N; i++)
979                 if ((m_s[i] < l) || (m_s[i] > h))
980                     return false;
981
982             return true;
983         }
984
985         inline uint get_major_axis(void) const
986         {
987             T m = fabs(m_s[0]);
988             uint r = 0;
989             for (uint i = 1; i < N; i++)
990             {
991                 const T c = fabs(m_s[i]);
992                 if (c > m)
993                 {
994                     m = c;
995                     r = i;
996                 }
997             }
998             return r;
999         }
1000
1001         inline uint get_minor_axis(void) const
1002         {
1003             T m = fabs(m_s[0]);
1004             uint r = 0;
1005             for (uint i = 1; i < N; i++)
1006             {
1007                 const T c = fabs(m_s[i]);
1008                 if (c < m)
1009                 {
1010                     m = c;
1011                     r = i;
1012                 }
1013             }
1014             return r;
1015         }
1016
1017         inline void get_projection_axes(uint &u, uint &v) const
1018         {
1019             const int axis = get_major_axis();
1020             if (m_s[axis] < 0.0f)
1021             {
1022                 v = math::next_wrap<uint>(axis, N);
1023                 u = math::next_wrap<uint>(v, N);
1024             }
1025             else
1026             {
1027                 u = math::next_wrap<uint>(axis, N);
1028                 v = math::next_wrap<uint>(u, N);
1029             }
1030         }
1031
1032         inline T get_absolute_minimum(void) const
1033         {
1034             T result = fabs(m_s[0]);
1035             for (uint i = 1; i < N; i++)
1036                 result = math::minimum(result, fabs(m_s[i]));
1037             return result;
1038         }
1039
1040         inline T get_absolute_maximum(void) const
1041         {
1042             T result = fabs(m_s[0]);
1043             for (uint i = 1; i < N; i++)
1044                 result = math::maximum(result, fabs(m_s[i]));
1045             return result;
1046         }
1047
1048         inline T get_minimum(void) const
1049         {
1050             T result = m_s[0];
1051             for (uint i = 1; i < N; i++)
1052                 result = math::minimum(result, m_s[i]);
1053             return result;
1054         }
1055
1056         inline T get_maximum(void) const
1057         {
1058             T result = m_s[0];
1059             for (uint i = 1; i < N; i++)
1060                 result = math::maximum(result, m_s[i]);
1061             return result;
1062         }
1063
1064         inline vec &remove_unit_direction(const vec &dir)
1065         {
1066             *this -= (dot(dir) * dir);
1067             return *this;
1068         }
1069
1070         inline vec get_remove_unit_direction(const vec &dir) const
1071         {
1072             return *this - (dot(dir) * dir);
1073         }
1074
1075         inline bool all_less(const vec &b) const
1076         {
1077             for (uint i = 0; i < N; i++)
1078                 if (m_s[i] >= b.m_s[i])
1079                     return false;
1080             return true;
1081         }
1082
1083         inline bool all_less_equal(const vec &b) const
1084         {
1085             for (uint i = 0; i < N; i++)
1086                 if (m_s[i] > b.m_s[i])
1087                     return false;
1088             return true;
1089         }
1090
1091         inline bool all_greater(const vec &b) const
1092         {
1093             for (uint i = 0; i < N; i++)
1094                 if (m_s[i] <= b.m_s[i])
1095                     return false;
1096             return true;
1097         }
1098
1099         inline bool all_greater_equal(const vec &b) const
1100         {
1101             for (uint i = 0; i < N; i++)
1102                 if (m_s[i] < b.m_s[i])
1103                     return false;
1104             return true;
1105         }
1106
1107         inline vec negate_xyz() const
1108         {
1109             vec ret;
1110
1111             ret[0] = -m_s[0];
1112             if (N >= 2)
1113                 ret[1] = -m_s[1];
1114             if (N >= 3)
1115                 ret[2] = -m_s[2];
1116
1117             for (uint i = 3; i < N; i++)
1118                 ret[i] = m_s[i];
1119
1120             return ret;
1121         }
1122
1123         inline vec &invert()
1124         {
1125             for (uint i = 0; i < N; i++)
1126                 if (m_s[i] != 0.0f)
1127                     m_s[i] = 1.0f / m_s[i];
1128             return *this;
1129         }
1130
1131         inline scalar_type perp_dot(const vec &b) const
1132         {
1133             VOGL_ASSUME(N == 2);
1134             return m_s[0] * b.m_s[1] - m_s[1] * b.m_s[0];
1135         }
1136
1137         inline vec perp() const
1138         {
1139             VOGL_ASSUME(N == 2);
1140             return vec(-m_s[1], m_s[0]);
1141         }
1142
1143         inline vec get_floor() const
1144         {
1145             vec result;
1146             for (uint i = 0; i < N; i++)
1147                 result[i] = floor(m_s[i]);
1148             return result;
1149         }
1150
1151         inline vec get_ceil() const
1152         {
1153             vec result;
1154             for (uint i = 0; i < N; i++)
1155                 result[i] = ceil(m_s[i]);
1156             return result;
1157         }
1158
1159         // static helper methods
1160
1161         static inline vec mul_components(const vec &lhs, const vec &rhs)
1162         {
1163             vec result;
1164             for (uint i = 0; i < N; i++)
1165                 result[i] = lhs.m_s[i] * rhs.m_s[i];
1166             return result;
1167         }
1168
1169         static inline vec mul_add_components(const vec &a, const vec &b, const vec &c)
1170         {
1171             vec result;
1172             for (uint i = 0; i < N; i++)
1173                 result[i] = a.m_s[i] * b.m_s[i] + c.m_s[i];
1174             return result;
1175         }
1176
1177         static inline vec make_axis(uint i)
1178         {
1179             vec result;
1180             result.clear();
1181             result[i] = 1;
1182             return result;
1183         }
1184
1185         static inline vec component_max(const vec &a, const vec &b)
1186         {
1187             vec ret;
1188             for (uint i = 0; i < N; i++)
1189                 ret.m_s[i] = math::maximum(a.m_s[i], b.m_s[i]);
1190             return ret;
1191         }
1192
1193         static inline vec component_min(const vec &a, const vec &b)
1194         {
1195             vec ret;
1196             for (uint i = 0; i < N; i++)
1197                 ret.m_s[i] = math::minimum(a.m_s[i], b.m_s[i]);
1198             return ret;
1199         }
1200
1201         static inline vec lerp(const vec &a, const vec &b, float t)
1202         {
1203             vec ret;
1204             for (uint i = 0; i < N; i++)
1205                 ret.m_s[i] = a.m_s[i] + (b.m_s[i] - a.m_s[i]) * t;
1206             return ret;
1207         }
1208
1209         static inline bool equal_tol(const vec &a, const vec &b, float t)
1210         {
1211             for (uint i = 0; i < N; i++)
1212                 if (!math::equal_tol(a.m_s[i], b.m_s[i], t))
1213                     return false;
1214             return true;
1215         }
1216
1217         inline bool equal_tol(const vec &b, float t) const
1218         {
1219             return equal_tol(*this, b, t);
1220         }
1221
1222         static inline vec make_random(random &r, float l, float h)
1223         {
1224             vec result;
1225             for (uint i = 0; i < N; i++)
1226                 result[i] = r.frand(l, h);
1227             return result;
1228         }
1229
1230         static inline vec make_random(fast_random &r, float l, float h)
1231         {
1232             vec result;
1233             for (uint i = 0; i < N; i++)
1234                 result[i] = r.frand(l, h);
1235             return result;
1236         }
1237
1238         static inline vec make_random(random &r, const vec &l, const vec &h)
1239         {
1240             vec result;
1241             for (uint i = 0; i < N; i++)
1242                 result[i] = r.frand(l[i], h[i]);
1243             return result;
1244         }
1245
1246         static inline vec make_random(fast_random &r, const vec &l, const vec &h)
1247         {
1248             vec result;
1249             for (uint i = 0; i < N; i++)
1250                 result[i] = r.frand(l[i], h[i]);
1251             return result;
1252         }
1253
1254     protected:
1255         T m_s[N];
1256     };
1257
1258     typedef vec<1, double> vec1D;
1259     typedef vec<2, double> vec2D;
1260     typedef vec<3, double> vec3D;
1261     typedef vec<4, double> vec4D;
1262
1263     typedef vec<1, float> vec1F;
1264
1265     typedef vec<2, float> vec2F;
1266     typedef vogl::vector<vec2F> vec2F_array;
1267
1268     typedef vec<3, float> vec3F;
1269     typedef vogl::vector<vec3F> vec3F_array;
1270
1271     typedef vec<4, float> vec4F;
1272     typedef vogl::vector<vec4F> vec4F_array;
1273
1274     typedef vec<2, uint> vec2U;
1275     typedef vec<2, int> vec2I;
1276     typedef vec<3, int> vec3I;
1277     typedef vec<4, int> vec4I;
1278
1279     typedef vec<2, int16> vec2I16;
1280     typedef vec<3, int16> vec3I16;
1281
1282     template <uint N, typename T>
1283     struct scalar_type<vec<N, T> >
1284     {
1285         enum
1286         {
1287             cFlag = true
1288         };
1289         static inline void construct(vec<N, T> *p)
1290         {
1291             VOGL_NOTE_UNUSED(p);
1292         }
1293         static inline void construct(vec<N, T> *p, const vec<N, T> &init)
1294         {
1295             memcpy(p, &init, sizeof(vec<N, T>));
1296         }
1297         static inline void construct_array(vec<N, T> *p, uint n)
1298         {
1299             VOGL_NOTE_UNUSED(p), VOGL_NOTE_UNUSED(n);
1300         }
1301         static inline void destruct(vec<N, T> *p)
1302         {
1303             VOGL_NOTE_UNUSED(p);
1304         }
1305         static inline void destruct_array(vec<N, T> *p, uint n)
1306         {
1307             VOGL_NOTE_UNUSED(p), VOGL_NOTE_UNUSED(n);
1308         }
1309     };
1310
1311 } // namespace vogl