1 ///////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
4 // Digital Ltd. LLC
5 //
6 // All rights reserved.
7 //
8 // Redistribution and use in source and binary forms, with or without
9 // modification, are permitted provided that the following conditions are
10 // met:
11 // *       Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 // *       Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
16 // distribution.
17 // *       Neither the name of Industrial Light & Magic nor the names of
18 // its contributors may be used to endorse or promote products derived
19 // from this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 //
33 ///////////////////////////////////////////////////////////////////////////
34 
35 
36 
37 #ifndef INCLUDED_IMATHVEC_H
38 #define INCLUDED_IMATHVEC_H
39 
40 //----------------------------------------------------
41 //
42 //	2D, 3D and 4D point/vector class templates
43 //
44 //----------------------------------------------------
45 
46 #include "ImathExc.h"
47 #include "ImathLimits.h"
48 #include "ImathMath.h"
49 
50 #include <iostream>
51 
52 #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
53 // suppress exception specification warnings
54 #pragma warning(push)
55 #pragma warning(disable:4290)
56 #endif
57 
58 
59 namespace Imath {
60 
61 template <class T> class Vec2;
62 template <class T> class Vec3;
63 template <class T> class Vec4;
64 
65 enum InfException {INF_EXCEPTION};
66 
67 
68 template <class T> class Vec2
69 {
70   public:
71 
72     //-------------------
73     // Access to elements
74     //-------------------
75 
76     T			x, y;
77 
78     T &			operator [] (int i);
79     const T &		operator [] (int i) const;
80 
81 
82     //-------------
83     // Constructors
84     //-------------
85 
86     Vec2 ();                        // no initialization
87     explicit Vec2 (T a);            // (a a)
88     Vec2 (T a, T b);                // (a b)
89 
90 
91     //---------------------------------
92     // Copy constructors and assignment
93     //---------------------------------
94 
95     Vec2 (const Vec2 &v);
96     template <class S> Vec2 (const Vec2<S> &v);
97 
98     const Vec2 &	operator = (const Vec2 &v);
99 
100 
101     //----------------------
102     // Compatibility with Sb
103     //----------------------
104 
105     template <class S>
106     void		setValue (S a, S b);
107 
108     template <class S>
109     void		setValue (const Vec2<S> &v);
110 
111     template <class S>
112     void		getValue (S &a, S &b) const;
113 
114     template <class S>
115     void		getValue (Vec2<S> &v) const;
116 
117     T *			getValue ();
118     const T *		getValue () const;
119 
120 
121     //---------
122     // Equality
123     //---------
124 
125     template <class S>
126     bool		operator == (const Vec2<S> &v) const;
127 
128     template <class S>
129     bool		operator != (const Vec2<S> &v) const;
130 
131 
132     //-----------------------------------------------------------------------
133     // Compare two vectors and test if they are "approximately equal":
134     //
135     // equalWithAbsError (v, e)
136     //
137     //	    Returns true if the coefficients of this and v are the same with
138     //	    an absolute error of no more than e, i.e., for all i
139     //
140     //      abs (this[i] - v[i]) <= e
141     //
142     // equalWithRelError (v, e)
143     //
144     //	    Returns true if the coefficients of this and v are the same with
145     //	    a relative error of no more than e, i.e., for all i
146     //
147     //      abs (this[i] - v[i]) <= e * abs (this[i])
148     //-----------------------------------------------------------------------
149 
150     bool		equalWithAbsError (const Vec2<T> &v, T e) const;
151     bool		equalWithRelError (const Vec2<T> &v, T e) const;
152 
153     //------------
154     // Dot product
155     //------------
156 
157     T			dot (const Vec2 &v) const;
158     T			operator ^ (const Vec2 &v) const;
159 
160 
161     //------------------------------------------------
162     // Right-handed cross product, i.e. z component of
163     // Vec3 (this->x, this->y, 0) % Vec3 (v.x, v.y, 0)
164     //------------------------------------------------
165 
166     T			cross (const Vec2 &v) const;
167     T			operator % (const Vec2 &v) const;
168 
169 
170     //------------------------
171     // Component-wise addition
172     //------------------------
173 
174     const Vec2 &	operator += (const Vec2 &v);
175     Vec2		operator + (const Vec2 &v) const;
176 
177 
178     //---------------------------
179     // Component-wise subtraction
180     //---------------------------
181 
182     const Vec2 &	operator -= (const Vec2 &v);
183     Vec2		operator - (const Vec2 &v) const;
184 
185 
186     //------------------------------------
187     // Component-wise multiplication by -1
188     //------------------------------------
189 
190     Vec2		operator - () const;
191     const Vec2 &	negate ();
192 
193 
194     //------------------------------
195     // Component-wise multiplication
196     //------------------------------
197 
198     const Vec2 &	operator *= (const Vec2 &v);
199     const Vec2 &	operator *= (T a);
200     Vec2		operator * (const Vec2 &v) const;
201     Vec2		operator * (T a) const;
202 
203 
204     //------------------------
205     // Component-wise division
206     //------------------------
207 
208     const Vec2 &	operator /= (const Vec2 &v);
209     const Vec2 &	operator /= (T a);
210     Vec2		operator / (const Vec2 &v) const;
211     Vec2		operator / (T a) const;
212 
213 
214     //----------------------------------------------------------------
215     // Length and normalization:  If v.length() is 0.0, v.normalize()
216     // and v.normalized() produce a null vector; v.normalizeExc() and
217     // v.normalizedExc() throw a NullVecExc.
218     // v.normalizeNonNull() and v.normalizedNonNull() are slightly
219     // faster than the other normalization routines, but if v.length()
220     // is 0.0, the result is undefined.
221     //----------------------------------------------------------------
222 
223     T			length () const;
224     T			length2 () const;
225 
226     const Vec2 &	normalize ();           // modifies *this
227     const Vec2 &	normalizeExc () throw (Iex::MathExc);
228     const Vec2 &	normalizeNonNull ();
229 
230     Vec2<T>		normalized () const;	// does not modify *this
231     Vec2<T>		normalizedExc () const throw (Iex::MathExc);
232     Vec2<T>		normalizedNonNull () const;
233 
234 
235     //--------------------------------------------------------
236     // Number of dimensions, i.e. number of elements in a Vec2
237     //--------------------------------------------------------
238 
dimensions()239     static unsigned int	dimensions() {return 2;}
240 
241 
242     //-------------------------------------------------
243     // Limitations of type T (see also class limits<T>)
244     //-------------------------------------------------
245 
baseTypeMin()246     static T		baseTypeMin()		{return limits<T>::min();}
baseTypeMax()247     static T		baseTypeMax()		{return limits<T>::max();}
baseTypeSmallest()248     static T		baseTypeSmallest()	{return limits<T>::smallest();}
baseTypeEpsilon()249     static T		baseTypeEpsilon()	{return limits<T>::epsilon();}
250 
251 
252     //--------------------------------------------------------------
253     // Base type -- in templates, which accept a parameter, V, which
254     // could be either a Vec2<T>, a Vec3<T>, or a Vec4<T> you can
255     // refer to T as V::BaseType
256     //--------------------------------------------------------------
257 
258     typedef T		BaseType;
259 
260   private:
261 
262     T			lengthTiny () const;
263 };
264 
265 
266 template <class T> class Vec3
267 {
268   public:
269 
270     //-------------------
271     // Access to elements
272     //-------------------
273 
274     T			x, y, z;
275 
276     T &			operator [] (int i);
277     const T &		operator [] (int i) const;
278 
279 
280     //-------------
281     // Constructors
282     //-------------
283 
284     Vec3 ();			   // no initialization
285     explicit Vec3 (T a);           // (a a a)
286     Vec3 (T a, T b, T c);	   // (a b c)
287 
288 
289     //---------------------------------
290     // Copy constructors and assignment
291     //---------------------------------
292 
293     Vec3 (const Vec3 &v);
294     template <class S> Vec3 (const Vec3<S> &v);
295 
296     const Vec3 &	operator = (const Vec3 &v);
297 
298 
299     //---------------------------------------------------------
300     // Vec4 to Vec3 conversion, divides x, y and z by w:
301     //
302     // The one-argument conversion function divides by w even
303     // if w is zero.  The result depends on how the environment
304     // handles floating-point exceptions.
305     //
306     // The two-argument version thows an InfPointExc exception
307     // if w is zero or if division by w would overflow.
308     //---------------------------------------------------------
309 
310     template <class S> explicit Vec3 (const Vec4<S> &v);
311     template <class S> explicit Vec3 (const Vec4<S> &v, InfException);
312 
313 
314     //----------------------
315     // Compatibility with Sb
316     //----------------------
317 
318     template <class S>
319     void		setValue (S a, S b, S c);
320 
321     template <class S>
322     void		setValue (const Vec3<S> &v);
323 
324     template <class S>
325     void		getValue (S &a, S &b, S &c) const;
326 
327     template <class S>
328     void		getValue (Vec3<S> &v) const;
329 
330     T *			getValue();
331     const T *		getValue() const;
332 
333 
334     //---------
335     // Equality
336     //---------
337 
338     template <class S>
339     bool		operator == (const Vec3<S> &v) const;
340 
341     template <class S>
342     bool		operator != (const Vec3<S> &v) const;
343 
344     //-----------------------------------------------------------------------
345     // Compare two vectors and test if they are "approximately equal":
346     //
347     // equalWithAbsError (v, e)
348     //
349     //	    Returns true if the coefficients of this and v are the same with
350     //	    an absolute error of no more than e, i.e., for all i
351     //
352     //      abs (this[i] - v[i]) <= e
353     //
354     // equalWithRelError (v, e)
355     //
356     //	    Returns true if the coefficients of this and v are the same with
357     //	    a relative error of no more than e, i.e., for all i
358     //
359     //      abs (this[i] - v[i]) <= e * abs (this[i])
360     //-----------------------------------------------------------------------
361 
362     bool		equalWithAbsError (const Vec3<T> &v, T e) const;
363     bool		equalWithRelError (const Vec3<T> &v, T e) const;
364 
365     //------------
366     // Dot product
367     //------------
368 
369     T			dot (const Vec3 &v) const;
370     T			operator ^ (const Vec3 &v) const;
371 
372 
373     //---------------------------
374     // Right-handed cross product
375     //---------------------------
376 
377     Vec3		cross (const Vec3 &v) const;
378     const Vec3 &	operator %= (const Vec3 &v);
379     Vec3		operator % (const Vec3 &v) const;
380 
381 
382     //------------------------
383     // Component-wise addition
384     //------------------------
385 
386     const Vec3 &	operator += (const Vec3 &v);
387     Vec3		operator + (const Vec3 &v) const;
388 
389 
390     //---------------------------
391     // Component-wise subtraction
392     //---------------------------
393 
394     const Vec3 &	operator -= (const Vec3 &v);
395     Vec3		operator - (const Vec3 &v) const;
396 
397 
398     //------------------------------------
399     // Component-wise multiplication by -1
400     //------------------------------------
401 
402     Vec3		operator - () const;
403     const Vec3 &	negate ();
404 
405 
406     //------------------------------
407     // Component-wise multiplication
408     //------------------------------
409 
410     const Vec3 &	operator *= (const Vec3 &v);
411     const Vec3 &	operator *= (T a);
412     Vec3		operator * (const Vec3 &v) const;
413     Vec3		operator * (T a) const;
414 
415 
416     //------------------------
417     // Component-wise division
418     //------------------------
419 
420     const Vec3 &	operator /= (const Vec3 &v);
421     const Vec3 &	operator /= (T a);
422     Vec3		operator / (const Vec3 &v) const;
423     Vec3		operator / (T a) const;
424 
425 
426     //----------------------------------------------------------------
427     // Length and normalization:  If v.length() is 0.0, v.normalize()
428     // and v.normalized() produce a null vector; v.normalizeExc() and
429     // v.normalizedExc() throw a NullVecExc.
430     // v.normalizeNonNull() and v.normalizedNonNull() are slightly
431     // faster than the other normalization routines, but if v.length()
432     // is 0.0, the result is undefined.
433     //----------------------------------------------------------------
434 
435     T			length () const;
436     T			length2 () const;
437 
438     const Vec3 &	normalize ();           // modifies *this
439     const Vec3 &	normalizeExc () throw (Iex::MathExc);
440     const Vec3 &	normalizeNonNull ();
441 
442     Vec3<T>		normalized () const;	// does not modify *this
443     Vec3<T>		normalizedExc () const throw (Iex::MathExc);
444     Vec3<T>		normalizedNonNull () const;
445 
446 
447     //--------------------------------------------------------
448     // Number of dimensions, i.e. number of elements in a Vec3
449     //--------------------------------------------------------
450 
dimensions()451     static unsigned int	dimensions() {return 3;}
452 
453 
454     //-------------------------------------------------
455     // Limitations of type T (see also class limits<T>)
456     //-------------------------------------------------
457 
baseTypeMin()458     static T		baseTypeMin()		{return limits<T>::min();}
baseTypeMax()459     static T		baseTypeMax()		{return limits<T>::max();}
baseTypeSmallest()460     static T		baseTypeSmallest()	{return limits<T>::smallest();}
baseTypeEpsilon()461     static T		baseTypeEpsilon()	{return limits<T>::epsilon();}
462 
463 
464     //--------------------------------------------------------------
465     // Base type -- in templates, which accept a parameter, V, which
466     // could be either a Vec2<T>, a Vec3<T>, or a Vec4<T> you can
467     // refer to T as V::BaseType
468     //--------------------------------------------------------------
469 
470     typedef T		BaseType;
471 
472   private:
473 
474     T			lengthTiny () const;
475 };
476 
477 
478 
479 template <class T> class Vec4
480 {
481   public:
482 
483     //-------------------
484     // Access to elements
485     //-------------------
486 
487     T               x, y, z, w;
488 
489     T &             operator [] (int i);
490     const T &       operator [] (int i) const;
491 
492 
493     //-------------
494     // Constructors
495     //-------------
496 
497     Vec4 ();			   // no initialization
498     explicit Vec4 (T a);           // (a a a a)
499     Vec4 (T a, T b, T c, T d);	   // (a b c d)
500 
501 
502     //---------------------------------
503     // Copy constructors and assignment
504     //---------------------------------
505 
506     Vec4 (const Vec4 &v);
507     template <class S> Vec4 (const Vec4<S> &v);
508 
509     const Vec4 &    operator = (const Vec4 &v);
510 
511 
512     //-------------------------------------
513     // Vec3 to Vec4 conversion, sets w to 1
514     //-------------------------------------
515 
516     template <class S> explicit Vec4 (const Vec3<S> &v);
517 
518 
519     //---------
520     // Equality
521     //---------
522 
523     template <class S>
524     bool            operator == (const Vec4<S> &v) const;
525 
526     template <class S>
527     bool            operator != (const Vec4<S> &v) const;
528 
529 
530     //-----------------------------------------------------------------------
531     // Compare two vectors and test if they are "approximately equal":
532     //
533     // equalWithAbsError (v, e)
534     //
535     //	    Returns true if the coefficients of this and v are the same with
536     //	    an absolute error of no more than e, i.e., for all i
537     //
538     //      abs (this[i] - v[i]) <= e
539     //
540     // equalWithRelError (v, e)
541     //
542     //	    Returns true if the coefficients of this and v are the same with
543     //	    a relative error of no more than e, i.e., for all i
544     //
545     //      abs (this[i] - v[i]) <= e * abs (this[i])
546     //-----------------------------------------------------------------------
547 
548     bool		equalWithAbsError (const Vec4<T> &v, T e) const;
549     bool		equalWithRelError (const Vec4<T> &v, T e) const;
550 
551 
552     //------------
553     // Dot product
554     //------------
555 
556     T			dot (const Vec4 &v) const;
557     T			operator ^ (const Vec4 &v) const;
558 
559 
560     //-----------------------------------
561     // Cross product is not defined in 4D
562     //-----------------------------------
563 
564     //------------------------
565     // Component-wise addition
566     //------------------------
567 
568     const Vec4 &    operator += (const Vec4 &v);
569     Vec4            operator + (const Vec4 &v) const;
570 
571 
572     //---------------------------
573     // Component-wise subtraction
574     //---------------------------
575 
576     const Vec4 &    operator -= (const Vec4 &v);
577     Vec4            operator - (const Vec4 &v) const;
578 
579 
580     //------------------------------------
581     // Component-wise multiplication by -1
582     //------------------------------------
583 
584     Vec4            operator - () const;
585     const Vec4 &    negate ();
586 
587 
588     //------------------------------
589     // Component-wise multiplication
590     //------------------------------
591 
592     const Vec4 &    operator *= (const Vec4 &v);
593     const Vec4 &    operator *= (T a);
594     Vec4            operator * (const Vec4 &v) const;
595     Vec4            operator * (T a) const;
596 
597 
598     //------------------------
599     // Component-wise division
600     //------------------------
601 
602     const Vec4 &    operator /= (const Vec4 &v);
603     const Vec4 &    operator /= (T a);
604     Vec4            operator / (const Vec4 &v) const;
605     Vec4            operator / (T a) const;
606 
607 
608     //----------------------------------------------------------------
609     // Length and normalization:  If v.length() is 0.0, v.normalize()
610     // and v.normalized() produce a null vector; v.normalizeExc() and
611     // v.normalizedExc() throw a NullVecExc.
612     // v.normalizeNonNull() and v.normalizedNonNull() are slightly
613     // faster than the other normalization routines, but if v.length()
614     // is 0.0, the result is undefined.
615     //----------------------------------------------------------------
616 
617     T               length () const;
618     T               length2 () const;
619 
620     const Vec4 &    normalize ();           // modifies *this
621     const Vec4 &    normalizeExc () throw (Iex::MathExc);
622     const Vec4 &    normalizeNonNull ();
623 
624     Vec4<T>         normalized () const;	// does not modify *this
625     Vec4<T>         normalizedExc () const throw (Iex::MathExc);
626     Vec4<T>         normalizedNonNull () const;
627 
628 
629     //--------------------------------------------------------
630     // Number of dimensions, i.e. number of elements in a Vec4
631     //--------------------------------------------------------
632 
dimensions()633     static unsigned int	dimensions() {return 4;}
634 
635 
636     //-------------------------------------------------
637     // Limitations of type T (see also class limits<T>)
638     //-------------------------------------------------
639 
baseTypeMin()640     static T		baseTypeMin()		{return limits<T>::min();}
baseTypeMax()641     static T		baseTypeMax()		{return limits<T>::max();}
baseTypeSmallest()642     static T		baseTypeSmallest()	{return limits<T>::smallest();}
baseTypeEpsilon()643     static T		baseTypeEpsilon()	{return limits<T>::epsilon();}
644 
645 
646     //--------------------------------------------------------------
647     // Base type -- in templates, which accept a parameter, V, which
648     // could be either a Vec2<T>, a Vec3<T>, or a Vec4<T> you can
649     // refer to T as V::BaseType
650     //--------------------------------------------------------------
651 
652     typedef T		BaseType;
653 
654   private:
655 
656     T			lengthTiny () const;
657 };
658 
659 
660 //--------------
661 // Stream output
662 //--------------
663 
664 template <class T>
665 std::ostream &	operator << (std::ostream &s, const Vec2<T> &v);
666 
667 template <class T>
668 std::ostream &	operator << (std::ostream &s, const Vec3<T> &v);
669 
670 template <class T>
671 std::ostream &	operator << (std::ostream &s, const Vec4<T> &v);
672 
673 //----------------------------------------------------
674 // Reverse multiplication: S * Vec2<T> and S * Vec3<T>
675 //----------------------------------------------------
676 
677 template <class T> Vec2<T>	operator * (T a, const Vec2<T> &v);
678 template <class T> Vec3<T>	operator * (T a, const Vec3<T> &v);
679 template <class T> Vec4<T>	operator * (T a, const Vec4<T> &v);
680 
681 
682 //-------------------------
683 // Typedefs for convenience
684 //-------------------------
685 
686 typedef Vec2 <short>  V2s;
687 typedef Vec2 <int>    V2i;
688 typedef Vec2 <float>  V2f;
689 typedef Vec2 <double> V2d;
690 typedef Vec3 <short>  V3s;
691 typedef Vec3 <int>    V3i;
692 typedef Vec3 <float>  V3f;
693 typedef Vec3 <double> V3d;
694 typedef Vec4 <short>  V4s;
695 typedef Vec4 <int>    V4i;
696 typedef Vec4 <float>  V4f;
697 typedef Vec4 <double> V4d;
698 
699 
700 //-------------------------------------------
701 // Specializations for VecN<short>, VecN<int>
702 //-------------------------------------------
703 
704 // Vec2<short>
705 
706 template <> short
707 Vec2<short>::length () const;
708 
709 template <> const Vec2<short> &
710 Vec2<short>::normalize ();
711 
712 template <> const Vec2<short> &
713 Vec2<short>::normalizeExc () throw (Iex::MathExc);
714 
715 template <> const Vec2<short> &
716 Vec2<short>::normalizeNonNull ();
717 
718 template <> Vec2<short>
719 Vec2<short>::normalized () const;
720 
721 template <> Vec2<short>
722 Vec2<short>::normalizedExc () const throw (Iex::MathExc);
723 
724 template <> Vec2<short>
725 Vec2<short>::normalizedNonNull () const;
726 
727 
728 // Vec2<int>
729 
730 template <> int
731 Vec2<int>::length () const;
732 
733 template <> const Vec2<int> &
734 Vec2<int>::normalize ();
735 
736 template <> const Vec2<int> &
737 Vec2<int>::normalizeExc () throw (Iex::MathExc);
738 
739 template <> const Vec2<int> &
740 Vec2<int>::normalizeNonNull ();
741 
742 template <> Vec2<int>
743 Vec2<int>::normalized () const;
744 
745 template <> Vec2<int>
746 Vec2<int>::normalizedExc () const throw (Iex::MathExc);
747 
748 template <> Vec2<int>
749 Vec2<int>::normalizedNonNull () const;
750 
751 
752 // Vec3<short>
753 
754 template <> short
755 Vec3<short>::length () const;
756 
757 template <> const Vec3<short> &
758 Vec3<short>::normalize ();
759 
760 template <> const Vec3<short> &
761 Vec3<short>::normalizeExc () throw (Iex::MathExc);
762 
763 template <> const Vec3<short> &
764 Vec3<short>::normalizeNonNull ();
765 
766 template <> Vec3<short>
767 Vec3<short>::normalized () const;
768 
769 template <> Vec3<short>
770 Vec3<short>::normalizedExc () const throw (Iex::MathExc);
771 
772 template <> Vec3<short>
773 Vec3<short>::normalizedNonNull () const;
774 
775 
776 // Vec3<int>
777 
778 template <> int
779 Vec3<int>::length () const;
780 
781 template <> const Vec3<int> &
782 Vec3<int>::normalize ();
783 
784 template <> const Vec3<int> &
785 Vec3<int>::normalizeExc () throw (Iex::MathExc);
786 
787 template <> const Vec3<int> &
788 Vec3<int>::normalizeNonNull ();
789 
790 template <> Vec3<int>
791 Vec3<int>::normalized () const;
792 
793 template <> Vec3<int>
794 Vec3<int>::normalizedExc () const throw (Iex::MathExc);
795 
796 template <> Vec3<int>
797 Vec3<int>::normalizedNonNull () const;
798 
799 // Vec4<short>
800 
801 template <> short
802 Vec4<short>::length () const;
803 
804 template <> const Vec4<short> &
805 Vec4<short>::normalize ();
806 
807 template <> const Vec4<short> &
808 Vec4<short>::normalizeExc () throw (Iex::MathExc);
809 
810 template <> const Vec4<short> &
811 Vec4<short>::normalizeNonNull ();
812 
813 template <> Vec4<short>
814 Vec4<short>::normalized () const;
815 
816 template <> Vec4<short>
817 Vec4<short>::normalizedExc () const throw (Iex::MathExc);
818 
819 template <> Vec4<short>
820 Vec4<short>::normalizedNonNull () const;
821 
822 
823 // Vec4<int>
824 
825 template <> int
826 Vec4<int>::length () const;
827 
828 template <> const Vec4<int> &
829 Vec4<int>::normalize ();
830 
831 template <> const Vec4<int> &
832 Vec4<int>::normalizeExc () throw (Iex::MathExc);
833 
834 template <> const Vec4<int> &
835 Vec4<int>::normalizeNonNull ();
836 
837 template <> Vec4<int>
838 Vec4<int>::normalized () const;
839 
840 template <> Vec4<int>
841 Vec4<int>::normalizedExc () const throw (Iex::MathExc);
842 
843 template <> Vec4<int>
844 Vec4<int>::normalizedNonNull () const;
845 
846 
847 //------------------------
848 // Implementation of Vec2:
849 //------------------------
850 
851 template <class T>
852 inline T &
853 Vec2<T>::operator [] (int i)
854 {
855     return (&x)[i];
856 }
857 
858 template <class T>
859 inline const T &
860 Vec2<T>::operator [] (int i) const
861 {
862     return (&x)[i];
863 }
864 
865 template <class T>
866 inline
Vec2()867 Vec2<T>::Vec2 ()
868 {
869     // empty
870 }
871 
872 template <class T>
873 inline
Vec2(T a)874 Vec2<T>::Vec2 (T a)
875 {
876     x = y = a;
877 }
878 
879 template <class T>
880 inline
Vec2(T a,T b)881 Vec2<T>::Vec2 (T a, T b)
882 {
883     x = a;
884     y = b;
885 }
886 
887 template <class T>
888 inline
Vec2(const Vec2 & v)889 Vec2<T>::Vec2 (const Vec2 &v)
890 {
891     x = v.x;
892     y = v.y;
893 }
894 
895 template <class T>
896 template <class S>
897 inline
Vec2(const Vec2<S> & v)898 Vec2<T>::Vec2 (const Vec2<S> &v)
899 {
900     x = T (v.x);
901     y = T (v.y);
902 }
903 
904 template <class T>
905 inline const Vec2<T> &
906 Vec2<T>::operator = (const Vec2 &v)
907 {
908     x = v.x;
909     y = v.y;
910     return *this;
911 }
912 
913 template <class T>
914 template <class S>
915 inline void
setValue(S a,S b)916 Vec2<T>::setValue (S a, S b)
917 {
918     x = T (a);
919     y = T (b);
920 }
921 
922 template <class T>
923 template <class S>
924 inline void
setValue(const Vec2<S> & v)925 Vec2<T>::setValue (const Vec2<S> &v)
926 {
927     x = T (v.x);
928     y = T (v.y);
929 }
930 
931 template <class T>
932 template <class S>
933 inline void
getValue(S & a,S & b)934 Vec2<T>::getValue (S &a, S &b) const
935 {
936     a = S (x);
937     b = S (y);
938 }
939 
940 template <class T>
941 template <class S>
942 inline void
getValue(Vec2<S> & v)943 Vec2<T>::getValue (Vec2<S> &v) const
944 {
945     v.x = S (x);
946     v.y = S (y);
947 }
948 
949 template <class T>
950 inline T *
getValue()951 Vec2<T>::getValue()
952 {
953     return (T *) &x;
954 }
955 
956 template <class T>
957 inline const T *
getValue()958 Vec2<T>::getValue() const
959 {
960     return (const T *) &x;
961 }
962 
963 template <class T>
964 template <class S>
965 inline bool
966 Vec2<T>::operator == (const Vec2<S> &v) const
967 {
968     return x == v.x && y == v.y;
969 }
970 
971 template <class T>
972 template <class S>
973 inline bool
974 Vec2<T>::operator != (const Vec2<S> &v) const
975 {
976     return x != v.x || y != v.y;
977 }
978 
979 template <class T>
980 bool
equalWithAbsError(const Vec2<T> & v,T e)981 Vec2<T>::equalWithAbsError (const Vec2<T> &v, T e) const
982 {
983     for (int i = 0; i < 2; i++)
984     if (!Imath::equalWithAbsError ((*this)[i], v[i], e))
985         return false;
986 
987     return true;
988 }
989 
990 template <class T>
991 bool
equalWithRelError(const Vec2<T> & v,T e)992 Vec2<T>::equalWithRelError (const Vec2<T> &v, T e) const
993 {
994     for (int i = 0; i < 2; i++)
995     if (!Imath::equalWithRelError ((*this)[i], v[i], e))
996         return false;
997 
998     return true;
999 }
1000 
1001 template <class T>
1002 inline T
dot(const Vec2 & v)1003 Vec2<T>::dot (const Vec2 &v) const
1004 {
1005     return x * v.x + y * v.y;
1006 }
1007 
1008 template <class T>
1009 inline T
1010 Vec2<T>::operator ^ (const Vec2 &v) const
1011 {
1012     return dot (v);
1013 }
1014 
1015 template <class T>
1016 inline T
cross(const Vec2 & v)1017 Vec2<T>::cross (const Vec2 &v) const
1018 {
1019     return x * v.y - y * v.x;
1020 
1021 }
1022 
1023 template <class T>
1024 inline T
1025 Vec2<T>::operator % (const Vec2 &v) const
1026 {
1027     return x * v.y - y * v.x;
1028 }
1029 
1030 template <class T>
1031 inline const Vec2<T> &
1032 Vec2<T>::operator += (const Vec2 &v)
1033 {
1034     x += v.x;
1035     y += v.y;
1036     return *this;
1037 }
1038 
1039 template <class T>
1040 inline Vec2<T>
1041 Vec2<T>::operator + (const Vec2 &v) const
1042 {
1043     return Vec2 (x + v.x, y + v.y);
1044 }
1045 
1046 template <class T>
1047 inline const Vec2<T> &
1048 Vec2<T>::operator -= (const Vec2 &v)
1049 {
1050     x -= v.x;
1051     y -= v.y;
1052     return *this;
1053 }
1054 
1055 template <class T>
1056 inline Vec2<T>
1057 Vec2<T>::operator - (const Vec2 &v) const
1058 {
1059     return Vec2 (x - v.x, y - v.y);
1060 }
1061 
1062 template <class T>
1063 inline Vec2<T>
1064 Vec2<T>::operator - () const
1065 {
1066     return Vec2 (-x, -y);
1067 }
1068 
1069 template <class T>
1070 inline const Vec2<T> &
negate()1071 Vec2<T>::negate ()
1072 {
1073     x = -x;
1074     y = -y;
1075     return *this;
1076 }
1077 
1078 template <class T>
1079 inline const Vec2<T> &
1080 Vec2<T>::operator *= (const Vec2 &v)
1081 {
1082     x *= v.x;
1083     y *= v.y;
1084     return *this;
1085 }
1086 
1087 template <class T>
1088 inline const Vec2<T> &
1089 Vec2<T>::operator *= (T a)
1090 {
1091     x *= a;
1092     y *= a;
1093     return *this;
1094 }
1095 
1096 template <class T>
1097 inline Vec2<T>
1098 Vec2<T>::operator * (const Vec2 &v) const
1099 {
1100     return Vec2 (x * v.x, y * v.y);
1101 }
1102 
1103 template <class T>
1104 inline Vec2<T>
1105 Vec2<T>::operator * (T a) const
1106 {
1107     return Vec2 (x * a, y * a);
1108 }
1109 
1110 template <class T>
1111 inline const Vec2<T> &
1112 Vec2<T>::operator /= (const Vec2 &v)
1113 {
1114     x /= v.x;
1115     y /= v.y;
1116     return *this;
1117 }
1118 
1119 template <class T>
1120 inline const Vec2<T> &
1121 Vec2<T>::operator /= (T a)
1122 {
1123     x /= a;
1124     y /= a;
1125     return *this;
1126 }
1127 
1128 template <class T>
1129 inline Vec2<T>
1130 Vec2<T>::operator / (const Vec2 &v) const
1131 {
1132     return Vec2 (x / v.x, y / v.y);
1133 }
1134 
1135 template <class T>
1136 inline Vec2<T>
1137 Vec2<T>::operator / (T a) const
1138 {
1139     return Vec2 (x / a, y / a);
1140 }
1141 
1142 template <class T>
1143 T
lengthTiny()1144 Vec2<T>::lengthTiny () const
1145 {
1146     T absX = (x >= T (0))? x: -x;
1147     T absY = (y >= T (0))? y: -y;
1148 
1149     T max = absX;
1150 
1151     if (max < absY)
1152     max = absY;
1153 
1154     if (max == T (0))
1155     return T (0);
1156 
1157     //
1158     // Do not replace the divisions by max with multiplications by 1/max.
1159     // Computing 1/max can overflow but the divisions below will always
1160     // produce results less than or equal to 1.
1161     //
1162 
1163     absX /= max;
1164     absY /= max;
1165 
1166     return max * Math<T>::sqrt (absX * absX + absY * absY);
1167 }
1168 
1169 template <class T>
1170 inline T
length()1171 Vec2<T>::length () const
1172 {
1173     T length2 = dot (*this);
1174 
1175     if (length2 < T (2) * limits<T>::smallest())
1176     return lengthTiny();
1177 
1178     return Math<T>::sqrt (length2);
1179 }
1180 
1181 template <class T>
1182 inline T
length2()1183 Vec2<T>::length2 () const
1184 {
1185     return dot (*this);
1186 }
1187 
1188 template <class T>
1189 const Vec2<T> &
normalize()1190 Vec2<T>::normalize ()
1191 {
1192     T l = length();
1193 
1194     if (l != T (0))
1195     {
1196         //
1197         // Do not replace the divisions by l with multiplications by 1/l.
1198         // Computing 1/l can overflow but the divisions below will always
1199         // produce results less than or equal to 1.
1200         //
1201 
1202     x /= l;
1203     y /= l;
1204     }
1205 
1206     return *this;
1207 }
1208 
1209 template <class T>
1210 const Vec2<T> &
normalizeExc()1211 Vec2<T>::normalizeExc () throw (Iex::MathExc)
1212 {
1213     T l = length();
1214 
1215     if (l == T (0))
1216     throw NullVecExc ("Cannot normalize null vector.");
1217 
1218     x /= l;
1219     y /= l;
1220     return *this;
1221 }
1222 
1223 template <class T>
1224 inline
1225 const Vec2<T> &
normalizeNonNull()1226 Vec2<T>::normalizeNonNull ()
1227 {
1228     T l = length();
1229     x /= l;
1230     y /= l;
1231     return *this;
1232 }
1233 
1234 template <class T>
1235 Vec2<T>
normalized()1236 Vec2<T>::normalized () const
1237 {
1238     T l = length();
1239 
1240     if (l == T (0))
1241     return Vec2 (T (0));
1242 
1243     return Vec2 (x / l, y / l);
1244 }
1245 
1246 template <class T>
1247 Vec2<T>
normalizedExc()1248 Vec2<T>::normalizedExc () const throw (Iex::MathExc)
1249 {
1250     T l = length();
1251 
1252     if (l == T (0))
1253     throw NullVecExc ("Cannot normalize null vector.");
1254 
1255     return Vec2 (x / l, y / l);
1256 }
1257 
1258 template <class T>
1259 inline
1260 Vec2<T>
normalizedNonNull()1261 Vec2<T>::normalizedNonNull () const
1262 {
1263     T l = length();
1264     return Vec2 (x / l, y / l);
1265 }
1266 
1267 
1268 //-----------------------
1269 // Implementation of Vec3
1270 //-----------------------
1271 
1272 template <class T>
1273 inline T &
1274 Vec3<T>::operator [] (int i)
1275 {
1276     return (&x)[i];
1277 }
1278 
1279 template <class T>
1280 inline const T &
1281 Vec3<T>::operator [] (int i) const
1282 {
1283     return (&x)[i];
1284 }
1285 
1286 template <class T>
1287 inline
Vec3()1288 Vec3<T>::Vec3 ()
1289 {
1290     // empty
1291 }
1292 
1293 template <class T>
1294 inline
Vec3(T a)1295 Vec3<T>::Vec3 (T a)
1296 {
1297     x = y = z = a;
1298 }
1299 
1300 template <class T>
1301 inline
Vec3(T a,T b,T c)1302 Vec3<T>::Vec3 (T a, T b, T c)
1303 {
1304     x = a;
1305     y = b;
1306     z = c;
1307 }
1308 
1309 template <class T>
1310 inline
Vec3(const Vec3 & v)1311 Vec3<T>::Vec3 (const Vec3 &v)
1312 {
1313     x = v.x;
1314     y = v.y;
1315     z = v.z;
1316 }
1317 
1318 template <class T>
1319 template <class S>
1320 inline
Vec3(const Vec3<S> & v)1321 Vec3<T>::Vec3 (const Vec3<S> &v)
1322 {
1323     x = T (v.x);
1324     y = T (v.y);
1325     z = T (v.z);
1326 }
1327 
1328 template <class T>
1329 inline const Vec3<T> &
1330 Vec3<T>::operator = (const Vec3 &v)
1331 {
1332     x = v.x;
1333     y = v.y;
1334     z = v.z;
1335     return *this;
1336 }
1337 
1338 template <class T>
1339 template <class S>
1340 inline
Vec3(const Vec4<S> & v)1341 Vec3<T>::Vec3 (const Vec4<S> &v)
1342 {
1343     x = T (v.x / v.w);
1344     y = T (v.y / v.w);
1345     z = T (v.z / v.w);
1346 }
1347 
1348 template <class T>
1349 template <class S>
Vec3(const Vec4<S> & v,InfException)1350 Vec3<T>::Vec3 (const Vec4<S> &v, InfException)
1351 {
1352     T vx = T (v.x);
1353     T vy = T (v.y);
1354     T vz = T (v.z);
1355     T vw = T (v.w);
1356 
1357     T absW = (vw >= T (0))? vw: -vw;
1358 
1359     if (absW < 1)
1360     {
1361         T m = baseTypeMax() * absW;
1362 
1363         if (vx <= -m || vx >= m || vy <= -m || vy >= m || vz <= -m || vz >= m)
1364             throw InfPointExc ("Cannot normalize point at infinity.");
1365     }
1366 
1367     x = vx / vw;
1368     y = vy / vw;
1369     z = vz / vw;
1370 }
1371 
1372 template <class T>
1373 template <class S>
1374 inline void
setValue(S a,S b,S c)1375 Vec3<T>::setValue (S a, S b, S c)
1376 {
1377     x = T (a);
1378     y = T (b);
1379     z = T (c);
1380 }
1381 
1382 template <class T>
1383 template <class S>
1384 inline void
setValue(const Vec3<S> & v)1385 Vec3<T>::setValue (const Vec3<S> &v)
1386 {
1387     x = T (v.x);
1388     y = T (v.y);
1389     z = T (v.z);
1390 }
1391 
1392 template <class T>
1393 template <class S>
1394 inline void
getValue(S & a,S & b,S & c)1395 Vec3<T>::getValue (S &a, S &b, S &c) const
1396 {
1397     a = S (x);
1398     b = S (y);
1399     c = S (z);
1400 }
1401 
1402 template <class T>
1403 template <class S>
1404 inline void
getValue(Vec3<S> & v)1405 Vec3<T>::getValue (Vec3<S> &v) const
1406 {
1407     v.x = S (x);
1408     v.y = S (y);
1409     v.z = S (z);
1410 }
1411 
1412 template <class T>
1413 inline T *
getValue()1414 Vec3<T>::getValue()
1415 {
1416     return (T *) &x;
1417 }
1418 
1419 template <class T>
1420 inline const T *
getValue()1421 Vec3<T>::getValue() const
1422 {
1423     return (const T *) &x;
1424 }
1425 
1426 template <class T>
1427 template <class S>
1428 inline bool
1429 Vec3<T>::operator == (const Vec3<S> &v) const
1430 {
1431     return x == v.x && y == v.y && z == v.z;
1432 }
1433 
1434 template <class T>
1435 template <class S>
1436 inline bool
1437 Vec3<T>::operator != (const Vec3<S> &v) const
1438 {
1439     return x != v.x || y != v.y || z != v.z;
1440 }
1441 
1442 template <class T>
1443 bool
equalWithAbsError(const Vec3<T> & v,T e)1444 Vec3<T>::equalWithAbsError (const Vec3<T> &v, T e) const
1445 {
1446     for (int i = 0; i < 3; i++)
1447     if (!Imath::equalWithAbsError ((*this)[i], v[i], e))
1448         return false;
1449 
1450     return true;
1451 }
1452 
1453 template <class T>
1454 bool
equalWithRelError(const Vec3<T> & v,T e)1455 Vec3<T>::equalWithRelError (const Vec3<T> &v, T e) const
1456 {
1457     for (int i = 0; i < 3; i++)
1458     if (!Imath::equalWithRelError ((*this)[i], v[i], e))
1459         return false;
1460 
1461     return true;
1462 }
1463 
1464 template <class T>
1465 inline T
dot(const Vec3 & v)1466 Vec3<T>::dot (const Vec3 &v) const
1467 {
1468     return x * v.x + y * v.y + z * v.z;
1469 }
1470 
1471 template <class T>
1472 inline T
1473 Vec3<T>::operator ^ (const Vec3 &v) const
1474 {
1475     return dot (v);
1476 }
1477 
1478 template <class T>
1479 inline Vec3<T>
cross(const Vec3 & v)1480 Vec3<T>::cross (const Vec3 &v) const
1481 {
1482     return Vec3 (y * v.z - z * v.y,
1483          z * v.x - x * v.z,
1484          x * v.y - y * v.x);
1485 }
1486 
1487 template <class T>
1488 inline const Vec3<T> &
1489 Vec3<T>::operator %= (const Vec3 &v)
1490 {
1491     T a = y * v.z - z * v.y;
1492     T b = z * v.x - x * v.z;
1493     T c = x * v.y - y * v.x;
1494     x = a;
1495     y = b;
1496     z = c;
1497     return *this;
1498 }
1499 
1500 template <class T>
1501 inline Vec3<T>
1502 Vec3<T>::operator % (const Vec3 &v) const
1503 {
1504     return Vec3 (y * v.z - z * v.y,
1505          z * v.x - x * v.z,
1506          x * v.y - y * v.x);
1507 }
1508 
1509 template <class T>
1510 inline const Vec3<T> &
1511 Vec3<T>::operator += (const Vec3 &v)
1512 {
1513     x += v.x;
1514     y += v.y;
1515     z += v.z;
1516     return *this;
1517 }
1518 
1519 template <class T>
1520 inline Vec3<T>
1521 Vec3<T>::operator + (const Vec3 &v) const
1522 {
1523     return Vec3 (x + v.x, y + v.y, z + v.z);
1524 }
1525 
1526 template <class T>
1527 inline const Vec3<T> &
1528 Vec3<T>::operator -= (const Vec3 &v)
1529 {
1530     x -= v.x;
1531     y -= v.y;
1532     z -= v.z;
1533     return *this;
1534 }
1535 
1536 template <class T>
1537 inline Vec3<T>
1538 Vec3<T>::operator - (const Vec3 &v) const
1539 {
1540     return Vec3 (x - v.x, y - v.y, z - v.z);
1541 }
1542 
1543 template <class T>
1544 inline Vec3<T>
1545 Vec3<T>::operator - () const
1546 {
1547     return Vec3 (-x, -y, -z);
1548 }
1549 
1550 template <class T>
1551 inline const Vec3<T> &
negate()1552 Vec3<T>::negate ()
1553 {
1554     x = -x;
1555     y = -y;
1556     z = -z;
1557     return *this;
1558 }
1559 
1560 template <class T>
1561 inline const Vec3<T> &
1562 Vec3<T>::operator *= (const Vec3 &v)
1563 {
1564     x *= v.x;
1565     y *= v.y;
1566     z *= v.z;
1567     return *this;
1568 }
1569 
1570 template <class T>
1571 inline const Vec3<T> &
1572 Vec3<T>::operator *= (T a)
1573 {
1574     x *= a;
1575     y *= a;
1576     z *= a;
1577     return *this;
1578 }
1579 
1580 template <class T>
1581 inline Vec3<T>
1582 Vec3<T>::operator * (const Vec3 &v) const
1583 {
1584     return Vec3 (x * v.x, y * v.y, z * v.z);
1585 }
1586 
1587 template <class T>
1588 inline Vec3<T>
1589 Vec3<T>::operator * (T a) const
1590 {
1591     return Vec3 (x * a, y * a, z * a);
1592 }
1593 
1594 template <class T>
1595 inline const Vec3<T> &
1596 Vec3<T>::operator /= (const Vec3 &v)
1597 {
1598     x /= v.x;
1599     y /= v.y;
1600     z /= v.z;
1601     return *this;
1602 }
1603 
1604 template <class T>
1605 inline const Vec3<T> &
1606 Vec3<T>::operator /= (T a)
1607 {
1608     x /= a;
1609     y /= a;
1610     z /= a;
1611     return *this;
1612 }
1613 
1614 template <class T>
1615 inline Vec3<T>
1616 Vec3<T>::operator / (const Vec3 &v) const
1617 {
1618     return Vec3 (x / v.x, y / v.y, z / v.z);
1619 }
1620 
1621 template <class T>
1622 inline Vec3<T>
1623 Vec3<T>::operator / (T a) const
1624 {
1625     return Vec3 (x / a, y / a, z / a);
1626 }
1627 
1628 template <class T>
1629 T
lengthTiny()1630 Vec3<T>::lengthTiny () const
1631 {
1632     T absX = (x >= T (0))? x: -x;
1633     T absY = (y >= T (0))? y: -y;
1634     T absZ = (z >= T (0))? z: -z;
1635 
1636     T max = absX;
1637 
1638     if (max < absY)
1639     max = absY;
1640 
1641     if (max < absZ)
1642     max = absZ;
1643 
1644     if (max == T (0))
1645     return T (0);
1646 
1647     //
1648     // Do not replace the divisions by max with multiplications by 1/max.
1649     // Computing 1/max can overflow but the divisions below will always
1650     // produce results less than or equal to 1.
1651     //
1652 
1653     absX /= max;
1654     absY /= max;
1655     absZ /= max;
1656 
1657     return max * Math<T>::sqrt (absX * absX + absY * absY + absZ * absZ);
1658 }
1659 
1660 template <class T>
1661 inline T
length()1662 Vec3<T>::length () const
1663 {
1664     T length2 = dot (*this);
1665 
1666     if (length2 < T (2) * limits<T>::smallest())
1667     return lengthTiny();
1668 
1669     return Math<T>::sqrt (length2);
1670 }
1671 
1672 template <class T>
1673 inline T
length2()1674 Vec3<T>::length2 () const
1675 {
1676     return dot (*this);
1677 }
1678 
1679 template <class T>
1680 const Vec3<T> &
normalize()1681 Vec3<T>::normalize ()
1682 {
1683     T l = length();
1684 
1685     if (l != T (0))
1686     {
1687         //
1688         // Do not replace the divisions by l with multiplications by 1/l.
1689         // Computing 1/l can overflow but the divisions below will always
1690         // produce results less than or equal to 1.
1691         //
1692 
1693     x /= l;
1694     y /= l;
1695     z /= l;
1696     }
1697 
1698     return *this;
1699 }
1700 
1701 template <class T>
1702 const Vec3<T> &
normalizeExc()1703 Vec3<T>::normalizeExc () throw (Iex::MathExc)
1704 {
1705     T l = length();
1706 
1707     if (l == T (0))
1708     throw NullVecExc ("Cannot normalize null vector.");
1709 
1710     x /= l;
1711     y /= l;
1712     z /= l;
1713     return *this;
1714 }
1715 
1716 template <class T>
1717 inline
1718 const Vec3<T> &
normalizeNonNull()1719 Vec3<T>::normalizeNonNull ()
1720 {
1721     T l = length();
1722     x /= l;
1723     y /= l;
1724     z /= l;
1725     return *this;
1726 }
1727 
1728 template <class T>
1729 Vec3<T>
normalized()1730 Vec3<T>::normalized () const
1731 {
1732     T l = length();
1733 
1734     if (l == T (0))
1735     return Vec3 (T (0));
1736 
1737     return Vec3 (x / l, y / l, z / l);
1738 }
1739 
1740 template <class T>
1741 Vec3<T>
normalizedExc()1742 Vec3<T>::normalizedExc () const throw (Iex::MathExc)
1743 {
1744     T l = length();
1745 
1746     if (l == T (0))
1747     throw NullVecExc ("Cannot normalize null vector.");
1748 
1749     return Vec3 (x / l, y / l, z / l);
1750 }
1751 
1752 template <class T>
1753 inline
1754 Vec3<T>
normalizedNonNull()1755 Vec3<T>::normalizedNonNull () const
1756 {
1757     T l = length();
1758     return Vec3 (x / l, y / l, z / l);
1759 }
1760 
1761 
1762 //-----------------------
1763 // Implementation of Vec4
1764 //-----------------------
1765 
1766 template <class T>
1767 inline T &
1768 Vec4<T>::operator [] (int i)
1769 {
1770     return (&x)[i];
1771 }
1772 
1773 template <class T>
1774 inline const T &
1775 Vec4<T>::operator [] (int i) const
1776 {
1777     return (&x)[i];
1778 }
1779 
1780 template <class T>
1781 inline
Vec4()1782 Vec4<T>::Vec4 ()
1783 {
1784     // empty
1785 }
1786 
1787 template <class T>
1788 inline
Vec4(T a)1789 Vec4<T>::Vec4 (T a)
1790 {
1791     x = y = z = w = a;
1792 }
1793 
1794 template <class T>
1795 inline
Vec4(T a,T b,T c,T d)1796 Vec4<T>::Vec4 (T a, T b, T c, T d)
1797 {
1798     x = a;
1799     y = b;
1800     z = c;
1801     w = d;
1802 }
1803 
1804 template <class T>
1805 inline
Vec4(const Vec4 & v)1806 Vec4<T>::Vec4 (const Vec4 &v)
1807 {
1808     x = v.x;
1809     y = v.y;
1810     z = v.z;
1811     w = v.w;
1812 }
1813 
1814 template <class T>
1815 template <class S>
1816 inline
Vec4(const Vec4<S> & v)1817 Vec4<T>::Vec4 (const Vec4<S> &v)
1818 {
1819     x = T (v.x);
1820     y = T (v.y);
1821     z = T (v.z);
1822     w = T (v.w);
1823 }
1824 
1825 template <class T>
1826 inline const Vec4<T> &
1827 Vec4<T>::operator = (const Vec4 &v)
1828 {
1829     x = v.x;
1830     y = v.y;
1831     z = v.z;
1832     w = v.w;
1833     return *this;
1834 }
1835 
1836 template <class T>
1837 template <class S>
1838 inline
Vec4(const Vec3<S> & v)1839 Vec4<T>::Vec4 (const Vec3<S> &v)
1840 {
1841     x = T (v.x);
1842     y = T (v.y);
1843     z = T (v.z);
1844     w = T (1);
1845 }
1846 
1847 template <class T>
1848 template <class S>
1849 inline bool
1850 Vec4<T>::operator == (const Vec4<S> &v) const
1851 {
1852     return x == v.x && y == v.y && z == v.z && w == v.w;
1853 }
1854 
1855 template <class T>
1856 template <class S>
1857 inline bool
1858 Vec4<T>::operator != (const Vec4<S> &v) const
1859 {
1860     return x != v.x || y != v.y || z != v.z || w != v.w;
1861 }
1862 
1863 template <class T>
1864 bool
equalWithAbsError(const Vec4<T> & v,T e)1865 Vec4<T>::equalWithAbsError (const Vec4<T> &v, T e) const
1866 {
1867     for (int i = 0; i < 4; i++)
1868         if (!Imath::equalWithAbsError ((*this)[i], v[i], e))
1869             return false;
1870 
1871     return true;
1872 }
1873 
1874 template <class T>
1875 bool
equalWithRelError(const Vec4<T> & v,T e)1876 Vec4<T>::equalWithRelError (const Vec4<T> &v, T e) const
1877 {
1878     for (int i = 0; i < 4; i++)
1879         if (!Imath::equalWithRelError ((*this)[i], v[i], e))
1880             return false;
1881 
1882     return true;
1883 }
1884 
1885 template <class T>
1886 inline T
dot(const Vec4 & v)1887 Vec4<T>::dot (const Vec4 &v) const
1888 {
1889     return x * v.x + y * v.y + z * v.z + w * v.w;
1890 }
1891 
1892 template <class T>
1893 inline T
1894 Vec4<T>::operator ^ (const Vec4 &v) const
1895 {
1896     return dot (v);
1897 }
1898 
1899 
1900 template <class T>
1901 inline const Vec4<T> &
1902 Vec4<T>::operator += (const Vec4 &v)
1903 {
1904     x += v.x;
1905     y += v.y;
1906     z += v.z;
1907     w += v.w;
1908     return *this;
1909 }
1910 
1911 template <class T>
1912 inline Vec4<T>
1913 Vec4<T>::operator + (const Vec4 &v) const
1914 {
1915     return Vec4 (x + v.x, y + v.y, z + v.z, w + v.w);
1916 }
1917 
1918 template <class T>
1919 inline const Vec4<T> &
1920 Vec4<T>::operator -= (const Vec4 &v)
1921 {
1922     x -= v.x;
1923     y -= v.y;
1924     z -= v.z;
1925     w -= v.w;
1926     return *this;
1927 }
1928 
1929 template <class T>
1930 inline Vec4<T>
1931 Vec4<T>::operator - (const Vec4 &v) const
1932 {
1933     return Vec4 (x - v.x, y - v.y, z - v.z, w - v.w);
1934 }
1935 
1936 template <class T>
1937 inline Vec4<T>
1938 Vec4<T>::operator - () const
1939 {
1940     return Vec4 (-x, -y, -z, -w);
1941 }
1942 
1943 template <class T>
1944 inline const Vec4<T> &
negate()1945 Vec4<T>::negate ()
1946 {
1947     x = -x;
1948     y = -y;
1949     z = -z;
1950     w = -w;
1951     return *this;
1952 }
1953 
1954 template <class T>
1955 inline const Vec4<T> &
1956 Vec4<T>::operator *= (const Vec4 &v)
1957 {
1958     x *= v.x;
1959     y *= v.y;
1960     z *= v.z;
1961     w *= v.w;
1962     return *this;
1963 }
1964 
1965 template <class T>
1966 inline const Vec4<T> &
1967 Vec4<T>::operator *= (T a)
1968 {
1969     x *= a;
1970     y *= a;
1971     z *= a;
1972     w *= a;
1973     return *this;
1974 }
1975 
1976 template <class T>
1977 inline Vec4<T>
1978 Vec4<T>::operator * (const Vec4 &v) const
1979 {
1980     return Vec4 (x * v.x, y * v.y, z * v.z, w * v.w);
1981 }
1982 
1983 template <class T>
1984 inline Vec4<T>
1985 Vec4<T>::operator * (T a) const
1986 {
1987     return Vec4 (x * a, y * a, z * a, w * a);
1988 }
1989 
1990 template <class T>
1991 inline const Vec4<T> &
1992 Vec4<T>::operator /= (const Vec4 &v)
1993 {
1994     x /= v.x;
1995     y /= v.y;
1996     z /= v.z;
1997     w /= v.w;
1998     return *this;
1999 }
2000 
2001 template <class T>
2002 inline const Vec4<T> &
2003 Vec4<T>::operator /= (T a)
2004 {
2005     x /= a;
2006     y /= a;
2007     z /= a;
2008     w /= a;
2009     return *this;
2010 }
2011 
2012 template <class T>
2013 inline Vec4<T>
2014 Vec4<T>::operator / (const Vec4 &v) const
2015 {
2016     return Vec4 (x / v.x, y / v.y, z / v.z, w / v.w);
2017 }
2018 
2019 template <class T>
2020 inline Vec4<T>
2021 Vec4<T>::operator / (T a) const
2022 {
2023     return Vec4 (x / a, y / a, z / a, w / a);
2024 }
2025 
2026 template <class T>
2027 T
lengthTiny()2028 Vec4<T>::lengthTiny () const
2029 {
2030     T absX = (x >= T (0))? x: -x;
2031     T absY = (y >= T (0))? y: -y;
2032     T absZ = (z >= T (0))? z: -z;
2033     T absW = (w >= T (0))? w: -w;
2034 
2035     T max = absX;
2036 
2037     if (max < absY)
2038         max = absY;
2039 
2040     if (max < absZ)
2041         max = absZ;
2042 
2043     if (max < absW)
2044         max = absW;
2045 
2046     if (max == T (0))
2047         return T (0);
2048 
2049     //
2050     // Do not replace the divisions by max with multiplications by 1/max.
2051     // Computing 1/max can overflow but the divisions below will always
2052     // produce results less than or equal to 1.
2053     //
2054 
2055     absX /= max;
2056     absY /= max;
2057     absZ /= max;
2058     absW /= max;
2059 
2060     return max *
2061         Math<T>::sqrt (absX * absX + absY * absY + absZ * absZ + absW * absW);
2062 }
2063 
2064 template <class T>
2065 inline T
length()2066 Vec4<T>::length () const
2067 {
2068     T length2 = dot (*this);
2069 
2070     if (length2 < T (2) * limits<T>::smallest())
2071         return lengthTiny();
2072 
2073     return Math<T>::sqrt (length2);
2074 }
2075 
2076 template <class T>
2077 inline T
length2()2078 Vec4<T>::length2 () const
2079 {
2080     return dot (*this);
2081 }
2082 
2083 template <class T>
2084 const Vec4<T> &
normalize()2085 Vec4<T>::normalize ()
2086 {
2087     T l = length();
2088 
2089     if (l != T (0))
2090     {
2091         //
2092         // Do not replace the divisions by l with multiplications by 1/l.
2093         // Computing 1/l can overflow but the divisions below will always
2094         // produce results less than or equal to 1.
2095         //
2096 
2097         x /= l;
2098         y /= l;
2099         z /= l;
2100         w /= l;
2101     }
2102 
2103     return *this;
2104 }
2105 
2106 template <class T>
2107 const Vec4<T> &
normalizeExc()2108 Vec4<T>::normalizeExc () throw (Iex::MathExc)
2109 {
2110     T l = length();
2111 
2112     if (l == T (0))
2113         throw NullVecExc ("Cannot normalize null vector.");
2114 
2115     x /= l;
2116     y /= l;
2117     z /= l;
2118     w /= l;
2119     return *this;
2120 }
2121 
2122 template <class T>
2123 inline
2124 const Vec4<T> &
normalizeNonNull()2125 Vec4<T>::normalizeNonNull ()
2126 {
2127     T l = length();
2128     x /= l;
2129     y /= l;
2130     z /= l;
2131     w /= l;
2132     return *this;
2133 }
2134 
2135 template <class T>
2136 Vec4<T>
normalized()2137 Vec4<T>::normalized () const
2138 {
2139     T l = length();
2140 
2141     if (l == T (0))
2142         return Vec4 (T (0));
2143 
2144     return Vec4 (x / l, y / l, z / l, w / l);
2145 }
2146 
2147 template <class T>
2148 Vec4<T>
normalizedExc()2149 Vec4<T>::normalizedExc () const throw (Iex::MathExc)
2150 {
2151     T l = length();
2152 
2153     if (l == T (0))
2154         throw NullVecExc ("Cannot normalize null vector.");
2155 
2156     return Vec4 (x / l, y / l, z / l, w / l);
2157 }
2158 
2159 template <class T>
2160 inline
2161 Vec4<T>
normalizedNonNull()2162 Vec4<T>::normalizedNonNull () const
2163 {
2164     T l = length();
2165     return Vec4 (x / l, y / l, z / l, w / l);
2166 }
2167 
2168 //-----------------------------
2169 // Stream output implementation
2170 //-----------------------------
2171 
2172 template <class T>
2173 std::ostream &
2174 operator << (std::ostream &s, const Vec2<T> &v)
2175 {
2176     return s << '(' << v.x << ' ' << v.y << ')';
2177 }
2178 
2179 template <class T>
2180 std::ostream &
2181 operator << (std::ostream &s, const Vec3<T> &v)
2182 {
2183     return s << '(' << v.x << ' ' << v.y << ' ' << v.z << ')';
2184 }
2185 
2186 template <class T>
2187 std::ostream &
2188 operator << (std::ostream &s, const Vec4<T> &v)
2189 {
2190     return s << '(' << v.x << ' ' << v.y << ' ' << v.z << ' ' << v.w << ')';
2191 }
2192 
2193 
2194 //-----------------------------------------
2195 // Implementation of reverse multiplication
2196 //-----------------------------------------
2197 
2198 template <class T>
2199 inline Vec2<T>
2200 operator * (T a, const Vec2<T> &v)
2201 {
2202     return Vec2<T> (a * v.x, a * v.y);
2203 }
2204 
2205 template <class T>
2206 inline Vec3<T>
2207 operator * (T a, const Vec3<T> &v)
2208 {
2209     return Vec3<T> (a * v.x, a * v.y, a * v.z);
2210 }
2211 
2212 template <class T>
2213 inline Vec4<T>
2214 operator * (T a, const Vec4<T> &v)
2215 {
2216     return Vec4<T> (a * v.x, a * v.y, a * v.z, a * v.w);
2217 }
2218 
2219 
2220 #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
2221 #pragma warning(pop)
2222 #endif
2223 
2224 } // namespace Imath
2225 
2226 #endif
2227