Home | History | Annotate | Line # | Download | only in noieee_src
      1  1.5     agc /*      $NetBSD: n_support.c,v 1.5 2003/08/07 16:44:52 agc Exp $ */
      2  1.1   ragge /*
      3  1.1   ragge  * Copyright (c) 1985, 1993
      4  1.1   ragge  *	The Regents of the University of California.  All rights reserved.
      5  1.1   ragge  *
      6  1.1   ragge  * Redistribution and use in source and binary forms, with or without
      7  1.1   ragge  * modification, are permitted provided that the following conditions
      8  1.1   ragge  * are met:
      9  1.1   ragge  * 1. Redistributions of source code must retain the above copyright
     10  1.1   ragge  *    notice, this list of conditions and the following disclaimer.
     11  1.1   ragge  * 2. Redistributions in binary form must reproduce the above copyright
     12  1.1   ragge  *    notice, this list of conditions and the following disclaimer in the
     13  1.1   ragge  *    documentation and/or other materials provided with the distribution.
     14  1.5     agc  * 3. Neither the name of the University nor the names of its contributors
     15  1.1   ragge  *    may be used to endorse or promote products derived from this software
     16  1.1   ragge  *    without specific prior written permission.
     17  1.1   ragge  *
     18  1.1   ragge  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     19  1.1   ragge  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     20  1.1   ragge  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     21  1.1   ragge  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     22  1.1   ragge  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     23  1.1   ragge  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     24  1.1   ragge  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     25  1.1   ragge  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     26  1.1   ragge  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     27  1.1   ragge  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     28  1.1   ragge  * SUCH DAMAGE.
     29  1.1   ragge  */
     30  1.1   ragge 
     31  1.1   ragge #ifndef lint
     32  1.1   ragge static char sccsid[] = "@(#)support.c	8.1 (Berkeley) 6/4/93";
     33  1.1   ragge #endif /* not lint */
     34  1.1   ragge 
     35  1.3  simonb /*
     36  1.3  simonb  * Some IEEE standard 754 recommended functions and remainder and sqrt for
     37  1.1   ragge  * supporting the C elementary functions.
     38  1.1   ragge  ******************************************************************************
     39  1.1   ragge  * WARNING:
     40  1.1   ragge  *      These codes are developed (in double) to support the C elementary
     41  1.1   ragge  * functions temporarily. They are not universal, and some of them are very
     42  1.3  simonb  * slow (in particular, drem and sqrt is extremely inefficient). Each
     43  1.3  simonb  * computer system should have its implementation of these functions using
     44  1.1   ragge  * its own assembler.
     45  1.1   ragge  ******************************************************************************
     46  1.1   ragge  *
     47  1.1   ragge  * IEEE 754 required operations:
     48  1.3  simonb  *     drem(x,p)
     49  1.1   ragge  *              returns  x REM y  =  x - [x/y]*y , where [x/y] is the integer
     50  1.1   ragge  *              nearest x/y; in half way case, choose the even one.
     51  1.3  simonb  *     sqrt(x)
     52  1.3  simonb  *              returns the square root of x correctly rounded according to
     53  1.1   ragge  *		the rounding mod.
     54  1.1   ragge  *
     55  1.1   ragge  * IEEE 754 recommended functions:
     56  1.3  simonb  * (a) copysign(x,y)
     57  1.3  simonb  *              returns x with the sign of y.
     58  1.3  simonb  * (b) scalb(x,N)
     59  1.1   ragge  *              returns  x * (2**N), for integer values N.
     60  1.3  simonb  * (c) logb(x)
     61  1.3  simonb  *              returns the unbiased exponent of x, a signed integer in
     62  1.3  simonb  *              double precision, except that logb(0) is -INF, logb(INF)
     63  1.1   ragge  *              is +INF, and logb(NAN) is that NAN.
     64  1.3  simonb  * (d) finite(x)
     65  1.3  simonb  *              returns the value TRUE if -INF < x < +INF and returns
     66  1.1   ragge  *              FALSE otherwise.
     67  1.1   ragge  *
     68  1.1   ragge  *
     69  1.1   ragge  * CODED IN C BY K.C. NG, 11/25/84;
     70  1.1   ragge  * REVISED BY K.C. NG on 1/22/85, 2/13/85, 3/24/85.
     71  1.1   ragge  */
     72  1.1   ragge 
     73  1.1   ragge #include "mathimpl.h"
     74  1.4    matt #include "trig.h"
     75  1.1   ragge 
     76  1.2    matt #if defined(__vax__)||defined(tahoe)      /* VAX D format */
     77  1.1   ragge #include <errno.h>
     78  1.1   ragge     static const unsigned short msign=0x7fff , mexp =0x7f80 ;
     79  1.3  simonb     static const short  prep1=57, gap=7, bias=129           ;
     80  1.4    matt     static const double novf=1.7E38, nunf=3.0E-39 ;
     81  1.2    matt #else	/* defined(__vax__)||defined(tahoe) */
     82  1.1   ragge     static const unsigned short msign=0x7fff, mexp =0x7ff0  ;
     83  1.1   ragge     static const short prep1=54, gap=4, bias=1023           ;
     84  1.4    matt     static const double novf=1.7E308, nunf=3.0E-308;
     85  1.2    matt #endif	/* defined(__vax__)||defined(tahoe) */
     86  1.1   ragge 
     87  1.4    matt double
     88  1.4    matt scalb(double x, int N)
     89  1.1   ragge {
     90  1.1   ragge         int k;
     91  1.1   ragge 
     92  1.1   ragge #ifdef national
     93  1.1   ragge         unsigned short *px=(unsigned short *) &x + 3;
     94  1.1   ragge #else	/* national */
     95  1.1   ragge         unsigned short *px=(unsigned short *) &x;
     96  1.1   ragge #endif	/* national */
     97  1.1   ragge 
     98  1.4    matt         if( x == __zero )  return(x);
     99  1.1   ragge 
    100  1.2    matt #if defined(__vax__)||defined(tahoe)
    101  1.1   ragge         if( (k= *px & mexp ) != ~msign ) {
    102  1.1   ragge             if (N < -260)
    103  1.1   ragge 		return(nunf*nunf);
    104  1.1   ragge 	    else if (N > 260) {
    105  1.1   ragge 		return(copysign(infnan(ERANGE),x));
    106  1.1   ragge 	    }
    107  1.2    matt #else	/* defined(__vax__)||defined(tahoe) */
    108  1.1   ragge         if( (k= *px & mexp ) != mexp ) {
    109  1.1   ragge             if( N<-2100) return(nunf*nunf); else if(N>2100) return(novf+novf);
    110  1.1   ragge             if( k == 0 ) {
    111  1.1   ragge                  x *= scalb(1.0,(int)prep1);  N -= prep1; return(scalb(x,N));}
    112  1.2    matt #endif	/* defined(__vax__)||defined(tahoe) */
    113  1.1   ragge 
    114  1.1   ragge             if((k = (k>>gap)+ N) > 0 )
    115  1.1   ragge                 if( k < (mexp>>gap) ) *px = (*px&~mexp) | (k<<gap);
    116  1.1   ragge                 else x=novf+novf;               /* overflow */
    117  1.1   ragge             else
    118  1.3  simonb                 if( k > -prep1 )
    119  1.1   ragge                                         /* gradual underflow */
    120  1.1   ragge                     {*px=(*px&~mexp)|(short)(1<<gap); x *= scalb(1.0,k-1);}
    121  1.1   ragge                 else
    122  1.1   ragge                 return(nunf*nunf);
    123  1.1   ragge             }
    124  1.1   ragge         return(x);
    125  1.1   ragge }
    126  1.1   ragge 
    127  1.1   ragge 
    128  1.4    matt double
    129  1.4    matt copysign(double x, double y)
    130  1.1   ragge {
    131  1.1   ragge #ifdef national
    132  1.1   ragge         unsigned short  *px=(unsigned short *) &x+3,
    133  1.1   ragge                         *py=(unsigned short *) &y+3;
    134  1.1   ragge #else	/* national */
    135  1.1   ragge         unsigned short  *px=(unsigned short *) &x,
    136  1.1   ragge                         *py=(unsigned short *) &y;
    137  1.1   ragge #endif	/* national */
    138  1.1   ragge 
    139  1.2    matt #if defined(__vax__)||defined(tahoe)
    140  1.1   ragge         if ( (*px & mexp) == 0 ) return(x);
    141  1.2    matt #endif	/* defined(__vax__)||defined(tahoe) */
    142  1.1   ragge 
    143  1.1   ragge         *px = ( *px & msign ) | ( *py & ~msign );
    144  1.1   ragge         return(x);
    145  1.1   ragge }
    146  1.1   ragge 
    147  1.4    matt double
    148  1.4    matt logb(double x)
    149  1.1   ragge {
    150  1.1   ragge 
    151  1.1   ragge #ifdef national
    152  1.1   ragge         short *px=(short *) &x+3, k;
    153  1.1   ragge #else	/* national */
    154  1.1   ragge         short *px=(short *) &x, k;
    155  1.1   ragge #endif	/* national */
    156  1.1   ragge 
    157  1.2    matt #if defined(__vax__)||defined(tahoe)
    158  1.1   ragge         return (int)(((*px&mexp)>>gap)-bias);
    159  1.2    matt #else	/* defined(__vax__)||defined(tahoe) */
    160  1.1   ragge         if( (k= *px & mexp ) != mexp )
    161  1.1   ragge             if ( k != 0 )
    162  1.1   ragge                 return ( (k>>gap) - bias );
    163  1.4    matt             else if( x != __zero)
    164  1.1   ragge                 return ( -1022.0 );
    165  1.3  simonb             else
    166  1.4    matt                 return(-(1.0/__zero));
    167  1.1   ragge         else if(x != x)
    168  1.1   ragge             return(x);
    169  1.1   ragge         else
    170  1.1   ragge             {*px &= msign; return(x);}
    171  1.2    matt #endif	/* defined(__vax__)||defined(tahoe) */
    172  1.1   ragge }
    173  1.1   ragge 
    174  1.4    matt int
    175  1.4    matt finite(double x)
    176  1.1   ragge {
    177  1.2    matt #if defined(__vax__)||defined(tahoe)
    178  1.1   ragge         return(1);
    179  1.2    matt #else	/* defined(__vax__)||defined(tahoe) */
    180  1.1   ragge #ifdef national
    181  1.1   ragge         return( (*((short *) &x+3 ) & mexp ) != mexp );
    182  1.1   ragge #else	/* national */
    183  1.1   ragge         return( (*((short *) &x ) & mexp ) != mexp );
    184  1.1   ragge #endif	/* national */
    185  1.2    matt #endif	/* defined(__vax__)||defined(tahoe) */
    186  1.1   ragge }
    187  1.1   ragge 
    188  1.4    matt double
    189  1.4    matt drem(double x, double p)
    190  1.1   ragge {
    191  1.1   ragge         short sign;
    192  1.1   ragge         double hp,dp,tmp;
    193  1.3  simonb         unsigned short  k;
    194  1.1   ragge #ifdef national
    195  1.1   ragge         unsigned short
    196  1.3  simonb               *px=(unsigned short *) &x  +3,
    197  1.1   ragge               *pp=(unsigned short *) &p  +3,
    198  1.1   ragge               *pd=(unsigned short *) &dp +3,
    199  1.1   ragge               *pt=(unsigned short *) &tmp+3;
    200  1.1   ragge #else	/* national */
    201  1.1   ragge         unsigned short
    202  1.3  simonb               *px=(unsigned short *) &x  ,
    203  1.1   ragge               *pp=(unsigned short *) &p  ,
    204  1.1   ragge               *pd=(unsigned short *) &dp ,
    205  1.1   ragge               *pt=(unsigned short *) &tmp;
    206  1.1   ragge #endif	/* national */
    207  1.1   ragge 
    208  1.1   ragge         *pp &= msign ;
    209  1.1   ragge 
    210  1.2    matt #if defined(__vax__)||defined(tahoe)
    211  1.1   ragge         if( ( *px & mexp ) == ~msign )	/* is x a reserved operand? */
    212  1.2    matt #else	/* defined(__vax__)||defined(tahoe) */
    213  1.1   ragge         if( ( *px & mexp ) == mexp )
    214  1.2    matt #endif	/* defined(__vax__)||defined(tahoe) */
    215  1.1   ragge 		return  (x-p)-(x-p);	/* create nan if x is inf */
    216  1.4    matt 	if (p == __zero) {
    217  1.2    matt #if defined(__vax__)||defined(tahoe)
    218  1.1   ragge 		return(infnan(EDOM));
    219  1.2    matt #else	/* defined(__vax__)||defined(tahoe) */
    220  1.4    matt 		return __zero/__zero;
    221  1.2    matt #endif	/* defined(__vax__)||defined(tahoe) */
    222  1.1   ragge 	}
    223  1.1   ragge 
    224  1.2    matt #if defined(__vax__)||defined(tahoe)
    225  1.1   ragge         if( ( *pp & mexp ) == ~msign )	/* is p a reserved operand? */
    226  1.2    matt #else	/* defined(__vax__)||defined(tahoe) */
    227  1.1   ragge         if( ( *pp & mexp ) == mexp )
    228  1.2    matt #endif	/* defined(__vax__)||defined(tahoe) */
    229  1.1   ragge 		{ if (p != p) return p; else return x;}
    230  1.1   ragge 
    231  1.3  simonb         else  if ( ((*pp & mexp)>>gap) <= 1 )
    232  1.1   ragge                 /* subnormal p, or almost subnormal p */
    233  1.1   ragge             { double b; b=scalb(1.0,(int)prep1);
    234  1.1   ragge               p *= b; x = drem(x,p); x *= b; return(drem(x,p)/b);}
    235  1.1   ragge         else  if ( p >= novf/2)
    236  1.1   ragge             { p /= 2 ; x /= 2; return(drem(x,p)*2);}
    237  1.3  simonb         else
    238  1.1   ragge             {
    239  1.1   ragge                 dp=p+p; hp=p/2;
    240  1.1   ragge                 sign= *px & ~msign ;
    241  1.1   ragge                 *px &= msign       ;
    242  1.1   ragge                 while ( x > dp )
    243  1.1   ragge                     {
    244  1.1   ragge                         k=(*px & mexp) - (*pd & mexp) ;
    245  1.1   ragge                         tmp = dp ;
    246  1.1   ragge                         *pt += k ;
    247  1.1   ragge 
    248  1.2    matt #if defined(__vax__)||defined(tahoe)
    249  1.1   ragge                         if( x < tmp ) *pt -= 128 ;
    250  1.2    matt #else	/* defined(__vax__)||defined(tahoe) */
    251  1.1   ragge                         if( x < tmp ) *pt -= 16 ;
    252  1.2    matt #endif	/* defined(__vax__)||defined(tahoe) */
    253  1.1   ragge 
    254  1.1   ragge                         x -= tmp ;
    255  1.1   ragge                     }
    256  1.1   ragge                 if ( x > hp )
    257  1.1   ragge                     { x -= p ;  if ( x >= hp ) x -= p ; }
    258  1.1   ragge 
    259  1.2    matt #if defined(__vax__)||defined(tahoe)
    260  1.1   ragge 		if (x)
    261  1.2    matt #endif	/* defined(__vax__)||defined(tahoe) */
    262  1.1   ragge 			*px ^= sign;
    263  1.1   ragge                 return( x);
    264  1.1   ragge 
    265  1.1   ragge             }
    266  1.1   ragge }
    267  1.1   ragge 
    268  1.1   ragge 
    269  1.4    matt double
    270  1.4    matt sqrt(double x)
    271  1.1   ragge {
    272  1.1   ragge         double q,s,b,r;
    273  1.1   ragge         double t;
    274  1.1   ragge         int m,n,i;
    275  1.2    matt #if defined(__vax__)||defined(tahoe)
    276  1.1   ragge         int k=54;
    277  1.2    matt #else	/* defined(__vax__)||defined(tahoe) */
    278  1.1   ragge         int k=51;
    279  1.2    matt #endif	/* defined(__vax__)||defined(tahoe) */
    280  1.1   ragge 
    281  1.1   ragge     /* sqrt(NaN) is NaN, sqrt(+-0) = +-0 */
    282  1.4    matt         if(x!=x||x==__zero) return(x);
    283  1.1   ragge 
    284  1.1   ragge     /* sqrt(negative) is invalid */
    285  1.4    matt         if(x<__zero) {
    286  1.2    matt #if defined(__vax__)||defined(tahoe)
    287  1.1   ragge 		return (infnan(EDOM));	/* NaN */
    288  1.2    matt #else	/* defined(__vax__)||defined(tahoe) */
    289  1.4    matt 		return(__zero/__zero);
    290  1.2    matt #endif	/* defined(__vax__)||defined(tahoe) */
    291  1.1   ragge 	}
    292  1.1   ragge 
    293  1.1   ragge     /* sqrt(INF) is INF */
    294  1.3  simonb         if(!finite(x)) return(x);
    295  1.1   ragge 
    296  1.1   ragge     /* scale x to [1,4) */
    297  1.1   ragge         n=logb(x);
    298  1.1   ragge         x=scalb(x,-n);
    299  1.1   ragge         if((m=logb(x))!=0) x=scalb(x,-m);       /* subnormal number */
    300  1.3  simonb         m += n;
    301  1.1   ragge         n = m/2;
    302  1.1   ragge         if((n+n)!=m) {x *= 2; m -=1; n=m/2;}
    303  1.1   ragge 
    304  1.1   ragge     /* generate sqrt(x) bit by bit (accumulating in q) */
    305  1.1   ragge             q=1.0; s=4.0; x -= 1.0; r=1;
    306  1.1   ragge             for(i=1;i<=k;i++) {
    307  1.1   ragge                 t=s+1; x *= 4; r /= 2;
    308  1.1   ragge                 if(t<=x) {
    309  1.1   ragge                     s=t+t+2, x -= t; q += r;}
    310  1.1   ragge                 else
    311  1.1   ragge                     s *= 2;
    312  1.1   ragge                 }
    313  1.3  simonb 
    314  1.1   ragge     /* generate the last bit and determine the final rounding */
    315  1.3  simonb             r/=2; x *= 4;
    316  1.4    matt             if(x==__zero) goto end; 100+r; /* trigger inexact flag */
    317  1.1   ragge             if(s<x) {
    318  1.1   ragge                 q+=r; x -=s; s += 2; s *= 2; x *= 4;
    319  1.3  simonb                 t = (x-s)-5;
    320  1.1   ragge                 b=1.0+3*r/4; if(b==1.0) goto end; /* b==1 : Round-to-zero */
    321  1.1   ragge                 b=1.0+r/4;   if(b>1.0) t=1;	/* b>1 : Round-to-(+INF) */
    322  1.1   ragge                 if(t>=0) q+=r; }	      /* else: Round-to-nearest */
    323  1.3  simonb             else {
    324  1.3  simonb                 s *= 2; x *= 4;
    325  1.3  simonb                 t = (x-s)-1;
    326  1.1   ragge                 b=1.0+3*r/4; if(b==1.0) goto end;
    327  1.1   ragge                 b=1.0+r/4;   if(b>1.0) t=1;
    328  1.1   ragge                 if(t>=0) q+=r; }
    329  1.3  simonb 
    330  1.1   ragge end:        return(scalb(q,n));
    331  1.1   ragge }
    332  1.1   ragge 
    333  1.1   ragge #if 0
    334  1.1   ragge /* DREM(X,Y)
    335  1.1   ragge  * RETURN X REM Y =X-N*Y, N=[X/Y] ROUNDED (ROUNDED TO EVEN IN THE HALF WAY CASE)
    336  1.1   ragge  * DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS)
    337  1.1   ragge  * INTENDED FOR ASSEMBLY LANGUAGE
    338  1.1   ragge  * CODED IN C BY K.C. NG, 3/23/85, 4/8/85.
    339  1.1   ragge  *
    340  1.1   ragge  * Warning: this code should not get compiled in unless ALL of
    341  1.1   ragge  * the following machine-dependent routines are supplied.
    342  1.3  simonb  *
    343  1.1   ragge  * Required machine dependent functions (not on a VAX):
    344  1.1   ragge  *     swapINX(i): save inexact flag and reset it to "i"
    345  1.1   ragge  *     swapENI(e): save inexact enable and reset it to "e"
    346  1.1   ragge  */
    347  1.1   ragge 
    348  1.4    matt double
    349  1.4    matt drem(double x, double y)
    350  1.1   ragge {
    351  1.1   ragge 
    352  1.1   ragge #ifdef national		/* order of words in floating point number */
    353  1.1   ragge 	static const n0=3,n1=2,n2=1,n3=0;
    354  1.1   ragge #else /* VAX, SUN, ZILOG, TAHOE */
    355  1.1   ragge 	static const n0=0,n1=1,n2=2,n3=3;
    356  1.1   ragge #endif
    357  1.1   ragge 
    358  1.1   ragge     	static const unsigned short mexp =0x7ff0, m25 =0x0190, m57 =0x0390;
    359  1.1   ragge 	double hy,y1,t,t1;
    360  1.1   ragge 	short k;
    361  1.1   ragge 	long n;
    362  1.3  simonb 	int i,e;
    363  1.3  simonb 	unsigned short xexp,yexp, *px  =(unsigned short *) &x  ,
    364  1.1   ragge 	      		nx,nf,	  *py  =(unsigned short *) &y  ,
    365  1.1   ragge 	      		sign,	  *pt  =(unsigned short *) &t  ,
    366  1.1   ragge 	      			  *pt1 =(unsigned short *) &t1 ;
    367  1.1   ragge 
    368  1.1   ragge 	xexp = px[n0] & mexp ;	/* exponent of x */
    369  1.1   ragge 	yexp = py[n0] & mexp ;	/* exponent of y */
    370  1.1   ragge 	sign = px[n0] &0x8000;	/* sign of x     */
    371  1.1   ragge 
    372  1.1   ragge /* return NaN if x is NaN, or y is NaN, or x is INF, or y is zero */
    373  1.1   ragge 	if(x!=x) return(x); if(y!=y) return(y);	     /* x or y is NaN */
    374  1.4    matt 	if( xexp == mexp )   return(__zero/__zero);      /* x is INF */
    375  1.4    matt 	if(y==__zero) return(y/y);
    376  1.1   ragge 
    377  1.1   ragge /* save the inexact flag and inexact enable in i and e respectively
    378  1.1   ragge  * and reset them to zero
    379  1.1   ragge  */
    380  1.3  simonb 	i=swapINX(0);	e=swapENI(0);
    381  1.1   ragge 
    382  1.1   ragge /* subnormal number */
    383  1.1   ragge 	nx=0;
    384  1.1   ragge 	if(yexp==0) {t=1.0,pt[n0]+=m57; y*=t; nx=m57;}
    385  1.1   ragge 
    386  1.1   ragge /* if y is tiny (biased exponent <= 57), scale up y to y*2**57 */
    387  1.1   ragge 	if( yexp <= m57 ) {py[n0]+=m57; nx+=m57; yexp+=m57;}
    388  1.1   ragge 
    389  1.1   ragge 	nf=nx;
    390  1.3  simonb 	py[n0] &= 0x7fff;
    391  1.1   ragge 	px[n0] &= 0x7fff;
    392  1.1   ragge 
    393  1.1   ragge /* mask off the least significant 27 bits of y */
    394  1.1   ragge 	t=y; pt[n3]=0; pt[n2]&=0xf800; y1=t;
    395  1.1   ragge 
    396  1.1   ragge /* LOOP: argument reduction on x whenever x > y */
    397  1.1   ragge loop:
    398  1.1   ragge 	while ( x > y )
    399  1.1   ragge 	{
    400  1.1   ragge 	    t=y;
    401  1.1   ragge 	    t1=y1;
    402  1.1   ragge 	    xexp=px[n0]&mexp;	  /* exponent of x */
    403  1.1   ragge 	    k=xexp-yexp-m25;
    404  1.1   ragge 	    if(k>0) 	/* if x/y >= 2**26, scale up y so that x/y < 2**26 */
    405  1.1   ragge 		{pt[n0]+=k;pt1[n0]+=k;}
    406  1.1   ragge 	    n=x/t; x=(x-n*t1)-n*(t-t1);
    407  1.3  simonb 	}
    408  1.1   ragge     /* end while (x > y) */
    409  1.1   ragge 
    410  1.1   ragge 	if(nx!=0) {t=1.0; pt[n0]+=nx; x*=t; nx=0; goto loop;}
    411  1.1   ragge 
    412  1.1   ragge /* final adjustment */
    413  1.1   ragge 
    414  1.1   ragge 	hy=y/2.0;
    415  1.3  simonb 	if(x>hy||((x==hy)&&n%2==1)) x-=y;
    416  1.1   ragge 	px[n0] ^= sign;
    417  1.1   ragge 	if(nf!=0) { t=1.0; pt[n0]-=nf; x*=t;}
    418  1.1   ragge 
    419  1.1   ragge /* restore inexact flag and inexact enable */
    420  1.3  simonb 	swapINX(i); swapENI(e);
    421  1.1   ragge 
    422  1.3  simonb 	return(x);
    423  1.1   ragge }
    424  1.1   ragge #endif
    425  1.1   ragge 
    426  1.1   ragge #if 0
    427  1.1   ragge /* SQRT
    428  1.1   ragge  * RETURN CORRECTLY ROUNDED (ACCORDING TO THE ROUNDING MODE) SQRT
    429  1.1   ragge  * FOR IEEE DOUBLE PRECISION ONLY, INTENDED FOR ASSEMBLY LANGUAGE
    430  1.1   ragge  * CODED IN C BY K.C. NG, 3/22/85.
    431  1.1   ragge  *
    432  1.1   ragge  * Warning: this code should not get compiled in unless ALL of
    433  1.1   ragge  * the following machine-dependent routines are supplied.
    434  1.3  simonb  *
    435  1.1   ragge  * Required machine dependent functions:
    436  1.1   ragge  *     swapINX(i)  ...return the status of INEXACT flag and reset it to "i"
    437  1.1   ragge  *     swapRM(r)   ...return the current Rounding Mode and reset it to "r"
    438  1.1   ragge  *     swapENI(e)  ...return the status of inexact enable and reset it to "e"
    439  1.1   ragge  *     addc(t)     ...perform t=t+1 regarding t as a 64 bit unsigned integer
    440  1.1   ragge  *     subc(t)     ...perform t=t-1 regarding t as a 64 bit unsigned integer
    441  1.1   ragge  */
    442  1.1   ragge 
    443  1.1   ragge static const unsigned long table[] = {
    444  1.1   ragge 0, 1204, 3062, 5746, 9193, 13348, 18162, 23592, 29598, 36145, 43202, 50740,
    445  1.1   ragge 58733, 67158, 75992, 85215, 83599, 71378, 60428, 50647, 41945, 34246, 27478,
    446  1.1   ragge 21581, 16499, 12183, 8588, 5674, 3403, 1742, 661, 130, };
    447  1.1   ragge 
    448  1.4    matt double
    449  1.4    matt newsqrt(double x)
    450  1.1   ragge {
    451  1.1   ragge         double y,z,t,addc(),subc()
    452  1.1   ragge 	double const b54=134217728.*134217728.; /* b54=2**54 */
    453  1.1   ragge         long mx,scalx;
    454  1.1   ragge 	long const mexp=0x7ff00000;
    455  1.3  simonb         int i,j,r,e,swapINX(),swapRM(),swapENI();
    456  1.1   ragge         unsigned long *py=(unsigned long *) &y   ,
    457  1.1   ragge                       *pt=(unsigned long *) &t   ,
    458  1.1   ragge                       *px=(unsigned long *) &x   ;
    459  1.1   ragge #ifdef national         /* ordering of word in a floating point number */
    460  1.3  simonb         const int n0=1, n1=0;
    461  1.1   ragge #else
    462  1.3  simonb         const int n0=0, n1=1;
    463  1.1   ragge #endif
    464  1.3  simonb /* Rounding Mode:  RN ...round-to-nearest
    465  1.1   ragge  *                 RZ ...round-towards 0
    466  1.1   ragge  *                 RP ...round-towards +INF
    467  1.1   ragge  *		   RM ...round-towards -INF
    468  1.1   ragge  */
    469  1.1   ragge         const int RN=0,RZ=1,RP=2,RM=3;
    470  1.1   ragge 				/* machine dependent: work on a Zilog Z8070
    471  1.1   ragge                                  * and a National 32081 & 16081
    472  1.1   ragge                                  */
    473  1.1   ragge 
    474  1.1   ragge /* exceptions */
    475  1.1   ragge 	if(x!=x||x==0.0) return(x);  /* sqrt(NaN) is NaN, sqrt(+-0) = +-0 */
    476  1.1   ragge 	if(x<0) return((x-x)/(x-x)); /* sqrt(negative) is invalid */
    477  1.1   ragge         if((mx=px[n0]&mexp)==mexp) return(x);  /* sqrt(+INF) is +INF */
    478  1.1   ragge 
    479  1.1   ragge /* save, reset, initialize */
    480  1.1   ragge         e=swapENI(0);   /* ...save and reset the inexact enable */
    481  1.1   ragge         i=swapINX(0);   /* ...save INEXACT flag */
    482  1.1   ragge         r=swapRM(RN);   /* ...save and reset the Rounding Mode to RN */
    483  1.1   ragge         scalx=0;
    484  1.1   ragge 
    485  1.1   ragge /* subnormal number, scale up x to x*2**54 */
    486  1.1   ragge         if(mx==0) {x *= b54 ; scalx-=0x01b00000;}
    487  1.1   ragge 
    488  1.1   ragge /* scale x to avoid intermediate over/underflow:
    489  1.1   ragge  * if (x > 2**512) x=x/2**512; if (x < 2**-512) x=x*2**512 */
    490  1.1   ragge         if(mx>0x5ff00000) {px[n0] -= 0x20000000; scalx+= 0x10000000;}
    491  1.1   ragge         if(mx<0x1ff00000) {px[n0] += 0x20000000; scalx-= 0x10000000;}
    492  1.1   ragge 
    493  1.1   ragge /* magic initial approximation to almost 8 sig. bits */
    494  1.1   ragge         py[n0]=(px[n0]>>1)+0x1ff80000;
    495  1.1   ragge         py[n0]=py[n0]-table[(py[n0]>>15)&31];
    496  1.1   ragge 
    497  1.1   ragge /* Heron's rule once with correction to improve y to almost 18 sig. bits */
    498  1.1   ragge         t=x/y; y=y+t; py[n0]=py[n0]-0x00100006; py[n1]=0;
    499  1.1   ragge 
    500  1.1   ragge /* triple to almost 56 sig. bits; now y approx. sqrt(x) to within 1 ulp */
    501  1.3  simonb         t=y*y; z=t;  pt[n0]+=0x00100000; t+=z; z=(x-z)*y;
    502  1.1   ragge         t=z/(t+x) ;  pt[n0]+=0x00100000; y+=t;
    503  1.1   ragge 
    504  1.3  simonb /* twiddle last bit to force y correctly rounded */
    505  1.1   ragge         swapRM(RZ);     /* ...set Rounding Mode to round-toward-zero */
    506  1.1   ragge         swapINX(0);     /* ...clear INEXACT flag */
    507  1.1   ragge         swapENI(e);     /* ...restore inexact enable status */
    508  1.1   ragge         t=x/y;          /* ...chopped quotient, possibly inexact */
    509  1.1   ragge         j=swapINX(i);   /* ...read and restore inexact flag */
    510  1.1   ragge         if(j==0) { if(t==y) goto end; else t=subc(t); }  /* ...t=t-ulp */
    511  1.1   ragge         b54+0.1;        /* ..trigger inexact flag, sqrt(x) is inexact */
    512  1.1   ragge         if(r==RN) t=addc(t);            /* ...t=t+ulp */
    513  1.1   ragge         else if(r==RP) { t=addc(t);y=addc(y);}/* ...t=t+ulp;y=y+ulp; */
    514  1.1   ragge         y=y+t;                          /* ...chopped sum */
    515  1.1   ragge         py[n0]=py[n0]-0x00100000;       /* ...correctly rounded sqrt(x) */
    516  1.1   ragge end:    py[n0]=py[n0]+scalx;            /* ...scale back y */
    517  1.1   ragge         swapRM(r);                      /* ...restore Rounding Mode */
    518  1.1   ragge         return(y);
    519  1.1   ragge }
    520  1.1   ragge #endif
    521