MDL SDK API nvidia_logo_transpbg.gif Up
function.h
Go to the documentation of this file.
1/***************************************************************************************************
2 * Copyright 2024 NVIDIA Corporation. All rights reserved.
3 **************************************************************************************************/
9
10#ifndef MI_MATH_FUNCTION_H
11#define MI_MATH_FUNCTION_H
12
13#include <mi/base/assert.h>
14#include <mi/base/types.h>
15
16#ifdef MI_PLATFORM_WINDOWS
17#include <intrin.h>
18#pragma intrinsic(_BitScanReverse)
19#ifdef MI_ARCH_64BIT
20#pragma intrinsic(_BitScanReverse64)
21#endif
22#endif
23
24namespace mi {
25
26namespace math {
27
60namespace functor {
78 template <typename T1, typename T2>
79 inline bool operator()( const T1& t1, const T2& t2) const { return t1 == t2; }
80};
81
85 template <typename T1, typename T2>
86 inline bool operator()( const T1& t1, const T2& t2) const { return t1 != t2; }
87};
88
92 template <typename T1, typename T2>
93 inline bool operator()( const T1& t1, const T2& t2) const { return t1 < t2; }
94};
95
99 template <typename T1, typename T2>
100 inline bool operator()( const T1& t1, const T2& t2) const { return t1 <= t2; }
101};
102
106 template <typename T1, typename T2>
107 inline bool operator()( const T1& t1, const T2& t2) const { return t1 > t2; }
108};
109
113 template <typename T1, typename T2>
114 inline bool operator()( const T1& t1, const T2& t2) const { return t1 >= t2; }
115};
116
120 template <typename T>
121 inline T operator()( const T& t1, const T& t2) const { return t1 + t2; }
122};
123
127 template <typename T>
128 inline T operator()( const T& t) const { return - t; }
130 template <typename T>
131 inline T operator()( const T& t1, const T& t2) const { return t1 - t2; }
132};
133
137 template <typename T>
138 inline T operator()( const T& t1, const T& t2) const { return t1 * t2; }
139};
140
144 template <typename T>
145 inline T operator()( const T& t1, const T& t2) const { return t1 / t2; }
146};
147
151 template <typename T>
152 inline bool operator()( const T& t1, const T& t2) const { return t1 && t2; }
153};
154
158 template <typename T>
159 inline bool operator()( const T& t1, const T& t2) const { return t1 || t2; }
160};
161
165 template <typename T>
166 inline bool operator()( const T& t1, const T& t2) const { return t1 ^ t2; }
167};
168
172 template <typename T>
173 inline bool operator()( const T& t) const { return ! t; }
174};
175
179 template <typename T>
180 inline T operator()( T& t) const { return ++ t; }
181};
182
186 template <typename T>
187 inline T operator()( T& t) const { return t ++; }
188};
189
193 template <typename T>
194 inline T operator()( T& t) const { return -- t; }
195};
196
200 template <typename T>
201 inline T operator()( T& t) const { return t --; }
202};
203 // end group mi_math_functor
205
206} // namespace functor
207
209namespace general {
233template <class Vector, class ResultVector, class UnaryFunctor>
234inline void transform( const Vector& vec, ResultVector& result, UnaryFunctor f)
235{
236 mi_static_assert( Vector::SIZE == ResultVector::SIZE);
237 for( Size i = 0; i != Vector::SIZE; ++i)
238 result.set( i, f( vec.get(i)));
239}
240
249template <class Vector1, class Vector2, class ResultVector, class BinaryFunctor>
250inline void transform(
251 const Vector1& vec1, const Vector2& vec2, ResultVector& result, BinaryFunctor f)
252{
253 mi_static_assert( Vector1::SIZE == Vector2::SIZE);
254 mi_static_assert( Vector1::SIZE == ResultVector::SIZE);
255 for( Size i = 0; i != Vector1::SIZE; ++i)
256 result.set( i, f( vec1.get(i), vec2.get(i)));
257}
258
268template <class Scalar, class Vector, class ResultVector, class BinaryFunctor>
270 const Scalar& s, const Vector& vec, ResultVector& result, BinaryFunctor f)
271{
272 mi_static_assert( Vector::SIZE == ResultVector::SIZE);
273 for( Size i = 0; i != Vector::SIZE; ++i)
274 result.set( i, f( s, vec.get(i)));
275}
276
286template <class Scalar, class Vector, class ResultVector, class BinaryFunctor>
288 const Vector& vec, const Scalar& s, ResultVector& result, BinaryFunctor f)
289{
290 mi_static_assert( Vector::SIZE == ResultVector::SIZE);
291 for( Size i = 0; i != Vector::SIZE; ++i)
292 result.set( i, f( vec.get(i), s));
293}
294
301template <class Vector, class UnaryFunctor>
302inline void for_each( Vector& vec, UnaryFunctor f)
303{
304 for( Size i = 0; i != Vector::SIZE; ++i)
305 f( vec.begin()[i]);
306}
307
315template <class Vector1, class Vector2, class BinaryFunctor>
316inline void for_each( Vector1& vec1, const Vector2& vec2, BinaryFunctor f)
317{
318 mi_static_assert( Vector1::SIZE == Vector2::SIZE);
319 for( Size i = 0; i != Vector1::SIZE; ++i)
320 f( vec1.begin()[i], vec2.begin()[i]);
321}
322 // end group mi_math_functor
324
325} // namespace general
326
328inline Float32 exp( Float32 s) { return std::exp(s); }
330inline Float64 exp( Float64 s) { return std::exp(s); }
331
333inline Float32 log( Float32 s) { return std::log(s); }
335inline Float64 log( Float64 s) { return std::log(s); }
336
337
338#ifndef __CUDACC__
339using mi::base::min;
340using mi::base::max;
341#endif
342using mi::base::abs;
343
344
358{
359 int tmp = base::binary_cast<int>( i);
360 tmp -= 1 << 23; // Remove last bit to not let it go to mantissa
361 // tmp is now an approximation to logbase2(i)
362 tmp = tmp >> 1; // Divide by 2
363 tmp += 1 << 29; // Add 64 to the exponent: (e+127)/2 = (e/2)+63
364 // that represents (e/2)-64 but we want e/2
365 return base::binary_cast<Float32>( tmp);
366}
367
370{
371 const Float32 EXP_C = 8388608.0f; // 2^23
372 const Float32 LOG_2_E = 1.4426950408889634073599246810019f; // 1 / log(2)
373
374 x *= LOG_2_E;
375 Float32 y = x - std::floor(x);
376 y = (y - y*y) * 0.33971f;
377 const Float32 z = max MI_PREVENT_MACRO_EXPAND ((x + 127.0f - y) * EXP_C, 0.f);
378 return base::binary_cast<Float32>( static_cast<int>( z));
379}
380
383{
384 const Float32 EXP_C = 8388608.0f; // 2^23
385
386 Float32 y = x - std::floor(x);
387 y = (y - y*y) * 0.33971f;
388 const Float32 z = max MI_PREVENT_MACRO_EXPAND ((x + 127.0f - y) * EXP_C, 0.f);
389 return base::binary_cast<Float32>( static_cast<int>( z));
390}
391
394{
395 const Float32 LOG_C = 0.00000011920928955078125f; // 2^(-23)
396
397 const Float32 x = static_cast<Float32>( base::binary_cast<int>( i)) * LOG_C - 127.f;
398 const Float32 y = x - std::floor(x);
399 return x + (y - y*y) * 0.346607f;
400}
401
404 Float32 b,
405 Float32 e)
406{
407 if( b == 0.0f)
408 return 0.0f;
409
410 const Float32 LOG_C = 0.00000011920928955078125f; // 2^(-23)
411 const Float32 EXP_C = 8388608.0f; // 2^23
412
413 const Float32 x = static_cast<Float32>( base::binary_cast<int>( b)) * LOG_C - 127.f;
414 const Float32 y = x - std::floor(x);
415 const Float32 fl = e * (x + (y - y*y) * 0.346607f);
416 const Float32 y2 = fl - std::floor(fl);
417 const Float32 z = max(
418 fl*EXP_C + static_cast<Float32>( 127.0*EXP_C)
419 - (y2 - y2*y2) * static_cast<Float32>( 0.33971*EXP_C), 0.f);
420
421 return base::binary_cast<Float32>( static_cast<int>( z));
422}
423 // end group mi_math_approx_function
425
426
428inline Float32 acos( Float32 s) { return std::acos(s); }
430inline Float64 acos( Float64 s) { return std::acos(s); }
431
433inline bool all( Uint8 v) { return Uint8 (0) != v; }
435inline bool all( Uint16 v) { return Uint16 (0) != v; }
437inline bool all( Uint32 v) { return Uint32 (0) != v; }
439inline bool all( Uint64 v) { return Uint64 (0) != v; }
441inline bool all( Sint8 v) { return Sint8 (0) != v; }
443inline bool all( Sint16 v) { return Sint16 (0) != v; }
445inline bool all( Sint32 v) { return Sint32 (0) != v; }
447inline bool all( Sint64 v) { return Sint64 (0) != v; }
449inline bool all( Float32 v) { return Float32(0) != v; }
451inline bool all( Float64 v) { return Float64(0) != v; }
452
454inline bool any( Uint8 v) { return Uint8 (0) != v; } //-V524 PVS
456inline bool any( Uint16 v) { return Uint16 (0) != v; } //-V524 PVS
458inline bool any( Uint32 v) { return Uint32 (0) != v; } //-V524 PVS
460inline bool any( Uint64 v) { return Uint64 (0) != v; } //-V524 PVS
462inline bool any( Sint8 v) { return Sint8 (0) != v; } //-V524 PVS
464inline bool any( Sint16 v) { return Sint16 (0) != v; } //-V524 PVS
466inline bool any( Sint32 v) { return Sint32 (0) != v; } //-V524 PVS
468inline bool any( Sint64 v) { return Sint64 (0) != v; } //-V524 PVS
470inline bool any( Float32 v) { return Float32(0) != v; } //-V524 PVS
472inline bool any( Float64 v) { return Float64(0) != v; } //-V524 PVS
473
475inline Float32 asin( Float32 s) { return std::asin(s); }
477inline Float64 asin( Float64 s) { return std::asin(s); }
478
480inline Float32 atan( Float32 s) { return std::atan(s); }
482inline Float64 atan( Float64 s) { return std::atan(s); }
483
487inline Float32 atan2( Float32 s, Float32 t) { return std::atan2(s,t); }
491inline Float64 atan2( Float64 s, Float64 t) { return std::atan2(s,t); }
492
494inline Float32 ceil( Float32 s) { return std::ceil(s); }
496inline Float64 ceil( Float64 s) { return std::ceil(s); }
497
500inline Uint8 clamp( Uint8 s, Uint8 low, Uint8 high)
501{
502 return min(high, max(low, s));
503}
506inline Uint16 clamp( Uint16 s, Uint16 low, Uint16 high)
507{
508 return min(high, max(low, s));
509}
512inline Uint32 clamp( Uint32 s, Uint32 low, Uint32 high)
513{
514 return min(high, max(low, s));
515}
518inline Uint64 clamp( Uint64 s, Uint64 low, Uint64 high)
519{
520 return min(high, max(low, s));
521}
524inline Sint8 clamp( Sint8 s, Sint8 low, Sint8 high)
525{
526 return min(high, max(low, s));
527}
530inline Sint16 clamp( Sint16 s, Sint16 low, Sint16 high)
531{
532 return min(high, max(low, s));
533}
536inline Sint32 clamp( Sint32 s, Sint32 low, Sint32 high)
537{
538 return min(high, max(low, s));
539}
542inline Sint64 clamp( Sint64 s, Sint64 low, Sint64 high)
543{
544 return min(high, max(low, s));
545}
548inline Float32 clamp( Float32 s, Float32 low, Float32 high)
549{
550 return min(high, max(low, s));
551}
554inline Float64 clamp( Float64 s, Float64 low, Float64 high)
555{
556 return min(high, max(low, s));
557}
558
560inline Float32 cos( Float32 a) { return std::cos(a); }
562inline Float64 cos( Float64 a) { return std::cos(a); }
563
565inline Float32 degrees( Float32 r) { return r * Float32(180.0/MI_PI); }
567inline Float64 degrees( Float64 r) { return r * Float64(180.0/MI_PI); }
568
570inline Float32 exp2( Float32 s) { return fast_pow2(s); }
573{
574 return std::exp(s * 0.69314718055994530941723212145818 /* log(2) */ );
575}
576
578inline Float32 floor( Float32 s) { return std::floor(s); }
580inline Float64 floor( Float64 s) { return std::floor(s); }
581
585inline Float32 fmod( Float32 a, Float32 b) { return std::fmod(a,b); }
589inline Float64 fmod( Float64 a, Float64 b) { return std::fmod(a,b); }
590
593{
594 return s - std::floor(s);
595}
596
599{
600 return s - std::floor(s);
601}
602
604inline bool is_approx_equal(
605 Float32 left,
606 Float32 right,
607 Float32 e)
608{
609 return abs( left - right ) <= e;
610}
611
613inline bool is_approx_equal(
614 Float64 left,
615 Float64 right,
616 Float64 e)
617{
618 return abs( left - right ) <= e;
619}
620
623 // This implementation tries to use built-in functions if available. For the fallback
624 // method, see Henry Warren: "Hacker's Delight" for reference.
625#if defined(MI_COMPILER_MSC)
626 unsigned long index;
627 const unsigned char valid = _BitScanReverse(&index, v);
628 return (valid != 0) ? 31 - index : 32;
629#elif defined(MI_COMPILER_ICC) || defined(MI_COMPILER_GCC)
630 return (v != 0) ? __builtin_clz(v) : 32;
631#else
632 // use fallback
633 if (v == 0) return 32;
634 Uint32 n = 1;
635 if ((v >> 16) == 0) { n += 16; v <<= 16; };
636 if ((v >> 24) == 0) { n += 8; v <<= 8; };
637 if ((v >> 28) == 0) { n += 4; v <<= 4; };
638 if ((v >> 30) == 0) { n += 2; v <<= 2; };
639 n -= Uint32(v >> 31);
640 return n;
641#endif
642}
643
646 // This implementation tries to use built-in functions if available. For the fallback
647 // method, see Henry Warren: "Hacker's Delight" for reference.
648#if defined(MI_COMPILER_MSC)
649#if defined(MI_ARCH_64BIT)
650 unsigned long index;
651 const unsigned char valid = _BitScanReverse64(&index, v);
652 return (valid != 0) ? 63 - index : 64;
653#else
654 unsigned long index_h, index_l;
655 const unsigned char valid_h = _BitScanReverse(&index_h,(Uint32)(v >> 32));
656 const unsigned char valid_l = _BitScanReverse(&index_l,(Uint32)(v & 0xFFFFFFFF));
657 if (valid_h == 0)
658 return (valid_l != 0) ? 63 - index_l : 64;
659 return 63 - index_h + 32;
660#endif
661#elif defined(MI_COMPILER_ICC) || defined(MI_COMPILER_GCC)
662 return (v != 0) ? __builtin_clzll(v) : 64;
663#else
664 // use fallback
665 if (v == 0) return 64;
666 Uint32 n = 1;
667 if ((v >> 32) == 0) { n += 32; v <<= 32; };
668 if ((v >> 48) == 0) { n += 16; v <<= 16; };
669 if ((v >> 56) == 0) { n += 8; v <<= 8; };
670 if ((v >> 60) == 0) { n += 4; v <<= 4; };
671 if ((v >> 62) == 0) { n += 2; v <<= 2; };
672 n -= Uint32(v >> 63);
673 return n;
674#endif
675}
676
680 Float32 s1,
681 Float32 s2,
682 Float32 t)
683{
684 return s1 * (Float32(1)-t) + s2 * t;
685}
686
690 Float64 s1,
691 Float64 s2,
692 Float64 t)
693{
694 return s1 * (Float64(1)-t) + s2 * t;
695}
696
699{ return std::log(s) * 1.4426950408889634073599246810019f /* log(2) */; }
702{ return std::log(s) * 1.4426950408889634073599246810019 /* log(2) */; }
703
705inline Sint32 log2_int( const Uint32 v) { return (v != 0) ? 31 - leading_zeros(v) : 0; }
706
708inline Sint32 log2_int( const Uint64 v) { return (v != 0) ? 63 - leading_zeros(v) : 0; }
709
711inline Sint32 log2_int( const Float32 v) {
712 return (mi::base::binary_cast<Uint32>(v) >> 23) - 127;
713}
714
716inline Sint32 log2_int( const Float64 v) {
717 return static_cast<Sint32>(mi::base::binary_cast<Uint64>(v) >> 52) - 1023;
718}
719
721template<typename Integer>
722inline Sint32 log2_int_ceil( const Integer v) {
723 // See Henry Warren: "Hacker's Delight" for reference.
724 return (v > 1) ? log2_int(v - 1) + 1 : 0;
725}
726
728inline Float32 log10( Float32 s) { return std::log10(s); }
730inline Float64 log10( Float64 s) { return std::log10(s); }
731
735inline Float32 modf( Float32 s, Float32& i) { return std::modf( s, &i); }
739inline Float64 modf( Float64 s, Float64& i) { return std::modf( s, &i); }
740
742inline Uint32 pow( Uint32 a, Uint32 b) { return Uint32(std::pow(double(a), int(b))); }
744inline Uint64 pow( Uint64 a, Uint64 b) { return Uint64(std::pow(double(a), int(b))); }
746inline Sint32 pow( Sint32 a, Sint32 b) { return Sint32(std::pow(double(a), int(b))); }
748inline Sint64 pow( Sint64 a, Sint64 b) { return Sint64(std::pow(double(a), int(b))); }
750inline Float32 pow( Float32 a, Float32 b) { return std::pow( a, b); }
752inline Float64 pow( Float64 a, Float64 b) { return std::pow( a, b); }
753
755inline Float32 radians( Float32 d) { return d * Float32(MI_PI/180.0); }
757inline Float64 radians( Float64 d) { return d * Float64(MI_PI/180.0); }
758
760inline Float32 round( Float32 s) { return std::floor(s + 0.5f); }
762inline Float64 round( Float64 s) { return std::floor(s + 0.5); }
763
765inline Float32 rsqrt( Float32 s) { return 1.0f / std::sqrt(s); }
767inline Float64 rsqrt( Float64 s) { return 1.0 / std::sqrt(s); }
768
770inline Float32 saturate( Float32 s) { return min(1.f, max(0.f, s)); }
772inline Float64 saturate( Float64 s) { return min(1. , max(0. , s)); }
773
775inline Sint8 sign( Sint8 s)
776{ int r = (s < 0 ) ? -1 : (s > 0) ? 1 : 0; return static_cast<Sint8>( r); }
779{ int r = (s < 0 ) ? -1 : (s > 0) ? 1 : 0; return static_cast<Sint16>( r); }
781inline Sint32 sign( Sint32 s) { return (s < 0 ) ? -1 : (s > 0) ? 1 : 0; }
783inline Sint64 sign( Sint64 s) { return (s < 0 ) ? -1 : (s > 0) ? 1 : 0; }
785inline Float32 sign( Float32 s) { return (s < 0.f) ? -1.f: (s > 0.f) ? 1.f : 0.f; }
787inline Float64 sign( Float64 s) { return (s < 0. ) ? -1. : (s > 0.) ? 1. : 0.; }
788
790inline bool sign_bit( Sint8 s) { return s < 0; }
792inline bool sign_bit( Sint16 s) { return s < 0; }
794inline bool sign_bit( Sint32 s) { return s < 0; }
796inline bool sign_bit( Sint64 s) { return s < 0; }
797
802inline bool sign_bit( Float32 s)
803{
804 return (base::binary_cast<Uint32>(s) & (1U << 31)) != 0U;
805}
806
811inline bool sign_bit( Float64 s)
812{
813 return (base::binary_cast<Uint64>(s) & (1ULL << 63)) != 0ULL;
814}
815
816#if (__cplusplus < 201103L)
820inline bool isnan MI_PREVENT_MACRO_EXPAND (const Float32 x)
821{
822 // interpret as Uint32 value
823 const Uint32 f = base::binary_cast<Uint32>(x);
824
825 // check bit pattern
826 return (f << 1) > 0xFF000000U; // shift sign bit, 8bit exp == 2^8-1, fraction != 0
827}
828
832inline bool isnan MI_PREVENT_MACRO_EXPAND (const Float64 x)
833{
834 // interpret as Uint64 value
835 const Uint64 f = base::binary_cast<Uint64>(x);
836
837 return (f << 1) > 0xFFE0000000000000ULL; // shift sign bit, 11bit exp == 2^11-1, fraction != 0
838}
839#else
840using std::isnan;
841#endif
842
843
844#ifndef __CUDA_ARCH__
845inline float __uint_as_float(const unsigned v)
846{ return base::binary_cast<float>(v);}
847
848inline unsigned __float_as_uint(const float v)
849{ return base::binary_cast<unsigned>(v);}
850#endif
851
852
857{
858 const Uint32 exponent_mask = 0x7F800000; // 8 bit exponent
859 const Uint32 fraction_mask = 0x7FFFFF; // 23 bit fraction
860
861 // interpret as Uint32 value
862 const Uint32 f = base::binary_cast<Uint32>(x);
863
864 // check bit pattern
865 return ((f & exponent_mask) == exponent_mask) && // exp == 2^8 - 1
866 ((f & fraction_mask) == 0); // fraction == 0
867}
868
873{
874 const Uint64 exponent_mask = 0x7FF0000000000000ULL; // 11 bit exponent
875 const Uint64 fraction_mask = 0xFFFFFFFFFFFFFULL; // 52 bit fraction
876
877 // interpret as Uint64 value
878 const Uint64 f = base::binary_cast<Uint64>(x);
879
880 // check bit pattern
881 return ((f & exponent_mask) == exponent_mask) && // exp == 2^11 - 1
882 ((f & fraction_mask) == 0); // fraction == 0
883}
884
885
886#if (__cplusplus < 201103L)
892inline bool isfinite MI_PREVENT_MACRO_EXPAND (const Float32 x)
893{
894 const Uint32 exponent_mask = 0x7F800000; // 8 bit exponent
895
896 // interpret as Uint32 value
897 const Uint32 f = base::binary_cast<Uint32>(x);
898
899 // check exponent bits
900 return ((f & exponent_mask) != exponent_mask); // exp != 2^8 - 1
901}
902
908inline bool isfinite MI_PREVENT_MACRO_EXPAND (const Float64 x)
909{
910 const Uint64 exponent_mask = 0x7FF0000000000000ULL; // 11 bit exponent
911
912 // interpret as Uint64 value
913 const Uint64 f = base::binary_cast<Uint64>(x);
914
915 // check exponent bits
916 return ((f & exponent_mask) != exponent_mask); // exp != 2^11 - 1
917}
918#else
919using std::isfinite;
920#endif
921
922
924inline Float32 sin( Float32 a) { return std::sin(a); }
926inline Float64 sin( Float64 a) { return std::sin(a); }
927
931inline void sincos( Float32 a, Float32& s, Float32& c)
932{
933 s = std::sin(a);
934 c = std::cos(a);
935}
939inline void sincos( Float64 a, Float64& s, Float64& c)
940{
941 s = std::sin(a);
942 c = std::cos(a);
943}
944
950{
951 if(x < a)
952 return 0.0f;
953 if(b < x)
954 return 1.0f;
955 Float32 t = (x - a) / (b - a);
956 return t * t * (3.0f - 2.0f * t);
957}
963{
964 if(x < a)
965 return 0.0;
966 if(b < x)
967 return 1.0;
968 Float64 t = (x - a) / (b - a);
969 return t * t * (3.0 - 2.0 * t);
970}
971
973inline Float32 sqrt( Float32 s) { return std::sqrt(s); }
975inline Float64 sqrt( Float64 s) { return std::sqrt(s); }
976
978inline Float32 step( Float32 a, Float32 x) { return (x < a) ? 0.0f : 1.0f; }
980inline Float64 step( Float64 a, Float64 x) { return (x < a) ? 0.0 : 1.0; }
981
983inline Float32 tan( Float32 a) { return std::tan(a); }
985inline Float64 tan( Float64 a) { return std::tan(a); }
986
987
989MI_HOST_DEVICE_INLINE void to_rgbe( const Float32 color[3], Uint32& rgbe)
990{
991 Float32 c[3];
992 c[0] = max( color[0], 0.0f);
993 c[1] = max( color[1], 0.0f);
994 c[2] = max( color[2], 0.0f);
995
996 const Float32 m = max( max( c[0], c[1]), c[2]);
997
998 // should actually be -126 or even -128, but avoid precision problems / denormalized numbers
999 if( m <= 7.5231631727e-37f) // ~2^(-120)
1000 rgbe = 0;
1001 else if( m >= 1.7014118346046923173168730371588e+38f) // 2^127
1002 rgbe = 0xFFFFFFFFu;
1003 else {
1004 const Uint32 e = __float_as_uint( m) & 0x7F800000u;
1005 const Float32 v = __uint_as_float( 0x82800000u - e);
1006
1007 rgbe = Uint32( c[0] * v)
1008 | (Uint32( c[1] * v) << 8)
1009 | (Uint32( c[2] * v) << 16)
1010 | (e * 2 + (2 << 24));
1011 }
1012}
1013
1015MI_HOST_DEVICE_INLINE void to_rgbe( const Float32 color[3], Uint8 rgbe[4])
1016{
1017 Float32 c[3];
1018 c[0] = max( color[0], 0.0f);
1019 c[1] = max( color[1], 0.0f);
1020 c[2] = max( color[2], 0.0f);
1021
1022 const Float32 m = max( max( c[0], c[1]), c[2]);
1023
1024 // should actually be -126 or even -128, but avoid precision problems / denormalized numbers
1025 if( m <= 7.5231631727e-37f) // ~2^(-120)
1026 rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
1027 else if( m >= 1.7014118346046923173168730371588e+38f) // 2^127
1028 rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 255;
1029 else {
1030 const Uint32 e = __float_as_uint( m) & 0x7F800000u;
1031 const Float32 v = __uint_as_float( 0x82800000u - e);
1032
1033 rgbe[0] = Uint8( c[0] * v);
1034 rgbe[1] = Uint8( c[1] * v);
1035 rgbe[2] = Uint8( c[2] * v);
1036 rgbe[3] = Uint8( (e >> 23) + 2);
1037 }
1038}
1039
1041MI_HOST_DEVICE_INLINE void from_rgbe( const Uint8 rgbe[4], Float32 color[3])
1042{
1043 if( rgbe[3] == 0) {
1044 color[0] = color[1] = color[2] = 0.0f;
1045 return;
1046 }
1047
1048 const Uint32 e = (static_cast<Uint32>( rgbe[3]) << 23) - 0x800000u;
1049 const Float32 v = __uint_as_float( e);
1050 const Float32 c = static_cast<Float32>( 1.0 - 0.5/256.0) * v;
1051
1052 color[0] = __uint_as_float( e | (static_cast<Uint32>( rgbe[0]) << 15)) - c;
1053 color[1] = __uint_as_float( e | (static_cast<Uint32>( rgbe[1]) << 15)) - c;
1054 color[2] = __uint_as_float( e | (static_cast<Uint32>( rgbe[2]) << 15)) - c;
1055}
1056
1058MI_HOST_DEVICE_INLINE void from_rgbe( const Uint32 rgbe, Float32 color[3])
1059{
1060 const Uint32 rgbe3 = rgbe & 0xFF000000u;
1061 if( rgbe3 == 0) {
1062 color[0] = color[1] = color[2] = 0.0f;
1063 return;
1064 }
1065
1066 const Uint32 e = (rgbe3 >> 1) - 0x800000u;
1067 const Float32 v = __uint_as_float( e);
1068 const Float32 c = static_cast<Float32>( 1.0 - 0.5/256.0) * v;
1069
1070 color[0] = __uint_as_float( e | ((rgbe << 15) & 0x7F8000u)) - c;
1071 color[1] = __uint_as_float( e | ((rgbe << 7) & 0x7F8000u)) - c;
1072 color[2] = __uint_as_float( e | ((rgbe >> 1) & 0x7F8000u)) - c;
1073}
1074
1075
1076//------ Generic Vector Algorithms --------------------------------------------
1077
1078// overloads for 1D vectors (scalars)
1079
1081inline Sint32 dot( Sint32 a, Sint32 b) { return a * b; }
1083inline Float32 dot( Float32 a, Float32 b) { return a * b; }
1085inline Float64 dot( Float64 a, Float64 b) { return a * b; }
1086
1088template <class V>
1089inline typename V::value_type dot( const V& lhs, const V& rhs)
1090{
1091 typename V::value_type v(0);
1092 for( Size i(0u); i < V::SIZE; ++i)
1093 v += lhs.get(i) * rhs.get(i);
1094 return v;
1095}
1096
1098template <class V>
1099inline typename V::value_type square_length( const V& v)
1100{
1101 return dot( v, v);
1102}
1103
1104// base case for scalars
1105
1107inline Float32 length( Float32 a) { return abs(a); }
1109inline Float64 length( Float64 a) { return abs(a); }
1110
1111
1115template <class V>
1116inline typename V::value_type length( const V& v)
1117{
1118 return sqrt( square_length(v));
1119}
1120
1122template <class V>
1123inline typename V::value_type square_euclidean_distance( const V& lhs, const V& rhs)
1124{
1125 return square_length( lhs - rhs);
1126}
1127
1131template <class V>
1132inline typename V::value_type euclidean_distance(
1133 const V& lhs, const V& rhs)
1134{
1135 return length( lhs - rhs);
1136}
1137
1139template <class V>
1140inline void set_bounds( V& v, const V& low, const V& high)
1141{
1142 for( Size i(0u); i < V::SIZE; ++i)
1143 v[i] = min MI_PREVENT_MACRO_EXPAND (
1144 max MI_PREVENT_MACRO_EXPAND (v.get(i), low.get(i)), high.get(i));
1145}
1146
1149template <class V>
1150inline bool is_equal( const V& lhs, const V& rhs)
1151{
1152 for( Size i(0u); i < V::SIZE; ++i)
1153 if( ! (lhs.get(i) == rhs.get(i)))
1154 return false;
1155 return true;
1156}
1157
1160template <class V>
1161inline bool is_not_equal( const V& lhs, const V& rhs)
1162{
1163 for( Size i(0u); i < V::SIZE; ++i)
1164 if( lhs.get(i) != rhs.get(i))
1165 return true;
1166 return false;
1167}
1168
1173template <class V>
1174inline bool lexicographically_less( const V& lhs, const V& rhs)
1175{
1176 for( Size i(0u); i < V::SIZE-1; ++i) {
1177 if( lhs.get(i) < rhs.get(i))
1178 return true;
1179 if( lhs.get(i) > rhs.get(i))
1180 return false;
1181 }
1182 return lhs.get(V::SIZE-1) < rhs.get(V::SIZE-1);
1183}
1184
1189template <class V>
1190inline bool lexicographically_less_or_equal( const V& lhs, const V& rhs)
1191{
1192 for( Size i(0u); i < V::SIZE-1; ++i) {
1193 if( lhs.get(i) < rhs.get(i))
1194 return true;
1195 if( lhs.get(i) > rhs.get(i))
1196 return false;
1197 }
1198 return lhs.get(V::SIZE-1) <= rhs.get(V::SIZE-1);
1199}
1200
1205template <class V>
1206inline bool lexicographically_greater( const V& lhs, const V& rhs)
1207{
1208 for( Size i(0u); i < V::SIZE-1; ++i) {
1209 if( lhs.get(i) > rhs.get(i))
1210 return true;
1211 if( lhs.get(i) < rhs.get(i))
1212 return false;
1213 }
1214 return lhs.get(V::SIZE-1) > rhs.get(V::SIZE-1);
1215}
1216
1221template <class V>
1222inline bool lexicographically_greater_or_equal( const V& lhs, const V& rhs)
1223{
1224 for( Size i(0u); i < V::SIZE-1; ++i) {
1225 if( lhs.get(i) > rhs.get(i))
1226 return true;
1227 if( lhs.get(i) < rhs.get(i))
1228 return false;
1229 }
1230 return lhs.get(V::SIZE-1) >= rhs.get(V::SIZE-1);
1231}
1232
1242template <class V>
1243inline Comparison_result lexicographically_compare( const V& lhs, const V& rhs)
1244{
1245 for( Size i(0u); i < V::SIZE; ++i) {
1246 Comparison_result result = three_valued_compare( lhs.get(i), rhs.get(i));
1247 if( result != EQUAL)
1248 return result;
1249 }
1250 return EQUAL;
1251}
1252 // end group mi_math_function
1254
1255} // namespace math
1256
1257} // namespace mi
1258
1259#endif // MI_MATH_FUNCTION_H
Assertions and compile-time assertions.
Fixed-size math vector class template with generic operations.
Definition: vector.h:286
#define mi_static_assert(expr)
Compile time assertion that raises a compilation error if the constant expression expr evaluates to f...
Definition: assert.h:58
#define MI_PREVENT_MACRO_EXPAND
Empty macro that can be used after function names to prevent macro expansion that happen to have the ...
Definition: config.h:97
long long Sint64
64-bit signed integer.
Definition: types.h:61
unsigned long long Uint64
64-bit unsigned integer.
Definition: types.h:62
signed short Sint16
16-bit signed integer.
Definition: types.h:45
unsigned int Uint32
32-bit unsigned integer.
Definition: types.h:49
unsigned char Uint8
8-bit unsigned integer.
Definition: types.h:47
Uint64 Size
Unsigned integral type that is large enough to hold the size of all types.
Definition: types.h:112
signed char Sint8
8-bit signed integer.
Definition: types.h:44
Comparison_result
An enum for a three-valued comparison result.
Definition: types.h:203
double Float64
64-bit float.
Definition: types.h:52
float Float32
32-bit float.
Definition: types.h:51
#define MI_PI
Value of Pi.
Definition: types.h:192
unsigned short Uint16
16-bit unsigned integer.
Definition: types.h:48
Comparison_result three_valued_compare(T lhs, T rhs)
Returns the three valued comparison result between two values of a numerical type T.
Definition: types.h:238
signed int Sint32
32-bit signed integer.
Definition: types.h:46
@ EQUAL
= 0. First value is equal to second value.
Definition: types.h:209
Float64 ceil(Float64 s)
Returns the smallest integral value that is not less than s.
Definition: function.h:496
bool lexicographically_less(const V &lhs, const V &rhs)
Returns true if vector lhs is lexicographically less than vector rhs, and false otherwise.
Definition: function.h:1174
Float32 fast_log2(Float32 i)
A fast implementation of log2(x) for floats.
Definition: function.h:393
Float64 log10(Float64 s)
Returns the base 10 logarithm of s.
Definition: function.h:730
Float64 tan(Float64 a)
Returns the tangent of a. The angle a is specified in radians.
Definition: function.h:985
Float64 modf(Float64 s, Float64 &i)
Returns the fractional part of s and stores the integral part of s in i.
Definition: function.h:739
bool lexicographically_less_or_equal(const V &lhs, const V &rhs)
Returns true if vector lhs is lexicographically less than or equal to vector rhs, and false otherwise...
Definition: function.h:1190
Float32 fast_pow(Float32 b, Float32 e)
A fast implementation of pow(x,y) for floats.
Definition: function.h:403
Float64 asin(Float64 s)
Returns the arc sine of s in radians.
Definition: function.h:477
V::value_type square_length(const V &v)
Returns the squared Euclidean norm of the vector v.
Definition: function.h:1099
V::value_type square_euclidean_distance(const V &lhs, const V &rhs)
Returns the squared Euclidean distance from the vector lhs to the vector rhs.
Definition: function.h:1123
Float64 acos(Float64 s)
Returns the arc cosine of s in radians.
Definition: function.h:430
Sint32 dot(Sint32 a, Sint32 b)
Returns the inner product (a.k.a. dot or scalar product) of two integers.
Definition: function.h:1081
Float64 sin(Float64 a)
Returns the sine of a. The angle a is specified in radians.
Definition: function.h:926
Sint32 log2_int(const Uint32 v)
Returns the integer log2 of v.
Definition: function.h:705
Sint32 log2_int_ceil(const Integer v)
Returns the integer log2 of v, i.e., rounded up to the next integer.
Definition: function.h:722
Uint32 leading_zeros(Uint32 v)
Returns the number of leading zeros of v, 32-bit version.
Definition: function.h:622
Float64 atan2(Float64 s, Float64 t)
Returns the arc tangent of s / t.
Definition: function.h:491
Float64 atan(Float64 s)
Returns the arc tangent of s.
Definition: function.h:482
V::value_type euclidean_distance(const V &lhs, const V &rhs)
Returns the Euclidean distance from the vector lhs to the vector rhs.
Definition: function.h:1132
bool lexicographically_greater_or_equal(const V &lhs, const V &rhs)
Returns true if vector lhs is lexicographically greater than or equal to vector rhs,...
Definition: function.h:1222
void set_bounds(V &v, const V &low, const V &high)
Bounds the value of vector v elementwise to the given low and high vector values.
Definition: function.h:1140
Float64 pow(Float64 a, Float64 b)
Returns a to the power of b.
Definition: function.h:752
bool is_not_equal(const V &lhs, const V &rhs)
Returns true if vector lhs is elementwise not equal to vector rhs, and false otherwise.
Definition: function.h:1161
Float32 length(Float32 a)
Returns the Euclidean norm of the scalar a (its absolute value).
Definition: function.h:1107
bool sign_bit(Sint8 s)
Returns true if s<0 and false if s>= 0.
Definition: function.h:790
bool lexicographically_greater(const V &lhs, const V &rhs)
Returns true if vector lhs is lexicographically greater than vector rhs, and false otherwise.
Definition: function.h:1206
Float64 fmod(Float64 a, Float64 b)
Returns a modulo b, in other words, the remainder of a/b.
Definition: function.h:589
Float32 fast_pow2(Float32 x)
A fast implementation of pow(2,x) for floats.
Definition: function.h:382
Float64 cos(Float64 a)
Returns the cosine of a. The angle a is specified in radians.
Definition: function.h:562
bool is_equal(const V &lhs, const V &rhs)
Returns true if vector lhs is elementwise equal to vector rhs, and false otherwise.
Definition: function.h:1150
Float32 fast_sqrt(Float32 i)
A fast implementation of sqrt(x) for floats.
Definition: function.h:357
Float32 fast_exp(Float32 x)
A fast implementation of exp for floats.
Definition: function.h:369
Comparison_result lexicographically_compare(const V &lhs, const V &rhs)
Compares two vectors lexicographically.
Definition: function.h:1243
Float64 floor(Float64 s)
Returns the largest integral value that is not greater than s.
Definition: function.h:580
Float64 sqrt(Float64 s)
Returns the square root of s.
Definition: function.h:975
Bbox<T, DIM> lerp(const Bbox<T, DIM> &bbox1, const Bbox<T, DIM> &bbox2, T t)
Returns the linear interpolation between bbox1 and bbox2, i.e., it returns (1-t) * bbox1 + t * bbox2.
Definition: bbox.h:672
Color frac(const Color &c)
Returns a color with the elementwise positive fractional part of the color c.
Definition: color.h:625
Color sqrt(const Color &c)
Returns the square root of each element of c.
Definition: color.h:804
bool isinfinite(const Color &c)
Indicates whether any component of the color is infinite.
Definition: color.h:831
Color acos(const Color &c)
Returns a color with the elementwise arc cosine of the color c.
Definition: color.h:477
Color ceil(const Color &c)
Returns a color with the elementwise smallest integral value that is not less than the element in col...
Definition: color.h:516
Color clamp(const Color &c, const Color &low, const Color &high)
Returns the color c elementwise clamped to the range [low, high].
Definition: color.h:522
Color abs(const Color &c)
Returns a color with the elementwise absolute values of the color c.
Definition: color.h:471
Color round(const Color &c)
Returns a color with the elements of color c rounded to nearest integers.
Definition: color.h:737
Color modf(const Color &c, Color &i)
Returns the elementwise fractional part of c and stores the elementwise integral part of c in i.
Definition: color.h:713
MI_HOST_DEVICE_INLINE void from_rgbe(const Uint8 rgbe[4], Color &color)
Decodes a color from RGBE representation.
Definition: color.h:867
Color atan(const Color &c)
Returns a color with the elementwise arc tangent of the color c.
Definition: color.h:501
bool isfinite(const Color &c)
Indicates whether all components of the color are finite.
Definition: color.h:822
Color step(const Color &a, const Color &c)
Returns elementwise 0 if c is less than a and 1 otherwise.
Definition: color.h:810
Color tan(const Color &c)
Returns a color with the elementwise tangent of the color c.
Definition: color.h:816
Color atan2(const Color &c, const Color &d)
Returns a color with the elementwise arc tangent of the color c / d.
Definition: color.h:509
Color sin(const Color &c)
Returns a color with the elementwise sine of the color c.
Definition: color.h:761
Color degrees(const Color &c)
Converts elementwise radians in c to degrees.
Definition: color.h:564
Color saturate(const Color &c)
Returns the color c clamped elementwise to the range [0,1].
Definition: color.h:749
Color rsqrt(const Color &c)
Returns the reciprocal of the square root of each element of c.
Definition: color.h:743
bool any(const Color &c)
Returns true if any element of c is not equal to zero.
Definition: color.h:489
Color radians(const Color &c)
Converts elementwise degrees in c to radians.
Definition: color.h:731
Color exp2(const Color &c)
Returns a color with elementwise 2 to the power of the element in the color c.
Definition: color.h:596
Color log(const Color &c)
Returns a color with elementwise natural logarithm of the color c.
Definition: color.h:689
Color floor(const Color &c)
Returns a color with the elementwise largest integral value that is not greater than the element in c...
Definition: color.h:603
Color smoothstep(const Color &a, const Color &b, const Color &c)
Returns 0 if c is less than a and 1 if c is greater than b in an elementwise fashion.
Definition: color.h:782
Color sign(const Color &c)
Returns the elementwise sign of color c.
Definition: color.h:755
Color fmod(const Color &a, const Color &b)
Returns elementwise a modulo b, in other words, the remainder of a/b.
Definition: color.h:611
Color cos(const Color &c)
Returns a color with the elementwise cosine of the color c.
Definition: color.h:558
MI_HOST_DEVICE_INLINE void to_rgbe(const Color &color, Uint32 &rgbe)
Encodes a color into RGBE representation.
Definition: color.h:851
Color pow(const Color &a, const Color &b)
Returns the color a elementwise to the power of b.
Definition: color.h:719
bool all(const Color &c)
Returns true if all elements of c are not equal to zero.
Definition: color.h:483
bool isnan(const Color &c)
Indicates whether any component of the color is "not a number".
Definition: color.h:840
Color log10(const Color &c)
Returns a color with elementwise base 10 logarithm of the color c.
Definition: color.h:704
Color log2(const Color &c)
Returns a color with elementwise base 2 logarithm of the color c.
Definition: color.h:695
Color exp(const Color &c)
Returns a color with elementwise e to the power of the element in the color c.
Definition: color.h:590
bool is_approx_equal(const Color &lhs, const Color &rhs, Float32 e)
Compares the two given values elementwise for equality within the given epsilon.
Definition: color.h:650
void sincos(const Color &a, Color &s, Color &c)
Computes elementwise the sine s and cosine c of angles a simultaneously.
Definition: color.h:769
Color asin(const Color &c)
Returns a color with the elementwise arc sine of the color c.
Definition: color.h:495
Float64 log(Float64 s)
Returns the natural logarithm of s.
Definition: function.h:335
Float64 exp(Float64 s)
Returns the constant e to the power of s (exponential function).
Definition: function.h:330
bool operator()(const T1 &t1, const T2 &t2) const
Functor call.
Definition: function.h:100
bool operator()(const T1 &t1, const T2 &t2) const
Functor call.
Definition: function.h:114
bool operator()(const T1 &t1, const T2 &t2) const
Functor call.
Definition: function.h:86
bool operator()(const T1 &t1, const T2 &t2) const
Functor call.
Definition: function.h:93
T operator()(const T &t1, const T &t2) const
Functor call.
Definition: function.h:121
T operator()(T &t) const
Functor call.
Definition: function.h:180
T operator()(T &t) const
Functor call.
Definition: function.h:201
bool operator()(const T &t1, const T &t2) const
Functor call.
Definition: function.h:152
bool operator()(const T &t) const
Functor call.
Definition: function.h:173
T operator()(const T &t1, const T &t2) const
Functor call.
Definition: function.h:145
bool operator()(const T &t1, const T &t2) const
Functor call.
Definition: function.h:159
T operator()(T &t) const
Functor call.
Definition: function.h:187
bool operator()(const T &t1, const T &t2) const
Functor call.
Definition: function.h:166
T operator()(const T &t1, const T &t2) const
Functor call.
Definition: function.h:138
T operator()(const T &t) const
Unary functor call.
Definition: function.h:128
T operator()(T &t) const
Functor call.
Definition: function.h:194
bool operator()(const T1 &t1, const T2 &t2) const
Functor call.
Definition: function.h:107
T operator()(const T &t1, const T &t2) const
Binary functor call.
Definition: function.h:131
bool operator()(const T1 &t1, const T2 &t2) const
Functor call.
Definition: function.h:79
void transform(const Vector &vec, ResultVector &result, UnaryFunctor f)
Generic transform function that applies a unary functor (return value).
Definition: function.h:234
void for_each(Vector &vec, UnaryFunctor f)
Generic transform function that applies a unary functor (in-place).
Definition: function.h:302
void transform_right_scalar(const Vector &vec, const Scalar &s, ResultVector &result, BinaryFunctor f)
Generic transform function that applies a binary functor (return value, RHS scalar).
Definition: function.h:287
void transform_left_scalar(const Scalar &s, const Vector &vec, ResultVector &result, BinaryFunctor f)
Generic transform function that applies a binary functor (return value, LHS scalar).
Definition: function.h:269
const T & get(Size i) const
Returns the i-th vector element.
Definition: vector.h:620
static const Size SIZE
Constant size of the vector.
Definition: vector.h:300
T * begin()
Returns the pointer to the first vector element.
Definition: vector.h:309
Common namespace for APIs of NVIDIA Advanced Rendering Center GmbH.
Definition: example_derivatives.dox:5
Functor for the logical and operator, &&.
Definition: function.h:149
Functor for the division operator, /.
Definition: function.h:142
Functor for the equality comparison operator, ==.
Definition: function.h:76
Functor for the greater-than-or-equal comparison operator, >=.
Definition: function.h:111
Functor for the greater-than comparison operator, >.
Definition: function.h:104
Functor for the less-than-or-equal comparison operator, <=.
Definition: function.h:97
Functor for the less-than comparison operator, <.
Definition: function.h:90
Functor for the minus operator, -, unary and binary.
Definition: function.h:125
Functor for the multiplication operator, *.
Definition: function.h:135
Functor for the inequality comparison operator, !=.
Definition: function.h:83
Functor for the logical not operator, !.
Definition: function.h:170
Functor for the logical or operator, ||.
Definition: function.h:156
Functor for the plus operator, +.
Definition: function.h:118
Functor for the post-decrement operator, --.
Definition: function.h:198
Functor for the post-increment operator, ++.
Definition: function.h:184
Functor for the pre-decrement operator, --.
Definition: function.h:191
Functor for the pre-increment operator, ++.
Definition: function.h:177
Functor for the xor operator, ^.
Definition: function.h:163
Basic types.