// limits standard header -*-c++-*-
// Copyright 2009-2017 IAR Systems AB.
#ifndef _LIMITS_
#define _LIMITS_

#ifndef _SYSTEM_BUILD
  #pragma system_include
#endif

#include <cfloat>
#include <climits>
#include <cmath>
#if _DLIB_WIDE_CHARACTERS
#include <cwchar>
#endif
#include <xstddef>

namespace std {

//      ASSUMES:
//      wraparound 2's complement integer arithmetic w/o traps
//      all CHAR_BITs of each byte used by integers
//      Almost IEC559 (IEEE 754) floating-point arithmetic
//	double and long double is 32 or 64 bits
//      floating-point errors cannot trap
//      tinyness detected before floating-point rounding
//      32 or 64-bit long long

#define _STCONS(ty, name, val) \
        _DLIB_CONST_ATTR static const ty name = (ty)(val)

// ENUM float_denorm_style
  typedef enum : signed char
{ // constants for different IEEE float denormalization styles
  denorm_indeterminate = -1,
  denorm_absent = 0,
  denorm_present = 1
} float_denorm_style;

// ENUM float_round_style
  typedef enum : signed char
{ // constants for different IEEE rounding styles
  round_indeterminate = -1,
  round_toward_zero = 0,
  round_to_nearest = 1,
  round_toward_infinity = 2,
  round_toward_neg_infinity = 3
} float_round_style;

// STRUCT _Num_base
struct _Num_base
{ // base for all types, with common defaults
  _STCONS(float_denorm_style, has_denorm, denorm_absent);
  _STCONS(bool, has_denorm_loss, false);
  _STCONS(bool, has_infinity, false);
  _STCONS(bool, has_quiet_NaN, false);
  _STCONS(bool, has_signaling_NaN, false);
  _STCONS(bool, is_bounded, false);
  _STCONS(bool, is_exact, false);
  _STCONS(bool, is_iec559, false);
  _STCONS(bool, is_integer, false);
  _STCONS(bool, is_modulo, false);
  _STCONS(bool, is_signed, false);
  _STCONS(bool, is_specialized, false);
  _STCONS(bool, tinyness_before, false);
  _STCONS(bool, traps, false);
  _STCONS(float_round_style, round_style, round_toward_zero);
  _STCONS(int, digits, 0);
  _STCONS(int, digits10, 0);
  _STCONS(int, max_digits10, 0);
  _STCONS(int, max_exponent, 0);
  _STCONS(int, max_exponent10, 0);
  _STCONS(int, min_exponent, 0);
  _STCONS(int, min_exponent10, 0);
  _STCONS(int, radix, 0);
};

// TEMPLATE CLASS numeric_limits
template<class _Ty>
class numeric_limits
  : public _Num_base
{       // numeric limits for arbitrary type _Ty (say little or nothing)
public:
  static constexpr _Ty (min)() _THROW0()
  {       // return minimum value
    return _Ty();
  }

  static constexpr _Ty (max)() _THROW0()
  {       // return maximum value
    return _Ty();
  }

  static constexpr _Ty lowest() _THROW0()
  {       // return most negative value
    return _Ty();
  }

  static constexpr _Ty epsilon() _THROW0()
  {       // return smallest effective increment from 1.0
    return _Ty();
  }

  static constexpr _Ty round_error() _THROW0()
  {       // return largest rounding error
    return _Ty();
  }

  static constexpr _Ty denorm_min() _THROW0()
  {       // return minimum denormalized value
    return _Ty();
  }

  static constexpr _Ty infinity() _THROW0()
  {       // return positive infinity
    return _Ty();
  }

  static constexpr _Ty quiet_NaN() _THROW0()
  {       // return non-signaling NaN
    return _Ty();
  }

  static constexpr _Ty signaling_NaN() _THROW0()
  {       // return signaling NaN
    return _Ty();
  }
};

template<class _Ty>
class numeric_limits<const _Ty>
  : public numeric_limits<_Ty>
{       // numeric limits for const types
};

template<class _Ty>
class numeric_limits<volatile _Ty>
  : public numeric_limits<_Ty>
{       // numeric limits for volatile types
};

template<class _Ty>
class numeric_limits<const volatile _Ty>
  : public numeric_limits<_Ty>
{       // numeric limits for const volatile types
};

// STRUCT _Num_int_base
struct _Num_int_base
  : public _Num_base
{       // base for integer types
  _STCONS(bool, is_bounded, true);
  _STCONS(bool, is_exact, true);
  _STCONS(bool, is_integer, true);
  _STCONS(bool, is_modulo, true);
  _STCONS(bool, is_specialized, true);
  _STCONS(int, radix, 2);
};

#ifdef __SUBNORMAL_FLOATING_POINTS__
  #if __SUBNORMAL_FLOATING_POINTS__
    #define __DENORM denorm_present
  #else
    #define __DENORM denorm_absent
  #endif
#else
  #define __DENORM denorm_present
#endif

// STRUCT _Num_float_base
struct _Num_float_base
  : public _Num_base
{       // base for floating-point types
  _STCONS(float_denorm_style, has_denorm, __DENORM);
  _STCONS(bool, has_denorm_loss, false);
  _STCONS(bool, has_infinity, true);
  _STCONS(bool, has_quiet_NaN, true);
  _STCONS(bool, has_signaling_NaN, false);
  _STCONS(bool, is_bounded, true);
  _STCONS(bool, is_exact, false);
  _STCONS(bool, is_iec559, false);
  _STCONS(bool, is_integer, false);
  _STCONS(bool, is_modulo, false);
  _STCONS(bool, is_signed, true);
  _STCONS(bool, is_specialized, true);
  _STCONS(bool, tinyness_before, true);
  _STCONS(bool, traps, false);
  _STCONS(float_round_style, round_style, round_to_nearest);
  _STCONS(int, radix, FLT_RADIX);
};

// CLASS numeric_limits<char>
template<> class numeric_limits<char>
  : public _Num_int_base
{       // limits for type char
public:
  typedef char _Ty;

  static constexpr _Ty (min)() _THROW0()
  {       // return minimum value
    return CHAR_MIN;
  }

  static constexpr _Ty (max)() _THROW0()
  {       // return maximum value
    return CHAR_MAX;
  }

  static constexpr _Ty lowest() _THROW0()
  {       // return most negative value
    return (min)();
  }

  static constexpr _Ty epsilon() _THROW0()
  {       // return smallest effective increment from 1.0
    return 0;
  }

  static constexpr _Ty round_error() _THROW0()
  {       // return largest rounding error
    return 0;
  }

  static constexpr _Ty denorm_min() _THROW0()
  {       // return minimum denormalized value
    return 0;
  }

  static constexpr _Ty infinity() _THROW0()
  {       // return positive infinity
    return 0;
  }

  static constexpr _Ty quiet_NaN() _THROW0()
  {       // return non-signaling NaN
    return 0;
  }

  static constexpr _Ty signaling_NaN() _THROW0()
  {       // return signaling NaN
    return 0;
  }

  _STCONS(bool, is_signed, CHAR_MIN != 0);
  _STCONS(int, digits, CHAR_BIT - (CHAR_MIN != 0 ? 1 : 0));
  _STCONS(int, digits10, (CHAR_BIT - (CHAR_MIN != 0 ? 1 : 0)) * 301L / 1000);
};

#if _DLIB_WIDE_CHARACTERS
// CLASS numeric_limits<wchar_t>
template<> class numeric_limits<wchar_t>
  : public _Num_int_base
{       // limits for type wchar_t
public:
  typedef wchar_t _Ty;

  static constexpr _Ty (min)() _THROW0()
  {       // return minimum value
    return (_Ty)WCHAR_MIN;
  }

  static constexpr _Ty (max)() _THROW0()
  {       // return maximum value
    return (_Ty)WCHAR_MAX;
  }

  static constexpr _Ty lowest() _THROW0()
  {       // return most negative value
    return (min)();
  }

  static constexpr _Ty epsilon() _THROW0()
  {       // return smallest effective increment from 1.0
    return 0;
  }

  static constexpr _Ty round_error() _THROW0()
  {       // return largest rounding error
    return 0;
  }

  static constexpr _Ty denorm_min() _THROW0()
  {       // return minimum denormalized value
    return 0;
  }

  static constexpr _Ty infinity() _THROW0()
  {       // return positive infinity
    return 0;
  }

  static constexpr _Ty quiet_NaN() _THROW0()
  {       // return non-signaling NaN
    return 0;
  }

  static constexpr _Ty signaling_NaN() _THROW0()
  {       // return signaling NaN
    return 0;
  }

  _STCONS(bool, is_signed, WCHAR_MIN != 0);
  _STCONS(int, digits, CHAR_BIT * sizeof (wchar_t) - (WCHAR_MIN != 0 ? 1 : 0));
  _STCONS(int, digits10, (CHAR_BIT * sizeof (wchar_t)
                          - (WCHAR_MIN != 0 ? 1 : 0)) * 301L / 1000);
};
#endif

// CLASS numeric_limits<bool>
template<> class numeric_limits<bool>
  : public _Num_int_base
{       // limits for type bool
public:
  typedef bool _Ty;

  static constexpr _Ty (min)() _THROW0()
  {       // return minimum value
    return false;
  }

  static constexpr _Ty (max)() _THROW0()
  {       // return maximum value
    return true;
  }

  static constexpr _Ty lowest() _THROW0()
  {       // return most negative value
    return (min)();
  }

  static constexpr _Ty epsilon() _THROW0()
  {       // return smallest effective increment from 1.0
    return 0;
  }

  static constexpr _Ty round_error() _THROW0()
  {       // return largest rounding error
    return 0;
  }

  static constexpr _Ty denorm_min() _THROW0()
  {       // return minimum denormalized value
    return 0;
  }

  static constexpr _Ty infinity() _THROW0()
  {       // return positive infinity
    return 0;
  }

  static constexpr _Ty quiet_NaN() _THROW0()
  {       // return non-signaling NaN
    return 0;
  }

  static constexpr _Ty signaling_NaN() _THROW0()
  {       // return signaling NaN
    return 0;
  }

  _STCONS(bool, is_modulo, false);
  _STCONS(bool, is_signed, false);
  _STCONS(int, digits, 1);
  _STCONS(int, digits10, 0);
};

// CLASS numeric_limits<signed char>
template<> class numeric_limits<signed char>
  : public _Num_int_base
{       // limits for type signed char
public:
  typedef signed char _Ty;

  static constexpr _Ty (min)() _THROW0()
  {       // return minimum value
    return SCHAR_MIN;
  }

  static constexpr _Ty (max)() _THROW0()
  {       // return maximum value
    return SCHAR_MAX;
  }

  static constexpr _Ty lowest() _THROW0()
  {       // return most negative value
    return (min)();
  }

  static constexpr _Ty epsilon() _THROW0()
  {       // return smallest effective increment from 1.0
    return 0;
  }

  static constexpr _Ty round_error() _THROW0()
  {       // return largest rounding error
    return 0;
  }

  static constexpr _Ty denorm_min() _THROW0()
  {       // return minimum denormalized value
    return 0;
  }

  static constexpr _Ty infinity() _THROW0()
  {       // return positive infinity
    return 0;
  }

  static constexpr _Ty quiet_NaN() _THROW0()
  {       // return non-signaling NaN
    return 0;
  }

  static constexpr _Ty signaling_NaN() _THROW0()
  {       // return signaling NaN
    return 0;
  }

  _STCONS(bool, is_signed, true);
  _STCONS(int, digits, CHAR_BIT - 1);
  _STCONS(int, digits10, (CHAR_BIT - 1) * 301L / 1000);
};

// CLASS numeric_limits<unsigned char>
template<> class numeric_limits<unsigned char>
  : public _Num_int_base
{       // limits for type unsigned char
public:
  typedef unsigned char _Ty;

  static constexpr _Ty (min)() _THROW0()
  {       // return minimum value
    return 0;
  }

  static constexpr _Ty (max)() _THROW0()
  {       // return maximum value
    return UCHAR_MAX;
  }

  static constexpr _Ty lowest() _THROW0()
  {       // return most negative value
    return (min)();
  }

  static constexpr _Ty epsilon() _THROW0()
  {       // return smallest effective increment from 1.0
    return 0;
  }

  static constexpr _Ty round_error() _THROW0()
  {       // return largest rounding error
    return 0;
  }

  static constexpr _Ty denorm_min() _THROW0()
  {       // return minimum denormalized value
    return 0;
  }

  static constexpr _Ty infinity() _THROW0()
  {       // return positive infinity
    return 0;
  }

  static constexpr _Ty quiet_NaN() _THROW0()
  {       // return non-signaling NaN
    return 0;
  }

  static constexpr _Ty signaling_NaN() _THROW0()
  {       // return signaling NaN
    return 0;
  }

  _STCONS(bool, is_signed, false);
  _STCONS(int, digits, CHAR_BIT);
  _STCONS(int, digits10, CHAR_BIT * 301L / 1000);
};

// CLASS numeric_limits<short>
template<> class numeric_limits<short>
  : public _Num_int_base
{       // limits for type short
public:
  typedef short _Ty;

  static constexpr _Ty (min)() _THROW0()
  {       // return minimum value
    return SHRT_MIN;
  }

  static constexpr _Ty (max)() _THROW0()
  {       // return maximum value
    return SHRT_MAX;
  }

  static constexpr _Ty lowest() _THROW0()
  {       // return most negative value
    return (min)();
  }

  static constexpr _Ty epsilon() _THROW0()
  {       // return smallest effective increment from 1.0
    return 0;
  }

  static constexpr _Ty round_error() _THROW0()
  {       // return largest rounding error
    return 0;
  }

  static constexpr _Ty denorm_min() _THROW0()
  {       // return minimum denormalized value
    return 0;
  }

  static constexpr _Ty infinity() _THROW0()
  {       // return positive infinity
    return 0;
  }

  static constexpr _Ty quiet_NaN() _THROW0()
  {       // return non-signaling NaN
    return 0;
  }

  static constexpr _Ty signaling_NaN() _THROW0()
  {       // return signaling NaN
    return 0;
  }

  _STCONS(bool, is_signed, true);
  _STCONS(int, digits, CHAR_BIT * sizeof (short) - 1);
  _STCONS(int, digits10, (CHAR_BIT * sizeof (short) - 1) * 301L / 1000);
};

// CLASS numeric_limits<unsigned short>
template<> class numeric_limits<unsigned short>
  : public _Num_int_base
{       // limits for type unsigned short
public:
  typedef unsigned short _Ty;

  static constexpr _Ty (min)() _THROW0()
  {       // return minimum value
    return 0;
  }

  static constexpr _Ty (max)() _THROW0()
  {       // return maximum value
    return USHRT_MAX;
  }

  static constexpr _Ty lowest() _THROW0()
  {       // return most negative value
    return (min)();
  }

  static constexpr _Ty epsilon() _THROW0()
  {       // return smallest effective increment from 1.0
    return 0;
  }

  static constexpr _Ty round_error() _THROW0()
  {       // return largest rounding error
    return 0;
  }

  static constexpr _Ty denorm_min() _THROW0()
  {       // return minimum denormalized value
    return 0;
  }

  static constexpr _Ty infinity() _THROW0()
  {       // return positive infinity
    return 0;
  }

  static constexpr _Ty quiet_NaN() _THROW0()
  {       // return non-signaling NaN
    return 0;
  }

  static constexpr _Ty signaling_NaN() _THROW0()
  {       // return signaling NaN
    return 0;
  }

  _STCONS(bool, is_signed, false);
  _STCONS(int, digits, CHAR_BIT * sizeof (unsigned short));
  _STCONS(int, digits10, CHAR_BIT * sizeof (unsigned short) * 301L / 1000);
};

// CLASS numeric_limits<char16_t>
template<> class numeric_limits<char16_t>
  : public _Num_int_base
{       // limits for type char16_t
public:
  typedef char16_t _Ty;

  static constexpr _Ty (min)() _THROW0()
  {       // return minimum value
    return 0;
  }

  static constexpr _Ty (max)() _THROW0()
  {       // return maximum value
    return USHRT_MAX;
  }

  static constexpr _Ty lowest() _THROW0()
  {       // return most negative value
    return (min)();
  }

  static constexpr _Ty epsilon() _THROW0()
  {       // return smallest effective increment from 1.0
    return 0;
  }

  static constexpr _Ty round_error() _THROW0()
  {       // return largest rounding error
    return 0;
  }

  static constexpr _Ty denorm_min() _THROW0()
  {       // return minimum denormalized value
    return 0;
  }

  static constexpr _Ty infinity() _THROW0()
  {       // return positive infinity
    return 0;
  }

  static constexpr _Ty quiet_NaN() _THROW0()
  {       // return non-signaling NaN
    return 0;
  }

    static constexpr _Ty signaling_NaN() _THROW0()
  {       // return signaling NaN
    return 0;
  }

  _STCONS(bool, is_signed, false);
  _STCONS(int, digits, CHAR_BIT * sizeof (char16_t));
  _STCONS(int, digits10, CHAR_BIT * sizeof (char16_t) * 301L / 1000);
};

// CLASS numeric_limits<int>
template<> class numeric_limits<int>
  : public _Num_int_base
{       // limits for type int
public:
  typedef int _Ty;

  static constexpr _Ty (min)() _THROW0()
  {       // return minimum value
    return INT_MIN;
  }

  static constexpr _Ty (max)() _THROW0()
  {       // return maximum value
    return INT_MAX;
  }

  static constexpr _Ty lowest() _THROW0()
  {       // return most negative value
    return (min)();
  }

  static constexpr _Ty epsilon() _THROW0()
  {       // return smallest effective increment from 1.0
    return 0;
  }

  static constexpr _Ty round_error() _THROW0()
  {       // return largest rounding error
    return 0;
  }

  static constexpr _Ty denorm_min() _THROW0()
  {       // return minimum denormalized value
    return 0;
  }

  static constexpr _Ty infinity() _THROW0()
  {       // return positive infinity
    return 0;
  }

  static constexpr _Ty quiet_NaN() _THROW0()
  {       // return non-signaling NaN
    return 0;
  }

  static constexpr _Ty signaling_NaN() _THROW0()
  {       // return signaling NaN
    return 0;
  }

  _STCONS(bool, is_signed, true);
  _STCONS(int, digits, CHAR_BIT * sizeof (int) - 1);
  _STCONS(int, digits10, (CHAR_BIT * sizeof (int) - 1) * 301L / 1000);
};

// CLASS numeric_limits<unsigned int>
template<> class numeric_limits<unsigned int>
  : public _Num_int_base
{       // limits for type unsigned int
public:
  typedef unsigned int _Ty;

  static constexpr _Ty (min)() _THROW0()
  {       // return minimum value
    return 0;
  }

  static constexpr _Ty (max)() _THROW0()
  {       // return maximum value
    return UINT_MAX;
  }

  static constexpr _Ty lowest() _THROW0()
  {       // return most negative value
    return (min)();
  }

  static constexpr _Ty epsilon() _THROW0()
  {       // return smallest effective increment from 1.0
    return 0;
  }

  static constexpr _Ty round_error() _THROW0()
  {       // return largest rounding error
    return 0;
  }

  static constexpr _Ty denorm_min() _THROW0()
  {       // return minimum denormalized value
    return 0;
  }

  static constexpr _Ty infinity() _THROW0()
  {       // return positive infinity
    return 0;
  }

  static constexpr _Ty quiet_NaN() _THROW0()
  {       // return non-signaling NaN
    return 0;
  }

  static constexpr _Ty signaling_NaN() _THROW0()
  {       // return signaling NaN
    return 0;
  }

  _STCONS(bool, is_signed, false);
  _STCONS(int, digits, CHAR_BIT * sizeof (unsigned int));
  _STCONS(int, digits10, CHAR_BIT * sizeof (unsigned int) * 301L / 1000);
};

// CLASS numeric_limits<long>
template<> class numeric_limits<long>
  : public _Num_int_base
{       // limits for type long
public:
  typedef long _Ty;

  static constexpr _Ty (min)() _THROW0()
  {       // return minimum value
    return LONG_MIN;
  }

  static constexpr _Ty (max)() _THROW0()
  {       // return maximum value
    return LONG_MAX;
  }

  static constexpr _Ty lowest() _THROW0()
  {       // return most negative value
    return (min)();
  }

  static constexpr _Ty epsilon() _THROW0()
  {       // return smallest effective increment from 1.0
    return 0;
  }

  static constexpr _Ty round_error() _THROW0()
  {       // return largest rounding error
    return 0;
  }

  static constexpr _Ty denorm_min() _THROW0()
  {       // return minimum denormalized value
    return 0;
  }

  static constexpr _Ty infinity() _THROW0()
  {       // return positive infinity
    return 0;
  }

  static constexpr _Ty quiet_NaN() _THROW0()
  {       // return non-signaling NaN
    return 0;
  }

  static constexpr _Ty signaling_NaN() _THROW0()
  {       // return signaling NaN
    return 0;
  }

  _STCONS(bool, is_signed, true);
  _STCONS(int, digits, CHAR_BIT * sizeof (long) - 1);
  _STCONS(int, digits10, (CHAR_BIT * sizeof (long) - 1) * 301L / 1000);
};

// CLASS numeric_limits<unsigned long>
template<> class numeric_limits<unsigned long>
  : public _Num_int_base
{       // limits for type unsigned long
public:
  typedef unsigned long _Ty;

  static constexpr _Ty (min)() _THROW0()
  {       // return minimum value
    return 0;
  }

  static constexpr _Ty (max)() _THROW0()
  {       // return maximum value
    return ULONG_MAX;
  }

  static constexpr _Ty lowest() _THROW0()
  {       // return most negative value
    return (min)();
  }

  static constexpr _Ty epsilon() _THROW0()
  {       // return smallest effective increment from 1.0
    return 0;
  }

  static constexpr _Ty round_error() _THROW0()
  {       // return largest rounding error
    return 0;
  }

  static constexpr _Ty denorm_min() _THROW0()
  {       // return minimum denormalized value
    return 0;
  }

  static constexpr _Ty infinity() _THROW0()
  {       // return positive infinity
    return 0;
  }

  static constexpr _Ty quiet_NaN() _THROW0()
  {       // return non-signaling NaN
    return 0;
  }

  static constexpr _Ty signaling_NaN() _THROW0()
  {       // return signaling NaN
    return 0;
  }

  _STCONS(bool, is_signed, false);
  _STCONS(int, digits, CHAR_BIT * sizeof (unsigned long));
  _STCONS(int, digits10, CHAR_BIT * sizeof (unsigned long) * 301L / 1000);
};

// CLASS numeric_limits<char32_t>
template<> class numeric_limits<char32_t>
  : public _Num_int_base
{       // limits for type char32_t
public:
  typedef char32_t _Ty;

  static constexpr _Ty (min)() _THROW0()
  {       // return minimum value
    return 0;
  }

  static constexpr _Ty (max)() _THROW0()
  {       // return maximum value
    return (_Ty)-1;
  }

  static constexpr _Ty lowest() _THROW0()
  {       // return most negative value
    return (min)();
  }

  static constexpr _Ty epsilon() _THROW0()
  {       // return smallest effective increment from 1.0
    return 0;
  }

  static constexpr _Ty round_error() _THROW0()
  {       // return largest rounding error
    return 0;
  }

  static constexpr _Ty denorm_min() _THROW0()
  {       // return minimum denormalized value
    return 0;
  }

  static constexpr _Ty infinity() _THROW0()
  {       // return positive infinity
    return 0;
  }

  static constexpr _Ty quiet_NaN() _THROW0()
  {       // return non-signaling NaN
    return 0;
  }

  static constexpr _Ty signaling_NaN() _THROW0()
  {       // return signaling NaN
    return 0;
  }

  _STCONS(bool, is_signed, false);
  _STCONS(int, digits, CHAR_BIT * sizeof (char32_t));
  _STCONS(int, digits10, CHAR_BIT * sizeof (char32_t) * 301L / 1000);
};

// CLASS numeric_limits<long long>
template<> class numeric_limits<long long>
  : public _Num_int_base
{       // limits for type long long
public:
  typedef long long _Ty;

  static constexpr _Ty (min)() _THROW0()
  {       // return minimum value
    return -__SIGNED_LONG_LONG_MAX__ - 1;
  }

  static constexpr _Ty (max)() _THROW0()
  {       // return maximum value
    return __SIGNED_LONG_LONG_MAX__;
  }

  static constexpr _Ty lowest() _THROW0()
  {       // return most negative value
    return (min)();
  }

  static constexpr _Ty epsilon() _THROW0()
  {       // return smallest effective increment from 1.0
    return 0;
  }

  static constexpr _Ty round_error() _THROW0()
  {       // return largest rounding error
    return 0;
  }

  static constexpr _Ty denorm_min() _THROW0()
  {       // return minimum denormalized value
    return 0;
  }

  static constexpr _Ty infinity() _THROW0()
  {       // return positive infinity
    return 0;
  }

  static constexpr _Ty quiet_NaN() _THROW0()
  {       // return non-signaling NaN
    return 0;
  }

  static constexpr _Ty signaling_NaN() _THROW0()
  {       // return signaling NaN
    return 0;
  }

  _STCONS(bool, is_signed, true);
  _STCONS(int, digits, CHAR_BIT * sizeof (long long) - 1);
  _STCONS(int, digits10, (CHAR_BIT * sizeof (long long) - 1) * 301L / 1000);
};

// CLASS numeric_limits<unsigned long long>
template<> class numeric_limits<unsigned long long>
  : public _Num_int_base
{       // limits for type unsigned long long
public:
  typedef unsigned long long _Ty;

  static constexpr _Ty (min)() _THROW0()
  {       // return minimum value
    return 0;
  }

  static constexpr _Ty (max)() _THROW0()
  {       // return maximum value
    return __UNSIGNED_LONG_LONG_MAX__;
  }

  static constexpr _Ty lowest() _THROW0()
  {       // return most negative value
    return (min)();
  }

  static constexpr _Ty epsilon() _THROW0()
  {       // return smallest effective increment from 1.0
    return 0;
  }

  static constexpr _Ty round_error() _THROW0()
  {       // return largest rounding error
    return 0;
  }

  static constexpr _Ty denorm_min() _THROW0()
  {       // return minimum denormalized value
    return 0;
  }

  static constexpr _Ty infinity() _THROW0()
  {       // return positive infinity
    return 0;
  }

  static constexpr _Ty quiet_NaN() _THROW0()
  {       // return non-signaling NaN
    return 0;
  }

  static constexpr _Ty signaling_NaN() _THROW0()
  {       // return signaling NaN
    return 0;
  }

  _STCONS(bool, is_signed, false);
  _STCONS(int, digits, CHAR_BIT * sizeof (unsigned long long));
  _STCONS(int, digits10, CHAR_BIT * sizeof (unsigned long long) * 301L / 1000);
};

// CLASS numeric_limits<float>
template<> class numeric_limits<float>
  : public _Num_float_base
{       // limits for type float
public:
  typedef float _Ty;

  static constexpr _Ty (min)() _THROW0()
  {       // return minimum value
    return FLT_MIN;
  }

  static constexpr _Ty (max)() _THROW0()
  {       // return maximum value
    return FLT_MAX;
  }

  static constexpr _Ty lowest() _THROW0()
  {       // return most negative value
    return -(max)();
  }

  static constexpr _Ty epsilon() _THROW0()
  {       // return smallest effective increment from 1.0
    return FLT_EPSILON;
  }

  static constexpr _Ty round_error() _THROW0()
  {       // return largest rounding error
    return 0.5F;
  }

  static constexpr _Ty denorm_min() _THROW0()
  {       // return minimum denormalized value
    #if __SUBNORMAL_FLOATING_POINTS__
      return min() * epsilon();
    #else
      return min();
    #endif
  }

  static constexpr _Ty infinity() _THROW0()
  {       // return positive infinity
    return 0.Infinity;
  }

  static constexpr _Ty quiet_NaN() _THROW0()
  {       // return non-signaling NaN
    return 0.NaN;
  }

  static constexpr _Ty signaling_NaN() _THROW0()
  {       // return signaling NaN
    return 0.NaN;
  }

  _STCONS(int, digits, FLT_MANT_DIG);
  _STCONS(int, digits10, FLT_DIG);
  _STCONS(int, max_digits10, 2 + FLT_MANT_DIG * 301L / 1000);
  _STCONS(int, max_exponent, (int)FLT_MAX_EXP);
  _STCONS(int, max_exponent10, (int)FLT_MAX_10_EXP);
  _STCONS(int, min_exponent, (int)FLT_MIN_EXP);
  _STCONS(int, min_exponent10, (int)FLT_MIN_10_EXP);
};

// CLASS numeric_limits<double>
template<> class numeric_limits<double>
  : public _Num_float_base
{       // limits for type double
public:
  typedef double _Ty;

  static constexpr _Ty (min)() _THROW0()
  {       // return minimum value
    return DBL_MIN;
  }

  static constexpr _Ty (max)() _THROW0()
  {       // return maximum value
    return DBL_MAX;
  }

  static constexpr _Ty lowest() _THROW0()
  {       // return most negative value
    return -(max)();
  }

  static constexpr _Ty epsilon() _THROW0()
  {       // return smallest effective increment from 1.0
    return DBL_EPSILON;
  }

  static constexpr _Ty round_error() _THROW0()
  {       // return largest rounding error
    return 0.5;
  }

  static constexpr _Ty denorm_min() _THROW0()
  {       // return minimum denormalized value
    #if __SUBNORMAL_FLOATING_POINTS__
      return min() * epsilon();
    #else
      return min();
    #endif
  }

  static constexpr _Ty infinity() _THROW0()
  {       // return positive infinity
    return 0.Infinity;
  }

  static constexpr _Ty quiet_NaN() _THROW0()
  {       // return non-signaling NaN
    return 0.NaN;
  }

  static constexpr _Ty signaling_NaN() _THROW0()
  {       // return signaling NaN
    return 0.NaN;
  }

  _STCONS(int, digits, DBL_MANT_DIG);
  _STCONS(int, digits10, DBL_DIG);
  _STCONS(int, max_digits10, 2 + DBL_MANT_DIG * 301L / 1000);
  _STCONS(int, max_exponent, (int)DBL_MAX_EXP);
  _STCONS(int, max_exponent10, (int)DBL_MAX_10_EXP);
  _STCONS(int, min_exponent, (int)DBL_MIN_EXP);
  _STCONS(int, min_exponent10, (int)DBL_MIN_10_EXP);
};

// CLASS numeric_limits<long double>
template<> class numeric_limits<long double>
  : public _Num_float_base
{       // limits for type long double
public:
  typedef long double _Ty;

  static constexpr _Ty (min)() _THROW0()
  {       // return minimum value
    return LDBL_MIN;
  }

  static constexpr _Ty (max)() _THROW0()
  {       // return maximum value
    return LDBL_MAX;
  }

  static constexpr _Ty lowest() _THROW0()
  {       // return most negative value
    return -(max)();
  }

  static constexpr _Ty epsilon() _THROW0()
  {       // return smallest effective increment from 1.0
    return LDBL_EPSILON;
  }

  static constexpr _Ty round_error() _THROW0()
  {       // return largest rounding error
    return 0.5L;
  }

  static constexpr _Ty denorm_min() _THROW0()
  {       // return minimum denormalized value
    #if __SUBNORMAL_FLOATING_POINTS__
      return min() * epsilon();
    #else
      return min();
    #endif
  }

  static constexpr _Ty infinity() _THROW0()
  {       // return positive infinity
    return 0.Infinity;
  }

  static constexpr _Ty quiet_NaN() _THROW0()
  {       // return non-signaling NaN
    return 0.NaN;
  }

  static constexpr _Ty signaling_NaN() _THROW0()
  {       // return signaling NaN
    return 0.NaN;
  }

  _STCONS(int, digits, LDBL_MANT_DIG);
  _STCONS(int, digits10, LDBL_DIG);
  _STCONS(int, max_digits10, 2 + LDBL_MANT_DIG * 301L / 1000);
  _STCONS(int, max_exponent, (int)LDBL_MAX_EXP);
  _STCONS(int, max_exponent10, (int)LDBL_MAX_10_EXP);
  _STCONS(int, min_exponent, (int)LDBL_MIN_EXP);
  _STCONS(int, min_exponent10, (int)LDBL_MIN_10_EXP);
};

} /* namespace std */

#endif /* _LIMITS_ */

/*
 * Copyright (c) by P.J. Plauger. All rights reserved.
 * Consult your license regarding permissions and restrictions.
V6.50:0576 */
