autodiff.hpp 81 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061
  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. #ifndef BOOST_MATH_DIFFERENTIATION_AUTODIFF_HPP
  6. #define BOOST_MATH_DIFFERENTIATION_AUTODIFF_HPP
  7. #include <boost/cstdfloat.hpp>
  8. #include <boost/math/constants/constants.hpp>
  9. #include <boost/math/special_functions/trunc.hpp>
  10. #include <boost/math/special_functions/round.hpp>
  11. #include <boost/math/special_functions/acosh.hpp>
  12. #include <boost/math/special_functions/asinh.hpp>
  13. #include <boost/math/special_functions/atanh.hpp>
  14. #include <boost/math/special_functions/digamma.hpp>
  15. #include <boost/math/special_functions/polygamma.hpp>
  16. #include <boost/math/special_functions/erf.hpp>
  17. #include <boost/math/special_functions/lambert_w.hpp>
  18. #include <boost/math/tools/config.hpp>
  19. #include <boost/math/tools/promotion.hpp>
  20. #include <algorithm>
  21. #include <array>
  22. #include <cmath>
  23. #include <functional>
  24. #include <limits>
  25. #include <numeric>
  26. #include <ostream>
  27. #include <tuple>
  28. #include <type_traits>
  29. namespace boost {
  30. namespace math {
  31. namespace differentiation {
  32. // Automatic Differentiation v1
  33. inline namespace autodiff_v1 {
  34. namespace detail {
  35. template <typename RealType, typename... RealTypes>
  36. struct promote_args_n {
  37. using type = typename tools::promote_args_2<RealType, typename promote_args_n<RealTypes...>::type>::type;
  38. };
  39. template <typename RealType>
  40. struct promote_args_n<RealType> {
  41. using type = typename tools::promote_arg<RealType>::type;
  42. };
  43. } // namespace detail
  44. template <typename RealType, typename... RealTypes>
  45. using promote = typename detail::promote_args_n<RealType, RealTypes...>::type;
  46. namespace detail {
  47. template <typename RealType, size_t Order>
  48. class fvar;
  49. template <typename T>
  50. struct is_fvar_impl : std::false_type {};
  51. template <typename RealType, size_t Order>
  52. struct is_fvar_impl<fvar<RealType, Order>> : std::true_type {};
  53. template <typename T>
  54. using is_fvar = is_fvar_impl<typename std::decay<T>::type>;
  55. template <typename RealType, size_t Order, size_t... Orders>
  56. struct nest_fvar {
  57. using type = fvar<typename nest_fvar<RealType, Orders...>::type, Order>;
  58. };
  59. template <typename RealType, size_t Order>
  60. struct nest_fvar<RealType, Order> {
  61. using type = fvar<RealType, Order>;
  62. };
  63. template <typename>
  64. struct get_depth_impl : std::integral_constant<size_t, 0> {};
  65. template <typename RealType, size_t Order>
  66. struct get_depth_impl<fvar<RealType, Order>>
  67. : std::integral_constant<size_t, get_depth_impl<RealType>::value + 1> {};
  68. template <typename T>
  69. using get_depth = get_depth_impl<typename std::decay<T>::type>;
  70. template <typename>
  71. struct get_order_sum_t : std::integral_constant<size_t, 0> {};
  72. template <typename RealType, size_t Order>
  73. struct get_order_sum_t<fvar<RealType, Order>>
  74. : std::integral_constant<size_t, get_order_sum_t<RealType>::value + Order> {};
  75. template <typename T>
  76. using get_order_sum = get_order_sum_t<typename std::decay<T>::type>;
  77. template <typename RealType>
  78. struct get_root_type {
  79. using type = RealType;
  80. };
  81. template <typename RealType, size_t Order>
  82. struct get_root_type<fvar<RealType, Order>> {
  83. using type = typename get_root_type<RealType>::type;
  84. };
  85. template <typename RealType, size_t Depth>
  86. struct type_at {
  87. using type = RealType;
  88. };
  89. template <typename RealType, size_t Order, size_t Depth>
  90. struct type_at<fvar<RealType, Order>, Depth> {
  91. using type = typename conditional<Depth == 0,
  92. fvar<RealType, Order>,
  93. typename type_at<RealType, Depth - 1>::type>::type;
  94. };
  95. template <typename RealType, size_t Depth>
  96. using get_type_at = typename type_at<RealType, Depth>::type;
  97. // Satisfies Boost's Conceptual Requirements for Real Number Types.
  98. // https://www.boost.org/libs/math/doc/html/math_toolkit/real_concepts.html
  99. template <typename RealType, size_t Order>
  100. class fvar {
  101. protected:
  102. std::array<RealType, Order + 1> v;
  103. public:
  104. using root_type = typename get_root_type<RealType>::type; // RealType in the root fvar<RealType,Order>.
  105. fvar() = default;
  106. // Initialize a variable or constant.
  107. fvar(root_type const&, bool const is_variable);
  108. // RealType(cr) | RealType | RealType is copy constructible.
  109. fvar(fvar const&) = default;
  110. // Be aware of implicit casting from one fvar<> type to another by this copy constructor.
  111. template <typename RealType2, size_t Order2>
  112. fvar(fvar<RealType2, Order2> const&);
  113. // RealType(ca) | RealType | RealType is copy constructible from the arithmetic types.
  114. explicit fvar(root_type const&); // Initialize a constant. (No epsilon terms.)
  115. template <typename RealType2>
  116. fvar(RealType2 const& ca); // Supports any RealType2 for which static_cast<root_type>(ca) compiles.
  117. // r = cr | RealType& | Assignment operator.
  118. fvar& operator=(fvar const&) = default;
  119. // r = ca | RealType& | Assignment operator from the arithmetic types.
  120. // Handled by constructor that takes a single parameter of generic type.
  121. // fvar& operator=(root_type const&); // Set a constant.
  122. // r += cr | RealType& | Adds cr to r.
  123. template <typename RealType2, size_t Order2>
  124. fvar& operator+=(fvar<RealType2, Order2> const&);
  125. // r += ca | RealType& | Adds ar to r.
  126. fvar& operator+=(root_type const&);
  127. // r -= cr | RealType& | Subtracts cr from r.
  128. template <typename RealType2, size_t Order2>
  129. fvar& operator-=(fvar<RealType2, Order2> const&);
  130. // r -= ca | RealType& | Subtracts ca from r.
  131. fvar& operator-=(root_type const&);
  132. // r *= cr | RealType& | Multiplies r by cr.
  133. template <typename RealType2, size_t Order2>
  134. fvar& operator*=(fvar<RealType2, Order2> const&);
  135. // r *= ca | RealType& | Multiplies r by ca.
  136. fvar& operator*=(root_type const&);
  137. // r /= cr | RealType& | Divides r by cr.
  138. template <typename RealType2, size_t Order2>
  139. fvar& operator/=(fvar<RealType2, Order2> const&);
  140. // r /= ca | RealType& | Divides r by ca.
  141. fvar& operator/=(root_type const&);
  142. // -r | RealType | Unary Negation.
  143. fvar operator-() const;
  144. // +r | RealType& | Identity Operation.
  145. fvar const& operator+() const;
  146. // cr + cr2 | RealType | Binary Addition
  147. template <typename RealType2, size_t Order2>
  148. promote<fvar, fvar<RealType2, Order2>> operator+(fvar<RealType2, Order2> const&) const;
  149. // cr + ca | RealType | Binary Addition
  150. fvar operator+(root_type const&) const;
  151. // ca + cr | RealType | Binary Addition
  152. template <typename RealType2, size_t Order2>
  153. friend fvar<RealType2, Order2> operator+(typename fvar<RealType2, Order2>::root_type const&,
  154. fvar<RealType2, Order2> const&);
  155. // cr - cr2 | RealType | Binary Subtraction
  156. template <typename RealType2, size_t Order2>
  157. promote<fvar, fvar<RealType2, Order2>> operator-(fvar<RealType2, Order2> const&) const;
  158. // cr - ca | RealType | Binary Subtraction
  159. fvar operator-(root_type const&) const;
  160. // ca - cr | RealType | Binary Subtraction
  161. template <typename RealType2, size_t Order2>
  162. friend fvar<RealType2, Order2> operator-(typename fvar<RealType2, Order2>::root_type const&,
  163. fvar<RealType2, Order2> const&);
  164. // cr * cr2 | RealType | Binary Multiplication
  165. template <typename RealType2, size_t Order2>
  166. promote<fvar, fvar<RealType2, Order2>> operator*(fvar<RealType2, Order2> const&)const;
  167. // cr * ca | RealType | Binary Multiplication
  168. fvar operator*(root_type const&)const;
  169. // ca * cr | RealType | Binary Multiplication
  170. template <typename RealType2, size_t Order2>
  171. friend fvar<RealType2, Order2> operator*(typename fvar<RealType2, Order2>::root_type const&,
  172. fvar<RealType2, Order2> const&);
  173. // cr / cr2 | RealType | Binary Subtraction
  174. template <typename RealType2, size_t Order2>
  175. promote<fvar, fvar<RealType2, Order2>> operator/(fvar<RealType2, Order2> const&) const;
  176. // cr / ca | RealType | Binary Subtraction
  177. fvar operator/(root_type const&) const;
  178. // ca / cr | RealType | Binary Subtraction
  179. template <typename RealType2, size_t Order2>
  180. friend fvar<RealType2, Order2> operator/(typename fvar<RealType2, Order2>::root_type const&,
  181. fvar<RealType2, Order2> const&);
  182. // For all comparison overloads, only the root term is compared.
  183. // cr == cr2 | bool | Equality Comparison
  184. template <typename RealType2, size_t Order2>
  185. bool operator==(fvar<RealType2, Order2> const&) const;
  186. // cr == ca | bool | Equality Comparison
  187. bool operator==(root_type const&) const;
  188. // ca == cr | bool | Equality Comparison
  189. template <typename RealType2, size_t Order2>
  190. friend bool operator==(typename fvar<RealType2, Order2>::root_type const&, fvar<RealType2, Order2> const&);
  191. // cr != cr2 | bool | Inequality Comparison
  192. template <typename RealType2, size_t Order2>
  193. bool operator!=(fvar<RealType2, Order2> const&) const;
  194. // cr != ca | bool | Inequality Comparison
  195. bool operator!=(root_type const&) const;
  196. // ca != cr | bool | Inequality Comparison
  197. template <typename RealType2, size_t Order2>
  198. friend bool operator!=(typename fvar<RealType2, Order2>::root_type const&, fvar<RealType2, Order2> const&);
  199. // cr <= cr2 | bool | Less than equal to.
  200. template <typename RealType2, size_t Order2>
  201. bool operator<=(fvar<RealType2, Order2> const&) const;
  202. // cr <= ca | bool | Less than equal to.
  203. bool operator<=(root_type const&) const;
  204. // ca <= cr | bool | Less than equal to.
  205. template <typename RealType2, size_t Order2>
  206. friend bool operator<=(typename fvar<RealType2, Order2>::root_type const&, fvar<RealType2, Order2> const&);
  207. // cr >= cr2 | bool | Greater than equal to.
  208. template <typename RealType2, size_t Order2>
  209. bool operator>=(fvar<RealType2, Order2> const&) const;
  210. // cr >= ca | bool | Greater than equal to.
  211. bool operator>=(root_type const&) const;
  212. // ca >= cr | bool | Greater than equal to.
  213. template <typename RealType2, size_t Order2>
  214. friend bool operator>=(typename fvar<RealType2, Order2>::root_type const&, fvar<RealType2, Order2> const&);
  215. // cr < cr2 | bool | Less than comparison.
  216. template <typename RealType2, size_t Order2>
  217. bool operator<(fvar<RealType2, Order2> const&) const;
  218. // cr < ca | bool | Less than comparison.
  219. bool operator<(root_type const&) const;
  220. // ca < cr | bool | Less than comparison.
  221. template <typename RealType2, size_t Order2>
  222. friend bool operator<(typename fvar<RealType2, Order2>::root_type const&, fvar<RealType2, Order2> const&);
  223. // cr > cr2 | bool | Greater than comparison.
  224. template <typename RealType2, size_t Order2>
  225. bool operator>(fvar<RealType2, Order2> const&) const;
  226. // cr > ca | bool | Greater than comparison.
  227. bool operator>(root_type const&) const;
  228. // ca > cr | bool | Greater than comparison.
  229. template <typename RealType2, size_t Order2>
  230. friend bool operator>(typename fvar<RealType2, Order2>::root_type const&, fvar<RealType2, Order2> const&);
  231. // Will throw std::out_of_range if Order < order.
  232. template <typename... Orders>
  233. get_type_at<RealType, sizeof...(Orders)> at(size_t order, Orders... orders) const;
  234. template <typename... Orders>
  235. get_type_at<fvar, sizeof...(Orders)> derivative(Orders... orders) const;
  236. const RealType& operator[](size_t) const;
  237. fvar inverse() const; // Multiplicative inverse.
  238. fvar& negate(); // Negate and return reference to *this.
  239. static constexpr size_t depth = get_depth<fvar>::value; // Number of nested std::array<RealType,Order>.
  240. static constexpr size_t order_sum = get_order_sum<fvar>::value;
  241. explicit operator root_type() const; // Must be explicit, otherwise overloaded operators are ambiguous.
  242. template <typename T, typename = typename std::enable_if<std::is_arithmetic<typename std::decay<T>::type>::value>>
  243. explicit operator T() const; // Must be explicit; multiprecision has trouble without the std::enable_if
  244. fvar& set_root(root_type const&);
  245. // Apply coefficients using horner method.
  246. template <typename Func, typename Fvar, typename... Fvars>
  247. promote<fvar<RealType, Order>, Fvar, Fvars...> apply_coefficients(size_t const order,
  248. Func const& f,
  249. Fvar const& cr,
  250. Fvars&&... fvars) const;
  251. template <typename Func>
  252. fvar apply_coefficients(size_t const order, Func const& f) const;
  253. // Use when function returns derivative(i)/factorial(i) and may have some infinite derivatives.
  254. template <typename Func, typename Fvar, typename... Fvars>
  255. promote<fvar<RealType, Order>, Fvar, Fvars...> apply_coefficients_nonhorner(size_t const order,
  256. Func const& f,
  257. Fvar const& cr,
  258. Fvars&&... fvars) const;
  259. template <typename Func>
  260. fvar apply_coefficients_nonhorner(size_t const order, Func const& f) const;
  261. // Apply derivatives using horner method.
  262. template <typename Func, typename Fvar, typename... Fvars>
  263. promote<fvar<RealType, Order>, Fvar, Fvars...> apply_derivatives(size_t const order,
  264. Func const& f,
  265. Fvar const& cr,
  266. Fvars&&... fvars) const;
  267. template <typename Func>
  268. fvar apply_derivatives(size_t const order, Func const& f) const;
  269. // Use when function returns derivative(i) and may have some infinite derivatives.
  270. template <typename Func, typename Fvar, typename... Fvars>
  271. promote<fvar<RealType, Order>, Fvar, Fvars...> apply_derivatives_nonhorner(size_t const order,
  272. Func const& f,
  273. Fvar const& cr,
  274. Fvars&&... fvars) const;
  275. template <typename Func>
  276. fvar apply_derivatives_nonhorner(size_t const order, Func const& f) const;
  277. private:
  278. RealType epsilon_inner_product(size_t z0,
  279. size_t isum0,
  280. size_t m0,
  281. fvar const& cr,
  282. size_t z1,
  283. size_t isum1,
  284. size_t m1,
  285. size_t j) const;
  286. fvar epsilon_multiply(size_t z0, size_t isum0, fvar const& cr, size_t z1, size_t isum1) const;
  287. fvar epsilon_multiply(size_t z0, size_t isum0, root_type const& ca) const;
  288. fvar inverse_apply() const;
  289. fvar& multiply_assign_by_root_type(bool is_root, root_type const&);
  290. template <typename RealType2, size_t Orders2>
  291. friend class fvar;
  292. template <typename RealType2, size_t Order2>
  293. friend std::ostream& operator<<(std::ostream&, fvar<RealType2, Order2> const&);
  294. // C++11 Compatibility
  295. #ifdef BOOST_NO_CXX17_IF_CONSTEXPR
  296. template <typename RootType>
  297. void fvar_cpp11(std::true_type, RootType const& ca, bool const is_variable);
  298. template <typename RootType>
  299. void fvar_cpp11(std::false_type, RootType const& ca, bool const is_variable);
  300. template <typename... Orders>
  301. get_type_at<RealType, sizeof...(Orders)> at_cpp11(std::true_type, size_t order, Orders... orders) const;
  302. template <typename... Orders>
  303. get_type_at<RealType, sizeof...(Orders)> at_cpp11(std::false_type, size_t order, Orders... orders) const;
  304. template <typename SizeType>
  305. fvar epsilon_multiply_cpp11(std::true_type,
  306. SizeType z0,
  307. size_t isum0,
  308. fvar const& cr,
  309. size_t z1,
  310. size_t isum1) const;
  311. template <typename SizeType>
  312. fvar epsilon_multiply_cpp11(std::false_type,
  313. SizeType z0,
  314. size_t isum0,
  315. fvar const& cr,
  316. size_t z1,
  317. size_t isum1) const;
  318. template <typename SizeType>
  319. fvar epsilon_multiply_cpp11(std::true_type, SizeType z0, size_t isum0, root_type const& ca) const;
  320. template <typename SizeType>
  321. fvar epsilon_multiply_cpp11(std::false_type, SizeType z0, size_t isum0, root_type const& ca) const;
  322. template <typename RootType>
  323. fvar& multiply_assign_by_root_type_cpp11(std::true_type, bool is_root, RootType const& ca);
  324. template <typename RootType>
  325. fvar& multiply_assign_by_root_type_cpp11(std::false_type, bool is_root, RootType const& ca);
  326. template <typename RootType>
  327. fvar& negate_cpp11(std::true_type, RootType const&);
  328. template <typename RootType>
  329. fvar& negate_cpp11(std::false_type, RootType const&);
  330. template <typename RootType>
  331. fvar& set_root_cpp11(std::true_type, RootType const& root);
  332. template <typename RootType>
  333. fvar& set_root_cpp11(std::false_type, RootType const& root);
  334. #endif
  335. };
  336. // Standard Library Support Requirements
  337. // fabs(cr1) | RealType
  338. template <typename RealType, size_t Order>
  339. fvar<RealType, Order> fabs(fvar<RealType, Order> const&);
  340. // abs(cr1) | RealType
  341. template <typename RealType, size_t Order>
  342. fvar<RealType, Order> abs(fvar<RealType, Order> const&);
  343. // ceil(cr1) | RealType
  344. template <typename RealType, size_t Order>
  345. fvar<RealType, Order> ceil(fvar<RealType, Order> const&);
  346. // floor(cr1) | RealType
  347. template <typename RealType, size_t Order>
  348. fvar<RealType, Order> floor(fvar<RealType, Order> const&);
  349. // exp(cr1) | RealType
  350. template <typename RealType, size_t Order>
  351. fvar<RealType, Order> exp(fvar<RealType, Order> const&);
  352. // pow(cr, ca) | RealType
  353. template <typename RealType, size_t Order>
  354. fvar<RealType, Order> pow(fvar<RealType, Order> const&, typename fvar<RealType, Order>::root_type const&);
  355. // pow(ca, cr) | RealType
  356. template <typename RealType, size_t Order>
  357. fvar<RealType, Order> pow(typename fvar<RealType, Order>::root_type const&, fvar<RealType, Order> const&);
  358. // pow(cr1, cr2) | RealType
  359. template <typename RealType1, size_t Order1, typename RealType2, size_t Order2>
  360. promote<fvar<RealType1, Order1>, fvar<RealType2, Order2>> pow(fvar<RealType1, Order1> const&,
  361. fvar<RealType2, Order2> const&);
  362. // sqrt(cr1) | RealType
  363. template <typename RealType, size_t Order>
  364. fvar<RealType, Order> sqrt(fvar<RealType, Order> const&);
  365. // log(cr1) | RealType
  366. template <typename RealType, size_t Order>
  367. fvar<RealType, Order> log(fvar<RealType, Order> const&);
  368. // frexp(cr1, &i) | RealType
  369. template <typename RealType, size_t Order>
  370. fvar<RealType, Order> frexp(fvar<RealType, Order> const&, int*);
  371. // ldexp(cr1, i) | RealType
  372. template <typename RealType, size_t Order>
  373. fvar<RealType, Order> ldexp(fvar<RealType, Order> const&, int);
  374. // cos(cr1) | RealType
  375. template <typename RealType, size_t Order>
  376. fvar<RealType, Order> cos(fvar<RealType, Order> const&);
  377. // sin(cr1) | RealType
  378. template <typename RealType, size_t Order>
  379. fvar<RealType, Order> sin(fvar<RealType, Order> const&);
  380. // asin(cr1) | RealType
  381. template <typename RealType, size_t Order>
  382. fvar<RealType, Order> asin(fvar<RealType, Order> const&);
  383. // tan(cr1) | RealType
  384. template <typename RealType, size_t Order>
  385. fvar<RealType, Order> tan(fvar<RealType, Order> const&);
  386. // atan(cr1) | RealType
  387. template <typename RealType, size_t Order>
  388. fvar<RealType, Order> atan(fvar<RealType, Order> const&);
  389. // atan2(cr, ca) | RealType
  390. template <typename RealType, size_t Order>
  391. fvar<RealType, Order> atan2(fvar<RealType, Order> const&, typename fvar<RealType, Order>::root_type const&);
  392. // atan2(ca, cr) | RealType
  393. template <typename RealType, size_t Order>
  394. fvar<RealType, Order> atan2(typename fvar<RealType, Order>::root_type const&, fvar<RealType, Order> const&);
  395. // atan2(cr1, cr2) | RealType
  396. template <typename RealType1, size_t Order1, typename RealType2, size_t Order2>
  397. promote<fvar<RealType1, Order1>, fvar<RealType2, Order2>> atan2(fvar<RealType1, Order1> const&,
  398. fvar<RealType2, Order2> const&);
  399. // fmod(cr1,cr2) | RealType
  400. template <typename RealType1, size_t Order1, typename RealType2, size_t Order2>
  401. promote<fvar<RealType1, Order1>, fvar<RealType2, Order2>> fmod(fvar<RealType1, Order1> const&,
  402. fvar<RealType2, Order2> const&);
  403. // round(cr1) | RealType
  404. template <typename RealType, size_t Order>
  405. fvar<RealType, Order> round(fvar<RealType, Order> const&);
  406. // iround(cr1) | int
  407. template <typename RealType, size_t Order>
  408. int iround(fvar<RealType, Order> const&);
  409. template <typename RealType, size_t Order>
  410. long lround(fvar<RealType, Order> const&);
  411. template <typename RealType, size_t Order>
  412. long long llround(fvar<RealType, Order> const&);
  413. // trunc(cr1) | RealType
  414. template <typename RealType, size_t Order>
  415. fvar<RealType, Order> trunc(fvar<RealType, Order> const&);
  416. template <typename RealType, size_t Order>
  417. long double truncl(fvar<RealType, Order> const&);
  418. // itrunc(cr1) | int
  419. template <typename RealType, size_t Order>
  420. int itrunc(fvar<RealType, Order> const&);
  421. template <typename RealType, size_t Order>
  422. long long lltrunc(fvar<RealType, Order> const&);
  423. // Additional functions
  424. template <typename RealType, size_t Order>
  425. fvar<RealType, Order> acos(fvar<RealType, Order> const&);
  426. template <typename RealType, size_t Order>
  427. fvar<RealType, Order> acosh(fvar<RealType, Order> const&);
  428. template <typename RealType, size_t Order>
  429. fvar<RealType, Order> asinh(fvar<RealType, Order> const&);
  430. template <typename RealType, size_t Order>
  431. fvar<RealType, Order> atanh(fvar<RealType, Order> const&);
  432. template <typename RealType, size_t Order>
  433. fvar<RealType, Order> cosh(fvar<RealType, Order> const&);
  434. template <typename RealType, size_t Order>
  435. fvar<RealType, Order> digamma(fvar<RealType, Order> const&);
  436. template <typename RealType, size_t Order>
  437. fvar<RealType, Order> erf(fvar<RealType, Order> const&);
  438. template <typename RealType, size_t Order>
  439. fvar<RealType, Order> erfc(fvar<RealType, Order> const&);
  440. template <typename RealType, size_t Order>
  441. fvar<RealType, Order> lambert_w0(fvar<RealType, Order> const&);
  442. template <typename RealType, size_t Order>
  443. fvar<RealType, Order> lgamma(fvar<RealType, Order> const&);
  444. template <typename RealType, size_t Order>
  445. fvar<RealType, Order> sinc(fvar<RealType, Order> const&);
  446. template <typename RealType, size_t Order>
  447. fvar<RealType, Order> sinh(fvar<RealType, Order> const&);
  448. template <typename RealType, size_t Order>
  449. fvar<RealType, Order> tanh(fvar<RealType, Order> const&);
  450. template <typename RealType, size_t Order>
  451. fvar<RealType, Order> tgamma(fvar<RealType, Order> const&);
  452. template <size_t>
  453. struct zero : std::integral_constant<size_t, 0> {};
  454. } // namespace detail
  455. template <typename RealType, size_t Order, size_t... Orders>
  456. using autodiff_fvar = typename detail::nest_fvar<RealType, Order, Orders...>::type;
  457. template <typename RealType, size_t Order, size_t... Orders>
  458. autodiff_fvar<RealType, Order, Orders...> make_fvar(RealType const& ca) {
  459. return autodiff_fvar<RealType, Order, Orders...>(ca, true);
  460. }
  461. #ifndef BOOST_NO_CXX17_IF_CONSTEXPR
  462. namespace detail {
  463. template <typename RealType, size_t Order, size_t... Is>
  464. auto make_fvar_for_tuple(std::index_sequence<Is...>, RealType const& ca) {
  465. return make_fvar<RealType, zero<Is>::value..., Order>(ca);
  466. }
  467. template <typename RealType, size_t... Orders, size_t... Is, typename... RealTypes>
  468. auto make_ftuple_impl(std::index_sequence<Is...>, RealTypes const&... ca) {
  469. return std::make_tuple(make_fvar_for_tuple<RealType, Orders>(std::make_index_sequence<Is>{}, ca)...);
  470. }
  471. } // namespace detail
  472. template <typename RealType, size_t... Orders, typename... RealTypes>
  473. auto make_ftuple(RealTypes const&... ca) {
  474. static_assert(sizeof...(Orders) == sizeof...(RealTypes),
  475. "Number of Orders must match number of function parameters.");
  476. return detail::make_ftuple_impl<RealType, Orders...>(std::index_sequence_for<RealTypes...>{}, ca...);
  477. }
  478. #endif
  479. namespace detail {
  480. #ifndef BOOST_NO_CXX17_IF_CONSTEXPR
  481. template <typename RealType, size_t Order>
  482. fvar<RealType, Order>::fvar(root_type const& ca, bool const is_variable) {
  483. if constexpr (is_fvar<RealType>::value) {
  484. v.front() = RealType(ca, is_variable);
  485. if constexpr (0 < Order)
  486. std::fill(v.begin() + 1, v.end(), static_cast<RealType>(0));
  487. } else {
  488. v.front() = ca;
  489. if constexpr (0 < Order)
  490. v[1] = static_cast<root_type>(static_cast<int>(is_variable));
  491. if constexpr (1 < Order)
  492. std::fill(v.begin() + 2, v.end(), static_cast<RealType>(0));
  493. }
  494. }
  495. #endif
  496. template <typename RealType, size_t Order>
  497. template <typename RealType2, size_t Order2>
  498. fvar<RealType, Order>::fvar(fvar<RealType2, Order2> const& cr) {
  499. for (size_t i = 0; i <= (std::min)(Order, Order2); ++i)
  500. v[i] = static_cast<RealType>(cr.v[i]);
  501. BOOST_IF_CONSTEXPR (Order2 < Order)
  502. std::fill(v.begin() + (Order2 + 1), v.end(), static_cast<RealType>(0));
  503. }
  504. template <typename RealType, size_t Order>
  505. fvar<RealType, Order>::fvar(root_type const& ca) : v{{static_cast<RealType>(ca)}} {}
  506. // Can cause compiler error if RealType2 cannot be cast to root_type.
  507. template <typename RealType, size_t Order>
  508. template <typename RealType2>
  509. fvar<RealType, Order>::fvar(RealType2 const& ca) : v{{static_cast<RealType>(ca)}} {}
  510. /*
  511. template<typename RealType, size_t Order>
  512. fvar<RealType,Order>& fvar<RealType,Order>::operator=(root_type const& ca)
  513. {
  514. v.front() = static_cast<RealType>(ca);
  515. if constexpr (0 < Order)
  516. std::fill(v.begin()+1, v.end(), static_cast<RealType>(0));
  517. return *this;
  518. }
  519. */
  520. template <typename RealType, size_t Order>
  521. template <typename RealType2, size_t Order2>
  522. fvar<RealType, Order>& fvar<RealType, Order>::operator+=(fvar<RealType2, Order2> const& cr) {
  523. for (size_t i = 0; i <= (std::min)(Order, Order2); ++i)
  524. v[i] += cr.v[i];
  525. return *this;
  526. }
  527. template <typename RealType, size_t Order>
  528. fvar<RealType, Order>& fvar<RealType, Order>::operator+=(root_type const& ca) {
  529. v.front() += ca;
  530. return *this;
  531. }
  532. template <typename RealType, size_t Order>
  533. template <typename RealType2, size_t Order2>
  534. fvar<RealType, Order>& fvar<RealType, Order>::operator-=(fvar<RealType2, Order2> const& cr) {
  535. for (size_t i = 0; i <= Order; ++i)
  536. v[i] -= cr.v[i];
  537. return *this;
  538. }
  539. template <typename RealType, size_t Order>
  540. fvar<RealType, Order>& fvar<RealType, Order>::operator-=(root_type const& ca) {
  541. v.front() -= ca;
  542. return *this;
  543. }
  544. template <typename RealType, size_t Order>
  545. template <typename RealType2, size_t Order2>
  546. fvar<RealType, Order>& fvar<RealType, Order>::operator*=(fvar<RealType2, Order2> const& cr) {
  547. using diff_t = typename std::array<RealType, Order + 1>::difference_type;
  548. promote<RealType, RealType2> const zero(0);
  549. BOOST_IF_CONSTEXPR (Order <= Order2)
  550. for (size_t i = 0, j = Order; i <= Order; ++i, --j)
  551. v[j] = std::inner_product(v.cbegin(), v.cend() - diff_t(i), cr.v.crbegin() + diff_t(i), zero);
  552. else {
  553. for (size_t i = 0, j = Order; i <= Order - Order2; ++i, --j)
  554. v[j] = std::inner_product(cr.v.cbegin(), cr.v.cend(), v.crbegin() + diff_t(i), zero);
  555. for (size_t i = Order - Order2 + 1, j = Order2 - 1; i <= Order; ++i, --j)
  556. v[j] = std::inner_product(cr.v.cbegin(), cr.v.cbegin() + diff_t(j + 1), v.crbegin() + diff_t(i), zero);
  557. }
  558. return *this;
  559. }
  560. template <typename RealType, size_t Order>
  561. fvar<RealType, Order>& fvar<RealType, Order>::operator*=(root_type const& ca) {
  562. return multiply_assign_by_root_type(true, ca);
  563. }
  564. template <typename RealType, size_t Order>
  565. template <typename RealType2, size_t Order2>
  566. fvar<RealType, Order>& fvar<RealType, Order>::operator/=(fvar<RealType2, Order2> const& cr) {
  567. using diff_t = typename std::array<RealType, Order + 1>::difference_type;
  568. RealType const zero(0);
  569. v.front() /= cr.v.front();
  570. BOOST_IF_CONSTEXPR (Order < Order2)
  571. for (size_t i = 1, j = Order2 - 1, k = Order; i <= Order; ++i, --j, --k)
  572. (v[i] -= std::inner_product(
  573. cr.v.cbegin() + 1, cr.v.cend() - diff_t(j), v.crbegin() + diff_t(k), zero)) /= cr.v.front();
  574. else BOOST_IF_CONSTEXPR (0 < Order2)
  575. for (size_t i = 1, j = Order2 - 1, k = Order; i <= Order; ++i, j && --j, --k)
  576. (v[i] -= std::inner_product(
  577. cr.v.cbegin() + 1, cr.v.cend() - diff_t(j), v.crbegin() + diff_t(k), zero)) /= cr.v.front();
  578. else
  579. for (size_t i = 1; i <= Order; ++i)
  580. v[i] /= cr.v.front();
  581. return *this;
  582. }
  583. template <typename RealType, size_t Order>
  584. fvar<RealType, Order>& fvar<RealType, Order>::operator/=(root_type const& ca) {
  585. std::for_each(v.begin(), v.end(), [&ca](RealType& x) { x /= ca; });
  586. return *this;
  587. }
  588. template <typename RealType, size_t Order>
  589. fvar<RealType, Order> fvar<RealType, Order>::operator-() const {
  590. fvar<RealType, Order> retval(*this);
  591. retval.negate();
  592. return retval;
  593. }
  594. template <typename RealType, size_t Order>
  595. fvar<RealType, Order> const& fvar<RealType, Order>::operator+() const {
  596. return *this;
  597. }
  598. template <typename RealType, size_t Order>
  599. template <typename RealType2, size_t Order2>
  600. promote<fvar<RealType, Order>, fvar<RealType2, Order2>> fvar<RealType, Order>::operator+(
  601. fvar<RealType2, Order2> const& cr) const {
  602. promote<fvar<RealType, Order>, fvar<RealType2, Order2>> retval;
  603. for (size_t i = 0; i <= (std::min)(Order, Order2); ++i)
  604. retval.v[i] = v[i] + cr.v[i];
  605. BOOST_IF_CONSTEXPR (Order < Order2)
  606. for (size_t i = Order + 1; i <= Order2; ++i)
  607. retval.v[i] = cr.v[i];
  608. else BOOST_IF_CONSTEXPR (Order2 < Order)
  609. for (size_t i = Order2 + 1; i <= Order; ++i)
  610. retval.v[i] = v[i];
  611. return retval;
  612. }
  613. template <typename RealType, size_t Order>
  614. fvar<RealType, Order> fvar<RealType, Order>::operator+(root_type const& ca) const {
  615. fvar<RealType, Order> retval(*this);
  616. retval.v.front() += ca;
  617. return retval;
  618. }
  619. template <typename RealType, size_t Order>
  620. fvar<RealType, Order> operator+(typename fvar<RealType, Order>::root_type const& ca,
  621. fvar<RealType, Order> const& cr) {
  622. return cr + ca;
  623. }
  624. template <typename RealType, size_t Order>
  625. template <typename RealType2, size_t Order2>
  626. promote<fvar<RealType, Order>, fvar<RealType2, Order2>> fvar<RealType, Order>::operator-(
  627. fvar<RealType2, Order2> const& cr) const {
  628. promote<fvar<RealType, Order>, fvar<RealType2, Order2>> retval;
  629. for (size_t i = 0; i <= (std::min)(Order, Order2); ++i)
  630. retval.v[i] = v[i] - cr.v[i];
  631. BOOST_IF_CONSTEXPR (Order < Order2)
  632. for (auto i = Order + 1; i <= Order2; ++i)
  633. retval.v[i] = -cr.v[i];
  634. else BOOST_IF_CONSTEXPR (Order2 < Order)
  635. for (auto i = Order2 + 1; i <= Order; ++i)
  636. retval.v[i] = v[i];
  637. return retval;
  638. }
  639. template <typename RealType, size_t Order>
  640. fvar<RealType, Order> fvar<RealType, Order>::operator-(root_type const& ca) const {
  641. fvar<RealType, Order> retval(*this);
  642. retval.v.front() -= ca;
  643. return retval;
  644. }
  645. template <typename RealType, size_t Order>
  646. fvar<RealType, Order> operator-(typename fvar<RealType, Order>::root_type const& ca,
  647. fvar<RealType, Order> const& cr) {
  648. fvar<RealType, Order> mcr = -cr; // Has same address as retval in operator-() due to NRVO.
  649. mcr += ca;
  650. return mcr; // <-- This allows for NRVO. The following does not. --> return mcr += ca;
  651. }
  652. template <typename RealType, size_t Order>
  653. template <typename RealType2, size_t Order2>
  654. promote<fvar<RealType, Order>, fvar<RealType2, Order2>> fvar<RealType, Order>::operator*(
  655. fvar<RealType2, Order2> const& cr) const {
  656. using diff_t = typename std::array<RealType, Order + 1>::difference_type;
  657. promote<RealType, RealType2> const zero(0);
  658. promote<fvar<RealType, Order>, fvar<RealType2, Order2>> retval;
  659. BOOST_IF_CONSTEXPR (Order < Order2)
  660. for (size_t i = 0, j = Order, k = Order2; i <= Order2; ++i, j && --j, --k)
  661. retval.v[i] = std::inner_product(v.cbegin(), v.cend() - diff_t(j), cr.v.crbegin() + diff_t(k), zero);
  662. else
  663. for (size_t i = 0, j = Order2, k = Order; i <= Order; ++i, j && --j, --k)
  664. retval.v[i] = std::inner_product(cr.v.cbegin(), cr.v.cend() - diff_t(j), v.crbegin() + diff_t(k), zero);
  665. return retval;
  666. }
  667. template <typename RealType, size_t Order>
  668. fvar<RealType, Order> fvar<RealType, Order>::operator*(root_type const& ca) const {
  669. fvar<RealType, Order> retval(*this);
  670. retval *= ca;
  671. return retval;
  672. }
  673. template <typename RealType, size_t Order>
  674. fvar<RealType, Order> operator*(typename fvar<RealType, Order>::root_type const& ca,
  675. fvar<RealType, Order> const& cr) {
  676. return cr * ca;
  677. }
  678. template <typename RealType, size_t Order>
  679. template <typename RealType2, size_t Order2>
  680. promote<fvar<RealType, Order>, fvar<RealType2, Order2>> fvar<RealType, Order>::operator/(
  681. fvar<RealType2, Order2> const& cr) const {
  682. using diff_t = typename std::array<RealType, Order + 1>::difference_type;
  683. promote<RealType, RealType2> const zero(0);
  684. promote<fvar<RealType, Order>, fvar<RealType2, Order2>> retval;
  685. retval.v.front() = v.front() / cr.v.front();
  686. BOOST_IF_CONSTEXPR (Order < Order2) {
  687. for (size_t i = 1, j = Order2 - 1; i <= Order; ++i, --j)
  688. retval.v[i] =
  689. (v[i] - std::inner_product(
  690. cr.v.cbegin() + 1, cr.v.cend() - diff_t(j), retval.v.crbegin() + diff_t(j + 1), zero)) /
  691. cr.v.front();
  692. for (size_t i = Order + 1, j = Order2 - Order - 1; i <= Order2; ++i, --j)
  693. retval.v[i] =
  694. -std::inner_product(
  695. cr.v.cbegin() + 1, cr.v.cend() - diff_t(j), retval.v.crbegin() + diff_t(j + 1), zero) /
  696. cr.v.front();
  697. } else BOOST_IF_CONSTEXPR (0 < Order2)
  698. for (size_t i = 1, j = Order2 - 1, k = Order; i <= Order; ++i, j && --j, --k)
  699. retval.v[i] =
  700. (v[i] - std::inner_product(
  701. cr.v.cbegin() + 1, cr.v.cend() - diff_t(j), retval.v.crbegin() + diff_t(k), zero)) /
  702. cr.v.front();
  703. else
  704. for (size_t i = 1; i <= Order; ++i)
  705. retval.v[i] = v[i] / cr.v.front();
  706. return retval;
  707. }
  708. template <typename RealType, size_t Order>
  709. fvar<RealType, Order> fvar<RealType, Order>::operator/(root_type const& ca) const {
  710. fvar<RealType, Order> retval(*this);
  711. retval /= ca;
  712. return retval;
  713. }
  714. template <typename RealType, size_t Order>
  715. fvar<RealType, Order> operator/(typename fvar<RealType, Order>::root_type const& ca,
  716. fvar<RealType, Order> const& cr) {
  717. using diff_t = typename std::array<RealType, Order + 1>::difference_type;
  718. fvar<RealType, Order> retval;
  719. retval.v.front() = ca / cr.v.front();
  720. BOOST_IF_CONSTEXPR (0 < Order) {
  721. RealType const zero(0);
  722. for (size_t i = 1, j = Order - 1; i <= Order; ++i, --j)
  723. retval.v[i] =
  724. -std::inner_product(
  725. cr.v.cbegin() + 1, cr.v.cend() - diff_t(j), retval.v.crbegin() + diff_t(j + 1), zero) /
  726. cr.v.front();
  727. }
  728. return retval;
  729. }
  730. template <typename RealType, size_t Order>
  731. template <typename RealType2, size_t Order2>
  732. bool fvar<RealType, Order>::operator==(fvar<RealType2, Order2> const& cr) const {
  733. return v.front() == cr.v.front();
  734. }
  735. template <typename RealType, size_t Order>
  736. bool fvar<RealType, Order>::operator==(root_type const& ca) const {
  737. return v.front() == ca;
  738. }
  739. template <typename RealType, size_t Order>
  740. bool operator==(typename fvar<RealType, Order>::root_type const& ca, fvar<RealType, Order> const& cr) {
  741. return ca == cr.v.front();
  742. }
  743. template <typename RealType, size_t Order>
  744. template <typename RealType2, size_t Order2>
  745. bool fvar<RealType, Order>::operator!=(fvar<RealType2, Order2> const& cr) const {
  746. return v.front() != cr.v.front();
  747. }
  748. template <typename RealType, size_t Order>
  749. bool fvar<RealType, Order>::operator!=(root_type const& ca) const {
  750. return v.front() != ca;
  751. }
  752. template <typename RealType, size_t Order>
  753. bool operator!=(typename fvar<RealType, Order>::root_type const& ca, fvar<RealType, Order> const& cr) {
  754. return ca != cr.v.front();
  755. }
  756. template <typename RealType, size_t Order>
  757. template <typename RealType2, size_t Order2>
  758. bool fvar<RealType, Order>::operator<=(fvar<RealType2, Order2> const& cr) const {
  759. return v.front() <= cr.v.front();
  760. }
  761. template <typename RealType, size_t Order>
  762. bool fvar<RealType, Order>::operator<=(root_type const& ca) const {
  763. return v.front() <= ca;
  764. }
  765. template <typename RealType, size_t Order>
  766. bool operator<=(typename fvar<RealType, Order>::root_type const& ca, fvar<RealType, Order> const& cr) {
  767. return ca <= cr.v.front();
  768. }
  769. template <typename RealType, size_t Order>
  770. template <typename RealType2, size_t Order2>
  771. bool fvar<RealType, Order>::operator>=(fvar<RealType2, Order2> const& cr) const {
  772. return v.front() >= cr.v.front();
  773. }
  774. template <typename RealType, size_t Order>
  775. bool fvar<RealType, Order>::operator>=(root_type const& ca) const {
  776. return v.front() >= ca;
  777. }
  778. template <typename RealType, size_t Order>
  779. bool operator>=(typename fvar<RealType, Order>::root_type const& ca, fvar<RealType, Order> const& cr) {
  780. return ca >= cr.v.front();
  781. }
  782. template <typename RealType, size_t Order>
  783. template <typename RealType2, size_t Order2>
  784. bool fvar<RealType, Order>::operator<(fvar<RealType2, Order2> const& cr) const {
  785. return v.front() < cr.v.front();
  786. }
  787. template <typename RealType, size_t Order>
  788. bool fvar<RealType, Order>::operator<(root_type const& ca) const {
  789. return v.front() < ca;
  790. }
  791. template <typename RealType, size_t Order>
  792. bool operator<(typename fvar<RealType, Order>::root_type const& ca, fvar<RealType, Order> const& cr) {
  793. return ca < cr.v.front();
  794. }
  795. template <typename RealType, size_t Order>
  796. template <typename RealType2, size_t Order2>
  797. bool fvar<RealType, Order>::operator>(fvar<RealType2, Order2> const& cr) const {
  798. return v.front() > cr.v.front();
  799. }
  800. template <typename RealType, size_t Order>
  801. bool fvar<RealType, Order>::operator>(root_type const& ca) const {
  802. return v.front() > ca;
  803. }
  804. template <typename RealType, size_t Order>
  805. bool operator>(typename fvar<RealType, Order>::root_type const& ca, fvar<RealType, Order> const& cr) {
  806. return ca > cr.v.front();
  807. }
  808. /*** Other methods and functions ***/
  809. #ifndef BOOST_NO_CXX17_IF_CONSTEXPR
  810. // f : order -> derivative(order)/factorial(order)
  811. // Use this when you have the polynomial coefficients, rather than just the derivatives. E.g. See atan2().
  812. template <typename RealType, size_t Order>
  813. template <typename Func, typename Fvar, typename... Fvars>
  814. promote<fvar<RealType, Order>, Fvar, Fvars...> fvar<RealType, Order>::apply_coefficients(
  815. size_t const order,
  816. Func const& f,
  817. Fvar const& cr,
  818. Fvars&&... fvars) const {
  819. fvar<RealType, Order> const epsilon = fvar<RealType, Order>(*this).set_root(0);
  820. size_t i = (std::min)(order, order_sum);
  821. promote<fvar<RealType, Order>, Fvar, Fvars...> accumulator = cr.apply_coefficients(
  822. order - i, [&f, i](auto... indices) { return f(i, indices...); }, std::forward<Fvars>(fvars)...);
  823. while (i--)
  824. (accumulator *= epsilon) += cr.apply_coefficients(
  825. order - i, [&f, i](auto... indices) { return f(i, indices...); }, std::forward<Fvars>(fvars)...);
  826. return accumulator;
  827. }
  828. #endif
  829. // f : order -> derivative(order)/factorial(order)
  830. // Use this when you have the polynomial coefficients, rather than just the derivatives. E.g. See atan().
  831. template <typename RealType, size_t Order>
  832. template <typename Func>
  833. fvar<RealType, Order> fvar<RealType, Order>::apply_coefficients(size_t const order, Func const& f) const {
  834. fvar<RealType, Order> const epsilon = fvar<RealType, Order>(*this).set_root(0);
  835. #ifndef BOOST_NO_CXX17_IF_CONSTEXPR
  836. size_t i = (std::min)(order, order_sum);
  837. #else // ODR-use of static constexpr
  838. size_t i = order < order_sum ? order : order_sum;
  839. #endif
  840. fvar<RealType, Order> accumulator = f(i);
  841. while (i--)
  842. (accumulator *= epsilon) += f(i);
  843. return accumulator;
  844. }
  845. #ifndef BOOST_NO_CXX17_IF_CONSTEXPR
  846. // f : order -> derivative(order)
  847. template <typename RealType, size_t Order>
  848. template <typename Func, typename Fvar, typename... Fvars>
  849. promote<fvar<RealType, Order>, Fvar, Fvars...> fvar<RealType, Order>::apply_coefficients_nonhorner(
  850. size_t const order,
  851. Func const& f,
  852. Fvar const& cr,
  853. Fvars&&... fvars) const {
  854. fvar<RealType, Order> const epsilon = fvar<RealType, Order>(*this).set_root(0);
  855. fvar<RealType, Order> epsilon_i = fvar<RealType, Order>(1); // epsilon to the power of i
  856. promote<fvar<RealType, Order>, Fvar, Fvars...> accumulator = cr.apply_coefficients_nonhorner(
  857. order,
  858. [&f](auto... indices) { return f(0, static_cast<std::size_t>(indices)...); },
  859. std::forward<Fvars>(fvars)...);
  860. size_t const i_max = (std::min)(order, order_sum);
  861. for (size_t i = 1; i <= i_max; ++i) {
  862. epsilon_i = epsilon_i.epsilon_multiply(i - 1, 0, epsilon, 1, 0);
  863. accumulator += epsilon_i.epsilon_multiply(
  864. i,
  865. 0,
  866. cr.apply_coefficients_nonhorner(
  867. order - i,
  868. [&f, i](auto... indices) { return f(i, static_cast<std::size_t>(indices)...); },
  869. std::forward<Fvars>(fvars)...),
  870. 0,
  871. 0);
  872. }
  873. return accumulator;
  874. }
  875. #endif
  876. // f : order -> coefficient(order)
  877. template <typename RealType, size_t Order>
  878. template <typename Func>
  879. fvar<RealType, Order> fvar<RealType, Order>::apply_coefficients_nonhorner(size_t const order,
  880. Func const& f) const {
  881. fvar<RealType, Order> const epsilon = fvar<RealType, Order>(*this).set_root(0);
  882. fvar<RealType, Order> epsilon_i = fvar<RealType, Order>(1); // epsilon to the power of i
  883. fvar<RealType, Order> accumulator = fvar<RealType, Order>(f(0u));
  884. #ifndef BOOST_NO_CXX17_IF_CONSTEXPR
  885. size_t const i_max = (std::min)(order, order_sum);
  886. #else // ODR-use of static constexpr
  887. size_t const i_max = order < order_sum ? order : order_sum;
  888. #endif
  889. for (size_t i = 1; i <= i_max; ++i) {
  890. epsilon_i = epsilon_i.epsilon_multiply(i - 1, 0, epsilon, 1, 0);
  891. accumulator += epsilon_i.epsilon_multiply(i, 0, f(i));
  892. }
  893. return accumulator;
  894. }
  895. #ifndef BOOST_NO_CXX17_IF_CONSTEXPR
  896. // f : order -> derivative(order)
  897. template <typename RealType, size_t Order>
  898. template <typename Func, typename Fvar, typename... Fvars>
  899. promote<fvar<RealType, Order>, Fvar, Fvars...> fvar<RealType, Order>::apply_derivatives(
  900. size_t const order,
  901. Func const& f,
  902. Fvar const& cr,
  903. Fvars&&... fvars) const {
  904. fvar<RealType, Order> const epsilon = fvar<RealType, Order>(*this).set_root(0);
  905. size_t i = (std::min)(order, order_sum);
  906. promote<fvar<RealType, Order>, Fvar, Fvars...> accumulator =
  907. cr.apply_derivatives(
  908. order - i, [&f, i](auto... indices) { return f(i, indices...); }, std::forward<Fvars>(fvars)...) /
  909. factorial<root_type>(static_cast<unsigned>(i));
  910. while (i--)
  911. (accumulator *= epsilon) +=
  912. cr.apply_derivatives(
  913. order - i, [&f, i](auto... indices) { return f(i, indices...); }, std::forward<Fvars>(fvars)...) /
  914. factorial<root_type>(static_cast<unsigned>(i));
  915. return accumulator;
  916. }
  917. #endif
  918. // f : order -> derivative(order)
  919. template <typename RealType, size_t Order>
  920. template <typename Func>
  921. fvar<RealType, Order> fvar<RealType, Order>::apply_derivatives(size_t const order, Func const& f) const {
  922. fvar<RealType, Order> const epsilon = fvar<RealType, Order>(*this).set_root(0);
  923. #ifndef BOOST_NO_CXX17_IF_CONSTEXPR
  924. size_t i = (std::min)(order, order_sum);
  925. #else // ODR-use of static constexpr
  926. size_t i = order < order_sum ? order : order_sum;
  927. #endif
  928. fvar<RealType, Order> accumulator = f(i) / factorial<root_type>(static_cast<unsigned>(i));
  929. while (i--)
  930. (accumulator *= epsilon) += f(i) / factorial<root_type>(static_cast<unsigned>(i));
  931. return accumulator;
  932. }
  933. #ifndef BOOST_NO_CXX17_IF_CONSTEXPR
  934. // f : order -> derivative(order)
  935. template <typename RealType, size_t Order>
  936. template <typename Func, typename Fvar, typename... Fvars>
  937. promote<fvar<RealType, Order>, Fvar, Fvars...> fvar<RealType, Order>::apply_derivatives_nonhorner(
  938. size_t const order,
  939. Func const& f,
  940. Fvar const& cr,
  941. Fvars&&... fvars) const {
  942. fvar<RealType, Order> const epsilon = fvar<RealType, Order>(*this).set_root(0);
  943. fvar<RealType, Order> epsilon_i = fvar<RealType, Order>(1); // epsilon to the power of i
  944. promote<fvar<RealType, Order>, Fvar, Fvars...> accumulator = cr.apply_derivatives_nonhorner(
  945. order,
  946. [&f](auto... indices) { return f(0, static_cast<std::size_t>(indices)...); },
  947. std::forward<Fvars>(fvars)...);
  948. size_t const i_max = (std::min)(order, order_sum);
  949. for (size_t i = 1; i <= i_max; ++i) {
  950. epsilon_i = epsilon_i.epsilon_multiply(i - 1, 0, epsilon, 1, 0);
  951. accumulator += epsilon_i.epsilon_multiply(
  952. i,
  953. 0,
  954. cr.apply_derivatives_nonhorner(
  955. order - i,
  956. [&f, i](auto... indices) { return f(i, static_cast<std::size_t>(indices)...); },
  957. std::forward<Fvars>(fvars)...) /
  958. factorial<root_type>(static_cast<unsigned>(i)),
  959. 0,
  960. 0);
  961. }
  962. return accumulator;
  963. }
  964. #endif
  965. // f : order -> derivative(order)
  966. template <typename RealType, size_t Order>
  967. template <typename Func>
  968. fvar<RealType, Order> fvar<RealType, Order>::apply_derivatives_nonhorner(size_t const order,
  969. Func const& f) const {
  970. fvar<RealType, Order> const epsilon = fvar<RealType, Order>(*this).set_root(0);
  971. fvar<RealType, Order> epsilon_i = fvar<RealType, Order>(1); // epsilon to the power of i
  972. fvar<RealType, Order> accumulator = fvar<RealType, Order>(f(0u));
  973. #ifndef BOOST_NO_CXX17_IF_CONSTEXPR
  974. size_t const i_max = (std::min)(order, order_sum);
  975. #else // ODR-use of static constexpr
  976. size_t const i_max = order < order_sum ? order : order_sum;
  977. #endif
  978. for (size_t i = 1; i <= i_max; ++i) {
  979. epsilon_i = epsilon_i.epsilon_multiply(i - 1, 0, epsilon, 1, 0);
  980. accumulator += epsilon_i.epsilon_multiply(i, 0, f(i) / factorial<root_type>(static_cast<unsigned>(i)));
  981. }
  982. return accumulator;
  983. }
  984. #ifndef BOOST_NO_CXX17_IF_CONSTEXPR
  985. // Can throw "std::out_of_range: array::at: __n (which is 7) >= _Nm (which is 7)"
  986. template <typename RealType, size_t Order>
  987. template <typename... Orders>
  988. get_type_at<RealType, sizeof...(Orders)> fvar<RealType, Order>::at(size_t order, Orders... orders) const {
  989. if constexpr (0 < sizeof...(Orders))
  990. return v.at(order).at(static_cast<std::size_t>(orders)...);
  991. else
  992. return v.at(order);
  993. }
  994. #endif
  995. #ifndef BOOST_NO_CXX17_IF_CONSTEXPR
  996. // Can throw "std::out_of_range: array::at: __n (which is 7) >= _Nm (which is 7)"
  997. template <typename RealType, size_t Order>
  998. template <typename... Orders>
  999. get_type_at<fvar<RealType, Order>, sizeof...(Orders)> fvar<RealType, Order>::derivative(
  1000. Orders... orders) const {
  1001. static_assert(sizeof...(Orders) <= depth,
  1002. "Number of parameters to derivative(...) cannot exceed fvar::depth.");
  1003. return at(static_cast<std::size_t>(orders)...) *
  1004. (... * factorial<root_type>(static_cast<unsigned>(orders)));
  1005. }
  1006. #endif
  1007. template <typename RealType, size_t Order>
  1008. const RealType& fvar<RealType, Order>::operator[](size_t i) const {
  1009. return v[i];
  1010. }
  1011. template <typename RealType, size_t Order>
  1012. RealType fvar<RealType, Order>::epsilon_inner_product(size_t z0,
  1013. size_t const isum0,
  1014. size_t const m0,
  1015. fvar<RealType, Order> const& cr,
  1016. size_t z1,
  1017. size_t const isum1,
  1018. size_t const m1,
  1019. size_t const j) const {
  1020. static_assert(is_fvar<RealType>::value, "epsilon_inner_product() must have 1 < depth.");
  1021. RealType accumulator = RealType();
  1022. auto const i0_max = m1 < j ? j - m1 : 0;
  1023. for (auto i0 = m0, i1 = j - m0; i0 <= i0_max; ++i0, --i1)
  1024. accumulator += v[i0].epsilon_multiply(z0, isum0 + i0, cr.v[i1], z1, isum1 + i1);
  1025. return accumulator;
  1026. }
  1027. #ifndef BOOST_NO_CXX17_IF_CONSTEXPR
  1028. template <typename RealType, size_t Order>
  1029. fvar<RealType, Order> fvar<RealType, Order>::epsilon_multiply(size_t z0,
  1030. size_t isum0,
  1031. fvar<RealType, Order> const& cr,
  1032. size_t z1,
  1033. size_t isum1) const {
  1034. using diff_t = typename std::array<RealType, Order + 1>::difference_type;
  1035. RealType const zero(0);
  1036. size_t const m0 = order_sum + isum0 < Order + z0 ? Order + z0 - (order_sum + isum0) : 0;
  1037. size_t const m1 = order_sum + isum1 < Order + z1 ? Order + z1 - (order_sum + isum1) : 0;
  1038. size_t const i_max = m0 + m1 < Order ? Order - (m0 + m1) : 0;
  1039. fvar<RealType, Order> retval = fvar<RealType, Order>();
  1040. if constexpr (is_fvar<RealType>::value)
  1041. for (size_t i = 0, j = Order; i <= i_max; ++i, --j)
  1042. retval.v[j] = epsilon_inner_product(z0, isum0, m0, cr, z1, isum1, m1, j);
  1043. else
  1044. for (size_t i = 0, j = Order; i <= i_max; ++i, --j)
  1045. retval.v[j] = std::inner_product(
  1046. v.cbegin() + diff_t(m0), v.cend() - diff_t(i + m1), cr.v.crbegin() + diff_t(i + m0), zero);
  1047. return retval;
  1048. }
  1049. #endif
  1050. #ifndef BOOST_NO_CXX17_IF_CONSTEXPR
  1051. // When called from outside this method, z0 should be non-zero. Otherwise if z0=0 then it will give an
  1052. // incorrect result of 0 when the root value is 0 and ca=inf, when instead the correct product is nan.
  1053. // If z0=0 then use the regular multiply operator*() instead.
  1054. template <typename RealType, size_t Order>
  1055. fvar<RealType, Order> fvar<RealType, Order>::epsilon_multiply(size_t z0,
  1056. size_t isum0,
  1057. root_type const& ca) const {
  1058. fvar<RealType, Order> retval(*this);
  1059. size_t const m0 = order_sum + isum0 < Order + z0 ? Order + z0 - (order_sum + isum0) : 0;
  1060. if constexpr (is_fvar<RealType>::value)
  1061. for (size_t i = m0; i <= Order; ++i)
  1062. retval.v[i] = retval.v[i].epsilon_multiply(z0, isum0 + i, ca);
  1063. else
  1064. for (size_t i = m0; i <= Order; ++i)
  1065. if (retval.v[i] != static_cast<RealType>(0))
  1066. retval.v[i] *= ca;
  1067. return retval;
  1068. }
  1069. #endif
  1070. template <typename RealType, size_t Order>
  1071. fvar<RealType, Order> fvar<RealType, Order>::inverse() const {
  1072. return static_cast<root_type>(*this) == 0 ? inverse_apply() : 1 / *this;
  1073. }
  1074. #ifndef BOOST_NO_CXX17_IF_CONSTEXPR
  1075. template <typename RealType, size_t Order>
  1076. fvar<RealType, Order>& fvar<RealType, Order>::negate() {
  1077. if constexpr (is_fvar<RealType>::value)
  1078. std::for_each(v.begin(), v.end(), [](RealType& r) { r.negate(); });
  1079. else
  1080. std::for_each(v.begin(), v.end(), [](RealType& a) { a = -a; });
  1081. return *this;
  1082. }
  1083. #endif
  1084. // This gives log(0.0) = depth(1)(-inf,inf,-inf,inf,-inf,inf)
  1085. // 1 / *this: log(0.0) = depth(1)(-inf,inf,-inf,-nan,-nan,-nan)
  1086. template <typename RealType, size_t Order>
  1087. fvar<RealType, Order> fvar<RealType, Order>::inverse_apply() const {
  1088. root_type derivatives[order_sum + 1]; // LCOV_EXCL_LINE This causes a false negative on lcov coverage test.
  1089. root_type const x0 = static_cast<root_type>(*this);
  1090. *derivatives = 1 / x0;
  1091. for (size_t i = 1; i <= order_sum; ++i)
  1092. derivatives[i] = -derivatives[i - 1] * i / x0;
  1093. return apply_derivatives_nonhorner(order_sum, [&derivatives](size_t j) { return derivatives[j]; });
  1094. }
  1095. #ifndef BOOST_NO_CXX17_IF_CONSTEXPR
  1096. template <typename RealType, size_t Order>
  1097. fvar<RealType, Order>& fvar<RealType, Order>::multiply_assign_by_root_type(bool is_root,
  1098. root_type const& ca) {
  1099. auto itr = v.begin();
  1100. if constexpr (is_fvar<RealType>::value) {
  1101. itr->multiply_assign_by_root_type(is_root, ca);
  1102. for (++itr; itr != v.end(); ++itr)
  1103. itr->multiply_assign_by_root_type(false, ca);
  1104. } else {
  1105. if (is_root || *itr != 0)
  1106. *itr *= ca; // Skip multiplication of 0 by ca=inf to avoid nan, except when is_root.
  1107. for (++itr; itr != v.end(); ++itr)
  1108. if (*itr != 0)
  1109. *itr *= ca;
  1110. }
  1111. return *this;
  1112. }
  1113. #endif
  1114. template <typename RealType, size_t Order>
  1115. fvar<RealType, Order>::operator root_type() const {
  1116. return static_cast<root_type>(v.front());
  1117. }
  1118. template <typename RealType, size_t Order>
  1119. template <typename T, typename>
  1120. fvar<RealType, Order>::operator T() const {
  1121. return static_cast<T>(static_cast<root_type>(v.front()));
  1122. }
  1123. #ifndef BOOST_NO_CXX17_IF_CONSTEXPR
  1124. template <typename RealType, size_t Order>
  1125. fvar<RealType, Order>& fvar<RealType, Order>::set_root(root_type const& root) {
  1126. if constexpr (is_fvar<RealType>::value)
  1127. v.front().set_root(root);
  1128. else
  1129. v.front() = root;
  1130. return *this;
  1131. }
  1132. #endif
  1133. // Standard Library Support Requirements
  1134. template <typename RealType, size_t Order>
  1135. fvar<RealType, Order> fabs(fvar<RealType, Order> const& cr) {
  1136. typename fvar<RealType, Order>::root_type const zero(0);
  1137. return cr < zero ? -cr
  1138. : cr == zero ? fvar<RealType, Order>() // Canonical fabs'(0) = 0.
  1139. : cr; // Propagate NaN.
  1140. }
  1141. template <typename RealType, size_t Order>
  1142. fvar<RealType, Order> abs(fvar<RealType, Order> const& cr) {
  1143. return fabs(cr);
  1144. }
  1145. template <typename RealType, size_t Order>
  1146. fvar<RealType, Order> ceil(fvar<RealType, Order> const& cr) {
  1147. using std::ceil;
  1148. return fvar<RealType, Order>(ceil(static_cast<typename fvar<RealType, Order>::root_type>(cr)));
  1149. }
  1150. template <typename RealType, size_t Order>
  1151. fvar<RealType, Order> floor(fvar<RealType, Order> const& cr) {
  1152. using std::floor;
  1153. return fvar<RealType, Order>(floor(static_cast<typename fvar<RealType, Order>::root_type>(cr)));
  1154. }
  1155. template <typename RealType, size_t Order>
  1156. fvar<RealType, Order> exp(fvar<RealType, Order> const& cr) {
  1157. using std::exp;
  1158. constexpr size_t order = fvar<RealType, Order>::order_sum;
  1159. using root_type = typename fvar<RealType, Order>::root_type;
  1160. root_type const d0 = exp(static_cast<root_type>(cr));
  1161. return cr.apply_derivatives(order, [&d0](size_t) { return d0; });
  1162. }
  1163. template <typename RealType, size_t Order>
  1164. fvar<RealType, Order> pow(fvar<RealType, Order> const& x,
  1165. typename fvar<RealType, Order>::root_type const& y) {
  1166. BOOST_MATH_STD_USING
  1167. using root_type = typename fvar<RealType, Order>::root_type;
  1168. constexpr size_t order = fvar<RealType, Order>::order_sum;
  1169. root_type const x0 = static_cast<root_type>(x);
  1170. root_type derivatives[order + 1]{pow(x0, y)};
  1171. if (fabs(x0) < std::numeric_limits<root_type>::epsilon()) {
  1172. root_type coef = 1;
  1173. for (size_t i = 0; i < order && y - i != 0; ++i) {
  1174. coef *= y - i;
  1175. derivatives[i + 1] = coef * pow(x0, y - (i + 1));
  1176. }
  1177. return x.apply_derivatives_nonhorner(order, [&derivatives](size_t i) { return derivatives[i]; });
  1178. } else {
  1179. for (size_t i = 0; i < order && y - i != 0; ++i)
  1180. derivatives[i + 1] = (y - i) * derivatives[i] / x0;
  1181. return x.apply_derivatives(order, [&derivatives](size_t i) { return derivatives[i]; });
  1182. }
  1183. }
  1184. template <typename RealType, size_t Order>
  1185. fvar<RealType, Order> pow(typename fvar<RealType, Order>::root_type const& x,
  1186. fvar<RealType, Order> const& y) {
  1187. BOOST_MATH_STD_USING
  1188. using root_type = typename fvar<RealType, Order>::root_type;
  1189. constexpr size_t order = fvar<RealType, Order>::order_sum;
  1190. root_type const y0 = static_cast<root_type>(y);
  1191. root_type derivatives[order + 1];
  1192. *derivatives = pow(x, y0);
  1193. root_type const logx = log(x);
  1194. for (size_t i = 0; i < order; ++i)
  1195. derivatives[i + 1] = derivatives[i] * logx;
  1196. return y.apply_derivatives(order, [&derivatives](size_t i) { return derivatives[i]; });
  1197. }
  1198. template <typename RealType1, size_t Order1, typename RealType2, size_t Order2>
  1199. promote<fvar<RealType1, Order1>, fvar<RealType2, Order2>> pow(fvar<RealType1, Order1> const& x,
  1200. fvar<RealType2, Order2> const& y) {
  1201. BOOST_MATH_STD_USING
  1202. using return_type = promote<fvar<RealType1, Order1>, fvar<RealType2, Order2>>;
  1203. using root_type = typename return_type::root_type;
  1204. constexpr size_t order = return_type::order_sum;
  1205. root_type const x0 = static_cast<root_type>(x);
  1206. root_type const y0 = static_cast<root_type>(y);
  1207. root_type dxydx[order + 1]{pow(x0, y0)};
  1208. BOOST_IF_CONSTEXPR (order == 0)
  1209. return return_type(*dxydx);
  1210. else {
  1211. for (size_t i = 0; i < order && y0 - i != 0; ++i)
  1212. dxydx[i + 1] = (y0 - i) * dxydx[i] / x0;
  1213. std::array<fvar<root_type, order>, order + 1> lognx;
  1214. lognx.front() = fvar<root_type, order>(1);
  1215. #ifndef BOOST_NO_CXX17_IF_CONSTEXPR
  1216. lognx[1] = log(make_fvar<root_type, order>(x0));
  1217. #else // for compilers that compile this branch when order == 0.
  1218. lognx[(std::min)(size_t(1), order)] = log(make_fvar<root_type, order>(x0));
  1219. #endif
  1220. for (size_t i = 1; i < order; ++i)
  1221. lognx[i + 1] = lognx[i] * lognx[1];
  1222. auto const f = [&dxydx, &lognx](size_t i, size_t j) {
  1223. size_t binomial = 1;
  1224. root_type sum = dxydx[i] * static_cast<root_type>(lognx[j]);
  1225. for (size_t k = 1; k <= i; ++k) {
  1226. (binomial *= (i - k + 1)) /= k; // binomial_coefficient(i,k)
  1227. sum += binomial * dxydx[i - k] * lognx[j].derivative(k);
  1228. }
  1229. return sum;
  1230. };
  1231. if (fabs(x0) < std::numeric_limits<root_type>::epsilon())
  1232. return x.apply_derivatives_nonhorner(order, f, y);
  1233. return x.apply_derivatives(order, f, y);
  1234. }
  1235. }
  1236. template <typename RealType, size_t Order>
  1237. fvar<RealType, Order> sqrt(fvar<RealType, Order> const& cr) {
  1238. using std::sqrt;
  1239. using root_type = typename fvar<RealType, Order>::root_type;
  1240. constexpr size_t order = fvar<RealType, Order>::order_sum;
  1241. root_type derivatives[order + 1];
  1242. root_type const x = static_cast<root_type>(cr);
  1243. *derivatives = sqrt(x);
  1244. BOOST_IF_CONSTEXPR (order == 0)
  1245. return fvar<RealType, Order>(*derivatives);
  1246. else {
  1247. root_type numerator = 0.5;
  1248. root_type powers = 1;
  1249. #ifndef BOOST_NO_CXX17_IF_CONSTEXPR
  1250. derivatives[1] = numerator / *derivatives;
  1251. #else // for compilers that compile this branch when order == 0.
  1252. derivatives[(std::min)(size_t(1), order)] = numerator / *derivatives;
  1253. #endif
  1254. using diff_t = typename std::array<RealType, Order + 1>::difference_type;
  1255. for (size_t i = 2; i <= order; ++i) {
  1256. numerator *= static_cast<root_type>(-0.5) * ((static_cast<diff_t>(i) << 1) - 3);
  1257. powers *= x;
  1258. derivatives[i] = numerator / (powers * *derivatives);
  1259. }
  1260. auto const f = [&derivatives](size_t i) { return derivatives[i]; };
  1261. if (cr < std::numeric_limits<root_type>::epsilon())
  1262. return cr.apply_derivatives_nonhorner(order, f);
  1263. return cr.apply_derivatives(order, f);
  1264. }
  1265. }
  1266. // Natural logarithm. If cr==0 then derivative(i) may have nans due to nans from inverse().
  1267. template <typename RealType, size_t Order>
  1268. fvar<RealType, Order> log(fvar<RealType, Order> const& cr) {
  1269. using std::log;
  1270. using root_type = typename fvar<RealType, Order>::root_type;
  1271. constexpr size_t order = fvar<RealType, Order>::order_sum;
  1272. root_type const d0 = log(static_cast<root_type>(cr));
  1273. BOOST_IF_CONSTEXPR (order == 0)
  1274. return fvar<RealType, Order>(d0);
  1275. else {
  1276. auto const d1 = make_fvar<root_type, bool(order) ? order - 1 : 0>(static_cast<root_type>(cr)).inverse(); // log'(x) = 1 / x
  1277. return cr.apply_coefficients_nonhorner(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; });
  1278. }
  1279. }
  1280. template <typename RealType, size_t Order>
  1281. fvar<RealType, Order> frexp(fvar<RealType, Order> const& cr, int* exp) {
  1282. using std::exp2;
  1283. using std::frexp;
  1284. using root_type = typename fvar<RealType, Order>::root_type;
  1285. frexp(static_cast<root_type>(cr), exp);
  1286. return cr * static_cast<root_type>(exp2(-*exp));
  1287. }
  1288. template <typename RealType, size_t Order>
  1289. fvar<RealType, Order> ldexp(fvar<RealType, Order> const& cr, int exp) {
  1290. // argument to std::exp2 must be casted to root_type, otherwise std::exp2 returns double (always)
  1291. using std::exp2;
  1292. return cr * exp2(static_cast<typename fvar<RealType, Order>::root_type>(exp));
  1293. }
  1294. template <typename RealType, size_t Order>
  1295. fvar<RealType, Order> cos(fvar<RealType, Order> const& cr) {
  1296. BOOST_MATH_STD_USING
  1297. using root_type = typename fvar<RealType, Order>::root_type;
  1298. constexpr size_t order = fvar<RealType, Order>::order_sum;
  1299. root_type const d0 = cos(static_cast<root_type>(cr));
  1300. BOOST_IF_CONSTEXPR (order == 0)
  1301. return fvar<RealType, Order>(d0);
  1302. else {
  1303. root_type const d1 = -sin(static_cast<root_type>(cr));
  1304. root_type const derivatives[4]{d0, d1, -d0, -d1};
  1305. return cr.apply_derivatives(order, [&derivatives](size_t i) { return derivatives[i & 3]; });
  1306. }
  1307. }
  1308. template <typename RealType, size_t Order>
  1309. fvar<RealType, Order> sin(fvar<RealType, Order> const& cr) {
  1310. BOOST_MATH_STD_USING
  1311. using root_type = typename fvar<RealType, Order>::root_type;
  1312. constexpr size_t order = fvar<RealType, Order>::order_sum;
  1313. root_type const d0 = sin(static_cast<root_type>(cr));
  1314. BOOST_IF_CONSTEXPR (order == 0)
  1315. return fvar<RealType, Order>(d0);
  1316. else {
  1317. root_type const d1 = cos(static_cast<root_type>(cr));
  1318. root_type const derivatives[4]{d0, d1, -d0, -d1};
  1319. return cr.apply_derivatives(order, [&derivatives](size_t i) { return derivatives[i & 3]; });
  1320. }
  1321. }
  1322. template <typename RealType, size_t Order>
  1323. fvar<RealType, Order> asin(fvar<RealType, Order> const& cr) {
  1324. using std::asin;
  1325. using root_type = typename fvar<RealType, Order>::root_type;
  1326. constexpr size_t order = fvar<RealType, Order>::order_sum;
  1327. root_type const d0 = asin(static_cast<root_type>(cr));
  1328. BOOST_IF_CONSTEXPR (order == 0)
  1329. return fvar<RealType, Order>(d0);
  1330. else {
  1331. auto x = make_fvar<root_type, bool(order) ? order - 1 : 0>(static_cast<root_type>(cr));
  1332. auto const d1 = sqrt((x *= x).negate() += 1).inverse(); // asin'(x) = 1 / sqrt(1-x*x).
  1333. return cr.apply_coefficients_nonhorner(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; });
  1334. }
  1335. }
  1336. template <typename RealType, size_t Order>
  1337. fvar<RealType, Order> tan(fvar<RealType, Order> const& cr) {
  1338. using std::tan;
  1339. using root_type = typename fvar<RealType, Order>::root_type;
  1340. constexpr size_t order = fvar<RealType, Order>::order_sum;
  1341. root_type const d0 = tan(static_cast<root_type>(cr));
  1342. BOOST_IF_CONSTEXPR (order == 0)
  1343. return fvar<RealType, Order>(d0);
  1344. else {
  1345. auto c = cos(make_fvar<root_type, bool(order) ? order - 1 : 0>(static_cast<root_type>(cr)));
  1346. auto const d1 = (c *= c).inverse(); // tan'(x) = 1 / cos(x)^2
  1347. return cr.apply_coefficients_nonhorner(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; });
  1348. }
  1349. }
  1350. template <typename RealType, size_t Order>
  1351. fvar<RealType, Order> atan(fvar<RealType, Order> const& cr) {
  1352. using std::atan;
  1353. using root_type = typename fvar<RealType, Order>::root_type;
  1354. constexpr size_t order = fvar<RealType, Order>::order_sum;
  1355. root_type const d0 = atan(static_cast<root_type>(cr));
  1356. BOOST_IF_CONSTEXPR (order == 0)
  1357. return fvar<RealType, Order>(d0);
  1358. else {
  1359. auto x = make_fvar<root_type, bool(order) ? order - 1 : 0>(static_cast<root_type>(cr));
  1360. auto const d1 = ((x *= x) += 1).inverse(); // atan'(x) = 1 / (x*x+1).
  1361. return cr.apply_coefficients(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; });
  1362. }
  1363. }
  1364. template <typename RealType, size_t Order>
  1365. fvar<RealType, Order> atan2(fvar<RealType, Order> const& cr,
  1366. typename fvar<RealType, Order>::root_type const& ca) {
  1367. using std::atan2;
  1368. using root_type = typename fvar<RealType, Order>::root_type;
  1369. constexpr size_t order = fvar<RealType, Order>::order_sum;
  1370. root_type const d0 = atan2(static_cast<root_type>(cr), ca);
  1371. BOOST_IF_CONSTEXPR (order == 0)
  1372. return fvar<RealType, Order>(d0);
  1373. else {
  1374. auto y = make_fvar<root_type, bool(order) ? order - 1 : 0>(static_cast<root_type>(cr));
  1375. auto const d1 = ca / ((y *= y) += (ca * ca)); // (d/dy)atan2(y,x) = x / (y*y+x*x)
  1376. return cr.apply_coefficients(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; });
  1377. }
  1378. }
  1379. template <typename RealType, size_t Order>
  1380. fvar<RealType, Order> atan2(typename fvar<RealType, Order>::root_type const& ca,
  1381. fvar<RealType, Order> const& cr) {
  1382. using std::atan2;
  1383. using root_type = typename fvar<RealType, Order>::root_type;
  1384. constexpr size_t order = fvar<RealType, Order>::order_sum;
  1385. root_type const d0 = atan2(ca, static_cast<root_type>(cr));
  1386. BOOST_IF_CONSTEXPR (order == 0)
  1387. return fvar<RealType, Order>(d0);
  1388. else {
  1389. auto x = make_fvar<root_type, bool(order) ? order - 1 : 0>(static_cast<root_type>(cr));
  1390. auto const d1 = -ca / ((x *= x) += (ca * ca)); // (d/dx)atan2(y,x) = -y / (x*x+y*y)
  1391. return cr.apply_coefficients(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; });
  1392. }
  1393. }
  1394. template <typename RealType1, size_t Order1, typename RealType2, size_t Order2>
  1395. promote<fvar<RealType1, Order1>, fvar<RealType2, Order2>> atan2(fvar<RealType1, Order1> const& cr1,
  1396. fvar<RealType2, Order2> const& cr2) {
  1397. using std::atan2;
  1398. using return_type = promote<fvar<RealType1, Order1>, fvar<RealType2, Order2>>;
  1399. using root_type = typename return_type::root_type;
  1400. constexpr size_t order = return_type::order_sum;
  1401. root_type const y = static_cast<root_type>(cr1);
  1402. root_type const x = static_cast<root_type>(cr2);
  1403. root_type const d00 = atan2(y, x);
  1404. BOOST_IF_CONSTEXPR (order == 0)
  1405. return return_type(d00);
  1406. else {
  1407. constexpr size_t order1 = fvar<RealType1, Order1>::order_sum;
  1408. constexpr size_t order2 = fvar<RealType2, Order2>::order_sum;
  1409. auto x01 = make_fvar<typename fvar<RealType2, Order2>::root_type, order2 - 1>(x);
  1410. auto const d01 = -y / ((x01 *= x01) += (y * y));
  1411. auto y10 = make_fvar<typename fvar<RealType1, Order1>::root_type, order1 - 1>(y);
  1412. auto x10 = make_fvar<typename fvar<RealType2, Order2>::root_type, 0, order2>(x);
  1413. auto const d10 = x10 / ((x10 * x10) + (y10 *= y10));
  1414. auto const f = [&d00, &d01, &d10](size_t i, size_t j) {
  1415. return i ? d10[i - 1][j] / i : j ? d01[j - 1] / j : d00;
  1416. };
  1417. return cr1.apply_coefficients(order, f, cr2);
  1418. }
  1419. }
  1420. template <typename RealType1, size_t Order1, typename RealType2, size_t Order2>
  1421. promote<fvar<RealType1, Order1>, fvar<RealType2, Order2>> fmod(fvar<RealType1, Order1> const& cr1,
  1422. fvar<RealType2, Order2> const& cr2) {
  1423. using boost::math::trunc;
  1424. auto const numer = static_cast<typename fvar<RealType1, Order1>::root_type>(cr1);
  1425. auto const denom = static_cast<typename fvar<RealType2, Order2>::root_type>(cr2);
  1426. return cr1 - cr2 * trunc(numer / denom);
  1427. }
  1428. template <typename RealType, size_t Order>
  1429. fvar<RealType, Order> round(fvar<RealType, Order> const& cr) {
  1430. using boost::math::round;
  1431. return fvar<RealType, Order>(round(static_cast<typename fvar<RealType, Order>::root_type>(cr)));
  1432. }
  1433. template <typename RealType, size_t Order>
  1434. int iround(fvar<RealType, Order> const& cr) {
  1435. using boost::math::iround;
  1436. return iround(static_cast<typename fvar<RealType, Order>::root_type>(cr));
  1437. }
  1438. template <typename RealType, size_t Order>
  1439. long lround(fvar<RealType, Order> const& cr) {
  1440. using boost::math::lround;
  1441. return lround(static_cast<typename fvar<RealType, Order>::root_type>(cr));
  1442. }
  1443. template <typename RealType, size_t Order>
  1444. long long llround(fvar<RealType, Order> const& cr) {
  1445. using boost::math::llround;
  1446. return llround(static_cast<typename fvar<RealType, Order>::root_type>(cr));
  1447. }
  1448. template <typename RealType, size_t Order>
  1449. fvar<RealType, Order> trunc(fvar<RealType, Order> const& cr) {
  1450. using boost::math::trunc;
  1451. return fvar<RealType, Order>(trunc(static_cast<typename fvar<RealType, Order>::root_type>(cr)));
  1452. }
  1453. template <typename RealType, size_t Order>
  1454. long double truncl(fvar<RealType, Order> const& cr) {
  1455. using std::truncl;
  1456. return truncl(static_cast<typename fvar<RealType, Order>::root_type>(cr));
  1457. }
  1458. template <typename RealType, size_t Order>
  1459. int itrunc(fvar<RealType, Order> const& cr) {
  1460. using boost::math::itrunc;
  1461. return itrunc(static_cast<typename fvar<RealType, Order>::root_type>(cr));
  1462. }
  1463. template <typename RealType, size_t Order>
  1464. long long lltrunc(fvar<RealType, Order> const& cr) {
  1465. using boost::math::lltrunc;
  1466. return lltrunc(static_cast<typename fvar<RealType, Order>::root_type>(cr));
  1467. }
  1468. template <typename RealType, size_t Order>
  1469. std::ostream& operator<<(std::ostream& out, fvar<RealType, Order> const& cr) {
  1470. out << "depth(" << cr.depth << ")(" << cr.v.front();
  1471. for (size_t i = 1; i <= Order; ++i)
  1472. out << ',' << cr.v[i];
  1473. return out << ')';
  1474. }
  1475. // Additional functions
  1476. template <typename RealType, size_t Order>
  1477. fvar<RealType, Order> acos(fvar<RealType, Order> const& cr) {
  1478. using std::acos;
  1479. using root_type = typename fvar<RealType, Order>::root_type;
  1480. constexpr size_t order = fvar<RealType, Order>::order_sum;
  1481. root_type const d0 = acos(static_cast<root_type>(cr));
  1482. BOOST_IF_CONSTEXPR (order == 0)
  1483. return fvar<RealType, Order>(d0);
  1484. else {
  1485. auto x = make_fvar<root_type, bool(order) ? order - 1 : 0>(static_cast<root_type>(cr));
  1486. auto const d1 = sqrt((x *= x).negate() += 1).inverse().negate(); // acos'(x) = -1 / sqrt(1-x*x).
  1487. return cr.apply_coefficients(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; });
  1488. }
  1489. }
  1490. template <typename RealType, size_t Order>
  1491. fvar<RealType, Order> acosh(fvar<RealType, Order> const& cr) {
  1492. using boost::math::acosh;
  1493. using root_type = typename fvar<RealType, Order>::root_type;
  1494. constexpr size_t order = fvar<RealType, Order>::order_sum;
  1495. root_type const d0 = acosh(static_cast<root_type>(cr));
  1496. BOOST_IF_CONSTEXPR (order == 0)
  1497. return fvar<RealType, Order>(d0);
  1498. else {
  1499. auto x = make_fvar<root_type, bool(order) ? order - 1 : 0>(static_cast<root_type>(cr));
  1500. auto const d1 = sqrt((x *= x) -= 1).inverse(); // acosh'(x) = 1 / sqrt(x*x-1).
  1501. return cr.apply_coefficients(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; });
  1502. }
  1503. }
  1504. template <typename RealType, size_t Order>
  1505. fvar<RealType, Order> asinh(fvar<RealType, Order> const& cr) {
  1506. using boost::math::asinh;
  1507. using root_type = typename fvar<RealType, Order>::root_type;
  1508. constexpr size_t order = fvar<RealType, Order>::order_sum;
  1509. root_type const d0 = asinh(static_cast<root_type>(cr));
  1510. BOOST_IF_CONSTEXPR (order == 0)
  1511. return fvar<RealType, Order>(d0);
  1512. else {
  1513. auto x = make_fvar<root_type, bool(order) ? order - 1 : 0>(static_cast<root_type>(cr));
  1514. auto const d1 = sqrt((x *= x) += 1).inverse(); // asinh'(x) = 1 / sqrt(x*x+1).
  1515. return cr.apply_coefficients(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; });
  1516. }
  1517. }
  1518. template <typename RealType, size_t Order>
  1519. fvar<RealType, Order> atanh(fvar<RealType, Order> const& cr) {
  1520. using boost::math::atanh;
  1521. using root_type = typename fvar<RealType, Order>::root_type;
  1522. constexpr size_t order = fvar<RealType, Order>::order_sum;
  1523. root_type const d0 = atanh(static_cast<root_type>(cr));
  1524. BOOST_IF_CONSTEXPR (order == 0)
  1525. return fvar<RealType, Order>(d0);
  1526. else {
  1527. auto x = make_fvar<root_type, bool(order) ? order - 1 : 0>(static_cast<root_type>(cr));
  1528. auto const d1 = ((x *= x).negate() += 1).inverse(); // atanh'(x) = 1 / (1-x*x)
  1529. return cr.apply_coefficients(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; });
  1530. }
  1531. }
  1532. template <typename RealType, size_t Order>
  1533. fvar<RealType, Order> cosh(fvar<RealType, Order> const& cr) {
  1534. BOOST_MATH_STD_USING
  1535. using root_type = typename fvar<RealType, Order>::root_type;
  1536. constexpr size_t order = fvar<RealType, Order>::order_sum;
  1537. root_type const d0 = cosh(static_cast<root_type>(cr));
  1538. BOOST_IF_CONSTEXPR (order == 0)
  1539. return fvar<RealType, Order>(d0);
  1540. else {
  1541. root_type const derivatives[2]{d0, sinh(static_cast<root_type>(cr))};
  1542. return cr.apply_derivatives(order, [&derivatives](size_t i) { return derivatives[i & 1]; });
  1543. }
  1544. }
  1545. template <typename RealType, size_t Order>
  1546. fvar<RealType, Order> digamma(fvar<RealType, Order> const& cr) {
  1547. using boost::math::digamma;
  1548. using root_type = typename fvar<RealType, Order>::root_type;
  1549. constexpr size_t order = fvar<RealType, Order>::order_sum;
  1550. root_type const x = static_cast<root_type>(cr);
  1551. root_type const d0 = digamma(x);
  1552. BOOST_IF_CONSTEXPR (order == 0)
  1553. return fvar<RealType, Order>(d0);
  1554. else {
  1555. static_assert(order <= static_cast<size_t>((std::numeric_limits<int>::max)()),
  1556. "order exceeds maximum derivative for boost::math::polygamma().");
  1557. return cr.apply_derivatives(
  1558. order, [&x, &d0](size_t i) { return i ? boost::math::polygamma(static_cast<int>(i), x) : d0; });
  1559. }
  1560. }
  1561. template <typename RealType, size_t Order>
  1562. fvar<RealType, Order> erf(fvar<RealType, Order> const& cr) {
  1563. using boost::math::erf;
  1564. using root_type = typename fvar<RealType, Order>::root_type;
  1565. constexpr size_t order = fvar<RealType, Order>::order_sum;
  1566. root_type const d0 = erf(static_cast<root_type>(cr));
  1567. BOOST_IF_CONSTEXPR (order == 0)
  1568. return fvar<RealType, Order>(d0);
  1569. else {
  1570. auto x = make_fvar<root_type, bool(order) ? order - 1 : 0>(static_cast<root_type>(cr)); // d1 = 2/sqrt(pi)*exp(-x*x)
  1571. auto const d1 = 2 * constants::one_div_root_pi<root_type>() * exp((x *= x).negate());
  1572. return cr.apply_coefficients(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; });
  1573. }
  1574. }
  1575. template <typename RealType, size_t Order>
  1576. fvar<RealType, Order> erfc(fvar<RealType, Order> const& cr) {
  1577. using boost::math::erfc;
  1578. using root_type = typename fvar<RealType, Order>::root_type;
  1579. constexpr size_t order = fvar<RealType, Order>::order_sum;
  1580. root_type const d0 = erfc(static_cast<root_type>(cr));
  1581. BOOST_IF_CONSTEXPR (order == 0)
  1582. return fvar<RealType, Order>(d0);
  1583. else {
  1584. auto x = make_fvar<root_type, bool(order) ? order - 1 : 0>(static_cast<root_type>(cr)); // erfc'(x) = -erf'(x)
  1585. auto const d1 = -2 * constants::one_div_root_pi<root_type>() * exp((x *= x).negate());
  1586. return cr.apply_coefficients(order, [&d0, &d1](size_t i) { return i ? d1[i - 1] / i : d0; });
  1587. }
  1588. }
  1589. template <typename RealType, size_t Order>
  1590. fvar<RealType, Order> lambert_w0(fvar<RealType, Order> const& cr) {
  1591. using std::exp;
  1592. using boost::math::lambert_w0;
  1593. using root_type = typename fvar<RealType, Order>::root_type;
  1594. constexpr size_t order = fvar<RealType, Order>::order_sum;
  1595. root_type derivatives[order + 1];
  1596. *derivatives = lambert_w0(static_cast<root_type>(cr));
  1597. BOOST_IF_CONSTEXPR (order == 0)
  1598. return fvar<RealType, Order>(*derivatives);
  1599. else {
  1600. root_type const expw = exp(*derivatives);
  1601. derivatives[1] = 1 / (static_cast<root_type>(cr) + expw);
  1602. BOOST_IF_CONSTEXPR (order == 1)
  1603. return cr.apply_derivatives_nonhorner(order, [&derivatives](size_t i) { return derivatives[i]; });
  1604. else {
  1605. using diff_t = typename std::array<RealType, Order + 1>::difference_type;
  1606. root_type d1powers = derivatives[1] * derivatives[1];
  1607. root_type const x = derivatives[1] * expw;
  1608. derivatives[2] = d1powers * (-1 - x);
  1609. std::array<root_type, order> coef{{-1, -1}}; // as in derivatives[2].
  1610. for (size_t n = 3; n <= order; ++n) {
  1611. coef[n - 1] = coef[n - 2] * -static_cast<root_type>(2 * n - 3);
  1612. for (size_t j = n - 2; j != 0; --j)
  1613. (coef[j] *= -static_cast<root_type>(n - 1)) -= (n + j - 2) * coef[j - 1];
  1614. coef[0] *= -static_cast<root_type>(n - 1);
  1615. d1powers *= derivatives[1];
  1616. derivatives[n] =
  1617. d1powers * std::accumulate(coef.crend() - diff_t(n - 1),
  1618. coef.crend(),
  1619. coef[n - 1],
  1620. [&x](root_type const& a, root_type const& b) { return a * x + b; });
  1621. }
  1622. return cr.apply_derivatives_nonhorner(order, [&derivatives](size_t i) { return derivatives[i]; });
  1623. }
  1624. }
  1625. }
  1626. template <typename RealType, size_t Order>
  1627. fvar<RealType, Order> lgamma(fvar<RealType, Order> const& cr) {
  1628. using std::lgamma;
  1629. using root_type = typename fvar<RealType, Order>::root_type;
  1630. constexpr size_t order = fvar<RealType, Order>::order_sum;
  1631. root_type const x = static_cast<root_type>(cr);
  1632. root_type const d0 = lgamma(x);
  1633. BOOST_IF_CONSTEXPR (order == 0)
  1634. return fvar<RealType, Order>(d0);
  1635. else {
  1636. static_assert(order <= static_cast<size_t>((std::numeric_limits<int>::max)()) + 1,
  1637. "order exceeds maximum derivative for boost::math::polygamma().");
  1638. return cr.apply_derivatives(
  1639. order, [&x, &d0](size_t i) { return i ? boost::math::polygamma(static_cast<int>(i - 1), x) : d0; });
  1640. }
  1641. }
  1642. template <typename RealType, size_t Order>
  1643. fvar<RealType, Order> sinc(fvar<RealType, Order> const& cr) {
  1644. if (cr != 0)
  1645. return sin(cr) / cr;
  1646. using root_type = typename fvar<RealType, Order>::root_type;
  1647. constexpr size_t order = fvar<RealType, Order>::order_sum;
  1648. root_type taylor[order + 1]{1}; // sinc(0) = 1
  1649. BOOST_IF_CONSTEXPR (order == 0)
  1650. return fvar<RealType, Order>(*taylor);
  1651. else {
  1652. for (size_t n = 2; n <= order; n += 2)
  1653. taylor[n] = (1 - static_cast<int>(n & 2)) / factorial<root_type>(static_cast<unsigned>(n + 1));
  1654. return cr.apply_coefficients_nonhorner(order, [&taylor](size_t i) { return taylor[i]; });
  1655. }
  1656. }
  1657. template <typename RealType, size_t Order>
  1658. fvar<RealType, Order> sinh(fvar<RealType, Order> const& cr) {
  1659. BOOST_MATH_STD_USING
  1660. using root_type = typename fvar<RealType, Order>::root_type;
  1661. constexpr size_t order = fvar<RealType, Order>::order_sum;
  1662. root_type const d0 = sinh(static_cast<root_type>(cr));
  1663. BOOST_IF_CONSTEXPR (fvar<RealType, Order>::order_sum == 0)
  1664. return fvar<RealType, Order>(d0);
  1665. else {
  1666. root_type const derivatives[2]{d0, cosh(static_cast<root_type>(cr))};
  1667. return cr.apply_derivatives(order, [&derivatives](size_t i) { return derivatives[i & 1]; });
  1668. }
  1669. }
  1670. template <typename RealType, size_t Order>
  1671. fvar<RealType, Order> tanh(fvar<RealType, Order> const& cr) {
  1672. fvar<RealType, Order> retval = exp(cr * 2);
  1673. fvar<RealType, Order> const denom = retval + 1;
  1674. (retval -= 1) /= denom;
  1675. return retval;
  1676. }
  1677. template <typename RealType, size_t Order>
  1678. fvar<RealType, Order> tgamma(fvar<RealType, Order> const& cr) {
  1679. using std::tgamma;
  1680. using root_type = typename fvar<RealType, Order>::root_type;
  1681. constexpr size_t order = fvar<RealType, Order>::order_sum;
  1682. BOOST_IF_CONSTEXPR (order == 0)
  1683. return fvar<RealType, Order>(tgamma(static_cast<root_type>(cr)));
  1684. else {
  1685. if (cr < 0)
  1686. return constants::pi<root_type>() / (sin(constants::pi<root_type>() * cr) * tgamma(1 - cr));
  1687. return exp(lgamma(cr)).set_root(tgamma(static_cast<root_type>(cr)));
  1688. }
  1689. }
  1690. } // namespace detail
  1691. } // namespace autodiff_v1
  1692. } // namespace differentiation
  1693. } // namespace math
  1694. } // namespace boost
  1695. namespace std {
  1696. // boost::math::tools::digits<RealType>() is handled by this std::numeric_limits<> specialization,
  1697. // and similarly for max_value, min_value, log_max_value, log_min_value, and epsilon.
  1698. template <typename RealType, size_t Order>
  1699. class numeric_limits<boost::math::differentiation::detail::fvar<RealType, Order>>
  1700. : public numeric_limits<typename boost::math::differentiation::detail::fvar<RealType, Order>::root_type> {
  1701. };
  1702. } // namespace std
  1703. namespace boost {
  1704. namespace math {
  1705. namespace tools {
  1706. namespace detail {
  1707. template <typename RealType, std::size_t Order>
  1708. using autodiff_fvar_type = differentiation::detail::fvar<RealType, Order>;
  1709. template <typename RealType, std::size_t Order>
  1710. using autodiff_root_type = typename autodiff_fvar_type<RealType, Order>::root_type;
  1711. } // namespace detail
  1712. // See boost/math/tools/promotion.hpp
  1713. template <typename RealType0, size_t Order0, typename RealType1, size_t Order1>
  1714. struct promote_args_2<detail::autodiff_fvar_type<RealType0, Order0>,
  1715. detail::autodiff_fvar_type<RealType1, Order1>> {
  1716. using type = detail::autodiff_fvar_type<typename promote_args_2<RealType0, RealType1>::type,
  1717. #ifndef BOOST_NO_CXX14_CONSTEXPR
  1718. (std::max)(Order0, Order1)>;
  1719. #else
  1720. Order0<Order1 ? Order1 : Order0>;
  1721. #endif
  1722. };
  1723. template <typename RealType, size_t Order>
  1724. struct promote_args<detail::autodiff_fvar_type<RealType, Order>> {
  1725. using type = detail::autodiff_fvar_type<typename promote_args<RealType>::type, Order>;
  1726. };
  1727. template <typename RealType0, size_t Order0, typename RealType1>
  1728. struct promote_args_2<detail::autodiff_fvar_type<RealType0, Order0>, RealType1> {
  1729. using type = detail::autodiff_fvar_type<typename promote_args_2<RealType0, RealType1>::type, Order0>;
  1730. };
  1731. template <typename RealType0, typename RealType1, size_t Order1>
  1732. struct promote_args_2<RealType0, detail::autodiff_fvar_type<RealType1, Order1>> {
  1733. using type = detail::autodiff_fvar_type<typename promote_args_2<RealType0, RealType1>::type, Order1>;
  1734. };
  1735. template <typename destination_t, typename RealType, std::size_t Order>
  1736. inline BOOST_MATH_CONSTEXPR destination_t real_cast(detail::autodiff_fvar_type<RealType, Order> const& from_v)
  1737. BOOST_NOEXCEPT_IF(BOOST_MATH_IS_FLOAT(destination_t) && BOOST_MATH_IS_FLOAT(RealType)) {
  1738. return real_cast<destination_t>(static_cast<detail::autodiff_root_type<RealType, Order>>(from_v));
  1739. }
  1740. } // namespace tools
  1741. namespace policies {
  1742. template <class Policy, std::size_t Order>
  1743. using fvar_t = differentiation::detail::fvar<Policy, Order>;
  1744. template <class Policy, std::size_t Order>
  1745. struct evaluation<fvar_t<float, Order>, Policy> {
  1746. using type = fvar_t<typename conditional<Policy::promote_float_type::value, double, float>::type, Order>;
  1747. };
  1748. template <class Policy, std::size_t Order>
  1749. struct evaluation<fvar_t<double, Order>, Policy> {
  1750. using type =
  1751. fvar_t<typename conditional<Policy::promote_double_type::value, long double, double>::type, Order>;
  1752. };
  1753. } // namespace policies
  1754. } // namespace math
  1755. } // namespace boost
  1756. #ifdef BOOST_NO_CXX17_IF_CONSTEXPR
  1757. #include "autodiff_cpp11.hpp"
  1758. #endif
  1759. #endif // BOOST_MATH_DIFFERENTIATION_AUTODIFF_HPP