text: ///////////////////////////////////////////////////////////////////////////
  //
  // Copyright (c) 2004, Industrial Light & Magic, a division of Lucas
  // Digital Ltd. LLC
  //
  // All rights reserved.
  //
  // Redistribution and use in source and binary forms, with or without
  // modification, are permitted provided that the following conditions are
  // met:
  // *       Redistributions of source code must retain the above copyright
  // notice, this list of conditions and the following disclaimer.
  // *       Redistributions in binary form must reproduce the above
  // copyright notice, this list of conditions and the following disclaimer
  // in the documentation and/or other materials provided with the
  // distribution.
  // *       Neither the name of Industrial Light & Magic nor the names of
  // its contributors may be used to endorse or promote products derived
  // from this software without specific prior written permission.
  //
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  //
  ///////////////////////////////////////////////////////////////////////////
  
  
  
  #ifndef INCLUDED_IMATHSHEAR_H
  #define INCLUDED_IMATHSHEAR_H
  
  //----------------------------------------------------
  //
  //	Shear6 class template.
  //
  //----------------------------------------------------
  
  #include "ImathExc.h"
  #include "ImathLimits.h"
  #include "ImathMath.h"
  #include "ImathVec.h"
  
  #include <iostream>
  
  
  namespace Imath {
  
  
  
  
  template <class T> class Shear6
  {
    public:
  
      //-------------------
      // Access to elements
      //-------------------
  
      T			xy, xz, yz, yx, zx, zy;
  
      T &			operator [] (int i);
      const T &		operator [] (int i) const;
  
  
      //-------------
      // Constructors
      //-------------
  
      Shear6 ();			   // (0 0 0 0 0 0)
      Shear6 (T XY, T XZ, T YZ);	   // (XY XZ YZ 0 0 0)
      Shear6 (const Vec3<T> &v);     // (v.x v.y v.z 0 0 0)
      template <class S>             // (v.x v.y v.z 0 0 0)
      Shear6 (const Vec3<S> &v);
      Shear6 (T XY, T XZ, T YZ,      // (XY XZ YZ YX ZX ZY)
          T YX, T ZX, T ZY);
  
  
      //---------------------------------
      // Copy constructors and assignment
      //---------------------------------
  
      Shear6 (const Shear6 &h);
      template <class S> Shear6 (const Shear6<S> &h);
  
      const Shear6 &	operator = (const Shear6 &h);
      template <class S>
      const Shear6 &	operator = (const Vec3<S> &v);
  
  
      //----------------------
      // Compatibility with Sb
      //----------------------
  
      template <class S>
      void		setValue (S XY, S XZ, S YZ, S YX, S ZX, S ZY);
  
      template <class S>
      void		setValue (const Shear6<S> &h);
  
      template <class S>
      void		getValue (S &XY, S &XZ, S &YZ,
                    S &YX, S &ZX, S &ZY) const;
  
      template <class S>
      void		getValue (Shear6<S> &h) const;
  
      T *			getValue();
      const T *		getValue() const;
  
  
      //---------
      // Equality
      //---------
  
      template <class S>
      bool		operator == (const Shear6<S> &h) const;
  
      template <class S>
      bool		operator != (const Shear6<S> &h) const;
  
      //-----------------------------------------------------------------------
      // Compare two shears and test if they are "approximately equal":
      //
      // equalWithAbsError (h, e)
      //
      //	    Returns true if the coefficients of this and h are the same with
      //	    an absolute error of no more than e, i.e., for all i
      //
      //      abs (this[i] - h[i]) <= e
      //
      // equalWithRelError (h, e)
      //
      //	    Returns true if the coefficients of this and h are the same with
      //	    a relative error of no more than e, i.e., for all i
      //
      //      abs (this[i] - h[i]) <= e * abs (this[i])
      //-----------------------------------------------------------------------
  
      bool		equalWithAbsError (const Shear6<T> &h, T e) const;
      bool		equalWithRelError (const Shear6<T> &h, T e) const;
  
  
      //------------------------
      // Component-wise addition
      //------------------------
  
      const Shear6 &	operator += (const Shear6 &h);
      Shear6		operator + (const Shear6 &h) const;
  
  
      //---------------------------
      // Component-wise subtraction
      //---------------------------
  
      const Shear6 &	operator -= (const Shear6 &h);
      Shear6		operator - (const Shear6 &h) const;
  
  
      //------------------------------------
      // Component-wise multiplication by -1
      //------------------------------------
  
      Shear6		operator - () const;
      const Shear6 &	negate ();
  
  
      //------------------------------
      // Component-wise multiplication
      //------------------------------
  
      const Shear6 &	operator *= (const Shear6 &h);
      const Shear6 &	operator *= (T a);
      Shear6		operator * (const Shear6 &h) const;
      Shear6		operator * (T a) const;
  
  
      //------------------------
      // Component-wise division
      //------------------------
  
      const Shear6 &	operator /= (const Shear6 &h);
      const Shear6 &	operator /= (T a);
      Shear6		operator / (const Shear6 &h) const;
      Shear6		operator / (T a) const;
  
  
      //----------------------------------------------------------
      // Number of dimensions, i.e. number of elements in a Shear6
      //----------------------------------------------------------
  
      static unsigned int	dimensions() {return 6;}
  
  
      //-------------------------------------------------
      // Limitations of type T (see also class limits<T>)
      //-------------------------------------------------
  
      static T		baseTypeMin()		{return limits<T>::min();}
      static T		baseTypeMax()		{return limits<T>::max();}
      static T		baseTypeSmallest()	{return limits<T>::smallest();}
      static T		baseTypeEpsilon()	{return limits<T>::epsilon();}
  
  
      //--------------------------------------------------------------
      // Base type -- in templates, which accept a parameter, V, which
      // could be either a Vec2<T> or a Shear6<T>, you can refer to T as
      // V::BaseType
      //--------------------------------------------------------------
  
      typedef T		BaseType;
  };
  
  
  //--------------
  // Stream output
  //--------------
  
  template <class T>
  std::ostream &	operator << (std::ostream &s, const Shear6<T> &h);
  
  
  //----------------------------------------------------
  // Reverse multiplication: scalar * Shear6<T>
  //----------------------------------------------------
  
  template <class S, class T> Shear6<T>	operator * (S a, const Shear6<T> &h);
  
  
  //-------------------------
  // Typedefs for convenience
  //-------------------------
  
  typedef Vec3   <float>  Shear3f;
  typedef Vec3   <double> Shear3d;
  typedef Shear6 <float>  Shear6f;
  typedef Shear6 <double> Shear6d;
  
  
  
  
  //-----------------------
  // Implementation of Shear6
  //-----------------------
  
  template <class T>
  inline T &
  Shear6<T>::operator [] (int i)
  {
      return (&xy)[i];
  }
  
  template <class T>
  inline const T &
  Shear6<T>::operator [] (int i) const
  {
      return (&xy)[i];
  }
  
  template <class T>
  inline
  Shear6<T>::Shear6 ()
  {
      xy = xz = yz = yx = zx = zy = 0;
  }
  
  template <class T>
  inline
  Shear6<T>::Shear6 (T XY, T XZ, T YZ)
  {
      xy = XY;
      xz = XZ;
      yz = YZ;
      yx = 0;
      zx = 0;
      zy = 0;
  }
  
  template <class T>
  inline
  Shear6<T>::Shear6 (const Vec3<T> &v)
  {
      xy = v.x;
      xz = v.y;
      yz = v.z;
      yx = 0;
      zx = 0;
      zy = 0;
  }
  
  template <class T>
  template <class S>
  inline
  Shear6<T>::Shear6 (const Vec3<S> &v)
  {
      xy = T (v.x);
      xz = T (v.y);
      yz = T (v.z);
      yx = 0;
      zx = 0;
      zy = 0;
  }
  
  template <class T>
  inline
  Shear6<T>::Shear6 (T XY, T XZ, T YZ, T YX, T ZX, T ZY)
  {
      xy = XY;
      xz = XZ;
      yz = YZ;
      yx = YX;
      zx = ZX;
      zy = ZY;
  }
  
  template <class T>
  inline
  Shear6<T>::Shear6 (const Shear6 &h)
  {
      xy = h.xy;
      xz = h.xz;
      yz = h.yz;
      yx = h.yx;
      zx = h.zx;
      zy = h.zy;
  }
  
  template <class T>
  template <class S>
  inline
  Shear6<T>::Shear6 (const Shear6<S> &h)
  {
      xy = T (h.xy);
      xz = T (h.xz);
      yz = T (h.yz);
      yx = T (h.yx);
      zx = T (h.zx);
      zy = T (h.zy);
  }
  
  template <class T>
  inline const Shear6<T> &
  Shear6<T>::operator = (const Shear6 &h)
  {
      xy = h.xy;
      xz = h.xz;
      yz = h.yz;
      yx = h.yx;
      zx = h.zx;
      zy = h.zy;
      return *this;
  }
  
  template <class T>
  template <class S>
  inline const Shear6<T> &
  Shear6<T>::operator = (const Vec3<S> &v)
  {
      xy = T (v.x);
      xz = T (v.y);
      yz = T (v.z);
      yx = 0;
      zx = 0;
      zy = 0;
      return *this;
  }
  
  template <class T>
  template <class S>
  inline void
  Shear6<T>::setValue (S XY, S XZ, S YZ, S YX, S ZX, S ZY)
  {
      xy = T (XY);
      xz = T (XZ);
      yz = T (YZ);
      yx = T (YX);
      zx = T (ZX);
      zy = T (ZY);
  }
  
  template <class T>
  template <class S>
  inline void
  Shear6<T>::setValue (const Shear6<S> &h)
  {
      xy = T (h.xy);
      xz = T (h.xz);
      yz = T (h.yz);
      yx = T (h.yx);
      zx = T (h.zx);
      zy = T (h.zy);
  }
  
  template <class T>
  template <class S>
  inline void
  Shear6<T>::getValue (S &XY, S &XZ, S &YZ, S &YX, S &ZX, S &ZY) const
  {
      XY = S (xy);
      XZ = S (xz);
      YZ = S (yz);
      YX = S (yx);
      ZX = S (zx);
      ZY = S (zy);
  }
  
  template <class T>
  template <class S>
  inline void
  Shear6<T>::getValue (Shear6<S> &h) const
  {
      h.xy = S (xy);
      h.xz = S (xz);
      h.yz = S (yz);
      h.yx = S (yx);
      h.zx = S (zx);
      h.zy = S (zy);
  }
  
  template <class T>
  inline T *
  Shear6<T>::getValue()
  {
      return (T *) &xy;
  }
  
  template <class T>
  inline const T *
  Shear6<T>::getValue() const
  {
      return (const T *) &xy;
  }
  
  template <class T>
  template <class S>
  inline bool
  Shear6<T>::operator == (const Shear6<S> &h) const
  {
      return xy == h.xy  &&  xz == h.xz  &&  yz == h.yz  &&
         yx == h.yx  &&  zx == h.zx  &&  zy == h.zy;
  }
  
  template <class T>
  template <class S>
  inline bool
  Shear6<T>::operator != (const Shear6<S> &h) const
  {
      return xy != h.xy  ||  xz != h.xz  ||  yz != h.yz  ||
         yx != h.yx  ||  zx != h.zx  ||  zy != h.zy;
  }
  
  template <class T>
  bool
  Shear6<T>::equalWithAbsError (const Shear6<T> &h, T e) const
  {
      for (int i = 0; i < 6; i++)
      if (!Imath::equalWithAbsError ((*this)[i], h[i], e))
          return false;
  
      return true;
  }
  
  template <class T>
  bool
  Shear6<T>::equalWithRelError (const Shear6<T> &h, T e) const
  {
      for (int i = 0; i < 6; i++)
      if (!Imath::equalWithRelError ((*this)[i], h[i], e))
          return false;
  
      return true;
  }
  
  
  template <class T>
  inline const Shear6<T> &
  Shear6<T>::operator += (const Shear6 &h)
  {
      xy += h.xy;
      xz += h.xz;
      yz += h.yz;
      yx += h.yx;
      zx += h.zx;
      zy += h.zy;
      return *this;
  }
  
  template <class T>
  inline Shear6<T>
  Shear6<T>::operator + (const Shear6 &h) const
  {
      return Shear6 (xy + h.xy, xz + h.xz, yz + h.yz,
             yx + h.yx, zx + h.zx, zy + h.zy);
  }
  
  template <class T>
  inline const Shear6<T> &
  Shear6<T>::operator -= (const Shear6 &h)
  {
      xy -= h.xy;
      xz -= h.xz;
      yz -= h.yz;
      yx -= h.yx;
      zx -= h.zx;
      zy -= h.zy;
      return *this;
  }
  
  template <class T>
  inline Shear6<T>
  Shear6<T>::operator - (const Shear6 &h) const
  {
      return Shear6 (xy - h.xy, xz - h.xz, yz - h.yz,
             yx - h.yx, zx - h.zx, zy - h.zy);
  }
  
  template <class T>
  inline Shear6<T>
  Shear6<T>::operator - () const
  {
      return Shear6 (-xy, -xz, -yz, -yx, -zx, -zy);
  }
  
  template <class T>
  inline const Shear6<T> &
  Shear6<T>::negate ()
  {
      xy = -xy;
      xz = -xz;
      yz = -yz;
      yx = -yx;
      zx = -zx;
      zy = -zy;
      return *this;
  }
  
  template <class T>
  inline const Shear6<T> &
  Shear6<T>::operator *= (const Shear6 &h)
  {
      xy *= h.xy;
      xz *= h.xz;
      yz *= h.yz;
      yx *= h.yx;
      zx *= h.zx;
      zy *= h.zy;
      return *this;
  }
  
  template <class T>
  inline const Shear6<T> &
  Shear6<T>::operator *= (T a)
  {
      xy *= a;
      xz *= a;
      yz *= a;
      yx *= a;
      zx *= a;
      zy *= a;
      return *this;
  }
  
  template <class T>
  inline Shear6<T>
  Shear6<T>::operator * (const Shear6 &h) const
  {
      return Shear6 (xy * h.xy, xz * h.xz, yz * h.yz,
             yx * h.yx, zx * h.zx, zy * h.zy);
  }
  
  template <class T>
  inline Shear6<T>
  Shear6<T>::operator * (T a) const
  {
      return Shear6 (xy * a, xz * a, yz * a,
             yx * a, zx * a, zy * a);
  }
  
  template <class T>
  inline const Shear6<T> &
  Shear6<T>::operator /= (const Shear6 &h)
  {
      xy /= h.xy;
      xz /= h.xz;
      yz /= h.yz;
      yx /= h.yx;
      zx /= h.zx;
      zy /= h.zy;
      return *this;
  }
  
  template <class T>
  inline const Shear6<T> &
  Shear6<T>::operator /= (T a)
  {
      xy /= a;
      xz /= a;
      yz /= a;
      yx /= a;
      zx /= a;
      zy /= a;
      return *this;
  }
  
  template <class T>
  inline Shear6<T>
  Shear6<T>::operator / (const Shear6 &h) const
  {
      return Shear6 (xy / h.xy, xz / h.xz, yz / h.yz,
             yx / h.yx, zx / h.zx, zy / h.zy);
  }
  
  template <class T>
  inline Shear6<T>
  Shear6<T>::operator / (T a) const
  {
      return Shear6 (xy / a, xz / a, yz / a,
             yx / a, zx / a, zy / a);
  }
  
  
  //-----------------------------
  // Stream output implementation
  //-----------------------------
  
  template <class T>
  std::ostream &
  operator << (std::ostream &s, const Shear6<T> &h)
  {
      return s << '('
           << h.xy << ' ' << h.xz << ' ' << h.yz
           << h.yx << ' ' << h.zx << ' ' << h.zy
           << ')';
  }
  
  
  //-----------------------------------------
  // Implementation of reverse multiplication
  //-----------------------------------------
  
  template <class S, class T>
  inline Shear6<T>
  operator * (S a, const Shear6<T> &h)
  {
      return Shear6<T> (a * h.xy, a * h.xz, a * h.yz,
                a * h.yx, a * h.zx, a * h.zy);
  }
  
  
  } // namespace Imath
  
  #endif
  