Coverage Report

Created: 2024-07-27 06:04

/work/_deps/imath-src/src/Imath/ImathVec.h
Line
Count
Source (jump to first uncovered line)
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
    /// @name Direct access to elements
51
52
    T x, y;
53
54
    /// @}
55
56
    /// Element access by index.
57
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T& operator[] (int i) IMATH_NOEXCEPT;
58
59
    /// Element access by index.
60
    IMATH_HOSTDEVICE constexpr const T& operator[] (int i) const IMATH_NOEXCEPT;
61
62
    /// @{
63
    /// @name Constructors and Assignment
64
65
    /// Uninitialized by default
66
    IMATH_HOSTDEVICE Vec2 () IMATH_NOEXCEPT;
67
68
    /// Initialize to a scalar `(a,a)`
69
    IMATH_HOSTDEVICE constexpr explicit Vec2 (T a) IMATH_NOEXCEPT;
70
71
    /// Initialize to given elements `(a,b)`
72
    IMATH_HOSTDEVICE constexpr Vec2 (T a, T b) IMATH_NOEXCEPT;
73
74
    /// Copy constructor
75
    IMATH_HOSTDEVICE constexpr Vec2 (const Vec2& v) IMATH_NOEXCEPT;
76
77
    /// Construct from Vec2 of another base type
78
    template <class S>
79
    IMATH_HOSTDEVICE constexpr Vec2 (const Vec2<S>& v) IMATH_NOEXCEPT;
80
81
    /// Assignment
82
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2&
83
    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
111
    template <
112
        typename V,
113
        IMATH_ENABLE_IF (has_subscript<V, T, 2>::value && !has_xy<V, T>::value)>
114
    IMATH_HOSTDEVICE explicit Vec2 (const V& v) : Vec2 (T (v[0]), T (v[1]))
115
    {}
116
117
    template <typename V, IMATH_ENABLE_IF (has_xy<V, T>::value)>
118
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2&
119
    operator= (const V& v) IMATH_NOEXCEPT
120
    {
121
        x = T (v.x);
122
        y = T (v.y);
123
        return *this;
124
    }
125
126
    template <
127
        typename V,
128
        IMATH_ENABLE_IF (has_subscript<V, T, 2>::value && !has_xy<V, T>::value)>
129
    IMATH_HOSTDEVICE const Vec2& operator= (const V& v)
130
    {
131
        x = T (v[0]);
132
        y = T (v[1]);
133
        return *this;
134
    }
135
#endif
136
137
    /// @{
138
    /// @name Compatibility with Sb
139
140
    /// Set the value
141
    template <class S> IMATH_HOSTDEVICE void setValue (S a, S b) IMATH_NOEXCEPT;
142
143
    /// Set the value
144
    template <class S>
145
    IMATH_HOSTDEVICE void setValue (const Vec2<S>& v) IMATH_NOEXCEPT;
146
147
    /// Return the value in `a` and `b`
148
    template <class S>
149
    IMATH_HOSTDEVICE void getValue (S& a, S& b) const IMATH_NOEXCEPT;
150
151
    /// Return the value in `v`
152
    template <class S>
153
    IMATH_HOSTDEVICE void getValue (Vec2<S>& v) const IMATH_NOEXCEPT;
154
155
    /// Return a raw pointer to the array of values
156
    IMATH_HOSTDEVICE T* getValue () IMATH_NOEXCEPT;
157
158
    /// Return a raw pointer to the array of values
159
    IMATH_HOSTDEVICE const T* getValue () const IMATH_NOEXCEPT;
160
161
    /// @}
162
163
    /// @{
164
    /// @name Arithmetic and Comparison
165
166
    /// Equality
167
    template <class S>
168
    IMATH_HOSTDEVICE constexpr bool
169
    operator== (const Vec2<S>& v) const IMATH_NOEXCEPT;
170
171
    /// Inequality
172
    template <class S>
173
    IMATH_HOSTDEVICE constexpr bool
174
    operator!= (const Vec2<S>& v) const IMATH_NOEXCEPT;
175
176
    /// Compare two matrices and test if they are "approximately equal":
177
    /// @return True if the coefficients of this and `m` are the same
178
    /// with an absolute error of no more than e, i.e., for all i, j:
179
    ///
180
    ///     abs (this[i][j] - m[i][j]) <= e
181
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool
182
    equalWithAbsError (const Vec2<T>& v, T e) const IMATH_NOEXCEPT;
183
184
    /// Compare two matrices and test if they are "approximately equal":
185
    /// @return True if the coefficients of this and m are the same with
186
    /// a relative error of no more than e, i.e., for all i, j:
187
    ///
188
    ///     abs (this[i] - v[i][j]) <= e * abs (this[i][j])
189
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool
190
    equalWithRelError (const Vec2<T>& v, T e) const IMATH_NOEXCEPT;
191
192
    /// Dot product
193
    IMATH_HOSTDEVICE constexpr T dot (const Vec2& v) const IMATH_NOEXCEPT;
194
195
    /// Dot product
196
    IMATH_HOSTDEVICE constexpr T operator^ (const Vec2& v) const IMATH_NOEXCEPT;
197
198
    /// Right-handed cross product, i.e. z component of
199
    /// Vec3 (this->x, this->y, 0) % Vec3 (v.x, v.y, 0)
200
    IMATH_HOSTDEVICE constexpr T cross (const Vec2& v) const IMATH_NOEXCEPT;
201
202
    /// Right-handed cross product, i.e. z component of
203
    /// Vec3 (this->x, this->y, 0) % Vec3 (v.x, v.y, 0)
204
    IMATH_HOSTDEVICE constexpr T operator% (const Vec2& v) const IMATH_NOEXCEPT;
205
206
    /// Component-wise addition
207
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2&
208
    operator+= (const Vec2& v) IMATH_NOEXCEPT;
209
210
    /// Component-wise addition
211
    IMATH_HOSTDEVICE constexpr Vec2
212
    operator+ (const Vec2& v) const IMATH_NOEXCEPT;
213
214
    /// Component-wise subtraction
215
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2&
216
    operator-= (const Vec2& v) IMATH_NOEXCEPT;
217
218
    /// Component-wise subtraction
219
    IMATH_HOSTDEVICE constexpr Vec2
220
    operator- (const Vec2& v) const IMATH_NOEXCEPT;
221
222
    /// Component-wise multiplication by -1
223
    IMATH_HOSTDEVICE constexpr Vec2 operator- () const IMATH_NOEXCEPT;
224
225
    /// Component-wise multiplication by -1
226
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& negate () IMATH_NOEXCEPT;
227
228
    /// Component-wise multiplication
229
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2&
230
    operator*= (const Vec2& v) IMATH_NOEXCEPT;
231
232
    /// Component-wise multiplication
233
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2&
234
    operator*= (T a) IMATH_NOEXCEPT;
235
236
    /// Component-wise multiplication
237
    IMATH_HOSTDEVICE constexpr Vec2
238
    operator* (const Vec2& v) const IMATH_NOEXCEPT;
239
240
    /// Component-wise multiplication
241
    IMATH_HOSTDEVICE constexpr Vec2 operator* (T a) const IMATH_NOEXCEPT;
242
243
    /// Component-wise division
244
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2&
245
    operator/= (const Vec2& v) IMATH_NOEXCEPT;
246
247
    /// Component-wise division
248
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2&
249
    operator/= (T a) IMATH_NOEXCEPT;
250
251
    /// Component-wise division
252
    IMATH_HOSTDEVICE constexpr Vec2
253
    operator/ (const Vec2& v) const IMATH_NOEXCEPT;
254
255
    /// Component-wise division
256
    IMATH_HOSTDEVICE constexpr Vec2 operator/ (T a) const IMATH_NOEXCEPT;
257
258
    /// @}
259
260
    /// @{
261
    /// @name Query and Manipulation
262
263
    /// Return the Euclidean norm
264
    IMATH_HOSTDEVICE T length () const IMATH_NOEXCEPT;
265
266
    /// Return the square of the Euclidean norm, i.e. the dot product
267
    /// with itself.
268
    IMATH_HOSTDEVICE constexpr T length2 () const IMATH_NOEXCEPT;
269
270
    /// Normalize in place. If length()==0, return a null vector.
271
    IMATH_HOSTDEVICE const Vec2& normalize () IMATH_NOEXCEPT;
272
273
    /// Normalize in place. If length()==0, throw an exception.
274
    const Vec2& normalizeExc ();
275
276
    /// Normalize without any checks for length()==0. Slightly faster
277
    /// than the other normalization routines, but if v.length() is
278
    /// 0.0, the result is undefined.
279
    IMATH_HOSTDEVICE const Vec2& normalizeNonNull () IMATH_NOEXCEPT;
280
281
    /// Return a normalized vector. Does not modify *this.
282
    IMATH_HOSTDEVICE Vec2<T> normalized () const IMATH_NOEXCEPT;
283
284
    /// Return a normalized vector. Does not modify *this. Throw an
285
    /// exception if length()==0.
286
    Vec2<T> normalizedExc () const;
287
288
    /// Return a normalized vector. Does not modify *this, and does
289
    /// not check for length()==0. Slightly faster than the other
290
    /// normalization routines, but if v.length() is 0.0, the result
291
    /// is undefined.
292
    IMATH_HOSTDEVICE Vec2<T> normalizedNonNull () const IMATH_NOEXCEPT;
293
294
    /// @}
295
296
    /// @{
297
    /// @name Numeric Limits
298
299
    /// Largest possible negative value
300
    IMATH_HOSTDEVICE constexpr static T baseTypeLowest () IMATH_NOEXCEPT
301
404k
    {
302
404k
        return std::numeric_limits<T>::lowest ();
303
404k
    }
Imath_3_2::Vec2<int>::baseTypeLowest()
Line
Count
Source
301
403k
    {
302
403k
        return std::numeric_limits<T>::lowest ();
303
403k
    }
Imath_3_2::Vec2<float>::baseTypeLowest()
Line
Count
Source
301
1.19k
    {
302
1.19k
        return std::numeric_limits<T>::lowest ();
303
1.19k
    }
304
305
    /// Largest possible positive value
306
    IMATH_HOSTDEVICE constexpr static T baseTypeMax () IMATH_NOEXCEPT
307
404k
    {
308
404k
        return std::numeric_limits<T>::max ();
309
404k
    }
Imath_3_2::Vec2<int>::baseTypeMax()
Line
Count
Source
307
403k
    {
308
403k
        return std::numeric_limits<T>::max ();
309
403k
    }
Imath_3_2::Vec2<float>::baseTypeMax()
Line
Count
Source
307
1.19k
    {
308
1.19k
        return std::numeric_limits<T>::max ();
309
1.19k
    }
310
311
    /// Smallest possible positive value
312
    IMATH_HOSTDEVICE constexpr static T baseTypeSmallest () IMATH_NOEXCEPT
313
    {
314
        return std::numeric_limits<T>::min ();
315
    }
316
317
    /// Smallest possible e for which 1+e != 1
318
    IMATH_HOSTDEVICE constexpr static T baseTypeEpsilon () IMATH_NOEXCEPT
319
    {
320
        return std::numeric_limits<T>::epsilon ();
321
    }
322
323
    /// @}
324
325
    /// Return the number of dimensions, i.e. 2
326
    IMATH_HOSTDEVICE constexpr static unsigned int dimensions () IMATH_NOEXCEPT
327
    {
328
        return 2;
329
    }
330
331
    /// The base type: In templates that accept a parameter `V`, you
332
    /// can refer to `T` as `V::BaseType`
333
    typedef T BaseType;
