// © Copyright 2008 Владимир Фролов
#define MGML_GLOBALS
#pragma warning(disable:4996)

#define INFINITY		1e38f
#define EPSILON			1e-12f
#define DELTA			1e-5f

#define EPSILON_E5M		1e-5f
#define EPSILON_E6M		1e-6f
#define EPSILON_E7M		1e-7f
#define EPSILON_E8M		1e-8f
#define EPSILON_E9M		1e-9f
#define EPSILON_E10M	1e-10f
#define EPSILON_E32M	1e-32f

#ifndef __CUDACC__
	#define __align__(N) __declspec(align(N))
#endif

#define SSE_ALIGNED __align__(16)


enum {HAL_NONE=0,
	  HAL_CUDA=1,
	  HAL_STREAM=2,
	  HAL_LARABEE=3};

#ifndef __CUDACC__
	#ifndef __device__
		#define __device__
	#endif
	
	#ifndef __host__
		#define __host__ 
	#endif

	#ifndef __constant__
		#define __constant__
	#endif

	const int HAL = HAL_NONE;
#else
	
	#ifndef ASSERT
		#define ASSERT(_expression) ((void)0)
	#endif

	typedef float4 __m128;

	const int HAL = HAL_CUDA;

#endif

#define universal_call __device__ __host__



#ifndef	 MPMG_GUARDIAN
	#include "MPMG.h"
#endif

#ifndef __CUDACC__
	#include <new>
#endif

namespace MGML_MATH
{
#ifndef __CUDACC__

struct SSE_ALIGNED SSE_Aligned_Object
{

   static void* operator new(size_t size)
   {
	  void* ptr = _aligned_malloc(size,16);
	  if(!ptr)
		  throw std::bad_alloc("_aligned_malloc(): unsufficient memory");
	  return ptr;
   }

   static void operator delete(void* raw_memory)
   {
	  if(!raw_memory) return;

	  _aligned_free(raw_memory);
   }

  // нужно переопределять new[] так как иначе не работают
  // напрямую команды sse с адресами объектов, расположенных в динамической памяти
  static void* operator new[](size_t size)
  {
	  void* ptr = _aligned_malloc(size,16);
	  if(!ptr)
		  throw std::bad_alloc("_aligned_malloc(): unsufficient memory");
	  return ptr;
  }

  static void operator delete[](void* raw_memory)
  {
	  if(!raw_memory) return;
	  _aligned_free(raw_memory);
  }



};

template<int n,class T>
class Auto_Align {};

template<>
class Auto_Align<4,float> : public SSE_Aligned_Object {};

#else

struct SSE_Aligned_Object {};

template<int n,class T>
class Auto_Align {};

template<>
class SSE_ALIGNED Auto_Align<4,float> {};

#endif

//#else
//
//	class SSE_Aligned_Object {};
//
//	template<int n,class T>
//	class Auto_Align {};
//
//	template<>
//	class Auto_Align<4,float> {};
//
//#endif

};


