|
|
|||
File indexing completed on 2026-09-16 09:10:25
0001 // 0002 // ******************************************************************** 0003 // * License and Disclaimer * 0004 // * * 0005 // * The Geant4 software is copyright of the Copyright Holders of * 0006 // * the Geant4 Collaboration. It is provided under the terms and * 0007 // * conditions of the Geant4 Software License, included in the file * 0008 // * LICENSE and available at http://cern.ch/geant4/license . These * 0009 // * include a list of copyright holders. * 0010 // * * 0011 // * Neither the authors of this software system, nor their employing * 0012 // * institutes,nor the agencies providing financial support for this * 0013 // * work make any representation or warranty, express or implied, * 0014 // * regarding this software system or assume any liability for its * 0015 // * use. Please see the license in the file LICENSE and URL above * 0016 // * for the full disclaimer and the limitation of liability. * 0017 // * * 0018 // * This code implementation is the result of the scientific and * 0019 // * technical work of the GEANT4 collaboration. * 0020 // * By using, copying, modifying or distributing the software (or * 0021 // * any work based on the software) you agree to acknowledge its * 0022 // * use in resulting scientific publications, and indicate your * 0023 // * acceptance of all terms of the Geant4 Software license. * 0024 // ******************************************************************** 0025 // 0026 // G4Exp 0027 // 0028 // Class description: 0029 // 0030 // The basic idea is to exploit Pade polynomials. 0031 // A lot of ideas were inspired by the cephes math library 0032 // (by Stephen L. Moshier moshier@na-net.ornl.gov) as well as actual code. 0033 // The Cephes library can be found here: http://www.netlib.org/cephes/ 0034 // Code and algorithms for G4Exp have been extracted and adapted for Geant4 0035 // from the original implementation in the VDT mathematical library 0036 // (https://svnweb.cern.ch/trac/vdt), version 0.3.7. 0037 0038 // Original implementation created on: Jun 23, 2012 0039 // Authors: Danilo Piparo, Thomas Hauth, Vincenzo Innocente 0040 // 0041 // -------------------------------------------------------------------- 0042 /* 0043 * VDT is free software: you can redistribute it and/or modify 0044 * it under the terms of the GNU Lesser Public License as published by 0045 * the Free Software Foundation, either version 3 of the License, or 0046 * (at your option) any later version. 0047 * 0048 * This program is distributed in the hope that it will be useful, 0049 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0050 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0051 * GNU Lesser Public License for more details. 0052 * 0053 * You should have received a copy of the GNU Lesser Public License 0054 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0055 */ 0056 // -------------------------------------------------------------------- 0057 #ifndef G4Exp_hh 0058 #define G4Exp_hh 1 0059 0060 #ifdef WIN32 0061 0062 # define G4Exp std::exp 0063 0064 #else 0065 0066 # include "G4Types.hh" 0067 # include "G4IEEE754.hh" 0068 # include <cstdint> 0069 # include <limits> 0070 0071 namespace G4ExpConsts 0072 { 0073 const G4double EXP_LIMIT = 708; 0074 0075 const G4double PX1exp = 1.26177193074810590878E-4; 0076 const G4double PX2exp = 3.02994407707441961300E-2; 0077 const G4double PX3exp = 9.99999999999999999910E-1; 0078 const G4double QX1exp = 3.00198505138664455042E-6; 0079 const G4double QX2exp = 2.52448340349684104192E-3; 0080 const G4double QX3exp = 2.27265548208155028766E-1; 0081 const G4double QX4exp = 2.00000000000000000009E0; 0082 0083 const G4double LOG2E = 1.4426950408889634073599; // 1/log(2) 0084 0085 const G4float MAXLOGF = 88.72283905206835f; 0086 const G4float MINLOGF = -88.f; 0087 0088 const G4float C1F = 0.693359375f; 0089 const G4float C2F = -2.12194440e-4f; 0090 0091 const G4float PX1expf = 1.9875691500E-4f; 0092 const G4float PX2expf = 1.3981999507E-3f; 0093 const G4float PX3expf = 8.3334519073E-3f; 0094 const G4float PX4expf = 4.1665795894E-2f; 0095 const G4float PX5expf = 1.6666665459E-1f; 0096 const G4float PX6expf = 5.0000001201E-1f; 0097 0098 const G4float LOG2EF = 1.44269504088896341f; 0099 0100 //---------------------------------------------------------------------------- 0101 /** 0102 * A vectorisable floor implementation, not only triggered by fast-math. 0103 * These functions do not distinguish between -0.0 and 0.0, so are not IEC6509 0104 * compliant for argument -0.0 0105 **/ 0106 inline G4double fpfloor(const G4double x) 0107 { 0108 // no problem since exp is defined between -708 and 708. Int is enough for 0109 // it! 0110 int32_t ret = int32_t(x); 0111 ret -= (G4IEEE754::sp2uint32(x) >> 31); 0112 return ret; 0113 } 0114 0115 //---------------------------------------------------------------------------- 0116 /** 0117 * A vectorisable floor implementation, not only triggered by fast-math. 0118 * These functions do not distinguish between -0.0 and 0.0, so are not IEC6509 0119 * compliant for argument -0.0 0120 **/ 0121 inline G4float fpfloor(const G4float x) 0122 { 0123 int32_t ret = int32_t(x); 0124 ret -= (G4IEEE754::sp2uint32(x) >> 31); 0125 return ret; 0126 } 0127 } // namespace G4ExpConsts 0128 0129 // Exp double precision -------------------------------------------------------- 0130 0131 /// Exponential Function double precision 0132 inline G4double G4Exp(G4double initial_x) 0133 { 0134 G4double x = initial_x; 0135 G4double px = G4ExpConsts::fpfloor(G4ExpConsts::LOG2E * x + 0.5); 0136 0137 const int32_t n = int32_t(px); 0138 0139 x -= px * 6.93145751953125E-1; 0140 x -= px * 1.42860682030941723212E-6; 0141 0142 const G4double xx = x * x; 0143 0144 // px = x * P(x**2). 0145 px = G4ExpConsts::PX1exp; 0146 px *= xx; 0147 px += G4ExpConsts::PX2exp; 0148 px *= xx; 0149 px += G4ExpConsts::PX3exp; 0150 px *= x; 0151 0152 // Evaluate Q(x**2). 0153 G4double qx = G4ExpConsts::QX1exp; 0154 qx *= xx; 0155 qx += G4ExpConsts::QX2exp; 0156 qx *= xx; 0157 qx += G4ExpConsts::QX3exp; 0158 qx *= xx; 0159 qx += G4ExpConsts::QX4exp; 0160 0161 // e**x = 1 + 2x P(x**2)/( Q(x**2) - P(x**2) ) 0162 x = px / (qx - px); 0163 x = 1.0 + 2.0 * x; 0164 0165 // Build 2^n in double. 0166 x *= G4IEEE754::uint642dp((((uint64_t) n) + 1023) << 52); 0167 0168 if(initial_x > G4ExpConsts::EXP_LIMIT) 0169 x = std::numeric_limits<G4double>::infinity(); 0170 if(initial_x < -G4ExpConsts::EXP_LIMIT) 0171 x = 0.; 0172 0173 return x; 0174 } 0175 0176 // Exp single precision -------------------------------------------------------- 0177 0178 /// Exponential Function single precision 0179 inline G4float G4Expf(G4float initial_x) 0180 { 0181 G4float x = initial_x; 0182 0183 G4float z = 0184 G4ExpConsts::fpfloor(G4ExpConsts::LOG2EF * x + 0185 0.5f); /* std::floor() truncates toward -infinity. */ 0186 0187 x -= z * G4ExpConsts::C1F; 0188 x -= z * G4ExpConsts::C2F; 0189 const int32_t n = int32_t(z); 0190 0191 const G4float x2 = x * x; 0192 0193 z = x * G4ExpConsts::PX1expf; 0194 z += G4ExpConsts::PX2expf; 0195 z *= x; 0196 z += G4ExpConsts::PX3expf; 0197 z *= x; 0198 z += G4ExpConsts::PX4expf; 0199 z *= x; 0200 z += G4ExpConsts::PX5expf; 0201 z *= x; 0202 z += G4ExpConsts::PX6expf; 0203 z *= x2; 0204 z += x + 1.0f; 0205 0206 /* multiply by power of 2 */ 0207 z *= G4IEEE754::uint322sp((n + 0x7f) << 23); 0208 0209 if(initial_x > G4ExpConsts::MAXLOGF) 0210 z = std::numeric_limits<G4float>::infinity(); 0211 if(initial_x < G4ExpConsts::MINLOGF) 0212 z = 0.f; 0213 0214 return z; 0215 } 0216 0217 #endif /* WIN32 */ 0218 0219 #endif
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|