Coverage Report

Created: 2026-09-14 07:15

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