Geant4 Cross Reference |
1 // 1 // 2 // ******************************************* 2 // ******************************************************************** 3 // * License and Disclaimer 3 // * License and Disclaimer * 4 // * 4 // * * 5 // * The Geant4 software is copyright of th 5 // * The Geant4 software is copyright of the Copyright Holders of * 6 // * the Geant4 Collaboration. It is provided 6 // * the Geant4 Collaboration. It is provided under the terms and * 7 // * conditions of the Geant4 Software License 7 // * conditions of the Geant4 Software License, included in the file * 8 // * LICENSE and available at http://cern.ch/ 8 // * LICENSE and available at http://cern.ch/geant4/license . These * 9 // * include a list of copyright holders. 9 // * include a list of copyright holders. * 10 // * 10 // * * 11 // * Neither the authors of this software syst 11 // * Neither the authors of this software system, nor their employing * 12 // * institutes,nor the agencies providing fin 12 // * institutes,nor the agencies providing financial support for this * 13 // * work make any representation or warran 13 // * work make any representation or warranty, express or implied, * 14 // * regarding this software system or assum 14 // * regarding this software system or assume any liability for its * 15 // * use. Please see the license in the file 15 // * use. Please see the license in the file LICENSE and URL above * 16 // * for the full disclaimer and the limitatio 16 // * for the full disclaimer and the limitation of liability. * 17 // * 17 // * * 18 // * This code implementation is the result 18 // * This code implementation is the result of the scientific and * 19 // * technical work of the GEANT4 collaboratio 19 // * technical work of the GEANT4 collaboration. * 20 // * By using, copying, modifying or distri 20 // * By using, copying, modifying or distributing the software (or * 21 // * any work based on the software) you ag 21 // * any work based on the software) you agree to acknowledge its * 22 // * use in resulting scientific publicati 22 // * use in resulting scientific publications, and indicate your * 23 // * acceptance of all terms of the Geant4 Sof 23 // * acceptance of all terms of the Geant4 Software license. * 24 // ******************************************* 24 // ******************************************************************** 25 // 25 // 26 // G4Log << 27 // 26 // 28 // Class description: << 27 // >> 28 // >> 29 // -------------------------------------------------------------------- >> 30 // >> 31 // Class Description: >> 32 // 29 // 33 // 30 // The basic idea is to exploit Pade polynomia 34 // The basic idea is to exploit Pade polynomials. 31 // A lot of ideas were inspired by the cephes 35 // A lot of ideas were inspired by the cephes math library 32 // (by Stephen L. Moshier moshier@na-net.ornl. << 36 // (by Stephen L. Moshier moshier@na-net.ornl.gov) as well as actual code. 33 // The Cephes library can be found here: http 37 // The Cephes library can be found here: http://www.netlib.org/cephes/ 34 // Code and algorithms for G4Exp have been ext 38 // Code and algorithms for G4Exp have been extracted and adapted for Geant4 35 // from the original implementation in the VDT 39 // from the original implementation in the VDT mathematical library 36 // (https://svnweb.cern.ch/trac/vdt), version 40 // (https://svnweb.cern.ch/trac/vdt), version 0.3.7. 37 41 38 // Original implementation created on: Jun 23, 42 // Original implementation created on: Jun 23, 2012 39 // Author: Danilo Piparo, Thomas Hauth, V 43 // Author: Danilo Piparo, Thomas Hauth, Vincenzo Innocente 40 // 44 // 41 // ------------------------------------------- 45 // -------------------------------------------------------------------- 42 /* << 46 /* 43 * VDT is free software: you can redistribute 47 * VDT is free software: you can redistribute it and/or modify 44 * it under the terms of the GNU Lesser Public 48 * it under the terms of the GNU Lesser Public License as published by 45 * the Free Software Foundation, either versio 49 * the Free Software Foundation, either version 3 of the License, or 46 * (at your option) any later version. 50 * (at your option) any later version. 47 * << 51 * 48 * This program is distributed in the hope tha 52 * This program is distributed in the hope that it will be useful, 49 * but WITHOUT ANY WARRANTY; without even the 53 * but WITHOUT ANY WARRANTY; without even the implied warranty of 50 * MERCHANTABILITY or FITNESS FOR A PARTICULAR 54 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 51 * GNU Lesser Public License for more details. 55 * GNU Lesser Public License for more details. 52 * << 56 * 53 * You should have received a copy of the GNU 57 * You should have received a copy of the GNU Lesser Public License 54 * along with this program. If not, see <http 58 * along with this program. If not, see <http://www.gnu.org/licenses/>. 55 */ 59 */ 56 // ------------------------------------------- 60 // -------------------------------------------------------------------- 57 #ifndef G4Log_hh << 61 #ifndef G4Log_h 58 #define G4Log_hh 1 << 62 #define G4Log_h 1 59 63 60 #ifdef WIN32 64 #ifdef WIN32 61 65 62 # define G4Log std::log << 66 #define G4Log std::log 63 67 64 #else 68 #else 65 69 66 # include "G4Types.hh" << 70 #include <limits> 67 << 71 #include <stdint.h> 68 # include <cstdint> << 72 #include "G4Types.hh" 69 # include <limits> << 70 73 71 // local namespace for the constants/functions 74 // local namespace for the constants/functions which are necessary only here 72 // 75 // 73 namespace G4LogConsts 76 namespace G4LogConsts 74 { 77 { 75 const G4double LOG_UPPER_LIMIT = 1e307; 78 const G4double LOG_UPPER_LIMIT = 1e307; 76 const G4double LOG_LOWER_LIMIT = 0; 79 const G4double LOG_LOWER_LIMIT = 0; 77 80 78 const G4double SQRTH = 0.707106781186547524 << 81 const G4double SQRTH = 0.70710678118654752440; 79 const G4float MAXNUMF = 3.402823466385288598 82 const G4float MAXNUMF = 3.4028234663852885981170418348451692544e38f; 80 83 81 //------------------------------------------ 84 //---------------------------------------------------------------------------- 82 // Used to switch between different type of 85 // Used to switch between different type of interpretations of the data 83 // (64 bits) 86 // (64 bits) 84 // 87 // 85 union ieee754 88 union ieee754 86 { 89 { 87 ieee754()= default; << 90 ieee754 () {}; 88 ieee754(G4double thed) { d = thed; }; << 91 ieee754 (G4double thed) {d=thed;}; 89 ieee754(uint64_t thell) { ll = thell; }; << 92 ieee754 (uint64_t thell) {ll=thell;}; 90 ieee754(G4float thef) { f[0] = thef; }; << 93 ieee754 (G4float thef) {f[0]=thef;}; 91 ieee754(uint32_t thei) { i[0] = thei; }; << 94 ieee754 (uint32_t thei) {i[0]=thei;}; 92 G4double d; 95 G4double d; 93 G4float f[2]; 96 G4float f[2]; 94 uint32_t i[2]; 97 uint32_t i[2]; 95 uint64_t ll; 98 uint64_t ll; 96 uint16_t s[4]; 99 uint16_t s[4]; 97 }; 100 }; 98 101 99 inline G4double get_log_px(const G4double x) 102 inline G4double get_log_px(const G4double x) 100 { 103 { 101 const G4double PX1log = 1.0187566380458093 << 104 const G4double PX1log = 1.01875663804580931796E-4; 102 const G4double PX2log = 4.9749499497674700 << 105 const G4double PX2log = 4.97494994976747001425E-1; 103 const G4double PX3log = 4.7057911987888172 << 106 const G4double PX3log = 4.70579119878881725854E0; 104 const G4double PX4log = 1.4498922534161093 << 107 const G4double PX4log = 1.44989225341610930846E1; 105 const G4double PX5log = 1.7936867850781981 << 108 const G4double PX5log = 1.79368678507819816313E1; 106 const G4double PX6log = 7.7083873375588539 << 109 const G4double PX6log = 7.70838733755885391666E0; 107 << 110 108 G4double px = PX1log; << 111 G4double px = PX1log; 109 px *= x; << 112 px *= x; 110 px += PX2log; << 113 px += PX2log; 111 px *= x; << 114 px *= x; 112 px += PX3log; << 115 px += PX3log; 113 px *= x; << 116 px *= x; 114 px += PX4log; << 117 px += PX4log; 115 px *= x; << 118 px *= x; 116 px += PX5log; << 119 px += PX5log; 117 px *= x; << 120 px *= x; 118 px += PX6log; << 121 px += PX6log; 119 return px; << 122 return px; 120 } 123 } 121 124 122 inline G4double get_log_qx(const G4double x) 125 inline G4double get_log_qx(const G4double x) 123 { 126 { 124 const G4double QX1log = 1.1287358718916745 << 127 const G4double QX1log = 1.12873587189167450590E1; 125 const G4double QX2log = 4.5227914583753222 << 128 const G4double QX2log = 4.52279145837532221105E1; 126 const G4double QX3log = 8.2987526691277660 << 129 const G4double QX3log = 8.29875266912776603211E1; 127 const G4double QX4log = 7.1154475061856389 << 130 const G4double QX4log = 7.11544750618563894466E1; 128 const G4double QX5log = 2.3125162012676534 << 131 const G4double QX5log = 2.31251620126765340583E1; 129 << 132 130 G4double qx = x; << 133 G4double qx = x; 131 qx += QX1log; << 134 qx += QX1log; 132 qx *= x; << 135 qx *=x; 133 qx += QX2log; << 136 qx += QX2log; 134 qx *= x; << 137 qx *=x; 135 qx += QX3log; << 138 qx += QX3log; 136 qx *= x; << 139 qx *=x; 137 qx += QX4log; << 140 qx += QX4log; 138 qx *= x; << 141 qx *=x; 139 qx += QX5log; << 142 qx += QX5log; 140 return qx; << 143 return qx; 141 } 144 } 142 145 143 //------------------------------------------ 146 //---------------------------------------------------------------------------- 144 // Converts a double to an unsigned long lon 147 // Converts a double to an unsigned long long 145 // 148 // 146 inline uint64_t dp2uint64(G4double x) 149 inline uint64_t dp2uint64(G4double x) 147 { 150 { 148 ieee754 tmp; 151 ieee754 tmp; 149 tmp.d = x; << 152 tmp.d=x; 150 return tmp.ll; 153 return tmp.ll; 151 } 154 } 152 155 153 //------------------------------------------ 156 //---------------------------------------------------------------------------- 154 // Converts an unsigned long long to a doubl 157 // Converts an unsigned long long to a double 155 // 158 // 156 inline G4double uint642dp(uint64_t ll) 159 inline G4double uint642dp(uint64_t ll) 157 { 160 { 158 ieee754 tmp; 161 ieee754 tmp; 159 tmp.ll = ll; << 162 tmp.ll=ll; 160 return tmp.d; 163 return tmp.d; 161 } 164 } 162 165 163 //------------------------------------------ 166 //---------------------------------------------------------------------------- 164 // Converts an int to a float 167 // Converts an int to a float 165 // 168 // 166 inline G4float uint322sp(G4int x) 169 inline G4float uint322sp(G4int x) 167 { 170 { 168 ieee754 tmp; 171 ieee754 tmp; 169 tmp.i[0] = x; << 172 tmp.i[0]=x; 170 return tmp.f[0]; 173 return tmp.f[0]; 171 } 174 } 172 175 173 //------------------------------------------ 176 //---------------------------------------------------------------------------- 174 // Converts a float to an int 177 // Converts a float to an int 175 // 178 // 176 inline uint32_t sp2uint32(G4float x) 179 inline uint32_t sp2uint32(G4float x) 177 { 180 { 178 ieee754 tmp; 181 ieee754 tmp; 179 tmp.f[0] = x; << 182 tmp.f[0]=x; 180 return tmp.i[0]; 183 return tmp.i[0]; 181 } 184 } 182 185 183 //------------------------------------------ 186 //---------------------------------------------------------------------------- 184 /// Like frexp but vectorising and the expon 187 /// Like frexp but vectorising and the exponent is a double. 185 inline G4double getMantExponent(const G4doub << 188 inline G4double getMantExponent(const G4double x, G4double & fe) 186 { 189 { 187 uint64_t n = dp2uint64(x); 190 uint64_t n = dp2uint64(x); 188 191 189 // Shift to the right up to the beginning 192 // Shift to the right up to the beginning of the exponent. 190 // Then with a mask, cut off the sign bit 193 // Then with a mask, cut off the sign bit 191 uint64_t le = (n >> 52); 194 uint64_t le = (n >> 52); 192 195 193 // chop the head of the number: an int con 196 // chop the head of the number: an int contains more than 11 bits (32) 194 int32_t e = << 197 int32_t e = le; // This is important since sums on uint64_t do not vectorise 195 (int32_t)le; // This is important since << 198 fe = e-1023 ; 196 fe = e - 1023; << 197 199 198 // This puts to 11 zeroes the exponent 200 // This puts to 11 zeroes the exponent 199 n &= 0x800FFFFFFFFFFFFFULL; << 201 n &=0x800FFFFFFFFFFFFFULL; 200 // build a mask which is 0.5, i.e. an expo 202 // build a mask which is 0.5, i.e. an exponent equal to 1022 201 // which means *2, see the above +1. 203 // which means *2, see the above +1. 202 const uint64_t p05 = 0x3FE0000000000000ULL << 204 const uint64_t p05 = 0x3FE0000000000000ULL; //dp2uint64(0.5); 203 n |= p05; 205 n |= p05; 204 206 205 return uint642dp(n); 207 return uint642dp(n); 206 } 208 } 207 209 208 //------------------------------------------ 210 //---------------------------------------------------------------------------- 209 /// Like frexp but vectorising and the expon 211 /// Like frexp but vectorising and the exponent is a float. 210 inline G4float getMantExponentf(const G4floa << 212 inline G4float getMantExponentf(const G4float x, G4float & fe) 211 { 213 { 212 uint32_t n = sp2uint32(x); 214 uint32_t n = sp2uint32(x); 213 int32_t e = (n >> 23) - 127; << 215 int32_t e = (n >> 23)-127; 214 fe = e; << 216 fe = e; 215 217 216 // fractional part 218 // fractional part 217 const uint32_t p05f = 0x3f000000; // //sp << 219 const uint32_t p05f = 0x3f000000; // //sp2uint32(0.5); 218 n &= 0x807fffff; // ~0x7 << 220 n &= 0x807fffff;// ~0x7f800000; 219 n |= p05f; 221 n |= p05f; 220 222 221 return uint322sp(n); 223 return uint322sp(n); 222 } 224 } 223 } // namespace G4LogConsts << 225 } 224 226 225 // Log double precision ---------------------- 227 // Log double precision -------------------------------------------------------- 226 228 227 inline G4double G4Log(G4double x) 229 inline G4double G4Log(G4double x) 228 { 230 { 229 const G4double original_x = x; << 231 const G4double original_x = x; 230 232 231 /* separate mantissa from exponent */ << 233 /* separate mantissa from exponent */ 232 G4double fe; << 234 G4double fe; 233 x = G4LogConsts::getMantExponent(x, fe); << 235 x = G4LogConsts::getMantExponent(x,fe); 234 236 235 // blending << 237 // blending 236 x > G4LogConsts::SQRTH ? fe += 1. : x += x; << 238 x > G4LogConsts::SQRTH? fe+=1. : x+=x ; 237 x -= 1.0; << 239 x -= 1.0; 238 240 239 /* rational form */ << 241 /* rational form */ 240 G4double px = G4LogConsts::get_log_px(x); << 242 G4double px = G4LogConsts::get_log_px(x); 241 243 242 // for the final formula << 244 //for the final formula 243 const G4double x2 = x * x; << 245 const G4double x2 = x*x; 244 px *= x; << 246 px *= x; 245 px *= x2; << 247 px *= x2; 246 248 247 const G4double qx = G4LogConsts::get_log_qx( << 249 const G4double qx = G4LogConsts::get_log_qx(x); 248 250 249 G4double res = px / qx; << 251 G4double res = px / qx ; 250 252 251 res -= fe * 2.121944400546905827679e-4; << 253 res -= fe * 2.121944400546905827679e-4; 252 res -= 0.5 * x2; << 254 res -= 0.5 * x2 ; 253 255 254 res = x + res; << 256 res = x + res; 255 res += fe * 0.693359375; << 257 res += fe * 0.693359375; 256 258 257 if(original_x > G4LogConsts::LOG_UPPER_LIMIT << 259 if (original_x > G4LogConsts::LOG_UPPER_LIMIT) 258 res = std::numeric_limits<G4double>::infin << 260 res = std::numeric_limits<G4double>::infinity(); 259 if(original_x < G4LogConsts::LOG_LOWER_LIMIT << 261 if (original_x < G4LogConsts::LOG_LOWER_LIMIT) // THIS IS NAN! 260 res = -std::numeric_limits<G4double>::quie << 262 res = - std::numeric_limits<G4double>::quiet_NaN(); 261 263 262 return res; << 264 return res; 263 } 265 } 264 266 265 // Log single precision ---------------------- 267 // Log single precision -------------------------------------------------------- 266 268 267 namespace G4LogConsts 269 namespace G4LogConsts 268 { 270 { 269 const G4float LOGF_UPPER_LIMIT = MAXNUMF; 271 const G4float LOGF_UPPER_LIMIT = MAXNUMF; 270 const G4float LOGF_LOWER_LIMIT = 0; 272 const G4float LOGF_LOWER_LIMIT = 0; 271 273 272 const G4float PX1logf = 7.0376836292E-2f; 274 const G4float PX1logf = 7.0376836292E-2f; 273 const G4float PX2logf = -1.1514610310E-1f; 275 const G4float PX2logf = -1.1514610310E-1f; 274 const G4float PX3logf = 1.1676998740E-1f; 276 const G4float PX3logf = 1.1676998740E-1f; 275 const G4float PX4logf = -1.2420140846E-1f; 277 const G4float PX4logf = -1.2420140846E-1f; 276 const G4float PX5logf = 1.4249322787E-1f; 278 const G4float PX5logf = 1.4249322787E-1f; 277 const G4float PX6logf = -1.6668057665E-1f; 279 const G4float PX6logf = -1.6668057665E-1f; 278 const G4float PX7logf = 2.0000714765E-1f; 280 const G4float PX7logf = 2.0000714765E-1f; 279 const G4float PX8logf = -2.4999993993E-1f; 281 const G4float PX8logf = -2.4999993993E-1f; 280 const G4float PX9logf = 3.3333331174E-1f; 282 const G4float PX9logf = 3.3333331174E-1f; 281 283 282 inline G4float get_log_poly(const G4float x) 284 inline G4float get_log_poly(const G4float x) 283 { 285 { 284 G4float y = x * PX1logf; << 286 G4float y = x*PX1logf; 285 y += PX2logf; << 287 y += PX2logf; 286 y *= x; << 288 y *= x; 287 y += PX3logf; << 289 y += PX3logf; 288 y *= x; << 290 y *= x; 289 y += PX4logf; << 291 y += PX4logf; 290 y *= x; << 292 y *= x; 291 y += PX5logf; << 293 y += PX5logf; 292 y *= x; << 294 y *= x; 293 y += PX6logf; << 295 y += PX6logf; 294 y *= x; << 296 y *= x; 295 y += PX7logf; << 297 y += PX7logf; 296 y *= x; << 298 y *= x; 297 y += PX8logf; << 299 y += PX8logf; 298 y *= x; << 300 y *= x; 299 y += PX9logf; << 301 y += PX9logf; 300 return y; << 302 return y; 301 } 303 } 302 304 303 const G4float SQRTHF = 0.707106781186547524f 305 const G4float SQRTHF = 0.707106781186547524f; 304 } // namespace G4LogConsts << 306 } 305 307 306 // Log single precision ---------------------- 308 // Log single precision -------------------------------------------------------- 307 309 308 inline G4float G4Logf(G4float x) << 310 inline G4float G4Logf( G4float x ) 309 { 311 { 310 const G4float original_x = x; << 312 const G4float original_x = x; 311 313 312 G4float fe; << 314 G4float fe; 313 x = G4LogConsts::getMantExponentf(x, fe); << 315 x = G4LogConsts::getMantExponentf( x, fe); 314 316 315 x > G4LogConsts::SQRTHF ? fe += 1.f : x += x << 317 x > G4LogConsts::SQRTHF? fe+=1.f : x+=x ; 316 x -= 1.0f; << 318 x -= 1.0f; 317 319 318 const G4float x2 = x * x; << 320 const G4float x2 = x*x; 319 321 320 G4float res = G4LogConsts::get_log_poly(x); << 322 G4float res = G4LogConsts::get_log_poly(x); 321 res *= x2 * x; << 323 res *= x2*x; 322 324 323 res += -2.12194440e-4f * fe; << 325 res += -2.12194440e-4f * fe; 324 res += -0.5f * x2; << 326 res += -0.5f * x2; 325 327 326 res = x + res; << 328 res= x + res; 327 329 328 res += 0.693359375f * fe; << 330 res += 0.693359375f * fe; 329 331 330 if(original_x > G4LogConsts::LOGF_UPPER_LIMI << 332 if (original_x > G4LogConsts::LOGF_UPPER_LIMIT) 331 res = std::numeric_limits<G4float>::infini << 333 res = std::numeric_limits<G4float>::infinity(); 332 if(original_x < G4LogConsts::LOGF_LOWER_LIMI << 334 if (original_x < G4LogConsts::LOGF_LOWER_LIMIT) 333 res = -std::numeric_limits<G4float>::quiet << 335 res = -std::numeric_limits<G4float>::quiet_NaN(); 334 336 335 return res; << 337 return res; 336 } 338 } 337 339 338 //-------------------------------------------- 340 //------------------------------------------------------------------------------ 339 341 340 void logv(const uint32_t size, G4double const* << 342 void logv(const uint32_t size, G4double const * __restrict__ iarray, G4double* __restrict__ oarray); 341 G4double* __restrict__ oarray); << 343 void G4Logv(const uint32_t size, G4double const * __restrict__ iarray, G4double* __restrict__ oarray); 342 void G4Logv(const uint32_t size, G4double cons << 344 void logfv(const uint32_t size, G4float const * __restrict__ iarray, G4float* __restrict__ oarray); 343 G4double* __restrict__ oarray); << 345 void G4Logfv(const uint32_t size, G4float const * __restrict__ iarray, G4float* __restrict__ oarray); 344 void logfv(const uint32_t size, G4float const* << 345 G4float* __restrict__ oarray); << 346 void G4Logfv(const uint32_t size, G4float cons << 347 G4float* __restrict__ oarray); << 348 346 349 #endif /* WIN32 */ 347 #endif /* WIN32 */ 350 348 351 #endif /* LOG_H_ */ 349 #endif /* LOG_H_ */ 352 350