diff options
author | Ulrich Drepper <drepper@redhat.com> | 2001-03-12 00:04:52 +0000 |
---|---|---|
committer | Ulrich Drepper <drepper@redhat.com> | 2001-03-12 00:04:52 +0000 |
commit | e4d8276142b9c07b23043ef44b0fe8fa7bcc3121 (patch) | |
tree | f153a80b6ce0fdd3261ff18a16fd80bd965231c3 /sysdeps/ieee754/dbl-64/sincos32.c | |
parent | d3c8723f6415af59a6ec14fcb918ad0e4d1fb588 (diff) | |
download | glibc-e4d8276142b9c07b23043ef44b0fe8fa7bcc3121.tar.gz glibc-e4d8276142b9c07b23043ef44b0fe8fa7bcc3121.tar.xz glibc-e4d8276142b9c07b23043ef44b0fe8fa7bcc3121.zip |
Update.
2001-03-11 Ulrich Drepper <drepper@redhat.com> Last-bit accurate math library implementation by IBM Haifa. Contributed by Abraham Ziv <ziv@il.ibm.com>, Moshe Olshansky <olshansk@il.ibm.com>, Ealan Henis <ealan@il.ibm.com>, and Anna Reitman <reitman@il.ibm.com>. * math/Makefile (dbl-only-routines): New variable. (libm-routines): Add $(dbl-only-routines). * sysdeps/ieee754/dbl-64/e_acos.c: Empty, definition is in e_asin.c. * sysdeps/ieee754/dbl-64/e_asin.c: Replaced with accurate asin implementation. * sysdeps/ieee754/dbl-64/e_atan2.c: Replaced with accurate atan2 implementation. * sysdeps/ieee754/dbl-64/e_exp.c: Replaced with accurate exp implementation. * sysdeps/ieee754/dbl-64/e_lgamma_r.c: Don't use __kernel_sin and __kernel_cos. * sysdeps/ieee754/dbl-64/e_log.c: Replaced with accurate log implementation. * sysdeps/ieee754/dbl-64/e_remainder.c: Replaced with accurate remainder implementation. * sysdeps/ieee754/dbl-64/e_pow.c: Replaced with accurate pow implementation. * sysdeps/ieee754/dbl-64/e_sqrt.c: Replaced with accurate sqrt implementation. * sysdeps/ieee754/dbl-64/k_cos.c: Empty, definition is in s_sin.c. * sysdeps/ieee754/dbl-64/k_sin.c: Empty, definition is in s_sin.c. * sysdeps/ieee754/dbl-64/s_atan.c: Replaced with accurate atan implementation. * sysdeps/ieee754/dbl-64/s_cos.c: Empty, definition is in s_sin.c. * sysdeps/ieee754/dbl-64/s_sin.c: Replaced with accurate sin/cos implementation. * sysdeps/ieee754/dbl-64/s_sincos.c: Rewritten to not use __kernel_sin and __kernel_cos. * sysdeps/ieee754/dbl-64/s_tan.c: Replaced with accurate tan implementation. * sysdeps/ieee754/dbl-64/Dist: Add new non-code files. * sysdeps/ieee754/dbl-64/MathLib.h: New file. * sysdeps/ieee754/dbl-64/asincos.tbl: New file. * sysdeps/ieee754/dbl-64/atnat.h: New file. * sysdeps/ieee754/dbl-64/atnat2.h: New file. * sysdeps/ieee754/dbl-64/branred.c: New file. * sysdeps/ieee754/dbl-64/branred.h: New file. * sysdeps/ieee754/dbl-64/dla.h: New file. * sysdeps/ieee754/dbl-64/doasin.c: New file. * sysdeps/ieee754/dbl-64/doasin.h: New file. * sysdeps/ieee754/dbl-64/dosincos.c: New file. * sysdeps/ieee754/dbl-64/dosincos.h: New file. * sysdeps/ieee754/dbl-64/endian.h: New file. * sysdeps/ieee754/dbl-64/halfulp.c: New file. * sysdeps/ieee754/dbl-64/mpa.c: New file. * sysdeps/ieee754/dbl-64/mpa.h: New file. * sysdeps/ieee754/dbl-64/mpa2.h: New file. * sysdeps/ieee754/dbl-64/mpatan.c: New file. * sysdeps/ieee754/dbl-64/mpatan.h: New file. * sysdeps/ieee754/dbl-64/mpatan2.c: New file. * sysdeps/ieee754/dbl-64/mpexp.c: New file. * sysdeps/ieee754/dbl-64/mpexp.h: New file. * sysdeps/ieee754/dbl-64/mplog.c: New file. * sysdeps/ieee754/dbl-64/mplog.h: New file. * sysdeps/ieee754/dbl-64/mpsqrt.c: New file. * sysdeps/ieee754/dbl-64/mpsqrt.h: New file. * sysdeps/ieee754/dbl-64/mptan.c: New file. * sysdeps/ieee754/dbl-64/mydefs.h: New file. * sysdeps/ieee754/dbl-64/powtwo.tbl: New file. * sysdeps/ieee754/dbl-64/root.tbl: New file. * sysdeps/ieee754/dbl-64/sincos.tbl: New file. * sysdeps/ieee754/dbl-64/sincos32.c: New file. * sysdeps/ieee754/dbl-64/sincos32.h: New file. * sysdeps/ieee754/dbl-64/slowexp.c: New file. * sysdeps/ieee754/dbl-64/slowpow.c: New file. * sysdeps/ieee754/dbl-64/uasncs.h: New file. * sysdeps/ieee754/dbl-64/uatan.tbl: New file. * sysdeps/ieee754/dbl-64/uexp.h: New file. * sysdeps/ieee754/dbl-64/uexp.tbl: New file. * sysdeps/ieee754/dbl-64/ulog.h: New file. * sysdeps/ieee754/dbl-64/ulog.tbl: New file. * sysdeps/ieee754/dbl-64/upow.h: New file. * sysdeps/ieee754/dbl-64/upow.tbl: New file. * sysdeps/ieee754/dbl-64/urem.h: New file. * sysdeps/ieee754/dbl-64/uroot.h: New file. * sysdeps/ieee754/dbl-64/usncs.h: New file. * sysdeps/ieee754/dbl-64/utan.h: New file. * sysdeps/ieee754/dbl-64/utan.tbl: New file. * sysdeps/i386/fpu/branred.c: New file. * sysdeps/i386/fpu/doasin.c: New file. * sysdeps/i386/fpu/dosincos.c: New file. * sysdeps/i386/fpu/halfulp.c: New file. * sysdeps/i386/fpu/mpa.c: New file. * sysdeps/i386/fpu/mpatan.c: New file. * sysdeps/i386/fpu/mpatan2.c: New file. * sysdeps/i386/fpu/mpexp.c: New file. * sysdeps/i386/fpu/mplog.c: New file. * sysdeps/i386/fpu/mpsqrt.c: New file. * sysdeps/i386/fpu/mptan.c: New file. * sysdeps/i386/fpu/sincos32.c: New file. * sysdeps/i386/fpu/slowexp.c: New file. * sysdeps/i386/fpu/slowpow.c: New file. * sysdeps/ia64/fpu/branred.c: New file. * sysdeps/ia64/fpu/doasin.c: New file. * sysdeps/ia64/fpu/dosincos.c: New file. * sysdeps/ia64/fpu/halfulp.c: New file. * sysdeps/ia64/fpu/mpa.c: New file. * sysdeps/ia64/fpu/mpatan.c: New file. * sysdeps/ia64/fpu/mpatan2.c: New file. * sysdeps/ia64/fpu/mpexp.c: New file. * sysdeps/ia64/fpu/mplog.c: New file. * sysdeps/ia64/fpu/mpsqrt.c: New file. * sysdeps/ia64/fpu/mptan.c: New file. * sysdeps/ia64/fpu/sincos32.c: New file. * sysdeps/ia64/fpu/slowexp.c: New file. * sysdeps/ia64/fpu/slowpow.c: New file. * sysdeps/m68k/fpu/branred.c: New file. * sysdeps/m68k/fpu/doasin.c: New file. * sysdeps/m68k/fpu/dosincos.c: New file. * sysdeps/m68k/fpu/halfulp.c: New file. * sysdeps/m68k/fpu/mpa.c: New file. * sysdeps/m68k/fpu/mpatan.c: New file. * sysdeps/m68k/fpu/mpatan2.c: New file. * sysdeps/m68k/fpu/mpexp.c: New file. * sysdeps/m68k/fpu/mplog.c: New file. * sysdeps/m68k/fpu/mpsqrt.c: New file. * sysdeps/m68k/fpu/mptan.c: New file. * sysdeps/m68k/fpu/sincos32.c: New file. * sysdeps/m68k/fpu/slowexp.c: New file. * sysdeps/m68k/fpu/slowpow.c: New file. * iconvdata/gconv-modules: Add a number of alias, mostly for IBM codepages.
Diffstat (limited to 'sysdeps/ieee754/dbl-64/sincos32.c')
-rw-r--r-- | sysdeps/ieee754/dbl-64/sincos32.c | 339 |
1 files changed, 339 insertions, 0 deletions
diff --git a/sysdeps/ieee754/dbl-64/sincos32.c b/sysdeps/ieee754/dbl-64/sincos32.c new file mode 100644 index 0000000000..41fe2f281a --- /dev/null +++ b/sysdeps/ieee754/dbl-64/sincos32.c @@ -0,0 +1,339 @@ + +/* + * IBM Accurate Mathematical Library + * Copyright (c) International Business Machines Corp., 2001 + * + * 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 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 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" + +/****************************************************************/ +/* Compute Multi-Precision sin() function for given p. Receive */ +/* Multi Precision number x and result stored at y */ +/****************************************************************/ +void ss32(mp_no *x, mp_no *y, int p) { + int i; + double a,b; + static const mp_no mpone = {1,1.0,1.0}; + mp_no mpt1,mpt2,x2,gor,sum ,mpk={1,1.0}; + 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 */ +/**********************************************************************/ +void cc32(mp_no *x, mp_no *y, int p) { + int i; + double a,b; + static const mp_no mpone = {1,1.0,1.0}; + mp_no mpt1,mpt2,x2,gor,sum ,mpk={1,1.0}; + 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,&a,&c,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 */ +} +/******************************************************************/ |