home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 4
/
FreshFish_May-June1994.bin
/
bsd
/
src
/
libm
/
libm-amiga
/
ieee
/
support.c
< prev
Wrap
C/C++ Source or Header
|
1993-09-23
|
18KB
|
525 lines
/*
* Copyright (c) 1985 Regents of the University of California.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
static char sccsid[] = "@(#)support.c 5.6 (Berkeley) 10/9/90";
#endif /* not lint */
/*
* Some IEEE standard 754 recommended functions and remainder and sqrt for
* supporting the C elementary functions.
******************************************************************************
* WARNING:
* These codes are developed (in double) to support the C elementary
* functions temporarily. They are not universal, and some of them are very
* slow (in particular, drem and sqrt is extremely inefficient). Each
* computer system should have its implementation of these functions using
* its own assembler.
******************************************************************************
*
* IEEE 754 required operations:
* drem(x,p)
* returns x REM y = x - [x/y]*y , where [x/y] is the integer
* nearest x/y; in half way case, choose the even one.
* sqrt(x)
* returns the square root of x correctly rounded according to
* the rounding mod.
*
* IEEE 754 recommended functions:
* (a) copysign(x,y)
* returns x with the sign of y.
* (b) scalb(x,N)
* returns x * (2**N), for integer values N.
* (c) logb(x)
* returns the unbiased exponent of x, a signed integer in
* double precision, except that logb(0) is -INF, logb(INF)
* is +INF, and logb(NAN) is that NAN.
* (d) finite(x)
* returns the value TRUE if -INF < x < +INF and returns
* FALSE otherwise.
*
*
* CODED IN C BY K.C. NG, 11/25/84;
* REVISED BY K.C. NG on 1/22/85, 2/13/85, 3/24/85.
*/
#include "mathimpl.h"
#if defined(vax)||defined(tahoe) /* VAX D format */
#include <errno.h>
static const unsigned short msign=0x7fff , mexp =0x7f80 ;
static const short prep1=57, gap=7, bias=129 ;
static const double novf=1.7E38, nunf=3.0E-39, zero=0.0 ;
#else /* defined(vax)||defined(tahoe) */
static const unsigned short msign=0x7fff, mexp =0x7ff0 ;
static const short prep1=54, gap=4, bias=1023 ;
static const double novf=1.7E308, nunf=3.0E-308,zero=0.0;
#endif /* defined(vax)||defined(tahoe) */
double scalb(x,N)
double x; int N;
{
int k;
#ifdef national
unsigned short *px=(unsigned short *) &x + 3;
#else /* national */
unsigned short *px=(unsigned short *) &x;
#endif /* national */
if( x == zero ) return(x);
#if defined(vax)||defined(tahoe)
if( (k= *px & mexp ) != ~msign ) {
if (N < -260)
return(nunf*nunf);
else if (N > 260) {
return(copysign(infnan(ERANGE),x));
}
#else /* defined(vax)||defined(tahoe) */
if( (k= *px & mexp ) != mexp ) {
if( N<-2100) return(nunf*nunf); else if(N>2100) return(novf+novf);
if( k == 0 ) {
x *= scalb(1.0,(int)prep1); N -= prep1; return(scalb(x,N));}
#endif /* defined(vax)||defined(tahoe) */
if((k = (k>>gap)+ N) > 0 )
if( k < (mexp>>gap) ) *px = (*px&~mexp) | (k<<gap);
else x=novf+novf; /* overflow */
else
if( k > -prep1 )
/* gradual underflow */
{*px=(*px&~mexp)|(short)(1<<gap); x *= scalb(1.0,k-1);}
else
return(nunf*nunf);
}
return(x);
}
double copysign(x,y)
double x,y;
{
#ifdef national
unsigned short *px=(unsigned short *) &x+3,
*py=(unsigned short *) &y+3;
#else /* national */
unsigned short *px=(unsigned short *) &x,
*py=(unsigned short *) &y;
#endif /* national */
#if defined(vax)||defined(tahoe)
if ( (*px & mexp) == 0 ) return(x);
#endif /* defined(vax)||defined(tahoe) */
*px = ( *px & msign ) | ( *py & ~msign );
return(x);
}
double logb(x)
double x;
{
#ifdef national
short *px=(short *) &x+3, k;
#else /* national */
short *px=(short *) &x, k;
#endif /* national */
#if defined(vax)||defined(tahoe)
return (int)(((*px&mexp)>>gap)-bias);
#else /* defined(vax)||defined(tahoe) */
if( (k= *px & mexp ) != mexp )
if ( k != 0 )
return ( (k>>gap) - bias );
else if( x != zero)
return ( -1022.0 );
else
return(-(1.0/zero));
else if(x != x)
return(x);
else
{*px &= msign; return(x);}
#endif /* defined(vax)||defined(tahoe) */
}
finite(x)
double x;
{
#if defined(vax)||defined(tahoe)
return(1);
#else /* defined(vax)||defined(tahoe) */
#ifdef national
return( (*((short *) &x+3 ) & mexp ) != mexp );
#else /* national */
return( (*((short *) &x ) & mexp ) != mexp );
#endif /* national */
#endif /* defined(vax)||defined(tahoe) */
}
double drem(x,p)
double x,p;
{
short sign;
double hp,dp,tmp;
unsigned short k;
#ifdef national
unsigned short
*px=(unsigned short *) &x +3,
*pp=(unsigned short *) &p +3,
*pd=(unsigned short *) &dp +3,
*pt=(unsigned short *) &tmp+3;
#else /* national */
unsigned short
*px=(unsigned short *) &x ,
*pp=(unsigned short *) &p ,
*pd=(unsigned short *) &dp ,
*pt=(unsigned short *) &tmp;
#endif /* national */
*pp &= msign ;
#if defined(vax)||defined(tahoe)
if( ( *px & mexp ) == ~msign ) /* is x a reserved operand? */
#else /* defined(vax)||defined(tahoe) */
if( ( *px & mexp ) == mexp )
#endif /* defined(vax)||defined(tahoe) */
return (x-p)-(x-p); /* create nan if x is inf */
if (p == zero) {
#if defined(vax)||defined(tahoe)
return(infnan(EDOM));
#else /* defined(vax)||defined(tahoe) */
return zero/zero;
#endif /* defined(vax)||defined(tahoe) */
}
#if defined(vax)||defined(tahoe)
if( ( *pp & mexp ) == ~msign ) /* is p a reserved operand? */
#else /* defined(vax)||defined(tahoe) */
if( ( *pp & mexp ) == mexp )
#endif /* defined(vax)||defined(tahoe) */
{ if (p != p) return p; else return x;}
else if ( ((*pp & mexp)>>gap) <= 1 )
/* subnormal p, or almost subnormal p */
{ double b; b=scalb(1.0,(int)