mirror of
https://github.com/adtools/clib2.git
synced 2025-12-08 14:59:05 +00:00
263 lines
6.1 KiB
C
263 lines
6.1 KiB
C
/*
|
|
* :ts=4
|
|
*
|
|
* Portable ISO 'C' (1994) runtime library for the Amiga computer
|
|
* Copyright (c) 2002-2025 by Olaf Barthel <obarthel (at) gmx.net>
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* - Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* - Neither the name of Olaf Barthel nor the names of contributors
|
|
* may be used to endorse or promote products derived from this
|
|
* software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
|
|
*
|
|
*
|
|
* PowerPC math library based in part on work by Sun Microsystems
|
|
* Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
|
*
|
|
* Developed at SunPro, a Sun Microsystems, Inc. business.
|
|
* Permission to use, copy, modify, and distribute this
|
|
* software is freely granted, provided that this notice
|
|
* is preserved.
|
|
*/
|
|
|
|
#ifndef _MATH_HEADERS_H
|
|
#include "math_headers.h"
|
|
#endif /* _MATH_HEADERS_H */
|
|
|
|
/****************************************************************************/
|
|
|
|
#if defined(FLOATING_POINT_SUPPORT)
|
|
|
|
/****************************************************************************/
|
|
|
|
#if defined(IEEE_FLOATING_POINT_SUPPORT)
|
|
|
|
/****************************************************************************/
|
|
|
|
#if defined(__GNUC__)
|
|
|
|
/****************************************************************************/
|
|
|
|
#if defined(SMALL_DATA)
|
|
#define A4(x) "a4@(" #x ":W)"
|
|
#elif defined(SMALL_DATA32)
|
|
#define A4(x) "a4@(" #x ":L)"
|
|
#else
|
|
#define A4(x) #x
|
|
#endif /* SMALL_DATA */
|
|
|
|
/****************************************************************************/
|
|
|
|
extern double __sqrt(double x);
|
|
|
|
/****************************************************************************/
|
|
|
|
asm("
|
|
|
|
.text
|
|
.even
|
|
|
|
.globl _MathIeeeDoubTransBase
|
|
.globl ___sqrt
|
|
|
|
___sqrt:
|
|
|
|
movel a6,sp@-
|
|
movel "A4(_MathIeeeDoubTransBase)",a6
|
|
moveml sp@(8),d0/d1
|
|
jsr a6@(-96:W)
|
|
movel sp@+,a6
|
|
rts
|
|
|
|
");
|
|
|
|
/****************************************************************************/
|
|
|
|
#else
|
|
|
|
/****************************************************************************/
|
|
|
|
INLINE STATIC const double
|
|
__sqrt(double x)
|
|
{
|
|
double result;
|
|
|
|
result = IEEEDPSqrt(x);
|
|
|
|
return(result);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
#endif /* __GNUC__ */
|
|
|
|
/****************************************************************************/
|
|
|
|
#endif /* IEEE_FLOATING_POINT_SUPPORT */
|
|
|
|
/****************************************************************************/
|
|
|
|
#if defined(M68881_FLOATING_POINT_SUPPORT)
|
|
|
|
INLINE STATIC const double
|
|
__sqrt(double x)
|
|
{
|
|
double result;
|
|
|
|
__asm ("fsqrt%.x %1,%0"
|
|
: "=f" (result)
|
|
: "f" (x));
|
|
|
|
return(result);
|
|
}
|
|
|
|
#endif /* M68881_FLOATING_POINT_SUPPORT */
|
|
|
|
/****************************************************************************/
|
|
|
|
#ifdef __PPC__
|
|
|
|
static const double one = 1.0, tiny=1.0e-300;
|
|
|
|
INLINE STATIC double
|
|
__sqrt(double x)
|
|
{
|
|
double z;
|
|
unsigned int sign = (unsigned int)0x80000000;
|
|
unsigned int r,t1,s1,ix1,q1;
|
|
int ix0,s0,q,m,t,i;
|
|
|
|
EXTRACT_WORDS(ix0,ix1,x);
|
|
|
|
/* take care of Inf and NaN */
|
|
if((ix0&0x7ff00000)==0x7ff00000) {
|
|
return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf
|
|
sqrt(-inf)=sNaN */
|
|
}
|
|
/* take care of zero */
|
|
if(ix0<=0) {
|
|
if(((ix0&(~sign))|ix1)==0) return x;/* sqrt(+-0) = +-0 */
|
|
else if(ix0<0)
|
|
return (x-x)/(x-x); /* sqrt(-ve) = sNaN */
|
|
}
|
|
/* normalize x */
|
|
m = (ix0>>20);
|
|
if(m==0) { /* subnormal x */
|
|
while(ix0==0) {
|
|
m -= 21;
|
|
ix0 |= (ix1>>11); ix1 <<= 21;
|
|
}
|
|
for(i=0;(ix0&0x00100000)==0;i++) ix0<<=1;
|
|
m -= i-1;
|
|
ix0 |= (ix1>>(32-i));
|
|
ix1 <<= i;
|
|
}
|
|
m -= 1023; /* unbias exponent */
|
|
ix0 = (ix0&0x000fffff)|0x00100000;
|
|
if(m&1){ /* odd m, double x to make it even */
|
|
ix0 += ix0 + ((ix1&sign)>>31);
|
|
ix1 += ix1;
|
|
}
|
|
m >>= 1; /* m = [m/2] */
|
|
|
|
/* generate sqrt(x) bit by bit */
|
|
ix0 += ix0 + ((ix1&sign)>>31);
|
|
ix1 += ix1;
|
|
q = q1 = s0 = s1 = 0; /* [q,q1] = sqrt(x) */
|
|
r = 0x00200000; /* r = moving bit from right to left */
|
|
|
|
while(r!=0) {
|
|
t = s0+r;
|
|
if(t<=ix0) {
|
|
s0 = t+r;
|
|
ix0 -= t;
|
|
q += r;
|
|
}
|
|
ix0 += ix0 + ((ix1&sign)>>31);
|
|
ix1 += ix1;
|
|
r>>=1;
|
|
}
|
|
|
|
r = sign;
|
|
while(r!=0) {
|
|
t1 = s1+r;
|
|
t = s0;
|
|
if((t<ix0)||((t==ix0)&&(t1<=ix1))) {
|
|
s1 = t1+r;
|
|
if(((t1&sign)==sign)&&(s1&sign)==0) s0 += 1;
|
|
ix0 -= t;
|
|
if (ix1 < t1) ix0 -= 1;
|
|
ix1 -= t1;
|
|
q1 += r;
|
|
}
|
|
ix0 += ix0 + ((ix1&sign)>>31);
|
|
ix1 += ix1;
|
|
r>>=1;
|
|
}
|
|
|
|
/* use floating add to find out rounding direction */
|
|
if((ix0|ix1)!=0) {
|
|
z = one-tiny; /* trigger inexact flag */
|
|
if (z>=one) {
|
|
z = one+tiny;
|
|
if (q1==(unsigned int)0xffffffff) { q1=0; q += 1;}
|
|
else if (z>one) {
|
|
if (q1==(unsigned int)0xfffffffe) q+=1;
|
|
q1+=2;
|
|
} else
|
|
q1 += (q1&1);
|
|
}
|
|
}
|
|
ix0 = (q>>1)+0x3fe00000;
|
|
ix1 = q1>>1;
|
|
if ((q&1)==1) ix1 |= sign;
|
|
ix0 += (m <<20);
|
|
INSERT_WORDS(z,ix0,ix1);
|
|
return z;
|
|
}
|
|
|
|
#endif
|
|
|
|
/****************************************************************************/
|
|
|
|
double
|
|
sqrt(double x)
|
|
{
|
|
double result;
|
|
|
|
if(x >= 0.0)
|
|
{
|
|
result = __sqrt(x);
|
|
}
|
|
else
|
|
{
|
|
result = NAN;
|
|
|
|
__set_errno(EDOM);
|
|
}
|
|
|
|
return(result);
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
#endif /* FLOATING_POINT_SUPPORT */
|