rts-lapack.c

     
   1  //!@file rts-lapack.c
   2  //!@author J. Marcel van der Veer
   3  //
   4  // !@section Copyright
   5  //
   6  // This file is part of VIF - vintage FORTRAN compiler.
   7  // Copyright 2020-2024 J. Marcel van der Veer <algol68g@xs4all.nl>.
   8  //
   9  //! @section License
  10  //
  11  // This program is free software; you can redistribute it and/or modify it 
  12  // under the terms of the GNU General Public License as published by the 
  13  // Free Software Foundation; either version 3 of the License, or 
  14  // (at your option) any later version.
  15  //
  16  // This program is distributed in the hope that it will be useful, but 
  17  // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
  18  // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 
  19  // more details. You should have received a copy of the GNU General Public 
  20  // License along with this program. If not, see <http://www.gnu.org/licenses/>.
  21  
  22  //! @section Synopsis
  23  //!
  24  //! Runtime support for LAPACK subprograms.
  25  
  26  // Auxilliary routines for LAPACK.
  27  
  28  #include "vif.h"
  29  
  30  int_4 xerbla_(char *, int_4 *);
  31  logical_4 _lsame (char _p_, char _p_);
  32  real_8 _dlamch (char _p_ cmach);
  33  int_4 _dlamc1 (int_4 *, int_4 *, logical_4 *, logical_4 *);
  34  int_4 _dlamc2 (int_4 *, int_4 *, logical_4 *, real_8 *, int_4 *, real_8 *, int_4 *, real_8 *);
  35  real_8 _dlamc3 (real_8 *, real_8 *);
  36  int_4 _dlamc4 (int_4 *, real_8 *, int_4 *);
  37  int_4 _dlamc5 (int_4 *, int_4 *, int_4 *, logical_4 *, int_4 *, real_8 *);
  38  
  39  static real_8 zero_arg = 0.0;
  40  
  41  logical_4 _lsame (char _p_ ca, char _p_ cb)
  42  {
  43  //  -- LAPACK auxiliary routine (version 3.2) --
  44  //   Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
  45  //   November 2006
  46  //
  47  //   .. Scalar Arguments ..
  48  //   ..
  49  //
  50  //  Purpose
  51  //  =======
  52  //
  53  //  LSAME returns .TRUE. if CA is the same letter as CB regardless of
  54  //  case.
  55  //
  56  //  Arguments
  57  //  =========
  58  //
  59  //  CA    (input) CHARACTER*1
  60  //  CB    (input) CHARACTER*1
  61  //      CA and CB specify the single characters to be compared.
  62  //
  63  // This is the VIF version of the verbose LAPACK routine.
  64  //
  65    if (ca != NULL && cb != NULL) {
  66      return tolower (*ca) == tolower (*cb);
  67    } else {
  68      return FALSE;
  69    }
  70  }
  71  
  72  real_8 _dlamch (char _p_ cmach)
  73  {
  74  //
  75  //  -- LAPACK auxiliary routine (version 3.2) --
  76  //   Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
  77  //   November 2006
  78  //
  79  //   .. Scalar Arguments ..
  80  //   ..
  81  //
  82  //  Purpose
  83  //  =======
  84  //
  85  //  DLAMCH determines double precision machine parameters.
  86  //
  87  //  Arguments
  88  //  =========
  89  //
  90  //  CMACH   (input) CHARACTER*1
  91  //      Specifies the value to be returned by DLAMCH:
  92  //      = 'E' or 'e',   DLAMCH := eps
  93  //      = 'S' or 's ,   DLAMCH := sfmin
  94  //      = 'B' or 'b',   DLAMCH := base
  95  //      = 'P' or 'p',   DLAMCH := eps*base
  96  //      = 'N' or 'n',   DLAMCH := t
  97  //      = 'R' or 'r',   DLAMCH := rnd
  98  //      = 'M' or 'm',   DLAMCH := emin
  99  //      = 'U' or 'u',   DLAMCH := rmin
 100  //      = 'L' or 'l',   DLAMCH := emax
 101  //      = 'O' or 'o',   DLAMCH := rmax
 102  //
 103  //      where
 104  //
 105  //      eps   = relative machine precision
 106  //      sfmin = safe minimum, such that 1/sfmin does not overflow
 107  //      base  = base of the machine
 108  //      prec  = eps*base
 109  //      t   = number of (base) digits in the mantissa
 110  //      rnd   = 1.0 when rounding occurs in addition, 0.0 otherwise
 111  //      emin  = minimum exponent before (gradual) underflow
 112  //      rmin  = underflow threshold - base**(emin-1)
 113  //      emax  = largest exponent before overflow
 114  //      rmax  = overflow threshold  - (base**emax)*(1-eps)
 115  //
 116    int_4 beta, imin, imax, it, i__1;
 117    logical_4 lrnd;
 118    real_8 rmach = 0.0, small;
 119    static logical_4 first = TRUE;
 120    static real_8 emin, prec, emax, rmin, rmax, rnd, eps, base, sfmin, t;
 121    if (first) {
 122      _dlamc2 (&beta, &it, &lrnd, &eps, &imin, &rmin, &imax, &rmax);
 123      base = (real_8) beta;
 124      t = (real_8) it;
 125      if (lrnd) {
 126        rnd = 1.0;
 127        i__1 = 1 - it;
 128        eps = _up_real_8 (base, i__1) / 2;
 129      } else {
 130        rnd = 0.0;
 131        i__1 = 1 - it;
 132        eps = _up_real_8 (base, i__1);
 133      }
 134      prec = eps * base;
 135      emin = (real_8) imin;
 136      emax = (real_8) imax;
 137      sfmin = rmin;
 138      small = 1.0 / rmax;
 139      if (small >= sfmin) {
 140  // Use SMALL plus a bit, to avoid the possibility of rounding
 141  // causing overflow when computing  1/sfmin.
 142        sfmin = small * (eps + 1.0);
 143      }
 144    }
 145  //
 146    if (_lsame (cmach, "E")) {
 147      rmach = eps;
 148    } else if (_lsame (cmach, "S")) {
 149      rmach = sfmin;
 150    } else if (_lsame (cmach, "B")) {
 151      rmach = base;
 152    } else if (_lsame (cmach, "P")) {
 153      rmach = prec;
 154    } else if (_lsame (cmach, "N")) {
 155      rmach = t;
 156    } else if (_lsame (cmach, "R")) {
 157      rmach = rnd;
 158    } else if (_lsame (cmach, "M")) {
 159      rmach = emin;
 160    } else if (_lsame (cmach, "U")) {
 161      rmach = rmin;
 162    } else if (_lsame (cmach, "L")) {
 163      rmach = emax;
 164    } else if (_lsame (cmach, "O")) {
 165      rmach = rmax;
 166    }
 167  //
 168    first = FALSE;
 169    return rmach;
 170  }
 171  
 172  int_4 _dlamc1 (int_4 _p_ beta, int_4 _p_ t, logical_4 _p_ rnd, logical_4 _p_ ieee1)
 173  {
 174  //
 175  //
 176  //  -- LAPACK auxiliary routine (version 3.2) --
 177  //   Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
 178  //   November 2006
 179  //
 180  //   .. Scalar Arguments ..
 181  //   ..
 182  //
 183  //  Purpose
 184  //  =======
 185  //
 186  //  DLAMC1 determines the machine parameters given by BETA, T, RND, and
 187  //  IEEE1.
 188  //
 189  //  Arguments
 190  //  =========
 191  //
 192  //  BETA  (output) INTEGER
 193  //      The base of the machine.
 194  //
 195  //  T     (output) INTEGER
 196  //      The number of ( BETA ) digits in the mantissa.
 197  //
 198  //  RND   (output) LOGICAL
 199  //      Specifies whether proper rounding  ( RND = .TRUE. )  or
 200  //      chopping  ( RND = .FALSE. )  occurs in addition. This may not
 201  //      be a reliable guide to the way in which the machine performs
 202  //      its arithmetic.
 203  //
 204  //  IEEE1   (output) LOGICAL
 205  //      Specifies whether rounding appears to be done in the IEEE
 206  //      'round to nearest' style.
 207  //
 208  //  Further Details
 209  //  ===============
 210  //
 211  //  The routine is based on the routine  ENVRON  by Malcolm and
 212  //  incorporates suggestions by Gentleman and Marovich. See
 213  //
 214  //   Malcolm M. A. (1972) Algorithms to reveal properties of
 215  //    floating-point arithmetic. Comms. of the ACM, 15, 949-951.
 216  //
 217  //   Gentleman W. M. and Marovich S. B. (1974) More on algorithms
 218  //    that reveal properties of floating point arithmetic units.
 219  //    Comms. of the ACM, 17, 276-277.
 220  //
 221    real_8 a, b, c__, f, t1, t2, d__1, d__2, one, qtr, savec;
 222    static int_4 lbeta, lt;
 223    static logical_4 first = TRUE, lieee1, lrnd;
 224    if (first) {
 225      one = 1.0;
 226  // LBETA,  LIEEE1,  LT and  LRND  are the  local values  of  BETA,
 227  // IEEE1, T and RND.
 228  //
 229  // Throughout this routine  we use the function  DLAMC3  to ensure
 230  // that relevant values are  stored and not held in registers,  or
 231  // are not affected by optimizers.
 232  //
 233  // Compute  a = 2.0**m  with the  smallest positive int_4 m such
 234  // that
 235  //
 236  // fl( a + 1.0 ) = a.
 237  //
 238      a = 1.0;
 239      c__ = 1.0;
 240  // +     WHILE( C.EQ.ONE )LOOP
 241      while (c__ == one) {
 242        a *= 2;
 243        c__ = _dlamc3 (&a, &one);
 244        d__1 = -a;
 245        c__ = _dlamc3 (&c__, &d__1);
 246      }
 247  // +     END WHILE
 248  //
 249  // Now compute  b = 2.0**m  with the smallest positive int_4 m
 250  // such that
 251  //
 252  // fl( a + b ) .gt. a.
 253      b = 1.0;
 254      c__ = _dlamc3 (&a, &b);
 255  // +     WHILE( C.EQ.A )LOOP
 256      while (c__ == a) {
 257        b *= 2;
 258        c__ = _dlamc3 (&a, &b);
 259      }
 260  // +     END WHILE
 261  //
 262  // Now compute the base.  a and c  are neighbouring floating point
 263  // numbers  in the  interval  ( beta**t, beta**( t + 1 ) )  and so
 264  // their difference is beta. Adding 0.25 to c is to ensure that it
 265  // is truncated to beta and not ( beta - 1 ).
 266      qtr = one / 4;
 267      savec = c__;
 268      d__1 = -a;
 269      c__ = _dlamc3 (&c__, &d__1);
 270      lbeta = (int_4) (c__ + qtr);
 271  // Now determine whether rounding or chopping occurs,  by adding a
 272  // bit  less  than  beta/2  and a  bit  more  than  beta/2  to  a.
 273      b = (real_8) lbeta;
 274      d__1 = b / 2;
 275      d__2 = -b / 100;
 276      f = _dlamc3 (&d__1, &d__2);
 277      c__ = _dlamc3 (&f, &a);
 278      if (c__ == a) {
 279        lrnd = TRUE;
 280      } else {
 281        lrnd = FALSE;
 282      }
 283      d__1 = b / 2;
 284      d__2 = b / 100;
 285      f = _dlamc3 (&d__1, &d__2);
 286      c__ = _dlamc3 (&f, &a);
 287      if (lrnd && c__ == a) {
 288        lrnd = FALSE;
 289      }
 290  // Try and decide whether rounding is done in the  IEEE  'round to
 291  // nearest' style. B/2 is half a unit in the last place of the two
 292  // numbers A and SAVEC. Furthermore, A is even, i.e. has last  bit
 293  // zero, and SAVEC is odd. Thus adding B/2 to A should not  change
 294  // A, but adding B/2 to SAVEC should change SAVEC.
 295      d__1 = b / 2;
 296      t1 = _dlamc3 (&d__1, &a);
 297      d__1 = b / 2;
 298      t2 = _dlamc3 (&d__1, &savec);
 299      lieee1 = t1 == a && t2 > savec && lrnd;
 300  // Now find  the  mantissa, t.  It should  be the  int_4 part of
 301  // log to the base beta of a,  however it is safer to determine  t
 302  // by powering.  So we find t as the smallest positive int_4 for
 303  // which
 304  //
 305  //    fl( beta**t + 1.0 ) = 1.0.
 306      lt = 0;
 307      a = 1.0;
 308      c__ = 1.0;
 309  // +     WHILE( C.EQ.ONE )LOOP
 310      while (c__ == one) {
 311        ++lt;
 312        a *= lbeta;
 313        c__ = _dlamc3 (&a, &one);
 314        d__1 = -a;
 315        c__ = _dlamc3 (&c__, &d__1);
 316      }
 317  // +     END WHILE
 318    }
 319    *beta = lbeta;
 320    *t = lt;
 321    *rnd = lrnd;
 322    *ieee1 = lieee1;
 323    first = FALSE;
 324    return 0;
 325  }
 326  
 327  int_4 _dlamc2 (int_4 _p_ beta, int_4 _p_ t, logical_4 _p_ rnd, real_8 _p_ eps, int_4 _p_ emin, 
 328                     real_8 _p_ rmin, int_4 _p_ emax, real_8 _p_ rmax)
 329  {
 330  //
 331  //  -- LAPACK auxiliary routine (version 3.2) --
 332  //   Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
 333  //   November 2006
 334  //
 335  //   .. Scalar Arguments ..
 336  //   ..
 337  //
 338  //  Purpose
 339  //  =======
 340  //
 341  //  DLAMC2 determines the machine parameters specified in its argument
 342  //  list.
 343  //
 344  //  Arguments
 345  //  =========
 346  //
 347  //  BETA  (output) INTEGER
 348  //      The base of the machine.
 349  //
 350  //  T     (output) INTEGER
 351  //      The number of ( BETA ) digits in the mantissa.
 352  //
 353  //  RND   (output) LOGICAL
 354  //      Specifies whether proper rounding  ( RND = .TRUE. )  or
 355  //      chopping  ( RND = .FALSE. )  occurs in addition. This may not
 356  //      be a reliable guide to the way in which the machine performs
 357  //      its arithmetic.
 358  //
 359  //  EPS   (output) DOUBLE PRECISION
 360  //      The smallest positive number such that
 361  //
 362  //       fl( 1.0 - EPS ) .LT. 1.0,
 363  //
 364  //      where fl denotes the computed value.
 365  //
 366  //  EMIN  (output) INTEGER
 367  //      The minimum exponent before (gradual) underflow occurs.
 368  //
 369  //  RMIN  (output) DOUBLE PRECISION
 370  //      The smallest normalized number for the machine, given by
 371  //      BASE**( EMIN - 1 ), where  BASE  is the floating point value
 372  //      of BETA.
 373  //
 374  //  EMAX  (output) INTEGER
 375  //      The maximum exponent before overflow occurs.
 376  //
 377  //  RMAX  (output) DOUBLE PRECISION
 378  //      The largest positive number for the machine, given by
 379  //      BASE**EMAX * ( 1 - EPS ), where  BASE  is the floating point
 380  //      value of BETA.
 381  //
 382  //  Further Details
 383  //  ===============
 384  //
 385  //  The computation of  EPS  is based on a routine PARANOIA by
 386  //  W. Kahan of the University of California at Berkeley.
 387  //
 388    int_4 gnmin, gpmin, i__, i__1, ngnmin, ngpmin;
 389    logical_4 ieee, lieee1, lrnd = TRUE;
 390    real_8 a, b, c__, d__1, d__2, d__3, d__4, d__5;
 391    real_8 half, one, two, rbase, sixth, small, third, zero;
 392    static int_4 lbeta, lemin, lemax, lt;
 393    static logical_4 first = TRUE, iwarn = FALSE;
 394    static real_8 leps, lrmin, lrmax;
 395    if (first) {
 396      zero = 0.0;
 397      one = 1.0;
 398      two = 2.0;
 399  // LBETA, LT, LRND, LEPS, LEMIN and LRMIN  are the local values of
 400  // BETA, T, RND, EPS, EMIN and RMIN.
 401  //
 402  // Throughout this routine  we use the function  DLAMC3  to ensure
 403  // that relevant values are stored  and not held in registers,  or
 404  // are not affected by optimizers.
 405  //
 406  // DLAMC1 returns the parameters  LBETA, LT, LRND and LIEEE1.
 407      _dlamc1 (&lbeta, &lt, &lrnd, &lieee1);
 408  // Start to find EPS.
 409      b = (real_8) lbeta;
 410      i__1 = -lt;
 411      a = _up_real_8 (b, i__1);
 412      leps = a;
 413  // Try some tricks to see whether or not this is the correct  EPS.
 414      b = two / 3;
 415      half = one / 2;
 416      d__1 = -half;
 417      sixth = _dlamc3 (&b, &d__1);
 418      third = _dlamc3 (&sixth, &sixth);
 419      d__1 = -half;
 420      b = _dlamc3 (&third, &d__1);
 421      b = _dlamc3 (&b, &sixth);
 422      b = abs (b);
 423      if (b < leps) {
 424        b = leps;
 425      }
 426      leps = 1.0;
 427  // +     WHILE( ( LEPS.GT.B ).AND.( B.GT.ZERO ) )LOOP
 428      while (leps > b && b > zero) {
 429        leps = b;
 430        d__1 = half * leps;
 431  // Computing 5th power
 432        d__3 = two, d__4 = d__3, d__3 *= d__3;
 433  // Computing 2nd power
 434        d__5 = leps;
 435        d__2 = d__4 * (d__3 * d__3) * (d__5 * d__5);
 436        c__ = _dlamc3 (&d__1, &d__2);
 437        d__1 = -c__;
 438        c__ = _dlamc3 (&half, &d__1);
 439        b = _dlamc3 (&half, &c__);
 440        d__1 = -b;
 441        c__ = _dlamc3 (&half, &d__1);
 442        b = _dlamc3 (&half, &c__);
 443      }
 444  // +     END WHILE
 445      if (a < leps) {
 446        leps = a;
 447      }
 448  // Computation of EPS complete.
 449  //
 450  // Now find  EMIN.  Let A = + or - 1, and + or - (1 + BASE**(-3)).
 451  // Keep dividing  A by BETA until (gradual) underflow occurs. This
 452  // is detected when we cannot recover the previous A.
 453      rbase = one / lbeta;
 454      small = one;
 455      for (i__ = 1; i__ <= 3; ++i__) {
 456        d__1 = small * rbase;
 457        small = _dlamc3 (&d__1, &zero);
 458      }
 459      a = _dlamc3 (&one, &small);
 460      _dlamc4 (&ngpmin, &one, &lbeta);
 461      d__1 = -one;
 462      _dlamc4 (&ngnmin, &d__1, &lbeta);
 463      _dlamc4 (&gpmin, &a, &lbeta);
 464      d__1 = -a;
 465      _dlamc4 (&gnmin, &d__1, &lbeta);
 466      ieee = FALSE;
 467      if (ngpmin == ngnmin && gpmin == gnmin) {
 468        if (ngpmin == gpmin) {
 469      lemin = ngpmin;
 470  // Non twos-complement machines, no gradual underflow; e.g., VAX
 471        } else if (gpmin - ngpmin == 3) {
 472      lemin = ngpmin - 1 + lt;
 473      ieee = TRUE;
 474  // Non twos-complement machines, with gradual underflow; e.g., IEEE standard followers
 475        } else {
 476      lemin = _min (ngpmin, gpmin);
 477  // A guess; no known machine
 478      iwarn = TRUE;
 479        }
 480      } else if (ngpmin == gpmin && ngnmin == gnmin) {
 481        if ((i__1 = ngpmin - ngnmin, abs (i__1)) == 1) {
 482      lemin = _max (ngpmin, ngnmin);
 483  // Twos-complement machines, no gradual underflow; e.g., CYBER 205
 484        } else {
 485      lemin = _min (ngpmin, ngnmin);
 486  // A guess; no known machine
 487      iwarn = TRUE;
 488        }
 489      } else if ((i__1 = ngpmin - ngnmin, abs (i__1)) == 1 && gpmin == gnmin) {
 490        if (gpmin - _min (ngpmin, ngnmin) == 3) {
 491      lemin = _max (ngpmin, ngnmin) - 1 + lt;
 492  // Twos-complement machines with gradual underflow; no known machine
 493        } else {
 494      lemin = _min (ngpmin, ngnmin);
 495  // A guess; no known machine
 496      iwarn = TRUE;
 497        }
 498      } else {
 499  // Computing MIN
 500        i__1 = _min (ngpmin, ngnmin), i__1 = _min (i__1, gpmin);
 501        lemin = _min (i__1, gnmin);
 502  // A guess; no known machine
 503        iwarn = TRUE;
 504      }
 505      first = FALSE;
 506  // **
 507  // Comment out this if block if EMIN is ok
 508      if (iwarn) {
 509        fprintf (stderr, "WARNING. The value EMIN may be incorrect: EMIN = %d",
 510             lemin);
 511        fprintf (stderr,
 512             "If, after inspection, the value EMIN looks acceptable please");
 513        fprintf (stderr,
 514             "comment out the IF block as marked within the code of routine,");
 515        fprintf (stderr, "DLAMC2, otherwise supply EMIN explicitly.");
 516        first = TRUE;
 517      }
 518  // Assume IEEE arithmetic if we found denormalised  numbers above,
 519  // or if arithmetic seems to round in the  IEEE style,  determined
 520  // in routine DLAMC1. A true IEEE machine should have both  things
 521  // true; however, faulty machines may have one or the other.
 522      ieee = ieee || lieee1;
 523  // Compute  RMIN by successive division by  BETA. We could compute
 524  // RMIN as BASE**( EMIN - 1 ),  but some machines underflow during
 525  // this computation.
 526      lrmin = 1.0;
 527      i__1 = 1 - lemin;
 528      for (i__ = 1; i__ <= i__1; ++i__) {
 529        d__1 = lrmin * rbase;
 530        lrmin = _dlamc3 (&d__1, &zero);
 531      }
 532  // Finally, call DLAMC5 to compute EMAX and RMAX.
 533      _dlamc5 (&lbeta, &lt, &lemin, &ieee, &lemax, &lrmax);
 534    }
 535    *beta = lbeta;
 536    *t = lt;
 537    *rnd = lrnd;
 538    *eps = leps;
 539    *emin = lemin;
 540    *rmin = lrmin;
 541    *emax = lemax;
 542    *rmax = lrmax;
 543    return 0;
 544  }
 545  
 546  real_8 _dlamc3 (real_8 _p_ a, real_8 _p_ b)
 547  {
 548  //
 549  //  -- LAPACK auxiliary routine (version 3.2) --
 550  //   Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
 551  //   November 2006
 552  //
 553  //   .. Scalar Arguments ..
 554  //   ..
 555  //
 556  //  Purpose
 557  //  =======
 558  //
 559  //  DLAMC3  is intended to force  A  and  B  to be stored prior to doing
 560  //  the addition of  A  and  B ,  for use in situations where optimizers
 561  //  might hold one of these in a register.
 562  //
 563  //  Arguments
 564  //  =========
 565  //
 566  //  A     (input) DOUBLE PRECISION
 567  //  B     (input) DOUBLE PRECISION
 568  //      The values A and B.
 569  //
 570    return (*a) + (*b);
 571  }
 572  
 573  int_4 _dlamc4 (int_4 _p_ emin, real_8 _p_ start, int_4 _p_ base)
 574  {
 575  //
 576  //  -- LAPACK auxiliary routine (version 3.2) --
 577  //   Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
 578  //   November 2006
 579  //
 580  //   .. Scalar Arguments ..
 581  //   ..
 582  //
 583  //  Purpose
 584  //  =======
 585  //
 586  //  DLAMC4 is a service routine for DLAMC2.
 587  //
 588  //  Arguments
 589  //  =========
 590  //
 591  //  EMIN  (output) INTEGER
 592  //      The minimum exponent before (gradual) underflow, computed by
 593  //      setting A = START and dividing by BASE until the previous A
 594  //      can not be recovered.
 595  //
 596  //  START   (input) DOUBLE PRECISION
 597  //      The starting point for determining EMIN.
 598  //
 599  //  BASE  (input) INTEGER
 600  //      The base of the machine.
 601  //
 602    int_4 i__, i__1;
 603    real_8 a, b1, b2, c1, c2, d__1, d1, d2, one, zero, rbase;
 604    a = *start;
 605    one = 1.0;
 606    rbase = one / *base;
 607    zero = 0.0;
 608    *emin = 1;
 609    d__1 = a * rbase;
 610    b1 = _dlamc3 (&d__1, &zero);
 611    c1 = a;
 612    c2 = a;
 613    d1 = a;
 614    d2 = a;
 615  // +  WHILE( ( C1.EQ.A ).AND.( C2.EQ.A ).AND.
 616  //  $     ( D1.EQ.A ).AND.( D2.EQ.A )    )LOOP
 617    while (c1 == a && c2 == a && d1 == a && d2 == a) {
 618      --(*emin);
 619      a = b1;
 620      d__1 = a / *base;
 621      b1 = _dlamc3 (&d__1, &zero);
 622      d__1 = b1 * *base;
 623      c1 = _dlamc3 (&d__1, &zero);
 624      d1 = zero;
 625      i__1 = *base;
 626      for (i__ = 1; i__ <= i__1; ++i__) {
 627        d1 += b1;
 628      }
 629      d__1 = a * rbase;
 630      b2 = _dlamc3 (&d__1, &zero);
 631      d__1 = b2 / rbase;
 632      c2 = _dlamc3 (&d__1, &zero);
 633      d2 = zero;
 634      i__1 = *base;
 635      for (i__ = 1; i__ <= i__1; ++i__) {
 636        d2 += b2;
 637      }
 638    }
 639  // +  END WHILE
 640    return 0;
 641  }
 642  
 643  int_4 _dlamc5 (int_4 _p_ beta, int_4 _p_ p, int_4 _p_ emin, logical_4 _p_ ieee, int_4 _p_ emax, real_8 _p_ rmax)
 644  {
 645  //
 646  //  -- LAPACK auxiliary routine (version 3.2) --
 647  //   Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd..
 648  //   November 2006
 649  //
 650  //   .. Scalar Arguments ..
 651  //   ..
 652  //
 653  //  Purpose
 654  //  =======
 655  //
 656  //  DLAMC5 attempts to compute RMAX, the largest machine floating-point
 657  //  number, without overflow.  It assumes that EMAX + abs(EMIN) sum
 658  //  approximately to a power of 2.  It will fail on machines where this
 659  //  assumption does not hold, for example, the Cyber 205 (EMIN = -28625,
 660  //  EMAX = 28718).  It will also fail if the value supplied for EMIN is
 661  //  too large (i.e. too close to zero), probably with overflow.
 662  //
 663  //  Arguments
 664  //  =========
 665  //
 666  //  BETA  (input) INTEGER
 667  //      The base of floating-point arithmetic.
 668  //
 669  //  P     (input) INTEGER
 670  //      The number of base BETA digits in the mantissa of a
 671  //      floating-point value.
 672  //
 673  //  EMIN  (input) INTEGER
 674  //      The minimum exponent before (gradual) underflow.
 675  //
 676  //  IEEE  (input) LOGICAL
 677  //      A logical flag specifying whether or not the arithmetic
 678  //      system is thought to comply with the IEEE standard.
 679  //
 680  //  EMAX  (output) INTEGER
 681  //      The largest exponent before overflow
 682  //
 683  //  RMAX  (output) DOUBLE PRECISION
 684  //      The largest machine floating-point number.
 685  //
 686  //   First compute LEXP and UEXP, two powers of 2 that bound
 687  //   abs(EMIN). We then assume that EMAX + abs(EMIN) will sum
 688  //   approximately to the bound that is closest to abs(EMIN).
 689  //   (EMAX is the exponent of the required number RMAX).
 690  //
 691    int_4 exbits, expsum, i__, i__1, try, lexp, uexp, nbits;
 692    real_8 d__1, oldy, recbas;
 693    lexp = 1;
 694    exbits = 1;
 695    logical_4 cont = TRUE;
 696    while (cont) {
 697      try = lexp << 1;
 698      if (try <= -(*emin)) {
 699        lexp = try;
 700        ++exbits;
 701      } else {
 702        cont = FALSE;
 703      }
 704    }
 705    if (lexp == -(*emin)) {
 706      uexp = lexp;
 707    } else {
 708      uexp = try;
 709      ++exbits;
 710    }
 711  // Now -LEXP is less than or equal to EMIN, and -UEXP is greater
 712  // than or equal to EMIN. EXBITS is the number of bits needed to
 713  // store the exponent.
 714    if (uexp + *emin > -lexp - *emin) {
 715      expsum = lexp << 1;
 716    } else {
 717      expsum = uexp << 1;
 718    }
 719  // EXPSUM is the exponent range, approximately equal to
 720  // EMAX - EMIN + 1 .
 721    *emax = expsum + *emin - 1;
 722    nbits = exbits + 1 + *p;
 723  // NBITS is the total number of bits needed to store a
 724  // floating-point number.
 725    if (nbits % 2 == 1 && *beta == 2) {
 726  // Either there are an odd number of bits used to store a
 727  // floating-point number, which is unlikely, or some bits are
 728  // not used in the representation of numbers, which is possible,
 729  // (e.g. Cray machines) or the mantissa has an implicit bit,
 730  // (e.g. IEEE machines, Dec Vax machines), which is perhaps the
 731  // most likely. We have to assume the last alternative.
 732  // If this is true, then we need to reduce EMAX by one because
 733  // there must be some way of representing zero in an implicit-bit
 734  // system. On machines like Cray, we are reducing EMAX by one
 735  // unnecessarily.
 736      --(*emax);
 737    }
 738    if (*ieee) {
 739  // Assume we are on an IEEE machine which reserves one exponent
 740  // for infinity and NaN.
 741      --(*emax);
 742    }
 743  // Now create RMAX, the largest machine number, which should
 744  // be equal to (1.0 - BETA**(-P)) * BETA**EMAX .
 745  //
 746  // First compute 1.0 - BETA**(-P), being careful that the
 747  // result is less than 1.0 .
 748    recbas = 1.0 / *beta;
 749    real_8 z__ = *beta - 1.0;
 750    real_8 y = 0.0;
 751    i__1 = *p;
 752    for (i__ = 1; i__ <= i__1; ++i__) {
 753      z__ *= recbas;
 754      if (y < 1.0) {
 755        oldy = y;
 756      }
 757      y = _dlamc3 (&y, &z__);
 758    }
 759    if (y >= 1.0) {
 760      y = oldy;
 761    }
 762  // Now multiply by BETA**EMAX to get RMAX.
 763    i__1 = *emax;
 764    for (i__ = 1; i__ <= i__1; ++i__) {
 765      d__1 = y * (*beta);
 766      y = _dlamc3 (&d__1, &zero_arg);
 767    }
 768    *rmax = y;
 769    return 0;
 770  }
 771  
 772  int_4 _xerbla(char _p_ srname, int_4 _p_ info)
 773  {
 774  //
 775  //  -- LAPACK auxiliary routine (version 3.2) -- 
 776  //     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. 
 777  //     November 2006 
 778  //
 779  //     .. Scalar Arguments .. 
 780  //     .. 
 781  //
 782  //  Purpose 
 783  //  ======= 
 784  //
 785  //  XERBLA  is an error handler for the LAPACK routines. 
 786  //  It is called by an LAPACK routine if an input parameter has an 
 787  //  invalid value.  A message is printed and execution stops. 
 788  //
 789  //  Installers may consider modifying the STOP statement in order to 
 790  //  call system-specific exception-handling facilities. 
 791  //
 792  //  Arguments 
 793  //  ========= 
 794  //
 795  //  SRNAME  (input) CHARACTER*(*) 
 796  //          The name of the routine which called XERBLA. 
 797  //
 798  //  INFO    (input) INTEGER 
 799  //          The position of the invalid parameter in the parameter list 
 800  //          of the calling routine. 
 801  //
 802      fprintf(stderr, "** blas       ** error: %6s: invalid parameter #%2d\n", srname, *info);
 803      exit (EXIT_FAILURE);
 804      return 0;
 805  }
     


© 2002-2024 J.M. van der Veer (jmvdveer@xs4all.nl)