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