erf.hpp

来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 1,085 行 · 第 1/3 页

HPP
1,085
字号
template <class T, class Policy>T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<64>& t){   BOOST_MATH_STD_USING   BOOST_MATH_INSTRUMENT_CODE("64-bit precision erf_imp called");   if(z < 0)   {      if(!invert)         return -erf_imp(-z, invert, pol, t);      else if(z < -0.5)         return 2 - erf_imp(-z, invert, pol, t);      else         return 1 + erf_imp(-z, false, pol, t);   }   T result;   //   // Big bunch of selection statements now to pick which   // implementation to use, try to put most likely options   // first:   //   if(z < 0.5)   {      //      // We're going to calculate erf:      //      if(z == 0)      {         result = 0;      }      else if(z < 1e-10)      {         result = z * 1.125 + z * 0.003379167095512573896158903121545171688L;      }      else      {         // Max Error found at long double precision =   1.623299e-20         // Maximum Deviation Found:                     4.326e-22         // Expected Error Term:                         -4.326e-22         // Maximum Relative Change in Control Points:   1.474e-04         static const T Y = 1.044948577880859375f;         static const T P[] = {                0.0834305892146531988966L,            -0.338097283075565413695L,            -0.0509602734406067204596L,            -0.00904906346158537794396L,            -0.000489468651464798669181L,            -0.200305626366151877759e-4L,         };         static const T Q[] = {                1L,            0.455817300515875172439L,            0.0916537354356241792007L,            0.0102722652675910031202L,            0.000650511752687851548735L,            0.189532519105655496778e-4L,         };         result = z * (Y + tools::evaluate_polynomial(P, z * z) / tools::evaluate_polynomial(Q, z * z));      }   }   else if((z < 110) || ((z < 110) && invert))  // TODO FIXME!!!   {      //      // We'll be calculating erfc:      //      invert = !invert;      if(z < 1.5)      {         // Max Error found at long double precision =   3.239590e-20         // Maximum Deviation Found:                     2.241e-20         // Expected Error Term:                         -2.241e-20         // Maximum Relative Change in Control Points:   5.110e-03         static const T Y = 0.405935764312744140625f;         static const T P[] = {                -0.0980905922162812031672L,            0.159989089922969141329L,            0.222359821619935712378L,            0.127303921703577362312L,            0.0384057530342762400273L,            0.00628431160851156719325L,            0.000441266654514391746428L,            0.266689068336295642561e-7L,         };         static const T Q[] = {                1L,            2.03237474985469469291L,            1.78355454954969405222L,            0.867940326293760578231L,            0.248025606990021698392L,            0.0396649631833002269861L,            0.00279220237309449026796L,         };         result = Y + tools::evaluate_polynomial(P, z - 0.5f) / tools::evaluate_polynomial(Q, z - 0.5f);         result *= exp(-z * z) / z;      }      else if(z < 2.5)      {         // Max Error found at long double precision =   3.686211e-21         // Maximum Deviation Found:                     1.495e-21         // Expected Error Term:                         -1.494e-21         // Maximum Relative Change in Control Points:   1.793e-04         static const T Y = 0.50672817230224609375f;         static const T P[] = {                -0.024350047620769840217L,            0.0343522687935671451309L,            0.0505420824305544949541L,            0.0257479325917757388209L,            0.00669349844190354356118L,            0.00090807914416099524444L,            0.515917266698050027934e-4L,         };         static const T Q[] = {                1L,            1.71657861671930336344L,            1.26409634824280366218L,            0.512371437838969015941L,            0.120902623051120950935L,            0.0158027197831887485261L,            0.000897871370778031611439L,         };         result = Y + tools::evaluate_polynomial(P, z - 1.5f) / tools::evaluate_polynomial(Q, z - 1.5f);         result *= exp(-z * z) / z;      }      else if(z < 4.5)      {         // Maximum Deviation Found:                     1.107e-20         // Expected Error Term:                         -1.106e-20         // Maximum Relative Change in Control Points:   1.709e-04         // Max Error found at long double precision =   1.446908e-20         static const T Y  = 0.5405750274658203125f;         static const T P[] = {                0.0029527671653097284033L,            0.0141853245895495604051L,            0.0104959584626432293901L,            0.00343963795976100077626L,            0.00059065441194877637899L,            0.523435380636174008685e-4L,            0.189896043050331257262e-5L,         };         static const T Q[] = {                1L,            1.19352160185285642574L,            0.603256964363454392857L,            0.165411142458540585835L,            0.0259729870946203166468L,            0.00221657568292893699158L,            0.804149464190309799804e-4L,         };         result = Y + tools::evaluate_polynomial(P, z - 3.5f) / tools::evaluate_polynomial(Q, z - 3.5f);         result *= exp(-z * z) / z;      }      else      {         // Max Error found at long double precision =   7.961166e-21         // Maximum Deviation Found:                     6.677e-21         // Expected Error Term:                         6.676e-21         // Maximum Relative Change in Control Points:   2.319e-05         static const T Y = 0.55825519561767578125f;         static const T P[] = {                0.00593438793008050214106L,            0.0280666231009089713937L,            -0.141597835204583050043L,            -0.978088201154300548842L,            -5.47351527796012049443L,            -13.8677304660245326627L,            -27.1274948720539821722L,            -29.2545152747009461519L,            -16.8865774499799676937L,         };         static const T Q[] = {                1L,            4.72948911186645394541L,            23.6750543147695749212L,            60.0021517335693186785L,            131.766251645149522868L,            178.167924971283482513L,            182.499390505915222699L,            104.365251479578577989L,            30.8365511891224291717L,         };         result = Y + tools::evaluate_polynomial(P, 1 / z) / tools::evaluate_polynomial(Q, 1 / z);         result *= exp(-z * z) / z;      }   }   else   {      //      // Any value of z larger than 110 will underflow to zero:      //      result = 0;      invert = !invert;   }   if(invert)   {      result = 1 - result;   }   return result;} // template <class T, class L>T erf_imp(T z, bool invert, const L& l, const mpl::int_<64>& t)template <class T, class Policy>T erf_imp(T z, bool invert, const Policy& pol, const mpl::int_<113>& t){   BOOST_MATH_STD_USING   BOOST_MATH_INSTRUMENT_CODE("113-bit precision erf_imp called");   if(z < 0)   {      if(!invert)         return -erf_imp(-z, invert, pol, t);      else if(z < -0.5)         return 2 - erf_imp(-z, invert, pol, t);      else         return 1 + erf_imp(-z, false, pol, t);   }   T result;   //   // Big bunch of selection statements now to pick which   // implementation to use, try to put most likely options   // first:   //   if(z < 0.5)   {      //      // We're going to calculate erf:      //      if(z == 0)      {         result = 0;      }      else if(z < 1e-20)      {         result = z * 1.125 + z * 0.003379167095512573896158903121545171688L;      }      else      {         // Max Error found at long double precision =   2.342380e-35         // Maximum Deviation Found:                     6.124e-36         // Expected Error Term:                         -6.124e-36         // Maximum Relative Change in Control Points:   3.492e-10         static const T Y = 1.0841522216796875f;         static const T P[] = {                0.0442269454158250738961589031215451778L,            -0.35549265736002144875335323556961233L,            -0.0582179564566667896225454670863270393L,            -0.0112694696904802304229950538453123925L,            -0.000805730648981801146251825329609079099L,            -0.566304966591936566229702842075966273e-4L,            -0.169655010425186987820201021510002265e-5L,            -0.344448249920445916714548295433198544e-7L,         };         static const T Q[] = {                1L,            0.466542092785657604666906909196052522L,            0.100005087012526447295176964142107611L,            0.0128341535890117646540050072234142603L,            0.00107150448466867929159660677016658186L,            0.586168368028999183607733369248338474e-4L,            0.196230608502104324965623171516808796e-5L,            0.313388521582925207734229967907890146e-7L,         };         result = z * (Y + tools::evaluate_polynomial(P, z * z) / tools::evaluate_polynomial(Q, z * z));      }   }   else if((z < 9) || ((z < 110) && invert))   {      //      // We'll be calculating erfc:      //      invert = !invert;      if(z < 1)      {         // Max Error found at long double precision =   3.246278e-35         // Maximum Deviation Found:                     1.388e-35         // Expected Error Term:                         1.387e-35         // Maximum Relative Change in Control Points:   6.127e-05         static const T Y = 0.371877193450927734375f;         static const T P[] = {                -0.0640320213544647969396032886581290455L,            0.200769874440155895637857443946706731L,            0.378447199873537170666487408805779826L,            0.30521399466465939450398642044975127L,            0.146890026406815277906781824723458196L,            0.0464837937749539978247589252732769567L,            0.00987895759019540115099100165904822903L,            0.00137507575429025512038051025154301132L,            0.0001144764551085935580772512359680516L,            0.436544865032836914773944382339900079e-5L,         };         static const T Q[] = {                1L,            2.47651182872457465043733800302427977L,            2.78706486002517996428836400245547955L,            1.87295924621659627926365005293130693L,            0.829375825174365625428280908787261065L,            0.251334771307848291593780143950311514L,            0.0522110268876176186719436765734722473L,            0.00718332151250963182233267040106902368L,            0.000595279058621482041084986219276392459L,            0.226988669466501655990637599399326874e-4L,            0.270666232259029102353426738909226413e-10L,         };         result = Y + tools::evaluate_polynomial(P, z - 0.5f) / tools::evaluate_polynomial(Q, z - 0.5f);         result *= exp(-z * z) / z;      }      else if(z < 1.5)      {         // Max Error found at long double precision =   2.215785e-35         // Maximum Deviation Found:                     1.539e-35         // Expected Error Term:                         1.538e-35         // Maximum Relative Change in Control Points:   6.104e-05         static const T Y = 0.45658016204833984375f;         static const T P[] = {                -0.0289965858925328393392496555094848345L,            0.0868181194868601184627743162571779226L,            0.169373435121178901746317404936356745L,            0.13350446515949251201104889028133486L,            0.0617447837290183627136837688446313313L,            0.0185618495228251406703152962489700468L,            0.00371949406491883508764162050169531013L,            0.000485121708792921297742105775823900772L,            0.376494706741453489892108068231400061e-4L,            0.133166058052466262415271732172490045e-5L,         };         static const T Q[] = {                1L,            2.32970330146503867261275580968135126L,            2.46325715420422771961250513514928746L,            1.55307882560757679068505047390857842L,            0.644274289865972449441174485441409076L,            0.182609091063258208068606847453955649L,            0.0354171651271241474946129665801606795L,            0.00454060370165285246451879969534083997L,            0.000349871943711566546821198612518656486L,            0.123749319840299552925421880481085392e-4L,         };         result = Y + tools::evaluate_polynomial(P, z - 1.0f) / tools::evaluate_polynomial(Q, z - 1.0f);         result *= exp(-z * z) / z;      }      else if(z < 2.25)      {         // Maximum Deviation Found:                     1.418e-35         // Expected Error Term:                         1.418e-35         // Maximum Relative Change in Control Points:   1.316e-04         // Max Error found at long double precision =   1.998462e-35         static const T Y = 0.50250148773193359375f;         static const T P[] = {                -0.0201233630504573402185161184151016606L,            0.0331864357574860196516686996302305002L,            0.0716562720864787193337475444413405461L,            0.0545835322082103985114927569724880658L,            0.0236692635189696678976549720784989593L,

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?