NVIDIA Iray API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
function.h
Go to the documentation of this file.
1 //*****************************************************************************
2 // Copyright 1986, 2014 NVIDIA Corporation. All rights reserved.
3 //*****************************************************************************
9 //*****************************************************************************
10 
11 #ifndef MI_MATH_FUNCTION_H
12 #define MI_MATH_FUNCTION_H
13 
14 #include <mi/base/assert.h>
15 #include <mi/base/types.h>
16 
17 namespace mi {
18 
19 namespace math {
20 
52 namespace functor {
68 struct Operator_equal_equal {
71  template <typename T1, typename T2>
72  inline bool operator()( const T1& t1, const T2& t2) const { return t1 == t2; }
73 };
74 
78  template <typename T1, typename T2>
79  inline bool operator()( const T1& t1, const T2& t2) const { return t1 != t2; }
80 };
81 
83 struct Operator_less {
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 T>
114  inline T operator()( const T& t1, const T& t2) const { return t1 + t2; }
115 };
116 
120  template <typename T>
121  inline T operator()( const T& t) const { return - t; }
123  template <typename T>
124  inline T operator()( const T& t1, const T& t2) const { return t1 - t2; }
125 };
126 
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 bool 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 
156 struct Operator_xor {
158  template <typename T>
159  inline bool operator()( const T& t1, const T& t2) const { return t1 ^ t2; }
160 };
161 
163 struct Operator_not {
165  template <typename T>
166  inline bool operator()( const T& t) const { return ! t; }
167 };
168 
172  template <typename T>
173  inline T operator()( 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  // end group mi_math_functor
198 
199 } // namespace functor
200 
202 namespace general {
219 template <class Vector, class ResultVector, class UnaryFunctor>
227 inline void transform( const Vector& vec, ResultVector& result, UnaryFunctor f)
228 {
229  mi_static_assert( Vector::SIZE == ResultVector::SIZE);
230  for( Size i = 0; i != Vector::SIZE; ++i)
231  result.set( i, f( vec.get(i)));
232 }
233 
242 template <class Vector1, class Vector2, class ResultVector, class BinaryFunctor>
243 inline void transform(
244  const Vector1& vec1, const Vector2& vec2, ResultVector& result, BinaryFunctor f)
245 {
246  mi_static_assert( Vector1::SIZE == Vector2::SIZE);
247  mi_static_assert( Vector1::SIZE == ResultVector::SIZE);
248  for( Size i = 0; i != Vector1::SIZE; ++i)
249  result.set( i, f( vec1.get(i), vec2.get(i)));
250 }
251 
261 template <class Scalar, class Vector, class ResultVector, class BinaryFunctor>
263  const Scalar& s, const Vector& vec, ResultVector& result, BinaryFunctor f)
264 {
265  mi_static_assert( Vector::SIZE == ResultVector::SIZE);
266  for( Size i = 0; i != Vector::SIZE; ++i)
267  result.set( i, f( s, vec.get(i)));
268 }
269 
279 template <class Scalar, class Vector, class ResultVector, class BinaryFunctor>
281  const Vector& vec, const Scalar& s, ResultVector& result, BinaryFunctor f)
282 {
283  mi_static_assert( Vector::SIZE == ResultVector::SIZE);
284  for( Size i = 0; i != Vector::SIZE; ++i)
285  result.set( i, f( vec.get(i), s));
286 }
287 
294 template <class Vector, class UnaryFunctor>
295 inline void for_each( Vector& vec, UnaryFunctor f)
296 {
297  for( Size i = 0; i != Vector::SIZE; ++i)
298  f( vec.begin()[i]);
299 }
300 
308 template <class Vector1, class Vector2, class BinaryFunctor>
309 inline void for_each( Vector1& vec1, const Vector2& vec2, BinaryFunctor f)
310 {
311  mi_static_assert( Vector1::SIZE == Vector2::SIZE);
312  for( Size i = 0; i != Vector1::SIZE; ++i)
313  f( vec1.begin()[i], vec2.begin()[i]);
314 }
315  // end group mi_math_functor
317 
318 } // namespace general
319 
321 inline Float32 exp( Float32 s) { return MISTD::exp(s); }
323 inline Float64 exp( Float64 s) { return MISTD::exp(s); }
324 
326 inline Float32 log( Float32 s) { return MISTD::log(s); }
328 inline Float64 log( Float64 s) { return MISTD::log(s); }
329 
330 
331 using mi::base::min;
332 using mi::base::max;
333 using mi::base::abs;
334 
335 
347 inline Float32 fast_sqrt( Float32 i)
349 {
350  int tmp = base::binary_cast<int>(i);
351  tmp -= 1 << 23; // Remove last bit to not let it go to mantissa
352  // tmp is now an approximation to logbase2(i)
353  tmp = tmp >> 1; // Divide by 2
354  tmp += 1 << 29; // Add 64 to the exponent: (e+127)/2 = (e/2)+63
355  // that represents (e/2)-64 but we want e/2
356  return base::binary_cast<Float32>(tmp);
357 }
358 
361 {
362  const Float32 EXP_C = 8388608.0f; // 2^23
363  const Float32 LOG_2_E = 1.4426950408889634073599246810019f; // 1 / log(2)
364 
365  x *= LOG_2_E;
366  Float32 y = x - MISTD::floor(x);
367  y = (y - y*y) * 0.33971f;
368  const Float32 z = max MI_PREVENT_MACRO_EXPAND ((x + 127.0f - y) * EXP_C, 0.f);
369  return base::binary_cast<Float32>(static_cast<int>(z));
370 }
371 
374 {
375  const Float32 EXP_C = 8388608.0f; // 2^23
376 
377  Float32 y = x - MISTD::floor(x);
378  y = (y - y*y) * 0.33971f;
379  const Float32 z = max MI_PREVENT_MACRO_EXPAND ((x + 127.0f - y) * EXP_C, 0.f);
380  return base::binary_cast<Float32>(static_cast<int>(z));
381 }
382 
385 {
386  const Float32 LOG_C = 0.00000011920928955078125f; // 2^(-23)
387 
388  const Float32 x = Float32(base::binary_cast<int>(i)) * LOG_C - 127.f;
389  const Float32 y = x - MISTD::floor(x);
390  return x + (y - y*y) * 0.346607f;
391 }
392 
395  Float32 b,
396  Float32 e)
397 {
398  if( b == 0.0f)
399  return 0.0f;
400 
401  const Float32 LOG_C = 0.00000011920928955078125f; // 2^(-23)
402  const Float32 EXP_C = 8388608.0f; // 2^23
403 
404  const Float32 x = (Float32)(base::binary_cast<int>(b)) * LOG_C - 127.f;
405  const Float32 y = x - MISTD::floor(x);
406  const Float32 fl = e * (x + (y - y*y) * 0.346607f);
407  const Float32 y2 = fl - MISTD::floor(fl);
408  const Float32 z = max(
409  fl*EXP_C + (Float32)(127.0*EXP_C) - (y2 - y2*y2) * (Float32)(0.33971*EXP_C), 0.f);
410 
411  return base::binary_cast<Float32>(static_cast<int>(z));
412 }
413  // end group mi_math_approx_function
415 
416 
418 inline Float32 acos( Float32 s) { return MISTD::acos(s); }
420 inline Float64 acos( Float64 s) { return MISTD::acos(s); }
421 
423 inline bool all( Uint8 v) { return Uint8 (0) != v; }
425 inline bool all( Uint16 v) { return Uint16 (0) != v; }
427 inline bool all( Uint32 v) { return Uint32 (0) != v; }
429 inline bool all( Uint64 v) { return Uint64 (0) != v; }
431 inline bool all( Sint8 v) { return Sint8 (0) != v; }
433 inline bool all( Sint16 v) { return Sint16 (0) != v; }
435 inline bool all( Sint32 v) { return Sint32 (0) != v; }
437 inline bool all( Sint64 v) { return Sint64 (0) != v; }
439 inline bool all( Float32 v) { return Float32(0) != v; }
441 inline bool all( Float64 v) { return Float64(0) != v; }
442 
444 inline bool any( Uint8 v) { return Uint8 (0) != v; } //-V524 PVS
446 inline bool any( Uint16 v) { return Uint16 (0) != v; } //-V524 PVS
448 inline bool any( Uint32 v) { return Uint32 (0) != v; } //-V524 PVS
450 inline bool any( Uint64 v) { return Uint64 (0) != v; } //-V524 PVS
452 inline bool any( Sint8 v) { return Sint8 (0) != v; } //-V524 PVS
454 inline bool any( Sint16 v) { return Sint16 (0) != v; } //-V524 PVS
456 inline bool any( Sint32 v) { return Sint32 (0) != v; } //-V524 PVS
458 inline bool any( Sint64 v) { return Sint64 (0) != v; } //-V524 PVS
460 inline bool any( Float32 v) { return Float32(0) != v; } //-V524 PVS
462 inline bool any( Float64 v) { return Float64(0) != v; } //-V524 PVS
463 
465 inline Float32 asin( Float32 s) { return MISTD::asin(s); }
467 inline Float64 asin( Float64 s) { return MISTD::asin(s); }
468 
470 inline Float32 atan( Float32 s) { return MISTD::atan(s); }
472 inline Float64 atan( Float64 s) { return MISTD::atan(s); }
473 
477 inline Float32 atan2( Float32 s, Float32 t) { return MISTD::atan2(s,t); }
481 inline Float64 atan2( Float64 s, Float64 t) { return MISTD::atan2(s,t); }
482 
484 inline Float32 ceil( Float32 s) { return MISTD::ceil(s); }
486 inline Float64 ceil( Float64 s) { return MISTD::ceil(s); }
487 
490 inline Uint8 clamp( Uint8 s, Uint8 low, Uint8 high)
491 {
492  return ( s < low) ? low : ( s > high) ? high : s;
493 }
496 inline Uint16 clamp( Uint16 s, Uint16 low, Uint16 high)
497 {
498  return ( s < low) ? low : ( s > high) ? high : s;
499 }
502 inline Uint32 clamp( Uint32 s, Uint32 low, Uint32 high)
503 {
504  return ( s < low) ? low : ( s > high) ? high : s;
505 }
508 inline Uint64 clamp( Uint64 s, Uint64 low, Uint64 high)
509 {
510  return ( s < low) ? low : ( s > high) ? high : s;
511 }
514 inline Sint8 clamp( Sint8 s, Sint8 low, Sint8 high)
515 {
516  return ( s < low) ? low : ( s > high) ? high : s;
517 }
520 inline Sint16 clamp( Sint16 s, Sint16 low, Sint16 high)
521 {
522  return ( s < low) ? low : ( s > high) ? high : s;
523 }
526 inline Sint32 clamp( Sint32 s, Sint32 low, Sint32 high)
527 {
528  return ( s < low) ? low : ( s > high) ? high : s;
529 }
532 inline Sint64 clamp( Sint64 s, Sint64 low, Sint64 high)
533 {
534  return ( s < low) ? low : ( s > high) ? high : s;
535 }
538 inline Float32 clamp( Float32 s, Float32 low, Float32 high)
539 {
540  return ( s < low) ? low : ( s > high) ? high : s;
541 }
544 inline Float64 clamp( Float64 s, Float64 low, Float64 high)
545 {
546  return ( s < low) ? low : ( s > high) ? high : s;
547 }
548 
550 inline Float32 cos( Float32 a) { return MISTD::cos(a); }
552 inline Float64 cos( Float64 a) { return MISTD::cos(a); }
553 
555 inline Float32 degrees( Float32 r) { return r * Float32(180.0/MI_PI); }
557 inline Float64 degrees( Float64 r) { return r * Float64(180.0/MI_PI); }
558 
560 inline Float32 exp2( Float32 s) { return fast_pow2(s); }
562 inline Float64 exp2( Float64 s)
563 {
564  return MISTD::exp(s * 0.69314718055994530941723212145818 /* log(2) */ );
565 }
566 
568 inline Float32 floor( Float32 s) { return MISTD::floor(s); }
570 inline Float64 floor( Float64 s) { return MISTD::floor(s); }
571 
575 inline Float32 fmod( Float32 a, Float32 b) { return MISTD::fmod(a,b); }
579 inline Float64 fmod( Float64 a, Float64 b) { return MISTD::fmod(a,b); }
580 
582 inline Float32 frac( Float32 s)
583 {
584  Float32 dummy;
585  if( s >= 0.0f)
586  return MISTD::modf( s, &dummy);
587  else
588  return 1.0f + MISTD::modf( s, &dummy);
589 }
591 inline Float64 frac( Float64 s)
592 {
593  Float64 dummy;
594  if( s >= 0.0f)
595  return MISTD::modf( s, &dummy);
596  else
597  return 1.0f + MISTD::modf( s, &dummy);
598 }
599 
601 inline bool is_approx_equal(
602  Float32 left,
603  Float32 right,
604  Float32 e)
605 {
606  return abs( left - right ) <= e;
607 }
608 
610 inline bool is_approx_equal(
611  Float64 left,
612  Float64 right,
613  Float64 e)
614 {
615  return abs( left - right ) <= e;
616 }
617 
618 
621 { return MISTD::log(s) * 1.4426950408889634073599246810019f /* log(2) */; }
624 { return MISTD::log(s) * 1.4426950408889634073599246810019 /* log(2) */; }
625 
627 inline Float32 log10( Float32 s) { return MISTD::log10(s); }
629 inline Float64 log10( Float64 s) { return MISTD::log10(s); }
630 
633 inline Float32 lerp(
634  Float32 s1,
635  Float32 s2,
636  Float32 t)
637 {
638  return s1 * (Float32(1)-t) + s2 * t;
639 }
640 
643 inline Float64 lerp(
644  Float64 s1,
645  Float64 s2,
646  Float64 t)
647 {
648  return s1 * (Float64(1)-t) + s2 * t;
649 }
650 
654 inline Float32 modf( Float32 s, Float32& i) { return MISTD::modf( s, &i); }
658 inline Float64 modf( Float64 s, Float64& i) { return MISTD::modf( s, &i); }
659 
661 inline Uint32 pow( Uint32 a, Uint32 b) { return Uint32(MISTD::pow(double(a), int(b))); }
663 inline Uint64 pow( Uint64 a, Uint64 b) { return Uint64(MISTD::pow(double(a), int(b))); }
665 inline Sint32 pow( Sint32 a, Sint32 b) { return Sint32(MISTD::pow(double(a), int(b))); }
667 inline Sint64 pow( Sint64 a, Sint64 b) { return Uint64(MISTD::pow(double(a), int(b))); }
669 inline Float32 pow( Float32 a, Float32 b) { return MISTD::pow( a, b); }
671 inline Float64 pow( Float64 a, Float64 b) { return MISTD::pow( a, b); }
672 
674 inline Float32 radians( Float32 d) { return d * Float32(MI_PI/180.0); }
676 inline Float64 radians( Float64 d) { return d * Float64(MI_PI/180.0); }
677 
679 inline Float32 round( Float32 s) { return MISTD::floor(s + 0.5f); }
681 inline Float64 round( Float64 s) { return MISTD::floor(s + 0.5); }
682 
684 inline Float32 rsqrt( Float32 s) { return 1.0f / MISTD::sqrt(s); }
686 inline Float64 rsqrt( Float64 s) { return 1.0 / MISTD::sqrt(s); }
687 
689 inline Float32 saturate( Float32 s) { return (s < 0.f) ? 0.f : (s > 1.f) ? 1.f : s;}
691 inline Float64 saturate( Float64 s) { return (s < 0.) ? 0. : (s > 1.) ? 1. : s;}
692 
694 inline Sint8 sign( Sint8 s) { return (s < 0) ? -1 : (s > 0) ? 1 : 0;}
696 inline Sint16 sign( Sint16 s) { return (s < 0) ? -1 : (s > 0) ? 1 : 0;}
698 inline Sint32 sign( Sint32 s) { return (s < 0) ? -1 : (s > 0) ? 1 : 0;}
700 inline Sint64 sign( Sint64 s) { return (s < 0) ? -1 : (s > 0) ? 1 : 0;}
702 inline Float32 sign( Float32 s) { return (s < 0.f) ? -1.f : (s > 0.f) ? 1.f : 0.f;}
704 inline Float64 sign( Float64 s) { return (s < 0.) ? -1. : (s > 0.) ? 1. : 0.;}
705 
707 inline bool sign_bit( Sint8 s) { return s < 0; }
709 inline bool sign_bit( Sint16 s) { return s < 0; }
711 inline bool sign_bit( Sint32 s) { return s < 0; }
713 inline bool sign_bit( Sint64 s) { return s < 0; }
714 
719 inline bool sign_bit( Float32 s)
720 {
721  return (base::binary_cast<Uint32>(s) & (1U << 31)) != 0U;
722 }
723 
728 inline bool sign_bit( Float64 s)
729 {
730  return (base::binary_cast<Uint64>(s) & (1ULL << 63)) != 0ULL;
731 }
732 
736 inline bool isnan MI_PREVENT_MACRO_EXPAND (const Float32 x)
737 {
738  const Uint32 exponent_mask = 0x7F800000; // 8 bit exponent
739  const Uint32 fraction_mask = 0x7FFFFF; // 23 bit fraction
740 
741  // interpret as Uint32 value
742  const Uint32 f = base::binary_cast<Uint32>(x);
743 
744  // check bit pattern
745  return ((f & exponent_mask) == exponent_mask) && // exp == 2^8 - 1
746  ((f & fraction_mask) != 0); // fraction != 0
747 }
748 
752 inline bool isnan MI_PREVENT_MACRO_EXPAND (const Float64 x)
753 {
754  const Uint64 exponent_mask = 0x7FF0000000000000ULL; // 11 bit exponent
755  const Uint64 fraction_mask = 0xFFFFFFFFFFFFFULL; // 52 bit fraction
756 
757  // interpret as Uint64 value
758  const Uint64 f = base::binary_cast<Uint64>(x);
759 
760  // check bit pattern
761  return ((f & exponent_mask) == exponent_mask) && // exp == 2^11 - 1
762  ((f & fraction_mask) != 0); // fraction != 0
763 }
764 
769 {
770  const Uint32 exponent_mask = 0x7F800000; // 8 bit exponent
771  const Uint32 fraction_mask = 0x7FFFFF; // 23 bit fraction
772 
773  // interpret as Uint32 value
774  const Uint32 f = base::binary_cast<Uint32>(x);
775 
776  // check bit pattern
777  return ((f & exponent_mask) == exponent_mask) && // exp == 2^8 - 1
778  ((f & fraction_mask) == 0); // fraction == 0
779 }
780 
785 {
786  const Uint64 exponent_mask = 0x7FF0000000000000ULL; // 11 bit exponent
787  const Uint64 fraction_mask = 0xFFFFFFFFFFFFFULL; // 52 bit fraction
788 
789  // interpret as Uint64 value
790  const Uint64 f = base::binary_cast<Uint64>(x);
791 
792  // check bit pattern
793  return ((f & exponent_mask) == exponent_mask) && // exp == 2^11 - 1
794  ((f & fraction_mask) == 0); // fraction == 0
795 }
796 
803 {
804  const Uint32 exponent_mask = 0x7F800000; // 8 bit exponent
805 
806  // interpret as Uint32 value
807  const Uint32 f = base::binary_cast<Uint32>(x);
808 
809  // check exponent bits
810  return ((f & exponent_mask) != exponent_mask); // exp != 2^8 - 1
811 }
812 
819 {
820  const Uint64 exponent_mask = 0x7FF0000000000000ULL; // 11 bit exponent
821 
822  // interpret as Uint64 value
823  const Uint64 f = base::binary_cast<Uint64>(x);
824 
825  // check exponent bits
826  return ((f & exponent_mask) != exponent_mask); // exp != 2^11 - 1
827 }
828 
830 inline Float32 sin( Float32 a) { return MISTD::sin(a); }
832 inline Float64 sin( Float64 a) { return MISTD::sin(a); }
833 
837 inline void sincos( Float32 a, Float32& s, Float32& c)
838 {
839  s = MISTD::sin(a);
840  c = MISTD::cos(a);
841 }
845 inline void sincos( Float64 a, Float64& s, Float64& c)
846 {
847  s = MISTD::sin(a);
848  c = MISTD::cos(a);
849 }
850 
856 {
857  if(x < a)
858  return 0.0f;
859  if(b < x)
860  return 1.0f;
861  Float32 t = (x - a) / (b - a);
862  return t * t * (3.0f - 2.0f * t);
863 }
869 {
870  if(x < a)
871  return 0.0;
872  if(b < x)
873  return 1.0;
874  Float64 t = (x - a) / (b - a);
875  return t * t * (3.0 - 2.0 * t);
876 }
877 
879 inline Float32 sqrt( Float32 s) { return MISTD::sqrt(s); }
881 inline Float64 sqrt( Float64 s) { return MISTD::sqrt(s); }
882 
884 inline Float32 step( Float32 a, Float32 x) { return (x < a) ? 0.0f : 1.0f; }
886 inline Float64 step( Float64 a, Float64 x) { return (x < a) ? 0.0 : 1.0; }
887 
889 inline Float32 tan( Float32 a) { return MISTD::tan(a); }
891 inline Float64 tan( Float64 a) { return MISTD::tan(a); }
892 
893 
895 inline void to_rgbe( const Float32 color[3], Uint32& rgbe)
896 {
897  Float32 c[3];
898  c[0] = mi::base::max( color[0], 0.0f);
899  c[1] = mi::base::max( color[1], 0.0f);
900  c[2] = mi::base::max( color[2], 0.0f);
901 
902  const Float32 max = mi::base::max( mi::base::max( c[0], c[1]), c[2]);
903 
904  // should actually be -126 or even -128, but avoid precision problems / denormalized numbers
905  if( max <= 7.5231631727e-37f) // ~2^(-120)
906  rgbe = 0;
907  else if( max >= 1.7014118346046923173168730371588e+38f) // 2^127
908  rgbe = 0xFFFFFFFFu;
909  else {
910  const Uint32 e = base::binary_cast<Uint32>( max) & 0x7F800000u;
911  const Float32 v = base::binary_cast<Float32>( 0x82800000u - e);
912 
913  rgbe = Uint32( c[0] * v)
914  | (Uint32( c[1] * v) << 8)
915  | (Uint32( c[2] * v) << 16)
916  | (e * 2 + (2 << 24));
917  }
918 }
919 
921 inline void to_rgbe( const Float32 color[3], Uint8 rgbe[4])
922 {
923  Float32 c[3];
924  c[0] = mi::base::max( color[0], 0.0f);
925  c[1] = mi::base::max( color[1], 0.0f);
926  c[2] = mi::base::max( color[2], 0.0f);
927 
928  const Float32 max = mi::base::max( mi::base::max( c[0], c[1]), c[2]);
929 
930  // should actually be -126 or even -128, but avoid precision problems / denormalized numbers
931  if( max <= 7.5231631727e-37f) // ~2^(-120)
932  rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0;
933  else if( max >= 1.7014118346046923173168730371588e+38f) // 2^127
934  rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 255;
935  else {
936  const Uint32 e = base::binary_cast<Uint32>( max) & 0x7F800000u;
937  const Float32 v = base::binary_cast<Float32>( 0x82800000u - e);
938 
939  rgbe[0] = Uint8( c[0] * v);
940  rgbe[1] = Uint8( c[1] * v);
941  rgbe[2] = Uint8( c[2] * v);
942  rgbe[3] = Uint8( (e >> 23) + 2);
943  }
944 }
945 
947 inline void from_rgbe( const Uint8 rgbe[4], Float32 color[3])
948 {
949  if( rgbe[3] == 0) {
950  color[0] = color[1] = color[2] = 0.0f;
951  return;
952  }
953 
954  const Uint32 e = ((Uint32) rgbe[3] << 23) - 0x800000u;
955  const Float32 v = base::binary_cast<Float32>( e);
956  const Float32 c = (Float32)(1.0 - 0.5/256.0) * v;
957 
958  color[0] = base::binary_cast<Float32>( e | ((Uint32) rgbe[0] << 15)) - c;
959  color[1] = base::binary_cast<Float32>( e | ((Uint32) rgbe[1] << 15)) - c;
960  color[2] = base::binary_cast<Float32>( e | ((Uint32) rgbe[2] << 15)) - c;
961 }
962 
964 inline void from_rgbe( const Uint32 rgbe, Float32 color[3])
965 {
966  const Uint32 rgbe3 = rgbe & 0xFF000000u;
967  if( rgbe3 == 0) {
968  color[0] = color[1] = color[2] = 0.0f;
969  return;
970  }
971 
972  const Uint32 e = (rgbe3 >> 1) - 0x800000u;
973  const Float32 v = base::binary_cast<Float32>( e);
974  const Float32 c = (Float32)(1.0 - 0.5/256.0) * v;
975 
976  color[0] = base::binary_cast<Float32>( e | ((rgbe << 15) & 0x7F8000u)) - c;
977  color[1] = base::binary_cast<Float32>( e | ((rgbe << 7) & 0x7F8000u)) - c;
978  color[2] = base::binary_cast<Float32>( e | ((rgbe >> 1) & 0x7F8000u)) - c;
979 }
980 
981 
982 //------ Generic Vector Algorithms --------------------------------------------
983 
984 // overloads for 1D vectors (scalars)
985 
987 inline Sint32 dot( Sint32 a, Sint32 b) { return a * b; }
989 inline Float32 dot( Float32 a, Float32 b) { return a * b; }
991 inline Float64 dot( Float64 a, Float64 b) { return a * b; }
992 
994 template <class V>
995 inline typename V::value_type dot( const V& lhs, const V& rhs)
996 {
997  typename V::value_type v(0);
998  for( Size i(0u); i < V::SIZE; ++i)
999  v += lhs.get(i) * rhs.get(i);
1000  return v;
1001 }
1002 
1004 template <class V>
1005 inline typename V::value_type square_length( const V& v)
1006 {
1007  return dot( v, v);
1008 }
1009 
1010 // base case for scalars
1011 
1013 inline Float32 length( Float32 a) { return abs(a); }
1015 inline Float64 length( Float64 a) { return abs(a); }
1016 
1017 
1021 template <class V>
1022 inline typename V::value_type length( const V& v)
1023 {
1024  return sqrt( square_length(v));
1025 }
1026 
1028 template <class V>
1029 inline typename V::value_type square_euclidean_distance( const V& lhs, const V& rhs)
1030 {
1031  return square_length( lhs - rhs);
1032 }
1033 
1037 template <class V>
1038 inline typename V::value_type euclidean_distance(
1039  const V& lhs, const V& rhs)
1040 {
1041  return length( lhs - rhs);
1042 }
1043 
1045 template <class V>
1046 inline void set_bounds( V& v, const V& low, const V& high)
1047 {
1048  for( Size i(0u); i < V::SIZE; ++i)
1049  v[i] = min MI_PREVENT_MACRO_EXPAND (
1050  max MI_PREVENT_MACRO_EXPAND (v.get(i), low.get(i)), high.get(i));
1051 }
1052 
1056 template <class V>
1057 inline bool is_equal( const V& lhs, const V& rhs)
1058 {
1059  for( Size i(0u); i < V::SIZE; ++i)
1060  if( lhs.get(i) != rhs.get(i))
1061  return false;
1062  return true;
1063 }
1064 
1065 
1073 template <class V>
1074 inline Comparison_result lexicographically_compare( const V& lhs, const V& rhs)
1075 {
1076  for( Size i(0u); i < V::SIZE; ++i) {
1077  Comparison_result result = three_valued_compare( lhs.get(i), rhs.get(i));
1078  if( result != EQUAL)
1079  return result;
1080  }
1081  return EQUAL;
1082 }
1083 
1088 template <class V>
1089 inline bool lexicographically_less( const V& lhs, const V& rhs)
1090 {
1091  return lexicographically_compare( lhs, rhs) == LESS;
1092 }
1093  // end group mi_math_function
1095 
1096 } // namespace math
1097 
1098 } // namespace mi
1099 
1100 #endif // MI_MATH_FUNCTION_H