ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4Exp.hh
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4Exp.hh
1 //
2 // ********************************************************************
3 // * License and Disclaimer *
4 // * *
5 // * The Geant4 software is copyright of the Copyright Holders of *
6 // * the Geant4 Collaboration. It is provided under the terms and *
7 // * conditions of the Geant4 Software License, included in the file *
8 // * LICENSE and available at http://cern.ch/geant4/license . These *
9 // * include a list of copyright holders. *
10 // * *
11 // * Neither the authors of this software system, nor their employing *
12 // * institutes,nor the agencies providing financial support for this *
13 // * work make any representation or warranty, express or implied, *
14 // * regarding this software system or assume any liability for its *
15 // * use. Please see the license in the file LICENSE and URL above *
16 // * for the full disclaimer and the limitation of liability. *
17 // * *
18 // * This code implementation is the result of the scientific and *
19 // * technical work of the GEANT4 collaboration. *
20 // * By using, copying, modifying or distributing the software (or *
21 // * any work based on the software) you agree to acknowledge its *
22 // * use in resulting scientific publications, and indicate your *
23 // * acceptance of all terms of the Geant4 Software license. *
24 // ********************************************************************
25 //
26 //
27 //
28 //
29 // --------------------------------------------------------------------
30 //
31 // Class Description:
32 //
33 // The basic idea is to exploit Pade polynomials.
34 // A lot of ideas were inspired by the cephes math library
35 // (by Stephen L. Moshier moshier@na-net.ornl.gov) as well as actual code.
36 // The Cephes library can be found here: http://www.netlib.org/cephes/
37 // Code and algorithms for G4Exp have been extracted and adapted for Geant4
38 // from the original implementation in the VDT mathematical library
39 // (https://svnweb.cern.ch/trac/vdt), version 0.3.7.
40 
41 // Original implementation created on: Jun 23, 2012
42 // Author: Danilo Piparo, Thomas Hauth, Vincenzo Innocente
43 //
44 // --------------------------------------------------------------------
45 /*
46  * VDT is free software: you can redistribute it and/or modify
47  * it under the terms of the GNU Lesser Public License as published by
48  * the Free Software Foundation, either version 3 of the License, or
49  * (at your option) any later version.
50  *
51  * This program is distributed in the hope that it will be useful,
52  * but WITHOUT ANY WARRANTY; without even the implied warranty of
53  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
54  * GNU Lesser Public License for more details.
55  *
56  * You should have received a copy of the GNU Lesser Public License
57  * along with this program. If not, see <http://www.gnu.org/licenses/>.
58  */
59 // --------------------------------------------------------------------
60 #ifndef G4Exp_h
61 #define G4Exp_h 1
62 
63 #ifdef WIN32
64 
65  #define G4Exp std::exp
66 
67 #else
68 
69 #include <limits>
70 #include <stdint.h>
71 #include "G4Types.hh"
72 
73 namespace G4ExpConsts
74 {
75  const G4double EXP_LIMIT = 708;
76 
77  const G4double PX1exp = 1.26177193074810590878E-4;
78  const G4double PX2exp = 3.02994407707441961300E-2;
79  const G4double PX3exp = 9.99999999999999999910E-1;
80  const G4double QX1exp = 3.00198505138664455042E-6;
81  const G4double QX2exp = 2.52448340349684104192E-3;
82  const G4double QX3exp = 2.27265548208155028766E-1;
83  const G4double QX4exp = 2.00000000000000000009E0;
84 
85  const G4double LOG2E = 1.4426950408889634073599; // 1/log(2)
86 
87  const G4float MAXLOGF = 88.72283905206835f;
88  const G4float MINLOGF = -88.f;
89 
90  const G4float C1F = 0.693359375f;
91  const G4float C2F = -2.12194440e-4f;
92 
93  const G4float PX1expf = 1.9875691500E-4f;
94  const G4float PX2expf =1.3981999507E-3f;
95  const G4float PX3expf =8.3334519073E-3f;
96  const G4float PX4expf =4.1665795894E-2f;
97  const G4float PX5expf =1.6666665459E-1f;
98  const G4float PX6expf =5.0000001201E-1f;
99 
100  const G4float LOG2EF = 1.44269504088896341f;
101 
102  //----------------------------------------------------------------------------
103  // Used to switch between different type of interpretations of the data
104  // (64 bits)
105  //
106  union ieee754
107  {
108  ieee754 () {};
109  ieee754 (G4double thed) {d=thed;};
110  ieee754 (uint64_t thell) {ll=thell;};
111  ieee754 (G4float thef) {f[0]=thef;};
112  ieee754 (uint32_t thei) {i[0]=thei;};
113  G4double d;
114  G4float f[2];
115  uint32_t i[2];
116  uint64_t ll;
117  uint16_t s[4];
118  };
119 
120  //----------------------------------------------------------------------------
121  // Converts an unsigned long long to a double
122  //
123  inline G4double uint642dp(uint64_t ll)
124  {
125  ieee754 tmp;
126  tmp.ll=ll;
127  return tmp.d;
128  }
129 
130  //----------------------------------------------------------------------------
131  // Converts an int to a float
132  //
134  {
135  ieee754 tmp;
136  tmp.i[0]=x;
137  return tmp.f[0];
138  }
139 
140  //----------------------------------------------------------------------------
141  // Converts a float to an int
142  //
143  inline uint32_t sp2uint32(G4float x)
144  {
145  ieee754 tmp;
146  tmp.f[0]=x;
147  return tmp.i[0];
148  }
149 
150  //----------------------------------------------------------------------------
156  inline G4double fpfloor(const G4double x)
157  {
158  // no problem since exp is defined between -708 and 708. Int is enough for it!
159  int32_t ret = int32_t (x);
160  ret-=(sp2uint32(x)>>31);
161  return ret;
162  }
163 
164  //----------------------------------------------------------------------------
170  inline G4float fpfloor(const G4float x)
171  {
172  int32_t ret = int32_t (x);
173  ret-=(sp2uint32(x)>>31);
174  return ret;
175  }
176 }
177 
178 // Exp double precision --------------------------------------------------------
179 
180 
182 inline G4double G4Exp(G4double initial_x)
183 {
184  G4double x = initial_x;
186 
187  const int32_t n = int32_t(px);
188 
189  x -= px * 6.93145751953125E-1;
190  x -= px * 1.42860682030941723212E-6;
191 
192  const G4double xx = x * x;
193 
194  // px = x * P(x**2).
195  px = G4ExpConsts::PX1exp;
196  px *= xx;
197  px += G4ExpConsts::PX2exp;
198  px *= xx;
199  px += G4ExpConsts::PX3exp;
200  px *= x;
201 
202  // Evaluate Q(x**2).
204  qx *= xx;
205  qx += G4ExpConsts::QX2exp;
206  qx *= xx;
207  qx += G4ExpConsts::QX3exp;
208  qx *= xx;
209  qx += G4ExpConsts::QX4exp;
210 
211  // e**x = 1 + 2x P(x**2)/( Q(x**2) - P(x**2) )
212  x = px / (qx - px);
213  x = 1.0 + 2.0 * x;
214 
215  // Build 2^n in double.
216  x *= G4ExpConsts::uint642dp(( ((uint64_t)n) +1023)<<52);
217 
218  if (initial_x > G4ExpConsts::EXP_LIMIT)
219  x = std::numeric_limits<G4double>::infinity();
220  if (initial_x < -G4ExpConsts::EXP_LIMIT)
221  x = 0.;
222 
223  return x;
224 }
225 
226 // Exp single precision --------------------------------------------------------
227 
229 inline G4float G4Expf(G4float initial_x)
230 {
231  G4float x = initial_x;
232 
233  G4float z = G4ExpConsts::fpfloor( G4ExpConsts::LOG2EF * x +0.5f ); /* std::floor() truncates toward -infinity. */
234 
235  x -= z * G4ExpConsts::C1F;
236  x -= z * G4ExpConsts::C2F;
237  const int32_t n = int32_t ( z );
238 
239  const G4float x2 = x * x;
240 
241  z = x*G4ExpConsts::PX1expf;
243  z *= x;
245  z *= x;
247  z *= x;
249  z *= x;
251  z *= x2;
252  z += x + 1.0f;
253 
254  /* multiply by power of 2 */
255  z *= G4ExpConsts::uint322sp((n+0x7f)<<23);
256 
257  if (initial_x > G4ExpConsts::MAXLOGF) z=std::numeric_limits<G4float>::infinity();
258  if (initial_x < G4ExpConsts::MINLOGF) z=0.f;
259 
260  return z;
261 }
262 
263 //------------------------------------------------------------------------------
264 
265 void expv(const uint32_t size, G4double const * __restrict__ iarray, G4double* __restrict__ oarray);
266 void G4Expv(const uint32_t size, G4double const * __restrict__ iarray, G4double* __restrict__ oarray);
267 void expfv(const uint32_t size, G4float const * __restrict__ iarray, G4float* __restrict__ oarray);
268 void G4Expfv(const uint32_t size, G4float const * __restrict__ iarray, G4float* __restrict__ oarray);
269 
270 #endif /* WIN32 */
271 
272 #endif