diff --git a/kmplot/parser.h b/kmplot/parser.h --- a/kmplot/parser.h +++ b/kmplot/parser.h @@ -85,7 +85,7 @@ const int legendreCount = 7; // number of legendre polynomials we allow for -const int ScalarCount = 40+legendreCount; // number of mathematical scalar functions +const int ScalarCount = 41+legendreCount; // number of mathematical scalar functions const int VectorCount = 3; // number of vector functions //@} @@ -125,6 +125,9 @@ double legendre5(double x); double legendre6(double x); +double evaluate_rational(const double* num, const double* denom, const double& z_, int count); +double besselj0(double x); + double factorial(double x); double lerf(double x); double lerfc(double x); diff --git a/kmplot/parser.cpp b/kmplot/parser.cpp --- a/kmplot/parser.cpp +++ b/kmplot/parser.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -115,6 +116,9 @@ {"P_4", QString(), legendre4}, // lengedre polynomial (n=4) {"P_5", QString(), legendre5}, // lengedre polynomial (n=5) {"P_6", QString(), legendre6}, // lengedre polynomial (n=6) + + // bessel + {"J0", QString(), besselj0}, // the cylindrical Bessel function of the first kind (n=0) }; VectorFunction Parser::vectorFunctions[ VectorCount ]= @@ -1395,6 +1399,165 @@ return (231*x*x*x*x*x*x - 315*x*x*x*x + 105*x*x - 5)/16; } +// The following function code is adopted from Boost. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +double evaluate_rational(const double* num, const double* denom, const double& x_, int count) +{ + double x(x_); + double s1, s2; + if (x <= 1) + { + s1 = num[count-1]; + s2 = denom[count-1]; + for (int i = count - 2; i >= 0; --i) + { + s1 *= x; + s2 *= x; + s1 += num[i]; + s2 += denom[i]; + } + } + else + { + x = 1 / x; + s1 = num[0]; + s2 = denom[0]; + for(unsigned i = 1; i < (unsigned)count; ++i) + { + s1 *= x; + s2 *= x; + s1 += num[i]; + s2 += denom[i]; + } + } + return s1 / s2; +} + +// The following function code is adopted from Boost. +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. (See accompanying file +// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +double besselj0( double x ) { + static const double P1[] = { + -4.1298668500990866786e+11, + 2.7282507878605942706e+10, + -6.2140700423540120665e+08, + 6.6302997904833794242e+06, + -3.6629814655107086448e+04, + 1.0344222815443188943e+02, + -1.2117036164593528341e-01 + }; + static const double Q1[] = { + 2.3883787996332290397e+12, + 2.6328198300859648632e+10, + 1.3985097372263433271e+08, + 4.5612696224219938200e+05, + 9.3614022392337710626e+02, + 1.0, + 0.0 + }; + static const double P2[] = { + -1.8319397969392084011e+03, + -1.2254078161378989535e+04, + -7.2879702464464618998e+03, + 1.0341910641583726701e+04, + 1.1725046279757103576e+04, + 4.4176707025325087628e+03, + 7.4321196680624245801e+02, + 4.8591703355916499363e+01 + }; + static const double Q2[] = { + -3.5783478026152301072e+05, + 2.4599102262586308984e+05, + -8.4055062591169562211e+04, + 1.8680990008359188352e+04, + -2.9458766545509337327e+03, + 3.3307310774649071172e+02, + -2.5258076240801555057e+01, + 1.0 + }; + static const double PC[] = { + 2.2779090197304684302e+04, + 4.1345386639580765797e+04, + 2.1170523380864944322e+04, + 3.4806486443249270347e+03, + 1.5376201909008354296e+02, + 8.8961548424210455236e-01 + }; + static const double QC[] = { + 2.2779090197304684318e+04, + 4.1370412495510416640e+04, + 2.1215350561880115730e+04, + 3.5028735138235608207e+03, + 1.5711159858080893649e+02, + 1.0 + }; + static const double PS[] = { + -8.9226600200800094098e+01, + -1.8591953644342993800e+02, + -1.1183429920482737611e+02, + -2.2300261666214198472e+01, + -1.2441026745835638459e+00, + -8.8033303048680751817e-03 + }; + static const double QS[] = { + 5.7105024128512061905e+03, + 1.1951131543434613647e+04, + 7.2642780169211018836e+03, + 1.4887231232283756582e+03, + 9.0593769594993125859e+01, + 1.0 + }; + static const double x1 = 2.4048255576957727686e+00, + x2 = 5.5200781102863106496e+00, + x11 = 6.160e+02, + x12 = -1.42444230422723137837e-03, + x21 = 1.4130e+03, + x22 = 5.46860286310649596604e-04; + + double value, factor, r, rc, rs; + + if (x < 0) + { + x = -x; // even function + } + if (x == 0) + { + return 1; + } + if (x <= 4) // x in (0, 4] + { + double y = x * x; + r = evaluate_rational(P1, Q1, y, 7); + factor = (x + x1) * ((x - x11/256) - x12); + value = factor * r; + } + else if (x <= 8.0) // x in (4, 8] + { + double y = 1 - (x * x)/64; + r = evaluate_rational(P2, Q2, y, 8); + factor = (x + x2) * ((x - x21/256) - x22); + value = factor * r; + } + else // x in (8, \infty) + { + double y = 8 / x; + double y2 = y * y; + rc = evaluate_rational(PC, QC, y2, 6); + rs = evaluate_rational(PS, QS, y2, 6); + factor = 1/ sqrt(M_PI) / sqrt(x); + double sx = sin(x); + double cx = cos(x); + value = factor * (rc * (cx + sx) - y * rs * (sx - cx)); + } + + return value; +} + double sign(double x) { if(x<0.)