// // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // 2D, 3D and 4D point/vector class templates // #ifndef INCLUDED_IMATHVEC_H #define INCLUDED_IMATHVEC_H #ifdef __has_include # if __has_include() # include # endif #endif #include "ImathExport.h" #include "ImathNamespace.h" #include "ImathTypeTraits.h" #include "ImathMath.h" #include "half.h" #include #include #include #include #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER // suppress exception specification warnings # pragma warning(push) # pragma warning(disable : 4290) #endif IMATH_INTERNAL_NAMESPACE_HEADER_ENTER template class Vec2; template class Vec3; template class Vec4; /// Enum for the Vec4 to Vec3 conversion constructor enum IMATH_EXPORT_ENUM InfException { INF_EXCEPTION }; /// /// 2-element vector /// template class IMATH_EXPORT_TEMPLATE_TYPE Vec2 { public: /// @{ /// @name Direct access to elements T x, y; /// @} /// Element access by index. /// /// NB: This method of access may use dynamic array accesses which /// can prevent compiler optimizations and force temporaries to be /// stored to the stack and other missed vectorization /// opportunities. Use of direct access to x, y when /// possible should be preferred. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T& operator[] (int i) IMATH_NOEXCEPT; /// Element access by index. /// /// NB: This method of access may use dynamic array accesses which /// can prevent compiler optimizations and force temporaries to be /// stored to the stack and other missed vectorization /// opportunities. Use of direct access to x, y when /// possible should be preferred. IMATH_HOSTDEVICE constexpr const T& operator[] (int i) const IMATH_NOEXCEPT; /// @{ /// @name Constructors and Assignment /// Uninitialized by default IMATH_HOSTDEVICE Vec2 () IMATH_NOEXCEPT; /// Initialize to a scalar `(a,a)` IMATH_HOSTDEVICE constexpr explicit Vec2 (T a) IMATH_NOEXCEPT; /// Initialize to given elements `(a,b)` IMATH_HOSTDEVICE constexpr Vec2 (T a, T b) IMATH_NOEXCEPT; /// Copy constructor IMATH_HOSTDEVICE constexpr Vec2 (const Vec2& v) IMATH_NOEXCEPT; /// Construct from Vec2 of another base type template IMATH_HOSTDEVICE constexpr Vec2 (const Vec2& v) IMATH_NOEXCEPT; /// Assignment IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& operator= (const Vec2& v) IMATH_NOEXCEPT; /// Destructor ~Vec2 () IMATH_NOEXCEPT = default; /// @} #if IMATH_FOREIGN_VECTOR_INTEROP /// @{ /// @name Interoperability with other vector types /// /// Construction and assignment are allowed from other classes that /// appear to be equivalent vector types, provided that they have either /// a subscripting operator, or data members .x and .y, that are of the /// same type as the elements of this vector, and their size appears to /// be the right number of elements. /// /// This functionality is disabled for gcc 4.x, which seems to have a /// compiler bug that results in spurious errors. It can also be /// disabled by defining IMATH_FOREIGN_VECTOR_INTEROP to be 0 prior to /// including any Imath header files. /// template ::value)> IMATH_HOSTDEVICE explicit constexpr Vec2 (const V& v) IMATH_NOEXCEPT : Vec2 (T (v.x), T (v.y)) {} template < typename V, IMATH_ENABLE_IF (has_subscript::value && !has_xy::value)> IMATH_HOSTDEVICE explicit Vec2 (const V& v) : Vec2 (T (v[0]), T (v[1])) {} template ::value)> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& operator= (const V& v) IMATH_NOEXCEPT { x = T (v.x); y = T (v.y); return *this; } template < typename V, IMATH_ENABLE_IF (has_subscript::value && !has_xy::value)> IMATH_HOSTDEVICE const Vec2& operator= (const V& v) { x = T (v[0]); y = T (v[1]); return *this; } #endif /// @{ /// @name Compatibility with Sb /// Set the value template IMATH_HOSTDEVICE void setValue (S a, S b) IMATH_NOEXCEPT; /// Set the value template IMATH_HOSTDEVICE void setValue (const Vec2& v) IMATH_NOEXCEPT; /// Return the value in `a` and `b` template IMATH_HOSTDEVICE void getValue (S& a, S& b) const IMATH_NOEXCEPT; /// Return the value in `v` template IMATH_HOSTDEVICE void getValue (Vec2& v) const IMATH_NOEXCEPT; /// Return a raw pointer to the array of values IMATH_HOSTDEVICE T* getValue () IMATH_NOEXCEPT; /// Return a raw pointer to the array of values IMATH_HOSTDEVICE const T* getValue () const IMATH_NOEXCEPT; /// @} /// @{ /// @name Arithmetic and Comparison /// Equality template IMATH_HOSTDEVICE constexpr bool operator== (const Vec2& v) const IMATH_NOEXCEPT; /// Inequality template IMATH_HOSTDEVICE constexpr bool operator!= (const Vec2& v) const IMATH_NOEXCEPT; /// Compare two vectors and test if they are "approximately equal": /// @return True if the components of this and `v` are the same /// with an absolute error of no more than e, i.e., for all i: /// /// abs (this[i] - v[i]) <= e IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithAbsError (const Vec2& v, T e) const IMATH_NOEXCEPT; /// Compare two vectors and test if they are "approximately equal": /// @return True if the components of this and `v` are the same with /// a relative error of no more than e, i.e., for all i: /// /// abs (this[i] - v[i]) <= e * abs (this[i]) IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithRelError (const Vec2& v, T e) const IMATH_NOEXCEPT; /// Dot product IMATH_HOSTDEVICE constexpr T dot (const Vec2& v) const IMATH_NOEXCEPT; /// Dot product IMATH_HOSTDEVICE constexpr T operator^ (const Vec2& v) const IMATH_NOEXCEPT; /// Right-handed cross product, i.e. z component of /// Vec3 (this->x, this->y, 0) % Vec3 (v.x, v.y, 0) IMATH_HOSTDEVICE constexpr T cross (const Vec2& v) const IMATH_NOEXCEPT; /// Right-handed cross product, i.e. z component of /// Vec3 (this->x, this->y, 0) % Vec3 (v.x, v.y, 0) IMATH_HOSTDEVICE constexpr T operator% (const Vec2& v) const IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& operator+= (const Vec2& v) IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE constexpr Vec2 operator+ (const Vec2& v) const IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& operator-= (const Vec2& v) IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE constexpr Vec2 operator- (const Vec2& v) const IMATH_NOEXCEPT; /// Component-wise multiplication by -1 IMATH_HOSTDEVICE constexpr Vec2 operator- () const IMATH_NOEXCEPT; /// Component-wise multiplication by -1 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& negate () IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& operator*= (const Vec2& v) IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& operator*= (T a) IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE constexpr Vec2 operator* (const Vec2& v) const IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE constexpr Vec2 operator* (T a) const IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& operator/= (const Vec2& v) IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& operator/= (T a) IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE constexpr Vec2 operator/ (const Vec2& v) const IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE constexpr Vec2 operator/ (T a) const IMATH_NOEXCEPT; /// @} /// @{ /// @name Query and Manipulation /// Return the Euclidean norm IMATH_HOSTDEVICE T length () const IMATH_NOEXCEPT; /// Return the square of the Euclidean norm, i.e. the dot product /// with itself. IMATH_HOSTDEVICE constexpr T length2 () const IMATH_NOEXCEPT; /// Normalize in place. If length()==0, return a null vector. IMATH_HOSTDEVICE const Vec2& normalize () IMATH_NOEXCEPT; /// Normalize in place. If length()==0, throw an exception. const Vec2& normalizeExc (); /// Normalize without any checks for length()==0. Slightly faster /// than the other normalization routines, but if v.length() is /// 0.0, the result is undefined. IMATH_HOSTDEVICE const Vec2& normalizeNonNull () IMATH_NOEXCEPT; /// Return a normalized vector. Does not modify *this. IMATH_HOSTDEVICE Vec2 normalized () const IMATH_NOEXCEPT; /// Return a normalized vector. Does not modify *this. Throw an /// exception if length()==0. Vec2 normalizedExc () const; /// Return a normalized vector. Does not modify *this, and does /// not check for length()==0. Slightly faster than the other /// normalization routines, but if v.length() is 0.0, the result /// is undefined. IMATH_HOSTDEVICE Vec2 normalizedNonNull () const IMATH_NOEXCEPT; /// @} /// @{ /// @name Numeric Limits /// Largest possible negative value IMATH_HOSTDEVICE constexpr static T baseTypeLowest () IMATH_NOEXCEPT { return std::numeric_limits::lowest (); } /// Largest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeMax () IMATH_NOEXCEPT { return std::numeric_limits::max (); } /// Smallest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeSmallest () IMATH_NOEXCEPT { return std::numeric_limits::min (); } /// Smallest possible e for which 1+e != 1 IMATH_HOSTDEVICE constexpr static T baseTypeEpsilon () IMATH_NOEXCEPT { return std::numeric_limits::epsilon (); } /// @} /// Return the number of dimensions, i.e. 2 IMATH_HOSTDEVICE constexpr static unsigned int dimensions () IMATH_NOEXCEPT { return 2; } /// The base type: In templates that accept a parameter `V`, you /// can refer to `T` as `V::BaseType` typedef T BaseType; private: IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T lengthTiny () const IMATH_NOEXCEPT; }; /// /// 3-element vector /// template class IMATH_EXPORT_TEMPLATE_TYPE Vec3 { public: /// @{ /// @name Direct access to elements T x, y, z; /// @} /// Element access by index. /// /// NB: This method of access uses dynamic array accesses which /// can prevent compiler optimizations and force temporaries to be /// stored to the stack and other missed vectorization /// opportunities. Use of direct access to x, y, z when /// possible should be preferred. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T& operator[] (int i) IMATH_NOEXCEPT; /// Element access by index. /// /// NB: This method of access uses dynamic array accesses which /// can prevent compiler optimizations and force temporaries to be /// stored to the stack and other missed vectorization /// opportunities. Use of direct access to x, y, z when /// possible should be preferred. IMATH_HOSTDEVICE constexpr const T& operator[] (int i) const IMATH_NOEXCEPT; /// @{ /// @name Constructors and Assignment /// Uninitialized by default IMATH_HOSTDEVICE Vec3 () IMATH_NOEXCEPT; /// Initialize to a scalar `(a,a,a)` IMATH_HOSTDEVICE constexpr explicit Vec3 (T a) IMATH_NOEXCEPT; /// Initialize to given elements `(a,b,c)` IMATH_HOSTDEVICE constexpr Vec3 (T a, T b, T c) IMATH_NOEXCEPT; /// Copy constructor IMATH_HOSTDEVICE constexpr Vec3 (const Vec3& v) IMATH_NOEXCEPT; /// Construct from Vec3 of another base type template IMATH_HOSTDEVICE constexpr Vec3 (const Vec3& v) IMATH_NOEXCEPT; /// Vec4 to Vec3 conversion: divide x, y and z by w, even if w is /// 0. The result depends on how the environment handles /// floating-point exceptions. template IMATH_HOSTDEVICE explicit constexpr Vec3 (const Vec4& v) IMATH_NOEXCEPT; /// Vec4 to Vec3 conversion: divide x, y and z by w. Throws an /// exception if w is zero or if division by w would overflow. template explicit IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Vec3 (const Vec4& v, InfException); /// Assignment IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator= (const Vec3& v) IMATH_NOEXCEPT; /// Destructor ~Vec3 () IMATH_NOEXCEPT = default; /// @} #if IMATH_FOREIGN_VECTOR_INTEROP /// @{ /// @name Interoperability with other vector types /// /// Construction and assignment are allowed from other classes that /// appear to be equivalent vector types, provided that they have either /// a subscripting operator, or data members .x, .y, .z, that are of the /// same type as the elements of this vector, and their size appears to /// be the right number of elements. /// /// This functionality is disabled for gcc 4.x, which seems to have a /// compiler bug that results in spurious errors. It can also be /// disabled by defining IMATH_FOREIGN_VECTOR_INTEROP to be 0 prior to /// including any Imath header files. /// template ::value)> IMATH_HOSTDEVICE explicit constexpr Vec3 (const V& v) IMATH_NOEXCEPT : Vec3 (T (v.x), T (v.y), T (v.z)) {} template < typename V, IMATH_ENABLE_IF ( has_subscript::value && !has_xyz::value)> IMATH_HOSTDEVICE explicit Vec3 (const V& v) : Vec3 (T (v[0]), T (v[1]), T (v[2])) {} /// Interoperability assignment from another type that behaves as if it /// were an equivalent vector. template ::value)> IMATH_HOSTDEVICE const Vec3& operator= (const V& v) IMATH_NOEXCEPT { x = T (v.x); y = T (v.y); z = T (v.z); return *this; } template < typename V, IMATH_ENABLE_IF ( has_subscript::value && !has_xyz::value)> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator= (const V& v) { x = T (v[0]); y = T (v[1]); z = T (v[2]); return *this; } /// @} #endif /// @{ /// @name Compatibility with Sb /// Set the value template IMATH_HOSTDEVICE void setValue (S a, S b, S c) IMATH_NOEXCEPT; /// Set the value template IMATH_HOSTDEVICE void setValue (const Vec3& v) IMATH_NOEXCEPT; /// Return the value in `a`, `b`, and `c` template IMATH_HOSTDEVICE void getValue (S& a, S& b, S& c) const IMATH_NOEXCEPT; /// Return the value in `v` template IMATH_HOSTDEVICE void getValue (Vec3& v) const IMATH_NOEXCEPT; /// Return a raw pointer to the array of values IMATH_HOSTDEVICE T* getValue () IMATH_NOEXCEPT; /// Return a raw pointer to the array of values IMATH_HOSTDEVICE const T* getValue () const IMATH_NOEXCEPT; /// @} /// @{ /// @name Arithmetic and Comparison /// Equality template IMATH_HOSTDEVICE constexpr bool operator== (const Vec3& v) const IMATH_NOEXCEPT; /// Inequality template IMATH_HOSTDEVICE constexpr bool operator!= (const Vec3& v) const IMATH_NOEXCEPT; /// Compare two vectors and test if they are "approximately equal": /// @return True if the components of this and `v` are the same /// with an absolute error of no more than e, i.e., for all i: /// /// abs (this[i] - v[i]) <= e IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithAbsError (const Vec3& v, T e) const IMATH_NOEXCEPT; /// Compare two vectors and test if they are "approximately equal": /// @return True if the components of this and `v` are the same with /// a relative error of no more than e, i.e., for all i: /// /// abs (this[i] - v[i]) <= e * abs (this[i]) IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithRelError (const Vec3& v, T e) const IMATH_NOEXCEPT; /// Dot product IMATH_HOSTDEVICE constexpr T dot (const Vec3& v) const IMATH_NOEXCEPT; /// Dot product IMATH_HOSTDEVICE constexpr T operator^ (const Vec3& v) const IMATH_NOEXCEPT; /// Right-handed cross product IMATH_HOSTDEVICE constexpr Vec3 cross (const Vec3& v) const IMATH_NOEXCEPT; /// Right-handed cross product IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator%= (const Vec3& v) IMATH_NOEXCEPT; /// Right-handed cross product IMATH_HOSTDEVICE constexpr Vec3 operator% (const Vec3& v) const IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator+= (const Vec3& v) IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE constexpr Vec3 operator+ (const Vec3& v) const IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator-= (const Vec3& v) IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE constexpr Vec3 operator- (const Vec3& v) const IMATH_NOEXCEPT; /// Component-wise multiplication by -1 IMATH_HOSTDEVICE constexpr Vec3 operator- () const IMATH_NOEXCEPT; /// Component-wise multiplication by -1 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& negate () IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator*= (const Vec3& v) IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator*= (T a) IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE constexpr Vec3 operator* (const Vec3& v) const IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE constexpr Vec3 operator* (T a) const IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator/= (const Vec3& v) IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator/= (T a) IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE constexpr Vec3 operator/ (const Vec3& v) const IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE constexpr Vec3 operator/ (T a) const IMATH_NOEXCEPT; /// @} /// @{ /// @name Query and Manipulation /// Return the Euclidean norm IMATH_HOSTDEVICE T length () const IMATH_NOEXCEPT; /// Return the square of the Euclidean norm, i.e. the dot product /// with itself. IMATH_HOSTDEVICE constexpr T length2 () const IMATH_NOEXCEPT; /// Normalize in place. If length()==0, return a null vector. IMATH_HOSTDEVICE const Vec3& normalize () IMATH_NOEXCEPT; /// Normalize in place. If length()==0, throw an exception. const Vec3& normalizeExc (); /// Normalize without any checks for length()==0. Slightly faster /// than the other normalization routines, but if v.length() is /// 0.0, the result is undefined. IMATH_HOSTDEVICE const Vec3& normalizeNonNull () IMATH_NOEXCEPT; /// Return a normalized vector. Does not modify *this. IMATH_HOSTDEVICE Vec3 normalized () const IMATH_NOEXCEPT; // does not modify *this /// Return a normalized vector. Does not modify *this. Throw an /// exception if length()==0. Vec3 normalizedExc () const; /// Return a normalized vector. Does not modify *this, and does /// not check for length()==0. Slightly faster than the other /// normalization routines, but if v.length() is 0.0, the result /// is undefined. IMATH_HOSTDEVICE Vec3 normalizedNonNull () const IMATH_NOEXCEPT; /// @} /// @{ /// @name Numeric Limits /// Largest possible negative value IMATH_HOSTDEVICE constexpr static T baseTypeLowest () IMATH_NOEXCEPT { return std::numeric_limits::lowest (); } /// Largest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeMax () IMATH_NOEXCEPT { return std::numeric_limits::max (); } /// Smallest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeSmallest () IMATH_NOEXCEPT { return std::numeric_limits::min (); } /// Smallest possible e for which 1+e != 1 IMATH_HOSTDEVICE constexpr static T baseTypeEpsilon () IMATH_NOEXCEPT { return std::numeric_limits::epsilon (); } /// @} /// Return the number of dimensions, i.e. 3 IMATH_HOSTDEVICE constexpr static unsigned int dimensions () IMATH_NOEXCEPT { return 3; } /// The base type: In templates that accept a parameter `V`, you /// can refer to `T` as `V::BaseType` typedef T BaseType; private: IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T lengthTiny () const IMATH_NOEXCEPT; }; /// /// 4-element vector /// template class IMATH_EXPORT_TEMPLATE_TYPE Vec4 { public: /// @{ /// @name Direct access to elements T x, y, z, w; /// @} /// Element access by index. /// /// NB: This method of access uses dynamic array accesses which /// can prevent compiler optimizations and force temporaries to be /// stored to the stack and other missed vectorization /// opportunities. Use of direct access to x, y, z, w when /// possible should be preferred. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T& operator[] (int i) IMATH_NOEXCEPT; /// Element access by index. /// /// NB: This method of access uses dynamic array accesses which /// can prevent compiler optimizations and force temporaries to be /// stored to the stack and other missed vectorization /// opportunities. Use of direct access to x, y, z, w when /// possible should be preferred. IMATH_HOSTDEVICE constexpr const T& operator[] (int i) const IMATH_NOEXCEPT; /// @{ /// @name Constructors and Assignment /// Uninitialized by default IMATH_HOSTDEVICE Vec4 () IMATH_NOEXCEPT; // no initialization /// Initialize to a scalar `(a,a,a,a)` IMATH_HOSTDEVICE constexpr explicit Vec4 (T a) IMATH_NOEXCEPT; /// Initialize to given elements `(a,b,c,d)` IMATH_HOSTDEVICE constexpr Vec4 (T a, T b, T c, T d) IMATH_NOEXCEPT; /// Copy constructor IMATH_HOSTDEVICE constexpr Vec4 (const Vec4& v) IMATH_NOEXCEPT; /// Construct from Vec4 of another base type template IMATH_HOSTDEVICE constexpr Vec4 (const Vec4& v) IMATH_NOEXCEPT; /// Vec3 to Vec4 conversion, sets w to 1. template IMATH_HOSTDEVICE explicit constexpr Vec4 (const Vec3& v) IMATH_NOEXCEPT; /// Assignment IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& operator= (const Vec4& v) IMATH_NOEXCEPT; /// Destructor ~Vec4 () IMATH_NOEXCEPT = default; /// @} #if IMATH_FOREIGN_VECTOR_INTEROP /// @{ /// @name Interoperability with other vector types /// /// Construction and assignment are allowed from other classes that /// appear to be equivalent vector types, provided that they have either /// a subscripting operator, or data members .x, .y, .z, .w that are of /// the same type as the elements of this vector, and their size appears /// to be the right number of elements. /// /// This functionality is disabled for gcc 4.x, which seems to have a /// compiler bug that results in spurious errors. It can also be /// disabled by defining IMATH_FOREIGN_VECTOR_INTEROP to be 0 prior to /// including any Imath header files. /// template ::value)> IMATH_HOSTDEVICE explicit constexpr Vec4 (const V& v) IMATH_NOEXCEPT : Vec4 (T (v.x), T (v.y), T (v.z), T (v.w)) {} template < typename V, IMATH_ENABLE_IF ( has_subscript::value && !has_xyzw::value)> IMATH_HOSTDEVICE explicit Vec4 (const V& v) : Vec4 (T (v[0]), T (v[1]), T (v[2]), T (v[3])) {} template ::value)> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& operator= (const V& v) IMATH_NOEXCEPT { x = T (v.x); y = T (v.y); z = T (v.z); w = T (v.w); return *this; } template < typename V, IMATH_ENABLE_IF ( has_subscript::value && !has_xyzw::value)> IMATH_HOSTDEVICE const Vec4& operator= (const V& v) { x = T (v[0]); y = T (v[1]); z = T (v[2]); w = T (v[3]); return *this; } /// @} #endif /// @{ /// @name Compatibility with Sb /// Set the value template IMATH_HOSTDEVICE void setValue (S a, S b, S c, S d) IMATH_NOEXCEPT; /// Set the value template IMATH_HOSTDEVICE void setValue (const Vec4& v) IMATH_NOEXCEPT; /// Return the value in `a` and `b` template IMATH_HOSTDEVICE void getValue (S& a, S& b, S& c, S& d) const IMATH_NOEXCEPT; /// Return the value in `v` template IMATH_HOSTDEVICE void getValue (Vec4& v) const IMATH_NOEXCEPT; /// Return a raw pointer to the array of values IMATH_HOSTDEVICE T* getValue () IMATH_NOEXCEPT; /// Return a raw pointer to the array of values IMATH_HOSTDEVICE const T* getValue () const IMATH_NOEXCEPT; /// @} /// @{ /// @name Arithmetic and Comparison /// Equality template IMATH_HOSTDEVICE constexpr bool operator== (const Vec4& v) const IMATH_NOEXCEPT; /// Inequality template IMATH_HOSTDEVICE constexpr bool operator!= (const Vec4& v) const IMATH_NOEXCEPT; /// Compare two vectors and test if they are "approximately equal": /// @return True if the components of this and `v` are the same /// with an absolute error of no more than e, i.e., for all i: /// /// abs (this[i] - v[i]) <= e IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithAbsError (const Vec4& v, T e) const IMATH_NOEXCEPT; /// Compare two vectors and test if they are "approximately equal": /// @return True if the components of this and `v` are the same with /// a relative error of no more than e, i.e., for all i: /// /// abs (this[i] - v[i]) <= e * abs (this[i]) IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithRelError (const Vec4& v, T e) const IMATH_NOEXCEPT; /// Dot product IMATH_HOSTDEVICE constexpr T dot (const Vec4& v) const IMATH_NOEXCEPT; /// Dot product IMATH_HOSTDEVICE constexpr T operator^ (const Vec4& v) const IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& operator+= (const Vec4& v) IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE constexpr Vec4 operator+ (const Vec4& v) const IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& operator-= (const Vec4& v) IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE constexpr Vec4 operator- (const Vec4& v) const IMATH_NOEXCEPT; /// Component-wise multiplication by -1 IMATH_HOSTDEVICE constexpr Vec4 operator- () const IMATH_NOEXCEPT; /// Component-wise multiplication by -1 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& negate () IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& operator*= (const Vec4& v) IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& operator*= (T a) IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE constexpr Vec4 operator* (const Vec4& v) const IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE constexpr Vec4 operator* (T a) const IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& operator/= (const Vec4& v) IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& operator/= (T a) IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE constexpr Vec4 operator/ (const Vec4& v) const IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE constexpr Vec4 operator/ (T a) const IMATH_NOEXCEPT; /// @} /// @{ /// @name Query and Manipulation /// Return the Euclidean norm IMATH_HOSTDEVICE T length () const IMATH_NOEXCEPT; /// Return the square of the Euclidean norm, i.e. the dot product /// with itself. IMATH_HOSTDEVICE constexpr T length2 () const IMATH_NOEXCEPT; /// Normalize in place. If length()==0, return a null vector. IMATH_HOSTDEVICE const Vec4& normalize () IMATH_NOEXCEPT; // modifies *this /// Normalize in place. If length()==0, throw an exception. const Vec4& normalizeExc (); /// Normalize without any checks for length()==0. Slightly faster /// than the other normalization routines, but if v.length() is /// 0.0, the result is undefined. IMATH_HOSTDEVICE const Vec4& normalizeNonNull () IMATH_NOEXCEPT; /// Return a normalized vector. Does not modify *this. IMATH_HOSTDEVICE Vec4 normalized () const IMATH_NOEXCEPT; // does not modify *this /// Return a normalized vector. Does not modify *this. Throw an /// exception if length()==0. Vec4 normalizedExc () const; /// Return a normalized vector. Does not modify *this, and does /// not check for length()==0. Slightly faster than the other /// normalization routines, but if v.length() is 0.0, the result /// is undefined. IMATH_HOSTDEVICE Vec4 normalizedNonNull () const IMATH_NOEXCEPT; /// @} /// @{ /// @name Numeric Limits /// Largest possible negative value IMATH_HOSTDEVICE constexpr static T baseTypeLowest () IMATH_NOEXCEPT { return std::numeric_limits::lowest (); } /// Largest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeMax () IMATH_NOEXCEPT { return std::numeric_limits::max (); } /// Smallest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeSmallest () IMATH_NOEXCEPT { return std::numeric_limits::min (); } /// Smallest possible e for which 1+e != 1 IMATH_HOSTDEVICE constexpr static T baseTypeEpsilon () IMATH_NOEXCEPT { return std::numeric_limits::epsilon (); } /// @} /// Return the number of dimensions, i.e. 4 IMATH_HOSTDEVICE constexpr static unsigned int dimensions () IMATH_NOEXCEPT { return 4; } /// The base type: In templates that accept a parameter `V`, you /// can refer to `T` as `V::BaseType` typedef T BaseType; private: IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T lengthTiny () const IMATH_NOEXCEPT; }; /// Stream output, as "(x y)" template std::ostream& operator<< (std::ostream& s, const Vec2& v); /// Stream output, as "(x y z)" template std::ostream& operator<< (std::ostream& s, const Vec3& v); /// Stream output, as "(x y z w)" template std::ostream& operator<< (std::ostream& s, const Vec4& v); /// Reverse multiplication: S * Vec2 template IMATH_HOSTDEVICE constexpr Vec2 operator* (T a, const Vec2& v) IMATH_NOEXCEPT; /// Reverse multiplication: S * Vec3 template IMATH_HOSTDEVICE constexpr Vec3 operator* (T a, const Vec3& v) IMATH_NOEXCEPT; /// Reverse multiplication: S * Vec4 template IMATH_HOSTDEVICE constexpr Vec4 operator* (T a, const Vec4& v) IMATH_NOEXCEPT; //------------------------- // Typedefs for convenience //------------------------- /// Vec2 of half typedef Vec2 V2h; /// Vec2 of short typedef Vec2 V2s; /// Vec2 of integer typedef Vec2 V2i; /// Vec2 of int64_t typedef Vec2 V2i64; /// Vec2 of float typedef Vec2 V2f; /// Vec2 of double typedef Vec2 V2d; /// Vec3 of half typedef Vec3 V3h; /// Vec3 of short typedef Vec3 V3s; /// Vec3 of integer typedef Vec3 V3i; /// Vec3 of int64_t typedef Vec3 V3i64; /// Vec3 of float typedef Vec3 V3f; /// Vec3 of double typedef Vec3 V3d; /// Vec4 of half typedef Vec4 V4h; /// Vec4 of short typedef Vec4 V4s; /// Vec4 of integer typedef Vec4 V4i; /// Vec4 of int64_t typedef Vec4 V4i64; /// Vec4 of float typedef Vec4 V4f; /// Vec4 of double typedef Vec4 V4d; //---------------------------------------------------------------------------- // Specializations for VecN, VecN // // Normalize and length don't make sense for integer vectors, so disable them. //---------------------------------------------------------------------------- /// @cond Doxygen_Suppress // Vec2 template <> IMATH_HOSTDEVICE short Vec2::length () const IMATH_NOEXCEPT = delete; template <> IMATH_HOSTDEVICE const Vec2& Vec2::normalize () IMATH_NOEXCEPT = delete; template <> const Vec2& Vec2::normalizeExc () = delete; template <> IMATH_HOSTDEVICE const Vec2& Vec2::normalizeNonNull () IMATH_NOEXCEPT = delete; template <> IMATH_HOSTDEVICE Vec2 Vec2::normalized () const IMATH_NOEXCEPT = delete; template <> Vec2 Vec2::normalizedExc () const = delete; template <> IMATH_HOSTDEVICE Vec2 Vec2::normalizedNonNull () const IMATH_NOEXCEPT = delete; // Vec2 template <> IMATH_HOSTDEVICE int Vec2::length () const IMATH_NOEXCEPT = delete; template <> IMATH_HOSTDEVICE const Vec2& Vec2::normalize () IMATH_NOEXCEPT = delete; template <> const Vec2& Vec2::normalizeExc () = delete; template <> IMATH_HOSTDEVICE const Vec2& Vec2::normalizeNonNull () IMATH_NOEXCEPT = delete; template <> IMATH_HOSTDEVICE Vec2 Vec2::normalized () const IMATH_NOEXCEPT = delete; template <> Vec2 Vec2::normalizedExc () const = delete; template <> IMATH_HOSTDEVICE Vec2 Vec2::normalizedNonNull () const IMATH_NOEXCEPT = delete; // Vec2 template <> IMATH_HOSTDEVICE int64_t Vec2::length () const IMATH_NOEXCEPT = delete; template <> IMATH_HOSTDEVICE const Vec2& Vec2::normalize () IMATH_NOEXCEPT = delete; template <> const Vec2& Vec2::normalizeExc () = delete; template <> IMATH_HOSTDEVICE const Vec2& Vec2::normalizeNonNull () IMATH_NOEXCEPT = delete; template <> IMATH_HOSTDEVICE Vec2 Vec2::normalized () const IMATH_NOEXCEPT = delete; template <> Vec2 Vec2::normalizedExc () const = delete; template <> IMATH_HOSTDEVICE Vec2 Vec2::normalizedNonNull () const IMATH_NOEXCEPT = delete; // Vec3 template <> IMATH_HOSTDEVICE short Vec3::length () const IMATH_NOEXCEPT = delete; template <> IMATH_HOSTDEVICE const Vec3& Vec3::normalize () IMATH_NOEXCEPT = delete; template <> const Vec3& Vec3::normalizeExc () = delete; template <> IMATH_HOSTDEVICE const Vec3& Vec3::normalizeNonNull () IMATH_NOEXCEPT = delete; template <> IMATH_HOSTDEVICE Vec3 Vec3::normalized () const IMATH_NOEXCEPT = delete; template <> Vec3 Vec3::normalizedExc () const = delete; template <> IMATH_HOSTDEVICE Vec3 Vec3::normalizedNonNull () const IMATH_NOEXCEPT = delete; // Vec3 template <> IMATH_HOSTDEVICE int Vec3::length () const IMATH_NOEXCEPT = delete; template <> IMATH_HOSTDEVICE const Vec3& Vec3::normalize () IMATH_NOEXCEPT = delete; template <> const Vec3& Vec3::normalizeExc () = delete; template <> IMATH_HOSTDEVICE const Vec3& Vec3::normalizeNonNull () IMATH_NOEXCEPT = delete; template <> IMATH_HOSTDEVICE Vec3 Vec3::normalized () const IMATH_NOEXCEPT = delete; template <> Vec3 Vec3::normalizedExc () const = delete; template <> IMATH_HOSTDEVICE Vec3 Vec3::normalizedNonNull () const IMATH_NOEXCEPT = delete; // Vec3 template <> IMATH_HOSTDEVICE int64_t Vec3::length () const IMATH_NOEXCEPT = delete; template <> IMATH_HOSTDEVICE const Vec3& Vec3::normalize () IMATH_NOEXCEPT = delete; template <> const Vec3& Vec3::normalizeExc () = delete; template <> IMATH_HOSTDEVICE const Vec3& Vec3::normalizeNonNull () IMATH_NOEXCEPT = delete; template <> IMATH_HOSTDEVICE Vec3 Vec3::normalized () const IMATH_NOEXCEPT = delete; template <> Vec3 Vec3::normalizedExc () const = delete; template <> IMATH_HOSTDEVICE Vec3 Vec3::normalizedNonNull () const IMATH_NOEXCEPT = delete; // Vec4 template <> IMATH_HOSTDEVICE short Vec4::length () const IMATH_NOEXCEPT = delete; template <> IMATH_HOSTDEVICE const Vec4& Vec4::normalize () IMATH_NOEXCEPT = delete; template <> const Vec4& Vec4::normalizeExc () = delete; template <> IMATH_HOSTDEVICE const Vec4& Vec4::normalizeNonNull () IMATH_NOEXCEPT = delete; template <> IMATH_HOSTDEVICE Vec4 Vec4::normalized () const IMATH_NOEXCEPT = delete; template <> Vec4 Vec4::normalizedExc () const = delete; template <> IMATH_HOSTDEVICE Vec4 Vec4::normalizedNonNull () const IMATH_NOEXCEPT = delete; // Vec4 template <> IMATH_HOSTDEVICE int Vec4::length () const IMATH_NOEXCEPT = delete; template <> IMATH_HOSTDEVICE const Vec4& Vec4::normalize () IMATH_NOEXCEPT = delete; template <> const Vec4& Vec4::normalizeExc () = delete; template <> IMATH_HOSTDEVICE const Vec4& Vec4::normalizeNonNull () IMATH_NOEXCEPT = delete; template <> IMATH_HOSTDEVICE Vec4 Vec4::normalized () const IMATH_NOEXCEPT = delete; template <> Vec4 Vec4::normalizedExc () const = delete; template <> IMATH_HOSTDEVICE Vec4 Vec4::normalizedNonNull () const IMATH_NOEXCEPT = delete; // Vec4 template <> IMATH_HOSTDEVICE int64_t Vec4::length () const IMATH_NOEXCEPT = delete; template <> IMATH_HOSTDEVICE const Vec4& Vec4::normalize () IMATH_NOEXCEPT = delete; template <> const Vec4& Vec4::normalizeExc () = delete; template <> IMATH_HOSTDEVICE const Vec4& Vec4::normalizeNonNull () IMATH_NOEXCEPT = delete; template <> IMATH_HOSTDEVICE Vec4 Vec4::normalized () const IMATH_NOEXCEPT = delete; template <> Vec4 Vec4::normalizedExc () const = delete; template <> IMATH_HOSTDEVICE Vec4 Vec4::normalizedNonNull () const IMATH_NOEXCEPT = delete; /// @endcond Doxygen_Suppress //------------------------ // Implementation of Vec2: //------------------------ template IMATH_CONSTEXPR14 IMATH_HOSTDEVICE inline T& Vec2::operator[] (int i) IMATH_NOEXCEPT { return reinterpret_cast (this)[i]; } template constexpr IMATH_HOSTDEVICE inline const T& Vec2::operator[] (int i) const IMATH_NOEXCEPT { #ifdef __cpp_if_consteval if consteval { return (i == 0) ? x : y; } else { return reinterpret_cast (this)[i]; } #else return reinterpret_cast (this)[i]; #endif } template IMATH_HOSTDEVICE inline Vec2::Vec2 () IMATH_NOEXCEPT { // empty, and not constexpr because data is uninitialized. } template IMATH_HOSTDEVICE constexpr inline Vec2::Vec2 (T a) IMATH_NOEXCEPT : x (a), y (a) {} template IMATH_HOSTDEVICE constexpr inline Vec2::Vec2 (T a, T b) IMATH_NOEXCEPT : x (a), y (b) {} template IMATH_HOSTDEVICE constexpr inline Vec2::Vec2 (const Vec2& v) IMATH_NOEXCEPT : x (v.x), y (v.y) {} template template IMATH_HOSTDEVICE constexpr inline Vec2::Vec2 (const Vec2& v) IMATH_NOEXCEPT : x (T (v.x)), y (T (v.y)) {} template IMATH_CONSTEXPR14 IMATH_HOSTDEVICE inline const Vec2& Vec2::operator= (const Vec2& v) IMATH_NOEXCEPT { x = v.x; y = v.y; return *this; } template template IMATH_HOSTDEVICE inline void Vec2::setValue (S a, S b) IMATH_NOEXCEPT { x = T (a); y = T (b); } template template IMATH_HOSTDEVICE inline void Vec2::setValue (const Vec2& v) IMATH_NOEXCEPT { x = T (v.x); y = T (v.y); } template template IMATH_HOSTDEVICE inline void Vec2::getValue (S& a, S& b) const IMATH_NOEXCEPT { a = S (x); b = S (y); } template template IMATH_HOSTDEVICE inline void Vec2::getValue (Vec2& v) const IMATH_NOEXCEPT { v.x = S (x); v.y = S (y); } template IMATH_HOSTDEVICE inline T* Vec2::getValue () IMATH_NOEXCEPT { return reinterpret_cast (this); } template IMATH_HOSTDEVICE inline const T* Vec2::getValue () const IMATH_NOEXCEPT { return reinterpret_cast (this); } template template IMATH_HOSTDEVICE constexpr inline bool Vec2::operator== (const Vec2& v) const IMATH_NOEXCEPT { return x == v.x && y == v.y; } template template IMATH_HOSTDEVICE constexpr inline bool Vec2::operator!= (const Vec2& v) const IMATH_NOEXCEPT { return x != v.x || y != v.y; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool Vec2::equalWithAbsError (const Vec2& v, T e) const IMATH_NOEXCEPT { if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError (x, v.x, e)) return false; if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError (y, v.y, e)) return false; return true; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool Vec2::equalWithRelError (const Vec2& v, T e) const IMATH_NOEXCEPT { if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError (x, v.x, e)) return false; if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError (y, v.y, e)) return false; return true; } template IMATH_HOSTDEVICE constexpr inline T Vec2::dot (const Vec2& v) const IMATH_NOEXCEPT { return x * v.x + y * v.y; } template IMATH_HOSTDEVICE constexpr inline T Vec2::operator^ (const Vec2& v) const IMATH_NOEXCEPT { return dot (v); } template IMATH_HOSTDEVICE constexpr inline T Vec2::cross (const Vec2& v) const IMATH_NOEXCEPT { return x * v.y - y * v.x; } template IMATH_HOSTDEVICE constexpr inline T Vec2::operator% (const Vec2& v) const IMATH_NOEXCEPT { return x * v.y - y * v.x; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2& Vec2::operator+= (const Vec2& v) IMATH_NOEXCEPT { x += v.x; y += v.y; return *this; } template IMATH_HOSTDEVICE constexpr inline Vec2 Vec2::operator+ (const Vec2& v) const IMATH_NOEXCEPT { return Vec2 (x + v.x, y + v.y); } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2& Vec2::operator-= (const Vec2& v) IMATH_NOEXCEPT { x -= v.x; y -= v.y; return *this; } template IMATH_HOSTDEVICE constexpr inline Vec2 Vec2::operator- (const Vec2& v) const IMATH_NOEXCEPT { return Vec2 (x - v.x, y - v.y); } template IMATH_HOSTDEVICE constexpr inline Vec2 Vec2::operator- () const IMATH_NOEXCEPT { return Vec2 (-x, -y); } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2& Vec2::negate () IMATH_NOEXCEPT { x = -x; y = -y; return *this; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2& Vec2::operator*= (const Vec2& v) IMATH_NOEXCEPT { x *= v.x; y *= v.y; return *this; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2& Vec2::operator*= (T a) IMATH_NOEXCEPT { x *= a; y *= a; return *this; } template IMATH_HOSTDEVICE constexpr inline Vec2 Vec2::operator* (const Vec2& v) const IMATH_NOEXCEPT { return Vec2 (x * v.x, y * v.y); } template IMATH_HOSTDEVICE constexpr inline Vec2 Vec2::operator* (T a) const IMATH_NOEXCEPT { return Vec2 (x * a, y * a); } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2& Vec2::operator/= (const Vec2& v) IMATH_NOEXCEPT { x /= v.x; y /= v.y; return *this; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2& Vec2::operator/= (T a) IMATH_NOEXCEPT { x /= a; y /= a; return *this; } template IMATH_HOSTDEVICE constexpr inline Vec2 Vec2::operator/ (const Vec2& v) const IMATH_NOEXCEPT { return Vec2 (x / v.x, y / v.y); } template IMATH_HOSTDEVICE constexpr inline Vec2 Vec2::operator/ (T a) const IMATH_NOEXCEPT { return Vec2 (x / a, y / a); } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline T Vec2::lengthTiny () const IMATH_NOEXCEPT { T absX = std::abs (x); T absY = std::abs (y); T max = absX; if (max < absY) max = absY; if (IMATH_UNLIKELY (max == T (0))) return T (0); // // Do not replace the divisions by max with multiplications by 1/max. // Computing 1/max can overflow but the divisions below will always // produce results less than or equal to 1. // absX /= max; absY /= max; return max * std::sqrt (absX * absX + absY * absY); } template IMATH_HOSTDEVICE inline T Vec2::length () const IMATH_NOEXCEPT { T length2 = dot (*this); if (IMATH_UNLIKELY (length2 < T (2) * std::numeric_limits::min ())) return lengthTiny (); return std::sqrt (length2); } template IMATH_HOSTDEVICE constexpr inline T Vec2::length2 () const IMATH_NOEXCEPT { return dot (*this); } template IMATH_HOSTDEVICE inline const Vec2& Vec2::normalize () IMATH_NOEXCEPT { T l = length (); if (IMATH_LIKELY (l != T (0))) { // // Do not replace the divisions by l with multiplications by 1/l. // Computing 1/l can overflow but the divisions below will always // produce results less than or equal to 1. // x /= l; y /= l; } return *this; } template inline const Vec2& Vec2::normalizeExc () { T l = length (); if (IMATH_UNLIKELY (l == T (0))) throw std::domain_error ("Cannot normalize null vector."); x /= l; y /= l; return *this; } template IMATH_HOSTDEVICE inline const Vec2& Vec2::normalizeNonNull () IMATH_NOEXCEPT { T l = length (); x /= l; y /= l; return *this; } template IMATH_HOSTDEVICE inline Vec2 Vec2::normalized () const IMATH_NOEXCEPT { T l = length (); if (IMATH_UNLIKELY (l == T (0))) return Vec2 (T (0)); return Vec2 (x / l, y / l); } template inline Vec2 Vec2::normalizedExc () const { T l = length (); if (IMATH_UNLIKELY (l == T (0))) throw std::domain_error ("Cannot normalize null vector."); return Vec2 (x / l, y / l); } template IMATH_HOSTDEVICE inline Vec2 Vec2::normalizedNonNull () const IMATH_NOEXCEPT { T l = length (); return Vec2 (x / l, y / l); } //----------------------- // Implementation of Vec3 //----------------------- template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline T& Vec3::operator[] (int i) IMATH_NOEXCEPT { return reinterpret_cast (this)[i]; } template constexpr IMATH_HOSTDEVICE inline const T& Vec3::operator[] (int i) const IMATH_NOEXCEPT { #ifdef __cpp_if_consteval if consteval { return (i == 0) ? x : ((i == 1) ? y : z); } else { return reinterpret_cast (this)[i]; } #else return reinterpret_cast (this)[i]; #endif } template IMATH_HOSTDEVICE inline Vec3::Vec3 () IMATH_NOEXCEPT { // empty, and not constexpr because data is uninitialized. } template IMATH_HOSTDEVICE constexpr inline Vec3::Vec3 (T a) IMATH_NOEXCEPT : x (a), y (a), z (a) {} template IMATH_HOSTDEVICE constexpr inline Vec3::Vec3 (T a, T b, T c) IMATH_NOEXCEPT : x (a), y (b), z (c) {} template IMATH_HOSTDEVICE constexpr inline Vec3::Vec3 (const Vec3& v) IMATH_NOEXCEPT : x (v.x), y (v.y), z (v.z) {} template template IMATH_HOSTDEVICE constexpr inline Vec3::Vec3 (const Vec3& v) IMATH_NOEXCEPT : x (T (v.x)), y (T (v.y)), z (T (v.z)) {} template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3& Vec3::operator= (const Vec3& v) IMATH_NOEXCEPT { x = v.x; y = v.y; z = v.z; return *this; } template template IMATH_HOSTDEVICE constexpr inline Vec3::Vec3 (const Vec4& v) IMATH_NOEXCEPT : x (T (v.x / v.w)), y (T (v.y / v.w)), z (T (v.z / v.w)) {} template template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Vec3::Vec3 (const Vec4& v, InfException) { T vx = T (v.x); T vy = T (v.y); T vz = T (v.z); T vw = T (v.w); T absW = (vw >= T (0)) ? vw : -vw; if (absW < 1) { T m = baseTypeMax () * absW; if (vx <= -m || vx >= m || vy <= -m || vy >= m || vz <= -m || vz >= m) throw std::domain_error ("Cannot normalize point at infinity."); } x = vx / vw; y = vy / vw; z = vz / vw; } template template IMATH_HOSTDEVICE inline void Vec3::setValue (S a, S b, S c) IMATH_NOEXCEPT { x = T (a); y = T (b); z = T (c); } template template IMATH_HOSTDEVICE inline void Vec3::setValue (const Vec3& v) IMATH_NOEXCEPT { x = T (v.x); y = T (v.y); z = T (v.z); } template template IMATH_HOSTDEVICE inline void Vec3::getValue (S& a, S& b, S& c) const IMATH_NOEXCEPT { a = S (x); b = S (y); c = S (z); } template template IMATH_HOSTDEVICE inline void Vec3::getValue (Vec3& v) const IMATH_NOEXCEPT { v.x = S (x); v.y = S (y); v.z = S (z); } template IMATH_HOSTDEVICE inline T* Vec3::getValue () IMATH_NOEXCEPT { return reinterpret_cast (this); } template IMATH_HOSTDEVICE inline const T* Vec3::getValue () const IMATH_NOEXCEPT { return reinterpret_cast (this); } template template IMATH_HOSTDEVICE constexpr inline bool Vec3::operator== (const Vec3& v) const IMATH_NOEXCEPT { return x == v.x && y == v.y && z == v.z; } template template IMATH_HOSTDEVICE constexpr inline bool Vec3::operator!= (const Vec3& v) const IMATH_NOEXCEPT { return x != v.x || y != v.y || z != v.z; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool Vec3::equalWithAbsError (const Vec3& v, T e) const IMATH_NOEXCEPT { for (int i = 0; i < 3; i++) if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i], v[i], e)) return false; return true; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool Vec3::equalWithRelError (const Vec3& v, T e) const IMATH_NOEXCEPT { for (int i = 0; i < 3; i++) if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i], v[i], e)) return false; return true; } template IMATH_HOSTDEVICE constexpr inline T Vec3::dot (const Vec3& v) const IMATH_NOEXCEPT { return x * v.x + y * v.y + z * v.z; } template IMATH_HOSTDEVICE constexpr inline T Vec3::operator^ (const Vec3& v) const IMATH_NOEXCEPT { return dot (v); } template IMATH_HOSTDEVICE constexpr inline Vec3 Vec3::cross (const Vec3& v) const IMATH_NOEXCEPT { return Vec3 (y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x); } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3& Vec3::operator%= (const Vec3& v) IMATH_NOEXCEPT { T a = y * v.z - z * v.y; T b = z * v.x - x * v.z; T c = x * v.y - y * v.x; x = a; y = b; z = c; return *this; } template IMATH_HOSTDEVICE constexpr inline Vec3 Vec3::operator% (const Vec3& v) const IMATH_NOEXCEPT { return Vec3 (y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x); } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3& Vec3::operator+= (const Vec3& v) IMATH_NOEXCEPT { x += v.x; y += v.y; z += v.z; return *this; } template IMATH_HOSTDEVICE constexpr inline Vec3 Vec3::operator+ (const Vec3& v) const IMATH_NOEXCEPT { return Vec3 (x + v.x, y + v.y, z + v.z); } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3& Vec3::operator-= (const Vec3& v) IMATH_NOEXCEPT { x -= v.x; y -= v.y; z -= v.z; return *this; } template IMATH_HOSTDEVICE constexpr inline Vec3 Vec3::operator- (const Vec3& v) const IMATH_NOEXCEPT { return Vec3 (x - v.x, y - v.y, z - v.z); } template IMATH_HOSTDEVICE constexpr inline Vec3 Vec3::operator- () const IMATH_NOEXCEPT { return Vec3 (-x, -y, -z); } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3& Vec3::negate () IMATH_NOEXCEPT { x = -x; y = -y; z = -z; return *this; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3& Vec3::operator*= (const Vec3& v) IMATH_NOEXCEPT { x *= v.x; y *= v.y; z *= v.z; return *this; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3& Vec3::operator*= (T a) IMATH_NOEXCEPT { x *= a; y *= a; z *= a; return *this; } template IMATH_HOSTDEVICE constexpr inline Vec3 Vec3::operator* (const Vec3& v) const IMATH_NOEXCEPT { return Vec3 (x * v.x, y * v.y, z * v.z); } template IMATH_HOSTDEVICE constexpr inline Vec3 Vec3::operator* (T a) const IMATH_NOEXCEPT { return Vec3 (x * a, y * a, z * a); } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3& Vec3::operator/= (const Vec3& v) IMATH_NOEXCEPT { x /= v.x; y /= v.y; z /= v.z; return *this; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3& Vec3::operator/= (T a) IMATH_NOEXCEPT { x /= a; y /= a; z /= a; return *this; } template IMATH_HOSTDEVICE constexpr inline Vec3 Vec3::operator/ (const Vec3& v) const IMATH_NOEXCEPT { return Vec3 (x / v.x, y / v.y, z / v.z); } template IMATH_HOSTDEVICE constexpr inline Vec3 Vec3::operator/ (T a) const IMATH_NOEXCEPT { return Vec3 (x / a, y / a, z / a); } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline T Vec3::lengthTiny () const IMATH_NOEXCEPT { T absX = (x >= T (0)) ? x : -x; T absY = (y >= T (0)) ? y : -y; T absZ = (z >= T (0)) ? z : -z; T max = absX; if (max < absY) max = absY; if (max < absZ) max = absZ; if (IMATH_UNLIKELY (max == T (0))) return T (0); // // Do not replace the divisions by max with multiplications by 1/max. // Computing 1/max can overflow but the divisions below will always // produce results less than or equal to 1. // absX /= max; absY /= max; absZ /= max; return max * std::sqrt (absX * absX + absY * absY + absZ * absZ); } template IMATH_HOSTDEVICE inline T Vec3::length () const IMATH_NOEXCEPT { T length2 = dot (*this); if (IMATH_UNLIKELY (length2 < T (2) * std::numeric_limits::min ())) return lengthTiny (); return std::sqrt (length2); } template IMATH_HOSTDEVICE constexpr inline T Vec3::length2 () const IMATH_NOEXCEPT { return dot (*this); } template IMATH_HOSTDEVICE inline const Vec3& Vec3::normalize () IMATH_NOEXCEPT { T l = length (); if (IMATH_LIKELY (l != T (0))) { // // Do not replace the divisions by l with multiplications by 1/l. // Computing 1/l can overflow but the divisions below will always // produce results less than or equal to 1. // x /= l; y /= l; z /= l; } return *this; } template inline const Vec3& Vec3::normalizeExc () { T l = length (); if (IMATH_UNLIKELY (l == T (0))) throw std::domain_error ("Cannot normalize null vector."); x /= l; y /= l; z /= l; return *this; } template IMATH_HOSTDEVICE inline const Vec3& Vec3::normalizeNonNull () IMATH_NOEXCEPT { T l = length (); x /= l; y /= l; z /= l; return *this; } template IMATH_HOSTDEVICE inline Vec3 Vec3::normalized () const IMATH_NOEXCEPT { T l = length (); if (IMATH_UNLIKELY ((l == T (0)))) return Vec3 (T (0)); return Vec3 (x / l, y / l, z / l); } template inline Vec3 Vec3::normalizedExc () const { T l = length (); if (IMATH_UNLIKELY (l == T (0))) throw std::domain_error ("Cannot normalize null vector."); return Vec3 (x / l, y / l, z / l); } template IMATH_HOSTDEVICE inline Vec3 Vec3::normalizedNonNull () const IMATH_NOEXCEPT { T l = length (); return Vec3 (x / l, y / l, z / l); } //----------------------- // Implementation of Vec4 //----------------------- template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline T& Vec4::operator[] (int i) IMATH_NOEXCEPT { return reinterpret_cast (this)[i]; } template IMATH_HOSTDEVICE constexpr inline const T& Vec4::operator[] (int i) const IMATH_NOEXCEPT { #ifdef __cpp_if_consteval if consteval { return (i == 0) ? x : ((i == 1) ? y : ((i == 2) ? z : w)); } else { return reinterpret_cast (this)[i]; } #else return reinterpret_cast (this)[i]; #endif } template IMATH_HOSTDEVICE inline Vec4::Vec4 () IMATH_NOEXCEPT { // empty, and not constexpr because data is uninitialized. } template IMATH_HOSTDEVICE constexpr inline Vec4::Vec4 (T a) IMATH_NOEXCEPT : x (a), y (a), z (a), w (a) {} template IMATH_HOSTDEVICE constexpr inline Vec4::Vec4 (T a, T b, T c, T d) IMATH_NOEXCEPT : x (a), y (b), z (c), w (d) {} template IMATH_HOSTDEVICE constexpr inline Vec4::Vec4 (const Vec4& v) IMATH_NOEXCEPT : x (v.x), y (v.y), z (v.z), w (v.w) {} template template IMATH_HOSTDEVICE constexpr inline Vec4::Vec4 (const Vec4& v) IMATH_NOEXCEPT : x (T (v.x)), y (T (v.y)), z (T (v.z)), w (T (v.w)) {} template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4& Vec4::operator= (const Vec4& v) IMATH_NOEXCEPT { x = v.x; y = v.y; z = v.z; w = v.w; return *this; } template template IMATH_HOSTDEVICE constexpr inline Vec4::Vec4 (const Vec3& v) IMATH_NOEXCEPT : x (T (v.x)), y (T (v.y)), z (T (v.z)), w (T (1)) {} template template IMATH_HOSTDEVICE inline void Vec4::setValue (S a, S b, S c, S d) IMATH_NOEXCEPT { x = T (a); y = T (b); z = T (c); w = T (d); } template template IMATH_HOSTDEVICE inline void Vec4::setValue (const Vec4& v) IMATH_NOEXCEPT { x = T (v.x); y = T (v.y); z = T (v.z); w = T (v.w); } template template IMATH_HOSTDEVICE inline void Vec4::getValue (S& a, S& b, S& c, S& d) const IMATH_NOEXCEPT { a = S (x); b = S (y); c = S (z); d = S (w); } template template IMATH_HOSTDEVICE inline void Vec4::getValue (Vec4& v) const IMATH_NOEXCEPT { v.x = S (x); v.y = S (y); v.z = S (z); v.w = S (w); } template IMATH_HOSTDEVICE inline T* Vec4::getValue () IMATH_NOEXCEPT { return reinterpret_cast (this); } template IMATH_HOSTDEVICE inline const T* Vec4::getValue () const IMATH_NOEXCEPT { return reinterpret_cast (this); } template template IMATH_HOSTDEVICE constexpr inline bool Vec4::operator== (const Vec4& v) const IMATH_NOEXCEPT { return x == v.x && y == v.y && z == v.z && w == v.w; } template template IMATH_HOSTDEVICE constexpr inline bool Vec4::operator!= (const Vec4& v) const IMATH_NOEXCEPT { return x != v.x || y != v.y || z != v.z || w != v.w; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool Vec4::equalWithAbsError (const Vec4& v, T e) const IMATH_NOEXCEPT { for (int i = 0; i < 4; i++) if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i], v[i], e)) return false; return true; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool Vec4::equalWithRelError (const Vec4& v, T e) const IMATH_NOEXCEPT { for (int i = 0; i < 4; i++) if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i], v[i], e)) return false; return true; } template IMATH_HOSTDEVICE constexpr inline T Vec4::dot (const Vec4& v) const IMATH_NOEXCEPT { return x * v.x + y * v.y + z * v.z + w * v.w; } template IMATH_HOSTDEVICE constexpr inline T Vec4::operator^ (const Vec4& v) const IMATH_NOEXCEPT { return dot (v); } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4& Vec4::operator+= (const Vec4& v) IMATH_NOEXCEPT { x += v.x; y += v.y; z += v.z; w += v.w; return *this; } template IMATH_HOSTDEVICE constexpr inline Vec4 Vec4::operator+ (const Vec4& v) const IMATH_NOEXCEPT { return Vec4 (x + v.x, y + v.y, z + v.z, w + v.w); } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4& Vec4::operator-= (const Vec4& v) IMATH_NOEXCEPT { x -= v.x; y -= v.y; z -= v.z; w -= v.w; return *this; } template IMATH_HOSTDEVICE constexpr inline Vec4 Vec4::operator- (const Vec4& v) const IMATH_NOEXCEPT { return Vec4 (x - v.x, y - v.y, z - v.z, w - v.w); } template IMATH_HOSTDEVICE constexpr inline Vec4 Vec4::operator- () const IMATH_NOEXCEPT { return Vec4 (-x, -y, -z, -w); } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4& Vec4::negate () IMATH_NOEXCEPT { x = -x; y = -y; z = -z; w = -w; return *this; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4& Vec4::operator*= (const Vec4& v) IMATH_NOEXCEPT { x *= v.x; y *= v.y; z *= v.z; w *= v.w; return *this; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4& Vec4::operator*= (T a) IMATH_NOEXCEPT { x *= a; y *= a; z *= a; w *= a; return *this; } template IMATH_HOSTDEVICE constexpr inline Vec4 Vec4::operator* (const Vec4& v) const IMATH_NOEXCEPT { return Vec4 (x * v.x, y * v.y, z * v.z, w * v.w); } template IMATH_HOSTDEVICE constexpr inline Vec4 Vec4::operator* (T a) const IMATH_NOEXCEPT { return Vec4 (x * a, y * a, z * a, w * a); } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4& Vec4::operator/= (const Vec4& v) IMATH_NOEXCEPT { x /= v.x; y /= v.y; z /= v.z; w /= v.w; return *this; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4& Vec4::operator/= (T a) IMATH_NOEXCEPT { x /= a; y /= a; z /= a; w /= a; return *this; } template IMATH_HOSTDEVICE constexpr inline Vec4 Vec4::operator/ (const Vec4& v) const IMATH_NOEXCEPT { return Vec4 (x / v.x, y / v.y, z / v.z, w / v.w); } template IMATH_HOSTDEVICE constexpr inline Vec4 Vec4::operator/ (T a) const IMATH_NOEXCEPT { return Vec4 (x / a, y / a, z / a, w / a); } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline T Vec4::lengthTiny () const IMATH_NOEXCEPT { T absX = (x >= T (0)) ? x : -x; T absY = (y >= T (0)) ? y : -y; T absZ = (z >= T (0)) ? z : -z; T absW = (w >= T (0)) ? w : -w; T max = absX; if (max < absY) max = absY; if (max < absZ) max = absZ; if (max < absW) max = absW; if (IMATH_UNLIKELY (max == T (0))) return T (0); // // Do not replace the divisions by max with multiplications by 1/max. // Computing 1/max can overflow but the divisions below will always // produce results less than or equal to 1. // absX /= max; absY /= max; absZ /= max; absW /= max; return max * std::sqrt (absX * absX + absY * absY + absZ * absZ + absW * absW); } template IMATH_HOSTDEVICE inline T Vec4::length () const IMATH_NOEXCEPT { T length2 = dot (*this); if (IMATH_UNLIKELY (length2 < T (2) * std::numeric_limits::min ())) return lengthTiny (); return std::sqrt (length2); } template IMATH_HOSTDEVICE constexpr inline T Vec4::length2 () const IMATH_NOEXCEPT { return dot (*this); } template IMATH_HOSTDEVICE const inline Vec4& Vec4::normalize () IMATH_NOEXCEPT { T l = length (); if (IMATH_LIKELY (l != T (0))) { // // Do not replace the divisions by l with multiplications by 1/l. // Computing 1/l can overflow but the divisions below will always // produce results less than or equal to 1. // x /= l; y /= l; z /= l; w /= l; } return *this; } template const inline Vec4& Vec4::normalizeExc () { T l = length (); if (IMATH_UNLIKELY (l == T (0))) throw std::domain_error ("Cannot normalize null vector."); x /= l; y /= l; z /= l; w /= l; return *this; } template IMATH_HOSTDEVICE inline const Vec4& Vec4::normalizeNonNull () IMATH_NOEXCEPT { T l = length (); x /= l; y /= l; z /= l; w /= l; return *this; } template IMATH_HOSTDEVICE inline Vec4 Vec4::normalized () const IMATH_NOEXCEPT { T l = length (); if (IMATH_UNLIKELY (l == T (0))) return Vec4 (T (0)); return Vec4 (x / l, y / l, z / l, w / l); } template inline Vec4 Vec4::normalizedExc () const { T l = length (); if (IMATH_UNLIKELY (l == T (0))) throw std::domain_error ("Cannot normalize null vector."); return Vec4 (x / l, y / l, z / l, w / l); } template IMATH_HOSTDEVICE inline Vec4 Vec4::normalizedNonNull () const IMATH_NOEXCEPT { T l = length (); return Vec4 (x / l, y / l, z / l, w / l); } //----------------------------- // Stream output implementation //----------------------------- template std::ostream& operator<< (std::ostream& s, const Vec2& v) { return s << '(' << v.x << ' ' << v.y << ')'; } template std::ostream& operator<< (std::ostream& s, const Vec3& v) { return s << '(' << v.x << ' ' << v.y << ' ' << v.z << ')'; } template std::ostream& operator<< (std::ostream& s, const Vec4& v) { return s << '(' << v.x << ' ' << v.y << ' ' << v.z << ' ' << v.w << ')'; } //----------------------------------------- // Implementation of reverse multiplication //----------------------------------------- template IMATH_HOSTDEVICE constexpr inline Vec2 operator* (T a, const Vec2& v) IMATH_NOEXCEPT { return Vec2 (a * v.x, a * v.y); } template IMATH_HOSTDEVICE constexpr inline Vec3 operator* (T a, const Vec3& v) IMATH_NOEXCEPT { return Vec3 (a * v.x, a * v.y, a * v.z); } template IMATH_HOSTDEVICE constexpr inline Vec4 operator* (T a, const Vec4& v) IMATH_NOEXCEPT { return Vec4 (a * v.x, a * v.y, a * v.z, a * v.w); } #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER # pragma warning(pop) #endif IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #endif // INCLUDED_IMATHVEC_H