autodiff.hpp 80 KB

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