334
335
private:
336
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T lengthTiny () const IMATH_NOEXCEPT;
337
};
338
339
///
340
/// 3-element vector
341
///
342
343
template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Vec3
344
{
345
public:
346
    /// @{
347
    /// @name Direct access to elements
348
349
    T x, y, z;
350
351
    /// @}
352
353
    /// Element access by index.
354
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T& operator[] (int i) IMATH_NOEXCEPT;
355
356
    /// Element access by index.
357
    IMATH_HOSTDEVICE constexpr const T& operator[] (int i) const IMATH_NOEXCEPT;
358
359
    /// @{
360
    /// @name Constructors and Assignment
361
362
    /// Uninitialized by default
363
    IMATH_HOSTDEVICE Vec3 () IMATH_NOEXCEPT;
364
365
    /// Initialize to a scalar `(a,a,a)`
366
    IMATH_HOSTDEVICE constexpr explicit Vec3 (T a) IMATH_NOEXCEPT;
367
368
    /// Initialize to given elements `(a,b,c)`
369
    IMATH_HOSTDEVICE constexpr Vec3 (T a, T b, T c) IMATH_NOEXCEPT;
370
371
    /// Copy constructor
372
    IMATH_HOSTDEVICE constexpr Vec3 (const Vec3& v) IMATH_NOEXCEPT;
373
374
    /// Construct from Vec3 of another base type
375
    template <class S>
376
    IMATH_HOSTDEVICE constexpr Vec3 (const Vec3<S>& v) IMATH_NOEXCEPT;
377
378
    /// Vec4 to Vec3 conversion: divide x, y and z by w, even if w is
379
    /// 0.  The result depends on how the environment handles
380
    /// floating-point exceptions.
381
    template <class S>
382
    IMATH_HOSTDEVICE explicit constexpr Vec3 (const Vec4<S>& v) IMATH_NOEXCEPT;
383
384
    /// Vec4 to Vec3 conversion: divide x, y and z by w.  Throws an
385
    /// exception if w is zero or if division by w would overflow.
386
    template <class S>
387
    explicit IMATH_HOSTDEVICE IMATH_CONSTEXPR14
388
    Vec3 (const Vec4<S>& v, InfException);
389
390
    /// Assignment
391
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3&
392
    operator= (const Vec3& v) IMATH_NOEXCEPT;
393
394
    /// Destructor
395
    ~Vec3 () IMATH_NOEXCEPT = default;
396
397
    /// @}
398
399
#if IMATH_FOREIGN_VECTOR_INTEROP
400
    /// @{
401
    /// @name Interoperability with other vector types
402
    ///
403
    /// Construction and assignment are allowed from other classes that
404
    /// appear to be equivalent vector types, provided that they have either
405
    /// a subscripting operator, or data members .x, .y, .z, that are of the
406
    /// same type as the elements of this vector, and their size appears to
407
    /// be the right number of elements.
408
    ///
409
    /// This functionality is disabled for gcc 4.x, which seems to have a
410
    /// compiler bug that results in spurious errors. It can also be
411
    /// disabled by defining IMATH_FOREIGN_VECTOR_INTEROP to be 0 prior to
412
    /// including any Imath header files.
413
    ///
414
415
    template <typename V, IMATH_ENABLE_IF (has_xyz<V, T>::value)>
416
    IMATH_HOSTDEVICE explicit constexpr Vec3 (const V& v) IMATH_NOEXCEPT
417
        : Vec3 (T (v.x), T (v.y), T (v.z))
418
    {}
419
420
    template <
421
        typename V,
422
        IMATH_ENABLE_IF (
423
            has_subscript<V, T, 3>::value && !has_xyz<V, T>::value)>
424
    IMATH_HOSTDEVICE explicit Vec3 (const V& v)
425
        : Vec3 (T (v[0]), T (v[1]), T (v[2]))
426
    {}
427
428
    /// Interoperability assignment from another type that behaves as if it
429
    /// were an equivalent vector.
430
    template <typename V, IMATH_ENABLE_IF (has_xyz<V, T>::value)>
431
    IMATH_HOSTDEVICE const Vec3& operator= (const V& v) IMATH_NOEXCEPT
432
    {
433
        x = T (v.x);
434
        y = T (v.y);
435
        z = T (v.z);
436
        return *this;
437
    }
438
439
    template <
440
        typename V,
441
        IMATH_ENABLE_IF (
442
            has_subscript<V, T, 3>::value && !has_xyz<V, T>::value)>
443
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator= (const V& v)
444
    {
445
        x = T (v[0]);
446
        y = T (v[1]);
447
        z = T (v[2]);
448
        return *this;
449
    }
450
    /// @}
451
#endif
452
453
    /// @{
454
    /// @name Compatibility with Sb
455
456
    /// Set the value
457
    template <class S>
458
    IMATH_HOSTDEVICE void setValue (S a, S b, S c) IMATH_NOEXCEPT;
459
460
    /// Set the value
461
    template <class S>
462
    IMATH_HOSTDEVICE void setValue (const Vec3<S>& v) IMATH_NOEXCEPT;
463
464
    /// Return the value in `a`, `b`, and `c`
465
    template <class S>
466
    IMATH_HOSTDEVICE void getValue (S& a, S& b, S& c) const IMATH_NOEXCEPT;
467
468
    /// Return the value in `v`
469
    template <class S>
470
    IMATH_HOSTDEVICE void getValue (Vec3<S>& v) const IMATH_NOEXCEPT;
471
472
    /// Return a raw pointer to the array of values
473
    IMATH_HOSTDEVICE T* getValue () IMATH_NOEXCEPT;
474
475
    /// Return a raw pointer to the array of values
476
    IMATH_HOSTDEVICE const T* getValue () const IMATH_NOEXCEPT;
477
478
    /// @}
479
480
    /// @{
481
    /// @name Arithmetic and Comparison
482
483
    /// Equality
484
    template <class S>
485
    IMATH_HOSTDEVICE constexpr bool
486
    operator== (const Vec3<S>& v) const IMATH_NOEXCEPT;
487
488
    /// Inequality
489
    template <class S>
490
    IMATH_HOSTDEVICE constexpr bool
491
    operator!= (const Vec3<S>& v) const IMATH_NOEXCEPT;
492
493
    /// Compare two matrices and test if they are "approximately equal":
494
    /// @return True if the coefficients of this and `m` are the same
495
    /// with an absolute error of no more than e, i.e., for all i, j:
496
    ///
497
    ///     abs (this[i][j] - m[i][j]) <= e
498
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool
499
    equalWithAbsError (const Vec3<T>& v, T e) const IMATH_NOEXCEPT;
500
501
    /// Compare two matrices and test if they are "approximately equal":
502
    /// @return True if the coefficients of this and m are the same with
503
    /// a relative error of no more than e, i.e., for all i, j:
504
    ///
505
    ///     abs (this[i] - v[i][j]) <= e * abs (this[i][j])
506
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool
507
    equalWithRelError (const Vec3<T>& v, T e) const IMATH_NOEXCEPT;
508
509
    /// Dot product
510
    IMATH_HOSTDEVICE constexpr T dot (const Vec3& v) const IMATH_NOEXCEPT;
511
512
    /// Dot product
513
    IMATH_HOSTDEVICE constexpr T operator^ (const Vec3& v) const IMATH_NOEXCEPT;
514
515
    /// Right-handed cross product
516
    IMATH_HOSTDEVICE constexpr Vec3 cross (const Vec3& v) const IMATH_NOEXCEPT;
517
518
    /// Right-handed cross product
519
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3&
520
    operator%= (const Vec3& v) IMATH_NOEXCEPT;
521
522
    /// Right-handed cross product
523
    IMATH_HOSTDEVICE constexpr Vec3
524
    operator% (const Vec3& v) const IMATH_NOEXCEPT;
525
526
    /// Component-wise addition
527
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3&
528
    operator+= (const Vec3& v) IMATH_NOEXCEPT;
529
530
    /// Component-wise addition
531
    IMATH_HOSTDEVICE constexpr Vec3
532
    operator+ (const Vec3& v) const IMATH_NOEXCEPT;
533
534
    /// Component-wise subtraction
535
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3&
536
    operator-= (const Vec3& v) IMATH_NOEXCEPT;
537
538
    /// Component-wise subtraction
539
    IMATH_HOSTDEVICE constexpr Vec3
540
    operator- (const Vec3& v) const IMATH_NOEXCEPT;
541
542
    /// Component-wise multiplication by -1
543
    IMATH_HOSTDEVICE constexpr Vec3 operator- () const IMATH_NOEXCEPT;
544
545
    /// Component-wise multiplication by -1
546
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& negate () IMATH_NOEXCEPT;
547
548
    /// Component-wise multiplication
549
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3&
550
    operator*= (const Vec3& v) IMATH_NOEXCEPT;
551
552
    /// Component-wise multiplication
553
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3&
554
    operator*= (T a) IMATH_NOEXCEPT;
555
556
    /// Component-wise multiplication
557
    IMATH_HOSTDEVICE constexpr Vec3
558
    operator* (const Vec3& v) const IMATH_NOEXCEPT;
559
560
    /// Component-wise multiplication
561
    IMATH_HOSTDEVICE constexpr Vec3 operator* (T a) const IMATH_NOEXCEPT;
562
563
    /// Component-wise division
564
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3&
565
    operator/= (const Vec3& v) IMATH_NOEXCEPT;
566
567
    /// Component-wise division
568
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3&
569
    operator/= (T a) IMATH_NOEXCEPT;
570
571
    /// Component-wise division
572
    IMATH_HOSTDEVICE constexpr Vec3
573
    operator/ (const Vec3& v) const IMATH_NOEXCEPT;
574
575
    /// Component-wise division
576
    IMATH_HOSTDEVICE constexpr Vec3 operator/ (T a) const IMATH_NOEXCEPT;
577
578
    /// @}
579
580
    /// @{
581
    /// @name Query and Manipulation
582
583
    /// Return the Euclidean norm
584
    IMATH_HOSTDEVICE T length () const IMATH_NOEXCEPT;
585
586
    /// Return the square of the Euclidean norm, i.e. the dot product
587
    /// with itself.
588
    IMATH_HOSTDEVICE constexpr T length2 () const IMATH_NOEXCEPT;
589
590
    /// Normalize in place. If length()==0, return a null vector.
591
    IMATH_HOSTDEVICE const Vec3& normalize () IMATH_NOEXCEPT;
592
593
    /// Normalize in place. If length()==0, throw an exception.
594
    const Vec3& normalizeExc ();
595
596
    /// Normalize without any checks for length()==0. Slightly faster
597
    /// than the other normalization routines, but if v.length() is
598
    /// 0.0, the result is undefined.
599
    IMATH_HOSTDEVICE const Vec3& normalizeNonNull () IMATH_NOEXCEPT;
600
601
    /// Return a normalized vector. Does not modify *this.
602
    IMATH_HOSTDEVICE Vec3<T>
603
    normalized () const IMATH_NOEXCEPT; // does not modify *this
604
605
    /// Return a normalized vector. Does not modify *this. Throw an
606
    /// exception if length()==0.
607
    Vec3<T> normalizedExc () const;
608
609
    /// Return a normalized vector. Does not modify *this, and does
610
    /// not check for length()==0. Slightly faster than the other
611
    /// normalization routines, but if v.length() is 0.0, the result
612
    /// is undefined.
613
    IMATH_HOSTDEVICE Vec3<T> normalizedNonNull () const IMATH_NOEXCEPT;
614
615
    /// @}
616
617
    /// @{
618
    /// @name Numeric Limits
619
620
    /// Largest possible negative value
621
    IMATH_HOSTDEVICE constexpr static T baseTypeLowest () IMATH_NOEXCEPT
622
    {
623
        return std::numeric_limits<T>::lowest ();
624
    }
625
626
    /// Largest possible positive value
627
    IMATH_HOSTDEVICE constexpr static T baseTypeMax () IMATH_NOEXCEPT
628
    {
629
        return std::numeric_limits<T>::max ();
630
    }
631
632
    /// Smallest possible positive value
633
    IMATH_HOSTDEVICE constexpr static T baseTypeSmallest () IMATH_NOEXCEPT
634
    {
635
        return std::numeric_limits<T>::min ();
636
    }
637
638
    /// Smallest possible e for which 1+e != 1
639
    IMATH_HOSTDEVICE constexpr static T baseTypeEpsilon () IMATH_NOEXCEPT
640
    {
641
        return std::numeric_limits<T>::epsilon ();
642
    }
643
644
    /// @}
645
646
    /// Return the number of dimensions, i.e. 3
647
    IMATH_HOSTDEVICE constexpr static unsigned int dimensions () IMATH_NOEXCEPT
648
    {
649
        return 3;
650
    }
651
652
    /// The base type: In templates that accept a parameter `V`, you
653
    /// can refer to `T` as `V::BaseType`
654
    typedef T BaseType;
655
656
private:
657
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T lengthTiny () const IMATH_NOEXCEPT;
658
};
659
660
///
661
/// 4-element vector
662
///
663
664
template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Vec4
665
{
666
public:
667
    /// @{
668
    /// @name Direct access to elements
669
670
    T x, y, z, w;
671
672
    /// @}
673
674
    /// Element access by index.
675
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T& operator[] (int i) IMATH_NOEXCEPT;
676
677
    /// Element access by index.
678
    IMATH_HOSTDEVICE constexpr const T& operator[] (int i) const IMATH_NOEXCEPT;
679
680
    /// @{
681
    /// @name Constructors and Assignment
682
683
    /// Uninitialized by default
684
    IMATH_HOSTDEVICE Vec4 () IMATH_NOEXCEPT; // no initialization
685
686
    /// Initialize to a scalar `(a,a,a,a)`
687
    IMATH_HOSTDEVICE constexpr explicit Vec4 (T a) IMATH_NOEXCEPT;
688
689
    /// Initialize to given elements `(a,b,c,d)`
690
    IMATH_HOSTDEVICE constexpr Vec4 (T a, T b, T c, T d) IMATH_NOEXCEPT;
691
692
    /// Copy constructor
693
    IMATH_HOSTDEVICE constexpr Vec4 (const Vec4& v) IMATH_NOEXCEPT;
694
695
    /// Construct from Vec4 of another base type
696
    template <class S>
697
    IMATH_HOSTDEVICE constexpr Vec4 (const Vec4<S>& v) IMATH_NOEXCEPT;
698
699
    /// Vec3 to Vec4 conversion, sets w to 1.
700
    template <class S>
701
    IMATH_HOSTDEVICE explicit constexpr Vec4 (const Vec3<S>& v) IMATH_NOEXCEPT;
702
703
    /// Assignment
704
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4&
705
    operator= (const Vec4& v) IMATH_NOEXCEPT;
706
707
    /// Destructor
708
    ~Vec4 () IMATH_NOEXCEPT = default;
709
710
    /// @}
711
712
#if IMATH_FOREIGN_VECTOR_INTEROP
713
    /// @{
714
    /// @name Interoperability with other vector types
715
    ///
716
    /// Construction and assignment are allowed from other classes that
717
    /// appear to be equivalent vector types, provided that they have either
718
    /// a subscripting operator, or data members .x, .y, .z, .w that are of
719
    /// the same type as the elements of this vector, and their size appears
720
    /// to be the right number of elements.
721
    ///
722
    /// This functionality is disabled for gcc 4.x, which seems to have a
723
    /// compiler bug that results in spurious errors. It can also be
724
    /// disabled by defining IMATH_FOREIGN_VECTOR_INTEROP to be 0 prior to
725
    /// including any Imath header files.
726
    ///
727
728
    template <typename V, IMATH_ENABLE_IF (has_xyzw<V, T>::value)>
729
    IMATH_HOSTDEVICE explicit constexpr Vec4 (const V& v) IMATH_NOEXCEPT
730
        : Vec4 (T (v.x), T (v.y), T (v.z), T (v.w))
731
    {}
732
733
    template <
734
        typename V,
735
        IMATH_ENABLE_IF (
736
            has_subscript<V, T, 4>::value && !has_xyzw<V, T>::value)>
737
    IMATH_HOSTDEVICE explicit Vec4 (const V& v)
738
        : Vec4 (T (v[0]), T (v[1]), T (v[2]), T (v[3]))
739
    {}
740
741
    template <typename V, IMATH_ENABLE_IF (has_xyzw<V, T>::value)>
742
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4&
743
    operator= (const V& v) IMATH_NOEXCEPT
744
    {
745
        x = T (v.x);
746
        y = T (v.y);
747
        z = T (v.z);
748
        w = T (v.w);
749
        return *this;
750
    }
751
752
    template <
753
        typename V,
754
        IMATH_ENABLE_IF (
755
            has_subscript<V, T, 4>::value && !has_xyzw<V, T>::value)>
756
    IMATH_HOSTDEVICE const Vec4& operator= (const V& v)
757
    {
758
        x = T (v[0]);
759
        y = T (v[1]);
760
        z = T (v[2]);
761
        w = T (v[3]);
762
        return *this;
763
    }
764
    /// @}
765
#endif
766
767
    /// @{
768
    /// @name Arithmetic and Comparison
769
770
    /// Equality
771
    template <class S>
772
    IMATH_HOSTDEVICE constexpr bool
773
    operator== (const Vec4<S>& v) const IMATH_NOEXCEPT;
774
775
    /// Inequality
776
    template <class S>
777
    IMATH_HOSTDEVICE constexpr bool
778
    operator!= (const Vec4<S>& v) const IMATH_NOEXCEPT;
779
780
    /// Compare two matrices and test if they are "approximately equal":
781
    /// @return True if the coefficients of this and `m` are the same
782
    /// with an absolute error of no more than e, i.e., for all i, j:
783
    ///
784
    ///     abs (this[i][j] - m[i][j]) <= e
785
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool
786
    equalWithAbsError (const Vec4<T>& v, T e) const IMATH_NOEXCEPT;
787
788
    /// Compare two matrices and test if they are "approximately equal":
789
    /// @return True if the coefficients of this and m are the same with
790
    /// a relative error of no more than e, i.e., for all i, j:
791
    ///
792
    ///     abs (this[i] - v[i][j]) <= e * abs (this[i][j])
793
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool
794
    equalWithRelError (const Vec4<T>& v, T e) const IMATH_NOEXCEPT;
795
796
    /// Dot product
797
    IMATH_HOSTDEVICE constexpr T dot (const Vec4& v) const IMATH_NOEXCEPT;
798
799
    /// Dot product
800
    IMATH_HOSTDEVICE constexpr T operator^ (const Vec4& v) const IMATH_NOEXCEPT;
801
802
    /// Component-wise addition
803
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4&
804
    operator+= (const Vec4& v) IMATH_NOEXCEPT;
805
806
    /// Component-wise addition
807
    IMATH_HOSTDEVICE constexpr Vec4
808
    operator+ (const Vec4& v) const IMATH_NOEXCEPT;
809
810
    /// Component-wise subtraction
811
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4&
812
    operator-= (const Vec4& v) IMATH_NOEXCEPT;
813
814
    /// Component-wise subtraction
815
    IMATH_HOSTDEVICE constexpr Vec4
816
    operator- (const Vec4& v) const IMATH_NOEXCEPT;
817
818
    /// Component-wise multiplication by -1
819
    IMATH_HOSTDEVICE constexpr Vec4 operator- () const IMATH_NOEXCEPT;
820
821
    /// Component-wise multiplication by -1
822
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& negate () IMATH_NOEXCEPT;
823
824
    /// Component-wise multiplication
825
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4&
826
    operator*= (const Vec4& v) IMATH_NOEXCEPT;
827
828
    /// Component-wise multiplication
829
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4&
830
    operator*= (T a) IMATH_NOEXCEPT;
831
832
    /// Component-wise multiplication
833
    IMATH_HOSTDEVICE constexpr Vec4
834
    operator* (const Vec4& v) const IMATH_NOEXCEPT;
835
836
    /// Component-wise multiplication
837
    IMATH_HOSTDEVICE constexpr Vec4 operator* (T a) const IMATH_NOEXCEPT;
838
839
    /// Component-wise division
840
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4&
841
    operator/= (const Vec4& v) IMATH_NOEXCEPT;
842
843
    /// Component-wise division
844
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4&
845
    operator/= (T a) IMATH_NOEXCEPT;
846
847
    /// Component-wise division
848
    IMATH_HOSTDEVICE constexpr Vec4
849
    operator/ (const Vec4& v) const IMATH_NOEXCEPT;
850
851
    /// Component-wise division
852
    IMATH_HOSTDEVICE constexpr Vec4 operator/ (T a) const IMATH_NOEXCEPT;
853
854
    /// @}
855
856
    /// @{
857
    /// @name Query and Manipulation
858
859
    /// Return the Euclidean norm
860
    IMATH_HOSTDEVICE T length () const IMATH_NOEXCEPT;
861
862
    /// Return the square of the Euclidean norm, i.e. the dot product
863
    /// with itself.
864
    IMATH_HOSTDEVICE constexpr T length2 () const IMATH_NOEXCEPT;
865
866
    /// Normalize in place. If length()==0, return a null vector.
867
    IMATH_HOSTDEVICE const Vec4& normalize () IMATH_NOEXCEPT; // modifies *this
868
869
    /// Normalize in place. If length()==0, throw an exception.
870
    const Vec4& normalizeExc ();
871
872
    /// Normalize without any checks for length()==0. Slightly faster
873
    /// than the other normalization routines, but if v.length() is
874
    /// 0.0, the result is undefined.
875
    IMATH_HOSTDEVICE const Vec4& normalizeNonNull () IMATH_NOEXCEPT;
876
877
    /// Return a normalized vector. Does not modify *this.
878
    IMATH_HOSTDEVICE Vec4<T>
879
    normalized () const IMATH_NOEXCEPT; // does not modify *this
880
881
    /// Return a normalized vector. Does not modify *this. Throw an
882
    /// exception if length()==0.
883
    Vec4<T> normalizedExc () const;
884
885
    /// Return a normalized vector. Does not modify *this, and does
886
    /// not check for length()==0. Slightly faster than the other
887
    /// normalization routines, but if v.length() is 0.0, the result
888
    /// is undefined.
889
    IMATH_HOSTDEVICE Vec4<T> normalizedNonNull () const IMATH_NOEXCEPT;
890
891
    /// @}
892
893
    /// @{
894
    /// @name Numeric Limits
895
896
    /// Largest possible negative value
897
    IMATH_HOSTDEVICE constexpr static T baseTypeLowest () IMATH_NOEXCEPT
898
    {
899
        return std::numeric_limits<T>::lowest ();
900
    }
901
902
    /// Largest possible positive value
903
    IMATH_HOSTDEVICE constexpr static T baseTypeMax () IMATH_NOEXCEPT
904
    {
905
        return std::numeric_limits<T>::max ();
906
    }
907
908
    /// Smallest possible positive value
909
    IMATH_HOSTDEVICE constexpr static T baseTypeSmallest () IMATH_NOEXCEPT
910
    {
911
        return std::numeric_limits<T>::min ();
912
    }
913
914
    /// Smallest possible e for which 1+e != 1
915
    IMATH_HOSTDEVICE constexpr static T baseTypeEpsilon () IMATH_NOEXCEPT
916
    {
917
        return std::numeric_limits<T>::epsilon ();
918
    }
919
920
    /// @}
921
922
    /// Return the number of dimensions, i.e. 4
923
    IMATH_HOSTDEVICE constexpr static unsigned int dimensions () IMATH_NOEXCEPT
924
    {
925
        return 4;
926
    }
927
928
    /// The base type: In templates that accept a parameter `V`, you
929
    /// can refer to `T` as `V::BaseType`
930
    typedef T BaseType;
931
932
private:
933
    IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T lengthTiny () const IMATH_NOEXCEPT;
934
};
935
936
/// Stream output, as "(x y)"
937
template <class T> std::ostream& operator<< (std::ostream& s, const Vec2<T>& v);
938
939
/// Stream output, as "(x y z)"
940
template <class T> std::ostream& operator<< (std::ostream& s, const Vec3<T>& v);
941
942
/// Stream output, as "(x y z w)"
943
template <class T> std::ostream& operator<< (std::ostream& s, const Vec4<T>& v);
944
945
/// Reverse multiplication: S * Vec2<T>
946
template <class T>
947
IMATH_HOSTDEVICE constexpr Vec2<T>
948
operator* (T a, const Vec2<T>& v) IMATH_NOEXCEPT;
949
950
/// Reverse multiplication: S * Vec3<T>
951
template <class T>
952
IMATH_HOSTDEVICE constexpr Vec3<T>
953
operator* (T a, const Vec3<T>& v) IMATH_NOEXCEPT;
954
955
/// Reverse multiplication: S * Vec4<T>
956
template <class T>
957
IMATH_HOSTDEVICE constexpr Vec4<T>
958
operator* (T a, const Vec4<T>& v) IMATH_NOEXCEPT;
959
960
//-------------------------
961
// Typedefs for convenience
962
//-------------------------
963
964
/// Vec2 of short
965
typedef Vec2<short> V2s;
966
967
/// Vec2 of integer
968
typedef Vec2<int> V2i;
969
970
/// Vec2 of int64_t
971
typedef Vec2<int64_t> V2i64;
972
973
/// Vec2 of float
974
typedef Vec2<float> V2f;
975
976
/// Vec2 of double
977
typedef Vec2<double> V2d;
978
979
/// Vec3 of short
980
typedef Vec3<short> V3s;
981
982
/// Vec3 of integer
983
typedef Vec3<int> V3i;
984
985
/// Vec3 of int64_t
986
typedef Vec3<int64_t> V3i64;
987
988
/// Vec3 of float
989
typedef Vec3<float> V3f;
990
991
/// Vec3 of double
992
typedef Vec3<double> V3d;
993
994
/// Vec4 of short
995
typedef Vec4<short> V4s;
996
997
/// Vec4 of integer
998
typedef Vec4<int> V4i;
999
1000
/// Vec4 of int64_t
1001
typedef Vec4<int64_t> V4i64;
1002
1003
/// Vec4 of float
1004
typedef Vec4<float> V4f;
1005
1006
/// Vec4 of double
1007
typedef Vec4<double> V4d;
1008
1009
//----------------------------------------------------------------------------
1010
// Specializations for VecN<short>, VecN<int>
1011
//
1012
// Normalize and length don't make sense for integer vectors, so disable them.
1013
//----------------------------------------------------------------------------
1014
1015
/// @cond Doxygen_Suppress
1016
1017
// Vec2<short>
1018
template <>
1019
IMATH_HOSTDEVICE short Vec2<short>::length () const IMATH_NOEXCEPT = delete;
1020
template <>
1021
IMATH_HOSTDEVICE const Vec2<short>&
1022
                       Vec2<short>::normalize () IMATH_NOEXCEPT = delete;
