ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
G4Log.hh
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file G4Log.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 //
34 // The basic idea is to exploit Pade polynomials.
35 // A lot of ideas were inspired by the cephes math library
36 // (by Stephen L. Moshier moshier@na-net.ornl.gov) as well as actual code.
37 // The Cephes library can be found here: http://www.netlib.org/cephes/
38 // Code and algorithms for G4Exp have been extracted and adapted for Geant4
39 // from the original implementation in the VDT mathematical library
40 // (https://svnweb.cern.ch/trac/vdt), version 0.3.7.
41 
42 // Original implementation created on: Jun 23, 2012
43 // Author: Danilo Piparo, Thomas Hauth, Vincenzo Innocente
44 //
45 // --------------------------------------------------------------------
46 /*
47  * VDT is free software: you can redistribute it and/or modify
48  * it under the terms of the GNU Lesser Public License as published by
49  * the Free Software Foundation, either version 3 of the License, or
50  * (at your option) any later version.
51  *
52  * This program is distributed in the hope that it will be useful,
53  * but WITHOUT ANY WARRANTY; without even the implied warranty of
54  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
55  * GNU Lesser Public License for more details.
56  *
57  * You should have received a copy of the GNU Lesser Public License
58  * along with this program. If not, see <http://www.gnu.org/licenses/>.
59  */
60 // --------------------------------------------------------------------
61 #ifndef G4Log_h
62 #define G4Log_h 1
63 
64 #ifdef WIN32
65 
66  #define G4Log std::log
67 
68 #else
69 
70 #include <limits>
71 #include <stdint.h>
72 #include "G4Types.hh"
73 
74 // local namespace for the constants/functions which are necessary only here
75 //
76 namespace G4LogConsts
77 {
78  const G4double LOG_UPPER_LIMIT = 1e307;
80 
81  const G4double SQRTH = 0.70710678118654752440;
82  const G4float MAXNUMF = 3.4028234663852885981170418348451692544e38f;
83 
84  //----------------------------------------------------------------------------
85  // Used to switch between different type of interpretations of the data
86  // (64 bits)
87  //
88  union ieee754
89  {
90  ieee754 () {};
91  ieee754 (G4double thed) {d=thed;};
92  ieee754 (uint64_t thell) {ll=thell;};
93  ieee754 (G4float thef) {f[0]=thef;};
94  ieee754 (uint32_t thei) {i[0]=thei;};
95  G4double d;
96  G4float f[2];
97  uint32_t i[2];
98  uint64_t ll;
99  uint16_t s[4];
100  };
101 
103  {
104  const G4double PX1log = 1.01875663804580931796E-4;
105  const G4double PX2log = 4.97494994976747001425E-1;
106  const G4double PX3log = 4.70579119878881725854E0;
107  const G4double PX4log = 1.44989225341610930846E1;
108  const G4double PX5log = 1.79368678507819816313E1;
109  const G4double PX6log = 7.70838733755885391666E0;
110 
111  G4double px = PX1log;
112  px *= x;
113  px += PX2log;
114  px *= x;
115  px += PX3log;
116  px *= x;
117  px += PX4log;
118  px *= x;
119  px += PX5log;
120  px *= x;
121  px += PX6log;
122  return px;
123  }
124 
126  {
127  const G4double QX1log = 1.12873587189167450590E1;
128  const G4double QX2log = 4.52279145837532221105E1;
129  const G4double QX3log = 8.29875266912776603211E1;
130  const G4double QX4log = 7.11544750618563894466E1;
131  const G4double QX5log = 2.31251620126765340583E1;
132 
133  G4double qx = x;
134  qx += QX1log;
135  qx *=x;
136  qx += QX2log;
137  qx *=x;
138  qx += QX3log;
139  qx *=x;
140  qx += QX4log;
141  qx *=x;
142  qx += QX5log;
143  return qx;
144  }
145 
146  //----------------------------------------------------------------------------
147  // Converts a double to an unsigned long long
148  //
149  inline uint64_t dp2uint64(G4double x)
150  {
151  ieee754 tmp;
152  tmp.d=x;
153  return tmp.ll;
154  }
155 
156  //----------------------------------------------------------------------------
157  // Converts an unsigned long long to a double
158  //
159  inline G4double uint642dp(uint64_t ll)
160  {
161  ieee754 tmp;
162  tmp.ll=ll;
163  return tmp.d;
164  }
165 
166  //----------------------------------------------------------------------------
167  // Converts an int to a float
168  //
170  {
171  ieee754 tmp;
172  tmp.i[0]=x;
173  return tmp.f[0];
174  }
175 
176  //----------------------------------------------------------------------------
177  // Converts a float to an int
178  //
179  inline uint32_t sp2uint32(G4float x)
180  {
181  ieee754 tmp;
182  tmp.f[0]=x;
183  return tmp.i[0];
184  }
185 
186  //----------------------------------------------------------------------------
189  {
190  uint64_t n = dp2uint64(x);
191 
192  // Shift to the right up to the beginning of the exponent.
193  // Then with a mask, cut off the sign bit
194  uint64_t le = (n >> 52);
195 
196  // chop the head of the number: an int contains more than 11 bits (32)
197  int32_t e = le; // This is important since sums on uint64_t do not vectorise
198  fe = e-1023 ;
199 
200  // This puts to 11 zeroes the exponent
201  n &=0x800FFFFFFFFFFFFFULL;
202  // build a mask which is 0.5, i.e. an exponent equal to 1022
203  // which means *2, see the above +1.
204  const uint64_t p05 = 0x3FE0000000000000ULL; //dp2uint64(0.5);
205  n |= p05;
206 
207  return uint642dp(n);
208  }
209 
210  //----------------------------------------------------------------------------
213  {
214  uint32_t n = sp2uint32(x);
215  int32_t e = (n >> 23)-127;
216  fe = e;
217 
218  // fractional part
219  const uint32_t p05f = 0x3f000000; // //sp2uint32(0.5);
220  n &= 0x807fffff;// ~0x7f800000;
221  n |= p05f;
222 
223  return uint322sp(n);
224  }
225 }
226 
227 // Log double precision --------------------------------------------------------
228 
230 {
231  const G4double original_x = x;
232 
233  /* separate mantissa from exponent */
234  G4double fe;
236 
237  // blending
238  x > G4LogConsts::SQRTH? fe+=1. : x+=x ;
239  x -= 1.0;
240 
241  /* rational form */
243 
244  //for the final formula
245  const G4double x2 = x*x;
246  px *= x;
247  px *= x2;
248 
249  const G4double qx = G4LogConsts::get_log_qx(x);
250 
251  G4double res = px / qx ;
252 
253  res -= fe * 2.121944400546905827679e-4;
254  res -= 0.5 * x2 ;
255 
256  res = x + res;
257  res += fe * 0.693359375;
258 
259  if (original_x > G4LogConsts::LOG_UPPER_LIMIT)
260  res = std::numeric_limits<G4double>::infinity();
261  if (original_x < G4LogConsts::LOG_LOWER_LIMIT) // THIS IS NAN!
262  res = - std::numeric_limits<G4double>::quiet_NaN();
263 
264  return res;
265 }
266 
267 // Log single precision --------------------------------------------------------
268 
269 namespace G4LogConsts
270 {
273 
274  const G4float PX1logf = 7.0376836292E-2f;
275  const G4float PX2logf = -1.1514610310E-1f;
276  const G4float PX3logf = 1.1676998740E-1f;
277  const G4float PX4logf = -1.2420140846E-1f;
278  const G4float PX5logf = 1.4249322787E-1f;
279  const G4float PX6logf = -1.6668057665E-1f;
280  const G4float PX7logf = 2.0000714765E-1f;
281  const G4float PX8logf = -2.4999993993E-1f;
282  const G4float PX9logf = 3.3333331174E-1f;
283 
285  {
286  G4float y = x*PX1logf;
287  y += PX2logf;
288  y *= x;
289  y += PX3logf;
290  y *= x;
291  y += PX4logf;
292  y *= x;
293  y += PX5logf;
294  y *= x;
295  y += PX6logf;
296  y *= x;
297  y += PX7logf;
298  y *= x;
299  y += PX8logf;
300  y *= x;
301  y += PX9logf;
302  return y;
303  }
304 
305  const G4float SQRTHF = 0.707106781186547524f;
306 }
307 
308 // Log single precision --------------------------------------------------------
309 
311 {
312  const G4float original_x = x;
313 
314  G4float fe;
315  x = G4LogConsts::getMantExponentf( x, fe);
316 
317  x > G4LogConsts::SQRTHF? fe+=1.f : x+=x ;
318  x -= 1.0f;
319 
320  const G4float x2 = x*x;
321 
323  res *= x2*x;
324 
325  res += -2.12194440e-4f * fe;
326  res += -0.5f * x2;
327 
328  res= x + res;
329 
330  res += 0.693359375f * fe;
331 
332  if (original_x > G4LogConsts::LOGF_UPPER_LIMIT)
333  res = std::numeric_limits<G4float>::infinity();
334  if (original_x < G4LogConsts::LOGF_LOWER_LIMIT)
335  res = -std::numeric_limits<G4float>::quiet_NaN();
336 
337  return res;
338 }
339 
340 //------------------------------------------------------------------------------
341 
342 void logv(const uint32_t size, G4double const * __restrict__ iarray, G4double* __restrict__ oarray);
343 void G4Logv(const uint32_t size, G4double const * __restrict__ iarray, G4double* __restrict__ oarray);
344 void logfv(const uint32_t size, G4float const * __restrict__ iarray, G4float* __restrict__ oarray);
345 void G4Logfv(const uint32_t size, G4float const * __restrict__ iarray, G4float* __restrict__ oarray);
346 
347 #endif /* WIN32 */
348 
349 #endif /* LOG_H_ */