neuray API Programmer's Manual

function.h File Reference

Description

Math functions and function templates on simple types or generic container and vector concepts. See Math Functions.

Code Example

function.h

‎/***************************************************************************************************
 * Copyright 2023 NVIDIA Corporation. All rights reserved.
 **************************************************************************************************/

#ifndef MI_MATH_FUNCTION_H
#define MI_MATH_FUNCTION_H

#include <mi/base/assert.h>
#include <mi/base/types.h>

#ifdef MI_PLATFORM_WINDOWS
#include <intrin.h>
#pragma intrinsic(_BitScanReverse)
#ifdef MI_ARCH_64BIT
#pragma intrinsic(_BitScanReverse64)
#endif
#endif

namespace mi {

namespace math {


namespace functor {

struct Operator_equal_equal {
    template <typename T1, typename T2>
    inline bool operator()( const T1& t1, const T2& t2) const { return t1 == t2; }
};

struct Operator_not_equal {
    template <typename T1, typename T2>
    inline bool operator()( const T1& t1, const T2& t2) const { return t1 != t2; }
};

struct Operator_less {
    template <typename T1, typename T2>
    inline bool operator()( const T1& t1, const T2& t2) const { return t1 < t2; }
};

struct Operator_less_equal {
    template <typename T1, typename T2>
    inline bool operator()( const T1& t1, const T2& t2) const { return t1 <= t2; }
};

struct Operator_greater {
    template <typename T1, typename T2>
    inline bool operator()( const T1& t1, const T2& t2) const { return t1 > t2; }
};

struct Operator_greater_equal {
    template <typename T1, typename T2>
    inline bool operator()( const T1& t1, const T2& t2) const { return t1 >= t2; }
};

struct Operator_plus {
    template <typename T>
    inline T operator()( const T& t1, const T& t2) const { return t1 + t2; }
};

struct Operator_minus {
    template <typename T>
    inline T operator()( const T& t)               const { return - t; }
    template <typename T>
    inline T operator()( const T& t1, const T& t2) const { return t1 - t2; }
};

struct Operator_multiply {
    template <typename T>
    inline T operator()( const T& t1, const T& t2) const { return t1 * t2; }
};

struct Operator_divide {
    template <typename T>
    inline T operator()( const T& t1, const T& t2) const { return t1 / t2; }
};

struct Operator_and_and {
    template <typename T>
    inline bool operator()( const T& t1, const T& t2) const { return t1 && t2; }
};

struct Operator_or_or {
    template <typename T>
    inline bool operator()( const T& t1, const T& t2) const { return t1 || t2; }
};

struct Operator_xor {
    template <typename T>
    inline bool operator()( const T& t1, const T& t2) const { return t1 ^ t2; }
};

struct Operator_not {
    template <typename T>
    inline bool operator()( const T& t) const { return ! t; }
};

struct Operator_pre_incr {
    template <typename T>
    inline T operator()( T& t) const { return ++ t; }
};

struct Operator_post_incr {
    template <typename T>
    inline T operator()( T& t) const { return t ++; }
};

struct Operator_pre_decr {
    template <typename T>
    inline T operator()( T& t) const { return -- t; }
};

struct Operator_post_decr {
    template <typename T>
    inline T operator()( T& t) const { return t --; }
};
 // end group mi_math_functor

} // namespace functor

namespace general {







template <class Vector, class ResultVector, class UnaryFunctor>
inline void transform( const Vector& vec, ResultVector& result, UnaryFunctor f)
{
    mi_static_assert( Vector::SIZE == ResultVector::SIZE);
    for( Size i = 0; i != Vector::SIZE; ++i)
        result.set( i, f( vec.get(i)));
}

template <class Vector1, class Vector2, class ResultVector, class BinaryFunctor>
inline void transform(
    const Vector1& vec1, const Vector2& vec2, ResultVector& result, BinaryFunctor f)
{
    mi_static_assert( Vector1::SIZE == Vector2::SIZE);
    mi_static_assert( Vector1::SIZE == ResultVector::SIZE);
    for( Size i = 0; i != Vector1::SIZE; ++i)
        result.set( i, f( vec1.get(i), vec2.get(i)));
}

template <class Scalar, class Vector, class ResultVector, class BinaryFunctor>
inline void transform_left_scalar(
    const Scalar& s, const Vector& vec, ResultVector& result, BinaryFunctor f)
{
    mi_static_assert( Vector::SIZE == ResultVector::SIZE);
    for( Size i = 0; i != Vector::SIZE; ++i)
        result.set( i, f( s, vec.get(i)));
}

template <class Scalar, class Vector, class ResultVector, class BinaryFunctor>
inline void transform_right_scalar(
    const Vector& vec, const Scalar& s, ResultVector& result, BinaryFunctor f)
{
    mi_static_assert( Vector::SIZE == ResultVector::SIZE);
    for( Size i = 0; i != Vector::SIZE; ++i)
        result.set( i, f( vec.get(i), s));
}

template <class Vector, class UnaryFunctor>
inline void for_each( Vector& vec, UnaryFunctor f)
{
    for( Size i = 0; i != Vector::SIZE; ++i)
        f( vec.begin()[i]);
}

template <class Vector1, class Vector2, class BinaryFunctor>
inline void for_each( Vector1& vec1, const Vector2& vec2, BinaryFunctor f)
{
    mi_static_assert( Vector1::SIZE == Vector2::SIZE);
    for( Size i = 0; i != Vector1::SIZE; ++i)
        f( vec1.begin()[i], vec2.begin()[i]);
}
 // end group mi_math_functor

} // namespace general

inline Float32 
               exp( Float32 s) { return std::exp(s); }
inline Float64 
               exp( Float64 s) { return std::exp(s); }

inline Float32 
               log( Float32 s) { return std::log(s); }
inline Float64 
               log( Float64 s) { return std::log(s); }


#ifndef __CUDACC__
using mi::base::min;
using mi::base::max;
#endif
using mi::base::abs;



inline Float32 
               fast_sqrt( Float32 i)
{
    int tmp = base::binary_cast<int>( i);
    tmp -= 1 << 23;     // Remove last bit to not let it go to mantissa
    // tmp is now an approximation to logbase2(i)
    tmp = tmp >> 1;     // Divide by 2
    tmp += 1 << 29;     // Add 64 to the exponent: (e+127)/2 = (e/2)+63
                        // that represents (e/2)-64 but we want e/2
    return base::binary_cast<Float32>( tmp);
}

inline Float32 
               fast_exp( Float32 x)
{
    const Float32 EXP_C   = 8388608.0f; // 2^23
    const Float32 LOG_2_E = 1.4426950408889634073599246810019f; // 1 / log(2)

    x *= LOG_2_E;
    Float32 y = x - std::floor(x);
    y = (y - y*y) * 0.33971f;
    const Float32 z = max MI_PREVENT_MACRO_EXPAND ((x + 127.0f - y) * EXP_C, 0.f);
    return base::binary_cast<Float32>( static_cast<int>( z));
}

inline Float32 
               fast_pow2( Float32 x)
{
    const Float32 EXP_C = 8388608.0f; // 2^23

    Float32 y = x - std::floor(x);
    y = (y - y*y) * 0.33971f;
    const Float32 z = max MI_PREVENT_MACRO_EXPAND ((x + 127.0f - y) * EXP_C, 0.f);
    return base::binary_cast<Float32>( static_cast<int>( z));
}

inline Float32 
               fast_log2( Float32 i)
{
    const Float32 LOG_C = 0.00000011920928955078125f; // 2^(-23)

    const Float32 x = static_cast<Float32>( base::binary_cast<int>( i)) * LOG_C - 127.f;
    const Float32 y = x - std::floor(x);
    return x + (y - y*y) * 0.346607f;
}

inline Float32 
               fast_pow(
    Float32 b,  
    Float32 e)  
{
    if( b == 0.0f)
        return 0.0f;

    const Float32 LOG_C = 0.00000011920928955078125f; // 2^(-23)
    const Float32 EXP_C = 8388608.0f; // 2^23

    const Float32 x  = static_cast<Float32>( base::binary_cast<int>( b)) * LOG_C - 127.f;
    const Float32 y  = x - std::floor(x);
    const Float32 fl = e * (x + (y - y*y) * 0.346607f);
    const Float32 y2 = fl - std::floor(fl);
    const Float32 z  = max(
        fl*EXP_C + static_cast<Float32>( 127.0*EXP_C)
                 - (y2 - y2*y2) * static_cast<Float32>( 0.33971*EXP_C), 0.f);

    return base::binary_cast<Float32>( static_cast<int>( z));
}
 // end group mi_math_approx_function


inline Float32 
               acos( Float32 s) { return std::acos(s); }
inline Float64 
               acos( Float64 s) { return std::acos(s); }

inline bool all( Uint8   v) { return Uint8  (0) != v; }
inline bool all( Uint16  v) { return Uint16 (0) != v; }
inline bool all( Uint32  v) { return Uint32 (0) != v; }
inline bool all( Uint64  v) { return Uint64 (0) != v; }
inline bool all( Sint8   v) { return Sint8  (0) != v; }
inline bool all( Sint16  v) { return Sint16 (0) != v; }
inline bool all( Sint32  v) { return Sint32 (0) != v; }
inline bool all( Sint64  v) { return Sint64 (0) != v; }
inline bool all( Float32 v) { return Float32(0) != v; }
inline bool all( Float64 v) { return Float64(0) != v; }

inline bool any( Uint8   v) { return Uint8  (0) != v; } //-V524 PVS
inline bool any( Uint16  v) { return Uint16 (0) != v; } //-V524 PVS
inline bool any( Uint32  v) { return Uint32 (0) != v; } //-V524 PVS
inline bool any( Uint64  v) { return Uint64 (0) != v; } //-V524 PVS
inline bool any( Sint8   v) { return Sint8  (0) != v; } //-V524 PVS
inline bool any( Sint16  v) { return Sint16 (0) != v; } //-V524 PVS
inline bool any( Sint32  v) { return Sint32 (0) != v; } //-V524 PVS
inline bool any( Sint64  v) { return Sint64 (0) != v; } //-V524 PVS
inline bool any( Float32 v) { return Float32(0) != v; } //-V524 PVS
inline bool any( Float64 v) { return Float64(0) != v; } //-V524 PVS

inline Float32 
               asin( Float32 s) { return std::asin(s); }
inline Float64 
               asin( Float64 s) { return std::asin(s); }

inline Float32 
               atan( Float32 s) { return std::atan(s); }
inline Float64 
               atan( Float64 s) { return std::atan(s); }

inline Float32 
               atan2( Float32 s, Float32 t) { return std::atan2(s,t); }
inline Float64 
               atan2( Float64 s, Float64 t) { return std::atan2(s,t); }

inline Float32 
               ceil( Float32 s) { return std::ceil(s); }
inline Float64 
               ceil( Float64 s) { return std::ceil(s); }

inline  Uint8 
               clamp(  Uint8 s,  Uint8 low,  Uint8 high)
{
    return min(high, max(low, s));
}
inline Uint16 
               clamp( Uint16 s, Uint16 low, Uint16 high)
{
    return min(high, max(low, s));
}
inline Uint32 
               clamp( Uint32 s, Uint32 low, Uint32 high)
{
    return min(high, max(low, s));
}
inline Uint64 
               clamp( Uint64 s, Uint64 low, Uint64 high)
{
    return min(high, max(low, s));
}
inline  Sint8 
               clamp(  Sint8 s,  Sint8 low,  Sint8 high)
{
    return min(high, max(low, s));
}
inline Sint16 
               clamp( Sint16 s, Sint16 low, Sint16 high)
{
    return min(high, max(low, s));
}
inline Sint32 
               clamp( Sint32 s, Sint32 low, Sint32 high)
{
    return min(high, max(low, s));
}
inline Sint64 
               clamp( Sint64 s, Sint64 low, Sint64 high)
{
    return min(high, max(low, s));
}
inline Float32 
               clamp( Float32 s, Float32 low, Float32 high)
{
    return min(high, max(low, s));
}
inline Float64 
               clamp( Float64 s, Float64 low, Float64 high)
{
    return min(high, max(low, s));
}

inline Float32 
               cos( Float32 a) { return std::cos(a); }
inline Float64 
               cos( Float64 a) { return std::cos(a); }

inline Float32 
               degrees( Float32 r) { return r * Float32(180.0/MI_PI); }
inline Float64 
               degrees( Float64 r) { return r * Float64(180.0/MI_PI); }

inline Float32 
               exp2( Float32 s) { return fast_pow2(s); }
inline Float64 
               exp2( Float64 s)
{
    return std::exp(s * 0.69314718055994530941723212145818 /* log(2) */ );
}

inline Float32 
               floor( Float32 s) { return std::floor(s); }
inline Float64 
               floor( Float64 s) { return std::floor(s); }

inline Float32 
               fmod( Float32 a, Float32 b) { return std::fmod(a,b); }
inline Float64 
               fmod( Float64 a, Float64 b) { return std::fmod(a,b); }

inline Float32 
               frac( Float32 s)
{
    Float32 dummy;
    if( s >= 0.0f)
        return std::modf( s, &dummy);
    else
        return 1.0f + std::modf( s, &dummy);
}
inline Float64 
               frac( Float64 s)
{
    Float64 dummy;
    if( s >= 0.0f)
        return std::modf( s, &dummy);
    else
        return 1.0f + std::modf( s, &dummy);
}

inline bool is_approx_equal(
    Float32 left,
    Float32 right,
    Float32 e)
{
    return abs( left - right ) <= e;
}

inline bool is_approx_equal(
    Float64 left,
    Float64 right,
    Float64 e)
{
    return abs( left - right ) <= e;
}

inline Uint32 
               leading_zeros(Uint32 v) {
    // This implementation tries to use built-in functions if available. For the fallback
    // method, see Henry Warren: "Hacker's Delight" for reference.
#if defined(MI_COMPILER_MSC)
    unsigned long index;
    const unsigned char valid = _BitScanReverse(&index, v);
    return (valid != 0) ? 31 - index : 32;
#elif defined(MI_COMPILER_ICC) || defined(MI_COMPILER_GCC)
    return (v != 0) ? __builtin_clz(v) : 32;
#else
    // use fallback
    if (v == 0) return 32;
    Uint32 n = 1;
    if ((v >> 16) == 0) { n += 16; v <<= 16; };
    if ((v >> 24) == 0) { n += 8;  v <<= 8; };
    if ((v >> 28) == 0) { n += 4;  v <<= 4; };
    if ((v >> 30) == 0) { n += 2;  v <<= 2; };
    n -= Uint32(v >> 31);
    return n;
#endif
}

inline Uint32 
               leading_zeros(Uint64 v) {
    // This implementation tries to use built-in functions if available. For the fallback
    // method, see Henry Warren: "Hacker's Delight" for reference.
#if defined(MI_COMPILER_MSC)
#if defined(MI_ARCH_64BIT)
    unsigned long index;
    const unsigned char valid = _BitScanReverse64(&index, v);
    return (valid != 0) ? 63 - index : 64;
#else
    unsigned long index_h, index_l;
    const unsigned char valid_h = _BitScanReverse(&index_h,(Uint32)(v >> 32));
    const unsigned char valid_l = _BitScanReverse(&index_l,(Uint32)(v & 0xFFFFFFFF));
    if (valid_h == 0)
    return (valid_l != 0) ? 63 - index_l : 64;
    return 63 - index_h + 32;
#endif
#elif defined(MI_COMPILER_ICC) || defined(MI_COMPILER_GCC)
    return (v != 0) ? __builtin_clzll(v) : 64;
#else
    // use fallback
    if (v == 0) return 64;
    Uint32 n = 1;
    if ((v >> 32) == 0) { n += 32; v <<= 32; };
    if ((v >> 48) == 0) { n += 16; v <<= 16; };
    if ((v >> 56) == 0) { n += 8;  v <<= 8; };
    if ((v >> 60) == 0) { n += 4;  v <<= 4; };
    if ((v >> 62) == 0) { n += 2;  v <<= 2; };
    n -= Uint32(v >> 63);
    return n;
#endif
}

inline Float32 
               lerp(
    Float32 s1,  
    Float32 s2,  
    Float32 t)   
{
    return s1 * (Float32(1)-t) + s2 * t;
}

inline Float64 
               lerp(
    Float64 s1,  
    Float64 s2,  
    Float64 t)   
{
    return s1 * (Float64(1)-t) + s2 * t;
}

inline Float32 
               log2 
               MI_PREVENT_MACRO_EXPAND ( Float32 s)
{ return std::log(s) * 1.4426950408889634073599246810019f /* log(2) */; }
inline Float64 
               log2 
               MI_PREVENT_MACRO_EXPAND ( Float64 s)
{ return std::log(s) * 1.4426950408889634073599246810019 /* log(2) */; }

inline Sint32 
               log2_int( const Uint32 v) { return (v != 0) ? 31 - leading_zeros(v) : 0; }

inline Sint32 
               log2_int( const Uint64 v) { return (v != 0) ? 63 - leading_zeros(v) : 0; }

inline Sint32 
               log2_int( const Float32 v) { 
    return (mi::base::binary_cast<Uint32>(v) >> 23) - 127; 
}

inline Sint32 
               log2_int( const Float64 v) { 
    return static_cast<Sint32>(mi::base::binary_cast<Uint64>(v) >> 52) - 1023;
}

template<typename Integer>
inline Sint32 
               log2_int_ceil( const Integer v) {
    // See Henry Warren: "Hacker's Delight" for reference.
    return (v > 1) ? log2_int(v - 1) + 1 : 0;
}

inline Float32 
               log10( Float32 s) { return std::log10(s); }
inline Float64 
               log10( Float64 s) { return std::log10(s); }

inline Float32 
               modf( Float32 s, Float32& i) { return std::modf( s, &i); }
inline Float64 
               modf( Float64 s, Float64& i) { return std::modf( s, &i); }

inline Uint32  
               pow( Uint32  a, Uint32  b) { return Uint32(std::pow(double(a), int(b))); }
inline Uint64  
               pow( Uint64  a, Uint64  b) { return Uint64(std::pow(double(a), int(b))); }
inline Sint32  
               pow( Sint32  a, Sint32  b) { return Sint32(std::pow(double(a), int(b))); }
inline Sint64  
               pow( Sint64  a, Sint64  b) { return Sint64(std::pow(double(a), int(b))); }
inline Float32 
               pow( Float32 a, Float32 b) { return std::pow( a, b); }
inline Float64 
               pow( Float64 a, Float64 b) { return std::pow( a, b); }

inline Float32 
               radians( Float32 d) { return d * Float32(MI_PI/180.0); }
inline Float64 
               radians( Float64 d) { return d * Float64(MI_PI/180.0); }

inline Float32 
               round( Float32 s) { return std::floor(s + 0.5f); }
inline Float64 
               round( Float64 s) { return std::floor(s + 0.5); }

inline Float32 
               rsqrt( Float32 s) { return 1.0f / std::sqrt(s); }
inline Float64 
               rsqrt( Float64 s) { return 1.0  / std::sqrt(s); }

inline Float32 
               saturate( Float32 s) { return min(1.f, max(0.f, s)); }
inline Float64 
               saturate( Float64 s) { return min(1. , max(0. , s)); }

inline Sint8   
               sign( Sint8   s)
{ int r = (s < 0 ) ? -1 : (s > 0) ? 1 : 0; return static_cast<Sint8>(  r); }
inline Sint16  
               sign( Sint16  s)
{ int r = (s < 0 ) ? -1 : (s > 0) ? 1 : 0; return static_cast<Sint16>( r); }
inline Sint32  
               sign( Sint32  s) { return (s < 0  )  ? -1 : (s > 0)   ? 1   : 0;   }
inline Sint64  
               sign( Sint64  s) { return (s < 0  )  ? -1 : (s > 0)   ? 1   : 0;   }
inline Float32 
               sign( Float32 s) { return (s < 0.f) ? -1.f: (s > 0.f) ? 1.f : 0.f; }
inline Float64 
               sign( Float64 s) { return (s < 0. ) ? -1. : (s > 0.)  ? 1.  : 0.;  }

inline bool   sign_bit( Sint8    s) { return s < 0; }
inline bool   sign_bit( Sint16   s) { return s < 0; }
inline bool   sign_bit( Sint32   s) { return s < 0; }
inline bool   sign_bit( Sint64   s) { return s < 0; }

inline bool sign_bit( Float32 s)
{
    return (base::binary_cast<Uint32>(s) & (1U << 31)) != 0U;
}

inline bool sign_bit( Float64 s)
{
    return (base::binary_cast<Uint64>(s) & (1ULL << 63)) != 0ULL;
}

#if (__cplusplus < 201103L)
inline bool isnan MI_PREVENT_MACRO_EXPAND (const Float32 x)
{
    // interpret as Uint32 value
    const Uint32 f = base::binary_cast<Uint32>(x);

    // check bit pattern
    return (f << 1) > 0xFF000000U; // shift sign bit, 8bit exp == 2^8-1, fraction != 0
}

inline bool isnan 
               MI_PREVENT_MACRO_EXPAND (const Float64 x)
{
    // interpret as Uint64 value
    const Uint64 f = base::binary_cast<Uint64>(x);

    return (f << 1) > 0xFFE0000000000000ULL; // shift sign bit, 11bit exp == 2^11-1, fraction != 0
}
#else
using std::isnan;
#endif


#ifndef __CUDA_ARCH__
inline float __uint_as_float(const unsigned v)
{ return base::binary_cast<float>(v);}

inline unsigned __float_as_uint(const float v)
{ return base::binary_cast<unsigned>(v);}
#endif


inline bool isinfinite 
               MI_PREVENT_MACRO_EXPAND (const Float32 x)
{
    const Uint32 exponent_mask = 0x7F800000; // 8 bit exponent
    const Uint32 fraction_mask = 0x7FFFFF;   // 23 bit fraction

    // interpret as Uint32 value
    const Uint32 f = base::binary_cast<Uint32>(x);

    // check bit pattern
    return ((f & exponent_mask) == exponent_mask) && // exp == 2^8 - 1
           ((f & fraction_mask) == 0);               // fraction == 0
}

inline bool isinfinite 
               MI_PREVENT_MACRO_EXPAND (const Float64 x)
{
    const Uint64 exponent_mask = 0x7FF0000000000000ULL; // 11 bit exponent
    const Uint64 fraction_mask = 0xFFFFFFFFFFFFFULL;    // 52 bit fraction

    // interpret as Uint64 value
    const Uint64 f = base::binary_cast<Uint64>(x);

    // check bit pattern
    return ((f & exponent_mask) == exponent_mask) && // exp == 2^11 - 1
           ((f & fraction_mask) == 0);               // fraction == 0
}


#if (__cplusplus < 201103L)
inline bool isfinite MI_PREVENT_MACRO_EXPAND (const Float32 x)
{
    const Uint32 exponent_mask = 0x7F800000; // 8 bit exponent

    // interpret as Uint32 value
    const Uint32 f = base::binary_cast<Uint32>(x);

    // check exponent bits
    return ((f & exponent_mask) != exponent_mask); // exp != 2^8 - 1
}

inline bool isfinite 
               MI_PREVENT_MACRO_EXPAND (const Float64 x)
{
    const Uint64 exponent_mask = 0x7FF0000000000000ULL; // 11 bit exponent

    // interpret as Uint64 value
    const Uint64 f = base::binary_cast<Uint64>(x);

    // check exponent bits
    return ((f & exponent_mask) != exponent_mask); // exp != 2^11 - 1
}
#else
using std::isfinite;
#endif


inline Float32 
               sin( Float32 a) { return std::sin(a); }
inline Float64 
               sin( Float64 a) { return std::sin(a); }

inline void sincos( Float32 a, Float32& s, Float32& c)
{
    s = std::sin(a);
    c = std::cos(a);
}
inline void sincos( Float64 a, Float64& s, Float64& c)
{
    s = std::sin(a);
    c = std::cos(a);
}

inline Float32 
               smoothstep( Float32 a, Float32 b, Float32 x)
{
    if(x < a)
        return 0.0f;
    if(b < x)
        return 1.0f;
    Float32 t = (x - a) / (b - a);
    return t * t * (3.0f - 2.0f * t);
}
inline Float64 
               smoothstep( Float64 a, Float64 b, Float64 x)
{
    if(x < a)
        return 0.0;
    if(b < x)
        return 1.0;
    Float64 t = (x - a) / (b - a);
    return t * t * (3.0 - 2.0 * t);
}

inline Float32 
               sqrt( Float32 s) { return std::sqrt(s); }
inline Float64 
               sqrt( Float64 s) { return std::sqrt(s); }

inline Float32 
               step( Float32 a, Float32 x) { return (x < a) ? 0.0f : 1.0f; }
inline Float64 
               step( Float64 a, Float64 x) { return (x < a) ? 0.0 : 1.0; }

inline Float32 
               tan( Float32 a) { return std::tan(a); }
inline Float64 
               tan( Float64 a) { return std::tan(a); }


MI_HOST_DEVICE_INLINE void to_rgbe( const Float32 color[3], Uint32& rgbe)
{
    Float32 c[3];
    c[0] = max( color[0], 0.0f);
    c[1] = max( color[1], 0.0f);
    c[2] = max( color[2], 0.0f);

    const Float32 m = max( max( c[0], c[1]), c[2]);

    // should actually be -126 or even -128, but avoid precision problems / denormalized numbers
    if( m <= 7.5231631727e-37f) // ~2^(-120)
        rgbe = 0;
    else if( m >= 1.7014118346046923173168730371588e+38f) // 2^127
        rgbe = 0xFFFFFFFFu;
    else {
        const Uint32  e = __float_as_uint( m) & 0x7F800000u;
        const Float32 v = __uint_as_float( 0x82800000u - e);

        rgbe =  Uint32( c[0] * v)
             | (Uint32( c[1] * v) <<  8)
             | (Uint32( c[2] * v) << 16)
             | (e * 2 + (2 << 24));
    }
}

MI_HOST_DEVICE_INLINE void to_rgbe( const Float32 color[3], Uint8 rgbe[4])
{
    Float32 c[3];
    c[0] = max( color[0], 0.0f);
    c[1] = max( color[1], 0.0f);
    c[2] = max( color[2], 0.0f);

    const Float32 m = max( max( c[0], c[1]), c[2]);

    // should actually be -126 or even -128, but avoid precision problems / denormalized numbers
    if( m <= 7.5231631727e-37f) // ~2^(-120)
        rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
    else if( m >= 1.7014118346046923173168730371588e+38f) // 2^127
        rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 255;
    else {
        const Uint32  e = __float_as_uint( m) & 0x7F800000u;
        const Float32 v = __uint_as_float( 0x82800000u - e);

        rgbe[0] = Uint8( c[0] * v);
        rgbe[1] = Uint8( c[1] * v);
        rgbe[2] = Uint8( c[2] * v);
        rgbe[3] = Uint8( (e >> 23) + 2);
    }
}

MI_HOST_DEVICE_INLINE void from_rgbe( const Uint8 rgbe[4], Float32 color[3])
{
    if( rgbe[3] == 0) {
        color[0] = color[1] = color[2] = 0.0f;
        return;
    }

    const Uint32  e = (static_cast<Uint32>( rgbe[3]) << 23) - 0x800000u;
    const Float32 v = __uint_as_float( e);
    const Float32 c = static_cast<Float32>( 1.0 - 0.5/256.0) * v;

    color[0] = __uint_as_float( e | (static_cast<Uint32>( rgbe[0]) << 15)) - c;
    color[1] = __uint_as_float( e | (static_cast<Uint32>( rgbe[1]) << 15)) - c;
    color[2] = __uint_as_float( e | (static_cast<Uint32>( rgbe[2]) << 15)) - c;
}

MI_HOST_DEVICE_INLINE void from_rgbe( const Uint32 rgbe, Float32 color[3])
{
    const Uint32 rgbe3 = rgbe & 0xFF000000u;
    if( rgbe3 == 0) {
        color[0] = color[1] = color[2] = 0.0f;
        return;
    }

    const Uint32  e = (rgbe3 >> 1) - 0x800000u;
    const Float32 v = __uint_as_float( e);
    const Float32 c = static_cast<Float32>( 1.0 - 0.5/256.0) * v;

    color[0] = __uint_as_float( e | ((rgbe << 15) & 0x7F8000u)) - c;
    color[1] = __uint_as_float( e | ((rgbe <<  7) & 0x7F8000u)) - c;
    color[2] = __uint_as_float( e | ((rgbe >>  1) & 0x7F8000u)) - c;
}


//------ Generic Vector Algorithms --------------------------------------------

// overloads for 1D vectors (scalars)

inline Sint32 
               dot( Sint32 a, Sint32 b) { return a * b; }
inline Float32 
               dot( Float32 a, Float32 b) { return a * b; }
inline Float64 
               dot( Float64 a, Float64 b) { return a * b; }

template <class V>
inline typename V::value_type dot( const V& lhs, const V& rhs)
{
    typename V::value_type v(0);
    for( Size i(0u); i < V::SIZE; ++i)
        v += lhs.get(i) * rhs.get(i);
    return v;
}

template <class V>
inline typename V::value_type square_length( const V& v)
{
    return dot( v, v);
}

// base case for scalars

inline Float32 
               length( Float32 a) { return abs(a); }
inline Float64 
               length( Float64 a) { return abs(a); }


template <class V>
inline typename V::value_type length( const V& v)
{
    return sqrt( square_length(v));
}

template <class V>
inline typename V::value_type square_euclidean_distance( const V& lhs, const V& rhs)
{
    return square_length( lhs - rhs);
}

template <class V>
inline typename V::value_type euclidean_distance(
    const V& lhs, const V& rhs)
{
    return length( lhs - rhs);
}

template <class V>
inline void set_bounds( V& v, const V& low, const V& high)
{
    for( Size i(0u); i < V::SIZE; ++i)
        v[i] = min MI_PREVENT_MACRO_EXPAND (
                   max MI_PREVENT_MACRO_EXPAND (v.get(i), low.get(i)), high.get(i));
}

template <class V>
inline bool is_equal( const V& lhs, const V& rhs)
{
    for( Size i(0u); i < V::SIZE; ++i)
        if( ! (lhs.get(i) == rhs.get(i)))
            return false;
    return true;
}

template <class V>
inline bool is_not_equal( const V& lhs, const V& rhs)
{
    for( Size i(0u); i < V::SIZE; ++i)
        if( lhs.get(i) != rhs.get(i))
            return true;
    return false;
}

template <class V>
inline bool lexicographically_less( const V& lhs, const V& rhs)
{
    for( Size i(0u); i < V::SIZE-1; ++i) {
        if( lhs.get(i) < rhs.get(i))
            return true;
        if( lhs.get(i) > rhs.get(i))
            return false;
    }
    return lhs.get(V::SIZE-1) < rhs.get(V::SIZE-1);
}

template <class V>
inline bool lexicographically_less_or_equal( const V& lhs, const V& rhs)
{
    for( Size i(0u); i < V::SIZE-1; ++i) {
        if( lhs.get(i) < rhs.get(i))
            return true;
        if( lhs.get(i) > rhs.get(i))
            return false;
    }
    return lhs.get(V::SIZE-1) <= rhs.get(V::SIZE-1);
}

template <class V>
inline bool lexicographically_greater( const V& lhs, const V& rhs)
{
    for( Size i(0u); i < V::SIZE-1; ++i) {
        if( lhs.get(i) > rhs.get(i))
            return true;
        if( lhs.get(i) < rhs.get(i))
            return false;
    }
    return lhs.get(V::SIZE-1) > rhs.get(V::SIZE-1);
}

template <class V>
inline bool lexicographically_greater_or_equal( const V& lhs, const V& rhs)
{
    for( Size i(0u); i < V::SIZE-1; ++i) {
        if( lhs.get(i) > rhs.get(i))
            return true;
        if( lhs.get(i) < rhs.get(i))
            return false;
    }
    return lhs.get(V::SIZE-1) >= rhs.get(V::SIZE-1);
}

template <class V>
inline Comparison_result 
               lexicographically_compare( const V& lhs, const V& rhs)
{
    for( Size i(0u); i < V::SIZE; ++i) {
        Comparison_result result = three_valued_compare( lhs.get(i), rhs.get(i));
        if( result != EQUAL)
            return result;
    }
    return EQUAL;
}
 // end group mi_math_function

} // namespace math

} // namespace mi

