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 1986, 2016 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>

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 MISTD::exp(s); }
inline Float64 
               exp( Float64 s) { return MISTD::exp(s); }

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


using mi::base::min;
using mi::base::max;
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 - MISTD::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 - MISTD::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 = Float32(base::binary_cast<int>(i)) * LOG_C - 127.f;
    const Float32 y = x - MISTD::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  = (Float32)(base::binary_cast<int>(b)) * LOG_C - 127.f;
    const Float32 y  = x - MISTD::floor(x);
    const Float32 fl = e * (x + (y - y*y) * 0.346607f);
    const Float32 y2 = fl - MISTD::floor(fl);
    const Float32 z  = max(
        fl*EXP_C + (Float32)(127.0*EXP_C) - (y2 - y2*y2) * (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 MISTD::acos(s); }
inline Float64 
               acos( Float64 s) { return MISTD::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 MISTD::asin(s); }
inline Float64 
               asin( Float64 s) { return MISTD::asin(s); }

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

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

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

inline  Uint8 
               clamp(  Uint8 s,  Uint8 low,  Uint8 high)
{
    return ( s < low) ? low : ( s > high) ? high : s;
}
inline Uint16 
               clamp( Uint16 s, Uint16 low, Uint16 high)
{
    return ( s < low) ? low : ( s > high) ? high : s;
}
inline Uint32 
               clamp( Uint32 s, Uint32 low, Uint32 high)
{
    return ( s < low) ? low : ( s > high) ? high : s;
}
inline Uint64 
               clamp( Uint64 s, Uint64 low, Uint64 high)
{
    return ( s < low) ? low : ( s > high) ? high : s;
}
inline  Sint8 
               clamp(  Sint8 s,  Sint8 low,  Sint8 high)
{
    return ( s < low) ? low : ( s > high) ? high : s;
}
inline Sint16 
               clamp( Sint16 s, Sint16 low, Sint16 high)
{
    return ( s < low) ? low : ( s > high) ? high : s;
}
inline Sint32 
               clamp( Sint32 s, Sint32 low, Sint32 high)
{
    return ( s < low) ? low : ( s > high) ? high : s;
}
inline Sint64 
               clamp( Sint64 s, Sint64 low, Sint64 high)
{
    return ( s < low) ? low : ( s > high) ? high : s;
}
inline Float32 
               clamp( Float32 s, Float32 low, Float32 high)
{
    return ( s < low) ? low : ( s > high) ? high : s;
}
inline Float64 
               clamp( Float64 s, Float64 low, Float64 high)
{
    return ( s < low) ? low : ( s > high) ? high : s;
}

inline Float32 
               cos( Float32 a) { return MISTD::cos(a); }
inline Float64 
               cos( Float64 a) { return MISTD::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 MISTD::exp(s * 0.69314718055994530941723212145818 /* log(2) */ );
}

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

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

inline Float32 
               frac( Float32 s)
{
    Float32 dummy;
    if( s >= 0.0f)
        return MISTD::modf( s, &dummy);
    else
        return 1.0f + MISTD::modf( s, &dummy);
}
inline Float64 
               frac( Float64 s)
{
    Float64 dummy;
    if( s >= 0.0f)
        return MISTD::modf( s, &dummy);
    else
        return 1.0f + MISTD::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 Float32 
               log2 
               MI_PREVENT_MACRO_EXPAND ( Float32 s)
{ return MISTD::log(s) * 1.4426950408889634073599246810019f /* log(2) */; }
inline Float64 
               log2 
               MI_PREVENT_MACRO_EXPAND ( Float64 s)
{ return MISTD::log(s) * 1.4426950408889634073599246810019 /* log(2) */; }

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

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 
               modf( Float32 s, Float32& i) { return MISTD::modf( s, &i); }
inline Float64 
               modf( Float64 s, Float64& i) { return MISTD::modf( s, &i); }

inline Uint32  
               pow( Uint32  a, Uint32  b) { return Uint32(MISTD::pow(double(a), int(b))); }
inline Uint64  
               pow( Uint64  a, Uint64  b) { return Uint64(MISTD::pow(double(a), int(b))); }
inline Sint32  
               pow( Sint32  a, Sint32  b) { return Sint32(MISTD::pow(double(a), int(b))); }
inline Sint64  
               pow( Sint64  a, Sint64  b) { return Sint64(MISTD::pow(double(a), int(b))); }
inline Float32 
               pow( Float32 a, Float32 b) { return MISTD::pow( a, b); }
inline Float64 
               pow( Float64 a, Float64 b) { return MISTD::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 MISTD::floor(s + 0.5f); }
inline Float64 
               round( Float64 s) { return MISTD::floor(s + 0.5); }

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

inline Float32 
               saturate( Float32 s) { return (s < 0.f) ? 0.f : (s > 1.f) ? 1.f : s;}
inline Float64 
               saturate( Float64 s) { return (s < 0.) ? 0. : (s > 1.) ? 1. : s;}

inline Sint8   
               sign( Sint8   s) { int r = (s < 0 )  ? -1 : (s > 0)   ? 1   : 0; return (Sint8)  r; }
inline Sint16  
               sign( Sint16  s) { int r = (s < 0 )  ? -1 : (s > 0)   ? 1   : 0; return (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;
}

inline bool isnan 
               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 isnan 
               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
}

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
}

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
}

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

