📄 slamch.c
字号:
/* + WHILE( ( LEPS.GT.B ).AND.( B.GT.ZERO ) )LOOP */L10: if (leps > b && b > zero) { leps = b; r__1 = half * leps;/* Computing 5th power */ r__3 = two, r__4 = r__3, r__3 *= r__3;/* Computing 2nd power */ r__5 = leps; r__2 = r__4 * (r__3 * r__3) * (r__5 * r__5); c = slamc3_(&r__1, &r__2); r__1 = -(double)c; c = slamc3_(&half, &r__1); b = slamc3_(&half, &c); r__1 = -(double)b; c = slamc3_(&half, &r__1); b = slamc3_(&half, &c); goto L10; }/* + END WHILE */ if (a < leps) { leps = a; }/* Computation of EPS complete. Now find EMIN. Let A = + or - 1, and + or - (1 + BASE**(-3)). Keep dividing A by BETA until (gradual) underflow occurs. This is detected when we cannot recover the previous A. */ rbase = one / lbeta; small = one; for (i = 1; i <= 3; ++i) { r__1 = small * rbase; small = slamc3_(&r__1, &zero);/* L20: */ } a = slamc3_(&one, &small); slamc4_(&ngpmin, &one, &lbeta); r__1 = -(double)one; slamc4_(&ngnmin, &r__1, &lbeta); slamc4_(&gpmin, &a, &lbeta); r__1 = -(double)a; slamc4_(&gnmin, &r__1, &lbeta); ieee = FALSE_; if (ngpmin == ngnmin && gpmin == gnmin) { if (ngpmin == gpmin) { lemin = ngpmin;/* ( Non twos-complement machines, no gradual underflow; e.g., VAX ) */ } else if (gpmin - ngpmin == 3) { lemin = ngpmin - 1 + lt; ieee = TRUE_;/* ( Non twos-complement machines, with gradual underflow; e.g., IEEE standard followers ) */ } else { lemin = min(ngpmin,gpmin);/* ( A guess; no known machine ) */ iwarn = TRUE_; } } else if (ngpmin == gpmin && ngnmin == gnmin) { if ((i__1 = ngpmin - ngnmin, abs(i__1)) == 1) { lemin = max(ngpmin,ngnmin);/* ( Twos-complement machines, no gradual underflow; e.g., CYBER 205 ) */ } else { lemin = min(ngpmin,ngnmin);/* ( A guess; no known machine ) */ iwarn = TRUE_; } } else if ((i__1 = ngpmin - ngnmin, abs(i__1)) == 1 && gpmin == gnmin) { if (gpmin - min(ngpmin,ngnmin) == 3) { lemin = max(ngpmin,ngnmin) - 1 + lt;/* ( Twos-complement machines with gradual underflow; no known machine ) */ } else { lemin = min(ngpmin,ngnmin);/* ( A guess; no known machine ) */ iwarn = TRUE_; } } else {/* Computing MIN */ i__1 = min(ngpmin,ngnmin), i__1 = min(i__1,gpmin); lemin = min(i__1,gnmin);/* ( A guess; no known machine ) */ iwarn = TRUE_; }/* ** Comment out this if block if EMIN is ok */ if (iwarn) { first = TRUE_; printf("\n\n WARNING. The value EMIN may be incorrect:- "); printf("EMIN = %8i\n",lemin); printf("If, after inspection, the value EMIN looks acceptable"); printf("please comment out \n the IF block as marked within the"); printf("code of routine SLAMC2, \n otherwise supply EMIN"); printf("explicitly.\n"); }/* ** Assume IEEE arithmetic if we found denormalised numbers above, or if arithmetic seems to round in the IEEE style, determined in routine SLAMC1. A true IEEE machine should have both things true; however, faulty machines may have one or the other. */ ieee = ieee || lieee1;/* Compute RMIN by successive division by BETA. We could compute RMIN as BASE**( EMIN - 1 ), but some machines underflow during this computation. */ lrmin = 1.f; i__1 = 1 - lemin; for (i = 1; i <= 1-lemin; ++i) { r__1 = lrmin * rbase; lrmin = slamc3_(&r__1, &zero);/* L30: */ }/* Finally, call SLAMC5 to compute EMAX and RMAX. */ slamc5_(&lbeta, <, &lemin, &ieee, &lemax, &lrmax); } *beta = lbeta; *t = lt; *rnd = lrnd; *eps = leps; *emin = lemin; *rmin = lrmin; *emax = lemax; *rmax = lrmax; return 0;/* End of SLAMC2 */} /* slamc2_ */double slamc3_(float *a, float *b){/* -- LAPACK auxiliary routine (version 2.0) -- Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., Courant Institute, Argonne National Lab, and Rice University October 31, 1992 Purpose ======= SLAMC3 is intended to force A and B to be stored prior to doing the addition of A and B , for use in situations where optimizers might hold one of these in a register. Arguments ========= A, B (input) FLOAT The values A and B. ===================================================================== *//* >>Start of File<< System generated locals */ float ret_val; ret_val = *a + *b; return ret_val;/* End of SLAMC3 */} /* slamc3_ *//* Subroutine */ int slamc4_(int *emin, float *start, int *base){/* -- LAPACK auxiliary routine (version 2.0) -- Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., Courant Institute, Argonne National Lab, and Rice University October 31, 1992 Purpose ======= SLAMC4 is a service routine for SLAMC2. Arguments ========= EMIN (output) EMIN The minimum exponent before (gradual) underflow, computed by setting A = START and dividing by BASE until the previous A can not be recovered. START (input) FLOAT The starting point for determining EMIN. BASE (input) INT The base of the machine. ===================================================================== */ /* System generated locals */ int i__1; float r__1; /* Local variables */ static float zero, a; static int i; static float rbase, b1, b2, c1, c2, d1, d2; extern double slamc3_(float *, float *); static float one; a = *start; one = 1.f; rbase = one / *base; zero = 0.f; *emin = 1; r__1 = a * rbase; b1 = slamc3_(&r__1, &zero); c1 = a; c2 = a; d1 = a; d2 = a;/* + WHILE( ( C1.EQ.A ).AND.( C2.EQ.A ).AND. $ ( D1.EQ.A ).AND.( D2.EQ.A ) )LOOP */L10: if (c1 == a && c2 == a && d1 == a && d2 == a) { --(*emin); a = b1; r__1 = a / *base; b1 = slamc3_(&r__1, &zero); r__1 = b1 * *base; c1 = slamc3_(&r__1, &zero); d1 = zero; i__1 = *base; for (i = 1; i <= *base; ++i) { d1 += b1;/* L20: */ } r__1 = a * rbase; b2 = slamc3_(&r__1, &zero); r__1 = b2 / rbase; c2 = slamc3_(&r__1, &zero); d2 = zero; i__1 = *base; for (i = 1; i <= *base; ++i) { d2 += b2;/* L30: */ } goto L10; }/* + END WHILE */ return 0;/* End of SLAMC4 */} /* slamc4_ *//* Subroutine */ int slamc5_(int *beta, int *p, int *emin, int *ieee, int *emax, float *rmax){/* -- LAPACK auxiliary routine (version 2.0) -- Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd., Courant Institute, Argonne National Lab, and Rice University October 31, 1992 Purpose ======= SLAMC5 attempts to compute RMAX, the largest machine floating-point number, without overflow. It assumes that EMAX + abs(EMIN) sum approximately to a power of 2. It will fail on machines where this assumption does not hold, for example, the Cyber 205 (EMIN = -28625, EMAX = 28718). It will also fail if the value supplied for EMIN is too large (i.e. too close to zero), probably with overflow. Arguments ========= BETA (input) INT The base of floating-point arithmetic. P (input) INT The number of base BETA digits in the mantissa of a floating-point value. EMIN (input) INT The minimum exponent before (gradual) underflow. IEEE (input) INT A logical flag specifying whether or not the arithmetic system is thought to comply with the IEEE standard. EMAX (output) INT The largest exponent before overflow RMAX (output) FLOAT The largest machine floating-point number. ===================================================================== First compute LEXP and UEXP, two powers of 2 that bound abs(EMIN). We then assume that EMAX + abs(EMIN) will sum approximately to the bound that is closest to abs(EMIN). (EMAX is the exponent of the required number RMAX). */ /* Table of constant values */ static float c_b5 = 0.f; /* System generated locals */ int i__1; float r__1; /* Local variables */ static int lexp; static float oldy; static int uexp, i; static float y, z; static int nbits; extern double slamc3_(float *, float *); static float recbas; static int exbits, expsum, try__; lexp = 1; exbits = 1;L10: try__ = lexp << 1; if (try__ <= -(*emin)) { lexp = try__; ++exbits; goto L10; } if (lexp == -(*emin)) { uexp = lexp; } else { uexp = try__; ++exbits; }/* Now -LEXP is less than or equal to EMIN, and -UEXP is greater than or equal to EMIN. EXBITS is the number of bits needed to store the exponent. */ if (uexp + *emin > -lexp - *emin) { expsum = lexp << 1; } else { expsum = uexp << 1; }/* EXPSUM is the exponent range, approximately equal to EMAX - EMIN + 1 . */ *emax = expsum + *emin - 1; nbits = exbits + 1 + *p;/* NBITS is the total number of bits needed to store a floating-point number. */ if (nbits % 2 == 1 && *beta == 2) {/* Either there are an odd number of bits used to store a floating-point number, which is unlikely, or some bits are not used in the representation of numbers, which is possible, (e.g. Cray machines) or the mantissa has an implicit bit, (e.g. IEEE machines, Dec Vax machines), which is perhaps the most likely. We have to assume the last alternative. If this is true, then we need to reduce EMAX by one because there must be some way of representing zero in an implicit-bit system. On machines like Cray, we are reducing EMAX by one unnecessarily. */ --(*emax); } if (*ieee) {/* Assume we are on an IEEE machine which reserves one exponent for infinity and NaN. */ --(*emax); }/* Now create RMAX, the largest machine number, which should be equal to (1.0 - BETA**(-P)) * BETA**EMAX . First compute 1.0 - BETA**(-P), being careful that the result is less than 1.0 . */ recbas = 1.f / *beta; z = *beta - 1.f; y = 0.f; i__1 = *p; for (i = 1; i <= *p; ++i) { z *= recbas; if (y < 1.f) { oldy = y; } y = slamc3_(&y, &z);/* L20: */ } if (y >= 1.f) { y = oldy; }/* Now multiply by BETA**EMAX to get RMAX. */ i__1 = *emax; for (i = 1; i <= *emax; ++i) { r__1 = y * *beta; y = slamc3_(&r__1, &c_b5);/* L30: */ } *rmax = y; return 0;/* End of SLAMC5 */} /* slamc5_ */double pow_ri(float *ap, int *bp){double pow, x;int n;pow = 1;x = *ap;n = *bp;if(n != 0) { if(n < 0) { n = -n; x = 1/x; } for( ; ; ) { if(n & 01) pow *= x; if(n >>= 1) x *= x; else break; } }return(pow);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -