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