Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-02-21 10:16:42

0001 /*
0002  * log.h
0003  * The basic idea is to exploit Pade polynomials.
0004  * A lot of ideas were inspired by the cephes math library (by Stephen L. Moshier
0005  * moshier@na-net.ornl.gov) as well as actual code. 
0006  * The Cephes library can be found here:  http://www.netlib.org/cephes/
0007  * 
0008  *  Created on: Jun 23, 2012
0009  *      Author: Danilo Piparo, Thomas Hauth, Vincenzo Innocente
0010  */
0011 
0012 /* 
0013  * VDT is free software: you can redistribute it and/or modify
0014  * it under the terms of the GNU Lesser Public License as published by
0015  * the Free Software Foundation, either version 3 of the License, or
0016  * (at your option) any later version.
0017  * 
0018  * This program is distributed in the hope that it will be useful,
0019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0021  * GNU Lesser Public License for more details.
0022  * 
0023  * You should have received a copy of the GNU Lesser Public License
0024  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
0025  */
0026 
0027 #ifndef LOG_H_
0028 #define LOG_H_
0029 
0030 #include "vdtcore_common.h"
0031 #include <limits>
0032 
0033 namespace vdt{
0034 
0035 // local namespace for the constants/functions which are necessary only here
0036 namespace details{
0037 
0038 const double LOG_UPPER_LIMIT = 1e307;
0039 const double LOG_LOWER_LIMIT = 0;
0040 
0041 const double SQRTH = 0.70710678118654752440;
0042 
0043 inline double get_log_px(const double x){
0044     const double PX1log = 1.01875663804580931796E-4;
0045     const double PX2log = 4.97494994976747001425E-1;
0046     const double PX3log = 4.70579119878881725854E0;
0047     const double PX4log = 1.44989225341610930846E1;
0048     const double PX5log = 1.79368678507819816313E1;
0049     const double PX6log = 7.70838733755885391666E0;
0050 
0051     double px = PX1log;
0052     px *= x;
0053     px += PX2log;
0054     px *= x;
0055     px += PX3log;
0056     px *= x;
0057     px += PX4log;
0058     px *= x;
0059     px += PX5log;
0060     px *= x;
0061     px += PX6log;
0062     return px;
0063 
0064 }
0065 
0066 inline double get_log_qx(const double x){
0067     const double QX1log = 1.12873587189167450590E1;
0068     const double QX2log = 4.52279145837532221105E1;
0069     const double QX3log = 8.29875266912776603211E1;
0070     const double QX4log = 7.11544750618563894466E1;
0071     const double QX5log = 2.31251620126765340583E1;
0072 
0073     double qx = x;
0074     qx += QX1log;
0075     qx *=x;
0076     qx += QX2log;
0077     qx *=x;
0078     qx += QX3log;
0079     qx *=x;
0080     qx += QX4log;
0081     qx *=x;
0082     qx += QX5log;
0083     return qx;
0084 }
0085 
0086 }
0087 
0088 // Log double precision --------------------------------------------------------
0089 inline double fast_log(double x){
0090 
0091     const double original_x = x;
0092 
0093     /* separate mantissa from exponent */
0094     double fe;
0095     x = details::getMantExponent(x,fe);
0096 
0097     // blending
0098     x > details::SQRTH? fe+=1. : x+=x ;
0099     x -= 1.0;
0100 
0101     /* rational form */
0102     double px =  details::get_log_px(x);
0103 
0104     //for the final formula
0105     const double x2 = x*x;
0106     px *= x;
0107     px *= x2;
0108 
0109     const double qx = details::get_log_qx(x);
0110 
0111     double res = px / qx ;
0112 
0113     res -= fe * 2.121944400546905827679e-4;
0114     res -= 0.5 * x2  ;
0115 
0116     res = x + res;
0117     res += fe * 0.693359375;
0118 
0119     if (original_x > details::LOG_UPPER_LIMIT)
0120         res = std::numeric_limits<double>::infinity();
0121     if (original_x < details::LOG_LOWER_LIMIT) // THIS IS NAN!
0122         res =  - std::numeric_limits<double>::quiet_NaN();
0123 
0124     return res;
0125 
0126 }
0127 
0128 // Log single precision --------------------------------------------------------
0129 
0130 
0131 
0132 namespace details{
0133 
0134 const float LOGF_UPPER_LIMIT = MAXNUMF;
0135 const float LOGF_LOWER_LIMIT = 0;
0136 
0137 const float PX1logf = 7.0376836292E-2f;
0138 const float PX2logf = -1.1514610310E-1f;
0139 const float PX3logf = 1.1676998740E-1f;
0140 const float PX4logf = -1.2420140846E-1f;
0141 const float PX5logf = 1.4249322787E-1f;
0142 const float PX6logf = -1.6668057665E-1f;
0143 const float PX7logf = 2.0000714765E-1f;
0144 const float PX8logf = -2.4999993993E-1f;
0145 const float PX9logf = 3.3333331174E-1f;
0146 
0147 inline float get_log_poly(const float x){
0148     float y = x*PX1logf;
0149     y += PX2logf;
0150     y *= x;
0151     y += PX3logf;
0152     y *= x;
0153     y += PX4logf;
0154     y *= x;
0155     y += PX5logf;
0156     y *= x;
0157     y += PX6logf;
0158     y *= x;
0159     y += PX7logf;
0160     y *= x;
0161     y += PX8logf;
0162     y *= x;
0163     y += PX9logf;
0164     return y;
0165 }
0166 
0167 const float SQRTHF = 0.707106781186547524f;
0168 
0169 }
0170 
0171 // Log single precision --------------------------------------------------------
0172 inline float fast_logf( float x ) {
0173 
0174     const float original_x = x;
0175 
0176     float fe;
0177     x = details::getMantExponentf( x, fe);
0178 
0179     x > details::SQRTHF? fe+=1.f : x+=x ;
0180     x -= 1.0f;
0181 
0182     const float x2 = x*x;
0183 
0184     float res = details::get_log_poly(x);
0185     res *= x2*x;
0186 
0187     res += -2.12194440e-4f * fe;
0188     res +=  -0.5f * x2;
0189 
0190     res= x + res;
0191 
0192     res += 0.693359375f * fe;
0193 
0194     if (original_x > details::LOGF_UPPER_LIMIT)
0195         res = std::numeric_limits<float>::infinity();
0196     if (original_x < details::LOGF_LOWER_LIMIT)
0197         res = -std::numeric_limits<float>::quiet_NaN();
0198 
0199     return res;
0200 }
0201 
0202 
0203 //------------------------------------------------------------------------------
0204 
0205 void logv(const uint32_t size, double const * __restrict__ iarray, double* __restrict__ oarray);
0206 void fast_logv(const uint32_t size, double const * __restrict__ iarray, double* __restrict__ oarray);
0207 void logfv(const uint32_t size, float const * __restrict__ iarray, float* __restrict__ oarray);
0208 void fast_logfv(const uint32_t size, float const * __restrict__ iarray, float* __restrict__ oarray);
0209 
0210 } //vdt namespace
0211 
0212 #endif /* LOG_H_ */