/**************************************************************************
 *{@C
 *	Copyright:	1988-2020 Paul Obermeier (obermeier@poSoft.de)
 *
 *	Module:		Utilities
 *	Filename:	UT_Const.h
 *
 *	Author:		Paul Obermeier
 *
 *      Description:    Machine independent constant definitions.
 *
 *	Additional documentation:
 *			None.
 *
 **************************************************************************/

#ifndef __UT_CONST_H__
#define __UT_CONST_H__

#include "UT_Compat.h"

/*
    MinFloat32		The smallest (normalized or denormalized)
			Float32 value greater than zero
    MinNrmFloat32	The smallest normalized Float32 value greater than zero
    MaxFloat32		The largest possible Float32 value

    MinFloat64		The smallest (normalized or denormalized)
			Float64 value greater than zero
    MinNrmFloat64 	The smallest normalized Float64 value greater than zero
    MaxFloat64		The largest possible Float64 value

    Float32Prec		Precision of Float32 numbers
    Float64Prec		Precision of Float64 numbers

    MaxUInt64		The largest  possible UInt64 value  (64 bit)
    MaxInt64		The largest  possible Int64  value  (64 bit)
    MinInt64		The smallest possible Int64  value  (64 bit)

    MaxUInt32		The largest  possible UInt32 value  (32 bit)
    MaxInt32		The largest  possible Int32  value  (32 bit)
    MinInt32		The smallest possible Int32  value  (32 bit)

    MaxUInt16		The largest  possible UInt16 value  (16 bit)
    MaxInt16		The largest  possible Int16  value  (16 bit)
    MinInt16		The smallest possible Int16  value  (16 bit)

    MaxUInt8		The largest  possible UInt8  value   ( 8 bit)
    MaxInt8		The largest  possible Int8   value   ( 8 bit)
    MinInt8		The smallest possible Int8   value   ( 8 bit)

    The assertion for normalized numbers is:
    1.0f + MinNrmFloat32 != 1.0f
    1.0  + MinNrmFloat64 != 1.0

    The "Precision" of a Float32 or Float64 number is:
    1.0 / (numeric value of least significant bit in mantissa).
*/

#if defined (USE_PLATFORM_CONST)

    #if defined (Linux)

	#include <float.h>

	#define PLAT_MINFLOAT	FLT_MIN
	#define PLAT_MAXFLOAT	FLT_MAX
	#define PLAT_MINDOUBLE	DBL_MIN
	#define PLAT_MAXDOUBLE	DBL_MAX
	#define PLAT_FSIGNIF	FLT_MANT_DIG
	#define PLAT_DSIGNIF	DBL_MANT_DIG
	#define PLAT_FLOATPREC	FLT_EPSILON
	#define PLAT_DOUBLEPREC	DBL_EPSILON

    #elif defined (Darwin)

	#include <float.h>

	#define PLAT_MINFLOAT	FLT_MIN
	#define PLAT_MAXFLOAT	FLT_MAX
	#define PLAT_MINDOUBLE	DBL_MIN
	#define PLAT_MAXDOUBLE	DBL_MAX
	#define PLAT_FSIGNIF	FLT_MANT_DIG
	#define PLAT_DSIGNIF	DBL_MANT_DIG
	#define PLAT_FLOATPREC	FLT_EPSILON
	#define PLAT_DOUBLEPREC	DBL_EPSILON

    #elif defined (CC_IS_MSC)

	#include <float.h>

	#define PLAT_MINFLOAT	FLT_MIN
	#define PLAT_MAXFLOAT	FLT_MAX
	#define PLAT_MINDOUBLE	DBL_MIN
	#define PLAT_MAXDOUBLE	DBL_MAX
	#define PLAT_FSIGNIF	FLT_MANT_DIG
	#define PLAT_DSIGNIF	DBL_MANT_DIG
	#define PLAT_FLOATPREC	FLT_EPSILON
	#define PLAT_DOUBLEPREC	DBL_EPSILON

    #elif defined (mingw)

        /* Cygwin and MSYS don't define the needed values for floating point
	 * numbers. We take the values from Visual C++ 6.0 file "float.h".
	 */

	#define PLAT_MINFLOAT	1.175494351e-38F
	#define PLAT_MAXFLOAT	3.402823466e+38F
	#define PLAT_MINDOUBLE	2.2250738585072014e-308
	#define PLAT_MAXDOUBLE	1.7976931348623158e+308
	#define PLAT_FSIGNIF	24
	#define PLAT_DSIGNIF	53
	#define PLAT_FLOATPREC	1.192092896e-07F
	#define PLAT_DOUBLEPREC	2.2204460492503131e-016

    #else

	#error "Definition of MINFLOAT, MAXFLOAT etc. missing here"

    #endif

    #define PO_MINFLOAT		PLAT_MINFLOAT
    #define PO_MAXFLOAT		PLAT_MAXFLOAT
    #define PO_MINDOUBLE	PLAT_MINDOUBLE
    #define PO_MAXDOUBLE	PLAT_MAXDOUBLE
    #define PO_FSIGNIF		PLAT_FSIGNIF
    #define PO_DSIGNIF		PLAT_DSIGNIF
    #define PO_FLOATPREC	PLAT_FLOATPREC
    #define PO_DOUBLEPREC	PLAT_DOUBLEPREC

