MDL SDK API nvidia_logo_transpbg.gif Up
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
spectrum.h
Go to the documentation of this file.
1 /***************************************************************************************************
2  * Copyright 2022 NVIDIA Corporation. All rights reserved.
3  **************************************************************************************************/
8 
9 #ifndef MI_MATH_SPECTRUM_H
10 #define MI_MATH_SPECTRUM_H
11 
12 #include <mi/base/types.h>
13 #include <mi/math/assert.h>
14 #include <mi/math/function.h>
15 #include <mi/math/vector.h>
16 #include <mi/math/color.h>
17 
18 namespace mi {
19 
20 namespace math {
21 
33 //------ Spectrum Class ---------------------------------------------------------
34 
52 class Spectrum : public Spectrum_struct
53 {
54 public:
57  typedef Float32 value_type;
58  typedef Size size_type;
60  typedef Float32 * pointer;
61  typedef const Float32 * const_pointer;
62  typedef Float32 & reference;
63  typedef const Float32 & const_reference;
64 
65  static const Size SIZE = 3;
66 
68  static inline Size size() { return SIZE; }
69 
71  static inline Size max_size() { return SIZE; }
72 
74  inline Float32* begin() { return &c[0]; }
75 
77  inline const Float32* begin() const { return &c[0]; }
78 
82  inline Float32* end() { return begin() + SIZE; }
83 
87  inline const Float32* end() const { return begin() + SIZE; }
88 
90  inline Spectrum()
91  {
92 #if defined(DEBUG) || (defined(_MSC_VER) && _MSC_VER <= 1310)
93  // In debug mode, default-constructed spectra are initialized with signaling NaNs or, if not
94  // applicable, with a maximum value to increase the chances of diagnosing incorrect use of
95  // an uninitialized spectrum.
96  //
97  // When compiling with Visual C++ 7.1 or earlier, this code is enabled in all variants to
98  // work around a very obscure compiler bug that causes the compiler to crash.
99  typedef mi::base::numeric_traits<Float32> Traits;
100  Float32 v = (Traits::has_signaling_NaN)
101  ? Traits::signaling_NaN() : Traits::max MI_PREVENT_MACRO_EXPAND ();
102  for( Size i = 0; i < SIZE; ++i)
103  c[i] = v;
104 #endif
105  }
106 
107 #if (__cplusplus >= 201103L)
108  Spectrum( const Spectrum& s ) = default;
110 #endif
111 
113  inline Spectrum( const Spectrum_struct& s)
114  {
115  for( Size i = 0; i < SIZE; ++i)
116  c[i] = s.c[i];
117  }
118 
119 
121  inline explicit Spectrum( const Float32 s)
122  {
123  for( Size i = 0; i < SIZE; ++i)
124  c[i] = s;
125  }
126 
128  inline Spectrum( Float32 nr, Float32 ng, Float32 nb)
129  {
130  c[0] = nr;
131  c[1] = ng;
132  c[2] = nb;
133  }
134 
136  inline explicit Spectrum( const Vector<Float32,3>& v3)
137  {
138  c[0] = v3[0];
139  c[1] = v3[1];
140  c[2] = v3[2];
141  }
142 
144  inline explicit Spectrum( const Vector<Float32,4>& v4)
145  {
146  c[0] = v4[0];
147  c[1] = v4[1];
148  c[2] = v4[2];
149  }
150 
152  inline explicit Spectrum( const Color& col)
153  {
154  c[0] = col.r;
155  c[1] = col.g;
156  c[2] = col.b;
157  }
158 
161  {
162  Vector<Float32,3> result;
163  result[0] = c[0];
164  result[1] = c[1];
165  result[2] = c[2];
166  return result;
167  }
168 
171  {
172  Vector<Float32,4> result;
173  result[0] = c[0];
174  result[1] = c[1];
175  result[2] = c[2];
176  result[3] = 1.0;
177  return result;
178  }
179 
181  MI_HOST_DEVICE_INLINE const Float32& operator[]( Size i) const
182  {
183  mi_math_assert_msg( i < SIZE, "precondition");
184  return c[i];
185  }
186 
188  MI_HOST_DEVICE_INLINE Float32& operator[]( Size i)
189  {
190  mi_math_assert_msg( i < SIZE, "precondition");
191  return c[i];
192  }
193 
194 
196  inline Float32 get( Size i) const
197  {
198  mi_math_assert_msg( i < SIZE, "precondition");
199  return c[i];
200  }
201 
203  inline void set( Size i, Float32 value)
204  {
205  mi_math_assert_msg( i < SIZE, "precondition");
206  c[i] = value;
207  }
208 
210  inline bool is_black() const
211  {
212  for( Size i = 0; i < SIZE; ++i)
213  if( c[i] != 0.0f)
214  return false;
215  return true;
216  }
217 
219  inline Float32 linear_intensity() const
220  {
221  Float32 sum = 0.f;
222  for( Size i = 0; i < SIZE; ++i)
223  sum += c[i];
224  return sum / Float32( SIZE);
225  }
226 };
227 
228 //------ Free comparison operators ==, !=, <, <=, >, >= for spectra ------------
229 
231 inline bool operator==( const Spectrum& lhs, const Spectrum& rhs)
232 {
233  return is_equal( lhs, rhs);
234 }
235 
237 inline bool operator!=( const Spectrum& lhs, const Spectrum& rhs)
238 {
239  return is_not_equal( lhs, rhs);
240 }
241 
245 inline bool operator<( const Spectrum& lhs, const Spectrum& rhs)
246 {
247  return lexicographically_less( lhs, rhs);
248 }
249 
253 inline bool operator<=( const Spectrum& lhs, const Spectrum& rhs)
254 {
255  return lexicographically_less_or_equal( lhs, rhs);
256 }
257 
261 inline bool operator>( const Spectrum& lhs, const Spectrum& rhs)
262 {
263  return lexicographically_greater( lhs, rhs);
264 }
265 
269 inline bool operator>=( const Spectrum& lhs, const Spectrum& rhs)
270 {
271  return lexicographically_greater_or_equal( lhs, rhs);
272 }
273 
274 
275 
276 //------ Free operators +=, -=, *=, /=, +, -, *, and / for spectra --------------
277 
279 inline Spectrum& operator+=( Spectrum& lhs, const Spectrum& rhs)
280 {
281  mi_math_assert_msg( lhs.size() == 3, "precondition");
282  mi_math_assert_msg( rhs.size() == 3, "precondition");
283  lhs[0] += rhs[0];
284  lhs[1] += rhs[1];
285  lhs[2] += rhs[2];
286  return lhs;
287 }
288 
290 inline Spectrum& operator-=( Spectrum& lhs, const Spectrum& rhs)
291 {
292  mi_math_assert_msg( lhs.size() == 3, "precondition");
293  mi_math_assert_msg( rhs.size() == 3, "precondition");
294  lhs[0] -= rhs[0];
295  lhs[1] -= rhs[1];
296  lhs[2] -= rhs[2];
297  return lhs;
298 }
299 
301 inline Spectrum& operator*=( Spectrum& lhs, const Spectrum& rhs)
302 {
303  mi_math_assert_msg( lhs.size() == 3, "precondition");
304  mi_math_assert_msg( rhs.size() == 3, "precondition");
305  lhs[0] *= rhs[0];
306  lhs[1] *= rhs[1];
307  lhs[2] *= rhs[2];
308  return lhs;
309 }
310 
312 inline Spectrum& operator/=( Spectrum& lhs, const Spectrum& rhs)
313 {
314  mi_math_assert_msg( lhs.size() == 3, "precondition");
315  mi_math_assert_msg( rhs.size() == 3, "precondition");
316  lhs[0] /= rhs[0];
317  lhs[1] /= rhs[1];
318  lhs[2] /= rhs[2];
319  return lhs;
320 }
321 
323 inline Spectrum operator+( const Spectrum& lhs, const Spectrum& rhs)
324 {
325  mi_math_assert_msg( lhs.size() == 3, "precondition");
326  mi_math_assert_msg( rhs.size() == 3, "precondition");
327  return Spectrum( lhs[0] + rhs[0], lhs[1] + rhs[1], lhs[2] + rhs[2]);
328 }
329 
331 inline Spectrum operator-( const Spectrum& lhs, const Spectrum& rhs)
332 {
333  mi_math_assert_msg( lhs.size() == 3, "precondition");
334  mi_math_assert_msg( rhs.size() == 3, "precondition");
335  return Spectrum( lhs[0] - rhs[0], lhs[1] - rhs[1], lhs[2] - rhs[2]);
336 }
337 
339 inline Spectrum operator*( const Spectrum& lhs, const Spectrum& rhs)
340 {
341  mi_math_assert_msg( lhs.size() == 3, "precondition");
342  mi_math_assert_msg( rhs.size() == 3, "precondition");
343  return Spectrum( lhs[0] * rhs[0], lhs[1] * rhs[1], lhs[2] * rhs[2]);
344 }
345 
347 inline Spectrum operator/( const Spectrum& lhs, const Spectrum& rhs)
348 {
349  mi_math_assert_msg( lhs.size() == 3, "precondition");
350  mi_math_assert_msg( rhs.size() == 3, "precondition");
351  return Spectrum( lhs[0] / rhs[0], lhs[1] / rhs[1], lhs[2] / rhs[2]);
352 }
353 
355 inline Spectrum operator-( const Spectrum& c)
356 {
357  mi_math_assert_msg( c.size() == 3, "precondition");
358  return Spectrum( -c[0], -c[1], -c[2]);
359 }
360 
361 
362 
363 //------ Free operator *=, /=, *, and / definitions for scalars ---------------
364 
368 {
369  mi_math_assert_msg( c.size() == 3, "precondition");
370  c[0] *= s;
371  c[1] *= s;
372  c[2] *= s;
373  return c;
374 }
375 
378 {
379  mi_math_assert_msg( c.size() == 3, "precondition");
380  const Float32 f = 1.0f / s;
381  c[0] *= f;
382  c[1] *= f;
383  c[2] *= f;
384  return c;
385 }
386 
388 inline Spectrum operator*( const Spectrum& c, Float32 s)
389 {
390  mi_math_assert_msg( c.size() == 3, "precondition");
391  return Spectrum( c[0] * s, c[1] * s, c[2] * s);
392 }
393 
395 inline Spectrum operator*( Float32 s, const Spectrum& c)
396 {
397  mi_math_assert_msg( c.size() == 3, "precondition");
398  return Spectrum( s * c[0], s * c[1], s* c[2]);
399 }
400 
402 inline Spectrum operator/( const Spectrum& c, Float32 s)
403 {
404  mi_math_assert_msg( c.size() == 3, "precondition");
405  Float32 f = 1.0f / s;
406  return Spectrum( c[0] * f, c[1] * f, c[2] * f);
407 }
408 
409 
410 //------ Function Overloads for Spectrum Algorithms ------------------------------
411 
412 
414 inline Spectrum abs( const Spectrum& c)
415 {
416  mi_math_assert_msg( c.size() == 3, "precondition");
417  return Spectrum( abs( c[0]), abs( c[1]), abs( c[2]));
418 }
419 
421 inline Spectrum acos( const Spectrum& c)
422 {
423  mi_math_assert_msg( c.size() == 3, "precondition");
424  return Spectrum( acos( c[0]), acos( c[1]), acos( c[2]));
425 }
426 
428 inline bool all( const Spectrum& c)
429 {
430  mi_math_assert_msg( c.size() == 3, "precondition");
431  return (c[0] != 0.0f) && (c[1] != 0.0f) && (c[2] != 0.0f);
432 }
433 
435 inline bool any( const Spectrum& c)
436 {
437  mi_math_assert_msg( c.size() == 3, "precondition");
438  return (c[0] != 0.0f) || (c[1] != 0.0f) || (c[2] != 0.0f);
439 }
440 
442 inline Spectrum asin( const Spectrum& c)
443 {
444  mi_math_assert_msg( c.size() == 3, "precondition");
445  return Spectrum( asin( c[0]), asin( c[1]), asin( c[2]));
446 }
447 
449 inline Spectrum atan( const Spectrum& c)
450 {
451  mi_math_assert_msg( c.size() == 3, "precondition");
452  return Spectrum( atan( c[0]), atan( c[1]), atan( c[2]));
453 }
454 
458 inline Spectrum atan2( const Spectrum& c, const Spectrum& d)
459 {
460  mi_math_assert_msg( c.size() == 3 && d.size() == 3, "precondition");
461  return Spectrum( atan2( c[0], d[0]), atan2( c[1], d[1]), atan2( c[2], d[2]));
462 }
463 
466 inline Spectrum ceil( const Spectrum& c)
467 {
468  mi_math_assert_msg( c.size() == 3, "precondition");
469  return Spectrum( ceil( c[0]), ceil( c[1]), ceil( c[2]));
470 }
471 
473 inline Spectrum clamp( const Spectrum& c, const Spectrum& low, const Spectrum& high)
474 {
475  mi_math_assert_msg( c.size() == 3, "precondition");
476  mi_math_assert_msg( low.size() == 3, "precondition");
477  mi_math_assert_msg( high.size() == 3, "precondition");
478  return Spectrum( clamp( c[0], low[0], high[0]),
479  clamp( c[1], low[1], high[1]),
480  clamp( c[2], low[2], high[2]));
481 }
482 
484 inline Spectrum clamp( const Spectrum& c, const Spectrum& low, Float32 high)
485 {
486  mi_math_assert_msg( c.size() == 3, "precondition");
487  mi_math_assert_msg( low.size() == 3, "precondition");
488  return Spectrum( clamp( c[0], low[0], high),
489  clamp( c[1], low[1], high),
490  clamp( c[2], low[2], high));
491 }
492 
494 inline Spectrum clamp( const Spectrum& c, Float32 low, const Spectrum& high)
495 {
496  mi_math_assert_msg( c.size() == 3, "precondition");
497  mi_math_assert_msg( high.size() == 3, "precondition");
498  return Spectrum( clamp( c[0], low, high[0]),
499  clamp( c[1], low, high[1]),
500  clamp( c[2], low, high[2]));
501 }
502 
504 inline Spectrum clamp( const Spectrum& c, Float32 low, Float32 high)
505 {
506  mi_math_assert_msg( c.size() == 3, "precondition");
507  return Spectrum( clamp( c[0], low, high),
508  clamp( c[1], low, high),
509  clamp( c[2], low, high));
510 }
511 
513 inline Spectrum cos( const Spectrum& c)
514 {
515  mi_math_assert_msg( c.size() == 3, "precondition");
516  return Spectrum( cos( c[0]), cos( c[1]), cos( c[2]));
517 }
518 
520 inline Spectrum degrees( const Spectrum& c)
521 {
522  mi_math_assert_msg( c.size() == 3, "precondition");
523  return Spectrum( degrees( c[0]), degrees( c[1]), degrees( c[2]));
524 }
525 
528 inline Spectrum elementwise_max( const Spectrum& lhs, const Spectrum& rhs)
529 {
530  mi_math_assert_msg( lhs.size() == 3, "precondition");
531  mi_math_assert_msg( rhs.size() == 3, "precondition");
532  return Spectrum( base::max MI_PREVENT_MACRO_EXPAND ( lhs[0], rhs[0]),
533  base::max MI_PREVENT_MACRO_EXPAND ( lhs[1], rhs[1]),
534  base::max MI_PREVENT_MACRO_EXPAND ( lhs[2], rhs[2]));
535 }
536 
539 inline Spectrum elementwise_min( const Spectrum& lhs, const Spectrum& rhs)
540 {
541  mi_math_assert_msg( lhs.size() == 3, "precondition");
542  mi_math_assert_msg( rhs.size() == 3, "precondition");
543  return Spectrum( base::min MI_PREVENT_MACRO_EXPAND ( lhs[0], rhs[0]),
544  base::min MI_PREVENT_MACRO_EXPAND ( lhs[1], rhs[1]),
545  base::min MI_PREVENT_MACRO_EXPAND ( lhs[2], rhs[2]));
546 }
547 
549 inline Spectrum exp( const Spectrum& c)
550 {
551  mi_math_assert_msg( c.size() == 3, "precondition");
552  return Spectrum( exp( c[0]), exp( c[1]), exp( c[2]));
553 }
554 
556 inline Spectrum exp2( const Spectrum& c)
557 {
558  mi_math_assert_msg( c.size() == 3, "precondition");
559  return Spectrum( exp2( c[0]), exp2( c[1]), exp2( c[2]));
560 }
561 
564 inline Spectrum floor( const Spectrum& c)
565 {
566  mi_math_assert_msg( c.size() == 3, "precondition");
567  return Spectrum( floor( c[0]), floor( c[1]), floor( c[2]));
568 }
569 
573 inline Spectrum fmod( const Spectrum& a, const Spectrum& b)
574 {
575  mi_math_assert_msg( a.size() == 3, "precondition");
576  mi_math_assert_msg( b.size() == 3, "precondition");
577  return Spectrum( fmod( a[0], b[0]), fmod( a[1], b[1]), fmod( a[2], b[2]));
578 }
579 
583 inline Spectrum fmod( const Spectrum& a, Float32 b)
584 {
585  mi_math_assert_msg( a.size() == 3, "precondition");
586  return Spectrum( fmod( a[0], b), fmod( a[1], b), fmod( a[2], b));
587 }
588 
590 inline Spectrum frac( const Spectrum& c)
591 {
592  mi_math_assert_msg( c.size() == 3, "precondition");
593  return Spectrum( frac( c[0]), frac( c[1]), frac( c[2]));
594 }
595 
604  const Spectrum& spectrum,
605  Float32 gamma_factor)
606 {
607  mi_math_assert_msg( spectrum.size() == 3, "precondition");
608  mi_math_assert( gamma_factor > 0);
609  const Float32 f = Float32(1.0) / gamma_factor;
610  return Spectrum( fast_pow( spectrum[0], f),
611  fast_pow( spectrum[1], f),
612  fast_pow( spectrum[2], f));
613 }
614 
616 inline bool is_approx_equal(
617  const Spectrum& lhs,
618  const Spectrum& rhs,
619  Float32 e)
620 {
621  mi_math_assert_msg( lhs.size() == 3, "precondition");
622  mi_math_assert_msg( rhs.size() == 3, "precondition");
623  return is_approx_equal( lhs[0], rhs[0], e)
624  && is_approx_equal( lhs[1], rhs[1], e)
625  && is_approx_equal( lhs[2], rhs[2], e);
626 }
627 
630 inline Spectrum lerp(
631  const Spectrum& c1,
632  const Spectrum& c2,
633  const Spectrum& t)
634 {
635  mi_math_assert_msg( c1.size() == 3, "precondition");
636  mi_math_assert_msg( c2.size() == 3, "precondition");
637  mi_math_assert_msg( t.size() == 3, "precondition");
638  return Spectrum( lerp( c1[0], c2[0], t[0]),
639  lerp( c1[1], c2[1], t[1]),
640  lerp( c1[2], c2[2], t[2]));
641 }
642 
645 inline Spectrum lerp(
646  const Spectrum& c1,
647  const Spectrum& c2,
648  Float32 t)
649 {
650  mi_math_assert_msg( c1.size() == 3, "precondition");
651  mi_math_assert_msg( c2.size() == 3, "precondition");
652  // equivalent to: return c1 * (Float32(1)-t) + c2 * t;
653  return Spectrum( lerp( c1[0], c2[0], t),
654  lerp( c1[1], c2[1], t),
655  lerp( c1[2], c2[2], t));
656 }
657 
659 inline Spectrum log( const Spectrum& c)
660 {
661  mi_math_assert_msg( c.size() == 3, "precondition");
662  return Spectrum( log( c[0]), log( c[1]), log( c[2]));
663 }
664 
667 {
668  mi_math_assert_msg( c.size() == 3, "precondition");
669  return Spectrum( log2 MI_PREVENT_MACRO_EXPAND (c[0]),
672 }
673 
675 inline Spectrum log10( const Spectrum& c)
676 {
677  mi_math_assert_msg( c.size() == 3, "precondition");
678  return Spectrum( log10( c[0]), log10( c[1]), log10( c[2]));
679 }
680 
685 inline Spectrum modf( const Spectrum& c, Spectrum& i)
686 {
687  mi_math_assert_msg( c.size() == 3, "precondition");
688  mi_math_assert_msg( i.size() == 3, "precondition");
689  return Spectrum( modf( c[0], i[0]), modf( c[1], i[1]), modf( c[2], i[2]));
690 }
691 
693 inline Spectrum pow( const Spectrum& a, const Spectrum& b)
694 {
695  mi_math_assert_msg( a.size() == 3, "precondition");
696  mi_math_assert_msg( b.size() == 3, "precondition");
697  return Spectrum( pow( a[0], b[0]), pow( a[1], b[1]), pow( a[2], b[2]));
698 }
699 
701 inline Spectrum pow( const Spectrum& a, Float32 b)
702 {
703  mi_math_assert_msg( a.size() == 3, "precondition");
704  return Spectrum( pow( a[0], b), pow( a[1], b), pow( a[2], b));
705 }
706 
708 inline Spectrum radians( const Spectrum& c)
709 {
710  mi_math_assert_msg( c.size() == 3, "precondition");
711  return Spectrum( radians( c[0]), radians( c[1]), radians( c[2]));
712 }
713 
715 inline Spectrum round( const Spectrum& c)
716 {
717  mi_math_assert_msg( c.size() == 3, "precondition");
718  return Spectrum( round( c[0]), round( c[1]), round( c[2]));
719 }
720 
722 inline Spectrum rsqrt( const Spectrum& c)
723 {
724  mi_math_assert_msg( c.size() == 3, "precondition");
725  return Spectrum( rsqrt( c[0]), rsqrt( c[1]), rsqrt( c[2]));
726 }
727 
729 inline Spectrum saturate( const Spectrum& c)
730 {
731  mi_math_assert_msg( c.size() == 3, "precondition");
732  return Spectrum( saturate( c[0]), saturate( c[1]), saturate( c[2]));
733 }
734 
736 inline Spectrum sign( const Spectrum& c)
737 {
738  mi_math_assert_msg( c.size() == 3, "precondition");
739  return Spectrum( sign( c[0]), sign( c[1]), sign( c[2]));
740 }
741 
743 inline Spectrum sin( const Spectrum& c)
744 {
745  mi_math_assert_msg( c.size() == 3, "precondition");
746  return Spectrum( sin( c[0]), sin( c[1]), sin( c[2]));
747 }
748 
752 inline void sincos( const Spectrum& a, Spectrum& s, Spectrum& c)
753 {
754  mi_math_assert_msg( a.size() == 3, "precondition");
755  mi_math_assert_msg( s.size() == 3, "precondition");
756  mi_math_assert_msg( c.size() == 3, "precondition");
757  sincos( a[0], s[0], c[0]);
758  sincos( a[1], s[1], c[1]);
759  sincos( a[2], s[2], c[2]);
760 }
761 
767 inline Spectrum smoothstep( const Spectrum& a, const Spectrum& b, const Spectrum& c)
768 {
769  mi_math_assert_msg( a.size() == 3, "precondition");
770  mi_math_assert_msg( b.size() == 3, "precondition");
771  mi_math_assert_msg( c.size() == 3, "precondition");
772  return Spectrum( smoothstep( a[0], b[0], c[0]),
773  smoothstep( a[1], b[1], c[1]),
774  smoothstep( a[2], b[2], c[2]));
775 }
776 
782 inline Spectrum smoothstep( const Spectrum& a, const Spectrum& b, Float32 x)
783 {
784  mi_math_assert_msg( a.size() == 3, "precondition");
785  mi_math_assert_msg( b.size() == 3, "precondition");
786  return Spectrum( smoothstep( a[0], b[0], x),
787  smoothstep( a[1], b[1], x),
788  smoothstep( a[2], b[2], x));
789 }
790 
792 inline Spectrum sqrt( const Spectrum& c)
793 {
794  mi_math_assert_msg( c.size() == 3, "precondition");
795  return Spectrum( sqrt( c[0]), sqrt( c[1]), sqrt( c[2]));
796 }
797 
799 inline Spectrum step( const Spectrum& a, const Spectrum& c)
800 {
801  mi_math_assert_msg( a.size() == 3, "precondition");
802  mi_math_assert_msg( c.size() == 3, "precondition");
803  return Spectrum( step( a[0], c[0]), step( a[1], c[1]), step( a[1], c[2]));
804 }
805 
807 inline Spectrum tan( const Spectrum& c)
808 {
809  mi_math_assert_msg( c.size() == 3, "precondition");
810  return Spectrum( tan( c[0]), tan( c[1]), tan( c[2]));
811 }
812 
815 {
816  mi_math_assert_msg( c.size() == 3, "precondition");
817  return isfinite MI_PREVENT_MACRO_EXPAND (c[0])
820 }
821 
824 {
825  mi_math_assert_msg( c.size() == 3, "precondition");
826  return isinfinite MI_PREVENT_MACRO_EXPAND (c[0])
829 }
830 
832 inline bool isnan MI_PREVENT_MACRO_EXPAND (const Spectrum& c)
833 {
834  mi_math_assert_msg( c.size() == 3, "precondition");
835  return isnan MI_PREVENT_MACRO_EXPAND (c[0])
837  || isnan MI_PREVENT_MACRO_EXPAND (c[2]);
838 }
839 
841 MI_HOST_DEVICE_INLINE void to_rgbe( const Spectrum& c, Uint32& rgbe)
842 {
843  mi_math_assert_msg( c.size() == 3, "precondition");
844  to_rgbe( &c[0], rgbe);
845 }
846 
848 MI_HOST_DEVICE_INLINE void to_rgbe( const Spectrum& c, Uint8 rgbe[4])
849 {
850  mi_math_assert_msg( c.size() == 3, "precondition");
851  to_rgbe( &c[0], rgbe);
852 }
853 
855 MI_HOST_DEVICE_INLINE void from_rgbe( const Uint8 rgbe[4], Spectrum& c)
856 {
857  mi_math_assert_msg( c.size() == 3, "precondition");
858  from_rgbe( rgbe, &c[0]);
859 }
860 
862 MI_HOST_DEVICE_INLINE void from_rgbe( const Uint32 rgbe, Spectrum& c)
863 {
864  mi_math_assert_msg( c.size() == 3, "precondition");
865  from_rgbe( rgbe, &c[0]);
866 }
867  // end group mi_math_spectrum
869 
870 } // namespace math
871 
872 } // namespace mi
873 
874 #endif // MI_MATH_SPECTRUM_H