#endif // MI_MATH_FUNCTION_H

Namespaces

namespace 
Common namespace for APIs of NVIDIA Advanced Rendering Center GmbH. More...
namespace 
Namespace for the Math API. More...
namespace 
Namespace for basic math functors in the Math API. More...
namespace 
Namespace for generic functions in the Math API. More...

Classes

struct 
Functor for the logical and operator, &&. More...
struct 
Functor for the division operator, /. More...
struct 
Functor for the equality comparison operator, ==. More...
struct 
Functor for the greater-than comparison operator, >. More...
struct 
Functor for the greater-than-or-equal comparison operator, >=. More...
struct 
Functor for the less-than comparison operator, <. More...
struct 
Functor for the less-than-or-equal comparison operator, <=. More...
struct 
Functor for the minus operator, -, unary and binary. More...
struct 
Functor for the multiplication operator, *. More...
struct 
Functor for the logical not operator, !. More...
struct 
Functor for the inequality comparison operator, !=. More...
struct 
Functor for the logical or operator, ||. More...
struct 
Functor for the plus operator, +. More...
struct 
Functor for the post-decrement operator, --. More...
struct 
Functor for the post-increment operator, ++. More...
struct 
Functor for the pre-decrement operator, --. More...
struct 
Functor for the pre-increment operator, ++. More...
struct 
Functor for the xor operator, ^. More...

