Coverage Report

Created: 2025-07-16 07:53

/usr/local/include/Imath/ImathVec.h
Line
Count
Source
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
30
IMATH_INTERNAL_NAMESPACE_HEADER_ENTER
31
32
template <class T> class Vec2;
33
template <class T> class Vec3;
34
template <class T> class Vec4;
35
36
/// Enum for the Vec4 to Vec3 conversion constructor
37
enum IMATH_EXPORT_ENUM InfException
38
{
39
    INF_EXCEPTION
40
};
41
42
///
43
/// 2-element vector
44
///
45
46
template <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
304
template <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
575
template <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)"
804
template <class T> std::ostream& operator<< (std::ostream& s, const Vec2<T>& v);
805
806
/// Stream output, as "(x y z)"
807
template <class T> std::ostream& operator<< (std::ostream& s, const Vec3<T>& v);
808
809
/// Stream output, as "(x y z w)"
810
template <class T> std::ostream& operator<< (std::ostream& s, const Vec4<T>& v);
811
812
/// Reverse multiplication: S * Vec2<T>
813
template <class T> IMATH_HOSTDEVICE constexpr Vec2<T> operator* (T a, const Vec2<T>& v) IMATH_NOEXCEPT;
814
815
/// Reverse multiplication: S * Vec3<T>
816
template <class T> IMATH_HOSTDEVICE constexpr Vec3<T> operator* (T a, const Vec3<T>& v) IMATH_NOEXCEPT;
817
818
/// Reverse multiplication: S * Vec4<T>
819
template <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
826
typedef Vec2<short> V2s;
827
828
/// Vec2 of integer
829
typedef Vec2<int> V2i;
830
831
/// Vec2 of int64_t
832
typedef Vec2<int64_t> V2i64;
833
834
/// Vec2 of float
835
typedef Vec2<float> V2f;
836
837
/// Vec2 of double
838
typedef Vec2<double> V2d;
839
840
/// Vec3 of short
841
typedef Vec3<short> V3s;
842
843
/// Vec3 of integer
844
typedef Vec3<int> V3i;
845
846
/// Vec3 of int64_t
847
typedef Vec3<int64_t> V3i64;
848
849
/// Vec3 of float
850
typedef Vec3<float> V3f;
851
852
/// Vec3 of double
853
typedef Vec3<double> V3d;
854
855
/// Vec4 of short
856
typedef Vec4<short> V4s;
857
858
/// Vec4 of integer
859
typedef Vec4<int> V4i;
860
861
/// Vec4 of int64_t
862
typedef Vec4<int64_t> V4i64;
863
864
/// Vec4 of float
865
typedef Vec4<float> V4f;
866
867
/// Vec4 of double
868
typedef 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>
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;
886
887
// Vec2<int>
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;
895
896
// Vec2<int64_t>
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;
904
905
// Vec3<short>
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;
913
914
// Vec3<int>
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;
922
923
// Vec3<int64_t>
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;
931
932
// Vec4<short>
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;
940
941
// Vec4<int>
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;
949
950
// Vec4<int64_t>
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;
958
959
/// @endcond Doxygen_Suppress
960
961
//------------------------
962
// Implementation of Vec2:
963
//------------------------
964
965
template <class T>
966
IMATH_CONSTEXPR14 IMATH_HOSTDEVICE inline T&
967
Vec2<T>::operator[] (int i) IMATH_NOEXCEPT
968
{
969
    return (&x)[i]; // NOSONAR - suppress SonarCloud bug report.
970
}
971
972
template <class T>
973
constexpr IMATH_HOSTDEVICE inline const T&
974
Vec2<T>::operator[] (int i) const IMATH_NOEXCEPT
975
{
976
    return (&x)[i]; // NOSONAR - suppress SonarCloud bug report.
977
}
978
979
template <class T> IMATH_HOSTDEVICE inline Vec2<T>::Vec2() IMATH_NOEXCEPT
980
{
981
    // empty, and not constexpr because data is uninitialized.
982
}
983
984
template <class T> IMATH_HOSTDEVICE constexpr inline Vec2<T>::Vec2 (T a) IMATH_NOEXCEPT
985
    : x(a), y(a)