1023
template <> const Vec2<short>& Vec2<short>::normalizeExc ()     = delete;
1024
template <>
1025
IMATH_HOSTDEVICE const Vec2<short>&
1026
                       Vec2<short>::normalizeNonNull () IMATH_NOEXCEPT = delete;
1027
template <>
1028
IMATH_HOSTDEVICE Vec2<short>
1029
                 Vec2<short>::normalized () const IMATH_NOEXCEPT = delete;
1030
template <> Vec2<short> Vec2<short>::normalizedExc () const      = delete;
1031
template <>
1032
IMATH_HOSTDEVICE Vec2<short>
1033
Vec2<short>::normalizedNonNull () const IMATH_NOEXCEPT = delete;
1034
1035
// Vec2<int>
1036
template <>
1037
IMATH_HOSTDEVICE int Vec2<int>::length () const IMATH_NOEXCEPT = delete;
1038
template <>
1039
IMATH_HOSTDEVICE const       Vec2<int>&
1040
                             Vec2<int>::normalize () IMATH_NOEXCEPT = delete;
1041
template <> const Vec2<int>& Vec2<int>::normalizeExc ()             = delete;
1042
template <>
1043
IMATH_HOSTDEVICE const Vec2<int>&
1044
                       Vec2<int>::normalizeNonNull () IMATH_NOEXCEPT = delete;