#else

    /* These numbers have been determined to fit the needs of all
     * supported machine and compiler versions.
     * The defines for the minimum values
     * PO_MINFLOAT, PO_MINDOUBLE, PO_FLOATPREC, PO_DOUBLEPREC
     * must be the biggest value of all supported platforms.
     * The defines for the maximum values 
     * PO_MAXFLOAT, PO_MAXDOUBLE, PO_FSIGNIF, PO_DSIGNIF
     * must be the lowest value of all supported platforms.
     *
     * If adding a new platform, add a new entry above. Then compile and
     * execute UT_ConstTest to check, if the platform specific values fit
     * in the range supplied by the numbers below.
     */

    #define PO_MINFLOAT		1.175494351e-38F
    #define PO_MAXFLOAT		3.402823466e+38F
    #define PO_MINDOUBLE	2.2250738585072014e-308
    #define PO_MAXDOUBLE	1.7976931348623157e+308
    #define PO_FSIGNIF		24
    #define PO_DSIGNIF		53
    #define PO_FLOATPREC	1.19209290e-07F
    #define PO_DOUBLEPREC	2.2204460492503131e-016

#endif /* USE_PLATFORM_CONST */

#define	MinFloat32	PO_MINFLOAT
#define MaxFloat32	PO_MAXFLOAT
#define Float32Prec	PO_FLOATPREC

#define MinFloat64	PO_MINDOUBLE
#define MaxFloat64	PO_MAXDOUBLE
#define Float64Prec	PO_DOUBLEPREC

#define MinNrmFloat32	(MinFloat32 * (1.0F / Float32Prec))
#define MinNrmFloat64	(MinFloat64 * (1.0  / Float64Prec))

#define Float32MantLen	PO_FSIGNIF
#define Float64MantLen	PO_DSIGNIF

#define MaxUInt64 ((UInt64)18446744073709551615)
#define MaxInt64  ((Int64) 9223372036854775807)
#define MinInt64  ((Int64) (-MaxInt64-1))

#define MaxUInt32 ((UInt32)4294967295)
#define MaxInt32  ((Int32) 2147483647)
#define MinInt32  ((Int32)(-MaxInt32-1))

#define MaxUInt16 ((UInt16)65535)
#define MaxInt16  ((Int16) 32767)
#define MinInt16  ((Int16)(-MaxInt16-1))

#define MaxUInt8 ((UInt8)255)
#define MaxInt8  ((Int8) 127)
#define MinInt8  ((Int8)(-MaxInt8-1))

#define UT_PI 3.14159265358979323846264338327950
#define UT_PI2 (3.14159265358979323846264338327950 / 2.0)
#define UT_2PI (3.14159265358979323846264338327950 * 2.0)

#endif /* __UT_CONST_H__ */