Functions

Float32  ( Float32 s)
Returns the arc cosine of s in radians. More...
Float64  ( Float64 s)
Returns the arc cosine of s in radians. More...
bool   ( Uint8 v)
Returns true if v is not equal to zero. More...
bool   ( Uint16 v)
Returns true if v is not equal to zero. More...
bool   ( Uint32 v)
Returns true if v is not equal to zero. More...
bool   ( Uint64 v)
Returns true if v is not equal to zero. More...
bool   ( Sint8 v)
Returns true if v is not equal to zero. More...
bool   ( Sint16 v)
Returns true if v is not equal to zero. More...
bool   ( Sint32 v)
Returns true if v is not equal to zero. More...
bool   ( Sint64 v)
Returns true if v is not equal to zero. More...
bool   ( Float32 v)
Returns true if v is not equal to zero. More...
bool   ( Float64 v)
Returns true if v is not equal to zero. More...
bool   ( Uint8 v)
Returns true if v is not equal to zero. More...
bool   ( Uint16 v)
Returns true if v is not equal to zero. More...
bool   ( Uint32 v)
Returns true if v is not equal to zero. More...
bool   ( Uint64 v)
Returns true if v is not equal to zero. More...
bool   ( Sint8 v)
Returns true if v is not equal to zero. More...
bool   ( Sint16 v)
Returns true if v is not equal to zero. More...
bool   ( Sint32 v)
Returns true if v is not equal to zero. More...
bool   ( Sint64 v)
Returns true if v is not equal to zero. More...
bool   ( Float32 v)
Returns true if v is not equal to zero. More...
bool   ( Float64 v)
Returns true if v is not equal to zero. More...
Float32  ( Float32 s)
Returns the arc sine of s in radians. More...
Float64  ( Float64 s)
Returns the arc sine of s in radians. More...
Float32  ( Float32 s)
Returns the arc tangent of s. More...
Float64  ( Float64 s)
Returns the arc tangent of s. More...
Float32  ( Float32 s, Float32 t)
Returns the arc tangent of s / t. More...
Float64  ( Float64 s, Float64 t)
Returns the arc tangent of s / t. More...
Float32  ( Float32 s)
Returns the smallest integral value that is not less than s. More...
Float64  ( Float64 s)
Returns the smallest integral value that is not less than s. More...
Uint8  ( Uint8 s, Uint8 low, Uint8 high)
Returns the value s if it is in the range [low, high], the value low if s < low, or the value high if s > high. More...
Uint16  ( Uint16 s, Uint16 low, Uint16 high)
Returns the value s if it is in the range [low, high], the value low if s < low, or the value high if s > high. More...
Uint32  ( Uint32 s, Uint32 low, Uint32 high)
Returns the value s if it is in the range [low, high], the value low if s < low, or the value high if s > high. More...
Uint64  ( Uint64 s, Uint64 low, Uint64 high)
Returns the value s if it is in the range [low, high], the value low if s < low, or the value high if s > high. More...
Sint8  ( Sint8 s, Sint8 low, Sint8 high)
Returns the value s if it is in the range [low, high], the value low if s < low, or the value high if s > high. More...
Sint16  ( Sint16 s, Sint16 low, Sint16 high)
Returns the value s if it is in the range [low, high], the value low if s < low, or the value high if s > high. More...
Sint32  ( Sint32 s, Sint32 low, Sint32 high)
Returns the value s if it is in the range [low, high], the value low if s < low, or the value high if s > high. More...
Sint64  ( Sint64 s, Sint64 low, Sint64 high)
Returns the value s if it is in the range [low, high], the value low if s < low, or the value high if s > high. More...
Float32  ( Float32 s, Float32 low, Float32 high)
Returns the value s if it is in the range [low, high], the value low if s < low, or the value high if s > high. More...
Float64  ( Float64 s, Float64 low, Float64 high)
Returns the value s if it is in the range [low, high], the value low if s < low, or the value high if s > high. More...
Float32  ( Float32 a)
Returns the cosine of a. The angle a is specified in radians. More...
Float64  ( Float64 a)
Returns the cosine of a. The angle a is specified in radians. More...
Float32  ( Float32 r)
Converts radians r to degrees. More...
Float64  ( Float64 r)
Converts radians r to degrees. More...
Sint32  ( Sint32 a, Sint32 b)
Returns the inner product (a.k.a. dot or scalar product) of two integers. More...
Float32  ( Float32 a, Float32 b)
Returns the inner product (a.k.a. dot or scalar product) of two scalars. More...
Float64  ( Float64 a, Float64 b)
Returns the inner product (a.k.a. dot or scalar product) of two scalars. More...
template< class V>V::​value_type  ( const V& lhs, const V& rhs)
Returns the inner product (a.k.a. dot or scalar product) of two vectors. More...
template< class V>V::​value_type  ( const V& lhs, const V& rhs)
Returns the Euclidean distance from the vector lhs to the vector rhs. More...
Float32  ( Float32 s)
Returns the constant e to the power of s (exponential function). More...
Float64  ( Float64 s)
Returns the constant e to the power of s (exponential function). More...
Float32  ( Float32 s)
Returns the constant 2 to the power of s (exponential function). More...
Float64  ( Float64 s)
Returns the constant 2 to the power of s (exponential function). More...
Float32  ( Float32 x)
A fast implementation of exp for floats. More...
Float32  ( Float32 i)
A fast implementation of log2(x) for floats. More...
Float32  ( Float32 b, Float32 e)
A fast implementation of pow(x,y) for floats. More...
Float32  ( Float32 x)
A fast implementation of pow(2,x) for floats. More...
Float32  ( Float32 i)
A fast implementation of sqrt(x) for floats. More...
Float32  ( Float32 s)
Returns the largest integral value that is not greater than s. More...
Float64  ( Float64 s)
Returns the largest integral value that is not greater than s. More...
Float32  ( Float32 a, Float32 b)
Returns a modulo b, in other words, the remainder of a/b. More...
Float64  ( Float64 a, Float64 b)
Returns a modulo b, in other words, the remainder of a/b. More...
Float32  ( Float32 s)
Returns the positive fractional part of s. More...
Float64  ( Float64 s)
Returns the positive fractional part of s. More...
MI_HOST_DEVICE_INLINE void  ( const Uint8 rgbe[4], Float32 color[3])
Decodes a color from RGBE representation. More...
MI_HOST_DEVICE_INLINE void  ( const Uint32 rgbe, Float32 color[3])
Decodes a color from RGBE representation. More...
template< class Vector, class UnaryFunctor>void  ( Vector& vec, UnaryFunctor f)
Generic transform function that applies a unary functor (in-place). More...
template< class Vector1, class Vector2, class BinaryFunctor>void  ( Vector1& vec1, const Vector2& vec2, BinaryFunctor f)
Generic transform function that applies a binary functor (in-place). More...
template< class Vector, class ResultVector, class UnaryFunctor>void  ( const Vector& vec, ResultVector& result, UnaryFunctor f)
Generic transform function that applies a unary functor (return value). More...
template< class Vector1, class Vector2, class ResultVector, class BinaryFunctor>void  ( const Vector1& vec1, const Vector2& vec2, ResultVector& result, BinaryFunctor f)
Generic transform function that applies a binary functor (return value). More...
template< class Scalar, class Vector, class ResultVector, class BinaryFunctor>void  ( const Scalar& s, const Vector& vec, ResultVector& result, BinaryFunctor f)
Generic transform function that applies a binary functor (return value, LHS scalar). More...
template< class Scalar, class Vector, class ResultVector, class BinaryFunctor>void  ( const Vector& vec, const Scalar& s, ResultVector& result, BinaryFunctor f)
Generic transform function that applies a binary functor (return value, RHS scalar). More...
bool   ( Float32 left, Float32 right, Float32 e)
Compares the two given values for equality within the given epsilon. More...
bool   ( Float64 left, Float64 right, Float64 e)
Compares the two given values for equality within the given epsilon. More...
template< class V>bool   ( const V& lhs, const V& rhs)
Returns true if vector lhs is elementwise equal to vector rhs, and false otherwise. More...
template< class V>bool   ( const V& lhs, const V& rhs)
Returns true if vector lhs is elementwise not equal to vector rhs, and false otherwise. More...
bool   ( const Float32 x)
Checks a single-precision floating point number for neither "not a number" nor "infinity". More...
bool   ( const Float64 x)
Checks a double-precision floating point number for neither "not a number" nor "infinity". More...
bool   ( const Float32 x)
Checks a single-precision floating point number for "infinity". More...
bool   ( const Float64 x)
Checks a double-precision floating point number for "infinity". More...
bool   ( const Float32 x)
Checks a single-precision floating point number for "not a number". More...
bool   ( const Float64 x)
Checks a double-precision floating point number for "not a number". More...
Uint32  ( Uint32 v)
Returns the number of leading zeros of v, 32-bit version. More...
Uint32  ( Uint64 v)
Returns the number of leading zeros of v, 64-bit version. More...
Float32  ( Float32 a)
Returns the Euclidean norm of the scalar a (its absolute value). More...
Float64  ( Float64 a)
Returns the Euclidean norm of the scalar a (its absolute value). More...
template< class V>V::​value_type  ( const V& v)
Returns the Euclidean norm of the vector v. More...
Float32  ( Float32 s1, Float32 s2, Float32 t)
Returns the linear interpolation between s1 and s2, i.e., it returns (1-t) * s1 + t * s2. More...
Float64  ( Float64 s1, Float64 s2, Float64 t)
Returns the linear interpolation between s1 and s2, i.e., it returns (1-t) * s1 + t * s2. More...
template< class V>Comparison_result  ( const V& lhs, const V& rhs)
Compares two vectors lexicographically. More...
template< class V>bool   ( const V& lhs, const V& rhs)
Returns true if vector lhs is lexicographically greater than vector rhs, and false otherwise. More...
template< class V>bool   ( const V& lhs, const V& rhs)
Returns true if vector lhs is lexicographically greater than or equal to vector rhs, and false otherwise. More...
template< class V>bool   ( const V& lhs, const V& rhs)
Returns true if vector lhs is lexicographically less than vector rhs, and false otherwise. More...
template< class V>bool   ( const V& lhs, const V& rhs)
Returns true if vector lhs is lexicographically less than or equal to vector rhs, and false otherwise. More...
Float32  ( Float32 s)
Returns the natural logarithm of s. More...
Float64  ( Float64 s)
Returns the natural logarithm of s. More...
Float32  ( Float32 s)
Returns the base 10 logarithm of s. More...
Float64  ( Float64 s)
Returns the base 10 logarithm of s. More...
Float32  ( Float32 s)
Returns the base 2 logarithm of s. More...
Float64  ( Float64 s)
Returns the base 2 logarithm of s. More...
Sint32  ( const Uint32 v)
Returns the integer log2 of v. More...
Sint32  ( const Uint64 v)
Returns the integer log2 of v. More...
Sint32  ( const Float32 v)
Returns the integer log2 of v. More...
Sint32  ( const Float64 v)
Returns the integer log2 of v. More...
template< typename Integer>Sint32  ( const Integer v)
Returns the integer log2 of v, i.e., rounded up to the next integer. More...
Float32  ( Float32 s, Float32& i)
Returns the fractional part of s and stores the integral part of s in i. More...
Float64  ( Float64 s, Float64& i)
Returns the fractional part of s and stores the integral part of s in i. More...
Uint32  ( Uint32 a, Uint32 b)
Returns a to the power of b. More...
Uint64  ( Uint64 a, Uint64 b)
Returns a to the power of b. More...
Sint32  ( Sint32 a, Sint32 b)
Returns a to the power of b. More...
Sint64  ( Sint64 a, Sint64 b)
Returns a to the power of b. More...
Float32  ( Float32 a, Float32 b)
Returns a to the power of b. More...
Float64  ( Float64 a, Float64 b)
Returns a to the power of b. More...
Float32  ( Float32 d)
Converts degrees d to radians. More...
Float64  ( Float64 d)
Converts degrees d to radians. More...
Float32  ( Float32 s)
Returns s rounded to the nearest integer value. More...
Float64  ( Float64 s)
Returns s rounded to the nearest integer value. More...
Float32  ( Float32 s)
Returns the reciprocal of the square root of s. More...
Float64  ( Float64 s)
Returns the reciprocal of the square root of s. More...
Float32  ( Float32 s)
Returns the value s clamped to the range [0,1]. More...
Float64  ( Float64 s)
Returns the value s clamped to the range [0,1]. More...
template< class V>void  ( V& v, const V& low, const V& high)
Bounds the value of vector v elementwise to the given low and high vector values. More...
Sint8  ( Sint8 s)
Returns -1 if s<0, 0 if s==0, and +1 if s>0. More...
Sint16  ( Sint16 s)
Returns -1 if s<0, 0 if s==0, and +1 if s>0. More...
Sint32  ( Sint32 s)
Returns -1 if s<0, 0 if s==0, and +1 if s>0. More...
Sint64  ( Sint64 s)
Returns -1 if s<0, 0 if s==0, and +1 if s>0. More...
Float32  ( Float32 s)
Returns -1 if s<0, 0 if s==0, and +1 if s>0. More...
Float64  ( Float64 s)
Returns -1 if s<0, 0 if s==0, and +1 if s>0. More...
bool   ( Sint8 s)
Returns true if s<0 and false if s>= 0. More...
bool   ( Sint16 s)
Returns true if s<0 and false if s>= 0. More...
bool   ( Sint32 s)
Returns true if s<0 and false if s>= 0. More...
bool   ( Sint64 s)
Returns true if s<0 and false if s>= 0. More...
bool   ( Float32 s)
Extracts the sign bit of a single-precision floating point number. More...
bool   ( Float64 s)
Extracts the sign bit of a double-precision floating point number. More...
Float32  ( Float32 a)
Returns the sine of a. The angle a is specified in radians. More...
Float64  ( Float64 a)
Returns the sine of a. The angle a is specified in radians. More...
void  ( Float32 a, Float32& s, Float32& c)
Computes the sine s and cosine c of angle a simultaneously. More...
void  ( Float64 a, Float64& s, Float64& c)
Computes the sine s and cosine c of angle a simultaneously. More...
Float32  ( Float32 a, Float32 b, Float32 x)
Returns 0 if x is less than a and 1 if x is greater than b. More...
Float64  ( Float64 a, Float64 b, Float64 x)
Returns 0 if x is less than a and 1 if x is greater than b. More...
Float32  ( Float32 s)
Returns the square root of s. More...
Float64  ( Float64 s)
Returns the square root of s. More...
template< class V>V::​value_type  ( const V& lhs, const V& rhs)
Returns the squared Euclidean distance from the vector lhs to the vector rhs. More...
template< class V>V::​value_type  ( const V& v)
Returns the squared Euclidean norm of the vector v. More...
Float32  ( Float32 a, Float32 x)
Returns 0 if x is less than a and 1 otherwise. More...
Float64  ( Float64 a, Float64 x)
Returns 0 if x is less than a and 1 otherwise. More...
Float32  ( Float32 a)
Returns the tangent of a. The angle a is specified in radians. More...
Float64  ( Float64 a)
Returns the tangent of a. The angle a is specified in radians. More...
MI_HOST_DEVICE_INLINE void  ( const Float32 color[3], Uint32& rgbe)
Encodes a color into RGBE representation. More...
MI_HOST_DEVICE_INLINE void  ( const Float32 color[3], Uint8 rgbe[4])
Encodes a color into RGBE representation. More...