Coverage Report

Created: 2022-08-24 06:20

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