OpenVDB 14.0.0
Loading...
Searching...
No Matches
Math.h
Go to the documentation of this file.
1// Copyright Contributors to the OpenVDB Project
2// SPDX-License-Identifier: Apache-2.0
3
4/*!
5 \file Math.h
6
7 \author Ken Museth
8
9 \date January 8, 2020
10
11 \brief Math functions and classes
12
13*/
14
15#ifndef NANOVDB_MATH_MATH_H_HAS_BEEN_INCLUDED
16#define NANOVDB_MATH_MATH_H_HAS_BEEN_INCLUDED
17
18#include <nanovdb/util/Util.h>// for __hostdev__ and lots of other utility functions
19
20#include <type_traits>// for std::is_floating_point (matches long double in addition to float / double)
21
22#if defined(__CUDA_ARCH__)
23#include <cuda/std/limits>// for ::cuda::std::numeric_limits
24#endif
25
26namespace nanovdb {// =================================================================
27
28namespace math {// =============================================================
29
30// ----------------------------> Various math functions <-------------------------------------
31
32//@{
33/// @brief Pi constant taken from Boost to match old behaviour
34template<typename T>
35inline __hostdev__ constexpr T pi() noexcept
36{
37 return 3.141592653589793238462643383279502884e+00;
38}
39template<>
40inline __hostdev__ constexpr float pi() noexcept
41{
42 return 3.141592653589793238462643383279502884e+00F;
43}
44template<>
45inline __hostdev__ constexpr double pi() noexcept
46{
47 return 3.141592653589793238462643383279502884e+00;
48}
49template<>
50inline __hostdev__ constexpr long double pi() noexcept
51{
52 return 3.141592653589793238462643383279502884e+00L;
53}
54//@}
55
56//@{
57/// @brief Per-type tolerance used by approximate floating-point comparisons.
58/// @details Returned by @c Tolerance<T>::value() and consumed by @c isApproxZero.
59/// Specialized for @c float, @c double, and @c long double. Instantiating on
60/// any other @c T is an "incomplete type" compile error by design — callers
61/// must opt in by adding a specialization.
62template<typename T>
63struct Tolerance;
64template<>
65struct Tolerance<float>
66{
67 __hostdev__ [[nodiscard]] static constexpr float value() noexcept { return 1e-8f; }
68};
69template<>
70struct Tolerance<double>
71{
72 __hostdev__ [[nodiscard]] static constexpr double value() noexcept { return 1e-15; }
73};
74template<>
75struct Tolerance<long double>
76{
77 __hostdev__ [[nodiscard]] static constexpr long double value() noexcept { return 1e-18L; }
78};
79//@}
80
81//@{
82/// @brief Per-type small floating-point offset, useful for nudging boundaries
83/// off-edge in geometric tests.
84/// @details Returned by @c Delta<T>::value(). Specialized for @c float,
85/// @c double, and @c long double; instantiating on any other @c T is a
86/// compile error by design.
87template<typename T>
88struct Delta;
89template<>
90struct Delta<float>
91{
92 __hostdev__ [[nodiscard]] static constexpr float value() noexcept { return 1e-5f; }
93};
94template<>
95struct Delta<double>
96{
97 __hostdev__ [[nodiscard]] static constexpr double value() noexcept { return 1e-9; }
98};
99template<>
100struct Delta<long double>
101{
102 __hostdev__ [[nodiscard]] static constexpr long double value() noexcept { return 1e-12L; }
103};
104//@}
105
106//@{
107/// @brief Per-type largest representable value (mirrors @c std::numeric_limits::max).
108/// @details Returned by @c Maximum<T>::value(). The host fallback (`#else`
109/// branch) forwards to @c std::numeric_limits so any @c T with a
110/// specialization there works; the CUDA-device branch uses
111/// @c ::cuda::std::numeric_limits; the HIP branch hard-codes a handful of
112/// common types because @c std::numeric_limits is unavailable on the device
113/// in some HIP toolchains.
114template<typename T>
115struct Maximum;
116#if defined(__CUDA_ARCH__)
117template<typename T>
118struct Maximum
119{
120 __hostdev__ [[nodiscard]] static constexpr T value() noexcept { return ::cuda::std::numeric_limits<T>::max(); }
121};
122#elif defined(__HIP__)
123template<>
124struct Maximum<int>
125{
126 __hostdev__ [[nodiscard]] static constexpr int value() noexcept { return 2147483647; }
127};
128template<>
129struct Maximum<uint32_t>
130{
131 __hostdev__ [[nodiscard]] static constexpr uint32_t value() noexcept { return 4294967295u; }
132};
133template<>
134struct Maximum<float>
135{
136 __hostdev__ [[nodiscard]] static constexpr float value() noexcept { return 1e+38f; }
137};
138template<>
139struct Maximum<double>
140{
141 __hostdev__ [[nodiscard]] static constexpr double value() noexcept { return 1e+308; }
142};
143#else
144template<typename T>
146{
147 [[nodiscard]] static constexpr T value() noexcept { return std::numeric_limits<T>::max(); }
148};
149#endif
150//@}
151
152/// @brief Return @c true if @c |x| is below @c Tolerance<Type>::value().
153template<typename Type>
154__hostdev__ [[nodiscard]] inline constexpr bool isApproxZero(const Type& x) noexcept
155{
156 return !(x > Tolerance<Type>::value()) && !(x < -Tolerance<Type>::value());
157}
158
159/// @brief Same-type minimum (the primary template).
160template<typename Type>
161__hostdev__ [[nodiscard]] inline constexpr Type Min(Type a, Type b) noexcept
162{
163 return (a < b) ? a : b;
164}
165// Mixed integer-type tiebreakers: the templated `Min<Type>` requires both
166// args to deduce to the same `Type`, so calls like `Min(uint32_t, size_t)`
167// would otherwise fall through to the float/double overloads with equal
168// implicit-conversion cost — ambiguous. These integer overloads win.
169__hostdev__ [[nodiscard]] inline constexpr int32_t Min(int32_t a, int32_t b) noexcept
170{
171 return a < b ? a : b;
172}
173__hostdev__ [[nodiscard]] inline constexpr uint32_t Min(uint32_t a, uint32_t b) noexcept
174{
175 return a < b ? a : b;
176}
177__hostdev__ [[nodiscard]] inline float Min(float a, float b) noexcept
178{
179 return fminf(a, b);
180}
181__hostdev__ [[nodiscard]] inline double Min(double a, double b) noexcept
182{
183 return fmin(a, b);
184}
185/// @brief Same-type maximum (the primary template).
186template<typename Type>
187__hostdev__ [[nodiscard]] inline constexpr Type Max(Type a, Type b) noexcept
188{
189 return (a > b) ? a : b;
190}
191// See Min above: these integer overloads disambiguate mixed-int calls.
192__hostdev__ [[nodiscard]] inline constexpr int32_t Max(int32_t a, int32_t b) noexcept
193{
194 return a > b ? a : b;
195}
196__hostdev__ [[nodiscard]] inline constexpr uint32_t Max(uint32_t a, uint32_t b) noexcept
197{
198 return a > b ? a : b;
199}
200__hostdev__ [[nodiscard]] inline float Max(float a, float b) noexcept
201{
202 return fmaxf(a, b);
203}
204__hostdev__ [[nodiscard]] inline double Max(double a, double b) noexcept
205{
206 return fmax(a, b);
207}
208//@{
209/// @brief Clamp @c x to the closed interval [@c a, @c b].
210__hostdev__ [[nodiscard]] inline float Clamp(float x, float a, float b) noexcept
211{
212 return Max(Min(x, b), a);
213}
214__hostdev__ [[nodiscard]] inline double Clamp(double x, double a, double b) noexcept
215{
216 return Max(Min(x, b), a);
217}
218//@}
219
220//@{
221/// @brief Fractional part of @c x, i.e. @c x @c - @c floor(x). Always non-negative.
222__hostdev__ [[nodiscard]] inline float Fract(float x) noexcept
223{
224 return x - floorf(x);
225}
226__hostdev__ [[nodiscard]] inline double Fract(double x) noexcept
227{
228 return x - floor(x);
229}
230//@}
231
232//@{
233/// @brief Floor of @c x as a 32-bit signed integer (truncation toward -inf).
234__hostdev__ [[nodiscard]] inline int32_t Floor(float x) noexcept
235{
236 return int32_t(floorf(x));
237}
238__hostdev__ [[nodiscard]] inline int32_t Floor(double x) noexcept
239{
240 return int32_t(floor(x));
241}
242//@}
243
244//@{
245/// @brief Ceil of @c x as a 32-bit signed integer (rounding toward +inf).
246__hostdev__ [[nodiscard]] inline int32_t Ceil(float x) noexcept
247{
248 return int32_t(ceilf(x));
249}
250__hostdev__ [[nodiscard]] inline int32_t Ceil(double x) noexcept
251{
252 return int32_t(ceil(x));
253}
254//@}
255
256/// @brief Return @c x * @c x.
257template<typename T>
258__hostdev__ [[nodiscard]] inline constexpr T Pow2(T x) noexcept
259{
260 return x * x;
261}
262
263/// @brief Return @c x * @c x * @c x.
264template<typename T>
265__hostdev__ [[nodiscard]] inline constexpr T Pow3(T x) noexcept
266{
267 return x * x * x;
268}
269
270/// @brief Return @c x raised to the fourth power.
271template<typename T>
272__hostdev__ [[nodiscard]] inline constexpr T Pow4(T x) noexcept
273{
274 return Pow2(x * x);
275}
276/// @brief Absolute value (generic primary template, branchless for arithmetic types).
277/// @note The @c float / @c double / @c int specializations below are not
278template<typename T>
279__hostdev__ [[nodiscard]] inline constexpr T Abs(T x) noexcept
280{
281 return x < 0 ? -x : x;
282}
283
284template<>
285__hostdev__ [[nodiscard]] inline float Abs(float x) noexcept
286{
287 return fabsf(x);
288}
289
290template<>
291__hostdev__ [[nodiscard]] inline double Abs(double x) noexcept
292{
293 return fabs(x);
294}
295
296template<>
297__hostdev__ [[nodiscard]] inline int Abs(int x) noexcept
298{
299 return abs(x);
300}
301
302//@{
303/// @brief Round @c x to the nearest 32-bit signed integer, with halfway cases
304/// rounded toward +inf.
305/// @details Exact for every input, because @c x - floor(x) has no rounding
306/// error. The shorter @c floor(x + 0.5) rounds the sum first, which moves
307/// e.g. @c 0.49999997f to 1 and @c 8388609.f to 8388610.
308__hostdev__ [[nodiscard]] inline int32_t Round(float x) noexcept
309{
310 const float f = floorf(x);
311 return int32_t(f) + (x - f >= 0.5f);
312}
313__hostdev__ [[nodiscard]] inline int32_t Round(double x) noexcept
314{
315 const double f = floor(x);
316 return int32_t(f) + (x - f >= 0.5);
317}
318//@}
319
320/// @brief Round each component of @c xyz to its closest integer coordinate.
321/// @details Forward declaration of the primary template — there is no
322/// definition here. Callers resolve to one of the @c float / @c double
323/// overloads below. Both use the scalar @c Round rule (nearest, halfway cases
324/// toward +inf), so float and double inputs with the same value yield the
325/// same integer coordinate.
326template<typename CoordT, typename RealT, template<typename> class Vec3T>
327__hostdev__ [[nodiscard]] inline CoordT Round(const Vec3T<RealT>& xyz) noexcept;
328
329/// @brief Round each component to its closest integer, halfway cases toward +inf.
330template<typename CoordT, template<typename> class Vec3T>
331__hostdev__ [[nodiscard]] inline CoordT Round(const Vec3T<float>& xyz) noexcept
332{
333 return CoordT(Round(xyz[0]), Round(xyz[1]), Round(xyz[2]));
334}
335
336/// @brief Double-precision variant of @c Round — see the @c float overload above.
337template<typename CoordT, template<typename> class Vec3T>
338__hostdev__ [[nodiscard]] inline CoordT Round(const Vec3T<double>& xyz) noexcept
339{
340 return CoordT(Round(xyz[0]), Round(xyz[1]), Round(xyz[2]));
341}
342
343/// @brief Round each component of @c xyz down (toward -inf) into a @c CoordT.
344template<typename CoordT, typename RealT, template<typename> class Vec3T>
345__hostdev__ [[nodiscard]] inline CoordT RoundDown(const Vec3T<RealT>& xyz) noexcept
346{
347 return CoordT(Floor(xyz[0]), Floor(xyz[1]), Floor(xyz[2]));
348}
349
350//@{
351/// Return the square root of a floating-point value.
352__hostdev__ [[nodiscard]] inline float Sqrt(float x) noexcept
353{
354 return sqrtf(x);
355}
356__hostdev__ [[nodiscard]] inline double Sqrt(double x) noexcept
357{
358 return sqrt(x);
359}
360//@}
361
362/// Return the sign of the given value as an integer (either -1, 0 or 1).
363template<typename T>
364__hostdev__ [[nodiscard]] inline constexpr T Sign(const T& x) noexcept
365{
366 return ((T(0) < x) ? T(1) : T(0)) - ((x < T(0)) ? T(1) : T(0));
367}
368
369/// @brief Return the component index (0, 1, or 2) of the smallest element of @c v.
370/// @note Ties resolve to the lowest index (i.e. x beats y, y beats z).
371template<typename Vec3T>
372__hostdev__ [[nodiscard]] inline constexpr int MinIndex(const Vec3T& v) noexcept
373{
374#if 0
375 static const int hashTable[8] = {2, 1, 9, 1, 2, 9, 0, 0}; //9 are dummy values
376 const int hashKey = ((v[0] < v[1]) << 2) + ((v[0] < v[2]) << 1) + (v[1] < v[2]); // ?*4+?*2+?*1
377 return hashTable[hashKey];
378#else
379 if (v[0] < v[1] && v[0] < v[2])
380 return 0;
381 if (v[1] < v[2])
382 return 1;
383 else
384 return 2;
385#endif
386}
387
388/// @brief Return the component index (0, 1, or 2) of the largest element of @c v.
389/// @note Ties resolve to the lowest index (i.e. x beats y, y beats z).
390template<typename Vec3T>
391__hostdev__ [[nodiscard]] inline constexpr int MaxIndex(const Vec3T& v) noexcept
392{
393#if 0
394 static const int hashTable[8] = {2, 1, 9, 1, 2, 9, 0, 0}; //9 are dummy values
395 const int hashKey = ((v[0] > v[1]) << 2) + ((v[0] > v[2]) << 1) + (v[1] > v[2]); // ?*4+?*2+?*1
396 return hashTable[hashKey];
397#else
398 if (v[0] > v[1] && v[0] > v[2])
399 return 0;
400 if (v[1] > v[2])
401 return 1;
402 else
403 return 2;
404#endif
405}
406
407/// @brief round up byteSize to the nearest wordSize, e.g. to align to machine word: AlignUp<sizeof(size_t)(n)
408///
409/// @details both wordSize and byteSize are in byte units
410template<uint64_t wordSize>
411__hostdev__ [[nodiscard]] inline constexpr uint64_t AlignUp(uint64_t byteCount) noexcept
412{
413 const uint64_t r = byteCount % wordSize;
414 return r ? byteCount - r + wordSize : byteCount;
415}
416
417// ------------------------------> Coord <--------------------------------------
418
419// forward declaration so we can define Coord::asVec3s and Coord::asVec3d
420template<typename>
421class Vec3;
422
423/// @brief Signed (i, j, k) 32-bit integer coordinate class, similar to openvdb::math::Coord
424class Coord
425{
426 int32_t mVec[3]; // private member data - three signed index coordinates
427public:
428 using ValueType = int32_t;
429 using IndexType = uint32_t;
430
431 /// @brief Initialize all coordinates to zero.
432 __hostdev__ constexpr Coord() noexcept
433 : mVec{0, 0, 0}
434 {
435 }
436
437 /// @brief Initializes all coordinates to the given signed integer.
438 __hostdev__ explicit constexpr Coord(ValueType n) noexcept
439 : mVec{n, n, n}
440 {
441 }
442
443 /// @brief Initializes coordinate to the given signed integers.
444 __hostdev__ constexpr Coord(ValueType i, ValueType j, ValueType k) noexcept
445 : mVec{i, j, k}
446 {
447 }
448
449 /// @brief Read three signed integers from @a ptr (no bounds check).
450 __hostdev__ constexpr Coord(ValueType* ptr) noexcept
451 : mVec{ptr[0], ptr[1], ptr[2]}
452 {
453 }
454
455 //@{
456 /// @brief Named component accessors (x = mVec[0], y = mVec[1], z = mVec[2]).
457 __hostdev__ constexpr int32_t x() const noexcept { return mVec[0]; }
458 __hostdev__ constexpr int32_t y() const noexcept { return mVec[1]; }
459 __hostdev__ constexpr int32_t z() const noexcept { return mVec[2]; }
460
461 __hostdev__ constexpr int32_t& x() noexcept { return mVec[0]; }
462 __hostdev__ constexpr int32_t& y() noexcept { return mVec[1]; }
463 __hostdev__ constexpr int32_t& z() noexcept { return mVec[2]; }
464 //@}
465
466 /// @brief Largest representable @c Coord (all components = INT32_MAX).
467 __hostdev__ [[nodiscard]] static constexpr Coord max() noexcept { return Coord(int32_t((1u << 31) - 1)); }
468
469 /// @brief Smallest representable @c Coord (all components = INT32_MIN).
470 __hostdev__ [[nodiscard]] static constexpr Coord min() noexcept { return Coord(-int32_t((1u << 31) - 1) - 1); }
471
472 /// @brief Byte size of a @c Coord (always 12 on a 32-bit @c int32_t platform).
473 __hostdev__ [[nodiscard]] static constexpr size_t memUsage() noexcept { return sizeof(Coord); }
474
475 /// @brief Return a const reference to the given Coord component.
476 /// @warning The argument is assumed to be 0, 1, or 2.
477 __hostdev__ constexpr const ValueType& operator[](IndexType i) const noexcept { NANOVDB_ASSERT(i < 3); return mVec[i]; }
478
479 /// @brief Return a non-const reference to the given Coord component.
480 /// @warning The argument is assumed to be 0, 1, or 2.
481 __hostdev__ constexpr ValueType& operator[](IndexType i) noexcept { NANOVDB_ASSERT(i < 3); return mVec[i]; }
482
483 /// @brief Assignment operator that works with openvdb::Coord
484 template<typename CoordT>
485 __hostdev__ constexpr Coord& operator=(const CoordT& other) noexcept
486 {
487 static_assert(sizeof(Coord) == sizeof(CoordT), "Mis-matched sizeof");
488 mVec[0] = other[0];
489 mVec[1] = other[1];
490 mVec[2] = other[2];
491 return *this;
492 }
493
494 /// @brief Return a new instance with coordinates masked by the given unsigned integer.
495 __hostdev__ [[nodiscard]] constexpr Coord operator&(IndexType n) const noexcept { return Coord(mVec[0] & n, mVec[1] & n, mVec[2] & n); }
496
497 /// @brief Return a new instance with coordinates left-shifted by the given unsigned integer.
498 __hostdev__ [[nodiscard]] constexpr Coord operator<<(IndexType n) const noexcept { return Coord(mVec[0] << n, mVec[1] << n, mVec[2] << n); }
499
500 /// @brief Return a new instance with coordinates right-shifted by the given unsigned integer.
501 __hostdev__ [[nodiscard]] constexpr Coord operator>>(IndexType n) const noexcept { return Coord(mVec[0] >> n, mVec[1] >> n, mVec[2] >> n); }
502
503 /// @brief Return true if this Coord is lexicographically less than the given Coord.
504 __hostdev__ [[nodiscard]] constexpr bool operator<(const Coord& rhs) const noexcept
505 {
506 return mVec[0] < rhs[0] ? true
507 : mVec[0] > rhs[0] ? false
508 : mVec[1] < rhs[1] ? true
509 : mVec[1] > rhs[1] ? false
510 : mVec[2] < rhs[2] ? true : false;
511 }
512
513 /// @brief Return true if this Coord is lexicographically less or equal to the given Coord.
514 __hostdev__ [[nodiscard]] constexpr bool operator<=(const Coord& rhs) const noexcept
515 {
516 return mVec[0] < rhs[0] ? true
517 : mVec[0] > rhs[0] ? false
518 : mVec[1] < rhs[1] ? true
519 : mVec[1] > rhs[1] ? false
520 : mVec[2] <=rhs[2] ? true : false;
521 }
522
523 /// @brief Return true if this Coord is lexicographically greater than the given Coord.
524 __hostdev__ [[nodiscard]] constexpr bool operator>(const Coord& rhs) const noexcept
525 {
526 return mVec[0] > rhs[0] ? true
527 : mVec[0] < rhs[0] ? false
528 : mVec[1] > rhs[1] ? true
529 : mVec[1] < rhs[1] ? false
530 : mVec[2] > rhs[2] ? true : false;
531 }
532
533 /// @brief Return true if this Coord is lexicographically greater or equal to the given Coord.
534 __hostdev__ [[nodiscard]] constexpr bool operator>=(const Coord& rhs) const noexcept
535 {
536 return mVec[0] > rhs[0] ? true
537 : mVec[0] < rhs[0] ? false
538 : mVec[1] > rhs[1] ? true
539 : mVec[1] < rhs[1] ? false
540 : mVec[2] >=rhs[2] ? true : false;
541 }
542
543 /// @brief Return true iff every component matches @a rhs.
544 __hostdev__ [[nodiscard]] constexpr bool operator==(const Coord& rhs) const noexcept { return mVec[0] == rhs[0] && mVec[1] == rhs[1] && mVec[2] == rhs[2]; }
545 /// @brief Return true iff any component differs from @a rhs.
546 __hostdev__ [[nodiscard]] constexpr bool operator!=(const Coord& rhs) const noexcept { return mVec[0] != rhs[0] || mVec[1] != rhs[1] || mVec[2] != rhs[2]; }
547 /// @brief In-place component-wise bitwise AND with the given mask.
548 __hostdev__ constexpr Coord& operator&=(int n) noexcept
549 {
550 mVec[0] &= n;
551 mVec[1] &= n;
552 mVec[2] &= n;
553 return *this;
554 }
555 /// @brief In-place left-shift of every component by @a n bits.
556 __hostdev__ constexpr Coord& operator<<=(uint32_t n) noexcept
557 {
558 mVec[0] <<= n;
559 mVec[1] <<= n;
560 mVec[2] <<= n;
561 return *this;
562 }
563 /// @brief In-place right-shift of every component by @a n bits.
564 __hostdev__ constexpr Coord& operator>>=(uint32_t n) noexcept
565 {
566 mVec[0] >>= n;
567 mVec[1] >>= n;
568 mVec[2] >>= n;
569 return *this;
570 }
571 /// @brief Add a scalar to every component in place.
572 __hostdev__ constexpr Coord& operator+=(int n) noexcept
573 {
574 mVec[0] += n;
575 mVec[1] += n;
576 mVec[2] += n;
577 return *this;
578 }
579 /// @brief Component-wise sum of two coordinates.
580 __hostdev__ [[nodiscard]] constexpr Coord operator+(const Coord& rhs) const noexcept { return Coord(mVec[0] + rhs[0], mVec[1] + rhs[1], mVec[2] + rhs[2]); }
581 /// @brief Component-wise difference of two coordinates.
582 __hostdev__ [[nodiscard]] constexpr Coord operator-(const Coord& rhs) const noexcept { return Coord(mVec[0] - rhs[0], mVec[1] - rhs[1], mVec[2] - rhs[2]); }
583 /// @brief Component-wise negation.
584 __hostdev__ [[nodiscard]] constexpr Coord operator-() const noexcept { return Coord(-mVec[0], -mVec[1], -mVec[2]); }
585 /// @brief In-place component-wise addition with another coordinate.
586 __hostdev__ constexpr Coord& operator+=(const Coord& rhs) noexcept
587 {
588 mVec[0] += rhs[0];
589 mVec[1] += rhs[1];
590 mVec[2] += rhs[2];
591 return *this;
592 }
593 /// @brief In-place component-wise subtraction with another coordinate.
594 __hostdev__ constexpr Coord& operator-=(const Coord& rhs) noexcept
595 {
596 mVec[0] -= rhs[0];
597 mVec[1] -= rhs[1];
598 mVec[2] -= rhs[2];
599 return *this;
600 }
601
602 /// @brief Perform a component-wise minimum with the other Coord.
603 __hostdev__ constexpr Coord& minComponent(const Coord& other) noexcept
604 {
605 if (other[0] < mVec[0])
606 mVec[0] = other[0];
607 if (other[1] < mVec[1])
608 mVec[1] = other[1];
609 if (other[2] < mVec[2])
610 mVec[2] = other[2];
611 return *this;
612 }
613
614 /// @brief Perform a component-wise maximum with the other Coord.
615 __hostdev__ constexpr Coord& maxComponent(const Coord& other) noexcept
616 {
617 if (other[0] > mVec[0])
618 mVec[0] = other[0];
619 if (other[1] > mVec[1])
620 mVec[1] = other[1];
621 if (other[2] > mVec[2])
622 mVec[2] = other[2];
623 return *this;
624 }
625#if defined(__CUDACC__) // the following functions only run on the GPU!
626 /// @brief Device-only @c atomicMin component-wise.
627 __device__ inline Coord& minComponentAtomic(const Coord& other) noexcept
628 {
629 atomicMin(&mVec[0], other[0]);
630 atomicMin(&mVec[1], other[1]);
631 atomicMin(&mVec[2], other[2]);
632 return *this;
633 }
634 /// @brief Device-only @c atomicMax component-wise.
635 __device__ inline Coord& maxComponentAtomic(const Coord& other) noexcept
636 {
637 atomicMax(&mVec[0], other[0]);
638 atomicMax(&mVec[1], other[1]);
639 atomicMax(&mVec[2], other[2]);
640 return *this;
641 }
642#endif
643
644 /// @brief Return a new @c Coord offset component-by-component by @a (dx, dy, dz).
645 __hostdev__ [[nodiscard]] constexpr Coord offsetBy(ValueType dx, ValueType dy, ValueType dz) const noexcept
646 {
647 return Coord(mVec[0] + dx, mVec[1] + dy, mVec[2] + dz);
648 }
649
650 /// @brief Return a new @c Coord offset by the same scalar @a n in every component.
651 __hostdev__ [[nodiscard]] constexpr Coord offsetBy(ValueType n) const noexcept { return this->offsetBy(n, n, n); }
652
653 /// Return true if any of the components of @a a are smaller than the
654 /// corresponding components of @a b.
655 __hostdev__ [[nodiscard]] static inline constexpr bool lessThan(const Coord& a, const Coord& b) noexcept
656 {
657 return (a[0] < b[0] || a[1] < b[1] || a[2] < b[2]);
658 }
659
660 /// @brief Return the largest integer coordinates that are not greater
661 /// than @a xyz (node centered conversion).
662 template<typename Vec3T>
663 __hostdev__ [[nodiscard]] static Coord Floor(const Vec3T& xyz) noexcept { return Coord(math::Floor(xyz[0]), math::Floor(xyz[1]), math::Floor(xyz[2])); }
664
665 /// @brief Return a hash key derived from the existing coordinates.
666 /// @details The hash function is originally taken from the SIGGRAPH paper:
667 /// "VDB: High-resolution sparse volumes with dynamic topology"
668 /// and the prime numbers are modified based on the ACM Transactions on Graphics paper:
669 /// "Real-time 3D reconstruction at scale using voxel hashing" (the second number had a typo!)
670 template<int Log2N = 3 + 4 + 5>
671 __hostdev__ [[nodiscard]] constexpr uint32_t hash() const noexcept { return ((1 << Log2N) - 1) & (mVec[0] * 73856093 ^ mVec[1] * 19349669 ^ mVec[2] * 83492791); }
672
673 /// @brief Return the octant of this Coord
674 __hostdev__ [[nodiscard]] constexpr uint8_t octant() const noexcept { return uint8_t((uint8_t(bool(mVec[0] & (1u << 31)))) |
675 (uint8_t(bool(mVec[1] & (1u << 31))) << 1) |
676 (uint8_t(bool(mVec[2] & (1u << 31))) << 2)); }
677
678 /// @brief Return a single precision floating-point vector of this coordinate
679 __hostdev__ [[nodiscard]] inline constexpr Vec3<float> asVec3s() const noexcept;
680
681 /// @brief Return a double precision floating-point vector of this coordinate
682 __hostdev__ [[nodiscard]] inline constexpr Vec3<double> asVec3d() const noexcept;
683
684 /// @brief Identity (Coord is already integer); provided so generic code
685 /// can call @c .round() uniformly on @c Coord and @c Vec3<T>.
686 __hostdev__ [[nodiscard]] inline constexpr Coord round() const noexcept { return *this; }
687}; // Coord class
688
689
690/// @brief Type alias for Coord so we have a consistent naming convention
691using Coord3 = Coord;
692
693
694template <typename T>
695class Vec2;
696
697/// @brief Signed (i, j) 32-bit integer coordinate class, similar to openvdb::math::Coord
699{
700 int32_t mVec[2]; // private member data - three signed index coordinates
701public:
702 using ValueType = int32_t;
703 using IndexType = uint32_t;
704
705 /// @brief Initialize all coordinates to zero.
706 __hostdev__ constexpr Coord2() noexcept
707 : mVec{0, 0}
708 {
709 }
710
711 /// @brief Initializes all coordinates to the given signed integer.
712 __hostdev__ explicit constexpr Coord2(ValueType n) noexcept
713 : mVec{n, n}
714 {
715 }
716
717 /// @brief Initializes coordinate to the given signed integers.
718 __hostdev__ constexpr Coord2(ValueType i, ValueType j) noexcept
719 : mVec{i, j}
720 {
721 }
722
723 /// @brief Read two signed integers from @a ptr (no bounds check).
724 __hostdev__ constexpr Coord2(ValueType* ptr) noexcept
725 : mVec{ptr[0], ptr[1]}
726 {
727 }
728
729 //@{
730 /// @brief Named component accessors (x = mVec[0], y = mVec[1]).
731 __hostdev__ constexpr int32_t x() const noexcept { return mVec[0]; }
732 __hostdev__ constexpr int32_t y() const noexcept { return mVec[1]; }
733
734 __hostdev__ constexpr int32_t& x() noexcept { return mVec[0]; }
735 __hostdev__ constexpr int32_t& y() noexcept { return mVec[1]; }
736 //@}
737
738 /// @brief Largest representable @c Coord2 (all components = INT32_MAX).
739 __hostdev__ [[nodiscard]] static constexpr Coord2 max() noexcept { return Coord2(int32_t((1u << 31) - 1)); }
740
741 /// @brief Smallest representable @c Coord2 (all components = INT32_MIN).
742 __hostdev__ [[nodiscard]] static constexpr Coord2 min() noexcept { return Coord2(-int32_t((1u << 31) - 1) - 1); }
743
744 /// @brief Byte size of a @c Coord2 (always 8 on a 32-bit @c int32_t platform).
745 __hostdev__ [[nodiscard]] static constexpr size_t memUsage() noexcept { return sizeof(Coord2); }
746
747 /// @brief Return a const reference to the given Coord component.
748 /// @warning The argument is assumed to be 0 or 1,
749 __hostdev__ constexpr const ValueType& operator[](IndexType i) const noexcept { NANOVDB_ASSERT(i < 2); return mVec[i]; }
750
751 /// @brief Return a non-const reference to the given Coord component.
752 /// @warning The argument is assumed to be 0 or 1.
753 __hostdev__ constexpr ValueType& operator[](IndexType i) noexcept { NANOVDB_ASSERT(i < 2); return mVec[i]; }
754
755 /// @brief Assignment operator that works with openvdb::Coord
756 template<typename CoordT>
757 __hostdev__ constexpr Coord2& operator=(const CoordT& other) noexcept
758 {
759 static_assert(sizeof(Coord2) == sizeof(CoordT), "Mis-matched sizeof");
760 mVec[0] = other[0];
761 mVec[1] = other[1];
762 return *this;
763 }
764
765 /// @brief Return a new instance with coordinates masked by the given unsigned integer.
766 __hostdev__ [[nodiscard]] constexpr Coord2 operator&(IndexType n) const noexcept { return Coord2(mVec[0] & n, mVec[1] & n); }
767
768 /// @brief Return a new instance with coordinates left-shifted by the given unsigned integer.
769 __hostdev__ [[nodiscard]] constexpr Coord2 operator<<(IndexType n) const noexcept { return Coord2(mVec[0] << n, mVec[1] << n); }
770
771 /// @brief Return a new instance with coordinates right-shifted by the given unsigned integer.
772 __hostdev__ [[nodiscard]] constexpr Coord2 operator>>(IndexType n) const noexcept { return Coord2(mVec[0] >> n, mVec[1] >> n); }
773
774 /// @brief Return true if this Coord is lexicographically less than the given Coord.
775 __hostdev__ [[nodiscard]] constexpr bool operator<(const Coord2& rhs) const noexcept
776 {
777 return mVec[0] < rhs[0] ? true
778 : mVec[0] > rhs[0] ? false
779 : mVec[1] < rhs[1] ? true : false;
780 }
781
782 /// @brief Return true if this Coord is lexicographically less or equal to the given Coord.
783 __hostdev__ [[nodiscard]] constexpr bool operator<=(const Coord2& rhs) const noexcept
784 {
785 return mVec[0] < rhs[0] ? true
786 : mVec[0] > rhs[0] ? false
787 : mVec[1] <= rhs[1] ? true : false;
788 }
789
790 /// @brief Return true if this Coord is lexicographically greater than the given Coord.
791 __hostdev__ [[nodiscard]] constexpr bool operator>(const Coord2& rhs) const noexcept
792 {
793 return mVec[0] > rhs[0] ? true
794 : mVec[0] < rhs[0] ? false
795 : mVec[1] > rhs[1] ? true : false;
796 }
797
798 /// @brief Return true if this Coord is lexicographically greater or equal to the given Coord.
799 __hostdev__ [[nodiscard]] constexpr bool operator>=(const Coord2& rhs) const noexcept
800 {
801 return mVec[0] > rhs[0] ? true
802 : mVec[0] < rhs[0] ? false
803 : mVec[1] >= rhs[1] ? true : false;
804 }
805
806 /// @brief Return true iff every component matches @a rhs.
807 __hostdev__ [[nodiscard]] constexpr bool operator==(const Coord2& rhs) const noexcept { return mVec[0] == rhs[0] && mVec[1] == rhs[1]; }
808 /// @brief Return true iff any component differs from @a rhs.
809 __hostdev__ [[nodiscard]] constexpr bool operator!=(const Coord2& rhs) const noexcept { return mVec[0] != rhs[0] || mVec[1] != rhs[1]; }
810 /// @brief In-place component-wise bitwise AND with the given mask.
811 __hostdev__ constexpr Coord2& operator&=(int n) noexcept
812 {
813 mVec[0] &= n;
814 mVec[1] &= n;
815 return *this;
816 }
817 /// @brief In-place left-shift of every component by @a n bits.
818 __hostdev__ constexpr Coord2& operator<<=(uint32_t n) noexcept
819 {
820 mVec[0] <<= n;
821 mVec[1] <<= n;
822 return *this;
823 }
824 /// @brief In-place right-shift of every component by @a n bits.
825 __hostdev__ constexpr Coord2& operator>>=(uint32_t n) noexcept
826 {
827 mVec[0] >>= n;
828 mVec[1] >>= n;
829 return *this;
830 }
831 /// @brief Add a scalar to every component in place.
832 __hostdev__ constexpr Coord2& operator+=(int n) noexcept
833 {
834 mVec[0] += n;
835 mVec[1] += n;
836 return *this;
837 }
838 /// @brief Component-wise sum of two coordinates.
839 __hostdev__ [[nodiscard]] constexpr Coord2 operator+(const Coord2& rhs) const noexcept { return Coord2(mVec[0] + rhs[0], mVec[1] + rhs[1]); }
840 /// @brief Component-wise difference of two coordinates.
841 __hostdev__ [[nodiscard]] constexpr Coord2 operator-(const Coord2& rhs) const noexcept { return Coord2(mVec[0] - rhs[0], mVec[1] - rhs[1]); }
842 /// @brief Component-wise negation.
843 __hostdev__ [[nodiscard]] constexpr Coord2 operator-() const noexcept { return Coord2(-mVec[0], -mVec[1]); }
844 /// @brief In-place component-wise addition with another coordinate.
845 __hostdev__ constexpr Coord2& operator+=(const Coord2& rhs) noexcept
846 {
847 mVec[0] += rhs[0];
848 mVec[1] += rhs[1];
849 return *this;
850 }
851 /// @brief In-place component-wise subtraction with another coordinate.
852 __hostdev__ constexpr Coord2& operator-=(const Coord2& rhs) noexcept
853 {
854 mVec[0] -= rhs[0];
855 mVec[1] -= rhs[1];
856 return *this;
857 }
858
859 /// @brief Perform a component-wise minimum with the other Coord.
860 __hostdev__ constexpr Coord2& minComponent(const Coord2& other) noexcept
861 {
862 if (other[0] < mVec[0])
863 mVec[0] = other[0];
864 if (other[1] < mVec[1])
865 mVec[1] = other[1];
866 return *this;
867 }
868
869 /// @brief Perform a component-wise maximum with the other Coord.
870 __hostdev__ constexpr Coord2& maxComponent(const Coord2& other) noexcept
871 {
872 if (other[0] > mVec[0])
873 mVec[0] = other[0];
874 if (other[1] > mVec[1])
875 mVec[1] = other[1];
876 return *this;
877 }
878#if defined(__CUDACC__) // the following functions only run on the GPU!
879 /// @brief Device-only @c atomicMin component-wise.
880 __device__ inline Coord2& minComponentAtomic(const Coord2& other) noexcept
881 {
882 atomicMin(&mVec[0], other[0]);
883 atomicMin(&mVec[1], other[1]);
884 return *this;
885 }
886 /// @brief Device-only @c atomicMax component-wise.
887 __device__ inline Coord2& maxComponentAtomic(const Coord2& other) noexcept
888 {
889 atomicMax(&mVec[0], other[0]);
890 atomicMax(&mVec[1], other[1]);
891 return *this;
892 }
893#endif
894
895 /// @brief Return a new @c Coord2 offset component-by-component by @a (dx, dy).
896 __hostdev__ [[nodiscard]] constexpr Coord2 offsetBy(ValueType dx, ValueType dy) const noexcept
897 {
898 return Coord2(mVec[0] + dx, mVec[1] + dy);
899 }
900
901 /// @brief Return a new @c Coord2 offset by the same scalar @a n in both components.
902 __hostdev__ [[nodiscard]] constexpr Coord2 offsetBy(ValueType n) const noexcept { return this->offsetBy(n, n); }
903
904 /// Return true if any of the components of @a a are smaller than the
905 /// corresponding components of @a b.
906 __hostdev__ [[nodiscard]] static inline constexpr bool lessThan(const Coord2& a, const Coord2& b) noexcept
907 {
908 return (a[0] < b[0] || a[1] < b[1]);
909 }
910
911 /// @brief Return the largest integer coordinates that are not greater
912 /// than @a xyz (node centered conversion).
913 template<typename Vec2T>
914 __hostdev__ [[nodiscard]] static Coord2 Floor(const Vec2T& xy) noexcept { return Coord2(math::Floor(xy[0]), math::Floor(xy[1])); }
915
916 /// @brief Return a single precision floating-point vector of this coordinate
917 __hostdev__ [[nodiscard]] inline constexpr Vec2<float> asVec2s() const noexcept;
918
919 /// @brief Return a double precision floating-point vector of this coordinate
920 __hostdev__ [[nodiscard]] inline constexpr Vec2<double> asVec2d() const noexcept;
921
922 /// @brief Identity (Coord2 is already integer); provided so generic code
923 /// can call @c .round() uniformly on @c Coord2 and @c Vec2<T>.
924 __hostdev__ [[nodiscard]] inline constexpr Coord2 round() const noexcept { return *this; }
925}; // Coord2 class
926
927// ----------------------------> VecBase <-----------------------------------
928
929/// @brief Base class for fixed-size vectors. Provides shared element-wise
930/// arithmetic, scalar arithmetic, equality, length/dot reductions,
931/// component min/max, and integer-coord rounding. Derived classes provide
932/// constructors and any dimension-specific extras (e.g. cross/outer on Vec3).
933template<typename T, int N>
935{
936protected:
937 T mVec[N];
938
939public:
940 using ValueType = T;
941 static constexpr int SIZE = N;
942
943 /// @brief Default-construct (mVec is left uninitialized for trivially-default-constructible @c T).
944 VecBase() noexcept = default;
945
946protected:
947 /// @brief Variadic component-init ctor — used only by derived ctors
948 /// (`Vec2(T x, T y) : Base(x, y) {}`). The member-init list directly
949 /// initializes @c mVec, avoiding the default-construct-then-assign that
950 /// a body-assignment ctor would impose on a non-fundamental @c T.
951 template<typename... Args>
952 __hostdev__ explicit constexpr VecBase(Args... args) noexcept : mVec{T(args)...}
953 {
954 static_assert(sizeof...(Args) == N, "VecBase: wrong number of constructor arguments");
955 }
956
957 /// @brief Return a @c Derived whose component @c i is @c f(i), built through its
958 /// N-component constructor. This is constexpr-valid in C++17 without first
959 /// value-initializing a result and overwriting it.
960 template<typename Derived, typename F, int... I>
961 __hostdev__ static constexpr Derived generate(F f, std::integer_sequence<int, I...>) noexcept
962 {
963 return Derived(typename Derived::ValueType(f(I))...);
964 }
965 template<typename Derived, typename F>
966 __hostdev__ static constexpr Derived generate(F f) noexcept
967 {
968 return generate<Derived>(f, std::make_integer_sequence<int, N>{});
969 }
970
971public:
972 /// @brief Indexed element access. Asserts 0 <= i < N in debug builds.
973 __hostdev__ constexpr const T& operator[](int i) const noexcept { NANOVDB_ASSERT(i >= 0 && i < N); return mVec[i]; }
974 __hostdev__ constexpr T& operator[](int i) noexcept { NANOVDB_ASSERT(i >= 0 && i < N); return mVec[i]; }
975
976 __hostdev__ constexpr const T& x() const noexcept { return mVec[0]; }
977 __hostdev__ constexpr T& x() noexcept { return mVec[0]; }
978 __hostdev__ constexpr const T& y() const noexcept { static_assert(N >= 2, "VecBase::y() requires N >= 2"); return mVec[1]; }
979 __hostdev__ constexpr T& y() noexcept { static_assert(N >= 2, "VecBase::y() requires N >= 2"); return mVec[1]; }
980 __hostdev__ constexpr const T& z() const noexcept { static_assert(N >= 3, "VecBase::z() requires N >= 3"); return mVec[2]; }
981 __hostdev__ constexpr T& z() noexcept { static_assert(N >= 3, "VecBase::z() requires N >= 3"); return mVec[2]; }
982 __hostdev__ constexpr const T& w() const noexcept { static_assert(N >= 4, "VecBase::w() requires N >= 4"); return mVec[3]; }
983 __hostdev__ constexpr T& w() noexcept { static_assert(N >= 4, "VecBase::w() requires N >= 4"); return mVec[3]; }
984
985 /// @brief raw pointer to the underlying N-element storage
986 __hostdev__ constexpr T* asPointer() noexcept { return mVec; }
987 __hostdev__ constexpr const T* asPointer() const noexcept { return mVec; }
988
989 // ---- generic element-wise helpers (taking/returning Derived) ----
990
991 /// @brief Return @c *this + @a rhs as a @c Derived.
992 template<typename Derived>
993 __hostdev__ [[nodiscard]] constexpr Derived plus(const Derived& rhs) const noexcept {
994 return generate<Derived>([&](int i) { return mVec[i] + rhs[i]; });
995 }
996 /// @brief Return @c *this - @a rhs as a @c Derived.
997 template<typename Derived>
998 __hostdev__ [[nodiscard]] constexpr Derived minus(const Derived& rhs) const noexcept {
999 return generate<Derived>([&](int i) { return mVec[i] - rhs[i]; });
1000 }
1001 /// @brief Return component-wise @c *this * @a rhs as a @c Derived (Hadamard product).
1002 template<typename Derived>
1003 __hostdev__ [[nodiscard]] constexpr Derived mul(const Derived& rhs) const noexcept {
1004 return generate<Derived>([&](int i) { return mVec[i] * rhs[i]; });
1005 }
1006 /// @brief Return component-wise @c *this / @a rhs as a @c Derived.
1007 template<typename Derived>
1008 __hostdev__ [[nodiscard]] constexpr Derived div(const Derived& rhs) const noexcept {
1009 return generate<Derived>([&](int i) { return mVec[i] / rhs[i]; });
1010 }
1011 /// @brief Return @c -(*this) as a @c Derived.
1012 template<typename Derived>
1013 __hostdev__ [[nodiscard]] constexpr Derived negate() const noexcept {
1014 return generate<Derived>([&](int i) { return -mVec[i]; });
1015 }
1016 /// @brief Return @c s * (*this) as a @c Derived (scalar broadcast).
1017 template<typename Derived>
1018 __hostdev__ [[nodiscard]] constexpr Derived scale(T s) const noexcept {
1019 return generate<Derived>([&](int i) { return mVec[i] * s; });
1020 }
1021 /// @brief Return @c (*this) / @a s element-wise as a @c Derived. Floating-point
1022 /// @c T multiplies by the reciprocal @c 1/s; integer @c T divides each element,
1023 /// since @c 1/s would truncate to zero.
1024 template<typename Derived>
1025 __hostdev__ [[nodiscard]] constexpr Derived divideBy(T s) const noexcept {
1026 if constexpr (std::is_floating_point<T>::value) {
1027 return this->template scale<Derived>(T(1) / s);
1028 } else {
1029 return generate<Derived>([&](int i) { return mVec[i] / s; });
1030 }
1031 }
1032 /// @brief Return a unit-length copy (@c *this divided by @c length()) as a @c Derived.
1033 /// Const, non-mutating counterpart of the derived @c normalize(). Not @c constexpr —
1034 /// @c length() calls @c Sqrt.
1035 template<typename Derived>
1036 __hostdev__ [[nodiscard]] Derived normalized() const noexcept {
1037 return this->template divideBy<Derived>(this->length());
1038 }
1039
1040 // ---- in-place compound assignment helpers ----
1041
1042 /// @brief Component-wise add @a rhs into @c *this and return @c *this.
1043 __hostdev__ constexpr VecBase& addAssign(const VecBase& rhs) noexcept {
1044 for (int i = 0; i < N; ++i) mVec[i] += rhs.mVec[i];
1045 return *this;
1046 }
1047 /// @brief Component-wise subtract @a rhs from @c *this and return @c *this.
1048 __hostdev__ constexpr VecBase& subAssign(const VecBase& rhs) noexcept {
1049 for (int i = 0; i < N; ++i) mVec[i] -= rhs.mVec[i];
1050 return *this;
1051 }
1052 /// @brief Component-wise multiply @c *this by @a rhs (Hadamard product) and return @c *this.
1053 __hostdev__ constexpr VecBase& mulAssign(const VecBase& rhs) noexcept {
1054 for (int i = 0; i < N; ++i) mVec[i] *= rhs.mVec[i];
1055 return *this;
1056 }
1057 /// @brief Component-wise divide @c *this by @a rhs and return @c *this.
1058 __hostdev__ constexpr VecBase& divAssign(const VecBase& rhs) noexcept {
1059 for (int i = 0; i < N; ++i) mVec[i] /= rhs.mVec[i];
1060 return *this;
1061 }
1062 /// @brief Multiply every component by scalar @a s in place; return @c *this.
1063 /// @a s is taken by value so @c v *= v[0] scales every component by the original value.
1064 __hostdev__ constexpr VecBase& scaleAssign(T s) noexcept {
1065 for (int i = 0; i < N; ++i) mVec[i] *= s;
1066 return *this;
1067 }
1068 /// @brief Divide every component by scalar @a s in place; return @c *this.
1069 /// Uses the same floating-point reciprocal / integer per-element split as
1070 /// @c divideBy. @a s is taken by value so @c v /= v[0] is safe.
1071 __hostdev__ constexpr VecBase& divideAssignScalar(T s) noexcept {
1072 if constexpr (std::is_floating_point<T>::value) {
1073 return this->scaleAssign(T(1) / s);
1074 } else {
1075 for (int i = 0; i < N; ++i) mVec[i] /= s;
1076 return *this;
1077 }
1078 }
1079
1080 /// @brief Return @c true iff every component compares equal to @a rhs.
1081 __hostdev__ [[nodiscard]] constexpr bool equals(const VecBase& rhs) const noexcept {
1082 for (int i = 0; i < N; ++i) if (mVec[i] != rhs.mVec[i]) return false;
1083 return true;
1084 }
1085
1086 // ---- reductions ----
1087
1088 /// @brief dot product. @a V must have @c operator[] valid for 0..N-1.
1089 /// Sums in the promoted type of the element products and converts to @c T
1090 /// once on return, so e.g. @c Vec3i::dot(Vec3d) does not truncate partial sums.
1091 template<typename V>
1092 __hostdev__ [[nodiscard]] constexpr T dot(const V& v) const noexcept {
1093 auto s = mVec[0] * v[0];
1094 for (int i = 1; i < N; ++i) s += mVec[i] * v[i];
1095 return T(s);
1096 }
1097 /// @brief Squared L2 length (sum of squared components). Constexpr, no sqrt.
1098 __hostdev__ [[nodiscard]] constexpr T lengthSqr() const noexcept {
1099 auto s = mVec[0] * mVec[0];
1100 for (int i = 1; i < N; ++i) s += mVec[i] * mVec[i];
1101 return T(s);
1102 }
1103 /// @brief L2 length (Euclidean norm). Not @c constexpr — calls @c Sqrt.
1104 __hostdev__ [[nodiscard]] T length() const noexcept { return Sqrt(this->lengthSqr()); }
1105
1106 /// @brief return the smallest of the N components
1107 __hostdev__ [[nodiscard]] constexpr T smallestComponent() const noexcept {
1108 T m = mVec[0];
1109 for (int i = 1; i < N; ++i) if (mVec[i] < m) m = mVec[i];
1110 return m;
1111 }
1112 /// @brief return the largest of the N components
1113 __hostdev__ [[nodiscard]] constexpr T largestComponent() const noexcept {
1114 T m = mVec[0];
1115 for (int i = 1; i < N; ++i) if (mVec[i] > m) m = mVec[i];
1116 return m;
1117 }
1118
1119 // ---- component-wise (mutating) min/max ----
1120
1121 /// @brief Component-wise take the @c min of @c *this and @a other (in place); return @c *this.
1122 template<typename V>
1123 __hostdev__ constexpr VecBase& mergeMin(const V& other) noexcept {
1124 for (int i = 0; i < N; ++i) if (other[i] < mVec[i]) mVec[i] = other[i];
1125 return *this;
1126 }
1127 /// @brief Component-wise take the @c max of @c *this and @a other (in place); return @c *this.
1128 template<typename V>
1129 __hostdev__ constexpr VecBase& mergeMax(const V& other) noexcept {
1130 for (int i = 0; i < N; ++i) if (other[i] > mVec[i]) mVec[i] = other[i];
1131 return *this;
1132 }
1133
1134 // ---- integer rounding (toward -inf / +inf / nearest) ----
1135 //
1136
1137 /// @brief floor-rounded components into the @c Result type (whose @c [i]
1138 /// must accept int32_t). For integer @c T the value is passed through.
1139 /// @note Only the integer-@c T specialization is usable as a constant
1140 /// expression; the floating-point branch calls @c math::Floor, which
1141 /// isn't constexpr until C++23.
1142 template<typename Result>
1143 __hostdev__ [[nodiscard]] constexpr Result floorAs() const noexcept {
1144 Result r{};
1145 if constexpr (std::is_floating_point<T>::value) {
1146 for (int i = 0; i < N; ++i) r[i] = math::Floor(mVec[i]);
1147 } else {
1148 for (int i = 0; i < N; ++i) r[i] = static_cast<int32_t>(mVec[i]);
1149 }
1150 return r;
1151 }
1152 /// @brief ceil-rounded components into the @c Result type (whose @c [i]
1153 /// must accept int32_t). For integer @c T the value is passed through.
1154 /// @note Only the integer-@c T specialization is usable as a constant
1155 /// expression; the floating-point branch calls @c math::Ceil, which
1156 /// isn't constexpr until C++23.
1157 template<typename Result>
1158 __hostdev__ [[nodiscard]] constexpr Result ceilAs() const noexcept {
1159 Result r{};
1160 if constexpr (std::is_floating_point<T>::value) {
1161 for (int i = 0; i < N; ++i) r[i] = math::Ceil(mVec[i]);
1162 } else {
1163 for (int i = 0; i < N; ++i) r[i] = static_cast<int32_t>(mVec[i]);
1164 }
1165 return r;
1166 }
1167 /// @brief nearest-integer rounding for floating @c T via the scalar
1168 /// @c math::Round (halfway cases toward +inf, exact for every input), so
1169 /// float and double agree; pass-through for integer @c T.
1170 /// @note See @c floorAs — only the integer-@c T branch is constexpr-usable.
1171 template<typename Result>
1172 __hostdev__ [[nodiscard]] constexpr Result roundAs() const noexcept {
1173 Result r{};
1174 if constexpr (std::is_floating_point<T>::value) {
1175 for (int i = 0; i < N; ++i) r[i] = math::Round(mVec[i]);
1176 } else {
1177 for (int i = 0; i < N; ++i) r[i] = static_cast<int32_t>(mVec[i]);
1178 }
1179 return r;
1180 }
1181}; // VecBase<T, N>
1182
1183// ----------------------------> Vec2 <--------------------------------------
1184
1185/// @brief A simple vector class with two components, similar to openvdb::math::Vec2
1186///
1187/// Naturally aligned (@c alignof(T)), like all Vec/Mat classes. Raising the
1188/// alignment would change the layout of every struct and buffer that holds one;
1189/// use @c Vec2Aligned for over-aligned arrays.
1190template<typename T>
1191class Vec2 : public VecBase<T, 2>
1192{
1193 using Base = VecBase<T, 2>;
1194
1195public:
1196 using ValueType = T;
1197 static constexpr int size = 2; // openvdb::math::Tuple-compat alias of SIZE
1198
1199 /// @brief Default-construct (components are left uninitialized for fundamental @c T).
1200 Vec2() noexcept = default;
1201 /// @brief Broadcast: set both components to @a x.
1202 __hostdev__ explicit constexpr Vec2(T x) noexcept : Base(x, x) {}
1203 /// @brief Component-wise construction.
1204 __hostdev__ constexpr Vec2(T x, T y) noexcept : Base(x, y) {}
1205
1206 /// @brief Explicit cross-template converting ctor (e.g. from @c openvdb::Vec2).
1207 /// Convert a foreign vector with a cast, e.g. @c Vec2<float>(v).
1208 template<template<class> class Vec2T, class T2>
1209 __hostdev__ explicit constexpr Vec2(const Vec2T<T2>& v) noexcept : Base(v[0], v[1])
1210 {
1211 static_assert(Vec2T<T2>::size == 2, "expected Vec2T::size==2!");
1212 }
1213 /// @brief Explicit cross-precision conversion within nanovdb (e.g. @c Vec2d → @c Vec2f).
1214 template<typename T2>
1215 __hostdev__ explicit constexpr Vec2(const Vec2<T2>& v) noexcept : Base(v[0], v[1]) {}
1216 /// @brief Construct from a 2D integer coordinate.
1217 __hostdev__ explicit constexpr Vec2(const Coord2& ijk) noexcept : Base(ijk[0], ijk[1]) {}
1218
1219 /// @brief Assign from any 2-component vector type (foreign or nanovdb).
1220 template<template<class> class Vec2T, class T2>
1221 __hostdev__ constexpr Vec2& operator=(const Vec2T<T2>& rhs) noexcept {
1222 static_assert(Vec2T<T2>::size == 2, "expected Vec2T::size==2!");
1223 this->mVec[0] = rhs[0]; this->mVec[1] = rhs[1];
1224 return *this;
1225 }
1226
1227 // ---- element-wise (Vec & Vec) ----
1228 /// @brief Component-wise negation.
1229 __hostdev__ [[nodiscard]] constexpr Vec2 operator-() const noexcept { return Base::template negate<Vec2>(); }
1230 /// @brief Component-wise sum.
1231 __hostdev__ [[nodiscard]] constexpr Vec2 operator+(const Vec2& v) const noexcept { return Base::template plus<Vec2>(v); }
1232 /// @brief Component-wise difference.
1233 __hostdev__ [[nodiscard]] constexpr Vec2 operator-(const Vec2& v) const noexcept { return Base::template minus<Vec2>(v); }
1234 /// @brief Component-wise (Hadamard) product.
1235 __hostdev__ [[nodiscard]] constexpr Vec2 operator*(const Vec2& v) const noexcept { return Base::template mul<Vec2>(v); }
1236 /// @brief Component-wise division.
1237 __hostdev__ [[nodiscard]] constexpr Vec2 operator/(const Vec2& v) const noexcept { return Base::template div<Vec2>(v); }
1238 /// @brief In-place component-wise addition.
1239 __hostdev__ constexpr Vec2& operator+=(const Vec2& v) noexcept { Base::addAssign(v); return *this; }
1240 /// @brief In-place component-wise subtraction.
1241 __hostdev__ constexpr Vec2& operator-=(const Vec2& v) noexcept { Base::subAssign(v); return *this; }
1242
1243 // ---- mixed Vec2 / Coord2 ----
1244 /// @brief Add an integer @c Coord2 to this vector (component-wise).
1245 __hostdev__ [[nodiscard]] constexpr Vec2 operator+(const Coord2& ijk) const noexcept { return Vec2(this->mVec[0] + ijk[0], this->mVec[1] + ijk[1]); }
1246 /// @brief Subtract an integer @c Coord2 from this vector (component-wise).
1247 __hostdev__ [[nodiscard]] constexpr Vec2 operator-(const Coord2& ijk) const noexcept { return Vec2(this->mVec[0] - ijk[0], this->mVec[1] - ijk[1]); }
1248 /// @brief In-place component-wise addition of an integer @c Coord2.
1249 __hostdev__ constexpr Vec2& operator+=(const Coord2& ijk) noexcept {
1250 this->mVec[0] += T(ijk[0]); this->mVec[1] += T(ijk[1]);
1251 return *this;
1252 }
1253 /// @brief In-place component-wise subtraction of an integer @c Coord2.
1254 __hostdev__ constexpr Vec2& operator-=(const Coord2& ijk) noexcept {
1255 this->mVec[0] -= T(ijk[0]); this->mVec[1] -= T(ijk[1]);
1256 return *this;
1257 }
1258
1259 // ---- scalar ----
1260 /// @brief Component-wise multiply by scalar @a s.
1261 __hostdev__ [[nodiscard]] constexpr Vec2 operator*(const T& s) const noexcept { return Base::template scale<Vec2>(s); }
1262 /// @brief Component-wise divide by scalar @a s (integer-safe).
1263 __hostdev__ [[nodiscard]] constexpr Vec2 operator/(const T& s) const noexcept { return Base::template divideBy<Vec2>(s); }
1264 /// @brief In-place component-wise multiply by scalar @a s.
1265 __hostdev__ constexpr Vec2& operator*=(const T& s) noexcept { Base::scaleAssign(s); return *this; }
1266 /// @brief In-place component-wise divide by scalar @a s.
1267 __hostdev__ constexpr Vec2& operator/=(const T& s) noexcept { Base::divideAssignScalar(s); return *this; }
1268 /// @brief Normalize in place (divide by @c length()). Not @c constexpr — calls @c std::sqrt.
1269 __hostdev__ Vec2& normalize() noexcept { return (*this) /= this->length(); }
1270 /// @brief Return a normalized (unit-length) copy; const counterpart of @c normalize().
1271 __hostdev__ [[nodiscard]] Vec2 normalized() const noexcept {
1272 return Base::template normalized<Vec2>();
1273 }
1274
1275 // ---- equality ----
1276 /// @brief Component-wise equality.
1277 __hostdev__ [[nodiscard]] constexpr bool operator==(const Vec2& rhs) const noexcept { return Base::equals(rhs); }
1278 /// @brief Component-wise inequality.
1279 __hostdev__ [[nodiscard]] constexpr bool operator!=(const Vec2& rhs) const noexcept { return !Base::equals(rhs); }
1280
1281 // ---- component-wise min/max ----
1282 /// @brief Take the component-wise minimum of @c *this and @a other in place.
1283 __hostdev__ constexpr Vec2& minComponent(const Vec2& other) noexcept { Base::mergeMin(other); return *this; }
1284 /// @brief Take the component-wise maximum of @c *this and @a other in place.
1285 __hostdev__ constexpr Vec2& maxComponent(const Vec2& other) noexcept { Base::mergeMax(other); return *this; }
1286
1287 /// @brief Return the smallest vector component
1288 __hostdev__ [[nodiscard]] constexpr ValueType min() const noexcept { return Base::smallestComponent(); }
1289 /// @brief Return the largest vector component
1290 __hostdev__ [[nodiscard]] constexpr ValueType max() const noexcept { return Base::largestComponent(); }
1291
1292 /// @brief Round each component down (toward negative infinity)
1293 /// @return integer Coord2
1294 /// @note Only constexpr for integer @c T (floorAs uses non-constexpr math::Floor for floating point).
1295 __hostdev__ [[nodiscard]] constexpr Coord2 floor() const noexcept { return Base::template floorAs<Coord2>(); }
1296 /// @brief Round each component up (toward positive infinity)
1297 /// @return integer Coord2
1298 /// @note Only constexpr for integer @c T (ceilAs uses non-constexpr math::Ceil for floating point).
1299 __hostdev__ [[nodiscard]] constexpr Coord2 ceil() const noexcept { return Base::template ceilAs<Coord2>(); }
1300 /// @brief Round each component to its closest integer value
1301 /// @return integer Coord2
1302 /// @note Only constexpr for integer @c T (roundAs uses non-constexpr math::Round for floating point).
1303 __hostdev__ [[nodiscard]] constexpr Coord2 round() const noexcept { return Base::template roundAs<Coord2>(); }
1304
1305 // ---- scalar * Vec / scalar / Vec (hidden friends — found only via ADL on Vec2,
1306 // never participate in unrelated namespace-scope overload sets) ----
1307
1308 /// @brief Scalar-on-the-left multiplication (hidden friend).
1309 template<typename T1>
1310 __hostdev__ [[nodiscard]] friend constexpr Vec2 operator*(T1 scalar, const Vec2& vec) noexcept
1311 {
1312 return Vec2(scalar * vec[0], scalar * vec[1]);
1313 }
1314 /// @brief Scalar-on-the-left division (hidden friend).
1315 template<typename T1>
1316 __hostdev__ [[nodiscard]] friend constexpr Vec2 operator/(T1 scalar, const Vec2& vec) noexcept
1317 {
1318 return Vec2(scalar / vec[0], scalar / vec[1]);
1319 }
1320}; // Vec2<T>
1321
1322/// @brief Return a single precision floating-point vector of this coordinate
1323__hostdev__ [[nodiscard]] inline constexpr Vec2<float> Coord2::asVec2s() const noexcept
1324{
1325 return Vec2<float>(float(mVec[0]), float(mVec[1]));
1326}
1327
1328/// @brief Return a double precision floating-point vector of this coordinate
1329__hostdev__ [[nodiscard]] inline constexpr Vec2<double> Coord2::asVec2d() const noexcept
1330{
1331 return Vec2<double>(double(mVec[0]), double(mVec[1]));
1332}
1333
1334
1335/// @brief Base class for fixed-size matrices. Provides shared element-wise
1336/// arithmetic, scalar arithmetic, equality, transpose, mat*mat, and mat*vec.
1337/// Storage is a flat row-major array @c mData[ROWS * COLS]. Derived classes
1338/// supply constructors plus any dimension-specific extras (e.g. @c inverse()
1339/// on @c Mat2).
1340template<typename T, int ROWS, int COLS>
1341class MatBase {
1342protected:
1343 T mData[ROWS * COLS]; // 1D array storage
1344
1345public:
1346 using ValueType = T;
1347
1348 /// @brief Compile-time row count.
1349 __hostdev__ [[nodiscard]] static constexpr int rows() noexcept { return ROWS; }
1350 /// @brief Compile-time column count.
1351 __hostdev__ [[nodiscard]] static constexpr int cols() noexcept { return COLS; }
1352 /// @brief Compile-time element count, i.e. @c ROWS * @c COLS.
1353 __hostdev__ [[nodiscard]] static constexpr int size() noexcept { return ROWS * COLS; }
1354
1355 /// @brief Default-construct (entries are left uninitialized for trivially-default-constructible @c T).
1356 MatBase() noexcept = default;
1357
1358 /// @brief Read @c ROWS*COLS elements from @a array in row-major order, converting each
1359 /// element from @c S to @c T via @c static_cast.
1360 template<typename S>
1361 __hostdev__ constexpr MatBase(S* array) noexcept {
1362 for (int i = 0; i < size(); ++i) {
1363 mData[i] = static_cast<T>(array[i]);
1364 }
1365 }
1366
1367protected:
1368 /// @brief Variadic component-init ctor — used only by derived ctors
1369 /// (`Mat2(T a, T b, T c, T d) : Base(a, b, c, d) {}`). The member-init
1370 /// list directly initializes @c mData, avoiding the default-construct-
1371 /// then-assign that a body-assignment ctor would impose on a
1372 /// non-fundamental @c T.
1373 template<typename... Args>
1374 __hostdev__ explicit constexpr MatBase(Args... args) noexcept : mData{T(args)...}
1375 {
1376 static_assert(sizeof...(Args) == ROWS * COLS, "MatBase: wrong number of constructor arguments");
1377 }
1378
1379 /// @brief Return a @c Result whose row-major element @c idx is @c f(idx), built
1380 /// through its @a Count-element constructor. This is constexpr-valid in C++17
1381 /// without first value-initializing a result and overwriting it.
1382 template<typename Result, typename F, int... I>
1383 __hostdev__ static constexpr Result generate(F f, std::integer_sequence<int, I...>) noexcept
1384 {
1385 return Result(typename Result::ValueType(f(I))...);
1386 }
1387 template<typename Result, int Count = ROWS * COLS, typename F>
1388 __hostdev__ static constexpr Result generate(F f) noexcept
1389 {
1390 return generate<Result>(f, std::make_integer_sequence<int, Count>{});
1391 }
1392
1393public:
1394
1395 /// @brief 2D row access. Returns a pointer to the start of @a row; the caller
1396 /// indexes into it with the column. Asserts @c 0 <= @a row < @c ROWS in debug
1397 /// builds; column index is the caller's responsibility (use @c 0 <= col < @c COLS).
1398 __hostdev__ constexpr T* operator[](int row) noexcept {
1399 NANOVDB_ASSERT(row >= 0 && row < ROWS);
1400 return &mData[row * COLS];
1401 }
1402 /// @brief Const overload of @c operator[](int); see non-const variant.
1403 __hostdev__ constexpr const T* operator[](int row) const noexcept {
1404 NANOVDB_ASSERT(row >= 0 && row < ROWS);
1405 return &mData[row * COLS];
1406 }
1407
1408 /// @brief return a raw pointer to the underlying 1D storage (row-major)
1409 __hostdev__ constexpr T* data() noexcept { return mData; }
1410 /// @brief return a const raw pointer to the underlying 1D storage (row-major)
1411 __hostdev__ constexpr const T* data() const noexcept { return mData; }
1412
1413 // ---- generic element-wise helpers ----
1414
1415 /// @brief return @c *this + @a rhs as a @c Derived
1416 template<typename Derived>
1417 __hostdev__ [[nodiscard]] constexpr Derived plus(const Derived& rhs) const noexcept {
1418 return generate<Derived>([&](int i) { return mData[i] + rhs.data()[i]; });
1419 }
1420
1421 /// @brief return @c *this - @a rhs as a @c Derived
1422 template<typename Derived>
1423 __hostdev__ [[nodiscard]] constexpr Derived minus(const Derived& rhs) const noexcept {
1424 return generate<Derived>([&](int i) { return mData[i] - rhs.data()[i]; });
1425 }
1426
1427 /// @brief return -(*this) as a @c Derived
1428 template<typename Derived>
1429 __hostdev__ [[nodiscard]] constexpr Derived negate() const noexcept {
1430 return generate<Derived>([&](int i) { return -mData[i]; });
1431 }
1432
1433 /// @brief return @a s * (*this) as a @c Derived
1434 template<typename Derived>
1435 __hostdev__ [[nodiscard]] constexpr Derived scale(T s) const noexcept {
1436 return generate<Derived>([&](int i) { return mData[i] * s; });
1437 }
1438
1439 /// @brief Element-wise add @a rhs into @c *this and return @c *this.
1440 __hostdev__ constexpr MatBase& addAssign(const MatBase& rhs) noexcept {
1441 for (int i = 0; i < size(); ++i) mData[i] += rhs.mData[i];
1442 return *this;
1443 }
1444 /// @brief Element-wise subtract @a rhs from @c *this and return @c *this.
1445 __hostdev__ constexpr MatBase& subAssign(const MatBase& rhs) noexcept {
1446 for (int i = 0; i < size(); ++i) mData[i] -= rhs.mData[i];
1447 return *this;
1448 }
1449 /// @brief Multiply every element by scalar @a s in place; return @c *this.
1450 /// @a s is taken by value so @c m *= m[0][0] scales every element by the original value.
1451 __hostdev__ constexpr MatBase& scaleAssign(T s) noexcept {
1452 for (int i = 0; i < size(); ++i) mData[i] *= s;
1453 return *this;
1454 }
1455
1456 /// @brief return (*this) / @a s element-wise as a @c Derived. Floating-point
1457 /// @c T multiplies by the reciprocal @c 1/s; integer @c T divides each element,
1458 /// since @c 1/s would truncate to zero.
1459 template<typename Derived>
1460 __hostdev__ [[nodiscard]] constexpr Derived divideBy(T s) const noexcept {
1461 if constexpr (std::is_floating_point<T>::value) {
1462 return this->template scale<Derived>(T(1) / s);
1463 } else {
1464 return generate<Derived>([&](int i) { return mData[i] / s; });
1465 }
1466 }
1467 /// @brief Divide every element by scalar @a s in place; return @c *this.
1468 /// Uses the same floating-point reciprocal / integer per-element split as
1469 /// @c divideBy. @a s is taken by value so @c m /= m[0][0] is safe.
1470 __hostdev__ constexpr MatBase& divideAssignScalar(T s) noexcept {
1471 if constexpr (std::is_floating_point<T>::value) {
1472 return this->scaleAssign(T(1) / s);
1473 } else {
1474 for (int i = 0; i < size(); ++i) mData[i] /= s;
1475 return *this;
1476 }
1477 }
1478
1479 /// @brief Return @c true iff every element compares equal to @a rhs.
1480 __hostdev__ [[nodiscard]] constexpr bool equals(const MatBase& rhs) const noexcept {
1481 for (int i = 0; i < size(); ++i) if (mData[i] != rhs.mData[i]) return false;
1482 return true;
1483 }
1484
1485 // ---- generic transpose ----
1486
1487 /// @brief return the transpose of @c *this as the @c Result type.
1488 /// @tparam Result a matrix type whose dimensions are (COLS, ROWS)
1489 template<typename Result>
1490 __hostdev__ [[nodiscard]] constexpr Result transposeAs() const noexcept {
1491 static_assert(Result::rows() == COLS && Result::cols() == ROWS,
1492 "transposeAs: result dims must be (COLS, ROWS)");
1493 // Result element (j, i) sits at row-major index j * ROWS + i.
1494 return generate<Result>([&](int idx) { return mData[(idx % ROWS) * COLS + idx / ROWS]; });
1495 }
1496
1497 // ---- generic matrix * matrix ----
1498
1499 /// @brief return (*this) * @a rhs as the @c Result type.
1500 /// @tparam Result a matrix type whose dimensions are (ROWS, Rhs::cols())
1501 /// @tparam Rhs a matrix type whose row count equals @c COLS
1502 template<typename Result, typename Rhs>
1503 __hostdev__ [[nodiscard]] constexpr Result multiply(const Rhs& rhs) const noexcept {
1504 static_assert(COLS == Rhs::rows(), "multiply: lhs.cols must equal rhs.rows");
1505 static_assert(Result::rows() == ROWS && Result::cols() == Rhs::cols(),
1506 "multiply: result dims mismatch");
1507 return generate<Result, ROWS * Rhs::cols()>([&](int idx) {
1508 const int i = idx / Rhs::cols(), j = idx % Rhs::cols();
1509 T sum = mData[i * COLS] * rhs[0][j];
1510 for (int k = 1; k < COLS; ++k) sum += mData[i * COLS + k] * rhs[k][j];
1511 return sum;
1512 });
1513 }
1514
1515 // ---- generic matrix * vector ----
1516
1517 /// @brief return (*this) * @a v as the @c VecResult type.
1518 /// @tparam VecResult a vector type whose @c SIZE equals @c ROWS
1519 /// @tparam VecRhs a vector type whose @c SIZE equals @c COLS
1520 template<typename VecResult, typename VecRhs>
1521 __hostdev__ [[nodiscard]] constexpr VecResult multiplyVec(const VecRhs& v) const noexcept {
1522 static_assert(VecRhs::SIZE == COLS && VecResult::SIZE == ROWS,
1523 "multiplyVec: dim mismatch");
1524 return generate<VecResult, ROWS>([&](int i) {
1525 T sum = mData[i * COLS] * v[0];
1526 for (int k = 1; k < COLS; ++k) sum += mData[i * COLS + k] * v[k];
1527 return sum;
1528 });
1529 }
1530};
1531
1532// Forward declarations
1533template<typename T> class Mat2;
1534template<typename T> class Mat2x3;
1535template<typename T> class Mat3x2;
1536template<typename T> class Mat3;
1537template<typename T> class Mat4;
1538template<typename T> class Vec4;
1539
1540
1541
1542/// @brief 2x2 row-major matrix.
1543/// @details Naturally aligned (@c alignof(T)), like all Vec/Mat classes, so the
1544/// layout of structs and buffers that hold one does not depend on this class.
1545template <typename T>
1546class Mat2 : public MatBase<T, 2, 2> {
1547 using Base = MatBase<T, 2, 2>;
1548public:
1549 /// @brief Default-construct (entries left uninitialized for fundamental @c T).
1550 Mat2() noexcept = default;
1551 /// @brief Constructor given individual array elements, the ordering is in row major form:
1552 /** @verbatim
1553 a b
1554 c d
1555 @endverbatim */
1556 __hostdev__ constexpr Mat2(T a, T b, T c, T d) noexcept : Base(a, b, c, d) {}
1557
1558 /// @brief Constructor given array of elements, the ordering is in row major form
1559 template<typename Source>
1560 __hostdev__ constexpr Mat2(Source* array) noexcept : Base(array) {}
1561
1562 // ---- element-wise ----
1563 __hostdev__ [[nodiscard]] constexpr Mat2 operator-() const noexcept { return this->template negate<Mat2>(); }
1564 __hostdev__ [[nodiscard]] constexpr Mat2 operator+(const Mat2& m) const noexcept { return this->template plus<Mat2>(m); }
1565 __hostdev__ [[nodiscard]] constexpr Mat2 operator-(const Mat2& m) const noexcept { return this->template minus<Mat2>(m); }
1566 __hostdev__ constexpr Mat2& operator+=(const Mat2& m) noexcept { Base::addAssign(m); return *this; }
1567 __hostdev__ constexpr Mat2& operator-=(const Mat2& m) noexcept { Base::subAssign(m); return *this; }
1568
1569 // ---- matrix * matrix / matrix * vector ----
1570 __hostdev__ [[nodiscard]] constexpr Mat2 operator*(const Mat2& m) const noexcept { return this->template multiply<Mat2, Mat2>(m); }
1571 __hostdev__ [[nodiscard]] constexpr Vec2<T> operator*(const Vec2<T>& v) const noexcept { return this->template multiplyVec<Vec2<T>, Vec2<T>>(v); }
1572
1573 // ---- scalar ----
1574 __hostdev__ [[nodiscard]] constexpr Mat2 operator*(const T& s) const noexcept { return this->template scale<Mat2>(s); }
1575 __hostdev__ [[nodiscard]] constexpr Mat2 operator/(const T& s) const noexcept { return this->template divideBy<Mat2>(s); }
1576 __hostdev__ constexpr Mat2& operator*=(const T& s) noexcept { Base::scaleAssign(s); return *this; }
1577 __hostdev__ constexpr Mat2& operator/=(const T& s) noexcept { Base::divideAssignScalar(s); return *this; }
1578
1579 // ---- equality ----
1580 __hostdev__ [[nodiscard]] constexpr bool operator==(const Mat2& m) const noexcept { return Base::equals(m); }
1581 __hostdev__ [[nodiscard]] constexpr bool operator!=(const Mat2& m) const noexcept { return !Base::equals(m); }
1582
1583 /// @brief returns transpose of this
1584 __hostdev__ [[nodiscard]] constexpr Mat2 transpose() const noexcept { return this->template transposeAs<Mat2>(); }
1585
1586 /// @brief returns inverse of this
1587 __hostdev__ [[nodiscard]] constexpr Mat2<T> inverse() const noexcept {
1588 T det = (*this)[0][0] * (*this)[1][1] - (*this)[0][1] * (*this)[1][0];
1589 if (isApproxZero(det)) {
1590 return Mat2<T>(T(0), T(0), T(0), T(0));
1591 }
1592 T invDet = T(1) / det;
1593 return Mat2<T>((*this)[1][1] * invDet, -(*this)[0][1] * invDet,
1594 -(*this)[1][0] * invDet, (*this)[0][0] * invDet);
1595 }
1596
1597 /// @brief scalar * Mat (hidden friend — found only via ADL on Mat2)
1598 __hostdev__ [[nodiscard]] friend constexpr Mat2 operator*(const T& s, const Mat2& m) noexcept {
1599 return m.template scale<Mat2>(s);
1600 }
1601};
1602
1603/// @brief 2x3 row-major matrix.
1604/// @details Intentionally NOT @c alignas-elevated: its byte size
1605/// (6*sizeof(T)) is not a power-of-2 multiple of @c alignof(T), so any
1606/// @c alignas(N > alignof(T)) would force tail padding and break
1607/// packed-array layout plus on-disk format compatibility.
1608template <typename T>
1609class Mat2x3 : public MatBase<T, 2, 3> {
1610 using Base = MatBase<T, 2, 3>;
1611public:
1612 /// @brief Default-construct (entries left uninitialized for fundamental @c T).
1613 Mat2x3() noexcept = default;
1614 /// @brief Constructor given individual array elements, the ordering is in row major form:
1615 /** @verbatim
1616 a b c
1617 d e f
1618 @endverbatim */
1619 __hostdev__ constexpr Mat2x3(T a, T b, T c, T d, T e, T f) noexcept : Base(a, b, c, d, e, f) {}
1620
1621 /// @brief Constructor given array of elements, the ordering is in row major form
1622 template<typename Source>
1623 __hostdev__ constexpr Mat2x3(Source* array) noexcept : Base(array) {}
1624
1625
1626 // ---- element-wise ----
1627 __hostdev__ [[nodiscard]] constexpr Mat2x3 operator-() const noexcept { return this->template negate<Mat2x3>(); }
1628 __hostdev__ [[nodiscard]] constexpr Mat2x3 operator+(const Mat2x3& m) const noexcept { return this->template plus<Mat2x3>(m); }
1629 __hostdev__ [[nodiscard]] constexpr Mat2x3 operator-(const Mat2x3& m) const noexcept { return this->template minus<Mat2x3>(m); }
1630 __hostdev__ constexpr Mat2x3& operator+=(const Mat2x3& m) noexcept { Base::addAssign(m); return *this; }
1631 __hostdev__ constexpr Mat2x3& operator-=(const Mat2x3& m) noexcept { Base::subAssign(m); return *this; }
1632
1633 // ---- matrix * vector ----
1634 __hostdev__ [[nodiscard]] constexpr Vec2<T> operator*(const Vec3<T>& v) const noexcept { return this->template multiplyVec<Vec2<T>, Vec3<T>>(v); }
1635
1636 // ---- scalar ----
1637 __hostdev__ [[nodiscard]] constexpr Mat2x3 operator*(const T& s) const noexcept { return this->template scale<Mat2x3>(s); }
1638 __hostdev__ [[nodiscard]] constexpr Mat2x3 operator/(const T& s) const noexcept { return this->template divideBy<Mat2x3>(s); }
1639 __hostdev__ constexpr Mat2x3& operator*=(const T& s) noexcept { Base::scaleAssign(s); return *this; }
1640 __hostdev__ constexpr Mat2x3& operator/=(const T& s) noexcept { Base::divideAssignScalar(s); return *this; }
1641
1642 // ---- equality ----
1643 __hostdev__ [[nodiscard]] constexpr bool operator==(const Mat2x3& m) const noexcept { return Base::equals(m); }
1644 __hostdev__ [[nodiscard]] constexpr bool operator!=(const Mat2x3& m) const noexcept { return !Base::equals(m); }
1645
1646 /// @brief returns transpose of this
1647 __hostdev__ [[nodiscard]] constexpr Mat3x2<T> transpose() const noexcept { return this->template transposeAs<Mat3x2<T>>(); }
1648
1649 /// @brief scalar * Mat (hidden friend — found only via ADL on Mat2x3)
1650 __hostdev__ [[nodiscard]] friend constexpr Mat2x3 operator*(const T& s, const Mat2x3& m) noexcept {
1651 return m.template scale<Mat2x3>(s);
1652 }
1653};
1654
1655/// @brief 3x2 row-major matrix.
1656/// @details Intentionally NOT @c alignas-elevated: its byte size
1657/// (6*sizeof(T)) is not a power-of-2 multiple of @c alignof(T), so any
1658/// @c alignas(N > alignof(T)) would force tail padding and break
1659/// packed-array layout plus on-disk format compatibility.
1660template <typename T>
1661class Mat3x2 : public MatBase<T, 3, 2> {
1662 using Base = MatBase<T, 3, 2>;
1663public:
1664 /// @brief Default-construct (entries left uninitialized for fundamental @c T).
1665 Mat3x2() noexcept = default;
1666
1667 /// @brief Constructor given individual array elements, the ordering is in row major form:
1668 /** @verbatim
1669 a b
1670 c d
1671 e f
1672 @endverbatim */
1673 __hostdev__ constexpr Mat3x2(T a, T b, T c, T d, T e, T f) noexcept : Base(a, b, c, d, e, f) {}
1674
1675 /// @brief Constructor given array of elements, the ordering is in row major form
1676 template<typename Source>
1677 __hostdev__ constexpr Mat3x2(Source *a) noexcept : Base(a) {}
1678
1679 // ---- element-wise ----
1680 __hostdev__ [[nodiscard]] constexpr Mat3x2 operator-() const noexcept { return this->template negate<Mat3x2>(); }
1681 __hostdev__ [[nodiscard]] constexpr Mat3x2 operator+(const Mat3x2& m) const noexcept { return this->template plus<Mat3x2>(m); }
1682 __hostdev__ [[nodiscard]] constexpr Mat3x2 operator-(const Mat3x2& m) const noexcept { return this->template minus<Mat3x2>(m); }
1683 __hostdev__ constexpr Mat3x2& operator+=(const Mat3x2& m) noexcept { Base::addAssign(m); return *this; }
1684 __hostdev__ constexpr Mat3x2& operator-=(const Mat3x2& m) noexcept { Base::subAssign(m); return *this; }
1685
1686 // ---- matrix * vector ----
1687 __hostdev__ [[nodiscard]] constexpr Vec3<T> operator*(const Vec2<T>& v) const noexcept { return this->template multiplyVec<Vec3<T>, Vec2<T>>(v); }
1688
1689 // ---- scalar ----
1690 __hostdev__ [[nodiscard]] constexpr Mat3x2 operator*(const T& s) const noexcept { return this->template scale<Mat3x2>(s); }
1691 __hostdev__ [[nodiscard]] constexpr Mat3x2 operator/(const T& s) const noexcept { return this->template divideBy<Mat3x2>(s); }
1692 __hostdev__ constexpr Mat3x2& operator*=(const T& s) noexcept { Base::scaleAssign(s); return *this; }
1693 __hostdev__ constexpr Mat3x2& operator/=(const T& s) noexcept { Base::divideAssignScalar(s); return *this; }
1694
1695 // ---- equality ----
1696 __hostdev__ [[nodiscard]] constexpr bool operator==(const Mat3x2& m) const noexcept { return Base::equals(m); }
1697 __hostdev__ [[nodiscard]] constexpr bool operator!=(const Mat3x2& m) const noexcept { return !Base::equals(m); }
1698
1699 /// @brief returns transpose of this
1700 __hostdev__ [[nodiscard]] constexpr Mat2x3<T> transpose() const noexcept { return this->template transposeAs<Mat2x3<T>>(); }
1701
1702 /// @brief scalar * Mat (hidden friend — found only via ADL on Mat3x2)
1703 __hostdev__ [[nodiscard]] friend constexpr Mat3x2 operator*(const T& s, const Mat3x2& m) noexcept {
1704 return m.template scale<Mat3x2>(s);
1705 }
1706};
1707
1708/// @brief 3x3 row-major matrix.
1709/// @details Intentionally NOT @c alignas-elevated: its byte size
1710/// (9*sizeof(T)) is not a power-of-2 multiple of @c alignof(T), so any
1711/// @c alignas(N > alignof(T)) would force tail padding and break
1712/// packed-array layout plus on-disk format compatibility.
1713template <typename T>
1714class Mat3 : public MatBase<T, 3, 3> {
1715 using Base = MatBase<T, 3, 3>;
1716public:
1717 /// @brief Default-construct (entries left uninitialized for fundamental @c T).
1718 Mat3() noexcept = default;
1719
1720 /// @brief Constructor given individual array elements, the ordering is in row major form:
1721 /** @verbatim
1722 a b c
1723 d e f
1724 g h i
1725 @endverbatim */
1726 __hostdev__ constexpr Mat3(T a, T b, T c,
1727 T d, T e, T f,
1728 T g, T h, T i) noexcept : Base(a, b, c, d, e, f, g, h, i) {}
1729
1730 /// @brief Constructor given array of elements, the ordering is in row major form
1731 template<typename Source>
1732 __hostdev__ constexpr Mat3(Source *a) noexcept : Base(a) {}
1733
1734
1735 // ---- element-wise ----
1736 __hostdev__ [[nodiscard]] constexpr Mat3 operator-() const noexcept { return this->template negate<Mat3>(); }
1737 __hostdev__ [[nodiscard]] constexpr Mat3 operator+(const Mat3& m) const noexcept { return this->template plus<Mat3>(m); }
1738 __hostdev__ [[nodiscard]] constexpr Mat3 operator-(const Mat3& m) const noexcept { return this->template minus<Mat3>(m); }
1739 __hostdev__ constexpr Mat3& operator+=(const Mat3& m) noexcept { Base::addAssign(m); return *this; }
1740 __hostdev__ constexpr Mat3& operator-=(const Mat3& m) noexcept { Base::subAssign(m); return *this; }
1741
1742 // ---- matrix * matrix / matrix * vector ----
1743 __hostdev__ [[nodiscard]] constexpr Mat3 operator*(const Mat3& m) const noexcept { return this->template multiply<Mat3, Mat3>(m); }
1744 __hostdev__ [[nodiscard]] constexpr Vec3<T> operator*(const Vec3<T>& v) const noexcept { return this->template multiplyVec<Vec3<T>, Vec3<T>>(v); }
1745
1746 // ---- scalar ----
1747 __hostdev__ [[nodiscard]] constexpr Mat3 operator*(const T& s) const noexcept { return this->template scale<Mat3>(s); }
1748 __hostdev__ [[nodiscard]] constexpr Mat3 operator/(const T& s) const noexcept { return this->template divideBy<Mat3>(s); }
1749 __hostdev__ constexpr Mat3& operator*=(const T& s) noexcept { Base::scaleAssign(s); return *this; }
1750 __hostdev__ constexpr Mat3& operator/=(const T& s) noexcept { Base::divideAssignScalar(s); return *this; }
1751
1752 // ---- equality ----
1753 __hostdev__ [[nodiscard]] constexpr bool operator==(const Mat3& m) const noexcept { return Base::equals(m); }
1754 __hostdev__ [[nodiscard]] constexpr bool operator!=(const Mat3& m) const noexcept { return !Base::equals(m); }
1755
1756 /// @brief returns transpose of this
1757 __hostdev__ [[nodiscard]] constexpr Mat3 transpose() const noexcept { return this->template transposeAs<Mat3>(); }
1758
1759 /// @brief scalar * Mat (hidden friend — found only via ADL on Mat3)
1760 __hostdev__ [[nodiscard]] friend constexpr Mat3 operator*(const T& s, const Mat3& m) noexcept {
1761 return m.template scale<Mat3>(s);
1762 }
1763};
1764
1765/// @brief 4x4 row-major matrix.
1766/// @details Naturally aligned (@c alignof(T)), like all Vec/Mat classes. Code may
1767/// place a @c Mat4 at any multiple of @c alignof(T), e.g. when packing matrices
1768/// into shared memory, so raising the alignment would make such placements invalid.
1769template <typename T>
1770class Mat4 : public MatBase<T, 4, 4> {
1771 using Base = MatBase<T, 4, 4>;
1772public:
1773 /// @brief Default-construct (entries left uninitialized for fundamental @c T).
1774 Mat4() noexcept = default;
1775
1776 /// @brief Constructor given individual array elements, the ordering is in row major form:
1777 /** @verbatim
1778 a b c d
1779 e f g h
1780 i j k l
1781 m n o p
1782 @endverbatim */
1783 __hostdev__ constexpr Mat4(T a, T b, T c, T d,
1784 T e, T f, T g, T h,
1785 T i, T j, T k, T l,
1786 T m, T n, T o, T p) noexcept
1787 : Base(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) {}
1788
1789 /// @brief Constructor given array of elements, the ordering is in row major form
1790 template<typename Source>
1791 __hostdev__ constexpr Mat4(Source *a) noexcept : Base(a) {}
1792
1793 // ---- element-wise ----
1794 __hostdev__ [[nodiscard]] constexpr Mat4 operator-() const noexcept { return this->template negate<Mat4>(); }
1795 __hostdev__ [[nodiscard]] constexpr Mat4 operator+(const Mat4& m) const noexcept { return this->template plus<Mat4>(m); }
1796 __hostdev__ [[nodiscard]] constexpr Mat4 operator-(const Mat4& m) const noexcept { return this->template minus<Mat4>(m); }
1797 __hostdev__ constexpr Mat4& operator+=(const Mat4& m) noexcept { Base::addAssign(m); return *this; }
1798 __hostdev__ constexpr Mat4& operator-=(const Mat4& m) noexcept { Base::subAssign(m); return *this; }
1799
1800 // ---- matrix * matrix / matrix * vector ----
1801 __hostdev__ [[nodiscard]] constexpr Mat4 operator*(const Mat4& m) const noexcept { return this->template multiply<Mat4, Mat4>(m); }
1802 __hostdev__ [[nodiscard]] constexpr Vec4<T> operator*(const Vec4<T>& v) const noexcept { return this->template multiplyVec<Vec4<T>, Vec4<T>>(v); }
1803
1804 // ---- scalar ----
1805 __hostdev__ [[nodiscard]] constexpr Mat4 operator*(const T& s) const noexcept { return this->template scale<Mat4>(s); }
1806 __hostdev__ [[nodiscard]] constexpr Mat4 operator/(const T& s) const noexcept { return this->template divideBy<Mat4>(s); }
1807 __hostdev__ constexpr Mat4& operator*=(const T& s) noexcept { Base::scaleAssign(s); return *this; }
1808 __hostdev__ constexpr Mat4& operator/=(const T& s) noexcept { Base::divideAssignScalar(s); return *this; }
1809
1810 // ---- equality ----
1811 __hostdev__ [[nodiscard]] constexpr bool operator==(const Mat4& m) const noexcept { return Base::equals(m); }
1812 __hostdev__ [[nodiscard]] constexpr bool operator!=(const Mat4& m) const noexcept { return !Base::equals(m); }
1813
1814 /// @brief returns transpose of this
1815 __hostdev__ [[nodiscard]] constexpr Mat4 transpose() const noexcept { return this->template transposeAs<Mat4>(); }
1816
1817 /// @brief scalar * Mat (hidden friend — found only via ADL on Mat4)
1818 __hostdev__ [[nodiscard]] friend constexpr Mat4 operator*(const T& s, const Mat4& m) noexcept {
1819 return m.template scale<Mat4>(s);
1820 }
1821};
1822
1823
1824/// @brief Multiply a 2x3 matrix by a 3x2 matrix, result is a 2x2 matrix
1825template<typename T>
1826__hostdev__ [[nodiscard]] constexpr Mat2<T> operator*(const Mat2x3<T>& lhs, const Mat3x2<T>& rhs) noexcept {
1827 return lhs.template multiply<Mat2<T>, Mat3x2<T>>(rhs);
1828}
1829/// @brief Multiply a 2x3 matrix by a 3x3 matrix, result is a 2x3 matrix
1830template<typename T>
1831__hostdev__ [[nodiscard]] constexpr Mat2x3<T> operator*(const Mat2x3<T>& lhs, const Mat3<T>& rhs) noexcept {
1832 return lhs.template multiply<Mat2x3<T>, Mat3<T>>(rhs);
1833}
1834/// @brief Multiply a 3x2 matrix by a 2x2 matrix, result is a 3x2 matrix
1835template<typename T>
1836__hostdev__ [[nodiscard]] constexpr Mat3x2<T> operator*(const Mat3x2<T>& lhs, const Mat2<T>& rhs) noexcept {
1837 return lhs.template multiply<Mat3x2<T>, Mat2<T>>(rhs);
1838}
1839/// @brief Multiply a 2x2 matrix by a 2x3 matrix, result is a 2x3 matrix
1840template<typename T>
1841__hostdev__ [[nodiscard]] constexpr Mat2x3<T> operator*(const Mat2<T>& lhs, const Mat2x3<T>& rhs) noexcept {
1842 return lhs.template multiply<Mat2x3<T>, Mat2x3<T>>(rhs);
1843}
1844/// @brief Multiply a 3x2 matrix by a 2x3 matrix, result is a 3x3 matrix
1845template<typename T>
1846__hostdev__ [[nodiscard]] constexpr Mat3<T> operator*(const Mat3x2<T>& lhs, const Mat2x3<T>& rhs) noexcept {
1847 return lhs.template multiply<Mat3<T>, Mat2x3<T>>(rhs);
1848}
1849/// @brief Multiply a 3x3 matrix by a 3x2 matrix, result is a 3x2 matrix
1850template<typename T>
1851__hostdev__ [[nodiscard]] constexpr Mat3x2<T> operator*(const Mat3<T>& lhs, const Mat3x2<T>& rhs) noexcept {
1852 return lhs.template multiply<Mat3x2<T>, Mat3x2<T>>(rhs);
1853}
1854// ----------------------------> Vec3 <--------------------------------------
1855
1856/// @brief A simple vector class with three components, similar to openvdb::math::Vec3
1857///
1858/// Vec3 is intentionally NOT alignas-elevated: its byte size
1859/// (3*sizeof(T)) is not a power-of-2 multiple of alignof(T), so any
1860/// alignas(N > alignof(T)) would force tail padding and break
1861/// packed-array layout plus on-disk format compatibility. Use @c Vec3Aligned
1862/// for padded, over-aligned user arrays.
1863template<typename T>
1864class Vec3 : public VecBase<T, 3>
1865{
1866 using Base = VecBase<T, 3>;
1867
1868public:
1869 using ValueType = T;
1870 static constexpr int size = 3; // openvdb::math::Tuple-compat alias of SIZE
1871
1872 /// @brief Default-construct (components are left uninitialized for fundamental @c T).
1873 Vec3() noexcept = default;
1874 /// @brief Broadcast: set all three components to @a x.
1875 __hostdev__ explicit constexpr Vec3(T x) noexcept : Base(x, x, x) {}
1876 /// @brief Component-wise construction.
1877 __hostdev__ constexpr Vec3(T x, T y, T z) noexcept : Base(x, y, z) {}
1878
1879 /// @brief Explicit cross-template converting ctor (e.g. from @c openvdb::Vec3).
1880 /// Convert a foreign vector with a cast, e.g. @c Vec3<float>(v).
1881 template<template<class> class Vec3T, class T2>
1882 __hostdev__ explicit constexpr Vec3(const Vec3T<T2>& v) noexcept : Base(v[0], v[1], v[2])
1883 {
1884 static_assert(Vec3T<T2>::size == 3, "expected Vec3T::size==3!");
1885 }
1886 /// @brief Explicit cross-precision conversion within nanovdb (e.g. @c Vec3d → @c Vec3f).
1887 template<typename T2>
1888 __hostdev__ explicit constexpr Vec3(const Vec3<T2>& v) noexcept : Base(v[0], v[1], v[2]) {}
1889 /// @brief Construct from a 3D integer coordinate.
1890 __hostdev__ explicit constexpr Vec3(const Coord& ijk) noexcept : Base(ijk[0], ijk[1], ijk[2]) {}
1891
1892 /// @brief Assign from any 3-component vector type (foreign or nanovdb).
1893 template<template<class> class Vec3T, class T2>
1894 __hostdev__ constexpr Vec3& operator=(const Vec3T<T2>& rhs) noexcept {
1895 static_assert(Vec3T<T2>::size == 3, "expected Vec3T::size==3!");
1896 this->mVec[0] = rhs[0]; this->mVec[1] = rhs[1]; this->mVec[2] = rhs[2];
1897 return *this;
1898 }
1899
1900 // ---- element-wise (Vec & Vec) ----
1901 /// @brief Component-wise negation.
1902 __hostdev__ [[nodiscard]] constexpr Vec3 operator-() const noexcept { return Base::template negate<Vec3>(); }
1903 /// @brief Component-wise sum.
1904 __hostdev__ [[nodiscard]] constexpr Vec3 operator+(const Vec3& v) const noexcept { return Base::template plus<Vec3>(v); }
1905 /// @brief Component-wise difference.
1906 __hostdev__ [[nodiscard]] constexpr Vec3 operator-(const Vec3& v) const noexcept { return Base::template minus<Vec3>(v); }
1907 /// @brief Component-wise (Hadamard) product.
1908 __hostdev__ [[nodiscard]] constexpr Vec3 operator*(const Vec3& v) const noexcept { return Base::template mul<Vec3>(v); }
1909 /// @brief Component-wise division.
1910 __hostdev__ [[nodiscard]] constexpr Vec3 operator/(const Vec3& v) const noexcept { return Base::template div<Vec3>(v); }
1911 /// @brief In-place component-wise addition.
1912 __hostdev__ constexpr Vec3& operator+=(const Vec3& v) noexcept { Base::addAssign(v); return *this; }
1913 /// @brief In-place component-wise subtraction.
1914 __hostdev__ constexpr Vec3& operator-=(const Vec3& v) noexcept { Base::subAssign(v); return *this; }
1915
1916 // ---- mixed Vec3 / Coord (3D) ----
1917 /// @brief Add an integer @c Coord to this vector (component-wise).
1918 __hostdev__ [[nodiscard]] constexpr Vec3 operator+(const Coord& ijk) const noexcept { return Vec3(this->mVec[0] + T(ijk[0]), this->mVec[1] + T(ijk[1]), this->mVec[2] + T(ijk[2])); }
1919 /// @brief Subtract an integer @c Coord from this vector (component-wise).
1920 __hostdev__ [[nodiscard]] constexpr Vec3 operator-(const Coord& ijk) const noexcept { return Vec3(this->mVec[0] - T(ijk[0]), this->mVec[1] - T(ijk[1]), this->mVec[2] - T(ijk[2])); }
1921 /// @brief In-place component-wise addition of an integer @c Coord.
1922 __hostdev__ constexpr Vec3& operator+=(const Coord& ijk) noexcept {
1923 this->mVec[0] += T(ijk[0]); this->mVec[1] += T(ijk[1]); this->mVec[2] += T(ijk[2]);
1924 return *this;
1925 }
1926 /// @brief In-place component-wise subtraction of an integer @c Coord.
1927 __hostdev__ constexpr Vec3& operator-=(const Coord& ijk) noexcept {
1928 this->mVec[0] -= T(ijk[0]); this->mVec[1] -= T(ijk[1]); this->mVec[2] -= T(ijk[2]);
1929 return *this;
1930 }
1931
1932 // ---- scalar ----
1933 /// @brief Component-wise multiply by scalar @a s.
1934 __hostdev__ [[nodiscard]] constexpr Vec3 operator*(const T& s) const noexcept { return Base::template scale<Vec3>(s); }
1935 /// @brief Component-wise divide by scalar @a s (integer-safe).
1936 __hostdev__ [[nodiscard]] constexpr Vec3 operator/(const T& s) const noexcept { return Base::template divideBy<Vec3>(s); }
1937 /// @brief In-place component-wise multiply by scalar @a s.
1938 __hostdev__ constexpr Vec3& operator*=(const T& s) noexcept { Base::scaleAssign(s); return *this; }
1939 /// @brief In-place component-wise divide by scalar @a s.
1940 __hostdev__ constexpr Vec3& operator/=(const T& s) noexcept { Base::divideAssignScalar(s); return *this; }
1941 /// @brief Normalize in place (divide by @c length()). Not @c constexpr — calls @c std::sqrt.
1942 __hostdev__ Vec3& normalize() noexcept { return (*this) /= this->length(); }
1943 /// @brief Return a normalized (unit-length) copy; const counterpart of @c normalize().
1944 __hostdev__ [[nodiscard]] Vec3 normalized() const noexcept {
1945 return Base::template normalized<Vec3>();
1946 }
1947
1948 // ---- equality ----
1949 /// @brief Component-wise equality.
1950 __hostdev__ [[nodiscard]] constexpr bool operator==(const Vec3& rhs) const noexcept { return Base::equals(rhs); }
1951 /// @brief Component-wise inequality.
1952 __hostdev__ [[nodiscard]] constexpr bool operator!=(const Vec3& rhs) const noexcept { return !Base::equals(rhs); }
1953
1954 // ---- component-wise min/max ----
1955 /// @brief Take the component-wise minimum of @c *this and @a other in place.
1956 __hostdev__ constexpr Vec3& minComponent(const Vec3& other) noexcept { Base::mergeMin(other); return *this; }
1957 /// @brief Take the component-wise maximum of @c *this and @a other in place.
1958 __hostdev__ constexpr Vec3& maxComponent(const Vec3& other) noexcept { Base::mergeMax(other); return *this; }
1959
1960 /// @brief Return the smallest vector component
1961 __hostdev__ [[nodiscard]] constexpr ValueType min() const noexcept { return Base::smallestComponent(); }
1962 /// @brief Return the largest vector component
1963 __hostdev__ [[nodiscard]] constexpr ValueType max() const noexcept { return Base::largestComponent(); }
1964
1965 /// @brief Round each component down (toward negative infinity)
1966 /// @return integer Coord
1967 /// @note Only constexpr for integer @c T (floorAs uses non-constexpr math::Floor for floating point).
1968 __hostdev__ [[nodiscard]] constexpr Coord floor() const noexcept { return Base::template floorAs<Coord>(); }
1969 /// @brief Round each component up (toward positive infinity)
1970 /// @return integer Coord
1971 /// @note Only constexpr for integer @c T (ceilAs uses non-constexpr math::Ceil for floating point).
1972 __hostdev__ [[nodiscard]] constexpr Coord ceil() const noexcept { return Base::template ceilAs<Coord>(); }
1973 /// @brief Round each component to its closest integer value
1974 /// @return integer Coord
1975 /// @note Only constexpr for integer @c T (roundAs uses non-constexpr math::Round for floating point).
1976 __hostdev__ [[nodiscard]] constexpr Coord round() const noexcept { return Base::template roundAs<Coord>(); }
1977
1978 // ---- 3D-specific ----
1979
1980 /// @brief cross product with another 3-vector
1981 template<typename Vec3T>
1982 __hostdev__ [[nodiscard]] constexpr Vec3 cross(const Vec3T& v) const noexcept {
1983 return Vec3(this->mVec[1] * v[2] - this->mVec[2] * v[1],
1984 this->mVec[2] * v[0] - this->mVec[0] * v[2],
1985 this->mVec[0] * v[1] - this->mVec[1] * v[0]);
1986 }
1987
1988 /// @brief Outer product of a 3x1 vector and a 1x3 vector, result is a 3x3 matrix
1989 template<typename Vec3T>
1990 __hostdev__ [[nodiscard]] constexpr Mat3<ValueType> outer(const Vec3T& v) const noexcept {
1991 return Mat3<ValueType>(this->mVec[0] * v[0], this->mVec[0] * v[1], this->mVec[0] * v[2],
1992 this->mVec[1] * v[0], this->mVec[1] * v[1], this->mVec[1] * v[2],
1993 this->mVec[2] * v[0], this->mVec[2] * v[1], this->mVec[2] * v[2]);
1994 }
1995
1996 // ---- scalar * Vec / scalar / Vec (hidden friends — found only via ADL on Vec3,
1997 // never participate in unrelated namespace-scope overload sets) ----
1998
1999 /// @brief Scalar-on-the-left multiplication (hidden friend).
2000 template<typename T1>
2001 __hostdev__ [[nodiscard]] friend constexpr Vec3 operator*(T1 scalar, const Vec3& vec) noexcept
2002 {
2003 return Vec3(T(scalar * vec[0]), T(scalar * vec[1]), T(scalar * vec[2]));
2004 }
2005 /// @brief Scalar-on-the-left division (hidden friend).
2006 template<typename T1>
2007 __hostdev__ [[nodiscard]] friend constexpr Vec3 operator/(T1 scalar, const Vec3& vec) noexcept
2008 {
2009 return Vec3(T(scalar / vec[0]), T(scalar / vec[1]), T(scalar / vec[2]));
2010 }
2011}; // Vec3<T>
2012
2013/// @brief Return a single precision floating-point vector of this coordinate
2014__hostdev__ [[nodiscard]] inline constexpr Vec3<float> Coord::asVec3s() const noexcept
2015{
2016 return Vec3<float>(float(mVec[0]), float(mVec[1]), float(mVec[2]));
2017}
2018
2019/// @brief Return a double precision floating-point vector of this coordinate
2020__hostdev__ [[nodiscard]] inline constexpr Vec3<double> Coord::asVec3d() const noexcept
2021{
2022 return Vec3<double>(double(mVec[0]), double(mVec[1]), double(mVec[2]));
2023}
2024
2025// ----------------------------> Vec4 <--------------------------------------
2026
2027/// @brief A simple vector class with four components, similar to openvdb::math::Vec4
2028///
2029/// Naturally aligned (@c alignof(T)). @c Vec4 is a grid value type, so its
2030/// alignment sets field offsets in the NanoVDB file format and in PNanoVDB.
2031/// Use @c Vec4Aligned for over-aligned user arrays.
2032template<typename T>
2033class Vec4 : public VecBase<T, 4>
2034{
2035 using Base = VecBase<T, 4>;
2036
2037public:
2038 using ValueType = T;
2039 static constexpr int size = 4; // openvdb::math::Tuple-compat alias of SIZE
2040
2041 /// @brief Default-construct (components are left uninitialized for fundamental @c T).
2042 Vec4() noexcept = default;
2043 /// @brief Broadcast: set all four components to @a x.
2044 __hostdev__ explicit constexpr Vec4(T x) noexcept : Base(x, x, x, x) {}
2045 /// @brief Component-wise construction.
2046 __hostdev__ constexpr Vec4(T x, T y, T z, T w) noexcept : Base(x, y, z, w) {}
2047
2048 /// @brief Explicit cross-precision conversion within nanovdb (e.g. @c Vec4d → @c Vec4f).
2049 template<typename T2>
2050 __hostdev__ explicit constexpr Vec4(const Vec4<T2>& v) noexcept : Base(v[0], v[1], v[2], v[3]) {}
2051 /// @brief Explicit cross-template converting ctor (e.g. from @c openvdb::Vec4).
2052 /// Convert a foreign vector with a cast, e.g. @c Vec4<float>(v).
2053 template<template<class> class Vec4T, class T2>
2054 __hostdev__ explicit constexpr Vec4(const Vec4T<T2>& v) noexcept : Base(v[0], v[1], v[2], v[3])
2055 {
2056 static_assert(Vec4T<T2>::size == 4, "expected Vec4T::size==4!");
2057 }
2058 /// @brief Assign from any 4-component vector type (foreign or nanovdb).
2059 template<template<class> class Vec4T, class T2>
2060 __hostdev__ constexpr Vec4& operator=(const Vec4T<T2>& rhs) noexcept {
2061 static_assert(Vec4T<T2>::size == 4, "expected Vec4T::size==4!");
2062 this->mVec[0] = rhs[0]; this->mVec[1] = rhs[1]; this->mVec[2] = rhs[2]; this->mVec[3] = rhs[3];
2063 return *this;
2064 }
2065
2066 // ---- element-wise (Vec & Vec) ----
2067 /// @brief Component-wise negation.
2068 __hostdev__ [[nodiscard]] constexpr Vec4 operator-() const noexcept { return Base::template negate<Vec4>(); }
2069 /// @brief Component-wise sum.
2070 __hostdev__ [[nodiscard]] constexpr Vec4 operator+(const Vec4& v) const noexcept { return Base::template plus<Vec4>(v); }
2071 /// @brief Component-wise difference.
2072 __hostdev__ [[nodiscard]] constexpr Vec4 operator-(const Vec4& v) const noexcept { return Base::template minus<Vec4>(v); }
2073 /// @brief Component-wise (Hadamard) product.
2074 __hostdev__ [[nodiscard]] constexpr Vec4 operator*(const Vec4& v) const noexcept { return Base::template mul<Vec4>(v); }
2075 /// @brief Component-wise division.
2076 __hostdev__ [[nodiscard]] constexpr Vec4 operator/(const Vec4& v) const noexcept { return Base::template div<Vec4>(v); }
2077 /// @brief In-place component-wise addition.
2078 __hostdev__ constexpr Vec4& operator+=(const Vec4& v) noexcept { Base::addAssign(v); return *this; }
2079 /// @brief In-place component-wise subtraction.
2080 __hostdev__ constexpr Vec4& operator-=(const Vec4& v) noexcept { Base::subAssign(v); return *this; }
2081
2082 // ---- scalar ----
2083 /// @brief Component-wise multiply by scalar @a s.
2084 __hostdev__ [[nodiscard]] constexpr Vec4 operator*(const T& s) const noexcept { return Base::template scale<Vec4>(s); }
2085 /// @brief Component-wise divide by scalar @a s (integer-safe).
2086 __hostdev__ [[nodiscard]] constexpr Vec4 operator/(const T& s) const noexcept { return Base::template divideBy<Vec4>(s); }
2087 /// @brief In-place component-wise multiply by scalar @a s.
2088 __hostdev__ constexpr Vec4& operator*=(const T& s) noexcept { Base::scaleAssign(s); return *this; }
2089 /// @brief In-place component-wise divide by scalar @a s.
2090 __hostdev__ constexpr Vec4& operator/=(const T& s) noexcept { Base::divideAssignScalar(s); return *this; }
2091 /// @brief Normalize in place (divide by @c length()). Not @c constexpr — calls @c std::sqrt.
2092 __hostdev__ Vec4& normalize() noexcept { return (*this) /= this->length(); }
2093 /// @brief Return a normalized (unit-length) copy; const counterpart of @c normalize().
2094 __hostdev__ [[nodiscard]] Vec4 normalized() const noexcept {
2095 return Base::template normalized<Vec4>();
2096 }
2097
2098 // ---- equality ----
2099 /// @brief Component-wise equality.
2100 __hostdev__ [[nodiscard]] constexpr bool operator==(const Vec4& rhs) const noexcept { return Base::equals(rhs); }
2101 /// @brief Component-wise inequality.
2102 __hostdev__ [[nodiscard]] constexpr bool operator!=(const Vec4& rhs) const noexcept { return !Base::equals(rhs); }
2103
2104 // ---- component-wise min/max ----
2105 /// @brief Take the component-wise minimum of @c *this and @a other in place.
2106 __hostdev__ constexpr Vec4& minComponent(const Vec4& other) noexcept { Base::mergeMin(other); return *this; }
2107 /// @brief Take the component-wise maximum of @c *this and @a other in place.
2108 __hostdev__ constexpr Vec4& maxComponent(const Vec4& other) noexcept { Base::mergeMax(other); return *this; }
2109
2110 /// @brief Return the smallest vector component
2111 __hostdev__ [[nodiscard]] constexpr ValueType min() const noexcept { return Base::smallestComponent(); }
2112 /// @brief Return the largest vector component
2113 __hostdev__ [[nodiscard]] constexpr ValueType max() const noexcept { return Base::largestComponent(); }
2114
2115 /// @brief Round each component down (toward negative infinity)
2116 /// @return Vec4<int32_t> (NanoVDB has no Coord4)
2117 /// @note Only constexpr for integer @c T (floorAs uses non-constexpr math::Floor for floating point).
2118 __hostdev__ [[nodiscard]] constexpr Vec4<int32_t> floor() const noexcept { return Base::template floorAs<Vec4<int32_t>>(); }
2119 /// @brief Round each component up (toward positive infinity)
2120 /// @return Vec4<int32_t>
2121 /// @note Only constexpr for integer @c T (ceilAs uses non-constexpr math::Ceil for floating point).
2122 __hostdev__ [[nodiscard]] constexpr Vec4<int32_t> ceil() const noexcept { return Base::template ceilAs<Vec4<int32_t>>(); }
2123 /// @brief Round each component to its closest integer value
2124 /// @return Vec4<int32_t>
2125 /// @note Only constexpr for integer @c T (roundAs uses non-constexpr math::Round for floating point).
2126 __hostdev__ [[nodiscard]] constexpr Vec4<int32_t> round() const noexcept { return Base::template roundAs<Vec4<int32_t>>(); }
2127
2128 // ---- scalar * Vec / scalar / Vec (hidden friends — found only via ADL on Vec4,
2129 // never participate in unrelated namespace-scope overload sets) ----
2130
2131 /// @brief Scalar-on-the-left multiplication (hidden friend).
2132 template<typename T1>
2133 __hostdev__ [[nodiscard]] friend constexpr Vec4 operator*(T1 scalar, const Vec4& vec) noexcept
2134 {
2135 return Vec4(scalar * vec[0], scalar * vec[1], scalar * vec[2], scalar * vec[3]);
2136 }
2137 /// @brief Scalar-on-the-left division (hidden friend).
2138 template<typename T1>
2139 __hostdev__ [[nodiscard]] friend constexpr Vec4 operator/(T1 scalar, const Vec4& vec) noexcept
2140 {
2141 return Vec4(scalar / vec[0], scalar / vec[1], scalar / vec[2], scalar / vec[3]);
2142 }
2143}; // Vec4<T>
2144
2145// ----------------------------> Vec2Aligned / Vec3Aligned / Vec4Aligned <------------
2146
2147/// @brief Opt-in over-aligned vectors for user-owned arrays, so each element can load
2148/// with one full-width vector instruction (e.g. 128 bits for @c Vec4Aligned<float>).
2149/// Whether that is faster depends on the access pattern and the GPU, so measure.
2150/// @details Each derives from its Vec class and converts to and from it, so the Vec
2151/// operators work unchanged and return the plain Vec type. @c Vec3Aligned is padded
2152/// to four components, so an array of them is not layout-compatible with an array of
2153/// @c Vec3. The plain Vec classes stay naturally aligned; see @c Vec4.
2154template<typename T>
2155struct alignas(2 * sizeof(T)) Vec2Aligned : Vec2<T>
2156{
2157 using Vec2<T>::Vec2;
2158 Vec2Aligned() noexcept = default;
2159 __hostdev__ constexpr Vec2Aligned(const Vec2<T>& v) noexcept : Vec2<T>(v) {}
2160};
2161
2162/// @brief Padded, over-aligned @c Vec3 for user-owned arrays; see @c Vec2Aligned.
2163template<typename T>
2164struct alignas(4 * sizeof(T)) Vec3Aligned : Vec3<T>
2165{
2166 using Vec3<T>::Vec3;
2167 Vec3Aligned() noexcept = default;
2168 __hostdev__ constexpr Vec3Aligned(const Vec3<T>& v) noexcept : Vec3<T>(v) {}
2169};
2170
2171/// @brief Over-aligned @c Vec4 for user-owned arrays; see @c Vec2Aligned.
2172template<typename T>
2173struct alignas(4 * sizeof(T)) Vec4Aligned : Vec4<T>
2174{
2175 using Vec4<T>::Vec4;
2176 Vec4Aligned() noexcept = default;
2177 __hostdev__ constexpr Vec4Aligned(const Vec4<T>& v) noexcept : Vec4<T>(v) {}
2178};
2179
2180// ----------------------------> matMult <--------------------------------------
2181//
2182// The matMult / matMultT overloads use plain arithmetic instead of fma / fmaf,
2183// which are not constexpr before C++23, so Map::applyMap and
2184// BBox<CoordT,false>::transform<Map> can be constexpr.
2185//
2186// The parentheses fix the accumulation order to right-to-left,
2187// x * m0 + (y * m1 + z * m2). With FP contraction and hardware FMA (nvcc's
2188// default -fmad=true, or GCC/Clang targeting an FMA-capable CPU) each step
2189// fuses into fma(x, m0, fma(y, m1, z * m2)). Without contraction each step
2190// rounds separately, and results may differ from the fused chain by ~1 ulp.
2191// Removing the parentheses reassociates the sum and loses the small terms
2192// under cancellation.
2193
2194/// @brief Multiply a 3x3 matrix and a 3d vector using 32bit floating point arithmetics
2195/// @note This corresponds to a linear mapping, e.g. scaling, rotation etc.
2196/// @tparam Vec3T Template type of the input and output 3d vectors
2197/// @param mat pointer to an array of floats with the 3x3 matrix
2198/// @param xyz input vector to be multiplied by the matrix
2199/// @return result of matrix-vector multiplication, i.e. mat x xyz
2200template<typename Vec3T>
2201__hostdev__ [[nodiscard]] inline constexpr Vec3T matMult(const float* mat, const Vec3T& xyz) noexcept
2202{
2203 const float x = static_cast<float>(xyz[0]);
2204 const float y = static_cast<float>(xyz[1]);
2205 const float z = static_cast<float>(xyz[2]);
2206 return Vec3T(x * mat[0] + (y * mat[1] + z * mat[2]),
2207 x * mat[3] + (y * mat[4] + z * mat[5]),
2208 x * mat[6] + (y * mat[7] + z * mat[8]));
2209}
2210
2211/// @brief Multiply a 3x3 matrix and a 3d vector using 64bit floating point arithmetics
2212/// @note This corresponds to a linear mapping, e.g. scaling, rotation etc.
2213/// @tparam Vec3T Template type of the input and output 3d vectors
2214/// @param mat pointer to an array of floats with the 3x3 matrix
2215/// @param xyz input vector to be multiplied by the matrix
2216/// @return result of matrix-vector multiplication, i.e. mat x xyz
2217template<typename Vec3T>
2218__hostdev__ [[nodiscard]] inline constexpr Vec3T matMult(const double* mat, const Vec3T& xyz) noexcept
2219{
2220 const double x = static_cast<double>(xyz[0]);
2221 const double y = static_cast<double>(xyz[1]);
2222 const double z = static_cast<double>(xyz[2]);
2223 using ValueT = std::decay_t<decltype(xyz[0])>;
2224 return Vec3T(ValueT(x * mat[0] + (y * mat[1] + z * mat[2])),
2225 ValueT(x * mat[3] + (y * mat[4] + z * mat[5])),
2226 ValueT(x * mat[6] + (y * mat[7] + z * mat[8])));
2227}
2228
2229/// @brief Multiply a 3x3 matrix to a 3d vector and add another 3d vector using 32bit floating point arithmetics
2230/// @note This corresponds to an affine transformation, i.e a linear mapping followed by a translation. e.g. scale/rotation and translation
2231/// @tparam Vec3T Template type of the input and output 3d vectors
2232/// @param mat pointer to an array of floats with the 3x3 matrix
2233/// @param vec 3d vector to be added AFTER the matrix multiplication
2234/// @param xyz input vector to be multiplied by the matrix and a translated by @c vec
2235/// @return result of affine transformation, i.e. (mat x xyz) + vec
2236template<typename Vec3T>
2237__hostdev__ [[nodiscard]] inline constexpr Vec3T matMult(const float* mat, const float* vec, const Vec3T& xyz) noexcept
2238{
2239 const float x = static_cast<float>(xyz[0]);
2240 const float y = static_cast<float>(xyz[1]);
2241 const float z = static_cast<float>(xyz[2]);
2242 return Vec3T(x * mat[0] + (y * mat[1] + (z * mat[2] + vec[0])),
2243 x * mat[3] + (y * mat[4] + (z * mat[5] + vec[1])),
2244 x * mat[6] + (y * mat[7] + (z * mat[8] + vec[2])));
2245}
2246
2247/// @brief Multiply a 3x3 matrix to a 3d vector and add another 3d vector using 64bit floating point arithmetics
2248/// @note This corresponds to an affine transformation, i.e a linear mapping followed by a translation. e.g. scale/rotation and translation
2249/// @tparam Vec3T Template type of the input and output 3d vectors
2250/// @param mat pointer to an array of floats with the 3x3 matrix
2251/// @param vec 3d vector to be added AFTER the matrix multiplication
2252/// @param xyz input vector to be multiplied by the matrix and a translated by @c vec
2253/// @return result of affine transformation, i.e. (mat x xyz) + vec
2254template<typename Vec3T>
2255__hostdev__ [[nodiscard]] inline constexpr Vec3T matMult(const double* mat, const double* vec, const Vec3T& xyz) noexcept
2256{
2257 const double x = static_cast<double>(xyz[0]);
2258 const double y = static_cast<double>(xyz[1]);
2259 const double z = static_cast<double>(xyz[2]);
2260 using ValueT = std::decay_t<decltype(xyz[0])>;
2261 return Vec3T(ValueT(x * mat[0] + (y * mat[1] + (z * mat[2] + vec[0]))),
2262 ValueT(x * mat[3] + (y * mat[4] + (z * mat[5] + vec[1]))),
2263 ValueT(x * mat[6] + (y * mat[7] + (z * mat[8] + vec[2]))));
2264}
2265
2266/// @brief Multiply the transposed of a 3x3 matrix and a 3d vector using 32bit floating point arithmetics
2267/// @note This corresponds to an inverse linear mapping, e.g. inverse scaling, inverse rotation etc.
2268/// @tparam Vec3T Template type of the input and output 3d vectors
2269/// @param mat pointer to an array of floats with the 3x3 matrix
2270/// @param xyz input vector to be multiplied by the transposed matrix
2271/// @return result of matrix-vector multiplication, i.e. mat^T x xyz
2272template<typename Vec3T>
2273__hostdev__ [[nodiscard]] inline constexpr Vec3T matMultT(const float* mat, const Vec3T& xyz) noexcept
2274{
2275 const float x = static_cast<float>(xyz[0]);
2276 const float y = static_cast<float>(xyz[1]);
2277 const float z = static_cast<float>(xyz[2]);
2278 return Vec3T(x * mat[0] + (y * mat[3] + z * mat[6]),
2279 x * mat[1] + (y * mat[4] + z * mat[7]),
2280 x * mat[2] + (y * mat[5] + z * mat[8]));
2281}
2282
2283/// @brief Multiply the transposed of a 3x3 matrix and a 3d vector using 64bit floating point arithmetics
2284/// @note This corresponds to an inverse linear mapping, e.g. inverse scaling, inverse rotation etc.
2285/// @tparam Vec3T Template type of the input and output 3d vectors
2286/// @param mat pointer to an array of floats with the 3x3 matrix
2287/// @param xyz input vector to be multiplied by the transposed matrix
2288/// @return result of matrix-vector multiplication, i.e. mat^T x xyz
2289template<typename Vec3T>
2290__hostdev__ [[nodiscard]] inline constexpr Vec3T matMultT(const double* mat, const Vec3T& xyz) noexcept
2291{
2292 const double x = static_cast<double>(xyz[0]);
2293 const double y = static_cast<double>(xyz[1]);
2294 const double z = static_cast<double>(xyz[2]);
2295 using ValueT = std::decay_t<decltype(xyz[0])>;
2296 return Vec3T(ValueT(x * mat[0] + (y * mat[3] + z * mat[6])),
2297 ValueT(x * mat[1] + (y * mat[4] + z * mat[7])),
2298 ValueT(x * mat[2] + (y * mat[5] + z * mat[8])));
2299}
2300
2301/// @brief Multiply the transpose of a 3x3 matrix by @a xyz and add @a vec (32-bit floats).
2302/// @note Corresponds to an inverse affine transform: @c (mat^T x xyz) + @c vec.
2303/// @tparam Vec3T Template type of the input and output 3d vectors
2304template<typename Vec3T>
2305__hostdev__ [[nodiscard]] inline constexpr Vec3T matMultT(const float* mat, const float* vec, const Vec3T& xyz) noexcept
2306{
2307 const float x = static_cast<float>(xyz[0]);
2308 const float y = static_cast<float>(xyz[1]);
2309 const float z = static_cast<float>(xyz[2]);
2310 return Vec3T(x * mat[0] + (y * mat[3] + (z * mat[6] + vec[0])),
2311 x * mat[1] + (y * mat[4] + (z * mat[7] + vec[1])),
2312 x * mat[2] + (y * mat[5] + (z * mat[8] + vec[2])));
2313}
2314
2315/// @brief Multiply the transpose of a 3x3 matrix by @a xyz and add @a vec (64-bit floats).
2316/// @note Corresponds to an inverse affine transform: @c (mat^T x xyz) + @c vec.
2317/// @tparam Vec3T Template type of the input and output 3d vectors
2318template<typename Vec3T>
2319__hostdev__ [[nodiscard]] inline constexpr Vec3T matMultT(const double* mat, const double* vec, const Vec3T& xyz) noexcept
2320{
2321 const double x = static_cast<double>(xyz[0]);
2322 const double y = static_cast<double>(xyz[1]);
2323 const double z = static_cast<double>(xyz[2]);
2324 using ValueT = std::decay_t<decltype(xyz[0])>;
2325 return Vec3T(ValueT(x * mat[0] + (y * mat[3] + (z * mat[6] + vec[0]))),
2326 ValueT(x * mat[1] + (y * mat[4] + (z * mat[7] + vec[1]))),
2327 ValueT(x * mat[2] + (y * mat[5] + (z * mat[8] + vec[2]))));
2328}
2329
2330// ----------------------------> BBox <-------------------------------------
2331
2332/// @brief Common base for floating-point and integer bounding boxes; not
2333/// constructible directly (only as a base of @c BBox).
2334/// @details Stores the closed-segment endpoints @c mCoord[0] (min corner) and
2335/// @c mCoord[1] (max corner). Whether the box is "min-inclusive max-inclusive"
2336/// or "min-inclusive max-exclusive" depends on the derived @c BBox
2337/// specialization (integer vs floating point).
2338template<typename Vec3T>
2340{
2341 Vec3T mCoord[2];
2342 /// @brief Equality on the two corner points.
2343 __hostdev__ [[nodiscard]] constexpr bool operator==(const BaseBBox& rhs) const noexcept { return mCoord[0] == rhs.mCoord[0] && mCoord[1] == rhs.mCoord[1]; };
2344 /// @brief Inequality on the two corner points.
2345 __hostdev__ [[nodiscard]] constexpr bool operator!=(const BaseBBox& rhs) const noexcept { return mCoord[0] != rhs.mCoord[0] || mCoord[1] != rhs.mCoord[1]; };
2346 /// @brief Indexed corner access: @a i = 0 returns min, @a i = 1 returns max.
2347 __hostdev__ constexpr const Vec3T& operator[](int i) const noexcept { NANOVDB_ASSERT(i >= 0 && i < 2); return mCoord[i]; }
2348 /// @brief Mutable variant of @c operator[].
2349 __hostdev__ constexpr Vec3T& operator[](int i) noexcept { NANOVDB_ASSERT(i >= 0 && i < 2); return mCoord[i]; }
2350 /// @brief Mutable accessor for the min corner.
2351 __hostdev__ constexpr Vec3T& min() noexcept { return mCoord[0]; }
2352 /// @brief Mutable accessor for the max corner.
2353 __hostdev__ constexpr Vec3T& max() noexcept { return mCoord[1]; }
2354 /// @brief Const accessor for the min corner.
2355 __hostdev__ constexpr const Vec3T& min() const noexcept { return mCoord[0]; }
2356 /// @brief Const accessor for the max corner.
2357 __hostdev__ constexpr const Vec3T& max() const noexcept { return mCoord[1]; }
2358 /// @brief Translate (rigid-shift) both corners by @a xyz; return @c *this.
2359 __hostdev__ constexpr BaseBBox& translate(const Vec3T& xyz) noexcept
2360 {
2361 mCoord[0] += xyz;
2362 mCoord[1] += xyz;
2363 return *this;
2364 }
2365 /// @brief Expand this bounding box to enclose point @c xyz.
2366 __hostdev__ constexpr BaseBBox& expand(const Vec3T& xyz) noexcept
2367 {
2368 mCoord[0].minComponent(xyz);
2369 mCoord[1].maxComponent(xyz);
2370 return *this;
2371 }
2372
2373 /// @brief Expand this bounding box to enclose the given bounding box.
2374 __hostdev__ constexpr BaseBBox& expand(const BaseBBox& bbox) noexcept
2375 {
2376 mCoord[0].minComponent(bbox[0]);
2377 mCoord[1].maxComponent(bbox[1]);
2378 return *this;
2379 }
2380
2381 /// @brief Intersect this bounding box with the given bounding box.
2382 __hostdev__ constexpr BaseBBox& intersect(const BaseBBox& bbox) noexcept
2383 {
2384 mCoord[0].maxComponent(bbox[0]);
2385 mCoord[1].minComponent(bbox[1]);
2386 return *this;
2387 }
2388
2389 /// @brief Return @c true iff @a xyz lies in the closed box (each component
2390 /// satisfies @c min[i] <= @c xyz[i] <= @c max[i]).
2391 __hostdev__ [[nodiscard]] constexpr bool isInside(const Vec3T& xyz) const noexcept
2392 {
2393 if (xyz[0] < mCoord[0][0] || xyz[1] < mCoord[0][1] || xyz[2] < mCoord[0][2])
2394 return false;
2395 if (xyz[0] > mCoord[1][0] || xyz[1] > mCoord[1][1] || xyz[2] > mCoord[1][2])
2396 return false;
2397 return true;
2398 }
2399
2400protected:
2401 /// @brief Default-construct (leaves corners uninitialized — derived classes
2402 /// supply a meaningful default).
2403 __hostdev__ constexpr BaseBBox() noexcept {}
2404 /// @brief Construct from @a min and @a max corners directly.
2405 __hostdev__ constexpr BaseBBox(const Vec3T& min, const Vec3T& max) noexcept
2406 : mCoord{min, max}
2407 {
2408 }
2409}; // BaseBBox
2410
2411template<typename Vec3T, bool = util::is_floating_point<typename Vec3T::ValueType>::value>
2412struct BBox;
2413
2414/// @brief Partial template specialization for floating point coordinate types.
2415///
2416/// @note Min is inclusive and max is exclusive. If min = max the dimension of
2417/// the bounding box is zero and therefore it is also empty.
2418template<typename Vec3T>
2419struct BBox<Vec3T, true> : public BaseBBox<Vec3T>
2420{
2421 using Vec3Type = Vec3T;
2422 using ValueType = typename Vec3T::ValueType;
2423 static_assert(util::is_floating_point<ValueType>::value, "Expected a floating point coordinate type");
2425 using BaseT::mCoord;
2426 /// @brief Default construction sets BBox to an empty bbox
2427 __hostdev__ constexpr BBox() noexcept
2428 : BaseT(Vec3T( Maximum<typename Vec3T::ValueType>::value()),
2429 Vec3T(-Maximum<typename Vec3T::ValueType>::value()))
2430 {
2431 }
2432 /// @brief Construct from explicit @a min / @a max corners.
2433 __hostdev__ constexpr BBox(const Vec3T& min, const Vec3T& max) noexcept
2434 : BaseT(min, max)
2435 {
2436 }
2437 /// @brief Convert an integer @c Coord box into this floating-point box.
2438 /// @note @c max is exclusive in the floating-point convention, so the
2439 /// integer @c max corner is incremented by 1 before conversion.
2440 __hostdev__ constexpr BBox(const Coord& min, const Coord& max) noexcept
2441 : BaseT(Vec3T(ValueType(min[0]), ValueType(min[1]), ValueType(min[2])),
2442 Vec3T(ValueType(max[0] + 1), ValueType(max[1] + 1), ValueType(max[2] + 1)))
2443 {
2444 }
2445 /// @brief Return a cube-shaped @c BBox with min corner @a min and edge length @a dim.
2446 __hostdev__ [[nodiscard]] static constexpr BBox createCube(const Coord& min, typename Coord::ValueType dim) noexcept
2447 {
2448 return BBox(min, min.offsetBy(dim));
2449 }
2450
2451 /// @brief Construct from a @c BaseBBox<Coord>; delegates to the @c (min, @c max) ctor.
2452 __hostdev__ constexpr BBox(const BaseBBox<Coord>& bbox) noexcept
2453 : BBox(bbox[0], bbox[1])
2454 {
2455 }
2456 /// @brief Return @c true if this bounding box is empty (max <= min in any axis).
2457 __hostdev__ [[nodiscard]] constexpr bool empty() const noexcept { return mCoord[0][0] >= mCoord[1][0] ||
2458 mCoord[0][1] >= mCoord[1][1] ||
2459 mCoord[0][2] >= mCoord[1][2]; }
2460 /// @brief Convert to bool: @c true iff this bounding box has positive volume.
2461 __hostdev__ [[nodiscard]] constexpr operator bool() const noexcept { return mCoord[0][0] < mCoord[1][0] &&
2462 mCoord[0][1] < mCoord[1][1] &&
2463 mCoord[0][2] < mCoord[1][2]; }
2464 /// @brief Return @c max - @c min when non-empty, else the zero vector.
2465 __hostdev__ [[nodiscard]] constexpr Vec3T dim() const noexcept { return *this ? this->max() - this->min() : Vec3T(0); }
2466 /// @brief Return @c true iff @a p is strictly inside the box (open interval — min is exclusive, max is exclusive).
2467 __hostdev__ [[nodiscard]] constexpr bool isInside(const Vec3T& p) const noexcept
2468 {
2469 return p[0] > mCoord[0][0] && p[1] > mCoord[0][1] && p[2] > mCoord[0][2] &&
2470 p[0] < mCoord[1][0] && p[1] < mCoord[1][1] && p[2] < mCoord[1][2];
2471 }
2472
2473}; // BBox<Vec3T, true>
2474
2475/// @brief Partial template specialization for integer coordinate types
2476///
2477/// @note Both min and max are INCLUDED in the bbox so dim = max - min + 1. So,
2478/// if min = max the bounding box contains exactly one point and dim = 1!
2479template<typename CoordT>
2480struct BBox<CoordT, false> : public BaseBBox<CoordT>
2481{
2482 static_assert(util::is_same<int, typename CoordT::ValueType>::value, "Expected \"int\" coordinate type");
2484 using BaseT::mCoord;
2485 /// @brief Iterator over the domain covered by a BBox
2486 /// @details z is the fastest-moving coordinate.
2488 {
2489 const BBox& mBBox;
2490 CoordT mPos;
2491
2492 public:
2493 /// @brief Construct an iterator positioned at @c b.min().
2494 __hostdev__ constexpr Iterator(const BBox& b) noexcept
2495 : mBBox(b)
2496 , mPos(b.min())
2497 {
2498 }
2499 /// @brief Construct an iterator positioned at the given @a p inside @a b.
2500 __hostdev__ constexpr Iterator(const BBox& b, const Coord& p) noexcept
2501 : mBBox(b)
2502 , mPos(p)
2503 {
2504 }
2505 /// @brief Pre-increment: advance to the next coordinate in row-major z-fastest order.
2506 __hostdev__ constexpr Iterator& operator++() noexcept
2507 {
2508 if (mPos[2] < mBBox[1][2]) { // this is the most common case
2509 ++mPos[2];// increment z
2510 } else if (mPos[1] < mBBox[1][1]) {
2511 mPos[2] = mBBox[0][2];// reset z
2512 ++mPos[1];// increment y
2513 } else if (mPos[0] <= mBBox[1][0]) {
2514 mPos[2] = mBBox[0][2];// reset z
2515 mPos[1] = mBBox[0][1];// reset y
2516 ++mPos[0];// increment x
2517 }
2518 return *this;
2519 }
2520 /// @brief Post-increment: advance to the next coordinate; return a copy of the previous state.
2521 __hostdev__ constexpr Iterator operator++(int) noexcept
2522 {
2523 auto tmp = *this;
2524 ++(*this);
2525 return tmp;
2526 }
2527 /// @brief Iterator equality (asserts both iterators belong to the same @c BBox).
2528 __hostdev__ [[nodiscard]] constexpr bool operator==(const Iterator& rhs) const noexcept
2529 {
2530 NANOVDB_ASSERT(mBBox == rhs.mBBox);
2531 return mPos == rhs.mPos;
2532 }
2533 /// @brief Iterator inequality (asserts both iterators belong to the same @c BBox).
2534 __hostdev__ [[nodiscard]] constexpr bool operator!=(const Iterator& rhs) const noexcept
2535 {
2536 NANOVDB_ASSERT(mBBox == rhs.mBBox);
2537 return mPos != rhs.mPos;
2538 }
2539 /// @brief Lexicographic less-than over the underlying position.
2540 __hostdev__ [[nodiscard]] constexpr bool operator<(const Iterator& rhs) const noexcept
2541 {
2542 NANOVDB_ASSERT(mBBox == rhs.mBBox);
2543 return mPos < rhs.mPos;
2544 }
2545 /// @brief Lexicographic less-than-or-equal over the underlying position.
2546 __hostdev__ [[nodiscard]] constexpr bool operator<=(const Iterator& rhs) const noexcept
2547 {
2548 NANOVDB_ASSERT(mBBox == rhs.mBBox);
2549 return mPos <= rhs.mPos;
2550 }
2551 /// @brief Return @c true if the iterator still points to a valid coordinate.
2552 __hostdev__ [[nodiscard]] constexpr operator bool() const noexcept { return mPos <= mBBox[1]; }
2553 /// @brief Dereference to the current coordinate.
2554 __hostdev__ [[nodiscard]] constexpr const CoordT& operator*() const noexcept { return mPos; }
2555 }; // Iterator
2556 /// @brief Iterator positioned at the min corner.
2557 __hostdev__ [[nodiscard]] constexpr Iterator begin() const noexcept { return Iterator{*this}; }
2558 /// @brief One-past-the-end iterator (max corner shifted by one in @c x).
2559 __hostdev__ [[nodiscard]] constexpr Iterator end() const noexcept { return Iterator{*this, CoordT(mCoord[1][0]+1, mCoord[0][1], mCoord[0][2])}; }
2560 /// @brief Default construct an empty bbox (@c min = @c CoordT::max(), @c max = @c CoordT::min()).
2561 __hostdev__ constexpr BBox() noexcept
2562 : BaseT(CoordT::max(), CoordT::min())
2563 {
2564 }
2565 /// @brief Construct from explicit @a min / @a max integer corners.
2566 __hostdev__ constexpr BBox(const CoordT& min, const CoordT& max) noexcept
2567 : BaseT(min, max)
2568 {
2569 }
2570
2571 /// @brief Splitting constructor (used by parallel range-based iteration).
2572 /// @details Halves the box along its longest axis: @c other keeps the upper
2573 /// half, the newly constructed @c BBox is the lower half. The @c SplitT tag
2574 /// type is ignored; it exists so this overload doesn't collide with the
2575 /// copy constructor.
2576 template<typename SplitT>
2577 __hostdev__ constexpr BBox(BBox& other, const SplitT&) noexcept
2578 : BaseT(other.mCoord[0], other.mCoord[1])
2579 {
2581 const int n = MaxIndex(this->dim());
2582 mCoord[1][n] = (mCoord[0][n] + mCoord[1][n]) >> 1;
2583 other.mCoord[0][n] = mCoord[1][n] + 1;
2584 }
2585
2586 /// @brief Return a cube-shaped @c BBox with min corner @a min and edge length @a dim.
2587 /// @note Subtracts 1 from @a dim because the integer convention is min/max inclusive.
2588 __hostdev__ [[nodiscard]] static constexpr BBox createCube(const CoordT& min, typename CoordT::ValueType dim) noexcept
2589 {
2590 return BBox(min, min.offsetBy(dim - 1));
2591 }
2592
2593 /// @brief Return a cube-shaped @c BBox spanning @a min..@a max in every axis.
2594 __hostdev__ [[nodiscard]] static constexpr BBox createCube(typename CoordT::ValueType min, typename CoordT::ValueType max) noexcept
2595 {
2596 return BBox(CoordT(min), CoordT(max));
2597 }
2598
2599 /// @brief Return @c true iff the box has more than one cell along every axis.
2600 __hostdev__ [[nodiscard]] constexpr bool is_divisible() const noexcept { return mCoord[0][0] < mCoord[1][0] &&
2601 mCoord[0][1] < mCoord[1][1] &&
2602 mCoord[0][2] < mCoord[1][2]; }
2603 /// @brief Return true if this bounding box is empty, e.g. uninitialized
2604 __hostdev__ [[nodiscard]] constexpr bool empty() const noexcept { return mCoord[0][0] > mCoord[1][0] ||
2605 mCoord[0][1] > mCoord[1][1] ||
2606 mCoord[0][2] > mCoord[1][2]; }
2607 /// @brief Convert this BBox to boolean true if it is not empty
2608 __hostdev__ [[nodiscard]] constexpr operator bool() const noexcept { return mCoord[0][0] <= mCoord[1][0] &&
2609 mCoord[0][1] <= mCoord[1][1] &&
2610 mCoord[0][2] <= mCoord[1][2]; }
2611 /// @brief Return the per-axis extent (max - min + 1 when non-empty, else 0).
2612 __hostdev__ [[nodiscard]] constexpr CoordT dim() const noexcept { return *this ? this->max() - this->min() + Coord(1) : Coord(0); }
2613 /// @brief Return the number of integer cells in the box, i.e. @c dim().x * @c dim().y * @c dim().z.
2614 __hostdev__ [[nodiscard]] constexpr uint64_t volume() const noexcept
2615 {
2616 auto d = this->dim();
2617 return uint64_t(d[0]) * uint64_t(d[1]) * uint64_t(d[2]);
2618 }
2619 /// @brief Return @c true iff the integer coordinate @a p lies inside the closed box.
2620 __hostdev__ [[nodiscard]] constexpr bool isInside(const CoordT& p) const noexcept { return !(CoordT::lessThan(p, this->min()) || CoordT::lessThan(this->max(), p)); }
2621 /// @brief Return @c true if the given bounding box is inside this bounding box.
2622 __hostdev__ [[nodiscard]] constexpr bool isInside(const BBox& b) const noexcept
2623 {
2624 return !(CoordT::lessThan(b.min(), this->min()) || CoordT::lessThan(this->max(), b.max()));
2625 }
2626
2627 /// @brief Return @c true if the given bounding box overlaps with this bounding box.
2628 __hostdev__ [[nodiscard]] constexpr bool hasOverlap(const BBox& b) const noexcept
2629 {
2630 return !(CoordT::lessThan(this->max(), b.min()) || CoordT::lessThan(b.max(), this->min()));
2631 }
2632
2633 /// @warning This converts a CoordBBox into a floating-point bounding box which implies that max += 1 !
2634 template<typename RealT = double>
2635 __hostdev__ [[nodiscard]] constexpr BBox<Vec3<RealT>> asReal() const noexcept
2636 {
2637 static_assert(util::is_floating_point<RealT>::value, "CoordBBox::asReal: Expected a floating point coordinate");
2638 return BBox<Vec3<RealT>>(Vec3<RealT>(RealT(mCoord[0][0]), RealT(mCoord[0][1]), RealT(mCoord[0][2])),
2639 Vec3<RealT>(RealT(mCoord[1][0] + 1), RealT(mCoord[1][1] + 1), RealT(mCoord[1][2] + 1)));
2640 }
2641 /// @brief Return a new instance that is expanded by the specified padding.
2642 __hostdev__ [[nodiscard]] constexpr BBox expandBy(typename CoordT::ValueType padding) const noexcept
2643 {
2644 return BBox(mCoord[0].offsetBy(-padding), mCoord[1].offsetBy(padding));
2645 }
2646
2647 /// @brief Transform this coordinate bounding box by the specified map.
2648 /// @param map mapping of index to world coordinates
2649 /// @return world bounding box
2650 template<typename Map>
2651 __hostdev__ [[nodiscard]] constexpr auto transform(const Map& map) const noexcept
2652 {
2653 using Vec3T = Vec3<double>;
2654 const Vec3T tmp = map.applyMap(Vec3T(mCoord[0][0], mCoord[0][1], mCoord[0][2]));
2655 BBox<Vec3T> bbox(tmp, tmp);// return value
2656 bbox.expand(map.applyMap(Vec3T(mCoord[0][0], mCoord[0][1], mCoord[1][2])));
2657 bbox.expand(map.applyMap(Vec3T(mCoord[0][0], mCoord[1][1], mCoord[0][2])));
2658 bbox.expand(map.applyMap(Vec3T(mCoord[1][0], mCoord[0][1], mCoord[0][2])));
2659 bbox.expand(map.applyMap(Vec3T(mCoord[1][0], mCoord[1][1], mCoord[0][2])));
2660 bbox.expand(map.applyMap(Vec3T(mCoord[1][0], mCoord[0][1], mCoord[1][2])));
2661 bbox.expand(map.applyMap(Vec3T(mCoord[0][0], mCoord[1][1], mCoord[1][2])));
2662 bbox.expand(map.applyMap(Vec3T(mCoord[1][0], mCoord[1][1], mCoord[1][2])));
2663 return bbox;
2664 }
2665
2666#if defined(__CUDACC__) // the following functions only run on the GPU!
2667 /// @brief Device-only: atomically expand the box to enclose the integer point @a ijk.
2668 __device__ inline BBox& expandAtomic(const CoordT& ijk) noexcept
2669 {
2670 mCoord[0].minComponentAtomic(ijk);
2671 mCoord[1].maxComponentAtomic(ijk);
2672 return *this;
2673 }
2674 /// @brief Device-only: atomically expand the box to enclose another @a bbox.
2675 __device__ inline BBox& expandAtomic(const BBox& bbox) noexcept
2676 {
2677 mCoord[0].minComponentAtomic(bbox[0]);
2678 mCoord[1].maxComponentAtomic(bbox[1]);
2679 return *this;
2680 }
2681 /// @brief Device-only: atomically intersect this box with @a bbox.
2682 __device__ inline BBox& intersectAtomic(const BBox& bbox) noexcept
2683 {
2684 mCoord[0].maxComponentAtomic(bbox[0]);
2685 mCoord[1].minComponentAtomic(bbox[1]);
2686 return *this;
2687 }
2688#endif
2689}; // BBox<CoordT, false>
2690
2691// --------------------------> Rgba8 <------------------------------------
2692
2693/// @brief 8-bit red, green, blue, alpha packed into 32 bit unsigned int
2695{
2696 union
2697 {
2698 uint8_t c[4]; // 4 integer color channels of red, green, blue and alpha components.
2699 uint32_t packed; // 32 bit packed representation
2700 } mData;
2701
2702public:
2703 static const int SIZE = 4;
2704 using ValueType = uint8_t;
2705
2706 /// @brief Default copy constructor
2707 Rgba8(const Rgba8&) noexcept = default;
2708
2709 /// @brief Default move constructor
2710 Rgba8(Rgba8&&) noexcept = default;
2711
2712 /// @brief Default move assignment operator
2713 /// @return non-const reference to this instance
2714 Rgba8& operator=(Rgba8&&) noexcept = default;
2715
2716 /// @brief Default copy assignment operator
2717 /// @return non-const reference to this instance
2718 Rgba8& operator=(const Rgba8&) noexcept = default;
2719
2720 /// @brief Default ctor initializes all channels to zero
2721 __hostdev__ constexpr Rgba8() noexcept
2722 : mData{{0, 0, 0, 0}}
2723 {
2724 static_assert(sizeof(uint32_t) == sizeof(Rgba8), "Unexpected sizeof");
2725 }
2726
2727 /// @brief integer r,g,b,a ctor where alpha channel defaults to opaque
2728 /// @note all values should be in the range 0u to 255u
2729 __hostdev__ constexpr Rgba8(uint8_t r, uint8_t g, uint8_t b, uint8_t a = 255u) noexcept
2730 : mData{{r, g, b, a}}
2731 {
2732 }
2733
2734 /// @brief Ctor where all channels are initialized to the same value.
2735 /// @note value should be in the range 0u to 255u
2736 explicit __hostdev__ constexpr Rgba8(uint8_t v) noexcept
2737 : mData{{v, v, v, v}}
2738 {
2739 }
2740
2741 /// @brief floating-point r,g,b,a ctor where alpha channel defaults to opaque
2742 /// @note all values should be in the range 0.0f to 1.0f
2743 __hostdev__ constexpr Rgba8(float r, float g, float b, float a = 1.0f) noexcept
2744 : mData{{static_cast<uint8_t>(0.5f + r * 255.0f), // round floats to nearest integers
2745 static_cast<uint8_t>(0.5f + g * 255.0f), // double {{}} is needed due to union
2746 static_cast<uint8_t>(0.5f + b * 255.0f),
2747 static_cast<uint8_t>(0.5f + a * 255.0f)}}
2748 {
2749 }
2750
2751 /// @brief Construct from a @c Vec3<float> with rgb components (alpha set to opaque).
2752 /// @note all values should be in the range 0.0f to 1.0f
2753 __hostdev__ constexpr Rgba8(const Vec3<float>& rgb) noexcept
2754 : Rgba8(rgb[0], rgb[1], rgb[2])
2755 {
2756 }
2757
2758 /// @brief Construct from a @c Vec4<float> with rgba components.
2759 /// @note all values should be in the range 0.0f to 1.0f
2760 __hostdev__ constexpr Rgba8(const Vec4<float>& rgba) noexcept
2761 : Rgba8(rgba[0], rgba[1], rgba[2], rgba[3])
2762 {
2763 }
2764
2765 /// @brief Compare on the 32-bit packed integer representation (lexicographic by byte).
2766 __hostdev__ [[nodiscard]] bool operator< (const Rgba8& rhs) const noexcept { return mData.packed < rhs.mData.packed; }
2767 /// @brief Equality on the 32-bit packed integer representation.
2768 __hostdev__ [[nodiscard]] bool operator==(const Rgba8& rhs) const noexcept { return mData.packed == rhs.mData.packed; }
2769 /// @brief Return the squared L2 length of the rgb channels in the [0, 1] range
2770 /// (alpha is ignored). @c 0.0000153787005f is @c 1/255^2.
2771 __hostdev__ [[nodiscard]] constexpr float lengthSqr() const noexcept
2772 {
2773 return 0.0000153787005f * (float(mData.c[0]) * mData.c[0] +
2774 float(mData.c[1]) * mData.c[1] +
2775 float(mData.c[2]) * mData.c[2]); //1/255^2
2776 }
2777 /// @brief L2 length of the rgb channels (alpha ignored). Not @c constexpr — calls @c sqrtf.
2778 __hostdev__ [[nodiscard]] float length() const noexcept { return sqrtf(this->lengthSqr()); }
2779 /// @brief Return the @a n'th color channel as a float in the range 0 to 1.
2780 __hostdev__ [[nodiscard]] constexpr float asFloat(int n) const noexcept { return 0.003921569f*float(mData.c[n]); }// divide by 255
2781 /// @brief Indexed channel access. Asserts @c 0 <= @a n < 4 in debug builds.
2782 __hostdev__ constexpr const uint8_t& operator[](int n) const noexcept { NANOVDB_ASSERT(n >= 0 && n < 4); return mData.c[n]; }
2783 /// @brief Mutable variant of @c operator[].
2784 __hostdev__ constexpr uint8_t& operator[](int n) noexcept { NANOVDB_ASSERT(n >= 0 && n < 4); return mData.c[n]; }
2785 /// @brief Const access to the 32-bit packed integer representation.
2786 __hostdev__ const uint32_t& packed() const noexcept { return mData.packed; }
2787 /// @brief Mutable access to the 32-bit packed integer representation.
2788 __hostdev__ uint32_t& packed() noexcept { return mData.packed; }
2789 //@{
2790 /// @brief Named channel accessors (r, g, b, a). Both const and non-const variants.
2791 __hostdev__ constexpr const uint8_t& r() const noexcept { return mData.c[0]; }
2792 __hostdev__ constexpr const uint8_t& g() const noexcept { return mData.c[1]; }
2793 __hostdev__ constexpr const uint8_t& b() const noexcept { return mData.c[2]; }
2794 __hostdev__ constexpr const uint8_t& a() const noexcept { return mData.c[3]; }
2795 __hostdev__ constexpr uint8_t& r() noexcept { return mData.c[0]; }
2796 __hostdev__ constexpr uint8_t& g() noexcept { return mData.c[1]; }
2797 __hostdev__ constexpr uint8_t& b() noexcept { return mData.c[2]; }
2798 __hostdev__ constexpr uint8_t& a() noexcept { return mData.c[3]; }
2799 //@}
2800 /// @brief Implicit conversion to a @c Vec3<float> with channels in [0, 1] (alpha dropped).
2801 __hostdev__ [[nodiscard]] constexpr operator Vec3<float>() const noexcept {
2802 return Vec3<float>(this->asFloat(0), this->asFloat(1), this->asFloat(2));
2803 }
2804 /// @brief Implicit conversion to a @c Vec4<float> with rgba channels in [0, 1].
2805 __hostdev__ [[nodiscard]] constexpr operator Vec4<float>() const noexcept {
2806 return Vec4<float>(this->asFloat(0), this->asFloat(1), this->asFloat(2), this->asFloat(3));
2807 }
2808}; // Rgba8
2809
2816
2821
2822}// namespace math ===============================================================
2823
2824using math::Coord;
2825
2832
2837
2840
2841} // namespace nanovdb ===================================================================
2842
2843#endif // end of NANOVDB_MATH_MATH_H_HAS_BEEN_INCLUDED
#define __hostdev__
Definition SampleFromVoxels.h:29
__hostdev__ constexpr Coord() noexcept
Initialize all coordinates to zero.
Definition Math.h:432
Iterator over the domain covered by a BBox.
Definition Math.h:2488
__hostdev__ constexpr bool operator==(const Iterator &rhs) const noexcept
Iterator equality (asserts both iterators belong to the same BBox).
Definition Math.h:2528
__hostdev__ constexpr const CoordT & operator*() const noexcept
Dereference to the current coordinate.
Definition Math.h:2554
__hostdev__ constexpr Iterator operator++(int) noexcept
Post-increment: advance to the next coordinate; return a copy of the previous state.
Definition Math.h:2521
__hostdev__ constexpr Iterator(const BBox &b, const Coord &p) noexcept
Construct an iterator positioned at the given p inside b.
Definition Math.h:2500
__hostdev__ constexpr Iterator(const BBox &b) noexcept
Construct an iterator positioned at b.min().
Definition Math.h:2494
__hostdev__ constexpr bool operator<=(const Iterator &rhs) const noexcept
Lexicographic less-than-or-equal over the underlying position.
Definition Math.h:2546
__hostdev__ constexpr bool operator<(const Iterator &rhs) const noexcept
Lexicographic less-than over the underlying position.
Definition Math.h:2540
__hostdev__ constexpr bool operator!=(const Iterator &rhs) const noexcept
Iterator inequality (asserts both iterators belong to the same BBox).
Definition Math.h:2534
__hostdev__ constexpr Iterator & operator++() noexcept
Pre-increment: advance to the next coordinate in row-major z-fastest order.
Definition Math.h:2506
Signed (i, j) 32-bit integer coordinate class, similar to openvdb::math::Coord.
Definition Math.h:699
__hostdev__ constexpr Coord2 & minComponent(const Coord2 &other) noexcept
Perform a component-wise minimum with the other Coord.
Definition Math.h:860
__hostdev__ constexpr Coord2 operator&(IndexType n) const noexcept
Return a new instance with coordinates masked by the given unsigned integer.
Definition Math.h:766
uint32_t IndexType
Definition Math.h:703
__hostdev__ constexpr Coord2 operator-() const noexcept
Component-wise negation.
Definition Math.h:843
__hostdev__ constexpr int32_t y() const noexcept
Definition Math.h:732
__hostdev__ constexpr bool operator==(const Coord2 &rhs) const noexcept
Return true iff every component matches rhs.
Definition Math.h:807
__hostdev__ constexpr bool operator>(const Coord2 &rhs) const noexcept
Return true if this Coord is lexicographically greater than the given Coord.
Definition Math.h:791
__hostdev__ constexpr Coord2 & operator-=(const Coord2 &rhs) noexcept
In-place component-wise subtraction with another coordinate.
Definition Math.h:852
__hostdev__ constexpr bool operator>=(const Coord2 &rhs) const noexcept
Return true if this Coord is lexicographically greater or equal to the given Coord.
Definition Math.h:799
__hostdev__ constexpr Coord2() noexcept
Initialize all coordinates to zero.
Definition Math.h:706
__hostdev__ constexpr Coord2 offsetBy(ValueType dx, ValueType dy) const noexcept
Return a new Coord2 offset component-by-component by (dx, dy).
Definition Math.h:896
__hostdev__ constexpr Coord2 & operator<<=(uint32_t n) noexcept
In-place left-shift of every component by n bits.
Definition Math.h:818
__hostdev__ constexpr Coord2 round() const noexcept
Identity (Coord2 is already integer); provided so generic code can call .round() uniformly on Coord2 ...
Definition Math.h:924
__hostdev__ constexpr bool operator<(const Coord2 &rhs) const noexcept
Return true if this Coord is lexicographically less than the given Coord.
Definition Math.h:775
static __hostdev__ constexpr Coord2 min() noexcept
Smallest representable Coord2 (all components = INT32_MIN).
Definition Math.h:742
__hostdev__ constexpr Coord2 & operator+=(const Coord2 &rhs) noexcept
In-place component-wise addition with another coordinate.
Definition Math.h:845
__hostdev__ constexpr Coord2 operator+(const Coord2 &rhs) const noexcept
Component-wise sum of two coordinates.
Definition Math.h:839
__hostdev__ constexpr bool operator<=(const Coord2 &rhs) const noexcept
Return true if this Coord is lexicographically less or equal to the given Coord.
Definition Math.h:783
static __hostdev__ Coord2 Floor(const Vec2T &xy) noexcept
Return the largest integer coordinates that are not greater than xyz (node centered conversion).
Definition Math.h:914
__hostdev__ constexpr Coord2(ValueType *ptr) noexcept
Read two signed integers from ptr (no bounds check).
Definition Math.h:724
__hostdev__ constexpr Coord2(ValueType i, ValueType j) noexcept
Initializes coordinate to the given signed integers.
Definition Math.h:718
__hostdev__ constexpr Vec2< float > asVec2s() const noexcept
Return a single precision floating-point vector of this coordinate.
Definition Math.h:1323
__hostdev__ constexpr bool operator!=(const Coord2 &rhs) const noexcept
Return true iff any component differs from rhs.
Definition Math.h:809
__hostdev__ constexpr Coord2 operator>>(IndexType n) const noexcept
Return a new instance with coordinates right-shifted by the given unsigned integer.
Definition Math.h:772
__hostdev__ constexpr const ValueType & operator[](IndexType i) const noexcept
Return a const reference to the given Coord component.
Definition Math.h:749
static __hostdev__ constexpr Coord2 max() noexcept
Largest representable Coord2 (all components = INT32_MAX).
Definition Math.h:739
__hostdev__ constexpr Coord2 offsetBy(ValueType n) const noexcept
Return a new Coord2 offset by the same scalar n in both components.
Definition Math.h:902
__hostdev__ constexpr Coord2 & maxComponent(const Coord2 &other) noexcept
Perform a component-wise maximum with the other Coord.
Definition Math.h:870
static __hostdev__ constexpr size_t memUsage() noexcept
Byte size of a Coord2 (always 8 on a 32-bit int32_t platform).
Definition Math.h:745
__hostdev__ constexpr Coord2(ValueType n) noexcept
Initializes all coordinates to the given signed integer.
Definition Math.h:712
__hostdev__ constexpr Coord2 operator-(const Coord2 &rhs) const noexcept
Component-wise difference of two coordinates.
Definition Math.h:841
__hostdev__ constexpr Coord2 & operator+=(int n) noexcept
Add a scalar to every component in place.
Definition Math.h:832
__hostdev__ constexpr int32_t & y() noexcept
Definition Math.h:735
__hostdev__ constexpr Coord2 & operator&=(int n) noexcept
In-place component-wise bitwise AND with the given mask.
Definition Math.h:811
__hostdev__ constexpr int32_t & x() noexcept
Definition Math.h:734
static __hostdev__ constexpr bool lessThan(const Coord2 &a, const Coord2 &b) noexcept
Definition Math.h:906
__hostdev__ constexpr Coord2 & operator>>=(uint32_t n) noexcept
In-place right-shift of every component by n bits.
Definition Math.h:825
__hostdev__ constexpr int32_t x() const noexcept
Named component accessors (x = mVec[0], y = mVec[1]).
Definition Math.h:731
__hostdev__ constexpr Coord2 & operator=(const CoordT &other) noexcept
Assignment operator that works with openvdb::Coord.
Definition Math.h:757
__hostdev__ constexpr Coord2 operator<<(IndexType n) const noexcept
Return a new instance with coordinates left-shifted by the given unsigned integer.
Definition Math.h:769
__hostdev__ constexpr Vec2< double > asVec2d() const noexcept
Return a double precision floating-point vector of this coordinate.
Definition Math.h:1329
int32_t ValueType
Definition Math.h:702
__hostdev__ constexpr ValueType & operator[](IndexType i) noexcept
Return a non-const reference to the given Coord component.
Definition Math.h:753
Signed (i, j, k) 32-bit integer coordinate class, similar to openvdb::math::Coord.
Definition Math.h:425
__hostdev__ constexpr Vec3< float > asVec3s() const noexcept
Return a single precision floating-point vector of this coordinate.
Definition Math.h:2014
__hostdev__ constexpr Coord() noexcept
Initialize all coordinates to zero.
Definition Math.h:432
__hostdev__ constexpr Vec3< double > asVec3d() const noexcept
Return a double precision floating-point vector of this coordinate.
Definition Math.h:2020
__hostdev__ constexpr uint32_t hash() const noexcept
Return a hash key derived from the existing coordinates.
Definition Math.h:671
uint32_t IndexType
Definition Math.h:429
__hostdev__ constexpr Coord operator-(const Coord &rhs) const noexcept
Component-wise difference of two coordinates.
Definition Math.h:582
__hostdev__ constexpr Coord & operator-=(const Coord &rhs) noexcept
In-place component-wise subtraction with another coordinate.
Definition Math.h:594
__hostdev__ constexpr Coord operator<<(IndexType n) const noexcept
Return a new instance with coordinates left-shifted by the given unsigned integer.
Definition Math.h:498
__hostdev__ constexpr uint8_t octant() const noexcept
Return the octant of this Coord.
Definition Math.h:674
__hostdev__ constexpr Coord & minComponent(const Coord &other) noexcept
Perform a component-wise minimum with the other Coord.
Definition Math.h:603
static __hostdev__ constexpr Coord min() noexcept
Smallest representable Coord (all components = INT32_MIN).
Definition Math.h:470
__hostdev__ constexpr int32_t y() const noexcept
Definition Math.h:458
__hostdev__ constexpr Coord operator>>(IndexType n) const noexcept
Return a new instance with coordinates right-shifted by the given unsigned integer.
Definition Math.h:501
__hostdev__ constexpr Coord & operator&=(int n) noexcept
In-place component-wise bitwise AND with the given mask.
Definition Math.h:548
__hostdev__ constexpr int32_t z() const noexcept
Definition Math.h:459
__hostdev__ constexpr Coord operator+(const Coord &rhs) const noexcept
Component-wise sum of two coordinates.
Definition Math.h:580
__hostdev__ constexpr Coord & maxComponent(const Coord &other) noexcept
Perform a component-wise maximum with the other Coord.
Definition Math.h:615
__hostdev__ constexpr Coord round() const noexcept
Identity (Coord is already integer); provided so generic code can call .round() uniformly on Coord an...
Definition Math.h:686
__hostdev__ constexpr bool operator<(const Coord &rhs) const noexcept
Return true if this Coord is lexicographically less than the given Coord.
Definition Math.h:504
__hostdev__ constexpr Coord offsetBy(ValueType dx, ValueType dy, ValueType dz) const noexcept
Return a new Coord offset component-by-component by (dx, dy, dz).
Definition Math.h:645
__hostdev__ constexpr Coord(ValueType n) noexcept
Initializes all coordinates to the given signed integer.
Definition Math.h:438
static __hostdev__ constexpr Coord max() noexcept
Largest representable Coord (all components = INT32_MAX).
Definition Math.h:467
__hostdev__ constexpr const ValueType & operator[](IndexType i) const noexcept
Return a const reference to the given Coord component.
Definition Math.h:477
__hostdev__ constexpr Coord & operator+=(const Coord &rhs) noexcept
In-place component-wise addition with another coordinate.
Definition Math.h:586
__hostdev__ constexpr bool operator==(const Coord &rhs) const noexcept
Return true iff every component matches rhs.
Definition Math.h:544
static __hostdev__ constexpr size_t memUsage() noexcept
Byte size of a Coord (always 12 on a 32-bit int32_t platform).
Definition Math.h:473
__hostdev__ constexpr bool operator>=(const Coord &rhs) const noexcept
Return true if this Coord is lexicographically greater or equal to the given Coord.
Definition Math.h:534
__hostdev__ constexpr Coord & operator<<=(uint32_t n) noexcept
In-place left-shift of every component by n bits.
Definition Math.h:556
__hostdev__ constexpr Coord & operator>>=(uint32_t n) noexcept
In-place right-shift of every component by n bits.
Definition Math.h:564
__hostdev__ constexpr Coord operator&(IndexType n) const noexcept
Return a new instance with coordinates masked by the given unsigned integer.
Definition Math.h:495
__hostdev__ constexpr Coord offsetBy(ValueType n) const noexcept
Return a new Coord offset by the same scalar n in every component.
Definition Math.h:651
__hostdev__ constexpr Coord & operator=(const CoordT &other) noexcept
Assignment operator that works with openvdb::Coord.
Definition Math.h:485
__hostdev__ constexpr Coord(ValueType i, ValueType j, ValueType k) noexcept
Initializes coordinate to the given signed integers.
Definition Math.h:444
__hostdev__ constexpr bool operator>(const Coord &rhs) const noexcept
Return true if this Coord is lexicographically greater than the given Coord.
Definition Math.h:524
__hostdev__ constexpr Coord(ValueType *ptr) noexcept
Read three signed integers from ptr (no bounds check).
Definition Math.h:450
__hostdev__ constexpr int32_t & y() noexcept
Definition Math.h:462
static __hostdev__ Coord Floor(const Vec3T &xyz) noexcept
Return the largest integer coordinates that are not greater than xyz (node centered conversion).
Definition Math.h:663
__hostdev__ constexpr bool operator<=(const Coord &rhs) const noexcept
Return true if this Coord is lexicographically less or equal to the given Coord.
Definition Math.h:514
__hostdev__ constexpr Coord & operator+=(int n) noexcept
Add a scalar to every component in place.
Definition Math.h:572
__hostdev__ constexpr int32_t & z() noexcept
Definition Math.h:463
__hostdev__ constexpr int32_t & x() noexcept
Definition Math.h:461
__hostdev__ constexpr int32_t x() const noexcept
Named component accessors (x = mVec[0], y = mVec[1], z = mVec[2]).
Definition Math.h:457
static __hostdev__ constexpr bool lessThan(const Coord &a, const Coord &b) noexcept
Definition Math.h:655
__hostdev__ constexpr Coord operator-() const noexcept
Component-wise negation.
Definition Math.h:584
__hostdev__ constexpr bool operator!=(const Coord &rhs) const noexcept
Return true iff any component differs from rhs.
Definition Math.h:546
int32_t ValueType
Definition Math.h:428
__hostdev__ constexpr ValueType & operator[](IndexType i) noexcept
Return a non-const reference to the given Coord component.
Definition Math.h:481
2x2 row-major matrix.
Definition Math.h:1546
__hostdev__ constexpr Mat2 operator/(const T &s) const noexcept
Definition Math.h:1575
__hostdev__ constexpr Mat2 operator*(const Mat2 &m) const noexcept
Definition Math.h:1570
__hostdev__ constexpr Mat2 operator-(const Mat2 &m) const noexcept
Definition Math.h:1565
__hostdev__ constexpr Mat2 & operator+=(const Mat2 &m) noexcept
Definition Math.h:1566
__hostdev__ constexpr bool operator==(const Mat2 &m) const noexcept
Definition Math.h:1580
__hostdev__ constexpr Mat2 & operator/=(const T &s) noexcept
Definition Math.h:1577
__hostdev__ constexpr Mat2(Source *array) noexcept
Constructor given array of elements, the ordering is in row major form.
Definition Math.h:1560
__hostdev__ constexpr Mat2< T > inverse() const noexcept
returns inverse of this
Definition Math.h:1587
__hostdev__ constexpr Mat2 operator+(const Mat2 &m) const noexcept
Definition Math.h:1564
__hostdev__ constexpr Mat2 operator*(const T &s) const noexcept
Definition Math.h:1574
__hostdev__ constexpr Mat2 transpose() const noexcept
returns transpose of this
Definition Math.h:1584
__hostdev__ friend constexpr Mat2 operator*(const T &s, const Mat2 &m) noexcept
scalar * Mat (hidden friend — found only via ADL on Mat2)
Definition Math.h:1598
__hostdev__ constexpr Mat2 & operator*=(const T &s) noexcept
Definition Math.h:1576
Mat2() noexcept=default
Default-construct (entries left uninitialized for fundamental T).
__hostdev__ constexpr bool operator!=(const Mat2 &m) const noexcept
Definition Math.h:1581
__hostdev__ constexpr Mat2 & operator-=(const Mat2 &m) noexcept
Definition Math.h:1567
__hostdev__ constexpr Mat2 operator-() const noexcept
Definition Math.h:1563
__hostdev__ constexpr Vec2< T > operator*(const Vec2< T > &v) const noexcept
Definition Math.h:1571
2x3 row-major matrix.
Definition Math.h:1609
__hostdev__ constexpr Mat2x3(Source *array) noexcept
Constructor given array of elements, the ordering is in row major form.
Definition Math.h:1623
__hostdev__ constexpr Mat2x3 & operator+=(const Mat2x3 &m) noexcept
Definition Math.h:1630
__hostdev__ constexpr Mat2x3 operator/(const T &s) const noexcept
Definition Math.h:1638
__hostdev__ constexpr Vec2< T > operator*(const Vec3< T > &v) const noexcept
Definition Math.h:1634
__hostdev__ constexpr Mat2x3 & operator*=(const T &s) noexcept
Definition Math.h:1639
__hostdev__ constexpr Mat3x2< T > transpose() const noexcept
returns transpose of this
Definition Math.h:1647
__hostdev__ constexpr Mat2x3 & operator/=(const T &s) noexcept
Definition Math.h:1640
__hostdev__ constexpr Mat2x3 & operator-=(const Mat2x3 &m) noexcept
Definition Math.h:1631
__hostdev__ constexpr bool operator==(const Mat2x3 &m) const noexcept
Definition Math.h:1643
__hostdev__ constexpr Mat2x3 operator-(const Mat2x3 &m) const noexcept
Definition Math.h:1629
__hostdev__ constexpr bool operator!=(const Mat2x3 &m) const noexcept
Definition Math.h:1644
__hostdev__ constexpr Mat2x3 operator-() const noexcept
Definition Math.h:1627
__hostdev__ constexpr Mat2x3 operator+(const Mat2x3 &m) const noexcept
Definition Math.h:1628
Mat2x3() noexcept=default
Default-construct (entries left uninitialized for fundamental T).
__hostdev__ constexpr Mat2x3 operator*(const T &s) const noexcept
Definition Math.h:1637
__hostdev__ friend constexpr Mat2x3 operator*(const T &s, const Mat2x3 &m) noexcept
scalar * Mat (hidden friend — found only via ADL on Mat2x3)
Definition Math.h:1650
3x3 row-major matrix.
Definition Math.h:1714
__hostdev__ constexpr Mat3 transpose() const noexcept
returns transpose of this
Definition Math.h:1757
__hostdev__ constexpr Mat3(Source *a) noexcept
Constructor given array of elements, the ordering is in row major form.
Definition Math.h:1732
__hostdev__ constexpr Mat3 & operator-=(const Mat3 &m) noexcept
Definition Math.h:1740
__hostdev__ constexpr Mat3 operator*(const Mat3 &m) const noexcept
Definition Math.h:1743
Mat3() noexcept=default
Default-construct (entries left uninitialized for fundamental T).
__hostdev__ friend constexpr Mat3 operator*(const T &s, const Mat3 &m) noexcept
scalar * Mat (hidden friend — found only via ADL on Mat3)
Definition Math.h:1760
__hostdev__ constexpr bool operator!=(const Mat3 &m) const noexcept
Definition Math.h:1754
__hostdev__ constexpr Mat3 & operator+=(const Mat3 &m) noexcept
Definition Math.h:1739
__hostdev__ constexpr bool operator==(const Mat3 &m) const noexcept
Definition Math.h:1753
__hostdev__ constexpr Mat3 operator+(const Mat3 &m) const noexcept
Definition Math.h:1737
__hostdev__ constexpr Mat3 operator*(const T &s) const noexcept
Definition Math.h:1747
__hostdev__ constexpr Mat3 & operator/=(const T &s) noexcept
Definition Math.h:1750
__hostdev__ constexpr Mat3 & operator*=(const T &s) noexcept
Definition Math.h:1749
__hostdev__ constexpr Mat3 operator/(const T &s) const noexcept
Definition Math.h:1748
__hostdev__ constexpr Vec3< T > operator*(const Vec3< T > &v) const noexcept
Definition Math.h:1744
__hostdev__ constexpr Mat3 operator-() const noexcept
Definition Math.h:1736
__hostdev__ constexpr Mat3 operator-(const Mat3 &m) const noexcept
Definition Math.h:1738
3x2 row-major matrix.
Definition Math.h:1661
__hostdev__ constexpr Mat2x3< T > transpose() const noexcept
returns transpose of this
Definition Math.h:1700
__hostdev__ constexpr Mat3x2 operator-(const Mat3x2 &m) const noexcept
Definition Math.h:1682
__hostdev__ constexpr bool operator==(const Mat3x2 &m) const noexcept
Definition Math.h:1696
__hostdev__ constexpr Mat3x2(Source *a) noexcept
Constructor given array of elements, the ordering is in row major form.
Definition Math.h:1677
__hostdev__ constexpr bool operator!=(const Mat3x2 &m) const noexcept
Definition Math.h:1697
__hostdev__ constexpr Mat3x2 operator+(const Mat3x2 &m) const noexcept
Definition Math.h:1681
__hostdev__ constexpr Mat3x2 & operator*=(const T &s) noexcept
Definition Math.h:1692
Mat3x2() noexcept=default
Default-construct (entries left uninitialized for fundamental T).
__hostdev__ constexpr Mat3x2 & operator-=(const Mat3x2 &m) noexcept
Definition Math.h:1684
__hostdev__ constexpr Mat3x2 operator-() const noexcept
Definition Math.h:1680
__hostdev__ constexpr Mat3x2 operator*(const T &s) const noexcept
Definition Math.h:1690
__hostdev__ constexpr Vec3< T > operator*(const Vec2< T > &v) const noexcept
Definition Math.h:1687
__hostdev__ friend constexpr Mat3x2 operator*(const T &s, const Mat3x2 &m) noexcept
scalar * Mat (hidden friend — found only via ADL on Mat3x2)
Definition Math.h:1703
__hostdev__ constexpr Mat3x2 & operator+=(const Mat3x2 &m) noexcept
Definition Math.h:1683
__hostdev__ constexpr Mat3x2 & operator/=(const T &s) noexcept
Definition Math.h:1693
__hostdev__ constexpr Mat3x2 operator/(const T &s) const noexcept
Definition Math.h:1691
__hostdev__ constexpr Mat4(Source *a) noexcept
Constructor given array of elements, the ordering is in row major form.
Definition Math.h:1791
Mat4() noexcept=default
Default-construct (entries left uninitialized for fundamental T).
__hostdev__ constexpr Mat4 operator*(const Mat4 &m) const noexcept
Definition Math.h:1801
__hostdev__ constexpr Mat4 & operator*=(const T &s) noexcept
Definition Math.h:1807
__hostdev__ constexpr Mat4 & operator+=(const Mat4 &m) noexcept
Definition Math.h:1797
__hostdev__ constexpr Mat4 operator-(const Mat4 &m) const noexcept
Definition Math.h:1796
__hostdev__ constexpr Mat4 operator-() const noexcept
Definition Math.h:1794
__hostdev__ constexpr Mat4 & operator/=(const T &s) noexcept
Definition Math.h:1808
__hostdev__ constexpr Mat4 operator/(const T &s) const noexcept
Definition Math.h:1806
__hostdev__ constexpr Mat4 transpose() const noexcept
returns transpose of this
Definition Math.h:1815
__hostdev__ constexpr Mat4 operator*(const T &s) const noexcept
Definition Math.h:1805
__hostdev__ constexpr Mat4 & operator-=(const Mat4 &m) noexcept
Definition Math.h:1798
__hostdev__ constexpr Vec4< T > operator*(const Vec4< T > &v) const noexcept
Definition Math.h:1802
__hostdev__ constexpr Mat4 operator+(const Mat4 &m) const noexcept
Definition Math.h:1795
__hostdev__ constexpr bool operator==(const Mat4 &m) const noexcept
Definition Math.h:1811
__hostdev__ friend constexpr Mat4 operator*(const T &s, const Mat4 &m) noexcept
scalar * Mat (hidden friend — found only via ADL on Mat4)
Definition Math.h:1818
__hostdev__ constexpr bool operator!=(const Mat4 &m) const noexcept
Definition Math.h:1812
__hostdev__ constexpr Result multiply(const Rhs &rhs) const noexcept
return (*this) * rhs as the Result type.
Definition Math.h:1503
__hostdev__ constexpr Derived negate() const noexcept
return -(*this) as a Derived
Definition Math.h:1429
MatBase() noexcept=default
Default-construct (entries are left uninitialized for trivially-default-constructible T).
__hostdev__ constexpr MatBase & scaleAssign(T s) noexcept
Multiply every element by scalar s in place; return *this. s is taken by value so m *= m[0][0] scales...
Definition Math.h:1451
__hostdev__ constexpr MatBase & divideAssignScalar(T s) noexcept
Divide every element by scalar s in place; return *this. Uses the same floating-point reciprocal / in...
Definition Math.h:1470
__hostdev__ constexpr Derived plus(const Derived &rhs) const noexcept
return *this + rhs as a Derived
Definition Math.h:1417
__hostdev__ constexpr const T * data() const noexcept
return a const raw pointer to the underlying 1D storage (row-major)
Definition Math.h:1411
T mData[ROWS *COLS]
Definition Math.h:1343
__hostdev__ constexpr bool equals(const MatBase &rhs) const noexcept
Return true iff every element compares equal to rhs.
Definition Math.h:1480
static __hostdev__ constexpr Result generate(F f) noexcept
Definition Math.h:1388
static __hostdev__ constexpr int cols() noexcept
Compile-time column count.
Definition Math.h:1351
__hostdev__ constexpr Result transposeAs() const noexcept
return the transpose of *this as the Result type.
Definition Math.h:1490
__hostdev__ constexpr MatBase & subAssign(const MatBase &rhs) noexcept
Element-wise subtract rhs from *this and return *this.
Definition Math.h:1445
__hostdev__ constexpr MatBase(Args... args) noexcept
Variadic component-init ctor — used only by derived ctors (Mat2(T a, T b, T c, T d) : Base(a,...
Definition Math.h:1374
__hostdev__ constexpr T * data() noexcept
return a raw pointer to the underlying 1D storage (row-major)
Definition Math.h:1409
__hostdev__ constexpr Derived minus(const Derived &rhs) const noexcept
return *this - rhs as a Derived
Definition Math.h:1423
__hostdev__ constexpr Derived divideBy(T s) const noexcept
return (*this) / s element-wise as a Derived. Floating-point T multiplies by the reciprocal 1/s; inte...
Definition Math.h:1460
static __hostdev__ constexpr int size() noexcept
Compile-time element count, i.e. ROWS * COLS.
Definition Math.h:1353
__hostdev__ constexpr MatBase & addAssign(const MatBase &rhs) noexcept
Element-wise add rhs into *this and return *this.
Definition Math.h:1440
static __hostdev__ constexpr int rows() noexcept
Compile-time row count.
Definition Math.h:1349
__hostdev__ constexpr VecResult multiplyVec(const VecRhs &v) const noexcept
return (*this) * v as the VecResult type.
Definition Math.h:1521
__hostdev__ constexpr const T * operator[](int row) const noexcept
Const overload of operator[](int); see non-const variant.
Definition Math.h:1403
__hostdev__ constexpr T * operator[](int row) noexcept
2D row access. Returns a pointer to the start of row; the caller indexes into it with the column....
Definition Math.h:1398
T ValueType
Definition Math.h:1346
static __hostdev__ constexpr Result generate(F f, std::integer_sequence< int, I... >) noexcept
Return a Result whose row-major element idx is f(idx), built through its Count-element constructor....
Definition Math.h:1383
__hostdev__ constexpr Derived scale(T s) const noexcept
return s * (*this) as a Derived
Definition Math.h:1435
8-bit red, green, blue, alpha packed into 32 bit unsigned int
Definition Math.h:2695
__hostdev__ bool operator==(const Rgba8 &rhs) const noexcept
Equality on the 32-bit packed integer representation.
Definition Math.h:2768
__hostdev__ constexpr float asFloat(int n) const noexcept
Return the n'th color channel as a float in the range 0 to 1.
Definition Math.h:2780
uint32_t packed
Definition Math.h:2699
__hostdev__ constexpr Rgba8(uint8_t v) noexcept
Ctor where all channels are initialized to the same value.
Definition Math.h:2736
__hostdev__ constexpr const uint8_t & a() const noexcept
Definition Math.h:2794
__hostdev__ constexpr const uint8_t & operator[](int n) const noexcept
Indexed channel access. Asserts 0 <= n < 4 in debug builds.
Definition Math.h:2782
__hostdev__ constexpr Rgba8(float r, float g, float b, float a=1.0f) noexcept
floating-point r,g,b,a ctor where alpha channel defaults to opaque
Definition Math.h:2743
Rgba8(Rgba8 &&) noexcept=default
Default move constructor.
__hostdev__ constexpr Rgba8(uint8_t r, uint8_t g, uint8_t b, uint8_t a=255u) noexcept
integer r,g,b,a ctor where alpha channel defaults to opaque
Definition Math.h:2729
__hostdev__ constexpr Rgba8(const Vec3< float > &rgb) noexcept
Construct from a Vec3<float> with rgb components (alpha set to opaque).
Definition Math.h:2753
__hostdev__ constexpr uint8_t & g() noexcept
Definition Math.h:2796
__hostdev__ constexpr const uint8_t & r() const noexcept
Named channel accessors (r, g, b, a). Both const and non-const variants.
Definition Math.h:2791
__hostdev__ constexpr uint8_t & b() noexcept
Definition Math.h:2797
__hostdev__ const uint32_t & packed() const noexcept
Const access to the 32-bit packed integer representation.
Definition Math.h:2786
__hostdev__ constexpr uint8_t & r() noexcept
Definition Math.h:2795
Rgba8(const Rgba8 &) noexcept=default
Default copy constructor.
uint8_t ValueType
Definition Math.h:2704
__hostdev__ float length() const noexcept
L2 length of the rgb channels (alpha ignored). Not constexpr — calls sqrtf.
Definition Math.h:2778
__hostdev__ constexpr const uint8_t & b() const noexcept
Definition Math.h:2793
__hostdev__ constexpr Rgba8(const Vec4< float > &rgba) noexcept
Construct from a Vec4<float> with rgba components.
Definition Math.h:2760
__hostdev__ constexpr uint8_t & operator[](int n) noexcept
Mutable variant of operator[].
Definition Math.h:2784
__hostdev__ uint32_t & packed() noexcept
Mutable access to the 32-bit packed integer representation.
Definition Math.h:2788
uint8_t c[4]
Definition Math.h:2698
__hostdev__ bool operator<(const Rgba8 &rhs) const noexcept
Compare on the 32-bit packed integer representation (lexicographic by byte).
Definition Math.h:2766
__hostdev__ constexpr float lengthSqr() const noexcept
Return the squared L2 length of the rgb channels in the [0, 1] range (alpha is ignored)....
Definition Math.h:2771
__hostdev__ constexpr uint8_t & a() noexcept
Definition Math.h:2798
static const int SIZE
Definition Math.h:2703
__hostdev__ constexpr Rgba8() noexcept
Default ctor initializes all channels to zero.
Definition Math.h:2721
__hostdev__ constexpr const uint8_t & g() const noexcept
Definition Math.h:2792
A simple vector class with two components, similar to openvdb::math::Vec2.
Definition Math.h:1192
__hostdev__ constexpr Vec2 operator-(const Vec2 &v) const noexcept
Component-wise difference.
Definition Math.h:1233
__hostdev__ constexpr Vec2 & operator/=(const T &s) noexcept
In-place component-wise divide by scalar s.
Definition Math.h:1267
__hostdev__ constexpr Vec2 operator+(const Vec2 &v) const noexcept
Component-wise sum.
Definition Math.h:1231
__hostdev__ constexpr Vec2 & operator*=(const T &s) noexcept
In-place component-wise multiply by scalar s.
Definition Math.h:1265
__hostdev__ constexpr Vec2(const Vec2< T2 > &v) noexcept
Explicit cross-precision conversion within nanovdb (e.g. Vec2d → Vec2f).
Definition Math.h:1215
__hostdev__ constexpr Vec2(T x, T y) noexcept
Component-wise construction.
Definition Math.h:1204
__hostdev__ constexpr Vec2 & operator+=(const Vec2 &v) noexcept
In-place component-wise addition.
Definition Math.h:1239
Vec2() noexcept=default
Default-construct (components are left uninitialized for fundamental T).
__hostdev__ Vec2 normalized() const noexcept
Return a normalized (unit-length) copy; const counterpart of normalize().
Definition Math.h:1271
__hostdev__ constexpr bool operator==(const Vec2 &rhs) const noexcept
Component-wise equality.
Definition Math.h:1277
__hostdev__ constexpr Coord2 round() const noexcept
Round each component to its closest integer value.
Definition Math.h:1303
__hostdev__ constexpr Vec2 operator*(const Vec2 &v) const noexcept
Component-wise (Hadamard) product.
Definition Math.h:1235
__hostdev__ constexpr Coord2 ceil() const noexcept
Round each component up (toward positive infinity)
Definition Math.h:1299
__hostdev__ constexpr Vec2 & operator-=(const Vec2 &v) noexcept
In-place component-wise subtraction.
Definition Math.h:1241
static constexpr int size
Definition Math.h:1197
__hostdev__ constexpr ValueType max() const noexcept
Return the largest vector component.
Definition Math.h:1290
__hostdev__ constexpr Vec2 & minComponent(const Vec2 &other) noexcept
Take the component-wise minimum of *this and other in place.
Definition Math.h:1283
__hostdev__ constexpr Vec2 operator*(const T &s) const noexcept
Component-wise multiply by scalar s.
Definition Math.h:1261
__hostdev__ constexpr Vec2 operator+(const Coord2 &ijk) const noexcept
Add an integer Coord2 to this vector (component-wise).
Definition Math.h:1245
__hostdev__ constexpr Vec2 operator-() const noexcept
Component-wise negation.
Definition Math.h:1229
__hostdev__ friend constexpr Vec2 operator*(T1 scalar, const Vec2 &vec) noexcept
Scalar-on-the-left multiplication (hidden friend).
Definition Math.h:1310
__hostdev__ constexpr Vec2(const Coord2 &ijk) noexcept
Construct from a 2D integer coordinate.
Definition Math.h:1217
__hostdev__ constexpr Vec2 & operator-=(const Coord2 &ijk) noexcept
In-place component-wise subtraction of an integer Coord2.
Definition Math.h:1254
__hostdev__ constexpr Vec2 & maxComponent(const Vec2 &other) noexcept
Take the component-wise maximum of *this and other in place.
Definition Math.h:1285
__hostdev__ constexpr Vec2(const Vec2T< T2 > &v) noexcept
Explicit cross-template converting ctor (e.g. from openvdb::Vec2). Convert a foreign vector with a ca...
Definition Math.h:1209
__hostdev__ friend constexpr Vec2 operator/(T1 scalar, const Vec2 &vec) noexcept
Scalar-on-the-left division (hidden friend).
Definition Math.h:1316
__hostdev__ constexpr ValueType min() const noexcept
Return the smallest vector component.
Definition Math.h:1288
__hostdev__ constexpr Vec2 operator/(const T &s) const noexcept
Component-wise divide by scalar s (integer-safe).
Definition Math.h:1263
__hostdev__ constexpr Vec2 operator/(const Vec2 &v) const noexcept
Component-wise division.
Definition Math.h:1237
__hostdev__ constexpr Vec2 & operator=(const Vec2T< T2 > &rhs) noexcept
Assign from any 2-component vector type (foreign or nanovdb).
Definition Math.h:1221
__hostdev__ Vec2 & normalize() noexcept
Normalize in place (divide by length()). Not constexpr — calls std::sqrt.
Definition Math.h:1269
__hostdev__ constexpr Vec2 operator-(const Coord2 &ijk) const noexcept
Subtract an integer Coord2 from this vector (component-wise).
Definition Math.h:1247
__hostdev__ constexpr Vec2 & operator+=(const Coord2 &ijk) noexcept
In-place component-wise addition of an integer Coord2.
Definition Math.h:1249
__hostdev__ constexpr bool operator!=(const Vec2 &rhs) const noexcept
Component-wise inequality.
Definition Math.h:1279
T ValueType
Definition Math.h:1196
__hostdev__ constexpr Coord2 floor() const noexcept
Round each component down (toward negative infinity)
Definition Math.h:1295
A simple vector class with three components, similar to openvdb::math::Vec3.
Definition Math.h:1865
__hostdev__ constexpr Vec3(T x, T y, T z) noexcept
Component-wise construction.
Definition Math.h:1877
__hostdev__ constexpr Vec3 & operator+=(const Vec3 &v) noexcept
In-place component-wise addition.
Definition Math.h:1912
__hostdev__ constexpr Vec3 & operator-=(const Vec3 &v) noexcept
In-place component-wise subtraction.
Definition Math.h:1914
__hostdev__ friend constexpr Vec3 operator*(T1 scalar, const Vec3 &vec) noexcept
Scalar-on-the-left multiplication (hidden friend).
Definition Math.h:2001
__hostdev__ constexpr Coord ceil() const noexcept
Round each component up (toward positive infinity)
Definition Math.h:1972
__hostdev__ constexpr Vec3 operator*(const T &s) const noexcept
Component-wise multiply by scalar s.
Definition Math.h:1934
__hostdev__ constexpr Vec3 operator/(const Vec3 &v) const noexcept
Component-wise division.
Definition Math.h:1910
__hostdev__ constexpr Vec3(const Vec3< T2 > &v) noexcept
Explicit cross-precision conversion within nanovdb (e.g. Vec3d → Vec3f).
Definition Math.h:1888
__hostdev__ constexpr Coord round() const noexcept
Round each component to its closest integer value.
Definition Math.h:1976
__hostdev__ constexpr Vec3 cross(const Vec3T &v) const noexcept
cross product with another 3-vector
Definition Math.h:1982
__hostdev__ constexpr Vec3 operator/(const T &s) const noexcept
Component-wise divide by scalar s (integer-safe).
Definition Math.h:1936
__hostdev__ constexpr Vec3 operator-() const noexcept
Component-wise negation.
Definition Math.h:1902
static constexpr int size
Definition Math.h:1870
__hostdev__ constexpr ValueType max() const noexcept
Return the largest vector component.
Definition Math.h:1963
__hostdev__ Vec3 & normalize() noexcept
Normalize in place (divide by length()). Not constexpr — calls std::sqrt.
Definition Math.h:1942
__hostdev__ constexpr Vec3 & minComponent(const Vec3 &other) noexcept
Take the component-wise minimum of *this and other in place.
Definition Math.h:1956
__hostdev__ constexpr Vec3(const Vec3T< T2 > &v) noexcept
Explicit cross-template converting ctor (e.g. from openvdb::Vec3). Convert a foreign vector with a ca...
Definition Math.h:1882
__hostdev__ constexpr Vec3 operator+(const Vec3 &v) const noexcept
Component-wise sum.
Definition Math.h:1904
__hostdev__ constexpr Vec3 & operator-=(const Coord &ijk) noexcept
In-place component-wise subtraction of an integer Coord.
Definition Math.h:1927
__hostdev__ constexpr Vec3(const Coord &ijk) noexcept
Construct from a 3D integer coordinate.
Definition Math.h:1890
__hostdev__ constexpr Coord floor() const noexcept
Round each component down (toward negative infinity)
Definition Math.h:1968
__hostdev__ constexpr Vec3 & operator+=(const Coord &ijk) noexcept
In-place component-wise addition of an integer Coord.
Definition Math.h:1922
__hostdev__ constexpr Vec3 operator*(const Vec3 &v) const noexcept
Component-wise (Hadamard) product.
Definition Math.h:1908
__hostdev__ constexpr Vec3 & operator=(const Vec3T< T2 > &rhs) noexcept
Assign from any 3-component vector type (foreign or nanovdb).
Definition Math.h:1894
Vec3() noexcept=default
Default-construct (components are left uninitialized for fundamental T).
__hostdev__ constexpr ValueType min() const noexcept
Return the smallest vector component.
Definition Math.h:1961
__hostdev__ constexpr Vec3 operator-(const Vec3 &v) const noexcept
Component-wise difference.
Definition Math.h:1906
__hostdev__ constexpr Vec3 & maxComponent(const Vec3 &other) noexcept
Take the component-wise maximum of *this and other in place.
Definition Math.h:1958
__hostdev__ constexpr bool operator==(const Vec3 &rhs) const noexcept
Component-wise equality.
Definition Math.h:1950
__hostdev__ Vec3 normalized() const noexcept
Return a normalized (unit-length) copy; const counterpart of normalize().
Definition Math.h:1944
__hostdev__ friend constexpr Vec3 operator/(T1 scalar, const Vec3 &vec) noexcept
Scalar-on-the-left division (hidden friend).
Definition Math.h:2007
__hostdev__ constexpr Vec3 operator-(const Coord &ijk) const noexcept
Subtract an integer Coord from this vector (component-wise).
Definition Math.h:1920
__hostdev__ constexpr Vec3 operator+(const Coord &ijk) const noexcept
Add an integer Coord to this vector (component-wise).
Definition Math.h:1918
__hostdev__ constexpr Vec3 & operator/=(const T &s) noexcept
In-place component-wise divide by scalar s.
Definition Math.h:1940
T ValueType
Definition Math.h:1869
__hostdev__ constexpr Mat3< ValueType > outer(const Vec3T &v) const noexcept
Outer product of a 3x1 vector and a 1x3 vector, result is a 3x3 matrix.
Definition Math.h:1990
__hostdev__ constexpr Vec3 & operator*=(const T &s) noexcept
In-place component-wise multiply by scalar s.
Definition Math.h:1938
__hostdev__ constexpr bool operator!=(const Vec3 &rhs) const noexcept
Component-wise inequality.
Definition Math.h:1952
A simple vector class with four components, similar to openvdb::math::Vec4.
Definition Math.h:2034
__hostdev__ constexpr Vec4 & operator=(const Vec4T< T2 > &rhs) noexcept
Assign from any 4-component vector type (foreign or nanovdb).
Definition Math.h:2060
__hostdev__ constexpr Vec4 & operator*=(const T &s) noexcept
In-place component-wise multiply by scalar s.
Definition Math.h:2088
__hostdev__ constexpr Vec4< int32_t > floor() const noexcept
Round each component down (toward negative infinity)
Definition Math.h:2118
__hostdev__ Vec4 normalized() const noexcept
Return a normalized (unit-length) copy; const counterpart of normalize().
Definition Math.h:2094
__hostdev__ constexpr Vec4(T x, T y, T z, T w) noexcept
Component-wise construction.
Definition Math.h:2046
__hostdev__ constexpr Vec4 operator/(const T &s) const noexcept
Component-wise divide by scalar s (integer-safe).
Definition Math.h:2086
__hostdev__ constexpr Vec4(const Vec4T< T2 > &v) noexcept
Explicit cross-template converting ctor (e.g. from openvdb::Vec4). Convert a foreign vector with a ca...
Definition Math.h:2054
__hostdev__ constexpr Vec4 & maxComponent(const Vec4 &other) noexcept
Take the component-wise maximum of *this and other in place.
Definition Math.h:2108
__hostdev__ constexpr Vec4< int32_t > round() const noexcept
Round each component to its closest integer value.
Definition Math.h:2126
static constexpr int size
Definition Math.h:2039
__hostdev__ constexpr ValueType max() const noexcept
Return the largest vector component.
Definition Math.h:2113
__hostdev__ constexpr Vec4 operator-() const noexcept
Component-wise negation.
Definition Math.h:2068
__hostdev__ constexpr Vec4 & operator-=(const Vec4 &v) noexcept
In-place component-wise subtraction.
Definition Math.h:2080
__hostdev__ constexpr Vec4 operator-(const Vec4 &v) const noexcept
Component-wise difference.
Definition Math.h:2072
__hostdev__ constexpr Vec4 operator*(const Vec4 &v) const noexcept
Component-wise (Hadamard) product.
Definition Math.h:2074
Vec4() noexcept=default
Default-construct (components are left uninitialized for fundamental T).
__hostdev__ constexpr ValueType min() const noexcept
Return the smallest vector component.
Definition Math.h:2111
__hostdev__ constexpr Vec4 & minComponent(const Vec4 &other) noexcept
Take the component-wise minimum of *this and other in place.
Definition Math.h:2106
__hostdev__ constexpr Vec4 operator*(const T &s) const noexcept
Component-wise multiply by scalar s.
Definition Math.h:2084
__hostdev__ constexpr Vec4 operator/(const Vec4 &v) const noexcept
Component-wise division.
Definition Math.h:2076
__hostdev__ friend constexpr Vec4 operator/(T1 scalar, const Vec4 &vec) noexcept
Scalar-on-the-left division (hidden friend).
Definition Math.h:2139
__hostdev__ friend constexpr Vec4 operator*(T1 scalar, const Vec4 &vec) noexcept
Scalar-on-the-left multiplication (hidden friend).
Definition Math.h:2133
__hostdev__ constexpr bool operator!=(const Vec4 &rhs) const noexcept
Component-wise inequality.
Definition Math.h:2102
__hostdev__ constexpr Vec4 & operator/=(const T &s) noexcept
In-place component-wise divide by scalar s.
Definition Math.h:2090
__hostdev__ constexpr Vec4(const Vec4< T2 > &v) noexcept
Explicit cross-precision conversion within nanovdb (e.g. Vec4d → Vec4f).
Definition Math.h:2050
__hostdev__ Vec4 & normalize() noexcept
Normalize in place (divide by length()). Not constexpr — calls std::sqrt.
Definition Math.h:2092
__hostdev__ constexpr Vec4 operator+(const Vec4 &v) const noexcept
Component-wise sum.
Definition Math.h:2070
__hostdev__ constexpr bool operator==(const Vec4 &rhs) const noexcept
Component-wise equality.
Definition Math.h:2100
T ValueType
Definition Math.h:2038
__hostdev__ constexpr Vec4< int32_t > ceil() const noexcept
Round each component up (toward positive infinity)
Definition Math.h:2122
__hostdev__ constexpr Vec4 & operator+=(const Vec4 &v) noexcept
In-place component-wise addition.
Definition Math.h:2078
__hostdev__ T length() const noexcept
L2 length (Euclidean norm). Not constexpr — calls Sqrt.
Definition Math.h:1104
__hostdev__ constexpr T * asPointer() noexcept
raw pointer to the underlying N-element storage
Definition Math.h:986
__hostdev__ constexpr T smallestComponent() const noexcept
return the smallest of the N components
Definition Math.h:1107
__hostdev__ constexpr VecBase & mergeMax(const V &other) noexcept
Component-wise take the max of *this and other (in place); return *this.
Definition Math.h:1129
__hostdev__ constexpr const T & y() const noexcept
Definition Math.h:978
static constexpr int SIZE
Definition Math.h:941
__hostdev__ Derived normalized() const noexcept
Return a unit-length copy (*this divided by length()) as a Derived. Const, non-mutating counterpart o...
Definition Math.h:1036
__hostdev__ constexpr T dot(const V &v) const noexcept
dot product. V must have operator[] valid for 0..N-1. Sums in the promoted type of the element produc...
Definition Math.h:1092
__hostdev__ constexpr VecBase & divideAssignScalar(T s) noexcept
Divide every component by scalar s in place; return *this. Uses the same floating-point reciprocal / ...
Definition Math.h:1071
__hostdev__ constexpr T & operator[](int i) noexcept
Definition Math.h:974
__hostdev__ constexpr Derived negate() const noexcept
Return -(*this) as a Derived.
Definition Math.h:1013
T mVec[N]
Definition Math.h:937
__hostdev__ constexpr T & x() noexcept
Definition Math.h:977
__hostdev__ constexpr T lengthSqr() const noexcept
Squared L2 length (sum of squared components). Constexpr, no sqrt.
Definition Math.h:1098
__hostdev__ constexpr T largestComponent() const noexcept
return the largest of the N components
Definition Math.h:1113
__hostdev__ constexpr Derived plus(const Derived &rhs) const noexcept
Return *this + rhs as a Derived.
Definition Math.h:993
__hostdev__ constexpr VecBase & mulAssign(const VecBase &rhs) noexcept
Component-wise multiply *this by rhs (Hadamard product) and return *this.
Definition Math.h:1053
__hostdev__ constexpr bool equals(const VecBase &rhs) const noexcept
Return true iff every component compares equal to rhs.
Definition Math.h:1081
__hostdev__ constexpr Derived div(const Derived &rhs) const noexcept
Return component-wise *this / rhs as a Derived.
Definition Math.h:1008
__hostdev__ constexpr Result floorAs() const noexcept
floor-rounded components into the Result type (whose [i] must accept int32_t). For integer T the valu...
Definition Math.h:1143
__hostdev__ constexpr VecBase & subAssign(const VecBase &rhs) noexcept
Component-wise subtract rhs from *this and return *this.
Definition Math.h:1048
__hostdev__ constexpr VecBase & divAssign(const VecBase &rhs) noexcept
Component-wise divide *this by rhs and return *this.
Definition Math.h:1058
__hostdev__ constexpr T & z() noexcept
Definition Math.h:981
__hostdev__ constexpr VecBase & scaleAssign(T s) noexcept
Multiply every component by scalar s in place; return *this. s is taken by value so v *= v[0] scales ...
Definition Math.h:1064
VecBase() noexcept=default
Default-construct (mVec is left uninitialized for trivially-default-constructible T).
static __hostdev__ constexpr Derived generate(F f, std::integer_sequence< int, I... >) noexcept
Return a Derived whose component i is f(i), built through its N-component constructor....
Definition Math.h:961
__hostdev__ constexpr const T & operator[](int i) const noexcept
Indexed element access. Asserts 0 <= i < N in debug builds.
Definition Math.h:973
__hostdev__ constexpr Derived mul(const Derived &rhs) const noexcept
Return component-wise *this * rhs as a Derived (Hadamard product).
Definition Math.h:1003
__hostdev__ constexpr Derived minus(const Derived &rhs) const noexcept
Return *this - rhs as a Derived.
Definition Math.h:998
__hostdev__ constexpr const T * asPointer() const noexcept
Definition Math.h:987
__hostdev__ constexpr Derived divideBy(T s) const noexcept
Return (*this) / s element-wise as a Derived. Floating-point T multiplies by the reciprocal 1/s; inte...
Definition Math.h:1025
__hostdev__ constexpr Result roundAs() const noexcept
nearest-integer rounding for floating T via the scalar math::Round (halfway cases toward +inf,...
Definition Math.h:1172
__hostdev__ constexpr const T & z() const noexcept
Definition Math.h:980
__hostdev__ constexpr T & y() noexcept
Definition Math.h:979
__hostdev__ constexpr VecBase & mergeMin(const V &other) noexcept
Component-wise take the min of *this and other (in place); return *this.
Definition Math.h:1123
__hostdev__ constexpr Result ceilAs() const noexcept
ceil-rounded components into the Result type (whose [i] must accept int32_t). For integer T the value...
Definition Math.h:1158
__hostdev__ constexpr VecBase & addAssign(const VecBase &rhs) noexcept
Component-wise add rhs into *this and return *this.
Definition Math.h:1043
__hostdev__ constexpr const T & x() const noexcept
Definition Math.h:976
T ValueType
Definition Math.h:940
__hostdev__ constexpr const T & w() const noexcept
Definition Math.h:982
static __hostdev__ constexpr Derived generate(F f) noexcept
Definition Math.h:966
__hostdev__ constexpr T & w() noexcept
Definition Math.h:983
__hostdev__ constexpr Derived scale(T s) const noexcept
Return s * (*this) as a Derived (scalar broadcast).
Definition Math.h:1018
Definition DitherLUT.h:19
__hostdev__ CoordT RoundDown(const Vec3T< RealT > &xyz) noexcept
Round each component of xyz down (toward -inf) into a CoordT.
Definition Math.h:345
__hostdev__ constexpr T Pow2(T x) noexcept
Return x * x.
Definition Math.h:258
Vec3< uint8_t > Vec3u8
Definition Math.h:2814
__hostdev__ int32_t Ceil(float x) noexcept
Ceil of x as a 32-bit signed integer (rounding toward +inf).
Definition Math.h:246
__hostdev__ int32_t Floor(float x) noexcept
Floor of x as a 32-bit signed integer (truncation toward -inf).
Definition Math.h:234
Vec3< float > Vec3f
Definition Math.h:2811
Vec4< float > Vec4f
Definition Math.h:2819
__hostdev__ constexpr Vec3T matMult(const float *mat, const Vec3T &xyz) noexcept
Multiply a 3x3 matrix and a 3d vector using 32bit floating point arithmetics.
Definition Math.h:2201
__hostdev__ constexpr T Pow3(T x) noexcept
Return x * x * x.
Definition Math.h:265
Coord Coord3
Type alias for Coord so we have a consistent naming convention.
Definition Math.h:691
__hostdev__ constexpr Mat2< T > operator*(const Mat2x3< T > &lhs, const Mat3x2< T > &rhs) noexcept
Multiply a 2x3 matrix by a 3x2 matrix, result is a 2x2 matrix.
Definition Math.h:1826
__hostdev__ constexpr Type Max(Type a, Type b) noexcept
Same-type maximum (the primary template).
Definition Math.h:187
__hostdev__ constexpr T Sign(const T &x) noexcept
Return the sign of the given value as an integer (either -1, 0 or 1).
Definition Math.h:364
Vec3< uint32_t > Vec3u
Definition Math.h:2813
__hostdev__ constexpr int MinIndex(const Vec3T &v) noexcept
Return the component index (0, 1, or 2) of the smallest element of v.
Definition Math.h:372
__hostdev__ float Sqrt(float x) noexcept
Return the square root of a floating-point value.
Definition Math.h:352
__hostdev__ int32_t Round(float x) noexcept
Round x to the nearest 32-bit signed integer, with halfway cases rounded toward +inf.
Definition Math.h:308
__hostdev__ constexpr T Abs(T x) noexcept
Absolute value (generic primary template, branchless for arithmetic types).
Definition Math.h:279
__hostdev__ constexpr int MaxIndex(const Vec3T &v) noexcept
Return the component index (0, 1, or 2) of the largest element of v.
Definition Math.h:391
Vec3< double > Vec3d
Definition Math.h:2810
__hostdev__ constexpr T pi() noexcept
Pi constant taken from Boost to match old behaviour.
Definition Math.h:35
__hostdev__ float Fract(float x) noexcept
Fractional part of x, i.e. x - floor(x). Always non-negative.
Definition Math.h:222
__hostdev__ float Clamp(float x, float a, float b) noexcept
Clamp x to the closed interval [a, b].
Definition Math.h:210
Vec4< double > Vec4R
Definition Math.h:2817
Vec4< int > Vec4i
Definition Math.h:2820
__hostdev__ constexpr uint64_t AlignUp(uint64_t byteCount) noexcept
round up byteSize to the nearest wordSize, e.g. to align to machine word: AlignUp<sizeof(size_t)(n)
Definition Math.h:411
__hostdev__ constexpr Vec3T matMultT(const float *mat, const Vec3T &xyz) noexcept
Multiply the transposed of a 3x3 matrix and a 3d vector using 32bit floating point arithmetics.
Definition Math.h:2273
Vec3< uint16_t > Vec3u16
Definition Math.h:2815
__hostdev__ constexpr Type Min(Type a, Type b) noexcept
Same-type minimum (the primary template).
Definition Math.h:161
Vec3< int32_t > Vec3i
Definition Math.h:2812
Vec4< double > Vec4d
Definition Math.h:2818
__hostdev__ constexpr T Pow4(T x) noexcept
Return x raised to the fourth power.
Definition Math.h:272
__hostdev__ constexpr bool isApproxZero(const Type &x) noexcept
Return true if |x| is below Tolerance<Type>::value().
Definition Math.h:154
Defines a simple memory pool used to call cub functions that use dynamic temporary storage.
Definition GridHandle.h:34
math::Vec4< float > Vec4f
Definition Math.h:2835
math::Vec4< int > Vec4i
Definition Math.h:2836
math::Vec3< uint32_t > Vec3u
Definition Math.h:2829
math::Vec3< uint16_t > Vec3u16
Definition Math.h:2831
math::Vec3< uint8_t > Vec3u8
Definition Math.h:2830
math::Vec3< int32_t > Vec3i
Definition Math.h:2828
math::Vec3< float > Vec3f
Definition Math.h:2827
math::Vec4< double > Vec4R
Definition Math.h:2833
math::BBox< Vec3d > Vec3dBBox
Definition Math.h:2839
math::Vec3< double > Vec3d
Definition Math.h:2826
math::BBox< Coord > CoordBBox
Definition Math.h:2838
math::Vec4< double > Vec4d
Definition Math.h:2834
Utility functions.
#define NANOVDB_ASSERT(x)
Definition Util.h:53
#define __device__
Definition Util.h:82
Defines an affine transform and its inverse represented as a 3x3 matrix and a vec3 translation.
Definition NanoVDB.h:1399
__hostdev__ constexpr auto transform(const Map &map) const noexcept
Transform this coordinate bounding box by the specified map.
Definition Math.h:2651
__hostdev__ constexpr Iterator begin() const noexcept
Iterator positioned at the min corner.
Definition Math.h:2557
__hostdev__ constexpr BBox< Vec3< RealT > > asReal() const noexcept
Definition Math.h:2635
__hostdev__ constexpr BBox(const CoordT &min, const CoordT &max) noexcept
Construct from explicit min / max integer corners.
Definition Math.h:2566
__hostdev__ constexpr BBox() noexcept
Default construct an empty bbox (min = CoordT::max(), max = CoordT::min()).
Definition Math.h:2561
__hostdev__ constexpr bool hasOverlap(const BBox &b) const noexcept
Return true if the given bounding box overlaps with this bounding box.
Definition Math.h:2628
__hostdev__ constexpr Iterator end() const noexcept
One-past-the-end iterator (max corner shifted by one in x).
Definition Math.h:2559
static __hostdev__ constexpr BBox createCube(const CoordT &min, typename CoordT::ValueType dim) noexcept
Return a cube-shaped BBox with min corner min and edge length dim.
Definition Math.h:2588
__hostdev__ constexpr BBox(BBox &other, const SplitT &) noexcept
Splitting constructor (used by parallel range-based iteration).
Definition Math.h:2577
__hostdev__ constexpr bool isInside(const BBox &b) const noexcept
Return true if the given bounding box is inside this bounding box.
Definition Math.h:2622
CoordT mCoord[2]
Definition Math.h:2341
__hostdev__ constexpr uint64_t volume() const noexcept
Return the number of integer cells in the box, i.e. dim().x * dim().y * dim().z.
Definition Math.h:2614
BaseBBox< CoordT > BaseT
Definition Math.h:2483
__hostdev__ constexpr CoordT dim() const noexcept
Return the per-axis extent (max - min + 1 when non-empty, else 0).
Definition Math.h:2612
__hostdev__ constexpr bool empty() const noexcept
Return true if this bounding box is empty, e.g. uninitialized.
Definition Math.h:2604
__hostdev__ constexpr bool is_divisible() const noexcept
Return true iff the box has more than one cell along every axis.
Definition Math.h:2600
__hostdev__ constexpr bool isInside(const CoordT &p) const noexcept
Return true iff the integer coordinate p lies inside the closed box.
Definition Math.h:2620
static __hostdev__ constexpr BBox createCube(typename CoordT::ValueType min, typename CoordT::ValueType max) noexcept
Return a cube-shaped BBox spanning min..max in every axis.
Definition Math.h:2594
__hostdev__ constexpr BBox expandBy(typename CoordT::ValueType padding) const noexcept
Return a new instance that is expanded by the specified padding.
Definition Math.h:2642
Vec3T mCoord[2]
Definition Math.h:2341
__hostdev__ constexpr bool isInside(const Vec3T &p) const noexcept
Return true iff p is strictly inside the box (open interval — min is exclusive, max is exclusive).
Definition Math.h:2467
__hostdev__ constexpr BBox() noexcept
Default construction sets BBox to an empty bbox.
Definition Math.h:2427
Vec3T Vec3Type
Definition Math.h:2421
__hostdev__ constexpr bool empty() const noexcept
Return true if this bounding box is empty (max <= min in any axis).
Definition Math.h:2457
BaseBBox< Vec3T > BaseT
Definition Math.h:2424
__hostdev__ constexpr BBox(const BaseBBox< Coord > &bbox) noexcept
Construct from a BaseBBox<Coord>; delegates to the (min, max) ctor.
Definition Math.h:2452
static __hostdev__ constexpr BBox createCube(const Coord &min, typename Coord::ValueType dim) noexcept
Return a cube-shaped BBox with min corner min and edge length dim.
Definition Math.h:2446
typename Vec3T::ValueType ValueType
Definition Math.h:2422
__hostdev__ constexpr Vec3T dim() const noexcept
Return max - min when non-empty, else the zero vector.
Definition Math.h:2465
__hostdev__ constexpr BBox(const Coord &min, const Coord &max) noexcept
Convert an integer Coord box into this floating-point box.
Definition Math.h:2440
__hostdev__ constexpr BBox(const Vec3T &min, const Vec3T &max) noexcept
Construct from explicit min / max corners.
Definition Math.h:2433
Definition Math.h:2412
__hostdev__ constexpr bool isInside(const Vec3T &xyz) const noexcept
Return true iff xyz lies in the closed box (each component satisfies min[i] <= xyz[i] <= max[i]).
Definition Math.h:2391
CoordT mCoord[2]
Definition Math.h:2341
__hostdev__ constexpr BaseBBox & expand(const Vec3T &xyz) noexcept
Expand this bounding box to enclose point xyz.
Definition Math.h:2366
__hostdev__ constexpr Vec3T & operator[](int i) noexcept
Mutable variant of operator[].
Definition Math.h:2349
__hostdev__ constexpr BaseBBox & translate(const Vec3T &xyz) noexcept
Translate (rigid-shift) both corners by xyz; return *this.
Definition Math.h:2359
__hostdev__ constexpr const Vec3T & max() const noexcept
Const accessor for the max corner.
Definition Math.h:2357
__hostdev__ constexpr BaseBBox() noexcept
Default-construct (leaves corners uninitialized — derived classes supply a meaningful default).
Definition Math.h:2403
__hostdev__ constexpr BaseBBox & expand(const BaseBBox &bbox) noexcept
Expand this bounding box to enclose the given bounding box.
Definition Math.h:2374
__hostdev__ constexpr bool operator==(const BaseBBox &rhs) const noexcept
Equality on the two corner points.
Definition Math.h:2343
__hostdev__ constexpr Vec3T & max() noexcept
Mutable accessor for the max corner.
Definition Math.h:2353
__hostdev__ constexpr Vec3T & min() noexcept
Mutable accessor for the min corner.
Definition Math.h:2351
__hostdev__ constexpr BaseBBox & intersect(const BaseBBox &bbox) noexcept
Intersect this bounding box with the given bounding box.
Definition Math.h:2382
__hostdev__ constexpr const Vec3T & min() const noexcept
Const accessor for the min corner.
Definition Math.h:2355
__hostdev__ constexpr bool operator!=(const BaseBBox &rhs) const noexcept
Inequality on the two corner points.
Definition Math.h:2345
__hostdev__ constexpr const Vec3T & operator[](int i) const noexcept
Indexed corner access: i = 0 returns min, i = 1 returns max.
Definition Math.h:2347
__hostdev__ constexpr BaseBBox(const Vec3T &min, const Vec3T &max) noexcept
Construct from min and max corners directly.
Definition Math.h:2405
static __hostdev__ constexpr double value() noexcept
Definition Math.h:97
static __hostdev__ constexpr float value() noexcept
Definition Math.h:92
static __hostdev__ constexpr long double value() noexcept
Definition Math.h:102
Per-type small floating-point offset, useful for nudging boundaries off-edge in geometric tests.
Definition Math.h:88
Per-type largest representable value (mirrors std::numeric_limits::max).
Definition Math.h:146
static constexpr T value() noexcept
Definition Math.h:147
static __hostdev__ constexpr double value() noexcept
Definition Math.h:72
static __hostdev__ constexpr float value() noexcept
Definition Math.h:67
static __hostdev__ constexpr long double value() noexcept
Definition Math.h:77
Per-type tolerance used by approximate floating-point comparisons.
Definition Math.h:63
Vec2Aligned() noexcept=default
Vec3Aligned() noexcept=default
Vec4Aligned() noexcept=default
static constexpr bool value
Definition Util.h:375
static constexpr bool value
Definition Util.h:359