1045
template <>
1046
IMATH_HOSTDEVICE      Vec2<int>
1047
                      Vec2<int>::normalized () const IMATH_NOEXCEPT = delete;
1048
template <> Vec2<int> Vec2<int>::normalizedExc () const             = delete;
1049
template <>
1050
IMATH_HOSTDEVICE Vec2<int>
1051
                 Vec2<int>::normalizedNonNull () const IMATH_NOEXCEPT = delete;
1052
1053
// Vec2<int64_t>
1054
template <>
1055
IMATH_HOSTDEVICE int64_t Vec2<int64_t>::length () const IMATH_NOEXCEPT = delete;
1056
template <>
1057
IMATH_HOSTDEVICE const Vec2<int64_t>&
1058
                       Vec2<int64_t>::normalize () IMATH_NOEXCEPT = delete;
1059
template <> const Vec2<int64_t>& Vec2<int64_t>::normalizeExc ()   = delete;
1060
template <>
1061
IMATH_HOSTDEVICE const Vec2<int64_t>&
1062
Vec2<int64_t>::normalizeNonNull () IMATH_NOEXCEPT = delete;
1063
template <>
1064
IMATH_HOSTDEVICE Vec2<int64_t>
1065
                 Vec2<int64_t>::normalized () const IMATH_NOEXCEPT = delete;
1066
template <> Vec2<int64_t> Vec2<int64_t>::normalizedExc () const    = delete;
1067
template <>
1068
IMATH_HOSTDEVICE Vec2<int64_t>
1069
Vec2<int64_t>::normalizedNonNull () const IMATH_NOEXCEPT = delete;
1070
1071
// Vec3<short>
1072
template <>
1073
IMATH_HOSTDEVICE short Vec3<short>::length () const IMATH_NOEXCEPT = delete;
1074
template <>
1075
IMATH_HOSTDEVICE const Vec3<short>&
1076
                       Vec3<short>::normalize () IMATH_NOEXCEPT = delete;
1077
template <> const Vec3<short>& Vec3<short>::normalizeExc ()     = delete;
1078
template <>
1079
IMATH_HOSTDEVICE const Vec3<short>&
1080
                       Vec3<short>::normalizeNonNull () IMATH_NOEXCEPT = delete;
1081
template <>
1082
IMATH_HOSTDEVICE Vec3<short>
1083
                 Vec3<short>::normalized () const IMATH_NOEXCEPT = delete;
1084
template <> Vec3<short> Vec3<short>::normalizedExc () const      = delete;
1085
template <>
1086
IMATH_HOSTDEVICE Vec3<short>
1087
Vec3<short>::normalizedNonNull () const IMATH_NOEXCEPT = delete;
1088
1089
// Vec3<int>
1090
template <>
1091
IMATH_HOSTDEVICE int Vec3<int>::length () const IMATH_NOEXCEPT = delete;
1092
template <>
1093
IMATH_HOSTDEVICE const       Vec3<int>&
1094
                             Vec3<int>::normalize () IMATH_NOEXCEPT = delete;
1095
template <> const Vec3<int>& Vec3<int>::normalizeExc ()             = delete;
1096
template <>
1097
IMATH_HOSTDEVICE const Vec3<int>&
1098
                       Vec3<int>::normalizeNonNull () IMATH_NOEXCEPT = delete;
1099
template <>
1100
IMATH_HOSTDEVICE      Vec3<int>
1101
                      Vec3<int>::normalized () const IMATH_NOEXCEPT = delete;
1102
template <> Vec3<int> Vec3<int>::normalizedExc () const             = delete;
1103
template <>
1104
IMATH_HOSTDEVICE Vec3<int>
1105
                 Vec3<int>::normalizedNonNull () const IMATH_NOEXCEPT = delete;
1106
1107
// Vec3<int64_t>
1108
template <>
1109
IMATH_HOSTDEVICE int64_t Vec3<int64_t>::length () const IMATH_NOEXCEPT = delete;
1110
template <>
1111
IMATH_HOSTDEVICE const Vec3<int64_t>&
1112
                       Vec3<int64_t>::normalize () IMATH_NOEXCEPT = delete;
1113
template <> const Vec3<int64_t>& Vec3<int64_t>::normalizeExc ()   = delete;
1114
template <>
1115
IMATH_HOSTDEVICE const Vec3<int64_t>&
1116
Vec3<int64_t>::normalizeNonNull () IMATH_NOEXCEPT = delete;
1117
template <>
1118
IMATH_HOSTDEVICE Vec3<int64_t>
1119
                 Vec3<int64_t>::normalized () const IMATH_NOEXCEPT = delete;
1120
template <> Vec3<int64_t> Vec3<int64_t>::normalizedExc () const    = delete;
1121
template <>
1122
IMATH_HOSTDEVICE Vec3<int64_t>
1123
Vec3<int64_t>::normalizedNonNull () const IMATH_NOEXCEPT = delete;
1124
1125
// Vec4<short>
1126
template <>
1127
IMATH_HOSTDEVICE short Vec4<short>::length () const IMATH_NOEXCEPT = delete;
1128
template <>
1129
IMATH_HOSTDEVICE const Vec4<short>&
1130
                       Vec4<short>::normalize () IMATH_NOEXCEPT = delete;
1131
template <> const Vec4<short>& Vec4<short>::normalizeExc ()     = delete;
1132
template <>
1133
IMATH_HOSTDEVICE const Vec4<short>&
1134
                       Vec4<short>::normalizeNonNull () IMATH_NOEXCEPT = delete;
1135
template <>
1136
IMATH_HOSTDEVICE Vec4<short>
1137
                 Vec4<short>::normalized () const IMATH_NOEXCEPT = delete;
1138
template <> Vec4<short> Vec4<short>::normalizedExc () const      = delete;
1139
template <>
1140
IMATH_HOSTDEVICE Vec4<short>
1141
Vec4<short>::normalizedNonNull () const IMATH_NOEXCEPT = delete;
1142
1143
// Vec4<int>
1144
template <>
1145
IMATH_HOSTDEVICE int Vec4<int>::length () const IMATH_NOEXCEPT = delete;
1146
template <>
1147
IMATH_HOSTDEVICE const       Vec4<int>&
1148
                             Vec4<int>::normalize () IMATH_NOEXCEPT = delete;
1149
template <> const Vec4<int>& Vec4<int>::normalizeExc ()             = delete;
1150
template <>
1151
IMATH_HOSTDEVICE const Vec4<int>&
1152
                       Vec4<int>::normalizeNonNull () IMATH_NOEXCEPT = delete;
1153
template <>
1154
IMATH_HOSTDEVICE      Vec4<int>
1155
                      Vec4<int>::normalized () const IMATH_NOEXCEPT = delete;
1156
template <> Vec4<int> Vec4<int>::normalizedExc () const             = delete;
1157
template <>
1158
IMATH_HOSTDEVICE Vec4<int>
1159
                 Vec4<int>::normalizedNonNull () const IMATH_NOEXCEPT = delete;
1160
1161
// Vec4<int64_t>
1162
template <>
1163
IMATH_HOSTDEVICE int64_t Vec4<int64_t>::length () const IMATH_NOEXCEPT = delete;
1164
template <>
1165
IMATH_HOSTDEVICE const Vec4<int64_t>&
1166
                       Vec4<int64_t>::normalize () IMATH_NOEXCEPT = delete;
1167
template <> const Vec4<int64_t>& Vec4<int64_t>::normalizeExc ()   = delete;
1168
template <>
1169
IMATH_HOSTDEVICE const Vec4<int64_t>&
1170
Vec4<int64_t>::normalizeNonNull () IMATH_NOEXCEPT = delete;
1171
template <>
1172
IMATH_HOSTDEVICE Vec4<int64_t>
1173
                 Vec4<int64_t>::normalized () const IMATH_NOEXCEPT = delete;
