POK
k_tanf.c
1 /*
2  * POK header
3  *
4  * The following file is a part of the POK project. Any modification should
5  * made according to the POK licence. You CANNOT use this file or a part of
6  * this file is this part of a file for your own project
7  *
8  * For more information on the POK licence, please see our LICENCE FILE
9  *
10  * Please follow the coding guidelines described in doc/CODING_GUIDELINES
11  *
12  * Copyright (c) 2007-2009 POK team
13  *
14  * Created by julien on Sat Jan 31 20:12:07 2009
15  */
16 
17 /* k_tanf.c -- float version of k_tan.c
18  * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com.
19  */
20 
21 /*
22  * ====================================================
23  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
24  *
25  * Developed at SunPro, a Sun Microsystems, Inc. business.
26  * Permission to use, copy, modify, and distribute this
27  * software is freely granted, provided that this notice
28  * is preserved.
29  * ====================================================
30  */
31 
32 #ifdef POK_NEEDS_LIBMATH
33 
34 #include <libm.h>
35 #include "math_private.h"
36 static const float
37 one = 1.0000000000e+00, /* 0x3f800000 */
38 pio4 = 7.8539812565e-01, /* 0x3f490fda */
39 pio4lo= 3.7748947079e-08, /* 0x33222168 */
40 T[] = {
41  3.3333334327e-01, /* 0x3eaaaaab */
42  1.3333334029e-01, /* 0x3e088889 */
43  5.3968254477e-02, /* 0x3d5d0dd1 */
44  2.1869488060e-02, /* 0x3cb327a4 */
45  8.8632395491e-03, /* 0x3c11371f */
46  3.5920790397e-03, /* 0x3b6b6916 */
47  1.4562094584e-03, /* 0x3abede48 */
48  5.8804126456e-04, /* 0x3a1a26c8 */
49  2.4646313977e-04, /* 0x398137b9 */
50  7.8179444245e-05, /* 0x38a3f445 */
51  7.1407252108e-05, /* 0x3895c07a */
52  -1.8558637748e-05, /* 0xb79bae5f */
53  2.5907305826e-05, /* 0x37d95384 */
54 };
55 
56 float
57 __kernel_tanf(float x, float y, int iy)
58 {
59  float z,r,v,w,s;
60  int32_t ix,hx;
61  GET_FLOAT_WORD(hx,x);
62  ix = hx&0x7fffffff; /* high word of |x| */
63  if(ix<0x31800000) /* x < 2**-28 */
64  {if((int)x==0) { /* generate inexact */
65  if((ix|(iy+1))==0) return one/fabsf(x);
66  else return (iy==1)? x: -one/x;
67  }
68  }
69  if(ix>=0x3f2ca140) { /* |x|>=0.6744 */
70  if(hx<0) {x = -x; y = -y;}
71  z = pio4-x;
72  w = pio4lo-y;
73  x = z+w; y = 0.0;
74  }
75  z = x*x;
76  w = z*z;
77  /* Break x^5*(T[1]+x^2*T[2]+...) into
78  * x^5(T[1]+x^4*T[3]+...+x^20*T[11]) +
79  * x^5(x^2*(T[2]+x^4*T[4]+...+x^22*[T12]))
80  */
81  r = T[1]+w*(T[3]+w*(T[5]+w*(T[7]+w*(T[9]+w*T[11]))));
82  v = z*(T[2]+w*(T[4]+w*(T[6]+w*(T[8]+w*(T[10]+w*T[12])))));
83  s = z*x;
84  r = y + z*(s*(r+v)+y);
85  r += T[0]*s;
86  w = x+r;
87  if(ix>=0x3f2ca140) {
88  v = (float)iy;
89  return (float)(1-((hx>>30)&2))*(v-(float)2.0*(x-(w*w/(w+v)-r)));
90  }
91  if(iy==1) return w;
92  else { /* if allow error up to 2 ulp,
93  simply return -1.0/(x+r) here */
94  /* compute -1.0/(x+r) accurately */
95  float a,t;
96  int32_t i;
97  z = w;
98  GET_FLOAT_WORD(i,z);
99  SET_FLOAT_WORD(z,i&0xfffff000);
100  v = r-(z - x); /* z+v = r+x */
101  t = a = -(float)1.0/w; /* a = -1.0/w */
102  GET_FLOAT_WORD(i,t);
103  SET_FLOAT_WORD(t,i&0xfffff000);
104  s = (float)1.0+t*z;
105  return t+a*(s+t*v);
106  }
107 }
108 
109 #endif