2 * Copyright (c) 1985, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * @(#)support.c 8.1 (Berkeley) 6/4/93
37 * Some IEEE standard 754 recommended functions and remainder and sqrt for
38 * supporting the C elementary functions.
39 ******************************************************************************
41 * These codes are developed (in double) to support the C elementary
42 * functions temporarily. They are not universal, and some of them are very
43 * slow (in particular, drem and sqrt is extremely inefficient). Each
44 * computer system should have its implementation of these functions using
46 ******************************************************************************
48 * IEEE 754 required operations:
50 * returns x REM y = x - [x/y]*y , where [x/y] is the integer
51 * nearest x/y; in half way case, choose the even one.
53 * returns the square root of x correctly rounded according to
56 * IEEE 754 recommended functions:
58 * returns x with the sign of y.
60 * returns x * (2**N), for integer values N.
62 * returns the unbiased exponent of x, a signed integer in
63 * double precision, except that logb(0) is -INF, logb(INF)
64 * is +INF, and logb(NAN) is that NAN.
66 * returns the value TRUE if -INF < x < +INF and returns
70 * CODED IN C BY K.C. NG, 11/25/84;
71 * REVISED BY K.C. NG on 1/22/85, 2/13/85, 3/24/85.
76 #if defined(vax)||defined(tahoe) /* VAX D format */
78 static const unsigned short msign=0x7fff , mexp =0x7f80 ;
79 static const short prep1=57, gap=7, bias=129 ;
80 static const double novf=1.7E38, nunf=3.0E-39, zero=0.0 ;
81 #else /* defined(vax)||defined(tahoe) */
82 static const unsigned short msign=0x7fff, mexp =0x7ff0 ;
83 static const short prep1=54, gap=4, bias=1023 ;
84 static const double novf=1.7E308, nunf=3.0E-308,zero=0.0;
85 #endif /* defined(vax)||defined(tahoe) */
93 unsigned short *px=(unsigned short *) &x + 3;
95 unsigned short *px=(unsigned short *) &x;
98 if( x == zero ) return(x);
100 #if defined(vax)||defined(tahoe)
101 if( (k= *px & mexp ) != ~msign ) {
105 return(copysign(infnan(ERANGE),x));
107 #else /* defined(vax)||defined(tahoe) */
108 if( (k= *px & mexp ) != mexp ) {
109 if( N<-2100) return(nunf*nunf); else if(N>2100) return(novf+novf);
111 x *= scalb(1.0,(int)prep1); N -= prep1; return(scalb(x,N));}
112 #endif /* defined(vax)||defined(tahoe) */
114 if((k = (k>>gap)+ N) > 0 )
115 if( k < (mexp>>gap) ) *px = (*px&~mexp) | (k<<gap);
116 else x=novf+novf; /* overflow */
119 /* gradual underflow */
120 {*px=(*px&~mexp)|(short)(1<<gap); x *= scalb(1.0,k-1);}
132 unsigned short *px=(unsigned short *) &x+3,
133 *py=(unsigned short *) &y+3;
135 unsigned short *px=(unsigned short *) &x,
136 *py=(unsigned short *) &y;
137 #endif /* national */
139 #if defined(vax)||defined(tahoe)
140 if ( (*px & mexp) == 0 ) return(x);
141 #endif /* defined(vax)||defined(tahoe) */
143 *px = ( *px & msign ) | ( *py & ~msign );
152 short *px=(short *) &x+3, k;
154 short *px=(short *) &x, k;
155 #endif /* national */
157 #if defined(vax)||defined(tahoe)
158 return (int)(((*px&mexp)>>gap)-bias);
159 #else /* defined(vax)||defined(tahoe) */
160 if( (k= *px & mexp ) != mexp )
162 return ( (k>>gap) - bias );
170 {*px &= msign; return(x);}
171 #endif /* defined(vax)||defined(tahoe) */
177 #if defined(vax)||defined(tahoe)
179 #else /* defined(vax)||defined(tahoe) */
181 return( (*((short *) &x+3 ) & mexp ) != mexp );
183 return( (*((short *) &x ) & mexp ) != mexp );
184 #endif /* national */
185 #endif /* defined(vax)||defined(tahoe) */
196 *px=(unsigned short *) &x +3,
197 *pp=(unsigned short *) &p +3,
198 *pd=(unsigned short *) &dp +3,
199 *pt=(unsigned short *) &tmp+3;
202 *px=(unsigned short *) &x ,
203 *pp=(unsigned short *) &p ,
204 *pd=(unsigned short *) &dp ,
205 *pt=(unsigned short *) &tmp;
206 #endif /* national */
210 #if defined(vax)||defined(tahoe)
211 if( ( *px & mexp ) == ~msign ) /* is x a reserved operand? */
212 #else /* defined(vax)||defined(tahoe) */
213 if( ( *px & mexp ) == mexp )
214 #endif /* defined(vax)||defined(tahoe) */
215 return (x-p)-(x-p); /* create nan if x is inf */
217 #if defined(vax)||defined(tahoe)
218 return(infnan(EDOM));
219 #else /* defined(vax)||defined(tahoe) */
221 #endif /* defined(vax)||defined(tahoe) */
224 #if defined(vax)||defined(tahoe)
225 if( ( *pp & mexp ) == ~msign ) /* is p a reserved operand? */
226 #else /* defined(vax)||defined(tahoe) */
227 if( ( *pp & mexp ) == mexp )
228 #endif /* defined(vax)||defined(tahoe) */
229 { if (p != p) return p; else return x;}
231 else if ( ((*pp & mexp)>>gap) <= 1 )
232 /* subnormal p, or almost subnormal p */
233 { double b; b=scalb(1.0,(int)prep1);
234 p *= b; x = drem(x,p); x *= b; return(drem(x,p)/b);}
235 else if ( p >= novf/2)
236 { p /= 2 ; x /= 2; return(drem(x,p)*2);}
244 k=(*px & mexp) - (*pd & mexp) ;
248 #if defined(vax)||defined(tahoe)
249 if( x < tmp ) *pt -= 128 ;
250 #else /* defined(vax)||defined(tahoe) */
251 if( x < tmp ) *pt -= 16 ;
252 #endif /* defined(vax)||defined(tahoe) */
257 { x -= p ; if ( x >= hp ) x -= p ; }
259 #if defined(vax)||defined(tahoe)
261 #endif /* defined(vax)||defined(tahoe) */
274 double const zero=0.0;
276 #if defined(vax)||defined(tahoe)
278 #else /* defined(vax)||defined(tahoe) */
280 #endif /* defined(vax)||defined(tahoe) */
282 /* sqrt(NaN) is NaN, sqrt(+-0) = +-0 */
283 if(x!=x||x==zero) return(x);
285 /* sqrt(negative) is invalid */
287 #if defined(vax)||defined(tahoe)
288 return (infnan(EDOM)); /* NaN */
289 #else /* defined(vax)||defined(tahoe) */
291 #endif /* defined(vax)||defined(tahoe) */
294 /* sqrt(INF) is INF */
295 if(!finite(x)) return(x);
297 /* scale x to [1,4) */
300 if((m=logb(x))!=0) x=scalb(x,-m); /* subnormal number */
303 if((n+n)!=m) {x *= 2; m -=1; n=m/2;}
305 /* generate sqrt(x) bit by bit (accumulating in q) */
306 q=1.0; s=4.0; x -= 1.0; r=1;
308 t=s+1; x *= 4; r /= 2;
310 s=t+t+2, x -= t; q += r;}
315 /* generate the last bit and determine the final rounding */
317 if(x==zero) goto end; 100+r; /* trigger inexact flag */
319 q+=r; x -=s; s += 2; s *= 2; x *= 4;
321 b=1.0+3*r/4; if(b==1.0) goto end; /* b==1 : Round-to-zero */
322 b=1.0+r/4; if(b>1.0) t=1; /* b>1 : Round-to-(+INF) */
323 if(t>=0) q+=r; } /* else: Round-to-nearest */
327 b=1.0+3*r/4; if(b==1.0) goto end;
328 b=1.0+r/4; if(b>1.0) t=1;
331 end: return(scalb(q,n));
336 * RETURN X REM Y =X-N*Y, N=[X/Y] ROUNDED (ROUNDED TO EVEN IN THE HALF WAY CASE)
337 * DOUBLE PRECISION (VAX D format 56 bits, IEEE DOUBLE 53 BITS)
338 * INTENDED FOR ASSEMBLY LANGUAGE
339 * CODED IN C BY K.C. NG, 3/23/85, 4/8/85.
341 * Warning: this code should not get compiled in unless ALL of
342 * the following machine-dependent routines are supplied.
344 * Required machine dependent functions (not on a VAX):
345 * swapINX(i): save inexact flag and reset it to "i"
346 * swapENI(e): save inexact enable and reset it to "e"
353 #ifdef national /* order of words in floating point number */
354 static const n0=3,n1=2,n2=1,n3=0;
355 #else /* VAX, SUN, ZILOG, TAHOE */
356 static const n0=0,n1=1,n2=2,n3=3;
359 static const unsigned short mexp =0x7ff0, m25 =0x0190, m57 =0x0390;
360 static const double zero=0.0;
365 unsigned short xexp,yexp, *px =(unsigned short *) &x ,
366 nx,nf, *py =(unsigned short *) &y ,
367 sign, *pt =(unsigned short *) &t ,
368 *pt1 =(unsigned short *) &t1 ;
370 xexp = px[n0] & mexp ; /* exponent of x */
371 yexp = py[n0] & mexp ; /* exponent of y */
372 sign = px[n0] &0x8000; /* sign of x */
374 /* return NaN if x is NaN, or y is NaN, or x is INF, or y is zero */
375 if(x!=x) return(x); if(y!=y) return(y); /* x or y is NaN */
376 if( xexp == mexp ) return(zero/zero); /* x is INF */
377 if(y==zero) return(y/y);
379 /* save the inexact flag and inexact enable in i and e respectively
380 * and reset them to zero
382 i=swapINX(0); e=swapENI(0);
384 /* subnormal number */
386 if(yexp==0) {t=1.0,pt[n0]+=m57; y*=t; nx=m57;}
388 /* if y is tiny (biased exponent <= 57), scale up y to y*2**57 */
389 if( yexp <= m57 ) {py[n0]+=m57; nx+=m57; yexp+=m57;}
395 /* mask off the least significant 27 bits of y */
396 t=y; pt[n3]=0; pt[n2]&=0xf800; y1=t;
398 /* LOOP: argument reduction on x whenever x > y */
404 xexp=px[n0]&mexp; /* exponent of x */
406 if(k>0) /* if x/y >= 2**26, scale up y so that x/y < 2**26 */
407 {pt[n0]+=k;pt1[n0]+=k;}
408 n=x/t; x=(x-n*t1)-n*(t-t1);
410 /* end while (x > y) */
412 if(nx!=0) {t=1.0; pt[n0]+=nx; x*=t; nx=0; goto loop;}
414 /* final adjustment */
417 if(x>hy||((x==hy)&&n%2==1)) x-=y;
419 if(nf!=0) { t=1.0; pt[n0]-=nf; x*=t;}
421 /* restore inexact flag and inexact enable */
422 swapINX(i); swapENI(e);
430 * RETURN CORRECTLY ROUNDED (ACCORDING TO THE ROUNDING MODE) SQRT
431 * FOR IEEE DOUBLE PRECISION ONLY, INTENDED FOR ASSEMBLY LANGUAGE
432 * CODED IN C BY K.C. NG, 3/22/85.
434 * Warning: this code should not get compiled in unless ALL of
435 * the following machine-dependent routines are supplied.
437 * Required machine dependent functions:
438 * swapINX(i) ...return the status of INEXACT flag and reset it to "i"
439 * swapRM(r) ...return the current Rounding Mode and reset it to "r"
440 * swapENI(e) ...return the status of inexact enable and reset it to "e"
441 * addc(t) ...perform t=t+1 regarding t as a 64 bit unsigned integer
442 * subc(t) ...perform t=t-1 regarding t as a 64 bit unsigned integer
445 static const unsigned long table[] = {
446 0, 1204, 3062, 5746, 9193, 13348, 18162, 23592, 29598, 36145, 43202, 50740,
447 58733, 67158, 75992, 85215, 83599, 71378, 60428, 50647, 41945, 34246, 27478,
448 21581, 16499, 12183, 8588, 5674, 3403, 1742, 661, 130, };
453 double y,z,t,addc(),subc()
454 double const b54=134217728.*134217728.; /* b54=2**54 */
456 long const mexp=0x7ff00000;
457 int i,j,r,e,swapINX(),swapRM(),swapENI();
458 unsigned long *py=(unsigned long *) &y ,
459 *pt=(unsigned long *) &t ,
460 *px=(unsigned long *) &x ;
461 #ifdef national /* ordering of word in a floating point number */
462 const int n0=1, n1=0;
464 const int n0=0, n1=1;
466 /* Rounding Mode: RN ...round-to-nearest
467 * RZ ...round-towards 0
468 * RP ...round-towards +INF
469 * RM ...round-towards -INF
471 const int RN=0,RZ=1,RP=2,RM=3;
472 /* machine dependent: work on a Zilog Z8070
473 * and a National 32081 & 16081
477 if(x!=x||x==0.0) return(x); /* sqrt(NaN) is NaN, sqrt(+-0) = +-0 */
478 if(x<0) return((x-x)/(x-x)); /* sqrt(negative) is invalid */
479 if((mx=px[n0]&mexp)==mexp) return(x); /* sqrt(+INF) is +INF */
481 /* save, reset, initialize */
482 e=swapENI(0); /* ...save and reset the inexact enable */
483 i=swapINX(0); /* ...save INEXACT flag */
484 r=swapRM(RN); /* ...save and reset the Rounding Mode to RN */
487 /* subnormal number, scale up x to x*2**54 */
488 if(mx==0) {x *= b54 ; scalx-=0x01b00000;}
490 /* scale x to avoid intermediate over/underflow:
491 * if (x > 2**512) x=x/2**512; if (x < 2**-512) x=x*2**512 */
492 if(mx>0x5ff00000) {px[n0] -= 0x20000000; scalx+= 0x10000000;}
493 if(mx<0x1ff00000) {px[n0] += 0x20000000; scalx-= 0x10000000;}
495 /* magic initial approximation to almost 8 sig. bits */
496 py[n0]=(px[n0]>>1)+0x1ff80000;
497 py[n0]=py[n0]-table[(py[n0]>>15)&31];
499 /* Heron's rule once with correction to improve y to almost 18 sig. bits */
500 t=x/y; y=y+t; py[n0]=py[n0]-0x00100006; py[n1]=0;
502 /* triple to almost 56 sig. bits; now y approx. sqrt(x) to within 1 ulp */
503 t=y*y; z=t; pt[n0]+=0x00100000; t+=z; z=(x-z)*y;
504 t=z/(t+x) ; pt[n0]+=0x00100000; y+=t;
506 /* twiddle last bit to force y correctly rounded */
507 swapRM(RZ); /* ...set Rounding Mode to round-toward-zero */
508 swapINX(0); /* ...clear INEXACT flag */
509 swapENI(e); /* ...restore inexact enable status */
510 t=x/y; /* ...chopped quotient, possibly inexact */
511 j=swapINX(i); /* ...read and restore inexact flag */
512 if(j==0) { if(t==y) goto end; else t=subc(t); } /* ...t=t-ulp */
513 b54+0.1; /* ..trigger inexact flag, sqrt(x) is inexact */
514 if(r==RN) t=addc(t); /* ...t=t+ulp */
515 else if(r==RP) { t=addc(t);y=addc(y);}/* ...t=t+ulp;y=y+ulp; */
516 y=y+t; /* ...chopped sum */
517 py[n0]=py[n0]-0x00100000; /* ...correctly rounded sqrt(x) */
518 end: py[n0]=py[n0]+scalx; /* ...scale back y */
519 swapRM(r); /* ...restore Rounding Mode */