1174
template <> Vec4<int64_t> Vec4<int64_t>::normalizedExc () const    = delete;
1175
template <>
1176
IMATH_HOSTDEVICE Vec4<int64_t>
1177
Vec4<int64_t>::normalizedNonNull () const IMATH_NOEXCEPT = delete;
1178
1179
/// @endcond Doxygen_Suppress
1180
1181
//------------------------
1182
// Implementation of Vec2:
1183
//------------------------
1184
1185
template <class T>
1186
IMATH_CONSTEXPR14 IMATH_HOSTDEVICE inline T&
1187
Vec2<T>::operator[] (int i) IMATH_NOEXCEPT
1188
158k
{
1189
158k
    return (&x)[i]; // NOSONAR - suppress SonarCloud bug report.
1190
158k
}
1191
1192
template <class T>
1193
constexpr IMATH_HOSTDEVICE inline const T&
1194
Vec2<T>::operator[] (int i) const IMATH_NOEXCEPT
1195
11.1k
{
1196
11.1k
    return (&x)[i]; // NOSONAR - suppress SonarCloud bug report.
1197
11.1k
}
1198
1199
template <class T> IMATH_HOSTDEVICE inline Vec2<T>::Vec2 () IMATH_NOEXCEPT
1200
1.41M
{
1201
    // empty, and not constexpr because data is uninitialized.
1202
1.41M
}
Imath_3_2::Vec2<int>::Vec2()
Line
Count
Source
1200
1.21M
{
1201
    // empty, and not constexpr because data is uninitialized.
1202
1.21M
}
Imath_3_2::Vec2<float>::Vec2()
Line
Count
Source
1200
198k
{
1201
    // empty, and not constexpr because data is uninitialized.
1202
198k
}
Imath_3_2::Vec2<double>::Vec2()
Line
Count
Source
1200
1.90k
{
1201
    // empty, and not constexpr because data is uninitialized.
1202
1.90k
}
1203
1204
template <class T>
1205
IMATH_HOSTDEVICE constexpr inline Vec2<T>::Vec2 (T a) IMATH_NOEXCEPT : x (a),
1206
                                                                       y (a)
1207
809k
{}
Imath_3_2::Vec2<int>::Vec2(int)
Line
Count
Source
1207
806k
{}
Imath_3_2::Vec2<float>::Vec2(float)
Line
Count
Source
1207
2.39k
{}
1208
1209
template <class T>
1210
IMATH_HOSTDEVICE constexpr inline Vec2<T>::Vec2 (T a, T b) IMATH_NOEXCEPT
1211
    : x (a),
1212
      y (b)
1213
571k
{}
Imath_3_2::Vec2<int>::Vec2(int, int)
Line
Count
Source
1213
478k
{}
Imath_3_2::Vec2<float>::Vec2(float, float)
Line
Count
Source
1213
93.7k
{}
1214
1215
template <class T>
1216
IMATH_HOSTDEVICE constexpr inline Vec2<T>::Vec2 (const Vec2& v) IMATH_NOEXCEPT
1217
    : x (v.x),
1218
      y (v.y)
1219
524k
{}
Imath_3_2::Vec2<int>::Vec2(Imath_3_2::Vec2<int> const&)
Line
Count
Source
1219
430k
{}
Imath_3_2::Vec2<float>::Vec2(Imath_3_2::Vec2<float> const&)
Line
Count
Source
1219
93.7k
{}
Unexecuted instantiation: Imath_3_2::Vec2<double>::Vec2(Imath_3_2::Vec2<double> const&)
1220
1221
template <class T>
1222
template <class S>
1223
IMATH_HOSTDEVICE constexpr inline Vec2<T>::Vec2 (const Vec2<S>& v)
1224
    IMATH_NOEXCEPT : x (T (v.x)),
1225
                     y (T (v.y))
1226
{}
1227
1228
template <class T>
1229
IMATH_CONSTEXPR14 IMATH_HOSTDEVICE inline const Vec2<T>&
1230
Vec2<T>::operator= (const Vec2& v) IMATH_NOEXCEPT
1231
2.21M
{
1232
2.21M
    x = v.x;
1233
2.21M
    y = v.y;
1234
2.21M
    return *this;
1235
2.21M
}
Imath_3_2::Vec2<int>::operator=(Imath_3_2::Vec2<int> const&)
Line
Count
Source
1231
2.01M
{
1232
2.01M
    x = v.x;
1233
2.01M
    y = v.y;
1234
2.01M
    return *this;
1235
2.01M
}
Imath_3_2::Vec2<float>::operator=(Imath_3_2::Vec2<float> const&)
Line
Count
Source
1231
203k
{
1232
203k
    x = v.x;
1233
203k
    y = v.y;
1234
203k
    return *this;
1235
203k
}
Imath_3_2::Vec2<double>::operator=(Imath_3_2::Vec2<double> const&)
Line
Count
Source
1231
1.24k
{
1232
1.24k
    x = v.x;
1233
1.24k
    y = v.y;
1234
1.24k
    return *this;
1235
1.24k
}
1236
1237
template <class T>
1238
template <class S>
1239
IMATH_HOSTDEVICE inline void
1240
Vec2<T>::setValue (S a, S b) IMATH_NOEXCEPT
1241
{
1242
    x = T (a);
1243
    y = T (b);
1244
}
1245
1246
template <class T>
1247
template <class S>
1248
IMATH_HOSTDEVICE inline void
1249
Vec2<T>::setValue (const Vec2<S>& v) IMATH_NOEXCEPT
1250
{
1251
    x = T (v.x);
1252
    y = T (v.y);
1253
}
1254
1255
template <class T>
1256
template <class S>
1257
IMATH_HOSTDEVICE inline void
1258
Vec2<T>::getValue (S& a, S& b) const IMATH_NOEXCEPT
1259
{
1260
    a = S (x);
1261
    b = S (y);
1262
}
1263
1264
template <class T>
1265
template <class S>
1266
IMATH_HOSTDEVICE inline void
1267
Vec2<T>::getValue (Vec2<S>& v) const IMATH_NOEXCEPT
1268
{
1269
    v.x = S (x);
1270
    v.y = S (y);
1271
}
1272
1273
template <class T>
1274
IMATH_HOSTDEVICE inline T*
1275
Vec2<T>::getValue () IMATH_NOEXCEPT
1276
{
1277
    return (T*) &x;
1278
}
1279
1280
template <class T>
1281
IMATH_HOSTDEVICE inline const T*
1282
Vec2<T>::getValue () const IMATH_NOEXCEPT
1283
{
1284
    return (const T*) &x;
1285
}
1286
1287
template <class T>
1288
template <class S>
1289
IMATH_HOSTDEVICE constexpr inline bool
1290
Vec2<T>::operator== (const Vec2<S>& v) const IMATH_NOEXCEPT
1291
0
{
1292
0
    return x == v.x && y == v.y;
1293
0
}
Unexecuted instantiation: bool Imath_3_2::Vec2<float>::operator==<float>(Imath_3_2::Vec2<float> const&) const
Unexecuted instantiation: bool Imath_3_2::Vec2<int>::operator==<int>(Imath_3_2::Vec2<int> const&) const
1294
1295
template <class T>
1296
template <class S>
1297
IMATH_HOSTDEVICE constexpr inline bool
1298
Vec2<T>::operator!= (const Vec2<S>& v) const IMATH_NOEXCEPT
1299
27.8k
{
1300
27.8k
    return x != v.x || y != v.y;
1301
27.8k
}
bool Imath_3_2::Vec2<int>::operator!=<int>(Imath_3_2::Vec2<int> const&) const
Line
Count
Source
1299
27.7k
{
1300
27.7k
    return x != v.x || y != v.y;
1301
27.7k
}
bool Imath_3_2::Vec2<float>::operator!=<float>(Imath_3_2::Vec2<float> const&) const
Line
Count
Source
1299
61
{
1300
61
    return x != v.x || y != v.y;
1301
61
}
1302
1303
template <class T>
1304
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool
1305
Vec2<T>::equalWithAbsError (const Vec2<T>& v, T e) const IMATH_NOEXCEPT
1306
{
1307
    for (int i = 0; i < 2; i++)
1308
        if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i], v[i], e))
1309
            return false;
1310
1311
    return true;
1312
}
1313
1314
template <class T>
1315
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool
1316
Vec2<T>::equalWithRelError (const Vec2<T>& v, T e) const IMATH_NOEXCEPT
1317
{
1318
    for (int i = 0; i < 2; i++)
1319
        if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i], v[i], e))
1320
            return false;
1321
1322
    return true;
1323
}
1324
1325
template <class T>
1326
IMATH_HOSTDEVICE constexpr inline T
1327
Vec2<T>::dot (const Vec2& v) const IMATH_NOEXCEPT
1328
{
1329
    return x * v.x + y * v.y;
1330
}
1331
1332
template <class T>
1333
IMATH_HOSTDEVICE constexpr inline T
1334
Vec2<T>::operator^ (const Vec2& v) const IMATH_NOEXCEPT
1335
{
1336
    return dot (v);
1337
}
1338
1339
template <class T>
1340
IMATH_HOSTDEVICE constexpr inline T
1341
Vec2<T>::cross (const Vec2& v) const IMATH_NOEXCEPT
1342
{
1343
    return x * v.y - y * v.x;
1344
}
1345
1346
template <class T>
1347
IMATH_HOSTDEVICE constexpr inline T
1348
Vec2<T>::operator% (const Vec2& v) const IMATH_NOEXCEPT
1349
{
1350
    return x * v.y - y * v.x;
1351
}
1352
1353
template <class T>
1354
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2<T>&
1355
Vec2<T>::operator+= (const Vec2& v) IMATH_NOEXCEPT
1356
{
1357
    x += v.x;
1358
    y += v.y;
1359
    return *this;
1360
}
1361
1362
template <class T>
1363
IMATH_HOSTDEVICE constexpr inline Vec2<T>
1364
Vec2<T>::operator+ (const Vec2& v) const IMATH_NOEXCEPT
1365
72.7k
{
1366
72.7k
    return Vec2 (x + v.x, y + v.y);
1367
72.7k
}
1368
1369
template <class T>
1370
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2<T>&
1371
Vec2<T>::operator-= (const Vec2& v) IMATH_NOEXCEPT
1372
{
1373
    x -= v.x;
1374
    y -= v.y;
1375
    return *this;
1376
}
1377
1378
template <class T>
1379
IMATH_HOSTDEVICE constexpr inline Vec2<T>
1380
Vec2<T>::operator- (const Vec2& v) const IMATH_NOEXCEPT
1381
2.79k
{
1382
2.79k
    return Vec2 (x - v.x, y - v.y);
1383
2.79k
}
1384
1385
template <class T>
1386
IMATH_HOSTDEVICE constexpr inline Vec2<T>
1387
Vec2<T>::operator- () const IMATH_NOEXCEPT
1388
{
1389
    return Vec2 (-x, -y);
1390
}
1391
1392
template <class T>
1393
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2<T>&
1394
                 Vec2<T>::negate () IMATH_NOEXCEPT
