Home | History | Annotate | Download | only in Imath
      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 
    239     static unsigned int	dimensions() {return 2;}
    240 
    241 
    242     //-------------------------------------------------
    243     // Limitations of type T (see also class limits<T>)
    244     //-------------------------------------------------
    245 
    246     static T		baseTypeMin()		{return limits<T>::min();}
    247     static T		baseTypeMax()		{return limits<T>::max();}
    248     static T		baseTypeSmallest()	{return limits<T>::smallest();}
    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 
    451     static unsigned int	dimensions() {return 3;}
    452 
    453 
    454     //-------------------------------------------------
    455     // Limitations of type T (see also class limits<T>)
    456     //-------------------------------------------------
    457 
    458     static T		baseTypeMin()		{return limits<T>::min();}
    459     static T		baseTypeMax()		{return limits<T>::max();}
    460     static T		baseTypeSmallest()	{return limits<T>::smallest();}
    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 
    633     static unsigned int	dimensions() {return 4;}
    634 
    635 
    636     //-------------------------------------------------
    637     // Limitations of type T (see also class limits<T>)
    638     //-------------------------------------------------
    639 
    640     static T		baseTypeMin()		{return limits<T>::min();}
    641     static T		baseTypeMax()		{return limits<T>::max();}
    642     static T		baseTypeSmallest()	{return limits<T>::smallest();}
    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
    867 Vec2<T>::Vec2 ()
    868 {
    869     // empty
    870 }
    871 
    872 template <class T>
    873 inline
    874 Vec2<T>::Vec2 (T a)
    875 {
    876     x = y = a;
    877 }
    878 
    879 template <class T>
    880 inline
    881 Vec2<T>::Vec2 (T a, T b)
    882 {
    883     x = a;
    884     y = b;
    885 }
    886 
    887 template <class T>
    888 inline
    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
    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
    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
    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
    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
    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 *
    951 Vec2<T>::getValue()
    952 {
    953     return (T *) &x;
    954 }
    955 
    956 template <class T>
    957 inline const T *
    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
    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
    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
   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
   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> &
   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
   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
   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
   1183 Vec2<T>::length2 () const
   1184 {
   1185     return dot (*this);
   1186 }
   1187 
   1188 template <class T>
   1189 const Vec2<T> &
   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> &
   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> &
   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>
   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>
   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>
   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
   1288 Vec3<T>::Vec3 ()
   1289 {
   1290     // empty
   1291 }
   1292 
   1293 template <class T>
   1294 inline
   1295 Vec3<T>::Vec3 (T a)
   1296 {
   1297     x = y = z = a;
   1298 }
   1299 
   1300 template <class T>
   1301 inline
   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
   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
   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
   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>
   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
   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
   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
   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
   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 *
   1414 Vec3<T>::getValue()
   1415 {
   1416     return (T *) &x;
   1417 }
   1418 
   1419 template <class T>
   1420 inline const T *
   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
   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
   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
   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>
   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> &
   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
   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
   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
   1674 Vec3<T>::length2 () const
   1675 {
   1676     return dot (*this);
   1677 }
   1678 
   1679 template <class T>
   1680 const Vec3<T> &
   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> &
   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> &
   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>
   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>
   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>
   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
   1782 Vec4<T>::Vec4 ()
   1783 {
   1784     // empty
   1785 }
   1786 
   1787 template <class T>
   1788 inline
   1789 Vec4<T>::Vec4 (T a)
   1790 {
   1791     x = y = z = w = a;
   1792 }
   1793 
   1794 template <class T>
   1795 inline
   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
   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
   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
   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
   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
   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
   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> &
   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
   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
   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
   2078 Vec4<T>::length2 () const
   2079 {
   2080     return dot (*this);
   2081 }
   2082 
   2083 template <class T>
   2084 const Vec4<T> &
   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> &
   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> &
   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>
   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>
   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>
   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