test_autodiff_3.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. // Copyright Matthew Pulver 2018 - 2019.
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE_1_0.txt or copy at
  4. // https://www.boost.org/LICENSE_1_0.txt)
  5. #include "test_autodiff.hpp"
  6. #include <boost/utility/identity_type.hpp>
  7. BOOST_AUTO_TEST_SUITE(test_autodiff_3)
  8. BOOST_AUTO_TEST_CASE_TEMPLATE(atanh_test, T, all_float_types) {
  9. const T eps = 3000 * test_constants_t<T>::pct_epsilon(); // percent
  10. constexpr unsigned m = 5;
  11. const T cx = 0.5;
  12. auto x = make_fvar<T, m>(cx);
  13. auto y = atanh(x);
  14. // BOOST_CHECK_EQUAL(y.derivative(0) , atanh(cx)); // fails due to overload
  15. BOOST_CHECK_CLOSE(y.derivative(0u), atanh(static_cast<T>(x)), eps);
  16. BOOST_CHECK_CLOSE(y.derivative(1u), static_cast<T>(4) / 3, eps);
  17. BOOST_CHECK_CLOSE(y.derivative(2u), static_cast<T>(16) / 9, eps);
  18. BOOST_CHECK_CLOSE(y.derivative(3u), static_cast<T>(224) / 27, eps);
  19. BOOST_CHECK_CLOSE(y.derivative(4u), static_cast<T>(1280) / 27, eps);
  20. BOOST_CHECK_CLOSE(y.derivative(5u), static_cast<T>(31232) / 81, eps);
  21. }
  22. BOOST_AUTO_TEST_CASE_TEMPLATE(atan_test, T, all_float_types) {
  23. BOOST_MATH_STD_USING
  24. using namespace boost;
  25. const T cx = 1.0;
  26. constexpr unsigned m = 5;
  27. const auto x = make_fvar<T, m>(cx);
  28. auto y = atan(x);
  29. const auto eps = boost::math::tools::epsilon<T>();
  30. BOOST_CHECK_CLOSE(y.derivative(0u), boost::math::constants::pi<T>() / 4, eps);
  31. BOOST_CHECK_CLOSE(y.derivative(1u), T(0.5), eps);
  32. BOOST_CHECK_CLOSE(y.derivative(2u), T(-0.5), eps);
  33. BOOST_CHECK_CLOSE(y.derivative(3u), T(0.5), eps);
  34. BOOST_CHECK_CLOSE(y.derivative(4u), T(0), eps);
  35. BOOST_CHECK_CLOSE(y.derivative(5u), T(-3), eps);
  36. }
  37. BOOST_AUTO_TEST_CASE_TEMPLATE(erf_test, T, all_float_types) {
  38. BOOST_MATH_STD_USING
  39. using namespace boost;
  40. const T eps = 300 * 100 * boost::math::tools::epsilon<T>(); // percent
  41. const T cx = 1.0;
  42. constexpr unsigned m = 5;
  43. const auto x = make_fvar<T, m>(cx);
  44. auto y = erf(x);
  45. BOOST_CHECK_CLOSE(y.derivative(0u), erf(static_cast<T>(x)), eps);
  46. BOOST_CHECK_CLOSE(
  47. y.derivative(1u),
  48. T(2) / (math::constants::e<T>() * math::constants::root_pi<T>()), eps);
  49. BOOST_CHECK_CLOSE(
  50. y.derivative(2u),
  51. T(-4) / (math::constants::e<T>() * math::constants::root_pi<T>()), eps);
  52. BOOST_CHECK_CLOSE(
  53. y.derivative(3u),
  54. T(4) / (math::constants::e<T>() * math::constants::root_pi<T>()), eps);
  55. BOOST_CHECK_CLOSE(
  56. y.derivative(4u),
  57. T(8) / (math::constants::e<T>() * math::constants::root_pi<T>()), eps);
  58. BOOST_CHECK_CLOSE(
  59. y.derivative(5u),
  60. T(-40) / (math::constants::e<T>() * math::constants::root_pi<T>()), eps);
  61. }
  62. BOOST_AUTO_TEST_CASE_TEMPLATE(sinc_test, T, bin_float_types) {
  63. BOOST_MATH_STD_USING
  64. const T eps = 20000 * boost::math::tools::epsilon<T>(); // percent
  65. const T cx = 1;
  66. constexpr unsigned m = 5;
  67. auto x = make_fvar<T, m>(cx);
  68. auto y = sinc(x);
  69. BOOST_CHECK_CLOSE(y.derivative(0u), sin(cx), eps);
  70. BOOST_CHECK_CLOSE(y.derivative(1u), cos(cx) - sin(cx), eps);
  71. BOOST_CHECK_CLOSE(y.derivative(2u), sin(cx) - 2 * cos(cx), eps);
  72. BOOST_CHECK_CLOSE(y.derivative(3u), T(5) * cos(cx) - T(3) * sin(cx), eps);
  73. BOOST_CHECK_CLOSE(y.derivative(4u), T(13) * sin(cx) - T(20) * cos(cx), eps);
  74. BOOST_CHECK_CLOSE(y.derivative(5u), T(101) * cos(cx) - T(65) * sin(cx), eps);
  75. // Test at x = 0
  76. auto y2 = sinc(make_fvar<T, 10>(0));
  77. BOOST_CHECK_CLOSE(y2.derivative(0u), T(1), eps);
  78. BOOST_CHECK_CLOSE(y2.derivative(1u), T(0), eps);
  79. BOOST_CHECK_CLOSE(y2.derivative(2u), -cx / T(3), eps);
  80. BOOST_CHECK_CLOSE(y2.derivative(3u), T(0), eps);
  81. BOOST_CHECK_CLOSE(y2.derivative(4u), cx / T(5), eps);
  82. BOOST_CHECK_CLOSE(y2.derivative(5u), T(0), eps);
  83. BOOST_CHECK_CLOSE(y2.derivative(6u), -cx / T(7), eps);
  84. BOOST_CHECK_CLOSE(y2.derivative(7u), T(0), eps);
  85. BOOST_CHECK_CLOSE(y2.derivative(8u), cx / T(9), eps);
  86. BOOST_CHECK_CLOSE(y2.derivative(9u), T(0), eps);
  87. BOOST_CHECK_CLOSE(y2.derivative(10u), -cx / T(11), eps);
  88. }
  89. BOOST_AUTO_TEST_CASE_TEMPLATE(sinh_and_cosh, T, bin_float_types) {
  90. BOOST_MATH_STD_USING
  91. const T eps = 300 * boost::math::tools::epsilon<T>(); // percent
  92. const T cx = 1;
  93. constexpr unsigned m = 5;
  94. auto x = make_fvar<T, m>(cx);
  95. auto s = sinh(x);
  96. auto c = cosh(x);
  97. BOOST_CHECK_CLOSE(s.derivative(0u), sinh(static_cast<T>(x)), eps);
  98. BOOST_CHECK_CLOSE(c.derivative(0u), cosh(static_cast<T>(x)), eps);
  99. for (auto i : boost::irange(m + 1)) {
  100. BOOST_CHECK_CLOSE(s.derivative(i), static_cast<T>(i % 2 == 1 ? c : s), eps);
  101. BOOST_CHECK_CLOSE(c.derivative(i), static_cast<T>(i % 2 == 1 ? s : c), eps);
  102. }
  103. }
  104. #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
  105. BOOST_AUTO_TEST_CASE_TEMPLATE(tanh_test, T, all_float_types) {
  106. using bmp::fabs;
  107. using bmp::tanh;
  108. using detail::fabs;
  109. using detail::tanh;
  110. using std::fabs;
  111. using std::tanh;
  112. constexpr std::array<const char *, 6> tanh_derivatives{
  113. {"0."
  114. "76159415595576488811945828260479359041276859725793655159681050012195324"
  115. "457663848345894752167367671442190275970155",
  116. "0."
  117. "41997434161402606939449673904170144491718672823077095471331144024458989"
  118. "95240483056156940088623187260",
  119. "-0."
  120. "63970000844922450018849176930384395321921136306079914494299856318702069"
  121. "34885434644440069533372017992",
  122. "0."
  123. "62162668077129626310653042872222339967572411755445418563968706335816206"
  124. "22188951465548376863495698762",
  125. "0."
  126. "66509104475050167773507148092106234992757132833203125448814929383096463"
  127. "47626843278089998045994094537",
  128. "-5."
  129. "55689355847371979760458290231697200987383372116293456019531342394708989"
  130. "7942786231796317250984197038"}};
  131. const T cx = 1;
  132. constexpr std::size_t m = 5;
  133. auto x = make_fvar<T, m>(cx);
  134. auto t = tanh(x);
  135. for (auto i : boost::irange(tanh_derivatives.size())) {
  136. BOOST_TEST_WARN(isNearZero(t.derivative(i) -
  137. boost::lexical_cast<T>(tanh_derivatives[i])));
  138. }
  139. }
  140. #endif
  141. BOOST_AUTO_TEST_CASE_TEMPLATE(tan_test, T, bin_float_types) {
  142. BOOST_MATH_STD_USING
  143. const T eps = 800 * boost::math::tools::epsilon<T>(); // percent
  144. const T cx = boost::math::constants::third_pi<T>();
  145. const T root_three = boost::math::constants::root_three<T>();
  146. constexpr unsigned m = 5;
  147. const auto x = make_fvar<T, m>(cx);
  148. auto y = tan(x);
  149. BOOST_CHECK_CLOSE(y.derivative(0u), root_three, eps);
  150. BOOST_CHECK_CLOSE(y.derivative(1u), T(4), eps);
  151. BOOST_CHECK_CLOSE(y.derivative(2u), T(8) * root_three, eps);
  152. BOOST_CHECK_CLOSE(y.derivative(3u), T(80), eps);
  153. BOOST_CHECK_CLOSE(y.derivative(4u), T(352) * root_three, eps);
  154. BOOST_CHECK_CLOSE(y.derivative(5u), T(5824), eps);
  155. }
  156. BOOST_AUTO_TEST_CASE_TEMPLATE(fmod_test, T, bin_float_types) {
  157. BOOST_MATH_STD_USING
  158. constexpr unsigned m = 3;
  159. const T cx = 3.25;
  160. const T cy = 0.5;
  161. auto x = make_fvar<T, m>(cx);
  162. auto y = fmod(x, autodiff_fvar<T, m>(cy));
  163. BOOST_CHECK_EQUAL(y.derivative(0u), T(0.25));
  164. BOOST_CHECK_EQUAL(y.derivative(1u), T(1));
  165. BOOST_CHECK_EQUAL(y.derivative(2u), T(0));
  166. BOOST_CHECK_EQUAL(y.derivative(3u), T(0));
  167. }
  168. BOOST_AUTO_TEST_CASE_TEMPLATE(round_and_trunc, T, all_float_types) {
  169. BOOST_MATH_STD_USING
  170. constexpr unsigned m = 3;
  171. const T cx = 3.25;
  172. auto x = make_fvar<T, m>(cx);
  173. auto y = round(x);
  174. BOOST_CHECK_EQUAL(y.derivative(0u), round(cx));
  175. BOOST_CHECK_EQUAL(y.derivative(1u), T(0));
  176. BOOST_CHECK_EQUAL(y.derivative(2u), T(0));
  177. BOOST_CHECK_EQUAL(y.derivative(3u), T(0));
  178. y = trunc(x);
  179. BOOST_CHECK_EQUAL(y.derivative(0u), trunc(cx));
  180. BOOST_CHECK_EQUAL(y.derivative(1u), T(0));
  181. BOOST_CHECK_EQUAL(y.derivative(2u), T(0));
  182. BOOST_CHECK_EQUAL(y.derivative(3u), T(0));
  183. }
  184. BOOST_AUTO_TEST_CASE_TEMPLATE(iround_and_itrunc, T, all_float_types) {
  185. BOOST_MATH_STD_USING
  186. using namespace boost::math;
  187. constexpr unsigned m = 3;
  188. const T cx = 3.25;
  189. auto x = make_fvar<T, m>(cx);
  190. int y = iround(x);
  191. BOOST_CHECK_EQUAL(y, iround(cx));
  192. y = itrunc(x);
  193. BOOST_CHECK_EQUAL(y, itrunc(cx));
  194. }
  195. BOOST_AUTO_TEST_CASE_TEMPLATE(lambert_w0_test, T, all_float_types) {
  196. const T eps = 1000 * boost::math::tools::epsilon<T>(); // percent
  197. constexpr unsigned m = 10;
  198. const T cx = 3;
  199. // Mathematica: N[Table[D[ProductLog[x], {x, n}], {n, 0, 10}] /. x -> 3, 52]
  200. constexpr std::array<const char *, m + 1> answers{
  201. {"1.049908894964039959988697070552897904589466943706341",
  202. "0.1707244807388472968312949774415522047470762509741737",
  203. "-0.04336545501146252734105411312976167858858970875797718",
  204. "0.02321456264324789334313200360870492961288748451791104",
  205. "-0.01909049778427783072663170526188353869136655225133878",
  206. "0.02122935002563637629500975949987796094687564718834156",
  207. "-0.02979093848448877259041971538394953658978044986784643",
  208. "0.05051290266216717699803334605370337985567016837482099",
  209. "-0.1004503154972645060971099914384090562800544486549660",
  210. "0.2292464437392250211967939182075930820454464472006425",
  211. "-0.5905839053125614593682763387470654123192290838719517"}};
  212. auto x = make_fvar<T, m>(cx);
  213. auto y = lambert_w0(x);
  214. for (auto i : boost::irange(m + 1)) {
  215. const T answer = boost::lexical_cast<T>(answers[i]);
  216. BOOST_CHECK_CLOSE(y.derivative(i), answer, eps);
  217. }
  218. // const T cx0 = -1 / boost::math::constants::e<T>();
  219. // auto edge = lambert_w0(make_fvar<T,m>(cx0));
  220. // std::cout << "edge = " << edge << std::endl;
  221. // edge = depth(1)(-1,inf,-inf,inf,-inf,inf,-inf,inf,-inf,inf,-inf)
  222. // edge = depth(1)(-1,inf,-inf,inf,-inf,inf,-inf,inf,-inf,inf,-inf)
  223. // edge =
  224. // depth(1)(-1,3.68935e+19,-9.23687e+57,4.62519e+96,-2.89497e+135,2.02945e+174,-1.52431e+213,1.19943e+252,-9.75959e+290,8.14489e+329,-6.93329e+368)
  225. }
  226. BOOST_AUTO_TEST_CASE_TEMPLATE(digamma_test, T, all_float_types) {
  227. const T eps = 1000 * boost::math::tools::epsilon<T>(); // percent
  228. constexpr unsigned m = 10;
  229. const T cx = 3;
  230. // Mathematica: N[Table[PolyGamma[n, 3], {n, 0, 10}], 52]
  231. constexpr std::array<const char *, m + 1> answers{
  232. {"0.9227843350984671393934879099175975689578406640600764"
  233. ,"0.3949340668482264364724151666460251892189499012067984"
  234. ,"-0.1541138063191885707994763230228999815299725846809978"
  235. ,"0.1189394022668291490960221792470074166485057115123614"
  236. ,"-0.1362661234408782319527716749688200333699420680459075"
  237. ,"0.2061674381338967657421515749104633482180988039424274"
  238. ,"-0.3864797149844353246542358918536669119017636069718686"
  239. ,"0.8623752376394704685736020836084249051623848752441025"
  240. ,"-2.228398747634885327823655450854278779627928241914664"
  241. ,"6.536422382626807143525565747764891144367614117601463"
  242. ,"-21.4366066287129906188428320541054572790340793874298"}};
  243. auto x = make_fvar<T, m>(cx);
  244. auto y = digamma(x);
  245. for (auto i : boost::irange(m + 1)) {
  246. const T answer = boost::lexical_cast<T>(answers[i]);
  247. BOOST_CHECK_CLOSE(y.derivative(i), answer, eps);
  248. }
  249. }
  250. BOOST_AUTO_TEST_CASE_TEMPLATE(lgamma_test, T, all_float_types) {
  251. const T eps = 1000 * boost::math::tools::epsilon<T>(); // percent
  252. constexpr unsigned m = 10;
  253. const T cx = 3;
  254. // Mathematica: N[Table[D[LogGamma[x],{x,n}] /. x->3, {n, 0, 10}], 52]
  255. constexpr std::array<const char *, m + 1> answers{
  256. {"0.6931471805599453094172321214581765680755001343602553"
  257. ,"0.9227843350984671393934879099175975689578406640600764"
  258. ,"0.3949340668482264364724151666460251892189499012067984"
  259. ,"-0.1541138063191885707994763230228999815299725846809978"
  260. ,"0.1189394022668291490960221792470074166485057115123614"
  261. ,"-0.1362661234408782319527716749688200333699420680459075"
  262. ,"0.2061674381338967657421515749104633482180988039424274"
  263. ,"-0.3864797149844353246542358918536669119017636069718686"
  264. ,"0.8623752376394704685736020836084249051623848752441025"
  265. ,"-2.228398747634885327823655450854278779627928241914664"
  266. ,"6.536422382626807143525565747764891144367614117601463"}};
  267. auto x = make_fvar<T, m>(cx);
  268. auto y = lgamma(x);
  269. for (auto i : boost::irange(m + 1)) {
  270. const T answer = boost::lexical_cast<T>(answers[i]);
  271. BOOST_CHECK_CLOSE(y.derivative(i), answer, eps);
  272. }
  273. }
  274. BOOST_AUTO_TEST_CASE_TEMPLATE(tgamma_test, T, all_float_types) {
  275. const T eps = 1000 * boost::math::tools::epsilon<T>(); // percent
  276. constexpr unsigned m = 10;
  277. const T cx = 3;
  278. // Mathematica: N[Table[D[Gamma[x],{x,n}] /. x->3, {n, 0, 10}], 52]
  279. constexpr std::array<const char *, m + 1> answers{
  280. {"2.0"
  281. ,"1.845568670196934278786975819835195137915681328120153"
  282. ,"2.492929991902693057942510065508124245503778067273315"
  283. ,"3.449965013523673365279327178241708777509009968597547"
  284. ,"5.521798578098737512443417699412265532987916790978887"
  285. ,"8.845805593922864253981346455183370214190789096412155"
  286. ,"15.86959874461221647760760269963155031595848150772695"
  287. ,"27.46172054213435946038727460195592342721862288816812"
  288. ,"54.64250508485402729556251663145824730270508661240771"
  289. ,"96.08542140594972502872131946513104238293824803599579"
  290. ,"222.0936743583156040996433943128676567542497584689499"}};
  291. auto x = make_fvar<T, m>(cx);
  292. auto y = tgamma(x);
  293. for (auto i : boost::irange(m + 1)) {
  294. const T answer = boost::lexical_cast<T>(answers[i]);
  295. BOOST_CHECK_CLOSE(y.derivative(i), answer, eps);
  296. }
  297. }
  298. BOOST_AUTO_TEST_CASE_TEMPLATE(tgamma2_test, T, all_float_types) {
  299. //const T eps = 5000 * boost::math::tools::epsilon<T>(); // ok for non-multiprecision
  300. const T eps = 500000 * boost::math::tools::epsilon<T>(); // percent
  301. constexpr unsigned m = 10;
  302. const T cx = -1.5;
  303. // Mathematica: N[Table[D[Gamma[x],{x,n}] /. x->-3/2, {n, 0, 10}], 52]
  304. constexpr std::array<const char *, m + 1> answers{
  305. {"2.363271801207354703064223311121526910396732608163183"
  306. ,"1.661750260668596505586468565464938761014714509096807"
  307. ,"23.33417984355457252918927856618603412638766668207679"
  308. ,"47.02130025080143055642555842335081335790754507072526"
  309. ,"1148.336052788822231948472800239024335856568111484074"
  310. ,"3831.214710988836934569706027888431190714054814541186"
  311. ,"138190.9008816865362698874238213771413807566436072179"
  312. ,"644956.0066517306036921195893233874126907491308967028"
  313. ,"3.096453684470713902448094810299787572782887316764214e7"
  314. ,"1.857893143852025058151037296906468662709947415219451e8"
  315. ,"1.114762466163487983067783853825224537320312784955935e10"}};
  316. auto x = make_fvar<T, m>(cx);
  317. auto y = tgamma(x);
  318. for (auto i : boost::irange(m + 1)) {
  319. const T answer = boost::lexical_cast<T>(answers[i]);
  320. BOOST_CHECK_CLOSE(y.derivative(i), answer, eps);
  321. }
  322. }
  323. BOOST_AUTO_TEST_SUITE_END()