File indexing completed on 2026-07-13 08:21:05
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057 #ifndef G4HepEmLog_HH
0058 #define G4HepEmLog_HH 1
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072 #ifdef WIN32
0073
0074 #define VDTLog std::log
0075
0076 #else
0077
0078 #include <limits>
0079 #include <stdint.h>
0080
0081
0082
0083 namespace DVTLogConsts {
0084 const double LOG_UPPER_LIMIT = 1e307;
0085 const double LOG_LOWER_LIMIT = 0;
0086
0087 const double SQRTH = 0.70710678118654752440;
0088 const float MAXNUMF = 3.4028234663852885981170418348451692544e38f;
0089
0090
0091
0092
0093
0094 union ieee754 {
0095 ieee754(){};
0096 ieee754(double thed) { d = thed; };
0097 ieee754(uint64_t thell) { ll = thell; };
0098 ieee754(float thef) { f[0] = thef; };
0099 ieee754(uint32_t thei) { i[0] = thei; };
0100 double d;
0101 float f[2];
0102 uint32_t i[2];
0103 uint64_t ll;
0104 uint16_t s[4];
0105 };
0106
0107 inline double get_log_px(const double x) {
0108 const double PX1log = 1.01875663804580931796E-4;
0109 const double PX2log = 4.97494994976747001425E-1;
0110 const double PX3log = 4.70579119878881725854E0;
0111 const double PX4log = 1.44989225341610930846E1;
0112 const double PX5log = 1.79368678507819816313E1;
0113 const double PX6log = 7.70838733755885391666E0;
0114
0115 double px = PX1log;
0116 px *= x;
0117 px += PX2log;
0118 px *= x;
0119 px += PX3log;
0120 px *= x;
0121 px += PX4log;
0122 px *= x;
0123 px += PX5log;
0124 px *= x;
0125 px += PX6log;
0126 return px;
0127 }
0128
0129 inline double get_log_qx(const double x) {
0130 const double QX1log = 1.12873587189167450590E1;
0131 const double QX2log = 4.52279145837532221105E1;
0132 const double QX3log = 8.29875266912776603211E1;
0133 const double QX4log = 7.11544750618563894466E1;
0134 const double QX5log = 2.31251620126765340583E1;
0135
0136 double qx = x;
0137 qx += QX1log;
0138 qx *= x;
0139 qx += QX2log;
0140 qx *= x;
0141 qx += QX3log;
0142 qx *= x;
0143 qx += QX4log;
0144 qx *= x;
0145 qx += QX5log;
0146 return qx;
0147 }
0148
0149
0150
0151
0152 inline uint64_t dp2uint64(double x) {
0153 ieee754 tmp;
0154 tmp.d = x;
0155 return tmp.ll;
0156 }
0157
0158
0159
0160
0161 inline double uint642dp(uint64_t ll) {
0162 ieee754 tmp;
0163 tmp.ll = ll;
0164 return tmp.d;
0165 }
0166
0167
0168
0169
0170 inline float uint322sp(int x) {
0171 ieee754 tmp;
0172 tmp.i[0] = x;
0173 return tmp.f[0];
0174 }
0175
0176
0177
0178
0179 inline uint32_t sp2uint32(float x)
0180 {
0181 ieee754 tmp;
0182 tmp.f[0] = x;
0183 return tmp.i[0];
0184 }
0185
0186
0187
0188 inline double getMantExponent(const double x, double& fe) {
0189 uint64_t n = dp2uint64(x);
0190
0191
0192
0193 uint64_t le = (n >> 52);
0194
0195
0196 int32_t e =
0197 le;
0198 fe = e - 1023;
0199
0200
0201 n &= 0x800FFFFFFFFFFFFFULL;
0202
0203
0204 const uint64_t p05 = 0x3FE0000000000000ULL;
0205 n |= p05;
0206
0207 return uint642dp(n);
0208 }
0209
0210
0211
0212 inline float getMantExponentf(const float x, float& fe) {
0213 uint32_t n = sp2uint32(x);
0214 int32_t e = (n >> 23) - 127;
0215 fe = e;
0216
0217
0218 const uint32_t p05f = 0x3f000000;
0219 n &= 0x807fffff;
0220 n |= p05f;
0221
0222 return uint322sp(n);
0223 }
0224 }
0225
0226
0227
0228 inline double VDTLog(double x) {
0229 const double original_x = x;
0230
0231
0232 double fe;
0233 x = DVTLogConsts::getMantExponent(x, fe);
0234
0235
0236 x > DVTLogConsts::SQRTH ? fe += 1. : x += x;
0237 x -= 1.0;
0238
0239
0240 double px = DVTLogConsts::get_log_px(x);
0241
0242
0243 const double x2 = x * x;
0244 px *= x;
0245 px *= x2;
0246
0247 const double qx = DVTLogConsts::get_log_qx(x);
0248
0249 double 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 > DVTLogConsts::LOG_UPPER_LIMIT)
0258 res = std::numeric_limits<double>::infinity();
0259 if(original_x < DVTLogConsts::LOG_LOWER_LIMIT)
0260 res = -std::numeric_limits<double>::quiet_NaN();
0261
0262 return res;
0263 }
0264
0265
0266
0267 namespace DVTLogConsts {
0268 const float LOGF_UPPER_LIMIT = MAXNUMF;
0269 const float LOGF_LOWER_LIMIT = 0;
0270
0271 const float PX1logf = 7.0376836292E-2f;
0272 const float PX2logf = -1.1514610310E-1f;
0273 const float PX3logf = 1.1676998740E-1f;
0274 const float PX4logf = -1.2420140846E-1f;
0275 const float PX5logf = 1.4249322787E-1f;
0276 const float PX6logf = -1.6668057665E-1f;
0277 const float PX7logf = 2.0000714765E-1f;
0278 const float PX8logf = -2.4999993993E-1f;
0279 const float PX9logf = 3.3333331174E-1f;
0280
0281 inline float get_log_poly(const float x)
0282 {
0283 float y = x * PX1logf;
0284 y += PX2logf;
0285 y *= x;
0286 y += PX3logf;
0287 y *= x;
0288 y += PX4logf;
0289 y *= x;
0290 y += PX5logf;
0291 y *= x;
0292 y += PX6logf;
0293 y *= x;
0294 y += PX7logf;
0295 y *= x;
0296 y += PX8logf;
0297 y *= x;
0298 y += PX9logf;
0299 return y;
0300 }
0301
0302 const float SQRTHF = 0.707106781186547524f;
0303 }
0304
0305
0306
0307 inline float VDTLogf(float x) {
0308 const float original_x = x;
0309
0310 float fe;
0311 x = DVTLogConsts::getMantExponentf(x, fe);
0312
0313 x > DVTLogConsts::SQRTHF ? fe += 1.f : x += x;
0314 x -= 1.0f;
0315
0316 const float x2 = x * x;
0317
0318 float res = DVTLogConsts::get_log_poly(x);
0319 res *= x2 * x;
0320
0321 res += -2.12194440e-4f * fe;
0322 res += -0.5f * x2;
0323
0324 res = x + res;
0325
0326 res += 0.693359375f * fe;
0327
0328 if(original_x > DVTLogConsts::LOGF_UPPER_LIMIT)
0329 res = std::numeric_limits<float>::infinity();
0330 if(original_x < DVTLogConsts::LOGF_LOWER_LIMIT)
0331 res = -std::numeric_limits<float>::quiet_NaN();
0332
0333 return res;
0334 }
0335
0336
0337
0338 void logv(const uint32_t size, double const* __restrict__ iarray,
0339 double* __restrict__ oarray);
0340 void logfv(const uint32_t size, float const* __restrict__ iarray,
0341 float* __restrict__ oarray);
0342
0343 #endif
0344
0345 #endif