* Removed libroot/posix/math completely and added the respective

functions from glibc 2.3.2. Adding those one by one is extremely
  boring and time-consuming work. We should probably just remove the
  math stuff again, add a verbatim copy of the glibc directories, and
  shuffle things around afterwards.
* Note that for x86 holds sizeof(long double) == 96. I removed the
  generic 128 bit long double functions that were in use before and
  added respective 96 bit versions to arch/x86 (or left them out, if
  they weren't used). For PPC the System V ABI spec supplement specifies
  sizeof(long double) == 128, but I had trouble configuring gcc to
  actually use that setting (looks like there simply is no support for
  TI mode for PPC 32). So we have to live with sizeof(long double) ==
  sizeof(double) == 64 for the time being.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15477 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2005-12-10 20:39:04 +00:00
parent 27de84142b
commit 901f399036
285 changed files with 45649 additions and 7430 deletions
-2
View File
@@ -16,8 +16,6 @@ local librootObjects =
posix_locale.o
posix_main.o
posix_malloc.o
posix_math.o
posix_math_arch_$(TARGET_ARCH).o
posix_pthread.o
posix_signal.o
posix_stdio.o
-1
View File
@@ -24,7 +24,6 @@ SubInclude HAIKU_TOP src system libroot posix arch $(TARGET_ARCH) ;
SubInclude HAIKU_TOP src system libroot posix crypt ;
SubInclude HAIKU_TOP src system libroot posix locale ;
SubInclude HAIKU_TOP src system libroot posix malloc ;
SubInclude HAIKU_TOP src system libroot posix math ;
SubInclude HAIKU_TOP src system libroot posix pthread ;
SubInclude HAIKU_TOP src system libroot posix signal ;
SubInclude HAIKU_TOP src system libroot posix stdio ;
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,144 @@
/*
* IBM Accurate Mathematical Library
* Written by International Business Machines Corp.
* Copyright (C) 2001 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*******************************************************************/
/* */
/* MODULE_NAME: branred.c */
/* */
/* FUNCTIONS: branred */
/* */
/* FILES NEEDED: branred.h mydefs.h endian.h mpa.h */
/* mha.c */
/* */
/* Routine branred() performs range reduction of a double number */
/* x into Double length number a+aa,such that */
/* x=n*pi/2+(a+aa), abs(a+aa)<pi/4, n=0,+-1,+-2,.... */
/* Routine returns the integer (n mod 4) of the above description */
/* of x. */
/*******************************************************************/
#include "endian.h"
#include "mydefs.h"
#include "branred.h"
#include "math_private.h"
/*******************************************************************/
/* Routine branred() performs range reduction of a double number */
/* x into Double length number a+aa,such that */
/* x=n*pi/2+(a+aa), abs(a+aa)<pi/4, n=0,+-1,+-2,.... */
/* Routine return integer (n mod 4) */
/*******************************************************************/
int __branred(double x, double *a, double *aa)
{
int i,k;
#if 0
int n;
#endif
mynumber u,gor;
#if 0
mynumber v;
#endif
double r[6],s,t,sum,b,bb,sum1,sum2,b1,bb1,b2,bb2,x1,x2,t1,t2;
x*=tm600.x;
t=x*split; /* split x to two numbers */
x1=t-(t-x);
x2=x-x1;
sum=0;
u.x = x1;
k = (u.i[HIGH_HALF]>>20)&2047;
k = (k-450)/24;
if (k<0)
k=0;
gor.x = t576.x;
gor.i[HIGH_HALF] -= ((k*24)<<20);
for (i=0;i<6;i++)
{ r[i] = x1*toverp[k+i]*gor.x; gor.x *= tm24.x; }
for (i=0;i<3;i++) {
s=(r[i]+big.x)-big.x;
sum+=s;
r[i]-=s;
}
t=0;
for (i=0;i<6;i++)
t+=r[5-i];
bb=(((((r[0]-t)+r[1])+r[2])+r[3])+r[4])+r[5];
s=(t+big.x)-big.x;
sum+=s;
t-=s;
b=t+bb;
bb=(t-b)+bb;
s=(sum+big1.x)-big1.x;
sum-=s;
b1=b;
bb1=bb;
sum1=sum;
sum=0;
u.x = x2;
k = (u.i[HIGH_HALF]>>20)&2047;
k = (k-450)/24;
if (k<0)
k=0;
gor.x = t576.x;
gor.i[HIGH_HALF] -= ((k*24)<<20);
for (i=0;i<6;i++)
{ r[i] = x2*toverp[k+i]*gor.x; gor.x *= tm24.x; }
for (i=0;i<3;i++) {
s=(r[i]+big.x)-big.x;
sum+=s;
r[i]-=s;
}
t=0;
for (i=0;i<6;i++)
t+=r[5-i];
bb=(((((r[0]-t)+r[1])+r[2])+r[3])+r[4])+r[5];
s=(t+big.x)-big.x;
sum+=s;
t-=s;
b=t+bb;
bb=(t-b)+bb;
s=(sum+big1.x)-big1.x;
sum-=s;
b2=b;
bb2=bb;
sum2=sum;
sum=sum1+sum2;
b=b1+b2;
bb = (ABS(b1)>ABS(b2))? (b1-b)+b2 : (b2-b)+b1;
if (b > 0.5)
{b-=1.0; sum+=1.0;}
else if (b < -0.5)
{b+=1.0; sum-=1.0;}
s=b+(bb+bb1+bb2);
t=((b-s)+bb)+(bb1+bb2);
b=s*split;
t1=b-(b-s);
t2=s-t1;
b=s*hp0.x;
bb=(((t1*mp1.x-b)+t1*mp2.x)+t2*mp1.x)+(t2*mp2.x+s*hp1.x+t*hp0.x);
s=b+bb;
t=(b-s)+bb;
*a=s;
*aa=t;
return ((int) sum)&3; /* return quater of unit circle */
}
@@ -0,0 +1,80 @@
/*
* IBM Accurate Mathematical Library
* Written by International Business Machines Corp.
* Copyright (C) 2001 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/************************************************************************/
/* MODULE_NAME: branred.h */
/* */
/* */
/* common data and variables definition for BIG or LITTLE ENDIAN */
/************************************************************************/
#ifndef BRANRED_H
#define BRANRED_H
#ifdef BIG_ENDI
static const mynumber
/**/ t576 = {{0x63f00000, 0x00000000}}, /* 2 ^ 576 */
/**/ tm600 = {{0x1a700000, 0x00000000}}, /* 2 ^- 600 */
/**/ tm24 = {{0x3e700000, 0x00000000}}, /* 2 ^- 24 */
/**/ big = {{0x43380000, 0x00000000}}, /* 6755399441055744 */
/**/ big1 = {{0x43580000, 0x00000000}}, /* 27021597764222976 */
/**/ hp0 = {{0x3FF921FB, 0x54442D18}} ,/* 1.5707963267948966 */
/**/ hp1 = {{0x3C91A626, 0x33145C07}} ,/* 6.123233995736766e-17 */
/**/ mp1 = {{0x3FF921FB, 0x58000000}}, /* 1.5707963407039642 */
/**/ mp2 = {{0xBE4DDE97, 0x40000000}}; /*-1.3909067675399456e-08 */
#else
#ifdef LITTLE_ENDI
static const mynumber
/**/ t576 = {{0x00000000, 0x63f00000}}, /* 2 ^ 576 */
/**/ tm600 = {{0x00000000, 0x1a700000}}, /* 2 ^- 600 */
/**/ tm24 = {{0x00000000, 0x3e700000}}, /* 2 ^- 24 */
/**/ big = {{0x00000000, 0x43380000}}, /* 6755399441055744 */
/**/ big1 = {{0x00000000, 0x43580000}}, /* 27021597764222976 */
/**/ hp0 = {{0x54442D18, 0x3FF921FB}}, /* 1.5707963267948966 */
/**/ hp1 = {{0x33145C07, 0x3C91A626}}, /* 6.123233995736766e-17 */
/**/ mp1 = {{0x58000000, 0x3FF921FB}}, /* 1.5707963407039642 */
/**/ mp2 = {{0x40000000, 0xBE4DDE97}}; /*-1.3909067675399456e-08 */
#endif
#endif
static const double toverp[75] = { /* 2/ PI base 24*/
10680707.0, 7228996.0, 1387004.0, 2578385.0, 16069853.0,
12639074.0, 9804092.0, 4427841.0, 16666979.0, 11263675.0,
12935607.0, 2387514.0, 4345298.0, 14681673.0, 3074569.0,
13734428.0, 16653803.0, 1880361.0, 10960616.0, 8533493.0,
3062596.0, 8710556.0, 7349940.0, 6258241.0, 3772886.0,
3769171.0, 3798172.0, 8675211.0, 12450088.0, 3874808.0,
9961438.0, 366607.0, 15675153.0, 9132554.0, 7151469.0,
3571407.0, 2607881.0, 12013382.0, 4155038.0, 6285869.0,
7677882.0, 13102053.0, 15825725.0, 473591.0, 9065106.0,
15363067.0, 6271263.0, 9264392.0, 5636912.0, 4652155.0,
7056368.0, 13614112.0, 10155062.0, 1944035.0, 9527646.0,
15080200.0, 6658437.0, 6231200.0, 6832269.0, 16767104.0,
5075751.0, 3212806.0, 1398474.0, 7579849.0, 6349435.0,
12618859.0, 4703257.0, 12806093.0, 14477321.0, 2786137.0,
12875403.0, 9837734.0, 14528324.0, 13719321.0, 343717.0 };
static const double split = 134217729.0;
#endif
@@ -0,0 +1,76 @@
/*
* IBM Accurate Mathematical Library
* written by International Business Machines Corp.
* Copyright (C) 2001 Free Software Foundation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/**********************************************************************/
/* MODULE_NAME: doasin.c */
/* */
/* FUNCTION: doasin */
/* */
/* FILES NEEDED:endian.h mydefs.h dla.h doasin.h */
/* mpa.c */
/* */
/* Compute arcsin(x,dx,v) of double-length number (x+dx) the result */
/* stored in v where v= v[0]+v[1] =arcsin(x+dx) */
/**********************************************************************/
#include "endian.h"
#include "mydefs.h"
#include "dla.h"
#include "math_private.h"
/********************************************************************/
/* Compute arcsin(x,dx,v) of double-length number (x+dx) the result */
/* stored in v where v= v[0]+v[1] =arcsin(x+dx) */
/********************************************************************/
void __doasin(double x, double dx, double v[]) {
#include "doasin.h"
static const double
d5 = 0.22372159090911789889975459505194491E-01,
d6 = 0.17352764422456822913014975683014622E-01,
d7 = 0.13964843843786693521653681033981614E-01,
d8 = 0.11551791438485242609036067259086589E-01,
d9 = 0.97622386568166960207425666787248914E-02,
d10 = 0.83638737193775788576092749009744976E-02,
d11 = 0.79470250400727425881446981833568758E-02;
double xx,p,pp,u,uu,r,s;
double hx,tx,hy,ty,tp,tq,tc,tcc;
/* Taylor series for arcsin for Double-Length numbers */
xx = x*x+2.0*x*dx;
p = ((((((d11*xx+d10)*xx+d9)*xx+d8)*xx+d7)*xx+d6)*xx+d5)*xx;
pp = 0;
MUL2(x,dx,x,dx,u,uu,tp,hx,tx,hy,ty,tq,tc,tcc);
ADD2(p,pp,c4.x,cc4.x,p,pp,r,s);
MUL2(p,pp,u,uu,p,pp,tp,hx,tx,hy,ty,tq,tc,tcc);
ADD2(p,pp,c3.x,cc3.x,p,pp,r,s);
MUL2(p,pp,u,uu,p,pp,tp,hx,tx,hy,ty,tq,tc,tcc);
ADD2(p,pp,c2.x,cc2.x,p,pp,r,s);
MUL2(p,pp,u,uu,p,pp,tp,hx,tx,hy,ty,tq,tc,tcc);
ADD2(p,pp,c1.x,cc1.x,p,pp,r,s);
MUL2(p,pp,u,uu,p,pp,tp,hx,tx,hy,ty,tq,tc,tcc);
MUL2(p,pp,x,dx,p,pp,tp,hx,tx,hy,ty,tq,tc,tcc);
ADD2(p,pp,x,dx,p,pp,r,s);
v[0]=p;
v[1]=pp; /* arcsin(x+dx)=v[0]+v[1] */
}
@@ -0,0 +1,64 @@
/*
* IBM Accurate Mathematical Library
* Written by International Business Machines Corp.
* Copyright (C) 2001 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/************************************************************************/
/* MODULE_NAME: doasin.h */
/* */
/* */
/* common data and variables definition for BIG or LITTLE ENDIAN */
/************************************************************************/
#ifndef DOASIN_H
#define DOASIN_H
#ifdef BIG_ENDI
static const mynumber
/**/ c1 = {{0x3FC55555, 0x55555555}}, /* 0.16666666666666666 */
/**/ cc1 = {{0x3C655555, 0x55775389}}, /* 9.2518585419753846e-18 */
/**/ c2 = {{0x3FB33333, 0x33333333}}, /* 0.074999999999999997 */
/**/ cc2 = {{0x3C499993, 0x63F1A115}}, /* 2.7755472886508899e-18 */
/**/ c3 = {{0x3FA6DB6D, 0xB6DB6DB7}}, /* 0.044642857142857144 */
/**/ cc3 = {{0xBC320FC0, 0x3D5CF0C5}}, /* -9.7911734574147224e-19 */
/**/ c4 = {{0x3F9F1C71, 0xC71C71C5}}, /* 0.030381944444444437 */
/**/ cc4 = {{0xBC02B240, 0xFF23ED1E}}; /* -1.2669108566898312e-19 */
#else
#ifdef LITTLE_ENDI
static const mynumber
/**/ c1 = {{0x55555555, 0x3FC55555}}, /* 0.16666666666666666 */
/**/ cc1 = {{0x55775389, 0x3C655555}}, /* 9.2518585419753846e-18 */
/**/ c2 = {{0x33333333, 0x3FB33333}}, /* 0.074999999999999997 */
/**/ cc2 = {{0x63F1A115, 0x3C499993}}, /* 2.7755472886508899e-18 */
/**/ c3 = {{0xB6DB6DB7, 0x3FA6DB6D}}, /* 0.044642857142857144 */
/**/ cc3 = {{0x3D5CF0C5, 0xBC320FC0}}, /* -9.7911734574147224e-19 */
/**/ c4 = {{0xC71C71C5, 0x3F9F1C71}}, /* 0.030381944444444437 */
/**/ cc4 = {{0xFF23ED1E, 0xBC02B240}}; /* -1.2669108566898312e-19 */
#endif
#endif
#endif
@@ -0,0 +1,189 @@
/*
* IBM Accurate Mathematical Library
* written by International Business Machines Corp.
* Copyright (C) 2001 Free Software Foundation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/********************************************************************/
/* */
/* MODULE_NAME: dosincos.c */
/* */
/* */
/* FUNCTIONS: dubsin */
/* dubcos */
/* docos */
/* FILES NEEDED: endian.h mydefs.h dla.h dosincos.h */
/* sincos.tbl */
/* */
/* Routines compute sin() and cos() as Double-Length numbers */
/********************************************************************/
#include "endian.h"
#include "mydefs.h"
#include "sincos.tbl"
#include "dla.h"
#include "dosincos.h"
#include "math_private.h"
/***********************************************************************/
/* Routine receive Double-Length number (x+dx) and computing sin(x+dx) */
/* as Double-Length number and store it at array v .It computes it by */
/* arithmetic action on Double-Length numbers */
/*(x+dx) between 0 and PI/4 */
/***********************************************************************/
void __dubsin(double x, double dx, double v[]) {
double r,s,p,hx,tx,hy,ty,q,c,cc,d,dd,d2,dd2,e,ee,
sn,ssn,cs,ccs,ds,dss,dc,dcc;
#if 0
double xx,y,yy,z,zz;
#endif
mynumber u;
int4 k;
u.x=x+big.x;
k = u.i[LOW_HALF]<<2;
x=x-(u.x-big.x);
d=x+dx;
dd=(x-d)+dx;
/* sin(x+dx)=sin(Xi+t)=sin(Xi)*cos(t) + cos(Xi)sin(t) where t ->0 */
MUL2(d,dd,d,dd,d2,dd2,p,hx,tx,hy,ty,q,c,cc);
sn=sincos.x[k]; /* */
ssn=sincos.x[k+1]; /* sin(Xi) and cos(Xi) */
cs=sincos.x[k+2]; /* */
ccs=sincos.x[k+3]; /* */
MUL2(d2,dd2,s7.x,ss7.x,ds,dss,p,hx,tx,hy,ty,q,c,cc); /* Taylor */
ADD2(ds,dss,s5.x,ss5.x,ds,dss,r,s);
MUL2(d2,dd2,ds,dss,ds,dss,p,hx,tx,hy,ty,q,c,cc); /* series */
ADD2(ds,dss,s3.x,ss3.x,ds,dss,r,s);
MUL2(d2,dd2,ds,dss,ds,dss,p,hx,tx,hy,ty,q,c,cc); /* for sin */
MUL2(d,dd,ds,dss,ds,dss,p,hx,tx,hy,ty,q,c,cc);
ADD2(ds,dss,d,dd,ds,dss,r,s); /* ds=sin(t) */
MUL2(d2,dd2,c8.x,cc8.x,dc,dcc,p,hx,tx,hy,ty,q,c,cc); ;/* Taylor */
ADD2(dc,dcc,c6.x,cc6.x,dc,dcc,r,s);
MUL2(d2,dd2,dc,dcc,dc,dcc,p,hx,tx,hy,ty,q,c,cc); /* series */
ADD2(dc,dcc,c4.x,cc4.x,dc,dcc,r,s);
MUL2(d2,dd2,dc,dcc,dc,dcc,p,hx,tx,hy,ty,q,c,cc); /* for cos */
ADD2(dc,dcc,c2.x,cc2.x,dc,dcc,r,s);
MUL2(d2,dd2,dc,dcc,dc,dcc,p,hx,tx,hy,ty,q,c,cc); /* dc=cos(t) */
MUL2(cs,ccs,ds,dss,e,ee,p,hx,tx,hy,ty,q,c,cc);
MUL2(dc,dcc,sn,ssn,dc,dcc,p,hx,tx,hy,ty,q,c,cc);
SUB2(e,ee,dc,dcc,e,ee,r,s);
ADD2(e,ee,sn,ssn,e,ee,r,s); /* e+ee=sin(x+dx) */
v[0]=e;
v[1]=ee;
}
/**********************************************************************/
/* Routine receive Double-Length number (x+dx) and computes cos(x+dx) */
/* as Double-Length number and store it in array v .It computes it by */
/* arithmetic action on Double-Length numbers */
/*(x+dx) between 0 and PI/4 */
/**********************************************************************/
void __dubcos(double x, double dx, double v[]) {
double r,s,p,hx,tx,hy,ty,q,c,cc,d,dd,d2,dd2,e,ee,
sn,ssn,cs,ccs,ds,dss,dc,dcc;
#if 0
double xx,y,yy,z,zz;
#endif
mynumber u;
int4 k;
u.x=x+big.x;
k = u.i[LOW_HALF]<<2;
x=x-(u.x-big.x);
d=x+dx;
dd=(x-d)+dx; /* cos(x+dx)=cos(Xi+t)=cos(Xi)cos(t) - sin(Xi)sin(t) */
MUL2(d,dd,d,dd,d2,dd2,p,hx,tx,hy,ty,q,c,cc);
sn=sincos.x[k]; /* */
ssn=sincos.x[k+1]; /* sin(Xi) and cos(Xi) */
cs=sincos.x[k+2]; /* */
ccs=sincos.x[k+3]; /* */
MUL2(d2,dd2,s7.x,ss7.x,ds,dss,p,hx,tx,hy,ty,q,c,cc);
ADD2(ds,dss,s5.x,ss5.x,ds,dss,r,s);
MUL2(d2,dd2,ds,dss,ds,dss,p,hx,tx,hy,ty,q,c,cc);
ADD2(ds,dss,s3.x,ss3.x,ds,dss,r,s);
MUL2(d2,dd2,ds,dss,ds,dss,p,hx,tx,hy,ty,q,c,cc);
MUL2(d,dd,ds,dss,ds,dss,p,hx,tx,hy,ty,q,c,cc);
ADD2(ds,dss,d,dd,ds,dss,r,s);
MUL2(d2,dd2,c8.x,cc8.x,dc,dcc,p,hx,tx,hy,ty,q,c,cc);
ADD2(dc,dcc,c6.x,cc6.x,dc,dcc,r,s);
MUL2(d2,dd2,dc,dcc,dc,dcc,p,hx,tx,hy,ty,q,c,cc);
ADD2(dc,dcc,c4.x,cc4.x,dc,dcc,r,s);
MUL2(d2,dd2,dc,dcc,dc,dcc,p,hx,tx,hy,ty,q,c,cc);
ADD2(dc,dcc,c2.x,cc2.x,dc,dcc,r,s);
MUL2(d2,dd2,dc,dcc,dc,dcc,p,hx,tx,hy,ty,q,c,cc);
MUL2(cs,ccs,ds,dss,e,ee,p,hx,tx,hy,ty,q,c,cc);
MUL2(dc,dcc,sn,ssn,dc,dcc,p,hx,tx,hy,ty,q,c,cc);
MUL2(d2,dd2,s7.x,ss7.x,ds,dss,p,hx,tx,hy,ty,q,c,cc);
ADD2(ds,dss,s5.x,ss5.x,ds,dss,r,s);
MUL2(d2,dd2,ds,dss,ds,dss,p,hx,tx,hy,ty,q,c,cc);
ADD2(ds,dss,s3.x,ss3.x,ds,dss,r,s);
MUL2(d2,dd2,ds,dss,ds,dss,p,hx,tx,hy,ty,q,c,cc);
MUL2(d,dd,ds,dss,ds,dss,p,hx,tx,hy,ty,q,c,cc);
ADD2(ds,dss,d,dd,ds,dss,r,s);
MUL2(d2,dd2,c8.x,cc8.x,dc,dcc,p,hx,tx,hy,ty,q,c,cc);
ADD2(dc,dcc,c6.x,cc6.x,dc,dcc,r,s);
MUL2(d2,dd2,dc,dcc,dc,dcc,p,hx,tx,hy,ty,q,c,cc);
ADD2(dc,dcc,c4.x,cc4.x,dc,dcc,r,s);
MUL2(d2,dd2,dc,dcc,dc,dcc,p,hx,tx,hy,ty,q,c,cc);
ADD2(dc,dcc,c2.x,cc2.x,dc,dcc,r,s);
MUL2(d2,dd2,dc,dcc,dc,dcc,p,hx,tx,hy,ty,q,c,cc);
MUL2(sn,ssn,ds,dss,e,ee,p,hx,tx,hy,ty,q,c,cc);
MUL2(dc,dcc,cs,ccs,dc,dcc,p,hx,tx,hy,ty,q,c,cc);
ADD2(e,ee,dc,dcc,e,ee,r,s);
SUB2(cs,ccs,e,ee,e,ee,r,s);
v[0]=e;
v[1]=ee;
}
/**********************************************************************/
/* Routine receive Double-Length number (x+dx) and computes cos(x+dx) */
/* as Double-Length number and store it in array v */
/**********************************************************************/
void __docos(double x, double dx, double v[]) {
double y,yy,p,w[2];
if (x>0) {y=x; yy=dx;}
else {y=-x; yy=-dx;}
if (y<0.5*hp0.x) /* y< PI/4 */
{__dubcos(y,yy,w); v[0]=w[0]; v[1]=w[1];}
else if (y<1.5*hp0.x) { /* y< 3/4 * PI */
p=hp0.x-y; /* p = PI/2 - y */
yy=hp1.x-yy;
y=p+yy;
yy=(p-y)+yy;
if (y>0) {__dubsin(y,yy,w); v[0]=w[0]; v[1]=w[1];}
/* cos(x) = sin ( 90 - x ) */
else {__dubsin(-y,-yy,w); v[0]=-w[0]; v[1]=-w[1];
}
}
else { /* y>= 3/4 * PI */
p=2.0*hp0.x-y; /* p = PI- y */
yy=2.0*hp1.x-yy;
y=p+yy;
yy=(p-y)+yy;
__dubcos(y,yy,w);
v[0]=-w[0];
v[1]=-w[1];
}
}
@@ -0,0 +1,81 @@
/*
* IBM Accurate Mathematical Library
* Written by International Business Machines Corp.
* Copyright (C) 2001 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/************************************************************************/
/* MODULE_NAME: dosincos.h */
/* */
/* */
/* common data and variables definition for BIG or LITTLE ENDIAN */
/************************************************************************/
#ifndef DOSINCOS_H
#define DOSINCOS_H
#ifdef BIG_ENDI
static const mynumber
/**/ s3 = {{0xBFC55555, 0x55555555}},/* -0.16666666666666666 */
/**/ ss3 = {{0xBC6553AA, 0xE77EE482}},/* -9.2490366677784492e-18 */
/**/ s5 = {{0x3F811111, 0x11110F15}},/* 0.008333333333332452 */
/**/ ss5 = {{0xBC21AC06, 0xDA488820}},/* -4.7899996586987931e-19 */
/**/ s7 = {{0xBF2A019F, 0x5816C78D}},/* -0.00019841261022928957 */
/**/ ss7 = {{0x3BCDCEC9, 0x6A18BF2A}},/* 1.2624077757871259e-20 */
/**/ c2 = {{0x3FE00000, 0x00000000}},/* 0.5 */
/**/ cc2 = {{0xBA282FD8, 0x00000000}},/* -1.5264073330037701e-28 */
/**/ c4 = {{0xBFA55555, 0x55555555}},/* -0.041666666666666664 */
/**/ cc4 = {{0xBC4554BC, 0x2FFF257E}},/* -2.312711276085743e-18 */
/**/ c6 = {{0x3F56C16C, 0x16C16A96}},/* 0.0013888888888888055 */
/**/ cc6 = {{0xBBD2E846, 0xE6346F14}},/* -1.6015133010194884e-20 */
/**/ c8 = {{0xBEFA019F, 0x821D5987}},/* -2.480157866754367e-05 */
/**/ cc8 = {{0x3B7AB71E, 0x72FFE5CC}},/* 3.5357416224857556e-22 */
/**/ big = {{0x42c80000, 0x00000000}}, /* 52776558133248 */
/**/ hp0 = {{0x3FF921FB, 0x54442D18}}, /* PI / 2 */
/**/ hp1 = {{0x3C91A626, 0x33145C07}}; /* 6.123233995736766e-17 */
#else
#ifdef LITTLE_ENDI
static const mynumber
/**/ s3 = {{0x55555555, 0xBFC55555}},/* -0.16666666666666666 */
/**/ ss3 = {{0xE77EE482, 0xBC6553AA}},/* -9.2490366677784492e-18 */
/**/ s5 = {{0x11110F15, 0x3F811111}},/* 0.008333333333332452 */
/**/ ss5 = {{0xDA488820, 0xBC21AC06}},/* -4.7899996586987931e-19 */
/**/ s7 = {{0x5816C78D, 0xBF2A019F}},/* -0.00019841261022928957 */
/**/ ss7 = {{0x6A18BF2A, 0x3BCDCEC9}},/* 1.2624077757871259e-20 */
/**/ c2 = {{0x00000000, 0x3FE00000}},/* 0.5 */
/**/ cc2 = {{0x00000000, 0xBA282FD8}},/* -1.5264073330037701e-28 */
/**/ c4 = {{0x55555555, 0xBFA55555}},/* -0.041666666666666664 */
/**/ cc4 = {{0x2FFF257E, 0xBC4554BC}},/* -2.312711276085743e-18 */
/**/ c6 = {{0x16C16A96, 0x3F56C16C}},/* 0.0013888888888888055 */
/**/ cc6 = {{0xE6346F14, 0xBBD2E846}},/* -1.6015133010194884e-20 */
/**/ c8 = {{0x821D5987, 0xBEFA019F}},/* -2.480157866754367e-05 */
/**/ cc8 = {{0x72FFE5CC, 0x3B7AB71E}},/* 3.5357416224857556e-22 */
/**/ big = {{0x00000000, 0x42c80000}}, /* 52776558133248 */
/**/ hp0 = {{0x54442D18, 0x3FF921FB}}, /* PI / 2 */
/**/ hp1 = {{0x33145C07, 0x3C91A626}}; /* 6.123233995736766e-17 */
#endif
#endif
#endif
@@ -0,0 +1,69 @@
/* @(#)e_acosh.c 5.1 93/09/24 */
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_acosh.c,v 1.9 1995/05/12 04:57:18 jtc Exp $";
#endif
/* __ieee754_acosh(x)
* Method :
* Based on
* acosh(x) = log [ x + sqrt(x*x-1) ]
* we have
* acosh(x) := log(x)+ln2, if x is large; else
* acosh(x) := log(2x-1/(sqrt(x*x-1)+x)) if x>2; else
* acosh(x) := log1p(t+sqrt(2.0*t+t*t)); where t=x-1.
*
* Special cases:
* acosh(x) is NaN with signal if x<1.
* acosh(NaN) is NaN without signal.
*/
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const double
#else
static double
#endif
one = 1.0,
ln2 = 6.93147180559945286227e-01; /* 0x3FE62E42, 0xFEFA39EF */
#ifdef __STDC__
double __ieee754_acosh(double x)
#else
double __ieee754_acosh(x)
double x;
#endif
{
double t;
int32_t hx;
u_int32_t lx;
EXTRACT_WORDS(hx,lx,x);
if(hx<0x3ff00000) { /* x < 1 */
return (x-x)/(x-x);
} else if(hx >=0x41b00000) { /* x > 2**28 */
if(hx >=0x7ff00000) { /* x is inf of NaN */
return x+x;
} else
return __ieee754_log(x)+ln2; /* acosh(huge)=log(2x) */
} else if(((hx-0x3ff00000)|lx)==0) {
return 0.0; /* acosh(1) = 0 */
} else if (hx > 0x40000000) { /* 2**28 > x > 2 */
t=x*x;
return __ieee754_log(2.0*x-one/(x+__ieee754_sqrt(t-one)));
} else { /* 1<x<2 */
t = x-one;
return __log1p(t+__sqrt(2.0*t+t*t));
}
}
@@ -0,0 +1,57 @@
/* e_acoshf.c -- float version of e_acosh.c.
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
*/
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_acoshf.c,v 1.5 1995/05/12 04:57:20 jtc Exp $";
#endif
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const float
#else
static float
#endif
one = 1.0,
ln2 = 6.9314718246e-01; /* 0x3f317218 */
#ifdef __STDC__
float __ieee754_acoshf(float x)
#else
float __ieee754_acoshf(x)
float x;
#endif
{
float t;
int32_t hx;
GET_FLOAT_WORD(hx,x);
if(hx<0x3f800000) { /* x < 1 */
return (x-x)/(x-x);
} else if(hx >=0x4d800000) { /* x > 2**28 */
if(hx >=0x7f800000) { /* x is inf of NaN */
return x+x;
} else
return __ieee754_logf(x)+ln2; /* acosh(huge)=log(2x) */
} else if (hx==0x3f800000) {
return 0.0; /* acosh(1) = 0 */
} else if (hx > 0x40000000) { /* 2**28 > x > 2 */
t=x*x;
return __ieee754_logf((float)2.0*x-one/(x+__ieee754_sqrtf(t-one)));
} else { /* 1<x<2 */
t = x-one;
return __log1pf(t+__sqrtf((float)2.0*t+t*t));
}
}
@@ -0,0 +1,637 @@
/*
* IBM Accurate Mathematical Library
* written by International Business Machines Corp.
* Copyright (C) 2001 Free Software Foundation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/******************************************************************/
/* MODULE_NAME:uasncs.c */
/* */
/* FUNCTIONS: uasin */
/* uacos */
/* FILES NEEDED: dla.h endian.h mpa.h mydefs.h usncs.h */
/* doasin.c sincos32.c dosincos.c mpa.c */
/* sincos.tbl asincos.tbl powtwo.tbl root.tbl */
/* */
/* Ultimate asin/acos routines. Given an IEEE double machine */
/* number x, compute the correctly rounded value of */
/* arcsin(x)or arccos(x) according to the function called. */
/* Assumption: Machine arithmetic operations are performed in */
/* round to nearest mode of IEEE 754 standard. */
/* */
/******************************************************************/
#include "endian.h"
#include "mydefs.h"
#include "asincos.tbl"
#include "root.tbl"
#include "powtwo.tbl"
#include "MathLib.h"
#include "uasncs.h"
#include "math_private.h"
void __doasin(double x, double dx, double w[]);
void __dubsin(double x, double dx, double v[]);
void __dubcos(double x, double dx, double v[]);
void __docos(double x, double dx, double v[]);
double __sin32(double x, double res, double res1);
double __cos32(double x, double res, double res1);
/***************************************************************************/
/* An ultimate asin routine. Given an IEEE double machine number x */
/* it computes the correctly rounded (to nearest) value of arcsin(x) */
/***************************************************************************/
double __ieee754_asin(double x){
double x1,x2,xx,s1,s2,res1,p,t,res,r,cor,cc,y,c,z,w[2];
mynumber u,v;
int4 k,m,n;
#if 0
int4 nn;
#endif
u.x = x;
m = u.i[HIGH_HALF];
k = 0x7fffffff&m; /* no sign */
if (k < 0x3e500000) return x; /* for x->0 => sin(x)=x */
/*----------------------2^-26 <= |x| < 2^ -3 -----------------*/
else
if (k < 0x3fc00000) {
x2 = x*x;
t = (((((f6*x2 + f5)*x2 + f4)*x2 + f3)*x2 + f2)*x2 + f1)*(x2*x);
res = x+t; /* res=arcsin(x) according to Taylor series */
cor = (x-res)+t;
if (res == res+1.025*cor) return res;
else {
x1 = x+big;
xx = x*x;
x1 -= big;
x2 = x - x1;
p = x1*x1*x1;
s1 = a1.x*p;
s2 = ((((((c7*xx + c6)*xx + c5)*xx + c4)*xx + c3)*xx + c2)*xx*xx*x +
((a1.x+a2.x)*x2*x2+ 0.5*x1*x)*x2) + a2.x*p;
res1 = x+s1;
s2 = ((x-res1)+s1)+s2;
res = res1+s2;
cor = (res1-res)+s2;
if (res == res+1.00014*cor) return res;
else {
__doasin(x,0,w);
if (w[0]==(w[0]+1.00000001*w[1])) return w[0];
else {
y=ABS(x);
res=ABS(w[0]);
res1=ABS(w[0]+1.1*w[1]);
return (m>0)?__sin32(y,res,res1):-__sin32(y,res,res1);
}
}
}
}
/*---------------------0.125 <= |x| < 0.5 -----------------------------*/
else if (k < 0x3fe00000) {
if (k<0x3fd00000) n = 11*((k&0x000fffff)>>15);
else n = 11*((k&0x000fffff)>>14)+352;
if (m>0) xx = x - asncs.x[n];
else xx = -x - asncs.x[n];
t = asncs.x[n+1]*xx;
p=xx*xx*(asncs.x[n+2]+xx*(asncs.x[n+3]+xx*(asncs.x[n+4]+xx*(asncs.x[n+5]
+xx*asncs.x[n+6]))))+asncs.x[n+7];
t+=p;
res =asncs.x[n+8] +t;
cor = (asncs.x[n+8]-res)+t;
if (res == res+1.05*cor) return (m>0)?res:-res;
else {
r=asncs.x[n+8]+xx*asncs.x[n+9];
t=((asncs.x[n+8]-r)+xx*asncs.x[n+9])+(p+xx*asncs.x[n+10]);
res = r+t;
cor = (r-res)+t;
if (res == res+1.0005*cor) return (m>0)?res:-res;
else {
res1=res+1.1*cor;
z=0.5*(res1-res);
__dubsin(res,z,w);
z=(w[0]-ABS(x))+w[1];
if (z>1.0e-27) return (m>0)?min(res,res1):-min(res,res1);
else if (z<-1.0e-27) return (m>0)?max(res,res1):-max(res,res1);
else {
y=ABS(x);
return (m>0)?__sin32(y,res,res1):-__sin32(y,res,res1);
}
}
}
} /* else if (k < 0x3fe00000) */
/*-------------------- 0.5 <= |x| < 0.75 -----------------------------*/
else
if (k < 0x3fe80000) {
n = 1056+((k&0x000fe000)>>11)*3;
if (m>0) xx = x - asncs.x[n];
else xx = -x - asncs.x[n];
t = asncs.x[n+1]*xx;
p=xx*xx*(asncs.x[n+2]+xx*(asncs.x[n+3]+xx*(asncs.x[n+4]+xx*(asncs.x[n+5]
+xx*(asncs.x[n+6]+xx*asncs.x[n+7])))))+asncs.x[n+8];
t+=p;
res =asncs.x[n+9] +t;
cor = (asncs.x[n+9]-res)+t;
if (res == res+1.01*cor) return (m>0)?res:-res;
else {
r=asncs.x[n+9]+xx*asncs.x[n+10];
t=((asncs.x[n+9]-r)+xx*asncs.x[n+10])+(p+xx*asncs.x[n+11]);
res = r+t;
cor = (r-res)+t;
if (res == res+1.0005*cor) return (m>0)?res:-res;
else {
res1=res+1.1*cor;
z=0.5*(res1-res);
__dubsin(res,z,w);
z=(w[0]-ABS(x))+w[1];
if (z>1.0e-27) return (m>0)?min(res,res1):-min(res,res1);
else if (z<-1.0e-27) return (m>0)?max(res,res1):-max(res,res1);
else {
y=ABS(x);
return (m>0)?__sin32(y,res,res1):-__sin32(y,res,res1);
}
}
}
} /* else if (k < 0x3fe80000) */
/*--------------------- 0.75 <= |x|< 0.921875 ----------------------*/
else
if (k < 0x3fed8000) {
n = 992+((k&0x000fe000)>>13)*13;
if (m>0) xx = x - asncs.x[n];
else xx = -x - asncs.x[n];
t = asncs.x[n+1]*xx;
p=xx*xx*(asncs.x[n+2]+xx*(asncs.x[n+3]+xx*(asncs.x[n+4]+xx*(asncs.x[n+5]
+xx*(asncs.x[n+6]+xx*(asncs.x[n+7]+xx*asncs.x[n+8]))))))+asncs.x[n+9];
t+=p;
res =asncs.x[n+10] +t;
cor = (asncs.x[n+10]-res)+t;
if (res == res+1.01*cor) return (m>0)?res:-res;
else {
r=asncs.x[n+10]+xx*asncs.x[n+11];
t=((asncs.x[n+10]-r)+xx*asncs.x[n+11])+(p+xx*asncs.x[n+12]);
res = r+t;
cor = (r-res)+t;
if (res == res+1.0008*cor) return (m>0)?res:-res;
else {
res1=res+1.1*cor;
z=0.5*(res1-res);
y=hp0.x-res;
z=((hp0.x-y)-res)+(hp1.x-z);
__dubcos(y,z,w);
z=(w[0]-ABS(x))+w[1];
if (z>1.0e-27) return (m>0)?min(res,res1):-min(res,res1);
else if (z<-1.0e-27) return (m>0)?max(res,res1):-max(res,res1);
else {
y=ABS(x);
return (m>0)?__sin32(y,res,res1):-__sin32(y,res,res1);
}
}
}
} /* else if (k < 0x3fed8000) */
/*-------------------0.921875 <= |x| < 0.953125 ------------------------*/
else
if (k < 0x3fee8000) {
n = 884+((k&0x000fe000)>>13)*14;
if (m>0) xx = x - asncs.x[n];
else xx = -x - asncs.x[n];
t = asncs.x[n+1]*xx;
p=xx*xx*(asncs.x[n+2]+xx*(asncs.x[n+3]+xx*(asncs.x[n+4]+
xx*(asncs.x[n+5]+xx*(asncs.x[n+6]
+xx*(asncs.x[n+7]+xx*(asncs.x[n+8]+
xx*asncs.x[n+9])))))))+asncs.x[n+10];
t+=p;
res =asncs.x[n+11] +t;
cor = (asncs.x[n+11]-res)+t;
if (res == res+1.01*cor) return (m>0)?res:-res;
else {
r=asncs.x[n+11]+xx*asncs.x[n+12];
t=((asncs.x[n+11]-r)+xx*asncs.x[n+12])+(p+xx*asncs.x[n+13]);
res = r+t;
cor = (r-res)+t;
if (res == res+1.0007*cor) return (m>0)?res:-res;
else {
res1=res+1.1*cor;
z=0.5*(res1-res);
y=(hp0.x-res)-z;
z=y+hp1.x;
y=(y-z)+hp1.x;
__dubcos(z,y,w);
z=(w[0]-ABS(x))+w[1];
if (z>1.0e-27) return (m>0)?min(res,res1):-min(res,res1);
else if (z<-1.0e-27) return (m>0)?max(res,res1):-max(res,res1);
else {
y=ABS(x);
return (m>0)?__sin32(y,res,res1):-__sin32(y,res,res1);
}
}
}
} /* else if (k < 0x3fee8000) */
/*--------------------0.953125 <= |x| < 0.96875 ------------------------*/
else
if (k < 0x3fef0000) {
n = 768+((k&0x000fe000)>>13)*15;
if (m>0) xx = x - asncs.x[n];
else xx = -x - asncs.x[n];
t = asncs.x[n+1]*xx;
p=xx*xx*(asncs.x[n+2]+xx*(asncs.x[n+3]+xx*(asncs.x[n+4]+
xx*(asncs.x[n+5]+xx*(asncs.x[n+6]
+xx*(asncs.x[n+7]+xx*(asncs.x[n+8]+
xx*(asncs.x[n+9]+xx*asncs.x[n+10]))))))))+asncs.x[n+11];
t+=p;
res =asncs.x[n+12] +t;
cor = (asncs.x[n+12]-res)+t;
if (res == res+1.01*cor) return (m>0)?res:-res;
else {
r=asncs.x[n+12]+xx*asncs.x[n+13];
t=((asncs.x[n+12]-r)+xx*asncs.x[n+13])+(p+xx*asncs.x[n+14]);
res = r+t;
cor = (r-res)+t;
if (res == res+1.0007*cor) return (m>0)?res:-res;
else {
res1=res+1.1*cor;
z=0.5*(res1-res);
y=(hp0.x-res)-z;
z=y+hp1.x;
y=(y-z)+hp1.x;
__dubcos(z,y,w);
z=(w[0]-ABS(x))+w[1];
if (z>1.0e-27) return (m>0)?min(res,res1):-min(res,res1);
else if (z<-1.0e-27) return (m>0)?max(res,res1):-max(res,res1);
else {
y=ABS(x);
return (m>0)?__sin32(y,res,res1):-__sin32(y,res,res1);
}
}
}
} /* else if (k < 0x3fef0000) */
/*--------------------0.96875 <= |x| < 1 --------------------------------*/
else
if (k<0x3ff00000) {
z = 0.5*((m>0)?(1.0-x):(1.0+x));
v.x=z;
k=v.i[HIGH_HALF];
t=inroot[(k&0x001fffff)>>14]*powtwo[511-(k>>21)];
r=1.0-t*t*z;
t = t*(rt0+r*(rt1+r*(rt2+r*rt3)));
c=t*z;
t=c*(1.5-0.5*t*c);
y=(c+t24)-t24;
cc = (z-y*y)/(t+y);
p=(((((f6*z+f5)*z+f4)*z+f3)*z+f2)*z+f1)*z;
cor = (hp1.x - 2.0*cc)-2.0*(y+cc)*p;
res1 = hp0.x - 2.0*y;
res =res1 + cor;
if (res == res+1.003*((res1-res)+cor)) return (m>0)?res:-res;
else {
c=y+cc;
cc=(y-c)+cc;
__doasin(c,cc,w);
res1=hp0.x-2.0*w[0];
cor=((hp0.x-res1)-2.0*w[0])+(hp1.x-2.0*w[1]);
res = res1+cor;
cor = (res1-res)+cor;
if (res==(res+1.0000001*cor)) return (m>0)?res:-res;
else {
y=ABS(x);
res1=res+1.1*cor;
return (m>0)?__sin32(y,res,res1):-__sin32(y,res,res1);
}
}
} /* else if (k < 0x3ff00000) */
/*---------------------------- |x|>=1 -------------------------------*/
else if (k==0x3ff00000 && u.i[LOW_HALF]==0) return (m>0)?hp0.x:-hp0.x;
else
if (k>0x7ff00000 || (k == 0x7ff00000 && u.i[LOW_HALF] != 0)) return x;
else {
u.i[HIGH_HALF]=0x7ff00000;
v.i[HIGH_HALF]=0x7ff00000;
u.i[LOW_HALF]=0;
v.i[LOW_HALF]=0;
return u.x/v.x; /* NaN */
}
}
/*******************************************************************/
/* */
/* End of arcsine, below is arccosine */
/* */
/*******************************************************************/
double __ieee754_acos(double x)
{
double x1,x2,xx,s1,s2,res1,p,t,res,r,cor,cc,y,c,z,w[2],eps;
#if 0
double fc;
#endif
mynumber u,v;
int4 k,m,n;
#if 0
int4 nn;
#endif
u.x = x;
m = u.i[HIGH_HALF];
k = 0x7fffffff&m;
/*------------------- |x|<2.77556*10^-17 ----------------------*/
if (k < 0x3c880000) return hp0.x;
/*----------------- 2.77556*10^-17 <= |x| < 2^-3 --------------*/
else
if (k < 0x3fc00000) {
x2 = x*x;
t = (((((f6*x2 + f5)*x2 + f4)*x2 + f3)*x2 + f2)*x2 + f1)*(x2*x);
r=hp0.x-x;
cor=(((hp0.x-r)-x)+hp1.x)-t;
res = r+cor;
cor = (r-res)+cor;
if (res == res+1.004*cor) return res;
else {
x1 = x+big;
xx = x*x;
x1 -= big;
x2 = x - x1;
p = x1*x1*x1;
s1 = a1.x*p;
s2 = ((((((c7*xx + c6)*xx + c5)*xx + c4)*xx + c3)*xx + c2)*xx*xx*x +
((a1.x+a2.x)*x2*x2+ 0.5*x1*x)*x2) + a2.x*p;
res1 = x+s1;
s2 = ((x-res1)+s1)+s2;
r=hp0.x-res1;
cor=(((hp0.x-r)-res1)+hp1.x)-s2;
res = r+cor;
cor = (r-res)+cor;
if (res == res+1.00004*cor) return res;
else {
__doasin(x,0,w);
r=hp0.x-w[0];
cor=((hp0.x-r)-w[0])+(hp1.x-w[1]);
res=r+cor;
cor=(r-res)+cor;
if (res ==(res +1.00000001*cor)) return res;
else {
res1=res+1.1*cor;
return __cos32(x,res,res1);
}
}
}
} /* else if (k < 0x3fc00000) */
/*---------------------- 0.125 <= |x| < 0.5 --------------------*/
else
if (k < 0x3fe00000) {
if (k<0x3fd00000) n = 11*((k&0x000fffff)>>15);
else n = 11*((k&0x000fffff)>>14)+352;
if (m>0) xx = x - asncs.x[n];
else xx = -x - asncs.x[n];
t = asncs.x[n+1]*xx;
p=xx*xx*(asncs.x[n+2]+xx*(asncs.x[n+3]+xx*(asncs.x[n+4]+
xx*(asncs.x[n+5]+xx*asncs.x[n+6]))))+asncs.x[n+7];
t+=p;
y = (m>0)?(hp0.x-asncs.x[n+8]):(hp0.x+asncs.x[n+8]);
t = (m>0)?(hp1.x-t):(hp1.x+t);
res = y+t;
if (res == res+1.02*((y-res)+t)) return res;
else {
r=asncs.x[n+8]+xx*asncs.x[n+9];
t=((asncs.x[n+8]-r)+xx*asncs.x[n+9])+(p+xx*asncs.x[n+10]);
if (m>0)
{p = hp0.x-r; t = (((hp0.x-p)-r)-t)+hp1.x; }
else
{p = hp0.x+r; t = ((hp0.x-p)+r)+(hp1.x+t); }
res = p+t;
cor = (p-res)+t;
if (res == (res+1.0002*cor)) return res;
else {
res1=res+1.1*cor;
z=0.5*(res1-res);
__docos(res,z,w);
z=(w[0]-x)+w[1];
if (z>1.0e-27) return max(res,res1);
else if (z<-1.0e-27) return min(res,res1);
else return __cos32(x,res,res1);
}
}
} /* else if (k < 0x3fe00000) */
/*--------------------------- 0.5 <= |x| < 0.75 ---------------------*/
else
if (k < 0x3fe80000) {
n = 1056+((k&0x000fe000)>>11)*3;
if (m>0) {xx = x - asncs.x[n]; eps=1.04; }
else {xx = -x - asncs.x[n]; eps=1.02; }
t = asncs.x[n+1]*xx;
p=xx*xx*(asncs.x[n+2]+xx*(asncs.x[n+3]+xx*(asncs.x[n+4]+
xx*(asncs.x[n+5]+xx*(asncs.x[n+6]+
xx*asncs.x[n+7])))))+asncs.x[n+8];
t+=p;
y = (m>0)?(hp0.x-asncs.x[n+9]):(hp0.x+asncs.x[n+9]);
t = (m>0)?(hp1.x-t):(hp1.x+t);
res = y+t;
if (res == res+eps*((y-res)+t)) return res;
else {
r=asncs.x[n+9]+xx*asncs.x[n+10];
t=((asncs.x[n+9]-r)+xx*asncs.x[n+10])+(p+xx*asncs.x[n+11]);
if (m>0) {p = hp0.x-r; t = (((hp0.x-p)-r)-t)+hp1.x; eps=1.0004; }
else {p = hp0.x+r; t = ((hp0.x-p)+r)+(hp1.x+t); eps=1.0002; }
res = p+t;
cor = (p-res)+t;
if (res == (res+eps*cor)) return res;
else {
res1=res+1.1*cor;
z=0.5*(res1-res);
__docos(res,z,w);
z=(w[0]-x)+w[1];
if (z>1.0e-27) return max(res,res1);
else if (z<-1.0e-27) return min(res,res1);
else return __cos32(x,res,res1);
}
}
} /* else if (k < 0x3fe80000) */
/*------------------------- 0.75 <= |x| < 0.921875 -------------*/
else
if (k < 0x3fed8000) {
n = 992+((k&0x000fe000)>>13)*13;
if (m>0) {xx = x - asncs.x[n]; eps = 1.04; }
else {xx = -x - asncs.x[n]; eps = 1.01; }
t = asncs.x[n+1]*xx;
p=xx*xx*(asncs.x[n+2]+xx*(asncs.x[n+3]+xx*(asncs.x[n+4]+
xx*(asncs.x[n+5]+xx*(asncs.x[n+6]+xx*(asncs.x[n+7]+
xx*asncs.x[n+8]))))))+asncs.x[n+9];
t+=p;
y = (m>0)?(hp0.x-asncs.x[n+10]):(hp0.x+asncs.x[n+10]);
t = (m>0)?(hp1.x-t):(hp1.x+t);
res = y+t;
if (res == res+eps*((y-res)+t)) return res;
else {
r=asncs.x[n+10]+xx*asncs.x[n+11];
t=((asncs.x[n+10]-r)+xx*asncs.x[n+11])+(p+xx*asncs.x[n+12]);
if (m>0) {p = hp0.x-r; t = (((hp0.x-p)-r)-t)+hp1.x; eps=1.0032; }
else {p = hp0.x+r; t = ((hp0.x-p)+r)+(hp1.x+t); eps=1.0008; }
res = p+t;
cor = (p-res)+t;
if (res == (res+eps*cor)) return res;
else {
res1=res+1.1*cor;
z=0.5*(res1-res);
__docos(res,z,w);
z=(w[0]-x)+w[1];
if (z>1.0e-27) return max(res,res1);
else if (z<-1.0e-27) return min(res,res1);
else return __cos32(x,res,res1);
}
}
} /* else if (k < 0x3fed8000) */
/*-------------------0.921875 <= |x| < 0.953125 ------------------*/
else
if (k < 0x3fee8000) {
n = 884+((k&0x000fe000)>>13)*14;
if (m>0) {xx = x - asncs.x[n]; eps=1.04; }
else {xx = -x - asncs.x[n]; eps =1.005; }
t = asncs.x[n+1]*xx;
p=xx*xx*(asncs.x[n+2]+xx*(asncs.x[n+3]+xx*(asncs.x[n+4]+
xx*(asncs.x[n+5]+xx*(asncs.x[n+6]
+xx*(asncs.x[n+7]+xx*(asncs.x[n+8]+
xx*asncs.x[n+9])))))))+asncs.x[n+10];
t+=p;
y = (m>0)?(hp0.x-asncs.x[n+11]):(hp0.x+asncs.x[n+11]);
t = (m>0)?(hp1.x-t):(hp1.x+t);
res = y+t;
if (res == res+eps*((y-res)+t)) return res;
else {
r=asncs.x[n+11]+xx*asncs.x[n+12];
t=((asncs.x[n+11]-r)+xx*asncs.x[n+12])+(p+xx*asncs.x[n+13]);
if (m>0) {p = hp0.x-r; t = (((hp0.x-p)-r)-t)+hp1.x; eps=1.0030; }
else {p = hp0.x+r; t = ((hp0.x-p)+r)+(hp1.x+t); eps=1.0005; }
res = p+t;
cor = (p-res)+t;
if (res == (res+eps*cor)) return res;
else {
res1=res+1.1*cor;
z=0.5*(res1-res);
__docos(res,z,w);
z=(w[0]-x)+w[1];
if (z>1.0e-27) return max(res,res1);
else if (z<-1.0e-27) return min(res,res1);
else return __cos32(x,res,res1);
}
}
} /* else if (k < 0x3fee8000) */
/*--------------------0.953125 <= |x| < 0.96875 ----------------*/
else
if (k < 0x3fef0000) {
n = 768+((k&0x000fe000)>>13)*15;
if (m>0) {xx = x - asncs.x[n]; eps=1.04; }
else {xx = -x - asncs.x[n]; eps=1.005;}
t = asncs.x[n+1]*xx;
p=xx*xx*(asncs.x[n+2]+xx*(asncs.x[n+3]+xx*(asncs.x[n+4]+
xx*(asncs.x[n+5]+xx*(asncs.x[n+6]
+xx*(asncs.x[n+7]+xx*(asncs.x[n+8]+xx*(asncs.x[n+9]+
xx*asncs.x[n+10]))))))))+asncs.x[n+11];
t+=p;
y = (m>0)?(hp0.x-asncs.x[n+12]):(hp0.x+asncs.x[n+12]);
t = (m>0)?(hp1.x-t):(hp1.x+t);
res = y+t;
if (res == res+eps*((y-res)+t)) return res;
else {
r=asncs.x[n+12]+xx*asncs.x[n+13];
t=((asncs.x[n+12]-r)+xx*asncs.x[n+13])+(p+xx*asncs.x[n+14]);
if (m>0) {p = hp0.x-r; t = (((hp0.x-p)-r)-t)+hp1.x; eps=1.0030; }
else {p = hp0.x+r; t = ((hp0.x-p)+r)+(hp1.x+t); eps=1.0005; }
res = p+t;
cor = (p-res)+t;
if (res == (res+eps*cor)) return res;
else {
res1=res+1.1*cor;
z=0.5*(res1-res);
__docos(res,z,w);
z=(w[0]-x)+w[1];
if (z>1.0e-27) return max(res,res1);
else if (z<-1.0e-27) return min(res,res1);
else return __cos32(x,res,res1);
}
}
} /* else if (k < 0x3fef0000) */
/*-----------------0.96875 <= |x| < 1 ---------------------------*/
else
if (k<0x3ff00000) {
z = 0.5*((m>0)?(1.0-x):(1.0+x));
v.x=z;
k=v.i[HIGH_HALF];
t=inroot[(k&0x001fffff)>>14]*powtwo[511-(k>>21)];
r=1.0-t*t*z;
t = t*(rt0+r*(rt1+r*(rt2+r*rt3)));
c=t*z;
t=c*(1.5-0.5*t*c);
y = (t27*c+c)-t27*c;
cc = (z-y*y)/(t+y);
p=(((((f6*z+f5)*z+f4)*z+f3)*z+f2)*z+f1)*z;
if (m<0) {
cor = (hp1.x - cc)-(y+cc)*p;
res1 = hp0.x - y;
res =res1 + cor;
if (res == res+1.002*((res1-res)+cor)) return (res+res);
else {
c=y+cc;
cc=(y-c)+cc;
__doasin(c,cc,w);
res1=hp0.x-w[0];
cor=((hp0.x-res1)-w[0])+(hp1.x-w[1]);
res = res1+cor;
cor = (res1-res)+cor;
if (res==(res+1.000001*cor)) return (res+res);
else {
res=res+res;
res1=res+1.2*cor;
return __cos32(x,res,res1);
}
}
}
else {
cor = cc+p*(y+cc);
res = y + cor;
if (res == res+1.03*((y-res)+cor)) return (res+res);
else {
c=y+cc;
cc=(y-c)+cc;
__doasin(c,cc,w);
res = w[0];
cor=w[1];
if (res==(res+1.000001*cor)) return (res+res);
else {
res=res+res;
res1=res+1.2*cor;
return __cos32(x,res,res1);
}
}
}
} /* else if (k < 0x3ff00000) */
/*---------------------------- |x|>=1 -----------------------*/
else
if (k==0x3ff00000 && u.i[LOW_HALF]==0) return (m>0)?0:2.0*hp0.x;
else
if (k>0x7ff00000 || (k == 0x7ff00000 && u.i[LOW_HALF] != 0)) return x;
else {
u.i[HIGH_HALF]=0x7ff00000;
v.i[HIGH_HALF]=0x7ff00000;
u.i[LOW_HALF]=0;
v.i[LOW_HALF]=0;
return u.x/v.x;
}
}
@@ -0,0 +1,110 @@
/* e_asinf.c -- float version of e_asin.c.
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
*/
/*
* ====================================================
* 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.
* ====================================================
*/
/*
Modifications for single precision expansion are
Copyright (C) 2001 Stephen L. Moshier <[email protected]>
and are incorporated herein by permission of the author. The author
reserves the right to distribute this material elsewhere under different
copying permissions. These modifications are distributed here under
the following terms:
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_asinf.c,v 1.5 1995/05/12 04:57:25 jtc Exp $";
#endif
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const float
#else
static float
#endif
one = 1.0000000000e+00, /* 0x3F800000 */
huge = 1.000e+30,
pio2_hi = 1.57079637050628662109375f,
pio2_lo = -4.37113900018624283e-8f,
pio4_hi = 0.785398185253143310546875f,
/* asin x = x + x^3 p(x^2)
-0.5 <= x <= 0.5;
Peak relative error 4.8e-9 */
p0 = 1.666675248e-1f,
p1 = 7.495297643e-2f,
p2 = 4.547037598e-2f,
p3 = 2.417951451e-2f,
p4 = 4.216630880e-2f;
#ifdef __STDC__
float __ieee754_asinf(float x)
#else
float __ieee754_asinf(x)
float x;
#endif
{
float t,w,p,q,c,r,s;
int32_t hx,ix;
GET_FLOAT_WORD(hx,x);
ix = hx&0x7fffffff;
if(ix==0x3f800000) {
/* asin(1)=+-pi/2 with inexact */
return x*pio2_hi+x*pio2_lo;
} else if(ix> 0x3f800000) { /* |x|>= 1 */
return (x-x)/(x-x); /* asin(|x|>1) is NaN */
} else if (ix<0x3f000000) { /* |x|<0.5 */
if(ix<0x32000000) { /* if |x| < 2**-27 */
if(huge+x>one) return x;/* return x with inexact if x!=0*/
} else {
t = x*x;
w = t * (p0 + t * (p1 + t * (p2 + t * (p3 + t * p4))));
return x+x*w;
}
}
/* 1> |x|>= 0.5 */
w = one-fabsf(x);
t = w*0.5f;
p = t * (p0 + t * (p1 + t * (p2 + t * (p3 + t * p4))));
s = __ieee754_sqrtf(t);
if(ix>=0x3F79999A) { /* if |x| > 0.975 */
t = pio2_hi-(2.0f*(s+s*p)-pio2_lo);
} else {
int32_t iw;
w = s;
GET_FLOAT_WORD(iw,w);
SET_FLOAT_WORD(w,iw&0xfffff000);
c = (t-w*w)/(s+w);
r = p;
p = 2.0f*s*r-(pio2_lo-2.0f*c);
q = pio4_hi-2.0f*w;
t = pio4_hi-(p-q);
}
if(hx>0) return t; else return -t;
}
@@ -0,0 +1,74 @@
/* @(#)e_atanh.c 5.1 93/09/24 */
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_atanh.c,v 1.8 1995/05/10 20:44:55 jtc Exp $";
#endif
/* __ieee754_atanh(x)
* Method :
* 1.Reduced x to positive by atanh(-x) = -atanh(x)
* 2.For x>=0.5
* 1 2x x
* atanh(x) = --- * log(1 + -------) = 0.5 * log1p(2 * --------)
* 2 1 - x 1 - x
*
* For x<0.5
* atanh(x) = 0.5*log1p(2x+2x*x/(1-x))
*
* Special cases:
* atanh(x) is NaN if |x| > 1 with signal;
* atanh(NaN) is that NaN with no signal;
* atanh(+-1) is +-INF with signal.
*
*/
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const double one = 1.0, huge = 1e300;
#else
static double one = 1.0, huge = 1e300;
#endif
#ifdef __STDC__
static const double zero = 0.0;
#else
static double zero = 0.0;
#endif
#ifdef __STDC__
double __ieee754_atanh(double x)
#else
double __ieee754_atanh(x)
double x;
#endif
{
double t;
int32_t hx,ix;
u_int32_t lx;
EXTRACT_WORDS(hx,lx,x);
ix = hx&0x7fffffff;
if ((ix|((lx|(-lx))>>31))>0x3ff00000) /* |x|>1 */
return (x-x)/(x-x);
if(ix==0x3ff00000)
return x/zero;
if(ix<0x3e300000&&(huge+x)>zero) return x; /* x<2**-28 */
SET_HIGH_WORD(x,ix);
if(ix<0x3fe00000) { /* x < 0.5 */
t = x+x;
t = 0.5*__log1p(t+t*x/(one-x));
} else
t = 0.5*__log1p((x+x)/(one-x));
if(hx>=0) return t; else return -t;
}
@@ -0,0 +1,58 @@
/* e_atanhf.c -- float version of e_atanh.c.
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
*/
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_atanhf.c,v 1.4 1995/05/10 20:44:56 jtc Exp $";
#endif
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const float one = 1.0, huge = 1e30;
#else
static float one = 1.0, huge = 1e30;
#endif
#ifdef __STDC__
static const float zero = 0.0;
#else
static float zero = 0.0;
#endif
#ifdef __STDC__
float __ieee754_atanhf(float x)
#else
float __ieee754_atanhf(x)
float x;
#endif
{
float t;
int32_t hx,ix;
GET_FLOAT_WORD(hx,x);
ix = hx&0x7fffffff;
if (ix>0x3f800000) /* |x|>1 */
return (x-x)/(x-x);
if(ix==0x3f800000)
return x/zero;
if(ix<0x31800000&&(huge+x)>zero) return x; /* x<2**-28 */
SET_FLOAT_WORD(x,ix);
if(ix<0x3f000000) { /* x < 0.5 */
t = x+x;
t = (float)0.5*__log1pf(t+t*x/(one-x));
} else
t = (float)0.5*__log1pf((x+x)/(one-x));
if(hx>=0) return t; else return -t;
}
@@ -0,0 +1,92 @@
/* @(#)e_cosh.c 5.1 93/09/24 */
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_cosh.c,v 1.7 1995/05/10 20:44:58 jtc Exp $";
#endif
/* __ieee754_cosh(x)
* Method :
* mathematically cosh(x) if defined to be (exp(x)+exp(-x))/2
* 1. Replace x by |x| (cosh(x) = cosh(-x)).
* 2.
* [ exp(x) - 1 ]^2
* 0 <= x <= ln2/2 : cosh(x) := 1 + -------------------
* 2*exp(x)
*
* exp(x) + 1/exp(x)
* ln2/2 <= x <= 22 : cosh(x) := -------------------
* 2
* 22 <= x <= lnovft : cosh(x) := exp(x)/2
* lnovft <= x <= ln2ovft: cosh(x) := exp(x/2)/2 * exp(x/2)
* ln2ovft < x : cosh(x) := huge*huge (overflow)
*
* Special cases:
* cosh(x) is |x| if x is +INF, -INF, or NaN.
* only cosh(0)=1 is exact for finite x.
*/
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const double one = 1.0, half=0.5, huge = 1.0e300;
#else
static double one = 1.0, half=0.5, huge = 1.0e300;
#endif
#ifdef __STDC__
double __ieee754_cosh(double x)
#else
double __ieee754_cosh(x)
double x;
#endif
{
double t,w;
int32_t ix;
u_int32_t lx;
/* High word of |x|. */
GET_HIGH_WORD(ix,x);
ix &= 0x7fffffff;
/* x is INF or NaN */
if(ix>=0x7ff00000) return x*x;
/* |x| in [0,0.5*ln2], return 1+expm1(|x|)^2/(2*exp(|x|)) */
if(ix<0x3fd62e43) {
t = __expm1(fabs(x));
w = one+t;
if (ix<0x3c800000) return w; /* cosh(tiny) = 1 */
return one+(t*t)/(w+w);
}
/* |x| in [0.5*ln2,22], return (exp(|x|)+1/exp(|x|)/2; */
if (ix < 0x40360000) {
t = __ieee754_exp(fabs(x));
return half*t+half/t;
}
/* |x| in [22, log(maxdouble)] return half*exp(|x|) */
if (ix < 0x40862e42) return half*__ieee754_exp(fabs(x));
/* |x| in [log(maxdouble), overflowthresold] */
GET_LOW_WORD(lx,x);
if (ix<0x408633ce || ((ix==0x408633ce)&&(lx<=(u_int32_t)0x8fb9f87d))) {
w = __ieee754_exp(half*fabs(x));
t = half*w;
return t*w;
}
/* |x| > overflowthresold, cosh(x) overflow */
return huge*huge;
}
@@ -0,0 +1,72 @@
/* e_coshf.c -- float version of e_cosh.c.
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
*/
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_coshf.c,v 1.6 1996/04/08 15:43:41 phil Exp $";
#endif
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const float huge = 1.0e30;
static const float one = 1.0, half=0.5;
#else
static float one = 1.0, half=0.5, huge = 1.0e30;
#endif
#ifdef __STDC__
float __ieee754_coshf(float x)
#else
float __ieee754_coshf(x)
float x;
#endif
{
float t,w;
int32_t ix;
GET_FLOAT_WORD(ix,x);
ix &= 0x7fffffff;
/* x is INF or NaN */
if(ix>=0x7f800000) return x*x;
/* |x| in [0,0.5*ln2], return 1+expm1(|x|)^2/(2*exp(|x|)) */
if(ix<0x3eb17218) {
t = __expm1f(fabsf(x));
w = one+t;
if (ix<0x24000000) return w; /* cosh(tiny) = 1 */
return one+(t*t)/(w+w);
}
/* |x| in [0.5*ln2,22], return (exp(|x|)+1/exp(|x|)/2; */
if (ix < 0x41b00000) {
t = __ieee754_expf(fabsf(x));
return half*t+half/t;
}
/* |x| in [22, log(maxdouble)] return half*exp(|x|) */
if (ix < 0x42b17180) return half*__ieee754_expf(fabsf(x));
/* |x| in [log(maxdouble), overflowthresold] */
if (ix<=0x42b2d4fc) {
w = __ieee754_expf(half*fabsf(x));
t = half*w;
return t*w;
}
/* |x| > overflowthresold, cosh(x) overflow */
return huge*huge;
}
@@ -0,0 +1,252 @@
/*
* IBM Accurate Mathematical Library
* written by International Business Machines Corp.
* Copyright (C) 2001 Free Software Foundation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/***************************************************************************/
/* MODULE_NAME:uexp.c */
/* */
/* FUNCTION:uexp */
/* exp1 */
/* */
/* FILES NEEDED:dla.h endian.h mpa.h mydefs.h uexp.h */
/* mpa.c mpexp.x slowexp.c */
/* */
/* An ultimate exp routine. Given an IEEE double machine number x */
/* it computes the correctly rounded (to nearest) value of e^x */
/* Assumption: Machine arithmetic operations are performed in */
/* round to nearest mode of IEEE 754 standard. */
/* */
/***************************************************************************/
#include "endian.h"
#include "uexp.h"
#include "mydefs.h"
#include "MathLib.h"
#include "uexp.tbl"
#include "math_private.h"
double __slowexp(double);
/***************************************************************************/
/* An ultimate exp routine. Given an IEEE double machine number x */
/* it computes the correctly rounded (to nearest) value of e^x */
/***************************************************************************/
double __ieee754_exp(double x) {
double bexp, t, eps, del, base, y, al, bet, res, rem, cor;
mynumber junk1, junk2, binexp = {{0,0}};
#if 0
int4 k;
#endif
int4 i,j,m,n,ex;
junk1.x = x;
m = junk1.i[HIGH_HALF];
n = m&hugeint;
if (n > smallint && n < bigint) {
y = x*log2e.x + three51.x;
bexp = y - three51.x; /* multiply the result by 2**bexp */
junk1.x = y;
eps = bexp*ln_two2.x; /* x = bexp*ln(2) + t - eps */
t = x - bexp*ln_two1.x;
y = t + three33.x;
base = y - three33.x; /* t rounded to a multiple of 2**-18 */
junk2.x = y;
del = (t - base) - eps; /* x = bexp*ln(2) + base + del */
eps = del + del*del*(p3.x*del + p2.x);
binexp.i[HIGH_HALF] =(junk1.i[LOW_HALF]+1023)<<20;
i = ((junk2.i[LOW_HALF]>>8)&0xfffffffe)+356;
j = (junk2.i[LOW_HALF]&511)<<1;
al = coar.x[i]*fine.x[j];
bet =(coar.x[i]*fine.x[j+1] + coar.x[i+1]*fine.x[j]) + coar.x[i+1]*fine.x[j+1];
rem=(bet + bet*eps)+al*eps;
res = al + rem;
cor = (al - res) + rem;
if (res == (res+cor*err_0)) return res*binexp.x;
else return __slowexp(x); /*if error is over bound */
}
if (n <= smallint) return 1.0;
if (n >= badint) {
if (n > infint) return(zero/zero); /* x is NaN, return invalid */
if (n < infint) return ( (x>0) ? (hhuge*hhuge) : (tiny*tiny) );
/* x is finite, cause either overflow or underflow */
if (junk1.i[LOW_HALF] != 0) return (zero/zero); /* x is NaN */
return ((x>0)?inf.x:zero ); /* |x| = inf; return either inf or 0 */
}
y = x*log2e.x + three51.x;
bexp = y - three51.x;
junk1.x = y;
eps = bexp*ln_two2.x;
t = x - bexp*ln_two1.x;
y = t + three33.x;
base = y - three33.x;
junk2.x = y;
del = (t - base) - eps;
eps = del + del*del*(p3.x*del + p2.x);
i = ((junk2.i[LOW_HALF]>>8)&0xfffffffe)+356;
j = (junk2.i[LOW_HALF]&511)<<1;
al = coar.x[i]*fine.x[j];
bet =(coar.x[i]*fine.x[j+1] + coar.x[i+1]*fine.x[j]) + coar.x[i+1]*fine.x[j+1];
rem=(bet + bet*eps)+al*eps;
res = al + rem;
cor = (al - res) + rem;
if (m>>31) {
ex=junk1.i[LOW_HALF];
if (res < 1.0) {res+=res; cor+=cor; ex-=1;}
if (ex >=-1022) {
binexp.i[HIGH_HALF] = (1023+ex)<<20;
if (res == (res+cor*err_0)) return res*binexp.x;
else return __slowexp(x); /*if error is over bound */
}
ex = -(1022+ex);
binexp.i[HIGH_HALF] = (1023-ex)<<20;
res*=binexp.x;
cor*=binexp.x;
eps=1.0000000001+err_0*binexp.x;
t=1.0+res;
y = ((1.0-t)+res)+cor;
res=t+y;
cor = (t-res)+y;
if (res == (res + eps*cor))
{ binexp.i[HIGH_HALF] = 0x00100000;
return (res-1.0)*binexp.x;
}
else return __slowexp(x); /* if error is over bound */
}
else {
binexp.i[HIGH_HALF] =(junk1.i[LOW_HALF]+767)<<20;
if (res == (res+cor*err_0)) return res*binexp.x*t256.x;
else return __slowexp(x);
}
}
/************************************************************************/
/* Compute e^(x+xx)(Double-Length number) .The routine also receive */
/* bound of error of previous calculation .If after computing exp */
/* error bigger than allows routine return non positive number */
/*else return e^(x + xx) (always positive ) */
/************************************************************************/
double __exp1(double x, double xx, double error) {
double bexp, t, eps, del, base, y, al, bet, res, rem, cor;
mynumber junk1, junk2, binexp = {{0,0}};
#if 0
int4 k;
#endif
int4 i,j,m,n,ex;
junk1.x = x;
m = junk1.i[HIGH_HALF];
n = m&hugeint; /* no sign */
if (n > smallint && n < bigint) {
y = x*log2e.x + three51.x;
bexp = y - three51.x; /* multiply the result by 2**bexp */
junk1.x = y;
eps = bexp*ln_two2.x; /* x = bexp*ln(2) + t - eps */
t = x - bexp*ln_two1.x;
y = t + three33.x;
base = y - three33.x; /* t rounded to a multiple of 2**-18 */
junk2.x = y;
del = (t - base) + (xx-eps); /* x = bexp*ln(2) + base + del */
eps = del + del*del*(p3.x*del + p2.x);
binexp.i[HIGH_HALF] =(junk1.i[LOW_HALF]+1023)<<20;
i = ((junk2.i[LOW_HALF]>>8)&0xfffffffe)+356;
j = (junk2.i[LOW_HALF]&511)<<1;
al = coar.x[i]*fine.x[j];
bet =(coar.x[i]*fine.x[j+1] + coar.x[i+1]*fine.x[j]) + coar.x[i+1]*fine.x[j+1];
rem=(bet + bet*eps)+al*eps;
res = al + rem;
cor = (al - res) + rem;
if (res == (res+cor*(1.0+error+err_1))) return res*binexp.x;
else return -10.0;
}
if (n <= smallint) return 1.0; /* if x->0 e^x=1 */
if (n >= badint) {
if (n > infint) return(zero/zero); /* x is NaN, return invalid */
if (n < infint) return ( (x>0) ? (hhuge*hhuge) : (tiny*tiny) );
/* x is finite, cause either overflow or underflow */
if (junk1.i[LOW_HALF] != 0) return (zero/zero); /* x is NaN */
return ((x>0)?inf.x:zero ); /* |x| = inf; return either inf or 0 */
}
y = x*log2e.x + three51.x;
bexp = y - three51.x;
junk1.x = y;
eps = bexp*ln_two2.x;
t = x - bexp*ln_two1.x;
y = t + three33.x;
base = y - three33.x;
junk2.x = y;
del = (t - base) + (xx-eps);
eps = del + del*del*(p3.x*del + p2.x);
i = ((junk2.i[LOW_HALF]>>8)&0xfffffffe)+356;
j = (junk2.i[LOW_HALF]&511)<<1;
al = coar.x[i]*fine.x[j];
bet =(coar.x[i]*fine.x[j+1] + coar.x[i+1]*fine.x[j]) + coar.x[i+1]*fine.x[j+1];
rem=(bet + bet*eps)+al*eps;
res = al + rem;
cor = (al - res) + rem;
if (m>>31) {
ex=junk1.i[LOW_HALF];
if (res < 1.0) {res+=res; cor+=cor; ex-=1;}
if (ex >=-1022) {
binexp.i[HIGH_HALF] = (1023+ex)<<20;
if (res == (res+cor*(1.0+error+err_1))) return res*binexp.x;
else return -10.0;
}
ex = -(1022+ex);
binexp.i[HIGH_HALF] = (1023-ex)<<20;
res*=binexp.x;
cor*=binexp.x;
eps=1.00000000001+(error+err_1)*binexp.x;
t=1.0+res;
y = ((1.0-t)+res)+cor;
res=t+y;
cor = (t-res)+y;
if (res == (res + eps*cor))
{binexp.i[HIGH_HALF] = 0x00100000; return (res-1.0)*binexp.x;}
else return -10.0;
}
else {
binexp.i[HIGH_HALF] =(junk1.i[LOW_HALF]+767)<<20;
if (res == (res+cor*(1.0+error+err_1)))
return res*binexp.x*t256.x;
else return -10.0;
}
}
@@ -0,0 +1,140 @@
/* Single-precision floating point e^x.
Copyright (C) 1997, 1998 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Geoffrey Keating <[email protected]>
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
/* How this works:
The input value, x, is written as
x = n * ln(2) + t/512 + delta[t] + x;
where:
- n is an integer, 127 >= n >= -150;
- t is an integer, 177 >= t >= -177
- delta is based on a table entry, delta[t] < 2^-28
- x is whatever is left, |x| < 2^-10
Then e^x is approximated as
e^x = 2^n ( e^(t/512 + delta[t])
+ ( e^(t/512 + delta[t])
* ( p(x + delta[t] + n * ln(2)) - delta ) ) )
where
- p(x) is a polynomial approximating e(x)-1;
- e^(t/512 + delta[t]) is obtained from a table.
The table used is the same one as for the double precision version;
since we have the table, we might as well use it.
It turns out to be faster to do calculations in double precision than
to perform an 'accurate table method' expf, because of the range reduction
overhead (compare exp2f).
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <float.h>
#include <ieee754.h>
#include <math.h>
#include <fenv.h>
#include <inttypes.h>
#include <math_private.h>
extern const float __exp_deltatable[178];
extern const double __exp_atable[355] /* __attribute__((mode(DF))) */;
static const volatile float TWOM100 = 7.88860905e-31;
static const volatile float TWO127 = 1.7014118346e+38;
float
__ieee754_expf (float x)
{
static const float himark = 88.72283935546875;
static const float lomark = -103.972084045410;
/* Check for usual case. */
if (isless (x, himark) && isgreater (x, lomark))
{
static const float THREEp42 = 13194139533312.0;
static const float THREEp22 = 12582912.0;
/* 1/ln(2). */
#undef M_1_LN2
static const float M_1_LN2 = 1.44269502163f;
/* ln(2) */
#undef M_LN2
static const double M_LN2 = .6931471805599452862;
int tval;
double x22, t, result, dx;
float n, delta;
union ieee754_double ex2_u;
fenv_t oldenv;
feholdexcept (&oldenv);
#ifdef FE_TONEAREST
fesetround (FE_TONEAREST);
#endif
/* Calculate n. */
n = x * M_1_LN2 + THREEp22;
n -= THREEp22;
dx = x - n*M_LN2;
/* Calculate t/512. */
t = dx + THREEp42;
t -= THREEp42;
dx -= t;
/* Compute tval = t. */
tval = (int) (t * 512.0);
if (t >= 0)
delta = - __exp_deltatable[tval];
else
delta = __exp_deltatable[-tval];
/* Compute ex2 = 2^n e^(t/512+delta[t]). */
ex2_u.d = __exp_atable[tval+177];
ex2_u.ieee.exponent += (int) n;
/* Approximate e^(dx+delta) - 1, using a second-degree polynomial,
with maximum error in [-2^-10-2^-28,2^-10+2^-28]
less than 5e-11. */
x22 = (0.5000000496709180453 * dx + 1.0000001192102037084) * dx + delta;
/* Return result. */
fesetenv (&oldenv);
result = x22 * ex2_u.d + ex2_u.d;
return (float) result;
}
/* Exceptional cases: */
else if (isless (x, himark))
{
if (__isinff (x))
/* e^-inf == 0, with no error. */
return 0;
else
/* Underflow */
return TWOM100 * TWOM100;
}
else
/* Return x, if x is a NaN or Inf; or overflow, otherwise. */
return TWO127*x;
}
@@ -0,0 +1,57 @@
/* Implementation of gamma function according to ISO C.
Copyright (C) 1997, 1999, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <[email protected]>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <math.h>
#include <math_private.h>
double
__ieee754_gamma_r (double x, int *signgamp)
{
/* We don't have a real gamma implementation now. We'll use lgamma
and the exp function. But due to the required boundary
conditions we must check some values separately. */
int32_t hx;
u_int32_t lx;
EXTRACT_WORDS (hx, lx, x);
if (((hx & 0x7fffffff) | lx) == 0)
{
/* Return value for x == 0 is NaN with invalid exception. */
*signgamp = 0;
return x / x;
}
if (hx < 0 && (u_int32_t) hx < 0xfff00000 && __rint (x) == x)
{
/* Return value for integer x < 0 is NaN with invalid exception. */
*signgamp = 0;
return (x - x) / (x - x);
}
if ((unsigned int) hx == 0xfff00000 && lx==0)
{
/* x == -Inf. According to ISO this is NaN. */
*signgamp = 0;
return x - x;
}
/* XXX FIXME. */
return __ieee754_exp (__ieee754_lgamma_r (x, signgamp));
}
@@ -0,0 +1,56 @@
/* Implementation of gamma function according to ISO C.
Copyright (C) 1997, 1999, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <[email protected]>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <math.h>
#include <math_private.h>
float
__ieee754_gammaf_r (float x, int *signgamp)
{
/* We don't have a real gamma implementation now. We'll use lgamma
and the exp function. But due to the required boundary
conditions we must check some values separately. */
int32_t hx;
GET_FLOAT_WORD (hx, x);
if ((hx & 0x7fffffff) == 0)
{
/* Return value for x == 0 is NaN with invalid exception. */
*signgamp = 0;
return x / x;
}
if (hx < 0 && (u_int32_t) hx < 0xff800000 && __rintf (x) == x)
{
/* Return value for integer x < 0 is NaN with invalid exception. */
*signgamp = 0;
return (x - x) / (x - x);
}
if (hx == 0xff800000)
{
/* x == -Inf. According to ISO this is NaN. */
*signgamp = 0;
return x - x;
}
/* XXX FIXME. */
return __ieee754_expf (__ieee754_lgammaf_r (x, signgamp));
}
@@ -0,0 +1,128 @@
/* @(#)e_hypot.c 5.1 93/09/24 */
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_hypot.c,v 1.9 1995/05/12 04:57:27 jtc Exp $";
#endif
/* __ieee754_hypot(x,y)
*
* Method :
* If (assume round-to-nearest) z=x*x+y*y
* has error less than sqrt(2)/2 ulp, than
* sqrt(z) has error less than 1 ulp (exercise).
*
* So, compute sqrt(x*x+y*y) with some care as
* follows to get the error below 1 ulp:
*
* Assume x>y>0;
* (if possible, set rounding to round-to-nearest)
* 1. if x > 2y use
* x1*x1+(y*y+(x2*(x+x1))) for x*x+y*y
* where x1 = x with lower 32 bits cleared, x2 = x-x1; else
* 2. if x <= 2y use
* t1*y1+((x-y)*(x-y)+(t1*y2+t2*y))
* where t1 = 2x with lower 32 bits cleared, t2 = 2x-t1,
* y1= y with lower 32 bits chopped, y2 = y-y1.
*
* NOTE: scaling may be necessary if some argument is too
* large or too tiny
*
* Special cases:
* hypot(x,y) is INF if x or y is +INF or -INF; else
* hypot(x,y) is NAN if x or y is NAN.
*
* Accuracy:
* hypot(x,y) returns sqrt(x^2+y^2) with error less
* than 1 ulps (units in the last place)
*/
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
double __ieee754_hypot(double x, double y)
#else
double __ieee754_hypot(x,y)
double x, y;
#endif
{
double a,b,t1,t2,y1,y2,w;
int32_t j,k,ha,hb;
GET_HIGH_WORD(ha,x);
ha &= 0x7fffffff;
GET_HIGH_WORD(hb,y);
hb &= 0x7fffffff;
if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;}
SET_HIGH_WORD(a,ha); /* a <- |a| */
SET_HIGH_WORD(b,hb); /* b <- |b| */
if((ha-hb)>0x3c00000) {return a+b;} /* x/y > 2**60 */
k=0;
if(ha > 0x5f300000) { /* a>2**500 */
if(ha >= 0x7ff00000) { /* Inf or NaN */
u_int32_t low;
w = a+b; /* for sNaN */
GET_LOW_WORD(low,a);
if(((ha&0xfffff)|low)==0) w = a;
GET_LOW_WORD(low,b);
if(((hb^0x7ff00000)|low)==0) w = b;
return w;
}
/* scale a and b by 2**-600 */
ha -= 0x25800000; hb -= 0x25800000; k += 600;
SET_HIGH_WORD(a,ha);
SET_HIGH_WORD(b,hb);
}
if(hb < 0x20b00000) { /* b < 2**-500 */
if(hb <= 0x000fffff) { /* subnormal b or 0 */
u_int32_t low;
GET_LOW_WORD(low,b);
if((hb|low)==0) return a;
t1=0;
SET_HIGH_WORD(t1,0x7fd00000); /* t1=2^1022 */
b *= t1;
a *= t1;
k -= 1022;
} else { /* scale a and b by 2^600 */
ha += 0x25800000; /* a *= 2^600 */
hb += 0x25800000; /* b *= 2^600 */
k -= 600;
SET_HIGH_WORD(a,ha);
SET_HIGH_WORD(b,hb);
}
}
/* medium size a and b */
w = a-b;
if (w>b) {
t1 = 0;
SET_HIGH_WORD(t1,ha);
t2 = a-t1;
w = __ieee754_sqrt(t1*t1-(b*(-b)-t2*(a+t1)));
} else {
a = a+a;
y1 = 0;
SET_HIGH_WORD(y1,hb);
y2 = b - y1;
t1 = 0;
SET_HIGH_WORD(t1,ha+0x00100000);
t2 = a - t1;
w = __ieee754_sqrt(t1*y1-(w*(-w)-(t1*y2+t2*b)));
}
if(k!=0) {
u_int32_t high;
t1 = 1.0;
GET_HIGH_WORD(high,t1);
SET_HIGH_WORD(t1,high+(k<<20));
return t1*w;
} else return w;
}
@@ -0,0 +1,87 @@
/* e_hypotf.c -- float version of e_hypot.c.
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
*/
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_hypotf.c,v 1.5 1995/05/12 04:57:30 jtc Exp $";
#endif
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
float __ieee754_hypotf(float x, float y)
#else
float __ieee754_hypot(x,y)
float x, y;
#endif
{
float a,b,t1,t2,y1,y2,w;
int32_t j,k,ha,hb;
GET_FLOAT_WORD(ha,x);
ha &= 0x7fffffff;
GET_FLOAT_WORD(hb,y);
hb &= 0x7fffffff;
if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;}
SET_FLOAT_WORD(a,ha); /* a <- |a| */
SET_FLOAT_WORD(b,hb); /* b <- |b| */
if((ha-hb)>0xf000000) {return a+b;} /* x/y > 2**30 */
k=0;
if(ha > 0x58800000) { /* a>2**50 */
if(ha >= 0x7f800000) { /* Inf or NaN */
w = a+b; /* for sNaN */
if(ha == 0x7f800000) w = a;
if(hb == 0x7f800000) w = b;
return w;
}
/* scale a and b by 2**-60 */
ha -= 0x5d800000; hb -= 0x5d800000; k += 60;
SET_FLOAT_WORD(a,ha);
SET_FLOAT_WORD(b,hb);
}
if(hb < 0x26800000) { /* b < 2**-50 */
if(hb <= 0x007fffff) { /* subnormal b or 0 */
if(hb==0) return a;
SET_FLOAT_WORD(t1,0x3f000000); /* t1=2^126 */
b *= t1;
a *= t1;
k -= 126;
} else { /* scale a and b by 2^60 */
ha += 0x5d800000; /* a *= 2^60 */
hb += 0x5d800000; /* b *= 2^60 */
k -= 60;
SET_FLOAT_WORD(a,ha);
SET_FLOAT_WORD(b,hb);
}
}
/* medium size a and b */
w = a-b;
if (w>b) {
SET_FLOAT_WORD(t1,ha&0xfffff000);
t2 = a-t1;
w = __ieee754_sqrtf(t1*t1-(b*(-b)-t2*(a+t1)));
} else {
a = a+a;
SET_FLOAT_WORD(y1,hb&0xfffff000);
y2 = b - y1;
SET_FLOAT_WORD(t1,ha+0x00800000);
t2 = a - t1;
w = __ieee754_sqrtf(t1*y1-(w*(-w)-(t1*y2+t2*b)));
}
if(k!=0) {
SET_FLOAT_WORD(t1,0x3f800000+(k<<23));
return t1*w;
} else return w;
}
@@ -0,0 +1,529 @@
/* @(#)e_j0.c 5.1 93/09/24 */
/*
* ====================================================
* 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.
* ====================================================
*/
/* Modified by Naohiko Shimizu/Tokai University, Japan 1997/08/26,
for performance improvement on pipelined processors.
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_j0.c,v 1.8 1995/05/10 20:45:23 jtc Exp $";
#endif
/* __ieee754_j0(x), __ieee754_y0(x)
* Bessel function of the first and second kinds of order zero.
* Method -- j0(x):
* 1. For tiny x, we use j0(x) = 1 - x^2/4 + x^4/64 - ...
* 2. Reduce x to |x| since j0(x)=j0(-x), and
* for x in (0,2)
* j0(x) = 1-z/4+ z^2*R0/S0, where z = x*x;
* (precision: |j0-1+z/4-z^2R0/S0 |<2**-63.67 )
* for x in (2,inf)
* j0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x0)-q0(x)*sin(x0))
* where x0 = x-pi/4. It is better to compute sin(x0),cos(x0)
* as follow:
* cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4)
* = 1/sqrt(2) * (cos(x) + sin(x))
* sin(x0) = sin(x)cos(pi/4)-cos(x)sin(pi/4)
* = 1/sqrt(2) * (sin(x) - cos(x))
* (To avoid cancellation, use
* sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
* to compute the worse one.)
*
* 3 Special cases
* j0(nan)= nan
* j0(0) = 1
* j0(inf) = 0
*
* Method -- y0(x):
* 1. For x<2.
* Since
* y0(x) = 2/pi*(j0(x)*(ln(x/2)+Euler) + x^2/4 - ...)
* therefore y0(x)-2/pi*j0(x)*ln(x) is an even function.
* We use the following function to approximate y0,
* y0(x) = U(z)/V(z) + (2/pi)*(j0(x)*ln(x)), z= x^2
* where
* U(z) = u00 + u01*z + ... + u06*z^6
* V(z) = 1 + v01*z + ... + v04*z^4
* with absolute approximation error bounded by 2**-72.
* Note: For tiny x, U/V = u0 and j0(x)~1, hence
* y0(tiny) = u0 + (2/pi)*ln(tiny), (choose tiny<2**-27)
* 2. For x>=2.
* y0(x) = sqrt(2/(pi*x))*(p0(x)*cos(x0)+q0(x)*sin(x0))
* where x0 = x-pi/4. It is better to compute sin(x0),cos(x0)
* by the method mentioned above.
* 3. Special cases: y0(0)=-inf, y0(x<0)=NaN, y0(inf)=0.
*/
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static double pzero(double), qzero(double);
#else
static double pzero(), qzero();
#endif
#ifdef __STDC__
static const double
#else
static double
#endif
huge = 1e300,
one = 1.0,
invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */
tpi = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
/* R0/S0 on [0, 2.00] */
R[] = {0.0, 0.0, 1.56249999999999947958e-02, /* 0x3F8FFFFF, 0xFFFFFFFD */
-1.89979294238854721751e-04, /* 0xBF28E6A5, 0xB61AC6E9 */
1.82954049532700665670e-06, /* 0x3EBEB1D1, 0x0C503919 */
-4.61832688532103189199e-09}, /* 0xBE33D5E7, 0x73D63FCE */
S[] = {0.0, 1.56191029464890010492e-02, /* 0x3F8FFCE8, 0x82C8C2A4 */
1.16926784663337450260e-04, /* 0x3F1EA6D2, 0xDD57DBF4 */
5.13546550207318111446e-07, /* 0x3EA13B54, 0xCE84D5A9 */
1.16614003333790000205e-09}; /* 0x3E1408BC, 0xF4745D8F */
#ifdef __STDC__
static const double zero = 0.0;
#else
static double zero = 0.0;
#endif
#ifdef __STDC__
double __ieee754_j0(double x)
#else
double __ieee754_j0(x)
double x;
#endif
{
double z, s,c,ss,cc,r,u,v,r1,r2,s1,s2,z2,z4;
int32_t hx,ix;
GET_HIGH_WORD(hx,x);
ix = hx&0x7fffffff;
if(ix>=0x7ff00000) return one/(x*x);
x = fabs(x);
if(ix >= 0x40000000) { /* |x| >= 2.0 */
__sincos (x, &s, &c);
ss = s-c;
cc = s+c;
if(ix<0x7fe00000) { /* make sure x+x not overflow */
z = -__cos(x+x);
if ((s*c)<zero) cc = z/ss;
else ss = z/cc;
}
/*
* j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x)
* y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x)
*/
if(ix>0x48000000) z = (invsqrtpi*cc)/__ieee754_sqrt(x);
else {
u = pzero(x); v = qzero(x);
z = invsqrtpi*(u*cc-v*ss)/__ieee754_sqrt(x);
}
return z;
}
if(ix<0x3f200000) { /* |x| < 2**-13 */
if(huge+x>one) { /* raise inexact if x != 0 */
if(ix<0x3e400000) return one; /* |x|<2**-27 */
else return one - 0.25*x*x;
}
}
z = x*x;
#ifdef DO_NOT_USE_THIS
r = z*(R02+z*(R03+z*(R04+z*R05)));
s = one+z*(S01+z*(S02+z*(S03+z*S04)));
#else
r1 = z*R[2]; z2=z*z;
r2 = R[3]+z*R[4]; z4=z2*z2;
r = r1 + z2*r2 + z4*R[5];
s1 = one+z*S[1];
s2 = S[2]+z*S[3];
s = s1 + z2*s2 + z4*S[4];
#endif
if(ix < 0x3FF00000) { /* |x| < 1.00 */
return one + z*(-0.25+(r/s));
} else {
u = 0.5*x;
return((one+u)*(one-u)+z*(r/s));
}
}
#ifdef __STDC__
static const double
#else
static double
#endif
U[] = {-7.38042951086872317523e-02, /* 0xBFB2E4D6, 0x99CBD01F */
1.76666452509181115538e-01, /* 0x3FC69D01, 0x9DE9E3FC */
-1.38185671945596898896e-02, /* 0xBF8C4CE8, 0xB16CFA97 */
3.47453432093683650238e-04, /* 0x3F36C54D, 0x20B29B6B */
-3.81407053724364161125e-06, /* 0xBECFFEA7, 0x73D25CAD */
1.95590137035022920206e-08, /* 0x3E550057, 0x3B4EABD4 */
-3.98205194132103398453e-11}, /* 0xBDC5E43D, 0x693FB3C8 */
V[] = {1.27304834834123699328e-02, /* 0x3F8A1270, 0x91C9C71A */
7.60068627350353253702e-05, /* 0x3F13ECBB, 0xF578C6C1 */
2.59150851840457805467e-07, /* 0x3E91642D, 0x7FF202FD */
4.41110311332675467403e-10}; /* 0x3DFE5018, 0x3BD6D9EF */
#ifdef __STDC__
double __ieee754_y0(double x)
#else
double __ieee754_y0(x)
double x;
#endif
{
double z, s,c,ss,cc,u,v,z2,z4,z6,u1,u2,u3,v1,v2;
int32_t hx,ix,lx;
EXTRACT_WORDS(hx,lx,x);
ix = 0x7fffffff&hx;
/* Y0(NaN) is NaN, y0(-inf) is Nan, y0(inf) is 0 */
if(ix>=0x7ff00000) return one/(x+x*x);
if((ix|lx)==0) return -one/zero;
if(hx<0) return zero/zero;
if(ix >= 0x40000000) { /* |x| >= 2.0 */
/* y0(x) = sqrt(2/(pi*x))*(p0(x)*sin(x0)+q0(x)*cos(x0))
* where x0 = x-pi/4
* Better formula:
* cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4)
* = 1/sqrt(2) * (sin(x) + cos(x))
* sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
* = 1/sqrt(2) * (sin(x) - cos(x))
* To avoid cancellation, use
* sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
* to compute the worse one.
*/
__sincos (x, &s, &c);
ss = s-c;
cc = s+c;
/*
* j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x)
* y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x)
*/
if(ix<0x7fe00000) { /* make sure x+x not overflow */
z = -__cos(x+x);
if ((s*c)<zero) cc = z/ss;
else ss = z/cc;
}
if(ix>0x48000000) z = (invsqrtpi*ss)/__ieee754_sqrt(x);
else {
u = pzero(x); v = qzero(x);
z = invsqrtpi*(u*ss+v*cc)/__ieee754_sqrt(x);
}
return z;
}
if(ix<=0x3e400000) { /* x < 2**-27 */
return(U[0] + tpi*__ieee754_log(x));
}
z = x*x;
#ifdef DO_NOT_USE_THIS
u = u00+z*(u01+z*(u02+z*(u03+z*(u04+z*(u05+z*u06)))));
v = one+z*(v01+z*(v02+z*(v03+z*v04)));
#else
u1 = U[0]+z*U[1]; z2=z*z;
u2 = U[2]+z*U[3]; z4=z2*z2;
u3 = U[4]+z*U[5]; z6=z4*z2;
u = u1 + z2*u2 + z4*u3 + z6*U[6];
v1 = one+z*V[0];
v2 = V[1]+z*V[2];
v = v1 + z2*v2 + z4*V[3];
#endif
return(u/v + tpi*(__ieee754_j0(x)*__ieee754_log(x)));
}
/* The asymptotic expansions of pzero is
* 1 - 9/128 s^2 + 11025/98304 s^4 - ..., where s = 1/x.
* For x >= 2, We approximate pzero by
* pzero(x) = 1 + (R/S)
* where R = pR0 + pR1*s^2 + pR2*s^4 + ... + pR5*s^10
* S = 1 + pS0*s^2 + ... + pS4*s^10
* and
* | pzero(x)-1-R/S | <= 2 ** ( -60.26)
*/
#ifdef __STDC__
static const double pR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
#else
static double pR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
#endif
0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
-7.03124999999900357484e-02, /* 0xBFB1FFFF, 0xFFFFFD32 */
-8.08167041275349795626e+00, /* 0xC02029D0, 0xB44FA779 */
-2.57063105679704847262e+02, /* 0xC0701102, 0x7B19E863 */
-2.48521641009428822144e+03, /* 0xC0A36A6E, 0xCD4DCAFC */
-5.25304380490729545272e+03, /* 0xC0B4850B, 0x36CC643D */
};
#ifdef __STDC__
static const double pS8[5] = {
#else
static double pS8[5] = {
#endif
1.16534364619668181717e+02, /* 0x405D2233, 0x07A96751 */
3.83374475364121826715e+03, /* 0x40ADF37D, 0x50596938 */
4.05978572648472545552e+04, /* 0x40E3D2BB, 0x6EB6B05F */
1.16752972564375915681e+05, /* 0x40FC810F, 0x8F9FA9BD */
4.76277284146730962675e+04, /* 0x40E74177, 0x4F2C49DC */
};
#ifdef __STDC__
static const double pR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
#else
static double pR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
#endif
-1.14125464691894502584e-11, /* 0xBDA918B1, 0x47E495CC */
-7.03124940873599280078e-02, /* 0xBFB1FFFF, 0xE69AFBC6 */
-4.15961064470587782438e+00, /* 0xC010A370, 0xF90C6BBF */
-6.76747652265167261021e+01, /* 0xC050EB2F, 0x5A7D1783 */
-3.31231299649172967747e+02, /* 0xC074B3B3, 0x6742CC63 */
-3.46433388365604912451e+02, /* 0xC075A6EF, 0x28A38BD7 */
};
#ifdef __STDC__
static const double pS5[5] = {
#else
static double pS5[5] = {
#endif
6.07539382692300335975e+01, /* 0x404E6081, 0x0C98C5DE */
1.05125230595704579173e+03, /* 0x40906D02, 0x5C7E2864 */
5.97897094333855784498e+03, /* 0x40B75AF8, 0x8FBE1D60 */
9.62544514357774460223e+03, /* 0x40C2CCB8, 0xFA76FA38 */
2.40605815922939109441e+03, /* 0x40A2CC1D, 0xC70BE864 */
};
#ifdef __STDC__
static const double pR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
#else
static double pR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
#endif
-2.54704601771951915620e-09, /* 0xBE25E103, 0x6FE1AA86 */
-7.03119616381481654654e-02, /* 0xBFB1FFF6, 0xF7C0E24B */
-2.40903221549529611423e+00, /* 0xC00345B2, 0xAEA48074 */
-2.19659774734883086467e+01, /* 0xC035F74A, 0x4CB94E14 */
-5.80791704701737572236e+01, /* 0xC04D0A22, 0x420A1A45 */
-3.14479470594888503854e+01, /* 0xC03F72AC, 0xA892D80F */
};
#ifdef __STDC__
static const double pS3[5] = {
#else
static double pS3[5] = {
#endif
3.58560338055209726349e+01, /* 0x4041ED92, 0x84077DD3 */
3.61513983050303863820e+02, /* 0x40769839, 0x464A7C0E */
1.19360783792111533330e+03, /* 0x4092A66E, 0x6D1061D6 */
1.12799679856907414432e+03, /* 0x40919FFC, 0xB8C39B7E */
1.73580930813335754692e+02, /* 0x4065B296, 0xFC379081 */
};
#ifdef __STDC__
static const double pR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
#else
static double pR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
#endif
-8.87534333032526411254e-08, /* 0xBE77D316, 0xE927026D */
-7.03030995483624743247e-02, /* 0xBFB1FF62, 0x495E1E42 */
-1.45073846780952986357e+00, /* 0xBFF73639, 0x8A24A843 */
-7.63569613823527770791e+00, /* 0xC01E8AF3, 0xEDAFA7F3 */
-1.11931668860356747786e+01, /* 0xC02662E6, 0xC5246303 */
-3.23364579351335335033e+00, /* 0xC009DE81, 0xAF8FE70F */
};
#ifdef __STDC__
static const double pS2[5] = {
#else
static double pS2[5] = {
#endif
2.22202997532088808441e+01, /* 0x40363865, 0x908B5959 */
1.36206794218215208048e+02, /* 0x4061069E, 0x0EE8878F */
2.70470278658083486789e+02, /* 0x4070E786, 0x42EA079B */
1.53875394208320329881e+02, /* 0x40633C03, 0x3AB6FAFF */
1.46576176948256193810e+01, /* 0x402D50B3, 0x44391809 */
};
#ifdef __STDC__
static double pzero(double x)
#else
static double pzero(x)
double x;
#endif
{
#ifdef __STDC__
const double *p,*q;
#else
double *p,*q;
#endif
double z,r,s,z2,z4,r1,r2,r3,s1,s2,s3;
int32_t ix;
GET_HIGH_WORD(ix,x);
ix &= 0x7fffffff;
if(ix>=0x40200000) {p = pR8; q= pS8;}
else if(ix>=0x40122E8B){p = pR5; q= pS5;}
else if(ix>=0x4006DB6D){p = pR3; q= pS3;}
else if(ix>=0x40000000){p = pR2; q= pS2;}
z = one/(x*x);
#ifdef DO_NOT_USE_THIS
r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4]))));
#else
r1 = p[0]+z*p[1]; z2=z*z;
r2 = p[2]+z*p[3]; z4=z2*z2;
r3 = p[4]+z*p[5];
r = r1 + z2*r2 + z4*r3;
s1 = one+z*q[0];
s2 = q[1]+z*q[2];
s3 = q[3]+z*q[4];
s = s1 + z2*s2 + z4*s3;
#endif
return one+ r/s;
}
/* For x >= 8, the asymptotic expansions of qzero is
* -1/8 s + 75/1024 s^3 - ..., where s = 1/x.
* We approximate pzero by
* qzero(x) = s*(-1.25 + (R/S))
* where R = qR0 + qR1*s^2 + qR2*s^4 + ... + qR5*s^10
* S = 1 + qS0*s^2 + ... + qS5*s^12
* and
* | qzero(x)/s +1.25-R/S | <= 2 ** ( -61.22)
*/
#ifdef __STDC__
static const double qR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
#else
static double qR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
#endif
0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
7.32421874999935051953e-02, /* 0x3FB2BFFF, 0xFFFFFE2C */
1.17682064682252693899e+01, /* 0x40278952, 0x5BB334D6 */
5.57673380256401856059e+02, /* 0x40816D63, 0x15301825 */
8.85919720756468632317e+03, /* 0x40C14D99, 0x3E18F46D */
3.70146267776887834771e+04, /* 0x40E212D4, 0x0E901566 */
};
#ifdef __STDC__
static const double qS8[6] = {
#else
static double qS8[6] = {
#endif
1.63776026895689824414e+02, /* 0x406478D5, 0x365B39BC */
8.09834494656449805916e+03, /* 0x40BFA258, 0x4E6B0563 */
1.42538291419120476348e+05, /* 0x41016652, 0x54D38C3F */
8.03309257119514397345e+05, /* 0x412883DA, 0x83A52B43 */
8.40501579819060512818e+05, /* 0x4129A66B, 0x28DE0B3D */
-3.43899293537866615225e+05, /* 0xC114FD6D, 0x2C9530C5 */
};
#ifdef __STDC__
static const double qR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
#else
static double qR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
#endif
1.84085963594515531381e-11, /* 0x3DB43D8F, 0x29CC8CD9 */
7.32421766612684765896e-02, /* 0x3FB2BFFF, 0xD172B04C */
5.83563508962056953777e+00, /* 0x401757B0, 0xB9953DD3 */
1.35111577286449829671e+02, /* 0x4060E392, 0x0A8788E9 */
1.02724376596164097464e+03, /* 0x40900CF9, 0x9DC8C481 */
1.98997785864605384631e+03, /* 0x409F17E9, 0x53C6E3A6 */
};
#ifdef __STDC__
static const double qS5[6] = {
#else
static double qS5[6] = {
#endif
8.27766102236537761883e+01, /* 0x4054B1B3, 0xFB5E1543 */
2.07781416421392987104e+03, /* 0x40A03BA0, 0xDA21C0CE */
1.88472887785718085070e+04, /* 0x40D267D2, 0x7B591E6D */
5.67511122894947329769e+04, /* 0x40EBB5E3, 0x97E02372 */
3.59767538425114471465e+04, /* 0x40E19118, 0x1F7A54A0 */
-5.35434275601944773371e+03, /* 0xC0B4EA57, 0xBEDBC609 */
};
#ifdef __STDC__
static const double qR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
#else
static double qR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
#endif
4.37741014089738620906e-09, /* 0x3E32CD03, 0x6ADECB82 */
7.32411180042911447163e-02, /* 0x3FB2BFEE, 0x0E8D0842 */
3.34423137516170720929e+00, /* 0x400AC0FC, 0x61149CF5 */
4.26218440745412650017e+01, /* 0x40454F98, 0x962DAEDD */
1.70808091340565596283e+02, /* 0x406559DB, 0xE25EFD1F */
1.66733948696651168575e+02, /* 0x4064D77C, 0x81FA21E0 */
};
#ifdef __STDC__
static const double qS3[6] = {
#else
static double qS3[6] = {
#endif
4.87588729724587182091e+01, /* 0x40486122, 0xBFE343A6 */
7.09689221056606015736e+02, /* 0x40862D83, 0x86544EB3 */
3.70414822620111362994e+03, /* 0x40ACF04B, 0xE44DFC63 */
6.46042516752568917582e+03, /* 0x40B93C6C, 0xD7C76A28 */
2.51633368920368957333e+03, /* 0x40A3A8AA, 0xD94FB1C0 */
-1.49247451836156386662e+02, /* 0xC062A7EB, 0x201CF40F */
};
#ifdef __STDC__
static const double qR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
#else
static double qR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
#endif
1.50444444886983272379e-07, /* 0x3E84313B, 0x54F76BDB */
7.32234265963079278272e-02, /* 0x3FB2BEC5, 0x3E883E34 */
1.99819174093815998816e+00, /* 0x3FFFF897, 0xE727779C */
1.44956029347885735348e+01, /* 0x402CFDBF, 0xAAF96FE5 */
3.16662317504781540833e+01, /* 0x403FAA8E, 0x29FBDC4A */
1.62527075710929267416e+01, /* 0x403040B1, 0x71814BB4 */
};
#ifdef __STDC__
static const double qS2[6] = {
#else
static double qS2[6] = {
#endif
3.03655848355219184498e+01, /* 0x403E5D96, 0xF7C07AED */
2.69348118608049844624e+02, /* 0x4070D591, 0xE4D14B40 */
8.44783757595320139444e+02, /* 0x408A6645, 0x22B3BF22 */
8.82935845112488550512e+02, /* 0x408B977C, 0x9C5CC214 */
2.12666388511798828631e+02, /* 0x406A9553, 0x0E001365 */
-5.31095493882666946917e+00, /* 0xC0153E6A, 0xF8B32931 */
};
#ifdef __STDC__
static double qzero(double x)
#else
static double qzero(x)
double x;
#endif
{
#ifdef __STDC__
const double *p,*q;
#else
double *p,*q;
#endif
double s,r,z,z2,z4,z6,r1,r2,r3,s1,s2,s3;
int32_t ix;
GET_HIGH_WORD(ix,x);
ix &= 0x7fffffff;
if(ix>=0x40200000) {p = qR8; q= qS8;}
else if(ix>=0x40122E8B){p = qR5; q= qS5;}
else if(ix>=0x4006DB6D){p = qR3; q= qS3;}
else if(ix>=0x40000000){p = qR2; q= qS2;}
z = one/(x*x);
#ifdef DO_NOT_USE_THIS
r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5])))));
#else
r1 = p[0]+z*p[1]; z2=z*z;
r2 = p[2]+z*p[3]; z4=z2*z2;
r3 = p[4]+z*p[5]; z6=z4*z2;
r= r1 + z2*r2 + z4*r3;
s1 = one+z*q[0];
s2 = q[1]+z*q[2];
s3 = q[3]+z*q[4];
s = s1 + z2*s2 + z4*s3 +z6*q[5];
#endif
return (-.125 + r/s)/x;
}
@@ -0,0 +1,442 @@
/* e_j0f.c -- float version of e_j0.c.
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
*/
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_j0f.c,v 1.4 1995/05/10 20:45:25 jtc Exp $";
#endif
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static float pzerof(float), qzerof(float);
#else
static float pzerof(), qzerof();
#endif
#ifdef __STDC__
static const float
#else
static float
#endif
huge = 1e30,
one = 1.0,
invsqrtpi= 5.6418961287e-01, /* 0x3f106ebb */
tpi = 6.3661974669e-01, /* 0x3f22f983 */
/* R0/S0 on [0, 2.00] */
R02 = 1.5625000000e-02, /* 0x3c800000 */
R03 = -1.8997929874e-04, /* 0xb947352e */
R04 = 1.8295404516e-06, /* 0x35f58e88 */
R05 = -4.6183270541e-09, /* 0xb19eaf3c */
S01 = 1.5619102865e-02, /* 0x3c7fe744 */
S02 = 1.1692678527e-04, /* 0x38f53697 */
S03 = 5.1354652442e-07, /* 0x3509daa6 */
S04 = 1.1661400734e-09; /* 0x30a045e8 */
#ifdef __STDC__
static const float zero = 0.0;
#else
static float zero = 0.0;
#endif
#ifdef __STDC__
float __ieee754_j0f(float x)
#else
float __ieee754_j0f(x)
float x;
#endif
{
float z, s,c,ss,cc,r,u,v;
int32_t hx,ix;
GET_FLOAT_WORD(hx,x);
ix = hx&0x7fffffff;
if(ix>=0x7f800000) return one/(x*x);
x = fabsf(x);
if(ix >= 0x40000000) { /* |x| >= 2.0 */
__sincosf (x, &s, &c);
ss = s-c;
cc = s+c;
if(ix<0x7f000000) { /* make sure x+x not overflow */
z = -__cosf(x+x);
if ((s*c)<zero) cc = z/ss;
else ss = z/cc;
}
/*
* j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x)
* y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x)
*/
if(ix>0x48000000) z = (invsqrtpi*cc)/__ieee754_sqrtf(x);
else {
u = pzerof(x); v = qzerof(x);
z = invsqrtpi*(u*cc-v*ss)/__ieee754_sqrtf(x);
}
return z;
}
if(ix<0x39000000) { /* |x| < 2**-13 */
if(huge+x>one) { /* raise inexact if x != 0 */
if(ix<0x32000000) return one; /* |x|<2**-27 */
else return one - (float)0.25*x*x;
}
}
z = x*x;
r = z*(R02+z*(R03+z*(R04+z*R05)));
s = one+z*(S01+z*(S02+z*(S03+z*S04)));
if(ix < 0x3F800000) { /* |x| < 1.00 */
return one + z*((float)-0.25+(r/s));
} else {
u = (float)0.5*x;
return((one+u)*(one-u)+z*(r/s));
}
}
#ifdef __STDC__
static const float
#else
static float
#endif
u00 = -7.3804296553e-02, /* 0xbd9726b5 */
u01 = 1.7666645348e-01, /* 0x3e34e80d */
u02 = -1.3818567619e-02, /* 0xbc626746 */
u03 = 3.4745343146e-04, /* 0x39b62a69 */
u04 = -3.8140706238e-06, /* 0xb67ff53c */
u05 = 1.9559013964e-08, /* 0x32a802ba */
u06 = -3.9820518410e-11, /* 0xae2f21eb */
v01 = 1.2730483897e-02, /* 0x3c509385 */
v02 = 7.6006865129e-05, /* 0x389f65e0 */
v03 = 2.5915085189e-07, /* 0x348b216c */
v04 = 4.4111031494e-10; /* 0x2ff280c2 */
#ifdef __STDC__
float __ieee754_y0f(float x)
#else
float __ieee754_y0f(x)
float x;
#endif
{
float z, s,c,ss,cc,u,v;
int32_t hx,ix;
GET_FLOAT_WORD(hx,x);
ix = 0x7fffffff&hx;
/* Y0(NaN) is NaN, y0(-inf) is Nan, y0(inf) is 0 */
if(ix>=0x7f800000) return one/(x+x*x);
if(ix==0) return -one/zero;
if(hx<0) return zero/zero;
if(ix >= 0x40000000) { /* |x| >= 2.0 */
/* y0(x) = sqrt(2/(pi*x))*(p0(x)*sin(x0)+q0(x)*cos(x0))
* where x0 = x-pi/4
* Better formula:
* cos(x0) = cos(x)cos(pi/4)+sin(x)sin(pi/4)
* = 1/sqrt(2) * (sin(x) + cos(x))
* sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
* = 1/sqrt(2) * (sin(x) - cos(x))
* To avoid cancellation, use
* sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
* to compute the worse one.
*/
__sincosf (x, &s, &c);
ss = s-c;
cc = s+c;
/*
* j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x)
* y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x)
*/
if(ix<0x7f000000) { /* make sure x+x not overflow */
z = -__cosf(x+x);
if ((s*c)<zero) cc = z/ss;
else ss = z/cc;
}
if(ix>0x48000000) z = (invsqrtpi*ss)/__ieee754_sqrtf(x);
else {
u = pzerof(x); v = qzerof(x);
z = invsqrtpi*(u*ss+v*cc)/__ieee754_sqrtf(x);
}
return z;
}
if(ix<=0x32000000) { /* x < 2**-27 */
return(u00 + tpi*__ieee754_logf(x));
}
z = x*x;
u = u00+z*(u01+z*(u02+z*(u03+z*(u04+z*(u05+z*u06)))));
v = one+z*(v01+z*(v02+z*(v03+z*v04)));
return(u/v + tpi*(__ieee754_j0f(x)*__ieee754_logf(x)));
}
/* The asymptotic expansions of pzero is
* 1 - 9/128 s^2 + 11025/98304 s^4 - ..., where s = 1/x.
* For x >= 2, We approximate pzero by
* pzero(x) = 1 + (R/S)
* where R = pR0 + pR1*s^2 + pR2*s^4 + ... + pR5*s^10
* S = 1 + pS0*s^2 + ... + pS4*s^10
* and
* | pzero(x)-1-R/S | <= 2 ** ( -60.26)
*/
#ifdef __STDC__
static const float pR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
#else
static float pR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
#endif
0.0000000000e+00, /* 0x00000000 */
-7.0312500000e-02, /* 0xbd900000 */
-8.0816707611e+00, /* 0xc1014e86 */
-2.5706311035e+02, /* 0xc3808814 */
-2.4852163086e+03, /* 0xc51b5376 */
-5.2530439453e+03, /* 0xc5a4285a */
};
#ifdef __STDC__
static const float pS8[5] = {
#else
static float pS8[5] = {
#endif
1.1653436279e+02, /* 0x42e91198 */
3.8337448730e+03, /* 0x456f9beb */
4.0597855469e+04, /* 0x471e95db */
1.1675296875e+05, /* 0x47e4087c */
4.7627726562e+04, /* 0x473a0bba */
};
#ifdef __STDC__
static const float pR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
#else
static float pR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
#endif
-1.1412546255e-11, /* 0xad48c58a */
-7.0312492549e-02, /* 0xbd8fffff */
-4.1596107483e+00, /* 0xc0851b88 */
-6.7674766541e+01, /* 0xc287597b */
-3.3123129272e+02, /* 0xc3a59d9b */
-3.4643338013e+02, /* 0xc3ad3779 */
};
#ifdef __STDC__
static const float pS5[5] = {
#else
static float pS5[5] = {
#endif
6.0753936768e+01, /* 0x42730408 */
1.0512523193e+03, /* 0x44836813 */
5.9789707031e+03, /* 0x45bad7c4 */
9.6254453125e+03, /* 0x461665c8 */
2.4060581055e+03, /* 0x451660ee */
};
#ifdef __STDC__
static const float pR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
#else
static float pR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
#endif
-2.5470459075e-09, /* 0xb12f081b */
-7.0311963558e-02, /* 0xbd8fffb8 */
-2.4090321064e+00, /* 0xc01a2d95 */
-2.1965976715e+01, /* 0xc1afba52 */
-5.8079170227e+01, /* 0xc2685112 */
-3.1447946548e+01, /* 0xc1fb9565 */
};
#ifdef __STDC__
static const float pS3[5] = {
#else
static float pS3[5] = {
#endif
3.5856033325e+01, /* 0x420f6c94 */
3.6151397705e+02, /* 0x43b4c1ca */
1.1936077881e+03, /* 0x44953373 */
1.1279968262e+03, /* 0x448cffe6 */
1.7358093262e+02, /* 0x432d94b8 */
};
#ifdef __STDC__
static const float pR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
#else
static float pR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
#endif
-8.8753431271e-08, /* 0xb3be98b7 */
-7.0303097367e-02, /* 0xbd8ffb12 */
-1.4507384300e+00, /* 0xbfb9b1cc */
-7.6356959343e+00, /* 0xc0f4579f */
-1.1193166733e+01, /* 0xc1331736 */
-3.2336456776e+00, /* 0xc04ef40d */
};
#ifdef __STDC__
static const float pS2[5] = {
#else
static float pS2[5] = {
#endif
2.2220300674e+01, /* 0x41b1c32d */
1.3620678711e+02, /* 0x430834f0 */
2.7047027588e+02, /* 0x43873c32 */
1.5387539673e+02, /* 0x4319e01a */
1.4657617569e+01, /* 0x416a859a */
};
#ifdef __STDC__
static float pzerof(float x)
#else
static float pzerof(x)
float x;
#endif
{
#ifdef __STDC__
const float *p,*q;
#else
float *p,*q;
#endif
float z,r,s;
int32_t ix;
GET_FLOAT_WORD(ix,x);
ix &= 0x7fffffff;
if(ix>=0x41000000) {p = pR8; q= pS8;}
else if(ix>=0x40f71c58){p = pR5; q= pS5;}
else if(ix>=0x4036db68){p = pR3; q= pS3;}
else if(ix>=0x40000000){p = pR2; q= pS2;}
z = one/(x*x);
r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4]))));
return one+ r/s;
}
/* For x >= 8, the asymptotic expansions of qzero is
* -1/8 s + 75/1024 s^3 - ..., where s = 1/x.
* We approximate pzero by
* qzero(x) = s*(-1.25 + (R/S))
* where R = qR0 + qR1*s^2 + qR2*s^4 + ... + qR5*s^10
* S = 1 + qS0*s^2 + ... + qS5*s^12
* and
* | qzero(x)/s +1.25-R/S | <= 2 ** ( -61.22)
*/
#ifdef __STDC__
static const float qR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
#else
static float qR8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
#endif
0.0000000000e+00, /* 0x00000000 */
7.3242187500e-02, /* 0x3d960000 */
1.1768206596e+01, /* 0x413c4a93 */
5.5767340088e+02, /* 0x440b6b19 */
8.8591972656e+03, /* 0x460a6cca */
3.7014625000e+04, /* 0x471096a0 */
};
#ifdef __STDC__
static const float qS8[6] = {
#else
static float qS8[6] = {
#endif
1.6377603149e+02, /* 0x4323c6aa */
8.0983447266e+03, /* 0x45fd12c2 */
1.4253829688e+05, /* 0x480b3293 */
8.0330925000e+05, /* 0x49441ed4 */
8.4050156250e+05, /* 0x494d3359 */
-3.4389928125e+05, /* 0xc8a7eb69 */
};
#ifdef __STDC__
static const float qR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
#else
static float qR5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
#endif
1.8408595828e-11, /* 0x2da1ec79 */
7.3242180049e-02, /* 0x3d95ffff */
5.8356351852e+00, /* 0x40babd86 */
1.3511157227e+02, /* 0x43071c90 */
1.0272437744e+03, /* 0x448067cd */
1.9899779053e+03, /* 0x44f8bf4b */
};
#ifdef __STDC__
static const float qS5[6] = {
#else
static float qS5[6] = {
#endif
8.2776611328e+01, /* 0x42a58da0 */
2.0778142090e+03, /* 0x4501dd07 */
1.8847289062e+04, /* 0x46933e94 */
5.6751113281e+04, /* 0x475daf1d */
3.5976753906e+04, /* 0x470c88c1 */
-5.3543427734e+03, /* 0xc5a752be */
};
#ifdef __STDC__
static const float qR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
#else
static float qR3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
#endif
4.3774099900e-09, /* 0x3196681b */
7.3241114616e-02, /* 0x3d95ff70 */
3.3442313671e+00, /* 0x405607e3 */
4.2621845245e+01, /* 0x422a7cc5 */
1.7080809021e+02, /* 0x432acedf */
1.6673394775e+02, /* 0x4326bbe4 */
};
#ifdef __STDC__
static const float qS3[6] = {
#else
static float qS3[6] = {
#endif
4.8758872986e+01, /* 0x42430916 */
7.0968920898e+02, /* 0x44316c1c */
3.7041481934e+03, /* 0x4567825f */
6.4604252930e+03, /* 0x45c9e367 */
2.5163337402e+03, /* 0x451d4557 */
-1.4924745178e+02, /* 0xc3153f59 */
};
#ifdef __STDC__
static const float qR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
#else
static float qR2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
#endif
1.5044444979e-07, /* 0x342189db */
7.3223426938e-02, /* 0x3d95f62a */
1.9981917143e+00, /* 0x3fffc4bf */
1.4495602608e+01, /* 0x4167edfd */
3.1666231155e+01, /* 0x41fd5471 */
1.6252708435e+01, /* 0x4182058c */
};
#ifdef __STDC__
static const float qS2[6] = {
#else
static float qS2[6] = {
#endif
3.0365585327e+01, /* 0x41f2ecb8 */
2.6934811401e+02, /* 0x4386ac8f */
8.4478375244e+02, /* 0x44533229 */
8.8293585205e+02, /* 0x445cbbe5 */
2.1266638184e+02, /* 0x4354aa98 */
-5.3109550476e+00, /* 0xc0a9f358 */
};
#ifdef __STDC__
static float qzerof(float x)
#else
static float qzerof(x)
float x;
#endif
{
#ifdef __STDC__
const float *p,*q;
#else
float *p,*q;
#endif
float s,r,z;
int32_t ix;
GET_FLOAT_WORD(ix,x);
ix &= 0x7fffffff;
if(ix>=0x41000000) {p = qR8; q= qS8;}
else if(ix>=0x40f71c58){p = qR5; q= qS5;}
else if(ix>=0x4036db68){p = qR3; q= qS3;}
else if(ix>=0x40000000){p = qR2; q= qS2;}
z = one/(x*x);
r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5])))));
return (-(float).125 + r/s)/x;
}
@@ -0,0 +1,530 @@
/* @(#)e_j1.c 5.1 93/09/24 */
/*
* ====================================================
* 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.
* ====================================================
*/
/* Modified by Naohiko Shimizu/Tokai University, Japan 1997/08/26,
for performance improvement on pipelined processors.
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_j1.c,v 1.8 1995/05/10 20:45:27 jtc Exp $";
#endif
/* __ieee754_j1(x), __ieee754_y1(x)
* Bessel function of the first and second kinds of order zero.
* Method -- j1(x):
* 1. For tiny x, we use j1(x) = x/2 - x^3/16 + x^5/384 - ...
* 2. Reduce x to |x| since j1(x)=-j1(-x), and
* for x in (0,2)
* j1(x) = x/2 + x*z*R0/S0, where z = x*x;
* (precision: |j1/x - 1/2 - R0/S0 |<2**-61.51 )
* for x in (2,inf)
* j1(x) = sqrt(2/(pi*x))*(p1(x)*cos(x1)-q1(x)*sin(x1))
* y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x1)+q1(x)*cos(x1))
* where x1 = x-3*pi/4. It is better to compute sin(x1),cos(x1)
* as follow:
* cos(x1) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4)
* = 1/sqrt(2) * (sin(x) - cos(x))
* sin(x1) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
* = -1/sqrt(2) * (sin(x) + cos(x))
* (To avoid cancellation, use
* sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
* to compute the worse one.)
*
* 3 Special cases
* j1(nan)= nan
* j1(0) = 0
* j1(inf) = 0
*
* Method -- y1(x):
* 1. screen out x<=0 cases: y1(0)=-inf, y1(x<0)=NaN
* 2. For x<2.
* Since
* y1(x) = 2/pi*(j1(x)*(ln(x/2)+Euler)-1/x-x/2+5/64*x^3-...)
* therefore y1(x)-2/pi*j1(x)*ln(x)-1/x is an odd function.
* We use the following function to approximate y1,
* y1(x) = x*U(z)/V(z) + (2/pi)*(j1(x)*ln(x)-1/x), z= x^2
* where for x in [0,2] (abs err less than 2**-65.89)
* U(z) = U0[0] + U0[1]*z + ... + U0[4]*z^4
* V(z) = 1 + v0[0]*z + ... + v0[4]*z^5
* Note: For tiny x, 1/x dominate y1 and hence
* y1(tiny) = -2/pi/tiny, (choose tiny<2**-54)
* 3. For x>=2.
* y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x1)+q1(x)*cos(x1))
* where x1 = x-3*pi/4. It is better to compute sin(x1),cos(x1)
* by method mentioned above.
*/
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static double pone(double), qone(double);
#else
static double pone(), qone();
#endif
#ifdef __STDC__
static const double
#else
static double
#endif
huge = 1e300,
one = 1.0,
invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */
tpi = 6.36619772367581382433e-01, /* 0x3FE45F30, 0x6DC9C883 */
/* R0/S0 on [0,2] */
R[] = {-6.25000000000000000000e-02, /* 0xBFB00000, 0x00000000 */
1.40705666955189706048e-03, /* 0x3F570D9F, 0x98472C61 */
-1.59955631084035597520e-05, /* 0xBEF0C5C6, 0xBA169668 */
4.96727999609584448412e-08}, /* 0x3E6AAAFA, 0x46CA0BD9 */
S[] = {0.0, 1.91537599538363460805e-02, /* 0x3F939D0B, 0x12637E53 */
1.85946785588630915560e-04, /* 0x3F285F56, 0xB9CDF664 */
1.17718464042623683263e-06, /* 0x3EB3BFF8, 0x333F8498 */
5.04636257076217042715e-09, /* 0x3E35AC88, 0xC97DFF2C */
1.23542274426137913908e-11}; /* 0x3DAB2ACF, 0xCFB97ED8 */
#ifdef __STDC__
static const double zero = 0.0;
#else
static double zero = 0.0;
#endif
#ifdef __STDC__
double __ieee754_j1(double x)
#else
double __ieee754_j1(x)
double x;
#endif
{
double z, s,c,ss,cc,r,u,v,y,r1,r2,s1,s2,s3,z2,z4;
int32_t hx,ix;
GET_HIGH_WORD(hx,x);
ix = hx&0x7fffffff;
if(ix>=0x7ff00000) return one/x;
y = fabs(x);
if(ix >= 0x40000000) { /* |x| >= 2.0 */
__sincos (y, &s, &c);
ss = -s-c;
cc = s-c;
if(ix<0x7fe00000) { /* make sure y+y not overflow */
z = __cos(y+y);
if ((s*c)>zero) cc = z/ss;
else ss = z/cc;
}
/*
* j1(x) = 1/sqrt(pi) * (P(1,x)*cc - Q(1,x)*ss) / sqrt(x)
* y1(x) = 1/sqrt(pi) * (P(1,x)*ss + Q(1,x)*cc) / sqrt(x)
*/
if(ix>0x48000000) z = (invsqrtpi*cc)/__ieee754_sqrt(y);
else {
u = pone(y); v = qone(y);
z = invsqrtpi*(u*cc-v*ss)/__ieee754_sqrt(y);
}
if(hx<0) return -z;
else return z;
}
if(ix<0x3e400000) { /* |x|<2**-27 */
if(huge+x>one) return 0.5*x;/* inexact if x!=0 necessary */
}
z = x*x;
#ifdef DO_NOT_USE_THIS
r = z*(r00+z*(r01+z*(r02+z*r03)));
s = one+z*(s01+z*(s02+z*(s03+z*(s04+z*s05))));
r *= x;
#else
r1 = z*R[0]; z2=z*z;
r2 = R[1]+z*R[2]; z4=z2*z2;
r = r1 + z2*r2 + z4*R[3];
r *= x;
s1 = one+z*S[1];
s2 = S[2]+z*S[3];
s3 = S[4]+z*S[5];
s = s1 + z2*s2 + z4*s3;
#endif
return(x*0.5+r/s);
}
#ifdef __STDC__
static const double U0[5] = {
#else
static double U0[5] = {
#endif
-1.96057090646238940668e-01, /* 0xBFC91866, 0x143CBC8A */
5.04438716639811282616e-02, /* 0x3FA9D3C7, 0x76292CD1 */
-1.91256895875763547298e-03, /* 0xBF5F55E5, 0x4844F50F */
2.35252600561610495928e-05, /* 0x3EF8AB03, 0x8FA6B88E */
-9.19099158039878874504e-08, /* 0xBE78AC00, 0x569105B8 */
};
#ifdef __STDC__
static const double V0[5] = {
#else
static double V0[5] = {
#endif
1.99167318236649903973e-02, /* 0x3F94650D, 0x3F4DA9F0 */
2.02552581025135171496e-04, /* 0x3F2A8C89, 0x6C257764 */
1.35608801097516229404e-06, /* 0x3EB6C05A, 0x894E8CA6 */
6.22741452364621501295e-09, /* 0x3E3ABF1D, 0x5BA69A86 */
1.66559246207992079114e-11, /* 0x3DB25039, 0xDACA772A */
};
#ifdef __STDC__
double __ieee754_y1(double x)
#else
double __ieee754_y1(x)
double x;
#endif
{
double z, s,c,ss,cc,u,v,u1,u2,v1,v2,v3,z2,z4;
int32_t hx,ix,lx;
EXTRACT_WORDS(hx,lx,x);
ix = 0x7fffffff&hx;
/* if Y1(NaN) is NaN, Y1(-inf) is NaN, Y1(inf) is 0 */
if(ix>=0x7ff00000) return one/(x+x*x);
if((ix|lx)==0) return -one/zero;
if(hx<0) return zero/zero;
if(ix >= 0x40000000) { /* |x| >= 2.0 */
__sincos (x, &s, &c);
ss = -s-c;
cc = s-c;
if(ix<0x7fe00000) { /* make sure x+x not overflow */
z = __cos(x+x);
if ((s*c)>zero) cc = z/ss;
else ss = z/cc;
}
/* y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x0)+q1(x)*cos(x0))
* where x0 = x-3pi/4
* Better formula:
* cos(x0) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4)
* = 1/sqrt(2) * (sin(x) - cos(x))
* sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
* = -1/sqrt(2) * (cos(x) + sin(x))
* To avoid cancellation, use
* sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
* to compute the worse one.
*/
if(ix>0x48000000) z = (invsqrtpi*ss)/__ieee754_sqrt(x);
else {
u = pone(x); v = qone(x);
z = invsqrtpi*(u*ss+v*cc)/__ieee754_sqrt(x);
}
return z;
}
if(ix<=0x3c900000) { /* x < 2**-54 */
return(-tpi/x);
}
z = x*x;
#ifdef DO_NOT_USE_THIS
u = U0[0]+z*(U0[1]+z*(U0[2]+z*(U0[3]+z*U0[4])));
v = one+z*(V0[0]+z*(V0[1]+z*(V0[2]+z*(V0[3]+z*V0[4]))));
#else
u1 = U0[0]+z*U0[1];z2=z*z;
u2 = U0[2]+z*U0[3];z4=z2*z2;
u = u1 + z2*u2 + z4*U0[4];
v1 = one+z*V0[0];
v2 = V0[1]+z*V0[2];
v3 = V0[3]+z*V0[4];
v = v1 + z2*v2 + z4*v3;
#endif
return(x*(u/v) + tpi*(__ieee754_j1(x)*__ieee754_log(x)-one/x));
}
/* For x >= 8, the asymptotic expansions of pone is
* 1 + 15/128 s^2 - 4725/2^15 s^4 - ..., where s = 1/x.
* We approximate pone by
* pone(x) = 1 + (R/S)
* where R = pr0 + pr1*s^2 + pr2*s^4 + ... + pr5*s^10
* S = 1 + ps0*s^2 + ... + ps4*s^10
* and
* | pone(x)-1-R/S | <= 2 ** ( -60.06)
*/
#ifdef __STDC__
static const double pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
#else
static double pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
#endif
0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
1.17187499999988647970e-01, /* 0x3FBDFFFF, 0xFFFFFCCE */
1.32394806593073575129e+01, /* 0x402A7A9D, 0x357F7FCE */
4.12051854307378562225e+02, /* 0x4079C0D4, 0x652EA590 */
3.87474538913960532227e+03, /* 0x40AE457D, 0xA3A532CC */
7.91447954031891731574e+03, /* 0x40BEEA7A, 0xC32782DD */
};
#ifdef __STDC__
static const double ps8[5] = {
#else
static double ps8[5] = {
#endif
1.14207370375678408436e+02, /* 0x405C8D45, 0x8E656CAC */
3.65093083420853463394e+03, /* 0x40AC85DC, 0x964D274F */
3.69562060269033463555e+04, /* 0x40E20B86, 0x97C5BB7F */
9.76027935934950801311e+04, /* 0x40F7D42C, 0xB28F17BB */
3.08042720627888811578e+04, /* 0x40DE1511, 0x697A0B2D */
};
#ifdef __STDC__
static const double pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
#else
static double pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
#endif
1.31990519556243522749e-11, /* 0x3DAD0667, 0xDAE1CA7D */
1.17187493190614097638e-01, /* 0x3FBDFFFF, 0xE2C10043 */
6.80275127868432871736e+00, /* 0x401B3604, 0x6E6315E3 */
1.08308182990189109773e+02, /* 0x405B13B9, 0x452602ED */
5.17636139533199752805e+02, /* 0x40802D16, 0xD052D649 */
5.28715201363337541807e+02, /* 0x408085B8, 0xBB7E0CB7 */
};
#ifdef __STDC__
static const double ps5[5] = {
#else
static double ps5[5] = {
#endif
5.92805987221131331921e+01, /* 0x404DA3EA, 0xA8AF633D */
9.91401418733614377743e+02, /* 0x408EFB36, 0x1B066701 */
5.35326695291487976647e+03, /* 0x40B4E944, 0x5706B6FB */
7.84469031749551231769e+03, /* 0x40BEA4B0, 0xB8A5BB15 */
1.50404688810361062679e+03, /* 0x40978030, 0x036F5E51 */
};
#ifdef __STDC__
static const double pr3[6] = {
#else
static double pr3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
#endif
3.02503916137373618024e-09, /* 0x3E29FC21, 0xA7AD9EDD */
1.17186865567253592491e-01, /* 0x3FBDFFF5, 0x5B21D17B */
3.93297750033315640650e+00, /* 0x400F76BC, 0xE85EAD8A */
3.51194035591636932736e+01, /* 0x40418F48, 0x9DA6D129 */
9.10550110750781271918e+01, /* 0x4056C385, 0x4D2C1837 */
4.85590685197364919645e+01, /* 0x4048478F, 0x8EA83EE5 */
};
#ifdef __STDC__
static const double ps3[5] = {
#else
static double ps3[5] = {
#endif
3.47913095001251519989e+01, /* 0x40416549, 0xA134069C */
3.36762458747825746741e+02, /* 0x40750C33, 0x07F1A75F */
1.04687139975775130551e+03, /* 0x40905B7C, 0x5037D523 */
8.90811346398256432622e+02, /* 0x408BD67D, 0xA32E31E9 */
1.03787932439639277504e+02, /* 0x4059F26D, 0x7C2EED53 */
};
#ifdef __STDC__
static const double pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
#else
static double pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
#endif
1.07710830106873743082e-07, /* 0x3E7CE9D4, 0xF65544F4 */
1.17176219462683348094e-01, /* 0x3FBDFF42, 0xBE760D83 */
2.36851496667608785174e+00, /* 0x4002F2B7, 0xF98FAEC0 */
1.22426109148261232917e+01, /* 0x40287C37, 0x7F71A964 */
1.76939711271687727390e+01, /* 0x4031B1A8, 0x177F8EE2 */
5.07352312588818499250e+00, /* 0x40144B49, 0xA574C1FE */
};
#ifdef __STDC__
static const double ps2[5] = {
#else
static double ps2[5] = {
#endif
2.14364859363821409488e+01, /* 0x40356FBD, 0x8AD5ECDC */
1.25290227168402751090e+02, /* 0x405F5293, 0x14F92CD5 */
2.32276469057162813669e+02, /* 0x406D08D8, 0xD5A2DBD9 */
1.17679373287147100768e+02, /* 0x405D6B7A, 0xDA1884A9 */
8.36463893371618283368e+00, /* 0x4020BAB1, 0xF44E5192 */
};
#ifdef __STDC__
static double pone(double x)
#else
static double pone(x)
double x;
#endif
{
#ifdef __STDC__
const double *p,*q;
#else
double *p,*q;
#endif
double z,r,s,r1,r2,r3,s1,s2,s3,z2,z4;
int32_t ix;
GET_HIGH_WORD(ix,x);
ix &= 0x7fffffff;
if(ix>=0x40200000) {p = pr8; q= ps8;}
else if(ix>=0x40122E8B){p = pr5; q= ps5;}
else if(ix>=0x4006DB6D){p = pr3; q= ps3;}
else if(ix>=0x40000000){p = pr2; q= ps2;}
z = one/(x*x);
#ifdef DO_NOT_USE_THIS
r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4]))));
#else
r1 = p[0]+z*p[1]; z2=z*z;
r2 = p[2]+z*p[3]; z4=z2*z2;
r3 = p[4]+z*p[5];
r = r1 + z2*r2 + z4*r3;
s1 = one+z*q[0];
s2 = q[1]+z*q[2];
s3 = q[3]+z*q[4];
s = s1 + z2*s2 + z4*s3;
#endif
return one+ r/s;
}
/* For x >= 8, the asymptotic expansions of qone is
* 3/8 s - 105/1024 s^3 - ..., where s = 1/x.
* We approximate pone by
* qone(x) = s*(0.375 + (R/S))
* where R = qr1*s^2 + qr2*s^4 + ... + qr5*s^10
* S = 1 + qs1*s^2 + ... + qs6*s^12
* and
* | qone(x)/s -0.375-R/S | <= 2 ** ( -61.13)
*/
#ifdef __STDC__
static const double qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
#else
static double qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
#endif
0.00000000000000000000e+00, /* 0x00000000, 0x00000000 */
-1.02539062499992714161e-01, /* 0xBFBA3FFF, 0xFFFFFDF3 */
-1.62717534544589987888e+01, /* 0xC0304591, 0xA26779F7 */
-7.59601722513950107896e+02, /* 0xC087BCD0, 0x53E4B576 */
-1.18498066702429587167e+04, /* 0xC0C724E7, 0x40F87415 */
-4.84385124285750353010e+04, /* 0xC0E7A6D0, 0x65D09C6A */
};
#ifdef __STDC__
static const double qs8[6] = {
#else
static double qs8[6] = {
#endif
1.61395369700722909556e+02, /* 0x40642CA6, 0xDE5BCDE5 */
7.82538599923348465381e+03, /* 0x40BE9162, 0xD0D88419 */
1.33875336287249578163e+05, /* 0x4100579A, 0xB0B75E98 */
7.19657723683240939863e+05, /* 0x4125F653, 0x72869C19 */
6.66601232617776375264e+05, /* 0x412457D2, 0x7719AD5C */
-2.94490264303834643215e+05, /* 0xC111F969, 0x0EA5AA18 */
};
#ifdef __STDC__
static const double qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
#else
static double qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
#endif
-2.08979931141764104297e-11, /* 0xBDB6FA43, 0x1AA1A098 */
-1.02539050241375426231e-01, /* 0xBFBA3FFF, 0xCB597FEF */
-8.05644828123936029840e+00, /* 0xC0201CE6, 0xCA03AD4B */
-1.83669607474888380239e+02, /* 0xC066F56D, 0x6CA7B9B0 */
-1.37319376065508163265e+03, /* 0xC09574C6, 0x6931734F */
-2.61244440453215656817e+03, /* 0xC0A468E3, 0x88FDA79D */
};
#ifdef __STDC__
static const double qs5[6] = {
#else
static double qs5[6] = {
#endif
8.12765501384335777857e+01, /* 0x405451B2, 0xFF5A11B2 */
1.99179873460485964642e+03, /* 0x409F1F31, 0xE77BF839 */
1.74684851924908907677e+04, /* 0x40D10F1F, 0x0D64CE29 */
4.98514270910352279316e+04, /* 0x40E8576D, 0xAABAD197 */
2.79480751638918118260e+04, /* 0x40DB4B04, 0xCF7C364B */
-4.71918354795128470869e+03, /* 0xC0B26F2E, 0xFCFFA004 */
};
#ifdef __STDC__
static const double qr3[6] = {
#else
static double qr3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
#endif
-5.07831226461766561369e-09, /* 0xBE35CFA9, 0xD38FC84F */
-1.02537829820837089745e-01, /* 0xBFBA3FEB, 0x51AEED54 */
-4.61011581139473403113e+00, /* 0xC01270C2, 0x3302D9FF */
-5.78472216562783643212e+01, /* 0xC04CEC71, 0xC25D16DA */
-2.28244540737631695038e+02, /* 0xC06C87D3, 0x4718D55F */
-2.19210128478909325622e+02, /* 0xC06B66B9, 0x5F5C1BF6 */
};
#ifdef __STDC__
static const double qs3[6] = {
#else
static double qs3[6] = {
#endif
4.76651550323729509273e+01, /* 0x4047D523, 0xCCD367E4 */
6.73865112676699709482e+02, /* 0x40850EEB, 0xC031EE3E */
3.38015286679526343505e+03, /* 0x40AA684E, 0x448E7C9A */
5.54772909720722782367e+03, /* 0x40B5ABBA, 0xA61D54A6 */
1.90311919338810798763e+03, /* 0x409DBC7A, 0x0DD4DF4B */
-1.35201191444307340817e+02, /* 0xC060E670, 0x290A311F */
};
#ifdef __STDC__
static const double qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
#else
static double qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
#endif
-1.78381727510958865572e-07, /* 0xBE87F126, 0x44C626D2 */
-1.02517042607985553460e-01, /* 0xBFBA3E8E, 0x9148B010 */
-2.75220568278187460720e+00, /* 0xC0060484, 0x69BB4EDA */
-1.96636162643703720221e+01, /* 0xC033A9E2, 0xC168907F */
-4.23253133372830490089e+01, /* 0xC04529A3, 0xDE104AAA */
-2.13719211703704061733e+01, /* 0xC0355F36, 0x39CF6E52 */
};
#ifdef __STDC__
static const double qs2[6] = {
#else
static double qs2[6] = {
#endif
2.95333629060523854548e+01, /* 0x403D888A, 0x78AE64FF */
2.52981549982190529136e+02, /* 0x406F9F68, 0xDB821CBA */
7.57502834868645436472e+02, /* 0x4087AC05, 0xCE49A0F7 */
7.39393205320467245656e+02, /* 0x40871B25, 0x48D4C029 */
1.55949003336666123687e+02, /* 0x40637E5E, 0x3C3ED8D4 */
-4.95949898822628210127e+00, /* 0xC013D686, 0xE71BE86B */
};
#ifdef __STDC__
static double qone(double x)
#else
static double qone(x)
double x;
#endif
{
#ifdef __STDC__
const double *p,*q;
#else
double *p,*q;
#endif
double s,r,z,r1,r2,r3,s1,s2,s3,z2,z4,z6;
int32_t ix;
GET_HIGH_WORD(ix,x);
ix &= 0x7fffffff;
if(ix>=0x40200000) {p = qr8; q= qs8;}
else if(ix>=0x40122E8B){p = qr5; q= qs5;}
else if(ix>=0x4006DB6D){p = qr3; q= qs3;}
else if(ix>=0x40000000){p = qr2; q= qs2;}
z = one/(x*x);
#ifdef DO_NOT_USE_THIS
r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5])))));
#else
r1 = p[0]+z*p[1]; z2=z*z;
r2 = p[2]+z*p[3]; z4=z2*z2;
r3 = p[4]+z*p[5]; z6=z4*z2;
r = r1 + z2*r2 + z4*r3;
s1 = one+z*q[0];
s2 = q[1]+z*q[2];
s3 = q[3]+z*q[4];
s = s1 + z2*s2 + z4*s3 + z6*q[5];
#endif
return (.375 + r/s)/x;
}
@@ -0,0 +1,442 @@
/* e_j1f.c -- float version of e_j1.c.
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
*/
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_j1f.c,v 1.4 1995/05/10 20:45:31 jtc Exp $";
#endif
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static float ponef(float), qonef(float);
#else
static float ponef(), qonef();
#endif
#ifdef __STDC__
static const float
#else
static float
#endif
huge = 1e30,
one = 1.0,
invsqrtpi= 5.6418961287e-01, /* 0x3f106ebb */
tpi = 6.3661974669e-01, /* 0x3f22f983 */
/* R0/S0 on [0,2] */
r00 = -6.2500000000e-02, /* 0xbd800000 */
r01 = 1.4070566976e-03, /* 0x3ab86cfd */
r02 = -1.5995563444e-05, /* 0xb7862e36 */
r03 = 4.9672799207e-08, /* 0x335557d2 */
s01 = 1.9153760746e-02, /* 0x3c9ce859 */
s02 = 1.8594678841e-04, /* 0x3942fab6 */
s03 = 1.1771846857e-06, /* 0x359dffc2 */
s04 = 5.0463624390e-09, /* 0x31ad6446 */
s05 = 1.2354227016e-11; /* 0x2d59567e */
#ifdef __STDC__
static const float zero = 0.0;
#else
static float zero = 0.0;
#endif
#ifdef __STDC__
float __ieee754_j1f(float x)
#else
float __ieee754_j1f(x)
float x;
#endif
{
float z, s,c,ss,cc,r,u,v,y;
int32_t hx,ix;
GET_FLOAT_WORD(hx,x);
ix = hx&0x7fffffff;
if(ix>=0x7f800000) return one/x;
y = fabsf(x);
if(ix >= 0x40000000) { /* |x| >= 2.0 */
__sincosf (y, &s, &c);
ss = -s-c;
cc = s-c;
if(ix<0x7f000000) { /* make sure y+y not overflow */
z = __cosf(y+y);
if ((s*c)>zero) cc = z/ss;
else ss = z/cc;
}
/*
* j1(x) = 1/sqrt(pi) * (P(1,x)*cc - Q(1,x)*ss) / sqrt(x)
* y1(x) = 1/sqrt(pi) * (P(1,x)*ss + Q(1,x)*cc) / sqrt(x)
*/
if(ix>0x48000000) z = (invsqrtpi*cc)/__ieee754_sqrtf(y);
else {
u = ponef(y); v = qonef(y);
z = invsqrtpi*(u*cc-v*ss)/__ieee754_sqrtf(y);
}
if(hx<0) return -z;
else return z;
}
if(ix<0x32000000) { /* |x|<2**-27 */
if(huge+x>one) return (float)0.5*x;/* inexact if x!=0 necessary */
}
z = x*x;
r = z*(r00+z*(r01+z*(r02+z*r03)));
s = one+z*(s01+z*(s02+z*(s03+z*(s04+z*s05))));
r *= x;
return(x*(float)0.5+r/s);
}
#ifdef __STDC__
static const float U0[5] = {
#else
static float U0[5] = {
#endif
-1.9605709612e-01, /* 0xbe48c331 */
5.0443872809e-02, /* 0x3d4e9e3c */
-1.9125689287e-03, /* 0xbafaaf2a */
2.3525259166e-05, /* 0x37c5581c */
-9.1909917899e-08, /* 0xb3c56003 */
};
#ifdef __STDC__
static const float V0[5] = {
#else
static float V0[5] = {
#endif
1.9916731864e-02, /* 0x3ca3286a */
2.0255257550e-04, /* 0x3954644b */
1.3560879779e-06, /* 0x35b602d4 */
6.2274145840e-09, /* 0x31d5f8eb */
1.6655924903e-11, /* 0x2d9281cf */
};
#ifdef __STDC__
float __ieee754_y1f(float x)
#else
float __ieee754_y1f(x)
float x;
#endif
{
float z, s,c,ss,cc,u,v;
int32_t hx,ix;
GET_FLOAT_WORD(hx,x);
ix = 0x7fffffff&hx;
/* if Y1(NaN) is NaN, Y1(-inf) is NaN, Y1(inf) is 0 */
if(ix>=0x7f800000) return one/(x+x*x);
if(ix==0) return -one/zero;
if(hx<0) return zero/zero;
if(ix >= 0x40000000) { /* |x| >= 2.0 */
__sincosf (x, &s, &c);
ss = -s-c;
cc = s-c;
if(ix<0x7f000000) { /* make sure x+x not overflow */
z = __cosf(x+x);
if ((s*c)>zero) cc = z/ss;
else ss = z/cc;
}
/* y1(x) = sqrt(2/(pi*x))*(p1(x)*sin(x0)+q1(x)*cos(x0))
* where x0 = x-3pi/4
* Better formula:
* cos(x0) = cos(x)cos(3pi/4)+sin(x)sin(3pi/4)
* = 1/sqrt(2) * (sin(x) - cos(x))
* sin(x0) = sin(x)cos(3pi/4)-cos(x)sin(3pi/4)
* = -1/sqrt(2) * (cos(x) + sin(x))
* To avoid cancellation, use
* sin(x) +- cos(x) = -cos(2x)/(sin(x) -+ cos(x))
* to compute the worse one.
*/
if(ix>0x48000000) z = (invsqrtpi*ss)/__ieee754_sqrtf(x);
else {
u = ponef(x); v = qonef(x);
z = invsqrtpi*(u*ss+v*cc)/__ieee754_sqrtf(x);
}
return z;
}
if(ix<=0x24800000) { /* x < 2**-54 */
return(-tpi/x);
}
z = x*x;
u = U0[0]+z*(U0[1]+z*(U0[2]+z*(U0[3]+z*U0[4])));
v = one+z*(V0[0]+z*(V0[1]+z*(V0[2]+z*(V0[3]+z*V0[4]))));
return(x*(u/v) + tpi*(__ieee754_j1f(x)*__ieee754_logf(x)-one/x));
}
/* For x >= 8, the asymptotic expansions of pone is
* 1 + 15/128 s^2 - 4725/2^15 s^4 - ..., where s = 1/x.
* We approximate pone by
* pone(x) = 1 + (R/S)
* where R = pr0 + pr1*s^2 + pr2*s^4 + ... + pr5*s^10
* S = 1 + ps0*s^2 + ... + ps4*s^10
* and
* | pone(x)-1-R/S | <= 2 ** ( -60.06)
*/
#ifdef __STDC__
static const float pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
#else
static float pr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
#endif
0.0000000000e+00, /* 0x00000000 */
1.1718750000e-01, /* 0x3df00000 */
1.3239480972e+01, /* 0x4153d4ea */
4.1205184937e+02, /* 0x43ce06a3 */
3.8747453613e+03, /* 0x45722bed */
7.9144794922e+03, /* 0x45f753d6 */
};
#ifdef __STDC__
static const float ps8[5] = {
#else
static float ps8[5] = {
#endif
1.1420736694e+02, /* 0x42e46a2c */
3.6509309082e+03, /* 0x45642ee5 */
3.6956207031e+04, /* 0x47105c35 */
9.7602796875e+04, /* 0x47bea166 */
3.0804271484e+04, /* 0x46f0a88b */
};
#ifdef __STDC__
static const float pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
#else
static float pr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
#endif
1.3199052094e-11, /* 0x2d68333f */
1.1718749255e-01, /* 0x3defffff */
6.8027510643e+00, /* 0x40d9b023 */
1.0830818176e+02, /* 0x42d89dca */
5.1763616943e+02, /* 0x440168b7 */
5.2871520996e+02, /* 0x44042dc6 */
};
#ifdef __STDC__
static const float ps5[5] = {
#else
static float ps5[5] = {
#endif
5.9280597687e+01, /* 0x426d1f55 */
9.9140142822e+02, /* 0x4477d9b1 */
5.3532670898e+03, /* 0x45a74a23 */
7.8446904297e+03, /* 0x45f52586 */
1.5040468750e+03, /* 0x44bc0180 */
};
#ifdef __STDC__
static const float pr3[6] = {
#else
static float pr3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
#endif
3.0250391081e-09, /* 0x314fe10d */
1.1718686670e-01, /* 0x3defffab */
3.9329774380e+00, /* 0x407bb5e7 */
3.5119403839e+01, /* 0x420c7a45 */
9.1055007935e+01, /* 0x42b61c2a */
4.8559066772e+01, /* 0x42423c7c */
};
#ifdef __STDC__
static const float ps3[5] = {
#else
static float ps3[5] = {
#endif
3.4791309357e+01, /* 0x420b2a4d */
3.3676245117e+02, /* 0x43a86198 */
1.0468714600e+03, /* 0x4482dbe3 */
8.9081134033e+02, /* 0x445eb3ed */
1.0378793335e+02, /* 0x42cf936c */
};
#ifdef __STDC__
static const float pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
#else
static float pr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
#endif
1.0771083225e-07, /* 0x33e74ea8 */
1.1717621982e-01, /* 0x3deffa16 */
2.3685150146e+00, /* 0x401795c0 */
1.2242610931e+01, /* 0x4143e1bc */
1.7693971634e+01, /* 0x418d8d41 */
5.0735230446e+00, /* 0x40a25a4d */
};
#ifdef __STDC__
static const float ps2[5] = {
#else
static float ps2[5] = {
#endif
2.1436485291e+01, /* 0x41ab7dec */
1.2529022980e+02, /* 0x42fa9499 */
2.3227647400e+02, /* 0x436846c7 */
1.1767937469e+02, /* 0x42eb5bd7 */
8.3646392822e+00, /* 0x4105d590 */
};
#ifdef __STDC__
static float ponef(float x)
#else
static float ponef(x)
float x;
#endif
{
#ifdef __STDC__
const float *p,*q;
#else
float *p,*q;
#endif
float z,r,s;
int32_t ix;
GET_FLOAT_WORD(ix,x);
ix &= 0x7fffffff;
if(ix>=0x41000000) {p = pr8; q= ps8;}
else if(ix>=0x40f71c58){p = pr5; q= ps5;}
else if(ix>=0x4036db68){p = pr3; q= ps3;}
else if(ix>=0x40000000){p = pr2; q= ps2;}
z = one/(x*x);
r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*q[4]))));
return one+ r/s;
}
/* For x >= 8, the asymptotic expansions of qone is
* 3/8 s - 105/1024 s^3 - ..., where s = 1/x.
* We approximate pone by
* qone(x) = s*(0.375 + (R/S))
* where R = qr1*s^2 + qr2*s^4 + ... + qr5*s^10
* S = 1 + qs1*s^2 + ... + qs6*s^12
* and
* | qone(x)/s -0.375-R/S | <= 2 ** ( -61.13)
*/
#ifdef __STDC__
static const float qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
#else
static float qr8[6] = { /* for x in [inf, 8]=1/[0,0.125] */
#endif
0.0000000000e+00, /* 0x00000000 */
-1.0253906250e-01, /* 0xbdd20000 */
-1.6271753311e+01, /* 0xc1822c8d */
-7.5960174561e+02, /* 0xc43de683 */
-1.1849806641e+04, /* 0xc639273a */
-4.8438511719e+04, /* 0xc73d3683 */
};
#ifdef __STDC__
static const float qs8[6] = {
#else
static float qs8[6] = {
#endif
1.6139537048e+02, /* 0x43216537 */
7.8253862305e+03, /* 0x45f48b17 */
1.3387534375e+05, /* 0x4802bcd6 */
7.1965775000e+05, /* 0x492fb29c */
6.6660125000e+05, /* 0x4922be94 */
-2.9449025000e+05, /* 0xc88fcb48 */
};
#ifdef __STDC__
static const float qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
#else
static float qr5[6] = { /* for x in [8,4.5454]=1/[0.125,0.22001] */
#endif
-2.0897993405e-11, /* 0xadb7d219 */
-1.0253904760e-01, /* 0xbdd1fffe */
-8.0564479828e+00, /* 0xc100e736 */
-1.8366960144e+02, /* 0xc337ab6b */
-1.3731937256e+03, /* 0xc4aba633 */
-2.6124443359e+03, /* 0xc523471c */
};
#ifdef __STDC__
static const float qs5[6] = {
#else
static float qs5[6] = {
#endif
8.1276550293e+01, /* 0x42a28d98 */
1.9917987061e+03, /* 0x44f8f98f */
1.7468484375e+04, /* 0x468878f8 */
4.9851425781e+04, /* 0x4742bb6d */
2.7948074219e+04, /* 0x46da5826 */
-4.7191835938e+03, /* 0xc5937978 */
};
#ifdef __STDC__
static const float qr3[6] = {
#else
static float qr3[6] = {/* for x in [4.547,2.8571]=1/[0.2199,0.35001] */
#endif
-5.0783124372e-09, /* 0xb1ae7d4f */
-1.0253783315e-01, /* 0xbdd1ff5b */
-4.6101160049e+00, /* 0xc0938612 */
-5.7847221375e+01, /* 0xc267638e */
-2.2824453735e+02, /* 0xc3643e9a */
-2.1921012878e+02, /* 0xc35b35cb */
};
#ifdef __STDC__
static const float qs3[6] = {
#else
static float qs3[6] = {
#endif
4.7665153503e+01, /* 0x423ea91e */
6.7386511230e+02, /* 0x4428775e */
3.3801528320e+03, /* 0x45534272 */
5.5477290039e+03, /* 0x45ad5dd5 */
1.9031191406e+03, /* 0x44ede3d0 */
-1.3520118713e+02, /* 0xc3073381 */
};
#ifdef __STDC__
static const float qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
#else
static float qr2[6] = {/* for x in [2.8570,2]=1/[0.3499,0.5] */
#endif
-1.7838172539e-07, /* 0xb43f8932 */
-1.0251704603e-01, /* 0xbdd1f475 */
-2.7522056103e+00, /* 0xc0302423 */
-1.9663616180e+01, /* 0xc19d4f16 */
-4.2325313568e+01, /* 0xc2294d1f */
-2.1371921539e+01, /* 0xc1aaf9b2 */
};
#ifdef __STDC__
static const float qs2[6] = {
#else
static float qs2[6] = {
#endif
2.9533363342e+01, /* 0x41ec4454 */
2.5298155212e+02, /* 0x437cfb47 */
7.5750280762e+02, /* 0x443d602e */
7.3939318848e+02, /* 0x4438d92a */
1.5594900513e+02, /* 0x431bf2f2 */
-4.9594988823e+00, /* 0xc09eb437 */
};
#ifdef __STDC__
static float qonef(float x)
#else
static float qonef(x)
float x;
#endif
{
#ifdef __STDC__
const float *p,*q;
#else
float *p,*q;
#endif
float s,r,z;
int32_t ix;
GET_FLOAT_WORD(ix,x);
ix &= 0x7fffffff;
if(ix>=0x40200000) {p = qr8; q= qs8;}
else if(ix>=0x40f71c58){p = qr5; q= qs5;}
else if(ix>=0x4036db68){p = qr3; q= qs3;}
else if(ix>=0x40000000){p = qr2; q= qs2;}
z = one/(x*x);
r = p[0]+z*(p[1]+z*(p[2]+z*(p[3]+z*(p[4]+z*p[5]))));
s = one+z*(q[0]+z*(q[1]+z*(q[2]+z*(q[3]+z*(q[4]+z*q[5])))));
return ((float).375 + r/s)/x;
}
@@ -0,0 +1,287 @@
/* @(#)e_jn.c 5.1 93/09/24 */
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_jn.c,v 1.9 1995/05/10 20:45:34 jtc Exp $";
#endif
/*
* __ieee754_jn(n, x), __ieee754_yn(n, x)
* floating point Bessel's function of the 1st and 2nd kind
* of order n
*
* Special cases:
* y0(0)=y1(0)=yn(n,0) = -inf with division by zero signal;
* y0(-ve)=y1(-ve)=yn(n,-ve) are NaN with invalid signal.
* Note 2. About jn(n,x), yn(n,x)
* For n=0, j0(x) is called,
* for n=1, j1(x) is called,
* for n<x, forward recursion us used starting
* from values of j0(x) and j1(x).
* for n>x, a continued fraction approximation to
* j(n,x)/j(n-1,x) is evaluated and then backward
* recursion is used starting from a supposed value
* for j(n,x). The resulting value of j(0,x) is
* compared with the actual value to correct the
* supposed value of j(n,x).
*
* yn(n,x) is similar in all respects, except
* that forward recursion is used for all
* values of n>1.
*
*/
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const double
#else
static double
#endif
invsqrtpi= 5.64189583547756279280e-01, /* 0x3FE20DD7, 0x50429B6D */
two = 2.00000000000000000000e+00, /* 0x40000000, 0x00000000 */
one = 1.00000000000000000000e+00; /* 0x3FF00000, 0x00000000 */
#ifdef __STDC__
static const double zero = 0.00000000000000000000e+00;
#else
static double zero = 0.00000000000000000000e+00;
#endif
#ifdef __STDC__
double __ieee754_jn(int n, double x)
#else
double __ieee754_jn(n,x)
int n; double x;
#endif
{
int32_t i,hx,ix,lx, sgn;
double a, b, temp, di;
double z, w;
/* J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x)
* Thus, J(-n,x) = J(n,-x)
*/
EXTRACT_WORDS(hx,lx,x);
ix = 0x7fffffff&hx;
/* if J(n,NaN) is NaN */
if((ix|((u_int32_t)(lx|-lx))>>31)>0x7ff00000) return x+x;
if(n<0){
n = -n;
x = -x;
hx ^= 0x80000000;
}
if(n==0) return(__ieee754_j0(x));
if(n==1) return(__ieee754_j1(x));
sgn = (n&1)&(hx>>31); /* even n -- 0, odd n -- sign(x) */
x = fabs(x);
if((ix|lx)==0||ix>=0x7ff00000) /* if x is 0 or inf */
b = zero;
else if((double)n<=x) {
/* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */
if(ix>=0x52D00000) { /* x > 2**302 */
/* (x >> n**2)
* Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi)
* Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi)
* Let s=sin(x), c=cos(x),
* xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then
*
* n sin(xn)*sqt2 cos(xn)*sqt2
* ----------------------------------
* 0 s-c c+s
* 1 -s-c -c+s
* 2 -s+c -c-s
* 3 s+c c-s
*/
double s;
double c;
__sincos (x, &s, &c);
switch(n&3) {
case 0: temp = c + s; break;
case 1: temp = -c + s; break;
case 2: temp = -c - s; break;
case 3: temp = c - s; break;
}
b = invsqrtpi*temp/__ieee754_sqrt(x);
} else {
a = __ieee754_j0(x);
b = __ieee754_j1(x);
for(i=1;i<n;i++){
temp = b;
b = b*((double)(i+i)/x) - a; /* avoid underflow */
a = temp;
}
}
} else {
if(ix<0x3e100000) { /* x < 2**-29 */
/* x is tiny, return the first Taylor expansion of J(n,x)
* J(n,x) = 1/n!*(x/2)^n - ...
*/
if(n>33) /* underflow */
b = zero;
else {
temp = x*0.5; b = temp;
for (a=one,i=2;i<=n;i++) {
a *= (double)i; /* a = n! */
b *= temp; /* b = (x/2)^n */
}
b = b/a;
}
} else {
/* use backward recurrence */
/* x x^2 x^2
* J(n,x)/J(n-1,x) = ---- ------ ------ .....
* 2n - 2(n+1) - 2(n+2)
*
* 1 1 1
* (for large x) = ---- ------ ------ .....
* 2n 2(n+1) 2(n+2)
* -- - ------ - ------ -
* x x x
*
* Let w = 2n/x and h=2/x, then the above quotient
* is equal to the continued fraction:
* 1
* = -----------------------
* 1
* w - -----------------
* 1
* w+h - ---------
* w+2h - ...
*
* To determine how many terms needed, let
* Q(0) = w, Q(1) = w(w+h) - 1,
* Q(k) = (w+k*h)*Q(k-1) - Q(k-2),
* When Q(k) > 1e4 good for single
* When Q(k) > 1e9 good for double
* When Q(k) > 1e17 good for quadruple
*/
/* determine k */
double t,v;
double q0,q1,h,tmp; int32_t k,m;
w = (n+n)/(double)x; h = 2.0/(double)x;
q0 = w; z = w+h; q1 = w*z - 1.0; k=1;
while(q1<1.0e9) {
k += 1; z += h;
tmp = z*q1 - q0;
q0 = q1;
q1 = tmp;
}
m = n+n;
for(t=zero, i = 2*(n+k); i>=m; i -= 2) t = one/(i/x-t);
a = t;
b = one;
/* estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n)
* Hence, if n*(log(2n/x)) > ...
* single 8.8722839355e+01
* double 7.09782712893383973096e+02
* long double 1.1356523406294143949491931077970765006170e+04
* then recurrent value may overflow and the result is
* likely underflow to zero
*/
tmp = n;
v = two/x;
tmp = tmp*__ieee754_log(fabs(v*tmp));
if(tmp<7.09782712893383973096e+02) {
for(i=n-1,di=(double)(i+i);i>0;i--){
temp = b;
b *= di;
b = b/x - a;
a = temp;
di -= two;
}
} else {
for(i=n-1,di=(double)(i+i);i>0;i--){
temp = b;
b *= di;
b = b/x - a;
a = temp;
di -= two;
/* scale b to avoid spurious overflow */
if(b>1e100) {
a /= b;
t /= b;
b = one;
}
}
}
b = (t*__ieee754_j0(x)/b);
}
}
if(sgn==1) return -b; else return b;
}
#ifdef __STDC__
double __ieee754_yn(int n, double x)
#else
double __ieee754_yn(n,x)
int n; double x;
#endif
{
int32_t i,hx,ix,lx;
int32_t sign;
double a, b, temp;
EXTRACT_WORDS(hx,lx,x);
ix = 0x7fffffff&hx;
/* if Y(n,NaN) is NaN */
if((ix|((u_int32_t)(lx|-lx))>>31)>0x7ff00000) return x+x;
if((ix|lx)==0) return -one/zero;
if(hx<0) return zero/zero;
sign = 1;
if(n<0){
n = -n;
sign = 1 - ((n&1)<<1);
}
if(n==0) return(__ieee754_y0(x));
if(n==1) return(sign*__ieee754_y1(x));
if(ix==0x7ff00000) return zero;
if(ix>=0x52D00000) { /* x > 2**302 */
/* (x >> n**2)
* Jn(x) = cos(x-(2n+1)*pi/4)*sqrt(2/x*pi)
* Yn(x) = sin(x-(2n+1)*pi/4)*sqrt(2/x*pi)
* Let s=sin(x), c=cos(x),
* xn=x-(2n+1)*pi/4, sqt2 = sqrt(2),then
*
* n sin(xn)*sqt2 cos(xn)*sqt2
* ----------------------------------
* 0 s-c c+s
* 1 -s-c -c+s
* 2 -s+c -c-s
* 3 s+c c-s
*/
double c;
double s;
__sincos (x, &s, &c);
switch(n&3) {
case 0: temp = s - c; break;
case 1: temp = -s - c; break;
case 2: temp = -s + c; break;
case 3: temp = s + c; break;
}
b = invsqrtpi*temp/__ieee754_sqrt(x);
} else {
u_int32_t high;
a = __ieee754_y0(x);
b = __ieee754_y1(x);
/* quit if b is -inf */
GET_HIGH_WORD(high,b);
for(i=1;i<n&&high!=0xfff00000;i++){
temp = b;
b = ((double)(i+i)/x)*b - a;
GET_HIGH_WORD(high,b);
a = temp;
}
}
if(sign>0) return b; else return -b;
}
@@ -0,0 +1,212 @@
/* e_jnf.c -- float version of e_jn.c.
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
*/
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_jnf.c,v 1.5 1995/05/10 20:45:37 jtc Exp $";
#endif
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const float
#else
static float
#endif
two = 2.0000000000e+00, /* 0x40000000 */
one = 1.0000000000e+00; /* 0x3F800000 */
#ifdef __STDC__
static const float zero = 0.0000000000e+00;
#else
static float zero = 0.0000000000e+00;
#endif
#ifdef __STDC__
float __ieee754_jnf(int n, float x)
#else
float __ieee754_jnf(n,x)
int n; float x;
#endif
{
int32_t i,hx,ix, sgn;
float a, b, temp, di;
float z, w;
/* J(-n,x) = (-1)^n * J(n, x), J(n, -x) = (-1)^n * J(n, x)
* Thus, J(-n,x) = J(n,-x)
*/
GET_FLOAT_WORD(hx,x);
ix = 0x7fffffff&hx;
/* if J(n,NaN) is NaN */
if(ix>0x7f800000) return x+x;
if(n<0){
n = -n;
x = -x;
hx ^= 0x80000000;
}
if(n==0) return(__ieee754_j0f(x));
if(n==1) return(__ieee754_j1f(x));
sgn = (n&1)&(hx>>31); /* even n -- 0, odd n -- sign(x) */
x = fabsf(x);
if(ix==0||ix>=0x7f800000) /* if x is 0 or inf */
b = zero;
else if((float)n<=x) {
/* Safe to use J(n+1,x)=2n/x *J(n,x)-J(n-1,x) */
a = __ieee754_j0f(x);
b = __ieee754_j1f(x);
for(i=1;i<n;i++){
temp = b;
b = b*((float)(i+i)/x) - a; /* avoid underflow */
a = temp;
}
} else {
if(ix<0x30800000) { /* x < 2**-29 */
/* x is tiny, return the first Taylor expansion of J(n,x)
* J(n,x) = 1/n!*(x/2)^n - ...
*/
if(n>33) /* underflow */
b = zero;
else {
temp = x*(float)0.5; b = temp;
for (a=one,i=2;i<=n;i++) {
a *= (float)i; /* a = n! */
b *= temp; /* b = (x/2)^n */
}
b = b/a;
}
} else {
/* use backward recurrence */
/* x x^2 x^2
* J(n,x)/J(n-1,x) = ---- ------ ------ .....
* 2n - 2(n+1) - 2(n+2)
*
* 1 1 1
* (for large x) = ---- ------ ------ .....
* 2n 2(n+1) 2(n+2)
* -- - ------ - ------ -
* x x x
*
* Let w = 2n/x and h=2/x, then the above quotient
* is equal to the continued fraction:
* 1
* = -----------------------
* 1
* w - -----------------
* 1
* w+h - ---------
* w+2h - ...
*
* To determine how many terms needed, let
* Q(0) = w, Q(1) = w(w+h) - 1,
* Q(k) = (w+k*h)*Q(k-1) - Q(k-2),
* When Q(k) > 1e4 good for single
* When Q(k) > 1e9 good for double
* When Q(k) > 1e17 good for quadruple
*/
/* determine k */
float t,v;
float q0,q1,h,tmp; int32_t k,m;
w = (n+n)/(float)x; h = (float)2.0/(float)x;
q0 = w; z = w+h; q1 = w*z - (float)1.0; k=1;
while(q1<(float)1.0e9) {
k += 1; z += h;
tmp = z*q1 - q0;
q0 = q1;
q1 = tmp;
}
m = n+n;
for(t=zero, i = 2*(n+k); i>=m; i -= 2) t = one/(i/x-t);
a = t;
b = one;
/* estimate log((2/x)^n*n!) = n*log(2/x)+n*ln(n)
* Hence, if n*(log(2n/x)) > ...
* single 8.8722839355e+01
* double 7.09782712893383973096e+02
* long double 1.1356523406294143949491931077970765006170e+04
* then recurrent value may overflow and the result is
* likely underflow to zero
*/
tmp = n;
v = two/x;
tmp = tmp*__ieee754_logf(fabsf(v*tmp));
if(tmp<(float)8.8721679688e+01) {
for(i=n-1,di=(float)(i+i);i>0;i--){
temp = b;
b *= di;
b = b/x - a;
a = temp;
di -= two;
}
} else {
for(i=n-1,di=(float)(i+i);i>0;i--){
temp = b;
b *= di;
b = b/x - a;
a = temp;
di -= two;
/* scale b to avoid spurious overflow */
if(b>(float)1e10) {
a /= b;
t /= b;
b = one;
}
}
}
b = (t*__ieee754_j0f(x)/b);
}
}
if(sgn==1) return -b; else return b;
}
#ifdef __STDC__
float __ieee754_ynf(int n, float x)
#else
float __ieee754_ynf(n,x)
int n; float x;
#endif
{
int32_t i,hx,ix;
u_int32_t ib;
int32_t sign;
float a, b, temp;
GET_FLOAT_WORD(hx,x);
ix = 0x7fffffff&hx;
/* if Y(n,NaN) is NaN */
if(ix>0x7f800000) return x+x;
if(ix==0) return -one/zero;
if(hx<0) return zero/zero;
sign = 1;
if(n<0){
n = -n;
sign = 1 - ((n&1)<<1);
}
if(n==0) return(__ieee754_y0f(x));
if(n==1) return(sign*__ieee754_y1f(x));
if(ix==0x7f800000) return zero;
a = __ieee754_y0f(x);
b = __ieee754_y1f(x);
/* quit if b is -inf */
GET_FLOAT_WORD(ib,b);
for(i=1;i<n&&ib!=0xff800000;i++){
temp = b;
b = ((float)(i+i)/x)*b - a;
GET_FLOAT_WORD(ib,b);
a = temp;
}
if(sign>0) return b; else return -b;
}
@@ -0,0 +1,312 @@
/* @(#)er_lgamma.c 5.1 93/09/24 */
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_lgamma_r.c,v 1.7 1995/05/10 20:45:42 jtc Exp $";
#endif
/* __ieee754_lgamma_r(x, signgamp)
* Reentrant version of the logarithm of the Gamma function
* with user provide pointer for the sign of Gamma(x).
*
* Method:
* 1. Argument Reduction for 0 < x <= 8
* Since gamma(1+s)=s*gamma(s), for x in [0,8], we may
* reduce x to a number in [1.5,2.5] by
* lgamma(1+s) = log(s) + lgamma(s)
* for example,
* lgamma(7.3) = log(6.3) + lgamma(6.3)
* = log(6.3*5.3) + lgamma(5.3)
* = log(6.3*5.3*4.3*3.3*2.3) + lgamma(2.3)
* 2. Polynomial approximation of lgamma around its
* minimun ymin=1.461632144968362245 to maintain monotonicity.
* On [ymin-0.23, ymin+0.27] (i.e., [1.23164,1.73163]), use
* Let z = x-ymin;
* lgamma(x) = -1.214862905358496078218 + z^2*poly(z)
* where
* poly(z) is a 14 degree polynomial.
* 2. Rational approximation in the primary interval [2,3]
* We use the following approximation:
* s = x-2.0;
* lgamma(x) = 0.5*s + s*P(s)/Q(s)
* with accuracy
* |P/Q - (lgamma(x)-0.5s)| < 2**-61.71
* Our algorithms are based on the following observation
*
* zeta(2)-1 2 zeta(3)-1 3
* lgamma(2+s) = s*(1-Euler) + --------- * s - --------- * s + ...
* 2 3
*
* where Euler = 0.5771... is the Euler constant, which is very
* close to 0.5.
*
* 3. For x>=8, we have
* lgamma(x)~(x-0.5)log(x)-x+0.5*log(2pi)+1/(12x)-1/(360x**3)+....
* (better formula:
* lgamma(x)~(x-0.5)*(log(x)-1)-.5*(log(2pi)-1) + ...)
* Let z = 1/x, then we approximation
* f(z) = lgamma(x) - (x-0.5)(log(x)-1)
* by
* 3 5 11
* w = w0 + w1*z + w2*z + w3*z + ... + w6*z
* where
* |w - f(z)| < 2**-58.74
*
* 4. For negative x, since (G is gamma function)
* -x*G(-x)*G(x) = pi/sin(pi*x),
* we have
* G(x) = pi/(sin(pi*x)*(-x)*G(-x))
* since G(-x) is positive, sign(G(x)) = sign(sin(pi*x)) for x<0
* Hence, for x<0, signgam = sign(sin(pi*x)) and
* lgamma(x) = log(|Gamma(x)|)
* = log(pi/(|x*sin(pi*x)|)) - lgamma(-x);
* Note: one should avoid compute pi*(-x) directly in the
* computation of sin(pi*(-x)).
*
* 5. Special Cases
* lgamma(2+s) ~ s*(1-Euler) for tiny s
* lgamma(1)=lgamma(2)=0
* lgamma(x) ~ -log(x) for tiny x
* lgamma(0) = lgamma(inf) = inf
* lgamma(-integer) = +-inf
*
*/
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const double
#else
static double
#endif
two52= 4.50359962737049600000e+15, /* 0x43300000, 0x00000000 */
half= 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
pi = 3.14159265358979311600e+00, /* 0x400921FB, 0x54442D18 */
a0 = 7.72156649015328655494e-02, /* 0x3FB3C467, 0xE37DB0C8 */
a1 = 3.22467033424113591611e-01, /* 0x3FD4A34C, 0xC4A60FAD */
a2 = 6.73523010531292681824e-02, /* 0x3FB13E00, 0x1A5562A7 */
a3 = 2.05808084325167332806e-02, /* 0x3F951322, 0xAC92547B */
a4 = 7.38555086081402883957e-03, /* 0x3F7E404F, 0xB68FEFE8 */
a5 = 2.89051383673415629091e-03, /* 0x3F67ADD8, 0xCCB7926B */
a6 = 1.19270763183362067845e-03, /* 0x3F538A94, 0x116F3F5D */
a7 = 5.10069792153511336608e-04, /* 0x3F40B6C6, 0x89B99C00 */
a8 = 2.20862790713908385557e-04, /* 0x3F2CF2EC, 0xED10E54D */
a9 = 1.08011567247583939954e-04, /* 0x3F1C5088, 0x987DFB07 */
a10 = 2.52144565451257326939e-05, /* 0x3EFA7074, 0x428CFA52 */
a11 = 4.48640949618915160150e-05, /* 0x3F07858E, 0x90A45837 */
tc = 1.46163214496836224576e+00, /* 0x3FF762D8, 0x6356BE3F */
tf = -1.21486290535849611461e-01, /* 0xBFBF19B9, 0xBCC38A42 */
/* tt = -(tail of tf) */
tt = -3.63867699703950536541e-18, /* 0xBC50C7CA, 0xA48A971F */
t0 = 4.83836122723810047042e-01, /* 0x3FDEF72B, 0xC8EE38A2 */
t1 = -1.47587722994593911752e-01, /* 0xBFC2E427, 0x8DC6C509 */
t2 = 6.46249402391333854778e-02, /* 0x3FB08B42, 0x94D5419B */
t3 = -3.27885410759859649565e-02, /* 0xBFA0C9A8, 0xDF35B713 */
t4 = 1.79706750811820387126e-02, /* 0x3F9266E7, 0x970AF9EC */
t5 = -1.03142241298341437450e-02, /* 0xBF851F9F, 0xBA91EC6A */
t6 = 6.10053870246291332635e-03, /* 0x3F78FCE0, 0xE370E344 */
t7 = -3.68452016781138256760e-03, /* 0xBF6E2EFF, 0xB3E914D7 */
t8 = 2.25964780900612472250e-03, /* 0x3F6282D3, 0x2E15C915 */
t9 = -1.40346469989232843813e-03, /* 0xBF56FE8E, 0xBF2D1AF1 */
t10 = 8.81081882437654011382e-04, /* 0x3F4CDF0C, 0xEF61A8E9 */
t11 = -5.38595305356740546715e-04, /* 0xBF41A610, 0x9C73E0EC */
t12 = 3.15632070903625950361e-04, /* 0x3F34AF6D, 0x6C0EBBF7 */
t13 = -3.12754168375120860518e-04, /* 0xBF347F24, 0xECC38C38 */
t14 = 3.35529192635519073543e-04, /* 0x3F35FD3E, 0xE8C2D3F4 */
u0 = -7.72156649015328655494e-02, /* 0xBFB3C467, 0xE37DB0C8 */
u1 = 6.32827064025093366517e-01, /* 0x3FE4401E, 0x8B005DFF */
u2 = 1.45492250137234768737e+00, /* 0x3FF7475C, 0xD119BD6F */
u3 = 9.77717527963372745603e-01, /* 0x3FEF4976, 0x44EA8450 */
u4 = 2.28963728064692451092e-01, /* 0x3FCD4EAE, 0xF6010924 */
u5 = 1.33810918536787660377e-02, /* 0x3F8B678B, 0xBF2BAB09 */
v1 = 2.45597793713041134822e+00, /* 0x4003A5D7, 0xC2BD619C */
v2 = 2.12848976379893395361e+00, /* 0x40010725, 0xA42B18F5 */
v3 = 7.69285150456672783825e-01, /* 0x3FE89DFB, 0xE45050AF */
v4 = 1.04222645593369134254e-01, /* 0x3FBAAE55, 0xD6537C88 */
v5 = 3.21709242282423911810e-03, /* 0x3F6A5ABB, 0x57D0CF61 */
s0 = -7.72156649015328655494e-02, /* 0xBFB3C467, 0xE37DB0C8 */
s1 = 2.14982415960608852501e-01, /* 0x3FCB848B, 0x36E20878 */
s2 = 3.25778796408930981787e-01, /* 0x3FD4D98F, 0x4F139F59 */
s3 = 1.46350472652464452805e-01, /* 0x3FC2BB9C, 0xBEE5F2F7 */
s4 = 2.66422703033638609560e-02, /* 0x3F9B481C, 0x7E939961 */
s5 = 1.84028451407337715652e-03, /* 0x3F5E26B6, 0x7368F239 */
s6 = 3.19475326584100867617e-05, /* 0x3F00BFEC, 0xDD17E945 */
r1 = 1.39200533467621045958e+00, /* 0x3FF645A7, 0x62C4AB74 */
r2 = 7.21935547567138069525e-01, /* 0x3FE71A18, 0x93D3DCDC */
r3 = 1.71933865632803078993e-01, /* 0x3FC601ED, 0xCCFBDF27 */
r4 = 1.86459191715652901344e-02, /* 0x3F9317EA, 0x742ED475 */
r5 = 7.77942496381893596434e-04, /* 0x3F497DDA, 0xCA41A95B */
r6 = 7.32668430744625636189e-06, /* 0x3EDEBAF7, 0xA5B38140 */
w0 = 4.18938533204672725052e-01, /* 0x3FDACFE3, 0x90C97D69 */
w1 = 8.33333333333329678849e-02, /* 0x3FB55555, 0x5555553B */
w2 = -2.77777777728775536470e-03, /* 0xBF66C16C, 0x16B02E5C */
w3 = 7.93650558643019558500e-04, /* 0x3F4A019F, 0x98CF38B6 */
w4 = -5.95187557450339963135e-04, /* 0xBF4380CB, 0x8C0FE741 */
w5 = 8.36339918996282139126e-04, /* 0x3F4B67BA, 0x4CDAD5D1 */
w6 = -1.63092934096575273989e-03; /* 0xBF5AB89D, 0x0B9E43E4 */
#ifdef __STDC__
static const double zero= 0.00000000000000000000e+00;
#else
static double zero= 0.00000000000000000000e+00;
#endif
#ifdef __STDC__
static double sin_pi(double x)
#else
static double sin_pi(x)
double x;
#endif
{
double y,z;
int n,ix;
GET_HIGH_WORD(ix,x);
ix &= 0x7fffffff;
if(ix<0x3fd00000) return __sin(pi*x);
y = -x; /* x is assume negative */
/*
* argument reduction, make sure inexact flag not raised if input
* is an integer
*/
z = __floor(y);
if(z!=y) { /* inexact anyway */
y *= 0.5;
y = 2.0*(y - __floor(y)); /* y = |x| mod 2.0 */
n = (int) (y*4.0);
} else {
if(ix>=0x43400000) {
y = zero; n = 0; /* y must be even */
} else {
if(ix<0x43300000) z = y+two52; /* exact */
GET_LOW_WORD(n,z);
n &= 1;
y = n;
n<<= 2;
}
}
switch (n) {
case 0: y = __sin(pi*y); break;
case 1:
case 2: y = __cos(pi*(0.5-y)); break;
case 3:
case 4: y = __sin(pi*(one-y)); break;
case 5:
case 6: y = -__cos(pi*(y-1.5)); break;
default: y = __sin(pi*(y-2.0)); break;
}
return -y;
}
#ifdef __STDC__
double __ieee754_lgamma_r(double x, int *signgamp)
#else
double __ieee754_lgamma_r(x,signgamp)
double x; int *signgamp;
#endif
{
double t,y,z,nadj,p,p1,p2,p3,q,r,w;
int i,hx,lx,ix;
EXTRACT_WORDS(hx,lx,x);
/* purge off +-inf, NaN, +-0, and negative arguments */
*signgamp = 1;
ix = hx&0x7fffffff;
if(ix>=0x7ff00000) return x*x;
if((ix|lx)==0) return one/fabs(x);
if(ix<0x3b900000) { /* |x|<2**-70, return -log(|x|) */
if(hx<0) {
*signgamp = -1;
return -__ieee754_log(-x);
} else return -__ieee754_log(x);
}
if(hx<0) {
if(ix>=0x43300000) /* |x|>=2**52, must be -integer */
return x/zero;
t = sin_pi(x);
if(t==zero) return one/fabsf(t); /* -integer */
nadj = __ieee754_log(pi/fabs(t*x));
if(t<zero) *signgamp = -1;
x = -x;
}
/* purge off 1 and 2 */
if((((ix-0x3ff00000)|lx)==0)||(((ix-0x40000000)|lx)==0)) r = 0;
/* for x < 2.0 */
else if(ix<0x40000000) {
if(ix<=0x3feccccc) { /* lgamma(x) = lgamma(x+1)-log(x) */
r = -__ieee754_log(x);
if(ix>=0x3FE76944) {y = one-x; i= 0;}
else if(ix>=0x3FCDA661) {y= x-(tc-one); i=1;}
else {y = x; i=2;}
} else {
r = zero;
if(ix>=0x3FFBB4C3) {y=2.0-x;i=0;} /* [1.7316,2] */
else if(ix>=0x3FF3B4C4) {y=x-tc;i=1;} /* [1.23,1.73] */
else {y=x-one;i=2;}
}
switch(i) {
case 0:
z = y*y;
p1 = a0+z*(a2+z*(a4+z*(a6+z*(a8+z*a10))));
p2 = z*(a1+z*(a3+z*(a5+z*(a7+z*(a9+z*a11)))));
p = y*p1+p2;
r += (p-0.5*y); break;
case 1:
z = y*y;
w = z*y;
p1 = t0+w*(t3+w*(t6+w*(t9 +w*t12))); /* parallel comp */
p2 = t1+w*(t4+w*(t7+w*(t10+w*t13)));
p3 = t2+w*(t5+w*(t8+w*(t11+w*t14)));
p = z*p1-(tt-w*(p2+y*p3));
r += (tf + p); break;
case 2:
p1 = y*(u0+y*(u1+y*(u2+y*(u3+y*(u4+y*u5)))));
p2 = one+y*(v1+y*(v2+y*(v3+y*(v4+y*v5))));
r += (-0.5*y + p1/p2);
}
}
else if(ix<0x40200000) { /* x < 8.0 */
i = (int)x;
t = zero;
y = x-(double)i;
p = y*(s0+y*(s1+y*(s2+y*(s3+y*(s4+y*(s5+y*s6))))));
q = one+y*(r1+y*(r2+y*(r3+y*(r4+y*(r5+y*r6)))));
r = half*y+p/q;
z = one; /* lgamma(1+s) = log(s) + lgamma(s) */
switch(i) {
case 7: z *= (y+6.0); /* FALLTHRU */
case 6: z *= (y+5.0); /* FALLTHRU */
case 5: z *= (y+4.0); /* FALLTHRU */
case 4: z *= (y+3.0); /* FALLTHRU */
case 3: z *= (y+2.0); /* FALLTHRU */
r += __ieee754_log(z); break;
}
/* 8.0 <= x < 2**58 */
} else if (ix < 0x43900000) {
t = __ieee754_log(x);
z = one/x;
y = z*z;
w = w0+z*(w1+y*(w2+y*(w3+y*(w4+y*(w5+y*w6)))));
r = (x-half)*(t-one)+w;
} else
/* 2**58 <= x <= inf */
r = x*(__ieee754_log(x)-one);
if(hx<0) r = nadj - r;
return r;
}
@@ -0,0 +1,248 @@
/* e_lgammaf_r.c -- float version of e_lgamma_r.c.
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
*/
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_lgammaf_r.c,v 1.3 1995/05/10 20:45:47 jtc Exp $";
#endif
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const float
#else
static float
#endif
two23= 8.3886080000e+06, /* 0x4b000000 */
half= 5.0000000000e-01, /* 0x3f000000 */
one = 1.0000000000e+00, /* 0x3f800000 */
pi = 3.1415927410e+00, /* 0x40490fdb */
a0 = 7.7215664089e-02, /* 0x3d9e233f */
a1 = 3.2246702909e-01, /* 0x3ea51a66 */
a2 = 6.7352302372e-02, /* 0x3d89f001 */
a3 = 2.0580807701e-02, /* 0x3ca89915 */
a4 = 7.3855509982e-03, /* 0x3bf2027e */
a5 = 2.8905137442e-03, /* 0x3b3d6ec6 */
a6 = 1.1927076848e-03, /* 0x3a9c54a1 */
a7 = 5.1006977446e-04, /* 0x3a05b634 */
a8 = 2.2086278477e-04, /* 0x39679767 */
a9 = 1.0801156895e-04, /* 0x38e28445 */
a10 = 2.5214456400e-05, /* 0x37d383a2 */
a11 = 4.4864096708e-05, /* 0x383c2c75 */
tc = 1.4616321325e+00, /* 0x3fbb16c3 */
tf = -1.2148628384e-01, /* 0xbdf8cdcd */
/* tt = -(tail of tf) */
tt = 6.6971006518e-09, /* 0x31e61c52 */
t0 = 4.8383611441e-01, /* 0x3ef7b95e */
t1 = -1.4758771658e-01, /* 0xbe17213c */
t2 = 6.4624942839e-02, /* 0x3d845a15 */
t3 = -3.2788541168e-02, /* 0xbd064d47 */
t4 = 1.7970675603e-02, /* 0x3c93373d */
t5 = -1.0314224288e-02, /* 0xbc28fcfe */
t6 = 6.1005386524e-03, /* 0x3bc7e707 */
t7 = -3.6845202558e-03, /* 0xbb7177fe */
t8 = 2.2596477065e-03, /* 0x3b141699 */
t9 = -1.4034647029e-03, /* 0xbab7f476 */
t10 = 8.8108185446e-04, /* 0x3a66f867 */
t11 = -5.3859531181e-04, /* 0xba0d3085 */
t12 = 3.1563205994e-04, /* 0x39a57b6b */
t13 = -3.1275415677e-04, /* 0xb9a3f927 */
t14 = 3.3552918467e-04, /* 0x39afe9f7 */
u0 = -7.7215664089e-02, /* 0xbd9e233f */
u1 = 6.3282704353e-01, /* 0x3f2200f4 */
u2 = 1.4549225569e+00, /* 0x3fba3ae7 */
u3 = 9.7771751881e-01, /* 0x3f7a4bb2 */
u4 = 2.2896373272e-01, /* 0x3e6a7578 */
u5 = 1.3381091878e-02, /* 0x3c5b3c5e */
v1 = 2.4559779167e+00, /* 0x401d2ebe */
v2 = 2.1284897327e+00, /* 0x4008392d */
v3 = 7.6928514242e-01, /* 0x3f44efdf */
v4 = 1.0422264785e-01, /* 0x3dd572af */
v5 = 3.2170924824e-03, /* 0x3b52d5db */
s0 = -7.7215664089e-02, /* 0xbd9e233f */
s1 = 2.1498242021e-01, /* 0x3e5c245a */
s2 = 3.2577878237e-01, /* 0x3ea6cc7a */
s3 = 1.4635047317e-01, /* 0x3e15dce6 */
s4 = 2.6642270386e-02, /* 0x3cda40e4 */
s5 = 1.8402845599e-03, /* 0x3af135b4 */
s6 = 3.1947532989e-05, /* 0x3805ff67 */
r1 = 1.3920053244e+00, /* 0x3fb22d3b */
r2 = 7.2193557024e-01, /* 0x3f38d0c5 */
r3 = 1.7193385959e-01, /* 0x3e300f6e */
r4 = 1.8645919859e-02, /* 0x3c98bf54 */
r5 = 7.7794247773e-04, /* 0x3a4beed6 */
r6 = 7.3266842264e-06, /* 0x36f5d7bd */
w0 = 4.1893854737e-01, /* 0x3ed67f1d */
w1 = 8.3333335817e-02, /* 0x3daaaaab */
w2 = -2.7777778450e-03, /* 0xbb360b61 */
w3 = 7.9365057172e-04, /* 0x3a500cfd */
w4 = -5.9518753551e-04, /* 0xba1c065c */
w5 = 8.3633989561e-04, /* 0x3a5b3dd2 */
w6 = -1.6309292987e-03; /* 0xbad5c4e8 */
#ifdef __STDC__
static const float zero= 0.0000000000e+00;
#else
static float zero= 0.0000000000e+00;
#endif
#ifdef __STDC__
static float sin_pif(float x)
#else
static float sin_pif(x)
float x;
#endif
{
float y,z;
int n,ix;
GET_FLOAT_WORD(ix,x);
ix &= 0x7fffffff;
if(ix<0x3e800000) return __kernel_sinf(pi*x,zero,0);
y = -x; /* x is assume negative */
/*
* argument reduction, make sure inexact flag not raised if input
* is an integer
*/
z = __floorf(y);
if(z!=y) { /* inexact anyway */
y *= (float)0.5;
y = (float)2.0*(y - __floorf(y)); /* y = |x| mod 2.0 */
n = (int) (y*(float)4.0);
} else {
if(ix>=0x4b800000) {
y = zero; n = 0; /* y must be even */
} else {
if(ix<0x4b000000) z = y+two23; /* exact */
GET_FLOAT_WORD(n,z);
n &= 1;
y = n;
n<<= 2;
}
}
switch (n) {
case 0: y = __kernel_sinf(pi*y,zero,0); break;
case 1:
case 2: y = __kernel_cosf(pi*((float)0.5-y),zero); break;
case 3:
case 4: y = __kernel_sinf(pi*(one-y),zero,0); break;
case 5:
case 6: y = -__kernel_cosf(pi*(y-(float)1.5),zero); break;
default: y = __kernel_sinf(pi*(y-(float)2.0),zero,0); break;
}
return -y;
}
#ifdef __STDC__
float __ieee754_lgammaf_r(float x, int *signgamp)
#else
float __ieee754_lgammaf_r(x,signgamp)
float x; int *signgamp;
#endif
{
float t,y,z,nadj,p,p1,p2,p3,q,r,w;
int i,hx,ix;
GET_FLOAT_WORD(hx,x);
/* purge off +-inf, NaN, +-0, and negative arguments */
*signgamp = 1;
ix = hx&0x7fffffff;
if(ix>=0x7f800000) return x*x;
if(ix==0) return one/fabsf(x);
if(ix<0x1c800000) { /* |x|<2**-70, return -log(|x|) */
if(hx<0) {
*signgamp = -1;
return -__ieee754_logf(-x);
} else return -__ieee754_logf(x);
}
if(hx<0) {
if(ix>=0x4b000000) /* |x|>=2**23, must be -integer */
return x/zero;
t = sin_pif(x);
if(t==zero) return one/fabsf(t); /* -integer */
nadj = __ieee754_logf(pi/fabsf(t*x));
if(t<zero) *signgamp = -1;
x = -x;
}
/* purge off 1 and 2 */
if (ix==0x3f800000||ix==0x40000000) r = 0;
/* for x < 2.0 */
else if(ix<0x40000000) {
if(ix<=0x3f666666) { /* lgamma(x) = lgamma(x+1)-log(x) */
r = -__ieee754_logf(x);
if(ix>=0x3f3b4a20) {y = one-x; i= 0;}
else if(ix>=0x3e6d3308) {y= x-(tc-one); i=1;}
else {y = x; i=2;}
} else {
r = zero;
if(ix>=0x3fdda618) {y=(float)2.0-x;i=0;} /* [1.7316,2] */
else if(ix>=0x3F9da620) {y=x-tc;i=1;} /* [1.23,1.73] */
else {y=x-one;i=2;}
}
switch(i) {
case 0:
z = y*y;
p1 = a0+z*(a2+z*(a4+z*(a6+z*(a8+z*a10))));
p2 = z*(a1+z*(a3+z*(a5+z*(a7+z*(a9+z*a11)))));
p = y*p1+p2;
r += (p-(float)0.5*y); break;
case 1:
z = y*y;
w = z*y;
p1 = t0+w*(t3+w*(t6+w*(t9 +w*t12))); /* parallel comp */
p2 = t1+w*(t4+w*(t7+w*(t10+w*t13)));
p3 = t2+w*(t5+w*(t8+w*(t11+w*t14)));
p = z*p1-(tt-w*(p2+y*p3));
r += (tf + p); break;
case 2:
p1 = y*(u0+y*(u1+y*(u2+y*(u3+y*(u4+y*u5)))));
p2 = one+y*(v1+y*(v2+y*(v3+y*(v4+y*v5))));
r += (-(float)0.5*y + p1/p2);
}
}
else if(ix<0x41000000) { /* x < 8.0 */
i = (int)x;
t = zero;
y = x-(float)i;
p = y*(s0+y*(s1+y*(s2+y*(s3+y*(s4+y*(s5+y*s6))))));
q = one+y*(r1+y*(r2+y*(r3+y*(r4+y*(r5+y*r6)))));
r = half*y+p/q;
z = one; /* lgamma(1+s) = log(s) + lgamma(s) */
switch(i) {
case 7: z *= (y+(float)6.0); /* FALLTHRU */
case 6: z *= (y+(float)5.0); /* FALLTHRU */
case 5: z *= (y+(float)4.0); /* FALLTHRU */
case 4: z *= (y+(float)3.0); /* FALLTHRU */
case 3: z *= (y+(float)2.0); /* FALLTHRU */
r += __ieee754_logf(z); break;
}
/* 8.0 <= x < 2**58 */
} else if (ix < 0x5c800000) {
t = __ieee754_logf(x);
z = one/x;
y = z*z;
w = w0+z*(w1+y*(w2+y*(w3+y*(w4+y*(w5+y*w6)))));
r = (x-half)*(t-one)+w;
} else
/* 2**58 <= x <= inf */
r = x*(__ieee754_logf(x)-one);
if(hx<0) r = nadj - r;
return r;
}
@@ -0,0 +1,203 @@
/*
* IBM Accurate Mathematical Library
* written by International Business Machines Corp.
* Copyright (C) 2001 Free Software Foundation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*********************************************************************/
/* */
/* MODULE_NAME:ulog.c */
/* */
/* FUNCTION:ulog */
/* */
/* FILES NEEDED: dla.h endian.h mpa.h mydefs.h ulog.h */
/* mpexp.c mplog.c mpa.c */
/* ulog.tbl */
/* */
/* An ultimate log routine. Given an IEEE double machine number x */
/* it computes the correctly rounded (to nearest) value of log(x). */
/* Assumption: Machine arithmetic operations are performed in */
/* round to nearest mode of IEEE 754 standard. */
/* */
/*********************************************************************/
#include "endian.h"
#include "dla.h"
#include "mpa.h"
#include "MathLib.h"
#include "math_private.h"
void __mplog(mp_no *, mp_no *, int);
/*********************************************************************/
/* An ultimate log routine. Given an IEEE double machine number x */
/* it computes the correctly rounded (to nearest) value of log(x). */
/*********************************************************************/
double __ieee754_log(double x) {
#define M 4
static const int pr[M]={8,10,18,32};
int i,j,n,ux,dx,p;
#if 0
int k;
#endif
double dbl_n,u,p0,q,r0,w,nln2a,luai,lubi,lvaj,lvbj,
sij,ssij,ttij,A,B,B0,y,y1,y2,polI,polII,sa,sb,
t1,t2,t3,t4,t5,t6,t7,t8,t,ra,rb,ww,
a0,aa0,s1,s2,ss2,s3,ss3,a1,aa1,a,aa,b,bb,c;
number num;
mp_no mpx,mpy,mpy1,mpy2,mperr;
#include "ulog.tbl"
#include "ulog.h"
/* Treating special values of x ( x<=0, x=INF, x=NaN etc.). */
num.d = x; ux = num.i[HIGH_HALF]; dx = num.i[LOW_HALF];
n=0;
if (ux < 0x00100000) {
if (((ux & 0x7fffffff) | dx) == 0) return MHALF/ZERO; /* return -INF */
if (ux < 0) return (x-x)/ZERO; /* return NaN */
n -= 54; x *= two54.d; /* scale x */
num.d = x;
}
if (ux >= 0x7ff00000) return x+x; /* INF or NaN */
/* Regular values of x */
w = x-ONE;
if (ABS(w) > U03) { goto case_03; }
/*--- Stage I, the case abs(x-1) < 0.03 */
t8 = MHALF*w;
EMULV(t8,w,a,aa,t1,t2,t3,t4,t5)
EADD(w,a,b,bb)
/* Evaluate polynomial II */
polII = (b0.d+w*(b1.d+w*(b2.d+w*(b3.d+w*(b4.d+
w*(b5.d+w*(b6.d+w*(b7.d+w*b8.d))))))))*w*w*w;
c = (aa+bb)+polII;
/* End stage I, case abs(x-1) < 0.03 */
if ((y=b+(c+b*E2)) == b+(c-b*E2)) return y;
/*--- Stage II, the case abs(x-1) < 0.03 */
a = d11.d+w*(d12.d+w*(d13.d+w*(d14.d+w*(d15.d+w*(d16.d+
w*(d17.d+w*(d18.d+w*(d19.d+w*d20.d))))))));
EMULV(w,a,s2,ss2,t1,t2,t3,t4,t5)
ADD2(d10.d,dd10.d,s2,ss2,s3,ss3,t1,t2)
MUL2(w,ZERO,s3,ss3,s2,ss2,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(d9.d,dd9.d,s2,ss2,s3,ss3,t1,t2)
MUL2(w,ZERO,s3,ss3,s2,ss2,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(d8.d,dd8.d,s2,ss2,s3,ss3,t1,t2)
MUL2(w,ZERO,s3,ss3,s2,ss2,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(d7.d,dd7.d,s2,ss2,s3,ss3,t1,t2)
MUL2(w,ZERO,s3,ss3,s2,ss2,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(d6.d,dd6.d,s2,ss2,s3,ss3,t1,t2)
MUL2(w,ZERO,s3,ss3,s2,ss2,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(d5.d,dd5.d,s2,ss2,s3,ss3,t1,t2)
MUL2(w,ZERO,s3,ss3,s2,ss2,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(d4.d,dd4.d,s2,ss2,s3,ss3,t1,t2)
MUL2(w,ZERO,s3,ss3,s2,ss2,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(d3.d,dd3.d,s2,ss2,s3,ss3,t1,t2)
MUL2(w,ZERO,s3,ss3,s2,ss2,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(d2.d,dd2.d,s2,ss2,s3,ss3,t1,t2)
MUL2(w,ZERO,s3,ss3,s2,ss2,t1,t2,t3,t4,t5,t6,t7,t8)
MUL2(w,ZERO,s2,ss2,s3,ss3,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(w,ZERO, s3,ss3, b, bb,t1,t2)
/* End stage II, case abs(x-1) < 0.03 */
if ((y=b+(bb+b*E4)) == b+(bb-b*E4)) return y;
goto stage_n;
/*--- Stage I, the case abs(x-1) > 0.03 */
case_03:
/* Find n,u such that x = u*2**n, 1/sqrt(2) < u < sqrt(2) */
n += (num.i[HIGH_HALF] >> 20) - 1023;
num.i[HIGH_HALF] = (num.i[HIGH_HALF] & 0x000fffff) | 0x3ff00000;
if (num.d > SQRT_2) { num.d *= HALF; n++; }
u = num.d; dbl_n = (double) n;
/* Find i such that ui=1+(i-75)/2**8 is closest to u (i= 0,1,2,...,181) */
num.d += h1.d;
i = (num.i[HIGH_HALF] & 0x000fffff) >> 12;
/* Find j such that vj=1+(j-180)/2**16 is closest to v=u/ui (j= 0,...,361) */
num.d = u*Iu[i].d + h2.d;
j = (num.i[HIGH_HALF] & 0x000fffff) >> 4;
/* Compute w=(u-ui*vj)/(ui*vj) */
p0=(ONE+(i-75)*DEL_U)*(ONE+(j-180)*DEL_V);
q=u-p0; r0=Iu[i].d*Iv[j].d; w=q*r0;
/* Evaluate polynomial I */
polI = w+(a2.d+a3.d*w)*w*w;
/* Add up everything */
nln2a = dbl_n*LN2A;
luai = Lu[i][0].d; lubi = Lu[i][1].d;
lvaj = Lv[j][0].d; lvbj = Lv[j][1].d;
EADD(luai,lvaj,sij,ssij)
EADD(nln2a,sij,A ,ttij)
B0 = (((lubi+lvbj)+ssij)+ttij)+dbl_n*LN2B;
B = polI+B0;
/* End stage I, case abs(x-1) >= 0.03 */
if ((y=A+(B+E1)) == A+(B-E1)) return y;
/*--- Stage II, the case abs(x-1) > 0.03 */
/* Improve the accuracy of r0 */
EMULV(p0,r0,sa,sb,t1,t2,t3,t4,t5)
t=r0*((ONE-sa)-sb);
EADD(r0,t,ra,rb)
/* Compute w */
MUL2(q,ZERO,ra,rb,w,ww,t1,t2,t3,t4,t5,t6,t7,t8)
EADD(A,B0,a0,aa0)
/* Evaluate polynomial III */
s1 = (c3.d+(c4.d+c5.d*w)*w)*w;
EADD(c2.d,s1,s2,ss2)
MUL2(s2,ss2,w,ww,s3,ss3,t1,t2,t3,t4,t5,t6,t7,t8)
MUL2(s3,ss3,w,ww,s2,ss2,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(s2,ss2,w,ww,s3,ss3,t1,t2)
ADD2(s3,ss3,a0,aa0,a1,aa1,t1,t2)
/* End stage II, case abs(x-1) >= 0.03 */
if ((y=a1+(aa1+E3)) == a1+(aa1-E3)) return y;
/* Final stages. Use multi-precision arithmetic. */
stage_n:
for (i=0; i<M; i++) {
p = pr[i];
__dbl_mp(x,&mpx,p); __dbl_mp(y,&mpy,p);
__mplog(&mpx,&mpy,p);
__dbl_mp(e[i].d,&mperr,p);
__add(&mpy,&mperr,&mpy1,p); __sub(&mpy,&mperr,&mpy2,p);
__mp_dbl(&mpy1,&y1,p); __mp_dbl(&mpy2,&y2,p);
if (y1==y2) return y1;
}
return y1;
}
@@ -0,0 +1,98 @@
/* @(#)e_log10.c 5.1 93/09/24 */
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_log10.c,v 1.9 1995/05/10 20:45:51 jtc Exp $";
#endif
/* __ieee754_log10(x)
* Return the base 10 logarithm of x
*
* Method :
* Let log10_2hi = leading 40 bits of log10(2) and
* log10_2lo = log10(2) - log10_2hi,
* ivln10 = 1/log(10) rounded.
* Then
* n = ilogb(x),
* if(n<0) n = n+1;
* x = scalbn(x,-n);
* log10(x) := n*log10_2hi + (n*log10_2lo + ivln10*log(x))
*
* Note 1:
* To guarantee log10(10**n)=n, where 10**n is normal, the rounding
* mode must set to Round-to-Nearest.
* Note 2:
* [1/log(10)] rounded to 53 bits has error .198 ulps;
* log10 is monotonic at all binary break points.
*
* Special cases:
* log10(x) is NaN with signal if x < 0;
* log10(+INF) is +INF with no signal; log10(0) is -INF with signal;
* log10(NaN) is that NaN with no signal;
* log10(10**N) = N for N=0,1,...,22.
*
* Constants:
* The hexadecimal values are the intended ones for the following constants.
* The decimal values may be used, provided that the compiler will convert
* from decimal to binary accurately enough to produce the hexadecimal values
* shown.
*/
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const double
#else
static double
#endif
two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
ivln10 = 4.34294481903251816668e-01, /* 0x3FDBCB7B, 0x1526E50E */
log10_2hi = 3.01029995663611771306e-01, /* 0x3FD34413, 0x509F6000 */
log10_2lo = 3.69423907715893078616e-13; /* 0x3D59FEF3, 0x11F12B36 */
#ifdef __STDC__
static const double zero = 0.0;
#else
static double zero = 0.0;
#endif
#ifdef __STDC__
double __ieee754_log10(double x)
#else
double __ieee754_log10(x)
double x;
#endif
{
double y,z;
int32_t i,k,hx;
u_int32_t lx;
EXTRACT_WORDS(hx,lx,x);
k=0;
if (hx < 0x00100000) { /* x < 2**-1022 */
if (((hx&0x7fffffff)|lx)==0)
return -two54/(x-x); /* log(+-0)=-inf */
if (hx<0) return (x-x)/(x-x); /* log(-#) = NaN */
k -= 54; x *= two54; /* subnormal number, scale up x */
GET_HIGH_WORD(hx,x);
}
if (hx >= 0x7ff00000) return x+x;
k += (hx>>20)-1023;
i = ((u_int32_t)k&0x80000000)>>31;
hx = (hx&0x000fffff)|((0x3ff-i)<<20);
y = (double)(k+i);
SET_HIGH_WORD(x,hx);
z = y*log10_2lo + ivln10*__ieee754_log(x);
return z+y*log10_2hi;
}
@@ -0,0 +1,67 @@
/* e_log10f.c -- float version of e_log10.c.
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
*/
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_log10f.c,v 1.5 1995/05/10 20:45:53 jtc Exp $";
#endif
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const float
#else
static float
#endif
two25 = 3.3554432000e+07, /* 0x4c000000 */
ivln10 = 4.3429449201e-01, /* 0x3ede5bd9 */
log10_2hi = 3.0102920532e-01, /* 0x3e9a2080 */
log10_2lo = 7.9034151668e-07; /* 0x355427db */
#ifdef __STDC__
static const float zero = 0.0;
#else
static float zero = 0.0;
#endif
#ifdef __STDC__
float __ieee754_log10f(float x)
#else
float __ieee754_log10f(x)
float x;
#endif
{
float y,z;
int32_t i,k,hx;
GET_FLOAT_WORD(hx,x);
k=0;
if (hx < 0x00800000) { /* x < 2**-126 */
if ((hx&0x7fffffff)==0)
return -two25/(x-x); /* log(+-0)=-inf */
if (hx<0) return (x-x)/(x-x); /* log(-#) = NaN */
k -= 25; x *= two25; /* subnormal number, scale up x */
GET_FLOAT_WORD(hx,x);
}
if (hx >= 0x7f800000) return x+x;
k += (hx>>23)-127;
i = ((u_int32_t)k&0x80000000)>>31;
hx = (hx&0x007fffff)|((0x7f-i)<<23);
y = (float)(k+i);
SET_FLOAT_WORD(x,hx);
z = y*log10_2lo + ivln10*__ieee754_logf(x);
return z+y*log10_2hi;
}
@@ -0,0 +1,99 @@
/* e_logf.c -- float version of e_log.c.
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
*/
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_logf.c,v 1.4 1995/05/10 20:45:54 jtc Exp $";
#endif
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const float
#else
static float
#endif
ln2_hi = 6.9313812256e-01, /* 0x3f317180 */
ln2_lo = 9.0580006145e-06, /* 0x3717f7d1 */
two25 = 3.355443200e+07, /* 0x4c000000 */
Lg1 = 6.6666668653e-01, /* 3F2AAAAB */
Lg2 = 4.0000000596e-01, /* 3ECCCCCD */
Lg3 = 2.8571429849e-01, /* 3E924925 */
Lg4 = 2.2222198546e-01, /* 3E638E29 */
Lg5 = 1.8183572590e-01, /* 3E3A3325 */
Lg6 = 1.5313838422e-01, /* 3E1CD04F */
Lg7 = 1.4798198640e-01; /* 3E178897 */
#ifdef __STDC__
static const float zero = 0.0;
#else
static float zero = 0.0;
#endif
#ifdef __STDC__
float __ieee754_logf(float x)
#else
float __ieee754_logf(x)
float x;
#endif
{
float hfsq,f,s,z,R,w,t1,t2,dk;
int32_t k,ix,i,j;
GET_FLOAT_WORD(ix,x);
k=0;
if (ix < 0x00800000) { /* x < 2**-126 */
if ((ix&0x7fffffff)==0)
return -two25/(x-x); /* log(+-0)=-inf */
if (ix<0) return (x-x)/(x-x); /* log(-#) = NaN */
k -= 25; x *= two25; /* subnormal number, scale up x */
GET_FLOAT_WORD(ix,x);
}
if (ix >= 0x7f800000) return x+x;
k += (ix>>23)-127;
ix &= 0x007fffff;
i = (ix+(0x95f64<<3))&0x800000;
SET_FLOAT_WORD(x,ix|(i^0x3f800000)); /* normalize x or x/2 */
k += (i>>23);
f = x-(float)1.0;
if((0x007fffff&(15+ix))<16) { /* |f| < 2**-20 */
if(f==zero) {
if(k==0) return zero; else {dk=(float)k;
return dk*ln2_hi+dk*ln2_lo;}
}
R = f*f*((float)0.5-(float)0.33333333333333333*f);
if(k==0) return f-R; else {dk=(float)k;
return dk*ln2_hi-((R-dk*ln2_lo)-f);}
}
s = f/((float)2.0+f);
dk = (float)k;
z = s*s;
i = ix-(0x6147a<<3);
w = z*z;
j = (0x6b851<<3)-ix;
t1= w*(Lg2+w*(Lg4+w*Lg6));
t2= z*(Lg1+w*(Lg3+w*(Lg5+w*Lg7)));
i |= j;
R = t2+t1;
if(i>0) {
hfsq=(float)0.5*f*f;
if(k==0) return f-(hfsq-s*(hfsq+R)); else
return dk*ln2_hi-((hfsq-(s*(hfsq+R)+dk*ln2_lo))-f);
} else {
if(k==0) return f-s*(f-R); else
return dk*ln2_hi-((s*(f-R)-dk*ln2_lo)-f);
}
}
@@ -0,0 +1,388 @@
/*
* IBM Accurate Mathematical Library
* written by International Business Machines Corp.
* Copyright (C) 2001, 2002 Free Software Foundation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/***************************************************************************/
/* MODULE_NAME: upow.c */
/* */
/* FUNCTIONS: upow */
/* power1 */
/* log2 */
/* log1 */
/* checkint */
/* FILES NEEDED: dla.h endian.h mpa.h mydefs.h */
/* halfulp.c mpexp.c mplog.c slowexp.c slowpow.c mpa.c */
/* uexp.c upow.c */
/* root.tbl uexp.tbl upow.tbl */
/* An ultimate power routine. Given two IEEE double machine numbers y,x */
/* it computes the correctly rounded (to nearest) value of x^y. */
/* Assumption: Machine arithmetic operations are performed in */
/* round to nearest mode of IEEE 754 standard. */
/* */
/***************************************************************************/
#include "endian.h"
#include "upow.h"
#include "dla.h"
#include "mydefs.h"
#include "MathLib.h"
#include "upow.tbl"
#include "math_private.h"
double __exp1(double x, double xx, double error);
static double log1(double x, double *delta, double *error);
static double log2(double x, double *delta, double *error);
double __slowpow(double x, double y,double z);
static double power1(double x, double y);
static int checkint(double x);
/***************************************************************************/
/* An ultimate power routine. Given two IEEE double machine numbers y,x */
/* it computes the correctly rounded (to nearest) value of X^y. */
/***************************************************************************/
double __ieee754_pow(double x, double y) {
double z,a,aa,error, t,a1,a2,y1,y2;
#if 0
double gor=1.0;
#endif
mynumber u,v;
int k;
int4 qx,qy;
v.x=y;
u.x=x;
if (v.i[LOW_HALF] == 0) { /* of y */
qx = u.i[HIGH_HALF]&0x7fffffff;
/* Checking if x is not too small to compute */
if (((qx==0x7ff00000)&&(u.i[LOW_HALF]!=0))||(qx>0x7ff00000)) return NaNQ.x;
if (y == 1.0) return x;
if (y == 2.0) return x*x;
if (y == -1.0) return 1.0/x;
if (y == 0) return 1.0;
}
/* else */
if(((u.i[HIGH_HALF]>0 && u.i[HIGH_HALF]<0x7ff00000)|| /* x>0 and not x->0 */
(u.i[HIGH_HALF]==0 && u.i[LOW_HALF]!=0)) &&
/* 2^-1023< x<= 2^-1023 * 0x1.0000ffffffff */
(v.i[HIGH_HALF]&0x7fffffff) < 0x4ff00000) { /* if y<-1 or y>1 */
z = log1(x,&aa,&error); /* x^y =e^(y log (X)) */
t = y*134217729.0;
y1 = t - (t-y);
y2 = y - y1;
t = z*134217729.0;
a1 = t - (t-z);
a2 = (z - a1)+aa;
a = y1*a1;
aa = y2*a1 + y*a2;
a1 = a+aa;
a2 = (a-a1)+aa;
error = error*ABS(y);
t = __exp1(a1,a2,1.9e16*error); /* return -10 or 0 if wasn't computed exactly */
return (t>0)?t:power1(x,y);
}
if (x == 0) {
if (((v.i[HIGH_HALF] & 0x7fffffff) == 0x7ff00000 && v.i[LOW_HALF] != 0)
|| (v.i[HIGH_HALF] & 0x7fffffff) > 0x7ff00000)
return y;
if (ABS(y) > 1.0e20) return (y>0)?0:INF.x;
k = checkint(y);
if (k == -1)
return y < 0 ? 1.0/x : x;
else
return y < 0 ? 1.0/ABS(x) : 0.0; /* return 0 */
}
/* if x<0 */
if (u.i[HIGH_HALF] < 0) {
k = checkint(y);
if (k==0) {
if ((v.i[HIGH_HALF] & 0x7fffffff) == 0x7ff00000 && v.i[LOW_HALF] == 0) {
if (x == -1.0) return 1.0;
else if (x > -1.0) return v.i[HIGH_HALF] < 0 ? INF.x : 0.0;
else return v.i[HIGH_HALF] < 0 ? 0.0 : INF.x;
}
else if (u.i[HIGH_HALF] == 0xfff00000 && u.i[LOW_HALF] == 0)
return y < 0 ? 0.0 : INF.x;
return NaNQ.x; /* y not integer and x<0 */
}
else if (u.i[HIGH_HALF] == 0xfff00000 && u.i[LOW_HALF] == 0)
{
if (k < 0)
return y < 0 ? nZERO.x : nINF.x;
else
return y < 0 ? 0.0 : INF.x;
}
return (k==1)?__ieee754_pow(-x,y):-__ieee754_pow(-x,y); /* if y even or odd */
}
/* x>0 */
qx = u.i[HIGH_HALF]&0x7fffffff; /* no sign */
qy = v.i[HIGH_HALF]&0x7fffffff; /* no sign */
if (qx > 0x7ff00000 || (qx == 0x7ff00000 && u.i[LOW_HALF] != 0)) return NaNQ.x;
/* if 0<x<2^-0x7fe */
if (qy > 0x7ff00000 || (qy == 0x7ff00000 && v.i[LOW_HALF] != 0))
return x == 1.0 ? 1.0 : NaNQ.x;
/* if y<2^-0x7fe */
if (qx == 0x7ff00000) /* x= 2^-0x3ff */
{if (y == 0) return NaNQ.x;
return (y>0)?x:0; }
if (qy > 0x45f00000 && qy < 0x7ff00000) {
if (x == 1.0) return 1.0;
if (y>0) return (x>1.0)?INF.x:0;
if (y<0) return (x<1.0)?INF.x:0;
}
if (x == 1.0) return 1.0;
if (y>0) return (x>1.0)?INF.x:0;
if (y<0) return (x<1.0)?INF.x:0;
return 0; /* unreachable, to make the compiler happy */
}
/**************************************************************************/
/* Computing x^y using more accurate but more slow log routine */
/**************************************************************************/
static double power1(double x, double y) {
double z,a,aa,error, t,a1,a2,y1,y2;
z = log2(x,&aa,&error);
t = y*134217729.0;
y1 = t - (t-y);
y2 = y - y1;
t = z*134217729.0;
a1 = t - (t-z);
a2 = z - a1;
a = y*z;
aa = ((y1*a1-a)+y1*a2+y2*a1)+y2*a2+aa*y;
a1 = a+aa;
a2 = (a-a1)+aa;
error = error*ABS(y);
t = __exp1(a1,a2,1.9e16*error);
return (t >= 0)?t:__slowpow(x,y,z);
}
/****************************************************************************/
/* Computing log(x) (x is left argument). The result is the returned double */
/* + the parameter delta. */
/* The result is bounded by error (rightmost argument) */
/****************************************************************************/
static double log1(double x, double *delta, double *error) {
int i,j,m;
#if 0
int n;
#endif
double uu,vv,eps,nx,e,e1,e2,t,t1,t2,res,add=0;
#if 0
double cor;
#endif
mynumber u,v;
#ifdef BIG_ENDI
mynumber
/**/ two52 = {{0x43300000, 0x00000000}}; /* 2**52 */
#else
#ifdef LITTLE_ENDI
mynumber
/**/ two52 = {{0x00000000, 0x43300000}}; /* 2**52 */
#endif
#endif
u.x = x;
m = u.i[HIGH_HALF];
*error = 0;
*delta = 0;
if (m < 0x00100000) /* 1<x<2^-1007 */
{ x = x*t52.x; add = -52.0; u.x = x; m = u.i[HIGH_HALF];}
if ((m&0x000fffff) < 0x0006a09e)
{u.i[HIGH_HALF] = (m&0x000fffff)|0x3ff00000; two52.i[LOW_HALF]=(m>>20); }
else
{u.i[HIGH_HALF] = (m&0x000fffff)|0x3fe00000; two52.i[LOW_HALF]=(m>>20)+1; }
v.x = u.x + bigu.x;
uu = v.x - bigu.x;
i = (v.i[LOW_HALF]&0x000003ff)<<2;
if (two52.i[LOW_HALF] == 1023) /* nx = 0 */
{
if (i > 1192 && i < 1208) /* |x-1| < 1.5*2**-10 */
{
t = x - 1.0;
t1 = (t+5.0e6)-5.0e6;
t2 = t-t1;
e1 = t - 0.5*t1*t1;
e2 = t*t*t*(r3+t*(r4+t*(r5+t*(r6+t*(r7+t*r8)))))-0.5*t2*(t+t1);
res = e1+e2;
*error = 1.0e-21*ABS(t);
*delta = (e1-res)+e2;
return res;
} /* |x-1| < 1.5*2**-10 */
else
{
v.x = u.x*(ui.x[i]+ui.x[i+1])+bigv.x;
vv = v.x-bigv.x;
j = v.i[LOW_HALF]&0x0007ffff;
j = j+j+j;
eps = u.x - uu*vv;
e1 = eps*ui.x[i];
e2 = eps*(ui.x[i+1]+vj.x[j]*(ui.x[i]+ui.x[i+1]));
e = e1+e2;
e2 = ((e1-e)+e2);
t=ui.x[i+2]+vj.x[j+1];
t1 = t+e;
t2 = (((t-t1)+e)+(ui.x[i+3]+vj.x[j+2]))+e2+e*e*(p2+e*(p3+e*p4));
res=t1+t2;
*error = 1.0e-24;
*delta = (t1-res)+t2;
return res;
}
} /* nx = 0 */
else /* nx != 0 */
{
eps = u.x - uu;
nx = (two52.x - two52e.x)+add;
e1 = eps*ui.x[i];
e2 = eps*ui.x[i+1];
e=e1+e2;
e2 = (e1-e)+e2;
t=nx*ln2a.x+ui.x[i+2];
t1=t+e;
t2=(((t-t1)+e)+nx*ln2b.x+ui.x[i+3]+e2)+e*e*(q2+e*(q3+e*(q4+e*(q5+e*q6))));
res = t1+t2;
*error = 1.0e-21;
*delta = (t1-res)+t2;
return res;
} /* nx != 0 */
}
/****************************************************************************/
/* More slow but more accurate routine of log */
/* Computing log(x)(x is left argument).The result is return double + delta.*/
/* The result is bounded by error (right argument) */
/****************************************************************************/
static double log2(double x, double *delta, double *error) {
int i,j,m;
#if 0
int n;
#endif
double uu,vv,eps,nx,e,e1,e2,t,t1,t2,res,add=0;
#if 0
double cor;
#endif
double ou1,ou2,lu1,lu2,ov,lv1,lv2,a,a1,a2;
double y,yy,z,zz,j1,j2,j3,j4,j5,j6,j7,j8;
mynumber u,v;
#ifdef BIG_ENDI
mynumber
/**/ two52 = {{0x43300000, 0x00000000}}; /* 2**52 */
#else
#ifdef LITTLE_ENDI
mynumber
/**/ two52 = {{0x00000000, 0x43300000}}; /* 2**52 */
#endif
#endif
u.x = x;
m = u.i[HIGH_HALF];
*error = 0;
*delta = 0;
add=0;
if (m<0x00100000) { /* x < 2^-1022 */
x = x*t52.x; add = -52.0; u.x = x; m = u.i[HIGH_HALF]; }
if ((m&0x000fffff) < 0x0006a09e)
{u.i[HIGH_HALF] = (m&0x000fffff)|0x3ff00000; two52.i[LOW_HALF]=(m>>20); }
else
{u.i[HIGH_HALF] = (m&0x000fffff)|0x3fe00000; two52.i[LOW_HALF]=(m>>20)+1; }
v.x = u.x + bigu.x;
uu = v.x - bigu.x;
i = (v.i[LOW_HALF]&0x000003ff)<<2;
/*------------------------------------- |x-1| < 2**-11------------------------------- */
if ((two52.i[LOW_HALF] == 1023) && (i == 1200))
{
t = x - 1.0;
EMULV(t,s3,y,yy,j1,j2,j3,j4,j5);
ADD2(-0.5,0,y,yy,z,zz,j1,j2);
MUL2(t,0,z,zz,y,yy,j1,j2,j3,j4,j5,j6,j7,j8);
MUL2(t,0,y,yy,z,zz,j1,j2,j3,j4,j5,j6,j7,j8);
e1 = t+z;
e2 = (((t-e1)+z)+zz)+t*t*t*(ss3+t*(s4+t*(s5+t*(s6+t*(s7+t*s8)))));
res = e1+e2;
*error = 1.0e-25*ABS(t);
*delta = (e1-res)+e2;
return res;
}
/*----------------------------- |x-1| > 2**-11 -------------------------- */
else
{ /*Computing log(x) according to log table */
nx = (two52.x - two52e.x)+add;
ou1 = ui.x[i];
ou2 = ui.x[i+1];
lu1 = ui.x[i+2];
lu2 = ui.x[i+3];
v.x = u.x*(ou1+ou2)+bigv.x;
vv = v.x-bigv.x;
j = v.i[LOW_HALF]&0x0007ffff;
j = j+j+j;
eps = u.x - uu*vv;
ov = vj.x[j];
lv1 = vj.x[j+1];
lv2 = vj.x[j+2];
a = (ou1+ou2)*(1.0+ov);
a1 = (a+1.0e10)-1.0e10;
a2 = a*(1.0-a1*uu*vv);
e1 = eps*a1;
e2 = eps*a2;
e = e1+e2;
e2 = (e1-e)+e2;
t=nx*ln2a.x+lu1+lv1;
t1 = t+e;
t2 = (((t-t1)+e)+(lu2+lv2+nx*ln2b.x+e2))+e*e*(p2+e*(p3+e*p4));
res=t1+t2;
*error = 1.0e-27;
*delta = (t1-res)+t2;
return res;
}
}
/**********************************************************************/
/* Routine receives a double x and checks if it is an integer. If not */
/* it returns 0, else it returns 1 if even or -1 if odd. */
/**********************************************************************/
static int checkint(double x) {
union {int4 i[2]; double x;} u;
int k,m,n;
#if 0
int l;
#endif
u.x = x;
m = u.i[HIGH_HALF]&0x7fffffff; /* no sign */
if (m >= 0x7ff00000) return 0; /* x is +/-inf or NaN */
if (m >= 0x43400000) return 1; /* |x| >= 2**53 */
if (m < 0x40000000) return 0; /* |x| < 2, can not be 0 or 1 */
n = u.i[LOW_HALF];
k = (m>>20)-1023; /* 1 <= k <= 52 */
if (k == 52) return (n&1)? -1:1; /* odd or even*/
if (k>20) {
if (n<<(k-20)) return 0; /* if not integer */
return (n<<(k-21))?-1:1;
}
if (n) return 0; /*if not integer*/
if (k == 20) return (m&1)? -1:1;
if (m<<(k+12)) return 0;
return (m<<(k+11))?-1:1;
}
@@ -0,0 +1,257 @@
/* e_powf.c -- float version of e_pow.c.
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
*/
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_powf.c,v 1.7 1996/04/08 15:43:44 phil Exp $";
#endif
#include "math.h"
#include "math_private.h"
static const float huge = 1.0e+30, tiny = 1.0e-30;
#ifdef __STDC__
static const float
#else
static float
#endif
bp[] = {1.0, 1.5,},
dp_h[] = { 0.0, 5.84960938e-01,}, /* 0x3f15c000 */
dp_l[] = { 0.0, 1.56322085e-06,}, /* 0x35d1cfdc */
zero = 0.0,
one = 1.0,
two = 2.0,
two24 = 16777216.0, /* 0x4b800000 */
/* poly coefs for (3/2)*(log(x)-2s-2/3*s**3 */
L1 = 6.0000002384e-01, /* 0x3f19999a */
L2 = 4.2857143283e-01, /* 0x3edb6db7 */
L3 = 3.3333334327e-01, /* 0x3eaaaaab */
L4 = 2.7272811532e-01, /* 0x3e8ba305 */
L5 = 2.3066075146e-01, /* 0x3e6c3255 */
L6 = 2.0697501302e-01, /* 0x3e53f142 */
P1 = 1.6666667163e-01, /* 0x3e2aaaab */
P2 = -2.7777778450e-03, /* 0xbb360b61 */
P3 = 6.6137559770e-05, /* 0x388ab355 */
P4 = -1.6533901999e-06, /* 0xb5ddea0e */
P5 = 4.1381369442e-08, /* 0x3331bb4c */
lg2 = 6.9314718246e-01, /* 0x3f317218 */
lg2_h = 6.93145752e-01, /* 0x3f317200 */
lg2_l = 1.42860654e-06, /* 0x35bfbe8c */
ovt = 4.2995665694e-08, /* -(128-log2(ovfl+.5ulp)) */
cp = 9.6179670095e-01, /* 0x3f76384f =2/(3ln2) */
cp_h = 9.6179199219e-01, /* 0x3f763800 =head of cp */
cp_l = 4.7017383622e-06, /* 0x369dc3a0 =tail of cp_h */
ivln2 = 1.4426950216e+00, /* 0x3fb8aa3b =1/ln2 */
ivln2_h = 1.4426879883e+00, /* 0x3fb8aa00 =16b 1/ln2*/
ivln2_l = 7.0526075433e-06; /* 0x36eca570 =1/ln2 tail*/
#ifdef __STDC__
float __ieee754_powf(float x, float y)
#else
float __ieee754_powf(x,y)
float x, y;
#endif
{
float z,ax,z_h,z_l,p_h,p_l;
float y1,t1,t2,r,s,t,u,v,w;
int32_t i,j,k,yisint,n;
int32_t hx,hy,ix,iy,is;
GET_FLOAT_WORD(hx,x);
GET_FLOAT_WORD(hy,y);
ix = hx&0x7fffffff; iy = hy&0x7fffffff;
/* y==zero: x**0 = 1 */
if(iy==0) return one;
/* x==+-1 */
if(x == 1.0) return one;
if(x == -1.0 && isinf(y)) return one;
/* +-NaN return x+y */
if(ix > 0x7f800000 ||
iy > 0x7f800000)
return x+y;
/* determine if y is an odd int when x < 0
* yisint = 0 ... y is not an integer
* yisint = 1 ... y is an odd int
* yisint = 2 ... y is an even int
*/
yisint = 0;
if(hx<0) {
if(iy>=0x4b800000) yisint = 2; /* even integer y */
else if(iy>=0x3f800000) {
k = (iy>>23)-0x7f; /* exponent */
j = iy>>(23-k);
if((j<<(23-k))==iy) yisint = 2-(j&1);
}
}
/* special value of y */
if (iy==0x7f800000) { /* y is +-inf */
if (ix==0x3f800000)
return y - y; /* inf**+-1 is NaN */
else if (ix > 0x3f800000)/* (|x|>1)**+-inf = inf,0 */
return (hy>=0)? y: zero;
else /* (|x|<1)**-,+inf = inf,0 */
return (hy<0)?-y: zero;
}
if(iy==0x3f800000) { /* y is +-1 */
if(hy<0) return one/x; else return x;
}
if(hy==0x40000000) return x*x; /* y is 2 */
if(hy==0x3f000000) { /* y is 0.5 */
if(hx>=0) /* x >= +0 */
return __ieee754_sqrtf(x);
}
ax = fabsf(x);
/* special value of x */
if(ix==0x7f800000||ix==0||ix==0x3f800000){
z = ax; /*x is +-0,+-inf,+-1*/
if(hy<0) z = one/z; /* z = (1/|x|) */
if(hx<0) {
if(((ix-0x3f800000)|yisint)==0) {
z = (z-z)/(z-z); /* (-1)**non-int is NaN */
} else if(yisint==1)
z = -z; /* (x<0)**odd = -(|x|**odd) */
}
return z;
}
/* (x<0)**(non-int) is NaN */
if(((((u_int32_t)hx>>31)-1)|yisint)==0) return (x-x)/(x-x);
/* |y| is huge */
if(iy>0x4d000000) { /* if |y| > 2**27 */
/* over/underflow if x is not close to one */
if(ix<0x3f7ffff8) return (hy<0)? huge*huge:tiny*tiny;
if(ix>0x3f800007) return (hy>0)? huge*huge:tiny*tiny;
/* now |1-x| is tiny <= 2**-20, suffice to compute
log(x) by x-x^2/2+x^3/3-x^4/4 */
t = x-1; /* t has 20 trailing zeros */
w = (t*t)*((float)0.5-t*((float)0.333333333333-t*(float)0.25));
u = ivln2_h*t; /* ivln2_h has 16 sig. bits */
v = t*ivln2_l-w*ivln2;
t1 = u+v;
GET_FLOAT_WORD(is,t1);
SET_FLOAT_WORD(t1,is&0xfffff000);
t2 = v-(t1-u);
} else {
float s2,s_h,s_l,t_h,t_l;
n = 0;
/* take care subnormal number */
if(ix<0x00800000)
{ax *= two24; n -= 24; GET_FLOAT_WORD(ix,ax); }
n += ((ix)>>23)-0x7f;
j = ix&0x007fffff;
/* determine interval */
ix = j|0x3f800000; /* normalize ix */
if(j<=0x1cc471) k=0; /* |x|<sqrt(3/2) */
else if(j<0x5db3d7) k=1; /* |x|<sqrt(3) */
else {k=0;n+=1;ix -= 0x00800000;}
SET_FLOAT_WORD(ax,ix);
/* compute s = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */
u = ax-bp[k]; /* bp[0]=1.0, bp[1]=1.5 */
v = one/(ax+bp[k]);
s = u*v;
s_h = s;
GET_FLOAT_WORD(is,s_h);
SET_FLOAT_WORD(s_h,is&0xfffff000);
/* t_h=ax+bp[k] High */
SET_FLOAT_WORD(t_h,((ix>>1)|0x20000000)+0x0040000+(k<<21));
t_l = ax - (t_h-bp[k]);
s_l = v*((u-s_h*t_h)-s_h*t_l);
/* compute log(ax) */
s2 = s*s;
r = s2*s2*(L1+s2*(L2+s2*(L3+s2*(L4+s2*(L5+s2*L6)))));
r += s_l*(s_h+s);
s2 = s_h*s_h;
t_h = (float)3.0+s2+r;
GET_FLOAT_WORD(is,t_h);
SET_FLOAT_WORD(t_h,is&0xfffff000);
t_l = r-((t_h-(float)3.0)-s2);
/* u+v = s*(1+...) */
u = s_h*t_h;
v = s_l*t_h+t_l*s;
/* 2/(3log2)*(s+...) */
p_h = u+v;
GET_FLOAT_WORD(is,p_h);
SET_FLOAT_WORD(p_h,is&0xfffff000);
p_l = v-(p_h-u);
z_h = cp_h*p_h; /* cp_h+cp_l = 2/(3*log2) */
z_l = cp_l*p_h+p_l*cp+dp_l[k];
/* log2(ax) = (s+..)*2/(3*log2) = n + dp_h + z_h + z_l */
t = (float)n;
t1 = (((z_h+z_l)+dp_h[k])+t);
GET_FLOAT_WORD(is,t1);
SET_FLOAT_WORD(t1,is&0xfffff000);
t2 = z_l-(((t1-t)-dp_h[k])-z_h);
}
s = one; /* s (sign of result -ve**odd) = -1 else = 1 */
if(((((u_int32_t)hx>>31)-1)|(yisint-1))==0)
s = -one; /* (-ve)**(odd int) */
/* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */
GET_FLOAT_WORD(is,y);
SET_FLOAT_WORD(y1,is&0xfffff000);
p_l = (y-y1)*t1+y*t2;
p_h = y1*t1;
z = p_l+p_h;
GET_FLOAT_WORD(j,z);
if (j>0x43000000) /* if z > 128 */
return s*huge*huge; /* overflow */
else if (j==0x43000000) { /* if z == 128 */
if(p_l+ovt>z-p_h) return s*huge*huge; /* overflow */
}
else if ((j&0x7fffffff)>0x43160000) /* z <= -150 */
return s*tiny*tiny; /* underflow */
else if ((u_int32_t) j==0xc3160000){ /* z == -150 */
if(p_l<=z-p_h) return s*tiny*tiny; /* underflow */
}
/*
* compute 2**(p_h+p_l)
*/
i = j&0x7fffffff;
k = (i>>23)-0x7f;
n = 0;
if(i>0x3f000000) { /* if |z| > 0.5, set n = [z+0.5] */
n = j+(0x00800000>>(k+1));
k = ((n&0x7fffffff)>>23)-0x7f; /* new k for n */
SET_FLOAT_WORD(t,n&~(0x007fffff>>k));
n = ((n&0x007fffff)|0x00800000)>>(23-k);
if(j<0) n = -n;
p_h -= t;
}
t = p_l+p_h;
GET_FLOAT_WORD(is,t);
SET_FLOAT_WORD(t,is&0xfffff000);
u = t*lg2_h;
v = (p_l-(t-p_h))*lg2+t*lg2_l;
z = u+v;
w = v-(z-u);
t = z*z;
t1 = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))));
r = (z*t1)/(t1-two)-(w+z*w);
z = one-(r-z);
GET_FLOAT_WORD(j,z);
j += (n<<23);
if((j>>23)<=0) z = __scalbnf(z,n); /* subnormal output */
else SET_FLOAT_WORD(z,j);
return s*z;
}
@@ -0,0 +1,196 @@
/* e_rem_pio2f.c -- float version of e_rem_pio2.c
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
*/
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_rem_pio2f.c,v 1.5 1995/05/10 20:46:03 jtc Exp $";
#endif
/* __ieee754_rem_pio2f(x,y)
*
* return the remainder of x rem pi/2 in y[0]+y[1]
* use __kernel_rem_pio2f()
*/
#include "math.h"
#include "math_private.h"
/*
* Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi
*/
#ifdef __STDC__
static const int32_t two_over_pi[] = {
#else
static int32_t two_over_pi[] = {
#endif
0xA2, 0xF9, 0x83, 0x6E, 0x4E, 0x44, 0x15, 0x29, 0xFC,
0x27, 0x57, 0xD1, 0xF5, 0x34, 0xDD, 0xC0, 0xDB, 0x62,
0x95, 0x99, 0x3C, 0x43, 0x90, 0x41, 0xFE, 0x51, 0x63,
0xAB, 0xDE, 0xBB, 0xC5, 0x61, 0xB7, 0x24, 0x6E, 0x3A,
0x42, 0x4D, 0xD2, 0xE0, 0x06, 0x49, 0x2E, 0xEA, 0x09,
0xD1, 0x92, 0x1C, 0xFE, 0x1D, 0xEB, 0x1C, 0xB1, 0x29,
0xA7, 0x3E, 0xE8, 0x82, 0x35, 0xF5, 0x2E, 0xBB, 0x44,
0x84, 0xE9, 0x9C, 0x70, 0x26, 0xB4, 0x5F, 0x7E, 0x41,
0x39, 0x91, 0xD6, 0x39, 0x83, 0x53, 0x39, 0xF4, 0x9C,
0x84, 0x5F, 0x8B, 0xBD, 0xF9, 0x28, 0x3B, 0x1F, 0xF8,
0x97, 0xFF, 0xDE, 0x05, 0x98, 0x0F, 0xEF, 0x2F, 0x11,
0x8B, 0x5A, 0x0A, 0x6D, 0x1F, 0x6D, 0x36, 0x7E, 0xCF,
0x27, 0xCB, 0x09, 0xB7, 0x4F, 0x46, 0x3F, 0x66, 0x9E,
0x5F, 0xEA, 0x2D, 0x75, 0x27, 0xBA, 0xC7, 0xEB, 0xE5,
0xF1, 0x7B, 0x3D, 0x07, 0x39, 0xF7, 0x8A, 0x52, 0x92,
0xEA, 0x6B, 0xFB, 0x5F, 0xB1, 0x1F, 0x8D, 0x5D, 0x08,
0x56, 0x03, 0x30, 0x46, 0xFC, 0x7B, 0x6B, 0xAB, 0xF0,
0xCF, 0xBC, 0x20, 0x9A, 0xF4, 0x36, 0x1D, 0xA9, 0xE3,
0x91, 0x61, 0x5E, 0xE6, 0x1B, 0x08, 0x65, 0x99, 0x85,
0x5F, 0x14, 0xA0, 0x68, 0x40, 0x8D, 0xFF, 0xD8, 0x80,
0x4D, 0x73, 0x27, 0x31, 0x06, 0x06, 0x15, 0x56, 0xCA,
0x73, 0xA8, 0xC9, 0x60, 0xE2, 0x7B, 0xC0, 0x8C, 0x6B,
};
/* This array is like the one in e_rem_pio2.c, but the numbers are
single precision and the last 8 bits are forced to 0. */
#ifdef __STDC__
static const int32_t npio2_hw[] = {
#else
static int32_t npio2_hw[] = {
#endif
0x3fc90f00, 0x40490f00, 0x4096cb00, 0x40c90f00, 0x40fb5300, 0x4116cb00,
0x412fed00, 0x41490f00, 0x41623100, 0x417b5300, 0x418a3a00, 0x4196cb00,
0x41a35c00, 0x41afed00, 0x41bc7e00, 0x41c90f00, 0x41d5a000, 0x41e23100,
0x41eec200, 0x41fb5300, 0x4203f200, 0x420a3a00, 0x42108300, 0x4216cb00,
0x421d1400, 0x42235c00, 0x4229a500, 0x422fed00, 0x42363600, 0x423c7e00,
0x4242c700, 0x42490f00
};
/*
* invpio2: 24 bits of 2/pi
* pio2_1: first 17 bit of pi/2
* pio2_1t: pi/2 - pio2_1
* pio2_2: second 17 bit of pi/2
* pio2_2t: pi/2 - (pio2_1+pio2_2)
* pio2_3: third 17 bit of pi/2
* pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3)
*/
#ifdef __STDC__
static const float
#else
static float
#endif
zero = 0.0000000000e+00, /* 0x00000000 */
half = 5.0000000000e-01, /* 0x3f000000 */
two8 = 2.5600000000e+02, /* 0x43800000 */
invpio2 = 6.3661980629e-01, /* 0x3f22f984 */
pio2_1 = 1.5707855225e+00, /* 0x3fc90f80 */
pio2_1t = 1.0804334124e-05, /* 0x37354443 */
pio2_2 = 1.0804273188e-05, /* 0x37354400 */
pio2_2t = 6.0770999344e-11, /* 0x2e85a308 */
pio2_3 = 6.0770943833e-11, /* 0x2e85a300 */
pio2_3t = 6.1232342629e-17; /* 0x248d3132 */
#ifdef __STDC__
int32_t __ieee754_rem_pio2f(float x, float *y)
#else
int32_t __ieee754_rem_pio2f(x,y)
float x,y[];
#endif
{
float z,w,t,r,fn;
float tx[3];
int32_t e0,i,j,nx,n,ix,hx;
GET_FLOAT_WORD(hx,x);
ix = hx&0x7fffffff;
if(ix<=0x3f490fd8) /* |x| ~<= pi/4 , no need for reduction */
{y[0] = x; y[1] = 0; return 0;}
if(ix<0x4016cbe4) { /* |x| < 3pi/4, special case with n=+-1 */
if(hx>0) {
z = x - pio2_1;
if((ix&0xfffffff0)!=0x3fc90fd0) { /* 24+24 bit pi OK */
y[0] = z - pio2_1t;
y[1] = (z-y[0])-pio2_1t;
} else { /* near pi/2, use 24+24+24 bit pi */
z -= pio2_2;
y[0] = z - pio2_2t;
y[1] = (z-y[0])-pio2_2t;
}
return 1;
} else { /* negative x */
z = x + pio2_1;
if((ix&0xfffffff0)!=0x3fc90fd0) { /* 24+24 bit pi OK */
y[0] = z + pio2_1t;
y[1] = (z-y[0])+pio2_1t;
} else { /* near pi/2, use 24+24+24 bit pi */
z += pio2_2;
y[0] = z + pio2_2t;
y[1] = (z-y[0])+pio2_2t;
}
return -1;
}
}
if(ix<=0x43490f80) { /* |x| ~<= 2^7*(pi/2), medium size */
t = fabsf(x);
n = (int32_t) (t*invpio2+half);
fn = (float)n;
r = t-fn*pio2_1;
w = fn*pio2_1t; /* 1st round good to 40 bit */
if(n<32&&(int32_t)(ix&0xffffff00)!=npio2_hw[n-1]) {
y[0] = r-w; /* quick check no cancellation */
} else {
u_int32_t high;
j = ix>>23;
y[0] = r-w;
GET_FLOAT_WORD(high,y[0]);
i = j-((high>>23)&0xff);
if(i>8) { /* 2nd iteration needed, good to 57 */
t = r;
w = fn*pio2_2;
r = t-w;
w = fn*pio2_2t-((t-r)-w);
y[0] = r-w;
GET_FLOAT_WORD(high,y[0]);
i = j-((high>>23)&0xff);
if(i>25) { /* 3rd iteration need, 74 bits acc */
t = r; /* will cover all possible cases */
w = fn*pio2_3;
r = t-w;
w = fn*pio2_3t-((t-r)-w);
y[0] = r-w;
}
}
}
y[1] = (r-y[0])-w;
if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;}
else return n;
}
/*
* all other (large) arguments
*/
if(ix>=0x7f800000) { /* x is inf or NaN */
y[0]=y[1]=x-x; return 0;
}
/* set z = scalbn(|x|,ilogb(x)-7) */
e0 = (ix>>23)-134; /* e0 = ilogb(z)-7; */
SET_FLOAT_WORD(z, ix - ((int32_t)(e0<<23)));
for(i=0;i<2;i++) {
tx[i] = (float)((int32_t)(z));
z = (z-tx[i])*two8;
}
tx[2] = z;
nx = 3;
while(tx[nx-1]==zero) nx--; /* skip zero term */
n = __kernel_rem_pio2f(tx,y,e0,nx,2,two_over_pi);
if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;}
return n;
}
@@ -0,0 +1,130 @@
/*
* IBM Accurate Mathematical Library
* written by International Business Machines Corp.
* Copyright (C) 2001 Free Software Foundation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/**************************************************************************/
/* MODULE_NAME urem.c */
/* */
/* FUNCTION: uremainder */
/* */
/* An ultimate remainder routine. Given two IEEE double machine numbers x */
/* ,y it computes the correctly rounded (to nearest) value of remainder */
/* of dividing x by y. */
/* Assumption: Machine arithmetic operations are performed in */
/* round to nearest mode of IEEE 754 standard. */
/* */
/* ************************************************************************/
#include "endian.h"
#include "mydefs.h"
#include "urem.h"
#include "MathLib.h"
#include "math_private.h"
/**************************************************************************/
/* An ultimate remainder routine. Given two IEEE double machine numbers x */
/* ,y it computes the correctly rounded (to nearest) value of remainder */
/**************************************************************************/
double __ieee754_remainder(double x, double y)
{
double z,d,xx;
#if 0
double yy;
#endif
int4 kx,ky,n,nn,n1,m1,l;
#if 0
int4 m;
#endif
mynumber u,t,w={{0,0}},v={{0,0}},ww={{0,0}},r;
u.x=x;
t.x=y;
kx=u.i[HIGH_HALF]&0x7fffffff; /* no sign for x*/
t.i[HIGH_HALF]&=0x7fffffff; /*no sign for y */
ky=t.i[HIGH_HALF];
/*------ |x| < 2^1023 and 2^-970 < |y| < 2^1024 ------------------*/
if (kx<0x7fe00000 && ky<0x7ff00000 && ky>=0x03500000) {
if (kx+0x00100000<ky) return x;
if ((kx-0x01500000)<ky) {
z=x/t.x;
v.i[HIGH_HALF]=t.i[HIGH_HALF];
d=(z+big.x)-big.x;
xx=(x-d*v.x)-d*(t.x-v.x);
if (d-z!=0.5&&d-z!=-0.5) return (xx!=0)?xx:((x>0)?ZERO.x:nZERO.x);
else {
if (ABS(xx)>0.5*t.x) return (z>d)?xx-t.x:xx+t.x;
else return xx;
}
} /* (kx<(ky+0x01500000)) */
else {
r.x=1.0/t.x;
n=t.i[HIGH_HALF];
nn=(n&0x7ff00000)+0x01400000;
w.i[HIGH_HALF]=n;
ww.x=t.x-w.x;
l=(kx-nn)&0xfff00000;
n1=ww.i[HIGH_HALF];
m1=r.i[HIGH_HALF];
while (l>0) {
r.i[HIGH_HALF]=m1-l;
z=u.x*r.x;
w.i[HIGH_HALF]=n+l;
ww.i[HIGH_HALF]=(n1)?n1+l:n1;
d=(z+big.x)-big.x;
u.x=(u.x-d*w.x)-d*ww.x;
l=(u.i[HIGH_HALF]&0x7ff00000)-nn;
}
r.i[HIGH_HALF]=m1;
w.i[HIGH_HALF]=n;
ww.i[HIGH_HALF]=n1;
z=u.x*r.x;
d=(z+big.x)-big.x;
u.x=(u.x-d*w.x)-d*ww.x;
if (ABS(u.x)<0.5*t.x) return (u.x!=0)?u.x:((x>0)?ZERO.x:nZERO.x);
else
if (ABS(u.x)>0.5*t.x) return (d>z)?u.x+t.x:u.x-t.x;
else
{z=u.x/t.x; d=(z+big.x)-big.x; return ((u.x-d*w.x)-d*ww.x);}
}
} /* (kx<0x7fe00000&&ky<0x7ff00000&&ky>=0x03500000) */
else {
if (kx<0x7fe00000&&ky<0x7ff00000&&(ky>0||t.i[LOW_HALF]!=0)) {
y=ABS(y)*t128.x;
z=__ieee754_remainder(x,y)*t128.x;
z=__ieee754_remainder(z,y)*tm128.x;
return z;
}
else {
if ((kx&0x7ff00000)==0x7fe00000&&ky<0x7ff00000&&(ky>0||t.i[LOW_HALF]!=0)) {
y=ABS(y);
z=2.0*__ieee754_remainder(0.5*x,y);
d = ABS(z);
if (d <= ABS(d-y)) return z;
else return (z>0)?z-y:z+y;
}
else { /* if x is too big */
if (kx == 0x7ff00000 && u.i[LOW_HALF] == 0 && y == 1.0)
return x / x;
if (kx>=0x7ff00000||(ky==0&&t.i[LOW_HALF]==0)||ky>0x7ff00000||
(ky==0x7ff00000&&t.i[LOW_HALF]!=0))
return (u.i[HIGH_HALF]&0x80000000)?nNAN.x:NAN.x;
else return x;
}
}
}
}
@@ -0,0 +1,73 @@
/* e_remainderf.c -- float version of e_remainder.c.
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
*/
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_remainderf.c,v 1.4 1995/05/10 20:46:08 jtc Exp $";
#endif
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const float zero = 0.0;
#else
static float zero = 0.0;
#endif
#ifdef __STDC__
float __ieee754_remainderf(float x, float p)
#else
float __ieee754_remainderf(x,p)
float x,p;
#endif
{
int32_t hx,hp;
u_int32_t sx;
float p_half;
GET_FLOAT_WORD(hx,x);
GET_FLOAT_WORD(hp,p);
sx = hx&0x80000000;
hp &= 0x7fffffff;
hx &= 0x7fffffff;
/* purge off exception values */
if(hp==0) return (x*p)/(x*p); /* p = 0 */
if((hx>=0x7f800000)|| /* x not finite */
((hp>0x7f800000))) /* p is NaN */
return (x*p)/(x*p);
if (hp<=0x7effffff) x = __ieee754_fmodf(x,p+p); /* now x < 2p */
if ((hx-hp)==0) return zero*x;
x = fabsf(x);
p = fabsf(p);
if (hp<0x01000000) {
if(x+x>p) {
x-=p;
if(x+x>=p) x -= p;
}
} else {
p_half = (float)0.5*p;
if(x>p_half) {
x-=p;
if(x>=p_half) x -= p;
}
}
GET_FLOAT_WORD(hx,x);
SET_FLOAT_WORD(x,hx^sx);
return x;
}
@@ -0,0 +1,71 @@
/* @(#)e_scalb.c 5.1 93/09/24 */
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_scalb.c,v 1.6 1995/05/10 20:46:09 jtc Exp $";
#endif
/*
* __ieee754_scalb(x, fn) is provide for
* passing various standard test suite. One
* should use scalbn() instead.
*/
#include <fenv.h>
#include "math.h"
#include "math_private.h"
#ifdef _SCALB_INT
#ifdef __STDC__
double __ieee754_scalb(double x, int fn)
#else
double __ieee754_scalb(x,fn)
double x; int fn;
#endif
#else
#ifdef __STDC__
double __ieee754_scalb(double x, double fn)
#else
double __ieee754_scalb(x,fn)
double x, fn;
#endif
#endif
{
#ifdef _SCALB_INT
return __scalbn(x,fn);
#else
if (__isnan(x)||__isnan(fn)) return x*fn;
if (!__finite(fn)) {
if(fn>0.0) return x*fn;
else if (x == 0)
return x;
else if (!__finite (x))
{
# ifdef FE_INVALID
feraiseexcept (FE_INVALID);
# endif
return __nan ("");
}
else return x/(-fn);
}
if (__rint(fn)!=fn)
{
# ifdef FE_INVALID
feraiseexcept (FE_INVALID);
# endif
return __nan ("");
}
if ( fn > 65000.0) return __scalbn(x, 65000);
if (-fn > 65000.0) return __scalbn(x,-65000);
return __scalbn(x,(int)fn);
#endif
}
@@ -0,0 +1,68 @@
/* e_scalbf.c -- float version of e_scalb.c.
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
*/
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_scalbf.c,v 1.3 1995/05/10 20:46:12 jtc Exp $";
#endif
#include <fenv.h>
#include "math.h"
#include "math_private.h"
#ifdef _SCALB_INT
#ifdef __STDC__
float __ieee754_scalbf(float x, int fn)
#else
float __ieee754_scalbf(x,fn)
float x; int fn;
#endif
#else
#ifdef __STDC__
float __ieee754_scalbf(float x, float fn)
#else
float __ieee754_scalbf(x,fn)
float x, fn;
#endif
#endif
{
#ifdef _SCALB_INT
return __scalbnf(x,fn);
#else
if (__isnanf(x)||__isnanf(fn)) return x*fn;
if (!__finitef(fn)) {
if(fn>(float)0.0) return x*fn;
else if (x == 0)
return x;
else if (!__finitef (x))
{
# ifdef FE_INVALID
feraiseexcept (FE_INVALID);
# endif
return __nanf ("");
}
else return x/(-fn);
}
if (__rintf(fn)!=fn)
{
# ifdef FE_INVALID
feraiseexcept (FE_INVALID);
# endif
return __nanf ("");
}
if ( fn > (float)65000.0) return __scalbnf(x, 65000);
if (-fn > (float)65000.0) return __scalbnf(x,-65000);
return __scalbnf(x,(int)fn);
#endif
}
@@ -0,0 +1,86 @@
/* @(#)e_sinh.c 5.1 93/09/24 */
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_sinh.c,v 1.7 1995/05/10 20:46:13 jtc Exp $";
#endif
/* __ieee754_sinh(x)
* Method :
* mathematically sinh(x) if defined to be (exp(x)-exp(-x))/2
* 1. Replace x by |x| (sinh(-x) = -sinh(x)).
* 2.
* E + E/(E+1)
* 0 <= x <= 22 : sinh(x) := --------------, E=expm1(x)
* 2
*
* 22 <= x <= lnovft : sinh(x) := exp(x)/2
* lnovft <= x <= ln2ovft: sinh(x) := exp(x/2)/2 * exp(x/2)
* ln2ovft < x : sinh(x) := x*shuge (overflow)
*
* Special cases:
* sinh(x) is |x| if x is +INF, -INF, or NaN.
* only sinh(0)=0 is exact for finite x.
*/
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const double one = 1.0, shuge = 1.0e307;
#else
static double one = 1.0, shuge = 1.0e307;
#endif
#ifdef __STDC__
double __ieee754_sinh(double x)
#else
double __ieee754_sinh(x)
double x;
#endif
{
double t,w,h;
int32_t ix,jx;
u_int32_t lx;
/* High word of |x|. */
GET_HIGH_WORD(jx,x);
ix = jx&0x7fffffff;
/* x is INF or NaN */
if(ix>=0x7ff00000) return x+x;
h = 0.5;
if (jx<0) h = -h;
/* |x| in [0,22], return sign(x)*0.5*(E+E/(E+1))) */
if (ix < 0x40360000) { /* |x|<22 */
if (ix<0x3e300000) /* |x|<2**-28 */
if(shuge+x>one) return x;/* sinh(tiny) = tiny with inexact */
t = __expm1(fabs(x));
if(ix<0x3ff00000) return h*(2.0*t-t*t/(t+one));
return h*(t+t/(t+one));
}
/* |x| in [22, log(maxdouble)] return 0.5*exp(|x|) */
if (ix < 0x40862e42) return h*__ieee754_exp(fabs(x));
/* |x| in [log(maxdouble), overflowthresold] */
GET_LOW_WORD(lx,x);
if (ix<0x408633ce || ((ix==0x408633ce)&&(lx<=(u_int32_t)0x8fb9f87d))) {
w = __ieee754_exp(0.5*fabs(x));
t = h*w;
return t*w;
}
/* |x| > overflowthresold, sinh(x) overflow */
return x*shuge;
}
@@ -0,0 +1,68 @@
/* e_sinhf.c -- float version of e_sinh.c.
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
*/
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: e_sinhf.c,v 1.4 1995/05/10 20:46:15 jtc Exp $";
#endif
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const float one = 1.0, shuge = 1.0e37;
#else
static float one = 1.0, shuge = 1.0e37;
#endif
#ifdef __STDC__
float __ieee754_sinhf(float x)
#else
float __ieee754_sinhf(x)
float x;
#endif
{
float t,w,h;
int32_t ix,jx;
GET_FLOAT_WORD(jx,x);
ix = jx&0x7fffffff;
/* x is INF or NaN */
if(ix>=0x7f800000) return x+x;
h = 0.5;
if (jx<0) h = -h;
/* |x| in [0,22], return sign(x)*0.5*(E+E/(E+1))) */
if (ix < 0x41b00000) { /* |x|<22 */
if (ix<0x31800000) /* |x|<2**-28 */
if(shuge+x>one) return x;/* sinh(tiny) = tiny with inexact */
t = __expm1f(fabsf(x));
if(ix<0x3f800000) return h*((float)2.0*t-t*t/(t+one));
return h*(t+t/(t+one));
}
/* |x| in [22, log(maxdouble)] return 0.5*exp(|x|) */
if (ix < 0x42b17180) return h*__ieee754_expf(fabsf(x));
/* |x| in [log(maxdouble), overflowthresold] */
if (ix<=0x42b2d4fc) {
w = __ieee754_expf((float)0.5*fabsf(x));
t = h*w;
return t*w;
}
/* |x| > overflowthresold, sinh(x) overflow */
return x*shuge;
}
@@ -0,0 +1,123 @@
/*
* IBM Accurate Mathematical Library
* written by International Business Machines Corp.
* Copyright (C) 2001 Free Software Foundation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/************************************************************************/
/* */
/* MODULE_NAME:halfulp.c */
/* */
/* FUNCTIONS:halfulp */
/* FILES NEEDED: mydefs.h dla.h endian.h */
/* uroot.c */
/* */
/*Routine halfulp(double x, double y) computes x^y where result does */
/*not need rounding. If the result is closer to 0 than can be */
/*represented it returns 0. */
/* In the following cases the function does not compute anything */
/*and returns a negative number: */
/*1. if the result needs rounding, */
/*2. if y is outside the interval [0, 2^20-1], */
/*3. if x can be represented by x=2**n for some integer n. */
/************************************************************************/
#include "endian.h"
#include "mydefs.h"
#include "dla.h"
#include "math_private.h"
double __ieee754_sqrt(double x);
int4 tab54[32] = {
262143, 11585, 1782, 511, 210, 107, 63, 42,
30, 22, 17, 14, 12, 10, 9, 7,
7, 6, 5, 5, 5, 4, 4, 4,
3, 3, 3, 3, 3, 3, 3, 3 };
double __halfulp(double x, double y)
{
mynumber v;
double z,u,uu,j1,j2,j3,j4,j5;
int4 k,l,m,n;
if (y <= 0) { /*if power is negative or zero */
v.x = y;
if (v.i[LOW_HALF] != 0) return -10.0;
v.x = x;
if (v.i[LOW_HALF] != 0) return -10.0;
if ((v.i[HIGH_HALF]&0x000fffff) != 0) return -10; /* if x =2 ^ n */
k = ((v.i[HIGH_HALF]&0x7fffffff)>>20)-1023; /* find this n */
z = (double) k;
return (z*y == -1075.0)?0: -10.0;
}
/* if y > 0 */
v.x = y;
if (v.i[LOW_HALF] != 0) return -10.0;
v.x=x;
/* case where x = 2**n for some integer n */
if (((v.i[HIGH_HALF]&0x000fffff)|v.i[LOW_HALF]) == 0) {
k=(v.i[HIGH_HALF]>>20)-1023;
return (((double) k)*y == -1075.0)?0:-10.0;
}
v.x = y;
k = v.i[HIGH_HALF];
m = k<<12;
l = 0;
while (m)
{m = m<<1; l++; }
n = (k&0x000fffff)|0x00100000;
n = n>>(20-l); /* n is the odd integer of y */
k = ((k>>20) -1023)-l; /* y = n*2**k */
if (k>5) return -10.0;
if (k>0) for (;k>0;k--) n *= 2;
if (n > 34) return -10.0;
k = -k;
if (k>5) return -10.0;
/* now treat x */
while (k>0) {
z = __ieee754_sqrt(x);
EMULV(z,z,u,uu,j1,j2,j3,j4,j5);
if (((u-x)+uu) != 0) break;
x = z;
k--;
}
if (k) return -10.0;
/* it is impossible that n == 2, so the mantissa of x must be short */
v.x = x;
if (v.i[LOW_HALF]) return -10.0;
k = v.i[HIGH_HALF];
m = k<<12;
l = 0;
while (m) {m = m<<1; l++; }
m = (k&0x000fffff)|0x00100000;
m = m>>(20-l); /* m is the odd integer of x */
/* now check whether the length of m**n is at most 54 bits */
if (m > tab54[n-3]) return -10.0;
/* yes, it is - now compute x**n by simple multiplications */
u = x;
for (k=1;k<n;k++) u = u*x;
return u;
}
@@ -0,0 +1 @@
/* Not needed anymore. */
@@ -0,0 +1,64 @@
/* k_cosf.c -- float version of k_cos.c
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
*/
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: k_cosf.c,v 1.4 1995/05/10 20:46:23 jtc Exp $";
#endif
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const float
#else
static float
#endif
one = 1.0000000000e+00, /* 0x3f800000 */
C1 = 4.1666667908e-02, /* 0x3d2aaaab */
C2 = -1.3888889225e-03, /* 0xbab60b61 */
C3 = 2.4801587642e-05, /* 0x37d00d01 */
C4 = -2.7557314297e-07, /* 0xb493f27c */
C5 = 2.0875723372e-09, /* 0x310f74f6 */
C6 = -1.1359647598e-11; /* 0xad47d74e */
#ifdef __STDC__
float __kernel_cosf(float x, float y)
#else
float __kernel_cosf(x, y)
float x,y;
#endif
{
float a,hz,z,r,qx;
int32_t ix;
GET_FLOAT_WORD(ix,x);
ix &= 0x7fffffff; /* ix = |x|'s high word*/
if(ix<0x32000000) { /* if x < 2**27 */
if(((int)x)==0) return one; /* generate inexact */
}
z = x*x;
r = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*C6)))));
if(ix < 0x3e99999a) /* if |x| < 0.3 */
return one - ((float)0.5*z - (z*r - x*y));
else {
if(ix > 0x3f480000) { /* x > 0.78125 */
qx = (float)0.28125;
} else {
SET_FLOAT_WORD(qx,ix-0x01000000); /* x/4 */
}
hz = (float)0.5*z-qx;
a = one-qx;
return a - (hz - (z*r-x*y));
}
}
@@ -0,0 +1,320 @@
/* @(#)k_rem_pio2.c 5.1 93/09/24 */
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: k_rem_pio2.c,v 1.7 1995/05/10 20:46:25 jtc Exp $";
#endif
/*
* __kernel_rem_pio2(x,y,e0,nx,prec,ipio2)
* double x[],y[]; int e0,nx,prec; int ipio2[];
*
* __kernel_rem_pio2 return the last three digits of N with
* y = x - N*pi/2
* so that |y| < pi/2.
*
* The method is to compute the integer (mod 8) and fraction parts of
* (2/pi)*x without doing the full multiplication. In general we
* skip the part of the product that are known to be a huge integer (
* more accurately, = 0 mod 8 ). Thus the number of operations are
* independent of the exponent of the input.
*
* (2/pi) is represented by an array of 24-bit integers in ipio2[].
*
* Input parameters:
* x[] The input value (must be positive) is broken into nx
* pieces of 24-bit integers in double precision format.
* x[i] will be the i-th 24 bit of x. The scaled exponent
* of x[0] is given in input parameter e0 (i.e., x[0]*2^e0
* match x's up to 24 bits.
*
* Example of breaking a double positive z into x[0]+x[1]+x[2]:
* e0 = ilogb(z)-23
* z = scalbn(z,-e0)
* for i = 0,1,2
* x[i] = floor(z)
* z = (z-x[i])*2**24
*
*
* y[] ouput result in an array of double precision numbers.
* The dimension of y[] is:
* 24-bit precision 1
* 53-bit precision 2
* 64-bit precision 2
* 113-bit precision 3
* The actual value is the sum of them. Thus for 113-bit
* precision, one may have to do something like:
*
* long double t,w,r_head, r_tail;
* t = (long double)y[2] + (long double)y[1];
* w = (long double)y[0];
* r_head = t+w;
* r_tail = w - (r_head - t);
*
* e0 The exponent of x[0]
*
* nx dimension of x[]
*
* prec an integer indicating the precision:
* 0 24 bits (single)
* 1 53 bits (double)
* 2 64 bits (extended)
* 3 113 bits (quad)
*
* ipio2[]
* integer array, contains the (24*i)-th to (24*i+23)-th
* bit of 2/pi after binary point. The corresponding
* floating value is
*
* ipio2[i] * 2^(-24(i+1)).
*
* External function:
* double scalbn(), floor();
*
*
* Here is the description of some local variables:
*
* jk jk+1 is the initial number of terms of ipio2[] needed
* in the computation. The recommended value is 2,3,4,
* 6 for single, double, extended,and quad.
*
* jz local integer variable indicating the number of
* terms of ipio2[] used.
*
* jx nx - 1
*
* jv index for pointing to the suitable ipio2[] for the
* computation. In general, we want
* ( 2^e0*x[0] * ipio2[jv-1]*2^(-24jv) )/8
* is an integer. Thus
* e0-3-24*jv >= 0 or (e0-3)/24 >= jv
* Hence jv = max(0,(e0-3)/24).
*
* jp jp+1 is the number of terms in PIo2[] needed, jp = jk.
*
* q[] double array with integral value, representing the
* 24-bits chunk of the product of x and 2/pi.
*
* q0 the corresponding exponent of q[0]. Note that the
* exponent for q[i] would be q0-24*i.
*
* PIo2[] double precision array, obtained by cutting pi/2
* into 24 bits chunks.
*
* f[] ipio2[] in floating point
*
* iq[] integer array by breaking up q[] in 24-bits chunk.
*
* fq[] final product of x*(2/pi) in fq[0],..,fq[jk]
*
* ih integer. If >0 it indicates q[] is >= 0.5, hence
* it also indicates the *sign* of the result.
*
*/
/*
* Constants:
* The hexadecimal values are the intended ones for the following
* constants. The decimal values may be used, provided that the
* compiler will convert from decimal to binary accurately enough
* to produce the hexadecimal values shown.
*/
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const int init_jk[] = {2,3,4,6}; /* initial value for jk */
#else
static int init_jk[] = {2,3,4,6};
#endif
#ifdef __STDC__
static const double PIo2[] = {
#else
static double PIo2[] = {
#endif
1.57079625129699707031e+00, /* 0x3FF921FB, 0x40000000 */
7.54978941586159635335e-08, /* 0x3E74442D, 0x00000000 */
5.39030252995776476554e-15, /* 0x3CF84698, 0x80000000 */
3.28200341580791294123e-22, /* 0x3B78CC51, 0x60000000 */
1.27065575308067607349e-29, /* 0x39F01B83, 0x80000000 */
1.22933308981111328932e-36, /* 0x387A2520, 0x40000000 */
2.73370053816464559624e-44, /* 0x36E38222, 0x80000000 */
2.16741683877804819444e-51, /* 0x3569F31D, 0x00000000 */
};
#ifdef __STDC__
static const double
#else
static double
#endif
zero = 0.0,
one = 1.0,
two24 = 1.67772160000000000000e+07, /* 0x41700000, 0x00000000 */
twon24 = 5.96046447753906250000e-08; /* 0x3E700000, 0x00000000 */
#ifdef __STDC__
int __kernel_rem_pio2(double *x, double *y, int e0, int nx, int prec, const int32_t *ipio2)
#else
int __kernel_rem_pio2(x,y,e0,nx,prec,ipio2)
double x[], y[]; int e0,nx,prec; int32_t ipio2[];
#endif
{
int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih;
double z,fw,f[20],fq[20],q[20];
/* initialize jk*/
jk = init_jk[prec];
jp = jk;
/* determine jx,jv,q0, note that 3>q0 */
jx = nx-1;
jv = (e0-3)/24; if(jv<0) jv=0;
q0 = e0-24*(jv+1);
/* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */
j = jv-jx; m = jx+jk;
for(i=0;i<=m;i++,j++) f[i] = (j<0)? zero : (double) ipio2[j];
/* compute q[0],q[1],...q[jk] */
for (i=0;i<=jk;i++) {
for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw;
}
jz = jk;
recompute:
/* distill q[] into iq[] reversingly */
for(i=0,j=jz,z=q[jz];j>0;i++,j--) {
fw = (double)((int32_t)(twon24* z));
iq[i] = (int32_t)(z-two24*fw);
z = q[j-1]+fw;
}
/* compute n */
z = __scalbn(z,q0); /* actual value of z */
z -= 8.0*__floor(z*0.125); /* trim off integer >= 8 */
n = (int32_t) z;
z -= (double)n;
ih = 0;
if(q0>0) { /* need iq[jz-1] to determine n */
i = (iq[jz-1]>>(24-q0)); n += i;
iq[jz-1] -= i<<(24-q0);
ih = iq[jz-1]>>(23-q0);
}
else if(q0==0) ih = iq[jz-1]>>23;
else if(z>=0.5) ih=2;
if(ih>0) { /* q > 0.5 */
n += 1; carry = 0;
for(i=0;i<jz ;i++) { /* compute 1-q */
j = iq[i];
if(carry==0) {
if(j!=0) {
carry = 1; iq[i] = 0x1000000- j;
}
} else iq[i] = 0xffffff - j;
}
if(q0>0) { /* rare case: chance is 1 in 12 */
switch(q0) {
case 1:
iq[jz-1] &= 0x7fffff; break;
case 2:
iq[jz-1] &= 0x3fffff; break;
}
}
if(ih==2) {
z = one - z;
if(carry!=0) z -= __scalbn(one,q0);
}
}
/* check if recomputation is needed */
if(z==zero) {
j = 0;
for (i=jz-1;i>=jk;i--) j |= iq[i];
if(j==0) { /* need recomputation */
for(k=1;iq[jk-k]==0;k++); /* k = no. of terms needed */
for(i=jz+1;i<=jz+k;i++) { /* add q[jz+1] to q[jz+k] */
f[jx+i] = (double) ipio2[jv+i];
for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j];
q[i] = fw;
}
jz += k;
goto recompute;
}
}
/* chop off zero terms */
if(z==0.0) {
jz -= 1; q0 -= 24;
while(iq[jz]==0) { jz--; q0-=24;}
} else { /* break z into 24-bit if necessary */
z = __scalbn(z,-q0);
if(z>=two24) {
fw = (double)((int32_t)(twon24*z));
iq[jz] = (int32_t)(z-two24*fw);
jz += 1; q0 += 24;
iq[jz] = (int32_t) fw;
} else iq[jz] = (int32_t) z ;
}
/* convert integer "bit" chunk to floating-point value */
fw = __scalbn(one,q0);
for(i=jz;i>=0;i--) {
q[i] = fw*(double)iq[i]; fw*=twon24;
}
/* compute PIo2[0,...,jp]*q[jz,...,0] */
for(i=jz;i>=0;i--) {
for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k];
fq[jz-i] = fw;
}
/* compress fq[] into y[] */
switch(prec) {
case 0:
fw = 0.0;
for (i=jz;i>=0;i--) fw += fq[i];
y[0] = (ih==0)? fw: -fw;
break;
case 1:
case 2:
fw = 0.0;
for (i=jz;i>=0;i--) fw += fq[i];
y[0] = (ih==0)? fw: -fw;
fw = fq[0]-fw;
for (i=1;i<=jz;i++) fw += fq[i];
y[1] = (ih==0)? fw: -fw;
break;
case 3: /* painful */
for (i=jz;i>0;i--) {
fw = fq[i-1]+fq[i];
fq[i] += fq[i-1]-fw;
fq[i-1] = fw;
}
for (i=jz;i>1;i--) {
fw = fq[i-1]+fq[i];
fq[i] += fq[i-1]-fw;
fq[i-1] = fw;
}
for (fw=0.0,i=jz;i>=2;i--) fw += fq[i];
if(ih==0) {
y[0] = fq[0]; y[1] = fq[1]; y[2] = fw;
} else {
y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw;
}
}
return n&7;
}
@@ -0,0 +1,213 @@
/* k_rem_pio2f.c -- float version of k_rem_pio2.c
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
*/
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: k_rem_pio2f.c,v 1.4 1995/05/10 20:46:28 jtc Exp $";
#endif
#include "math.h"
#include "math_private.h"
/* In the float version, the input parameter x contains 8 bit
integers, not 24 bit integers. 113 bit precision is not supported. */
#ifdef __STDC__
static const int init_jk[] = {4,7,9}; /* initial value for jk */
#else
static int init_jk[] = {4,7,9};
#endif
#ifdef __STDC__
static const float PIo2[] = {
#else
static float PIo2[] = {
#endif
1.5703125000e+00, /* 0x3fc90000 */
4.5776367188e-04, /* 0x39f00000 */
2.5987625122e-05, /* 0x37da0000 */
7.5437128544e-08, /* 0x33a20000 */
6.0026650317e-11, /* 0x2e840000 */
7.3896444519e-13, /* 0x2b500000 */
5.3845816694e-15, /* 0x27c20000 */
5.6378512969e-18, /* 0x22d00000 */
8.3009228831e-20, /* 0x1fc40000 */
3.2756352257e-22, /* 0x1bc60000 */
6.3331015649e-25, /* 0x17440000 */
};
#ifdef __STDC__
static const float
#else
static float
#endif
zero = 0.0,
one = 1.0,
two8 = 2.5600000000e+02, /* 0x43800000 */
twon8 = 3.9062500000e-03; /* 0x3b800000 */
#ifdef __STDC__
int __kernel_rem_pio2f(float *x, float *y, int e0, int nx, int prec, const int32_t *ipio2)
#else
int __kernel_rem_pio2f(x,y,e0,nx,prec,ipio2)
float x[], y[]; int e0,nx,prec; int32_t ipio2[];
#endif
{
int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih;
float z,fw,f[20],fq[20],q[20];
/* initialize jk*/
jk = init_jk[prec];
jp = jk;
/* determine jx,jv,q0, note that 3>q0 */
jx = nx-1;
jv = (e0-3)/8; if(jv<0) jv=0;
q0 = e0-8*(jv+1);
/* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */
j = jv-jx; m = jx+jk;
for(i=0;i<=m;i++,j++) f[i] = (j<0)? zero : (float) ipio2[j];
/* compute q[0],q[1],...q[jk] */
for (i=0;i<=jk;i++) {
for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw;
}
jz = jk;
recompute:
/* distill q[] into iq[] reversingly */
for(i=0,j=jz,z=q[jz];j>0;i++,j--) {
fw = (float)((int32_t)(twon8* z));
iq[i] = (int32_t)(z-two8*fw);
z = q[j-1]+fw;
}
/* compute n */
z = __scalbnf(z,q0); /* actual value of z */
z -= (float)8.0*__floorf(z*(float)0.125); /* trim off integer >= 8 */
n = (int32_t) z;
z -= (float)n;
ih = 0;
if(q0>0) { /* need iq[jz-1] to determine n */
i = (iq[jz-1]>>(8-q0)); n += i;
iq[jz-1] -= i<<(8-q0);
ih = iq[jz-1]>>(7-q0);
}
else if(q0==0) ih = iq[jz-1]>>8;
else if(z>=(float)0.5) ih=2;
if(ih>0) { /* q > 0.5 */
n += 1; carry = 0;
for(i=0;i<jz ;i++) { /* compute 1-q */
j = iq[i];
if(carry==0) {
if(j!=0) {
carry = 1; iq[i] = 0x100- j;
}
} else iq[i] = 0xff - j;
}
if(q0>0) { /* rare case: chance is 1 in 12 */
switch(q0) {
case 1:
iq[jz-1] &= 0x7f; break;
case 2:
iq[jz-1] &= 0x3f; break;
}
}
if(ih==2) {
z = one - z;
if(carry!=0) z -= __scalbnf(one,q0);
}
}
/* check if recomputation is needed */
if(z==zero) {
j = 0;
for (i=jz-1;i>=jk;i--) j |= iq[i];
if(j==0) { /* need recomputation */
for(k=1;iq[jk-k]==0;k++); /* k = no. of terms needed */
for(i=jz+1;i<=jz+k;i++) { /* add q[jz+1] to q[jz+k] */
f[jx+i] = (float) ipio2[jv+i];
for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j];
q[i] = fw;
}
jz += k;
goto recompute;
}
}
/* chop off zero terms */
if(z==(float)0.0) {
jz -= 1; q0 -= 8;
while(iq[jz]==0) { jz--; q0-=8;}
} else { /* break z into 8-bit if necessary */
z = __scalbnf(z,-q0);
if(z>=two8) {
fw = (float)((int32_t)(twon8*z));
iq[jz] = (int32_t)(z-two8*fw);
jz += 1; q0 += 8;
iq[jz] = (int32_t) fw;
} else iq[jz] = (int32_t) z ;
}
/* convert integer "bit" chunk to floating-point value */
fw = __scalbnf(one,q0);
for(i=jz;i>=0;i--) {
q[i] = fw*(float)iq[i]; fw*=twon8;
}
/* compute PIo2[0,...,jp]*q[jz,...,0] */
for(i=jz;i>=0;i--) {
for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k];
fq[jz-i] = fw;
}
/* compress fq[] into y[] */
switch(prec) {
case 0:
fw = 0.0;
for (i=jz;i>=0;i--) fw += fq[i];
y[0] = (ih==0)? fw: -fw;
break;
case 1:
case 2:
fw = 0.0;
for (i=jz;i>=0;i--) fw += fq[i];
y[0] = (ih==0)? fw: -fw;
fw = fq[0]-fw;
for (i=1;i<=jz;i++) fw += fq[i];
y[1] = (ih==0)? fw: -fw;
break;
case 3: /* painful */
for (i=jz;i>0;i--) {
fw = fq[i-1]+fq[i];
fq[i] += fq[i-1]-fw;
fq[i-1] = fw;
}
for (i=jz;i>1;i--) {
fw = fq[i-1]+fq[i];
fq[i] += fq[i-1]-fw;
fq[i-1] = fw;
}
for (fw=0.0,i=jz;i>=2;i--) fw += fq[i];
if(ih==0) {
y[0] = fq[0]; y[1] = fq[1]; y[2] = fw;
} else {
y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw;
}
}
return n&7;
}
@@ -0,0 +1 @@
/* Not needed anymore. */
@@ -0,0 +1,54 @@
/* k_sinf.c -- float version of k_sin.c
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
*/
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: k_sinf.c,v 1.4 1995/05/10 20:46:33 jtc Exp $";
#endif
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const float
#else
static float
#endif
half = 5.0000000000e-01,/* 0x3f000000 */
S1 = -1.6666667163e-01, /* 0xbe2aaaab */
S2 = 8.3333337680e-03, /* 0x3c088889 */
S3 = -1.9841270114e-04, /* 0xb9500d01 */
S4 = 2.7557314297e-06, /* 0x3638ef1b */
S5 = -2.5050759689e-08, /* 0xb2d72f34 */
S6 = 1.5896910177e-10; /* 0x2f2ec9d3 */
#ifdef __STDC__
float __kernel_sinf(float x, float y, int iy)
#else
float __kernel_sinf(x, y, iy)
float x,y; int iy; /* iy=0 if y is zero */
#endif
{
float z,r,v;
int32_t ix;
GET_FLOAT_WORD(ix,x);
ix &= 0x7fffffff; /* high word of x */
if(ix<0x32000000) /* |x| < 2**-27 */
{if((int)x==0) return x;} /* generate inexact */
z = x*x;
v = z*x;
r = S2+z*(S3+z*(S4+z*(S5+z*S6)));
if(iy==0) return x+v*(S1+z*r);
else return x-((z*(half*y-v*r)-y)-v*S1);
}
@@ -0,0 +1,145 @@
/* @(#)k_tan.c 5.1 93/09/24 */
/*
* ====================================================
* 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.
* ====================================================
*/
/* Modified by Naohiko Shimizu/Tokai University, Japan 1997/08/25,
for performance improvement on pipelined processors.
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: k_tan.c,v 1.8 1995/05/10 20:46:37 jtc Exp $";
#endif
/* __kernel_tan( x, y, k )
* kernel tan function on [-pi/4, pi/4], pi/4 ~ 0.7854
* Input x is assumed to be bounded by ~pi/4 in magnitude.
* Input y is the tail of x.
* Input k indicates whether tan (if k=1) or
* -1/tan (if k= -1) is returned.
*
* Algorithm
* 1. Since tan(-x) = -tan(x), we need only to consider positive x.
* 2. if x < 2^-28 (hx<0x3e300000 0), return x with inexact if x!=0.
* 3. tan(x) is approximated by a odd polynomial of degree 27 on
* [0,0.67434]
* 3 27
* tan(x) ~ x + T1*x + ... + T13*x
* where
*
* |tan(x) 2 4 26 | -59.2
* |----- - (1+T1*x +T2*x +.... +T13*x )| <= 2
* | x |
*
* Note: tan(x+y) = tan(x) + tan'(x)*y
* ~ tan(x) + (1+x*x)*y
* Therefore, for better accuracy in computing tan(x+y), let
* 3 2 2 2 2
* r = x *(T2+x *(T3+x *(...+x *(T12+x *T13))))
* then
* 3 2
* tan(x+y) = x + (T1*x + (x *(r+y)+y))
*
* 4. For x in [0.67434,pi/4], let y = pi/4 - x, then
* tan(x) = tan(pi/4-y) = (1-tan(y))/(1+tan(y))
* = 1 - 2*(tan(y) - (tan(y)^2)/(1+tan(y)))
*/
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const double
#else
static double
#endif
one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
pio4 = 7.85398163397448278999e-01, /* 0x3FE921FB, 0x54442D18 */
pio4lo= 3.06161699786838301793e-17, /* 0x3C81A626, 0x33145C07 */
T[] = {
3.33333333333334091986e-01, /* 0x3FD55555, 0x55555563 */
1.33333333333201242699e-01, /* 0x3FC11111, 0x1110FE7A */
5.39682539762260521377e-02, /* 0x3FABA1BA, 0x1BB341FE */
2.18694882948595424599e-02, /* 0x3F9664F4, 0x8406D637 */
8.86323982359930005737e-03, /* 0x3F8226E3, 0xE96E8493 */
3.59207910759131235356e-03, /* 0x3F6D6D22, 0xC9560328 */
1.45620945432529025516e-03, /* 0x3F57DBC8, 0xFEE08315 */
5.88041240820264096874e-04, /* 0x3F4344D8, 0xF2F26501 */
2.46463134818469906812e-04, /* 0x3F3026F7, 0x1A8D1068 */
7.81794442939557092300e-05, /* 0x3F147E88, 0xA03792A6 */
7.14072491382608190305e-05, /* 0x3F12B80F, 0x32F0A7E9 */
-1.85586374855275456654e-05, /* 0xBEF375CB, 0xDB605373 */
2.59073051863633712884e-05, /* 0x3EFB2A70, 0x74BF7AD4 */
};
#ifdef __STDC__
double __kernel_tan(double x, double y, int iy)
#else
double __kernel_tan(x, y, iy)
double x,y; int iy;
#endif
{
double z,r,v,w,s,r1,r2,r3,v1,v2,v3,w2,w4;
int32_t ix,hx;
GET_HIGH_WORD(hx,x);
ix = hx&0x7fffffff; /* high word of |x| */
if(ix<0x3e300000) /* x < 2**-28 */
{if((int)x==0) { /* generate inexact */
u_int32_t low;
GET_LOW_WORD(low,x);
if(((ix|low)|(iy+1))==0) return one/fabs(x);
else return (iy==1)? x: -one/x;
}
}
if(ix>=0x3FE59428) { /* |x|>=0.6744 */
if(hx<0) {x = -x; y = -y;}
z = pio4-x;
w = pio4lo-y;
x = z+w; y = 0.0;
}
z = x*x;
w = z*z;
/* Break x^5*(T[1]+x^2*T[2]+...) into
* x^5(T[1]+x^4*T[3]+...+x^20*T[11]) +
* x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12]))
*/
#ifdef DO_NOT_USE_THIS
r = T[1]+w*(T[3]+w*(T[5]+w*(T[7]+w*(T[9]+w*T[11]))));
v = z*(T[2]+w*(T[4]+w*(T[6]+w*(T[8]+w*(T[10]+w*T[12])))));
#else
v1 = T[10]+w*T[12]; w2=w*w;
v2 = T[6]+w*T[8]; w4=w2*w2;
v3 = T[2]+w*T[4]; v1=z*v1;
r1 = T[9]+w*T[11]; v2=z*v2;
r2 = T[5]+w*T[7]; v3=z*v3;
r3 = T[1]+w*T[3];
v = v3 + w2*v2 + w4*v1;
r = r3 + w2*r2 + w4*r1;
#endif
s = z*x;
r = y + z*(s*(r+v)+y);
r += T[0]*s;
w = x+r;
if(ix>=0x3FE59428) {
v = (double)iy;
return (double)(1-((hx>>30)&2))*(v-2.0*(x-(w*w/(w+v)-r)));
}
if(iy==1) return w;
else { /* if allow error up to 2 ulp,
simply return -1.0/(x+r) here */
/* compute -1.0/(x+r) accurately */
double a,t;
z = w;
SET_LOW_WORD(z,0);
v = r-(z - x); /* z+v = r+x */
t = a = -1.0/w; /* a = -1.0/w */
SET_LOW_WORD(t,0);
s = 1.0+t*z;
return t+a*(s+t*v);
}
}
@@ -0,0 +1,101 @@
/* k_tanf.c -- float version of k_tan.c
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
*/
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: k_tanf.c,v 1.4 1995/05/10 20:46:39 jtc Exp $";
#endif
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const float
#else
static float
#endif
one = 1.0000000000e+00, /* 0x3f800000 */
pio4 = 7.8539812565e-01, /* 0x3f490fda */
pio4lo= 3.7748947079e-08, /* 0x33222168 */
T[] = {
3.3333334327e-01, /* 0x3eaaaaab */
1.3333334029e-01, /* 0x3e088889 */
5.3968254477e-02, /* 0x3d5d0dd1 */
2.1869488060e-02, /* 0x3cb327a4 */
8.8632395491e-03, /* 0x3c11371f */
3.5920790397e-03, /* 0x3b6b6916 */
1.4562094584e-03, /* 0x3abede48 */
5.8804126456e-04, /* 0x3a1a26c8 */
2.4646313977e-04, /* 0x398137b9 */
7.8179444245e-05, /* 0x38a3f445 */
7.1407252108e-05, /* 0x3895c07a */
-1.8558637748e-05, /* 0xb79bae5f */
2.5907305826e-05, /* 0x37d95384 */
};
#ifdef __STDC__
float __kernel_tanf(float x, float y, int iy)
#else
float __kernel_tanf(x, y, iy)
float x,y; int iy;
#endif
{
float z,r,v,w,s;
int32_t ix,hx;
GET_FLOAT_WORD(hx,x);
ix = hx&0x7fffffff; /* high word of |x| */
if(ix<0x31800000) /* x < 2**-28 */
{if((int)x==0) { /* generate inexact */
if((ix|(iy+1))==0) return one/fabsf(x);
else return (iy==1)? x: -one/x;
}
}
if(ix>=0x3f2ca140) { /* |x|>=0.6744 */
if(hx<0) {x = -x; y = -y;}
z = pio4-x;
w = pio4lo-y;
x = z+w; y = 0.0;
}
z = x*x;
w = z*z;
/* Break x^5*(T[1]+x^2*T[2]+...) into
* x^5(T[1]+x^4*T[3]+...+x^20*T[11]) +
* x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12]))
*/
r = T[1]+w*(T[3]+w*(T[5]+w*(T[7]+w*(T[9]+w*T[11]))));
v = z*(T[2]+w*(T[4]+w*(T[6]+w*(T[8]+w*(T[10]+w*T[12])))));
s = z*x;
r = y + z*(s*(r+v)+y);
r += T[0]*s;
w = x+r;
if(ix>=0x3f2ca140) {
v = (float)iy;
return (float)(1-((hx>>30)&2))*(v-(float)2.0*(x-(w*w/(w+v)-r)));
}
if(iy==1) return w;
else { /* if allow error up to 2 ulp,
simply return -1.0/(x+r) here */
/* compute -1.0/(x+r) accurately */
float a,t;
int32_t i;
z = w;
GET_FLOAT_WORD(i,z);
SET_FLOAT_WORD(z,i&0xfffff000);
v = r-(z - x); /* z+v = r+x */
t = a = -(float)1.0/w; /* a = -1.0/w */
GET_FLOAT_WORD(i,t);
SET_FLOAT_WORD(t,i&0xfffff000);
s = (float)1.0+t*z;
return t+a*(s+t*v);
}
}
@@ -0,0 +1,105 @@
/*
* IBM Accurate Mathematical Library
* written by International Business Machines Corp.
* Copyright (C) 2001 Free Software Foundation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*************************************************************************/
/* MODULE_NAME:mpexp.c */
/* */
/* FUNCTIONS: mpexp */
/* */
/* FILES NEEDED: mpa.h endian.h mpexp.h */
/* mpa.c */
/* */
/* Multi-Precision exponential function subroutine */
/* ( for p >= 4, 2**(-55) <= abs(x) <= 1024 ). */
/*************************************************************************/
#include "endian.h"
#include "mpa.h"
#include "mpexp.h"
/* Multi-Precision exponential function subroutine (for p >= 4, */
/* 2**(-55) <= abs(x) <= 1024). */
void __mpexp(mp_no *x, mp_no *y, int p) {
int i,j,k,m,m1,m2,n;
double a,b;
static const int np[33] = {0,0,0,0,3,3,4,4,5,4,4,5,5,5,6,6,6,6,6,6,
6,6,6,6,7,7,7,7,8,8,8,8,8};
static const int m1p[33]= {0,0,0,0,17,23,23,28,27,38,42,39,43,47,43,47,50,54,
57,60,64,67,71,74,68,71,74,77,70,73,76,78,81};
static const int m1np[7][18] = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0,36,48,60,72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0,24,32,40,48,56,64,72, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0,17,23,29,35,41,47,53,59,65, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0,23,28,33,38,42,47,52,57,62,66, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0,27, 0, 0,39,43,47,51,55,59,63},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,43,47,50,54}};
mp_no mpone = {0,{0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0}};
mp_no mpk = {0,{0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0}};
mp_no mps,mpak,mpt1,mpt2;
/* Choose m,n and compute a=2**(-m) */
n = np[p]; m1 = m1p[p]; a = twomm1[p].d;
for (i=0; i<EX; i++) a *= RADIXI;
for ( ; i>EX; i--) a *= RADIX;
b = X[1]*RADIXI; m2 = 24*EX;
for (; b<HALF; m2--) { a *= TWO; b *= TWO; }
if (b == HALF) {
for (i=2; i<=p; i++) { if (X[i]!=ZERO) break; }
if (i==p+1) { m2--; a *= TWO; }
}
if ((m=m1+m2) <= 0) {
m=0; a=ONE;
for (i=n-1; i>0; i--,n--) { if (m1np[i][p]+m2>0) break; }
}
/* Compute s=x*2**(-m). Put result in mps */
__dbl_mp(a,&mpt1,p);
__mul(x,&mpt1,&mps,p);
/* Evaluate the polynomial. Put result in mpt2 */
mpone.e=1; mpone.d[0]=ONE; mpone.d[1]=ONE;
mpk.e = 1; mpk.d[0] = ONE; mpk.d[1]=nn[n].d;
__dvd(&mps,&mpk,&mpt1,p);
__add(&mpone,&mpt1,&mpak,p);
for (k=n-1; k>1; k--) {
__mul(&mps,&mpak,&mpt1,p);
mpk.d[1]=nn[k].d;
__dvd(&mpt1,&mpk,&mpt2,p);
__add(&mpone,&mpt2,&mpak,p);
}
__mul(&mps,&mpak,&mpt1,p);
__add(&mpone,&mpt1,&mpt2,p);
/* Raise polynomial value to the power of 2**m. Put result in y */
for (k=0,j=0; k<m; ) {
__mul(&mpt2,&mpt2,&mpt1,p); k++;
if (k==m) { j=1; break; }
__mul(&mpt1,&mpt1,&mpt2,p); k++;
}
if (j) __cpy(&mpt1,y,p);
else __cpy(&mpt2,y,p);
return;
}
@@ -0,0 +1,158 @@
/*
* IBM Accurate Mathematical Library
* Written by International Business Machines Corp.
* Copyright (C) 2001 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/******************************************************************/
/* */
/* MODULE_NAME:mpexp.h */
/* */
/* common data and variables prototype and definition */
/******************************************************************/
#ifndef MPEXP_H
#define MPEXP_H
#ifdef BIG_ENDI
static const number
twomm1[33] = { /* 2**-m1 */
/**/ {{0x00000000, 0x00000000} }, /* 0 */
/**/ {{0x00000000, 0x00000000} }, /* 0 */
/**/ {{0x00000000, 0x00000000} }, /* 0 */
/**/ {{0x00000000, 0x00000000} }, /* 0 */
/**/ {{0x3ee00000, 0x00000000} }, /* 2**-17 */
/**/ {{0x3e800000, 0x00000000} }, /* 2**-23 */
/**/ {{0x3e800000, 0x00000000} }, /* 2**-23 */
/**/ {{0x3e300000, 0x00000000} }, /* 2**-28 */
/**/ {{0x3e400000, 0x00000000} }, /* 2**-27 */
/**/ {{0x3d900000, 0x00000000} }, /* 2**-38 */
/**/ {{0x3d500000, 0x00000000} }, /* 2**-42 */
/**/ {{0x3d800000, 0x00000000} }, /* 2**-39 */
/**/ {{0x3d400000, 0x00000000} }, /* 2**-43 */
/**/ {{0x3d000000, 0x00000000} }, /* 2**-47 */
/**/ {{0x3d400000, 0x00000000} }, /* 2**-43 */
/**/ {{0x3d000000, 0x00000000} }, /* 2**-47 */
/**/ {{0x3cd00000, 0x00000000} }, /* 2**-50 */
/**/ {{0x3c900000, 0x00000000} }, /* 2**-54 */
/**/ {{0x3c600000, 0x00000000} }, /* 2**-57 */
/**/ {{0x3c300000, 0x00000000} }, /* 2**-60 */
/**/ {{0x3bf00000, 0x00000000} }, /* 2**-64 */
/**/ {{0x3bc00000, 0x00000000} }, /* 2**-67 */
/**/ {{0x3b800000, 0x00000000} }, /* 2**-71 */
/**/ {{0x3b500000, 0x00000000} }, /* 2**-74 */
/**/ {{0x3bb00000, 0x00000000} }, /* 2**-68 */
/**/ {{0x3b800000, 0x00000000} }, /* 2**-71 */
/**/ {{0x3b500000, 0x00000000} }, /* 2**-74 */
/**/ {{0x3b200000, 0x00000000} }, /* 2**-77 */
/**/ {{0x3b900000, 0x00000000} }, /* 2**-70 */
/**/ {{0x3b600000, 0x00000000} }, /* 2**-73 */
/**/ {{0x3b300000, 0x00000000} }, /* 2**-76 */
/**/ {{0x3b100000, 0x00000000} }, /* 2**-78 */
/**/ {{0x3ae00000, 0x00000000} }, /* 2**-81 */
};
static const number
nn[9]={ /* n */
/**/ {{0x00000000, 0x00000000} }, /* 0 */
/**/ {{0x3ff00000, 0x00000000} }, /* 1 */
/**/ {{0x40000000, 0x00000000} }, /* 2 */
/**/ {{0x40080000, 0x00000000} }, /* 3 */
/**/ {{0x40100000, 0x00000000} }, /* 4 */
/**/ {{0x40140000, 0x00000000} }, /* 5 */
/**/ {{0x40180000, 0x00000000} }, /* 6 */
/**/ {{0x401c0000, 0x00000000} }, /* 7 */
/**/ {{0x40200000, 0x00000000} }, /* 8 */
};
static const number
/**/ radix = {{0x41700000, 0x00000000} }, /* 2**24 */
/**/ radixi = {{0x3e700000, 0x00000000} }, /* 2**-24 */
/**/ zero = {{0x00000000, 0x00000000} }, /* 0 */
/**/ one = {{0x3ff00000, 0x00000000} }, /* 1 */
/**/ two = {{0x40000000, 0x00000000} }, /* 2 */
/**/ half = {{0x3fe00000, 0x00000000} }; /* 1/2 */
#else
#ifdef LITTLE_ENDI
static const number
twomm1[33] = { /* 2**-m1 */
/**/ {{0x00000000, 0x00000000} }, /* 0 */
/**/ {{0x00000000, 0x00000000} }, /* 0 */
/**/ {{0x00000000, 0x00000000} }, /* 0 */
/**/ {{0x00000000, 0x00000000} }, /* 0 */
/**/ {{0x00000000, 0x3ee00000} }, /* 2**-17 */
/**/ {{0x00000000, 0x3e800000} }, /* 2**-23 */
/**/ {{0x00000000, 0x3e800000} }, /* 2**-23 */
/**/ {{0x00000000, 0x3e300000} }, /* 2**-28 */
/**/ {{0x00000000, 0x3e400000} }, /* 2**-27 */
/**/ {{0x00000000, 0x3d900000} }, /* 2**-38 */
/**/ {{0x00000000, 0x3d500000} }, /* 2**-42 */
/**/ {{0x00000000, 0x3d800000} }, /* 2**-39 */
/**/ {{0x00000000, 0x3d400000} }, /* 2**-43 */
/**/ {{0x00000000, 0x3d000000} }, /* 2**-47 */
/**/ {{0x00000000, 0x3d400000} }, /* 2**-43 */
/**/ {{0x00000000, 0x3d000000} }, /* 2**-47 */
/**/ {{0x00000000, 0x3cd00000} }, /* 2**-50 */
/**/ {{0x00000000, 0x3c900000} }, /* 2**-54 */
/**/ {{0x00000000, 0x3c600000} }, /* 2**-57 */
/**/ {{0x00000000, 0x3c300000} }, /* 2**-60 */
/**/ {{0x00000000, 0x3bf00000} }, /* 2**-64 */
/**/ {{0x00000000, 0x3bc00000} }, /* 2**-67 */
/**/ {{0x00000000, 0x3b800000} }, /* 2**-71 */
/**/ {{0x00000000, 0x3b500000} }, /* 2**-74 */
/**/ {{0x00000000, 0x3bb00000} }, /* 2**-68 */
/**/ {{0x00000000, 0x3b800000} }, /* 2**-71 */
/**/ {{0x00000000, 0x3b500000} }, /* 2**-74 */
/**/ {{0x00000000, 0x3b200000} }, /* 2**-77 */
/**/ {{0x00000000, 0x3b900000} }, /* 2**-70 */
/**/ {{0x00000000, 0x3b600000} }, /* 2**-73 */
/**/ {{0x00000000, 0x3b300000} }, /* 2**-76 */
/**/ {{0x00000000, 0x3b100000} }, /* 2**-78 */
/**/ {{0x00000000, 0x3ae00000} }, /* 2**-81 */
};
static const number
nn[9]={ /* n */
/**/ {{0x00000000, 0x00000000} }, /* 0 */
/**/ {{0x00000000, 0x3ff00000} }, /* 1 */
/**/ {{0x00000000, 0x40000000} }, /* 2 */
/**/ {{0x00000000, 0x40080000} }, /* 3 */
/**/ {{0x00000000, 0x40100000} }, /* 4 */
/**/ {{0x00000000, 0x40140000} }, /* 5 */
/**/ {{0x00000000, 0x40180000} }, /* 6 */
/**/ {{0x00000000, 0x401c0000} }, /* 7 */
/**/ {{0x00000000, 0x40200000} }, /* 8 */
};
static const number
/**/ radix = {{0x00000000, 0x41700000} }, /* 2**24 */
/**/ radixi = {{0x00000000, 0x3e700000} }, /* 2**-24 */
/**/ zero = {{0x00000000, 0x00000000} }, /* 0 */
/**/ one = {{0x00000000, 0x3ff00000} }, /* 1 */
/**/ two = {{0x00000000, 0x40000000} }, /* 2 */
/**/ half = {{0x00000000, 0x3fe00000} }; /* 1/2 */
#endif
#endif
#define RADIX radix.d
#define RADIXI radixi.d
#define ZERO zero.d
#define ONE one.d
#define TWO two.d
#define HALF half.d
#endif
@@ -0,0 +1,72 @@
/*
* IBM Accurate Mathematical Library
* written by International Business Machines Corp.
* Copyright (C) 2001 Free Software Foundation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/************************************************************************/
/* */
/* MODULE_NAME:mplog.c */
/* */
/* FUNCTIONS: mplog */
/* */
/* FILES NEEDED: endian.h mpa.h mplog.h */
/* mpexp.c */
/* */
/* Multi-Precision logarithm function subroutine (for precision p >= 4, */
/* 2**(-1024) < x < 2**1024) and x is outside of the interval */
/* [1-2**(-54),1+2**(-54)]. Upon entry, x should be set to the */
/* multi-precision value of the input and y should be set into a multi- */
/* precision value of an approximation of log(x) with relative error */
/* bound of at most 2**(-52). The routine improves the accuracy of y. */
/* */
/************************************************************************/
#include "endian.h"
#include "mpa.h"
void __mpexp(mp_no *, mp_no *, int);
void __mplog(mp_no *x, mp_no *y, int p) {
#include "mplog.h"
int i,m;
#if 0
int j,k,m1,m2,n;
double a,b;
#endif
static const int mp[33] = {0,0,0,0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
4,4,4,4,4,4,4,4,4,4,4,4,4,4};
mp_no mpone = {0,{0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0}};
mp_no mpt1,mpt2;
/* Choose m and initiate mpone */
m = mp[p]; mpone.e = 1; mpone.d[0]=mpone.d[1]=ONE;
/* Perform m newton iterations to solve for y: exp(y)-x=0. */
/* The iterations formula is: y(n+1)=y(n)+(x*exp(-y(n))-1). */
__cpy(y,&mpt1,p);
for (i=0; i<m; i++) {
mpt1.d[0]=-mpt1.d[0];
__mpexp(&mpt1,&mpt2,p);
__mul(x,&mpt2,&mpt1,p);
__sub(&mpt1,&mpone,&mpt2,p);
__add(y,&mpt2,&mpt1,p);
__cpy(&mpt1,y,p);
}
return;
}
@@ -0,0 +1,45 @@
/*
* IBM Accurate Mathematical Library
* Written by International Business Machines Corp.
* Copyright (C) 2001 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/******************************************************************/
/* */
/* MODULE_NAME:mplog.h */
/* */
/* common data and variables prototype and definition */
/******************************************************************/
#ifndef MPLOG_H
#define MPLOG_H
#ifdef BIG_ENDI
static const number
/**/ one = {{0x3ff00000, 0x00000000} }; /* 1 */
#else
#ifdef LITTLE_ENDI
static const number
/**/ one = {{0x00000000, 0x3ff00000} }; /* 1 */
#endif
#endif
#define ONE one.d
#endif
@@ -0,0 +1,60 @@
/*
* IBM Accurate Mathematical Library
* written by International Business Machines Corp.
* Copyright (C) 2001 Free Software Foundation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/**********************************************************************/
/* MODULE_NAME:mptan.c */
/* */
/* FUNCTION: mptan */
/* */
/* FILES NEEDED: endian.h mpa.h */
/* mpa.c sincos32.c branred.c */
/* */
/* Multi-Precision tan() function subroutine, for p=32. It is based */
/* on the routines mpranred() and c32(). mpranred() performs range */
/* reduction of a double number x into a multiple precision number */
/* y, such that y=x-n*pi/2, abs(y)<pi/4, n=0,+-1,+-2,.... c32() */
/* computes both sin(y), cos(y). tan(x) is either sin(y)/cos(y) */
/* or -cos(y)/sin(y). The precision of the result is of about 559 */
/* significant bits. */
/* */
/**********************************************************************/
#include "endian.h"
#include "mpa.h"
int __mpranred(double, mp_no *, int);
void __c32(mp_no *, mp_no *, mp_no *, int);
void __mptan(double x, mp_no *mpy, int p) {
static const double MONE = -1.0;
int n;
mp_no mpw, mpc, mps;
n = __mpranred(x, &mpw, p) & 0x00000001; /* negative or positive result */
__c32(&mpw, &mpc, &mps, p); /* computing sin(x) and cos(x) */
if (n) /* second or fourth quarter of unit circle */
{ __dvd(&mpc,&mps,mpy,p);
mpy->d[0] *= MONE;
} /* tan is negative in this area */
else __dvd(&mps,&mpc,mpy,p);
return;
}
@@ -0,0 +1,38 @@
/*
* IBM Accurate Mathematical Library
* Written by International Business Machines Corp.
* Copyright (C) 2001 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/******************************************************************/
/* */
/* MODULE_NAME:mydefs.h */
/* */
/* common data and definition */
/******************************************************************/
#ifndef MY_H
#define MY_H
typedef int int4;
typedef union {int4 i[2]; double x;} mynumber;
#define ABS(x) (((x)>0)?(x):-(x))
#define max(x,y) (((y)>(x))?(y):(x))
#define min(x,y) (((y)<(x))?(y):(x))
#endif
@@ -0,0 +1,32 @@
/*
* IBM Accurate Mathematical Library
* Written by International Business Machines Corp.
* Copyright (C) 2001 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/****************************************************************/
/* TABLES FOR THE upow() FUNCTION */
/****************************************************************/
static const double powtwo[] = { 1.0, 2.0, 4.0,
8.0, 16.0, 32.0, 64.0, 128.0,
256.0, 512.0, 1024.0, 2048.0, 4096.0,
8192.0, 16384.0, 32768.0, 65536.0, 131072.0,
262144.0, 524288.0, 1048576.0, 2097152.0, 4194304.0,
8388608.0, 16777216.0, 33554432.0, 67108864.0, 134217728.0 };
@@ -0,0 +1,58 @@
/*
* IBM Accurate Mathematical Library
* Written by International Business Machines Corp.
* Copyright (C) 2001 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/****************************************************************/
/* TABLES FOR THE usqrt() FUNCTION */
/****************************************************************/
static const double inroot[128] = {
1.40872145012100, 1.39792649065766, 1.38737595123859, 1.37706074531819,
1.36697225234682, 1.35710228748795, 1.34744307370643, 1.33798721601135,
1.32872767765984, 1.31965775814772, 1.31077107283046, 1.30206153403386,
1.29352333352711, 1.28515092624400, 1.27693901514820, 1.26888253714903,
1.26097664998256, 1.25321671998073, 1.24559831065844, 1.23811717205462,
1.23076923076923, 1.22355058064300, 1.21645747403153, 1.20948631362953,
1.20263364480453, 1.19589614840310, 1.18927063399547, 1.18275403352732,
1.17634339535009, 1.17003587860341, 1.16382874792529, 1.15771936846787,
1.15170520119791, 1.14578379846309, 1.13995279980655, 1.13420992801334,
1.12855298537376, 1.12297985014975, 1.11748847323133, 1.11207687497107,
1.10674314218572, 1.10148542531442, 1.09630193572405, 1.09119094315276,
1.08615077328341, 1.08117980543918, 1.07627647039410, 1.07143924829188,
1.06666666666667, 1.06195729855996, 1.05730976072814, 1.05272271193563,
1.04819485132867, 1.04372491688551, 1.03931168393861, 1.03495396376504,
1.03065060224133, 1.02640047855933, 1.02220250399990, 1.01805562076124,
1.01395880083916, 1.00991104495649, 1.00591138153909, 1.00195886573624,
0.99611649018350, 0.98848330114434, 0.98102294317595, 0.97372899112030,
0.96659534932828, 0.95961623024651, 0.95278613468066, 0.94609983358253,
0.93955235122353, 0.93313894963169, 0.92685511418159, 0.92069654023750,
0.91465912076005, 0.90873893479530, 0.90293223677296, 0.89723544654727,
0.89164514012056, 0.88615804099474, 0.88077101210109, 0.87548104826333,
0.87028526915267, 0.86518091269740, 0.86016532891275, 0.85523597411976,
0.85039040552437, 0.84562627613070, 0.84094132996422, 0.83633339758291,
0.83180039185606, 0.82734030399203, 0.82295119979782, 0.81863121615464,
0.81437855769486, 0.81019149366693, 0.80606835497581, 0.80200753138734,
0.79800746888611, 0.79406666717674, 0.79018367731967, 0.78635709949278,
0.78258558087123, 0.77886781361798, 0.77520253297841, 0.77158851547266,
0.76802457717971, 0.76450957210799, 0.76104239064719, 0.75762195809661,
0.75424723326565, 0.75091720714229, 0.74763090162560, 0.74438736831878,
0.74118568737933, 0.73802496642311, 0.73490433947940, 0.73182296599416,
0.72878002987884, 0.72577473860242, 0.72280632232420, 0.71987403306536,
0.71697714391715, 0.71411494828392, 0.71128675915902, 0.70849190843208 };
@@ -0,0 +1,70 @@
/* @(#)s_asinh.c 5.1 93/09/24 */
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: s_asinh.c,v 1.9 1995/05/12 04:57:37 jtc Exp $";
#endif
/* asinh(x)
* Method :
* Based on
* asinh(x) = sign(x) * log [ |x| + sqrt(x*x+1) ]
* we have
* asinh(x) := x if 1+x*x=1,
* := sign(x)*(log(x)+ln2)) for large |x|, else
* := sign(x)*log(2|x|+1/(|x|+sqrt(x*x+1))) if|x|>2, else
* := sign(x)*log1p(|x| + x^2/(1 + sqrt(1+x^2)))
*/
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const double
#else
static double
#endif
one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
ln2 = 6.93147180559945286227e-01, /* 0x3FE62E42, 0xFEFA39EF */
huge= 1.00000000000000000000e+300;
#ifdef __STDC__
double __asinh(double x)
#else
double __asinh(x)
double x;
#endif
{
double t,w;
int32_t hx,ix;
GET_HIGH_WORD(hx,x);
ix = hx&0x7fffffff;
if(ix>=0x7ff00000) return x+x; /* x is inf or NaN */
if(ix< 0x3e300000) { /* |x|<2**-28 */
if(huge+x>one) return x; /* return x inexact except 0 */
}
if(ix>0x41b00000) { /* |x| > 2**28 */
w = __ieee754_log(fabs(x))+ln2;
} else if (ix>0x40000000) { /* 2**28 > |x| > 2.0 */
t = fabs(x);
w = __ieee754_log(2.0*t+one/(__ieee754_sqrt(x*x+one)+t));
} else { /* 2.0 > |x| > 2**-28 */
t = x*x;
w =__log1p(fabs(x)+t/(one+__ieee754_sqrt(one+t)));
}
if(hx>0) return w; else return -w;
}
weak_alias (__asinh, asinh)
#ifdef NO_LONG_DOUBLE
strong_alias (__asinh, __asinhl)
weak_alias (__asinh, asinhl)
#endif
@@ -0,0 +1,58 @@
/* s_asinhf.c -- float version of s_asinh.c.
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
*/
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: s_asinhf.c,v 1.5 1995/05/12 04:57:39 jtc Exp $";
#endif
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const float
#else
static float
#endif
one = 1.0000000000e+00, /* 0x3F800000 */
ln2 = 6.9314718246e-01, /* 0x3f317218 */
huge= 1.0000000000e+30;
#ifdef __STDC__
float __asinhf(float x)
#else
float __asinhf(x)
float x;
#endif
{
float t,w;
int32_t hx,ix;
GET_FLOAT_WORD(hx,x);
ix = hx&0x7fffffff;
if(ix>=0x7f800000) return x+x; /* x is inf or NaN */
if(ix< 0x38000000) { /* |x|<2**-14 */
if(huge+x>one) return x; /* return x inexact except 0 */
}
if(ix>0x47000000) { /* |x| > 2**14 */
w = __ieee754_logf(fabsf(x))+ln2;
} else if (ix>0x40000000) { /* 2**14 > |x| > 2.0 */
t = fabsf(x);
w = __ieee754_logf((float)2.0*t+one/(__ieee754_sqrtf(x*x+one)+t));
} else { /* 2.0 > |x| > 2**-14 */
t = x*x;
w =__log1pf(fabsf(x)+t/(one+__ieee754_sqrtf(one+t)));
}
if(hx>0) return w; else return -w;
}
weak_alias (__asinhf, asinhf)
@@ -0,0 +1,76 @@
/* Compute cubic root of double value.
Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Dirk Alboth <[email protected]> and
Ulrich Drepper <[email protected]>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include "math.h"
#include "math_private.h"
#define CBRT2 1.2599210498948731648 /* 2^(1/3) */
#define SQR_CBRT2 1.5874010519681994748 /* 2^(2/3) */
static const double factor[5] =
{
1.0 / SQR_CBRT2,
1.0 / CBRT2,
1.0,
CBRT2,
SQR_CBRT2
};
double
__cbrt (double x)
{
double xm, ym, u, t2;
int xe;
/* Reduce X. XM now is an range 1.0 to 0.5. */
xm = __frexp (fabs (x), &xe);
/* If X is not finite or is null return it (with raising exceptions
if necessary.
Note: *Our* version of `frexp' sets XE to zero if the argument is
Inf or NaN. This is not portable but faster. */
if (xe == 0 && fpclassify (x) <= FP_ZERO)
return x + x;
u = (0.354895765043919860
+ ((1.50819193781584896
+ ((-2.11499494167371287
+ ((2.44693122563534430
+ ((-1.83469277483613086
+ (0.784932344976639262 - 0.145263899385486377 * xm) * xm)
* xm))
* xm))
* xm))
* xm));
t2 = u * u * u;
ym = u * (t2 + 2.0 * xm) / (2.0 * t2 + xm) * factor[2 + xe % 3];
return __ldexp (x > 0.0 ? ym : -ym, xe / 3);
}
weak_alias (__cbrt, cbrt)
#ifdef NO_LONG_DOUBLE
strong_alias (__cbrt, __cbrtl)
weak_alias (__cbrt, cbrtl)
#endif
@@ -0,0 +1,64 @@
/* Compute cubic root of float value.
Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Dirk Alboth <[email protected]> and
Ulrich Drepper <[email protected]>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include "math.h"
#include "math_private.h"
#define CBRT2 1.2599210498948731648 /* 2^(1/3) */
#define SQR_CBRT2 1.5874010519681994748 /* 2^(2/3) */
static const double factor[5] =
{
1.0 / SQR_CBRT2,
1.0 / CBRT2,
1.0,
CBRT2,
SQR_CBRT2
};
float
__cbrtf (float x)
{
float xm, ym, u, t2;
int xe;
/* Reduce X. XM now is an range 1.0 to 0.5. */
xm = __frexpf (fabsf (x), &xe);
/* If X is not finite or is null return it (with raising exceptions
if necessary.
Note: *Our* version of `frexp' sets XE to zero if the argument is
Inf or NaN. This is not portable but faster. */
if (xe == 0 && fpclassify (x) <= FP_ZERO)
return x + x;
u = (0.492659620528969547 + (0.697570460207922770
- 0.191502161678719066 * xm) * xm);
t2 = u * u * u;
ym = u * (t2 + 2.0 * xm) / (2.0 * t2 + xm) * factor[2 + xe % 3];
return __ldexpf (x > 0.0 ? ym : -ym, xe / 3);
}
weak_alias (__cbrtf, cbrtf)
@@ -0,0 +1 @@
/* In s_sin.c. */
@@ -0,0 +1,60 @@
/* s_cosf.c -- float version of s_cos.c.
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
*/
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: s_cosf.c,v 1.4 1995/05/10 20:47:03 jtc Exp $";
#endif
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const float one=1.0;
#else
static float one=1.0;
#endif
#ifdef __STDC__
float __cosf(float x)
#else
float __cosf(x)
float x;
#endif
{
float y[2],z=0.0;
int32_t n,ix;
GET_FLOAT_WORD(ix,x);
/* |x| ~< pi/4 */
ix &= 0x7fffffff;
if(ix <= 0x3f490fd8) return __kernel_cosf(x,z);
/* cos(Inf or NaN) is NaN */
else if (ix>=0x7f800000) return x-x;
/* argument reduction needed */
else {
n = __ieee754_rem_pio2f(x,y);
switch(n&3) {
case 0: return __kernel_cosf(y[0],y[1]);
case 1: return -__kernel_sinf(y[0],y[1],1);
case 2: return -__kernel_cosf(y[0],y[1]);
default:
return __kernel_sinf(y[0],y[1],1);
}
}
}
weak_alias (__cosf, cosf)
@@ -0,0 +1,431 @@
/* @(#)s_erf.c 5.1 93/09/24 */
/*
* ====================================================
* 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.
* ====================================================
*/
/* Modified by Naohiko Shimizu/Tokai University, Japan 1997/08/25,
for performance improvement on pipelined processors.
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: s_erf.c,v 1.8 1995/05/10 20:47:05 jtc Exp $";
#endif
/* double erf(double x)
* double erfc(double x)
* x
* 2 |\
* erf(x) = --------- | exp(-t*t)dt
* sqrt(pi) \|
* 0
*
* erfc(x) = 1-erf(x)
* Note that
* erf(-x) = -erf(x)
* erfc(-x) = 2 - erfc(x)
*
* Method:
* 1. For |x| in [0, 0.84375]
* erf(x) = x + x*R(x^2)
* erfc(x) = 1 - erf(x) if x in [-.84375,0.25]
* = 0.5 + ((0.5-x)-x*R) if x in [0.25,0.84375]
* where R = P/Q where P is an odd poly of degree 8 and
* Q is an odd poly of degree 10.
* -57.90
* | R - (erf(x)-x)/x | <= 2
*
*
* Remark. The formula is derived by noting
* erf(x) = (2/sqrt(pi))*(x - x^3/3 + x^5/10 - x^7/42 + ....)
* and that
* 2/sqrt(pi) = 1.128379167095512573896158903121545171688
* is close to one. The interval is chosen because the fix
* point of erf(x) is near 0.6174 (i.e., erf(x)=x when x is
* near 0.6174), and by some experiment, 0.84375 is chosen to
* guarantee the error is less than one ulp for erf.
*
* 2. For |x| in [0.84375,1.25], let s = |x| - 1, and
* c = 0.84506291151 rounded to single (24 bits)
* erf(x) = sign(x) * (c + P1(s)/Q1(s))
* erfc(x) = (1-c) - P1(s)/Q1(s) if x > 0
* 1+(c+P1(s)/Q1(s)) if x < 0
* |P1/Q1 - (erf(|x|)-c)| <= 2**-59.06
* Remark: here we use the taylor series expansion at x=1.
* erf(1+s) = erf(1) + s*Poly(s)
* = 0.845.. + P1(s)/Q1(s)
* That is, we use rational approximation to approximate
* erf(1+s) - (c = (single)0.84506291151)
* Note that |P1/Q1|< 0.078 for x in [0.84375,1.25]
* where
* P1(s) = degree 6 poly in s
* Q1(s) = degree 6 poly in s
*
* 3. For x in [1.25,1/0.35(~2.857143)],
* erfc(x) = (1/x)*exp(-x*x-0.5625+R1/S1)
* erf(x) = 1 - erfc(x)
* where
* R1(z) = degree 7 poly in z, (z=1/x^2)
* S1(z) = degree 8 poly in z
*
* 4. For x in [1/0.35,28]
* erfc(x) = (1/x)*exp(-x*x-0.5625+R2/S2) if x > 0
* = 2.0 - (1/x)*exp(-x*x-0.5625+R2/S2) if -6<x<0
* = 2.0 - tiny (if x <= -6)
* erf(x) = sign(x)*(1.0 - erfc(x)) if x < 6, else
* erf(x) = sign(x)*(1.0 - tiny)
* where
* R2(z) = degree 6 poly in z, (z=1/x^2)
* S2(z) = degree 7 poly in z
*
* Note1:
* To compute exp(-x*x-0.5625+R/S), let s be a single
* precision number and s := x; then
* -x*x = -s*s + (s-x)*(s+x)
* exp(-x*x-0.5626+R/S) =
* exp(-s*s-0.5625)*exp((s-x)*(s+x)+R/S);
* Note2:
* Here 4 and 5 make use of the asymptotic series
* exp(-x*x)
* erfc(x) ~ ---------- * ( 1 + Poly(1/x^2) )
* x*sqrt(pi)
* We use rational approximation to approximate
* g(s)=f(1/x^2) = log(erfc(x)*x) - x*x + 0.5625
* Here is the error bound for R1/S1 and R2/S2
* |R1/S1 - f(x)| < 2**(-62.57)
* |R2/S2 - f(x)| < 2**(-61.52)
*
* 5. For inf > x >= 28
* erf(x) = sign(x) *(1 - tiny) (raise inexact)
* erfc(x) = tiny*tiny (raise underflow) if x > 0
* = 2 - tiny if x<0
*
* 7. Special case:
* erf(0) = 0, erf(inf) = 1, erf(-inf) = -1,
* erfc(0) = 1, erfc(inf) = 0, erfc(-inf) = 2,
* erfc/erf(NaN) is NaN
*/
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const double
#else
static double
#endif
tiny = 1e-300,
half= 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */
one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
two = 2.00000000000000000000e+00, /* 0x40000000, 0x00000000 */
/* c = (float)0.84506291151 */
erx = 8.45062911510467529297e-01, /* 0x3FEB0AC1, 0x60000000 */
/*
* Coefficients for approximation to erf on [0,0.84375]
*/
efx = 1.28379167095512586316e-01, /* 0x3FC06EBA, 0x8214DB69 */
efx8= 1.02703333676410069053e+00, /* 0x3FF06EBA, 0x8214DB69 */
pp[] = {1.28379167095512558561e-01, /* 0x3FC06EBA, 0x8214DB68 */
-3.25042107247001499370e-01, /* 0xBFD4CD7D, 0x691CB913 */
-2.84817495755985104766e-02, /* 0xBF9D2A51, 0xDBD7194F */
-5.77027029648944159157e-03, /* 0xBF77A291, 0x236668E4 */
-2.37630166566501626084e-05}, /* 0xBEF8EAD6, 0x120016AC */
qq[] = {0.0, 3.97917223959155352819e-01, /* 0x3FD97779, 0xCDDADC09 */
6.50222499887672944485e-02, /* 0x3FB0A54C, 0x5536CEBA */
5.08130628187576562776e-03, /* 0x3F74D022, 0xC4D36B0F */
1.32494738004321644526e-04, /* 0x3F215DC9, 0x221C1A10 */
-3.96022827877536812320e-06}, /* 0xBED09C43, 0x42A26120 */
/*
* Coefficients for approximation to erf in [0.84375,1.25]
*/
pa[] = {-2.36211856075265944077e-03, /* 0xBF6359B8, 0xBEF77538 */
4.14856118683748331666e-01, /* 0x3FDA8D00, 0xAD92B34D */
-3.72207876035701323847e-01, /* 0xBFD7D240, 0xFBB8C3F1 */
3.18346619901161753674e-01, /* 0x3FD45FCA, 0x805120E4 */
-1.10894694282396677476e-01, /* 0xBFBC6398, 0x3D3E28EC */
3.54783043256182359371e-02, /* 0x3FA22A36, 0x599795EB */
-2.16637559486879084300e-03}, /* 0xBF61BF38, 0x0A96073F */
qa[] = {0.0, 1.06420880400844228286e-01, /* 0x3FBB3E66, 0x18EEE323 */
5.40397917702171048937e-01, /* 0x3FE14AF0, 0x92EB6F33 */
7.18286544141962662868e-02, /* 0x3FB2635C, 0xD99FE9A7 */
1.26171219808761642112e-01, /* 0x3FC02660, 0xE763351F */
1.36370839120290507362e-02, /* 0x3F8BEDC2, 0x6B51DD1C */
1.19844998467991074170e-02}, /* 0x3F888B54, 0x5735151D */
/*
* Coefficients for approximation to erfc in [1.25,1/0.35]
*/
ra[] = {-9.86494403484714822705e-03, /* 0xBF843412, 0x600D6435 */
-6.93858572707181764372e-01, /* 0xBFE63416, 0xE4BA7360 */
-1.05586262253232909814e+01, /* 0xC0251E04, 0x41B0E726 */
-6.23753324503260060396e+01, /* 0xC04F300A, 0xE4CBA38D */
-1.62396669462573470355e+02, /* 0xC0644CB1, 0x84282266 */
-1.84605092906711035994e+02, /* 0xC067135C, 0xEBCCABB2 */
-8.12874355063065934246e+01, /* 0xC0545265, 0x57E4D2F2 */
-9.81432934416914548592e+00}, /* 0xC023A0EF, 0xC69AC25C */
sa[] = {0.0,1.96512716674392571292e+01, /* 0x4033A6B9, 0xBD707687 */
1.37657754143519042600e+02, /* 0x4061350C, 0x526AE721 */
4.34565877475229228821e+02, /* 0x407B290D, 0xD58A1A71 */
6.45387271733267880336e+02, /* 0x40842B19, 0x21EC2868 */
4.29008140027567833386e+02, /* 0x407AD021, 0x57700314 */
1.08635005541779435134e+02, /* 0x405B28A3, 0xEE48AE2C */
6.57024977031928170135e+00, /* 0x401A47EF, 0x8E484A93 */
-6.04244152148580987438e-02}, /* 0xBFAEEFF2, 0xEE749A62 */
/*
* Coefficients for approximation to erfc in [1/.35,28]
*/
rb[] = {-9.86494292470009928597e-03, /* 0xBF843412, 0x39E86F4A */
-7.99283237680523006574e-01, /* 0xBFE993BA, 0x70C285DE */
-1.77579549177547519889e+01, /* 0xC031C209, 0x555F995A */
-1.60636384855821916062e+02, /* 0xC064145D, 0x43C5ED98 */
-6.37566443368389627722e+02, /* 0xC083EC88, 0x1375F228 */
-1.02509513161107724954e+03, /* 0xC0900461, 0x6A2E5992 */
-4.83519191608651397019e+02}, /* 0xC07E384E, 0x9BDC383F */
sb[] = {0.0,3.03380607434824582924e+01, /* 0x403E568B, 0x261D5190 */
3.25792512996573918826e+02, /* 0x40745CAE, 0x221B9F0A */
1.53672958608443695994e+03, /* 0x409802EB, 0x189D5118 */
3.19985821950859553908e+03, /* 0x40A8FFB7, 0x688C246A */
2.55305040643316442583e+03, /* 0x40A3F219, 0xCEDF3BE6 */
4.74528541206955367215e+02, /* 0x407DA874, 0xE79FE763 */
-2.24409524465858183362e+01}; /* 0xC03670E2, 0x42712D62 */
#ifdef __STDC__
double __erf(double x)
#else
double __erf(x)
double x;
#endif
{
int32_t hx,ix,i;
double R,S,P,Q,s,y,z,r;
GET_HIGH_WORD(hx,x);
ix = hx&0x7fffffff;
if(ix>=0x7ff00000) { /* erf(nan)=nan */
i = ((u_int32_t)hx>>31)<<1;
return (double)(1-i)+one/x; /* erf(+-inf)=+-1 */
}
if(ix < 0x3feb0000) { /* |x|<0.84375 */
double r1,r2,s1,s2,s3,z2,z4;
if(ix < 0x3e300000) { /* |x|<2**-28 */
if (ix < 0x00800000)
return 0.125*(8.0*x+efx8*x); /*avoid underflow */
return x + efx*x;
}
z = x*x;
#ifdef DO_NOT_USE_THIS
r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4)));
s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5))));
#else
r1 = pp[0]+z*pp[1]; z2=z*z;
r2 = pp[2]+z*pp[3]; z4=z2*z2;
s1 = one+z*qq[1];
s2 = qq[2]+z*qq[3];
s3 = qq[4]+z*qq[5];
r = r1 + z2*r2 + z4*pp[4];
s = s1 + z2*s2 + z4*s3;
#endif
y = r/s;
return x + x*y;
}
if(ix < 0x3ff40000) { /* 0.84375 <= |x| < 1.25 */
double s2,s4,s6,P1,P2,P3,P4,Q1,Q2,Q3,Q4;
s = fabs(x)-one;
#ifdef DO_NOT_USE_THIS
P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6)))));
Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6)))));
#else
P1 = pa[0]+s*pa[1]; s2=s*s;
Q1 = one+s*qa[1]; s4=s2*s2;
P2 = pa[2]+s*pa[3]; s6=s4*s2;
Q2 = qa[2]+s*qa[3];
P3 = pa[4]+s*pa[5];
Q3 = qa[4]+s*qa[5];
P4 = pa[6];
Q4 = qa[6];
P = P1 + s2*P2 + s4*P3 + s6*P4;
Q = Q1 + s2*Q2 + s4*Q3 + s6*Q4;
#endif
if(hx>=0) return erx + P/Q; else return -erx - P/Q;
}
if (ix >= 0x40180000) { /* inf>|x|>=6 */
if(hx>=0) return one-tiny; else return tiny-one;
}
x = fabs(x);
s = one/(x*x);
if(ix< 0x4006DB6E) { /* |x| < 1/0.35 */
#ifdef DO_NOT_USE_THIS
R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(
ra5+s*(ra6+s*ra7))))));
S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(
sa5+s*(sa6+s*(sa7+s*sa8)))))));
#else
double R1,R2,R3,R4,S1,S2,S3,S4,s2,s4,s6,s8;
R1 = ra[0]+s*ra[1];s2 = s*s;
S1 = one+s*sa[1]; s4 = s2*s2;
R2 = ra[2]+s*ra[3];s6 = s4*s2;
S2 = sa[2]+s*sa[3];s8 = s4*s4;
R3 = ra[4]+s*ra[5];
S3 = sa[4]+s*sa[5];
R4 = ra[6]+s*ra[7];
S4 = sa[6]+s*sa[7];
R = R1 + s2*R2 + s4*R3 + s6*R4;
S = S1 + s2*S2 + s4*S3 + s6*S4 + s8*sa[8];
#endif
} else { /* |x| >= 1/0.35 */
#ifdef DO_NOT_USE_THIS
R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(
rb5+s*rb6)))));
S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(
sb5+s*(sb6+s*sb7))))));
#else
double R1,R2,R3,S1,S2,S3,S4,s2,s4,s6;
R1 = rb[0]+s*rb[1];s2 = s*s;
S1 = one+s*sb[1]; s4 = s2*s2;
R2 = rb[2]+s*rb[3];s6 = s4*s2;
S2 = sb[2]+s*sb[3];
R3 = rb[4]+s*rb[5];
S3 = sb[4]+s*sb[5];
S4 = sb[6]+s*sb[7];
R = R1 + s2*R2 + s4*R3 + s6*rb[6];
S = S1 + s2*S2 + s4*S3 + s6*S4;
#endif
}
z = x;
SET_LOW_WORD(z,0);
r = __ieee754_exp(-z*z-0.5625)*__ieee754_exp((z-x)*(z+x)+R/S);
if(hx>=0) return one-r/x; else return r/x-one;
}
weak_alias (__erf, erf)
#ifdef NO_LONG_DOUBLE
strong_alias (__erf, __erfl)
weak_alias (__erf, erfl)
#endif
#ifdef __STDC__
double __erfc(double x)
#else
double __erfc(x)
double x;
#endif
{
int32_t hx,ix;
double R,S,P,Q,s,y,z,r;
GET_HIGH_WORD(hx,x);
ix = hx&0x7fffffff;
if(ix>=0x7ff00000) { /* erfc(nan)=nan */
/* erfc(+-inf)=0,2 */
return (double)(((u_int32_t)hx>>31)<<1)+one/x;
}
if(ix < 0x3feb0000) { /* |x|<0.84375 */
double r1,r2,s1,s2,s3,z2,z4;
if(ix < 0x3c700000) /* |x|<2**-56 */
return one-x;
z = x*x;
#ifdef DO_NOT_USE_THIS
r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4)));
s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5))));
#else
r1 = pp[0]+z*pp[1]; z2=z*z;
r2 = pp[2]+z*pp[3]; z4=z2*z2;
s1 = one+z*qq[1];
s2 = qq[2]+z*qq[3];
s3 = qq[4]+z*qq[5];
r = r1 + z2*r2 + z4*pp[4];
s = s1 + z2*s2 + z4*s3;
#endif
y = r/s;
if(hx < 0x3fd00000) { /* x<1/4 */
return one-(x+x*y);
} else {
r = x*y;
r += (x-half);
return half - r ;
}
}
if(ix < 0x3ff40000) { /* 0.84375 <= |x| < 1.25 */
double s2,s4,s6,P1,P2,P3,P4,Q1,Q2,Q3,Q4;
s = fabs(x)-one;
#ifdef DO_NOT_USE_THIS
P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6)))));
Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6)))));
#else
P1 = pa[0]+s*pa[1]; s2=s*s;
Q1 = one+s*qa[1]; s4=s2*s2;
P2 = pa[2]+s*pa[3]; s6=s4*s2;
Q2 = qa[2]+s*qa[3];
P3 = pa[4]+s*pa[5];
Q3 = qa[4]+s*qa[5];
P4 = pa[6];
Q4 = qa[6];
P = P1 + s2*P2 + s4*P3 + s6*P4;
Q = Q1 + s2*Q2 + s4*Q3 + s6*Q4;
#endif
if(hx>=0) {
z = one-erx; return z - P/Q;
} else {
z = erx+P/Q; return one+z;
}
}
if (ix < 0x403c0000) { /* |x|<28 */
x = fabs(x);
s = one/(x*x);
if(ix< 0x4006DB6D) { /* |x| < 1/.35 ~ 2.857143*/
#ifdef DO_NOT_USE_THIS
R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(
ra5+s*(ra6+s*ra7))))));
S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(
sa5+s*(sa6+s*(sa7+s*sa8)))))));
#else
double R1,R2,R3,R4,S1,S2,S3,S4,s2,s4,s6,s8;
R1 = ra[0]+s*ra[1];s2 = s*s;
S1 = one+s*sa[1]; s4 = s2*s2;
R2 = ra[2]+s*ra[3];s6 = s4*s2;
S2 = sa[2]+s*sa[3];s8 = s4*s4;
R3 = ra[4]+s*ra[5];
S3 = sa[4]+s*sa[5];
R4 = ra[6]+s*ra[7];
S4 = sa[6]+s*sa[7];
R = R1 + s2*R2 + s4*R3 + s6*R4;
S = S1 + s2*S2 + s4*S3 + s6*S4 + s8*sa[8];
#endif
} else { /* |x| >= 1/.35 ~ 2.857143 */
double R1,R2,R3,S1,S2,S3,S4,s2,s4,s6;
if(hx<0&&ix>=0x40180000) return two-tiny;/* x < -6 */
#ifdef DO_NOT_USE_THIS
R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(
rb5+s*rb6)))));
S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(
sb5+s*(sb6+s*sb7))))));
#else
R1 = rb[0]+s*rb[1];s2 = s*s;
S1 = one+s*sb[1]; s4 = s2*s2;
R2 = rb[2]+s*rb[3];s6 = s4*s2;
S2 = sb[2]+s*sb[3];
R3 = rb[4]+s*rb[5];
S3 = sb[4]+s*sb[5];
S4 = sb[6]+s*sb[7];
R = R1 + s2*R2 + s4*R3 + s6*rb[6];
S = S1 + s2*S2 + s4*S3 + s6*S4;
#endif
}
z = x;
SET_LOW_WORD(z,0);
r = __ieee754_exp(-z*z-0.5625)*
__ieee754_exp((z-x)*(z+x)+R/S);
if(hx>0) return r/x; else return two-r/x;
} else {
if(hx>0) return tiny*tiny; else return two-tiny;
}
}
weak_alias (__erfc, erfc)
#ifdef NO_LONG_DOUBLE
strong_alias (__erfc, __erfcl)
weak_alias (__erfc, erfcl)
#endif
@@ -0,0 +1,225 @@
/* s_erff.c -- float version of s_erf.c.
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
*/
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: s_erff.c,v 1.4 1995/05/10 20:47:07 jtc Exp $";
#endif
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const float
#else
static float
#endif
tiny = 1e-30,
half= 5.0000000000e-01, /* 0x3F000000 */
one = 1.0000000000e+00, /* 0x3F800000 */
two = 2.0000000000e+00, /* 0x40000000 */
/* c = (subfloat)0.84506291151 */
erx = 8.4506291151e-01, /* 0x3f58560b */
/*
* Coefficients for approximation to erf on [0,0.84375]
*/
efx = 1.2837916613e-01, /* 0x3e0375d4 */
efx8= 1.0270333290e+00, /* 0x3f8375d4 */
pp0 = 1.2837916613e-01, /* 0x3e0375d4 */
pp1 = -3.2504209876e-01, /* 0xbea66beb */
pp2 = -2.8481749818e-02, /* 0xbce9528f */
pp3 = -5.7702702470e-03, /* 0xbbbd1489 */
pp4 = -2.3763017452e-05, /* 0xb7c756b1 */
qq1 = 3.9791721106e-01, /* 0x3ecbbbce */
qq2 = 6.5022252500e-02, /* 0x3d852a63 */
qq3 = 5.0813062117e-03, /* 0x3ba68116 */
qq4 = 1.3249473704e-04, /* 0x390aee49 */
qq5 = -3.9602282413e-06, /* 0xb684e21a */
/*
* Coefficients for approximation to erf in [0.84375,1.25]
*/
pa0 = -2.3621185683e-03, /* 0xbb1acdc6 */
pa1 = 4.1485610604e-01, /* 0x3ed46805 */
pa2 = -3.7220788002e-01, /* 0xbebe9208 */
pa3 = 3.1834661961e-01, /* 0x3ea2fe54 */
pa4 = -1.1089469492e-01, /* 0xbde31cc2 */
pa5 = 3.5478305072e-02, /* 0x3d1151b3 */
pa6 = -2.1663755178e-03, /* 0xbb0df9c0 */
qa1 = 1.0642088205e-01, /* 0x3dd9f331 */
qa2 = 5.4039794207e-01, /* 0x3f0a5785 */
qa3 = 7.1828655899e-02, /* 0x3d931ae7 */
qa4 = 1.2617121637e-01, /* 0x3e013307 */
qa5 = 1.3637083583e-02, /* 0x3c5f6e13 */
qa6 = 1.1984500103e-02, /* 0x3c445aa3 */
/*
* Coefficients for approximation to erfc in [1.25,1/0.35]
*/
ra0 = -9.8649440333e-03, /* 0xbc21a093 */
ra1 = -6.9385856390e-01, /* 0xbf31a0b7 */
ra2 = -1.0558626175e+01, /* 0xc128f022 */
ra3 = -6.2375331879e+01, /* 0xc2798057 */
ra4 = -1.6239666748e+02, /* 0xc322658c */
ra5 = -1.8460508728e+02, /* 0xc3389ae7 */
ra6 = -8.1287437439e+01, /* 0xc2a2932b */
ra7 = -9.8143291473e+00, /* 0xc11d077e */
sa1 = 1.9651271820e+01, /* 0x419d35ce */
sa2 = 1.3765776062e+02, /* 0x4309a863 */
sa3 = 4.3456588745e+02, /* 0x43d9486f */
sa4 = 6.4538726807e+02, /* 0x442158c9 */
sa5 = 4.2900814819e+02, /* 0x43d6810b */
sa6 = 1.0863500214e+02, /* 0x42d9451f */
sa7 = 6.5702495575e+00, /* 0x40d23f7c */
sa8 = -6.0424413532e-02, /* 0xbd777f97 */
/*
* Coefficients for approximation to erfc in [1/.35,28]
*/
rb0 = -9.8649431020e-03, /* 0xbc21a092 */
rb1 = -7.9928326607e-01, /* 0xbf4c9dd4 */
rb2 = -1.7757955551e+01, /* 0xc18e104b */
rb3 = -1.6063638306e+02, /* 0xc320a2ea */
rb4 = -6.3756646729e+02, /* 0xc41f6441 */
rb5 = -1.0250950928e+03, /* 0xc480230b */
rb6 = -4.8351919556e+02, /* 0xc3f1c275 */
sb1 = 3.0338060379e+01, /* 0x41f2b459 */
sb2 = 3.2579251099e+02, /* 0x43a2e571 */
sb3 = 1.5367296143e+03, /* 0x44c01759 */
sb4 = 3.1998581543e+03, /* 0x4547fdbb */
sb5 = 2.5530502930e+03, /* 0x451f90ce */
sb6 = 4.7452853394e+02, /* 0x43ed43a7 */
sb7 = -2.2440952301e+01; /* 0xc1b38712 */
#ifdef __STDC__
float __erff(float x)
#else
float __erff(x)
float x;
#endif
{
int32_t hx,ix,i;
float R,S,P,Q,s,y,z,r;
GET_FLOAT_WORD(hx,x);
ix = hx&0x7fffffff;
if(ix>=0x7f800000) { /* erf(nan)=nan */
i = ((u_int32_t)hx>>31)<<1;
return (float)(1-i)+one/x; /* erf(+-inf)=+-1 */
}
if(ix < 0x3f580000) { /* |x|<0.84375 */
if(ix < 0x31800000) { /* |x|<2**-28 */
if (ix < 0x04000000)
/*avoid underflow */
return (float)0.125*((float)8.0*x+efx8*x);
return x + efx*x;
}
z = x*x;
r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4)));
s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5))));
y = r/s;
return x + x*y;
}
if(ix < 0x3fa00000) { /* 0.84375 <= |x| < 1.25 */
s = fabsf(x)-one;
P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6)))));
Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6)))));
if(hx>=0) return erx + P/Q; else return -erx - P/Q;
}
if (ix >= 0x40c00000) { /* inf>|x|>=6 */
if(hx>=0) return one-tiny; else return tiny-one;
}
x = fabsf(x);
s = one/(x*x);
if(ix< 0x4036DB6E) { /* |x| < 1/0.35 */
R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(
ra5+s*(ra6+s*ra7))))));
S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(
sa5+s*(sa6+s*(sa7+s*sa8)))))));
} else { /* |x| >= 1/0.35 */
R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(
rb5+s*rb6)))));
S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(
sb5+s*(sb6+s*sb7))))));
}
GET_FLOAT_WORD(ix,x);
SET_FLOAT_WORD(z,ix&0xfffff000);
r = __ieee754_expf(-z*z-(float)0.5625)*__ieee754_expf((z-x)*(z+x)+R/S);
if(hx>=0) return one-r/x; else return r/x-one;
}
weak_alias (__erff, erff)
#ifdef __STDC__
float __erfcf(float x)
#else
float __erfcf(x)
float x;
#endif
{
int32_t hx,ix;
float R,S,P,Q,s,y,z,r;
GET_FLOAT_WORD(hx,x);
ix = hx&0x7fffffff;
if(ix>=0x7f800000) { /* erfc(nan)=nan */
/* erfc(+-inf)=0,2 */
return (float)(((u_int32_t)hx>>31)<<1)+one/x;
}
if(ix < 0x3f580000) { /* |x|<0.84375 */
if(ix < 0x23800000) /* |x|<2**-56 */
return one-x;
z = x*x;
r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4)));
s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5))));
y = r/s;
if(hx < 0x3e800000) { /* x<1/4 */
return one-(x+x*y);
} else {
r = x*y;
r += (x-half);
return half - r ;
}
}
if(ix < 0x3fa00000) { /* 0.84375 <= |x| < 1.25 */
s = fabsf(x)-one;
P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6)))));
Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6)))));
if(hx>=0) {
z = one-erx; return z - P/Q;
} else {
z = erx+P/Q; return one+z;
}
}
if (ix < 0x41e00000) { /* |x|<28 */
x = fabsf(x);
s = one/(x*x);
if(ix< 0x4036DB6D) { /* |x| < 1/.35 ~ 2.857143*/
R=ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*(
ra5+s*(ra6+s*ra7))))));
S=one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*(
sa5+s*(sa6+s*(sa7+s*sa8)))))));
} else { /* |x| >= 1/.35 ~ 2.857143 */
if(hx<0&&ix>=0x40c00000) return two-tiny;/* x < -6 */
R=rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*(
rb5+s*rb6)))));
S=one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*(
sb5+s*(sb6+s*sb7))))));
}
GET_FLOAT_WORD(ix,x);
SET_FLOAT_WORD(z,ix&0xfffff000);
r = __ieee754_expf(-z*z-(float)0.5625)*
__ieee754_expf((z-x)*(z+x)+R/S);
if(hx>0) return r/x; else return two-r/x;
} else {
if(hx>0) return tiny*tiny; else return two-tiny;
}
}
weak_alias (__erfcf, erfcf)
@@ -0,0 +1,243 @@
/* @(#)s_expm1.c 5.1 93/09/24 */
/*
* ====================================================
* 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.
* ====================================================
*/
/* Modified by Naohiko Shimizu/Tokai University, Japan 1997/08/25,
for performance improvement on pipelined processors.
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: s_expm1.c,v 1.8 1995/05/10 20:47:09 jtc Exp $";
#endif
/* expm1(x)
* Returns exp(x)-1, the exponential of x minus 1.
*
* Method
* 1. Argument reduction:
* Given x, find r and integer k such that
*
* x = k*ln2 + r, |r| <= 0.5*ln2 ~ 0.34658
*
* Here a correction term c will be computed to compensate
* the error in r when rounded to a floating-point number.
*
* 2. Approximating expm1(r) by a special rational function on
* the interval [0,0.34658]:
* Since
* r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 - r^4/360 + ...
* we define R1(r*r) by
* r*(exp(r)+1)/(exp(r)-1) = 2+ r^2/6 * R1(r*r)
* That is,
* R1(r**2) = 6/r *((exp(r)+1)/(exp(r)-1) - 2/r)
* = 6/r * ( 1 + 2.0*(1/(exp(r)-1) - 1/r))
* = 1 - r^2/60 + r^4/2520 - r^6/100800 + ...
* We use a special Reme algorithm on [0,0.347] to generate
* a polynomial of degree 5 in r*r to approximate R1. The
* maximum error of this polynomial approximation is bounded
* by 2**-61. In other words,
* R1(z) ~ 1.0 + Q1*z + Q2*z**2 + Q3*z**3 + Q4*z**4 + Q5*z**5
* where Q1 = -1.6666666666666567384E-2,
* Q2 = 3.9682539681370365873E-4,
* Q3 = -9.9206344733435987357E-6,
* Q4 = 2.5051361420808517002E-7,
* Q5 = -6.2843505682382617102E-9;
* (where z=r*r, and the values of Q1 to Q5 are listed below)
* with error bounded by
* | 5 | -61
* | 1.0+Q1*z+...+Q5*z - R1(z) | <= 2
* | |
*
* expm1(r) = exp(r)-1 is then computed by the following
* specific way which minimize the accumulation rounding error:
* 2 3
* r r [ 3 - (R1 + R1*r/2) ]
* expm1(r) = r + --- + --- * [--------------------]
* 2 2 [ 6 - r*(3 - R1*r/2) ]
*
* To compensate the error in the argument reduction, we use
* expm1(r+c) = expm1(r) + c + expm1(r)*c
* ~ expm1(r) + c + r*c
* Thus c+r*c will be added in as the correction terms for
* expm1(r+c). Now rearrange the term to avoid optimization
* screw up:
* ( 2 2 )
* ({ ( r [ R1 - (3 - R1*r/2) ] ) } r )
* expm1(r+c)~r - ({r*(--- * [--------------------]-c)-c} - --- )
* ({ ( 2 [ 6 - r*(3 - R1*r/2) ] ) } 2 )
* ( )
*
* = r - E
* 3. Scale back to obtain expm1(x):
* From step 1, we have
* expm1(x) = either 2^k*[expm1(r)+1] - 1
* = or 2^k*[expm1(r) + (1-2^-k)]
* 4. Implementation notes:
* (A). To save one multiplication, we scale the coefficient Qi
* to Qi*2^i, and replace z by (x^2)/2.
* (B). To achieve maximum accuracy, we compute expm1(x) by
* (i) if x < -56*ln2, return -1.0, (raise inexact if x!=inf)
* (ii) if k=0, return r-E
* (iii) if k=-1, return 0.5*(r-E)-0.5
* (iv) if k=1 if r < -0.25, return 2*((r+0.5)- E)
* else return 1.0+2.0*(r-E);
* (v) if (k<-2||k>56) return 2^k(1-(E-r)) - 1 (or exp(x)-1)
* (vi) if k <= 20, return 2^k((1-2^-k)-(E-r)), else
* (vii) return 2^k(1-((E+2^-k)-r))
*
* Special cases:
* expm1(INF) is INF, expm1(NaN) is NaN;
* expm1(-INF) is -1, and
* for finite argument, only expm1(0)=0 is exact.
*
* Accuracy:
* according to an error analysis, the error is always less than
* 1 ulp (unit in the last place).
*
* Misc. info.
* For IEEE double
* if x > 7.09782712893383973096e+02 then expm1(x) overflow
*
* Constants:
* The hexadecimal values are the intended ones for the following
* constants. The decimal values may be used, provided that the
* compiler will convert from decimal to binary accurately enough
* to produce the hexadecimal values shown.
*/
#include "math.h"
#include "math_private.h"
#define one Q[0]
#ifdef __STDC__
static const double
#else
static double
#endif
huge = 1.0e+300,
tiny = 1.0e-300,
o_threshold = 7.09782712893383973096e+02,/* 0x40862E42, 0xFEFA39EF */
ln2_hi = 6.93147180369123816490e-01,/* 0x3fe62e42, 0xfee00000 */
ln2_lo = 1.90821492927058770002e-10,/* 0x3dea39ef, 0x35793c76 */
invln2 = 1.44269504088896338700e+00,/* 0x3ff71547, 0x652b82fe */
/* scaled coefficients related to expm1 */
Q[] = {1.0, -3.33333333333331316428e-02, /* BFA11111 111110F4 */
1.58730158725481460165e-03, /* 3F5A01A0 19FE5585 */
-7.93650757867487942473e-05, /* BF14CE19 9EAADBB7 */
4.00821782732936239552e-06, /* 3ED0CFCA 86E65239 */
-2.01099218183624371326e-07}; /* BE8AFDB7 6E09C32D */
#ifdef __STDC__
double __expm1(double x)
#else
double __expm1(x)
double x;
#endif
{
double y,hi,lo,c,t,e,hxs,hfx,r1,h2,h4,R1,R2,R3;
int32_t k,xsb;
u_int32_t hx;
GET_HIGH_WORD(hx,x);
xsb = hx&0x80000000; /* sign bit of x */
if(xsb==0) y=x; else y= -x; /* y = |x| */
hx &= 0x7fffffff; /* high word of |x| */
/* filter out huge and non-finite argument */
if(hx >= 0x4043687A) { /* if |x|>=56*ln2 */
if(hx >= 0x40862E42) { /* if |x|>=709.78... */
if(hx>=0x7ff00000) {
u_int32_t low;
GET_LOW_WORD(low,x);
if(((hx&0xfffff)|low)!=0)
return x+x; /* NaN */
else return (xsb==0)? x:-1.0;/* exp(+-inf)={inf,-1} */
}
if(x > o_threshold) return huge*huge; /* overflow */
}
if(xsb!=0) { /* x < -56*ln2, return -1.0 with inexact */
if(x+tiny<0.0) /* raise inexact */
return tiny-one; /* return -1 */
}
}
/* argument reduction */
if(hx > 0x3fd62e42) { /* if |x| > 0.5 ln2 */
if(hx < 0x3FF0A2B2) { /* and |x| < 1.5 ln2 */
if(xsb==0)
{hi = x - ln2_hi; lo = ln2_lo; k = 1;}
else
{hi = x + ln2_hi; lo = -ln2_lo; k = -1;}
} else {
k = invln2*x+((xsb==0)?0.5:-0.5);
t = k;
hi = x - t*ln2_hi; /* t*ln2_hi is exact here */
lo = t*ln2_lo;
}
x = hi - lo;
c = (hi-x)-lo;
}
else if(hx < 0x3c900000) { /* when |x|<2**-54, return x */
t = huge+x; /* return x with inexact flags when x!=0 */
return x - (t-(huge+x));
}
else k = 0;
/* x is now in primary range */
hfx = 0.5*x;
hxs = x*hfx;
#ifdef DO_NOT_USE_THIS
r1 = one+hxs*(Q1+hxs*(Q2+hxs*(Q3+hxs*(Q4+hxs*Q5))));
#else
R1 = one+hxs*Q[1]; h2 = hxs*hxs;
R2 = Q[2]+hxs*Q[3]; h4 = h2*h2;
R3 = Q[4]+hxs*Q[5];
r1 = R1 + h2*R2 + h4*R3;
#endif
t = 3.0-r1*hfx;
e = hxs*((r1-t)/(6.0 - x*t));
if(k==0) return x - (x*e-hxs); /* c is 0 */
else {
e = (x*(e-c)-c);
e -= hxs;
if(k== -1) return 0.5*(x-e)-0.5;
if(k==1) {
if(x < -0.25) return -2.0*(e-(x+0.5));
else return one+2.0*(x-e);
}
if (k <= -2 || k>56) { /* suffice to return exp(x)-1 */
u_int32_t high;
y = one-(e-x);
GET_HIGH_WORD(high,y);
SET_HIGH_WORD(y,high+(k<<20)); /* add k to y's exponent */
return y-one;
}
t = one;
if(k<20) {
u_int32_t high;
SET_HIGH_WORD(t,0x3ff00000 - (0x200000>>k)); /* t=1-2^-k */
y = t-(e-x);
GET_HIGH_WORD(high,y);
SET_HIGH_WORD(y,high+(k<<20)); /* add k to y's exponent */
} else {
u_int32_t high;
SET_HIGH_WORD(t,((0x3ff-k)<<20)); /* 2^-k */
y = x-(e+t);
y += one;
GET_HIGH_WORD(high,y);
SET_HIGH_WORD(y,high+(k<<20)); /* add k to y's exponent */
}
}
return y;
}
weak_alias (__expm1, expm1)
#ifdef NO_LONG_DOUBLE
strong_alias (__expm1, __expm1l)
weak_alias (__expm1, expm1l)
#endif
@@ -0,0 +1,135 @@
/* s_expm1f.c -- float version of s_expm1.c.
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
*/
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: s_expm1f.c,v 1.5 1995/05/10 20:47:11 jtc Exp $";
#endif
#include "math.h"
#include "math_private.h"
static const volatile float huge = 1.0e+30, tiny = 1.0e-30;
#ifdef __STDC__
static const float
#else
static float
#endif
one = 1.0,
o_threshold = 8.8721679688e+01,/* 0x42b17180 */
ln2_hi = 6.9313812256e-01,/* 0x3f317180 */
ln2_lo = 9.0580006145e-06,/* 0x3717f7d1 */
invln2 = 1.4426950216e+00,/* 0x3fb8aa3b */
/* scaled coefficients related to expm1 */
Q1 = -3.3333335072e-02, /* 0xbd088889 */
Q2 = 1.5873016091e-03, /* 0x3ad00d01 */
Q3 = -7.9365076090e-05, /* 0xb8a670cd */
Q4 = 4.0082177293e-06, /* 0x36867e54 */
Q5 = -2.0109921195e-07; /* 0xb457edbb */
#ifdef __STDC__
float __expm1f(float x)
#else
float __expm1f(x)
float x;
#endif
{
float y,hi,lo,c,t,e,hxs,hfx,r1;
int32_t k,xsb;
u_int32_t hx;
GET_FLOAT_WORD(hx,x);
xsb = hx&0x80000000; /* sign bit of x */
if(xsb==0) y=x; else y= -x; /* y = |x| */
hx &= 0x7fffffff; /* high word of |x| */
/* filter out huge and non-finite argument */
if(hx >= 0x4195b844) { /* if |x|>=27*ln2 */
if(hx >= 0x42b17218) { /* if |x|>=88.721... */
if(hx>0x7f800000)
return x+x; /* NaN */
if(hx==0x7f800000)
return (xsb==0)? x:-1.0;/* exp(+-inf)={inf,-1} */
if(x > o_threshold) return huge*huge; /* overflow */
}
if(xsb!=0) { /* x < -27*ln2, return -1.0 with inexact */
if(x+tiny<(float)0.0) /* raise inexact */
return tiny-one; /* return -1 */
}
}
/* argument reduction */
if(hx > 0x3eb17218) { /* if |x| > 0.5 ln2 */
if(hx < 0x3F851592) { /* and |x| < 1.5 ln2 */
if(xsb==0)
{hi = x - ln2_hi; lo = ln2_lo; k = 1;}
else
{hi = x + ln2_hi; lo = -ln2_lo; k = -1;}
} else {
k = invln2*x+((xsb==0)?(float)0.5:(float)-0.5);
t = k;
hi = x - t*ln2_hi; /* t*ln2_hi is exact here */
lo = t*ln2_lo;
}
x = hi - lo;
c = (hi-x)-lo;
}
else if(hx < 0x33000000) { /* when |x|<2**-25, return x */
t = huge+x; /* return x with inexact flags when x!=0 */
return x - (t-(huge+x));
}
else k = 0;
/* x is now in primary range */
hfx = (float)0.5*x;
hxs = x*hfx;
r1 = one+hxs*(Q1+hxs*(Q2+hxs*(Q3+hxs*(Q4+hxs*Q5))));
t = (float)3.0-r1*hfx;
e = hxs*((r1-t)/((float)6.0 - x*t));
if(k==0) return x - (x*e-hxs); /* c is 0 */
else {
e = (x*(e-c)-c);
e -= hxs;
if(k== -1) return (float)0.5*(x-e)-(float)0.5;
if(k==1) {
if(x < (float)-0.25) return -(float)2.0*(e-(x+(float)0.5));
else return one+(float)2.0*(x-e);
}
if (k <= -2 || k>56) { /* suffice to return exp(x)-1 */
int32_t i;
y = one-(e-x);
GET_FLOAT_WORD(i,y);
SET_FLOAT_WORD(y,i+(k<<23)); /* add k to y's exponent */
return y-one;
}
t = one;
if(k<23) {
int32_t i;
SET_FLOAT_WORD(t,0x3f800000 - (0x1000000>>k)); /* t=1-2^-k */
y = t-(e-x);
GET_FLOAT_WORD(i,y);
SET_FLOAT_WORD(y,i+(k<<23)); /* add k to y's exponent */
} else {
int32_t i;
SET_FLOAT_WORD(t,((0x7f-k)<<23)); /* 2^-k */
y = x-(e+t);
y += one;
GET_FLOAT_WORD(i,y);
SET_FLOAT_WORD(y,i+(k<<23)); /* add k to y's exponent */
}
}
return y;
}
weak_alias (__expm1f, expm1f)
@@ -0,0 +1,64 @@
/* @(#)s_frexp.c 5.1 93/09/24 */
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: s_frexp.c,v 1.9 1995/05/10 20:47:24 jtc Exp $";
#endif
/*
* for non-zero x
* x = frexp(arg,&exp);
* return a double fp quantity x such that 0.5 <= |x| <1.0
* and the corresponding binary exponent "exp". That is
* arg = x*2^exp.
* If arg is inf, 0.0, or NaN, then frexp(arg,&exp) returns arg
* with *exp=0.
*/
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const double
#else
static double
#endif
two54 = 1.80143985094819840000e+16; /* 0x43500000, 0x00000000 */
#ifdef __STDC__
double __frexp(double x, int *eptr)
#else
double __frexp(x, eptr)
double x; int *eptr;
#endif
{
int32_t hx, ix, lx;
EXTRACT_WORDS(hx,lx,x);
ix = 0x7fffffff&hx;
*eptr = 0;
if(ix>=0x7ff00000||((ix|lx)==0)) return x; /* 0,inf,nan */
if (ix<0x00100000) { /* subnormal */
x *= two54;
GET_HIGH_WORD(hx,x);
ix = hx&0x7fffffff;
*eptr = -54;
}
*eptr += (ix>>20)-1022;
hx = (hx&0x800fffff)|0x3fe00000;
SET_HIGH_WORD(x,hx);
return x;
}
weak_alias (__frexp, frexp)
#ifdef NO_LONG_DOUBLE
strong_alias (__frexp, __frexpl)
weak_alias (__frexp, frexpl)
#endif
@@ -0,0 +1,53 @@
/* s_frexpf.c -- float version of s_frexp.c.
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
*/
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: s_frexpf.c,v 1.5 1995/05/10 20:47:26 jtc Exp $";
#endif
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const float
#else
static float
#endif
two25 = 3.3554432000e+07; /* 0x4c000000 */
#ifdef __STDC__
float __frexpf(float x, int *eptr)
#else
float __frexpf(x, eptr)
float x; int *eptr;
#endif
{
int32_t hx,ix;
GET_FLOAT_WORD(hx,x);
ix = 0x7fffffff&hx;
*eptr = 0;
if(ix>=0x7f800000||(ix==0)) return x; /* 0,inf,nan */
if (ix<0x00800000) { /* subnormal */
x *= two25;
GET_FLOAT_WORD(hx,x);
ix = hx&0x7fffffff;
*eptr = -25;
}
*eptr += (ix>>23)-126;
hx = (hx&0x807fffff)|0x3f000000;
SET_FLOAT_WORD(x,hx);
return x;
}
weak_alias (__frexpf, frexpf)
@@ -0,0 +1,33 @@
/*
* Written by J.T. Conklin <[email protected]>.
* Changed to return -1 for -Inf by Ulrich Drepper <[email protected]>.
* Public domain.
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: s_isinf.c,v 1.3 1995/05/11 23:20:14 jtc Exp $";
#endif
/*
* isinf(x) returns 1 is x is inf, -1 if x is -inf, else 0;
* no branching!
*/
#include "math.h"
#include "math_private.h"
int
__isinf (double x)
{
int32_t hx,lx;
EXTRACT_WORDS(hx,lx,x);
lx |= (hx & 0x7fffffff) ^ 0x7ff00000;
lx |= -lx;
return ~(lx >> 31) & (hx >> 30);
}
hidden_def (__isinf)
weak_alias (__isinf, isinf)
#ifdef NO_LONG_DOUBLE
strong_alias (__isinf, __isinfl)
weak_alias (__isinf, isinfl)
#endif
@@ -0,0 +1,29 @@
/*
* Written by J.T. Conklin <[email protected]>.
* Public domain.
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: s_isinff.c,v 1.3 1995/05/11 23:20:21 jtc Exp $";
#endif
/*
* isinff(x) returns 1 if x is inf, -1 if x is -inf, else 0;
* no branching!
*/
#include "math.h"
#include "math_private.h"
int
__isinff (float x)
{
int32_t ix,t;
GET_FLOAT_WORD(ix,x);
t = ix & 0x7fffffff;
t ^= 0x7f800000;
t |= -t;
return ~(t >> 31) & (ix >> 30);
}
hidden_def (__isinff)
weak_alias (__isinff, isinff)
@@ -0,0 +1,44 @@
/* @(#)s_isnan.c 5.1 93/09/24 */
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: s_isnan.c,v 1.8 1995/05/10 20:47:36 jtc Exp $";
#endif
/*
* isnan(x) returns 1 is x is nan, else 0;
* no branching!
*/
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
int __isnan(double x)
#else
int __isnan(x)
double x;
#endif
{
int32_t hx,lx;
EXTRACT_WORDS(hx,lx,x);
hx &= 0x7fffffff;
hx |= (u_int32_t)(lx|(-lx))>>31;
hx = 0x7ff00000 - hx;
return (int)(((u_int32_t)hx)>>31);
}
hidden_def (__isnan)
weak_alias (__isnan, isnan)
#ifdef NO_LONG_DOUBLE
strong_alias (__isnan, __isnanl)
weak_alias (__isnan, isnanl)
#endif
@@ -0,0 +1,42 @@
/* s_isnanf.c -- float version of s_isnan.c.
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
*/
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: s_isnanf.c,v 1.4 1995/05/10 20:47:38 jtc Exp $";
#endif
/*
* isnanf(x) returns 1 is x is nan, else 0;
* no branching!
*/
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
int __isnanf(float x)
#else
int __isnanf(x)
float x;
#endif
{
int32_t ix;
GET_FLOAT_WORD(ix,x);
ix &= 0x7fffffff;
ix = 0x7f800000 - ix;
return (int)(((u_int32_t)(ix))>>31);
}
hidden_def (__isnanf)
weak_alias (__isnanf, isnanf)
@@ -0,0 +1,37 @@
/* @(#)s_ldexp.c 5.1 93/09/24 */
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: s_ldexp.c,v 1.6 1995/05/10 20:47:40 jtc Exp $";
#endif
#include "math.h"
#include "math_private.h"
#include <errno.h>
#ifdef __STDC__
double __ldexp(double value, int exp)
#else
double __ldexp(value, exp)
double value; int exp;
#endif
{
if(!__finite(value)||value==0.0) return value;
value = __scalbn(value,exp);
if(!__finite(value)||value==0.0) __set_errno (ERANGE);
return value;
}
weak_alias (__ldexp, ldexp)
#ifdef NO_LONG_DOUBLE
strong_alias (__ldexp, __ldexpl)
weak_alias (__ldexp, ldexpl)
#endif
@@ -0,0 +1,37 @@
/* s_ldexpf.c -- float version of s_ldexp.c.
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
*/
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: s_ldexpf.c,v 1.3 1995/05/10 20:47:42 jtc Exp $";
#endif
#include "math.h"
#include "math_private.h"
#include <errno.h>
#ifdef __STDC__
float __ldexpf(float value, int exp)
#else
float __ldexpf(value, exp)
float value; int exp;
#endif
{
if(!__finitef(value)||value==(float)0.0) return value;
value = __scalbnf(value,exp);
if(!__finitef(value)||value==(float)0.0) __set_errno (ERANGE);
return value;
}
INTDEF(__ldexpf)
weak_alias (__ldexpf, ldexpf)
@@ -0,0 +1,191 @@
/* @(#)s_log1p.c 5.1 93/09/24 */
/*
* ====================================================
* 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.
* ====================================================
*/
/* Modified by Naohiko Shimizu/Tokai University, Japan 1997/08/25,
for performance improvement on pipelined processors.
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: s_log1p.c,v 1.8 1995/05/10 20:47:46 jtc Exp $";
#endif
/* double log1p(double x)
*
* Method :
* 1. Argument Reduction: find k and f such that
* 1+x = 2^k * (1+f),
* where sqrt(2)/2 < 1+f < sqrt(2) .
*
* Note. If k=0, then f=x is exact. However, if k!=0, then f
* may not be representable exactly. In that case, a correction
* term is need. Let u=1+x rounded. Let c = (1+x)-u, then
* log(1+x) - log(u) ~ c/u. Thus, we proceed to compute log(u),
* and add back the correction term c/u.
* (Note: when x > 2**53, one can simply return log(x))
*
* 2. Approximation of log1p(f).
* Let s = f/(2+f) ; based on log(1+f) = log(1+s) - log(1-s)
* = 2s + 2/3 s**3 + 2/5 s**5 + .....,
* = 2s + s*R
* We use a special Reme algorithm on [0,0.1716] to generate
* a polynomial of degree 14 to approximate R The maximum error
* of this polynomial approximation is bounded by 2**-58.45. In
* other words,
* 2 4 6 8 10 12 14
* R(z) ~ Lp1*s +Lp2*s +Lp3*s +Lp4*s +Lp5*s +Lp6*s +Lp7*s
* (the values of Lp1 to Lp7 are listed in the program)
* and
* | 2 14 | -58.45
* | Lp1*s +...+Lp7*s - R(z) | <= 2
* | |
* Note that 2s = f - s*f = f - hfsq + s*hfsq, where hfsq = f*f/2.
* In order to guarantee error in log below 1ulp, we compute log
* by
* log1p(f) = f - (hfsq - s*(hfsq+R)).
*
* 3. Finally, log1p(x) = k*ln2 + log1p(f).
* = k*ln2_hi+(f-(hfsq-(s*(hfsq+R)+k*ln2_lo)))
* Here ln2 is split into two floating point number:
* ln2_hi + ln2_lo,
* where n*ln2_hi is always exact for |n| < 2000.
*
* Special cases:
* log1p(x) is NaN with signal if x < -1 (including -INF) ;
* log1p(+INF) is +INF; log1p(-1) is -INF with signal;
* log1p(NaN) is that NaN with no signal.
*
* Accuracy:
* according to an error analysis, the error is always less than
* 1 ulp (unit in the last place).
*
* Constants:
* The hexadecimal values are the intended ones for the following
* constants. The decimal values may be used, provided that the
* compiler will convert from decimal to binary accurately enough
* to produce the hexadecimal values shown.
*
* Note: Assuming log() return accurate answer, the following
* algorithm can be used to compute log1p(x) to within a few ULP:
*
* u = 1+x;
* if(u==1.0) return x ; else
* return log(u)*(x/(u-1.0));
*
* See HP-15C Advanced Functions Handbook, p.193.
*/
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const double
#else
static double
#endif
ln2_hi = 6.93147180369123816490e-01, /* 3fe62e42 fee00000 */
ln2_lo = 1.90821492927058770002e-10, /* 3dea39ef 35793c76 */
two54 = 1.80143985094819840000e+16, /* 43500000 00000000 */
Lp[] = {0.0, 6.666666666666735130e-01, /* 3FE55555 55555593 */
3.999999999940941908e-01, /* 3FD99999 9997FA04 */
2.857142874366239149e-01, /* 3FD24924 94229359 */
2.222219843214978396e-01, /* 3FCC71C5 1D8E78AF */
1.818357216161805012e-01, /* 3FC74664 96CB03DE */
1.531383769920937332e-01, /* 3FC39A09 D078C69F */
1.479819860511658591e-01}; /* 3FC2F112 DF3E5244 */
#ifdef __STDC__
static const double zero = 0.0;
#else
static double zero = 0.0;
#endif
#ifdef __STDC__
double __log1p(double x)
#else
double __log1p(x)
double x;
#endif
{
double hfsq,f,c,s,z,R,u,z2,z4,z6,R1,R2,R3,R4;
int32_t k,hx,hu,ax;
GET_HIGH_WORD(hx,x);
ax = hx&0x7fffffff;
k = 1;
if (hx < 0x3FDA827A) { /* x < 0.41422 */
if(ax>=0x3ff00000) { /* x <= -1.0 */
if(x==-1.0) return -two54/(x-x);/* log1p(-1)=+inf */
else return (x-x)/(x-x); /* log1p(x<-1)=NaN */
}
if(ax<0x3e200000) { /* |x| < 2**-29 */
if(two54+x>zero /* raise inexact */
&&ax<0x3c900000) /* |x| < 2**-54 */
return x;
else
return x - x*x*0.5;
}
if(hx>0||hx<=((int32_t)0xbfd2bec3)) {
k=0;f=x;hu=1;} /* -0.2929<x<0.41422 */
}
if (hx >= 0x7ff00000) return x+x;
if(k!=0) {
if(hx<0x43400000) {
u = 1.0+x;
GET_HIGH_WORD(hu,u);
k = (hu>>20)-1023;
c = (k>0)? 1.0-(u-x):x-(u-1.0);/* correction term */
c /= u;
} else {
u = x;
GET_HIGH_WORD(hu,u);
k = (hu>>20)-1023;
c = 0;
}
hu &= 0x000fffff;
if(hu<0x6a09e) {
SET_HIGH_WORD(u,hu|0x3ff00000); /* normalize u */
} else {
k += 1;
SET_HIGH_WORD(u,hu|0x3fe00000); /* normalize u/2 */
hu = (0x00100000-hu)>>2;
}
f = u-1.0;
}
hfsq=0.5*f*f;
if(hu==0) { /* |f| < 2**-20 */
if(f==zero) {
if(k==0) return zero;
else {c += k*ln2_lo; return k*ln2_hi+c;}
}
R = hfsq*(1.0-0.66666666666666666*f);
if(k==0) return f-R; else
return k*ln2_hi-((R-(k*ln2_lo+c))-f);
}
s = f/(2.0+f);
z = s*s;
#ifdef DO_NOT_USE_THIS
R = z*(Lp1+z*(Lp2+z*(Lp3+z*(Lp4+z*(Lp5+z*(Lp6+z*Lp7))))));
#else
R1 = z*Lp[1]; z2=z*z;
R2 = Lp[2]+z*Lp[3]; z4=z2*z2;
R3 = Lp[4]+z*Lp[5]; z6=z4*z2;
R4 = Lp[6]+z*Lp[7];
R = R1 + z2*R2 + z4*R3 + z6*R4;
#endif
if(k==0) return f-(hfsq-s*(hfsq+R)); else
return k*ln2_hi-((hfsq-(s*(hfsq+R)+(k*ln2_lo+c)))-f);
}
weak_alias (__log1p, log1p)
#ifdef NO_LONG_DOUBLE
strong_alias (__log1p, __log1pl)
weak_alias (__log1p, log1pl)
#endif
@@ -0,0 +1,115 @@
/* s_log1pf.c -- float version of s_log1p.c.
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
*/
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: s_log1pf.c,v 1.4 1995/05/10 20:47:48 jtc Exp $";
#endif
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const float
#else
static float
#endif
ln2_hi = 6.9313812256e-01, /* 0x3f317180 */
ln2_lo = 9.0580006145e-06, /* 0x3717f7d1 */
two25 = 3.355443200e+07, /* 0x4c000000 */
Lp1 = 6.6666668653e-01, /* 3F2AAAAB */
Lp2 = 4.0000000596e-01, /* 3ECCCCCD */
Lp3 = 2.8571429849e-01, /* 3E924925 */
Lp4 = 2.2222198546e-01, /* 3E638E29 */
Lp5 = 1.8183572590e-01, /* 3E3A3325 */
Lp6 = 1.5313838422e-01, /* 3E1CD04F */
Lp7 = 1.4798198640e-01; /* 3E178897 */
#ifdef __STDC__
static const float zero = 0.0;
#else
static float zero = 0.0;
#endif
#ifdef __STDC__
float __log1pf(float x)
#else
float __log1pf(x)
float x;
#endif
{
float hfsq,f,c,s,z,R,u;
int32_t k,hx,hu,ax;
GET_FLOAT_WORD(hx,x);
ax = hx&0x7fffffff;
k = 1;
if (hx < 0x3ed413d7) { /* x < 0.41422 */
if(ax>=0x3f800000) { /* x <= -1.0 */
if(x==(float)-1.0) return -two25/(x-x); /* log1p(-1)=+inf */
else return (x-x)/(x-x); /* log1p(x<-1)=NaN */
}
if(ax<0x31000000) { /* |x| < 2**-29 */
if(two25+x>zero /* raise inexact */
&&ax<0x24800000) /* |x| < 2**-54 */
return x;
else
return x - x*x*(float)0.5;
}
if(hx>0||hx<=((int32_t)0xbe95f61f)) {
k=0;f=x;hu=1;} /* -0.2929<x<0.41422 */
}
if (hx >= 0x7f800000) return x+x;
if(k!=0) {
if(hx<0x5a000000) {
u = (float)1.0+x;
GET_FLOAT_WORD(hu,u);
k = (hu>>23)-127;
/* correction term */
c = (k>0)? (float)1.0-(u-x):x-(u-(float)1.0);
c /= u;
} else {
u = x;
GET_FLOAT_WORD(hu,u);
k = (hu>>23)-127;
c = 0;
}
hu &= 0x007fffff;
if(hu<0x3504f7) {
SET_FLOAT_WORD(u,hu|0x3f800000);/* normalize u */
} else {
k += 1;
SET_FLOAT_WORD(u,hu|0x3f000000); /* normalize u/2 */
hu = (0x00800000-hu)>>2;
}
f = u-(float)1.0;
}
hfsq=(float)0.5*f*f;
if(hu==0) { /* |f| < 2**-20 */
if(f==zero) {
if(k==0) return zero;
else {c += k*ln2_lo; return k*ln2_hi+c;}
}
R = hfsq*((float)1.0-(float)0.66666666666666666*f);
if(k==0) return f-R; else
return k*ln2_hi-((R-(k*ln2_lo+c))-f);
}
s = f/((float)2.0+f);
z = s*s;
R = z*(Lp1+z*(Lp2+z*(Lp3+z*(Lp4+z*(Lp5+z*(Lp6+z*Lp7))))));
if(k==0) return f-(hfsq-s*(hfsq+R)); else
return k*ln2_hi-((hfsq-(s*(hfsq+R)+(k*ln2_lo+c)))-f);
}
weak_alias (__log1pf, log1pf)
@@ -1,88 +0,0 @@
/* s_modfl.c -- long double version of s_modf.c.
* Conversion to IEEE quad long double by Jakub Jelinek, [email protected].
*/
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: $";
#endif
/*
* modfl(long double x, long double *iptr)
* return fraction part of x, and return x's integral part in *iptr.
* Method:
* Bit twiddling.
*
* Exception:
* No exception.
*/
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const long double one = 1.0;
#else
static long double one = 1.0;
#endif
#ifdef __STDC__
long double __modfl(long double x, long double *iptr)
#else
long double __modfl(x, iptr)
long double x,*iptr;
#endif
{
int64_t i0,i1,j0;
u_int64_t i;
GET_LDOUBLE_WORDS64(i0,i1,x);
j0 = ((i0>>48)&0x7fff)-0x3fff; /* exponent of x */
if(j0<48) { /* integer part in high x */
if(j0<0) { /* |x|<1 */
/* *iptr = +-0 */
SET_LDOUBLE_WORDS64(*iptr,i0&0x8000000000000000ULL,0);
return x;
} else {
i = (0x0000ffffffffffffLL)>>j0;
if(((i0&i)|i1)==0) { /* x is integral */
*iptr = x;
/* return +-0 */
SET_LDOUBLE_WORDS64(x,i0&0x8000000000000000ULL,0);
return x;
} else {
SET_LDOUBLE_WORDS64(*iptr,i0&(~i),0);
return x - *iptr;
}
}
} else if (j0>111) { /* no fraction part */
*iptr = x*one;
/* We must handle NaNs separately. */
if (j0 == 0x4000 && ((i0 & 0x0000ffffffffffffLL) | i1))
return x*one;
/* return +-0 */
SET_LDOUBLE_WORDS64(x,i0&0x8000000000000000ULL,0);
return x;
} else { /* fraction part in low x */
i = -1ULL>>(j0-48);
if((i1&i)==0) { /* x is integral */
*iptr = x;
/* return +-0 */
SET_LDOUBLE_WORDS64(x,i0&0x8000000000000000ULL,0);
return x;
} else {
SET_LDOUBLE_WORDS64(*iptr,i0,i1&(~i));
return x - *iptr;
}
}
}
weak_alias (__modfl, modfl)
@@ -0,0 +1,44 @@
/* Return quiet nan.
Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <[email protected]>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ieee754.h>
double
__nan (const char *tagp)
{
if (tagp[0] != '\0')
{
char buf[6 + strlen (tagp)];
sprintf (buf, "NAN(%s)", tagp);
return strtod (buf, NULL);
}
return NAN;
}
weak_alias (__nan, nan)
#ifdef NO_LONG_DOUBLE
strong_alias (__nan, __nanl)
weak_alias (__nan, nanl)
#endif
@@ -0,0 +1,40 @@
/* Return quiet nan.
Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <[email protected]>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ieee754.h>
float
__nanf (const char *tagp)
{
if (tagp[0] != '\0')
{
char buf[6 + strlen (tagp)];
sprintf (buf, "NAN(%s)", tagp);
return strtof (buf, NULL);
}
return NAN;
}
weak_alias (__nanf, nanf)
@@ -0,0 +1,97 @@
/* Round double to integer away from zero.
Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <[email protected]>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <math.h>
#include "math_private.h"
static const double huge = 1.0e300;
double
__round (double x)
{
int32_t i0, j0;
u_int32_t i1;
EXTRACT_WORDS (i0, i1, x);
j0 = ((i0 >> 20) & 0x7ff) - 0x3ff;
if (j0 < 20)
{
if (j0 < 0)
{
if (huge + x > 0.0)
{
i0 &= 0x80000000;
if (j0 == -1)
i0 |= 0x3ff00000;
i1 = 0;
}
}
else
{
u_int32_t i = 0x000fffff >> j0;
if (((i0 & i) | i1) == 0)
/* X is integral. */
return x;
if (huge + x > 0.0)
{
/* Raise inexact if x != 0. */
i0 += 0x00080000 >> j0;
i0 &= ~i;
i1 = 0;
}
}
}
else if (j0 > 51)
{
if (j0 == 0x400)
/* Inf or NaN. */
return x + x;
else
return x;
}
else
{
u_int32_t i = 0xffffffff >> (j0 - 20);
if ((i1 & i) == 0)
/* X is integral. */
return x;
if (huge + x > 0.0)
{
/* Raise inexact if x != 0. */
u_int32_t j = i1 + (1 << (51 - j0));
if (j < i1)
i0 += 1;
i1 = j;
}
i1 &= ~i;
}
INSERT_WORDS (x, i0, i1);
return x;
}
weak_alias (__round, round)
#ifdef NO_LONG_DOUBLE
strong_alias (__round, __roundl)
weak_alias (__round, roundl)
#endif
@@ -0,0 +1,73 @@
/* Round float to integer away from zero.
Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <[email protected]>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <math.h>
#include "math_private.h"
static const float huge = 1.0e30;
float
__roundf (float x)
{
int32_t i0, j0;
GET_FLOAT_WORD (i0, x);
j0 = ((i0 >> 23) & 0xff) - 0x7f;
if (j0 < 23)
{
if (j0 < 0)
{
if (huge + x > 0.0F)
{
i0 &= 0x80000000;
if (j0 == -1)
i0 |= 0x3f800000;
}
}
else
{
u_int32_t i = 0x007fffff >> j0;
if ((i0 & i) == 0)
/* X is integral. */
return x;
if (huge + x > 0.0F)
{
/* Raise inexact if x != 0. */
i0 += 0x00400000 >> j0;
i0 &= ~i;
}
}
}
else
{
if (j0 == 0x80)
/* Inf or NaN. */
return x + x;
else
return x;
}
SET_FLOAT_WORD (x, i0);
return x;
}
weak_alias (__roundf, roundf)
@@ -1,8 +1,7 @@
/* Return classification value corresponding to argument.
Copyright (C) 1997, 1999, 2002 Free Software Foundation, Inc.
/* Return nonzero value if number is negative.
Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997 and
Jakub Jelinek <jj@ultra.linux.cz>, 1999.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -23,23 +22,11 @@
#include "math_private.h"
int
__fpclassifyl (long double x)
__signbit (double x)
{
u_int64_t hx, lx;
int retval = FP_NORMAL;
int32_t hx;
GET_LDOUBLE_WORDS64 (hx, lx, x);
lx |= (hx & 0x0000ffffffffffffLL);
hx &= 0x7fff000000000000LL;
if ((hx | lx) == 0)
retval = FP_ZERO;
else if (hx == 0)
retval = FP_SUBNORMAL;
else if (hx == 0x7fff000000000000LL)
retval = lx != 0 ? FP_NAN : FP_INFINITE;
return retval;
GET_HIGH_WORD (hx, x);
return hx & 0x80000000;
}
libm_hidden_def (__fpclassifyl)
@@ -0,0 +1,32 @@
/* Return nonzero value if number is negative.
Copyright (C) 1997 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <[email protected]>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <math.h>
#include "math_private.h"
int
__signbitf (float x)
{
int32_t hx;
GET_FLOAT_WORD (hx, x);
return hx & 0x80000000;
}
@@ -0,0 +1,3 @@
#include "math.h"
#include "math_private.h"
int signgam;
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,51 @@
/* Compute sine and cosine of argument.
Copyright (C) 1997, 2001 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <[email protected]>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <math.h>
#include "math_private.h"
void
__sincos (double x, double *sinx, double *cosx)
{
int32_t ix;
/* High word of x. */
GET_HIGH_WORD (ix, x);
/* |x| ~< pi/4 */
ix &= 0x7fffffff;
if (ix>=0x7ff00000)
{
/* sin(Inf or NaN) is NaN */
*sinx = *cosx = x - x;
}
else
{
*sinx = sin (x);
*cosx = cos (x);
}
}
weak_alias (__sincos, sincos)
#ifdef NO_LONG_DOUBLE
strong_alias (__sincos, __sincosl)
weak_alias (__sincos, sincosl)
#endif
@@ -0,0 +1,74 @@
/* Compute sine and cosine of argument.
Copyright (C) 1997, 2000 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <[email protected]>, 1997.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <math.h>
#include "math_private.h"
void
__sincosf (float x, float *sinx, float *cosx)
{
int32_t ix;
/* High word of x. */
GET_FLOAT_WORD (ix, x);
/* |x| ~< pi/4 */
ix &= 0x7fffffff;
if (ix <= 0x3f490fd8)
{
*sinx = __kernel_sinf (x, 0.0, 0);
*cosx = __kernel_cosf (x, 0.0);
}
else if (ix>=0x7f800000)
{
/* sin(Inf or NaN) is NaN */
*sinx = *cosx = x - x;
}
else
{
/* Argument reduction needed. */
float y[2];
int n;
n = __ieee754_rem_pio2f (x, y);
switch (n & 3)
{
case 0:
*sinx = __kernel_sinf (y[0], y[1], 1);
*cosx = __kernel_cosf (y[0], y[1]);
break;
case 1:
*sinx = __kernel_cosf (y[0], y[1]);
*cosx = -__kernel_sinf (y[0], y[1], 1);
break;
case 2:
*sinx = -__kernel_sinf (y[0], y[1], 1);
*cosx = -__kernel_cosf (y[0], y[1]);
break;
default:
*sinx = -__kernel_cosf (y[0], y[1]);
*cosx = __kernel_sinf (y[0], y[1], 1);
break;
}
}
}
weak_alias (__sincosf, sincosf)
@@ -0,0 +1,54 @@
/* s_sinf.c -- float version of s_sin.c.
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
*/
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: s_sinf.c,v 1.4 1995/05/10 20:48:16 jtc Exp $";
#endif
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
float __sinf(float x)
#else
float __sinf(x)
float x;
#endif
{
float y[2],z=0.0;
int32_t n, ix;
GET_FLOAT_WORD(ix,x);
/* |x| ~< pi/4 */
ix &= 0x7fffffff;
if(ix <= 0x3f490fd8) return __kernel_sinf(x,z,0);
/* sin(Inf or NaN) is NaN */
else if (ix>=0x7f800000) return x-x;
/* argument reduction needed */
else {
n = __ieee754_rem_pio2f(x,y);
switch(n&3) {
case 0: return __kernel_sinf(y[0],y[1],1);
case 1: return __kernel_cosf(y[0],y[1]);
case 2: return -__kernel_sinf(y[0],y[1],1);
default:
return -__kernel_cosf(y[0],y[1]);
}
}
}
weak_alias (__sinf, sinf)
@@ -0,0 +1,486 @@
/*
* IBM Accurate Mathematical Library
* written by International Business Machines Corp.
* Copyright (C) 2001 Free Software Foundation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*********************************************************************/
/* MODULE_NAME: utan.c */
/* */
/* FUNCTIONS: utan */
/* tanMp */
/* */
/* FILES NEEDED:dla.h endian.h mpa.h mydefs.h utan.h */
/* branred.c sincos32.c mptan.c */
/* utan.tbl */
/* */
/* An ultimate tan routine. Given an IEEE double machine number x */
/* it computes the correctly rounded (to nearest) value of tan(x). */
/* Assumption: Machine arithmetic operations are performed in */
/* round to nearest mode of IEEE 754 standard. */
/* */
/*********************************************************************/
#include "endian.h"
#include "dla.h"
#include "mpa.h"
#include "MathLib.h"
#include "math.h"
static double tanMp(double);
void __mptan(double, mp_no *, int);
double tan(double x) {
#include "utan.h"
#include "utan.tbl"
int ux,i,n;
double a,da,a2,b,db,c,dc,c1,cc1,c2,cc2,c3,cc3,fi,ffi,gi,pz,s,sy,
t,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,w,x2,xn,xx2,y,ya,yya,z0,z,zz,z2,zz2;
int p;
number num,v;
mp_no mpa,mpt1,mpt2;
#if 0
mp_no mpy;
#endif
int __branred(double, double *, double *);
int __mpranred(double, mp_no *, int);
/* x=+-INF, x=NaN */
num.d = x; ux = num.i[HIGH_HALF];
if ((ux&0x7ff00000)==0x7ff00000) return x-x;
w=(x<ZERO) ? -x : x;
/* (I) The case abs(x) <= 1.259e-8 */
if (w<=g1.d) return x;
/* (II) The case 1.259e-8 < abs(x) <= 0.0608 */
if (w<=g2.d) {
/* First stage */
x2 = x*x;
t2 = x*x2*(d3.d+x2*(d5.d+x2*(d7.d+x2*(d9.d+x2*d11.d))));
if ((y=x+(t2-u1.d*t2)) == x+(t2+u1.d*t2)) return y;
/* Second stage */
c1 = x2*(a15.d+x2*(a17.d+x2*(a19.d+x2*(a21.d+x2*(a23.d+x2*(a25.d+
x2*a27.d))))));
EMULV(x,x,x2,xx2,t1,t2,t3,t4,t5)
ADD2(a13.d,aa13.d,c1,zero.d,c2,cc2,t1,t2)
MUL2(x2,xx2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(a11.d,aa11.d,c1,cc1,c2,cc2,t1,t2)
MUL2(x2,xx2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(a9.d ,aa9.d ,c1,cc1,c2,cc2,t1,t2)
MUL2(x2,xx2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(a7.d ,aa7.d ,c1,cc1,c2,cc2,t1,t2)
MUL2(x2,xx2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(a5.d ,aa5.d ,c1,cc1,c2,cc2,t1,t2)
MUL2(x2,xx2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(a3.d ,aa3.d ,c1,cc1,c2,cc2,t1,t2)
MUL2(x2,xx2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
MUL2(x ,zero.d,c1,cc1,c2,cc2,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(x ,zero.d,c2,cc2,c1,cc1,t1,t2)
if ((y=c1+(cc1-u2.d*c1)) == c1+(cc1+u2.d*c1)) return y;
return tanMp(x);
}
/* (III) The case 0.0608 < abs(x) <= 0.787 */
if (w<=g3.d) {
/* First stage */
i = ((int) (mfftnhf.d+TWO8*w));
z = w-xfg[i][0].d; z2 = z*z; s = (x<ZERO) ? MONE : ONE;
pz = z+z*z2*(e0.d+z2*e1.d);
fi = xfg[i][1].d; gi = xfg[i][2].d; t2 = pz*(gi+fi)/(gi-pz);
if ((y=fi+(t2-fi*u3.d))==fi+(t2+fi*u3.d)) return (s*y);
t3 = (t2<ZERO) ? -t2 : t2;
if ((y=fi+(t2-(t4=fi*ua3.d+t3*ub3.d)))==fi+(t2+t4)) return (s*y);
/* Second stage */
ffi = xfg[i][3].d;
c1 = z2*(a7.d+z2*(a9.d+z2*a11.d));
EMULV(z,z,z2,zz2,t1,t2,t3,t4,t5)
ADD2(a5.d,aa5.d,c1,zero.d,c2,cc2,t1,t2)
MUL2(z2,zz2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(a3.d,aa3.d,c1,cc1,c2,cc2,t1,t2)
MUL2(z2,zz2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
MUL2(z ,zero.d,c1,cc1,c2,cc2,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(z ,zero.d,c2,cc2,c1,cc1,t1,t2)
ADD2(fi ,ffi,c1,cc1,c2,cc2,t1,t2)
MUL2(fi ,ffi,c1,cc1,c3,cc3,t1,t2,t3,t4,t5,t6,t7,t8)
SUB2(one.d,zero.d,c3,cc3,c1,cc1,t1,t2)
DIV2(c2,cc2,c1,cc1,c3,cc3,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10)
if ((y=c3+(cc3-u4.d*c3))==c3+(cc3+u4.d*c3)) return (s*y);
return tanMp(x);
}
/* (---) The case 0.787 < abs(x) <= 25 */
if (w<=g4.d) {
/* Range reduction by algorithm i */
t = (x*hpinv.d + toint.d);
xn = t - toint.d;
v.d = t;
t1 = (x - xn*mp1.d) - xn*mp2.d;
n =v.i[LOW_HALF] & 0x00000001;
da = xn*mp3.d;
a=t1-da;
da = (t1-a)-da;
if (a<ZERO) {ya=-a; yya=-da; sy=MONE;}
else {ya= a; yya= da; sy= ONE;}
/* (IV),(V) The case 0.787 < abs(x) <= 25, abs(y) <= 1e-7 */
if (ya<=gy1.d) return tanMp(x);
/* (VI) The case 0.787 < abs(x) <= 25, 1e-7 < abs(y) <= 0.0608 */
if (ya<=gy2.d) {
a2 = a*a;
t2 = da+a*a2*(d3.d+a2*(d5.d+a2*(d7.d+a2*(d9.d+a2*d11.d))));
if (n) {
/* First stage -cot */
EADD(a,t2,b,db)
DIV2(one.d,zero.d,b,db,c,dc,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10)
if ((y=c+(dc-u6.d*c))==c+(dc+u6.d*c)) return (-y); }
else {
/* First stage tan */
if ((y=a+(t2-u5.d*a))==a+(t2+u5.d*a)) return y; }
/* Second stage */
/* Range reduction by algorithm ii */
t = (x*hpinv.d + toint.d);
xn = t - toint.d;
v.d = t;
t1 = (x - xn*mp1.d) - xn*mp2.d;
n =v.i[LOW_HALF] & 0x00000001;
da = xn*pp3.d;
t=t1-da;
da = (t1-t)-da;
t1 = xn*pp4.d;
a = t - t1;
da = ((t-a)-t1)+da;
/* Second stage */
EADD(a,da,t1,t2) a=t1; da=t2;
MUL2(a,da,a,da,x2,xx2,t1,t2,t3,t4,t5,t6,t7,t8)
c1 = x2*(a15.d+x2*(a17.d+x2*(a19.d+x2*(a21.d+x2*(a23.d+x2*(a25.d+
x2*a27.d))))));
ADD2(a13.d,aa13.d,c1,zero.d,c2,cc2,t1,t2)
MUL2(x2,xx2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(a11.d,aa11.d,c1,cc1,c2,cc2,t1,t2)
MUL2(x2,xx2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(a9.d ,aa9.d ,c1,cc1,c2,cc2,t1,t2)
MUL2(x2,xx2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(a7.d ,aa7.d ,c1,cc1,c2,cc2,t1,t2)
MUL2(x2,xx2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(a5.d ,aa5.d ,c1,cc1,c2,cc2,t1,t2)
MUL2(x2,xx2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(a3.d ,aa3.d ,c1,cc1,c2,cc2,t1,t2)
MUL2(x2,xx2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
MUL2(a ,da ,c1,cc1,c2,cc2,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(a ,da ,c2,cc2,c1,cc1,t1,t2)
if (n) {
/* Second stage -cot */
DIV2(one.d,zero.d,c1,cc1,c2,cc2,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10)
if ((y=c2+(cc2-u8.d*c2)) == c2+(cc2+u8.d*c2)) return (-y); }
else {
/* Second stage tan */
if ((y=c1+(cc1-u7.d*c1)) == c1+(cc1+u7.d*c1)) return y; }
return tanMp(x);
}
/* (VII) The case 0.787 < abs(x) <= 25, 0.0608 < abs(y) <= 0.787 */
/* First stage */
i = ((int) (mfftnhf.d+TWO8*ya));
z = (z0=(ya-xfg[i][0].d))+yya; z2 = z*z;
pz = z+z*z2*(e0.d+z2*e1.d);
fi = xfg[i][1].d; gi = xfg[i][2].d;
if (n) {
/* -cot */
t2 = pz*(fi+gi)/(fi+pz);
if ((y=gi-(t2-gi*u10.d))==gi-(t2+gi*u10.d)) return (-sy*y);
t3 = (t2<ZERO) ? -t2 : t2;
if ((y=gi-(t2-(t4=gi*ua10.d+t3*ub10.d)))==gi-(t2+t4)) return (-sy*y); }
else {
/* tan */
t2 = pz*(gi+fi)/(gi-pz);
if ((y=fi+(t2-fi*u9.d))==fi+(t2+fi*u9.d)) return (sy*y);
t3 = (t2<ZERO) ? -t2 : t2;
if ((y=fi+(t2-(t4=fi*ua9.d+t3*ub9.d)))==fi+(t2+t4)) return (sy*y); }
/* Second stage */
ffi = xfg[i][3].d;
EADD(z0,yya,z,zz)
MUL2(z,zz,z,zz,z2,zz2,t1,t2,t3,t4,t5,t6,t7,t8)
c1 = z2*(a7.d+z2*(a9.d+z2*a11.d));
ADD2(a5.d,aa5.d,c1,zero.d,c2,cc2,t1,t2)
MUL2(z2,zz2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(a3.d,aa3.d,c1,cc1,c2,cc2,t1,t2)
MUL2(z2,zz2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
MUL2(z ,zz ,c1,cc1,c2,cc2,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(z ,zz ,c2,cc2,c1,cc1,t1,t2)
ADD2(fi ,ffi,c1,cc1,c2,cc2,t1,t2)
MUL2(fi ,ffi,c1,cc1,c3,cc3,t1,t2,t3,t4,t5,t6,t7,t8)
SUB2(one.d,zero.d,c3,cc3,c1,cc1,t1,t2)
if (n) {
/* -cot */
DIV2(c1,cc1,c2,cc2,c3,cc3,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10)
if ((y=c3+(cc3-u12.d*c3))==c3+(cc3+u12.d*c3)) return (-sy*y); }
else {
/* tan */
DIV2(c2,cc2,c1,cc1,c3,cc3,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10)
if ((y=c3+(cc3-u11.d*c3))==c3+(cc3+u11.d*c3)) return (sy*y); }
return tanMp(x);
}
/* (---) The case 25 < abs(x) <= 1e8 */
if (w<=g5.d) {
/* Range reduction by algorithm ii */
t = (x*hpinv.d + toint.d);
xn = t - toint.d;
v.d = t;
t1 = (x - xn*mp1.d) - xn*mp2.d;
n =v.i[LOW_HALF] & 0x00000001;
da = xn*pp3.d;
t=t1-da;
da = (t1-t)-da;
t1 = xn*pp4.d;
a = t - t1;
da = ((t-a)-t1)+da;
EADD(a,da,t1,t2) a=t1; da=t2;
if (a<ZERO) {ya=-a; yya=-da; sy=MONE;}
else {ya= a; yya= da; sy= ONE;}
/* (+++) The case 25 < abs(x) <= 1e8, abs(y) <= 1e-7 */
if (ya<=gy1.d) return tanMp(x);
/* (VIII) The case 25 < abs(x) <= 1e8, 1e-7 < abs(y) <= 0.0608 */
if (ya<=gy2.d) {
a2 = a*a;
t2 = da+a*a2*(d3.d+a2*(d5.d+a2*(d7.d+a2*(d9.d+a2*d11.d))));
if (n) {
/* First stage -cot */
EADD(a,t2,b,db)
DIV2(one.d,zero.d,b,db,c,dc,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10)
if ((y=c+(dc-u14.d*c))==c+(dc+u14.d*c)) return (-y); }
else {
/* First stage tan */
if ((y=a+(t2-u13.d*a))==a+(t2+u13.d*a)) return y; }
/* Second stage */
MUL2(a,da,a,da,x2,xx2,t1,t2,t3,t4,t5,t6,t7,t8)
c1 = x2*(a15.d+x2*(a17.d+x2*(a19.d+x2*(a21.d+x2*(a23.d+x2*(a25.d+
x2*a27.d))))));
ADD2(a13.d,aa13.d,c1,zero.d,c2,cc2,t1,t2)
MUL2(x2,xx2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(a11.d,aa11.d,c1,cc1,c2,cc2,t1,t2)
MUL2(x2,xx2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(a9.d ,aa9.d ,c1,cc1,c2,cc2,t1,t2)
MUL2(x2,xx2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(a7.d ,aa7.d ,c1,cc1,c2,cc2,t1,t2)
MUL2(x2,xx2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(a5.d ,aa5.d ,c1,cc1,c2,cc2,t1,t2)
MUL2(x2,xx2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(a3.d ,aa3.d ,c1,cc1,c2,cc2,t1,t2)
MUL2(x2,xx2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
MUL2(a ,da ,c1,cc1,c2,cc2,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(a ,da ,c2,cc2,c1,cc1,t1,t2)
if (n) {
/* Second stage -cot */
DIV2(one.d,zero.d,c1,cc1,c2,cc2,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10)
if ((y=c2+(cc2-u16.d*c2)) == c2+(cc2+u16.d*c2)) return (-y); }
else {
/* Second stage tan */
if ((y=c1+(cc1-u15.d*c1)) == c1+(cc1+u15.d*c1)) return (y); }
return tanMp(x);
}
/* (IX) The case 25 < abs(x) <= 1e8, 0.0608 < abs(y) <= 0.787 */
/* First stage */
i = ((int) (mfftnhf.d+TWO8*ya));
z = (z0=(ya-xfg[i][0].d))+yya; z2 = z*z;
pz = z+z*z2*(e0.d+z2*e1.d);
fi = xfg[i][1].d; gi = xfg[i][2].d;
if (n) {
/* -cot */
t2 = pz*(fi+gi)/(fi+pz);
if ((y=gi-(t2-gi*u18.d))==gi-(t2+gi*u18.d)) return (-sy*y);
t3 = (t2<ZERO) ? -t2 : t2;
if ((y=gi-(t2-(t4=gi*ua18.d+t3*ub18.d)))==gi-(t2+t4)) return (-sy*y); }
else {
/* tan */
t2 = pz*(gi+fi)/(gi-pz);
if ((y=fi+(t2-fi*u17.d))==fi+(t2+fi*u17.d)) return (sy*y);
t3 = (t2<ZERO) ? -t2 : t2;
if ((y=fi+(t2-(t4=fi*ua17.d+t3*ub17.d)))==fi+(t2+t4)) return (sy*y); }
/* Second stage */
ffi = xfg[i][3].d;
EADD(z0,yya,z,zz)
MUL2(z,zz,z,zz,z2,zz2,t1,t2,t3,t4,t5,t6,t7,t8)
c1 = z2*(a7.d+z2*(a9.d+z2*a11.d));
ADD2(a5.d,aa5.d,c1,zero.d,c2,cc2,t1,t2)
MUL2(z2,zz2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(a3.d,aa3.d,c1,cc1,c2,cc2,t1,t2)
MUL2(z2,zz2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
MUL2(z ,zz ,c1,cc1,c2,cc2,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(z ,zz ,c2,cc2,c1,cc1,t1,t2)
ADD2(fi ,ffi,c1,cc1,c2,cc2,t1,t2)
MUL2(fi ,ffi,c1,cc1,c3,cc3,t1,t2,t3,t4,t5,t6,t7,t8)
SUB2(one.d,zero.d,c3,cc3,c1,cc1,t1,t2)
if (n) {
/* -cot */
DIV2(c1,cc1,c2,cc2,c3,cc3,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10)
if ((y=c3+(cc3-u20.d*c3))==c3+(cc3+u20.d*c3)) return (-sy*y); }
else {
/* tan */
DIV2(c2,cc2,c1,cc1,c3,cc3,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10)
if ((y=c3+(cc3-u19.d*c3))==c3+(cc3+u19.d*c3)) return (sy*y); }
return tanMp(x);
}
/* (---) The case 1e8 < abs(x) < 2**1024 */
/* Range reduction by algorithm iii */
n = (__branred(x,&a,&da)) & 0x00000001;
EADD(a,da,t1,t2) a=t1; da=t2;
if (a<ZERO) {ya=-a; yya=-da; sy=MONE;}
else {ya= a; yya= da; sy= ONE;}
/* (+++) The case 1e8 < abs(x) < 2**1024, abs(y) <= 1e-7 */
if (ya<=gy1.d) return tanMp(x);
/* (X) The case 1e8 < abs(x) < 2**1024, 1e-7 < abs(y) <= 0.0608 */
if (ya<=gy2.d) {
a2 = a*a;
t2 = da+a*a2*(d3.d+a2*(d5.d+a2*(d7.d+a2*(d9.d+a2*d11.d))));
if (n) {
/* First stage -cot */
EADD(a,t2,b,db)
DIV2(one.d,zero.d,b,db,c,dc,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10)
if ((y=c+(dc-u22.d*c))==c+(dc+u22.d*c)) return (-y); }
else {
/* First stage tan */
if ((y=a+(t2-u21.d*a))==a+(t2+u21.d*a)) return y; }
/* Second stage */
/* Reduction by algorithm iv */
p=10; n = (__mpranred(x,&mpa,p)) & 0x00000001;
__mp_dbl(&mpa,&a,p); __dbl_mp(a,&mpt1,p);
__sub(&mpa,&mpt1,&mpt2,p); __mp_dbl(&mpt2,&da,p);
MUL2(a,da,a,da,x2,xx2,t1,t2,t3,t4,t5,t6,t7,t8)
c1 = x2*(a15.d+x2*(a17.d+x2*(a19.d+x2*(a21.d+x2*(a23.d+x2*(a25.d+
x2*a27.d))))));
ADD2(a13.d,aa13.d,c1,zero.d,c2,cc2,t1,t2)
MUL2(x2,xx2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(a11.d,aa11.d,c1,cc1,c2,cc2,t1,t2)
MUL2(x2,xx2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(a9.d ,aa9.d ,c1,cc1,c2,cc2,t1,t2)
MUL2(x2,xx2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(a7.d ,aa7.d ,c1,cc1,c2,cc2,t1,t2)
MUL2(x2,xx2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(a5.d ,aa5.d ,c1,cc1,c2,cc2,t1,t2)
MUL2(x2,xx2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(a3.d ,aa3.d ,c1,cc1,c2,cc2,t1,t2)
MUL2(x2,xx2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
MUL2(a ,da ,c1,cc1,c2,cc2,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(a ,da ,c2,cc2,c1,cc1,t1,t2)
if (n) {
/* Second stage -cot */
DIV2(one.d,zero.d,c1,cc1,c2,cc2,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10)
if ((y=c2+(cc2-u24.d*c2)) == c2+(cc2+u24.d*c2)) return (-y); }
else {
/* Second stage tan */
if ((y=c1+(cc1-u23.d*c1)) == c1+(cc1+u23.d*c1)) return y; }
return tanMp(x);
}
/* (XI) The case 1e8 < abs(x) < 2**1024, 0.0608 < abs(y) <= 0.787 */
/* First stage */
i = ((int) (mfftnhf.d+TWO8*ya));
z = (z0=(ya-xfg[i][0].d))+yya; z2 = z*z;
pz = z+z*z2*(e0.d+z2*e1.d);
fi = xfg[i][1].d; gi = xfg[i][2].d;
if (n) {
/* -cot */
t2 = pz*(fi+gi)/(fi+pz);
if ((y=gi-(t2-gi*u26.d))==gi-(t2+gi*u26.d)) return (-sy*y);
t3 = (t2<ZERO) ? -t2 : t2;
if ((y=gi-(t2-(t4=gi*ua26.d+t3*ub26.d)))==gi-(t2+t4)) return (-sy*y); }
else {
/* tan */
t2 = pz*(gi+fi)/(gi-pz);
if ((y=fi+(t2-fi*u25.d))==fi+(t2+fi*u25.d)) return (sy*y);
t3 = (t2<ZERO) ? -t2 : t2;
if ((y=fi+(t2-(t4=fi*ua25.d+t3*ub25.d)))==fi+(t2+t4)) return (sy*y); }
/* Second stage */
ffi = xfg[i][3].d;
EADD(z0,yya,z,zz)
MUL2(z,zz,z,zz,z2,zz2,t1,t2,t3,t4,t5,t6,t7,t8)
c1 = z2*(a7.d+z2*(a9.d+z2*a11.d));
ADD2(a5.d,aa5.d,c1,zero.d,c2,cc2,t1,t2)
MUL2(z2,zz2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(a3.d,aa3.d,c1,cc1,c2,cc2,t1,t2)
MUL2(z2,zz2,c2,cc2,c1,cc1,t1,t2,t3,t4,t5,t6,t7,t8)
MUL2(z ,zz ,c1,cc1,c2,cc2,t1,t2,t3,t4,t5,t6,t7,t8)
ADD2(z ,zz ,c2,cc2,c1,cc1,t1,t2)
ADD2(fi ,ffi,c1,cc1,c2,cc2,t1,t2)
MUL2(fi ,ffi,c1,cc1,c3,cc3,t1,t2,t3,t4,t5,t6,t7,t8)
SUB2(one.d,zero.d,c3,cc3,c1,cc1,t1,t2)
if (n) {
/* -cot */
DIV2(c1,cc1,c2,cc2,c3,cc3,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10)
if ((y=c3+(cc3-u28.d*c3))==c3+(cc3+u28.d*c3)) return (-sy*y); }
else {
/* tan */
DIV2(c2,cc2,c1,cc1,c3,cc3,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10)
if ((y=c3+(cc3-u27.d*c3))==c3+(cc3+u27.d*c3)) return (sy*y); }
return tanMp(x);
}
/* multiple precision stage */
/* Convert x to multi precision number,compute tan(x) by mptan() routine */
/* and converts result back to double */
static double tanMp(double x)
{
int p;
double y;
mp_no mpy;
p=32;
__mptan(x, &mpy, p);
__mp_dbl(&mpy,&y,p);
return y;
}
#ifdef NO_LONG_DOUBLE
weak_alias (tan, tanl)
#endif
@@ -0,0 +1,49 @@
/* s_tanf.c -- float version of s_tan.c.
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
*/
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: s_tanf.c,v 1.4 1995/05/10 20:48:20 jtc Exp $";
#endif
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
float __tanf(float x)
#else
float __tanf(x)
float x;
#endif
{
float y[2],z=0.0;
int32_t n, ix;
GET_FLOAT_WORD(ix,x);
/* |x| ~< pi/4 */
ix &= 0x7fffffff;
if(ix <= 0x3f490fda) return __kernel_tanf(x,z,1);
/* tan(Inf or NaN) is NaN */
else if (ix>=0x7f800000) return x-x; /* NaN */
/* argument reduction needed */
else {
n = __ieee754_rem_pio2f(x,y);
return __kernel_tanf(y[0],y[1],1-((n&1)<<1)); /* 1 -- n even
-1 -- n odd */
}
}
weak_alias (__tanf, tanf)
@@ -0,0 +1,93 @@
/* @(#)s_tanh.c 5.1 93/09/24 */
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: s_tanh.c,v 1.7 1995/05/10 20:48:22 jtc Exp $";
#endif
/* Tanh(x)
* Return the Hyperbolic Tangent of x
*
* Method :
* x -x
* e - e
* 0. tanh(x) is defined to be -----------
* x -x
* e + e
* 1. reduce x to non-negative by tanh(-x) = -tanh(x).
* 2. 0 <= x <= 2**-55 : tanh(x) := x*(one+x)
* -t
* 2**-55 < x <= 1 : tanh(x) := -----; t = expm1(-2x)
* t + 2
* 2
* 1 <= x <= 22.0 : tanh(x) := 1- ----- ; t=expm1(2x)
* t + 2
* 22.0 < x <= INF : tanh(x) := 1.
*
* Special cases:
* tanh(NaN) is NaN;
* only tanh(0)=0 is exact for finite argument.
*/
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const double one=1.0, two=2.0, tiny = 1.0e-300;
#else
static double one=1.0, two=2.0, tiny = 1.0e-300;
#endif
#ifdef __STDC__
double __tanh(double x)
#else
double __tanh(x)
double x;
#endif
{
double t,z;
int32_t jx,ix,lx;
/* High word of |x|. */
EXTRACT_WORDS(jx,lx,x);
ix = jx&0x7fffffff;
/* x is INF or NaN */
if(ix>=0x7ff00000) {
if (jx>=0) return one/x+one; /* tanh(+-inf)=+-1 */
else return one/x-one; /* tanh(NaN) = NaN */
}
/* |x| < 22 */
if (ix < 0x40360000) { /* |x|<22 */
if ((ix | lx) == 0)
return x; /* x == +-0 */
if (ix<0x3c800000) /* |x|<2**-55 */
return x*(one+x); /* tanh(small) = small */
if (ix>=0x3ff00000) { /* |x|>=1 */
t = __expm1(two*fabs(x));
z = one - two/(t+two);
} else {
t = __expm1(-two*fabs(x));
z= -t/(t+two);
}
/* |x| > 22, return +-1 */
} else {
z = one - tiny; /* raised inexact flag */
}
return (jx>=0)? z: -z;
}
weak_alias (__tanh, tanh)
#ifdef NO_LONG_DOUBLE
strong_alias (__tanh, __tanhl)
weak_alias (__tanh, tanhl)
#endif
@@ -0,0 +1,67 @@
/* s_tanhf.c -- float version of s_tanh.c.
* Conversion to float by Ian Lance Taylor, Cygnus Support, [email protected].
*/
/*
* ====================================================
* 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.
* ====================================================
*/
#if defined(LIBM_SCCS) && !defined(lint)
static char rcsid[] = "$NetBSD: s_tanhf.c,v 1.4 1995/05/10 20:48:24 jtc Exp $";
#endif
#include "math.h"
#include "math_private.h"
#ifdef __STDC__
static const float one=1.0, two=2.0, tiny = 1.0e-30;
#else
static float one=1.0, two=2.0, tiny = 1.0e-30;
#endif
#ifdef __STDC__
float __tanhf(float x)
#else
float __tanhf(x)
float x;
#endif
{
float t,z;
int32_t jx,ix;
GET_FLOAT_WORD(jx,x);
ix = jx&0x7fffffff;
/* x is INF or NaN */
if(ix>=0x7f800000) {
if (jx>=0) return one/x+one; /* tanh(+-inf)=+-1 */
else return one/x-one; /* tanh(NaN) = NaN */
}
/* |x| < 22 */
if (ix < 0x41b00000) { /* |x|<22 */
if (ix == 0)
return x; /* x == +-0 */
if (ix<0x24000000) /* |x|<2**-55 */
return x*(one+x); /* tanh(small) = small */
if (ix>=0x3f800000) { /* |x|>=1 */
t = __expm1f(two*fabsf(x));
z = one - two/(t+two);
} else {
t = __expm1f(-two*fabsf(x));
z= -t/(t+two);
}
/* |x| > 22, return +-1 */
} else {
z = one - tiny; /* raised inexact flag */
}
return (jx>=0)? z: -z;
}
weak_alias (__tanhf, tanhf)
@@ -0,0 +1,912 @@
/*
* IBM Accurate Mathematical Library
* Written by International Business Machines Corp.
* Copyright (C) 2001 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/****************************************************************/
/* TABLES FOR THE usin() and ucos() FUNCTION */
/****************************************************************/
#ifdef BIG_ENDI
static const union {int4 i[880]; double x[40];}sincos = { .i = {
/**/ 0x00000000, 0x00000000,
/**/ 0x00000000, 0x00000000,
/**/ 0x3FF00000, 0x00000000,
/**/ 0x00000000, 0x00000000,
/**/ 0x3F7FFFEA, 0xAAAEEEEF,
/**/ 0xBC1E45E2, 0xEC67B77C,
/**/ 0x3FEFFFC0, 0x00155552,
/**/ 0x3C8F4A01, 0xA0196DAE,
/**/ 0x3F8FFFAA, 0xAAEEEED5,
/**/ 0xBC02AB63, 0x9A9F0777,
/**/ 0x3FEFFF00, 0x0155549F,
/**/ 0x3C828A28, 0xA03A5EF3,
/**/ 0x3F97FF70, 0x01033255,
/**/ 0x3BFEFE2B, 0x51527336,
/**/ 0x3FEFFDC0, 0x06BFF7E6,
/**/ 0x3C8AE6DA, 0xE86977BD,
/**/ 0x3F9FFEAA, 0xAEEEE86F,
/**/ 0xBC3CD406, 0xFB224AE2,
/**/ 0x3FEFFC00, 0x155527D3,
/**/ 0xBC83B544, 0x92D89B5B,
/**/ 0x3FA3FEB2, 0xB12D45D5,
/**/ 0x3C34EC54, 0x203D1C11,
/**/ 0x3FEFF9C0, 0x3414A7BA,
/**/ 0x3C6991F4, 0xBE6C59BF,
/**/ 0x3FA7FDC0, 0x1032FBA9,
/**/ 0xBC4599BD, 0xF46E997A,
/**/ 0x3FEFF700, 0x6BFDF99F,
/**/ 0xBC78B3B5, 0x60648D5F,
/**/ 0x3FABFC6D, 0x78586DAC,
/**/ 0x3C18E4FD, 0x03DBF236,
/**/ 0x3FEFF3C0, 0xC8103A31,
/**/ 0x3C74856D, 0xBDDC0E66,
/**/ 0x3FAFFAAA, 0xEEED4EDB,
/**/ 0xBC42D16D, 0x32684B69,
/**/ 0x3FEFF001, 0x5549F4D3,
/**/ 0x3C832838, 0x7B99426F,
/**/ 0x3FB1FC34, 0x3D808BEF,
/**/ 0xBC5F3D32, 0xE6F3BE4F,
/**/ 0x3FEFEBC2, 0x22A8EF9F,
/**/ 0x3C579349, 0x34F54C77,
/**/ 0x3FB3FACB, 0x12D1755B,
/**/ 0xBC592191, 0x5299468C,
/**/ 0x3FEFE703, 0x4129EF6F,
/**/ 0xBC6CBF43, 0x37C96F97,
/**/ 0x3FB5F911, 0xFD10B737,
/**/ 0xBC50184F, 0x02BE9102,
/**/ 0x3FEFE1C4, 0xC3C873EB,
/**/ 0xBC35A9C9, 0x057C4A02,
/**/ 0x3FB7F701, 0x032550E4,
/**/ 0x3C3AFC2D, 0x1800501A,
/**/ 0x3FEFDC06, 0xBF7E6B9B,
/**/ 0x3C831902, 0xB535F8DB,
/**/ 0x3FB9F490, 0x2D55D1F9,
/**/ 0x3C52696D, 0x7EAC1DC1,
/**/ 0x3FEFD5C9, 0x4B43E000,
/**/ 0xBC62E768, 0xCB4F92F9,
/**/ 0x3FBBF1B7, 0x8568391D,
/**/ 0x3C5E9184, 0x1DEA4CC8,
/**/ 0x3FEFCF0C, 0x800E99B1,
/**/ 0x3C6EA3D7, 0x86D186AC,
/**/ 0x3FBDEE6F, 0x16C1CCE6,
/**/ 0xBC450F8E, 0x2FB71673,
/**/ 0x3FEFC7D0, 0x78D1BC88,
/**/ 0x3C8075D2, 0x447DB685,
/**/ 0x3FBFEAAE, 0xEE86EE36,
/**/ 0xBC4AFCB2, 0xBCC6F03B,
/**/ 0x3FEFC015, 0x527D5BD3,
/**/ 0x3C8B68F3, 0x5094EFB8,
/**/ 0x3FC0F337, 0x8DDD71D1,
/**/ 0x3C6D8468, 0x724F0F9E,
/**/ 0x3FEFB7DB, 0x2BFE0695,
/**/ 0x3C821DAD, 0xF4F65AB1,
/**/ 0x3FC1F0D3, 0xD7AFCEAF,
/**/ 0xBC66EF95, 0x099769A5,
/**/ 0x3FEFAF22, 0x263C4BD3,
/**/ 0xBC552ACE, 0x133A2769,
/**/ 0x3FC2EE28, 0x5E4AB88F,
/**/ 0xBC6E4D0F, 0x05DEE058,
/**/ 0x3FEFA5EA, 0x641C36F2,
/**/ 0x3C404DA6, 0xED17CC7C,
/**/ 0x3FC3EB31, 0x2C5D66CB,
/**/ 0x3C647D66, 0x6B66CB91,
/**/ 0x3FEF9C34, 0x0A7CC428,
/**/ 0x3C8C5B6B, 0x063B7462,
/**/ 0x3FC4E7EA, 0x4DC5F27B,
/**/ 0x3C5949DB, 0x2AC072FC,
/**/ 0x3FEF91FF, 0x40374D01,
/**/ 0xBC67D03F, 0x4D3A9E4C,
/**/ 0x3FC5E44F, 0xCFA126F3,
/**/ 0xBC66F443, 0x063F89B6,
/**/ 0x3FEF874C, 0x2E1EECF6,
/**/ 0xBC8C6514, 0xE1332B16,
/**/ 0x3FC6E05D, 0xC05A4D4C,
/**/ 0xBBD32C5C, 0x8B81C940,
/**/ 0x3FEF7C1A, 0xFEFFDE24,
/**/ 0xBC78F55B, 0xC47540B1,
/**/ 0x3FC7DC10, 0x2FBAF2B5,
/**/ 0x3C45AB50, 0xE23C97C3,
/**/ 0x3FEF706B, 0xDF9ECE1C,
/**/ 0xBC8698C8, 0x0C36DCB4,
/**/ 0x3FC8D763, 0x2EFAA944,
/**/ 0xBC620FA2, 0x62CBB953,
/**/ 0x3FEF643E, 0xFEB82ACD,
/**/ 0x3C76B00A, 0xC1FE28AC,
/**/ 0x3FC9D252, 0xD0CEC312,
/**/ 0x3C59C43D, 0x80B1137D,
/**/ 0x3FEF5794, 0x8CFF6797,
/**/ 0x3C6E3A0D, 0x3E03B1D5,
/**/ 0x3FCACCDB, 0x297A0765,
/**/ 0xBC59883B, 0x57D6CDEB,
/**/ 0x3FEF4A6C, 0xBD1E3A79,
/**/ 0x3C813DF0, 0xEDAEBB57,
/**/ 0x3FCBC6F8, 0x4EDC6199,
/**/ 0x3C69C1A5, 0x6A7B0CAB,
/**/ 0x3FEF3CC7, 0xC3B3D16E,
/**/ 0xBC621A3A, 0xD28A3494,
/**/ 0x3FCCC0A6, 0x588289A3,
/**/ 0xBC6868D0, 0x9BC87C6B,
/**/ 0x3FEF2EA5, 0xD753FFED,
/**/ 0x3C8CC421, 0x5F56D583,
/**/ 0x3FCDB9E1, 0x5FB5A5D0,
/**/ 0xBC632E20, 0xD6CC6FC2,
/**/ 0x3FEF2007, 0x3086649F,
/**/ 0x3C7B9404, 0x16C1984B,
/**/ 0x3FCEB2A5, 0x7F8AE5A3,
/**/ 0xBC60BE06, 0xAF572CEB,
/**/ 0x3FEF10EC, 0x09C5873B,
/**/ 0x3C8D9072, 0x762C1283,
/**/ 0x3FCFAAEE, 0xD4F31577,
/**/ 0xBC615D88, 0x508E32B8,
/**/ 0x3FEF0154, 0x9F7DEEA1,
/**/ 0x3C8D3C1E, 0x99E5CAFD,
/**/ 0x3FD0515C, 0xBF65155C,
/**/ 0xBC79B8C2, 0x9DFD8EC8,
/**/ 0x3FEEF141, 0x300D2F26,
/**/ 0xBC82AA1B, 0x08DED372,
/**/ 0x3FD0CD00, 0xCEF36436,
/**/ 0xBC79FB0A, 0x0C93E2B5,
/**/ 0x3FEEE0B1, 0xFBC0F11C,
/**/ 0xBC4BFD23, 0x80BBC3B1,
/**/ 0x3FD14861, 0xAA94DDEB,
/**/ 0xBC6BE881, 0xB5B615A4,
/**/ 0x3FEECFA7, 0x44D5EFA1,
/**/ 0xBC556D0A, 0x4AF541D0,
/**/ 0x3FD1C37D, 0x64C6B876,
/**/ 0x3C746076, 0xFE0DCFF5,
/**/ 0x3FEEBE21, 0x4F76EFA8,
/**/ 0xBC802F9F, 0x12BA543E,
/**/ 0x3FD23E52, 0x111AAF36,
/**/ 0xBC74F080, 0x334EFF18,
/**/ 0x3FEEAC20, 0x61BBAF4F,
/**/ 0x3C62C1D5, 0x3E94658D,
/**/ 0x3FD2B8DD, 0xC43EB49F,
/**/ 0x3C615538, 0x99F2D807,
/**/ 0x3FEE99A4, 0xC3A7CD83,
/**/ 0xBC82264B, 0x1BC53CE8,
/**/ 0x3FD3331E, 0x94049F87,
/**/ 0x3C7E0CB6, 0xB40C302C,
/**/ 0x3FEE86AE, 0xBF29A9ED,
/**/ 0x3C89397A, 0xFDBB58A7,
/**/ 0x3FD3AD12, 0x9769D3D8,
/**/ 0x3C003D55, 0x04878398,
/**/ 0x3FEE733E, 0xA0193D40,
/**/ 0xBC86428B, 0x3546CE13,
/**/ 0x3FD426B7, 0xE69EE697,
/**/ 0xBC7F09C7, 0x5705C59F,
/**/ 0x3FEE5F54, 0xB436E9D0,
/**/ 0x3C87EB0F, 0xD02FC8BC,
/**/ 0x3FD4A00C, 0x9B0F3D20,
/**/ 0x3C7823BA, 0x6BB08EAD,
/**/ 0x3FEE4AF1, 0x4B2A449C,
/**/ 0xBC868CA0, 0x2E8A6833,
/**/ 0x3FD5190E, 0xCF68A77A,
/**/ 0x3C7B3571, 0x55EEF0F3,
/**/ 0x3FEE3614, 0xB680D6A5,
/**/ 0xBC727793, 0xAA015237,
/**/ 0x3FD591BC, 0x9FA2F597,
/**/ 0x3C67C74B, 0xAC3FE0CB,
/**/ 0x3FEE20BF, 0x49ACD6C1,
/**/ 0xBC5660AE, 0xC7EF636C,
/**/ 0x3FD60A14, 0x29078775,
/**/ 0x3C5B1FD8, 0x0BA89133,
/**/ 0x3FEE0AF1, 0x5A03DBCE,
/**/ 0x3C5FE8E7, 0x02771AE6,
/**/ 0x3FD68213, 0x8A38D7F7,
/**/ 0xBC7D8892, 0x02444AAD,
/**/ 0x3FEDF4AB, 0x3EBD875E,
/**/ 0xBC8E2D8A, 0x7E6736C4,
/**/ 0x3FD6F9B8, 0xE33A0255,
/**/ 0x3C742BC1, 0x4EE9DA0D,
/**/ 0x3FEDDDED, 0x50F228D6,
/**/ 0xBC6E80C8, 0xD42BA2BF,
/**/ 0x3FD77102, 0x55764214,
/**/ 0xBC66EAD7, 0x314BB6CE,
/**/ 0x3FEDC6B7, 0xEB995912,
/**/ 0x3C54B364, 0x776DCD35,
/**/ 0x3FD7E7EE, 0x03C86D4E,
/**/ 0xBC7B63BC, 0xDABF5AF2,
/**/ 0x3FEDAF0B, 0x6B888E83,
/**/ 0x3C8A249E, 0x2B5E5CEA,
/**/ 0x3FD85E7A, 0x12826949,
/**/ 0x3C78A40E, 0x9B5FACE0,
/**/ 0x3FED96E8, 0x2F71A9DC,
/**/ 0x3C8FF61B, 0xD5D2039D,
/**/ 0x3FD8D4A4, 0xA774992F,
/**/ 0x3C744A02, 0xEA766326,
/**/ 0x3FED7E4E, 0x97E17B4A,
/**/ 0xBC63B770, 0x352BED94,
/**/ 0x3FD94A6B, 0xE9F546C5,
/**/ 0xBC769CE1, 0x3E683F58,
/**/ 0x3FED653F, 0x073E4040,
/**/ 0xBC876236, 0x434BEC37,
/**/ 0x3FD9BFCE, 0x02E80510,
/**/ 0x3C709E39, 0xA320B0A4,
/**/ 0x3FED4BB9, 0xE1C619E0,
/**/ 0x3C8F34BB, 0x77858F61,
/**/ 0x3FDA34C9, 0x1CC50CCA,
/**/ 0xBC5A310E, 0x3B50CECD,
/**/ 0x3FED31BF, 0x8D8D7C06,
/**/ 0x3C7E60DD, 0x3089CBDD,
/**/ 0x3FDAA95B, 0x63A09277,
/**/ 0xBC66293E, 0xB13C0381,
/**/ 0x3FED1750, 0x727D94F0,
/**/ 0x3C80D52B, 0x1EC1A48E,
/**/ 0x3FDB1D83, 0x05321617,
/**/ 0xBC7AE242, 0xCB99F519,
/**/ 0x3FECFC6C, 0xFA52AD9F,
/**/ 0x3C88B5B5, 0x508F2A0D,
/**/ 0x3FDB913E, 0x30DBAC43,
/**/ 0xBC7E38AD, 0x2F6C3FF1,
/**/ 0x3FECE115, 0x909A82E5,
/**/ 0x3C81F139, 0xBB31109A,
/**/ 0x3FDC048B, 0x17B140A3,
/**/ 0x3C619FE6, 0x757E9FA7,
/**/ 0x3FECC54A, 0xA2B2972E,
/**/ 0x3C64EE16, 0x2BA83A98,
/**/ 0x3FDC7767, 0xEC7FD19E,
/**/ 0xBC5EB14D, 0x1A3D5826,
/**/ 0x3FECA90C, 0x9FC67D0B,
/**/ 0xBC646A81, 0x485E3462,
/**/ 0x3FDCE9D2, 0xE3D4A51F,
/**/ 0xBC62FC8A, 0x12DAE298,
/**/ 0x3FEC8C5B, 0xF8CE1A84,
/**/ 0x3C7AB3D1, 0xA1590123,
/**/ 0x3FDD5BCA, 0x34047661,
/**/ 0x3C728A44, 0xA75FC29C,
/**/ 0x3FEC6F39, 0x208BE53B,
/**/ 0xBC8741DB, 0xFBAADB42,
/**/ 0x3FDDCD4C, 0x15329C9A,
/**/ 0x3C70D4C6, 0xE171FD9A,
/**/ 0x3FEC51A4, 0x8B8B175E,
/**/ 0xBC61BBB4, 0x3B9AA880,
/**/ 0x3FDE3E56, 0xC1582A69,
/**/ 0xBC50A482, 0x1099F88F,
/**/ 0x3FEC339E, 0xB01DDD81,
/**/ 0xBC8CAAF5, 0xEE82C5C0,
/**/ 0x3FDEAEE8, 0x744B05F0,
/**/ 0xBC5789B4, 0x3C9B027D,
/**/ 0x3FEC1528, 0x065B7D50,
/**/ 0xBC889211, 0x1312E828,
/**/ 0x3FDF1EFF, 0x6BC4F97B,
/**/ 0x3C717212, 0xF8A7525C,
/**/ 0x3FEBF641, 0x081E7536,
/**/ 0x3C8B7BD7, 0x1628A9A1,
/**/ 0x3FDF8E99, 0xE76ABC97,
/**/ 0x3C59D950, 0xAF2D00A3,
/**/ 0x3FEBD6EA, 0x310294F5,
/**/ 0x3C731BBC, 0xC88C109D,
/**/ 0x3FDFFDB6, 0x28D2F57A,
/**/ 0x3C6F4A99, 0x2E905B6A,
/**/ 0x3FEBB723, 0xFE630F32,
/**/ 0x3C772BD2, 0x452D0A39,
/**/ 0x3FE03629, 0x39C69955,
/**/ 0xBC82D8CD, 0x78397B01,
/**/ 0x3FEB96EE, 0xEF58840E,
/**/ 0x3C545A3C, 0xC78FADE0,
/**/ 0x3FE06D36, 0x86946E5B,
/**/ 0x3C83F5AE, 0x4538FF1B,
/**/ 0x3FEB764B, 0x84B704C2,
/**/ 0xBC8F5848, 0xC21B389B,
/**/ 0x3FE0A402, 0x1E9E1001,
/**/ 0xBC86F643, 0xA13914F6,
/**/ 0x3FEB553A, 0x410C104E,
/**/ 0x3C58FF79, 0x47027A16,
/**/ 0x3FE0DA8B, 0x26B5672E,
/**/ 0xBC8A58DE, 0xF0BEE909,
/**/ 0x3FEB33BB, 0xA89C8948,
/**/ 0x3C8EA6A5, 0x1D1F6CA9,
/**/ 0x3FE110D0, 0xC4B69C3B,
/**/ 0x3C8D9189, 0x98809981,
/**/ 0x3FEB11D0, 0x4162A4C6,
/**/ 0x3C71DD56, 0x1EFBC0C2,
/**/ 0x3FE146D2, 0x1F8B7F82,
/**/ 0x3C7BF953, 0x5E2739A8,
/**/ 0x3FEAEF78, 0x930BD275,
/**/ 0xBC7F8362, 0x79746F94,
/**/ 0x3FE17C8E, 0x5F2EEDB0,
/**/ 0x3C635E57, 0x102E2488,
/**/ 0x3FEACCB5, 0x26F69DE5,
/**/ 0x3C88FB6A, 0x8DD6B6CC,
/**/ 0x3FE1B204, 0xACB02FDD,
/**/ 0xBC5F190C, 0x70CBB5FF,
/**/ 0x3FEAA986, 0x88308913,
/**/ 0xBC0B83D6, 0x07CD5070,
/**/ 0x3FE1E734, 0x3236574C,
/**/ 0x3C722A3F, 0xA4F41D5A,
/**/ 0x3FEA85ED, 0x4373E02D,
/**/ 0x3C69BE06, 0x385EC792,
/**/ 0x3FE21C1C, 0x1B0394CF,
/**/ 0x3C5E5B32, 0x4B23AA31,
/**/ 0x3FEA61E9, 0xE72586AF,
/**/ 0x3C858330, 0xE2FD453F,
/**/ 0x3FE250BB, 0x93788BBB,
/**/ 0x3C7EA3D0, 0x2457BCCE,
/**/ 0x3FEA3D7D, 0x0352BDCF,
/**/ 0xBC868DBA, 0xECA19669,
/**/ 0x3FE28511, 0xC917A067,
/**/ 0xBC801DF1, 0xD9A16B70,
/**/ 0x3FEA18A7, 0x29AEE445,
/**/ 0x3C395E25, 0x736C0358,
/**/ 0x3FE2B91D, 0xEA88421E,
/**/ 0xBC8FA371, 0xDB216AB0,
/**/ 0x3FE9F368, 0xED912F85,
/**/ 0xBC81D200, 0xC5791606,
/**/ 0x3FE2ECDF, 0x279A3082,
/**/ 0x3C8D3557, 0xE0E7E37E,
/**/ 0x3FE9CDC2, 0xE3F25E5C,
/**/ 0x3C83F991, 0x12993F62,
/**/ 0x3FE32054, 0xB148BC4F,
/**/ 0x3C8F6B42, 0x095A135B,
/**/ 0x3FE9A7B5, 0xA36A6514,
/**/ 0x3C8722CF, 0xCC9FA7A9,
/**/ 0x3FE3537D, 0xB9BE0367,
/**/ 0x3C6B327E, 0x7AF040F0,
/**/ 0x3FE98141, 0xC42E1310,
/**/ 0x3C8D1FF8, 0x0488F08D,
/**/ 0x3FE38659, 0x7456282B,
/**/ 0xBC710FAD, 0xA93B07A8,
/**/ 0x3FE95A67, 0xE00CB1FD,
/**/ 0xBC80BEFD, 0xA21F862D,
/**/ 0x3FE3B8E7, 0x15A2840A,
/**/ 0xBC797653, 0xA7D2F07B,
/**/ 0x3FE93328, 0x926D9E92,
/**/ 0xBC8BB770, 0x03600CDA,
/**/ 0x3FE3EB25, 0xD36CD53A,
/**/ 0xBC5BE570, 0xE1570FC0,
/**/ 0x3FE90B84, 0x784DDAF7,
/**/ 0xBC70FEB1, 0x0AB93B87,
/**/ 0x3FE41D14, 0xE4BA6790,
/**/ 0x3C84608F, 0xD287ECF5,
/**/ 0x3FE8E37C, 0x303D9AD1,
/**/ 0xBC6463A4, 0xB53D4BF8,
/**/ 0x3FE44EB3, 0x81CF386B,
/**/ 0xBC83ED6C, 0x1E6A5505,
/**/ 0x3FE8BB10, 0x5A5DC900,
/**/ 0x3C8863E0, 0x3E9474C1,
/**/ 0x3FE48000, 0xE431159F,
/**/ 0xBC8B194A, 0x7463ED10,
/**/ 0x3FE89241, 0x985D871F,
/**/ 0x3C8C48D9, 0xC413ED84,
/**/ 0x3FE4B0FC, 0x46AAB761,
/**/ 0x3C20DA05, 0x738CC59A,
/**/ 0x3FE86910, 0x8D77A6C6,
/**/ 0x3C7338FF, 0xE2BFE9DD,
/**/ 0x3FE4E1A4, 0xE54ED51B,
/**/ 0xBC8A492F, 0x89B7C76A,
/**/ 0x3FE83F7D, 0xDE701CA0,
/**/ 0xBC4152CF, 0x609BC6E8,
/**/ 0x3FE511F9, 0xFD7B351C,
/**/ 0xBC85C0E8, 0x61C48831,
/**/ 0x3FE8158A, 0x31916D5D,
/**/ 0xBC6DE8B9, 0x0B8228DE,
/**/ 0x3FE541FA, 0xCDDBB724,
/**/ 0x3C7232C2, 0x8520D391,
/**/ 0x3FE7EB36, 0x2EAA1488,
/**/ 0x3C5A1D65, 0xA4A5959F,
/**/ 0x3FE571A6, 0x966D59B3,
/**/ 0x3C5C843B, 0x4D0FB198,
/**/ 0x3FE7C082, 0x7F09E54F,
/**/ 0xBC6C73D6, 0xD72AEE68,
/**/ 0x3FE5A0FC, 0x98813A12,
/**/ 0xBC8D82E2, 0xB7D4227B,
/**/ 0x3FE7956F, 0xCD7F6543,
/**/ 0xBC8AB276, 0xE9D45AE4,
/**/ 0x3FE5CFFC, 0x16BF8F0D,
/**/ 0x3C896CB3, 0x70EB578A,
/**/ 0x3FE769FE, 0xC655211F,
/**/ 0xBC6827D5, 0xCF8C68C5,
/**/ 0x3FE5FEA4, 0x552A9E57,
/**/ 0x3C80B6CE, 0xF7EE20B7,
/**/ 0x3FE73E30, 0x174EFBA1,
/**/ 0xBC65D3AE, 0x3D94AD5F,
/**/ 0x3FE62CF4, 0x9921AC79,
/**/ 0xBC8EDD98, 0x55B6241A,
/**/ 0x3FE71204, 0x6FA77678,
/**/ 0x3C8425B0, 0xA5029C81,
/**/ 0x3FE65AEC, 0x2963E755,
/**/ 0x3C8126F9, 0x6B71053C,
/**/ 0x3FE6E57C, 0x800CF55E,
/**/ 0x3C860286, 0xDEDBD0A6,
/**/ 0x3FE6888A, 0x4E134B2F,
/**/ 0xBC86B7D3, 0x7644D5E6,
/**/ 0x3FE6B898, 0xFA9EFB5D,
/**/ 0x3C715AC7, 0x86CCF4B2,
/**/ 0x3FE6B5CE, 0x50B7821A,
/**/ 0xBC65D515, 0x8F702E0F,
/**/ 0x3FE68B5A, 0x92EB6253,
/**/ 0xBC89A91A, 0xD985F89C,
/**/ 0x3FE6E2B7, 0x7C40BDE1,
/**/ 0xBC70E729, 0x857FAD53,
/**/ 0x3FE65DC1, 0xFDEB8CBA,
/**/ 0xBC597C1B, 0x47337C77,
/**/ 0x3FE70F45, 0x1D0A8C40,
/**/ 0x3C697EDE, 0x3885770D,
/**/ 0x3FE62FCF, 0xF20191C7,
/**/ 0x3C6D9143, 0x895756EF,
/**/ 0x3FE73B76, 0x80DEA578,
/**/ 0xBC722483, 0x06DC12A2,
/**/ 0x3FE60185, 0x26F563DF,
/**/ 0x3C846CA5, 0xE0E432D0,
/**/ 0x3FE7674A, 0xF6F7B524,
/**/ 0x3C7E9D3F, 0x94AC84A8,
/**/ 0x3FE5D2E2, 0x55F1F17A,
/**/ 0x3C803141, 0x04C8892B,
/**/ 0x3FE792C1, 0xD0041D52,
/**/ 0xBC8ABF05, 0xEEB354EB,
/**/ 0x3FE5A3E8, 0x39824077,
/**/ 0x3C8428AA, 0x2759BE62,
/**/ 0x3FE7BDDA, 0x5E28B3C2,
/**/ 0x3C4AD119, 0x7CCD0393,
/**/ 0x3FE57497, 0x8D8E83F2,
/**/ 0x3C8F4714, 0xAF282D23,
/**/ 0x3FE7E893, 0xF5037959,
/**/ 0x3C80EEFB, 0xAA650C4C,
/**/ 0x3FE544F1, 0x0F592CA5,
/**/ 0xBC8E7AE8, 0xE6C7A62F,
/**/ 0x3FE812ED, 0xE9AE4BA4,
/**/ 0xBC87830A, 0xDF402DDA,
/**/ 0x3FE514F5, 0x7D7BF3DA,
/**/ 0x3C747A10, 0x8073C259 } };
#else
#ifdef LITTLE_ENDI
static const union {int4 i[880]; double x[440];} sincos = { .i = {
/**/ 0x00000000, 0x00000000,
/**/ 0x00000000, 0x00000000,
/**/ 0x00000000, 0x3FF00000,
/**/ 0x00000000, 0x00000000,
/**/ 0xAAAEEEEF, 0x3F7FFFEA,
/**/ 0xEC67B77C, 0xBC1E45E2,
/**/ 0x00155552, 0x3FEFFFC0,
/**/ 0xA0196DAE, 0x3C8F4A01,
/**/ 0xAAEEEED5, 0x3F8FFFAA,
/**/ 0x9A9F0777, 0xBC02AB63,
/**/ 0x0155549F, 0x3FEFFF00,
/**/ 0xA03A5EF3, 0x3C828A28,
/**/ 0x01033255, 0x3F97FF70,
/**/ 0x51527336, 0x3BFEFE2B,
/**/ 0x06BFF7E6, 0x3FEFFDC0,
/**/ 0xE86977BD, 0x3C8AE6DA,
/**/ 0xAEEEE86F, 0x3F9FFEAA,
/**/ 0xFB224AE2, 0xBC3CD406,
/**/ 0x155527D3, 0x3FEFFC00,
/**/ 0x92D89B5B, 0xBC83B544,
/**/ 0xB12D45D5, 0x3FA3FEB2,
/**/ 0x203D1C11, 0x3C34EC54,
/**/ 0x3414A7BA, 0x3FEFF9C0,
/**/ 0xBE6C59BF, 0x3C6991F4,
/**/ 0x1032FBA9, 0x3FA7FDC0,
/**/ 0xF46E997A, 0xBC4599BD,
/**/ 0x6BFDF99F, 0x3FEFF700,
/**/ 0x60648D5F, 0xBC78B3B5,
/**/ 0x78586DAC, 0x3FABFC6D,
/**/ 0x03DBF236, 0x3C18E4FD,
/**/ 0xC8103A31, 0x3FEFF3C0,
/**/ 0xBDDC0E66, 0x3C74856D,
/**/ 0xEEED4EDB, 0x3FAFFAAA,
/**/ 0x32684B69, 0xBC42D16D,
/**/ 0x5549F4D3, 0x3FEFF001,
/**/ 0x7B99426F, 0x3C832838,
/**/ 0x3D808BEF, 0x3FB1FC34,
/**/ 0xE6F3BE4F, 0xBC5F3D32,
/**/ 0x22A8EF9F, 0x3FEFEBC2,
/**/ 0x34F54C77, 0x3C579349,
/**/ 0x12D1755B, 0x3FB3FACB,
/**/ 0x5299468C, 0xBC592191,
/**/ 0x4129EF6F, 0x3FEFE703,
/**/ 0x37C96F97, 0xBC6CBF43,
/**/ 0xFD10B737, 0x3FB5F911,
/**/ 0x02BE9102, 0xBC50184F,
/**/ 0xC3C873EB, 0x3FEFE1C4,
/**/ 0x057C4A02, 0xBC35A9C9,
/**/ 0x032550E4, 0x3FB7F701,
/**/ 0x1800501A, 0x3C3AFC2D,
/**/ 0xBF7E6B9B, 0x3FEFDC06,
/**/ 0xB535F8DB, 0x3C831902,
/**/ 0x2D55D1F9, 0x3FB9F490,
/**/ 0x7EAC1DC1, 0x3C52696D,
/**/ 0x4B43E000, 0x3FEFD5C9,
/**/ 0xCB4F92F9, 0xBC62E768,
/**/ 0x8568391D, 0x3FBBF1B7,
/**/ 0x1DEA4CC8, 0x3C5E9184,
/**/ 0x800E99B1, 0x3FEFCF0C,
/**/ 0x86D186AC, 0x3C6EA3D7,
/**/ 0x16C1CCE6, 0x3FBDEE6F,
/**/ 0x2FB71673, 0xBC450F8E,
/**/ 0x78D1BC88, 0x3FEFC7D0,
/**/ 0x447DB685, 0x3C8075D2,
/**/ 0xEE86EE36, 0x3FBFEAAE,
/**/ 0xBCC6F03B, 0xBC4AFCB2,
/**/ 0x527D5BD3, 0x3FEFC015,
/**/ 0x5094EFB8, 0x3C8B68F3,
/**/ 0x8DDD71D1, 0x3FC0F337,
/**/ 0x724F0F9E, 0x3C6D8468,
/**/ 0x2BFE0695, 0x3FEFB7DB,
/**/ 0xF4F65AB1, 0x3C821DAD,
/**/ 0xD7AFCEAF, 0x3FC1F0D3,
/**/ 0x099769A5, 0xBC66EF95,
/**/ 0x263C4BD3, 0x3FEFAF22,
/**/ 0x133A2769, 0xBC552ACE,
/**/ 0x5E4AB88F, 0x3FC2EE28,
/**/ 0x05DEE058, 0xBC6E4D0F,
/**/ 0x641C36F2, 0x3FEFA5EA,
/**/ 0xED17CC7C, 0x3C404DA6,
/**/ 0x2C5D66CB, 0x3FC3EB31,
/**/ 0x6B66CB91, 0x3C647D66,
/**/ 0x0A7CC428, 0x3FEF9C34,
/**/ 0x063B7462, 0x3C8C5B6B,
/**/ 0x4DC5F27B, 0x3FC4E7EA,
/**/ 0x2AC072FC, 0x3C5949DB,
/**/ 0x40374D01, 0x3FEF91FF,
/**/ 0x4D3A9E4C, 0xBC67D03F,
/**/ 0xCFA126F3, 0x3FC5E44F,
/**/ 0x063F89B6, 0xBC66F443,
/**/ 0x2E1EECF6, 0x3FEF874C,
/**/ 0xE1332B16, 0xBC8C6514,
/**/ 0xC05A4D4C, 0x3FC6E05D,
/**/ 0x8B81C940, 0xBBD32C5C,
/**/ 0xFEFFDE24, 0x3FEF7C1A,
/**/ 0xC47540B1, 0xBC78F55B,
/**/ 0x2FBAF2B5, 0x3FC7DC10,
/**/ 0xE23C97C3, 0x3C45AB50,
/**/ 0xDF9ECE1C, 0x3FEF706B,
/**/ 0x0C36DCB4, 0xBC8698C8,
/**/ 0x2EFAA944, 0x3FC8D763,
/**/ 0x62CBB953, 0xBC620FA2,
/**/ 0xFEB82ACD, 0x3FEF643E,
/**/ 0xC1FE28AC, 0x3C76B00A,
/**/ 0xD0CEC312, 0x3FC9D252,
/**/ 0x80B1137D, 0x3C59C43D,
/**/ 0x8CFF6797, 0x3FEF5794,
/**/ 0x3E03B1D5, 0x3C6E3A0D,
/**/ 0x297A0765, 0x3FCACCDB,
/**/ 0x57D6CDEB, 0xBC59883B,
/**/ 0xBD1E3A79, 0x3FEF4A6C,
/**/ 0xEDAEBB57, 0x3C813DF0,
/**/ 0x4EDC6199, 0x3FCBC6F8,
/**/ 0x6A7B0CAB, 0x3C69C1A5,
/**/ 0xC3B3D16E, 0x3FEF3CC7,
/**/ 0xD28A3494, 0xBC621A3A,
/**/ 0x588289A3, 0x3FCCC0A6,
/**/ 0x9BC87C6B, 0xBC6868D0,
/**/ 0xD753FFED, 0x3FEF2EA5,
/**/ 0x5F56D583, 0x3C8CC421,
/**/ 0x5FB5A5D0, 0x3FCDB9E1,
/**/ 0xD6CC6FC2, 0xBC632E20,
/**/ 0x3086649F, 0x3FEF2007,
/**/ 0x16C1984B, 0x3C7B9404,
/**/ 0x7F8AE5A3, 0x3FCEB2A5,
/**/ 0xAF572CEB, 0xBC60BE06,
/**/ 0x09C5873B, 0x3FEF10EC,
/**/ 0x762C1283, 0x3C8D9072,
/**/ 0xD4F31577, 0x3FCFAAEE,
/**/ 0x508E32B8, 0xBC615D88,
/**/ 0x9F7DEEA1, 0x3FEF0154,
/**/ 0x99E5CAFD, 0x3C8D3C1E,
/**/ 0xBF65155C, 0x3FD0515C,
/**/ 0x9DFD8EC8, 0xBC79B8C2,
/**/ 0x300D2F26, 0x3FEEF141,
/**/ 0x08DED372, 0xBC82AA1B,
/**/ 0xCEF36436, 0x3FD0CD00,
/**/ 0x0C93E2B5, 0xBC79FB0A,
/**/ 0xFBC0F11C, 0x3FEEE0B1,
/**/ 0x80BBC3B1, 0xBC4BFD23,
/**/ 0xAA94DDEB, 0x3FD14861,
/**/ 0xB5B615A4, 0xBC6BE881,
/**/ 0x44D5EFA1, 0x3FEECFA7,
/**/ 0x4AF541D0, 0xBC556D0A,
/**/ 0x64C6B876, 0x3FD1C37D,
/**/ 0xFE0DCFF5, 0x3C746076,
/**/ 0x4F76EFA8, 0x3FEEBE21,
/**/ 0x12BA543E, 0xBC802F9F,
/**/ 0x111AAF36, 0x3FD23E52,
/**/ 0x334EFF18, 0xBC74F080,
/**/ 0x61BBAF4F, 0x3FEEAC20,
/**/ 0x3E94658D, 0x3C62C1D5,
/**/ 0xC43EB49F, 0x3FD2B8DD,
/**/ 0x99F2D807, 0x3C615538,
/**/ 0xC3A7CD83, 0x3FEE99A4,
/**/ 0x1BC53CE8, 0xBC82264B,
/**/ 0x94049F87, 0x3FD3331E,
/**/ 0xB40C302C, 0x3C7E0CB6,
/**/ 0xBF29A9ED, 0x3FEE86AE,
/**/ 0xFDBB58A7, 0x3C89397A,
/**/ 0x9769D3D8, 0x3FD3AD12,
/**/ 0x04878398, 0x3C003D55,
/**/ 0xA0193D40, 0x3FEE733E,
/**/ 0x3546CE13, 0xBC86428B,
/**/ 0xE69EE697, 0x3FD426B7,
/**/ 0x5705C59F, 0xBC7F09C7,
/**/ 0xB436E9D0, 0x3FEE5F54,
/**/ 0xD02FC8BC, 0x3C87EB0F,
/**/ 0x9B0F3D20, 0x3FD4A00C,
/**/ 0x6BB08EAD, 0x3C7823BA,
/**/ 0x4B2A449C, 0x3FEE4AF1,
/**/ 0x2E8A6833, 0xBC868CA0,
/**/ 0xCF68A77A, 0x3FD5190E,
/**/ 0x55EEF0F3, 0x3C7B3571,
/**/ 0xB680D6A5, 0x3FEE3614,
/**/ 0xAA015237, 0xBC727793,
/**/ 0x9FA2F597, 0x3FD591BC,
/**/ 0xAC3FE0CB, 0x3C67C74B,
/**/ 0x49ACD6C1, 0x3FEE20BF,
/**/ 0xC7EF636C, 0xBC5660AE,
/**/ 0x29078775, 0x3FD60A14,
/**/ 0x0BA89133, 0x3C5B1FD8,
/**/ 0x5A03DBCE, 0x3FEE0AF1,
/**/ 0x02771AE6, 0x3C5FE8E7,
/**/ 0x8A38D7F7, 0x3FD68213,
/**/ 0x02444AAD, 0xBC7D8892,
/**/ 0x3EBD875E, 0x3FEDF4AB,
/**/ 0x7E6736C4, 0xBC8E2D8A,
/**/ 0xE33A0255, 0x3FD6F9B8,
/**/ 0x4EE9DA0D, 0x3C742BC1,
/**/ 0x50F228D6, 0x3FEDDDED,
/**/ 0xD42BA2BF, 0xBC6E80C8,
/**/ 0x55764214, 0x3FD77102,
/**/ 0x314BB6CE, 0xBC66EAD7,
/**/ 0xEB995912, 0x3FEDC6B7,
/**/ 0x776DCD35, 0x3C54B364,
/**/ 0x03C86D4E, 0x3FD7E7EE,
/**/ 0xDABF5AF2, 0xBC7B63BC,
/**/ 0x6B888E83, 0x3FEDAF0B,
/**/ 0x2B5E5CEA, 0x3C8A249E,
/**/ 0x12826949, 0x3FD85E7A,
/**/ 0x9B5FACE0, 0x3C78A40E,
/**/ 0x2F71A9DC, 0x3FED96E8,
/**/ 0xD5D2039D, 0x3C8FF61B,
/**/ 0xA774992F, 0x3FD8D4A4,
/**/ 0xEA766326, 0x3C744A02,
/**/ 0x97E17B4A, 0x3FED7E4E,
/**/ 0x352BED94, 0xBC63B770,
/**/ 0xE9F546C5, 0x3FD94A6B,
/**/ 0x3E683F58, 0xBC769CE1,
/**/ 0x073E4040, 0x3FED653F,
/**/ 0x434BEC37, 0xBC876236,
/**/ 0x02E80510, 0x3FD9BFCE,
/**/ 0xA320B0A4, 0x3C709E39,
/**/ 0xE1C619E0, 0x3FED4BB9,
/**/ 0x77858F61, 0x3C8F34BB,
/**/ 0x1CC50CCA, 0x3FDA34C9,
/**/ 0x3B50CECD, 0xBC5A310E,
/**/ 0x8D8D7C06, 0x3FED31BF,
/**/ 0x3089CBDD, 0x3C7E60DD,
/**/ 0x63A09277, 0x3FDAA95B,
/**/ 0xB13C0381, 0xBC66293E,
/**/ 0x727D94F0, 0x3FED1750,
/**/ 0x1EC1A48E, 0x3C80D52B,
/**/ 0x05321617, 0x3FDB1D83,
/**/ 0xCB99F519, 0xBC7AE242,
/**/ 0xFA52AD9F, 0x3FECFC6C,
/**/ 0x508F2A0D, 0x3C88B5B5,
/**/ 0x30DBAC43, 0x3FDB913E,
/**/ 0x2F6C3FF1, 0xBC7E38AD,
/**/ 0x909A82E5, 0x3FECE115,
/**/ 0xBB31109A, 0x3C81F139,
/**/ 0x17B140A3, 0x3FDC048B,
/**/ 0x757E9FA7, 0x3C619FE6,
/**/ 0xA2B2972E, 0x3FECC54A,
/**/ 0x2BA83A98, 0x3C64EE16,
/**/ 0xEC7FD19E, 0x3FDC7767,
/**/ 0x1A3D5826, 0xBC5EB14D,
/**/ 0x9FC67D0B, 0x3FECA90C,
/**/ 0x485E3462, 0xBC646A81,
/**/ 0xE3D4A51F, 0x3FDCE9D2,
/**/ 0x12DAE298, 0xBC62FC8A,
/**/ 0xF8CE1A84, 0x3FEC8C5B,
/**/ 0xA1590123, 0x3C7AB3D1,
/**/ 0x34047661, 0x3FDD5BCA,
/**/ 0xA75FC29C, 0x3C728A44,
/**/ 0x208BE53B, 0x3FEC6F39,
/**/ 0xFBAADB42, 0xBC8741DB,
/**/ 0x15329C9A, 0x3FDDCD4C,
/**/ 0xE171FD9A, 0x3C70D4C6,
/**/ 0x8B8B175E, 0x3FEC51A4,
/**/ 0x3B9AA880, 0xBC61BBB4,
/**/ 0xC1582A69, 0x3FDE3E56,
/**/ 0x1099F88F, 0xBC50A482,
/**/ 0xB01DDD81, 0x3FEC339E,
/**/ 0xEE82C5C0, 0xBC8CAAF5,
/**/ 0x744B05F0, 0x3FDEAEE8,
/**/ 0x3C9B027D, 0xBC5789B4,
/**/ 0x065B7D50, 0x3FEC1528,
/**/ 0x1312E828, 0xBC889211,
/**/ 0x6BC4F97B, 0x3FDF1EFF,
/**/ 0xF8A7525C, 0x3C717212,
/**/ 0x081E7536, 0x3FEBF641,
/**/ 0x1628A9A1, 0x3C8B7BD7,
/**/ 0xE76ABC97, 0x3FDF8E99,
/**/ 0xAF2D00A3, 0x3C59D950,
/**/ 0x310294F5, 0x3FEBD6EA,
/**/ 0xC88C109D, 0x3C731BBC,
/**/ 0x28D2F57A, 0x3FDFFDB6,
/**/ 0x2E905B6A, 0x3C6F4A99,
/**/ 0xFE630F32, 0x3FEBB723,
/**/ 0x452D0A39, 0x3C772BD2,
/**/ 0x39C69955, 0x3FE03629,
/**/ 0x78397B01, 0xBC82D8CD,
/**/ 0xEF58840E, 0x3FEB96EE,
/**/ 0xC78FADE0, 0x3C545A3C,
/**/ 0x86946E5B, 0x3FE06D36,
/**/ 0x4538FF1B, 0x3C83F5AE,
/**/ 0x84B704C2, 0x3FEB764B,
/**/ 0xC21B389B, 0xBC8F5848,
/**/ 0x1E9E1001, 0x3FE0A402,
/**/ 0xA13914F6, 0xBC86F643,
/**/ 0x410C104E, 0x3FEB553A,
/**/ 0x47027A16, 0x3C58FF79,
/**/ 0x26B5672E, 0x3FE0DA8B,
/**/ 0xF0BEE909, 0xBC8A58DE,
/**/ 0xA89C8948, 0x3FEB33BB,
/**/ 0x1D1F6CA9, 0x3C8EA6A5,
/**/ 0xC4B69C3B, 0x3FE110D0,
/**/ 0x98809981, 0x3C8D9189,
/**/ 0x4162A4C6, 0x3FEB11D0,
/**/ 0x1EFBC0C2, 0x3C71DD56,
/**/ 0x1F8B7F82, 0x3FE146D2,
/**/ 0x5E2739A8, 0x3C7BF953,
/**/ 0x930BD275, 0x3FEAEF78,
/**/ 0x79746F94, 0xBC7F8362,
/**/ 0x5F2EEDB0, 0x3FE17C8E,
/**/ 0x102E2488, 0x3C635E57,
/**/ 0x26F69DE5, 0x3FEACCB5,
/**/ 0x8DD6B6CC, 0x3C88FB6A,
/**/ 0xACB02FDD, 0x3FE1B204,
/**/ 0x70CBB5FF, 0xBC5F190C,
/**/ 0x88308913, 0x3FEAA986,
/**/ 0x07CD5070, 0xBC0B83D6,
/**/ 0x3236574C, 0x3FE1E734,
/**/ 0xA4F41D5A, 0x3C722A3F,
/**/ 0x4373E02D, 0x3FEA85ED,
/**/ 0x385EC792, 0x3C69BE06,
/**/ 0x1B0394CF, 0x3FE21C1C,
/**/ 0x4B23AA31, 0x3C5E5B32,
/**/ 0xE72586AF, 0x3FEA61E9,
/**/ 0xE2FD453F, 0x3C858330,
/**/ 0x93788BBB, 0x3FE250BB,
/**/ 0x2457BCCE, 0x3C7EA3D0,
/**/ 0x0352BDCF, 0x3FEA3D7D,
/**/ 0xECA19669, 0xBC868DBA,
/**/ 0xC917A067, 0x3FE28511,
/**/ 0xD9A16B70, 0xBC801DF1,
/**/ 0x29AEE445, 0x3FEA18A7,
/**/ 0x736C0358, 0x3C395E25,
/**/ 0xEA88421E, 0x3FE2B91D,
/**/ 0xDB216AB0, 0xBC8FA371,
/**/ 0xED912F85, 0x3FE9F368,
/**/ 0xC5791606, 0xBC81D200,
/**/ 0x279A3082, 0x3FE2ECDF,
/**/ 0xE0E7E37E, 0x3C8D3557,
/**/ 0xE3F25E5C, 0x3FE9CDC2,
/**/ 0x12993F62, 0x3C83F991,
/**/ 0xB148BC4F, 0x3FE32054,
/**/ 0x095A135B, 0x3C8F6B42,
/**/ 0xA36A6514, 0x3FE9A7B5,
/**/ 0xCC9FA7A9, 0x3C8722CF,
/**/ 0xB9BE0367, 0x3FE3537D,
/**/ 0x7AF040F0, 0x3C6B327E,
/**/ 0xC42E1310, 0x3FE98141,
/**/ 0x0488F08D, 0x3C8D1FF8,
/**/ 0x7456282B, 0x3FE38659,
/**/ 0xA93B07A8, 0xBC710FAD,
/**/ 0xE00CB1FD, 0x3FE95A67,
/**/ 0xA21F862D, 0xBC80BEFD,
/**/ 0x15A2840A, 0x3FE3B8E7,
/**/ 0xA7D2F07B, 0xBC797653,
/**/ 0x926D9E92, 0x3FE93328,
/**/ 0x03600CDA, 0xBC8BB770,
/**/ 0xD36CD53A, 0x3FE3EB25,
/**/ 0xE1570FC0, 0xBC5BE570,
/**/ 0x784DDAF7, 0x3FE90B84,
/**/ 0x0AB93B87, 0xBC70FEB1,
/**/ 0xE4BA6790, 0x3FE41D14,
/**/ 0xD287ECF5, 0x3C84608F,
/**/ 0x303D9AD1, 0x3FE8E37C,
/**/ 0xB53D4BF8, 0xBC6463A4,
/**/ 0x81CF386B, 0x3FE44EB3,
/**/ 0x1E6A5505, 0xBC83ED6C,
/**/ 0x5A5DC900, 0x3FE8BB10,
/**/ 0x3E9474C1, 0x3C8863E0,
/**/ 0xE431159F, 0x3FE48000,
/**/ 0x7463ED10, 0xBC8B194A,
/**/ 0x985D871F, 0x3FE89241,
/**/ 0xC413ED84, 0x3C8C48D9,
/**/ 0x46AAB761, 0x3FE4B0FC,
/**/ 0x738CC59A, 0x3C20DA05,
/**/ 0x8D77A6C6, 0x3FE86910,
/**/ 0xE2BFE9DD, 0x3C7338FF,
/**/ 0xE54ED51B, 0x3FE4E1A4,
/**/ 0x89B7C76A, 0xBC8A492F,
/**/ 0xDE701CA0, 0x3FE83F7D,
/**/ 0x609BC6E8, 0xBC4152CF,
/**/ 0xFD7B351C, 0x3FE511F9,
/**/ 0x61C48831, 0xBC85C0E8,
/**/ 0x31916D5D, 0x3FE8158A,
/**/ 0x0B8228DE, 0xBC6DE8B9,
/**/ 0xCDDBB724, 0x3FE541FA,
/**/ 0x8520D391, 0x3C7232C2,
/**/ 0x2EAA1488, 0x3FE7EB36,
/**/ 0xA4A5959F, 0x3C5A1D65,
/**/ 0x966D59B3, 0x3FE571A6,
/**/ 0x4D0FB198, 0x3C5C843B,
/**/ 0x7F09E54F, 0x3FE7C082,
/**/ 0xD72AEE68, 0xBC6C73D6,
/**/ 0x98813A12, 0x3FE5A0FC,
/**/ 0xB7D4227B, 0xBC8D82E2,
/**/ 0xCD7F6543, 0x3FE7956F,
/**/ 0xE9D45AE4, 0xBC8AB276,
/**/ 0x16BF8F0D, 0x3FE5CFFC,
/**/ 0x70EB578A, 0x3C896CB3,
/**/ 0xC655211F, 0x3FE769FE,
/**/ 0xCF8C68C5, 0xBC6827D5,
/**/ 0x552A9E57, 0x3FE5FEA4,
/**/ 0xF7EE20B7, 0x3C80B6CE,
/**/ 0x174EFBA1, 0x3FE73E30,
/**/ 0x3D94AD5F, 0xBC65D3AE,
/**/ 0x9921AC79, 0x3FE62CF4,
/**/ 0x55B6241A, 0xBC8EDD98,
/**/ 0x6FA77678, 0x3FE71204,
/**/ 0xA5029C81, 0x3C8425B0,
/**/ 0x2963E755, 0x3FE65AEC,
/**/ 0x6B71053C, 0x3C8126F9,
/**/ 0x800CF55E, 0x3FE6E57C,
/**/ 0xDEDBD0A6, 0x3C860286,
/**/ 0x4E134B2F, 0x3FE6888A,
/**/ 0x7644D5E6, 0xBC86B7D3,
/**/ 0xFA9EFB5D, 0x3FE6B898,
/**/ 0x86CCF4B2, 0x3C715AC7,
/**/ 0x50B7821A, 0x3FE6B5CE,
/**/ 0x8F702E0F, 0xBC65D515,
/**/ 0x92EB6253, 0x3FE68B5A,
/**/ 0xD985F89C, 0xBC89A91A,
/**/ 0x7C40BDE1, 0x3FE6E2B7,
/**/ 0x857FAD53, 0xBC70E729,
/**/ 0xFDEB8CBA, 0x3FE65DC1,
/**/ 0x47337C77, 0xBC597C1B,
/**/ 0x1D0A8C40, 0x3FE70F45,
/**/ 0x3885770D, 0x3C697EDE,
/**/ 0xF20191C7, 0x3FE62FCF,
/**/ 0x895756EF, 0x3C6D9143,
/**/ 0x80DEA578, 0x3FE73B76,
/**/ 0x06DC12A2, 0xBC722483,
/**/ 0x26F563DF, 0x3FE60185,
/**/ 0xE0E432D0, 0x3C846CA5,
/**/ 0xF6F7B524, 0x3FE7674A,
/**/ 0x94AC84A8, 0x3C7E9D3F,
/**/ 0x55F1F17A, 0x3FE5D2E2,
/**/ 0x04C8892B, 0x3C803141,
/**/ 0xD0041D52, 0x3FE792C1,
/**/ 0xEEB354EB, 0xBC8ABF05,
/**/ 0x39824077, 0x3FE5A3E8,
/**/ 0x2759BE62, 0x3C8428AA,
/**/ 0x5E28B3C2, 0x3FE7BDDA,
/**/ 0x7CCD0393, 0x3C4AD119,
/**/ 0x8D8E83F2, 0x3FE57497,
/**/ 0xAF282D23, 0x3C8F4714,
/**/ 0xF5037959, 0x3FE7E893,
/**/ 0xAA650C4C, 0x3C80EEFB,
/**/ 0x0F592CA5, 0x3FE544F1,
/**/ 0xE6C7A62F, 0xBC8E7AE8,
/**/ 0xE9AE4BA4, 0x3FE812ED,
/**/ 0xDF402DDA, 0xBC87830A,
/**/ 0x7D7BF3DA, 0x3FE514F5,
/**/ 0x8073C259, 0x3C747A10 } };
#endif
#endif
@@ -0,0 +1,352 @@
/*
* IBM Accurate Mathematical Library
* written by International Business Machines Corp.
* Copyright (C) 2001 Free Software Foundation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/****************************************************************/
/* MODULE_NAME: sincos32.c */
/* */
/* FUNCTIONS: ss32 */
/* cc32 */
/* c32 */
/* sin32 */
/* cos32 */
/* mpsin */
/* mpcos */
/* mpranred */
/* mpsin1 */
/* mpcos1 */
/* */
/* FILES NEEDED: endian.h mpa.h sincos32.h */
/* mpa.c */
/* */
/* Multi Precision sin() and cos() function with p=32 for sin()*/
/* cos() arcsin() and arccos() routines */
/* In addition mpranred() routine performs range reduction of */
/* a double number x into multi precision number y, */
/* such that y=x-n*pi/2, abs(y)<pi/4, n=0,+-1,+-2,.... */
/****************************************************************/
#include "endian.h"
#include "mpa.h"
#include "sincos32.h"
#include "math_private.h"
/****************************************************************/
/* Compute Multi-Precision sin() function for given p. Receive */
/* Multi Precision number x and result stored at y */
/****************************************************************/
static void ss32(mp_no *x, mp_no *y, int p) {
int i;
double a;
#if 0
double b;
static const mp_no mpone = {1,{1.0,1.0}};
#endif
mp_no mpt1,x2,gor,sum ,mpk={1,{1.0}};
#if 0
mp_no mpt2;
#endif
for (i=1;i<=p;i++) mpk.d[i]=0;
__mul(x,x,&x2,p);
__cpy(&oofac27,&gor,p);
__cpy(&gor,&sum,p);
for (a=27.0;a>1.0;a-=2.0) {
mpk.d[1]=a*(a-1.0);
__mul(&gor,&mpk,&mpt1,p);
__cpy(&mpt1,&gor,p);
__mul(&x2,&sum,&mpt1,p);
__sub(&gor,&mpt1,&sum,p);
}
__mul(x,&sum,y,p);
}
/**********************************************************************/
/* Compute Multi-Precision cos() function for given p. Receive Multi */
/* Precision number x and result stored at y */
/**********************************************************************/
static void cc32(mp_no *x, mp_no *y, int p) {
int i;
double a;
#if 0
double b;
static const mp_no mpone = {1,{1.0,1.0}};
#endif
mp_no mpt1,x2,gor,sum ,mpk={1,{1.0}};
#if 0
mp_no mpt2;
#endif
for (i=1;i<=p;i++) mpk.d[i]=0;
__mul(x,x,&x2,p);
mpk.d[1]=27.0;
__mul(&oofac27,&mpk,&gor,p);
__cpy(&gor,&sum,p);
for (a=26.0;a>2.0;a-=2.0) {
mpk.d[1]=a*(a-1.0);
__mul(&gor,&mpk,&mpt1,p);
__cpy(&mpt1,&gor,p);
__mul(&x2,&sum,&mpt1,p);
__sub(&gor,&mpt1,&sum,p);
}
__mul(&x2,&sum,y,p);
}
/***************************************************************************/
/* c32() computes both sin(x), cos(x) as Multi precision numbers */
/***************************************************************************/
void __c32(mp_no *x, mp_no *y, mp_no *z, int p) {
static const mp_no mpt={1,{1.0,2.0}}, one={1,{1.0,1.0}};
mp_no u,t,t1,t2,c,s;
int i;
__cpy(x,&u,p);
u.e=u.e-1;
cc32(&u,&c,p);
ss32(&u,&s,p);
for (i=0;i<24;i++) {
__mul(&c,&s,&t,p);
__sub(&s,&t,&t1,p);
__add(&t1,&t1,&s,p);
__sub(&mpt,&c,&t1,p);
__mul(&t1,&c,&t2,p);
__add(&t2,&t2,&c,p);
}
__sub(&one,&c,y,p);
__cpy(&s,z,p);
}
/************************************************************************/
/*Routine receive double x and two double results of sin(x) and return */
/*result which is more accurate */
/*Computing sin(x) with multi precision routine c32 */
/************************************************************************/
double __sin32(double x, double res, double res1) {
int p;
mp_no a,b,c;
p=32;
__dbl_mp(res,&a,p);
__dbl_mp(0.5*(res1-res),&b,p);
__add(&a,&b,&c,p);
if (x>0.8)
{ __sub(&hp,&c,&a,p);
__c32(&a,&b,&c,p);
}
else __c32(&c,&a,&b,p); /* b=sin(0.5*(res+res1)) */
__dbl_mp(x,&c,p); /* c = x */
__sub(&b,&c,&a,p);
/* if a>0 return min(res,res1), otherwise return max(res,res1) */
if (a.d[0]>0) return (res<res1)?res:res1;
else return (res>res1)?res:res1;
}
/************************************************************************/
/*Routine receive double x and two double results of cos(x) and return */
/*result which is more accurate */
/*Computing cos(x) with multi precision routine c32 */
/************************************************************************/
double __cos32(double x, double res, double res1) {
int p;
mp_no a,b,c;
p=32;
__dbl_mp(res,&a,p);
__dbl_mp(0.5*(res1-res),&b,p);
__add(&a,&b,&c,p);
if (x>2.4)
{ __sub(&pi,&c,&a,p);
__c32(&a,&b,&c,p);
b.d[0]=-b.d[0];
}
else if (x>0.8)
{ __sub(&hp,&c,&a,p);
__c32(&a,&c,&b,p);
}
else __c32(&c,&b,&a,p); /* b=cos(0.5*(res+res1)) */
__dbl_mp(x,&c,p); /* c = x */
__sub(&b,&c,&a,p);
/* if a>0 return max(res,res1), otherwise return min(res,res1) */
if (a.d[0]>0) return (res>res1)?res:res1;
else return (res<res1)?res:res1;
}
/*******************************************************************/
/*Compute sin(x+dx) as Multi Precision number and return result as */
/* double */
/*******************************************************************/
double __mpsin(double x, double dx) {
int p;
double y;
mp_no a,b,c;
p=32;
__dbl_mp(x,&a,p);
__dbl_mp(dx,&b,p);
__add(&a,&b,&c,p);
if (x>0.8) { __sub(&hp,&c,&a,p); __c32(&a,&b,&c,p); }
else __c32(&c,&a,&b,p); /* b = sin(x+dx) */
__mp_dbl(&b,&y,p);
return y;
}
/*******************************************************************/
/* Compute cos()of double-length number (x+dx) as Multi Precision */
/* number and return result as double */
/*******************************************************************/
double __mpcos(double x, double dx) {
int p;
double y;
mp_no a,b,c;
p=32;
__dbl_mp(x,&a,p);
__dbl_mp(dx,&b,p);
__add(&a,&b,&c,p);
if (x>0.8)
{ __sub(&hp,&c,&b,p);
__c32(&b,&c,&a,p);
}
else __c32(&c,&a,&b,p); /* a = cos(x+dx) */
__mp_dbl(&a,&y,p);
return y;
}
/******************************************************************/
/* mpranred() performs range reduction of a double number x into */
/* multi precision number y, such that y=x-n*pi/2, abs(y)<pi/4, */
/* n=0,+-1,+-2,.... */
/* Return int which indicates in which quarter of circle x is */
/******************************************************************/
int __mpranred(double x, mp_no *y, int p)
{
number v;
double t,xn;
int i,k,n;
static const mp_no one = {1,{1.0,1.0}};
mp_no a,b,c;
if (ABS(x) < 2.8e14) {
t = (x*hpinv.d + toint.d);
xn = t - toint.d;
v.d = t;
n =v.i[LOW_HALF]&3;
__dbl_mp(xn,&a,p);
__mul(&a,&hp,&b,p);
__dbl_mp(x,&c,p);
__sub(&c,&b,y,p);
return n;
}
else { /* if x is very big more precision required */
__dbl_mp(x,&a,p);
a.d[0]=1.0;
k = a.e-5;
if (k < 0) k=0;
b.e = -k;
b.d[0] = 1.0;
for (i=0;i<p;i++) b.d[i+1] = toverp[i+k];
__mul(&a,&b,&c,p);
t = c.d[c.e];
for (i=1;i<=p-c.e;i++) c.d[i]=c.d[i+c.e];
for (i=p+1-c.e;i<=p;i++) c.d[i]=0;
c.e=0;
if (c.d[1] >= 8388608.0)
{ t +=1.0;
__sub(&c,&one,&b,p);
__mul(&b,&hp,y,p);
}
else __mul(&c,&hp,y,p);
n = (int) t;
if (x < 0) { y->d[0] = - y->d[0]; n = -n; }
return (n&3);
}
}
/*******************************************************************/
/* Multi-Precision sin() function subroutine, for p=32. It is */
/* based on the routines mpranred() and c32(). */
/*******************************************************************/
double __mpsin1(double x)
{
int p;
int n;
mp_no u,s,c;
double y;
p=32;
n=__mpranred(x,&u,p); /* n is 0, 1, 2 or 3 */
__c32(&u,&c,&s,p);
switch (n) { /* in which quarter of unit circle y is*/
case 0:
__mp_dbl(&s,&y,p);
return y;
break;
case 2:
__mp_dbl(&s,&y,p);
return -y;
break;
case 1:
__mp_dbl(&c,&y,p);
return y;
break;
case 3:
__mp_dbl(&c,&y,p);
return -y;
break;
}
return 0; /* unreachable, to make the compiler happy */
}
/*****************************************************************/
/* Multi-Precision cos() function subroutine, for p=32. It is */
/* based on the routines mpranred() and c32(). */
/*****************************************************************/
double __mpcos1(double x)
{
int p;
int n;
mp_no u,s,c;
double y;
p=32;
n=__mpranred(x,&u,p); /* n is 0, 1, 2 or 3 */
__c32(&u,&c,&s,p);
switch (n) { /* in what quarter of unit circle y is*/
case 0:
__mp_dbl(&c,&y,p);
return y;
break;
case 2:
__mp_dbl(&c,&y,p);
return -y;
break;
case 1:
__mp_dbl(&s,&y,p);
return -y;
break;
case 3:
__mp_dbl(&s,&y,p);
return y;
break;
}
return 0; /* unreachable, to make the compiler happy */
}
/******************************************************************/
@@ -0,0 +1,82 @@
/*
* IBM Accurate Mathematical Library
* Written by International Business Machines Corp.
* Copyright (C) 2001 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/******************************************************************/
/* */
/* MODULE_NAME:sincos32.h */
/* */
/* common data and variables prototype and definition */
/******************************************************************/
#ifndef SINCOS32_H
#define SINCCOS32_H
#ifdef BIG_ENDI
static const number
/**/ hpinv = {{0x3FE45F30, 0x6DC9C883}}, /* 0.63661977236758138 */
/**/ toint = {{0x43380000, 0x00000000}}; /* 6755399441055744 */
#else
#ifdef LITTLE_ENDI
static const number
/**/ hpinv = {{0x6DC9C883, 0x3FE45F30}}, /* 0.63661977236758138 */
/**/ toint = {{0x00000000, 0x43380000}}; /* 6755399441055744 */
#endif
#endif
static const mp_no
oofac27 = {-3,{1.0,7.0,4631664.0,12006312.0,13118056.0,6538613.0,646354.0,
8508025.0,9131256.0,7548776.0,2529842.0,8864927.0,660489.0,15595125.0,12777885.0,
11618489.0,13348664.0,5486686.0,514518.0,11275535.0,4727621.0,3575562.0,
13579710.0,5829745.0,7531862.0,9507898.0,6915060.0,4079264.0,1907586.0,
6078398.0,13789314.0,5504104.0,14136.0}},
pi = {1,{1.0,3.0,
2375530.0,8947107.0,578323.0,1673774.0,225395.0,4498441.0,3678761.0,
10432976.0,536314.0,10021966.0,7113029.0,2630118.0,3723283.0,7847508.0,
6737716.0,15273068.0,12626985.0,12044668.0,5299519.0,8705461.0,11880201.0,
1544726.0,14014857.0,7994139.0,13709579.0,10918111.0,11906095.0,16610011.0,
13638367.0,12040417.0,11529578.0,2522774.0}},
hp = {1,{1.0, 1.0,
9576373.0,4473553.0,8677769.0,9225495.0,112697.0,10637828.0,
10227988.0,13605096.0,268157.0,5010983.0,3556514.0,9703667.0,
1861641.0,12312362.0,3368858.0,7636534.0,6313492.0,14410942.0,
2649759.0,12741338.0,14328708.0,9160971.0,7007428.0,12385677.0,
15243397.0,13847663.0,14341655.0,16693613.0,15207791.0,14408816.0,
14153397.0,1261387.0,6110792.0,2291862.0,4181138.0,5295267.0}};
static const double toverp[75] = {
10680707.0, 7228996.0, 1387004.0, 2578385.0, 16069853.0,
12639074.0, 9804092.0, 4427841.0, 16666979.0, 11263675.0,
12935607.0, 2387514.0, 4345298.0, 14681673.0, 3074569.0,
13734428.0, 16653803.0, 1880361.0, 10960616.0, 8533493.0,
3062596.0, 8710556.0, 7349940.0, 6258241.0, 3772886.0,
3769171.0, 3798172.0, 8675211.0, 12450088.0, 3874808.0,
9961438.0, 366607.0, 15675153.0, 9132554.0, 7151469.0,
3571407.0, 2607881.0, 12013382.0, 4155038.0, 6285869.0,
7677882.0, 13102053.0, 15825725.0, 473591.0, 9065106.0,
15363067.0, 6271263.0, 9264392.0, 5636912.0, 4652155.0,
7056368.0, 13614112.0, 10155062.0, 1944035.0, 9527646.0,
15080200.0, 6658437.0, 6231200.0, 6832269.0, 16767104.0,
5075751.0, 3212806.0, 1398474.0, 7579849.0, 6349435.0,
12618859.0, 4703257.0, 12806093.0, 14477321.0, 2786137.0,
12875403.0, 9837734.0, 14528324.0, 13719321.0, 343717.0 };
#endif

Some files were not shown because too many files have changed in this diff Show More