1395
{
1396
    x = -x;
1397
    y = -y;
1398
    return *this;
1399
}
1400
1401
template <class T>
1402
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2<T>&
1403
Vec2<T>::operator*= (const Vec2& v) IMATH_NOEXCEPT
1404
{
1405
    x *= v.x;
1406
    y *= v.y;
1407
    return *this;
1408
}
1409
1410
template <class T>
1411
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2<T>&
1412
Vec2<T>::operator*= (T a) IMATH_NOEXCEPT
1413
{
1414
    x *= a;
1415
    y *= a;
1416
    return *this;
1417
}
1418
1419
template <class T>
1420
IMATH_HOSTDEVICE constexpr inline Vec2<T>
1421
Vec2<T>::operator* (const Vec2& v) const IMATH_NOEXCEPT
1422
{
1423
    return Vec2 (x * v.x, y * v.y);
1424
}
1425
1426
template <class T>
1427
IMATH_HOSTDEVICE constexpr inline Vec2<T>
1428
Vec2<T>::operator* (T a) const IMATH_NOEXCEPT
1429
{
1430
    return Vec2 (x * a, y * a);
1431
}
1432
1433
template <class T>
1434
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2<T>&
1435
Vec2<T>::operator/= (const Vec2& v) IMATH_NOEXCEPT
1436
{
1437
    x /= v.x;
1438
    y /= v.y;
1439
    return *this;
1440
}
1441
1442
template <class T>
1443
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec2<T>&
1444
Vec2<T>::operator/= (T a) IMATH_NOEXCEPT
1445
{
1446
    x /= a;
1447
    y /= a;
1448
    return *this;
1449
}
1450
1451
template <class T>
1452
IMATH_HOSTDEVICE constexpr inline Vec2<T>
1453
Vec2<T>::operator/ (const Vec2& v) const IMATH_NOEXCEPT
1454
{
1455
    return Vec2 (x / v.x, y / v.y);
1456
}
1457
1458
template <class T>
1459
IMATH_HOSTDEVICE constexpr inline Vec2<T>
1460
Vec2<T>::operator/ (T a) const IMATH_NOEXCEPT
1461
{
1462
    return Vec2 (x / a, y / a);
1463
}
1464
1465
template <class T>
1466
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline T
1467
Vec2<T>::lengthTiny () const IMATH_NOEXCEPT
1468
{
1469
    T absX = std::abs (x);
1470
    T absY = std::abs (y);
1471
1472
    T max = absX;
1473
1474
    if (max < absY) max = absY;
1475
1476
    if (IMATH_UNLIKELY (max == T (0))) return T (0);
1477
1478
    //
1479
    // Do not replace the divisions by max with multiplications by 1/max.
1480
    // Computing 1/max can overflow but the divisions below will always
1481
    // produce results less than or equal to 1.
1482
    //
1483
1484
    absX /= max;
1485
    absY /= max;
1486
1487
    return max * std::sqrt (absX * absX + absY * absY);
1488
}
1489
1490
template <class T>
1491
IMATH_HOSTDEVICE inline T
1492
Vec2<T>::length () const IMATH_NOEXCEPT
1493
{
1494
    T length2 = dot (*this);
1495
1496
    if (IMATH_UNLIKELY (length2 < T (2) * std::numeric_limits<T>::min ()))
1497
        return lengthTiny ();
1498
1499
    return std::sqrt (length2);
1500
}
1501
1502
template <class T>
1503
IMATH_HOSTDEVICE constexpr inline T
1504
Vec2<T>::length2 () const IMATH_NOEXCEPT
1505
{
1506
    return dot (*this);
1507
}
1508
1509
template <class T>
1510
IMATH_HOSTDEVICE inline const Vec2<T>&
1511
Vec2<T>::normalize () IMATH_NOEXCEPT
1512
{
1513
    T l = length ();
1514
1515
    if (IMATH_LIKELY (l != T (0)))
1516
    {
1517
        //
1518
        // Do not replace the divisions by l with multiplications by 1/l.
1519
        // Computing 1/l can overflow but the divisions below will always
1520
        // produce results less than or equal to 1.
1521
        //
1522
1523
        x /= l;
1524
        y /= l;
1525
    }
1526
1527
    return *this;
1528
}
1529
1530
template <class T>
1531
inline const Vec2<T>&
1532
Vec2<T>::normalizeExc ()
1533
{
1534
    T l = length ();
1535
1536
    if (IMATH_UNLIKELY (l == T (0)))
1537
        throw std::domain_error ("Cannot normalize null vector.");
1538
1539
    x /= l;
1540
    y /= l;
1541
    return *this;
1542
}
1543
1544
template <class T>
1545
IMATH_HOSTDEVICE inline const Vec2<T>&
1546
Vec2<T>::normalizeNonNull () IMATH_NOEXCEPT
1547
{
1548
    T l = length ();
1549
    x /= l;
1550
    y /= l;
1551
    return *this;
1552
}
1553
1554
template <class T>
1555
IMATH_HOSTDEVICE inline Vec2<T>
1556
Vec2<T>::normalized () const IMATH_NOEXCEPT
1557
{
1558
    T l = length ();
1559
1560
    if (IMATH_UNLIKELY (l == T (0))) return Vec2 (T (0));
1561
1562
    return Vec2 (x / l, y / l);
1563
}
1564
1565
template <class T>
1566
inline Vec2<T>
1567
Vec2<T>::normalizedExc () const
1568
{
1569
    T l = length ();
1570
1571
    if (IMATH_UNLIKELY (l == T (0)))
1572
        throw std::domain_error ("Cannot normalize null vector.");
1573
1574
    return Vec2 (x / l, y / l);
1575
}
1576
1577
template <class T>
1578
IMATH_HOSTDEVICE inline Vec2<T>
1579
Vec2<T>::normalizedNonNull () const IMATH_NOEXCEPT
1580
{
1581
    T l = length ();
1582
    return Vec2 (x / l, y / l);
1583
}
1584
1585
//-----------------------
1586
// Implementation of Vec3
1587
//-----------------------
1588
1589
template <class T>
1590
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline T&
1591
Vec3<T>::operator[] (int i) IMATH_NOEXCEPT
1592
{
1593
    return (&x)[i]; // NOSONAR - suppress SonarCloud bug report.
1594
}
1595
1596
template <class T>
1597
IMATH_HOSTDEVICE constexpr inline const T&
1598
Vec3<T>::operator[] (int i) const IMATH_NOEXCEPT
1599
{
1600
    return (&x)[i]; // NOSONAR - suppress SonarCloud bug report.
1601
}
1602
1603
template <class T> IMATH_HOSTDEVICE inline Vec3<T>::Vec3 () IMATH_NOEXCEPT
1604
7.83k
{
1605
    // empty, and not constexpr because data is uninitialized.
1606
7.83k
}
Imath_3_2::Vec3<float>::Vec3()
Line
Count
Source
1604
4.74k
{
1605
    // empty, and not constexpr because data is uninitialized.
1606
4.74k
}
Imath_3_2::Vec3<int>::Vec3()
Line
Count
Source
1604
1.29k
{
1605
    // empty, and not constexpr because data is uninitialized.
1606
1.29k
}
Imath_3_2::Vec3<double>::Vec3()
Line
Count
Source
1604
1.79k
{
1605
    // empty, and not constexpr because data is uninitialized.
1606
1.79k
}
1607
1608
template <class T>
1609
IMATH_HOSTDEVICE constexpr inline Vec3<T>::Vec3 (T a) IMATH_NOEXCEPT : x (a),
1610
                                                                       y (a),
1611
                                                                       z (a)
1612
{}
1613
1614
template <class T>
1615
IMATH_HOSTDEVICE constexpr inline Vec3<T>::Vec3 (T a, T b, T c) IMATH_NOEXCEPT
1616
    : x (a),
1617
      y (b),
1618
      z (c)
1619
0
{}
1620
1621
template <class T>
1622
IMATH_HOSTDEVICE constexpr inline Vec3<T>::Vec3 (const Vec3& v) IMATH_NOEXCEPT
1623
    : x (v.x),
1624
      y (v.y),
1625
      z (v.z)
1626
0
{}
Unexecuted instantiation: Imath_3_2::Vec3<int>::Vec3(Imath_3_2::Vec3<int> const&)
Unexecuted instantiation: Imath_3_2::Vec3<float>::Vec3(Imath_3_2::Vec3<float> const&)
Unexecuted instantiation: Imath_3_2::Vec3<double>::Vec3(Imath_3_2::Vec3<double> const&)
1627
1628
template <class T>
1629
template <class S>
1630
IMATH_HOSTDEVICE constexpr inline Vec3<T>::Vec3 (const Vec3<S>& v)
1631
    IMATH_NOEXCEPT : x (T (v.x)),
1632
                     y (T (v.y)),
1633
                     z (T (v.z))
1634
{}
1635
1636
template <class T>
1637
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1638
Vec3<T>::operator= (const Vec3& v) IMATH_NOEXCEPT
1639
5.37k
{
1640
5.37k
    x = v.x;
1641
5.37k
    y = v.y;
1642
5.37k
    z = v.z;
1643
5.37k
    return *this;
1644
5.37k
}
Imath_3_2::Vec3<float>::operator=(Imath_3_2::Vec3<float> const&)
Line
Count
Source
1639
3.31k
{
1640
3.31k
    x = v.x;
1641
3.31k
    y = v.y;
1642
3.31k
    z = v.z;
1643
3.31k
    return *this;
1644
3.31k
}
Imath_3_2::Vec3<int>::operator=(Imath_3_2::Vec3<int> const&)
Line
Count
Source
1639
783
{
1640
783
    x = v.x;
1641
783
    y = v.y;
1642
783
    z = v.z;
1643
783
    return *this;
1644
783
}
Imath_3_2::Vec3<double>::operator=(Imath_3_2::Vec3<double> const&)
Line
Count
Source
1639
1.27k
{
1640
1.27k
    x = v.x;
1641
1.27k
    y = v.y;
1642
1.27k
    z = v.z;
1643
1.27k
    return *this;
1644
1.27k
}
1645
1646
template <class T>
1647
template <class S>
1648
IMATH_HOSTDEVICE constexpr inline Vec3<T>::Vec3 (const Vec4<S>& v)
1649
    IMATH_NOEXCEPT : x (T (v.x / v.w)),
1650
                     y (T (v.y / v.w)),
1651
                     z (T (v.z / v.w))
1652
{}
1653
1654
template <class T>
1655
template <class S>
1656
IMATH_HOSTDEVICE
1657
    IMATH_CONSTEXPR14 inline Vec3<T>::Vec3 (const Vec4<S>& v, InfException)
1658
{
1659
    T vx = T (v.x);
1660
    T vy = T (v.y);
1661
    T vz = T (v.z);
1662
    T vw = T (v.w);
1663
1664
    T absW = (vw >= T (0)) ? vw : -vw;
1665
1666
    if (absW < 1)
1667
    {
1668
        T m = baseTypeMax () * absW;
1669
1670
        if (vx <= -m || vx >= m || vy <= -m || vy >= m || vz <= -m || vz >= m)
1671
            throw std::domain_error ("Cannot normalize point at infinity.");
1672
    }
1673
1674
    x = vx / vw;
1675
    y = vy / vw;
1676
    z = vz / vw;
1677
}
1678
1679
template <class T>
1680
template <class S>
1681
IMATH_HOSTDEVICE inline void
1682
Vec3<T>::setValue (S a, S b, S c) IMATH_NOEXCEPT
1683
{
1684
    x = T (a);
1685
    y = T (b);
1686
    z = T (c);
1687
}
1688
1689
template <class T>
1690
template <class S>
1691
IMATH_HOSTDEVICE inline void
1692
Vec3<T>::setValue (const Vec3<S>& v) IMATH_NOEXCEPT
1693
{
1694
    x = T (v.x);
1695
    y = T (v.y);
1696
    z = T (v.z);
1697
}
1698
1699
template <class T>
1700
template <class S>
1701
IMATH_HOSTDEVICE inline void
1702
Vec3<T>::getValue (S& a, S& b, S& c) const IMATH_NOEXCEPT
1703
{
1704
    a = S (x);
1705
    b = S (y);
1706
    c = S (z);
1707
}
1708
1709
template <class T>
1710
template <class S>
1711
IMATH_HOSTDEVICE inline void
1712
Vec3<T>::getValue (Vec3<S>& v) const IMATH_NOEXCEPT
1713
{
1714
    v.x = S (x);
1715
    v.y = S (y);
1716
    v.z = S (z);
1717
}
1718
1719
template <class T>
1720
IMATH_HOSTDEVICE inline T*
1721
Vec3<T>::getValue () IMATH_NOEXCEPT
1722
{
1723
    return (T*) &x;
1724
}
1725
1726
template <class T>
1727
IMATH_HOSTDEVICE inline const T*
1728
Vec3<T>::getValue () const IMATH_NOEXCEPT
1729
{
1730
    return (const T*) &x;
1731
}
1732
1733
template <class T>
1734
template <class S>
1735
IMATH_HOSTDEVICE constexpr inline bool
1736
Vec3<T>::operator== (const Vec3<S>& v) const IMATH_NOEXCEPT
1737
{
1738
    return x == v.x && y == v.y && z == v.z;
1739
}
1740
1741
template <class T>
1742
template <class S>
1743
IMATH_HOSTDEVICE constexpr inline bool
1744
Vec3<T>::operator!= (const Vec3<S>& v) const IMATH_NOEXCEPT
1745
{
1746
    return x != v.x || y != v.y || z != v.z;
1747
}
1748
1749
template <class T>
1750
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool
1751
Vec3<T>::equalWithAbsError (const Vec3<T>& v, T e) const IMATH_NOEXCEPT
1752
{
1753
    for (int i = 0; i < 3; i++)
1754
        if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i], v[i], e))
1755
            return false;
1756
1757
    return true;
1758
}
1759
1760
template <class T>
1761
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool
1762
Vec3<T>::equalWithRelError (const Vec3<T>& v, T e) const IMATH_NOEXCEPT
1763
{
1764
    for (int i = 0; i < 3; i++)
1765
        if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i], v[i], e))
1766
            return false;
1767
1768
    return true;
