📄 pdsteqr.f
字号:
LOGICAL IEEE1, RND INTEGER 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, LRND INTEGER LBETA, LT DOUBLE PRECISION A, B, C, F, ONE, QTR, SAVEC, T1, T2* ..* .. External Functions .. DOUBLE PRECISION PDLAMC3 EXTERNAL PDLAMC3* ..* .. Save statement .. SAVE FIRST, LIEEE1, LBETA, LRND, LT* ..* .. Data statements .. DATA FIRST / .TRUE. /* ..* .. Executable Statements ..* IF( FIRST ) THEN FIRST = .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 = 1 C = 1**+ WHILE( C.EQ.ONE )LOOP 10 CONTINUE IF( C.EQ.ONE ) THEN A = 2*A C = PDLAMC3( A, ONE ) C = PDLAMC3( C, -A ) GO TO 10 END IF*+ END WHILE** Now compute b = 2.0**m with the smallest positive integer m* such that** fl( a + b ) .gt. a.* B = 1 C = PDLAMC3( A, B )**+ WHILE( C.EQ.A )LOOP 20 CONTINUE IF( C.EQ.A ) THEN B = 2*B C = PDLAMC3( A, B ) GO TO 20 END 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 / 4 SAVEC = C C = PDLAMC3( 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 = LBETA F = PDLAMC3( B / 2, -B / 100 ) C = PDLAMC3( F, A ) IF( C.EQ.A ) THEN LRND = .TRUE. ELSE LRND = .FALSE. END IF F = PDLAMC3( B / 2, B / 100 ) C = PDLAMC3( 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 = PDLAMC3( B / 2, A ) T2 = PDLAMC3( 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 = 0 A = 1 C = 1**+ WHILE( C.EQ.ONE )LOOP 30 CONTINUE IF( C.EQ.ONE ) THEN LT = LT + 1 A = A*LBETA C = PDLAMC3( A, ONE ) C = PDLAMC3( C, -A ) GO TO 30 END IF*+ END WHILE* END IF* BETA = LBETA T = LT RND = LRND IEEE1 = LIEEE1 RETURN** End of DLAMC1* END************************************************************************** SUBROUTINE PDLAMC2( 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 RND INTEGER BETA, EMAX, EMIN, T DOUBLE 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, LRND INTEGER GNMIN, GPMIN, I, LBETA, LEMAX, LEMIN, LT, $ NGNMIN, NGPMIN DOUBLE PRECISION A, B, C, HALF, LEPS, LRMAX, LRMIN, ONE, RBASE, $ SIXTH, SMALL, THIRD, TWO, ZERO* ..* .. External Functions .. DOUBLE PRECISION PDLAMC3 EXTERNAL PDLAMC3* ..* .. External Subroutines .. EXTERNAL PDLAMC1, PDLAMC4, PDLAMC5* ..* .. 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 ) THEN FIRST = .FALSE. ZERO = 0 ONE = 1 TWO = 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 PDLAMC1( LBETA, LT, LRND, LIEEE1 )** Start to find EPS.* B = LBETA A = B**( -LT ) LEPS = A** Try some tricks to see whether or not this is the correct EPS.* B = TWO / 3 HALF = ONE / 2 SIXTH = PDLAMC3( B, -HALF ) THIRD = PDLAMC3( SIXTH, SIXTH ) B = PDLAMC3( THIRD, -HALF ) B = PDLAMC3( B, SIXTH ) B = ABS( B ) IF( B.LT.LEPS ) $ B = LEPS* LEPS = 1**+ WHILE( ( LEPS.GT.B ).AND.( B.GT.ZERO ) )LOOP 10 CONTINUE IF( ( LEPS.GT.B ) .AND. ( B.GT.ZERO ) ) THEN LEPS = B C = PDLAMC3( HALF*LEPS, ( TWO**5 )*( LEPS**2 ) ) C = PDLAMC3( HALF, -C ) B = PDLAMC3( HALF, C ) C = PDLAMC3( HALF, -B ) B = PDLAMC3( HALF, C ) GO TO 10 END 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 / LBETA SMALL = ONE DO 20 I = 1, 3 SMALL = PDLAMC3( SMALL*RBASE, ZERO ) 20 CONTINUE A = PDLAMC3( ONE, SMALL ) CALL PDLAMC4( NGPMIN, ONE, LBETA ) CALL PDLAMC4( NGNMIN, -ONE, LBETA ) CALL PDLAMC4( GPMIN, A, LBETA ) CALL PDLAMC4( GNMIN, -A, LBETA ) IEEE = .FALSE.* IF( ( NGPMIN.EQ.NGNMIN ) .AND. ( GPMIN.EQ.GNMIN ) ) THEN IF( NGPMIN.EQ.GPMIN ) THEN LEMIN = NGPMIN* ( Non twos-complement machines, no gradual underflow;* e.g., VAX ) ELSE IF( ( GPMIN-NGPMIN ).EQ.3 ) THEN 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. END IF* ELSE IF( ( NGPMIN.EQ.GPMIN ) .AND. ( NGNMIN.EQ.GNMIN ) ) THEN IF( ABS( NGPMIN-NGNMIN ).EQ.1 ) THEN 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. END IF* ELSE IF( ( ABS( NGPMIN-NGNMIN ).EQ.1 ) .AND. $ ( GPMIN.EQ.GNMIN ) ) THEN IF( ( GPMIN-MIN( NGPMIN, NGNMIN ) ).EQ.3 ) THEN 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. END IF* ELSE LEMIN = MIN( NGPMIN, NGNMIN, GPMIN, GNMIN )* ( A guess; no known machine ) IWARN = .TRUE. END IF**** Comment out this if block if EMIN is ok IF( IWARN ) THEN FIRST = .TRUE. WRITE( 6, FMT = 9999 )LEMIN 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 = 1 DO 30 I = 1, 1 - LEMIN LRMIN = PDLAMC3( LRMIN*RBASE, ZERO ) 30 CONTINUE** Finally, call DLAMC5 to compute EMAX and RMAX.* CALL PDLAMC5( LBETA, LT, LEMIN, IEEE, LEMAX, LRMAX ) END IF* BETA = LBETA T = LT RND = LRND EPS = LEPS EMIN = LEMIN RMIN = LRMIN EMAX = LEMAX RMAX = LRMAX* RETURN* 9999 FORMAT( / / ' WARNING. The value EMIN may be incorrect:-', $ ' EMIN = ', I8, / $ ' If, after inspection, the value EMIN looks', $ ' acceptable please comment out ', $ / ' the IF block as marked within the code of routine', $ ' DLAMC2,', / ' otherwise supply EMIN explicitly.', / )** End of DLAMC2* END************************************************************************** DOUBLE PRECISION FUNCTION PDLAMC3( 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.** =====================================================================*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -