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 Float32 dummy;
595 if( s >= 0.0f)
596 return std::modf( s, &dummy);
597 else
598 return 1.0f + std::modf( s, &dummy);
599}
602{
603 Float64 dummy;
604 if( s >= 0.0f)
605 return std::modf( s, &dummy);
606 else
607 return 1.0f + std::modf( s, &dummy);
608}
609
611inline bool is_approx_equal(
612 Float32 left,
613 Float32 right,
614 Float32 e)
615{
616 return abs( left - right ) <= e;
617}
618
620inline bool is_approx_equal(
621 Float64 left,
622 Float64 right,
623 Float64 e)
624{
625 return abs( left - right ) <= e;
626}
627
630 // This implementation tries to use built-in functions if available. For the fallback
631 // method, see Henry Warren: "Hacker's Delight" for reference.
632#if defined(MI_COMPILER_MSC)
633 unsigned long index;
634 const unsigned char valid = _BitScanReverse(&index, v);
635 return (valid != 0) ? 31 - index : 32;
636#elif defined(MI_COMPILER_ICC) || defined(MI_COMPILER_GCC)
637 return (v != 0) ? __builtin_clz(v) : 32;
638#else
639 // use fallback
640 if (v == 0) return 32;
641 Uint32 n = 1;
642 if ((v >> 16) == 0) { n += 16; v <<= 16; };
643 if ((v >> 24) == 0) { n += 8; v <<= 8; };
644 if ((v >> 28) == 0) { n += 4; v <<= 4; };
645 if ((v >> 30) == 0) { n += 2; v <<= 2; };
646 n -= Uint32(v >> 31);
647 return n;
648#endif
649}
650
653 // This implementation tries to use built-in functions if available. For the fallback
654 // method, see Henry Warren: "Hacker's Delight" for reference.
655#if defined(MI_COMPILER_MSC)
656#if defined(MI_ARCH_64BIT)
657 unsigned long index;
658 const unsigned char valid = _BitScanReverse64(&index, v);
659 return (valid != 0) ? 63 - index : 64;
660#else
661 unsigned long index_h, index_l;
662 const unsigned char valid_h = _BitScanReverse(&index_h,(Uint32)(v >> 32));
663 const unsigned char valid_l = _BitScanReverse(&index_l,(Uint32)(v & 0xFFFFFFFF));
664 if (valid_h == 0)
665 return (valid_l != 0) ? 63 - index_l : 64;
666 return 63 - index_h + 32;
667#endif
668#elif defined(MI_COMPILER_ICC) || defined(MI_COMPILER_GCC)
669 return (v != 0) ? __builtin_clzll(v) : 64;
670#else
671 // use fallback
672 if (v == 0) return 64;
673 Uint32 n = 1;
674 if ((v >> 32) == 0) { n += 32; v <<= 32; };
675 if ((v >> 48) == 0) { n += 16; v <<= 16; };
676 if ((v >> 56) == 0) { n += 8; v <<= 8; };
677 if ((v >> 60) == 0) { n += 4; v <<= 4; };
678 if ((v >> 62) == 0) { n += 2; v <<= 2; };
679 n -= Uint32(v >> 63);
680 return n;
681#endif
682}
683
687 Float32 s1,
688 Float32 s2,
689 Float32 t)
690{
691 return s1 * (Float32(1)-t) + s2 * t;
692}
693
697 Float64 s1,
698 Float64 s2,
699 Float64 t)
700{
701 return s1 * (Float64(1)-t) + s2 * t;
702}
703
706{ return std::log(s) * 1.4426950408889634073599246810019f /* log(2) */; }
709{ return std::log(s) * 1.4426950408889634073599246810019 /* log(2) */; }
710
712inline Sint32 log2_int( const Uint32 v) { return (v != 0) ? 31 - leading_zeros(v) : 0; }
713
715inline Sint32 log2_int( const Uint64 v) { return (v != 0) ? 63 - leading_zeros(v) : 0; }
716
718inline Sint32 log2_int( const Float32 v) {
719 return (mi::base::binary_cast<Uint32>(v) >> 23) - 127;
720}
721
723inline Sint32 log2_int( const Float64 v) {
724 return static_cast<Sint32>(mi::base::binary_cast<Uint64>(v) >> 52) - 1023;
725}
726
728template<typename Integer>
729inline Sint32 log2_int_ceil( const Integer v) {
730 // See Henry Warren: "Hacker's Delight" for reference.
731 return (v > 1) ? log2_int(v - 1) + 1 : 0;
732}
733
735inline Float32 log10( Float32 s) { return std::log10(s); }
737inline Float64 log10( Float64 s) { return std::log10(s); }
738
742inline Float32 modf( Float32 s, Float32& i) { return std::modf( s, &i); }
746inline Float64 modf( Float64 s, Float64& i) { return std::modf( s, &i); }
747
749inline Uint32 pow( Uint32 a, Uint32 b) { return Uint32(std::pow(double(a), int(b))); }
751inline Uint64 pow( Uint64 a, Uint64 b) { return Uint64(std::pow(double(a), int(b))); }
753inline Sint32 pow( Sint32 a, Sint32 b) { return Sint32(std::pow(double(a), int(b))); }
755inline Sint64 pow( Sint64 a, Sint64 b) { return Sint64(std::pow(double(a), int(b))); }
757inline Float32 pow( Float32 a, Float32 b) { return std::pow( a, b); }
759inline Float64 pow( Float64 a, Float64 b) { return std::pow( a, b); }
760
762inline Float32 radians( Float32 d) { return d * Float32(MI_PI/180.0); }
764inline Float64 radians( Float64 d) { return d * Float64(MI_PI/180.0); }
765
767inline Float32 round( Float32 s) { return std::floor(s + 0.5f); }
769inline Float64 round( Float64 s) { return std::floor(s + 0.5); }
770
772inline Float32 rsqrt( Float32 s) { return 1.0f / std::sqrt(s); }
774inline Float64 rsqrt( Float64 s) { return 1.0 / std::sqrt(s); }
775
777inline Float32 saturate( Float32 s) { return min(1.f, max(0.f, s)); }
779inline Float64 saturate( Float64 s) { return min(1. , max(0. , s)); }
780
782inline Sint8 sign( Sint8 s)
783{ int r = (s < 0 ) ? -1 : (s > 0) ? 1 : 0; return static_cast<Sint8>( r); }
786{ int r = (s < 0 ) ? -1 : (s > 0) ? 1 : 0; return static_cast<Sint16>( r); }
788inline Sint32 sign( Sint32 s) { return (s < 0 ) ? -1 : (s > 0) ? 1 : 0; }
790inline Sint64 sign( Sint64 s) { return (s < 0 ) ? -1 : (s > 0) ? 1 : 0; }
792inline Float32 sign( Float32 s) { return (s < 0.f) ? -1.f: (s > 0.f) ? 1.f : 0.f; }
794inline Float64 sign( Float64 s) { return (s < 0. ) ? -1. : (s > 0.) ? 1. : 0.; }
795
797inline bool sign_bit( Sint8 s) { return s < 0; }
799inline bool sign_bit( Sint16 s) { return s < 0; }
801inline bool sign_bit( Sint32 s) { return s < 0; }
803inline bool sign_bit( Sint64 s) { return s < 0; }
804
809inline bool sign_bit( Float32 s)
810{
811 return (base::binary_cast<Uint32>(s) & (1U << 31)) != 0U;
812}
813
818inline bool sign_bit( Float64 s)
819{
820 return (base::binary_cast<Uint64>(s) & (1ULL << 63)) != 0ULL;
821}
822
823#if (__cplusplus < 201103L)
827inline bool isnan MI_PREVENT_MACRO_EXPAND (const Float32 x)
828{
829 // interpret as Uint32 value
830 const Uint32 f = base::binary_cast<Uint32>(x);
831
832 // check bit pattern
833 return (f << 1) > 0xFF000000U; // shift sign bit, 8bit exp == 2^8-1, fraction != 0
834}
835
839inline bool isnan MI_PREVENT_MACRO_EXPAND (const Float64 x)
840{
841 // interpret as Uint64 value
842 const Uint64 f = base::binary_cast<Uint64>(x);
843
844 return (f << 1) > 0xFFE0000000000000ULL; // shift sign bit, 11bit exp == 2^11-1, fraction != 0
845}
846#else
847using std::isnan;
848#endif
849
850
851#ifndef __CUDA_ARCH__
852inline float __uint_as_float(const unsigned v)
853{ return base::binary_cast<float>(v);}
854
855inline unsigned __float_as_uint(const float v)
856{ return base::binary_cast<unsigned>(v);}
857#endif
858
859
864{
865 const Uint32 exponent_mask = 0x7F800000; // 8 bit exponent
866 const Uint32 fraction_mask = 0x7FFFFF; // 23 bit fraction
867
868 // interpret as Uint32 value
869 const Uint32 f = base::binary_cast<Uint32>(x);
870
871 // check bit pattern
872 return ((f & exponent_mask) == exponent_mask) && // exp == 2^8 - 1
873 ((f & fraction_mask) == 0); // fraction == 0
874}
875
880{
881 const Uint64 exponent_mask = 0x7FF0000000000000ULL; // 11 bit exponent
882 const Uint64 fraction_mask = 0xFFFFFFFFFFFFFULL; // 52 bit fraction
883
884 // interpret as Uint64 value
885 const Uint64 f = base::binary_cast<Uint64>(x);
886
887 // check bit pattern
888 return ((f & exponent_mask) == exponent_mask) && // exp == 2^11 - 1
889 ((f & fraction_mask) == 0); // fraction == 0
890}
891
892
893#if (__cplusplus < 201103L)
899inline bool isfinite MI_PREVENT_MACRO_EXPAND (const Float32 x)
900{
901 const Uint32 exponent_mask = 0x7F800000; // 8 bit exponent
902
903 // interpret as Uint32 value
904 const Uint32 f = base::binary_cast<Uint32>(x);
905
906 // check exponent bits
907 return ((f & exponent_mask) != exponent_mask); // exp != 2^8 - 1
908}
909
915inline bool isfinite MI_PREVENT_MACRO_EXPAND (const Float64 x)
916{
917 const Uint64 exponent_mask = 0x7FF0000000000000ULL; // 11 bit exponent
918
919 // interpret as Uint64 value
920 const Uint64 f = base::binary_cast<Uint64>(x);
921
922 // check exponent bits
923 return ((f & exponent_mask) != exponent_mask); // exp != 2^11 - 1
924}
925#else
926using std::isfinite;
927#endif
928
929
931inline Float32 sin( Float32 a) { return std::sin(a); }
933inline Float64 sin( Float64 a) { return std::sin(a); }
934
938inline void sincos( Float32 a, Float32& s, Float32& c)
939{
940 s = std::sin(a);
941 c = std::cos(a);
942}
946inline void sincos( Float64 a, Float64& s, Float64& c)
947{
948 s = std::sin(a);
949 c = std::cos(a);
950}
951
957{
958 if(x < a)
959 return 0.0f;
960 if(b < x)
961 return 1.0f;
962 Float32 t = (x - a) / (b - a);
963 return t * t * (3.0f - 2.0f * t);
964}
970{
971 if(x < a)
972 return 0.0;
973 if(b < x)
974 return 1.0;
975 Float64 t = (x - a) / (b - a);
976 return t * t * (3.0 - 2.0 * t);
977}
978
980inline Float32 sqrt( Float32 s) { return std::sqrt(s); }
982inline Float64 sqrt( Float64 s) { return std::sqrt(s); }
983
985inline Float32 step( Float32 a, Float32 x) { return (x < a) ? 0.0f : 1.0f; }
987inline Float64 step( Float64 a, Float64 x) { return (x < a) ? 0.0 : 1.0; }
988
990inline Float32 tan( Float32 a) { return std::tan(a); }
992inline Float64 tan( Float64 a) { return std::tan(a); }
993
994
996MI_HOST_DEVICE_INLINE void to_rgbe( const Float32 color[3], Uint32& rgbe)
997{
998 Float32 c[3];
999 c[0] = max( color[0], 0.0f);
1000 c[1] = max( color[1], 0.0f);
1001 c[2] = max( color[2], 0.0f);
1002
1003 const Float32 m = max( max( c[0], c[1]), c[2]);
1004
1005 // should actually be -126 or even -128, but avoid precision problems / denormalized numbers
1006 if( m <= 7.5231631727e-37f) // ~2^(-120)
1007 rgbe = 0;
1008 else if( m >= 1.7014118346046923173168730371588e+38f) // 2^127
1009 rgbe = 0xFFFFFFFFu;
1010 else {
1011 const Uint32 e = __float_as_uint( m) & 0x7F800000u;
1012 const Float32 v = __uint_as_float( 0x82800000u - e);
1013
1014 rgbe = Uint32( c[0] * v)
1015 | (Uint32( c[1] * v) << 8)
1016 | (Uint32( c[2] * v) << 16)
1017 | (e * 2 + (2 << 24));
1018 }
1019}
1020
1022MI_HOST_DEVICE_INLINE void to_rgbe( const Float32 color[3], Uint8 rgbe[4])
1023{
1024 Float32 c[3];
1025 c[0] = max( color[0], 0.0f);
1026 c[1] = max( color[1], 0.0f);
1027 c[2] = max( color[2], 0.0f);
1028
1029 const Float32 m = max( max( c[0], c[1]), c[2]);
1030
1031 // should actually be -126 or even -128, but avoid precision problems / denormalized numbers
1032 if( m <= 7.5231631727e-37f) // ~2^(-120)
1033 rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
1034 else if( m >= 1.7014118346046923173168730371588e+38f) // 2^127
1035 rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 255;
1036 else {
1037 const Uint32 e = __float_as_uint( m) & 0x7F800000u;
1038 const Float32 v = __uint_as_float( 0x82800000u - e);
1039
1040 rgbe[0] = Uint8( c[0] * v);
1041 rgbe[1] = Uint8( c[1] * v);
1042 rgbe[2] = Uint8( c[2] * v);
1043 rgbe[3] = Uint8( (e >> 23) + 2);
1044 }
1045}
1046
1048MI_HOST_DEVICE_INLINE void from_rgbe( const Uint8 rgbe[4], Float32 color[3])
1049{
1050 if( rgbe[3] == 0) {
1051 color[0] = color[1] = color[2] = 0.0f;
1052 return;
1053 }
1054
1055 const Uint32 e = (static_cast<Uint32>( rgbe[3]) << 23) - 0x800000u;
1056 const Float32 v = __uint_as_float( e);
1057 const Float32 c = static_cast<Float32>( 1.0 - 0.5/256.0) * v;
1058
1059 color[0] = __uint_as_float( e | (static_cast<Uint32>( rgbe[0]) << 15)) - c;
1060 color[1] = __uint_as_float( e | (static_cast<Uint32>( rgbe[1]) << 15)) - c;
1061 color[2] = __uint_as_float( e | (static_cast<Uint32>( rgbe[2]) << 15)) - c;
1062}
1063
1065MI_HOST_DEVICE_INLINE void from_rgbe( const Uint32 rgbe, Float32 color[3])
1066{
1067 const Uint32 rgbe3 = rgbe & 0xFF000000u;
1068 if( rgbe3 == 0) {
1069 color[0] = color[1] = color[2] = 0.0f;
1070 return;
1071 }
1072
1073 const Uint32 e = (rgbe3 >> 1) - 0x800000u;
1074 const Float32 v = __uint_as_float( e);
1075 const Float32 c = static_cast<Float32>( 1.0 - 0.5/256.0) * v;
1076
1077 color[0] = __uint_as_float( e | ((rgbe << 15) & 0x7F8000u)) - c;
1078 color[1] = __uint_as_float( e | ((rgbe << 7) & 0x7F8000u)) - c;
1079 color[2] = __uint_as_float( e | ((rgbe >> 1) & 0x7F8000u)) - c;
1080}
1081
1082
1083//------ Generic Vector Algorithms --------------------------------------------
1084
1085// overloads for 1D vectors (scalars)
1086
1088inline Sint32 dot( Sint32 a, Sint32 b) { return a * b; }
1090inline Float32 dot( Float32 a, Float32 b) { return a * b; }
1092inline Float64 dot( Float64 a, Float64 b) { return a * b; }
1093
1095template <class V>
1096inline typename V::value_type dot( const V& lhs, const V& rhs)
1097{
1098 typename V::value_type v(0);
1099 for( Size i(0u); i < V::SIZE; ++i)
1100 v += lhs.get(i) * rhs.get(i);
1101 return v;
1102}
1103
1105template <class V>
1106inline typename V::value_type square_length( const V& v)
1107{
1108 return dot( v, v);
1109}
1110
1111// base case for scalars
1112
1114inline Float32 length( Float32 a) { return abs(a); }
1116inline Float64 length( Float64 a) { return abs(a); }
1117
1118
1122template <class V>
1123inline typename V::value_type length( const V& v)
1124{
1125 return sqrt( square_length(v));
1126}
1127
1129template <class V>
1130inline typename V::value_type square_euclidean_distance( const V& lhs, const V& rhs)
1131{
1132 return square_length( lhs - rhs);
1133}
1134
1138template <class V>
1139inline typename V::value_type euclidean_distance(
1140 const V& lhs, const V& rhs)
1141{
1142 return length( lhs - rhs);
1143}
1144
1146template <class V>
1147inline void set_bounds( V& v, const V& low, const V& high)
1148{
1149 for( Size i(0u); i < V::SIZE; ++i)
1150 v[i] = min MI_PREVENT_MACRO_EXPAND (
1151 max MI_PREVENT_MACRO_EXPAND (v.get(i), low.get(i)), high.get(i));
1152}
1153
1156template <class V>
1157inline bool is_equal( const V& lhs, const V& rhs)
1158{
1159 for( Size i(0u); i < V::SIZE; ++i)
1160 if( ! (lhs.get(i) == rhs.get(i)))
1161 return false;
1162 return true;
1163}
1164
1167template <class V>
1168inline bool is_not_equal( const V& lhs, const V& rhs)
1169{
1170 for( Size i(0u); i < V::SIZE; ++i)
1171 if( lhs.get(i) != rhs.get(i))
1172 return true;
1173 return false;
1174}
1175
1180template <class V>
1181inline bool lexicographically_less( const V& lhs, const V& rhs)
1182{
1183 for( Size i(0u); i < V::SIZE-1; ++i) {
1184 if( lhs.get(i) < rhs.get(i))
1185 return true;
1186 if( lhs.get(i) > rhs.get(i))
1187 return false;
1188 }
1189 return lhs.get(V::SIZE-1) < rhs.get(V::SIZE-1);
1190}
1191
1196template <class V>
1197inline bool lexicographically_less_or_equal( const V& lhs, const V& rhs)
1198{
1199 for( Size i(0u); i < V::SIZE-1; ++i) {
1200 if( lhs.get(i) < rhs.get(i))
1201 return true;
1202 if( lhs.get(i) > rhs.get(i))
1203 return false;
1204 }
1205 return lhs.get(V::SIZE-1) <= rhs.get(V::SIZE-1);
1206}
1207
1212template <class V>
1213inline bool lexicographically_greater( const V& lhs, const V& rhs)
1214{
1215 for( Size i(0u); i < V::SIZE-1; ++i) {
1216 if( lhs.get(i) > rhs.get(i))
1217 return true;
1218 if( lhs.get(i) < rhs.get(i))
1219 return false;
1220 }
1221 return lhs.get(V::SIZE-1) > rhs.get(V::SIZE-1);
1222}
1223
1228template <class V>
1229inline bool lexicographically_greater_or_equal( const V& lhs, const V& rhs)
1230{
1231 for( Size i(0u); i < V::SIZE-1; ++i) {
1232 if( lhs.get(i) > rhs.get(i))
1233 return true;
1234 if( lhs.get(i) < rhs.get(i))
1235 return false;
1236 }
1237 return lhs.get(V::SIZE-1) >= rhs.get(V::SIZE-1);
1238}
1239
1249template <class V>
1250inline Comparison_result lexicographically_compare( const V& lhs, const V& rhs)
1251{
1252 for( Size i(0u); i < V::SIZE; ++i) {
1253 Comparison_result result = three_valued_compare( lhs.get(i), rhs.get(i));
1254 if( result != EQUAL)
1255 return result;
1256 }
1257 return EQUAL;
1258}
1259 // end group mi_math_function
1261
1262} // namespace math
1263
1264} // namespace mi
1265
1266#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:1181
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:737
Float64 tan(Float64 a)
Returns the tangent of a. The angle a is specified in radians.
Definition: function.h:992
Float64 modf(Float64 s, Float64 &i)
Returns the fractional part of s and stores the integral part of s in i.
Definition: function.h:746
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:1197
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:1106
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:1130
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:1088
Float64 sin(Float64 a)
Returns the sine of a. The angle a is specified in radians.
Definition: function.h:933
Sint32 log2_int(const Uint32 v)
Returns the integer log2 of v.
Definition: function.h:712
Sint32 log2_int_ceil(const Integer v)
Returns the integer log2 of v, i.e., rounded up to the next integer.
Definition: function.h:729
Uint32 leading_zeros(Uint32 v)
Returns the number of leading zeros of v, 32-bit version.
Definition: function.h:629
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:1139
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:1229
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:1147
Float64 pow(Float64 a, Float64 b)
Returns a to the power of b.
Definition: function.h:759
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:1168
Float32 length(Float32 a)
Returns the Euclidean norm of the scalar a (its absolute value).
Definition: function.h:1114
bool sign_bit(Sint8 s)
Returns true if s<0 and false if s>= 0.
Definition: function.h:797
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:1213
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:1157
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:1250
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:982
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.