Go to the documentation of this file.00001 #ifndef DataFormats_Math_FastMath_h
00002 #define DataFormats_Math_FastMath_h
00003
00004
00005 #include<cmath>
00006 #include<utility>
00007 #ifdef __SSE2__
00008 # include <emmintrin.h>
00009 #endif
00010 namespace fastmath {
00011 inline float invSqrt( float in ) {
00012 #ifndef __SSE2__
00013 return 1.f/std::sqrt(in);
00014 #else
00015 float out;
00016 _mm_store_ss( &out, _mm_rsqrt_ss( _mm_load_ss( &in ) ) );
00017
00018 return out * (1.5f - 0.5f * in * out * out);
00019 #endif
00020 }
00021
00022 inline double invSqrt(double in ) {
00023 return 1./std::sqrt(in);
00024 }
00025
00026 }
00027
00028 namespace fastmath_details {
00029 const double _2pi = (2.0 * 3.1415926535897932384626434);
00030 const float _2pif = float(_2pi);
00031 extern float atanbuf_[257 * 2];
00032 extern double datanbuf_[513 * 2];
00033 }
00034
00035 namespace fastmath {
00036
00037
00038
00039
00040 inline std::pair<float,float> atan2r(float y_, float x_, bool overR=false) {
00041 using namespace fastmath_details;
00042 float mag2 = x_ * x_ + y_ * y_;
00043 if(!(mag2 > 0)) { return std::pair<float,float>(0.f,0.f); }
00044
00045
00046 float rinv = invSqrt(mag2);
00047 unsigned int flags = 0;
00048 float x, y;
00049 union {
00050 float f;
00051 int i;
00052 } yp;
00053 yp.f = 32768.f;
00054 if (y_ < 0 ) { flags |= 4; y_ = -y_; }
00055 if (x_ < 0 ) { flags |= 2; x_ = -x_; }
00056 if (y_ > x_) {
00057 flags |= 1;
00058 x = rinv * y_; y = rinv * x_; yp.f += y;
00059 }
00060 else {
00061 x = rinv * x_; y = rinv * y_; yp.f += y;
00062 }
00063 int ind = (yp.i & 0x01FF) * 2;
00064
00065 float* asbuf = (float*)(atanbuf_ + ind);
00066 float sv = yp.f - 32768.f;
00067 float cv = asbuf[0];
00068 float asv = asbuf[1];
00069 sv = y * cv - x * sv;
00070
00071 float asvd = 6.f + sv * sv; sv *= float(1.0f / 6.0f);
00072 float th = asv + asvd * sv;
00073 if (flags & 1) { th = (_2pif / 4.f) - th; }
00074 if (flags & 2) { th = (_2pif / 2.f) - th; }
00075 if (flags & 4) { th = -th; }
00076 return std::pair<float,float>(th,overR ? rinv : rinv*mag2);
00077 }
00078
00079
00080
00081
00082 inline std::pair<double, double> atan2r(double y_, double x_, bool overR=false) {
00083 using namespace fastmath_details;
00084
00085 double mag2 = x_ * x_ + y_ * y_;
00086 if(!(mag2 > 0)) { return std::pair<double, double>(0.,0.); }
00087
00088 double r_ = std::sqrt(mag2);
00089 double rinv = 1./r_;
00090 unsigned int flags = 0;
00091 double x, y;
00092 const double _2p43 = 65536.0 * 65536.0 * 2048.0;
00093 union {
00094 double d;
00095 int i[2];
00096 } yp;
00097
00098 yp.d = _2p43;
00099 if (y_ < 0) { flags |= 4; y_ = -y_; }
00100 if (x_ < 0) { flags |= 2; x_ = -x_; }
00101 if (y_ > x_) {
00102 flags |= 1;
00103 x = rinv * y_; y = rinv * x_; yp.d += y;
00104 }
00105 else {
00106 x = rinv * x_; y = rinv * y_; yp.d += y;
00107 }
00108
00109 int ind = (yp.i[0] & 0x03FF) * 2;
00110
00111 double* dasbuf = (double*)(datanbuf_ + ind);
00112 double sv = yp.d - _2p43;
00113 double cv = dasbuf[0];
00114 double asv = dasbuf[1];
00115 sv = y * cv - x * sv;
00116
00117
00118 double asvd = 6 + sv * sv; sv *= double(1.0 / 6.0);
00119 double th = asv + asvd * sv;
00120 if (flags & 1) { th = (_2pi / 4) - th; }
00121 if (flags & 2) { th = (_2pi / 2) - th; }
00122 if (flags & 4) { th = -th; }
00123 return std::pair<double,double>(th,overR ? rinv : r_);
00124 }
00125
00126
00127 template<typename T>
00128 inline std::pair<T,T> etaphi(T x, T y, T z) {
00129 std::pair<T,T> por = atan2r(y,x, true);
00130 x = z*por.second;
00131 return std::pair<float,float>( std::log(x+std::sqrt(x*x+T(1))), por.first);
00132 }
00133
00134 }
00135
00136
00137 #endif