Update to 2.0.0 tree from current Fremantle build
[opencv] / 3rdparty / lapack / slamch.c
1 #include "clapack.h"
2 #include <float.h>
3 #include <stdio.h>
4
5 /* *********************************************************************** */
6
7 doublereal slamc3_(real *a, real *b)
8 {
9     /* System generated locals */
10     real ret_val;
11     
12     
13     /*  -- LAPACK auxiliary routine (version 3.1) -- */
14     /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
15     /*     November 2006 */
16     
17     /*     .. Scalar Arguments .. */
18     /*     .. */
19     
20     /*  Purpose */
21     /*  ======= */
22     
23     /*  SLAMC3  is intended to force  A  and  B  to be stored prior to doing */
24     /*  the addition of  A  and  B ,  for use in situations where optimizers */
25     /*  might hold one of these in a register. */
26     
27     /*  Arguments */
28     /*  ========= */
29     
30     /*  A       (input) REAL */
31     /*  B       (input) REAL */
32     /*          The values A and B. */
33     
34     /* ===================================================================== */
35     
36     /*     .. Executable Statements .. */
37     
38     ret_val = *a + *b;
39     
40     return ret_val;
41     
42     /*     End of SLAMC3 */
43     
44 } /* slamc3_ */
45
46
47 #if 1
48
49 /* simpler version of dlamch for the case of IEEE754-compliant FPU module by Piotr Luszczek S.
50  taken from http://www.mail-archive.com/numpy-discussion@lists.sourceforge.net/msg02448.html */
51
52 #ifndef FLT_DIGITS
53 #define FLT_DIGITS 24
54 #endif
55
56 doublereal
57 slamch_(char *cmach) {
58     char ch = cmach[0];
59     float eps=FLT_EPSILON*0.5f, sfmin, small;
60
61     if ('B' == ch || 'b' == ch) {
62         return FLT_RADIX;
63     } else if ('E' == ch || 'e' == ch) {
64         return eps;
65     } else if ('L' == ch || 'l' == ch) {
66         return FLT_MAX_EXP;
67     } else if ('M' == ch || 'm' == ch) {
68         return FLT_MIN_EXP;
69     } else if ('N' == ch || 'n' == ch) {
70         return FLT_DIGITS;
71     } else if ('O' == ch || 'o' == ch) {
72         return FLT_MAX;
73     } else if ('P' == ch || 'p' == ch) {
74         return eps * FLT_RADIX;
75     } else if ('R' == ch || 'r' == ch) {
76         return FLT_ROUNDS < 2;
77     } else if ('S' == ch || 's' == ch) {
78         /* Use SMALL plus a bit, to avoid the possibility of rounding causing overflow
79          when computing  1/sfmin. */
80         sfmin = FLT_MIN;
81         small = 2. / FLT_MAX;
82         if (small <= sfmin) small = sfmin * (1 + eps);
83         return small;
84     } else if ('U' == ch || 'u' == ch) {
85         return FLT_MIN;
86     }
87
88     return 0;
89 }
90
91 #else
92
93 /* Table of constant values */
94
95 static integer c__1 = 1;
96 static real c_b32 = 0.f;
97
98 doublereal slamch_(char *cmach)
99 {
100     /* Initialized data */
101
102     static logical first = TRUE_;
103
104     /* System generated locals */
105     integer i__1;
106     real ret_val;
107
108     /* Builtin functions */
109     double pow_ri(real *, integer *);
110
111     /* Local variables */
112     static real t;
113     integer it;
114     static real rnd, eps, base;
115     integer beta;
116     static real emin, prec, emax;
117     integer imin, imax;
118     logical lrnd;
119     static real rmin, rmax;
120     real rmach;
121     extern logical lsame_(char *, char *);
122     real small;
123     static real sfmin;
124     extern /* Subroutine */ int slamc2_(integer *, integer *, logical *, real 
125             *, integer *, real *, integer *, real *);
126
127
128 /*  -- LAPACK auxiliary routine (version 3.1) -- */
129 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
130 /*     November 2006 */
131
132 /*     .. Scalar Arguments .. */
133 /*     .. */
134
135 /*  Purpose */
136 /*  ======= */
137
138 /*  SLAMCH determines single precision machine parameters. */
139
140 /*  Arguments */
141 /*  ========= */
142
143 /*  CMACH   (input) CHARACTER*1 */
144 /*          Specifies the value to be returned by SLAMCH: */
145 /*          = 'E' or 'e',   SLAMCH := eps */
146 /*          = 'S' or 's ,   SLAMCH := sfmin */
147 /*          = 'B' or 'b',   SLAMCH := base */
148 /*          = 'P' or 'p',   SLAMCH := eps*base */
149 /*          = 'N' or 'n',   SLAMCH := t */
150 /*          = 'R' or 'r',   SLAMCH := rnd */
151 /*          = 'M' or 'm',   SLAMCH := emin */
152 /*          = 'U' or 'u',   SLAMCH := rmin */
153 /*          = 'L' or 'l',   SLAMCH := emax */
154 /*          = 'O' or 'o',   SLAMCH := rmax */
155
156 /*          where */
157
158 /*          eps   = relative machine precision */
159 /*          sfmin = safe minimum, such that 1/sfmin does not overflow */
160 /*          base  = base of the machine */
161 /*          prec  = eps*base */
162 /*          t     = number of (base) digits in the mantissa */
163 /*          rnd   = 1.0 when rounding occurs in addition, 0.0 otherwise */
164 /*          emin  = minimum exponent before (gradual) underflow */
165 /*          rmin  = underflow threshold - base**(emin-1) */
166 /*          emax  = largest exponent before overflow */
167 /*          rmax  = overflow threshold  - (base**emax)*(1-eps) */
168
169 /* ===================================================================== */
170
171 /*     .. Parameters .. */
172 /*     .. */
173 /*     .. Local Scalars .. */
174 /*     .. */
175 /*     .. External Functions .. */
176 /*     .. */
177 /*     .. External Subroutines .. */
178 /*     .. */
179 /*     .. Save statement .. */
180 /*     .. */
181 /*     .. Data statements .. */
182 /*     .. */
183 /*     .. Executable Statements .. */
184
185     if (first) {
186         slamc2_(&beta, &it, &lrnd, &eps, &imin, &rmin, &imax, &rmax);
187         base = (real) beta;
188         t = (real) it;
189         if (lrnd) {
190             rnd = 1.f;
191             i__1 = 1 - it;
192             eps = pow_ri(&base, &i__1) / 2;
193         } else {
194             rnd = 0.f;
195             i__1 = 1 - it;
196             eps = pow_ri(&base, &i__1);
197         }
198         prec = eps * base;
199         emin = (real) imin;
200         emax = (real) imax;
201         sfmin = rmin;
202         small = 1.f / rmax;
203         if (small >= sfmin) {
204
205 /*           Use SMALL plus a bit, to avoid the possibility of rounding */
206 /*           causing overflow when computing  1/sfmin. */
207
208             sfmin = small * (eps + 1.f);
209         }
210     }
211
212     if (lsame_(cmach, "E")) {
213         rmach = eps;
214     } else if (lsame_(cmach, "S")) {
215         rmach = sfmin;
216     } else if (lsame_(cmach, "B")) {
217         rmach = base;
218     } else if (lsame_(cmach, "P")) {
219         rmach = prec;
220     } else if (lsame_(cmach, "N")) {
221         rmach = t;
222     } else if (lsame_(cmach, "R")) {
223         rmach = rnd;
224     } else if (lsame_(cmach, "M")) {
225         rmach = emin;
226     } else if (lsame_(cmach, "U")) {
227         rmach = rmin;
228     } else if (lsame_(cmach, "L")) {
229         rmach = emax;
230     } else if (lsame_(cmach, "O")) {
231         rmach = rmax;
232     }
233
234     ret_val = rmach;
235     first = FALSE_;
236     return ret_val;
237
238 /*     End of SLAMCH */
239
240 } /* slamch_ */
241
242
243 /* *********************************************************************** */
244
245 /* Subroutine */ int slamc1_(integer *beta, integer *t, logical *rnd, logical 
246         *ieee1)
247 {
248     /* Initialized data */
249
250     static logical first = TRUE_;
251
252     /* System generated locals */
253     real r__1, r__2;
254
255     /* Local variables */
256     real a, b, c__, f, t1, t2;
257     static integer lt;
258     real one, qtr;
259     static logical lrnd;
260     static integer lbeta;
261     real savec;
262     static logical lieee1;
263     extern doublereal slamc3_(real *, real *);
264
265
266 /*  -- LAPACK auxiliary routine (version 3.1) -- */
267 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
268 /*     November 2006 */
269
270 /*     .. Scalar Arguments .. */
271 /*     .. */
272
273 /*  Purpose */
274 /*  ======= */
275
276 /*  SLAMC1 determines the machine parameters given by BETA, T, RND, and */
277 /*  IEEE1. */
278
279 /*  Arguments */
280 /*  ========= */
281
282 /*  BETA    (output) INTEGER */
283 /*          The base of the machine. */
284
285 /*  T       (output) INTEGER */
286 /*          The number of ( BETA ) digits in the mantissa. */
287
288 /*  RND     (output) LOGICAL */
289 /*          Specifies whether proper rounding  ( RND = .TRUE. )  or */
290 /*          chopping  ( RND = .FALSE. )  occurs in addition. This may not */
291 /*          be a reliable guide to the way in which the machine performs */
292 /*          its arithmetic. */
293
294 /*  IEEE1   (output) LOGICAL */
295 /*          Specifies whether rounding appears to be done in the IEEE */
296 /*          'round to nearest' style. */
297
298 /*  Further Details */
299 /*  =============== */
300
301 /*  The routine is based on the routine  ENVRON  by Malcolm and */
302 /*  incorporates suggestions by Gentleman and Marovich. See */
303
304 /*     Malcolm M. A. (1972) Algorithms to reveal properties of */
305 /*        floating-point arithmetic. Comms. of the ACM, 15, 949-951. */
306
307 /*     Gentleman W. M. and Marovich S. B. (1974) More on algorithms */
308 /*        that reveal properties of floating point arithmetic units. */
309 /*        Comms. of the ACM, 17, 276-277. */
310
311 /* ===================================================================== */
312
313 /*     .. Local Scalars .. */
314 /*     .. */
315 /*     .. External Functions .. */
316 /*     .. */
317 /*     .. Save statement .. */
318 /*     .. */
319 /*     .. Data statements .. */
320 /*     .. */
321 /*     .. Executable Statements .. */
322
323     if (first) {
324         one = 1.f;
325
326 /*        LBETA,  LIEEE1,  LT and  LRND  are the  local values  of  BETA, */
327 /*        IEEE1, T and RND. */
328
329 /*        Throughout this routine  we use the function  SLAMC3  to ensure */
330 /*        that relevant values are  stored and not held in registers,  or */
331 /*        are not affected by optimizers. */
332
333 /*        Compute  a = 2.0**m  with the  smallest positive integer m such */
334 /*        that */
335
336 /*           fl( a + 1.0 ) = a. */
337
338         a = 1.f;
339         c__ = 1.f;
340
341 /* +       WHILE( C.EQ.ONE )LOOP */
342 L10:
343         if (c__ == one) {
344             a *= 2;
345             c__ = slamc3_(&a, &one);
346             r__1 = -a;
347             c__ = slamc3_(&c__, &r__1);
348             goto L10;
349         }
350 /* +       END WHILE */
351
352 /*        Now compute  b = 2.0**m  with the smallest positive integer m */
353 /*        such that */
354
355 /*           fl( a + b ) .gt. a. */
356
357         b = 1.f;
358         c__ = slamc3_(&a, &b);
359
360 /* +       WHILE( C.EQ.A )LOOP */
361 L20:
362         if (c__ == a) {
363             b *= 2;
364             c__ = slamc3_(&a, &b);
365             goto L20;
366         }
367 /* +       END WHILE */
368
369 /*        Now compute the base.  a and c  are neighbouring floating point */
370 /*        numbers  in the  interval  ( beta**t, beta**( t + 1 ) )  and so */
371 /*        their difference is beta. Adding 0.25 to c is to ensure that it */
372 /*        is truncated to beta and not ( beta - 1 ). */
373
374         qtr = one / 4;
375         savec = c__;
376         r__1 = -a;
377         c__ = slamc3_(&c__, &r__1);
378         lbeta = c__ + qtr;
379
380 /*        Now determine whether rounding or chopping occurs,  by adding a */
381 /*        bit  less  than  beta/2  and a  bit  more  than  beta/2  to  a. */
382
383         b = (real) lbeta;
384         r__1 = b / 2;
385         r__2 = -b / 100;
386         f = slamc3_(&r__1, &r__2);
387         c__ = slamc3_(&f, &a);
388         if (c__ == a) {
389             lrnd = TRUE_;
390         } else {
391             lrnd = FALSE_;
392         }
393         r__1 = b / 2;
394         r__2 = b / 100;
395         f = slamc3_(&r__1, &r__2);
396         c__ = slamc3_(&f, &a);
397         if (lrnd && c__ == a) {
398             lrnd = FALSE_;
399         }
400
401 /*        Try and decide whether rounding is done in the  IEEE  'round to */
402 /*        nearest' style. B/2 is half a unit in the last place of the two */
403 /*        numbers A and SAVEC. Furthermore, A is even, i.e. has last  bit */
404 /*        zero, and SAVEC is odd. Thus adding B/2 to A should not  change */
405 /*        A, but adding B/2 to SAVEC should change SAVEC. */
406
407         r__1 = b / 2;
408         t1 = slamc3_(&r__1, &a);
409         r__1 = b / 2;
410         t2 = slamc3_(&r__1, &savec);
411         lieee1 = t1 == a && t2 > savec && lrnd;
412
413 /*        Now find  the  mantissa, t.  It should  be the  integer part of */
414 /*        log to the base beta of a,  however it is safer to determine  t */
415 /*        by powering.  So we find t as the smallest positive integer for */
416 /*        which */
417
418 /*           fl( beta**t + 1.0 ) = 1.0. */
419
420         lt = 0;
421         a = 1.f;
422         c__ = 1.f;
423
424 /* +       WHILE( C.EQ.ONE )LOOP */
425 L30:
426         if (c__ == one) {
427             ++lt;
428             a *= lbeta;
429             c__ = slamc3_(&a, &one);
430             r__1 = -a;
431             c__ = slamc3_(&c__, &r__1);
432             goto L30;
433         }
434 /* +       END WHILE */
435
436     }
437
438     *beta = lbeta;
439     *t = lt;
440     *rnd = lrnd;
441     *ieee1 = lieee1;
442     first = FALSE_;
443     return 0;
444
445 /*     End of SLAMC1 */
446
447 } /* slamc1_ */
448
449
450 /* *********************************************************************** */
451
452 /* Subroutine */ int slamc2_(integer *beta, integer *t, logical *rnd, real *
453         eps, integer *emin, real *rmin, integer *emax, real *rmax)
454 {
455     /* Initialized data */
456
457     static logical first = TRUE_;
458     static logical iwarn = FALSE_;
459
460     /* Format strings */
461     static char fmt_9999[] = "(//\002 WARNING. The value EMIN may be incorre"
462             "ct:-\002,\002  EMIN = \002,i8,/\002 If, after inspection, the va"
463             "lue EMIN looks\002,\002 acceptable please comment out \002,/\002"
464             " the IF block as marked within the code of routine\002,\002 SLAM"
465             "C2,\002,/\002 otherwise supply EMIN explicitly.\002,/)";
466
467     /* System generated locals */
468     integer i__1;
469     real r__1, r__2, r__3, r__4, r__5;
470
471     /* Builtin functions */
472     double pow_ri(real *, integer *);
473     //integer s_wsfe(cilist *), do_fio(integer *, char *, ftnlen), e_wsfe(void);
474
475     /* Local variables */
476     real a, b, c__;
477     integer i__;
478     static integer lt;
479     real one, two;
480     logical ieee;
481     real half;
482     logical lrnd;
483     static real leps;
484     real zero;
485     static integer lbeta;
486     real rbase;
487     static integer lemin, lemax;
488     integer gnmin;
489     real small;
490     integer gpmin;
491     real third;
492     static real lrmin, lrmax;
493     real sixth;
494     logical lieee1;
495     extern /* Subroutine */ int slamc1_(integer *, integer *, logical *, 
496             logical *);
497     extern doublereal slamc3_(real *, real *);
498     extern /* Subroutine */ int slamc4_(integer *, real *, integer *), 
499             slamc5_(integer *, integer *, integer *, logical *, integer *, 
500             real *);
501     integer ngnmin, ngpmin;
502
503     /* Fortran I/O blocks */
504     static cilist io___58 = { 0, 6, 0, fmt_9999, 0 };
505
506
507
508 /*  -- LAPACK auxiliary routine (version 3.1) -- */
509 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
510 /*     November 2006 */
511
512 /*     .. Scalar Arguments .. */
513 /*     .. */
514
515 /*  Purpose */
516 /*  ======= */
517
518 /*  SLAMC2 determines the machine parameters specified in its argument */
519 /*  list. */
520
521 /*  Arguments */
522 /*  ========= */
523
524 /*  BETA    (output) INTEGER */
525 /*          The base of the machine. */
526
527 /*  T       (output) INTEGER */
528 /*          The number of ( BETA ) digits in the mantissa. */
529
530 /*  RND     (output) LOGICAL */
531 /*          Specifies whether proper rounding  ( RND = .TRUE. )  or */
532 /*          chopping  ( RND = .FALSE. )  occurs in addition. This may not */
533 /*          be a reliable guide to the way in which the machine performs */
534 /*          its arithmetic. */
535
536 /*  EPS     (output) REAL */
537 /*          The smallest positive number such that */
538
539 /*             fl( 1.0 - EPS ) .LT. 1.0, */
540
541 /*          where fl denotes the computed value. */
542
543 /*  EMIN    (output) INTEGER */
544 /*          The minimum exponent before (gradual) underflow occurs. */
545
546 /*  RMIN    (output) REAL */
547 /*          The smallest normalized number for the machine, given by */
548 /*          BASE**( EMIN - 1 ), where  BASE  is the floating point value */
549 /*          of BETA. */
550
551 /*  EMAX    (output) INTEGER */
552 /*          The maximum exponent before overflow occurs. */
553
554 /*  RMAX    (output) REAL */
555 /*          The largest positive number for the machine, given by */
556 /*          BASE**EMAX * ( 1 - EPS ), where  BASE  is the floating point */
557 /*          value of BETA. */
558
559 /*  Further Details */
560 /*  =============== */
561
562 /*  The computation of  EPS  is based on a routine PARANOIA by */
563 /*  W. Kahan of the University of California at Berkeley. */
564
565 /* ===================================================================== */
566
567 /*     .. Local Scalars .. */
568 /*     .. */
569 /*     .. External Functions .. */
570 /*     .. */
571 /*     .. External Subroutines .. */
572 /*     .. */
573 /*     .. Intrinsic Functions .. */
574 /*     .. */
575 /*     .. Save statement .. */
576 /*     .. */
577 /*     .. Data statements .. */
578 /*     .. */
579 /*     .. Executable Statements .. */
580
581     if (first) {
582         zero = 0.f;
583         one = 1.f;
584         two = 2.f;
585
586 /*        LBETA, LT, LRND, LEPS, LEMIN and LRMIN  are the local values of */
587 /*        BETA, T, RND, EPS, EMIN and RMIN. */
588
589 /*        Throughout this routine  we use the function  SLAMC3  to ensure */
590 /*        that relevant values are stored  and not held in registers,  or */
591 /*        are not affected by optimizers. */
592
593 /*        SLAMC1 returns the parameters  LBETA, LT, LRND and LIEEE1. */
594
595         slamc1_(&lbeta, &lt, &lrnd, &lieee1);
596
597 /*        Start to find EPS. */
598
599         b = (real) lbeta;
600         i__1 = -lt;
601         a = pow_ri(&b, &i__1);
602         leps = a;
603
604 /*        Try some tricks to see whether or not this is the correct  EPS. */
605
606         b = two / 3;
607         half = one / 2;
608         r__1 = -half;
609         sixth = slamc3_(&b, &r__1);
610         third = slamc3_(&sixth, &sixth);
611         r__1 = -half;
612         b = slamc3_(&third, &r__1);
613         b = slamc3_(&b, &sixth);
614         b = dabs(b);
615         if (b < leps) {
616             b = leps;
617         }
618
619         leps = 1.f;
620
621 /* +       WHILE( ( LEPS.GT.B ).AND.( B.GT.ZERO ) )LOOP */
622 L10:
623         if (leps > b && b > zero) {
624             leps = b;
625             r__1 = half * leps;
626 /* Computing 5th power */
627             r__3 = two, r__4 = r__3, r__3 *= r__3;
628 /* Computing 2nd power */
629             r__5 = leps;
630             r__2 = r__4 * (r__3 * r__3) * (r__5 * r__5);
631             c__ = slamc3_(&r__1, &r__2);
632             r__1 = -c__;
633             c__ = slamc3_(&half, &r__1);
634             b = slamc3_(&half, &c__);
635             r__1 = -b;
636             c__ = slamc3_(&half, &r__1);
637             b = slamc3_(&half, &c__);
638             goto L10;
639         }
640 /* +       END WHILE */
641
642         if (a < leps) {
643             leps = a;
644         }
645
646 /*        Computation of EPS complete. */
647
648 /*        Now find  EMIN.  Let A = + or - 1, and + or - (1 + BASE**(-3)). */
649 /*        Keep dividing  A by BETA until (gradual) underflow occurs. This */
650 /*        is detected when we cannot recover the previous A. */
651
652         rbase = one / lbeta;
653         small = one;
654         for (i__ = 1; i__ <= 3; ++i__) {
655             r__1 = small * rbase;
656             small = slamc3_(&r__1, &zero);
657 /* L20: */
658         }
659         a = slamc3_(&one, &small);
660         slamc4_(&ngpmin, &one, &lbeta);
661         r__1 = -one;
662         slamc4_(&ngnmin, &r__1, &lbeta);
663         slamc4_(&gpmin, &a, &lbeta);
664         r__1 = -a;
665         slamc4_(&gnmin, &r__1, &lbeta);
666         ieee = FALSE_;
667
668         if (ngpmin == ngnmin && gpmin == gnmin) {
669             if (ngpmin == gpmin) {
670                 lemin = ngpmin;
671 /*            ( Non twos-complement machines, no gradual underflow; */
672 /*              e.g.,  VAX ) */
673             } else if (gpmin - ngpmin == 3) {
674                 lemin = ngpmin - 1 + lt;
675                 ieee = TRUE_;
676 /*            ( Non twos-complement machines, with gradual underflow; */
677 /*              e.g., IEEE standard followers ) */
678             } else {
679                 lemin = min(ngpmin,gpmin);
680 /*            ( A guess; no known machine ) */
681                 iwarn = TRUE_;
682             }
683
684         } else if (ngpmin == gpmin && ngnmin == gnmin) {
685             if ((i__1 = ngpmin - ngnmin, abs(i__1)) == 1) {
686                 lemin = max(ngpmin,ngnmin);
687 /*            ( Twos-complement machines, no gradual underflow; */
688 /*              e.g., CYBER 205 ) */
689             } else {
690                 lemin = min(ngpmin,ngnmin);
691 /*            ( A guess; no known machine ) */
692                 iwarn = TRUE_;
693             }
694
695         } else if ((i__1 = ngpmin - ngnmin, abs(i__1)) == 1 && gpmin == gnmin)
696                  {
697             if (gpmin - min(ngpmin,ngnmin) == 3) {
698                 lemin = max(ngpmin,ngnmin) - 1 + lt;
699 /*            ( Twos-complement machines with gradual underflow; */
700 /*              no known machine ) */
701             } else {
702                 lemin = min(ngpmin,ngnmin);
703 /*            ( A guess; no known machine ) */
704                 iwarn = TRUE_;
705             }
706
707         } else {
708 /* Computing MIN */
709             i__1 = min(ngpmin,ngnmin), i__1 = min(i__1,gpmin);
710             lemin = min(i__1,gnmin);
711 /*         ( A guess; no known machine ) */
712             iwarn = TRUE_;
713         }
714         first = FALSE_;
715 /* ** */
716 /* Comment out this if block if EMIN is ok */
717         if (iwarn) {
718             first = TRUE_;
719             printf("\n\n WARNING. The value EMIN may be incorrect:- ");
720             printf("EMIN = %8i\n",lemin);
721             printf("If, after inspection, the value EMIN looks acceptable");
722             printf("please comment out \n the IF block as marked within the"); 
723             printf("code of routine SLAMC2, \n otherwise supply EMIN"); 
724             printf("explicitly.\n");
725          /*
726             s_wsfe(&io___58);
727             do_fio(&c__1, (char *)&lemin, (ftnlen)sizeof(integer));
728             e_wsfe();
729          */
730         }
731 /* ** */
732
733 /*        Assume IEEE arithmetic if we found denormalised  numbers above, */
734 /*        or if arithmetic seems to round in the  IEEE style,  determined */
735 /*        in routine SLAMC1. A true IEEE machine should have both  things */
736 /*        true; however, faulty machines may have one or the other. */
737
738         ieee = ieee || lieee1;
739
740 /*        Compute  RMIN by successive division by  BETA. We could compute */
741 /*        RMIN as BASE**( EMIN - 1 ),  but some machines underflow during */
742 /*        this computation. */
743
744         lrmin = 1.f;
745         i__1 = 1 - lemin;
746         for (i__ = 1; i__ <= i__1; ++i__) {
747             r__1 = lrmin * rbase;
748             lrmin = slamc3_(&r__1, &zero);
749 /* L30: */
750         }
751
752 /*        Finally, call SLAMC5 to compute EMAX and RMAX. */
753
754         slamc5_(&lbeta, &lt, &lemin, &ieee, &lemax, &lrmax);
755     }
756
757     *beta = lbeta;
758     *t = lt;
759     *rnd = lrnd;
760     *eps = leps;
761     *emin = lemin;
762     *rmin = lrmin;
763     *emax = lemax;
764     *rmax = lrmax;
765
766     return 0;
767
768
769 /*     End of SLAMC2 */
770
771 } /* slamc2_ */
772
773
774 /* *********************************************************************** */
775
776 /* Subroutine */ int slamc4_(integer *emin, real *start, integer *base)
777 {
778     /* System generated locals */
779     integer i__1;
780     real r__1;
781
782     /* Local variables */
783     real a;
784     integer i__;
785     real b1, b2, c1, c2, d1, d2, one, zero, rbase;
786     extern doublereal slamc3_(real *, real *);
787
788
789 /*  -- LAPACK auxiliary routine (version 3.1) -- */
790 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
791 /*     November 2006 */
792
793 /*     .. Scalar Arguments .. */
794 /*     .. */
795
796 /*  Purpose */
797 /*  ======= */
798
799 /*  SLAMC4 is a service routine for SLAMC2. */
800
801 /*  Arguments */
802 /*  ========= */
803
804 /*  EMIN    (output) INTEGER */
805 /*          The minimum exponent before (gradual) underflow, computed by */
806 /*          setting A = START and dividing by BASE until the previous A */
807 /*          can not be recovered. */
808
809 /*  START   (input) REAL */
810 /*          The starting point for determining EMIN. */
811
812 /*  BASE    (input) INTEGER */
813 /*          The base of the machine. */
814
815 /* ===================================================================== */
816
817 /*     .. Local Scalars .. */
818 /*     .. */
819 /*     .. External Functions .. */
820 /*     .. */
821 /*     .. Executable Statements .. */
822
823     a = *start;
824     one = 1.f;
825     rbase = one / *base;
826     zero = 0.f;
827     *emin = 1;
828     r__1 = a * rbase;
829     b1 = slamc3_(&r__1, &zero);
830     c1 = a;
831     c2 = a;
832     d1 = a;
833     d2 = a;
834 /* +    WHILE( ( C1.EQ.A ).AND.( C2.EQ.A ).AND. */
835 /*    $       ( D1.EQ.A ).AND.( D2.EQ.A )      )LOOP */
836 L10:
837     if (c1 == a && c2 == a && d1 == a && d2 == a) {
838         --(*emin);
839         a = b1;
840         r__1 = a / *base;
841         b1 = slamc3_(&r__1, &zero);
842         r__1 = b1 * *base;
843         c1 = slamc3_(&r__1, &zero);
844         d1 = zero;
845         i__1 = *base;
846         for (i__ = 1; i__ <= i__1; ++i__) {
847             d1 += b1;
848 /* L20: */
849         }
850         r__1 = a * rbase;
851         b2 = slamc3_(&r__1, &zero);
852         r__1 = b2 / rbase;
853         c2 = slamc3_(&r__1, &zero);
854         d2 = zero;
855         i__1 = *base;
856         for (i__ = 1; i__ <= i__1; ++i__) {
857             d2 += b2;
858 /* L30: */
859         }
860         goto L10;
861     }
862 /* +    END WHILE */
863
864     return 0;
865
866 /*     End of SLAMC4 */
867
868 } /* slamc4_ */
869
870
871 /* *********************************************************************** */
872
873 /* Subroutine */ int slamc5_(integer *beta, integer *p, integer *emin, 
874         logical *ieee, integer *emax, real *rmax)
875 {
876     /* System generated locals */
877     integer i__1;
878     real r__1;
879
880     /* Local variables */
881     integer i__;
882     real y, z__;
883     integer try__, lexp;
884     real oldy;
885     integer uexp, nbits;
886     extern doublereal slamc3_(real *, real *);
887     real recbas;
888     integer exbits, expsum;
889
890
891 /*  -- LAPACK auxiliary routine (version 3.1) -- */
892 /*     Univ. of Tennessee, Univ. of California Berkeley and NAG Ltd.. */
893 /*     November 2006 */
894
895 /*     .. Scalar Arguments .. */
896 /*     .. */
897
898 /*  Purpose */
899 /*  ======= */
900
901 /*  SLAMC5 attempts to compute RMAX, the largest machine floating-point */
902 /*  number, without overflow.  It assumes that EMAX + abs(EMIN) sum */
903 /*  approximately to a power of 2.  It will fail on machines where this */
904 /*  assumption does not hold, for example, the Cyber 205 (EMIN = -28625, */
905 /*  EMAX = 28718).  It will also fail if the value supplied for EMIN is */
906 /*  too large (i.e. too close to zero), probably with overflow. */
907
908 /*  Arguments */
909 /*  ========= */
910
911 /*  BETA    (input) INTEGER */
912 /*          The base of floating-point arithmetic. */
913
914 /*  P       (input) INTEGER */
915 /*          The number of base BETA digits in the mantissa of a */
916 /*          floating-point value. */
917
918 /*  EMIN    (input) INTEGER */
919 /*          The minimum exponent before (gradual) underflow. */
920
921 /*  IEEE    (input) LOGICAL */
922 /*          A logical flag specifying whether or not the arithmetic */
923 /*          system is thought to comply with the IEEE standard. */
924
925 /*  EMAX    (output) INTEGER */
926 /*          The largest exponent before overflow */
927
928 /*  RMAX    (output) REAL */
929 /*          The largest machine floating-point number. */
930
931 /* ===================================================================== */
932
933 /*     .. Parameters .. */
934 /*     .. */
935 /*     .. Local Scalars .. */
936 /*     .. */
937 /*     .. External Functions .. */
938 /*     .. */
939 /*     .. Intrinsic Functions .. */
940 /*     .. */
941 /*     .. Executable Statements .. */
942
943 /*     First compute LEXP and UEXP, two powers of 2 that bound */
944 /*     abs(EMIN). We then assume that EMAX + abs(EMIN) will sum */
945 /*     approximately to the bound that is closest to abs(EMIN). */
946 /*     (EMAX is the exponent of the required number RMAX). */
947
948     lexp = 1;
949     exbits = 1;
950 L10:
951     try__ = lexp << 1;
952     if (try__ <= -(*emin)) {
953         lexp = try__;
954         ++exbits;
955         goto L10;
956     }
957     if (lexp == -(*emin)) {
958         uexp = lexp;
959     } else {
960         uexp = try__;
961         ++exbits;
962     }
963
964 /*     Now -LEXP is less than or equal to EMIN, and -UEXP is greater */
965 /*     than or equal to EMIN. EXBITS is the number of bits needed to */
966 /*     store the exponent. */
967
968     if (uexp + *emin > -lexp - *emin) {
969         expsum = lexp << 1;
970     } else {
971         expsum = uexp << 1;
972     }
973
974 /*     EXPSUM is the exponent range, approximately equal to */
975 /*     EMAX - EMIN + 1 . */
976
977     *emax = expsum + *emin - 1;
978     nbits = exbits + 1 + *p;
979
980 /*     NBITS is the total number of bits needed to store a */
981 /*     floating-point number. */
982
983     if (nbits % 2 == 1 && *beta == 2) {
984
985 /*        Either there are an odd number of bits used to store a */
986 /*        floating-point number, which is unlikely, or some bits are */
987 /*        not used in the representation of numbers, which is possible, */
988 /*        (e.g. Cray machines) or the mantissa has an implicit bit, */
989 /*        (e.g. IEEE machines, Dec Vax machines), which is perhaps the */
990 /*        most likely. We have to assume the last alternative. */
991 /*        If this is true, then we need to reduce EMAX by one because */
992 /*        there must be some way of representing zero in an implicit-bit */
993 /*        system. On machines like Cray, we are reducing EMAX by one */
994 /*        unnecessarily. */
995
996         --(*emax);
997     }
998
999     if (*ieee) {
1000
1001 /*        Assume we are on an IEEE machine which reserves one exponent */
1002 /*        for infinity and NaN. */
1003
1004         --(*emax);
1005     }
1006
1007 /*     Now create RMAX, the largest machine number, which should */
1008 /*     be equal to (1.0 - BETA**(-P)) * BETA**EMAX . */
1009
1010 /*     First compute 1.0 - BETA**(-P), being careful that the */
1011 /*     result is less than 1.0 . */
1012
1013     recbas = 1.f / *beta;
1014     z__ = *beta - 1.f;
1015     y = 0.f;
1016     i__1 = *p;
1017     for (i__ = 1; i__ <= i__1; ++i__) {
1018         z__ *= recbas;
1019         if (y < 1.f) {
1020             oldy = y;
1021         }
1022         y = slamc3_(&y, &z__);
1023 /* L20: */
1024     }
1025     if (y >= 1.f) {
1026         y = oldy;
1027     }
1028
1029 /*     Now multiply by BETA**EMAX to get RMAX. */
1030
1031     i__1 = *emax;
1032     for (i__ = 1; i__ <= i__1; ++i__) {
1033         r__1 = y * *beta;
1034         y = slamc3_(&r__1, &c_b32);
1035 /* L30: */
1036     }
1037
1038     *rmax = y;
1039     return 0;
1040
1041 /*     End of SLAMC5 */
1042
1043 } /* slamc5_ */
1044
1045 #endif