1769
}
1770
1771
template <class T>
1772
IMATH_HOSTDEVICE constexpr inline T
1773
Vec3<T>::dot (const Vec3& v) const IMATH_NOEXCEPT
1774
{
1775
    return x * v.x + y * v.y + z * v.z;
1776
}
1777
1778
template <class T>
1779
IMATH_HOSTDEVICE constexpr inline T
1780
Vec3<T>::operator^ (const Vec3& v) const IMATH_NOEXCEPT
1781
{
1782
    return dot (v);
1783
}
1784
1785
template <class T>
1786
IMATH_HOSTDEVICE constexpr inline Vec3<T>
1787
Vec3<T>::cross (const Vec3& v) const IMATH_NOEXCEPT
1788
{
1789
    return Vec3 (y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x);
1790
}
1791
1792
template <class T>
1793
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1794
Vec3<T>::operator%= (const Vec3& v) IMATH_NOEXCEPT
1795
{
1796
    T a = y * v.z - z * v.y;
1797
    T b = z * v.x - x * v.z;
1798
    T c = x * v.y - y * v.x;
1799
    x   = a;
1800
    y   = b;
1801
    z   = c;
1802
    return *this;
1803
}
1804
1805
template <class T>
1806
IMATH_HOSTDEVICE constexpr inline Vec3<T>
1807
Vec3<T>::operator% (const Vec3& v) const IMATH_NOEXCEPT
1808
{
1809
    return Vec3 (y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x);
1810
}
1811
1812
template <class T>
1813
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1814
Vec3<T>::operator+= (const Vec3& v) IMATH_NOEXCEPT
1815
{
1816
    x += v.x;
1817
    y += v.y;
1818
    z += v.z;
1819
    return *this;
1820
}
1821
1822
template <class T>
1823
IMATH_HOSTDEVICE constexpr inline Vec3<T>
1824
Vec3<T>::operator+ (const Vec3& v) const IMATH_NOEXCEPT
1825
{
1826
    return Vec3 (x + v.x, y + v.y, z + v.z);
1827
}
1828
1829
template <class T>
1830
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1831
Vec3<T>::operator-= (const Vec3& v) IMATH_NOEXCEPT
1832
{
1833
    x -= v.x;
1834
    y -= v.y;
1835
    z -= v.z;
1836
    return *this;
1837
}
1838
1839
template <class T>
1840
IMATH_HOSTDEVICE constexpr inline Vec3<T>
1841
Vec3<T>::operator- (const Vec3& v) const IMATH_NOEXCEPT
1842
{
1843
    return Vec3 (x - v.x, y - v.y, z - v.z);
1844
}
1845
1846
template <class T>
1847
IMATH_HOSTDEVICE constexpr inline Vec3<T>
1848
Vec3<T>::operator- () const IMATH_NOEXCEPT
1849
{
1850
    return Vec3 (-x, -y, -z);
1851
}
1852
1853
template <class T>
1854
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1855
                 Vec3<T>::negate () IMATH_NOEXCEPT
1856
{
1857
    x = -x;
1858
    y = -y;
1859
    z = -z;
1860
    return *this;
1861
}
1862
1863
template <class T>
1864
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1865
Vec3<T>::operator*= (const Vec3& v) IMATH_NOEXCEPT
1866
{
1867
    x *= v.x;
1868
    y *= v.y;
1869
    z *= v.z;
1870
    return *this;
1871
}
1872
1873
template <class T>
1874
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1875
Vec3<T>::operator*= (T a) IMATH_NOEXCEPT
1876
{
1877
    x *= a;
1878
    y *= a;
1879
    z *= a;
1880
    return *this;
1881
}
1882
1883
template <class T>
1884
IMATH_HOSTDEVICE constexpr inline Vec3<T>
1885
Vec3<T>::operator* (const Vec3& v) const IMATH_NOEXCEPT
1886
{
1887
    return Vec3 (x * v.x, y * v.y, z * v.z);
1888
}
1889
1890
template <class T>
1891
IMATH_HOSTDEVICE constexpr inline Vec3<T>
1892
Vec3<T>::operator* (T a) const IMATH_NOEXCEPT
1893
{
1894
    return Vec3 (x * a, y * a, z * a);
1895
}
1896
1897
template <class T>
1898
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1899
Vec3<T>::operator/= (const Vec3& v) IMATH_NOEXCEPT
1900
{
1901
    x /= v.x;
1902
    y /= v.y;
1903
    z /= v.z;
1904
    return *this;
1905
}
1906
1907
template <class T>
1908
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec3<T>&
1909
Vec3<T>::operator/= (T a) IMATH_NOEXCEPT
1910
{
1911
    x /= a;
1912
    y /= a;
1913
    z /= a;
1914
    return *this;
1915
}
1916
1917
template <class T>
1918
IMATH_HOSTDEVICE constexpr inline Vec3<T>
1919
Vec3<T>::operator/ (const Vec3& v) const IMATH_NOEXCEPT
1920
{
1921
    return Vec3 (x / v.x, y / v.y, z / v.z);
1922
}
1923
1924
template <class T>
1925
IMATH_HOSTDEVICE constexpr inline Vec3<T>
1926
Vec3<T>::operator/ (T a) const IMATH_NOEXCEPT
1927
0
{
1928
0
    return Vec3 (x / a, y / a, z / a);
1929
0
}
1930
1931
template <class T>
1932
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline T
1933
Vec3<T>::lengthTiny () const IMATH_NOEXCEPT
1934
{
1935
    T absX = (x >= T (0)) ? x : -x;
1936
    T absY = (y >= T (0)) ? y : -y;
1937
    T absZ = (z >= T (0)) ? z : -z;
1938
1939
    T max = absX;
1940
1941
    if (max < absY) max = absY;
1942
1943
    if (max < absZ) max = absZ;
1944
1945
    if (IMATH_UNLIKELY (max == T (0))) return T (0);
1946
1947
    //
1948
    // Do not replace the divisions by max with multiplications by 1/max.
1949
    // Computing 1/max can overflow but the divisions below will always
1950
    // produce results less than or equal to 1.
1951
    //
1952
1953
    absX /= max;
1954
    absY /= max;
1955
    absZ /= max;
1956
1957
    return max * std::sqrt (absX * absX + absY * absY + absZ * absZ);
1958
}
1959
1960
template <class T>
1961
IMATH_HOSTDEVICE inline T
1962
Vec3<T>::length () const IMATH_NOEXCEPT
1963
{
1964
    T length2 = dot (*this);
1965
1966
    if (IMATH_UNLIKELY (length2 < T (2) * std::numeric_limits<T>::min ()))
1967
        return lengthTiny ();
1968
1969
    return std::sqrt (length2);
1970
}
1971
1972
template <class T>
1973
IMATH_HOSTDEVICE constexpr inline T
1974
Vec3<T>::length2 () const IMATH_NOEXCEPT
1975
{
1976
    return dot (*this);
1977
}
1978
1979
template <class T>
1980
IMATH_HOSTDEVICE inline const Vec3<T>&
1981
Vec3<T>::normalize () IMATH_NOEXCEPT
1982
{
1983
    T l = length ();
1984
1985
    if (IMATH_LIKELY (l != T (0)))
1986
    {
1987
        //
1988
        // Do not replace the divisions by l with multiplications by 1/l.
1989
        // Computing 1/l can overflow but the divisions below will always
1990
        // produce results less than or equal to 1.
1991
        //
1992
1993
        x /= l;
1994
        y /= l;
1995
        z /= l;
1996
    }
1997
1998
    return *this;
1999
}
2000
2001
template <class T>
2002
inline const Vec3<T>&
2003
Vec3<T>::normalizeExc ()
2004
{
2005
    T l = length ();
2006
2007
    if (IMATH_UNLIKELY (l == T (0)))
2008
        throw std::domain_error ("Cannot normalize null vector.");
2009
2010
    x /= l;
2011
    y /= l;
2012
    z /= l;
2013
    return *this;
2014
}
2015
2016
template <class T>
2017
IMATH_HOSTDEVICE inline const Vec3<T>&
2018
Vec3<T>::normalizeNonNull () IMATH_NOEXCEPT
2019
{
2020
    T l = length ();
2021
    x /= l;
2022
    y /= l;
2023
    z /= l;
2024
    return *this;
2025
}
2026
2027
template <class T>
2028
IMATH_HOSTDEVICE inline Vec3<T>
2029
Vec3<T>::normalized () const IMATH_NOEXCEPT
2030
{
2031
    T l = length ();
2032
2033
    if (IMATH_UNLIKELY ((l == T (0)))) return Vec3 (T (0));
2034
2035
    return Vec3 (x / l, y / l, z / l);
2036
}
2037
2038
template <class T>
2039
inline Vec3<T>
2040
Vec3<T>::normalizedExc () const
2041
{
2042
    T l = length ();
2043
2044
    if (IMATH_UNLIKELY (l == T (0)))
2045
        throw std::domain_error ("Cannot normalize null vector.");
2046
2047
    return Vec3 (x / l, y / l, z / l);
2048
}
2049
2050
template <class T>
2051
IMATH_HOSTDEVICE inline Vec3<T>
2052
Vec3<T>::normalizedNonNull () const IMATH_NOEXCEPT
2053
{
2054
    T l = length ();
2055
    return Vec3 (x / l, y / l, z / l);
2056
}
2057
2058
//-----------------------
2059
// Implementation of Vec4
2060
//-----------------------
2061
2062
template <class T>
2063
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline T&
2064
Vec4<T>::operator[] (int i) IMATH_NOEXCEPT
2065
{
2066
    return (&x)[i]; // NOSONAR - suppress SonarCloud bug report.
2067
}
2068
2069
template <class T>
2070
IMATH_HOSTDEVICE constexpr inline const T&
2071
Vec4<T>::operator[] (int i) const IMATH_NOEXCEPT
2072
{
2073
    return (&x)[i]; // NOSONAR - suppress SonarCloud bug report.
2074
}
2075
2076
template <class T> IMATH_HOSTDEVICE inline Vec4<T>::Vec4 () IMATH_NOEXCEPT
2077
{
2078
    // empty, and not constexpr because data is uninitialized.
2079
}
2080
2081
template <class T>
2082
IMATH_HOSTDEVICE constexpr inline Vec4<T>::Vec4 (T a) IMATH_NOEXCEPT : x (a),
2083
                                                                       y (a),
2084
                                                                       z (a),
2085
                                                                       w (a)
2086
{}
2087
2088
template <class T>
2089
IMATH_HOSTDEVICE constexpr inline Vec4<T>::Vec4 (T a, T b, T c, T d)
2090
    IMATH_NOEXCEPT : x (a),
2091
                     y (b),
2092
                     z (c),
2093
                     w (d)
2094
{}
2095
2096
template <class T>
2097
IMATH_HOSTDEVICE constexpr inline Vec4<T>::Vec4 (const Vec4& v) IMATH_NOEXCEPT
2098
    : x (v.x),
2099
      y (v.y),
2100
      z (v.z),
2101
      w (v.w)
2102
{}
2103
2104
template <class T>
2105
template <class S>
2106
IMATH_HOSTDEVICE constexpr inline Vec4<T>::Vec4 (const Vec4<S>& v)
2107
    IMATH_NOEXCEPT : x (T (v.x)),
2108
                     y (T (v.y)),
2109
                     z (T (v.z)),
2110
                     w (T (v.w))
2111
{}
2112
2113
template <class T>
2114
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4<T>&
2115
Vec4<T>::operator= (const Vec4& v) IMATH_NOEXCEPT
2116
{
2117
    x = v.x;
2118
    y = v.y;
2119
    z = v.z;
2120
    w = v.w;
2121
    return *this;
2122
}
2123
2124
template <class T>
2125
template <class S>
2126
IMATH_HOSTDEVICE constexpr inline Vec4<T>::Vec4 (const Vec3<S>& v)
2127
    IMATH_NOEXCEPT : x (T (v.x)),
2128
                     y (T (v.y)),
2129
                     z (T (v.z)),
2130
                     w (T (1))
