1//
2// SPDX-License-Identifier: BSD-3-Clause
3// Copyright Contributors to the OpenEXR Project.
4//
5
6//
7// 2D, 3D and 4D point/vector class templates
8//
9
10#ifndef INCLUDED_IMATHVEC_H
11#define INCLUDED_IMATHVEC_H
12
13#include "ImathExport.h"
14#include "ImathNamespace.h"
15#include "ImathTypeTraits.h"
16
17#include "ImathMath.h"
18
19#include <iostream>
20#include <limits>
21#include <cstdint>
22#include <stdexcept>
23
24#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
25// suppress exception specification warnings
26# pragma warning(push)
27# pragma warning(disable : 4290)
28#endif
29
30IMATH_INTERNAL_NAMESPACE_HEADER_ENTER
31
32template <class T> class Vec2;
33template <class T> class Vec3;
34template <class T> class Vec4;
35
36/// Enum for the Vec4 to Vec3 conversion constructor
37enum IMATH_EXPORT_ENUM InfException
38{
39 INF_EXCEPTION
40};
41
42///
43/// 2-element vector
44///
45
46template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Vec2
47{
48 public:
49
50 /// @{
51 /// @name Direct access to elements
52
53 T x, y;
54
55 /// @}
56
57 /// Element access by index.
58 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T& operator[] (int i) IMATH_NOEXCEPT;
59
60 /// Element access by index.
61 IMATH_HOSTDEVICE constexpr const T& operator[] (int i) const IMATH_NOEXCEPT;
62
63 /// @{
64 /// @name Constructors and Assignment
65
66 /// Uninitialized by default
67 IMATH_HOSTDEVICE Vec2() IMATH_NOEXCEPT;
68
69 /// Initialize to a scalar `(a,a)`
70 IMATH_HOSTDEVICE constexpr explicit Vec2 (T a) IMATH_NOEXCEPT;
71
72 /// Initialize to given elements `(a,b)`
73 IMATH_HOSTDEVICE constexpr Vec2 (T a, T b) IMATH_NOEXCEPT;
74
75 /// Copy constructor
76 IMATH_HOSTDEVICE constexpr Vec2 (const Vec2& v) IMATH_NOEXCEPT;
77
78 /// Construct from Vec2 of another base type
79 template <class S> IMATH_HOSTDEVICE constexpr Vec2 (const Vec2<S>& v) IMATH_NOEXCEPT;
80
81
82 /// Assignment
83 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& operator= (const Vec2& v) IMATH_NOEXCEPT;
84
85 /// Destructor
86 ~Vec2() IMATH_NOEXCEPT = default;
87
88 /// @}
89
90#if IMATH_FOREIGN_VECTOR_INTEROP
91 /// @{
92 /// @name Interoperability with other vector types
93 ///
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.
99 ///
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.
104 ///
105
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)) { }
109
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])) { }
113
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 {
116 x = T(v.x);
117 y = T(v.y);
118 return *this;
119 }
120
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) {
124 x = T(v[0]);
125 y = T(v[1]);
126 return *this;
127 }
128#endif
129
130 /// @{
131 /// @name Compatibility with Sb
132
133 /// Set the value
134 template <class S> IMATH_HOSTDEVICE void setValue (S a, S b) IMATH_NOEXCEPT;
135
136 /// Set the value
137 template <class S> IMATH_HOSTDEVICE void setValue (const Vec2<S>& v) IMATH_NOEXCEPT;
138
139 /// Return the value in `a` and `b`
140 template <class S> IMATH_HOSTDEVICE void getValue (S& a, S& b) const IMATH_NOEXCEPT;
141
142 /// Return the value in `v`
143 template <class S> IMATH_HOSTDEVICE void getValue (Vec2<S>& v) const IMATH_NOEXCEPT;
144
145 /// Return a raw pointer to the array of values
146 IMATH_HOSTDEVICE T* getValue() IMATH_NOEXCEPT;
147
148 /// Return a raw pointer to the array of values
149 IMATH_HOSTDEVICE const T* getValue() const IMATH_NOEXCEPT;
150
151 /// @}
152
153 /// @{
154 /// @name Arithmetic and Comparison
155
156 /// Equality
157 template <class S> IMATH_HOSTDEVICE constexpr bool operator== (const Vec2<S>& v) const IMATH_NOEXCEPT;
158
159
160 /// Inequality
161 template <class S> IMATH_HOSTDEVICE constexpr bool operator!= (const Vec2<S>& v) const IMATH_NOEXCEPT;
162
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:
166 ///
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;
169
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:
173 ///
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;
176
177 /// Dot product
178 IMATH_HOSTDEVICE constexpr T dot (const Vec2& v) const IMATH_NOEXCEPT;
179
180 /// Dot product
181 IMATH_HOSTDEVICE constexpr T operator^ (const Vec2& v) const IMATH_NOEXCEPT;
182
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;
186
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;
190
191 /// Component-wise addition
192 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& operator+= (const Vec2& v) IMATH_NOEXCEPT;
193
194 /// Component-wise addition
195 IMATH_HOSTDEVICE constexpr Vec2 operator+ (const Vec2& v) const IMATH_NOEXCEPT;
196
197 /// Component-wise subtraction
198 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& operator-= (const Vec2& v) IMATH_NOEXCEPT;
199
200 /// Component-wise subtraction
201 IMATH_HOSTDEVICE constexpr Vec2 operator- (const Vec2& v) const IMATH_NOEXCEPT;
202
203 /// Component-wise multiplication by -1
204 IMATH_HOSTDEVICE constexpr Vec2 operator-() const IMATH_NOEXCEPT;
205
206 /// Component-wise multiplication by -1
207 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& negate() IMATH_NOEXCEPT;
208
209 /// Component-wise multiplication
210 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& operator*= (const Vec2& v) IMATH_NOEXCEPT;
211
212 /// Component-wise multiplication
213 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& operator*= (T a) IMATH_NOEXCEPT;
214
215 /// Component-wise multiplication
216 IMATH_HOSTDEVICE constexpr Vec2 operator* (const Vec2& v) const IMATH_NOEXCEPT;
217
218 /// Component-wise multiplication
219 IMATH_HOSTDEVICE constexpr Vec2 operator* (T a) const IMATH_NOEXCEPT;
220
221 /// Component-wise division
222 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& operator/= (const Vec2& v) IMATH_NOEXCEPT;
223
224 /// Component-wise division
225 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& operator/= (T a) IMATH_NOEXCEPT;
226
227 /// Component-wise division
228 IMATH_HOSTDEVICE constexpr Vec2 operator/ (const Vec2& v) const IMATH_NOEXCEPT;
229
230 /// Component-wise division
231 IMATH_HOSTDEVICE constexpr Vec2 operator/ (T a) const IMATH_NOEXCEPT;
232
233 /// @}
234
235 /// @{
236 /// @name Query and Manipulation
237
238 /// Return the Euclidean norm
239 IMATH_HOSTDEVICE T length() const IMATH_NOEXCEPT;
240
241 /// Return the square of the Euclidean norm, i.e. the dot product
242 /// with itself.
243 IMATH_HOSTDEVICE constexpr T length2() const IMATH_NOEXCEPT;
244
245 /// Normalize in place. If length()==0, return a null vector.
246 IMATH_HOSTDEVICE const Vec2& normalize() IMATH_NOEXCEPT;
247
248 /// Normalize in place. If length()==0, throw an exception.
249 const Vec2& normalizeExc();
250
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;
255
256 /// Return a normalized vector. Does not modify *this.
257 IMATH_HOSTDEVICE Vec2<T> normalized() const IMATH_NOEXCEPT;
258
259 /// Return a normalized vector. Does not modify *this. Throw an
260 /// exception if length()==0.
261 Vec2<T> normalizedExc() const;
262
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
266 /// is undefined.
267 IMATH_HOSTDEVICE Vec2<T> normalizedNonNull() const IMATH_NOEXCEPT;
268
269 /// @}
270
271 /// @{
272 /// @name Numeric Limits
273
274 /// Largest possible negative value
275 IMATH_HOSTDEVICE constexpr static T baseTypeLowest() IMATH_NOEXCEPT { return std::numeric_limits<T>::lowest(); }
276
277 /// Largest possible positive value
278 IMATH_HOSTDEVICE constexpr static T baseTypeMax() IMATH_NOEXCEPT { return std::numeric_limits<T>::max(); }
279
280 /// Smallest possible positive value
281 IMATH_HOSTDEVICE constexpr static T baseTypeSmallest() IMATH_NOEXCEPT { return std::numeric_limits<T>::min(); }
282
283 /// Smallest possible e for which 1+e != 1
284 IMATH_HOSTDEVICE constexpr static T baseTypeEpsilon() IMATH_NOEXCEPT { return std::numeric_limits<T>::epsilon(); }
285
286 /// @}
287
288 /// Return the number of dimensions, i.e. 2
289 IMATH_HOSTDEVICE constexpr static unsigned int dimensions() IMATH_NOEXCEPT { return 2; }
290
291 /// The base type: In templates that accept a parameter `V`, you
292 /// can refer to `T` as `V::BaseType`
293 typedef T BaseType;
294
295 private:
296
297 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T lengthTiny() const IMATH_NOEXCEPT;
298};
299
300///
301/// 3-element vector
302///
303
304template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Vec3
305{
306 public:
307
308 /// @{
309 /// @name Direct access to elements
310
311 T x, y, z;
312
313 /// @}
314
315 /// Element access by index.
316 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T& operator[] (int i) IMATH_NOEXCEPT;
317
318 /// Element access by index.
319 IMATH_HOSTDEVICE constexpr const T& operator[] (int i) const IMATH_NOEXCEPT;
320
321 /// @{
322 /// @name Constructors and Assignment
323
324 /// Uninitialized by default
325 IMATH_HOSTDEVICE Vec3() IMATH_NOEXCEPT;
326
327 /// Initialize to a scalar `(a,a,a)`
328 IMATH_HOSTDEVICE constexpr explicit Vec3 (T a) IMATH_NOEXCEPT;
329
330 /// Initialize to given elements `(a,b,c)`
331 IMATH_HOSTDEVICE constexpr Vec3 (T a, T b, T c) IMATH_NOEXCEPT;
332
333 /// Copy constructor
334 IMATH_HOSTDEVICE constexpr Vec3 (const Vec3& v) IMATH_NOEXCEPT;
335
336 /// Construct from Vec3 of another base type
337 template <class S> IMATH_HOSTDEVICE constexpr Vec3 (const Vec3<S>& v) IMATH_NOEXCEPT;
338
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;
343
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.
346 template <class S>
347 explicit IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Vec3 (const Vec4<S>& v, InfException);
348
349 /// Assignment
350 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator= (const Vec3& v) IMATH_NOEXCEPT;
351
352 /// Destructor
353 ~Vec3() IMATH_NOEXCEPT = default;
354
355 /// @}
356
357#if IMATH_FOREIGN_VECTOR_INTEROP
358 /// @{
359 /// @name Interoperability with other vector types
360 ///
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.
366 ///
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.
371 ///
372
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)) { }
376
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])) { }
380
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 {
385 x = T(v.x);
386 y = T(v.y);
387 z = T(v.z);
388 return *this;
389 }
390
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) {
394 x = T(v[0]);
395 y = T(v[1]);
396 z = T(v[2]);
397 return *this;
398 }
399 /// @}
400#endif
401
402 /// @{
403 /// @name Compatibility with Sb
404
405 /// Set the value
406 template <class S> IMATH_HOSTDEVICE void setValue (S a, S b, S c) IMATH_NOEXCEPT;
407
408 /// Set the value
409 template <class S> IMATH_HOSTDEVICE void setValue (const Vec3<S>& v) IMATH_NOEXCEPT;
410
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;
413
414 /// Return the value in `v`
415 template <class S> IMATH_HOSTDEVICE void getValue (Vec3<S>& v) const IMATH_NOEXCEPT;
416
417 /// Return a raw pointer to the array of values
418 IMATH_HOSTDEVICE T* getValue() IMATH_NOEXCEPT;
419
420 /// Return a raw pointer to the array of values
421 IMATH_HOSTDEVICE const T* getValue() const IMATH_NOEXCEPT;
422
423 /// @}
424
425 /// @{
426 /// @name Arithmetic and Comparison
427
428 /// Equality
429 template <class S> IMATH_HOSTDEVICE constexpr bool operator== (const Vec3<S>& v) const IMATH_NOEXCEPT;
430
431 /// Inequality
432 template <class S> IMATH_HOSTDEVICE constexpr bool operator!= (const Vec3<S>& v) const IMATH_NOEXCEPT;
433
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:
437 ///
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;
440
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:
444 ///
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;
447
448 /// Dot product
449 IMATH_HOSTDEVICE constexpr T dot (const Vec3& v) const IMATH_NOEXCEPT;
450
451 /// Dot product
452 IMATH_HOSTDEVICE constexpr T operator^ (const Vec3& v) const IMATH_NOEXCEPT;
453
454 /// Right-handed cross product
455 IMATH_HOSTDEVICE constexpr Vec3 cross (const Vec3& v) const IMATH_NOEXCEPT;
456
457 /// Right-handed cross product
458 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator%= (const Vec3& v) IMATH_NOEXCEPT;
459
460 /// Right-handed cross product
461 IMATH_HOSTDEVICE constexpr Vec3 operator% (const Vec3& v) const IMATH_NOEXCEPT;
462
463 /// Component-wise addition
464 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator+= (const Vec3& v) IMATH_NOEXCEPT;
465
466 /// Component-wise addition
467 IMATH_HOSTDEVICE constexpr Vec3 operator+ (const Vec3& v) const IMATH_NOEXCEPT;
468
469 /// Component-wise subtraction
470 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator-= (const Vec3& v) IMATH_NOEXCEPT;
471
472 /// Component-wise subtraction
473 IMATH_HOSTDEVICE constexpr Vec3 operator- (const Vec3& v) const IMATH_NOEXCEPT;
474
475 /// Component-wise multiplication by -1
476 IMATH_HOSTDEVICE constexpr Vec3 operator-() const IMATH_NOEXCEPT;
477
478 /// Component-wise multiplication by -1
479 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& negate() IMATH_NOEXCEPT;
480
481 /// Component-wise multiplication
482 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator*= (const Vec3& v) IMATH_NOEXCEPT;
483
484 /// Component-wise multiplication
485 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator*= (T a) IMATH_NOEXCEPT;
486
487 /// Component-wise multiplication
488 IMATH_HOSTDEVICE constexpr Vec3 operator* (const Vec3& v) const IMATH_NOEXCEPT;
489
490 /// Component-wise multiplication
491 IMATH_HOSTDEVICE constexpr Vec3 operator* (T a) const IMATH_NOEXCEPT;
492
493 /// Component-wise division
494 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator/= (const Vec3& v) IMATH_NOEXCEPT;
495
496 /// Component-wise division
497 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator/= (T a) IMATH_NOEXCEPT;
498
499 /// Component-wise division
500 IMATH_HOSTDEVICE constexpr Vec3 operator/ (const Vec3& v) const IMATH_NOEXCEPT;
501
502 /// Component-wise division
503 IMATH_HOSTDEVICE constexpr Vec3 operator/ (T a) const IMATH_NOEXCEPT;
504
505 /// @}
506
507 /// @{
508 /// @name Query and Manipulation
509
510 /// Return the Euclidean norm
511 IMATH_HOSTDEVICE T length() const IMATH_NOEXCEPT;
512
513 /// Return the square of the Euclidean norm, i.e. the dot product
514 /// with itself.
515 IMATH_HOSTDEVICE constexpr T length2() const IMATH_NOEXCEPT;
516
517 /// Normalize in place. If length()==0, return a null vector.
518 IMATH_HOSTDEVICE const Vec3& normalize() IMATH_NOEXCEPT;
519
520 /// Normalize in place. If length()==0, throw an exception.
521 const Vec3& normalizeExc();
522
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;
527
528 /// Return a normalized vector. Does not modify *this.
529 IMATH_HOSTDEVICE Vec3<T> normalized() const IMATH_NOEXCEPT; // does not modify *this
530
531 /// Return a normalized vector. Does not modify *this. Throw an
532 /// exception if length()==0.
533 Vec3<T> normalizedExc() const;
534
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
538 /// is undefined.
539 IMATH_HOSTDEVICE Vec3<T> normalizedNonNull() const IMATH_NOEXCEPT;
540
541 /// @}
542
543 /// @{
544 /// @name Numeric Limits
545
546 /// Largest possible negative value
547 IMATH_HOSTDEVICE constexpr static T baseTypeLowest() IMATH_NOEXCEPT { return std::numeric_limits<T>::lowest(); }
548
549 /// Largest possible positive value
550 IMATH_HOSTDEVICE constexpr static T baseTypeMax() IMATH_NOEXCEPT { return std::numeric_limits<T>::max(); }
551
552 /// Smallest possible positive value
553 IMATH_HOSTDEVICE constexpr static T baseTypeSmallest() IMATH_NOEXCEPT { return std::numeric_limits<T>::min(); }
554
555 /// Smallest possible e for which 1+e != 1
556 IMATH_HOSTDEVICE constexpr static T baseTypeEpsilon() IMATH_NOEXCEPT { return std::numeric_limits<T>::epsilon(); }
557
558 /// @}
559
560 /// Return the number of dimensions, i.e. 3
561 IMATH_HOSTDEVICE constexpr static unsigned int dimensions() IMATH_NOEXCEPT { return 3; }
562
563 /// The base type: In templates that accept a parameter `V`, you
564 /// can refer to `T` as `V::BaseType`
565 typedef T BaseType;
566
567 private:
568 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T lengthTiny() const IMATH_NOEXCEPT;
569};
570
571///
572/// 4-element vector
573///
574
575template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Vec4
576{
577 public:
578
579 /// @{
580 /// @name Direct access to elements
581
582 T x, y, z, w;
583
584 /// @}
585
586 /// Element access by index.
587 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T& operator[] (int i) IMATH_NOEXCEPT;
588
589 /// Element access by index.
590 IMATH_HOSTDEVICE constexpr const T& operator[] (int i) const IMATH_NOEXCEPT;
591
592 /// @{
593 /// @name Constructors and Assignment
594
595 /// Uninitialized by default
596 IMATH_HOSTDEVICE Vec4() IMATH_NOEXCEPT; // no initialization
597
598 /// Initialize to a scalar `(a,a,a,a)`
599 IMATH_HOSTDEVICE constexpr explicit Vec4 (T a) IMATH_NOEXCEPT;
600
601 /// Initialize to given elements `(a,b,c,d)`
602 IMATH_HOSTDEVICE constexpr Vec4 (T a, T b, T c, T d) IMATH_NOEXCEPT;
603
604 /// Copy constructor
605 IMATH_HOSTDEVICE constexpr Vec4 (const Vec4& v) IMATH_NOEXCEPT;
606
607 /// Construct from Vec4 of another base type
608 template <class S> IMATH_HOSTDEVICE constexpr Vec4 (const Vec4<S>& v) IMATH_NOEXCEPT;
609
610 /// Vec3 to Vec4 conversion, sets w to 1.
611 template <class S> IMATH_HOSTDEVICE explicit constexpr Vec4 (const Vec3<S>& v) IMATH_NOEXCEPT;
612
613 /// Assignment
614 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& operator= (const Vec4& v) IMATH_NOEXCEPT;
615
616 /// Destructor
617 ~Vec4() IMATH_NOEXCEPT = default;
618
619 /// @}
620
621#if IMATH_FOREIGN_VECTOR_INTEROP
622 /// @{
623 /// @name Interoperability with other vector types
624 ///
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.
630 ///
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.
635 ///
636
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)) { }
640
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])) { }
644
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 {
647 x = T(v.x);
648 y = T(v.y);
649 z = T(v.z);
650 w = T(v.w);
651 return *this;
652 }
653
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) {
657 x = T(v[0]);
658 y = T(v[1]);
659 z = T(v[2]);
660 w = T(v[3]);
661 return *this;
662 }
663 /// @}
664#endif
665
666 /// @{
667 /// @name Arithmetic and Comparison
668
669 /// Equality
670 template <class S> IMATH_HOSTDEVICE constexpr bool operator== (const Vec4<S>& v) const IMATH_NOEXCEPT;
671
672 /// Inequality
673 template <class S> IMATH_HOSTDEVICE constexpr bool operator!= (const Vec4<S>& v) const IMATH_NOEXCEPT;
674
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:
678 ///
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;
681
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:
685 ///
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;
688
689 /// Dot product
690 IMATH_HOSTDEVICE constexpr T dot (const Vec4& v) const IMATH_NOEXCEPT;
691
692 /// Dot product
693 IMATH_HOSTDEVICE constexpr T operator^ (const Vec4& v) const IMATH_NOEXCEPT;
694
695 /// Component-wise addition
696 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& operator+= (const Vec4& v) IMATH_NOEXCEPT;
697
698 /// Component-wise addition
699 IMATH_HOSTDEVICE constexpr Vec4 operator+ (const Vec4& v) const IMATH_NOEXCEPT;
700
701 /// Component-wise subtraction
702 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& operator-= (const Vec4& v) IMATH_NOEXCEPT;
703
704 /// Component-wise subtraction
705 IMATH_HOSTDEVICE constexpr Vec4 operator- (const Vec4& v) const IMATH_NOEXCEPT;
706
707 /// Component-wise multiplication by -1
708 IMATH_HOSTDEVICE constexpr Vec4 operator-() const IMATH_NOEXCEPT;
709
710 /// Component-wise multiplication by -1
711 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& negate() IMATH_NOEXCEPT;
712
713 /// Component-wise multiplication
714 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& operator*= (const Vec4& v) IMATH_NOEXCEPT;
715
716 /// Component-wise multiplication
717 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& operator*= (T a) IMATH_NOEXCEPT;
718
719 /// Component-wise multiplication
720 IMATH_HOSTDEVICE constexpr Vec4 operator* (const Vec4& v) const IMATH_NOEXCEPT;
721
722 /// Component-wise multiplication
723 IMATH_HOSTDEVICE constexpr Vec4 operator* (T a) const IMATH_NOEXCEPT;
724
725 /// Component-wise division
726 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& operator/= (const Vec4& v) IMATH_NOEXCEPT;
727
728 /// Component-wise division
729 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& operator/= (T a) IMATH_NOEXCEPT;
730
731 /// Component-wise division
732 IMATH_HOSTDEVICE constexpr Vec4 operator/ (const Vec4& v) const IMATH_NOEXCEPT;
733
734 /// Component-wise division
735 IMATH_HOSTDEVICE constexpr Vec4 operator/ (T a) const IMATH_NOEXCEPT;
736
737 /// @}
738
739 /// @{
740 /// @name Query and Manipulation
741
742 /// Return the Euclidean norm
743 IMATH_HOSTDEVICE T length() const IMATH_NOEXCEPT;
744
745 /// Return the square of the Euclidean norm, i.e. the dot product
746 /// with itself.
747 IMATH_HOSTDEVICE constexpr T length2() const IMATH_NOEXCEPT;
748
749 /// Normalize in place. If length()==0, return a null vector.
750 IMATH_HOSTDEVICE const Vec4& normalize() IMATH_NOEXCEPT; // modifies *this
751
752 /// Normalize in place. If length()==0, throw an exception.
753 const Vec4& normalizeExc();
754
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;
759
760 /// Return a normalized vector. Does not modify *this.
761 IMATH_HOSTDEVICE Vec4<T> normalized() const IMATH_NOEXCEPT; // does not modify *this
762
763 /// Return a normalized vector. Does not modify *this. Throw an
764 /// exception if length()==0.
765 Vec4<T> normalizedExc() const;
766
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
770 /// is undefined.
771 IMATH_HOSTDEVICE Vec4<T> normalizedNonNull() const IMATH_NOEXCEPT;
772
773 /// @}
774
775 /// @{
776 /// @name Numeric Limits
777
778 /// Largest possible negative value
779 IMATH_HOSTDEVICE constexpr static T baseTypeLowest() IMATH_NOEXCEPT { return std::numeric_limits<T>::lowest(); }
780
781 /// Largest possible positive value
782 IMATH_HOSTDEVICE constexpr static T baseTypeMax() IMATH_NOEXCEPT { return std::numeric_limits<T>::max(); }
783
784 /// Smallest possible positive value
785 IMATH_HOSTDEVICE constexpr static T baseTypeSmallest() IMATH_NOEXCEPT { return std::numeric_limits<T>::min(); }
786
787 /// Smallest possible e for which 1+e != 1
788 IMATH_HOSTDEVICE constexpr static T baseTypeEpsilon() IMATH_NOEXCEPT { return std::numeric_limits<T>::epsilon(); }
789
790 /// @}
791
792 /// Return the number of dimensions, i.e. 4
793 IMATH_HOSTDEVICE constexpr static unsigned int dimensions() IMATH_NOEXCEPT { return 4; }
794
795 /// The base type: In templates that accept a parameter `V`, you
796 /// can refer to `T` as `V::BaseType`
797 typedef T BaseType;
798
799 private:
800 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T lengthTiny() const IMATH_NOEXCEPT;
801};
802
803/// Stream output, as "(x y)"
804template <class T> std::ostream& operator<< (std::ostream& s, const Vec2<T>& v);
805
806/// Stream output, as "(x y z)"
807template <class T> std::ostream& operator<< (std::ostream& s, const Vec3<T>& v);
808
809/// Stream output, as "(x y z w)"
810template <class T> std::ostream& operator<< (std::ostream& s, const Vec4<T>& v);
811
812/// Reverse multiplication: S * Vec2<T>
813template <class T> IMATH_HOSTDEVICE constexpr Vec2<T> operator* (T a, const Vec2<T>& v) IMATH_NOEXCEPT;
814
815/// Reverse multiplication: S * Vec3<T>
816template <class T> IMATH_HOSTDEVICE constexpr Vec3<T> operator* (T a, const Vec3<T>& v) IMATH_NOEXCEPT;
817
818/// Reverse multiplication: S * Vec4<T>
819template <class T> IMATH_HOSTDEVICE constexpr Vec4<T> operator* (T a, const Vec4<T>& v) IMATH_NOEXCEPT;
820
821//-------------------------
822// Typedefs for convenience
823//-------------------------
824
825/// Vec2 of short
826typedef Vec2<short> V2s;
827
828/// Vec2 of integer
829typedef Vec2<int> V2i;
830
831/// Vec2 of int64_t
832typedef Vec2<int64_t> V2i64;
833
834/// Vec2 of float
835typedef Vec2<float> V2f;
836
837/// Vec2 of double
838typedef Vec2<double> V2d;
839
840/// Vec3 of short
841typedef Vec3<short> V3s;
842
843/// Vec3 of integer
844typedef Vec3<int> V3i;
845
846/// Vec3 of int64_t
847typedef Vec3<int64_t> V3i64;
848
849/// Vec3 of float
850typedef Vec3<float> V3f;
851
852/// Vec3 of double
853typedef Vec3<double> V3d;
854
855/// Vec4 of short
856typedef Vec4<short> V4s;
857
858/// Vec4 of integer
859typedef Vec4<int> V4i;
860
861/// Vec4 of int64_t
862typedef Vec4<int64_t> V4i64;
863
864/// Vec4 of float
865typedef Vec4<float> V4f;
866
867/// Vec4 of double
868typedef Vec4<double> V4d;
869
870//----------------------------------------------------------------------------
871// Specializations for VecN<short>, VecN<int>
872//
873// Normalize and length don't make sense for integer vectors, so disable them.
874//----------------------------------------------------------------------------
875
876/// @cond Doxygen_Suppress
877
878// Vec2<short>
879template <> IMATH_HOSTDEVICE short Vec2<short>::length() const IMATH_NOEXCEPT = delete;
880template <> IMATH_HOSTDEVICE const Vec2<short>& Vec2<short>::normalize() IMATH_NOEXCEPT = delete;
881template <> const Vec2<short>& Vec2<short>::normalizeExc() = delete;
882template <> IMATH_HOSTDEVICE const Vec2<short>& Vec2<short>::normalizeNonNull() IMATH_NOEXCEPT = delete;
883template <> IMATH_HOSTDEVICE Vec2<short> Vec2<short>::normalized() const IMATH_NOEXCEPT = delete;
884template <> Vec2<short> Vec2<short>::normalizedExc() const = delete;
885template <> IMATH_HOSTDEVICE Vec2<short> Vec2<short>::normalizedNonNull() const IMATH_NOEXCEPT = delete;
886
887// Vec2<int>
888template <> IMATH_HOSTDEVICE int Vec2<int>::length() const IMATH_NOEXCEPT = delete;
889template <> IMATH_HOSTDEVICE const Vec2<int>& Vec2<int>::normalize() IMATH_NOEXCEPT = delete;
890template <> const Vec2<int>& Vec2<int>::normalizeExc() = delete;
891template <> IMATH_HOSTDEVICE const Vec2<int>& Vec2<int>::normalizeNonNull() IMATH_NOEXCEPT = delete;
892template <> IMATH_HOSTDEVICE Vec2<int> Vec2<int>::normalized() const IMATH_NOEXCEPT = delete;
893template <> Vec2<int> Vec2<int>::normalizedExc() const = delete;
894template <> IMATH_HOSTDEVICE Vec2<int> Vec2<int>::normalizedNonNull() const IMATH_NOEXCEPT = delete;
895
896// Vec2<int64_t>
897template <> IMATH_HOSTDEVICE int64_t Vec2<int64_t>::length() const IMATH_NOEXCEPT = delete;
898template <> IMATH_HOSTDEVICE const Vec2<int64_t>& Vec2<int64_t>::normalize() IMATH_NOEXCEPT = delete;
899template <> const Vec2<int64_t>& Vec2<int64_t>::normalizeExc() = delete;
900template <> IMATH_HOSTDEVICE const Vec2<int64_t>& Vec2<int64_t>::normalizeNonNull() IMATH_NOEXCEPT = delete;
901template <> IMATH_HOSTDEVICE Vec2<int64_t> Vec2<int64_t>::normalized() const IMATH_NOEXCEPT = delete;
902template <> Vec2<int64_t> Vec2<int64_t>::normalizedExc() const = delete;
903template <> IMATH_HOSTDEVICE Vec2<int64_t> Vec2<int64_t>::normalizedNonNull() const IMATH_NOEXCEPT = delete;
904
905// Vec3<short>
906template <> IMATH_HOSTDEVICE short Vec3<short>::length() const IMATH_NOEXCEPT = delete;
907template <> IMATH_HOSTDEVICE const Vec3<short>& Vec3<short>::normalize() IMATH_NOEXCEPT = delete;
908template <> const Vec3<short>& Vec3<short>::normalizeExc() = delete;
909template <> IMATH_HOSTDEVICE const Vec3<short>& Vec3<short>::normalizeNonNull() IMATH_NOEXCEPT = delete;
910template <> IMATH_HOSTDEVICE Vec3<short> Vec3<short>::normalized() const IMATH_NOEXCEPT = delete;
911template <> Vec3<short> Vec3<short>::normalizedExc() const = delete;
912template <> IMATH_HOSTDEVICE Vec3<short> Vec3<short>::normalizedNonNull() const IMATH_NOEXCEPT = delete;
913
914// Vec3<int>
915template <> IMATH_HOSTDEVICE int Vec3<int>::length() const IMATH_NOEXCEPT = delete;
916template <> IMATH_HOSTDEVICE const Vec3<int>& Vec3<int>::normalize() IMATH_NOEXCEPT = delete;
917template <> const Vec3<int>& Vec3<int>::normalizeExc() = delete;
918template <> IMATH_HOSTDEVICE const Vec3<int>& Vec3<int>::normalizeNonNull() IMATH_NOEXCEPT = delete;
919template <> IMATH_HOSTDEVICE Vec3<int> Vec3<int>::normalized() const IMATH_NOEXCEPT = delete;
920template <> Vec3<int> Vec3<int>::normalizedExc() const = delete;
921template <> IMATH_HOSTDEVICE Vec3<int> Vec3<int>::normalizedNonNull() const IMATH_NOEXCEPT = delete;
922
923// Vec3<int64_t>
924template <> IMATH_HOSTDEVICE int64_t Vec3<int64_t>::length() const IMATH_NOEXCEPT = delete;
925template <> IMATH_HOSTDEVICE const Vec3<int64_t>& Vec3<int64_t>::normalize() IMATH_NOEXCEPT = delete;
926template <> const Vec3<int64_t>& Vec3<int64_t>::normalizeExc() = delete;
927template <> IMATH_HOSTDEVICE const Vec3<int64_t>& Vec3<int64_t>::normalizeNonNull() IMATH_NOEXCEPT = delete;
928template <> IMATH_HOSTDEVICE Vec3<int64_t> Vec3<int64_t>::normalized() const IMATH_NOEXCEPT = delete;
929template <> Vec3<int64_t> Vec3<int64_t>::normalizedExc() const = delete;
930template <> IMATH_HOSTDEVICE Vec3<int64_t> Vec3<int64_t>::normalizedNonNull() const IMATH_NOEXCEPT = delete;
931
932// Vec4<short>
933template <> IMATH_HOSTDEVICE short Vec4<short>::length() const IMATH_NOEXCEPT = delete;
934template <> IMATH_HOSTDEVICE const Vec4<short>& Vec4<short>::normalize() IMATH_NOEXCEPT = delete;
935template <> const Vec4<short>& Vec4<short>::normalizeExc() = delete;
936template <> IMATH_HOSTDEVICE const Vec4<short>& Vec4<short>::normalizeNonNull() IMATH_NOEXCEPT = delete;
937template <> IMATH_HOSTDEVICE Vec4<short> Vec4<short>::normalized() const IMATH_NOEXCEPT = delete;
938template <> Vec4<short> Vec4<short>::normalizedExc() const = delete;
939template <> IMATH_HOSTDEVICE Vec4<short> Vec4<short>::normalizedNonNull() const IMATH_NOEXCEPT = delete;
940
941// Vec4<int>
942template <> IMATH_HOSTDEVICE int Vec4<int>::length() const IMATH_NOEXCEPT = delete;
943template <> IMATH_HOSTDEVICE const Vec4<int>& Vec4<int>::normalize() IMATH_NOEXCEPT = delete;
944template <> const Vec4<int>& Vec4<int>::normalizeExc() = delete;
945template <> IMATH_HOSTDEVICE const Vec4<int>& Vec4<int>::normalizeNonNull() IMATH_NOEXCEPT = delete;
946template <> IMATH_HOSTDEVICE Vec4<int> Vec4<int>::normalized() const IMATH_NOEXCEPT = delete;
947template <> Vec4<int> Vec4<int>::normalizedExc() const = delete;
948template <> IMATH_HOSTDEVICE Vec4<int> Vec4<int>::normalizedNonNull() const IMATH_NOEXCEPT = delete;
949
950// Vec4<int64_t>
951template <> IMATH_HOSTDEVICE int64_t Vec4<int64_t>::length() const IMATH_NOEXCEPT = delete;
952template <> IMATH_HOSTDEVICE const Vec4<int64_t>& Vec4<int64_t>::normalize() IMATH_NOEXCEPT = delete;
953template <> const Vec4<int64_t>& Vec4<int64_t>::normalizeExc() = delete;
954template <> IMATH_HOSTDEVICE const Vec4<int64_t>& Vec4<int64_t>::normalizeNonNull() IMATH_NOEXCEPT = delete;
955template <> IMATH_HOSTDEVICE Vec4<int64_t> Vec4<int64_t>::normalized() const IMATH_NOEXCEPT = delete;
956template <> Vec4<int64_t> Vec4<int64_t>::normalizedExc() const = delete;
957template <> IMATH_HOSTDEVICE Vec4<int64_t> Vec4<int64_t>::normalizedNonNull() const IMATH_NOEXCEPT = delete;
958
959/// @endcond Doxygen_Suppress
960
961//------------------------
962// Implementation of Vec2:
963//------------------------
964
965template <class T>
966IMATH_CONSTEXPR14 IMATH_HOSTDEVICE inline T&
967Vec2<T>::operator[] (int i) IMATH_NOEXCEPT
968{
969 return (&x)[i]; // NOSONAR - suppress SonarCloud bug report.
970}
971
972template <class T>
973constexpr IMATH_HOSTDEVICE inline const T&
974Vec2<T>::operator[] (int i) const IMATH_NOEXCEPT
975{
976 return (&x)[i]; // NOSONAR - suppress SonarCloud bug report.
977}
978
979template <class T> IMATH_HOSTDEVICE inline Vec2<T>::Vec2() IMATH_NOEXCEPT
980{
981 // empty, and not constexpr because data is uninitialized.
982}
983
984template <class T> IMATH_HOSTDEVICE constexpr inline Vec2<T>::Vec2 (T a) IMATH_NOEXCEPT
985 : x(a), y(a)
986{
987}
988
989template <class T> IMATH_HOSTDEVICE constexpr inline Vec2<T>::Vec2 (T a, T b) IMATH_NOEXCEPT
990 : x(a), y(b)
991{
992}
993
994template <class T> IMATH_HOSTDEVICE constexpr inline Vec2<T>::Vec2 (const Vec2& v) IMATH_NOEXCEPT
995 : x(v.x), y(v.y)
996{
997}
998
999template <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))
1001{
1002}
1003
1004template <class T>
1005IMATH_CONSTEXPR14 IMATH_HOSTDEVICE inline const Vec2<T>&
1006Vec2<T>::operator= (const Vec2& v) IMATH_NOEXCEPT
1007{
1008 x = v.x;
1009 y = v.y;
1010 return *this;
1011}
1012
1013template <class T>
1014template <class S>
1015IMATH_HOSTDEVICE inline void
1016Vec2<T>::setValue (S a, S b) IMATH_NOEXCEPT
1017{
1018 x = T (a);
1019 y = T (b);
1020}
1021
1022template <class T>
1023template <class S>
1024IMATH_HOSTDEVICE inline void
1025Vec2<T>::setValue (const Vec2<S>& v) IMATH_NOEXCEPT
1026{
1027 x = T (v.x);
1028 y = T (v.y);
1029}
1030
1031template <class T>
1032template <class S>
1033IMATH_HOSTDEVICE inline void
1034Vec2<T>::getValue (S& a, S& b) const IMATH_NOEXCEPT
1035{
1036 a = S (x);
1037 b = S (y);
1038}
1039
1040template <class T>
1041template <class S>
1042IMATH_HOSTDEVICE inline void
1043Vec2<T>::getValue (Vec2<S>& v) const IMATH_NOEXCEPT
1044{
1045 v.x = S (x);
1046 v.y = S (y);
1047}
1048
1049template <class T>
1050IMATH_HOSTDEVICE inline T*
1051Vec2<T>::getValue() IMATH_NOEXCEPT
1052{
1053 return (T*) &x;
1054}
1055
1056template <class T>
1057IMATH_HOSTDEVICE inline const T*
1058Vec2<T>::getValue() const IMATH_NOEXCEPT
1059{
1060 return (const T*) &x;
1061}
1062
1063template <class T>
1064template <class S>
1065IMATH_HOSTDEVICE constexpr inline bool
1066Vec2<T>::operator== (const Vec2<S>& v) const IMATH_NOEXCEPT
1067{
1068 return x == v.x && y == v.y;
1069}
1070
1071template <class T>
1072template <class S>
1073IMATH_HOSTDEVICE constexpr inline bool
1074Vec2<T>::operator!= (const Vec2<S>& v) const IMATH_NOEXCEPT
1075{
1076 return x != v.x || y != v.y;
1077}
1078
1079template <class T>
1080IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool
1081Vec2<T>::equalWithAbsError (const Vec2<T>& v, T e) const IMATH_NOEXCEPT
1082{
1083 for (int i = 0; i < 2; i++)
1084 if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i], v[i], e))
1085 return false;
1086
1087 return true;
1088}
1089
1090template <class T>
1091IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool
1092Vec2<T>::equalWithRelError (const Vec2<T>& v, T e) const IMATH_NOEXCEPT
1093{
1094 for (int i = 0; i < 2; i++)
1095 if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i], v[i], e))
1096 return false;
1097
1098 return true;
1099}
1100
1101template <class T>
1102IMATH_HOSTDEVICE constexpr inline T
1103Vec2<T>::dot (const Vec2& v) const IMATH_NOEXCEPT
1104{
1105 return x * v.x + y * v.y;
1106}
1107
1108template <class T>
1109IMATH_HOSTDEVICE constexpr inline T
1110Vec2<T>::operator^ (const Vec2& v) const IMATH_NOEXCEPT
1111{
1112 return dot (v);
1113}
1114
1115template <class T>
1116IMATH_HOSTDEVICE constexpr inline T
1117Vec2<T>::cross (const Vec2& v) const IMATH_NOEXCEPT
1118{
1119 return x * v.y - y * v.x;
1120}
1121
1122template <class T>
1123IMATH_HOSTDEVICE constexpr inline T
1124Vec2<T>::operator% (const Vec2& v) const IMATH_NOEXCEPT
1125{
1126 return x * v.y - y * v.x;
1127}
1128
1129template <class T>
1130IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2<T>&
1131Vec2<T>::operator+= (const Vec2& v) IMATH_NOEXCEPT
1132{
1133 x += v.x;
1134 y += v.y;
1135 return *this;
1136}
1137
1138template <class T>
1139IMATH_HOSTDEVICE constexpr inline Vec2<T>
1140Vec2<T>::operator+ (const Vec2& v) const IMATH_NOEXCEPT
1141{
1142 return Vec2 (x + v.x, y + v.y);
1143}
1144
1145template <class T>
1146IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2<T>&
1147Vec2<T>::operator-= (const Vec2& v) IMATH_NOEXCEPT
1148{
1149 x -= v.x;
1150 y -= v.y;
1151 return *this;
1152}
1153
1154template <class T>
1155IMATH_HOSTDEVICE constexpr inline Vec2<T>
1156Vec2<T>::operator- (const Vec2& v) const IMATH_NOEXCEPT
1157{
1158 return Vec2 (x - v.x, y - v.y);
1159}
1160
1161template <class T>
1162IMATH_HOSTDEVICE constexpr inline Vec2<T>
1163Vec2<T>::operator-() const IMATH_NOEXCEPT
1164{
1165 return Vec2 (-x, -y);
1166}
1167
1168template <class T>
1169IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2<T>&
1170Vec2<T>::negate() IMATH_NOEXCEPT
1171{
1172 x = -x;
1173 y = -y;
1174 return *this;
1175}
1176
1177template <class T>
1178IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2<T>&
1179Vec2<T>::operator*= (const Vec2& v) IMATH_NOEXCEPT
1180{
1181 x *= v.x;
1182 y *= v.y;
1183 return *this;
1184}
1185
1186template <class T>
1187IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2<T>&
1188Vec2<T>::operator*= (T a) IMATH_NOEXCEPT
1189{
1190 x *= a;
1191 y *= a;
1192 return *this;
1193}
1194
1195template <class T>
1196IMATH_HOSTDEVICE constexpr inline Vec2<T>
1197Vec2<T>::operator* (const Vec2& v) const IMATH_NOEXCEPT
1198{
1199 return Vec2 (x * v.x, y * v.y);
1200}
1201
1202template <class T>
1203IMATH_HOSTDEVICE constexpr inline Vec2<T>
1204Vec2<T>::operator* (T a) const IMATH_NOEXCEPT
1205{
1206 return Vec2 (x * a, y * a);
1207}
1208
1209template <class T>
1210IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2<T>&
1211Vec2<T>::operator/= (const Vec2& v) IMATH_NOEXCEPT
1212{
1213 x /= v.x;
1214 y /= v.y;
1215 return *this;
1216}
1217
1218template <class T>
1219IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2<T>&
1220Vec2<T>::operator/= (T a) IMATH_NOEXCEPT
1221{
1222 x /= a;
1223 y /= a;
1224 return *this;
1225}
1226
1227template <class T>
1228IMATH_HOSTDEVICE constexpr inline Vec2<T>
1229Vec2<T>::operator/ (const Vec2& v) const IMATH_NOEXCEPT
1230{
1231 return Vec2 (x / v.x, y / v.y);
1232}
1233
1234template <class T>
1235IMATH_HOSTDEVICE constexpr inline Vec2<T>
1236Vec2<T>::operator/ (T a) const IMATH_NOEXCEPT
1237{
1238 return Vec2 (x / a, y / a);
1239}
1240
1241template <class T>
1242IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline T
1243Vec2<T>::lengthTiny() const IMATH_NOEXCEPT
1244{
1245 T absX = std::abs(x);
1246 T absY = std::abs(y);
1247
1248 T max = absX;
1249
1250 if (max < absY)
1251 max = absY;
1252
1253 if (IMATH_UNLIKELY(max == T (0)))
1254 return T (0);
1255
1256 //
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.
1260 //
1261
1262 absX /= max;
1263 absY /= max;
1264
1265 return max * std::sqrt (absX * absX + absY * absY);
1266}
1267
1268template <class T>
1269IMATH_HOSTDEVICE inline T
1270Vec2<T>::length() const IMATH_NOEXCEPT
1271{
1272 T length2 = dot (v: *this);
1273
1274 if (IMATH_UNLIKELY(length2 < T (2) * std::numeric_limits<T>::min()))
1275 return lengthTiny();
1276
1277 return std::sqrt (length2);
1278}
1279
1280template <class T>
1281IMATH_HOSTDEVICE constexpr inline T
1282Vec2<T>::length2() const IMATH_NOEXCEPT
1283{
1284 return dot (v: *this);
1285}
1286
1287template <class T>
1288IMATH_HOSTDEVICE inline const Vec2<T>&
1289Vec2<T>::normalize() IMATH_NOEXCEPT
1290{
1291 T l = length();
1292
1293 if (IMATH_LIKELY(l != T (0)))
1294 {
1295 //
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.
1299 //
1300
1301 x /= l;
1302 y /= l;
1303 }
1304
1305 return *this;
1306}
1307
1308template <class T>
1309inline const Vec2<T>&
1310Vec2<T>::normalizeExc()
1311{
1312 T l = length();
1313
1314 if (IMATH_UNLIKELY(l == T (0)))
1315 throw std::domain_error ("Cannot normalize null vector.");
1316
1317 x /= l;
1318 y /= l;
1319 return *this;
1320}
1321
1322template <class T>
1323IMATH_HOSTDEVICE inline const Vec2<T>&
1324Vec2<T>::normalizeNonNull() IMATH_NOEXCEPT
1325{
1326 T l = length();
1327 x /= l;
1328 y /= l;
1329 return *this;
1330}
1331
1332template <class T>
1333IMATH_HOSTDEVICE inline Vec2<T>
1334Vec2<T>::normalized() const IMATH_NOEXCEPT
1335{
1336 T l = length();
1337
1338 if (IMATH_UNLIKELY(l == T (0)))
1339 return Vec2 (T (0));
1340
1341 return Vec2 (x / l, y / l);
1342}
1343
1344template <class T>
1345inline Vec2<T>
1346Vec2<T>::normalizedExc() const
1347{
1348 T l = length();
1349
1350 if (IMATH_UNLIKELY(l == T (0)))
1351 throw std::domain_error ("Cannot normalize null vector.");
1352
1353 return Vec2 (x / l, y / l);
1354}
1355
1356template <class T>
1357IMATH_HOSTDEVICE inline Vec2<T>
1358Vec2<T>::normalizedNonNull() const IMATH_NOEXCEPT
1359{
1360 T l = length();
1361 return Vec2 (x / l, y / l);
1362}
1363
1364//-----------------------
1365// Implementation of Vec3
1366//-----------------------
1367
1368template <class T>
1369IMATH_HOSTDEVICE
1370IMATH_CONSTEXPR14 inline T&
1371Vec3<T>::operator[] (int i) IMATH_NOEXCEPT
1372{
1373 return (&x)[i]; // NOSONAR - suppress SonarCloud bug report.
1374}
1375
1376template <class T>
1377IMATH_HOSTDEVICE constexpr inline const T&
1378Vec3<T>::operator[] (int i) const IMATH_NOEXCEPT
1379{
1380 return (&x)[i]; // NOSONAR - suppress SonarCloud bug report.
1381}
1382
1383template <class T> IMATH_HOSTDEVICE inline Vec3<T>::Vec3() IMATH_NOEXCEPT
1384{
1385 // empty, and not constexpr because data is uninitialized.
1386}
1387
1388template <class T> IMATH_HOSTDEVICE constexpr inline Vec3<T>::Vec3 (T a) IMATH_NOEXCEPT
1389 : x(a), y(a), z(a)
1390{
1391}
1392
1393template <class T> IMATH_HOSTDEVICE constexpr inline Vec3<T>::Vec3 (T a, T b, T c) IMATH_NOEXCEPT
1394 : x(a), y(b), z(c)
1395{
1396}
1397
1398template <class T> IMATH_HOSTDEVICE constexpr inline Vec3<T>::Vec3 (const Vec3& v) IMATH_NOEXCEPT
1399 : x(v.x), y(v.y), z(v.z)
1400{
1401}
1402
1403template <class T> template <class S>
1404IMATH_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))
1406{
1407}
1408
1409template <class T>
1410IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1411Vec3<T>::operator= (const Vec3& v) IMATH_NOEXCEPT
1412{
1413 x = v.x;
1414 y = v.y;
1415 z = v.z;
1416 return *this;
1417}
1418
1419template <class T> template <class S>
1420IMATH_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))
1422{
1423}
1424
1425template <class T>
1426template <class S>
1427IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Vec3<T>::Vec3 (const Vec4<S>& v, InfException)
1428{
1429 T vx = T (v.x);
1430 T vy = T (v.y);
1431 T vz = T (v.z);
1432 T vw = T (v.w);
1433
1434 T absW = (vw >= T (0)) ? vw : -vw;
1435
1436 if (absW < 1)
1437 {
1438 T m = baseTypeMax() * absW;
1439
1440 if (vx <= -m || vx >= m || vy <= -m || vy >= m || vz <= -m || vz >= m)
1441 throw std::domain_error ("Cannot normalize point at infinity.");
1442 }
1443
1444 x = vx / vw;
1445 y = vy / vw;
1446 z = vz / vw;
1447}
1448
1449template <class T>
1450template <class S>
1451IMATH_HOSTDEVICE inline void
1452Vec3<T>::setValue (S a, S b, S c) IMATH_NOEXCEPT
1453{
1454 x = T (a);
1455 y = T (b);
1456 z = T (c);
1457}
1458
1459template <class T>
1460template <class S>
1461IMATH_HOSTDEVICE inline void
1462Vec3<T>::setValue (const Vec3<S>& v) IMATH_NOEXCEPT
1463{
1464 x = T (v.x);
1465 y = T (v.y);
1466 z = T (v.z);
1467}
1468
1469template <class T>
1470template <class S>
1471IMATH_HOSTDEVICE inline void
1472Vec3<T>::getValue (S& a, S& b, S& c) const IMATH_NOEXCEPT
1473{
1474 a = S (x);
1475 b = S (y);
1476 c = S (z);
1477}
1478
1479template <class T>
1480template <class S>
1481IMATH_HOSTDEVICE inline void
1482Vec3<T>::getValue (Vec3<S>& v) const IMATH_NOEXCEPT
1483{
1484 v.x = S (x);
1485 v.y = S (y);
1486 v.z = S (z);
1487}
1488
1489template <class T>
1490IMATH_HOSTDEVICE inline T*
1491Vec3<T>::getValue() IMATH_NOEXCEPT
1492{
1493 return (T*) &x;
1494}
1495
1496template <class T>
1497IMATH_HOSTDEVICE inline const T*
1498Vec3<T>::getValue() const IMATH_NOEXCEPT
1499{
1500 return (const T*) &x;
1501}
1502
1503template <class T>
1504template <class S>
1505IMATH_HOSTDEVICE constexpr inline bool
1506Vec3<T>::operator== (const Vec3<S>& v) const IMATH_NOEXCEPT
1507{
1508 return x == v.x && y == v.y && z == v.z;
1509}
1510
1511template <class T>
1512template <class S>
1513IMATH_HOSTDEVICE constexpr inline bool
1514Vec3<T>::operator!= (const Vec3<S>& v) const IMATH_NOEXCEPT
1515{
1516 return x != v.x || y != v.y || z != v.z;
1517}
1518
1519template <class T>
1520IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool
1521Vec3<T>::equalWithAbsError (const Vec3<T>& v, T e) const IMATH_NOEXCEPT
1522{
1523 for (int i = 0; i < 3; i++)
1524 if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i], v[i], e))
1525 return false;
1526
1527 return true;
1528}
1529
1530template <class T>
1531IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool
1532Vec3<T>::equalWithRelError (const Vec3<T>& v, T e) const IMATH_NOEXCEPT
1533{
1534 for (int i = 0; i < 3; i++)
1535 if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i], v[i], e))
1536 return false;
1537
1538 return true;
1539}
1540
1541template <class T>
1542IMATH_HOSTDEVICE constexpr inline T
1543Vec3<T>::dot (const Vec3& v) const IMATH_NOEXCEPT
1544{
1545 return x * v.x + y * v.y + z * v.z;
1546}
1547
1548template <class T>
1549IMATH_HOSTDEVICE constexpr inline T
1550Vec3<T>::operator^ (const Vec3& v) const IMATH_NOEXCEPT
1551{
1552 return dot (v);
1553}
1554
1555template <class T>
1556IMATH_HOSTDEVICE constexpr inline Vec3<T>
1557Vec3<T>::cross (const Vec3& v) const IMATH_NOEXCEPT
1558{
1559 return Vec3 (y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x);
1560}
1561
1562template <class T>
1563IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1564Vec3<T>::operator%= (const Vec3& v) IMATH_NOEXCEPT
1565{
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;
1569 x = a;
1570 y = b;
1571 z = c;
1572 return *this;
1573}
1574
1575template <class T>
1576IMATH_HOSTDEVICE constexpr inline Vec3<T>
1577Vec3<T>::operator% (const Vec3& v) const IMATH_NOEXCEPT
1578{
1579 return Vec3 (y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x);
1580}
1581
1582template <class T>
1583IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1584Vec3<T>::operator+= (const Vec3& v) IMATH_NOEXCEPT
1585{
1586 x += v.x;
1587 y += v.y;
1588 z += v.z;
1589 return *this;
1590}
1591
1592template <class T>
1593IMATH_HOSTDEVICE constexpr inline Vec3<T>
1594Vec3<T>::operator+ (const Vec3& v) const IMATH_NOEXCEPT
1595{
1596 return Vec3 (x + v.x, y + v.y, z + v.z);
1597}
1598
1599template <class T>
1600IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1601Vec3<T>::operator-= (const Vec3& v) IMATH_NOEXCEPT
1602{
1603 x -= v.x;
1604 y -= v.y;
1605 z -= v.z;
1606 return *this;
1607}
1608
1609template <class T>
1610IMATH_HOSTDEVICE constexpr inline Vec3<T>
1611Vec3<T>::operator- (const Vec3& v) const IMATH_NOEXCEPT
1612{
1613 return Vec3 (x - v.x, y - v.y, z - v.z);
1614}
1615
1616template <class T>
1617IMATH_HOSTDEVICE constexpr inline Vec3<T>
1618Vec3<T>::operator-() const IMATH_NOEXCEPT
1619{
1620 return Vec3 (-x, -y, -z);
1621}
1622
1623template <class T>
1624IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1625Vec3<T>::negate() IMATH_NOEXCEPT
1626{
1627 x = -x;
1628 y = -y;
1629 z = -z;
1630 return *this;
1631}
1632
1633template <class T>
1634IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1635Vec3<T>::operator*= (const Vec3& v) IMATH_NOEXCEPT
1636{
1637 x *= v.x;
1638 y *= v.y;
1639 z *= v.z;
1640 return *this;
1641}
1642
1643template <class T>
1644IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1645Vec3<T>::operator*= (T a) IMATH_NOEXCEPT
1646{
1647 x *= a;
1648 y *= a;
1649 z *= a;
1650 return *this;
1651}
1652
1653template <class T>
1654IMATH_HOSTDEVICE constexpr inline Vec3<T>
1655Vec3<T>::operator* (const Vec3& v) const IMATH_NOEXCEPT
1656{
1657 return Vec3 (x * v.x, y * v.y, z * v.z);
1658}
1659
1660template <class T>
1661IMATH_HOSTDEVICE constexpr inline Vec3<T>
1662Vec3<T>::operator* (T a) const IMATH_NOEXCEPT
1663{
1664 return Vec3 (x * a, y * a, z * a);
1665}
1666
1667template <class T>
1668IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1669Vec3<T>::operator/= (const Vec3& v) IMATH_NOEXCEPT
1670{
1671 x /= v.x;
1672 y /= v.y;
1673 z /= v.z;
1674 return *this;
1675}
1676
1677template <class T>
1678IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1679Vec3<T>::operator/= (T a) IMATH_NOEXCEPT
1680{
1681 x /= a;
1682 y /= a;
1683 z /= a;
1684 return *this;
1685}
1686
1687template <class T>
1688IMATH_HOSTDEVICE constexpr inline Vec3<T>
1689Vec3<T>::operator/ (const Vec3& v) const IMATH_NOEXCEPT
1690{
1691 return Vec3 (x / v.x, y / v.y, z / v.z);
1692}
1693
1694template <class T>
1695IMATH_HOSTDEVICE constexpr inline Vec3<T>
1696Vec3<T>::operator/ (T a) const IMATH_NOEXCEPT
1697{
1698 return Vec3 (x / a, y / a, z / a);
1699}
1700
1701template <class T>
1702IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline T
1703Vec3<T>::lengthTiny() const IMATH_NOEXCEPT
1704{
1705 T absX = (x >= T (0)) ? x : -x;
1706 T absY = (y >= T (0)) ? y : -y;
1707 T absZ = (z >= T (0)) ? z : -z;
1708
1709 T max = absX;
1710
1711 if (max < absY)
1712 max = absY;
1713
1714 if (max < absZ)
1715 max = absZ;
1716
1717 if (IMATH_UNLIKELY(max == T (0)))
1718 return T (0);
1719
1720 //
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.
1724 //
1725
1726 absX /= max;
1727 absY /= max;
1728 absZ /= max;
1729
1730 return max * std::sqrt (absX * absX + absY * absY + absZ * absZ);
1731}
1732
1733template <class T>
1734IMATH_HOSTDEVICE inline T
1735Vec3<T>::length() const IMATH_NOEXCEPT
1736{
1737 T length2 = dot (v: *this);
1738
1739 if (IMATH_UNLIKELY(length2 < T (2) * std::numeric_limits<T>::min()))
1740 return lengthTiny();
1741
1742 return std::sqrt (length2);
1743}
1744
1745template <class T>
1746IMATH_HOSTDEVICE constexpr inline T
1747Vec3<T>::length2() const IMATH_NOEXCEPT
1748{
1749 return dot (v: *this);
1750}
1751
1752template <class T>
1753IMATH_HOSTDEVICE inline const Vec3<T>&
1754Vec3<T>::normalize() IMATH_NOEXCEPT
1755{
1756 T l = length();
1757
1758 if (IMATH_LIKELY(l != T (0)))
1759 {
1760 //
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.
1764 //
1765
1766 x /= l;
1767 y /= l;
1768 z /= l;
1769 }
1770
1771 return *this;
1772}
1773
1774template <class T>
1775inline const Vec3<T>&
1776Vec3<T>::normalizeExc()
1777{
1778 T l = length();
1779
1780 if (IMATH_UNLIKELY(l == T (0)))
1781 throw std::domain_error ("Cannot normalize null vector.");
1782
1783 x /= l;
1784 y /= l;
1785 z /= l;
1786 return *this;
1787}
1788
1789template <class T>
1790IMATH_HOSTDEVICE inline const Vec3<T>&
1791Vec3<T>::normalizeNonNull() IMATH_NOEXCEPT
1792{
1793 T l = length();
1794 x /= l;
1795 y /= l;
1796 z /= l;
1797 return *this;
1798}
1799
1800template <class T>
1801IMATH_HOSTDEVICE inline Vec3<T>
1802Vec3<T>::normalized() const IMATH_NOEXCEPT
1803{
1804 T l = length();
1805
1806 if (IMATH_UNLIKELY((l == T (0))))
1807 return Vec3 (T (0));
1808
1809 return Vec3 (x / l, y / l, z / l);
1810}
1811
1812template <class T>
1813inline Vec3<T>
1814Vec3<T>::normalizedExc() const
1815{
1816 T l = length();
1817
1818 if (IMATH_UNLIKELY(l == T (0)))
1819 throw std::domain_error ("Cannot normalize null vector.");
1820
1821 return Vec3 (x / l, y / l, z / l);
1822}
1823
1824template <class T>
1825IMATH_HOSTDEVICE inline Vec3<T>
1826Vec3<T>::normalizedNonNull() const IMATH_NOEXCEPT
1827{
1828 T l = length();
1829 return Vec3 (x / l, y / l, z / l);
1830}
1831
1832//-----------------------
1833// Implementation of Vec4
1834//-----------------------
1835
1836template <class T>
1837IMATH_HOSTDEVICE
1838IMATH_CONSTEXPR14 inline T&
1839Vec4<T>::operator[] (int i) IMATH_NOEXCEPT
1840{
1841 return (&x)[i]; // NOSONAR - suppress SonarCloud bug report.
1842}
1843
1844template <class T>
1845IMATH_HOSTDEVICE constexpr inline const T&
1846Vec4<T>::operator[] (int i) const IMATH_NOEXCEPT
1847{
1848 return (&x)[i]; // NOSONAR - suppress SonarCloud bug report.
1849}
1850
1851template <class T> IMATH_HOSTDEVICE inline Vec4<T>::Vec4() IMATH_NOEXCEPT
1852{
1853 // empty, and not constexpr because data is uninitialized.
1854}
1855
1856template <class T> IMATH_HOSTDEVICE constexpr inline Vec4<T>::Vec4 (T a) IMATH_NOEXCEPT
1857 : x(a), y(a), z(a), w(a)
1858{
1859}
1860
1861template <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)
1863{
1864}
1865
1866template <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)
1868{
1869}
1870
1871template <class T> template <class S>
1872IMATH_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))
1874{
1875}
1876
1877template <class T>
1878IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4<T>&
1879Vec4<T>::operator= (const Vec4& v) IMATH_NOEXCEPT
1880{
1881 x = v.x;
1882 y = v.y;
1883 z = v.z;
1884 w = v.w;
1885 return *this;
1886}
1887
1888template <class T> template <class S>
1889IMATH_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))
1891{
1892}
1893
1894template <class T>
1895template <class S>
1896IMATH_HOSTDEVICE constexpr inline bool
1897Vec4<T>::operator== (const Vec4<S>& v) const IMATH_NOEXCEPT
1898{
1899 return x == v.x && y == v.y && z == v.z && w == v.w;
1900}
1901
1902template <class T>
1903template <class S>
1904IMATH_HOSTDEVICE constexpr inline bool
1905Vec4<T>::operator!= (const Vec4<S>& v) const IMATH_NOEXCEPT
1906{
1907 return x != v.x || y != v.y || z != v.z || w != v.w;
1908}
1909
1910template <class T>
1911IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool
1912Vec4<T>::equalWithAbsError (const Vec4<T>& v, T e) const IMATH_NOEXCEPT
1913{
1914 for (int i = 0; i < 4; i++)
1915 if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i], v[i], e))
1916 return false;
1917
1918 return true;
1919}
1920
1921template <class T>
1922IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool
1923Vec4<T>::equalWithRelError (const Vec4<T>& v, T e) const IMATH_NOEXCEPT
1924{
1925 for (int i = 0; i < 4; i++)
1926 if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i], v[i], e))
1927 return false;
1928
1929 return true;
1930}
1931
1932template <class T>
1933IMATH_HOSTDEVICE constexpr inline T
1934Vec4<T>::dot (const Vec4& v) const IMATH_NOEXCEPT
1935{
1936 return x * v.x + y * v.y + z * v.z + w * v.w;
1937}
1938
1939template <class T>
1940IMATH_HOSTDEVICE constexpr inline T
1941Vec4<T>::operator^ (const Vec4& v) const IMATH_NOEXCEPT
1942{
1943 return dot (v);
1944}
1945
1946template <class T>
1947IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4<T>&
1948Vec4<T>::operator+= (const Vec4& v) IMATH_NOEXCEPT
1949{
1950 x += v.x;
1951 y += v.y;
1952 z += v.z;
1953 w += v.w;
1954 return *this;
1955}
1956
1957template <class T>
1958IMATH_HOSTDEVICE constexpr inline Vec4<T>
1959Vec4<T>::operator+ (const Vec4& v) const IMATH_NOEXCEPT
1960{
1961 return Vec4 (x + v.x, y + v.y, z + v.z, w + v.w);
1962}
1963
1964template <class T>
1965IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4<T>&
1966Vec4<T>::operator-= (const Vec4& v) IMATH_NOEXCEPT
1967{
1968 x -= v.x;
1969 y -= v.y;
1970 z -= v.z;
1971 w -= v.w;
1972 return *this;
1973}
1974
1975template <class T>
1976IMATH_HOSTDEVICE constexpr inline Vec4<T>
1977Vec4<T>::operator- (const Vec4& v) const IMATH_NOEXCEPT
1978{
1979 return Vec4 (x - v.x, y - v.y, z - v.z, w - v.w);
1980}
1981
1982template <class T>
1983IMATH_HOSTDEVICE constexpr inline Vec4<T>
1984Vec4<T>::operator-() const IMATH_NOEXCEPT
1985{
1986 return Vec4 (-x, -y, -z, -w);
1987}
1988
1989template <class T>
1990IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4<T>&
1991Vec4<T>::negate() IMATH_NOEXCEPT
1992{
1993 x = -x;
1994 y = -y;
1995 z = -z;
1996 w = -w;
1997 return *this;
1998}
1999
2000template <class T>
2001IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4<T>&
2002Vec4<T>::operator*= (const Vec4& v) IMATH_NOEXCEPT
2003{
2004 x *= v.x;
2005 y *= v.y;
2006 z *= v.z;
2007 w *= v.w;
2008 return *this;
2009}
2010
2011template <class T>
2012IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4<T>&
2013Vec4<T>::operator*= (T a) IMATH_NOEXCEPT
2014{
2015 x *= a;
2016 y *= a;
2017 z *= a;
2018 w *= a;
2019 return *this;
2020}
2021
2022template <class T>
2023IMATH_HOSTDEVICE constexpr inline Vec4<T>
2024Vec4<T>::operator* (const Vec4& v) const IMATH_NOEXCEPT
2025{
2026 return Vec4 (x * v.x, y * v.y, z * v.z, w * v.w);
2027}
2028
2029template <class T>
2030IMATH_HOSTDEVICE constexpr inline Vec4<T>
2031Vec4<T>::operator* (T a) const IMATH_NOEXCEPT
2032{
2033 return Vec4 (x * a, y * a, z * a, w * a);
2034}
2035
2036template <class T>
2037IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4<T>&
2038Vec4<T>::operator/= (const Vec4& v) IMATH_NOEXCEPT
2039{
2040 x /= v.x;
2041 y /= v.y;
2042 z /= v.z;
2043 w /= v.w;
2044 return *this;
2045}
2046
2047template <class T>
2048IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4<T>&
2049Vec4<T>::operator/= (T a) IMATH_NOEXCEPT
2050{
2051 x /= a;
2052 y /= a;
2053 z /= a;
2054 w /= a;
2055 return *this;
2056}
2057
2058template <class T>
2059IMATH_HOSTDEVICE constexpr inline Vec4<T>
2060Vec4<T>::operator/ (const Vec4& v) const IMATH_NOEXCEPT
2061{
2062 return Vec4 (x / v.x, y / v.y, z / v.z, w / v.w);
2063}
2064
2065template <class T>
2066IMATH_HOSTDEVICE constexpr inline Vec4<T>
2067Vec4<T>::operator/ (T a) const IMATH_NOEXCEPT
2068{
2069 return Vec4 (x / a, y / a, z / a, w / a);
2070}
2071
2072template <class T>
2073IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline T
2074Vec4<T>::lengthTiny() const IMATH_NOEXCEPT
2075{
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;
2080
2081 T max = absX;
2082
2083 if (max < absY)
2084 max = absY;
2085
2086 if (max < absZ)
2087 max = absZ;
2088
2089 if (max < absW)
2090 max = absW;
2091
2092 if (IMATH_UNLIKELY(max == T (0)))
2093 return T (0);
2094
2095 //
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.
2099 //
2100
2101 absX /= max;
2102 absY /= max;
2103 absZ /= max;
2104 absW /= max;
2105
2106 return max * std::sqrt (absX * absX + absY * absY + absZ * absZ + absW * absW);
2107}
2108
2109template <class T>
2110IMATH_HOSTDEVICE inline T
2111Vec4<T>::length() const IMATH_NOEXCEPT
2112{
2113 T length2 = dot (v: *this);
2114
2115 if (IMATH_UNLIKELY(length2 < T (2) * std::numeric_limits<T>::min()))
2116 return lengthTiny();
2117
2118 return std::sqrt (length2);
2119}
2120
2121template <class T>
2122IMATH_HOSTDEVICE constexpr inline T
2123Vec4<T>::length2() const IMATH_NOEXCEPT
2124{
2125 return dot (v: *this);
2126}
2127
2128template <class T>
2129IMATH_HOSTDEVICE const inline Vec4<T>&
2130Vec4<T>::normalize() IMATH_NOEXCEPT
2131{
2132 T l = length();
2133
2134 if (IMATH_LIKELY(l != T (0)))
2135 {
2136 //
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.
2140 //
2141
2142 x /= l;
2143 y /= l;
2144 z /= l;
2145 w /= l;
2146 }
2147
2148 return *this;
2149}
2150
2151template <class T>
2152const inline Vec4<T>&
2153Vec4<T>::normalizeExc()
2154{
2155 T l = length();
2156
2157 if (IMATH_UNLIKELY(l == T (0)))
2158 throw std::domain_error ("Cannot normalize null vector.");
2159
2160 x /= l;
2161 y /= l;
2162 z /= l;
2163 w /= l;
2164 return *this;
2165}
2166
2167template <class T>
2168IMATH_HOSTDEVICE inline const Vec4<T>&
2169Vec4<T>::normalizeNonNull() IMATH_NOEXCEPT
2170{
2171 T l = length();
2172 x /= l;
2173 y /= l;
2174 z /= l;
2175 w /= l;
2176 return *this;
2177}
2178
2179template <class T>
2180IMATH_HOSTDEVICE inline Vec4<T>
2181Vec4<T>::normalized() const IMATH_NOEXCEPT
2182{
2183 T l = length();
2184
2185 if (IMATH_UNLIKELY(l == T (0)))
2186 return Vec4 (T (0));
2187
2188 return Vec4 (x / l, y / l, z / l, w / l);
2189}
2190
2191template <class T>
2192inline Vec4<T>
2193Vec4<T>::normalizedExc() const
2194{
2195 T l = length();
2196
2197 if (IMATH_UNLIKELY(l == T (0)))
2198 throw std::domain_error ("Cannot normalize null vector.");
2199
2200 return Vec4 (x / l, y / l, z / l, w / l);
2201}
2202
2203template <class T>
2204IMATH_HOSTDEVICE inline Vec4<T>
2205Vec4<T>::normalizedNonNull() const IMATH_NOEXCEPT
2206{
2207 T l = length();
2208 return Vec4 (x / l, y / l, z / l, w / l);
2209}
2210
2211//-----------------------------
2212// Stream output implementation
2213//-----------------------------
2214
2215template <class T>
2216std::ostream&
2217operator<< (std::ostream& s, const Vec2<T>& v)
2218{
2219 return s << '(' << v.x << ' ' << v.y << ')';
2220}
2221
2222template <class T>
2223std::ostream&
2224operator<< (std::ostream& s, const Vec3<T>& v)
2225{
2226 return s << '(' << v.x << ' ' << v.y << ' ' << v.z << ')';
2227}
2228
2229template <class T>
2230std::ostream&
2231operator<< (std::ostream& s, const Vec4<T>& v)
2232{
2233 return s << '(' << v.x << ' ' << v.y << ' ' << v.z << ' ' << v.w << ')';
2234}
2235
2236//-----------------------------------------
2237// Implementation of reverse multiplication
2238//-----------------------------------------
2239
2240template <class T>
2241IMATH_HOSTDEVICE constexpr inline Vec2<T>
2242operator* (T a, const Vec2<T>& v) IMATH_NOEXCEPT
2243{
2244 return Vec2<T> (a * v.x, a * v.y);
2245}
2246
2247template <class T>
2248IMATH_HOSTDEVICE constexpr inline Vec3<T>
2249operator* (T a, const Vec3<T>& v) IMATH_NOEXCEPT
2250{
2251 return Vec3<T> (a * v.x, a * v.y, a * v.z);
2252}
2253
2254template <class T>
2255IMATH_HOSTDEVICE constexpr inline Vec4<T>
2256operator* (T a, const Vec4<T>& v) IMATH_NOEXCEPT
2257{
2258 return Vec4<T> (a * v.x, a * v.y, a * v.z, a * v.w);
2259}
2260
2261#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
2262# pragma warning(pop)
2263#endif
2264
2265IMATH_INTERNAL_NAMESPACE_HEADER_EXIT
2266
2267#endif // INCLUDED_IMATHVEC_H
2268

source code of include/Imath/ImathVec.h