inline void sincos( Float32 a, Float32& s, Float32& c)
{
    s = MISTD::sin(a);
    c = MISTD::cos(a);
}
inline void sincos( Float64 a, Float64& s, Float64& c)
{
    s = MISTD::sin(a);
    c = MISTD::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 MISTD::sqrt(s); }
inline Float64 
               sqrt( Float64 s) { return MISTD::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 MISTD::tan(a); }
inline Float64 
               tan( Float64 a) { return MISTD::tan(a); }


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

    const Float32 max = mi::base::max( mi::base::max( c[0], c[1]), c[2]);

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

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

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

    const Float32 max = mi::base::max( mi::base::max( c[0], c[1]), c[2]);

    // should actually be -126 or even -128, but avoid precision problems / denormalized numbers
    if( max <= 7.5231631727e-37f) // ~2^(-120)
        rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
    else if( max >= 1.7014118346046923173168730371588e+38f) // 2^127
        rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 255;
    else {
        const Uint32  e = base::binary_cast<Uint32>( max) & 0x7F800000u;
        const Float32 v = base::binary_cast<Float32>( 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);
    }
}

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 = ((Uint32) rgbe[3] << 23) - 0x800000u;
    const Float32 v = base::binary_cast<Float32>( e);
    const Float32 c = (Float32)(1.0 - 0.5/256.0) * v;

    color[0] = base::binary_cast<Float32>( e | ((Uint32) rgbe[0] << 15)) - c;
    color[1] = base::binary_cast<Float32>( e | ((Uint32) rgbe[1] << 15)) - c;
    color[2] = base::binary_cast<Float32>( e | ((Uint32) rgbe[2] << 15)) - c;
}

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 = base::binary_cast<Float32>( e);
    const Float32 c = (Float32)(1.0 - 0.5/256.0) * v;

    color[0] = base::binary_cast<Float32>( e | ((rgbe << 15) & 0x7F8000u)) - c;
    color[1] = base::binary_cast<Float32>( e | ((rgbe <<  7) & 0x7F8000u)) - c;
    color[2] = base::binary_cast<Float32>( 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...
void  ( const Uint8 rgbe[4], Float32 color[3])
Decodes a color from RGBE representation. More...
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...
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...
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...
void  ( const Float32 color[3], Uint32& rgbe)
Encodes a color into RGBE representation. More...
void  ( const Float32 color[3], Uint8 rgbe[4])
Encodes a color into RGBE representation. More...