/*********************************************************************** This file defines typedefs and symbols for interfacing C IEEE 754 support functions to Fortran code. The model representation of a t-digit floating-point number is x = (-1)**s * 0.d1 d2 d3 ... dt * beta**e where the digits dk satisfy 0 <= dk < beta The fractional part, which we call the significand, is defined to lie in the range 1/beta <= significand < 1 For IEEE floating-point, with its hidden bit and denormalized numbers, we adjust parameters to conform to our model. Denormalized numbers are normalized by expanding their exponent range. IEEE floating point arithmetic has these formats, where s is the sign bit, e is an exponent bit, and f is a fraction bit. Single precision: seee eeee efff ffff ffff ffff ffff ffff significand = 1.fff ffff ffff ffff ffff ffff (1 + 23 bits) exponent bias = 127 Double precision: seee eeee eeee ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff significand = 1.ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff (1 + 52 bits) exponent bias = 1023 Here are some sample IEEE bit patterns: ======================================================================== LITTLE ENDIAN Single precision 0 0x00000000 1 0x3f800000 -1 0xbf800000 2 0x40000000 -2 0xc0000000 1.19209e-07 0x34000000 eps(1.0) -1.19209e-07 0xb4000000 1.17549e-38 0x00800000 smallest normal -1.17549e-38 0x80800000 1.4013e-45 0x00000001 smallest subnormal -1.4013e-45 0x80000001 3.4028235e+38 0x7f7fffff largest normal -3.4028235e+38 0xff7fffff Infinity 0x7f800000 -Infinity 0xff800000 NaN 0x7f80ffff Double precision 0 0x00000000 00000000 1 0x00000000 3ff00000 -1 0x00000000 bff00000 2 0x00000000 40000000 -2 0x00000000 c0000000 1.11022e-16 0x00000002 3ca00000 eps(1.0) -1.11022e-16 0x00000002 bca00000 2.22507e-308 0x00000000 00100000 smallest normal -2.22507e-308 0x00000000 80100000 4.94066e-324 0x00000001 00000000 smallest subnormal -4.94066e-324 0x00000001 80000000 1.79769e+308 0xffffffff 7fefffff largest normal -1.79769e+308 0xffffffff ffefffff Infinity 0x00000000 7ff00000 -Infinity 0x00000000 fff00000 NaN 0xffffffff 7ff7ffff ======================================================================== BIG ENDIAN Single precision 0 0x00000000 1 0x3f800000 -1 0xbf800000 2 0x40000000 -2 0xc0000000 1.19209e-07 0x34000000 eps(1.0) -1.19209e-07 0xb4000000 1.17549e-38 0x00800000 smallest normal -1.17549e-38 0x80800000 1.4013e-45 0x00000001 smallest subnormal -1.4013e-45 0x80000001 3.4028235e+38 0x7f7fffff largest normal -3.4028235e+38 0xff7fffff Inf 0x7f800000 -Inf 0xff800000 NaN 0x7fffffff Double precision 0 0x00000000 00000000 1 0x3ff00000 00000000 -1 0xbff00000 00000000 2 0x40000000 00000000 -2 0xc0000000 00000000 1.11022e-16 0x3ca00000 00000002 eps(1.0) -1.11022e-16 0xbca00000 00000002 2.22507e-308 0x00100000 00000000 smallest normal -2.22507e-308 0x80100000 00000000 4.94066e-324 0x00000000 00000001 smallest subnormal -4.94066e-324 0x80000000 00000001 1.79769e+308 0x7fefffff ffffffff largest normal -1.79769e+308 0xffefffff ffffffff Inf 0x7ff00000 00000000 -Inf 0xfff00000 00000000 NaN 0x7fffffff ffffffff ======================================================================== ***********************************************************************/ /* type mappings from Fortran to C */ typedef double DOUBLEPRECISION; typedef float REAL; #if defined(__alpha) typedef int INTEGER; /* need 32-bit integers, not 64-bit ones */ #else typedef long INTEGER; #endif typedef int LOGICAL; /* use int, not long, to avoid conflicts on HP-UX with */ /* system header file declarations of isinf(), isnan() */ typedef union { REAL r; INTEGER i; } REAL_PARTS; /* decomposition of REAL */ typedef union { DOUBLEPRECISION r; INTEGER i[2]; } DOUBLEPRECISION_PARTS; /* decomposition of DOUBLEPRECISION */ /* Fortran LOGICAL values -- compiler dependent! Most (all?) UNIX */ /* Fortran compilers use 0 for .FALSE. and non-zero for .TRUE., like C. */ #ifdef _FALSE_ #undef _FALSE_ #endif #ifdef _TRUE_ #undef _TRUE_ #endif #define _FALSE_ ((LOGICAL)0) #define _TRUE_ ((LOGICAL)1) #define BASE 2 /* number base */ /* stored significand bits in single and double precision */ #define T_SP 23 #define T_DP 52 #define BASE_TO_THE_T_SP ((REAL)8388608.0) #define BASE_TO_THE_T_DP ((DOUBLEPRECISION)4503599627370496.0) #define _SHIFTED_EXPONENT_MASK_SP 0xff #define EXPONENT_MASK_SP 0x7f800000L #define EXPONENT_MASK_DP 0x7ff00000L #define _SHIFTED_EXPONENT_MASK_DP 0x7ff #define _SIGNIFICAND_MASK_SP 0x007fffffL #define _SIGNIFICAND_MASK_DP 0x000fffffL /* Exponent biases such that significand lies in (1/beta) <= significand < 1. These are 1 less than the IEEE biases, because its stored significand lies in 1 <= significand < beta due to the hidden bit. We define them with a leading underscore because they are for internal use only. */ #define _BIAS_SP 126 #define _BIAS_DP 1022 /* Indexes into two-word INTEGER array to account for addressing order */ #if i386 || sun386 || __i386__ || __sun386__ || msdos || MIPSEL || __alpha /* Intel 80xxx or MIPS little endian */ #define DP_LOW 0 #define DP_HIGH 1 #else /* big endian (MIPS, Motorola, SPARC, ...) */ #define DP_LOW 1 #define DP_HIGH 0 #endif /* macros to extract (high-order) significand and exponent as integer values */ #define GET_EXPONENT_SP(x) ((((x) >> T_SP) & \ _SHIFTED_EXPONENT_MASK_SP) - _BIAS_SP) #define GET_EXPONENT_DP(x) ((((x) >> (T_DP - 32)) & \ _SHIFTED_EXPONENT_MASK_DP) - _BIAS_DP) #define SET_EXPONENT_SP(x) (((x) + _BIAS_SP) << T_SP) #define SET_EXPONENT_DP(x) (((x) + _BIAS_DP) << (T_DP - 32)) #define EXPONENT_DENORM_SP (-_BIAS_SP) #define EXPONENT_DENORM_DP (-_BIAS_DP) #define EXPONENT_INFNAN_SP (255 - _BIAS_SP) #define EXPONENT_INFNAN_DP (2047 - _BIAS_DP) #define SIGNIFICAND_SP(x) (((x) & _SIGNIFICAND_MASK_SP)) #define SIGNIFICAND_DP(x) (((x) & _SIGNIFICAND_MASK_DP)) #define MAX_NORMAL_SP 0x7f7fffffL #define MAX_NORMAL_DP 0x7fefffffL #define MAX_NORMAL_Low_DP 0xffffffffL #define MIN_NORMAL_SP 0x00800000L #define MIN_DENORMAL_SP 0x00000001L #define MIN_NORMAL_DP 0x00100000L #define MIN_NORMAL_Low_DP 0x00000000L #define MIN_DENORMAL_DP 0x00000000L #define MIN_DENORMAL_Low_DP 0x00000001L #define Inf_SP 0x7f800000L #define NegInf_SP 0xff800000L #define NaN_SP 0x7fffffffL /* significand is */ /* arbitrary non-zero */ /* High-order words for double-precision Infinity and NaN. */ #define Inf_DP 0x7ff00000L #define Inf_Low_DP 0x00000000L #define NegInf_DP 0xfff00000L #define NegInf_Low_DP 0x00000000L #define NaN_DP 0x7fffffffL /* significand is */ #define NaN_Low_DP 0xffffffffL /* arbitrary non-zero */ #define ISNEG_SP(x) ((x) & 0x80000000L) #define ISNEG_DP(x) ((x) & 0x80000000L) #ifndef ABS #define ABS(x) (((x) < 0.0) ? -(x) : (x)) #endif /* Map external names onto the conventions of the local Fortran compiler. */ #if _AIX || __hppa #define _FTN_NAME_TYPE 1 /* name unchanged */ #endif #if ardent #define _FTN_NAME_TYPE 2 /* name -> NAME */ #endif #ifndef _FTN_NAME_TYPE #define _FTN_NAME_TYPE 3 /* name -> name_ */ #endif #if (_FTN_NAME_TYPE == 2) #define adx ADX #define dadx DADX #define deps DEPS #define deps2 DEPS2 #define dintxp DINTXP #define disden DISDEN #define disinf DISINF #define disnan DISNAN #define dsetxp DSETXP #define eps EPS #define eps2 EPS2 #define intxp INTXP #define isden ISDEN #define isinf ISINF #define isnan ISNAN #define setxp SETXP #endif /* (_FTN_NAME_TYPE == 2) */ #if (_FTN_NAME_TYPE == 3) #define adx adx_ #define dadx dadx_ #define deps deps_ #define deps2 deps2_ #define dintxp dintxp_ #define disden disden_ #define disinf disinf_ #define disnan disnan_ #define dsetxp dsetxp_ #define eps eps_ #define eps2 eps2_ #define intxp intxp_ #define isden isden_ #define isinf isinf_ #define isnan isnan_ #define setxp setxp_ #endif /* (_FTN_NAME_TYPE == 3) */ #if defined(__STDC__) || defined(__cplusplus) #define ARGS(plist) plist #define STDC 1 #define VOID_ARG void #else #define const #define ARGS(plist) () #define STDC 0 #define VOID_ARG #endif #if defined(__cplusplus) extern "C" { #endif DOUBLEPRECISION dadx ARGS((DOUBLEPRECISION *x__, INTEGER *n__)); DOUBLEPRECISION deps ARGS((DOUBLEPRECISION *x__)); INTEGER dintxp ARGS((DOUBLEPRECISION *x__)); DOUBLEPRECISION dsetxp ARGS((DOUBLEPRECISION *x__, INTEGER *n__)); LOGICAL disden ARGS((DOUBLEPRECISION *x__)); LOGICAL disinf ARGS((DOUBLEPRECISION *x__)); LOGICAL disnan ARGS((DOUBLEPRECISION *x__)); REAL adx ARGS((REAL *x__, INTEGER *n__)); REAL eps ARGS((REAL *x__)); INTEGER intxp ARGS((REAL *x__)); REAL setxp ARGS((REAL *x__, INTEGER *n__)); LOGICAL isden ARGS((REAL *x__)); LOGICAL isinf ARGS((REAL *x__)); LOGICAL isnan ARGS((REAL *x__)); #if defined(__cplusplus) }; #endif #if STDC #include #endif #ifndef EXIT_SUCCESS #define EXIT_SUCCESS 0 #endif