Logo ROOT   6.08/07
Reference Guide
atan.h
Go to the documentation of this file.
1 /*
2  * atan.h
3  * The basic idea is to exploit Pade polynomials.
4  * A lot of ideas were inspired by the cephes math library (by Stephen L. Moshier
5  * moshier@na-net.ornl.gov) as well as actual code.
6  * The Cephes library can be found here: http://www.netlib.org/cephes/
7  *
8  * Created on: Jun 23, 2012
9  * Author: Danilo Piparo, Thomas Hauth, Vincenzo Innocente
10  */
11 
12 /*
13  * VDT is free software: you can redistribute it and/or modify
14  * it under the terms of the GNU Lesser Public License as published by
15  * the Free Software Foundation, either version 3 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU Lesser Public License for more details.
22  *
23  * You should have received a copy of the GNU Lesser Public License
24  * along with this program. If not, see <http://www.gnu.org/licenses/>.
25  */
26 
27 #ifndef ATAN_H_
28 #define ATAN_H_
29 
30 #include "vdtcore_common.h"
31 
32 namespace vdt{
33 
34 namespace details{
35 const double T3PO8 = 2.41421356237309504880;
36 const double MOREBITSO2 = MOREBITS * 0.5;
37 
38 inline double get_atan_px(const double x2){
39 
40  const double PX1atan = -8.750608600031904122785E-1;
41  const double PX2atan = -1.615753718733365076637E1;
42  const double PX3atan = -7.500855792314704667340E1;
43  const double PX4atan = -1.228866684490136173410E2;
44  const double PX5atan = -6.485021904942025371773E1;
45 
46  double px = PX1atan;
47  px *= x2;
48  px += PX2atan;
49  px *= x2;
50  px += PX3atan;
51  px *= x2;
52  px += PX4atan;
53  px *= x2;
54  px += PX5atan;
55 
56  return px;
57 }
58 
59 
60 inline double get_atan_qx(const double x2){
61  const double QX1atan = 2.485846490142306297962E1;
62  const double QX2atan = 1.650270098316988542046E2;
63  const double QX3atan = 4.328810604912902668951E2;
64  const double QX4atan = 4.853903996359136964868E2;
65  const double QX5atan = 1.945506571482613964425E2;
66 
67  double qx=x2;
68  qx += QX1atan;
69  qx *=x2;
70  qx += QX2atan;
71  qx *=x2;
72  qx += QX3atan;
73  qx *=x2;
74  qx += QX4atan;
75  qx *=x2;
76  qx += QX5atan;
77 
78  return qx;
79 }
80 
81 }
82 
83 
84 
85 /// Fast Atan implementation double precision
86 inline double fast_atan(double x){
87 
88  /* make argument positive and save the sign */
89  const uint64_t sign_mask = details::getSignMask(x);
90  x=std::fabs(x);
91 
92  /* range reduction */
93  const double originalx=x;
94 
95  double y = details::PIO4;
96  double factor = details::MOREBITSO2;
97  x = (x-1.0) / (x+1.0);
98 
99  if( originalx > details::T3PO8 ) {
100  y = details::PIO2;
101  factor = details::MOREBITS;
102  x = -1.0 / originalx ;
103  }
104  if ( originalx <= 0.66 ) {
105  y = 0.;
106  factor = 0.;
107  x = originalx;
108  }
109 
110  const double x2 = x * x;
111 
112  const double px = details::get_atan_px(x2);
113  const double qx = details::get_atan_qx(x2);
114 
115  //double res = y +x * x2 * px / qx + x +factor;
116 
117  const double poq=px / qx;
118 
119  double res = x * x2 * poq + x;
120  res+=y;
121 
122  res+=factor;
123 
124  return details::dpORuint64(res,sign_mask);
125 }
126 
127 //------------------------------------------------------------------------------
128 /// Fast Atan implementation single precision
129 inline float fast_atanf( float xx ) {
130 
131  const uint32_t sign_mask = details::getSignMask(xx);
132 
133  float x= std::fabs(xx);
134  const float x0=x;
135  float y=0.0f;
136 
137  /* range reduction */
138  if( x0 > 0.4142135623730950f ){ // * tan pi/8
139  x = (x0-1.0f)/(x0+1.0f);
140  y = details::PIO4F;
141  }
142  if( x0 > 2.414213562373095f ){ // tan 3pi/8
143  x = -( 1.0f/x0 );
144  y = details::PIO2F;
145  }
146 
147 
148  const float x2 = x * x;
149  y +=
150  ((( 8.05374449538e-2f * x2
151  - 1.38776856032E-1f) * x2
152  + 1.99777106478E-1f) * x2
153  - 3.33329491539E-1f) * x2 * x
154  + x;
155 
156  return details::spORuint32(y,sign_mask);
157 }
158 
159 //------------------------------------------------------------------------------
160 // // Vector signatures
161 //
162 // void atanv(const uint32_t size, double const * __restrict__ iarray, double* __restrict__ oarray);
163 // void fast_atanv(const uint32_t size, double const * __restrict__ iarray, double* __restrict__ oarray);
164 // void atanfv(const uint32_t size, float const * __restrict__ iarray, float* __restrict__ oarray);
165 // void fast_atanfv(const uint32_t size, float const * __restrict__ iarray, float* __restrict__ oarray);
166 
167 }// end of vdt
168 
169 #endif // end of atan
double get_atan_px(const double x2)
Definition: atan.h:38
const double PIO2
const float PIO4F
static const double x2[5]
Double_t x[n]
Definition: legend1.C:17
double fast_atan(double x)
Fast Atan implementation double precision.
Definition: atan.h:86
uint64_t getSignMask(const double x)
const float PIO2F
const double PIO4
VecExpr< UnaryOp< Fabs< T >, VecExpr< A, T, D >, T >, T, D > fabs(const VecExpr< A, T, D > &rhs)
Double_t E()
Definition: TMath.h:54
const double MOREBITS
double f(double x)
Double_t y[n]
Definition: legend1.C:17
Definition: asin.h:32
float spORuint32(const float x, const uint32_t i)
Makes an OR of a float and a unsigned long.
double get_atan_qx(const double x2)
Definition: atan.h:60
double dpORuint64(const double x, const uint64_t i)
Makes an OR of a double and a unsigned long long.
const double MOREBITSO2
Definition: atan.h:36
float fast_atanf(float xx)
Fast Atan implementation single precision.
Definition: atan.h:129
const double T3PO8
Definition: atan.h:35