/* This file combines the single and double precision versions of machar, selected by cc -DSP or cc -DDP. This feature provided by D. G. Hough, August 3, 1988. */ #ifndef DP #define SP #endif #ifdef SP #define REAL float #define ZERO 0.0 #define ONE 1.0 #define PREC "Single " #define REALSIZE 1 #endif #ifdef DP #define REAL double #define ZERO 0.0e0 #define ONE 1.0e0 #define PREC "Double " #define REALSIZE 2 #endif #include #include #define ABS(xxx) ((xxx>ZERO)?(xxx):(-xxx)) extern void rmachar(int *, int *, int *, int *, int *, int *, int *, int *, int *, float *, float *, float *, float *); main(void) { /* This program prints hardware-determined double-precision machine constants obtained from rmachar. Dmachar is a C translation of the Fortran routine MACHAR from W. J. Cody, "MACHAR: A subroutine to dynamically determine machine parameters". TOMS (14), 1988. Descriptions of the machine constants are given in the prologue comments in rmachar. Subprograms called rmachar Original driver: Richard Bartels, October 16, 1985 Modified by: W. J. Cody July 26, 1988 ********** */ int ibeta, iexp, irnd, it, machep, maxexp, minexp, negep, ngrd; int i; REAL eps, epsneg, xmax, xmin; union wjc { long int jj[REALSIZE]; REAL xbig; } uval; rmachar(&ibeta, &it, &irnd, &ngrd, &machep, &negep, &iexp, &minexp, &maxexp, &eps, &epsneg, &xmin, &xmax); printf(PREC); printf(" precision MACHAR constants\n"); printf("ibeta = %d\n", ibeta); printf("it = %d\n", it); printf("irnd = %d\n", irnd); printf("ngrd = %d\n", ngrd); printf("machep = %d\n", machep); printf("negep = %d\n", negep); printf("iexp = %d\n", iexp); printf("minexp = %d\n", minexp); printf("maxexp = %d\n", maxexp); #define DISPLAY(s,x) { \ uval.xbig = x ; \ printf(s); \ printf(" %24.16e ",(double) x) ; \ for(i=0;i y)) break; tmp1 = tmp * betain; if (tmp1 * beta == z) break; i = i + 1; k = k + k; } /* determine k such that (1/beta)**k does not underflow first set k = 2 ** i */ (*iexp) = i + 1; mx = k + k; if (*ibeta == 10) { /* for decimal machines only */ (*iexp) = 2; iz = *ibeta; while (k >= iz) { iz = iz * (*ibeta); (*iexp) = (*iexp) + 1; } mx = iz + iz - 1; } /* loop to determine minexp, xmin. exit from loop is signaled by an underflow. */ for (;;) { (*xmin) = y; y = y * betain; a = y * one; tmp = y * t; tmp1 = a + a; if ((tmp1 == zero) || (ABS(y) >= (*xmin))) break; k = k + 1; tmp1 = tmp * betain; tmp1 = tmp1 * beta; if ((tmp1 == y) && (tmp != y)) { nxres = 3; *xmin = y; break; } } (*minexp) = -k; /* determine maxexp, xmax */ if ((mx <= k + k - 3) && ((*ibeta) != 10)) { mx = mx + mx; (*iexp) = (*iexp) + 1; } (*maxexp) = mx + (*minexp); /* Adjust *irnd to reflect partial underflow. */ (*irnd) = (*irnd) + nxres; /* Adjust for IEEE style machines. */ if ((*irnd) >= 2) (*maxexp) = (*maxexp) - 2; /* adjust for machines with implicit leading bit in binary significand and machines with radix point at extreme right of significand. */ i = (*maxexp) + (*minexp); if (((*ibeta) == 2) && (i == 0)) (*maxexp) = (*maxexp) - 1; if (i > 20) (*maxexp) = (*maxexp) - 1; if (a != y) (*maxexp) = (*maxexp) - 2; (*xmax) = one - (*epsneg); tmp = (*xmax) * one; if (tmp != (*xmax)) (*xmax) = one - beta * (*epsneg); (*xmax) = (*xmax) / (beta * beta * beta * (*xmin)); i = (*maxexp) + (*minexp) + 3; if (i > 0) { for (j = 1; j <= i; j++) { if ((*ibeta) == 2) (*xmax) = (*xmax) + (*xmax); if ((*ibeta) != 2) (*xmax) = (*xmax) * beta; } } }