Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-13 09:10:15

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 #  include "G4IEEE754.hh"
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   inline G4double get_log_px(const G4double x)
0082   {
0083     const G4double PX1log = 1.01875663804580931796E-4;
0084     const G4double PX2log = 4.97494994976747001425E-1;
0085     const G4double PX3log = 4.70579119878881725854E0;
0086     const G4double PX4log = 1.44989225341610930846E1;
0087     const G4double PX5log = 1.79368678507819816313E1;
0088     const G4double PX6log = 7.70838733755885391666E0;
0089 
0090     G4double px = PX1log;
0091     px *= x;
0092     px += PX2log;
0093     px *= x;
0094     px += PX3log;
0095     px *= x;
0096     px += PX4log;
0097     px *= x;
0098     px += PX5log;
0099     px *= x;
0100     px += PX6log;
0101     return px;
0102   }
0103 
0104   inline G4double get_log_qx(const G4double x)
0105   {
0106     const G4double QX1log = 1.12873587189167450590E1;
0107     const G4double QX2log = 4.52279145837532221105E1;
0108     const G4double QX3log = 8.29875266912776603211E1;
0109     const G4double QX4log = 7.11544750618563894466E1;
0110     const G4double QX5log = 2.31251620126765340583E1;
0111 
0112     G4double qx = x;
0113     qx += QX1log;
0114     qx *= x;
0115     qx += QX2log;
0116     qx *= x;
0117     qx += QX3log;
0118     qx *= x;
0119     qx += QX4log;
0120     qx *= x;
0121     qx += QX5log;
0122     return qx;
0123   }
0124 
0125   //----------------------------------------------------------------------------
0126   /// Like frexp but vectorising and the exponent is a double.
0127   inline G4double getMantExponent(const G4double x, G4double& fe)
0128   {
0129     uint64_t n = G4IEEE754::dp2uint64(x);
0130 
0131     // Shift to the right up to the beginning of the exponent.
0132     // Then with a mask, cut off the sign bit
0133     uint64_t le = (n >> 52);
0134 
0135     // chop the head of the number: an int contains more than 11 bits (32)
0136     int32_t e =
0137       (int32_t)le;  // This is important since sums on uint64_t do not vectorise
0138     fe = e - 1023;
0139 
0140     // This puts to 11 zeroes the exponent
0141     n &= 0x800FFFFFFFFFFFFFULL;
0142     // build a mask which is 0.5, i.e. an exponent equal to 1022
0143     // which means *2, see the above +1.
0144     const uint64_t p05 = 0x3FE0000000000000ULL;  // dp2uint64(0.5);
0145     n |= p05;
0146 
0147     return G4IEEE754::uint642dp(n);
0148   }
0149 
0150   //----------------------------------------------------------------------------
0151   /// Like frexp but vectorising and the exponent is a float.
0152   inline G4float getMantExponentf(const G4float x, G4float& fe)
0153   {
0154     uint32_t n = G4IEEE754::sp2uint32(x);
0155     int32_t e  = (n >> 23) - 127;
0156     fe         = e;
0157 
0158     // fractional part
0159     const uint32_t p05f = 0x3f000000;  // //sp2uint32(0.5);
0160     n &= 0x807fffff;                   // ~0x7f800000;
0161     n |= p05f;
0162 
0163     return G4IEEE754::uint322sp(n);
0164   }
0165 }  // namespace G4LogConsts
0166 
0167 // Log double precision --------------------------------------------------------
0168 
0169 inline G4double G4Log(G4double x)
0170 {
0171   const G4double original_x = x;
0172 
0173   /* separate mantissa from exponent */
0174   G4double fe;
0175   x = G4LogConsts::getMantExponent(x, fe);
0176 
0177   // blending
0178   x > G4LogConsts::SQRTH ? fe += 1. : x += x;
0179   x -= 1.0;
0180 
0181   /* rational form */
0182   G4double px = G4LogConsts::get_log_px(x);
0183 
0184   // for the final formula
0185   const G4double x2 = x * x;
0186   px *= x;
0187   px *= x2;
0188 
0189   const G4double qx = G4LogConsts::get_log_qx(x);
0190 
0191   G4double res = px / qx;
0192 
0193   res -= fe * 2.121944400546905827679e-4;
0194   res -= 0.5 * x2;
0195 
0196   res = x + res;
0197   res += fe * 0.693359375;
0198 
0199   if(original_x > G4LogConsts::LOG_UPPER_LIMIT)
0200     res = std::numeric_limits<G4double>::infinity();
0201   if(original_x < G4LogConsts::LOG_LOWER_LIMIT)  // THIS IS NAN!
0202     res = -std::numeric_limits<G4double>::quiet_NaN();
0203 
0204   return res;
0205 }
0206 
0207 // Log single precision --------------------------------------------------------
0208 
0209 namespace G4LogConsts
0210 {
0211   const G4float LOGF_UPPER_LIMIT = MAXNUMF;
0212   const G4float LOGF_LOWER_LIMIT = 0;
0213 
0214   const G4float PX1logf = 7.0376836292E-2f;
0215   const G4float PX2logf = -1.1514610310E-1f;
0216   const G4float PX3logf = 1.1676998740E-1f;
0217   const G4float PX4logf = -1.2420140846E-1f;
0218   const G4float PX5logf = 1.4249322787E-1f;
0219   const G4float PX6logf = -1.6668057665E-1f;
0220   const G4float PX7logf = 2.0000714765E-1f;
0221   const G4float PX8logf = -2.4999993993E-1f;
0222   const G4float PX9logf = 3.3333331174E-1f;
0223 
0224   inline G4float get_log_poly(const G4float x)
0225   {
0226     G4float y = x * PX1logf;
0227     y += PX2logf;
0228     y *= x;
0229     y += PX3logf;
0230     y *= x;
0231     y += PX4logf;
0232     y *= x;
0233     y += PX5logf;
0234     y *= x;
0235     y += PX6logf;
0236     y *= x;
0237     y += PX7logf;
0238     y *= x;
0239     y += PX8logf;
0240     y *= x;
0241     y += PX9logf;
0242     return y;
0243   }
0244 
0245   const G4float SQRTHF = 0.707106781186547524f;
0246 }  // namespace G4LogConsts
0247 
0248 // Log single precision --------------------------------------------------------
0249 
0250 inline G4float G4Logf(G4float x)
0251 {
0252   const G4float original_x = x;
0253 
0254   G4float fe;
0255   x = G4LogConsts::getMantExponentf(x, fe);
0256 
0257   x > G4LogConsts::SQRTHF ? fe += 1.f : x += x;
0258   x -= 1.0f;
0259 
0260   const G4float x2 = x * x;
0261 
0262   G4float res = G4LogConsts::get_log_poly(x);
0263   res *= x2 * x;
0264 
0265   res += -2.12194440e-4f * fe;
0266   res += -0.5f * x2;
0267 
0268   res = x + res;
0269 
0270   res += 0.693359375f * fe;
0271 
0272   if(original_x > G4LogConsts::LOGF_UPPER_LIMIT)
0273     res = std::numeric_limits<G4float>::infinity();
0274   if(original_x < G4LogConsts::LOGF_LOWER_LIMIT)
0275     res = -std::numeric_limits<G4float>::quiet_NaN();
0276 
0277   return res;
0278 }
0279 
0280 #endif /* WIN32 */
0281 
0282 #endif /* LOG_H_ */