#pragma once
#include <climits>

namespace __jitify_limits_ns {
    // TODO: Floating-point limits
    namespace __jitify_detail {
	template<class T, T Min, T Max, int Digits=-1>
            struct IntegerLimits {
		static inline __host__ __device__ T min() { return Min; }
		static inline __host__ __device__ T max() { return Max; }
		enum {
                    digits     = (Digits == -1) ? (int)(sizeof(T)*8 - (Min != 0)) : Digits,
                    digits10   = (digits * 30103) / 100000,
                    is_signed  = ((T)(-1)<0),
                    is_integer = true,
                    is_exact   = true,
                    radix      = 2,
                    is_bounded = true,
                    is_modulo  = false
		};
            };
    } // namespace detail
    template<typename T> struct numeric_limits {};
    template<> struct numeric_limits<bool>               : public __jitify_detail::IntegerLimits<bool,              false,    true,1> {};
    template<> struct numeric_limits<char>               : public __jitify_detail::IntegerLimits<char,              CHAR_MIN, CHAR_MAX> {};
    template<> struct numeric_limits<signed char>        : public __jitify_detail::IntegerLimits<signed char,       SCHAR_MIN,SCHAR_MAX> {};
    template<> struct numeric_limits<unsigned char>      : public __jitify_detail::IntegerLimits<unsigned char,     0,        UCHAR_MAX> {};
    template<> struct numeric_limits<wchar_t>            : public __jitify_detail::IntegerLimits<wchar_t,           INT_MIN,  INT_MAX> {};
    template<> struct numeric_limits<short>              : public __jitify_detail::IntegerLimits<short,             SHRT_MIN, SHRT_MAX> {};
    template<> struct numeric_limits<unsigned short>     : public __jitify_detail::IntegerLimits<unsigned short,    0,        USHRT_MAX> {};
    template<> struct numeric_limits<int>                : public __jitify_detail::IntegerLimits<int,               INT_MIN,  INT_MAX> {};
    template<> struct numeric_limits<unsigned int>       : public __jitify_detail::IntegerLimits<unsigned int,      0,        UINT_MAX> {};
    template<> struct numeric_limits<long>               : public __jitify_detail::IntegerLimits<long,              LONG_MIN, LONG_MAX> {};
    template<> struct numeric_limits<unsigned long>      : public __jitify_detail::IntegerLimits<unsigned long,     0,        ULONG_MAX> {};
    template<> struct numeric_limits<long long>          : public __jitify_detail::IntegerLimits<long long,         LLONG_MIN,LLONG_MAX> {};
    template<> struct numeric_limits<unsigned long long> : public __jitify_detail::IntegerLimits<unsigned long long,0,        ULLONG_MAX> {};
    //template<typename T> struct numeric_limits { static const bool is_signed = ((T)(-1)<0); };
} // namespace __jitify_limits_ns
namespace std { using namespace __jitify_limits_ns; }
using namespace __jitify_limits_ns;
