#define MGML_GPU_GUARDIAN

namespace RAYTR
{

#ifndef __CUDACC__

  #ifndef MGML_GUARDIAN
    #include "../CSL/MGML.h"
  #endif

  typedef MGML::vec4f float4;
  typedef MGML::vec3f float3;
  typedef MGML::vec2f float2;

  static inline float3 make_float3(float a, float b, float c) { return float3(a,b,c);}
  static inline float4 make_float4(float a, float b, float c, float d) { return float4(a,b,c,d);}

#else
  #include "float4.cu"

  #define universal_call IDH_CALL

  template<bool>
  struct STATIC_ASSERT;

  template<>
  struct STATIC_ASSERT<true> {};

  #ifdef __CUDACC__ 
    #ifdef __DEVICE_EMULATION__
      #undef ASSERT 
      #define ASSERT(_expression) \
      if(!(_expression)) { fprintf(stderr,"Assertion failed. File: %s, Line %d\n",__FILE__,__LINE__); \
      abort(); }
    #else
      #define ASSERT(_expression) ((void)0)
    #endif
  #endif

  typedef unsigned int uint;
  typedef unsigned short ushort;

  #define EPSILON_E5M (1e-5f)
  #define EPSILON_E6M (1e-6f)
  #define EPSILON_E7M (1e-7f)
  #define EPSILON_E8M (1e-8f)

  template <class T> universal_call T MIN(T a, T b){ return a < b ? a : b; }
  template <class T> universal_call T MAX(T a, T b){ return a > b ? a : b; }

  template <class T> inline universal_call T MIN(T a,T b,T c)
  {
    if(a <= b && a <= c)
      return a;
    else if(b <= a && b <= c)
      return b;
    else
      return c;
  }

  template <class T> inline universal_call T MAX(T a,T b,T c)
  { 
    if(a >= b && a >= c)
      return a;
    else if(b >= a && b >= c)
      return b;
    else
      return c;
  }

#endif

}