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