// // 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 #include "ImathExport.h" #include "ImathNamespace.h" #include "ImathTypeTraits.h" #include "ImathMath.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. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T& operator[] (int i) IMATH_NOEXCEPT; /// Element access by index. 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::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::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 matrices and test if they are "approximately equal": /// @return True if the coefficients of this and `m` are the same /// with an absolute error of no more than e, i.e., for all i, j: /// /// abs (this[i][j] - m[i][j]) <= e IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithAbsError (const Vec2& v, T e) const IMATH_NOEXCEPT; /// Compare two matrices and test if they are "approximately equal": /// @return True if the coefficients of this and m are the same with /// a relative error of no more than e, i.e., for all i, j: /// /// abs (this[i] - v[i][j]) <= e * abs (this[i][j]) 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. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T& operator[] (int i) IMATH_NOEXCEPT; /// Element access by index. 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::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::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 matrices and test if they are "approximately equal": /// @return True if the coefficients of this and `m` are the same /// with an absolute error of no more than e, i.e., for all i, j: /// /// abs (this[i][j] - m[i][j]) <= e IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithAbsError (const Vec3& v, T e) const IMATH_NOEXCEPT; /// Compare two matrices and test if they are "approximately equal": /// @return True if the coefficients of this and m are the same with /// a relative error of no more than e, i.e., for all i, j: /// /// abs (this[i] - v[i][j]) <= e * abs (this[i][j]) 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. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T& operator[] (int i) IMATH_NOEXCEPT; /// Element access by index. 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::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::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 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 matrices and test if they are "approximately equal": /// @return True if the coefficients of this and `m` are the same /// with an absolute error of no more than e, i.e., for all i, j: /// /// abs (this[i][j] - m[i][j]) <= e IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithAbsError (const Vec4& v, T e) const IMATH_NOEXCEPT; /// Compare two matrices and test if they are "approximately equal": /// @return True if the coefficients of this and m are the same with /// a relative error of no more than e, i.e., for all i, j: /// /// abs (this[i] - v[i][j]) <= e * abs (this[i][j]) 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 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 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 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 (&x)[i]; // NOSONAR - suppress SonarCloud bug report. } template constexpr IMATH_HOSTDEVICE inline const T& Vec2::operator[] (int i) const IMATH_NOEXCEPT { return (&x)[i]; // NOSONAR - suppress SonarCloud bug report. } 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 (T*) &x; } template IMATH_HOSTDEVICE inline const T* Vec2::getValue() const IMATH_NOEXCEPT { return (const T*) &x; } 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 { for (int i = 0; i < 2; i++) if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i], v[i], e)) return false; return true; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool Vec2::equalWithRelError (const Vec2& v, T e) const IMATH_NOEXCEPT { for (int i = 0; i < 2; i++) if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i], v[i], 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 (&x)[i]; // NOSONAR - suppress SonarCloud bug report. } template IMATH_HOSTDEVICE constexpr inline const T& Vec3::operator[] (int i) const IMATH_NOEXCEPT { return (&x)[i]; // NOSONAR - suppress SonarCloud bug report. } 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 (T*) &x; } template IMATH_HOSTDEVICE inline const T* Vec3::getValue() const IMATH_NOEXCEPT { return (const T*) &x; } 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 (&x)[i]; // NOSONAR - suppress SonarCloud bug report. } template IMATH_HOSTDEVICE constexpr inline const T& Vec4::operator[] (int i) const IMATH_NOEXCEPT { return (&x)[i]; // NOSONAR - suppress SonarCloud bug report. } 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 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