n_support.c revision 1.3 1 1.3 simonb /* $NetBSD: n_support.c,v 1.3 1999/07/02 15:37:37 simonb 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.3 simonb /*
40 1.3 simonb * 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.3 simonb * slow (in particular, drem and sqrt is extremely inefficient). Each
47 1.3 simonb * 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.3 simonb * 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.3 simonb * sqrt(x)
56 1.3 simonb * 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.3 simonb * (a) copysign(x,y)
61 1.3 simonb * returns x with the sign of y.
62 1.3 simonb * (b) scalb(x,N)
63 1.1 ragge * returns x * (2**N), for integer values N.
64 1.3 simonb * (c) logb(x)
65 1.3 simonb * returns the unbiased exponent of x, a signed integer in
66 1.3 simonb * double precision, except that logb(0) is -INF, logb(INF)
67 1.1 ragge * is +INF, and logb(NAN) is that NAN.
68 1.3 simonb * (d) finite(x)
69 1.3 simonb * 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.3 simonb 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.3 simonb 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.3 simonb 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.3 simonb 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.3 simonb else
169 1.3 simonb 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.3 simonb 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.3 simonb unsigned short k;
197 1.1 ragge #ifdef national
198 1.1 ragge unsigned short
199 1.3 simonb *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.3 simonb *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.3 simonb 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.3 simonb 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.3 simonb 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.3 simonb 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.3 simonb
318 1.1 ragge /* generate the last bit and determine the final rounding */
319 1.3 simonb 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.3 simonb 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.3 simonb else {
328 1.3 simonb s *= 2; x *= 4;
329 1.3 simonb 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.3 simonb
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.3 simonb *
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.3 simonb 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.3 simonb int i,e;
368 1.3 simonb 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.3 simonb 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.3 simonb 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.3 simonb }
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.3 simonb 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.3 simonb swapINX(i); swapENI(e);
426 1.1 ragge
427 1.3 simonb 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.3 simonb *
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.3 simonb 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.3 simonb const int n0=1, n1=0;
466 1.1 ragge #else
467 1.3 simonb const int n0=0, n1=1;
468 1.1 ragge #endif
469 1.3 simonb /* 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.3 simonb 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.3 simonb /* 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