ROOT  6.07/01
Reference Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
exponential.h
Go to the documentation of this file.
1 #ifndef COMMON_EXPONENTIAL_H
2 #define COMMON_EXPONENTIAL_H
3 /* This file is part of the Vc library. {{{
4 
5  Copyright (C) 2012 Matthias Kretz <kretz@kde.org>
6 
7  Vc is free software: you can redistribute it and/or modify
8  it under the terms of the GNU Lesser General Public License as
9  published by the Free Software Foundation, either version 3 of
10  the License, or (at your option) any later version.
11 
12  Vc is distributed in the hope that it will be useful, but
13  WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU Lesser General Public License for more details.
16 
17  You should have received a copy of the GNU Lesser General Public
18  License along with Vc. If not, see <http://www.gnu.org/licenses/>.
19 
20  -------------------------------------------------------------------
21 
22  The exp implementation is derived from Cephes, which carries the
23  following Copyright notice:
24 
25  Cephes Math Library Release 2.2: June, 1992
26  Copyright 1984, 1987, 1989 by Stephen L. Moshier
27  Direct inquiries to 30 Frost Street, Cambridge, MA 02140
28 
29 }}}*/
30 
31 #ifndef VC_COMMON_EXPONENTIAL_H
32 #define VC_COMMON_EXPONENTIAL_H
33 
34 #include "macros.h"
35 namespace ROOT {
36 namespace Vc
37 {
38 namespace Common
39 {
40  using Vc::VC__USE_NAMESPACE::c_log;
41  using Vc::VC__USE_NAMESPACE::Vector;
44 
45  static const float log2_e = 1.44269504088896341f;
46  static const float MAXLOGF = 88.72283905206835f;
47  static const float MINLOGF = -103.278929903431851103f; /* log(2^-149) */
48  static const float MAXNUMF = 3.4028234663852885981170418348451692544e38f;
49 
50  template<typename T> struct TypenameForLdexp { typedef Vector<int> Type; };
51  template<> struct TypenameForLdexp<Vc::sfloat> { typedef Vector<short> Type; };
52 
53  template<typename T> static inline Vector<T> exp(VC_ALIGNED_PARAMETER(Vector<T>) _x) {
54  typedef Vector<T> V;
55  typedef typename V::Mask M;
56  typedef typename TypenameForLdexp<T>::Type I;
57  typedef Const<T> C;
58 
59  V x(_x);
60 
61  const M overflow = x > MAXLOGF;
62  const M underflow = x < MINLOGF;
63 
64  // log₂(eˣ) = x * log₂(e) * log₂(2)
65  // = log₂(2^(x * log₂(e)))
66  // => eˣ = 2^(x * log₂(e))
67  // => n = ⌊x * log₂(e) + ½⌋
68  // => y = x - n * ln(2) | recall that: ln(2) * log₂(e) == 1
69  // <=> eˣ = 2ⁿ * eʸ
70  V z = floor(C::log2_e() * x + 0.5f);
71  I n = static_cast<I>(z);
72  x -= z * C::ln2_large();
73  x -= z * C::ln2_small();
74 
75  /* Theoretical peak relative error in [-0.5, +0.5] is 4.2e-9. */
76  z = ((((( 1.9875691500E-4f * x
77  + 1.3981999507E-3f) * x
78  + 8.3334519073E-3f) * x
79  + 4.1665795894E-2f) * x
80  + 1.6666665459E-1f) * x
81  + 5.0000001201E-1f) * (x * x)
82  + x
83  + 1.0f;
84 
85  x = ldexp(z, n); // == z * 2ⁿ
86 
88  x.setZero(underflow);
89 
90  return x;
91  }
92  static inline Vector<double> exp(Vector<double>::AsArg _x) {
93  Vector<double> x = _x;
94  typedef Vector<double> V;
95  typedef V::Mask M;
96  typedef Const<double> C;
97 
98  const M overflow = x > Vc_buildDouble( 1, 0x0006232bdd7abcd2ull, 9); // max log
99  const M underflow = x < Vc_buildDouble(-1, 0x0006232bdd7abcd2ull, 9); // min log
100 
101  V px = floor(C::log2_e() * x + 0.5);
102 #ifdef VC_IMPL_SSE
103  Vector<int> n(px);
104  n.data() = Mem::permute<X0, X2, X1, X3>(n.data());
105 #elif defined(VC_IMPL_AVX)
106  __m128i tmp = _mm256_cvttpd_epi32(px.data());
107  Vector<int> n = AVX::concat(_mm_unpacklo_epi32(tmp, tmp), _mm_unpackhi_epi32(tmp, tmp));
108 #endif
109  x -= px * C::ln2_large(); //Vc_buildDouble(1, 0x00062e4000000000ull, -1); // ln2
110  x -= px * C::ln2_small(); //Vc_buildDouble(1, 0x0007f7d1cf79abcaull, -20); // ln2
111 
112  const double P[] = {
113  Vc_buildDouble(1, 0x000089cdd5e44be8ull, -13),
114  Vc_buildDouble(1, 0x000f06d10cca2c7eull, -6),
115  Vc_buildDouble(1, 0x0000000000000000ull, 0)
116  };
117  const double Q[] = {
118  Vc_buildDouble(1, 0x00092eb6bc365fa0ull, -19),
119  Vc_buildDouble(1, 0x0004ae39b508b6c0ull, -9),
120  Vc_buildDouble(1, 0x000d17099887e074ull, -3),
121  Vc_buildDouble(1, 0x0000000000000000ull, 1)
122  };
123  const V x2 = x * x;
124  px = x * ((P[0] * x2 + P[1]) * x2 + P[2]);
125  x = px / ((((Q[0] * x2 + Q[1]) * x2 + Q[2]) * x2 + Q[3]) - px);
126  x = V::One() + 2.0 * x;
127 
128  x = ldexp(x, n); // == x * 2ⁿ
129 
131  x.setZero(underflow);
132 
133  return x;
134  }
135 } // namespace Common
137 {
138  using Vc::Common::exp;
139 } // namespace VC__USE_NAMESPACE
140 } // namespace Vc
141 } // namespace ROOT
142 #include "undomacros.h"
143 
144 #endif // VC_COMMON_EXPONENTIAL_H
145 #endif // COMMON_EXPONENTIAL_H
static const float MAXLOGF
Definition: exponential.h:46
static const float log2_e
Definition: exponential.h:45
static const float MAXNUMF
Definition: exponential.h:48
TFile * f
static const double x2[5]
Double_t x[n]
Definition: legend1.C:17
Vc_INTRINSIC Vc_CONST m256 concat(param128 a, param128 b)
Definition: casts.h:123
Float_t z[5]
Definition: Ifit.C:16
#define VC_ALIGNED_PARAMETER(_Type)
Definition: macros.h:368
static double C[]
#define Vc_buildDouble(sign, mantissa, exponent)
Definition: macros.h:283
Double_t E()
Definition: TMath.h:54
double floor(double)
const Double_t infinity
Definition: CsgOps.cxx:85
static const float MINLOGF
Definition: exponential.h:47
MyComplex< T > P(MyComplex< T > z, T c_real, T c_imag)
[MyComplex]
Definition: mandel.cpp:155
static Vector< T > exp(VC_ALIGNED_PARAMETER(Vector< T >) _x)
Definition: exponential.h:53
Float_t px
Definition: hprod.C:33
#define VC__USE_NAMESPACE
Definition: math.h:115
#define I(x, y, z)
const Int_t n
Definition: legend1.C:16
static double Q[]
double ldexp(double, int)