2131
{}
2132
2133
template <class T>
2134
template <class S>
2135
IMATH_HOSTDEVICE constexpr inline bool
2136
Vec4<T>::operator== (const Vec4<S>& v) const IMATH_NOEXCEPT
2137
{
2138
    return x == v.x && y == v.y && z == v.z && w == v.w;
2139
}
2140
2141
template <class T>
2142
template <class S>
2143
IMATH_HOSTDEVICE constexpr inline bool
2144
Vec4<T>::operator!= (const Vec4<S>& v) const IMATH_NOEXCEPT
2145
{
2146
    return x != v.x || y != v.y || z != v.z || w != v.w;
2147
}
2148
2149
template <class T>
2150
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool
2151
Vec4<T>::equalWithAbsError (const Vec4<T>& v, T e) const IMATH_NOEXCEPT
2152
{
2153
    for (int i = 0; i < 4; i++)
2154
        if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i], v[i], e))
2155
            return false;
2156
2157
    return true;
2158
}
2159
2160
template <class T>
2161
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool
2162
Vec4<T>::equalWithRelError (const Vec4<T>& v, T e) const IMATH_NOEXCEPT
2163
{
2164
    for (int i = 0; i < 4; i++)
2165
        if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i], v[i], e))
2166
            return false;
2167
2168
    return true;
2169
}
2170
2171
template <class T>
2172
IMATH_HOSTDEVICE constexpr inline T
2173
Vec4<T>::dot (const Vec4& v) const IMATH_NOEXCEPT
2174
{
2175
    return x * v.x + y * v.y + z * v.z + w * v.w;
2176
}
2177
2178
template <class T>
2179
IMATH_HOSTDEVICE constexpr inline T
2180
Vec4<T>::operator^ (const Vec4& v) const IMATH_NOEXCEPT
2181
{
2182
    return dot (v);
2183
}
2184
2185
template <class T>
2186
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4<T>&
2187
Vec4<T>::operator+= (const Vec4& v) IMATH_NOEXCEPT
2188
{
2189
    x += v.x;
2190
    y += v.y;
2191
    z += v.z;
2192
    w += v.w;
2193
    return *this;
2194
}
2195
2196
template <class T>
2197
IMATH_HOSTDEVICE constexpr inline Vec4<T>
2198
Vec4<T>::operator+ (const Vec4& v) const IMATH_NOEXCEPT
2199
{
2200
    return Vec4 (x + v.x, y + v.y, z + v.z, w + v.w);
2201
}
2202
2203
template <class T>
2204
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4<T>&
2205
Vec4<T>::operator-= (const Vec4& v) IMATH_NOEXCEPT
2206
{
2207
    x -= v.x;
2208
    y -= v.y;
2209
    z -= v.z;
2210
    w -= v.w;
2211
    return *this;
2212
}
2213
2214
template <class T>
2215
IMATH_HOSTDEVICE constexpr inline Vec4<T>
2216
Vec4<T>::operator- (const Vec4& v) const IMATH_NOEXCEPT
2217
{
2218
    return Vec4 (x - v.x, y - v.y, z - v.z, w - v.w);
2219
}
2220
2221
template <class T>
2222
IMATH_HOSTDEVICE constexpr inline Vec4<T>
2223
Vec4<T>::operator- () const IMATH_NOEXCEPT
2224
{
2225
    return Vec4 (-x, -y, -z, -w);
2226
}
2227
2228
template <class T>
2229
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4<T>&
2230
                 Vec4<T>::negate () IMATH_NOEXCEPT
2231
{
2232
    x = -x;
2233
    y = -y;
2234
    z = -z;
2235
    w = -w;
2236
    return *this;
2237
}
2238
2239
template <class T>
2240
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4<T>&
2241
Vec4<T>::operator*= (const Vec4& v) IMATH_NOEXCEPT
2242
{
2243
    x *= v.x;
2244
    y *= v.y;
2245
    z *= v.z;
2246
    w *= v.w;
2247
    return *this;
2248
}
2249
2250
template <class T>
2251
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4<T>&
2252
Vec4<T>::operator*= (T a) IMATH_NOEXCEPT
2253
{
2254
    x *= a;
2255
    y *= a;
2256
    z *= a;
2257
    w *= a;
2258
    return *this;
2259
}
2260
2261
template <class T>
2262
IMATH_HOSTDEVICE constexpr inline Vec4<T>
2263
Vec4<T>::operator* (const Vec4& v) const IMATH_NOEXCEPT
2264
{
2265
    return Vec4 (x * v.x, y * v.y, z * v.z, w * v.w);
2266
}
2267
2268
template <class T>
2269
IMATH_HOSTDEVICE constexpr inline Vec4<T>
2270
Vec4<T>::operator* (T a) const IMATH_NOEXCEPT
2271
{
2272
    return Vec4 (x * a, y * a, z * a, w * a);
2273
}
2274
2275
template <class T>
2276
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4<T>&
2277
Vec4<T>::operator/= (const Vec4& v) IMATH_NOEXCEPT
2278
{
2279
    x /= v.x;
2280
    y /= v.y;
2281
    z /= v.z;
2282
    w /= v.w;
2283
    return *this;
2284
}
2285
2286
template <class T>
2287
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline const Vec4<T>&
2288
Vec4<T>::operator/= (T a) IMATH_NOEXCEPT
2289
{
2290
    x /= a;
2291
    y /= a;
2292
    z /= a;
2293
    w /= a;
2294
    return *this;
2295
}
2296
2297
template <class T>
2298
IMATH_HOSTDEVICE constexpr inline Vec4<T>
2299
Vec4<T>::operator/ (const Vec4& v) const IMATH_NOEXCEPT
2300
{
2301
    return Vec4 (x / v.x, y / v.y, z / v.z, w / v.w);
2302
}
2303
2304
template <class T>
2305
IMATH_HOSTDEVICE constexpr inline Vec4<T>
2306
Vec4<T>::operator/ (T a) const IMATH_NOEXCEPT
2307
{
2308
    return Vec4 (x / a, y / a, z / a, w / a);
2309
}
2310
2311
template <class T>
2312
IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline T
2313
Vec4<T>::lengthTiny () const IMATH_NOEXCEPT
2314
{
2315
    T absX = (x >= T (0)) ? x : -x;
2316
    T absY = (y >= T (0)) ? y : -y;
2317
    T absZ = (z >= T (0)) ? z : -z;
2318
    T absW = (w >= T (0)) ? w : -w;
2319
2320
    T max = absX;
2321
2322
    if (max < absY) max = absY;
2323
2324
    if (max < absZ) max = absZ;
2325
2326
    if (max < absW) max = absW;
2327
2328
    if (IMATH_UNLIKELY (max == T (0))) return T (0);
2329
2330
    //
2331
    // Do not replace the divisions by max with multiplications by 1/max.
2332
    // Computing 1/max can overflow but the divisions below will always
2333
    // produce results less than or equal to 1.
2334
    //
2335
2336
    absX /= max;
2337
    absY /= max;
2338
    absZ /= max;
2339
    absW /= max;
2340
2341
    return max *
2342
           std::sqrt (absX * absX + absY * absY + absZ * absZ + absW * absW);
2343
}
2344
2345
template <class T>
2346
IMATH_HOSTDEVICE inline T
2347
Vec4<T>::length () const IMATH_NOEXCEPT
2348
{
2349
    T length2 = dot (*this);
2350
2351
    if (IMATH_UNLIKELY (length2 < T (2) * std::numeric_limits<T>::min ()))
2352
        return lengthTiny ();
2353
2354
    return std::sqrt (length2);
2355
}
2356
2357
template <class T>
2358
IMATH_HOSTDEVICE constexpr inline T
2359
Vec4<T>::length2 () const IMATH_NOEXCEPT
2360
{
2361
    return dot (*this);
2362
}
2363
2364
template <class T>
2365
IMATH_HOSTDEVICE const inline Vec4<T>&
2366
Vec4<T>::normalize () IMATH_NOEXCEPT
2367
{
2368
    T l = length ();
2369
2370
    if (IMATH_LIKELY (l != T (0)))
2371
    {
2372
        //
2373
        // Do not replace the divisions by l with multiplications by 1/l.
2374
        // Computing 1/l can overflow but the divisions below will always
2375
        // produce results less than or equal to 1.
2376
        //
2377
2378
        x /= l;
2379
        y /= l;
2380
        z /= l;
2381
        w /= l;
2382
    }
2383
2384
    return *this;
2385
}
2386
2387
template <class T>
2388
const inline Vec4<T>&
2389
Vec4<T>::normalizeExc ()
2390
{
2391
    T l = length ();
2392
2393
    if (IMATH_UNLIKELY (l == T (0)))
2394
        throw std::domain_error ("Cannot normalize null vector.");
2395
2396
    x /= l;
2397
    y /= l;
2398
    z /= l;
2399
    w /= l;
2400
    return *this;
2401
}
2402
2403
template <class T>
2404
IMATH_HOSTDEVICE inline const Vec4<T>&
2405
Vec4<T>::normalizeNonNull () IMATH_NOEXCEPT
2406
{
2407
    T l = length ();
2408
    x /= l;
2409
    y /= l;
2410
    z /= l;
2411
    w /= l;
2412
    return *this;
2413
}
2414
2415
template <class T>
2416
IMATH_HOSTDEVICE inline Vec4<T>
2417
Vec4<T>::normalized () const IMATH_NOEXCEPT
2418
{
2419
    T l = length ();
2420
2421
    if (IMATH_UNLIKELY (l == T (0))) return Vec4 (T (0));
2422
2423
    return Vec4 (x / l, y / l, z / l, w / l);
2424
}
2425
2426
template <class T>
2427
inline Vec4<T>
2428
Vec4<T>::normalizedExc () const
2429
{
2430
    T l = length ();
2431
2432
    if (IMATH_UNLIKELY (l == T (0)))
2433
        throw std::domain_error ("Cannot normalize null vector.");
2434
2435
    return Vec4 (x / l, y / l, z / l, w / l);
2436
}
2437
2438
template <class T>
2439
IMATH_HOSTDEVICE inline Vec4<T>
2440
Vec4<T>::normalizedNonNull () const IMATH_NOEXCEPT
2441
{
2442
    T l = length ();
2443
    return Vec4 (x / l, y / l, z / l, w / l);
2444
}
2445
2446
//-----------------------------
2447
// Stream output implementation
2448
//-----------------------------
2449
2450
template <class T>
2451
std::ostream&
2452
operator<< (std::ostream& s, const Vec2<T>& v)
2453
{
2454
    return s << '(' << v.x << ' ' << v.y << ')';
2455
}
2456
2457
template <class T>
2458
std::ostream&
2459
operator<< (std::ostream& s, const Vec3<T>& v)
2460
{
2461
    return s << '(' << v.x << ' ' << v.y << ' ' << v.z << ')';
2462
}
2463
2464
template <class T>
2465
std::ostream&
2466
operator<< (std::ostream& s, const Vec4<T>& v)
2467
{
2468
    return s << '(' << v.x << ' ' << v.y << ' ' << v.z << ' ' << v.w << ')';
2469
}
2470
2471
//-----------------------------------------
2472
// Implementation of reverse multiplication
2473
//-----------------------------------------
2474
2475
template <class T>
2476
IMATH_HOSTDEVICE constexpr inline Vec2<T>
2477
operator* (T a, const Vec2<T>& v) IMATH_NOEXCEPT
2478
{
2479
    return Vec2<T> (a * v.x, a * v.y);
2480
}
2481
2482
template <class T>
2483
IMATH_HOSTDEVICE constexpr inline Vec3<T>
2484
operator* (T a, const Vec3<T>& v) IMATH_NOEXCEPT
2485
{
2486
    return Vec3<T> (a * v.x, a * v.y, a * v.z);
2487
}
2488
2489
template <class T>
2490
IMATH_HOSTDEVICE constexpr inline Vec4<T>
2491
operator* (T a, const Vec4<T>& v) IMATH_NOEXCEPT
2492
{
2493
    return Vec4<T> (a * v.x, a * v.y, a * v.z, a * v.w);
2494
}
2495
2496
#if (defined _WIN32 || defined _WIN64) && defined _MSC_VER
2497
#    pragma warning(pop)
2498
#endif
2499
2500
IMATH_INTERNAL_NAMESPACE_HEADER_EXIT
2501
2502
#endif // INCLUDED_IMATHVEC_H