986
{
987
}
988
989
template <class T> IMATH_HOSTDEVICE constexpr inline Vec2<T>::Vec2 (T a, T b) IMATH_NOEXCEPT
990
147k
    : x(a), y(b)
991
147k
{
992
147k
}
993
994
template <class T> IMATH_HOSTDEVICE constexpr inline Vec2<T>::Vec2 (const Vec2& v) IMATH_NOEXCEPT
995
353k
    : x(v.x), y(v.y)
996
353k
{
997
353k
}
998
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))
1001
{
1002
}
1003
1004
template <class T>
1005
IMATH_CONSTEXPR14 IMATH_HOSTDEVICE inline const Vec2<T>&
1006
Vec2<T>::operator= (const Vec2& v) IMATH_NOEXCEPT
1007
{
1008
    x = v.x;
1009
    y = v.y;
1010
    return *this;
1011
}
1012
1013
template <class T>
1014
template <class S>
1015
IMATH_HOSTDEVICE inline void
1016
Vec2<T>::setValue (S a, S b) IMATH_NOEXCEPT
1017
{
1018
    x = T (a);
1019
    y = T (b);
1020
}
1021
1022
template <class T>
1023
template <class S>
1024
IMATH_HOSTDEVICE inline void
1025
Vec2<T>::setValue (const Vec2<S>& v) IMATH_NOEXCEPT
1026
{
1027
    x = T (v.x);
1028
    y = T (v.y);
1029
}
1030
1031
template <class T>
1032
template <class S>
1033
IMATH_HOSTDEVICE inline void
1034
Vec2<T>::getValue (S& a, S& b) const IMATH_NOEXCEPT
1035
{
1036
    a = S (x);
1037
    b = S (y);
1038
}
1039
1040
template <class T>
1041
template <class S>
1042
IMATH_HOSTDEVICE inline void
1043
Vec2<T>::getValue (Vec2<S>& v) const IMATH_NOEXCEPT
1044
{
1045
    v.x = S (x);
1046
    v.y = S (y);
1047
}
1048
1049
template <class T>
1050
IMATH_HOSTDEVICE inline T*
1051
Vec2<T>::getValue() IMATH_NOEXCEPT
1052
{
1053
    return (T*) &x;
1054
}
1055
1056
template <class T>
1057
IMATH_HOSTDEVICE inline const T*
1058
Vec2<T>::getValue() const IMATH_NOEXCEPT
1059
{
1060
    return (const T*) &x;
1061
}
1062
1063
template <class T>
1064
template <class S>
1065
IMATH_HOSTDEVICE constexpr inline bool
1066
Vec2<T>::operator== (const Vec2<S>& v) const IMATH_NOEXCEPT
1067
{
1068
    return x == v.x && y == v.y;
1069
}
1070
1071
template <class T>
1072
template <class S>
1073
IMATH_HOSTDEVICE constexpr inline bool
1074
Vec2<T>::operator!= (const Vec2<S>& v) const IMATH_NOEXCEPT
1075
{
1076
    return x != v.x || y != v.y;
1077
}
1078
1079
template <class T>
1080
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool
1081
Vec2<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
1090
template <class T>
1091
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool
1092
Vec2<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
1101
template <class T>
1102
IMATH_HOSTDEVICE constexpr inline T
1103
Vec2<T>::dot (const Vec2& v) const IMATH_NOEXCEPT
1104
{
1105
    return x * v.x + y * v.y;
1106
}
1107
1108
template <class T>
1109
IMATH_HOSTDEVICE constexpr inline T
1110
Vec2<T>::operator^ (const Vec2& v) const IMATH_NOEXCEPT
1111
{
1112
    return dot (v);
1113
}
1114
1115
template <class T>
1116
IMATH_HOSTDEVICE constexpr inline T
1117
Vec2<T>::cross (const Vec2& v) const IMATH_NOEXCEPT
1118
{
1119
    return x * v.y - y * v.x;
1120
}
1121
1122
template <class T>
1123
IMATH_HOSTDEVICE constexpr inline T
1124
Vec2<T>::operator% (const Vec2& v) const IMATH_NOEXCEPT
1125
{
1126
    return x * v.y - y * v.x;
1127
}
1128
1129
template <class T>
1130
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2<T>&
1131
Vec2<T>::operator+= (const Vec2& v) IMATH_NOEXCEPT
1132
{
1133
    x += v.x;
1134
    y += v.y;
1135
    return *this;
1136
}
1137
1138
template <class T>
1139
IMATH_HOSTDEVICE constexpr inline Vec2<T>
1140
Vec2<T>::operator+ (const Vec2& v) const IMATH_NOEXCEPT
1141
{
1142
    return Vec2 (x + v.x, y + v.y);
1143
}
1144
1145
template <class T>
1146
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2<T>&
1147
Vec2<T>::operator-= (const Vec2& v) IMATH_NOEXCEPT
1148
{
1149
    x -= v.x;
1150
    y -= v.y;
1151
    return *this;
1152
}
1153
1154
template <class T>
1155
IMATH_HOSTDEVICE constexpr inline Vec2<T>
1156
Vec2<T>::operator- (const Vec2& v) const IMATH_NOEXCEPT
1157
{
1158
    return Vec2 (x - v.x, y - v.y);
1159
}
1160
1161
template <class T>
1162
IMATH_HOSTDEVICE constexpr inline Vec2<T>
1163
Vec2<T>::operator-() const IMATH_NOEXCEPT
1164
{
1165
    return Vec2 (-x, -y);
1166
}
1167
1168
template <class T>
1169
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2<T>&
1170
Vec2<T>::negate() IMATH_NOEXCEPT
1171
{
1172
    x = -x;
1173
    y = -y;
1174
    return *this;
1175
}
1176
1177
template <class T>
1178
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2<T>&
1179
Vec2<T>::operator*= (const Vec2& v) IMATH_NOEXCEPT
1180
{
1181
    x *= v.x;
1182
    y *= v.y;
1183
    return *this;
1184
}
1185
1186
template <class T>
1187
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2<T>&
1188
Vec2<T>::operator*= (T a) IMATH_NOEXCEPT
1189
{
1190
    x *= a;
1191
    y *= a;
1192
    return *this;
1193
}
1194
1195
template <class T>
1196
IMATH_HOSTDEVICE constexpr inline Vec2<T>
1197
Vec2<T>::operator* (const Vec2& v) const IMATH_NOEXCEPT
1198
{
1199
    return Vec2 (x * v.x, y * v.y);
1200
}
1201
1202
template <class T>
1203
IMATH_HOSTDEVICE constexpr inline Vec2<T>
1204
Vec2<T>::operator* (T a) const IMATH_NOEXCEPT
1205
{
1206
    return Vec2 (x * a, y * a);
1207
}
1208
1209
template <class T>
1210
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2<T>&
1211
Vec2<T>::operator/= (const Vec2& v) IMATH_NOEXCEPT
1212
{
1213
    x /= v.x;
1214
    y /= v.y;
1215
    return *this;
1216
}
1217
1218
template <class T>
1219
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2<T>&
1220
Vec2<T>::operator/= (T a) IMATH_NOEXCEPT
1221
{
1222
    x /= a;
1223
    y /= a;
1224
    return *this;
1225
}
1226
1227
template <class T>
1228
IMATH_HOSTDEVICE constexpr inline Vec2<T>
1229
Vec2<T>::operator/ (const Vec2& v) const IMATH_NOEXCEPT
1230
{
1231
    return Vec2 (x / v.x, y / v.y);
1232
}
1233
1234
template <class T>
1235
IMATH_HOSTDEVICE constexpr inline Vec2<T>
1236
Vec2<T>::operator/ (T a) const IMATH_NOEXCEPT
1237
{
1238
    return Vec2 (x / a, y / a);
1239
}
1240
1241
template <class T>
1242
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline T
1243
Vec2<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
1268
template <class T>
1269
IMATH_HOSTDEVICE inline T
1270
Vec2<T>::length() const IMATH_NOEXCEPT
1271
{
1272
    T length2 = dot (*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
1280
template <class T>
1281
IMATH_HOSTDEVICE constexpr inline T
1282
Vec2<T>::length2() const IMATH_NOEXCEPT
1283
{
1284
    return dot (*this);
1285
}
1286
1287
template <class T>
1288
IMATH_HOSTDEVICE inline const Vec2<T>&
1289
Vec2<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
1308
template <class T>
1309
inline const Vec2<T>&
1310
Vec2<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
1322
template <class T>
1323
IMATH_HOSTDEVICE inline const Vec2<T>&
1324
Vec2<T>::normalizeNonNull() IMATH_NOEXCEPT
1325
{
1326
    T l = length();
1327
    x /= l;
1328
    y /= l;
1329
    return *this;
1330
}
1331
1332
template <class T>
1333
IMATH_HOSTDEVICE inline Vec2<T>
1334
Vec2<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
1344
template <class T>
1345
inline Vec2<T>
1346
Vec2<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
1356
template <class T>
1357
IMATH_HOSTDEVICE inline Vec2<T>
1358
Vec2<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
1368
template <class T>
1369
IMATH_HOSTDEVICE
1370
IMATH_CONSTEXPR14 inline T&
1371
Vec3<T>::operator[] (int i) IMATH_NOEXCEPT
1372
{
1373
    return (&x)[i]; // NOSONAR - suppress SonarCloud bug report.
1374
}
1375
1376
template <class T>
1377
IMATH_HOSTDEVICE constexpr inline const T&
1378
Vec3<T>::operator[] (int i) const IMATH_NOEXCEPT
1379
{
1380
    return (&x)[i]; // NOSONAR - suppress SonarCloud bug report.
1381
}
1382
1383
template <class T> IMATH_HOSTDEVICE inline Vec3<T>::Vec3() IMATH_NOEXCEPT
1384
{
1385
    // empty, and not constexpr because data is uninitialized.
1386
}
1387
1388
template <class T> IMATH_HOSTDEVICE constexpr inline Vec3<T>::Vec3 (T a) IMATH_NOEXCEPT
1389
    : x(a), y(a), z(a)
1390
{
1391
}
1392
1393
template <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
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)
1400
{
1401
}
1402
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))
1406
{
1407
}
1408
1409
template <class T>
1410
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1411
Vec3<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
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))
1422
{
1423
}
1424
1425
template <class T>
1426
template <class S>
1427
IMATH_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
1449
template <class T>
1450
template <class S>
1451
IMATH_HOSTDEVICE inline void
1452
Vec3<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
1459
template <class T>
1460
template <class S>
1461
IMATH_HOSTDEVICE inline void
1462
Vec3<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
1469
template <class T>
1470
template <class S>
1471
IMATH_HOSTDEVICE inline void
1472
Vec3<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
1479
template <class T>
1480
template <class S>
1481
IMATH_HOSTDEVICE inline void
1482
Vec3<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
1489
template <class T>
1490
IMATH_HOSTDEVICE inline T*
1491
Vec3<T>::getValue() IMATH_NOEXCEPT
1492
{
1493
    return (T*) &x;
1494
}
1495
1496
template <class T>
1497
IMATH_HOSTDEVICE inline const T*
1498
Vec3<T>::getValue() const IMATH_NOEXCEPT
1499
{
1500
    return (const T*) &x;
1501
}
1502
1503
template <class T>
1504
template <class S>
1505
IMATH_HOSTDEVICE constexpr inline bool
1506
Vec3<T>::operator== (const Vec3<S>& v) const IMATH_NOEXCEPT
1507
{
1508
    return x == v.x && y == v.y && z == v.z;
1509
}
1510
1511
template <class T>
1512
template <class S>
1513
IMATH_HOSTDEVICE constexpr inline bool
1514
Vec3<T>::operator!= (const Vec3<S>& v) const IMATH_NOEXCEPT
1515
{
1516
    return x != v.x || y != v.y || z != v.z;
1517
}
1518
1519
template <class T>
1520
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool
1521
Vec3<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
1530
template <class T>
1531
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool
1532
Vec3<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
1541
template <class T>
1542
IMATH_HOSTDEVICE constexpr inline T
1543
Vec3<T>::dot (const Vec3& v) const IMATH_NOEXCEPT
1544
{
1545
    return x * v.x + y * v.y + z * v.z;
1546
}
1547
1548
template <class T>
1549
IMATH_HOSTDEVICE constexpr inline T
1550
Vec3<T>::operator^ (const Vec3& v) const IMATH_NOEXCEPT
1551
{
1552
    return dot (v);
1553
}
1554
1555
template <class T>
1556
IMATH_HOSTDEVICE constexpr inline Vec3<T>
1557
Vec3<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
1562
template <class T>
1563
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1564
Vec3<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
1575
template <class T>
1576
IMATH_HOSTDEVICE constexpr inline Vec3<T>
1577
Vec3<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
1582
template <class T>
1583
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1584
Vec3<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
1592
template <class T>
1593
IMATH_HOSTDEVICE constexpr inline Vec3<T>
1594
Vec3<T>::operator+ (const Vec3& v) const IMATH_NOEXCEPT
1595
{
1596
    return Vec3 (x + v.x, y + v.y, z + v.z);
1597
}
1598
1599
template <class T>
1600
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1601
Vec3<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
1609
template <class T>
1610
IMATH_HOSTDEVICE constexpr inline Vec3<T>
1611
Vec3<T>::operator- (const Vec3& v) const IMATH_NOEXCEPT
1612
{
1613
    return Vec3 (x - v.x, y - v.y, z - v.z);
1614
}
1615
1616
template <class T>
1617
IMATH_HOSTDEVICE constexpr inline Vec3<T>
1618
Vec3<T>::operator-() const IMATH_NOEXCEPT
1619
{
1620
    return Vec3 (-x, -y, -z);
1621
}
1622
1623
template <class T>
1624
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1625
Vec3<T>::negate() IMATH_NOEXCEPT
1626
{
1627
    x = -x;
1628
    y = -y;
1629
    z = -z;
1630
    return *this;
1631
}
1632
1633
template <class T>
1634
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1635
Vec3<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
1643
template <class T>
1644
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1645
Vec3<T>::operator*= (T a) IMATH_NOEXCEPT
1646
{
1647
    x *= a;
1648
    y *= a;
1649
    z *= a;
1650
    return *this;
1651
}
1652
1653
template <class T>
1654
IMATH_HOSTDEVICE constexpr inline Vec3<T>
1655
Vec3<T>::operator* (const Vec3& v) const IMATH_NOEXCEPT
1656
{
1657
    return Vec3 (x * v.x, y * v.y, z * v.z);
1658
}
1659
1660
template <class T>
1661
IMATH_HOSTDEVICE constexpr inline Vec3<T>
1662
Vec3<T>::operator* (T a) const IMATH_NOEXCEPT
1663
{
1664
    return Vec3 (x * a, y * a, z * a);
1665
}
1666
1667
template <class T>
1668
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1669
Vec3<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
1677
template <class T>
1678
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1679
Vec3<T>::operator/= (T a) IMATH_NOEXCEPT
1680
{
1681
    x /= a;
1682
    y /= a;
1683
    z /= a;
1684
    return *this;
1685
}
1686
1687
template <class T>
1688
IMATH_HOSTDEVICE constexpr inline Vec3<T>
1689
Vec3<T>::operator/ (const Vec3& v) const IMATH_NOEXCEPT
1690
{
1691
    return Vec3 (x / v.x, y / v.y, z / v.z);
1692
}
1693
1694
template <class T>
1695
IMATH_HOSTDEVICE constexpr inline Vec3<T>
1696
Vec3<T>::operator/ (T a) const IMATH_NOEXCEPT
1697
{
1698
    return Vec3 (x / a, y / a, z / a);
1699
}
1700
1701
template <class T>
1702
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline T
1703
Vec3<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
1733
template <class T>
1734
IMATH_HOSTDEVICE inline T
1735
Vec3<T>::length() const IMATH_NOEXCEPT
1736
{
1737
    T length2 = dot (*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
1745
template <class T>
1746
IMATH_HOSTDEVICE constexpr inline T
1747
Vec3<T>::length2() const IMATH_NOEXCEPT
1748
{
1749
    return dot (*this);
1750
}
1751
1752
template <class T>
1753
IMATH_HOSTDEVICE inline const Vec3<T>&
1754
Vec3<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
1774
template <class T>
1775
inline const Vec3<T>&
1776
Vec3<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
1789
template <class T>
1790
IMATH_HOSTDEVICE inline const Vec3<T>&
1791
Vec3<T>::normalizeNonNull() IMATH_NOEXCEPT
1792
{
1793
    T l = length();
1794
    x /= l;
1795
    y /= l;
1796
    z /= l;
1797
    return *this;
1798
}
1799
1800
template <class T>
1801
IMATH_HOSTDEVICE inline Vec3<T>
1802
Vec3<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
1812
template <class T>
1813
inline Vec3<T>
1814
Vec3<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
1824
template <class T>
1825
IMATH_HOSTDEVICE inline Vec3<T>
1826
Vec3<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
1836
template <class T>
1837
IMATH_HOSTDEVICE
1838
IMATH_CONSTEXPR14 inline T&
1839
Vec4<T>::operator[] (int i) IMATH_NOEXCEPT
1840
{
1841
    return (&x)[i]; // NOSONAR - suppress SonarCloud bug report.
1842
}
1843
1844
template <class T>
1845
IMATH_HOSTDEVICE constexpr inline const T&
1846
Vec4<T>::operator[] (int i) const IMATH_NOEXCEPT
1847
{
1848
    return (&x)[i]; // NOSONAR - suppress SonarCloud bug report.
1849
}
1850
1851
template <class T> IMATH_HOSTDEVICE inline Vec4<T>::Vec4() IMATH_NOEXCEPT
1852
{
1853
    // empty, and not constexpr because data is uninitialized.
1854
}
1855
1856
template <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
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)
1863
{
1864
}
1865
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)
1868
{
1869
}
1870
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))
1874
{
1875
}
1876
1877
template <class T>
1878
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4<T>&
1879
Vec4<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
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))
1891
{
1892
}
1893
1894
template <class T>
1895
template <class S>
1896
IMATH_HOSTDEVICE constexpr inline bool
1897
Vec4<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
1902
template <class T>
1903
template <class S>
1904
IMATH_HOSTDEVICE constexpr inline bool
1905
Vec4<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
1910
template <class T>
1911
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool
1912
Vec4<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
1921
template <class T>
1922
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool
1923
Vec4<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
1932
template <class T>
1933
IMATH_HOSTDEVICE constexpr inline T
1934
Vec4<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
1939
template <class T>
1940
IMATH_HOSTDEVICE constexpr inline T
1941
Vec4<T>::operator^ (const Vec4& v) const IMATH_NOEXCEPT
1942
{
1943
    return dot (v);
1944
}
1945
1946
template <class T>
1947
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4<T>&
1948
Vec4<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
1957
template <class T>
1958
IMATH_HOSTDEVICE constexpr inline Vec4<T>
1959
Vec4<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
1964
template <class T>
1965
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4<T>&
1966
Vec4<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
1975
template <class T>
1976
IMATH_HOSTDEVICE constexpr inline Vec4<T>
1977
Vec4<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
1982
template <class T>
1983
IMATH_HOSTDEVICE constexpr inline Vec4<T>
1984
Vec4<T>::operator-() const IMATH_NOEXCEPT
1985
{
1986
    return Vec4 (-x, -y, -z, -w);
1987
}
1988
1989
template <class T>
1990
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4<T>&
1991
Vec4<T>::negate() IMATH_NOEXCEPT
1992
{
1993
    x = -x;
1994
    y = -y;
1995
    z = -z;
1996
    w = -w;
1997
    return *this;
1998
}
1999
2000
template <class T>
2001
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4<T>&
2002
Vec4<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
2011
template <class T>
2012
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4<T>&
2013
Vec4<T>::operator*= (T a) IMATH_NOEXCEPT
2014
{
2015
    x *= a;
2016
    y *= a;
2017
    z *= a;
2018
    w *= a;
2019
    return *this;
2020
}
2021
2022
template <class T>
2023
IMATH_HOSTDEVICE constexpr inline Vec4<T>
2024
Vec4<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
2029
template <class T>
2030
IMATH_HOSTDEVICE constexpr inline Vec4<T>
2031
Vec4<T>::operator* (T a) const IMATH_NOEXCEPT
2032
{
2033
    return Vec4 (x * a, y * a, z * a, w * a);
2034
}
2035
2036
template <class T>
2037
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4<T>&
2038
Vec4<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
2047
template <class T>
2048
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4<T>&
2049
Vec4<T>::operator/= (T a) IMATH_NOEXCEPT
2050
{
2051
    x /= a;
2052
    y /= a;
2053
    z /= a;
2054
    w /= a;
2055
    return *this;
2056
}
2057
2058
template <class T>
2059
IMATH_HOSTDEVICE constexpr inline Vec4<T>
2060
Vec4<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
2065
template <class T>
2066
IMATH_HOSTDEVICE constexpr inline Vec4<T>
2067
Vec4<T>::operator/ (T a) const IMATH_NOEXCEPT
2068
{
2069
    return Vec4 (x / a, y / a, z / a, w / a);
2070
}
2071
2072
template <class T>
2073
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline T
2074
Vec4<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
2109
template <class T>
2110
IMATH_HOSTDEVICE inline T
2111
Vec4<T>::length() const IMATH_NOEXCEPT
2112
{
2113
    T length2 = dot (*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
2121
template <class T>
2122
IMATH_HOSTDEVICE constexpr inline T
2123
Vec4<T>::length2() const IMATH_NOEXCEPT
2124
{
2125
    return dot (*this);
2126
}
2127
2128
template <class T>
2129
IMATH_HOSTDEVICE const inline Vec4<T>&
2130
Vec4<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
2151
template <class T>
2152
const inline Vec4<T>&
2153
Vec4<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
2167
template <class T>
2168
IMATH_HOSTDEVICE inline const Vec4<T>&
2169
Vec4<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
2179
template <class T>
2180
IMATH_HOSTDEVICE inline Vec4<T>
2181
Vec4<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
2191
template <class T>
2192
inline Vec4<T>
2193
Vec4<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
2203
template <class T>
2204
IMATH_HOSTDEVICE inline Vec4<T>
2205
Vec4<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
2215
template <class T>
2216
std::ostream&
2217
operator<< (std::ostream& s, const Vec2<T>& v)
2218
{
2219
    return s << '(' << v.x << ' ' << v.y << ')';
2220
}
2221
2222
template <class T>
2223
std::ostream&
2224
operator<< (std::ostream& s, const Vec3<T>& v)
2225
{
2226
    return s << '(' << v.x << ' ' << v.y << ' ' << v.z << ')';
2227
}
2228
2229
template <class T>
2230
std::ostream&
2231
operator<< (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
2240
template <class T>
2241
IMATH_HOSTDEVICE constexpr inline Vec2<T>
2242
operator* (T a, const Vec2<T>& v) IMATH_NOEXCEPT
2243
{
2244
    return Vec2<T> (a * v.x, a * v.y);
2245
}
2246
2247
template <class T>
2248
IMATH_HOSTDEVICE constexpr inline Vec3<T>
2249
operator* (T a, const Vec3<T>& v) IMATH_NOEXCEPT
2250
{
2251
    return Vec3<T> (a * v.x, a * v.y, a * v.z);
2252
}
2253
2254
template <class T>
2255
IMATH_HOSTDEVICE constexpr inline Vec4<T>
2256
operator* (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
2265
IMATH_INTERNAL_NAMESPACE_HEADER_EXIT
2266
2267
#endif // INCLUDED_IMATHVEC_H