Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:58:38

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 // G4Log
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 //      Author: 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 G4Log_hh
0058 #define G4Log_hh 1
0059 
0060 #ifdef WIN32
0061 
0062 #  define G4Log std::log
0063 
0064 #else
0065 
0066 #  include "G4Types.hh"
0067 
0068 #  include <cstdint>
0069 #  include <limits>
0070 
0071 // local namespace for the constants/functions which are necessary only here
0072 //
0073 namespace G4LogConsts
0074 {
0075   const G4double LOG_UPPER_LIMIT = 1e307;
0076   const G4double LOG_LOWER_LIMIT = 0;
0077 
0078   const G4double SQRTH  = 0.70710678118654752440;
0079   const G4float MAXNUMF = 3.4028234663852885981170418348451692544e38f;
0080 
0081   //----------------------------------------------------------------------------
0082   // Used to switch between different type of interpretations of the data
0083   // (64 bits)
0084   //
0085   union ieee754
0086   {
0087     ieee754()= default;
0088     ieee754(G4double thed) { d = thed; };
0089     ieee754(uint64_t thell) { ll = thell; };
0090     ieee754(G4float thef) { f[0] = thef; };
0091     ieee754(uint32_t thei) { i[0] = thei; };
0092     G4double d;
0093     G4float f[2];
0094     uint32_t i[2];
0095     uint64_t ll;
0096     uint16_t s[4];
0097   };
0098 
0099   inline G4double get_log_px(const G4double x)
0100   {
0101     const G4double PX1log = 1.01875663804580931796E-4;
0102     const G4double PX2log = 4.97494994976747001425E-1;
0103     const G4double PX3log = 4.70579119878881725854E0;
0104     const G4double PX4log = 1.44989225341610930846E1;
0105     const G4double PX5log = 1.79368678507819816313E1;
0106     const G4double PX6log = 7.70838733755885391666E0;
0107 
0108     G4double px = PX1log;
0109     px *= x;
0110     px += PX2log;
0111     px *= x;
0112     px += PX3log;
0113     px *= x;
0114     px += PX4log;
0115     px *= x;
0116     px += PX5log;
0117     px *= x;
0118     px += PX6log;
0119     return px;
0120   }
0121 
0122   inline G4double get_log_qx(const G4double x)
0123   {
0124     const G4double QX1log = 1.12873587189167450590E1;
0125     const G4double QX2log = 4.52279145837532221105E1;
0126     const G4double QX3log = 8.29875266912776603211E1;
0127     const G4double QX4log = 7.11544750618563894466E1;
0128     const G4double QX5log = 2.31251620126765340583E1;
0129 
0130     G4double qx = x;
0131     qx += QX1log;
0132     qx *= x;
0133     qx += QX2log;
0134     qx *= x;
0135     qx += QX3log;
0136     qx *= x;
0137     qx += QX4log;
0138     qx *= x;
0139     qx += QX5log;
0140     return qx;
0141   }
0142 
0143   //----------------------------------------------------------------------------
0144   // Converts a double to an unsigned long long
0145   //
0146   inline uint64_t dp2uint64(G4double x)
0147   {
0148     ieee754 tmp;
0149     tmp.d = x;
0150     return tmp.ll;
0151   }
0152 
0153   //----------------------------------------------------------------------------
0154   // Converts an unsigned long long to a double
0155   //
0156   inline G4double uint642dp(uint64_t ll)
0157   {
0158     ieee754 tmp;
0159     tmp.ll = ll;
0160     return tmp.d;
0161   }
0162 
0163   //----------------------------------------------------------------------------
0164   // Converts an int to a float
0165   //
0166   inline G4float uint322sp(G4int x)
0167   {
0168     ieee754 tmp;
0169     tmp.i[0] = x;
0170     return tmp.f[0];
0171   }
0172 
0173   //----------------------------------------------------------------------------
0174   // Converts a float to an int
0175   //
0176   inline uint32_t sp2uint32(G4float x)
0177   {
0178     ieee754 tmp;
0179     tmp.f[0] = x;
0180     return tmp.i[0];
0181   }
0182 
0183   //----------------------------------------------------------------------------
0184   /// Like frexp but vectorising and the exponent is a double.
0185   inline G4double getMantExponent(const G4double x, G4double& fe)
0186   {
0187     uint64_t n = dp2uint64(x);
0188 
0189     // Shift to the right up to the beginning of the exponent.
0190     // Then with a mask, cut off the sign bit
0191     uint64_t le = (n >> 52);
0192 
0193     // chop the head of the number: an int contains more than 11 bits (32)
0194     int32_t e =
0195       (int32_t)le;  // This is important since sums on uint64_t do not vectorise
0196     fe = e - 1023;
0197 
0198     // This puts to 11 zeroes the exponent
0199     n &= 0x800FFFFFFFFFFFFFULL;
0200     // build a mask which is 0.5, i.e. an exponent equal to 1022
0201     // which means *2, see the above +1.
0202     const uint64_t p05 = 0x3FE0000000000000ULL;  // dp2uint64(0.5);
0203     n |= p05;
0204 
0205     return uint642dp(n);
0206   }
0207 
0208   //----------------------------------------------------------------------------
0209   /// Like frexp but vectorising and the exponent is a float.
0210   inline G4float getMantExponentf(const G4float x, G4float& fe)
0211   {
0212     uint32_t n = sp2uint32(x);
0213     int32_t e  = (n >> 23) - 127;
0214     fe         = e;
0215 
0216     // fractional part
0217     const uint32_t p05f = 0x3f000000;  // //sp2uint32(0.5);
0218     n &= 0x807fffff;                   // ~0x7f800000;
0219     n |= p05f;
0220 
0221     return uint322sp(n);
0222   }
0223 }  // namespace G4LogConsts
0224 
0225 // Log double precision --------------------------------------------------------
0226 
0227 inline G4double G4Log(G4double x)
0228 {
0229   const G4double original_x = x;
0230 
0231   /* separate mantissa from exponent */
0232   G4double fe;
0233   x = G4LogConsts::getMantExponent(x, fe);
0234 
0235   // blending
0236   x > G4LogConsts::SQRTH ? fe += 1. : x += x;
0237   x -= 1.0;
0238 
0239   /* rational form */
0240   G4double px = G4LogConsts::get_log_px(x);
0241 
0242   // for the final formula
0243   const G4double x2 = x * x;
0244   px *= x;
0245   px *= x2;
0246 
0247   const G4double qx = G4LogConsts::get_log_qx(x);
0248 
0249   G4double res = px / qx;
0250 
0251   res -= fe * 2.121944400546905827679e-4;
0252   res -= 0.5 * x2;
0253 
0254   res = x + res;
0255   res += fe * 0.693359375;
0256 
0257   if(original_x > G4LogConsts::LOG_UPPER_LIMIT)
0258     res = std::numeric_limits<G4double>::infinity();
0259   if(original_x < G4LogConsts::LOG_LOWER_LIMIT)  // THIS IS NAN!
0260     res = -std::numeric_limits<G4double>::quiet_NaN();
0261 
0262   return res;
0263 }
0264 
0265 // Log single precision --------------------------------------------------------
0266 
0267 namespace G4LogConsts
0268 {
0269   const G4float LOGF_UPPER_LIMIT = MAXNUMF;
0270   const G4float LOGF_LOWER_LIMIT = 0;
0271 
0272   const G4float PX1logf = 7.0376836292E-2f;
0273   const G4float PX2logf = -1.1514610310E-1f;
0274   const G4float PX3logf = 1.1676998740E-1f;
0275   const G4float PX4logf = -1.2420140846E-1f;
0276   const G4float PX5logf = 1.4249322787E-1f;
0277   const G4float PX6logf = -1.6668057665E-1f;
0278   const G4float PX7logf = 2.0000714765E-1f;
0279   const G4float PX8logf = -2.4999993993E-1f;
0280   const G4float PX9logf = 3.3333331174E-1f;
0281 
0282   inline G4float get_log_poly(const G4float x)
0283   {
0284     G4float y = x * PX1logf;
0285     y += PX2logf;
0286     y *= x;
0287     y += PX3logf;
0288     y *= x;
0289     y += PX4logf;
0290     y *= x;
0291     y += PX5logf;
0292     y *= x;
0293     y += PX6logf;
0294     y *= x;
0295     y += PX7logf;
0296     y *= x;
0297     y += PX8logf;
0298     y *= x;
0299     y += PX9logf;
0300     return y;
0301   }
0302 
0303   const G4float SQRTHF = 0.707106781186547524f;
0304 }  // namespace G4LogConsts
0305 
0306 // Log single precision --------------------------------------------------------
0307 
0308 inline G4float G4Logf(G4float x)
0309 {
0310   const G4float original_x = x;
0311 
0312   G4float fe;
0313   x = G4LogConsts::getMantExponentf(x, fe);
0314 
0315   x > G4LogConsts::SQRTHF ? fe += 1.f : x += x;
0316   x -= 1.0f;
0317 
0318   const G4float x2 = x * x;
0319 
0320   G4float res = G4LogConsts::get_log_poly(x);
0321   res *= x2 * x;
0322 
0323   res += -2.12194440e-4f * fe;
0324   res += -0.5f * x2;
0325 
0326   res = x + res;
0327 
0328   res += 0.693359375f * fe;
0329 
0330   if(original_x > G4LogConsts::LOGF_UPPER_LIMIT)
0331     res = std::numeric_limits<G4float>::infinity();
0332   if(original_x < G4LogConsts::LOGF_LOWER_LIMIT)
0333     res = -std::numeric_limits<G4float>::quiet_NaN();
0334 
0335   return res;
0336 }
0337 
0338 //------------------------------------------------------------------------------
0339 
0340 void logv(const uint32_t size, G4double const* __restrict__ iarray,
0341           G4double* __restrict__ oarray);
0342 void G4Logv(const uint32_t size, G4double const* __restrict__ iarray,
0343             G4double* __restrict__ oarray);
0344 void logfv(const uint32_t size, G4float const* __restrict__ iarray,
0345            G4float* __restrict__ oarray);
0346 void G4Logfv(const uint32_t size, G4float const* __restrict__ iarray,
0347              G4float* __restrict__ oarray);
0348 
0349 #endif /* WIN32 */
0350 
0351 #endif /* LOG_H_ */