sf_graphs.cpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766
  1. // Copyright John Maddock 2008.
  2. // Copyright Paul A. Bristow 2016
  3. // Use, modification and distribution are subject to the
  4. // Boost Software License, Version 1.0. (See accompanying file
  5. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. #ifdef _MSC_VER
  7. # pragma warning (disable : 4127) // conditional expression is constant
  8. # pragma warning (disable : 4180) // qualifier applied to function type has no meaning; ignored
  9. # pragma warning (disable : 4503) // decorated name length exceeded, name was truncated
  10. # pragma warning (disable : 4512) // assignment operator could not be generated
  11. # pragma warning (disable : 4224) // nonstandard extension used : formal parameter 'function_ptr' was previously defined as a type
  12. #endif
  13. // #define BOOST_SVG_DIAGNOSTICS // define to provide diagnostic output from plotting.
  14. #include <boost/math/special_functions.hpp>
  15. #include <boost/math/tools/roots.hpp>
  16. #include <boost/function.hpp>
  17. #include <boost/bind.hpp>
  18. #include <list>
  19. #include <map>
  20. #include <string>
  21. #include <boost/svg_plot/svg_2d_plot.hpp>
  22. #include <boost/svg_plot/show_2d_settings.hpp>
  23. class function_arity1_plotter
  24. {
  25. public:
  26. function_arity1_plotter() : m_min_x(0), m_max_x(0), m_min_y(0), m_max_y(0), m_has_legend(false) {}
  27. //! Add a function to the plotter, compute the axes using range a to b and compute & add data points to map.
  28. void add(boost::function<double(double)> f, double x_lo, double x_hi, const std::string& name)
  29. {
  30. std::cout << "Adding function " << name << ", x range " << x_lo << " to " << x_hi << std::endl;
  31. if(name.size())
  32. m_has_legend = true;
  33. //
  34. // Now set our x-axis limits:
  35. if(m_max_x == m_min_x)
  36. {
  37. m_max_x = x_hi;
  38. m_min_x = x_lo;
  39. }
  40. else
  41. {
  42. if(x_lo < m_min_x)
  43. m_min_x = x_lo;
  44. if(x_hi > m_max_x)
  45. m_max_x = x_hi;
  46. }
  47. m_points.push_back(std::pair<std::string, std::map<double,double> >(name, std::map<double,double>()));
  48. std::map<double,double>& points = m_points.rbegin()->second;
  49. double interval = (x_hi - x_lo) / 200;
  50. for(double x = x_lo; x <= x_hi; x += interval)
  51. {
  52. double y = f(x); // Evaluate the function.
  53. // Set the Y axis limits if needed.
  54. if((m_min_y == m_max_y) && (m_min_y == 0))
  55. m_min_y = m_max_y = y;
  56. if(m_min_y > y)
  57. m_min_y = y;
  58. if(m_max_y < y)
  59. m_max_y = y;
  60. points[x] = y; // Store the pair of points values.
  61. } // for x
  62. #ifdef BOOST_SVG_DIAGNOSTICS
  63. std::cout << "Added function " << name
  64. << ", x range " << x_lo << " to " << x_hi
  65. << ", x min = " << m_min_x << ", x max = " << m_max_x
  66. << ", y min = " << m_min_y << ", y max = " << m_max_y
  67. << ", interval = " << interval
  68. << std::endl;
  69. #endif
  70. } // void add(boost::function<double(double)> f, double a, double b, const std::string& name)
  71. //! Compute x and y min and max from a map of pre-computed data points.
  72. void add(const std::map<double, double>& m, const std::string& name)
  73. {
  74. if (name.size() != 0)
  75. {
  76. m_has_legend = true;
  77. }
  78. m_points.push_back(std::pair<std::string, std::map<double,double> >(name, m));
  79. std::map<double, double>::const_iterator i = m.begin();
  80. while(i != m.end())
  81. {
  82. if((m_min_x == m_min_y) && (m_min_y == 0))
  83. {
  84. m_min_x = m_max_x = i->first;
  85. }
  86. if(i->first < m_min_x)
  87. {
  88. m_min_x = i->first;
  89. }
  90. if(i->first > m_max_x)
  91. {
  92. m_max_x = i->first;
  93. }
  94. if((m_min_y == m_max_y) && (m_min_y == 0))
  95. {
  96. m_min_y = m_max_y = i->second;
  97. }
  98. if(i->second < m_min_y)
  99. {
  100. m_min_y = i->second;
  101. }
  102. if(i->second > m_max_y)
  103. {
  104. m_max_y = i->second;
  105. }
  106. ++i;
  107. }
  108. } // void add(const std::map<double, double>& m, const std::string& name)
  109. //! Plot pre-computed m_points data for function.
  110. void plot(const std::string& title, const std::string& file,
  111. const std::string& x_lable = std::string(), const std::string& y_lable = std::string())
  112. {
  113. using namespace boost::svg;
  114. static const svg_color colors[5] =
  115. { // Colors for plot curves, used in turn.
  116. darkblue,
  117. darkred,
  118. darkgreen,
  119. darkorange,
  120. chartreuse
  121. };
  122. std::cout << "Plotting Special Function " << title << " to file " << file << std::endl;
  123. svg_2d_plot plot;
  124. plot.image_x_size(600);
  125. plot.image_y_size(400);
  126. plot.copyright_holder("John Maddock").copyright_date("2008").boost_license_on(true);
  127. plot.coord_precision(4); // Could be 3 for smaller plots?
  128. plot.title(title).title_font_size(20).title_on(true);
  129. plot.legend_on(m_has_legend);
  130. double x_delta = (m_max_x - m_min_x) / 50;
  131. double y_delta = (m_max_y - m_min_y) / 50;
  132. plot.x_range(m_min_x, m_max_x + x_delta)
  133. .y_range(m_min_y, m_max_y + y_delta);
  134. plot.x_label_on(true).x_label(x_lable);
  135. plot.y_label_on(true).y_label(y_lable);
  136. plot.y_major_grid_on(false).x_major_grid_on(false);
  137. plot.x_num_minor_ticks(3);
  138. plot.y_num_minor_ticks(3);
  139. //
  140. // Work out axis tick intervals:
  141. double l = std::floor(std::log10((m_max_x - m_min_x) / 10) + 0.5);
  142. double interval = std::pow(10.0, (int)l);
  143. if(((m_max_x - m_min_x) / interval) > 10)
  144. interval *= 5;
  145. plot.x_major_interval(interval);
  146. l = std::floor(std::log10((m_max_y - m_min_y) / 10) + 0.5);
  147. interval = std::pow(10.0, (int)l);
  148. if(((m_max_y - m_min_y) / interval) > 10)
  149. interval *= 5;
  150. plot.y_major_interval(interval);
  151. plot.plot_window_on(true);
  152. plot.plot_border_color(lightslategray)
  153. .background_border_color(lightslategray)
  154. .legend_border_color(lightslategray)
  155. .legend_background_color(white);
  156. int color_index = 0; // Cycle through the colors for each curve.
  157. for(std::list<std::pair<std::string, std::map<double,double> > >::const_iterator i = m_points.begin();
  158. i != m_points.end(); ++i)
  159. {
  160. plot.plot(i->second, i->first)
  161. .line_on(true)
  162. .line_color(colors[color_index])
  163. .line_width(1.)
  164. .shape(none);
  165. if(i->first.size())
  166. ++color_index;
  167. color_index = color_index % (sizeof(colors)/sizeof(colors[0]));
  168. }
  169. plot.write(file);
  170. } // void plot(const std::string& title, const std::string& file,
  171. void clear()
  172. {
  173. m_points.clear();
  174. m_min_x = m_min_y = m_max_x = m_max_y = 0;
  175. m_has_legend = false;
  176. } // clear
  177. private:
  178. std::list<std::pair<std::string, std::map<double, double> > > m_points;
  179. double m_min_x, m_max_x, m_min_y, m_max_y;
  180. bool m_has_legend;
  181. };
  182. template <class F>
  183. struct location_finder
  184. {
  185. location_finder(F _f, double t, double x0) : f(_f), target(t), x_off(x0){}
  186. double operator()(double x)
  187. {
  188. try
  189. {
  190. return f(x + x_off) - target;
  191. }
  192. catch(const std::overflow_error&)
  193. {
  194. return boost::math::tools::max_value<double>();
  195. }
  196. catch(const std::domain_error&)
  197. {
  198. if(x + x_off == x_off)
  199. return f(x_off + boost::math::tools::epsilon<double>() * x_off);
  200. throw;
  201. }
  202. }
  203. private:
  204. F f;
  205. double target;
  206. double x_off;
  207. };
  208. template <class F>
  209. double find_end_point(F f, double x0, double target, bool rising, double x_off = 0)
  210. {
  211. boost::math::tools::eps_tolerance<double> tol(50);
  212. boost::uintmax_t max_iter = 1000;
  213. return x_off + boost::math::tools::bracket_and_solve_root(
  214. location_finder<F>(f, target, x_off),
  215. x0,
  216. 1.5,
  217. rising,
  218. tol,
  219. max_iter).first;
  220. }
  221. double sqrt1pm1(double x)
  222. {
  223. return boost::math::sqrt1pm1(x);
  224. }
  225. double lbeta(double a, double b)
  226. {
  227. return std::log(boost::math::beta(a, b));
  228. }
  229. int main()
  230. {
  231. try
  232. {
  233. function_arity1_plotter plot;
  234. // Functions may have varying numbers and types of parameters.
  235. // plot.add calls must use the appropriate function type.
  236. // Not all function types may be used, so can ignore any warning like
  237. // "C4101: 'f4': unreferenced local variable"
  238. double(*f)(double); // Simplest function type, suits most functions.
  239. double(*f2)(double, double);
  240. double(*f2u)(unsigned, double);
  241. double(*f2i)(int, double);
  242. double(*f3)(double, double, double);
  243. double(*f4)(double, double, double, double);
  244. double max_val; // Hold evaluated value of function for use in find_end_point.
  245. f = boost::math::zeta;
  246. plot.add(f, find_end_point(f, 0.1, 40.0, false, 1.0), 10, "");
  247. plot.add(f, -20, find_end_point(f, -0.1, -40.0, false, 1.0), "");
  248. plot.plot("Zeta Function Over [-20,10]", "zeta1.svg", "z", "zeta(z)");
  249. plot.clear();
  250. plot.add(f, -14, 0, "");
  251. plot.plot("Zeta Function Over [-14,0]", "zeta2.svg", "z", "zeta(z)");
  252. f = boost::math::tgamma;
  253. max_val = f(6);
  254. plot.clear();
  255. plot.add(f, find_end_point(f, 0.1, max_val, false), 6, "");
  256. plot.add(f, find_end_point(f, 0.1, -max_val, true, -1), find_end_point(f, -0.1, -max_val, false), "");
  257. plot.add(f, find_end_point(f, 0.1, max_val, false, -2), find_end_point(f, -0.1, max_val, true, -1), "");
  258. plot.add(f, find_end_point(f, 0.1, -max_val, true, -3), find_end_point(f, -0.1, -max_val, false, -2), "");
  259. plot.add(f, find_end_point(f, 0.1, max_val, false, -4), find_end_point(f, -0.1, max_val, true, -3), "");
  260. plot.plot("tgamma", "tgamma.svg", "z", "tgamma(z)");
  261. f = boost::math::lgamma;
  262. max_val = f(10);
  263. plot.clear();
  264. plot.add(f, find_end_point(f, 0.1, max_val, false), 10, "");
  265. plot.add(f, find_end_point(f, 0.1, max_val, false, -1), find_end_point(f, -0.1, max_val, true), "");
  266. plot.add(f, find_end_point(f, 0.1, max_val, false, -2), find_end_point(f, -0.1, max_val, true, -1), "");
  267. plot.add(f, find_end_point(f, 0.1, max_val, false, -3), find_end_point(f, -0.1, max_val, true, -2), "");
  268. plot.add(f, find_end_point(f, 0.1, max_val, false, -4), find_end_point(f, -0.1, max_val, true, -3), "");
  269. plot.add(f, find_end_point(f, 0.1, max_val, false, -5), find_end_point(f, -0.1, max_val, true, -4), "");
  270. plot.plot("lgamma", "lgamma.svg", "z", "lgamma(z)");
  271. f = boost::math::digamma;
  272. max_val = 10;
  273. plot.clear();
  274. plot.add(f, find_end_point(f, 0.1, -max_val, true), 10, "");
  275. plot.add(f, find_end_point(f, 0.1, -max_val, true, -1), find_end_point(f, -0.1, max_val, true), "");
  276. plot.add(f, find_end_point(f, 0.1, -max_val, true, -2), find_end_point(f, -0.1, max_val, true, -1), "");
  277. plot.add(f, find_end_point(f, 0.1, -max_val, true, -3), find_end_point(f, -0.1, max_val, true, -2), "");
  278. plot.add(f, find_end_point(f, 0.1, -max_val, true, -4), find_end_point(f, -0.1, max_val, true, -3), "");
  279. plot.plot("digamma", "digamma.svg", "z", "digamma(z)");
  280. f = boost::math::erf;
  281. plot.clear();
  282. plot.add(f, -3, 3, "erf");
  283. plot.plot("erf", "erf.svg", "z", "erf(z)");
  284. f = boost::math::erfc;
  285. plot.clear();
  286. plot.add(f, -3, 3, "erfc");
  287. plot.plot("erfc", "erfc.svg", "z", "erfc(z)");
  288. f = boost::math::erf_inv;
  289. plot.clear();
  290. plot.add(f, find_end_point(f, 0.1, -3, true, -1), find_end_point(f, -0.1, 3, true, 1), "");
  291. plot.plot("erf_inv", "erf_inv.svg", "z", "erf_inv(z)");
  292. f = boost::math::erfc_inv;
  293. plot.clear();
  294. plot.add(f, find_end_point(f, 0.1, 3, false), find_end_point(f, -0.1, -3, false, 2), "");
  295. plot.plot("erfc_inv", "erfc_inv.svg", "z", "erfc_inv(z)");
  296. f = boost::math::log1p;
  297. plot.clear();
  298. plot.add(f, find_end_point(f, 0.1, -10, true, -1), 10, "");
  299. plot.plot("log1p", "log1p.svg", "z", "log1p(z)");
  300. f = boost::math::expm1;
  301. plot.clear();
  302. plot.add(f, -4, 2, "");
  303. plot.plot("expm1", "expm1.svg", "z", "expm1(z)");
  304. f = boost::math::cbrt;
  305. plot.clear();
  306. plot.add(f, -10, 10, "");
  307. plot.plot("cbrt", "cbrt.svg", "z", "cbrt(z)");
  308. f = sqrt1pm1;
  309. plot.clear();
  310. plot.add(f, find_end_point(f, 0.1, -10, true, -1), 5, "");
  311. plot.plot("sqrt1pm1", "sqrt1pm1.svg", "z", "sqrt1pm1(z)");
  312. f2 = boost::math::powm1;
  313. plot.clear();
  314. plot.add(boost::bind(f2, 0.0001, _1), find_end_point(boost::bind(f2, 0.0001, _1), -1, 10, false), 5, "a=0.0001");
  315. plot.add(boost::bind(f2, 0.001, _1), find_end_point(boost::bind(f2, 0.001, _1), -1, 10, false), 5, "a=0.001");
  316. plot.add(boost::bind(f2, 0.01, _1), find_end_point(boost::bind(f2, 0.01, _1), -1, 10, false), 5, "a=0.01");
  317. plot.add(boost::bind(f2, 0.1, _1), find_end_point(boost::bind(f2, 0.1, _1), -1, 10, false), 5, "a=0.1");
  318. plot.add(boost::bind(f2, 0.75, _1), -5, 5, "a=0.75");
  319. plot.add(boost::bind(f2, 1.25, _1), -5, 5, "a=1.25");
  320. plot.plot("powm1", "powm1.svg", "z", "powm1(a, z)");
  321. f = boost::math::sinc_pi;
  322. plot.clear();
  323. plot.add(f, -10, 10, "");
  324. plot.plot("sinc_pi", "sinc_pi.svg", "z", "sinc_pi(z)");
  325. f = boost::math::sinhc_pi;
  326. plot.clear();
  327. plot.add(f, -5, 5, "");
  328. plot.plot("sinhc_pi", "sinhc_pi.svg", "z", "sinhc_pi(z)");
  329. f = boost::math::acosh;
  330. plot.clear();
  331. plot.add(f, 1, 10, "acosh");
  332. plot.plot("acosh", "acosh.svg", "z", "acosh(z)");
  333. f = boost::math::asinh;
  334. plot.clear();
  335. plot.add(f, -10, 10, "");
  336. plot.plot("asinh", "asinh.svg", "z", "asinh(z)");
  337. f = boost::math::atanh;
  338. plot.clear();
  339. plot.add(f, find_end_point(f, 0.1, -5, true, -1), find_end_point(f, -0.1, 5, true, 1), "");
  340. plot.plot("atanh", "atanh.svg", "z", "atanh(z)");
  341. f2 = boost::math::tgamma_delta_ratio;
  342. plot.clear();
  343. plot.add(boost::bind(f2, _1, -0.5), 1, 40, "delta = -0.5");
  344. plot.add(boost::bind(f2, _1, -0.2), 1, 40, "delta = -0.2");
  345. plot.add(boost::bind(f2, _1, -0.1), 1, 40, "delta = -0.1");
  346. plot.add(boost::bind(f2, _1, 0.1), 1, 40, "delta = 0.1");
  347. plot.add(boost::bind(f2, _1, 0.2), 1, 40, "delta = 0.2");
  348. plot.add(boost::bind(f2, _1, 0.5), 1, 40, "delta = 0.5");
  349. plot.add(boost::bind(f2, _1, 1.0), 1, 40, "delta = 1.0");
  350. plot.plot("tgamma_delta_ratio", "tgamma_delta_ratio.svg", "z", "tgamma_delta_ratio(delta, z)");
  351. f2 = boost::math::gamma_p;
  352. plot.clear();
  353. plot.add(boost::bind(f2, 0.5, _1), 0, 20, "a = 0.5");
  354. plot.add(boost::bind(f2, 1.0, _1), 0, 20, "a = 1.0");
  355. plot.add(boost::bind(f2, 5.0, _1), 0, 20, "a = 5.0");
  356. plot.add(boost::bind(f2, 10.0, _1), 0, 20, "a = 10.0");
  357. plot.plot("gamma_p", "gamma_p.svg", "z", "gamma_p(a, z)");
  358. f2 = boost::math::gamma_q;
  359. plot.clear();
  360. plot.add(boost::bind(f2, 0.5, _1), 0, 20, "a = 0.5");
  361. plot.add(boost::bind(f2, 1.0, _1), 0, 20, "a = 1.0");
  362. plot.add(boost::bind(f2, 5.0, _1), 0, 20, "a = 5.0");
  363. plot.add(boost::bind(f2, 10.0, _1), 0, 20, "a = 10.0");
  364. plot.plot("gamma_q", "gamma_q.svg", "z", "gamma_q(a, z)");
  365. f2 = lbeta;
  366. plot.clear();
  367. plot.add(boost::bind(f2, 0.5, _1), 0.00001, 5, "a = 0.5");
  368. plot.add(boost::bind(f2, 1.0, _1), 0.00001, 5, "a = 1.0");
  369. plot.add(boost::bind(f2, 5.0, _1), 0.00001, 5, "a = 5.0");
  370. plot.add(boost::bind(f2, 10.0, _1), 0.00001, 5, "a = 10.0");
  371. plot.plot("beta", "beta.svg", "z", "log(beta(a, z))");
  372. f = boost::math::expint;
  373. max_val = f(4);
  374. plot.clear();
  375. plot.add(f, find_end_point(f, 0.1, -max_val, true), 4, "");
  376. plot.add(f, -3, find_end_point(f, -0.1, -max_val, false), "");
  377. plot.plot("Exponential Integral Ei", "expint_i.svg", "z", "expint(z)");
  378. f2u = boost::math::expint;
  379. max_val = 1;
  380. plot.clear();
  381. plot.add(boost::bind(f2u, 1, _1), find_end_point(boost::bind(f2u, 1, _1), 0.1, max_val, false), 2, "n = 1 ");
  382. plot.add(boost::bind(f2u, 2, _1), find_end_point(boost::bind(f2u, 2, _1), 0.1, max_val, false), 2, "n = 2 ");
  383. plot.add(boost::bind(f2u, 3, _1), 0, 2, "n = 3 ");
  384. plot.add(boost::bind(f2u, 4, _1), 0, 2, "n = 4 ");
  385. plot.plot("Exponential Integral En", "expint2.svg", "z", "expint(n, z)");
  386. f3 = boost::math::ibeta;
  387. plot.clear();
  388. plot.add(boost::bind(f3, 9, 1, _1), 0, 1, "a = 9, b = 1");
  389. plot.add(boost::bind(f3, 7, 2, _1), 0, 1, "a = 7, b = 2");
  390. plot.add(boost::bind(f3, 5, 5, _1), 0, 1, "a = 5, b = 5");
  391. plot.add(boost::bind(f3, 2, 7, _1), 0, 1, "a = 2, b = 7");
  392. plot.add(boost::bind(f3, 1, 9, _1), 0, 1, "a = 1, b = 9");
  393. plot.plot("ibeta", "ibeta.svg", "z", "ibeta(a, b, z)");
  394. f2i = boost::math::legendre_p;
  395. plot.clear();
  396. plot.add(boost::bind(f2i, 1, _1), -1, 1, "l = 1");
  397. plot.add(boost::bind(f2i, 2, _1), -1, 1, "l = 2");
  398. plot.add(boost::bind(f2i, 3, _1), -1, 1, "l = 3");
  399. plot.add(boost::bind(f2i, 4, _1), -1, 1, "l = 4");
  400. plot.add(boost::bind(f2i, 5, _1), -1, 1, "l = 5");
  401. plot.plot("Legendre Polynomials", "legendre_p.svg", "x", "legendre_p(l, x)");
  402. f2u = boost::math::legendre_q;
  403. plot.clear();
  404. plot.add(boost::bind(f2u, 1, _1), -0.95, 0.95, "l = 1");
  405. plot.add(boost::bind(f2u, 2, _1), -0.95, 0.95, "l = 2");
  406. plot.add(boost::bind(f2u, 3, _1), -0.95, 0.95, "l = 3");
  407. plot.add(boost::bind(f2u, 4, _1), -0.95, 0.95, "l = 4");
  408. plot.add(boost::bind(f2u, 5, _1), -0.95, 0.95, "l = 5");
  409. plot.plot("Legendre Polynomials of the Second Kind", "legendre_q.svg", "x", "legendre_q(l, x)");
  410. f2u = boost::math::laguerre;
  411. plot.clear();
  412. plot.add(boost::bind(f2u, 0, _1), -5, 10, "n = 0");
  413. plot.add(boost::bind(f2u, 1, _1), -5, 10, "n = 1");
  414. plot.add(boost::bind(f2u, 2, _1),
  415. find_end_point(boost::bind(f2u, 2, _1), -2, 20, false),
  416. find_end_point(boost::bind(f2u, 2, _1), 4, 20, true),
  417. "n = 2");
  418. plot.add(boost::bind(f2u, 3, _1),
  419. find_end_point(boost::bind(f2u, 3, _1), -2, 20, false),
  420. find_end_point(boost::bind(f2u, 3, _1), 1, 20, false, 8),
  421. "n = 3");
  422. plot.add(boost::bind(f2u, 4, _1),
  423. find_end_point(boost::bind(f2u, 4, _1), -2, 20, false),
  424. find_end_point(boost::bind(f2u, 4, _1), 1, 20, true, 8),
  425. "n = 4");
  426. plot.add(boost::bind(f2u, 5, _1),
  427. find_end_point(boost::bind(f2u, 5, _1), -2, 20, false),
  428. find_end_point(boost::bind(f2u, 5, _1), 1, 20, true, 8),
  429. "n = 5");
  430. plot.plot("Laguerre Polynomials", "laguerre.svg", "x", "laguerre(n, x)");
  431. f2u = boost::math::hermite;
  432. plot.clear();
  433. plot.add(boost::bind(f2u, 0, _1), -1.8, 1.8, "n = 0");
  434. plot.add(boost::bind(f2u, 1, _1), -1.8, 1.8, "n = 1");
  435. plot.add(boost::bind(f2u, 2, _1), -1.8, 1.8, "n = 2");
  436. plot.add(boost::bind(f2u, 3, _1), -1.8, 1.8, "n = 3");
  437. plot.add(boost::bind(f2u, 4, _1), -1.8, 1.8, "n = 4");
  438. plot.plot("Hermite Polynomials", "hermite.svg", "x", "hermite(n, x)");
  439. f2 = boost::math::cyl_bessel_j;
  440. plot.clear();
  441. plot.add(boost::bind(f2, 0, _1), -20, 20, "v = 0");
  442. plot.add(boost::bind(f2, 1, _1), -20, 20, "v = 1");
  443. plot.add(boost::bind(f2, 2, _1), -20, 20, "v = 2");
  444. plot.add(boost::bind(f2, 3, _1), -20, 20, "v = 3");
  445. plot.add(boost::bind(f2, 4, _1), -20, 20, "v = 4");
  446. plot.plot("Bessel J", "cyl_bessel_j.svg", "x", "cyl_bessel_j(v, x)");
  447. f2 = boost::math::cyl_neumann;
  448. plot.clear();
  449. plot.add(boost::bind(f2, 0, _1), find_end_point(boost::bind(f2, 0, _1), 0.1, -5, true), 20, "v = 0");
  450. plot.add(boost::bind(f2, 1, _1), find_end_point(boost::bind(f2, 1, _1), 0.1, -5, true), 20, "v = 1");
  451. plot.add(boost::bind(f2, 2, _1), find_end_point(boost::bind(f2, 2, _1), 0.1, -5, true), 20, "v = 2");
  452. plot.add(boost::bind(f2, 3, _1), find_end_point(boost::bind(f2, 3, _1), 0.1, -5, true), 20, "v = 3");
  453. plot.add(boost::bind(f2, 4, _1), find_end_point(boost::bind(f2, 4, _1), 0.1, -5, true), 20, "v = 4");
  454. plot.plot("Bessel Y", "cyl_neumann.svg", "x", "cyl_neumann(v, x)");
  455. f2 = boost::math::cyl_bessel_i;
  456. plot.clear();
  457. plot.add(boost::bind(f2, 0, _1), find_end_point(boost::bind(f2, 0, _1), -0.1, 20, false), find_end_point(boost::bind(f2, 0, _1), 0.1, 20, true), "v = 0");
  458. plot.add(boost::bind(f2, 2, _1), find_end_point(boost::bind(f2, 2, _1), -0.1, 20, false), find_end_point(boost::bind(f2, 2, _1), 0.1, 20, true), "v = 2");
  459. plot.add(boost::bind(f2, 5, _1), find_end_point(boost::bind(f2, 5, _1), -0.1, -20, true), find_end_point(boost::bind(f2, 5, _1), 0.1, 20, true), "v = 5");
  460. plot.add(boost::bind(f2, 7, _1), find_end_point(boost::bind(f2, 7, _1), -0.1, -20, true), find_end_point(boost::bind(f2, 7, _1), 0.1, 20, true), "v = 7");
  461. plot.add(boost::bind(f2, 10, _1), find_end_point(boost::bind(f2, 10, _1), -0.1, 20, false), find_end_point(boost::bind(f2, 10, _1), 0.1, 20, true), "v = 10");
  462. plot.plot("Bessel I", "cyl_bessel_i.svg", "x", "cyl_bessel_i(v, x)");
  463. f2 = boost::math::cyl_bessel_k;
  464. plot.clear();
  465. plot.add(boost::bind(f2, 0, _1), find_end_point(boost::bind(f2, 0, _1), 0.1, 10, false), 10, "v = 0");
  466. plot.add(boost::bind(f2, 2, _1), find_end_point(boost::bind(f2, 2, _1), 0.1, 10, false), 10, "v = 2");
  467. plot.add(boost::bind(f2, 5, _1), find_end_point(boost::bind(f2, 5, _1), 0.1, 10, false), 10, "v = 5");
  468. plot.add(boost::bind(f2, 7, _1), find_end_point(boost::bind(f2, 7, _1), 0.1, 10, false), 10, "v = 7");
  469. plot.add(boost::bind(f2, 10, _1), find_end_point(boost::bind(f2, 10, _1), 0.1, 10, false), 10, "v = 10");
  470. plot.plot("Bessel K", "cyl_bessel_k.svg", "x", "cyl_bessel_k(v, x)");
  471. f2u = boost::math::sph_bessel;
  472. plot.clear();
  473. plot.add(boost::bind(f2u, 0, _1), 0, 20, "v = 0");
  474. plot.add(boost::bind(f2u, 2, _1), 0, 20, "v = 2");
  475. plot.add(boost::bind(f2u, 5, _1), 0, 20, "v = 5");
  476. plot.add(boost::bind(f2u, 7, _1), 0, 20, "v = 7");
  477. plot.add(boost::bind(f2u, 10, _1), 0, 20, "v = 10");
  478. plot.plot("Bessel j", "sph_bessel.svg", "x", "sph_bessel(v, x)");
  479. f2u = boost::math::sph_neumann;
  480. plot.clear();
  481. plot.add(boost::bind(f2u, 0, _1), find_end_point(boost::bind(f2u, 0, _1), 0.1, -5, true), 20, "v = 0");
  482. plot.add(boost::bind(f2u, 2, _1), find_end_point(boost::bind(f2u, 2, _1), 0.1, -5, true), 20, "v = 2");
  483. plot.add(boost::bind(f2u, 5, _1), find_end_point(boost::bind(f2u, 5, _1), 0.1, -5, true), 20, "v = 5");
  484. plot.add(boost::bind(f2u, 7, _1), find_end_point(boost::bind(f2u, 7, _1), 0.1, -5, true), 20, "v = 7");
  485. plot.add(boost::bind(f2u, 10, _1), find_end_point(boost::bind(f2u, 10, _1), 0.1, -5, true), 20, "v = 10");
  486. plot.plot("Bessel y", "sph_neumann.svg", "x", "sph_neumann(v, x)");
  487. f4 = boost::math::ellint_rj;
  488. plot.clear();
  489. plot.add(boost::bind(f4, _1, _1, _1, _1), find_end_point(boost::bind(f4, _1, _1, _1, _1), 0.1, 10, false), 4, "RJ");
  490. f3 = boost::math::ellint_rf;
  491. plot.add(boost::bind(f3, _1, _1, _1), find_end_point(boost::bind(f3, _1, _1, _1), 0.1, 10, false), 4, "RF");
  492. plot.plot("Elliptic Integrals", "ellint_carlson.svg", "x", "");
  493. f2 = boost::math::ellint_1;
  494. plot.clear();
  495. plot.add(boost::bind(f2, _1, 0.5), -0.9, 0.9, "&#x3C6;=0.5");
  496. plot.add(boost::bind(f2, _1, 0.75), -0.9, 0.9, "&#x3C6;=0.75");
  497. plot.add(boost::bind(f2, _1, 1.25), -0.9, 0.9, "&#x3C6;=1.25");
  498. plot.add(boost::bind(f2, _1, boost::math::constants::pi<double>() / 2), -0.9, 0.9, "&#x3C6;=&#x3C0;/2");
  499. plot.plot("Elliptic Of the First Kind", "ellint_1.svg", "k", "ellint_1(k, phi)");
  500. f2 = boost::math::ellint_2;
  501. plot.clear();
  502. plot.add(boost::bind(f2, _1, 0.5), -1, 1, "&#x3C6;=0.5");
  503. plot.add(boost::bind(f2, _1, 0.75), -1, 1, "&#x3C6;=0.75");
  504. plot.add(boost::bind(f2, _1, 1.25), -1, 1, "&#x3C6;=1.25");
  505. plot.add(boost::bind(f2, _1, boost::math::constants::pi<double>() / 2), -1, 1, "&#x3C6;=&#x3C0;/2");
  506. plot.plot("Elliptic Of the Second Kind", "ellint_2.svg", "k", "ellint_2(k, phi)");
  507. f3 = boost::math::ellint_3;
  508. plot.clear();
  509. plot.add(boost::bind(f3, _1, 0, 1.25), -1, 1, "n=0 &#x3C6;=1.25");
  510. plot.add(boost::bind(f3, _1, 0.5, 1.25), -1, 1, "n=0.5 &#x3C6;=1.25");
  511. plot.add(boost::bind(f3, _1, 0.25, boost::math::constants::pi<double>() / 2),
  512. find_end_point(
  513. boost::bind(f3, _1, 0.25, boost::math::constants::pi<double>() / 2),
  514. 0.5, 4, false, -1),
  515. find_end_point(
  516. boost::bind(f3, _1, 0.25, boost::math::constants::pi<double>() / 2),
  517. -0.5, 4, true, 1), "n=0.25 &#x3C6;=&#x3C0;/2");
  518. plot.add(boost::bind(f3, _1, 0.75, boost::math::constants::pi<double>() / 2),
  519. find_end_point(
  520. boost::bind(f3, _1, 0.75, boost::math::constants::pi<double>() / 2),
  521. 0.5, 4, false, -1),
  522. find_end_point(
  523. boost::bind(f3, _1, 0.75, boost::math::constants::pi<double>() / 2),
  524. -0.5, 4, true, 1), "n=0.75 &#x3C6;=&#x3C0;/2");
  525. plot.plot("Elliptic Of the Third Kind", "ellint_3.svg", "k", "ellint_3(k, n, phi)");
  526. f2 = boost::math::jacobi_sn;
  527. plot.clear();
  528. plot.add(boost::bind(f2, 0, _1), -10, 10, "k=0");
  529. plot.add(boost::bind(f2, 0.5, _1), -10, 10, "k=0.5");
  530. plot.add(boost::bind(f2, 0.75, _1), -10, 10, "k=0.75");
  531. plot.add(boost::bind(f2, 0.95, _1), -10, 10, "k=0.95");
  532. plot.add(boost::bind(f2, 1, _1), -10, 10, "k=1");
  533. plot.plot("Jacobi Elliptic sn", "jacobi_sn.svg", "k", "jacobi_sn(k, u)");
  534. f2 = boost::math::jacobi_cn;
  535. plot.clear();
  536. plot.add(boost::bind(f2, 0, _1), -10, 10, "k=0");
  537. plot.add(boost::bind(f2, 0.5, _1), -10, 10, "k=0.5");
  538. plot.add(boost::bind(f2, 0.75, _1), -10, 10, "k=0.75");
  539. plot.add(boost::bind(f2, 0.95, _1), -10, 10, "k=0.95");
  540. plot.add(boost::bind(f2, 1, _1), -10, 10, "k=1");
  541. plot.plot("Jacobi Elliptic cn", "jacobi_cn.svg", "k", "jacobi_cn(k, u)");
  542. f2 = boost::math::jacobi_dn;
  543. plot.clear();
  544. plot.add(boost::bind(f2, 0, _1), -10, 10, "k=0");
  545. plot.add(boost::bind(f2, 0.5, _1), -10, 10, "k=0.5");
  546. plot.add(boost::bind(f2, 0.75, _1), -10, 10, "k=0.75");
  547. plot.add(boost::bind(f2, 0.95, _1), -10, 10, "k=0.95");
  548. plot.add(boost::bind(f2, 1, _1), -10, 10, "k=1");
  549. plot.plot("Jacobi Elliptic dn", "jacobi_dn.svg", "k", "jacobi_dn(k, u)");
  550. f2 = boost::math::jacobi_cd;
  551. plot.clear();
  552. plot.add(boost::bind(f2, 0, _1), -10, 10, "k=0");
  553. plot.add(boost::bind(f2, 0.5, _1), -10, 10, "k=0.5");
  554. plot.add(boost::bind(f2, 0.75, _1), -10, 10, "k=0.75");
  555. plot.add(boost::bind(f2, 0.95, _1), -10, 10, "k=0.95");
  556. plot.add(boost::bind(f2, 1, _1), -10, 10, "k=1");
  557. plot.plot("Jacobi Elliptic cd", "jacobi_cd.svg", "k", "jacobi_cd(k, u)");
  558. f2 = boost::math::jacobi_cs;
  559. plot.clear();
  560. plot.add(boost::bind(f2, 0, _1), 0.1, 3, "k=0");
  561. plot.add(boost::bind(f2, 0.5, _1), 0.1, 3, "k=0.5");
  562. plot.add(boost::bind(f2, 0.75, _1), 0.1, 3, "k=0.75");
  563. plot.add(boost::bind(f2, 0.95, _1), 0.1, 3, "k=0.95");
  564. plot.add(boost::bind(f2, 1, _1), 0.1, 3, "k=1");
  565. plot.plot("Jacobi Elliptic cs", "jacobi_cs.svg", "k", "jacobi_cs(k, u)");
  566. f2 = boost::math::jacobi_dc;
  567. plot.clear();
  568. plot.add(boost::bind(f2, 0, _1), -10, 10, "k=0");
  569. plot.add(boost::bind(f2, 0.5, _1), -10, 10, "k=0.5");
  570. plot.add(boost::bind(f2, 0.75, _1), -10, 10, "k=0.75");
  571. plot.add(boost::bind(f2, 0.95, _1), -10, 10, "k=0.95");
  572. plot.add(boost::bind(f2, 1, _1), -10, 10, "k=1");
  573. plot.plot("Jacobi Elliptic dc", "jacobi_dc.svg", "k", "jacobi_dc(k, u)");
  574. f2 = boost::math::jacobi_ds;
  575. plot.clear();
  576. plot.add(boost::bind(f2, 0, _1), 0.1, 3, "k=0");
  577. plot.add(boost::bind(f2, 0.5, _1), 0.1, 3, "k=0.5");
  578. plot.add(boost::bind(f2, 0.75, _1), 0.1, 3, "k=0.75");
  579. plot.add(boost::bind(f2, 0.95, _1), 0.1, 3, "k=0.95");
  580. plot.add(boost::bind(f2, 1, _1), 0.1, 3, "k=1");
  581. plot.plot("Jacobi Elliptic ds", "jacobi_ds.svg", "k", "jacobi_ds(k, u)");
  582. f2 = boost::math::jacobi_nc;
  583. plot.clear();
  584. plot.add(boost::bind(f2, 0, _1), -5, 5, "k=0");
  585. plot.add(boost::bind(f2, 0.5, _1), -5, 5, "k=0.5");
  586. plot.add(boost::bind(f2, 0.75, _1), -5, 5, "k=0.75");
  587. plot.add(boost::bind(f2, 0.95, _1), -5, 5, "k=0.95");
  588. plot.add(boost::bind(f2, 1, _1), -5, 5, "k=1");
  589. plot.plot("Jacobi Elliptic nc", "jacobi_nc.svg", "k", "jacobi_nc(k, u)");
  590. f2 = boost::math::jacobi_ns;
  591. plot.clear();
  592. plot.add(boost::bind(f2, 0, _1), 0.1, 4, "k=0");
  593. plot.add(boost::bind(f2, 0.5, _1), 0.1, 4, "k=0.5");
  594. plot.add(boost::bind(f2, 0.75, _1), 0.1, 4, "k=0.75");
  595. plot.add(boost::bind(f2, 0.95, _1), 0.1, 4, "k=0.95");
  596. plot.add(boost::bind(f2, 1, _1), 0.1, 4, "k=1");
  597. plot.plot("Jacobi Elliptic ns", "jacobi_ns.svg", "k", "jacobi_ns(k, u)");
  598. f2 = boost::math::jacobi_nd;
  599. plot.clear();
  600. plot.add(boost::bind(f2, 0, _1), -2, 2, "k=0");
  601. plot.add(boost::bind(f2, 0.5, _1), -2, 2, "k=0.5");
  602. plot.add(boost::bind(f2, 0.75, _1), -2, 2, "k=0.75");
  603. plot.add(boost::bind(f2, 0.95, _1), -2, 2, "k=0.95");
  604. plot.add(boost::bind(f2, 1, _1), -2, 2, "k=1");
  605. plot.plot("Jacobi Elliptic nd", "jacobi_nd.svg", "k", "jacobi_nd(k, u)");
  606. f2 = boost::math::jacobi_sc;
  607. plot.clear();
  608. plot.add(boost::bind(f2, 0, _1), -5, 5, "k=0");
  609. plot.add(boost::bind(f2, 0.5, _1), -5, 5, "k=0.5");
  610. plot.add(boost::bind(f2, 0.75, _1), -5, 5, "k=0.75");
  611. plot.add(boost::bind(f2, 0.95, _1), -5, 5, "k=0.95");
  612. plot.add(boost::bind(f2, 1, _1), -5, 5, "k=1");
  613. plot.plot("Jacobi Elliptic sc", "jacobi_sc.svg", "k", "jacobi_sc(k, u)");
  614. f2 = boost::math::jacobi_sd;
  615. plot.clear();
  616. plot.add(boost::bind(f2, 0, _1), -2.5, 2.5, "k=0");
  617. plot.add(boost::bind(f2, 0.5, _1), -2.5, 2.5, "k=0.5");
  618. plot.add(boost::bind(f2, 0.75, _1), -2.5, 2.5, "k=0.75");
  619. plot.add(boost::bind(f2, 0.95, _1), -2.5, 2.5, "k=0.95");
  620. plot.add(boost::bind(f2, 1, _1), -2.5, 2.5, "k=1");
  621. plot.plot("Jacobi Elliptic sd", "jacobi_sd.svg", "k", "jacobi_sd(k, u)");
  622. f = boost::math::airy_ai;
  623. plot.clear();
  624. plot.add(f, -20, 20, "");
  625. plot.plot("Ai", "airy_ai.svg", "z", "airy_ai(z)");
  626. f = boost::math::airy_bi;
  627. plot.clear();
  628. plot.add(f, -20, 3, "");
  629. plot.plot("Bi", "airy_bi.svg", "z", "airy_bi(z)");
  630. f = boost::math::airy_ai_prime;
  631. plot.clear();
  632. plot.add(f, -20, 20, "");
  633. plot.plot("Ai'", "airy_aip.svg", "z", "airy_ai_prime(z)");
  634. f = boost::math::airy_bi_prime;
  635. plot.clear();
  636. plot.add(f, -20, 3, "");
  637. plot.plot("Bi'", "airy_bip.svg", "z", "airy_bi_prime(z)");
  638. f = boost::math::trigamma;
  639. max_val = 30;
  640. plot.clear();
  641. plot.add(f, find_end_point(f, 0.1, max_val, false), 5, "");
  642. plot.add(f, find_end_point(f, 0.1, max_val, false, -1), find_end_point(f, -0.1, max_val, true), "");
  643. plot.add(f, find_end_point(f, 0.1, max_val, false, -2), find_end_point(f, -0.1, max_val, true, -1), "");
  644. plot.add(f, find_end_point(f, 0.1, max_val, false, -3), find_end_point(f, -0.1, max_val, true, -2), "");
  645. plot.add(f, find_end_point(f, 0.1, max_val, false, -4), find_end_point(f, -0.1, max_val, true, -3), "");
  646. plot.add(f, find_end_point(f, 0.1, max_val, false, -5), find_end_point(f, -0.1, max_val, true, -4), "");
  647. plot.plot("Trigamma", "trigamma.svg", "x", "trigamma(x)");
  648. f2i = boost::math::polygamma;
  649. max_val = -50;
  650. plot.clear();
  651. plot.add(boost::bind(f2i, 2, _1), find_end_point(boost::bind(f2i, 2, _1), 0.1, max_val, true), 5, "");
  652. plot.add(boost::bind(f2i, 2, _1), find_end_point(boost::bind(f2i, 2, _1), 0.1, max_val, true, -1), find_end_point(boost::bind(f2i, 2, _1), -0.1, -max_val, true), "");
  653. plot.add(boost::bind(f2i, 2, _1), find_end_point(boost::bind(f2i, 2, _1), 0.1, max_val, true, -2), find_end_point(boost::bind(f2i, 2, _1), -0.1, -max_val, true, -1), "");
  654. plot.add(boost::bind(f2i, 2, _1), find_end_point(boost::bind(f2i, 2, _1), 0.1, max_val, true, -3), find_end_point(boost::bind(f2i, 2, _1), -0.1, -max_val, true, -2), "");
  655. plot.add(boost::bind(f2i, 2, _1), find_end_point(boost::bind(f2i, 2, _1), 0.1, max_val, true, -4), find_end_point(boost::bind(f2i, 2, _1), -0.1, -max_val, true, -3), "");
  656. plot.add(boost::bind(f2i, 2, _1), find_end_point(boost::bind(f2i, 2, _1), 0.1, max_val, true, -5), find_end_point(boost::bind(f2i, 2, _1), -0.1, -max_val, true, -4), "");
  657. plot.add(boost::bind(f2i, 2, _1), find_end_point(boost::bind(f2i, 2, _1), 0.1, max_val, true, -6), find_end_point(boost::bind(f2i, 2, _1), -0.1, -max_val, true, -5), "");
  658. plot.plot("Polygamma", "polygamma2.svg", "x", "polygamma(2, x)");
  659. max_val = 800;
  660. plot.clear();
  661. plot.add(boost::bind(f2i, 3, _1), find_end_point(boost::bind(f2i, 3, _1), 0.1, max_val, false), 5, "");
  662. plot.add(boost::bind(f2i, 3, _1), find_end_point(boost::bind(f2i, 3, _1), 0.1, max_val, false, -1), find_end_point(boost::bind(f2i, 3, _1), -0.1, max_val, true), "");
  663. plot.add(boost::bind(f2i, 3, _1), find_end_point(boost::bind(f2i, 3, _1), 0.1, max_val, false, -2), find_end_point(boost::bind(f2i, 3, _1), -0.1, max_val, true, -1), "");
  664. plot.add(boost::bind(f2i, 3, _1), find_end_point(boost::bind(f2i, 3, _1), 0.1, max_val, false, -3), find_end_point(boost::bind(f2i, 3, _1), -0.1, max_val, true, -2), "");
  665. plot.add(boost::bind(f2i, 3, _1), find_end_point(boost::bind(f2i, 3, _1), 0.1, max_val, false, -4), find_end_point(boost::bind(f2i, 3, _1), -0.1, max_val, true, -3), "");
  666. plot.add(boost::bind(f2i, 3, _1), find_end_point(boost::bind(f2i, 3, _1), 0.1, max_val, false, -5), find_end_point(boost::bind(f2i, 3, _1), -0.1, max_val, true, -4), "");
  667. plot.add(boost::bind(f2i, 3, _1), find_end_point(boost::bind(f2i, 3, _1), 0.1, max_val, false, -6), find_end_point(boost::bind(f2i, 3, _1), -0.1, max_val, true, -5), "");
  668. plot.plot("Polygamma", "polygamma3.svg", "x", "polygamma(3, x)");
  669. }
  670. catch (const std::exception& ex)
  671. {
  672. std::cout << ex.what() << std::endl;
  673. }
  674. return 0;
  675. }