2 // SPDX-License-Identifier: BSD-3-Clause
3 // Copyright Contributors to the OpenEXR Project.
7 // 2D, 3D and 4D point/vector class templates
10 #ifndef INCLUDED_IMATHVEC_H
11 #define INCLUDED_IMATHVEC_H
13 #include "ImathExport.h"
14 #include "ImathNamespace.h"
15 #include "ImathTypeTraits.h"
17 #include "ImathMath.h"
24 #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
25 // suppress exception specification warnings
26 # pragma warning(push)
27 # pragma warning(disable : 4290)
30 IMATH_INTERNAL_NAMESPACE_HEADER_ENTER
32 template <class T> class Vec2;
33 template <class T> class Vec3;
34 template <class T> class Vec4;
36 /// Enum for the Vec4 to Vec3 conversion constructor
37 enum IMATH_EXPORT_ENUM InfException
46 template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Vec2
51 /// @name Direct access to elements
57 /// Element access by index.
58 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T& operator[] (int i) IMATH_NOEXCEPT;
60 /// Element access by index.
61 IMATH_HOSTDEVICE constexpr const T& operator[] (int i) const IMATH_NOEXCEPT;
64 /// @name Constructors and Assignment
66 /// Uninitialized by default
67 IMATH_HOSTDEVICE Vec2() IMATH_NOEXCEPT;
69 /// Initialize to a scalar `(a,a)`
70 IMATH_HOSTDEVICE constexpr explicit Vec2 (T a) IMATH_NOEXCEPT;
72 /// Initialize to given elements `(a,b)`
73 IMATH_HOSTDEVICE constexpr Vec2 (T a, T b) IMATH_NOEXCEPT;
76 IMATH_HOSTDEVICE constexpr Vec2 (const Vec2& v) IMATH_NOEXCEPT;
78 /// Construct from Vec2 of another base type
79 template <class S> IMATH_HOSTDEVICE constexpr Vec2 (const Vec2<S>& v) IMATH_NOEXCEPT;
83 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& operator= (const Vec2& v) IMATH_NOEXCEPT;
86 ~Vec2() IMATH_NOEXCEPT = default;
90 #if IMATH_FOREIGN_VECTOR_INTEROP
92 /// @name Interoperability with other vector types
94 /// Construction and assignment are allowed from other classes that
95 /// appear to be equivalent vector types, provided that they have either
96 /// a subscripting operator, or data members .x and .y, that are of the
97 /// same type as the elements of this vector, and their size appears to
98 /// be the right number of elements.
100 /// This functionality is disabled for gcc 4.x, which seems to have a
101 /// compiler bug that results in spurious errors. It can also be
102 /// disabled by defining IMATH_FOREIGN_VECTOR_INTEROP to be 0 prior to
103 /// including any Imath header files.
106 template<typename V, IMATH_ENABLE_IF(has_xy<V,T>::value)>
107 IMATH_HOSTDEVICE explicit constexpr Vec2 (const V& v) IMATH_NOEXCEPT
108 : Vec2(T(v.x), T(v.y)) { }
110 template<typename V, IMATH_ENABLE_IF(has_subscript<V,T,2>::value
111 && !has_xy<V,T>::value)>
112 IMATH_HOSTDEVICE explicit Vec2 (const V& v) : Vec2(T(v[0]), T(v[1])) { }
114 template<typename V, IMATH_ENABLE_IF(has_xy<V,T>::value)>
115 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& operator= (const V& v) IMATH_NOEXCEPT {
121 template<typename V, IMATH_ENABLE_IF(has_subscript<V,T,2>::value
122 && !has_xy<V,T>::value)>
123 IMATH_HOSTDEVICE const Vec2& operator= (const V& v) {
131 /// @name Compatibility with Sb
134 template <class S> IMATH_HOSTDEVICE void setValue (S a, S b) IMATH_NOEXCEPT;
137 template <class S> IMATH_HOSTDEVICE void setValue (const Vec2<S>& v) IMATH_NOEXCEPT;
139 /// Return the value in `a` and `b`
140 template <class S> IMATH_HOSTDEVICE void getValue (S& a, S& b) const IMATH_NOEXCEPT;
142 /// Return the value in `v`
143 template <class S> IMATH_HOSTDEVICE void getValue (Vec2<S>& v) const IMATH_NOEXCEPT;
145 /// Return a raw pointer to the array of values
146 IMATH_HOSTDEVICE T* getValue() IMATH_NOEXCEPT;
148 /// Return a raw pointer to the array of values
149 IMATH_HOSTDEVICE const T* getValue() const IMATH_NOEXCEPT;
154 /// @name Arithmetic and Comparison
157 template <class S> IMATH_HOSTDEVICE constexpr bool operator== (const Vec2<S>& v) const IMATH_NOEXCEPT;
161 template <class S> IMATH_HOSTDEVICE constexpr bool operator!= (const Vec2<S>& v) const IMATH_NOEXCEPT;
163 /// Compare two matrices and test if they are "approximately equal":
164 /// @return True if the coefficients of this and `m` are the same
165 /// with an absolute error of no more than e, i.e., for all i, j:
167 /// abs (this[i][j] - m[i][j]) <= e
168 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithAbsError (const Vec2<T>& v, T e) const IMATH_NOEXCEPT;
170 /// Compare two matrices and test if they are "approximately equal":
171 /// @return True if the coefficients of this and m are the same with
172 /// a relative error of no more than e, i.e., for all i, j:
174 /// abs (this[i] - v[i][j]) <= e * abs (this[i][j])
175 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithRelError (const Vec2<T>& v, T e) const IMATH_NOEXCEPT;
178 IMATH_HOSTDEVICE constexpr T dot (const Vec2& v) const IMATH_NOEXCEPT;
181 IMATH_HOSTDEVICE constexpr T operator^ (const Vec2& v) const IMATH_NOEXCEPT;
183 /// Right-handed cross product, i.e. z component of
184 /// Vec3 (this->x, this->y, 0) % Vec3 (v.x, v.y, 0)
185 IMATH_HOSTDEVICE constexpr T cross (const Vec2& v) const IMATH_NOEXCEPT;
187 /// Right-handed cross product, i.e. z component of
188 /// Vec3 (this->x, this->y, 0) % Vec3 (v.x, v.y, 0)
189 IMATH_HOSTDEVICE constexpr T operator% (const Vec2& v) const IMATH_NOEXCEPT;
191 /// Component-wise addition
192 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& operator+= (const Vec2& v) IMATH_NOEXCEPT;
194 /// Component-wise addition
195 IMATH_HOSTDEVICE constexpr Vec2 operator+ (const Vec2& v) const IMATH_NOEXCEPT;
197 /// Component-wise subtraction
198 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& operator-= (const Vec2& v) IMATH_NOEXCEPT;
200 /// Component-wise subtraction
201 IMATH_HOSTDEVICE constexpr Vec2 operator- (const Vec2& v) const IMATH_NOEXCEPT;
203 /// Component-wise multiplication by -1
204 IMATH_HOSTDEVICE constexpr Vec2 operator-() const IMATH_NOEXCEPT;
206 /// Component-wise multiplication by -1
207 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& negate() IMATH_NOEXCEPT;
209 /// Component-wise multiplication
210 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& operator*= (const Vec2& v) IMATH_NOEXCEPT;
212 /// Component-wise multiplication
213 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& operator*= (T a) IMATH_NOEXCEPT;
215 /// Component-wise multiplication
216 IMATH_HOSTDEVICE constexpr Vec2 operator* (const Vec2& v) const IMATH_NOEXCEPT;
218 /// Component-wise multiplication
219 IMATH_HOSTDEVICE constexpr Vec2 operator* (T a) const IMATH_NOEXCEPT;
221 /// Component-wise division
222 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& operator/= (const Vec2& v) IMATH_NOEXCEPT;
224 /// Component-wise division
225 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& operator/= (T a) IMATH_NOEXCEPT;
227 /// Component-wise division
228 IMATH_HOSTDEVICE constexpr Vec2 operator/ (const Vec2& v) const IMATH_NOEXCEPT;
230 /// Component-wise division
231 IMATH_HOSTDEVICE constexpr Vec2 operator/ (T a) const IMATH_NOEXCEPT;
236 /// @name Query and Manipulation
238 /// Return the Euclidean norm
239 IMATH_HOSTDEVICE T length() const IMATH_NOEXCEPT;
241 /// Return the square of the Euclidean norm, i.e. the dot product
243 IMATH_HOSTDEVICE constexpr T length2() const IMATH_NOEXCEPT;
245 /// Normalize in place. If length()==0, return a null vector.
246 IMATH_HOSTDEVICE const Vec2& normalize() IMATH_NOEXCEPT;
248 /// Normalize in place. If length()==0, throw an exception.
249 const Vec2& normalizeExc();
251 /// Normalize without any checks for length()==0. Slightly faster
252 /// than the other normalization routines, but if v.length() is
253 /// 0.0, the result is undefined.
254 IMATH_HOSTDEVICE const Vec2& normalizeNonNull() IMATH_NOEXCEPT;
256 /// Return a normalized vector. Does not modify *this.
257 IMATH_HOSTDEVICE Vec2<T> normalized() const IMATH_NOEXCEPT;
259 /// Return a normalized vector. Does not modify *this. Throw an
260 /// exception if length()==0.
261 Vec2<T> normalizedExc() const;
263 /// Return a normalized vector. Does not modify *this, and does
264 /// not check for length()==0. Slightly faster than the other
265 /// normalization routines, but if v.length() is 0.0, the result
267 IMATH_HOSTDEVICE Vec2<T> normalizedNonNull() const IMATH_NOEXCEPT;
272 /// @name Numeric Limits
274 /// Largest possible negative value
275 IMATH_HOSTDEVICE constexpr static T baseTypeLowest() IMATH_NOEXCEPT { return std::numeric_limits<T>::lowest(); }
277 /// Largest possible positive value
278 IMATH_HOSTDEVICE constexpr static T baseTypeMax() IMATH_NOEXCEPT { return std::numeric_limits<T>::max(); }
280 /// Smallest possible positive value
281 IMATH_HOSTDEVICE constexpr static T baseTypeSmallest() IMATH_NOEXCEPT { return std::numeric_limits<T>::min(); }
283 /// Smallest possible e for which 1+e != 1
284 IMATH_HOSTDEVICE constexpr static T baseTypeEpsilon() IMATH_NOEXCEPT { return std::numeric_limits<T>::epsilon(); }
288 /// Return the number of dimensions, i.e. 2
289 IMATH_HOSTDEVICE constexpr static unsigned int dimensions() IMATH_NOEXCEPT { return 2; }
291 /// The base type: In templates that accept a parameter `V`, you
292 /// can refer to `T` as `V::BaseType`
297 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T lengthTiny() const IMATH_NOEXCEPT;
304 template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Vec3
309 /// @name Direct access to elements
315 /// Element access by index.
316 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T& operator[] (int i) IMATH_NOEXCEPT;
318 /// Element access by index.
319 IMATH_HOSTDEVICE constexpr const T& operator[] (int i) const IMATH_NOEXCEPT;
322 /// @name Constructors and Assignment
324 /// Uninitialized by default
325 IMATH_HOSTDEVICE Vec3() IMATH_NOEXCEPT;
327 /// Initialize to a scalar `(a,a,a)`
328 IMATH_HOSTDEVICE constexpr explicit Vec3 (T a) IMATH_NOEXCEPT;
330 /// Initialize to given elements `(a,b,c)`
331 IMATH_HOSTDEVICE constexpr Vec3 (T a, T b, T c) IMATH_NOEXCEPT;
334 IMATH_HOSTDEVICE constexpr Vec3 (const Vec3& v) IMATH_NOEXCEPT;
336 /// Construct from Vec3 of another base type
337 template <class S> IMATH_HOSTDEVICE constexpr Vec3 (const Vec3<S>& v) IMATH_NOEXCEPT;
339 /// Vec4 to Vec3 conversion: divide x, y and z by w, even if w is
340 /// 0. The result depends on how the environment handles
341 /// floating-point exceptions.
342 template <class S> IMATH_HOSTDEVICE explicit constexpr Vec3 (const Vec4<S>& v) IMATH_NOEXCEPT;
344 /// Vec4 to Vec3 conversion: divide x, y and z by w. Throws an
345 /// exception if w is zero or if division by w would overflow.
347 explicit IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Vec3 (const Vec4<S>& v, InfException);
350 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator= (const Vec3& v) IMATH_NOEXCEPT;
353 ~Vec3() IMATH_NOEXCEPT = default;
357 #if IMATH_FOREIGN_VECTOR_INTEROP
359 /// @name Interoperability with other vector types
361 /// Construction and assignment are allowed from other classes that
362 /// appear to be equivalent vector types, provided that they have either
363 /// a subscripting operator, or data members .x, .y, .z, that are of the
364 /// same type as the elements of this vector, and their size appears to
365 /// be the right number of elements.
367 /// This functionality is disabled for gcc 4.x, which seems to have a
368 /// compiler bug that results in spurious errors. It can also be
369 /// disabled by defining IMATH_FOREIGN_VECTOR_INTEROP to be 0 prior to
370 /// including any Imath header files.
373 template<typename V, IMATH_ENABLE_IF(has_xyz<V,T>::value)>
374 IMATH_HOSTDEVICE explicit constexpr Vec3 (const V& v) IMATH_NOEXCEPT
375 : Vec3(T(v.x), T(v.y), T(v.z)) { }
377 template<typename V, IMATH_ENABLE_IF(has_subscript<V,T,3>::value
378 && !has_xyz<V,T>::value)>
379 IMATH_HOSTDEVICE explicit Vec3 (const V& v) : Vec3(T(v[0]), T(v[1]), T(v[2])) { }
381 /// Interoperability assignment from another type that behaves as if it
382 /// were an equivalent vector.
383 template<typename V, IMATH_ENABLE_IF(has_xyz<V,T>::value)>
384 IMATH_HOSTDEVICE const Vec3& operator= (const V& v) IMATH_NOEXCEPT {
391 template<typename V, IMATH_ENABLE_IF(has_subscript<V,T,3>::value
392 && !has_xyz<V,T>::value)>
393 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator= (const V& v) {
403 /// @name Compatibility with Sb
406 template <class S> IMATH_HOSTDEVICE void setValue (S a, S b, S c) IMATH_NOEXCEPT;
409 template <class S> IMATH_HOSTDEVICE void setValue (const Vec3<S>& v) IMATH_NOEXCEPT;
411 /// Return the value in `a`, `b`, and `c`
412 template <class S> IMATH_HOSTDEVICE void getValue (S& a, S& b, S& c) const IMATH_NOEXCEPT;
414 /// Return the value in `v`
415 template <class S> IMATH_HOSTDEVICE void getValue (Vec3<S>& v) const IMATH_NOEXCEPT;
417 /// Return a raw pointer to the array of values
418 IMATH_HOSTDEVICE T* getValue() IMATH_NOEXCEPT;
420 /// Return a raw pointer to the array of values
421 IMATH_HOSTDEVICE const T* getValue() const IMATH_NOEXCEPT;
426 /// @name Arithmetic and Comparison
429 template <class S> IMATH_HOSTDEVICE constexpr bool operator== (const Vec3<S>& v) const IMATH_NOEXCEPT;
432 template <class S> IMATH_HOSTDEVICE constexpr bool operator!= (const Vec3<S>& v) const IMATH_NOEXCEPT;
434 /// Compare two matrices and test if they are "approximately equal":
435 /// @return True if the coefficients of this and `m` are the same
436 /// with an absolute error of no more than e, i.e., for all i, j:
438 /// abs (this[i][j] - m[i][j]) <= e
439 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithAbsError (const Vec3<T>& v, T e) const IMATH_NOEXCEPT;
441 /// Compare two matrices and test if they are "approximately equal":
442 /// @return True if the coefficients of this and m are the same with
443 /// a relative error of no more than e, i.e., for all i, j:
445 /// abs (this[i] - v[i][j]) <= e * abs (this[i][j])
446 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithRelError (const Vec3<T>& v, T e) const IMATH_NOEXCEPT;
449 IMATH_HOSTDEVICE constexpr T dot (const Vec3& v) const IMATH_NOEXCEPT;
452 IMATH_HOSTDEVICE constexpr T operator^ (const Vec3& v) const IMATH_NOEXCEPT;
454 /// Right-handed cross product
455 IMATH_HOSTDEVICE constexpr Vec3 cross (const Vec3& v) const IMATH_NOEXCEPT;
457 /// Right-handed cross product
458 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator%= (const Vec3& v) IMATH_NOEXCEPT;
460 /// Right-handed cross product
461 IMATH_HOSTDEVICE constexpr Vec3 operator% (const Vec3& v) const IMATH_NOEXCEPT;
463 /// Component-wise addition
464 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator+= (const Vec3& v) IMATH_NOEXCEPT;
466 /// Component-wise addition
467 IMATH_HOSTDEVICE constexpr Vec3 operator+ (const Vec3& v) const IMATH_NOEXCEPT;
469 /// Component-wise subtraction
470 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator-= (const Vec3& v) IMATH_NOEXCEPT;
472 /// Component-wise subtraction
473 IMATH_HOSTDEVICE constexpr Vec3 operator- (const Vec3& v) const IMATH_NOEXCEPT;
475 /// Component-wise multiplication by -1
476 IMATH_HOSTDEVICE constexpr Vec3 operator-() const IMATH_NOEXCEPT;
478 /// Component-wise multiplication by -1
479 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& negate() IMATH_NOEXCEPT;
481 /// Component-wise multiplication
482 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator*= (const Vec3& v) IMATH_NOEXCEPT;
484 /// Component-wise multiplication
485 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator*= (T a) IMATH_NOEXCEPT;
487 /// Component-wise multiplication
488 IMATH_HOSTDEVICE constexpr Vec3 operator* (const Vec3& v) const IMATH_NOEXCEPT;
490 /// Component-wise multiplication
491 IMATH_HOSTDEVICE constexpr Vec3 operator* (T a) const IMATH_NOEXCEPT;
493 /// Component-wise division
494 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator/= (const Vec3& v) IMATH_NOEXCEPT;
496 /// Component-wise division
497 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator/= (T a) IMATH_NOEXCEPT;
499 /// Component-wise division
500 IMATH_HOSTDEVICE constexpr Vec3 operator/ (const Vec3& v) const IMATH_NOEXCEPT;
502 /// Component-wise division
503 IMATH_HOSTDEVICE constexpr Vec3 operator/ (T a) const IMATH_NOEXCEPT;
508 /// @name Query and Manipulation
510 /// Return the Euclidean norm
511 IMATH_HOSTDEVICE T length() const IMATH_NOEXCEPT;
513 /// Return the square of the Euclidean norm, i.e. the dot product
515 IMATH_HOSTDEVICE constexpr T length2() const IMATH_NOEXCEPT;
517 /// Normalize in place. If length()==0, return a null vector.
518 IMATH_HOSTDEVICE const Vec3& normalize() IMATH_NOEXCEPT;
520 /// Normalize in place. If length()==0, throw an exception.
521 const Vec3& normalizeExc();
523 /// Normalize without any checks for length()==0. Slightly faster
524 /// than the other normalization routines, but if v.length() is
525 /// 0.0, the result is undefined.
526 IMATH_HOSTDEVICE const Vec3& normalizeNonNull() IMATH_NOEXCEPT;
528 /// Return a normalized vector. Does not modify *this.
529 IMATH_HOSTDEVICE Vec3<T> normalized() const IMATH_NOEXCEPT; // does not modify *this
531 /// Return a normalized vector. Does not modify *this. Throw an
532 /// exception if length()==0.
533 Vec3<T> normalizedExc() const;
535 /// Return a normalized vector. Does not modify *this, and does
536 /// not check for length()==0. Slightly faster than the other
537 /// normalization routines, but if v.length() is 0.0, the result
539 IMATH_HOSTDEVICE Vec3<T> normalizedNonNull() const IMATH_NOEXCEPT;
544 /// @name Numeric Limits
546 /// Largest possible negative value
547 IMATH_HOSTDEVICE constexpr static T baseTypeLowest() IMATH_NOEXCEPT { return std::numeric_limits<T>::lowest(); }
549 /// Largest possible positive value
550 IMATH_HOSTDEVICE constexpr static T baseTypeMax() IMATH_NOEXCEPT { return std::numeric_limits<T>::max(); }
552 /// Smallest possible positive value
553 IMATH_HOSTDEVICE constexpr static T baseTypeSmallest() IMATH_NOEXCEPT { return std::numeric_limits<T>::min(); }
555 /// Smallest possible e for which 1+e != 1
556 IMATH_HOSTDEVICE constexpr static T baseTypeEpsilon() IMATH_NOEXCEPT { return std::numeric_limits<T>::epsilon(); }
560 /// Return the number of dimensions, i.e. 3
561 IMATH_HOSTDEVICE constexpr static unsigned int dimensions() IMATH_NOEXCEPT { return 3; }
563 /// The base type: In templates that accept a parameter `V`, you
564 /// can refer to `T` as `V::BaseType`
568 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T lengthTiny() const IMATH_NOEXCEPT;
575 template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Vec4
580 /// @name Direct access to elements
586 /// Element access by index.
587 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T& operator[] (int i) IMATH_NOEXCEPT;
589 /// Element access by index.
590 IMATH_HOSTDEVICE constexpr const T& operator[] (int i) const IMATH_NOEXCEPT;
593 /// @name Constructors and Assignment
595 /// Uninitialized by default
596 IMATH_HOSTDEVICE Vec4() IMATH_NOEXCEPT; // no initialization
598 /// Initialize to a scalar `(a,a,a,a)`
599 IMATH_HOSTDEVICE constexpr explicit Vec4 (T a) IMATH_NOEXCEPT;
601 /// Initialize to given elements `(a,b,c,d)`
602 IMATH_HOSTDEVICE constexpr Vec4 (T a, T b, T c, T d) IMATH_NOEXCEPT;
605 IMATH_HOSTDEVICE constexpr Vec4 (const Vec4& v) IMATH_NOEXCEPT;
607 /// Construct from Vec4 of another base type
608 template <class S> IMATH_HOSTDEVICE constexpr Vec4 (const Vec4<S>& v) IMATH_NOEXCEPT;
610 /// Vec3 to Vec4 conversion, sets w to 1.
611 template <class S> IMATH_HOSTDEVICE explicit constexpr Vec4 (const Vec3<S>& v) IMATH_NOEXCEPT;
614 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& operator= (const Vec4& v) IMATH_NOEXCEPT;
617 ~Vec4() IMATH_NOEXCEPT = default;
621 #if IMATH_FOREIGN_VECTOR_INTEROP
623 /// @name Interoperability with other vector types
625 /// Construction and assignment are allowed from other classes that
626 /// appear to be equivalent vector types, provided that they have either
627 /// a subscripting operator, or data members .x, .y, .z, .w that are of
628 /// the same type as the elements of this vector, and their size appears
629 /// to be the right number of elements.
631 /// This functionality is disabled for gcc 4.x, which seems to have a
632 /// compiler bug that results in spurious errors. It can also be
633 /// disabled by defining IMATH_FOREIGN_VECTOR_INTEROP to be 0 prior to
634 /// including any Imath header files.
637 template<typename V, IMATH_ENABLE_IF(has_xyzw<V,T>::value)>
638 IMATH_HOSTDEVICE explicit constexpr Vec4 (const V& v) IMATH_NOEXCEPT
639 : Vec4(T(v.x), T(v.y), T(v.z), T(v.w)) { }
641 template<typename V, IMATH_ENABLE_IF(has_subscript<V,T,4>::value
642 && !has_xyzw<V,T>::value)>
643 IMATH_HOSTDEVICE explicit Vec4 (const V& v) : Vec4(T(v[0]), T(v[1]), T(v[2]), T(v[3])) { }
645 template<typename V, IMATH_ENABLE_IF(has_xyzw<V,T>::value)>
646 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& operator= (const V& v) IMATH_NOEXCEPT {
654 template<typename V, IMATH_ENABLE_IF(has_subscript<V,T,4>::value
655 && !has_xyzw<V,T>::value)>
656 IMATH_HOSTDEVICE const Vec4& operator= (const V& v) {
667 /// @name Arithmetic and Comparison
670 template <class S> IMATH_HOSTDEVICE constexpr bool operator== (const Vec4<S>& v) const IMATH_NOEXCEPT;
673 template <class S> IMATH_HOSTDEVICE constexpr bool operator!= (const Vec4<S>& v) const IMATH_NOEXCEPT;
675 /// Compare two matrices and test if they are "approximately equal":
676 /// @return True if the coefficients of this and `m` are the same
677 /// with an absolute error of no more than e, i.e., for all i, j:
679 /// abs (this[i][j] - m[i][j]) <= e
680 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithAbsError (const Vec4<T>& v, T e) const IMATH_NOEXCEPT;
682 /// Compare two matrices and test if they are "approximately equal":
683 /// @return True if the coefficients of this and m are the same with
684 /// a relative error of no more than e, i.e., for all i, j:
686 /// abs (this[i] - v[i][j]) <= e * abs (this[i][j])
687 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithRelError (const Vec4<T>& v, T e) const IMATH_NOEXCEPT;
690 IMATH_HOSTDEVICE constexpr T dot (const Vec4& v) const IMATH_NOEXCEPT;
693 IMATH_HOSTDEVICE constexpr T operator^ (const Vec4& v) const IMATH_NOEXCEPT;
695 /// Component-wise addition
696 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& operator+= (const Vec4& v) IMATH_NOEXCEPT;
698 /// Component-wise addition
699 IMATH_HOSTDEVICE constexpr Vec4 operator+ (const Vec4& v) const IMATH_NOEXCEPT;
701 /// Component-wise subtraction
702 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& operator-= (const Vec4& v) IMATH_NOEXCEPT;
704 /// Component-wise subtraction
705 IMATH_HOSTDEVICE constexpr Vec4 operator- (const Vec4& v) const IMATH_NOEXCEPT;
707 /// Component-wise multiplication by -1
708 IMATH_HOSTDEVICE constexpr Vec4 operator-() const IMATH_NOEXCEPT;
710 /// Component-wise multiplication by -1
711 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& negate() IMATH_NOEXCEPT;
713 /// Component-wise multiplication
714 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& operator*= (const Vec4& v) IMATH_NOEXCEPT;
716 /// Component-wise multiplication
717 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& operator*= (T a) IMATH_NOEXCEPT;
719 /// Component-wise multiplication
720 IMATH_HOSTDEVICE constexpr Vec4 operator* (const Vec4& v) const IMATH_NOEXCEPT;
722 /// Component-wise multiplication
723 IMATH_HOSTDEVICE constexpr Vec4 operator* (T a) const IMATH_NOEXCEPT;
725 /// Component-wise division
726 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& operator/= (const Vec4& v) IMATH_NOEXCEPT;
728 /// Component-wise division
729 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& operator/= (T a) IMATH_NOEXCEPT;
731 /// Component-wise division
732 IMATH_HOSTDEVICE constexpr Vec4 operator/ (const Vec4& v) const IMATH_NOEXCEPT;
734 /// Component-wise division
735 IMATH_HOSTDEVICE constexpr Vec4 operator/ (T a) const IMATH_NOEXCEPT;
740 /// @name Query and Manipulation
742 /// Return the Euclidean norm
743 IMATH_HOSTDEVICE T length() const IMATH_NOEXCEPT;
745 /// Return the square of the Euclidean norm, i.e. the dot product
747 IMATH_HOSTDEVICE constexpr T length2() const IMATH_NOEXCEPT;
749 /// Normalize in place. If length()==0, return a null vector.
750 IMATH_HOSTDEVICE const Vec4& normalize() IMATH_NOEXCEPT; // modifies *this
752 /// Normalize in place. If length()==0, throw an exception.
753 const Vec4& normalizeExc();
755 /// Normalize without any checks for length()==0. Slightly faster
756 /// than the other normalization routines, but if v.length() is
757 /// 0.0, the result is undefined.
758 IMATH_HOSTDEVICE const Vec4& normalizeNonNull() IMATH_NOEXCEPT;
760 /// Return a normalized vector. Does not modify *this.
761 IMATH_HOSTDEVICE Vec4<T> normalized() const IMATH_NOEXCEPT; // does not modify *this
763 /// Return a normalized vector. Does not modify *this. Throw an
764 /// exception if length()==0.
765 Vec4<T> normalizedExc() const;
767 /// Return a normalized vector. Does not modify *this, and does
768 /// not check for length()==0. Slightly faster than the other
769 /// normalization routines, but if v.length() is 0.0, the result
771 IMATH_HOSTDEVICE Vec4<T> normalizedNonNull() const IMATH_NOEXCEPT;
776 /// @name Numeric Limits
778 /// Largest possible negative value
779 IMATH_HOSTDEVICE constexpr static T baseTypeLowest() IMATH_NOEXCEPT { return std::numeric_limits<T>::lowest(); }
781 /// Largest possible positive value
782 IMATH_HOSTDEVICE constexpr static T baseTypeMax() IMATH_NOEXCEPT { return std::numeric_limits<T>::max(); }
784 /// Smallest possible positive value
785 IMATH_HOSTDEVICE constexpr static T baseTypeSmallest() IMATH_NOEXCEPT { return std::numeric_limits<T>::min(); }
787 /// Smallest possible e for which 1+e != 1
788 IMATH_HOSTDEVICE constexpr static T baseTypeEpsilon() IMATH_NOEXCEPT { return std::numeric_limits<T>::epsilon(); }
792 /// Return the number of dimensions, i.e. 4
793 IMATH_HOSTDEVICE constexpr static unsigned int dimensions() IMATH_NOEXCEPT { return 4; }
795 /// The base type: In templates that accept a parameter `V`, you
796 /// can refer to `T` as `V::BaseType`
800 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T lengthTiny() const IMATH_NOEXCEPT;
803 /// Stream output, as "(x y)"
804 template <class T> std::ostream& operator<< (std::ostream& s, const Vec2<T>& v);
806 /// Stream output, as "(x y z)"
807 template <class T> std::ostream& operator<< (std::ostream& s, const Vec3<T>& v);
809 /// Stream output, as "(x y z w)"
810 template <class T> std::ostream& operator<< (std::ostream& s, const Vec4<T>& v);
812 /// Reverse multiplication: S * Vec2<T>
813 template <class T> IMATH_HOSTDEVICE constexpr Vec2<T> operator* (T a, const Vec2<T>& v) IMATH_NOEXCEPT;
815 /// Reverse multiplication: S * Vec3<T>
816 template <class T> IMATH_HOSTDEVICE constexpr Vec3<T> operator* (T a, const Vec3<T>& v) IMATH_NOEXCEPT;
818 /// Reverse multiplication: S * Vec4<T>
819 template <class T> IMATH_HOSTDEVICE constexpr Vec4<T> operator* (T a, const Vec4<T>& v) IMATH_NOEXCEPT;
821 //-------------------------
822 // Typedefs for convenience
823 //-------------------------
826 typedef Vec2<short> V2s;
829 typedef Vec2<int> V2i;
832 typedef Vec2<int64_t> V2i64;
835 typedef Vec2<float> V2f;
838 typedef Vec2<double> V2d;
841 typedef Vec3<short> V3s;
844 typedef Vec3<int> V3i;
847 typedef Vec3<int64_t> V3i64;
850 typedef Vec3<float> V3f;
853 typedef Vec3<double> V3d;
856 typedef Vec4<short> V4s;
859 typedef Vec4<int> V4i;
862 typedef Vec4<int64_t> V4i64;
865 typedef Vec4<float> V4f;
868 typedef Vec4<double> V4d;
870 //----------------------------------------------------------------------------
871 // Specializations for VecN<short>, VecN<int>
873 // Normalize and length don't make sense for integer vectors, so disable them.
874 //----------------------------------------------------------------------------
876 /// @cond Doxygen_Suppress
879 template <> IMATH_HOSTDEVICE short Vec2<short>::length() const IMATH_NOEXCEPT = delete;
880 template <> IMATH_HOSTDEVICE const Vec2<short>& Vec2<short>::normalize() IMATH_NOEXCEPT = delete;
881 template <> const Vec2<short>& Vec2<short>::normalizeExc() = delete;
882 template <> IMATH_HOSTDEVICE const Vec2<short>& Vec2<short>::normalizeNonNull() IMATH_NOEXCEPT = delete;
883 template <> IMATH_HOSTDEVICE Vec2<short> Vec2<short>::normalized() const IMATH_NOEXCEPT = delete;
884 template <> Vec2<short> Vec2<short>::normalizedExc() const = delete;
885 template <> IMATH_HOSTDEVICE Vec2<short> Vec2<short>::normalizedNonNull() const IMATH_NOEXCEPT = delete;
888 template <> IMATH_HOSTDEVICE int Vec2<int>::length() const IMATH_NOEXCEPT = delete;
889 template <> IMATH_HOSTDEVICE const Vec2<int>& Vec2<int>::normalize() IMATH_NOEXCEPT = delete;
890 template <> const Vec2<int>& Vec2<int>::normalizeExc() = delete;
891 template <> IMATH_HOSTDEVICE const Vec2<int>& Vec2<int>::normalizeNonNull() IMATH_NOEXCEPT = delete;
892 template <> IMATH_HOSTDEVICE Vec2<int> Vec2<int>::normalized() const IMATH_NOEXCEPT = delete;
893 template <> Vec2<int> Vec2<int>::normalizedExc() const = delete;
894 template <> IMATH_HOSTDEVICE Vec2<int> Vec2<int>::normalizedNonNull() const IMATH_NOEXCEPT = delete;
897 template <> IMATH_HOSTDEVICE int64_t Vec2<int64_t>::length() const IMATH_NOEXCEPT = delete;
898 template <> IMATH_HOSTDEVICE const Vec2<int64_t>& Vec2<int64_t>::normalize() IMATH_NOEXCEPT = delete;
899 template <> const Vec2<int64_t>& Vec2<int64_t>::normalizeExc() = delete;
900 template <> IMATH_HOSTDEVICE const Vec2<int64_t>& Vec2<int64_t>::normalizeNonNull() IMATH_NOEXCEPT = delete;
901 template <> IMATH_HOSTDEVICE Vec2<int64_t> Vec2<int64_t>::normalized() const IMATH_NOEXCEPT = delete;
902 template <> Vec2<int64_t> Vec2<int64_t>::normalizedExc() const = delete;
903 template <> IMATH_HOSTDEVICE Vec2<int64_t> Vec2<int64_t>::normalizedNonNull() const IMATH_NOEXCEPT = delete;
906 template <> IMATH_HOSTDEVICE short Vec3<short>::length() const IMATH_NOEXCEPT = delete;
907 template <> IMATH_HOSTDEVICE const Vec3<short>& Vec3<short>::normalize() IMATH_NOEXCEPT = delete;
908 template <> const Vec3<short>& Vec3<short>::normalizeExc() = delete;
909 template <> IMATH_HOSTDEVICE const Vec3<short>& Vec3<short>::normalizeNonNull() IMATH_NOEXCEPT = delete;
910 template <> IMATH_HOSTDEVICE Vec3<short> Vec3<short>::normalized() const IMATH_NOEXCEPT = delete;
911 template <> Vec3<short> Vec3<short>::normalizedExc() const = delete;
912 template <> IMATH_HOSTDEVICE Vec3<short> Vec3<short>::normalizedNonNull() const IMATH_NOEXCEPT = delete;
915 template <> IMATH_HOSTDEVICE int Vec3<int>::length() const IMATH_NOEXCEPT = delete;
916 template <> IMATH_HOSTDEVICE const Vec3<int>& Vec3<int>::normalize() IMATH_NOEXCEPT = delete;
917 template <> const Vec3<int>& Vec3<int>::normalizeExc() = delete;
918 template <> IMATH_HOSTDEVICE const Vec3<int>& Vec3<int>::normalizeNonNull() IMATH_NOEXCEPT = delete;
919 template <> IMATH_HOSTDEVICE Vec3<int> Vec3<int>::normalized() const IMATH_NOEXCEPT = delete;
920 template <> Vec3<int> Vec3<int>::normalizedExc() const = delete;
921 template <> IMATH_HOSTDEVICE Vec3<int> Vec3<int>::normalizedNonNull() const IMATH_NOEXCEPT = delete;
924 template <> IMATH_HOSTDEVICE int64_t Vec3<int64_t>::length() const IMATH_NOEXCEPT = delete;
925 template <> IMATH_HOSTDEVICE const Vec3<int64_t>& Vec3<int64_t>::normalize() IMATH_NOEXCEPT = delete;
926 template <> const Vec3<int64_t>& Vec3<int64_t>::normalizeExc() = delete;
927 template <> IMATH_HOSTDEVICE const Vec3<int64_t>& Vec3<int64_t>::normalizeNonNull() IMATH_NOEXCEPT = delete;
928 template <> IMATH_HOSTDEVICE Vec3<int64_t> Vec3<int64_t>::normalized() const IMATH_NOEXCEPT = delete;
929 template <> Vec3<int64_t> Vec3<int64_t>::normalizedExc() const = delete;
930 template <> IMATH_HOSTDEVICE Vec3<int64_t> Vec3<int64_t>::normalizedNonNull() const IMATH_NOEXCEPT = delete;
933 template <> IMATH_HOSTDEVICE short Vec4<short>::length() const IMATH_NOEXCEPT = delete;
934 template <> IMATH_HOSTDEVICE const Vec4<short>& Vec4<short>::normalize() IMATH_NOEXCEPT = delete;
935 template <> const Vec4<short>& Vec4<short>::normalizeExc() = delete;
936 template <> IMATH_HOSTDEVICE const Vec4<short>& Vec4<short>::normalizeNonNull() IMATH_NOEXCEPT = delete;
937 template <> IMATH_HOSTDEVICE Vec4<short> Vec4<short>::normalized() const IMATH_NOEXCEPT = delete;
938 template <> Vec4<short> Vec4<short>::normalizedExc() const = delete;
939 template <> IMATH_HOSTDEVICE Vec4<short> Vec4<short>::normalizedNonNull() const IMATH_NOEXCEPT = delete;
942 template <> IMATH_HOSTDEVICE int Vec4<int>::length() const IMATH_NOEXCEPT = delete;
943 template <> IMATH_HOSTDEVICE const Vec4<int>& Vec4<int>::normalize() IMATH_NOEXCEPT = delete;
944 template <> const Vec4<int>& Vec4<int>::normalizeExc() = delete;
945 template <> IMATH_HOSTDEVICE const Vec4<int>& Vec4<int>::normalizeNonNull() IMATH_NOEXCEPT = delete;
946 template <> IMATH_HOSTDEVICE Vec4<int> Vec4<int>::normalized() const IMATH_NOEXCEPT = delete;
947 template <> Vec4<int> Vec4<int>::normalizedExc() const = delete;
948 template <> IMATH_HOSTDEVICE Vec4<int> Vec4<int>::normalizedNonNull() const IMATH_NOEXCEPT = delete;
951 template <> IMATH_HOSTDEVICE int64_t Vec4<int64_t>::length() const IMATH_NOEXCEPT = delete;
952 template <> IMATH_HOSTDEVICE const Vec4<int64_t>& Vec4<int64_t>::normalize() IMATH_NOEXCEPT = delete;
953 template <> const Vec4<int64_t>& Vec4<int64_t>::normalizeExc() = delete;
954 template <> IMATH_HOSTDEVICE const Vec4<int64_t>& Vec4<int64_t>::normalizeNonNull() IMATH_NOEXCEPT = delete;
955 template <> IMATH_HOSTDEVICE Vec4<int64_t> Vec4<int64_t>::normalized() const IMATH_NOEXCEPT = delete;
956 template <> Vec4<int64_t> Vec4<int64_t>::normalizedExc() const = delete;
957 template <> IMATH_HOSTDEVICE Vec4<int64_t> Vec4<int64_t>::normalizedNonNull() const IMATH_NOEXCEPT = delete;
959 /// @endcond Doxygen_Suppress
961 //------------------------
962 // Implementation of Vec2:
963 //------------------------
966 IMATH_CONSTEXPR14 IMATH_HOSTDEVICE inline T&
967 Vec2<T>::operator[] (int i) IMATH_NOEXCEPT
969 return (&x)[i]; // NOSONAR - suppress SonarCloud bug report.
973 constexpr IMATH_HOSTDEVICE inline const T&
974 Vec2<T>::operator[] (int i) const IMATH_NOEXCEPT
976 return (&x)[i]; // NOSONAR - suppress SonarCloud bug report.
979 template <class T> IMATH_HOSTDEVICE inline Vec2<T>::Vec2() IMATH_NOEXCEPT
981 // empty, and not constexpr because data is uninitialized.
984 template <class T> IMATH_HOSTDEVICE constexpr inline Vec2<T>::Vec2 (T a) IMATH_NOEXCEPT
989 template <class T> IMATH_HOSTDEVICE constexpr inline Vec2<T>::Vec2 (T a, T b) IMATH_NOEXCEPT
994 template <class T> IMATH_HOSTDEVICE constexpr inline Vec2<T>::Vec2 (const Vec2& v) IMATH_NOEXCEPT
999 template <class T> template <class S> IMATH_HOSTDEVICE constexpr inline Vec2<T>::Vec2 (const Vec2<S>& v) IMATH_NOEXCEPT
1000 : x(T(v.x)), y(T(v.y))
1005 IMATH_CONSTEXPR14 IMATH_HOSTDEVICE inline const Vec2<T>&
1006 Vec2<T>::operator= (const Vec2& v) IMATH_NOEXCEPT
1015 IMATH_HOSTDEVICE inline void
1016 Vec2<T>::setValue (S a, S b) IMATH_NOEXCEPT
1024 IMATH_HOSTDEVICE inline void
1025 Vec2<T>::setValue (const Vec2<S>& v) IMATH_NOEXCEPT
1033 IMATH_HOSTDEVICE inline void
1034 Vec2<T>::getValue (S& a, S& b) const IMATH_NOEXCEPT
1042 IMATH_HOSTDEVICE inline void
1043 Vec2<T>::getValue (Vec2<S>& v) const IMATH_NOEXCEPT
1050 IMATH_HOSTDEVICE inline T*
1051 Vec2<T>::getValue() IMATH_NOEXCEPT
1057 IMATH_HOSTDEVICE inline const T*
1058 Vec2<T>::getValue() const IMATH_NOEXCEPT
1060 return (const T*) &x;
1065 IMATH_HOSTDEVICE constexpr inline bool
1066 Vec2<T>::operator== (const Vec2<S>& v) const IMATH_NOEXCEPT
1068 return x == v.x && y == v.y;
1073 IMATH_HOSTDEVICE constexpr inline bool
1074 Vec2<T>::operator!= (const Vec2<S>& v) const IMATH_NOEXCEPT
1076 return x != v.x || y != v.y;
1080 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool
1081 Vec2<T>::equalWithAbsError (const Vec2<T>& v, T e) const IMATH_NOEXCEPT
1083 for (int i = 0; i < 2; i++)
1084 if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i], v[i], e))
1091 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool
1092 Vec2<T>::equalWithRelError (const Vec2<T>& v, T e) const IMATH_NOEXCEPT
1094 for (int i = 0; i < 2; i++)
1095 if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i], v[i], e))
1102 IMATH_HOSTDEVICE constexpr inline T
1103 Vec2<T>::dot (const Vec2& v) const IMATH_NOEXCEPT
1105 return x * v.x + y * v.y;
1109 IMATH_HOSTDEVICE constexpr inline T
1110 Vec2<T>::operator^ (const Vec2& v) const IMATH_NOEXCEPT
1116 IMATH_HOSTDEVICE constexpr inline T
1117 Vec2<T>::cross (const Vec2& v) const IMATH_NOEXCEPT
1119 return x * v.y - y * v.x;
1123 IMATH_HOSTDEVICE constexpr inline T
1124 Vec2<T>::operator% (const Vec2& v) const IMATH_NOEXCEPT
1126 return x * v.y - y * v.x;
1130 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2<T>&
1131 Vec2<T>::operator+= (const Vec2& v) IMATH_NOEXCEPT
1139 IMATH_HOSTDEVICE constexpr inline Vec2<T>
1140 Vec2<T>::operator+ (const Vec2& v) const IMATH_NOEXCEPT
1142 return Vec2 (x + v.x, y + v.y);
1146 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2<T>&
1147 Vec2<T>::operator-= (const Vec2& v) IMATH_NOEXCEPT
1155 IMATH_HOSTDEVICE constexpr inline Vec2<T>
1156 Vec2<T>::operator- (const Vec2& v) const IMATH_NOEXCEPT
1158 return Vec2 (x - v.x, y - v.y);
1162 IMATH_HOSTDEVICE constexpr inline Vec2<T>
1163 Vec2<T>::operator-() const IMATH_NOEXCEPT
1165 return Vec2 (-x, -y);
1169 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2<T>&
1170 Vec2<T>::negate() IMATH_NOEXCEPT
1178 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2<T>&
1179 Vec2<T>::operator*= (const Vec2& v) IMATH_NOEXCEPT
1187 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2<T>&
1188 Vec2<T>::operator*= (T a) IMATH_NOEXCEPT
1196 IMATH_HOSTDEVICE constexpr inline Vec2<T>
1197 Vec2<T>::operator* (const Vec2& v) const IMATH_NOEXCEPT
1199 return Vec2 (x * v.x, y * v.y);
1203 IMATH_HOSTDEVICE constexpr inline Vec2<T>
1204 Vec2<T>::operator* (T a) const IMATH_NOEXCEPT
1206 return Vec2 (x * a, y * a);
1210 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2<T>&
1211 Vec2<T>::operator/= (const Vec2& v) IMATH_NOEXCEPT
1219 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2<T>&
1220 Vec2<T>::operator/= (T a) IMATH_NOEXCEPT
1228 IMATH_HOSTDEVICE constexpr inline Vec2<T>
1229 Vec2<T>::operator/ (const Vec2& v) const IMATH_NOEXCEPT
1231 return Vec2 (x / v.x, y / v.y);
1235 IMATH_HOSTDEVICE constexpr inline Vec2<T>
1236 Vec2<T>::operator/ (T a) const IMATH_NOEXCEPT
1238 return Vec2 (x / a, y / a);
1242 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline T
1243 Vec2<T>::lengthTiny() const IMATH_NOEXCEPT
1245 T absX = std::abs(x);
1246 T absY = std::abs(y);
1253 if (IMATH_UNLIKELY(max == T (0)))
1257 // Do not replace the divisions by max with multiplications by 1/max.
1258 // Computing 1/max can overflow but the divisions below will always
1259 // produce results less than or equal to 1.
1265 return max * std::sqrt (absX * absX + absY * absY);
1269 IMATH_HOSTDEVICE inline T
1270 Vec2<T>::length() const IMATH_NOEXCEPT
1272 T length2 = dot (*this);
1274 if (IMATH_UNLIKELY(length2 < T (2) * std::numeric_limits<T>::min()))
1275 return lengthTiny();
1277 return std::sqrt (length2);
1281 IMATH_HOSTDEVICE constexpr inline T
1282 Vec2<T>::length2() const IMATH_NOEXCEPT
1288 IMATH_HOSTDEVICE inline const Vec2<T>&
1289 Vec2<T>::normalize() IMATH_NOEXCEPT
1293 if (IMATH_LIKELY(l != T (0)))
1296 // Do not replace the divisions by l with multiplications by 1/l.
1297 // Computing 1/l can overflow but the divisions below will always
1298 // produce results less than or equal to 1.
1309 inline const Vec2<T>&
1310 Vec2<T>::normalizeExc()
1314 if (IMATH_UNLIKELY(l == T (0)))
1315 throw std::domain_error ("Cannot normalize null vector.");
1323 IMATH_HOSTDEVICE inline const Vec2<T>&
1324 Vec2<T>::normalizeNonNull() IMATH_NOEXCEPT
1333 IMATH_HOSTDEVICE inline Vec2<T>
1334 Vec2<T>::normalized() const IMATH_NOEXCEPT
1338 if (IMATH_UNLIKELY(l == T (0)))
1339 return Vec2 (T (0));
1341 return Vec2 (x / l, y / l);
1346 Vec2<T>::normalizedExc() const
1350 if (IMATH_UNLIKELY(l == T (0)))
1351 throw std::domain_error ("Cannot normalize null vector.");
1353 return Vec2 (x / l, y / l);
1357 IMATH_HOSTDEVICE inline Vec2<T>
1358 Vec2<T>::normalizedNonNull() const IMATH_NOEXCEPT
1361 return Vec2 (x / l, y / l);
1364 //-----------------------
1365 // Implementation of Vec3
1366 //-----------------------
1370 IMATH_CONSTEXPR14 inline T&
1371 Vec3<T>::operator[] (int i) IMATH_NOEXCEPT
1373 return (&x)[i]; // NOSONAR - suppress SonarCloud bug report.
1377 IMATH_HOSTDEVICE constexpr inline const T&
1378 Vec3<T>::operator[] (int i) const IMATH_NOEXCEPT
1380 return (&x)[i]; // NOSONAR - suppress SonarCloud bug report.
1383 template <class T> IMATH_HOSTDEVICE inline Vec3<T>::Vec3() IMATH_NOEXCEPT
1385 // empty, and not constexpr because data is uninitialized.
1388 template <class T> IMATH_HOSTDEVICE constexpr inline Vec3<T>::Vec3 (T a) IMATH_NOEXCEPT
1393 template <class T> IMATH_HOSTDEVICE constexpr inline Vec3<T>::Vec3 (T a, T b, T c) IMATH_NOEXCEPT
1398 template <class T> IMATH_HOSTDEVICE constexpr inline Vec3<T>::Vec3 (const Vec3& v) IMATH_NOEXCEPT
1399 : x(v.x), y(v.y), z(v.z)
1403 template <class T> template <class S>
1404 IMATH_HOSTDEVICE constexpr inline Vec3<T>::Vec3 (const Vec3<S>& v) IMATH_NOEXCEPT
1405 : x(T(v.x)), y(T(v.y)), z(T(v.z))
1410 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1411 Vec3<T>::operator= (const Vec3& v) IMATH_NOEXCEPT
1419 template <class T> template <class S>
1420 IMATH_HOSTDEVICE constexpr inline Vec3<T>::Vec3 (const Vec4<S>& v) IMATH_NOEXCEPT
1421 : x(T(v.x/v.w)), y(T(v.y/v.w)), z(T(v.z/v.w))
1427 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Vec3<T>::Vec3 (const Vec4<S>& v, InfException)
1434 T absW = (vw >= T (0)) ? vw : -vw;
1438 T m = baseTypeMax() * absW;
1440 if (vx <= -m || vx >= m || vy <= -m || vy >= m || vz <= -m || vz >= m)
1441 throw std::domain_error ("Cannot normalize point at infinity.");
1451 IMATH_HOSTDEVICE inline void
1452 Vec3<T>::setValue (S a, S b, S c) IMATH_NOEXCEPT
1461 IMATH_HOSTDEVICE inline void
1462 Vec3<T>::setValue (const Vec3<S>& v) IMATH_NOEXCEPT
1471 IMATH_HOSTDEVICE inline void
1472 Vec3<T>::getValue (S& a, S& b, S& c) const IMATH_NOEXCEPT
1481 IMATH_HOSTDEVICE inline void
1482 Vec3<T>::getValue (Vec3<S>& v) const IMATH_NOEXCEPT
1490 IMATH_HOSTDEVICE inline T*
1491 Vec3<T>::getValue() IMATH_NOEXCEPT
1497 IMATH_HOSTDEVICE inline const T*
1498 Vec3<T>::getValue() const IMATH_NOEXCEPT
1500 return (const T*) &x;
1505 IMATH_HOSTDEVICE constexpr inline bool
1506 Vec3<T>::operator== (const Vec3<S>& v) const IMATH_NOEXCEPT
1508 return x == v.x && y == v.y && z == v.z;
1513 IMATH_HOSTDEVICE constexpr inline bool
1514 Vec3<T>::operator!= (const Vec3<S>& v) const IMATH_NOEXCEPT
1516 return x != v.x || y != v.y || z != v.z;
1520 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool
1521 Vec3<T>::equalWithAbsError (const Vec3<T>& v, T e) const IMATH_NOEXCEPT
1523 for (int i = 0; i < 3; i++)
1524 if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i], v[i], e))
1531 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool
1532 Vec3<T>::equalWithRelError (const Vec3<T>& v, T e) const IMATH_NOEXCEPT
1534 for (int i = 0; i < 3; i++)
1535 if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i], v[i], e))
1542 IMATH_HOSTDEVICE constexpr inline T
1543 Vec3<T>::dot (const Vec3& v) const IMATH_NOEXCEPT
1545 return x * v.x + y * v.y + z * v.z;
1549 IMATH_HOSTDEVICE constexpr inline T
1550 Vec3<T>::operator^ (const Vec3& v) const IMATH_NOEXCEPT
1556 IMATH_HOSTDEVICE constexpr inline Vec3<T>
1557 Vec3<T>::cross (const Vec3& v) const IMATH_NOEXCEPT
1559 return Vec3 (y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x);
1563 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1564 Vec3<T>::operator%= (const Vec3& v) IMATH_NOEXCEPT
1566 T a = y * v.z - z * v.y;
1567 T b = z * v.x - x * v.z;
1568 T c = x * v.y - y * v.x;
1576 IMATH_HOSTDEVICE constexpr inline Vec3<T>
1577 Vec3<T>::operator% (const Vec3& v) const IMATH_NOEXCEPT
1579 return Vec3 (y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x);
1583 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1584 Vec3<T>::operator+= (const Vec3& v) IMATH_NOEXCEPT
1593 IMATH_HOSTDEVICE constexpr inline Vec3<T>
1594 Vec3<T>::operator+ (const Vec3& v) const IMATH_NOEXCEPT
1596 return Vec3 (x + v.x, y + v.y, z + v.z);
1600 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1601 Vec3<T>::operator-= (const Vec3& v) IMATH_NOEXCEPT
1610 IMATH_HOSTDEVICE constexpr inline Vec3<T>
1611 Vec3<T>::operator- (const Vec3& v) const IMATH_NOEXCEPT
1613 return Vec3 (x - v.x, y - v.y, z - v.z);
1617 IMATH_HOSTDEVICE constexpr inline Vec3<T>
1618 Vec3<T>::operator-() const IMATH_NOEXCEPT
1620 return Vec3 (-x, -y, -z);
1624 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1625 Vec3<T>::negate() IMATH_NOEXCEPT
1634 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1635 Vec3<T>::operator*= (const Vec3& v) IMATH_NOEXCEPT
1644 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1645 Vec3<T>::operator*= (T a) IMATH_NOEXCEPT
1654 IMATH_HOSTDEVICE constexpr inline Vec3<T>
1655 Vec3<T>::operator* (const Vec3& v) const IMATH_NOEXCEPT
1657 return Vec3 (x * v.x, y * v.y, z * v.z);
1661 IMATH_HOSTDEVICE constexpr inline Vec3<T>
1662 Vec3<T>::operator* (T a) const IMATH_NOEXCEPT
1664 return Vec3 (x * a, y * a, z * a);
1668 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1669 Vec3<T>::operator/= (const Vec3& v) IMATH_NOEXCEPT
1678 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1679 Vec3<T>::operator/= (T a) IMATH_NOEXCEPT
1688 IMATH_HOSTDEVICE constexpr inline Vec3<T>
1689 Vec3<T>::operator/ (const Vec3& v) const IMATH_NOEXCEPT
1691 return Vec3 (x / v.x, y / v.y, z / v.z);
1695 IMATH_HOSTDEVICE constexpr inline Vec3<T>
1696 Vec3<T>::operator/ (T a) const IMATH_NOEXCEPT
1698 return Vec3 (x / a, y / a, z / a);
1702 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline T
1703 Vec3<T>::lengthTiny() const IMATH_NOEXCEPT
1705 T absX = (x >= T (0)) ? x : -x;
1706 T absY = (y >= T (0)) ? y : -y;
1707 T absZ = (z >= T (0)) ? z : -z;
1717 if (IMATH_UNLIKELY(max == T (0)))
1721 // Do not replace the divisions by max with multiplications by 1/max.
1722 // Computing 1/max can overflow but the divisions below will always
1723 // produce results less than or equal to 1.
1730 return max * std::sqrt (absX * absX + absY * absY + absZ * absZ);
1734 IMATH_HOSTDEVICE inline T
1735 Vec3<T>::length() const IMATH_NOEXCEPT
1737 T length2 = dot (*this);
1739 if (IMATH_UNLIKELY(length2 < T (2) * std::numeric_limits<T>::min()))
1740 return lengthTiny();
1742 return std::sqrt (length2);
1746 IMATH_HOSTDEVICE constexpr inline T
1747 Vec3<T>::length2() const IMATH_NOEXCEPT
1753 IMATH_HOSTDEVICE inline const Vec3<T>&
1754 Vec3<T>::normalize() IMATH_NOEXCEPT
1758 if (IMATH_LIKELY(l != T (0)))
1761 // Do not replace the divisions by l with multiplications by 1/l.
1762 // Computing 1/l can overflow but the divisions below will always
1763 // produce results less than or equal to 1.
1775 inline const Vec3<T>&
1776 Vec3<T>::normalizeExc()
1780 if (IMATH_UNLIKELY(l == T (0)))
1781 throw std::domain_error ("Cannot normalize null vector.");
1790 IMATH_HOSTDEVICE inline const Vec3<T>&
1791 Vec3<T>::normalizeNonNull() IMATH_NOEXCEPT
1801 IMATH_HOSTDEVICE inline Vec3<T>
1802 Vec3<T>::normalized() const IMATH_NOEXCEPT
1806 if (IMATH_UNLIKELY((l == T (0))))
1807 return Vec3 (T (0));
1809 return Vec3 (x / l, y / l, z / l);
1814 Vec3<T>::normalizedExc() const
1818 if (IMATH_UNLIKELY(l == T (0)))
1819 throw std::domain_error ("Cannot normalize null vector.");
1821 return Vec3 (x / l, y / l, z / l);
1825 IMATH_HOSTDEVICE inline Vec3<T>
1826 Vec3<T>::normalizedNonNull() const IMATH_NOEXCEPT
1829 return Vec3 (x / l, y / l, z / l);
1832 //-----------------------
1833 // Implementation of Vec4
1834 //-----------------------
1838 IMATH_CONSTEXPR14 inline T&
1839 Vec4<T>::operator[] (int i) IMATH_NOEXCEPT
1841 return (&x)[i]; // NOSONAR - suppress SonarCloud bug report.
1845 IMATH_HOSTDEVICE constexpr inline const T&
1846 Vec4<T>::operator[] (int i) const IMATH_NOEXCEPT
1848 return (&x)[i]; // NOSONAR - suppress SonarCloud bug report.
1851 template <class T> IMATH_HOSTDEVICE inline Vec4<T>::Vec4() IMATH_NOEXCEPT
1853 // empty, and not constexpr because data is uninitialized.
1856 template <class T> IMATH_HOSTDEVICE constexpr inline Vec4<T>::Vec4 (T a) IMATH_NOEXCEPT
1857 : x(a), y(a), z(a), w(a)
1861 template <class T> IMATH_HOSTDEVICE constexpr inline Vec4<T>::Vec4 (T a, T b, T c, T d) IMATH_NOEXCEPT
1862 : x(a), y(b), z(c), w(d)
1866 template <class T> IMATH_HOSTDEVICE constexpr inline Vec4<T>::Vec4 (const Vec4& v) IMATH_NOEXCEPT
1867 : x(v.x), y(v.y), z(v.z), w(v.w)
1871 template <class T> template <class S>
1872 IMATH_HOSTDEVICE constexpr inline Vec4<T>::Vec4 (const Vec4<S>& v) IMATH_NOEXCEPT
1873 : x(T(v.x)), y(T(v.y)), z(T(v.z)), w(T(v.w))
1878 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4<T>&
1879 Vec4<T>::operator= (const Vec4& v) IMATH_NOEXCEPT
1888 template <class T> template <class S>
1889 IMATH_HOSTDEVICE constexpr inline Vec4<T>::Vec4 (const Vec3<S>& v) IMATH_NOEXCEPT
1890 : x(T(v.x)), y(T(v.y)), z(T(v.z)), w(T(1))
1896 IMATH_HOSTDEVICE constexpr inline bool
1897 Vec4<T>::operator== (const Vec4<S>& v) const IMATH_NOEXCEPT
1899 return x == v.x && y == v.y && z == v.z && w == v.w;
1904 IMATH_HOSTDEVICE constexpr inline bool
1905 Vec4<T>::operator!= (const Vec4<S>& v) const IMATH_NOEXCEPT
1907 return x != v.x || y != v.y || z != v.z || w != v.w;
1911 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool
1912 Vec4<T>::equalWithAbsError (const Vec4<T>& v, T e) const IMATH_NOEXCEPT
1914 for (int i = 0; i < 4; i++)
1915 if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i], v[i], e))
1922 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool
1923 Vec4<T>::equalWithRelError (const Vec4<T>& v, T e) const IMATH_NOEXCEPT
1925 for (int i = 0; i < 4; i++)
1926 if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i], v[i], e))
1933 IMATH_HOSTDEVICE constexpr inline T
1934 Vec4<T>::dot (const Vec4& v) const IMATH_NOEXCEPT
1936 return x * v.x + y * v.y + z * v.z + w * v.w;
1940 IMATH_HOSTDEVICE constexpr inline T
1941 Vec4<T>::operator^ (const Vec4& v) const IMATH_NOEXCEPT
1947 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4<T>&
1948 Vec4<T>::operator+= (const Vec4& v) IMATH_NOEXCEPT
1958 IMATH_HOSTDEVICE constexpr inline Vec4<T>
1959 Vec4<T>::operator+ (const Vec4& v) const IMATH_NOEXCEPT
1961 return Vec4 (x + v.x, y + v.y, z + v.z, w + v.w);
1965 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4<T>&
1966 Vec4<T>::operator-= (const Vec4& v) IMATH_NOEXCEPT
1976 IMATH_HOSTDEVICE constexpr inline Vec4<T>
1977 Vec4<T>::operator- (const Vec4& v) const IMATH_NOEXCEPT
1979 return Vec4 (x - v.x, y - v.y, z - v.z, w - v.w);
1983 IMATH_HOSTDEVICE constexpr inline Vec4<T>
1984 Vec4<T>::operator-() const IMATH_NOEXCEPT
1986 return Vec4 (-x, -y, -z, -w);
1990 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4<T>&
1991 Vec4<T>::negate() IMATH_NOEXCEPT
2001 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4<T>&
2002 Vec4<T>::operator*= (const Vec4& v) IMATH_NOEXCEPT
2012 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4<T>&
2013 Vec4<T>::operator*= (T a) IMATH_NOEXCEPT
2023 IMATH_HOSTDEVICE constexpr inline Vec4<T>
2024 Vec4<T>::operator* (const Vec4& v) const IMATH_NOEXCEPT
2026 return Vec4 (x * v.x, y * v.y, z * v.z, w * v.w);
2030 IMATH_HOSTDEVICE constexpr inline Vec4<T>
2031 Vec4<T>::operator* (T a) const IMATH_NOEXCEPT
2033 return Vec4 (x * a, y * a, z * a, w * a);
2037 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4<T>&
2038 Vec4<T>::operator/= (const Vec4& v) IMATH_NOEXCEPT
2048 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4<T>&
2049 Vec4<T>::operator/= (T a) IMATH_NOEXCEPT
2059 IMATH_HOSTDEVICE constexpr inline Vec4<T>
2060 Vec4<T>::operator/ (const Vec4& v) const IMATH_NOEXCEPT
2062 return Vec4 (x / v.x, y / v.y, z / v.z, w / v.w);
2066 IMATH_HOSTDEVICE constexpr inline Vec4<T>
2067 Vec4<T>::operator/ (T a) const IMATH_NOEXCEPT
2069 return Vec4 (x / a, y / a, z / a, w / a);
2073 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline T
2074 Vec4<T>::lengthTiny() const IMATH_NOEXCEPT
2076 T absX = (x >= T (0)) ? x : -x;
2077 T absY = (y >= T (0)) ? y : -y;
2078 T absZ = (z >= T (0)) ? z : -z;
2079 T absW = (w >= T (0)) ? w : -w;
2092 if (IMATH_UNLIKELY(max == T (0)))
2096 // Do not replace the divisions by max with multiplications by 1/max.
2097 // Computing 1/max can overflow but the divisions below will always
2098 // produce results less than or equal to 1.
2106 return max * std::sqrt (absX * absX + absY * absY + absZ * absZ + absW * absW);
2110 IMATH_HOSTDEVICE inline T
2111 Vec4<T>::length() const IMATH_NOEXCEPT
2113 T length2 = dot (*this);
2115 if (IMATH_UNLIKELY(length2 < T (2) * std::numeric_limits<T>::min()))
2116 return lengthTiny();
2118 return std::sqrt (length2);
2122 IMATH_HOSTDEVICE constexpr inline T
2123 Vec4<T>::length2() const IMATH_NOEXCEPT
2129 IMATH_HOSTDEVICE const inline Vec4<T>&
2130 Vec4<T>::normalize() IMATH_NOEXCEPT
2134 if (IMATH_LIKELY(l != T (0)))
2137 // Do not replace the divisions by l with multiplications by 1/l.
2138 // Computing 1/l can overflow but the divisions below will always
2139 // produce results less than or equal to 1.
2152 const inline Vec4<T>&
2153 Vec4<T>::normalizeExc()
2157 if (IMATH_UNLIKELY(l == T (0)))
2158 throw std::domain_error ("Cannot normalize null vector.");
2168 IMATH_HOSTDEVICE inline const Vec4<T>&
2169 Vec4<T>::normalizeNonNull() IMATH_NOEXCEPT
2180 IMATH_HOSTDEVICE inline Vec4<T>
2181 Vec4<T>::normalized() const IMATH_NOEXCEPT
2185 if (IMATH_UNLIKELY(l == T (0)))
2186 return Vec4 (T (0));
2188 return Vec4 (x / l, y / l, z / l, w / l);
2193 Vec4<T>::normalizedExc() const
2197 if (IMATH_UNLIKELY(l == T (0)))
2198 throw std::domain_error ("Cannot normalize null vector.");
2200 return Vec4 (x / l, y / l, z / l, w / l);
2204 IMATH_HOSTDEVICE inline Vec4<T>
2205 Vec4<T>::normalizedNonNull() const IMATH_NOEXCEPT
2208 return Vec4 (x / l, y / l, z / l, w / l);
2211 //-----------------------------
2212 // Stream output implementation
2213 //-----------------------------
2217 operator<< (std::ostream& s, const Vec2<T>& v)
2219 return s << '(' << v.x << ' ' << v.y << ')';
2224 operator<< (std::ostream& s, const Vec3<T>& v)
2226 return s << '(' << v.x << ' ' << v.y << ' ' << v.z << ')';
2231 operator<< (std::ostream& s, const Vec4<T>& v)
2233 return s << '(' << v.x << ' ' << v.y << ' ' << v.z << ' ' << v.w << ')';
2236 //-----------------------------------------
2237 // Implementation of reverse multiplication
2238 //-----------------------------------------
2241 IMATH_HOSTDEVICE constexpr inline Vec2<T>
2242 operator* (T a, const Vec2<T>& v) IMATH_NOEXCEPT
2244 return Vec2<T> (a * v.x, a * v.y);
2248 IMATH_HOSTDEVICE constexpr inline Vec3<T>
2249 operator* (T a, const Vec3<T>& v) IMATH_NOEXCEPT
2251 return Vec3<T> (a * v.x, a * v.y, a * v.z);
2255 IMATH_HOSTDEVICE constexpr inline Vec4<T>
2256 operator* (T a, const Vec4<T>& v) IMATH_NOEXCEPT
2258 return Vec4<T> (a * v.x, a * v.y, a * v.z, a * v.w);
2261 #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
2262 # pragma warning(pop)
2265 IMATH_INTERNAL_NAMESPACE_HEADER_EXIT
2267 #endif // INCLUDED_IMATHVEC_H