Rev 35751 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
DOUBLE PRECISION FUNCTION DLAMCH( CMACH )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1992** .. Scalar Arguments ..CHARACTER CMACH* ..** Purpose* =======** DLAMCH determines double precision machine parameters.** Arguments* =========** CMACH (input) CHARACTER*1* Specifies the value to be returned by DLAMCH:* = 'E' or 'e', DLAMCH := eps* = 'S' or 's , DLAMCH := sfmin* = 'B' or 'b', DLAMCH := base* = 'P' or 'p', DLAMCH := eps*base* = 'N' or 'n', DLAMCH := t* = 'R' or 'r', DLAMCH := rnd* = 'M' or 'm', DLAMCH := emin* = 'U' or 'u', DLAMCH := rmin* = 'L' or 'l', DLAMCH := emax* = 'O' or 'o', DLAMCH := rmax** where** eps = relative machine precision* sfmin = safe minimum, such that 1/sfmin does not overflow* base = base of the machine* prec = eps*base* t = number of (base) digits in the mantissa* rnd = 1.0 when rounding occurs in addition, 0.0 otherwise* emin = minimum exponent before (gradual) underflow* rmin = underflow threshold - base**(emin-1)* emax = largest exponent before overflow* rmax = overflow threshold - (base**emax)*(1-eps)** =====================================================================** .. Parameters ..DOUBLE PRECISION ONE, ZEROPARAMETER ( ONE = 1.0D+0, ZERO = 0.0D+0 )* ..* .. Local Scalars ..LOGICAL FIRST, LRNDINTEGER BETA, IMAX, IMIN, ITDOUBLE PRECISION BASE, EMAX, EMIN, EPS, PREC, RMACH, RMAX, RMIN,$ RND, SFMIN, SMALL, T* ..* .. External Functions ..LOGICAL LSAMEEXTERNAL LSAME* ..* .. External Subroutines ..EXTERNAL DLAMC2* ..* .. Save statement ..SAVE FIRST, EPS, SFMIN, BASE, T, RND, EMIN, RMIN,$ EMAX, RMAX, PREC* ..* .. Data statements ..DATA FIRST / .TRUE. /* ..* .. Executable Statements ..*IF( FIRST ) THENFIRST = .FALSE.CALL DLAMC2( BETA, IT, LRND, EPS, IMIN, RMIN, IMAX, RMAX )BASE = BETAT = ITIF( LRND ) THENRND = ONEEPS = ( BASE**( 1-IT ) ) / 2ELSERND = ZEROEPS = BASE**( 1-IT )END IFPREC = EPS*BASEEMIN = IMINEMAX = IMAXSFMIN = RMINSMALL = ONE / RMAXIF( SMALL.GE.SFMIN ) THEN** Use SMALL plus a bit, to avoid the possibility of rounding* causing overflow when computing 1/sfmin.*SFMIN = SMALL*( ONE+EPS )END IFEND IF*IF( LSAME( CMACH, 'E' ) ) THENRMACH = EPSELSE IF( LSAME( CMACH, 'S' ) ) THENRMACH = SFMINELSE IF( LSAME( CMACH, 'B' ) ) THENRMACH = BASEELSE IF( LSAME( CMACH, 'P' ) ) THENRMACH = PRECELSE IF( LSAME( CMACH, 'N' ) ) THENRMACH = TELSE IF( LSAME( CMACH, 'R' ) ) THENRMACH = RNDELSE IF( LSAME( CMACH, 'M' ) ) THENRMACH = EMINELSE IF( LSAME( CMACH, 'U' ) ) THENRMACH = RMINELSE IF( LSAME( CMACH, 'L' ) ) THENRMACH = EMAXELSE IF( LSAME( CMACH, 'O' ) ) THENRMACH = RMAXEND IF*DLAMCH = RMACHRETURN** End of DLAMCH*END**************************************************************************SUBROUTINE DLAMC1( BETA, T, RND, IEEE1 )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1992** .. Scalar Arguments ..LOGICAL IEEE1, RNDINTEGER BETA, T* ..** Purpose* =======** DLAMC1 determines the machine parameters given by BETA, T, RND, and* IEEE1.** Arguments* =========** BETA (output) INTEGER* The base of the machine.** T (output) INTEGER* The number of ( BETA ) digits in the mantissa.** RND (output) LOGICAL* Specifies whether proper rounding ( RND = .TRUE. ) or* chopping ( RND = .FALSE. ) occurs in addition. This may not* be a reliable guide to the way in which the machine performs* its arithmetic.** IEEE1 (output) LOGICAL* Specifies whether rounding appears to be done in the IEEE* 'round to nearest' style.** Further Details* ===============** The routine is based on the routine ENVRON by Malcolm and* incorporates suggestions by Gentleman and Marovich. See** Malcolm M. A. (1972) Algorithms to reveal properties of* floating-point arithmetic. Comms. of the ACM, 15, 949-951.** Gentleman W. M. and Marovich S. B. (1974) More on algorithms* that reveal properties of floating point arithmetic units.* Comms. of the ACM, 17, 276-277.** =====================================================================** .. Local Scalars ..LOGICAL FIRST, LIEEE1, LRNDINTEGER LBETA, LTDOUBLE PRECISION A, B, C, F, ONE, QTR, SAVEC, T1, T2* ..* .. External Functions ..DOUBLE PRECISION DLAMC3EXTERNAL DLAMC3* ..* .. Save statement ..SAVE FIRST, LIEEE1, LBETA, LRND, LT* ..* .. Data statements ..DATA FIRST / .TRUE. /* ..* .. Executable Statements ..*IF( FIRST ) THENFIRST = .FALSE.ONE = 1** LBETA, LIEEE1, LT and LRND are the local values of BETA,* IEEE1, T and RND.** Throughout this routine we use the function DLAMC3 to ensure* that relevant values are stored and not held in registers, or* are not affected by optimizers.** Compute a = 2.0**m with the smallest positive integer m such* that** fl( a + 1.0 ) = a.*A = 1C = 1**+ WHILE( C.EQ.ONE )LOOP10 CONTINUEIF( C.EQ.ONE ) THENA = 2*AC = DLAMC3( A, ONE )C = DLAMC3( C, -A )GO TO 10END IF*+ END WHILE** Now compute b = 2.0**m with the smallest positive integer m* such that** fl( a + b ) .gt. a.*B = 1C = DLAMC3( A, B )**+ WHILE( C.EQ.A )LOOP20 CONTINUEIF( C.EQ.A ) THENB = 2*BC = DLAMC3( A, B )GO TO 20END IF*+ END WHILE** Now compute the base. a and c are neighbouring floating point* numbers in the interval ( beta**t, beta**( t + 1 ) ) and so* their difference is beta. Adding 0.25 to c is to ensure that it* is truncated to beta and not ( beta - 1 ).*QTR = ONE / 4SAVEC = CC = DLAMC3( C, -A )LBETA = C + QTR** Now determine whether rounding or chopping occurs, by adding a* bit less than beta/2 and a bit more than beta/2 to a.*B = LBETAF = DLAMC3( B / 2, -B / 100 )C = DLAMC3( F, A )IF( C.EQ.A ) THENLRND = .TRUE.ELSELRND = .FALSE.END IFF = DLAMC3( B / 2, B / 100 )C = DLAMC3( F, A )IF( ( LRND ) .AND. ( C.EQ.A ) )$ LRND = .FALSE.** Try and decide whether rounding is done in the IEEE 'round to* nearest' style. B/2 is half a unit in the last place of the two* numbers A and SAVEC. Furthermore, A is even, i.e. has last bit* zero, and SAVEC is odd. Thus adding B/2 to A should not change* A, but adding B/2 to SAVEC should change SAVEC.*T1 = DLAMC3( B / 2, A )T2 = DLAMC3( B / 2, SAVEC )LIEEE1 = ( T1.EQ.A ) .AND. ( T2.GT.SAVEC ) .AND. LRND** Now find the mantissa, t. It should be the integer part of* log to the base beta of a, however it is safer to determine t* by powering. So we find t as the smallest positive integer for* which** fl( beta**t + 1.0 ) = 1.0.*LT = 0A = 1C = 1**+ WHILE( C.EQ.ONE )LOOP30 CONTINUEIF( C.EQ.ONE ) THENLT = LT + 1A = A*LBETAC = DLAMC3( A, ONE )C = DLAMC3( C, -A )GO TO 30END IF*+ END WHILE*END IF*BETA = LBETAT = LTRND = LRNDIEEE1 = LIEEE1RETURN** End of DLAMC1*END**************************************************************************SUBROUTINE DLAMC2( BETA, T, RND, EPS, EMIN, RMIN, EMAX, RMAX )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1992** .. Scalar Arguments ..LOGICAL RNDINTEGER BETA, EMAX, EMIN, TDOUBLE PRECISION EPS, RMAX, RMIN* ..** Purpose* =======** DLAMC2 determines the machine parameters specified in its argument* list.** Arguments* =========** BETA (output) INTEGER* The base of the machine.** T (output) INTEGER* The number of ( BETA ) digits in the mantissa.** RND (output) LOGICAL* Specifies whether proper rounding ( RND = .TRUE. ) or* chopping ( RND = .FALSE. ) occurs in addition. This may not* be a reliable guide to the way in which the machine performs* its arithmetic.** EPS (output) DOUBLE PRECISION* The smallest positive number such that** fl( 1.0 - EPS ) .LT. 1.0,** where fl denotes the computed value.** EMIN (output) INTEGER* The minimum exponent before (gradual) underflow occurs.** RMIN (output) DOUBLE PRECISION* The smallest normalized number for the machine, given by* BASE**( EMIN - 1 ), where BASE is the floating point value* of BETA.** EMAX (output) INTEGER* The maximum exponent before overflow occurs.** RMAX (output) DOUBLE PRECISION* The largest positive number for the machine, given by* BASE**EMAX * ( 1 - EPS ), where BASE is the floating point* value of BETA.** Further Details* ===============** The computation of EPS is based on a routine PARANOIA by* W. Kahan of the University of California at Berkeley.** =====================================================================** .. Local Scalars ..LOGICAL FIRST, IEEE, IWARN, LIEEE1, LRNDINTEGER GNMIN, GPMIN, I, LBETA, LEMAX, LEMIN, LT,$ NGNMIN, NGPMINDOUBLE PRECISION A, B, C, HALF, LEPS, LRMAX, LRMIN, ONE, RBASE,$ SIXTH, SMALL, THIRD, TWO, ZERO* ..* .. External Functions ..DOUBLE PRECISION DLAMC3EXTERNAL DLAMC3* ..* .. External Subroutines ..EXTERNAL DLAMC1, DLAMC4, DLAMC5* ..* .. Intrinsic Functions ..INTRINSIC ABS, MAX, MIN* ..* .. Save statement ..SAVE FIRST, IWARN, LBETA, LEMAX, LEMIN, LEPS, LRMAX,$ LRMIN, LT* ..* .. Data statements ..DATA FIRST / .TRUE. / , IWARN / .FALSE. /* ..* .. Executable Statements ..*IF( FIRST ) THENFIRST = .FALSE.ZERO = 0ONE = 1TWO = 2** LBETA, LT, LRND, LEPS, LEMIN and LRMIN are the local values of* BETA, T, RND, EPS, EMIN and RMIN.** Throughout this routine we use the function DLAMC3 to ensure* that relevant values are stored and not held in registers, or* are not affected by optimizers.** DLAMC1 returns the parameters LBETA, LT, LRND and LIEEE1.*CALL DLAMC1( LBETA, LT, LRND, LIEEE1 )** Start to find EPS.*B = LBETAA = B**( -LT )LEPS = A** Try some tricks to see whether or not this is the correct EPS.*B = TWO / 3HALF = ONE / 2SIXTH = DLAMC3( B, -HALF )THIRD = DLAMC3( SIXTH, SIXTH )B = DLAMC3( THIRD, -HALF )B = DLAMC3( B, SIXTH )B = ABS( B )IF( B.LT.LEPS )$ B = LEPS*LEPS = 1**+ WHILE( ( LEPS.GT.B ).AND.( B.GT.ZERO ) )LOOP10 CONTINUEIF( ( LEPS.GT.B ) .AND. ( B.GT.ZERO ) ) THENLEPS = BC = DLAMC3( HALF*LEPS, ( TWO**5 )*( LEPS**2 ) )C = DLAMC3( HALF, -C )B = DLAMC3( HALF, C )C = DLAMC3( HALF, -B )B = DLAMC3( HALF, C )GO TO 10END IF*+ END WHILE*IF( A.LT.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 / LBETASMALL = ONEDO 20 I = 1, 3SMALL = DLAMC3( SMALL*RBASE, ZERO )20 CONTINUEA = DLAMC3( ONE, SMALL )CALL DLAMC4( NGPMIN, ONE, LBETA )CALL DLAMC4( NGNMIN, -ONE, LBETA )CALL DLAMC4( GPMIN, A, LBETA )CALL DLAMC4( GNMIN, -A, LBETA )IEEE = .FALSE.*IF( ( NGPMIN.EQ.NGNMIN ) .AND. ( GPMIN.EQ.GNMIN ) ) THENIF( NGPMIN.EQ.GPMIN ) THENLEMIN = NGPMIN* ( Non twos-complement machines, no gradual underflow;* e.g., VAX )ELSE IF( ( GPMIN-NGPMIN ).EQ.3 ) THENLEMIN = NGPMIN - 1 + LTIEEE = .TRUE.* ( Non twos-complement machines, with gradual underflow;* e.g., IEEE standard followers )ELSELEMIN = MIN( NGPMIN, GPMIN )* ( A guess; no known machine )IWARN = .TRUE.END IF*ELSE IF( ( NGPMIN.EQ.GPMIN ) .AND. ( NGNMIN.EQ.GNMIN ) ) THENIF( ABS( NGPMIN-NGNMIN ).EQ.1 ) THENLEMIN = MAX( NGPMIN, NGNMIN )* ( Twos-complement machines, no gradual underflow;* e.g., CYBER 205 )ELSELEMIN = MIN( NGPMIN, NGNMIN )* ( A guess; no known machine )IWARN = .TRUE.END IF*ELSE IF( ( ABS( NGPMIN-NGNMIN ).EQ.1 ) .AND.$ ( GPMIN.EQ.GNMIN ) ) THENIF( ( GPMIN-MIN( NGPMIN, NGNMIN ) ).EQ.3 ) THENLEMIN = MAX( NGPMIN, NGNMIN ) - 1 + LT* ( Twos-complement machines with gradual underflow;* no known machine )ELSELEMIN = MIN( NGPMIN, NGNMIN )* ( A guess; no known machine )IWARN = .TRUE.END IF*ELSELEMIN = MIN( NGPMIN, NGNMIN, GPMIN, GNMIN )* ( A guess; no known machine )IWARN = .TRUE.END IF**** Comment out this if block if EMIN is okC IF( IWARN ) THENC FIRST = .TRUE.C WRITE( 6, FMT = 9999 )LEMINC END IF***** Assume IEEE arithmetic if we found denormalised numbers above,* or if arithmetic seems to round in the IEEE style, determined* in routine DLAMC1. A true IEEE machine should have both things* true; however, faulty machines may have one or the other.*IEEE = IEEE .OR. LIEEE1** Compute RMIN by successive division by BETA. We could compute* RMIN as BASE**( EMIN - 1 ), but some machines underflow during* this computation.*LRMIN = 1DO 30 I = 1, 1 - LEMINLRMIN = DLAMC3( LRMIN*RBASE, ZERO )30 CONTINUE** Finally, call DLAMC5 to compute EMAX and RMAX.*CALL DLAMC5( LBETA, LT, LEMIN, IEEE, LEMAX, LRMAX )END IF*BETA = LBETAT = LTRND = LRNDEPS = LEPSEMIN = LEMINRMIN = LRMINEMAX = LEMAXRMAX = LRMAX*RETURN*C 9999 FORMAT( / / ' WARNING. The value EMIN may be incorrect:-',C $ ' EMIN = ', I8, /C $ ' If, after inspection, the value EMIN looks',C $ ' acceptable please comment out ',C $ / ' the IF block as marked within the code of routine',C $ ' DLAMC2,', / ' otherwise supply EMIN explicitly.', / )** End of DLAMC2*END**************************************************************************DOUBLE PRECISION FUNCTION DLAMC3( A, B )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1992** .. Scalar Arguments ..DOUBLE PRECISION A, B* ..** Purpose* =======** DLAMC3 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) DOUBLE PRECISION* The values A and B.** =====================================================================** .. Executable Statements ..*DLAMC3 = A + B*RETURN** End of DLAMC3*END**************************************************************************SUBROUTINE DLAMC4( EMIN, START, BASE )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1992** .. Scalar Arguments ..INTEGER BASE, EMINDOUBLE PRECISION START* ..** Purpose* =======** DLAMC4 is a service routine for DLAMC2.** 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) DOUBLE PRECISION* The starting point for determining EMIN.** BASE (input) INTEGER* The base of the machine.** =====================================================================** .. Local Scalars ..INTEGER IDOUBLE PRECISION A, B1, B2, C1, C2, D1, D2, ONE, RBASE, ZERO* ..* .. External Functions ..DOUBLE PRECISION DLAMC3EXTERNAL DLAMC3* ..* .. Executable Statements ..*A = STARTONE = 1RBASE = ONE / BASEZERO = 0EMIN = 1B1 = DLAMC3( A*RBASE, ZERO )C1 = AC2 = AD1 = AD2 = A*+ WHILE( ( C1.EQ.A ).AND.( C2.EQ.A ).AND.* $ ( D1.EQ.A ).AND.( D2.EQ.A ) )LOOP10 CONTINUEIF( ( C1.EQ.A ) .AND. ( C2.EQ.A ) .AND. ( D1.EQ.A ) .AND.$ ( D2.EQ.A ) ) THENEMIN = EMIN - 1A = B1B1 = DLAMC3( A / BASE, ZERO )C1 = DLAMC3( B1*BASE, ZERO )D1 = ZERODO 20 I = 1, BASED1 = D1 + B120 CONTINUEB2 = DLAMC3( A*RBASE, ZERO )C2 = DLAMC3( B2 / RBASE, ZERO )D2 = ZERODO 30 I = 1, BASED2 = D2 + B230 CONTINUEGO TO 10END IF*+ END WHILE*RETURN** End of DLAMC4*END**************************************************************************SUBROUTINE DLAMC5( BETA, P, EMIN, IEEE, EMAX, RMAX )** -- LAPACK auxiliary routine (version 3.0) --* Univ. of Tennessee, Univ. of California Berkeley, NAG Ltd.,* Courant Institute, Argonne National Lab, and Rice University* October 31, 1992** .. Scalar Arguments ..LOGICAL IEEEINTEGER BETA, EMAX, EMIN, PDOUBLE PRECISION RMAX* ..** Purpose* =======** DLAMC5 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) INTEGER* The base of floating-point arithmetic.** P (input) INTEGER* The number of base BETA digits in the mantissa of a* floating-point value.** EMIN (input) INTEGER* The minimum exponent before (gradual) underflow.** IEEE (input) LOGICAL* A logical flag specifying whether or not the arithmetic* system is thought to comply with the IEEE standard.** EMAX (output) INTEGER* The largest exponent before overflow** RMAX (output) DOUBLE PRECISION* The largest machine floating-point number.** =====================================================================** .. Parameters ..DOUBLE PRECISION ZERO, ONEPARAMETER ( ZERO = 0.0D0, ONE = 1.0D0 )* ..* .. Local Scalars ..INTEGER EXBITS, EXPSUM, I, LEXP, NBITS, TRY, UEXPDOUBLE PRECISION OLDY, RECBAS, Y, Z* ..* .. External Functions ..DOUBLE PRECISION DLAMC3EXTERNAL DLAMC3* ..* .. Intrinsic Functions ..INTRINSIC MOD* ..* .. Executable Statements ..** 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).*LEXP = 1EXBITS = 110 CONTINUETRY = LEXP*2IF( TRY.LE.( -EMIN ) ) THENLEXP = TRYEXBITS = EXBITS + 1GO TO 10END IFIF( LEXP.EQ.-EMIN ) THENUEXP = LEXPELSEUEXP = TRYEXBITS = EXBITS + 1END IF** 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 ).GT.( -LEXP-EMIN ) ) THENEXPSUM = 2*LEXPELSEEXPSUM = 2*UEXPEND IF** EXPSUM is the exponent range, approximately equal to* EMAX - EMIN + 1 .*EMAX = EXPSUM + EMIN - 1NBITS = 1 + EXBITS + P** NBITS is the total number of bits needed to store a* floating-point number.*IF( ( MOD( NBITS, 2 ).EQ.1 ) .AND. ( BETA.EQ.2 ) ) THEN** 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 = EMAX - 1END IF*IF( IEEE ) THEN** Assume we are on an IEEE machine which reserves one exponent* for infinity and NaN.*EMAX = EMAX - 1END IF** 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 = ONE / BETAZ = BETA - ONEY = ZERODO 20 I = 1, PZ = Z*RECBASIF( Y.LT.ONE )$ OLDY = YY = DLAMC3( Y, Z )20 CONTINUEIF( Y.GE.ONE )$ Y = OLDY** Now multiply by BETA**EMAX to get RMAX.*DO 30 I = 1, EMAXY = DLAMC3( Y*BETA, ZERO )30 CONTINUE*RMAX = YRETURN** End of DLAMC5*END