/*
 * Copyright (c) 1999 Johnny C. Lam.
 * All rights reserved.
 *
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  The author makes no representations
 * about the suitability of this software for any purpose.  It is
 * provided "as is" without express or implied warranty.
 */

#ifndef STD_INTERNAL_LIMITS_H
#define STD_INTERNAL_LIMITS_H

#ifndef CFLOAT_INCLUDED
#include <cfloat>
#define CFLOAT_INCLUDED
#endif

#ifndef CLIMITS_INCLUDED
#include <climits>
#define CLIMITS_INCLUDED
#endif

STD_BEGIN_NAMESPACE

template <class T>
class numeric_limits {
public:
    typedef T numeric_type;
    
    static const bool	is_specialized = false;
};

template <>
class numeric_limits<char> {
public:
    typedef char numeric_type;
    
    static const bool	is_specialized = true;

    static const bool	is_signed = true;
    static const bool	is_integer = true;
    static const bool	is_exact = true;

    inline static numeric_type	min() throw() { return SCHAR_MIN; }
    inline static numeric_type	max() throw() { return SCHAR_MAX; }
};

template <>
class numeric_limits<unsigned char> {
public:
    typedef unsigned char numeric_type;
    
    static const bool	is_specialized = true;

    static const bool	is_signed = false;
    static const bool	is_integer = true;
    static const bool	is_exact = true;

    inline static numeric_type	min() throw() { return 0; }
    inline static numeric_type	max() throw() { return UCHAR_MAX; }
};

template <>
class numeric_limits<int> {
public:
    typedef int	numeric_type;
    
    static const bool	is_specialized = true;

    static const bool	is_signed = true;
    static const bool	is_integer = true;
    static const bool	is_exact = true;

    inline static numeric_type	min() throw() { return INT_MIN; }
    inline static numeric_type	max() throw() { return INT_MAX; }
};

template <>
class numeric_limits<unsigned int> {
public:
    typedef unsigned int numeric_type;
    
    static const bool	is_specialized = true;

    static const bool	is_signed = false;
    static const bool	is_integer = true;
    static const bool	is_exact = true;

    inline static numeric_type	min() throw() { return 0; }
    inline static numeric_type	max() throw() { return UINT_MAX; }
};

template <>
class numeric_limits<long> {
public:
    typedef long	numeric_type;

    static const bool	is_specialized = true;

    static const bool	is_signed = true;
    static const bool	is_integer = true;
    static const bool	is_exact = true;

    inline static numeric_type	min() throw() { return LONG_MIN; }
    inline static numeric_type	max() throw() { return LONG_MAX; }
};

template <>
class numeric_limits<float> {
public:
    typedef float	numeric_type;

    static const bool	is_specialized = true;

    static const int	radix = FLT_RADIX;
    static const int	digits = FLT_MANT_DIG;
    static const int	digits10 = FLT_DIG;

    static const bool	is_signed = true;
    static const bool	is_integer = false;
    static const bool	is_exact = false;

    inline static numeric_type	min() throw() { return FLT_MIN; }
    inline static numeric_type	max() throw() { return FLT_MAX; }

    inline static numeric_type	epsilon() throw() { return FLT_EPSILON; }

    static const int	min_exponent = FLT_MIN_EXP;
    static const int	min_exponent10 = FLT_MIN_10_EXP;
    static const int	max_exponent = FLT_MAX_EXP;
    static const int	max_exponent10 = FLT_MAX_10_EXP;

    static const bool	has_infinity = false;
};

#ifdef __NetBSD__
extern const char __infinity[];
#endif

template <>
class numeric_limits<double> {
public:
    typedef double	numeric_type;

    static const bool	is_specialized = true;

    static const int	digits = DBL_MANT_DIG;
    static const int	digits10 = DBL_DIG;

    static const bool	is_signed = true;
    static const bool	is_integer = false;
    static const bool	is_exact = false;

    inline static numeric_type	min() throw() { return DBL_MIN; }
    inline static numeric_type	max() throw() { return DBL_MAX; }

    inline static numeric_type	epsilon() throw() { return DBL_EPSILON; }
#ifdef __NetBSD__
    inline static numeric_type	infinity() throw() {
	return *(reinterpret_cast<const double *>(__infinity));
    }
#endif

    static const int	min_exponent = DBL_MIN_EXP;
    static const int	min_exponent10 = DBL_MIN_10_EXP;
    static const int	max_exponent = DBL_MAX_EXP;
    static const int	max_exponent10 = DBL_MAX_10_EXP;

    static const bool	has_infinity = true;
};

STD_END_NAMESPACE

#endif /* STD_INTERNAL_LIMITS_H */
