LAPACK  3.4.0
LAPACK: Linear Algebra PACKage
slamchf77.f
Go to the documentation of this file.
00001 *> \brief \b SLAMCHF77 deprecated
00002 *
00003 *  =========== DOCUMENTATION ===========
00004 *
00005 * Online html documentation available at 
00006 *            http://www.netlib.org/lapack/explore-html/ 
00007 *
00008 *  Definition:
00009 *  ===========
00010 *
00011 *      REAL FUNCTION SLAMCH( CMACH )
00012 *
00013 *     .. Scalar Arguments ..
00014 *      CHARACTER          CMACH
00015 *     ..
00016 *  
00017 *
00018 *> \par Purpose:
00019 *  =============
00020 *>
00021 *> \verbatim
00022 *>
00023 *> SLAMCH determines single precision machine parameters.
00024 *> \endverbatim
00025 *
00026 *  Arguments:
00027 *  ==========
00028 *
00029 *> \param[in] CMACH
00030 *> \verbatim
00031 *>          Specifies the value to be returned by SLAMCH:
00032 *>          = 'E' or 'e',   SLAMCH := eps
00033 *>          = 'S' or 's ,   SLAMCH := sfmin
00034 *>          = 'B' or 'b',   SLAMCH := base
00035 *>          = 'P' or 'p',   SLAMCH := eps*base
00036 *>          = 'N' or 'n',   SLAMCH := t
00037 *>          = 'R' or 'r',   SLAMCH := rnd
00038 *>          = 'M' or 'm',   SLAMCH := emin
00039 *>          = 'U' or 'u',   SLAMCH := rmin
00040 *>          = 'L' or 'l',   SLAMCH := emax
00041 *>          = 'O' or 'o',   SLAMCH := rmax
00042 *>          where
00043 *>          eps   = relative machine precision
00044 *>          sfmin = safe minimum, such that 1/sfmin does not overflow
00045 *>          base  = base of the machine
00046 *>          prec  = eps*base
00047 *>          t     = number of (base) digits in the mantissa
00048 *>          rnd   = 1.0 when rounding occurs in addition, 0.0 otherwise
00049 *>          emin  = minimum exponent before (gradual) underflow
00050 *>          rmin  = underflow threshold - base**(emin-1)
00051 *>          emax  = largest exponent before overflow
00052 *>          rmax  = overflow threshold  - (base**emax)*(1-eps)
00053 *> \endverbatim
00054 *
00055 *  Authors:
00056 *  ========
00057 *
00058 *> \author Univ. of Tennessee 
00059 *> \author Univ. of California Berkeley 
00060 *> \author Univ. of Colorado Denver 
00061 *> \author NAG Ltd. 
00062 *
00063 *> \date November 2011
00064 *
00065 *> \ingroup auxOTHERauxiliary
00066 *
00067 *  =====================================================================
00068       REAL FUNCTION SLAMCH( CMACH )
00069 *
00070 *  -- LAPACK auxiliary routine (version 3.4.0) --
00071 *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
00072 *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
00073 *     November 2011
00074 *
00075 *     .. Scalar Arguments ..
00076       CHARACTER          CMACH
00077 *     ..
00078 *
00079 *     .. Scalar Arguments ..
00080       LOGICAL            IEEE1, RND
00081       INTEGER            BETA, T
00082 *     ..
00083 *
00084 *     .. Scalar Arguments ..
00085       LOGICAL            RND
00086       INTEGER            BETA, EMAX, EMIN, T
00087       REAL               EPS, RMAX, RMIN
00088 *     ..
00089 *
00090 *     .. Scalar Arguments ..
00091       REAL               A, B
00092 *     ..
00093 *
00094 *     .. Scalar Arguments ..
00095       INTEGER            BASE
00096       INTEGER            EMIN
00097       REAL               START
00098 *     ..
00099 *
00100 *     .. Scalar Arguments ..
00101       LOGICAL            IEEE
00102       INTEGER            BETA, EMAX, EMIN, P
00103       REAL               RMAX
00104 *     ..
00105 *
00106 * =====================================================================
00107 *
00108 *     .. Parameters ..
00109       REAL               ONE, ZERO
00110       PARAMETER          ( ONE = 1.0E+0, ZERO = 0.0E+0 )
00111 *     ..
00112 *     .. Local Scalars ..
00113       LOGICAL            FIRST, LRND
00114       INTEGER            BETA, IMAX, IMIN, IT
00115       REAL               BASE, EMAX, EMIN, EPS, PREC, RMACH, RMAX, RMIN,
00116      $                   RND, SFMIN, SMALL, T
00117 *     ..
00118 *     .. External Functions ..
00119       LOGICAL            LSAME
00120       EXTERNAL           LSAME
00121 *     ..
00122 *     .. External Subroutines ..
00123       EXTERNAL           SLAMC2
00124 *     ..
00125 *     .. Save statement ..
00126       SAVE               FIRST, EPS, SFMIN, BASE, T, RND, EMIN, RMIN,
00127      $                   EMAX, RMAX, PREC
00128 *     ..
00129 *     .. Data statements ..
00130       DATA               FIRST / .TRUE. /
00131 *     ..
00132 *     .. Executable Statements ..
00133 *
00134       IF( FIRST ) THEN
00135          CALL SLAMC2( BETA, IT, LRND, EPS, IMIN, RMIN, IMAX, RMAX )
00136          BASE = BETA
00137          T = IT
00138          IF( LRND ) THEN
00139             RND = ONE
00140             EPS = ( BASE**( 1-IT ) ) / 2
00141          ELSE
00142             RND = ZERO
00143             EPS = BASE**( 1-IT )
00144          END IF
00145          PREC = EPS*BASE
00146          EMIN = IMIN
00147          EMAX = IMAX
00148          SFMIN = RMIN
00149          SMALL = ONE / RMAX
00150          IF( SMALL.GE.SFMIN ) THEN
00151 *
00152 *           Use SMALL plus a bit, to avoid the possibility of rounding
00153 *           causing overflow when computing  1/sfmin.
00154 *
00155             SFMIN = SMALL*( ONE+EPS )
00156          END IF
00157       END IF
00158 *
00159       IF( LSAME( CMACH, 'E' ) ) THEN
00160          RMACH = EPS
00161       ELSE IF( LSAME( CMACH, 'S' ) ) THEN
00162          RMACH = SFMIN
00163       ELSE IF( LSAME( CMACH, 'B' ) ) THEN
00164          RMACH = BASE
00165       ELSE IF( LSAME( CMACH, 'P' ) ) THEN
00166          RMACH = PREC
00167       ELSE IF( LSAME( CMACH, 'N' ) ) THEN
00168          RMACH = T
00169       ELSE IF( LSAME( CMACH, 'R' ) ) THEN
00170          RMACH = RND
00171       ELSE IF( LSAME( CMACH, 'M' ) ) THEN
00172          RMACH = EMIN
00173       ELSE IF( LSAME( CMACH, 'U' ) ) THEN
00174          RMACH = RMIN
00175       ELSE IF( LSAME( CMACH, 'L' ) ) THEN
00176          RMACH = EMAX
00177       ELSE IF( LSAME( CMACH, 'O' ) ) THEN
00178          RMACH = RMAX
00179       END IF
00180 *
00181       SLAMCH = RMACH
00182       FIRST  = .FALSE.
00183       RETURN
00184 *
00185 *     End of SLAMCH
00186 *
00187       END
00188 *
00189 ************************************************************************
00190 *
00191 *> \brief \b SLAMC1
00192 *> \details
00193 *> \b Purpose:
00194 *> \verbatim
00195 *> SLAMC1 determines the machine parameters given by BETA, T, RND, and
00196 *> IEEE1.
00197 *> \endverbatim
00198 *>
00199 *> \param[out] BETA
00200 *> \verbatim
00201 *>          The base of the machine.
00202 *> \endverbatim
00203 *>
00204 *> \param[out] T
00205 *> \verbatim
00206 *>          The number of ( BETA ) digits in the mantissa.
00207 *> \endverbatim
00208 *>
00209 *> \param[out] RND
00210 *> \verbatim
00211 *>          Specifies whether proper rounding  ( RND = .TRUE. )  or
00212 *>          chopping  ( RND = .FALSE. )  occurs in addition. This may not
00213 *>          be a reliable guide to the way in which the machine performs
00214 *>          its arithmetic.
00215 *> \endverbatim
00216 *>
00217 *> \param[out] IEEE1
00218 *> \verbatim
00219 *>          Specifies whether rounding appears to be done in the IEEE
00220 *>          'round to nearest' style.
00221 *> \endverbatim
00222 *> \author LAPACK is a software package provided by Univ. of Tennessee, Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..
00223 *> \date November 2011
00224 *> \ingroup auxOTHERauxiliary
00225 *>
00226 *> \details \b Further \b Details
00227 *> \verbatim
00228 *>
00229 *>  The routine is based on the routine  ENVRON  by Malcolm and
00230 *>  incorporates suggestions by Gentleman and Marovich. See
00231 *>
00232 *>     Malcolm M. A. (1972) Algorithms to reveal properties of
00233 *>        floating-point arithmetic. Comms. of the ACM, 15, 949-951.
00234 *>
00235 *>     Gentleman W. M. and Marovich S. B. (1974) More on algorithms
00236 *>        that reveal properties of floating point arithmetic units.
00237 *>        Comms. of the ACM, 17, 276-277.
00238 *> \endverbatim
00239 *>
00240       SUBROUTINE SLAMC1( BETA, T, RND, IEEE1 )
00241 *
00242 *  -- LAPACK auxiliary routine (version 3.4.0) --
00243 *     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
00244 *     November 2010
00245 *
00246 *     .. Scalar Arguments ..
00247       LOGICAL            IEEE1, RND
00248       INTEGER            BETA, T
00249 *     ..
00250 * =====================================================================
00251 *
00252 *     .. Local Scalars ..
00253       LOGICAL            FIRST, LIEEE1, LRND
00254       INTEGER            LBETA, LT
00255       REAL               A, B, C, F, ONE, QTR, SAVEC, T1, T2
00256 *     ..
00257 *     .. External Functions ..
00258       REAL               SLAMC3
00259       EXTERNAL           SLAMC3
00260 *     ..
00261 *     .. Save statement ..
00262       SAVE               FIRST, LIEEE1, LBETA, LRND, LT
00263 *     ..
00264 *     .. Data statements ..
00265       DATA               FIRST / .TRUE. /
00266 *     ..
00267 *     .. Executable Statements ..
00268 *
00269       IF( FIRST ) THEN
00270          ONE = 1
00271 *
00272 *        LBETA,  LIEEE1,  LT and  LRND  are the  local values  of  BETA,
00273 *        IEEE1, T and RND.
00274 *
00275 *        Throughout this routine  we use the function  SLAMC3  to ensure
00276 *        that relevant values are  stored and not held in registers,  or
00277 *        are not affected by optimizers.
00278 *
00279 *        Compute  a = 2.0**m  with the  smallest positive integer m such
00280 *        that
00281 *
00282 *           fl( a + 1.0 ) = a.
00283 *
00284          A = 1
00285          C = 1
00286 *
00287 *+       WHILE( C.EQ.ONE )LOOP
00288    10    CONTINUE
00289          IF( C.EQ.ONE ) THEN
00290             A = 2*A
00291             C = SLAMC3( A, ONE )
00292             C = SLAMC3( C, -A )
00293             GO TO 10
00294          END IF
00295 *+       END WHILE
00296 *
00297 *        Now compute  b = 2.0**m  with the smallest positive integer m
00298 *        such that
00299 *
00300 *           fl( a + b ) .gt. a.
00301 *
00302          B = 1
00303          C = SLAMC3( A, B )
00304 *
00305 *+       WHILE( C.EQ.A )LOOP
00306    20    CONTINUE
00307          IF( C.EQ.A ) THEN
00308             B = 2*B
00309             C = SLAMC3( A, B )
00310             GO TO 20
00311          END IF
00312 *+       END WHILE
00313 *
00314 *        Now compute the base.  a and c  are neighbouring floating point
00315 *        numbers  in the  interval  ( beta**t, beta**( t + 1 ) )  and so
00316 *        their difference is beta. Adding 0.25 to c is to ensure that it
00317 *        is truncated to beta and not ( beta - 1 ).
00318 *
00319          QTR = ONE / 4
00320          SAVEC = C
00321          C = SLAMC3( C, -A )
00322          LBETA = C + QTR
00323 *
00324 *        Now determine whether rounding or chopping occurs,  by adding a
00325 *        bit  less  than  beta/2  and a  bit  more  than  beta/2  to  a.
00326 *
00327          B = LBETA
00328          F = SLAMC3( B / 2, -B / 100 )
00329          C = SLAMC3( F, A )
00330          IF( C.EQ.A ) THEN
00331             LRND = .TRUE.
00332          ELSE
00333             LRND = .FALSE.
00334          END IF
00335          F = SLAMC3( B / 2, B / 100 )
00336          C = SLAMC3( F, A )
00337          IF( ( LRND ) .AND. ( C.EQ.A ) )
00338      $      LRND = .FALSE.
00339 *
00340 *        Try and decide whether rounding is done in the  IEEE  'round to
00341 *        nearest' style. B/2 is half a unit in the last place of the two
00342 *        numbers A and SAVEC. Furthermore, A is even, i.e. has last  bit
00343 *        zero, and SAVEC is odd. Thus adding B/2 to A should not  change
00344 *        A, but adding B/2 to SAVEC should change SAVEC.
00345 *
00346          T1 = SLAMC3( B / 2, A )
00347          T2 = SLAMC3( B / 2, SAVEC )
00348          LIEEE1 = ( T1.EQ.A ) .AND. ( T2.GT.SAVEC ) .AND. LRND
00349 *
00350 *        Now find  the  mantissa, t.  It should  be the  integer part of
00351 *        log to the base beta of a,  however it is safer to determine  t
00352 *        by powering.  So we find t as the smallest positive integer for
00353 *        which
00354 *
00355 *           fl( beta**t + 1.0 ) = 1.0.
00356 *
00357          LT = 0
00358          A = 1
00359          C = 1
00360 *
00361 *+       WHILE( C.EQ.ONE )LOOP
00362    30    CONTINUE
00363          IF( C.EQ.ONE ) THEN
00364             LT = LT + 1
00365             A = A*LBETA
00366             C = SLAMC3( A, ONE )
00367             C = SLAMC3( C, -A )
00368             GO TO 30
00369          END IF
00370 *+       END WHILE
00371 *
00372       END IF
00373 *
00374       BETA = LBETA
00375       T = LT
00376       RND = LRND
00377       IEEE1 = LIEEE1
00378       FIRST = .FALSE.
00379       RETURN
00380 *
00381 *     End of SLAMC1
00382 *
00383       END
00384 *
00385 ************************************************************************
00386 *
00387 *> \brief \b SLAMC2
00388 *> \details
00389 *> \b Purpose:
00390 *> \verbatim
00391 *> SLAMC2 determines the machine parameters specified in its argument
00392 *> list.
00393 *> \endverbatim
00394 *> \author LAPACK is a software package provided by Univ. of Tennessee, Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..
00395 *> \date November 2011
00396 *> \ingroup auxOTHERauxiliary
00397 *>
00398 *> \param[out] BETA
00399 *> \verbatim
00400 *>          The base of the machine.
00401 *> \endverbatim
00402 *>
00403 *> \param[out] T
00404 *> \verbatim
00405 *>          The number of ( BETA ) digits in the mantissa.
00406 *> \endverbatim
00407 *>
00408 *> \param[out] RND
00409 *> \verbatim
00410 *>          Specifies whether proper rounding  ( RND = .TRUE. )  or
00411 *>          chopping  ( RND = .FALSE. )  occurs in addition. This may not
00412 *>          be a reliable guide to the way in which the machine performs
00413 *>          its arithmetic.
00414 *> \endverbatim
00415 *>
00416 *> \param[out] EPS
00417 *> \verbatim
00418 *>          The smallest positive number such that
00419 *>             fl( 1.0 - EPS ) .LT. 1.0,
00420 *>          where fl denotes the computed value.
00421 *> \endverbatim
00422 *>
00423 *> \param[out] EMIN
00424 *> \verbatim
00425 *>          The minimum exponent before (gradual) underflow occurs.
00426 *> \endverbatim
00427 *>
00428 *> \param[out] RMIN
00429 *> \verbatim
00430 *>          The smallest normalized number for the machine, given by
00431 *>          BASE**( EMIN - 1 ), where  BASE  is the floating point value
00432 *>          of BETA.
00433 *> \endverbatim
00434 *>
00435 *> \param[out] EMAX
00436 *> \verbatim
00437 *>          The maximum exponent before overflow occurs.
00438 *> \endverbatim
00439 *>
00440 *> \param[out] RMAX
00441 *> \verbatim
00442 *>          The largest positive number for the machine, given by
00443 *>          BASE**EMAX * ( 1 - EPS ), where  BASE  is the floating point
00444 *>          value of BETA.
00445 *> \endverbatim
00446 *>
00447 *> \details \b Further \b Details
00448 *> \verbatim
00449 *>
00450 *>  The computation of  EPS  is based on a routine PARANOIA by
00451 *>  W. Kahan of the University of California at Berkeley.
00452 *> \endverbatim
00453       SUBROUTINE SLAMC2( BETA, T, RND, EPS, EMIN, RMIN, EMAX, RMAX )
00454 *
00455 *  -- LAPACK auxiliary routine (version 3.4.0) --
00456 *     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
00457 *     November 2010
00458 *
00459 *     .. Scalar Arguments ..
00460       LOGICAL            RND
00461       INTEGER            BETA, EMAX, EMIN, T
00462       REAL               EPS, RMAX, RMIN
00463 *     ..
00464 * =====================================================================
00465 *
00466 *     .. Local Scalars ..
00467       LOGICAL            FIRST, IEEE, IWARN, LIEEE1, LRND
00468       INTEGER            GNMIN, GPMIN, I, LBETA, LEMAX, LEMIN, LT,
00469      $                   NGNMIN, NGPMIN
00470       REAL               A, B, C, HALF, LEPS, LRMAX, LRMIN, ONE, RBASE,
00471      $                   SIXTH, SMALL, THIRD, TWO, ZERO
00472 *     ..
00473 *     .. External Functions ..
00474       REAL               SLAMC3
00475       EXTERNAL           SLAMC3
00476 *     ..
00477 *     .. External Subroutines ..
00478       EXTERNAL           SLAMC1, SLAMC4, SLAMC5
00479 *     ..
00480 *     .. Intrinsic Functions ..
00481       INTRINSIC          ABS, MAX, MIN
00482 *     ..
00483 *     .. Save statement ..
00484       SAVE               FIRST, IWARN, LBETA, LEMAX, LEMIN, LEPS, LRMAX,
00485      $                   LRMIN, LT
00486 *     ..
00487 *     .. Data statements ..
00488       DATA               FIRST / .TRUE. / , IWARN / .FALSE. /
00489 *     ..
00490 *     .. Executable Statements ..
00491 *
00492       IF( FIRST ) THEN
00493          ZERO = 0
00494          ONE = 1
00495          TWO = 2
00496 *
00497 *        LBETA, LT, LRND, LEPS, LEMIN and LRMIN  are the local values of
00498 *        BETA, T, RND, EPS, EMIN and RMIN.
00499 *
00500 *        Throughout this routine  we use the function  SLAMC3  to ensure
00501 *        that relevant values are stored  and not held in registers,  or
00502 *        are not affected by optimizers.
00503 *
00504 *        SLAMC1 returns the parameters  LBETA, LT, LRND and LIEEE1.
00505 *
00506          CALL SLAMC1( LBETA, LT, LRND, LIEEE1 )
00507 *
00508 *        Start to find EPS.
00509 *
00510          B = LBETA
00511          A = B**( -LT )
00512          LEPS = A
00513 *
00514 *        Try some tricks to see whether or not this is the correct  EPS.
00515 *
00516          B = TWO / 3
00517          HALF = ONE / 2
00518          SIXTH = SLAMC3( B, -HALF )
00519          THIRD = SLAMC3( SIXTH, SIXTH )
00520          B = SLAMC3( THIRD, -HALF )
00521          B = SLAMC3( B, SIXTH )
00522          B = ABS( B )
00523          IF( B.LT.LEPS )
00524      $      B = LEPS
00525 *
00526          LEPS = 1
00527 *
00528 *+       WHILE( ( LEPS.GT.B ).AND.( B.GT.ZERO ) )LOOP
00529    10    CONTINUE
00530          IF( ( LEPS.GT.B ) .AND. ( B.GT.ZERO ) ) THEN
00531             LEPS = B
00532             C = SLAMC3( HALF*LEPS, ( TWO**5 )*( LEPS**2 ) )
00533             C = SLAMC3( HALF, -C )
00534             B = SLAMC3( HALF, C )
00535             C = SLAMC3( HALF, -B )
00536             B = SLAMC3( HALF, C )
00537             GO TO 10
00538          END IF
00539 *+       END WHILE
00540 *
00541          IF( A.LT.LEPS )
00542      $      LEPS = A
00543 *
00544 *        Computation of EPS complete.
00545 *
00546 *        Now find  EMIN.  Let A = + or - 1, and + or - (1 + BASE**(-3)).
00547 *        Keep dividing  A by BETA until (gradual) underflow occurs. This
00548 *        is detected when we cannot recover the previous A.
00549 *
00550          RBASE = ONE / LBETA
00551          SMALL = ONE
00552          DO 20 I = 1, 3
00553             SMALL = SLAMC3( SMALL*RBASE, ZERO )
00554    20    CONTINUE
00555          A = SLAMC3( ONE, SMALL )
00556          CALL SLAMC4( NGPMIN, ONE, LBETA )
00557          CALL SLAMC4( NGNMIN, -ONE, LBETA )
00558          CALL SLAMC4( GPMIN, A, LBETA )
00559          CALL SLAMC4( GNMIN, -A, LBETA )
00560          IEEE = .FALSE.
00561 *
00562          IF( ( NGPMIN.EQ.NGNMIN ) .AND. ( GPMIN.EQ.GNMIN ) ) THEN
00563             IF( NGPMIN.EQ.GPMIN ) THEN
00564                LEMIN = NGPMIN
00565 *            ( Non twos-complement machines, no gradual underflow;
00566 *              e.g.,  VAX )
00567             ELSE IF( ( GPMIN-NGPMIN ).EQ.3 ) THEN
00568                LEMIN = NGPMIN - 1 + LT
00569                IEEE = .TRUE.
00570 *            ( Non twos-complement machines, with gradual underflow;
00571 *              e.g., IEEE standard followers )
00572             ELSE
00573                LEMIN = MIN( NGPMIN, GPMIN )
00574 *            ( A guess; no known machine )
00575                IWARN = .TRUE.
00576             END IF
00577 *
00578          ELSE IF( ( NGPMIN.EQ.GPMIN ) .AND. ( NGNMIN.EQ.GNMIN ) ) THEN
00579             IF( ABS( NGPMIN-NGNMIN ).EQ.1 ) THEN
00580                LEMIN = MAX( NGPMIN, NGNMIN )
00581 *            ( Twos-complement machines, no gradual underflow;
00582 *              e.g., CYBER 205 )
00583             ELSE
00584                LEMIN = MIN( NGPMIN, NGNMIN )
00585 *            ( A guess; no known machine )
00586                IWARN = .TRUE.
00587             END IF
00588 *
00589          ELSE IF( ( ABS( NGPMIN-NGNMIN ).EQ.1 ) .AND.
00590      $            ( GPMIN.EQ.GNMIN ) ) THEN
00591             IF( ( GPMIN-MIN( NGPMIN, NGNMIN ) ).EQ.3 ) THEN
00592                LEMIN = MAX( NGPMIN, NGNMIN ) - 1 + LT
00593 *            ( Twos-complement machines with gradual underflow;
00594 *              no known machine )
00595             ELSE
00596                LEMIN = MIN( NGPMIN, NGNMIN )
00597 *            ( A guess; no known machine )
00598                IWARN = .TRUE.
00599             END IF
00600 *
00601          ELSE
00602             LEMIN = MIN( NGPMIN, NGNMIN, GPMIN, GNMIN )
00603 *         ( A guess; no known machine )
00604             IWARN = .TRUE.
00605          END IF
00606          FIRST = .FALSE.
00607 ***
00608 * Comment out this if block if EMIN is ok
00609          IF( IWARN ) THEN
00610             FIRST = .TRUE.
00611             WRITE( 6, FMT = 9999 )LEMIN
00612          END IF
00613 ***
00614 *
00615 *        Assume IEEE arithmetic if we found denormalised  numbers above,
00616 *        or if arithmetic seems to round in the  IEEE style,  determined
00617 *        in routine SLAMC1. A true IEEE machine should have both  things
00618 *        true; however, faulty machines may have one or the other.
00619 *
00620          IEEE = IEEE .OR. LIEEE1
00621 *
00622 *        Compute  RMIN by successive division by  BETA. We could compute
00623 *        RMIN as BASE**( EMIN - 1 ),  but some machines underflow during
00624 *        this computation.
00625 *
00626          LRMIN = 1
00627          DO 30 I = 1, 1 - LEMIN
00628             LRMIN = SLAMC3( LRMIN*RBASE, ZERO )
00629    30    CONTINUE
00630 *
00631 *        Finally, call SLAMC5 to compute EMAX and RMAX.
00632 *
00633          CALL SLAMC5( LBETA, LT, LEMIN, IEEE, LEMAX, LRMAX )
00634       END IF
00635 *
00636       BETA = LBETA
00637       T = LT
00638       RND = LRND
00639       EPS = LEPS
00640       EMIN = LEMIN
00641       RMIN = LRMIN
00642       EMAX = LEMAX
00643       RMAX = LRMAX
00644 *
00645       RETURN
00646 *
00647  9999 FORMAT( / / ' WARNING. The value EMIN may be incorrect:-',
00648      $      '  EMIN = ', I8, /
00649      $      ' If, after inspection, the value EMIN looks',
00650      $      ' acceptable please comment out ',
00651      $      / ' the IF block as marked within the code of routine',
00652      $      ' SLAMC2,', / ' otherwise supply EMIN explicitly.', / )
00653 *
00654 *     End of SLAMC2
00655 *
00656       END
00657 *
00658 ************************************************************************
00659 *
00660 *> \brief \b SLAMC3
00661 *> \details
00662 *> \b Purpose:
00663 *> \verbatim
00664 *> SLAMC3  is intended to force  A  and  B  to be stored prior to doing
00665 *> the addition of  A  and  B ,  for use in situations where optimizers
00666 *> might hold one of these in a register.
00667 *> \endverbatim
00668 *>
00669 *> \param[in] A
00670 *>
00671 *> \param[in] B
00672 *> \verbatim
00673 *>          The values A and B.
00674 *> \endverbatim
00675 
00676       REAL FUNCTION SLAMC3( A, B )
00677 *
00678 *  -- LAPACK auxiliary routine (version 3.4.0) --
00679 *     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
00680 *     November 2010
00681 *
00682 *     .. Scalar Arguments ..
00683       REAL               A, B
00684 *     ..
00685 * =====================================================================
00686 *
00687 *     .. Executable Statements ..
00688 *
00689       SLAMC3 = A + B
00690 *
00691       RETURN
00692 *
00693 *     End of SLAMC3
00694 *
00695       END
00696 *
00697 ************************************************************************
00698 *
00699 *> \brief \b SLAMC4
00700 *> \details
00701 *> \b Purpose:
00702 *> \verbatim
00703 *> SLAMC4 is a service routine for SLAMC2.
00704 *> \endverbatim
00705 *>
00706 *> \param[out] EMIN
00707 *> \verbatim
00708 *>          The minimum exponent before (gradual) underflow, computed by
00709 *>          setting A = START and dividing by BASE until the previous A
00710 *>          can not be recovered.
00711 *> \endverbatim
00712 *>
00713 *> \param[in] START
00714 *> \verbatim
00715 *>          The starting point for determining EMIN.
00716 *> \endverbatim
00717 *>
00718 *> \param[in] BASE
00719 *> \verbatim
00720 *>          The base of the machine.
00721 *> \endverbatim
00722 *>
00723       SUBROUTINE SLAMC4( EMIN, START, BASE )
00724 *
00725 *  -- LAPACK auxiliary routine (version 3.4.0) --
00726 *     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
00727 *     November 2010
00728 *
00729 *     .. Scalar Arguments ..
00730       INTEGER            BASE
00731       INTEGER            EMIN
00732       REAL               START
00733 *     ..
00734 * =====================================================================
00735 *
00736 *     .. Local Scalars ..
00737       INTEGER            I
00738       REAL               A, B1, B2, C1, C2, D1, D2, ONE, RBASE, ZERO
00739 *     ..
00740 *     .. External Functions ..
00741       REAL               SLAMC3
00742       EXTERNAL           SLAMC3
00743 *     ..
00744 *     .. Executable Statements ..
00745 *
00746       A = START
00747       ONE = 1
00748       RBASE = ONE / BASE
00749       ZERO = 0
00750       EMIN = 1
00751       B1 = SLAMC3( A*RBASE, ZERO )
00752       C1 = A
00753       C2 = A
00754       D1 = A
00755       D2 = A
00756 *+    WHILE( ( C1.EQ.A ).AND.( C2.EQ.A ).AND.
00757 *    $       ( D1.EQ.A ).AND.( D2.EQ.A )      )LOOP
00758    10 CONTINUE
00759       IF( ( C1.EQ.A ) .AND. ( C2.EQ.A ) .AND. ( D1.EQ.A ) .AND.
00760      $    ( D2.EQ.A ) ) THEN
00761          EMIN = EMIN - 1
00762          A = B1
00763          B1 = SLAMC3( A / BASE, ZERO )
00764          C1 = SLAMC3( B1*BASE, ZERO )
00765          D1 = ZERO
00766          DO 20 I = 1, BASE
00767             D1 = D1 + B1
00768    20    CONTINUE
00769          B2 = SLAMC3( A*RBASE, ZERO )
00770          C2 = SLAMC3( B2 / RBASE, ZERO )
00771          D2 = ZERO
00772          DO 30 I = 1, BASE
00773             D2 = D2 + B2
00774    30    CONTINUE
00775          GO TO 10
00776       END IF
00777 *+    END WHILE
00778 *
00779       RETURN
00780 *
00781 *     End of SLAMC4
00782 *
00783       END
00784 *
00785 ************************************************************************
00786 *
00787 *> \brief \b SLAMC5
00788 *> \details
00789 *> \b Purpose:
00790 *> \verbatim
00791 *> SLAMC5 attempts to compute RMAX, the largest machine floating-point
00792 *> number, without overflow.  It assumes that EMAX + abs(EMIN) sum
00793 *> approximately to a power of 2.  It will fail on machines where this
00794 *> assumption does not hold, for example, the Cyber 205 (EMIN = -28625,
00795 *> EMAX = 28718).  It will also fail if the value supplied for EMIN is
00796 *> too large (i.e. too close to zero), probably with overflow.
00797 *> \endverbatim
00798 *>
00799 *> \param[in] BETA
00800 *> \verbatim
00801 *>          The base of floating-point arithmetic.
00802 *> \endverbatim
00803 *>
00804 *> \param[in] P
00805 *> \verbatim
00806 *>          The number of base BETA digits in the mantissa of a
00807 *>          floating-point value.
00808 *> \endverbatim
00809 *>
00810 *> \param[in] EMIN
00811 *> \verbatim
00812 *>          The minimum exponent before (gradual) underflow.
00813 *> \endverbatim
00814 *>
00815 *> \param[in] IEEE
00816 *> \verbatim
00817 *>          A logical flag specifying whether or not the arithmetic
00818 *>          system is thought to comply with the IEEE standard.
00819 *> \endverbatim
00820 *>
00821 *> \param[out] EMAX
00822 *> \verbatim
00823 *>          The largest exponent before overflow
00824 *> \endverbatim
00825 *>
00826 *> \param[out] RMAX
00827 *> \verbatim
00828 *>          The largest machine floating-point number.
00829 *> \endverbatim
00830 *>
00831       SUBROUTINE SLAMC5( BETA, P, EMIN, IEEE, EMAX, RMAX )
00832 *
00833 *  -- LAPACK auxiliary routine (version 3.4.0) --
00834 *     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
00835 *     November 2010
00836 *
00837 *     .. Scalar Arguments ..
00838       LOGICAL            IEEE
00839       INTEGER            BETA, EMAX, EMIN, P
00840       REAL               RMAX
00841 *     ..
00842 * =====================================================================
00843 *
00844 *     .. Parameters ..
00845       REAL               ZERO, ONE
00846       PARAMETER          ( ZERO = 0.0E0, ONE = 1.0E0 )
00847 *     ..
00848 *     .. Local Scalars ..
00849       INTEGER            EXBITS, EXPSUM, I, LEXP, NBITS, TRY, UEXP
00850       REAL               OLDY, RECBAS, Y, Z
00851 *     ..
00852 *     .. External Functions ..
00853       REAL               SLAMC3
00854       EXTERNAL           SLAMC3
00855 *     ..
00856 *     .. Intrinsic Functions ..
00857       INTRINSIC          MOD
00858 *     ..
00859 *     .. Executable Statements ..
00860 *
00861 *     First compute LEXP and UEXP, two powers of 2 that bound
00862 *     abs(EMIN). We then assume that EMAX + abs(EMIN) will sum
00863 *     approximately to the bound that is closest to abs(EMIN).
00864 *     (EMAX is the exponent of the required number RMAX).
00865 *
00866       LEXP = 1
00867       EXBITS = 1
00868    10 CONTINUE
00869       TRY = LEXP*2
00870       IF( TRY.LE.( -EMIN ) ) THEN
00871          LEXP = TRY
00872          EXBITS = EXBITS + 1
00873          GO TO 10
00874       END IF
00875       IF( LEXP.EQ.-EMIN ) THEN
00876          UEXP = LEXP
00877       ELSE
00878          UEXP = TRY
00879          EXBITS = EXBITS + 1
00880       END IF
00881 *
00882 *     Now -LEXP is less than or equal to EMIN, and -UEXP is greater
00883 *     than or equal to EMIN. EXBITS is the number of bits needed to
00884 *     store the exponent.
00885 *
00886       IF( ( UEXP+EMIN ).GT.( -LEXP-EMIN ) ) THEN
00887          EXPSUM = 2*LEXP
00888       ELSE
00889          EXPSUM = 2*UEXP
00890       END IF
00891 *
00892 *     EXPSUM is the exponent range, approximately equal to
00893 *     EMAX - EMIN + 1 .
00894 *
00895       EMAX = EXPSUM + EMIN - 1
00896       NBITS = 1 + EXBITS + P
00897 *
00898 *     NBITS is the total number of bits needed to store a
00899 *     floating-point number.
00900 *
00901       IF( ( MOD( NBITS, 2 ).EQ.1 ) .AND. ( BETA.EQ.2 ) ) THEN
00902 *
00903 *        Either there are an odd number of bits used to store a
00904 *        floating-point number, which is unlikely, or some bits are
00905 *        not used in the representation of numbers, which is possible,
00906 *        (e.g. Cray machines) or the mantissa has an implicit bit,
00907 *        (e.g. IEEE machines, Dec Vax machines), which is perhaps the
00908 *        most likely. We have to assume the last alternative.
00909 *        If this is true, then we need to reduce EMAX by one because
00910 *        there must be some way of representing zero in an implicit-bit
00911 *        system. On machines like Cray, we are reducing EMAX by one
00912 *        unnecessarily.
00913 *
00914          EMAX = EMAX - 1
00915       END IF
00916 *
00917       IF( IEEE ) THEN
00918 *
00919 *        Assume we are on an IEEE machine which reserves one exponent
00920 *        for infinity and NaN.
00921 *
00922          EMAX = EMAX - 1
00923       END IF
00924 *
00925 *     Now create RMAX, the largest machine number, which should
00926 *     be equal to (1.0 - BETA**(-P)) * BETA**EMAX .
00927 *
00928 *     First compute 1.0 - BETA**(-P), being careful that the
00929 *     result is less than 1.0 .
00930 *
00931       RECBAS = ONE / BETA
00932       Z = BETA - ONE
00933       Y = ZERO
00934       DO 20 I = 1, P
00935          Z = Z*RECBAS
00936          IF( Y.LT.ONE )
00937      $      OLDY = Y
00938          Y = SLAMC3( Y, Z )
00939    20 CONTINUE
00940       IF( Y.GE.ONE )
00941      $   Y = OLDY
00942 *
00943 *     Now multiply by BETA**EMAX to get RMAX.
00944 *
00945       DO 30 I = 1, EMAX
00946          Y = SLAMC3( Y*BETA, ZERO )
00947    30 CONTINUE
00948 *
00949       RMAX = Y
00950       RETURN
00951 *
00952 *     End of SLAMC5
00953 *
00954       END
 All Files Functions