default_ops.hpp 75 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Copyright 2011 John Maddock. Distributed under the Boost
  3. // Software License, Version 1.0. (See accompanying file
  4. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #ifndef BOOST_MATH_BIG_NUM_DEF_OPS
  6. #define BOOST_MATH_BIG_NUM_DEF_OPS
  7. #include <boost/math/policies/error_handling.hpp>
  8. #include <boost/multiprecision/detail/number_base.hpp>
  9. #include <boost/math/special_functions/fpclassify.hpp>
  10. #include <boost/utility/enable_if.hpp>
  11. #include <boost/mpl/front.hpp>
  12. #include <boost/mpl/fold.hpp>
  13. #include <boost/cstdint.hpp>
  14. #include <boost/type_traits/make_unsigned.hpp>
  15. #ifndef INSTRUMENT_BACKEND
  16. #ifndef BOOST_MP_INSTRUMENT
  17. #define INSTRUMENT_BACKEND(x)
  18. #else
  19. #define INSTRUMENT_BACKEND(x)\
  20. std::cout << BOOST_STRINGIZE(x) << " = " << x.str(0, std::ios_base::scientific) << std::endl;
  21. #endif
  22. #endif
  23. namespace boost{ namespace multiprecision{ namespace default_ops{
  24. #ifdef BOOST_MSVC
  25. // warning C4127: conditional expression is constant
  26. #pragma warning(push)
  27. #pragma warning(disable:4127)
  28. #endif
  29. //
  30. // Default versions of mixed arithmetic, these just construct a temporary
  31. // from the arithmetic value and then do the arithmetic on that, two versions
  32. // of each depending on whether the backend can be directly constructed from type V.
  33. //
  34. // Note that we have to provide *all* the template parameters to class number when used in
  35. // enable_if as MSVC-10 won't compile the code if we rely on a computed-default parameter.
  36. // Since the result of the test doesn't depend on whether expression templates are on or off
  37. // we just use et_on everywhere. We could use a BOOST_WORKAROUND but that just obfuscates the
  38. // code even more....
  39. //
  40. template <class T, class V>
  41. inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value >::type
  42. eval_add(T& result, V const& v)
  43. {
  44. T t;
  45. t = v;
  46. eval_add(result, t);
  47. }
  48. template <class T, class V>
  49. inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value >::type
  50. eval_add(T& result, V const& v)
  51. {
  52. T t(v);
  53. eval_add(result, t);
  54. }
  55. template <class T, class V>
  56. inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
  57. eval_subtract(T& result, V const& v)
  58. {
  59. T t;
  60. t = v;
  61. eval_subtract(result, t);
  62. }
  63. template <class T, class V>
  64. inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
  65. eval_subtract(T& result, V const& v)
  66. {
  67. T t(v);
  68. eval_subtract(result, t);
  69. }
  70. template <class T, class V>
  71. inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
  72. eval_multiply(T& result, V const& v)
  73. {
  74. T t;
  75. t = v;
  76. eval_multiply(result, t);
  77. }
  78. template <class T, class V>
  79. inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
  80. eval_multiply(T& result, V const& v)
  81. {
  82. T t(v);
  83. eval_multiply(result, t);
  84. }
  85. template <class T, class U, class V>
  86. void eval_multiply(T& t, const U& u, const V& v);
  87. template <class T, class U, class V>
  88. inline typename disable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v)
  89. {
  90. T z;
  91. eval_multiply(z, u, v);
  92. eval_add(t, z);
  93. }
  94. template <class T, class U, class V>
  95. inline typename enable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v)
  96. {
  97. eval_multiply_add(t, v, u);
  98. }
  99. template <class T, class U, class V>
  100. inline typename disable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_subtract(T& t, const U& u, const V& v)
  101. {
  102. T z;
  103. eval_multiply(z, u, v);
  104. eval_subtract(t, z);
  105. }
  106. template <class T, class U, class V>
  107. inline typename enable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_subtract(T& t, const U& u, const V& v)
  108. {
  109. eval_multiply_subtract(t, v, u);
  110. }
  111. template <class T, class V>
  112. inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
  113. eval_divide(T& result, V const& v)
  114. {
  115. T t;
  116. t = v;
  117. eval_divide(result, t);
  118. }
  119. template <class T, class V>
  120. inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
  121. eval_divide(T& result, V const& v)
  122. {
  123. T t(v);
  124. eval_divide(result, t);
  125. }
  126. template <class T, class V>
  127. inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
  128. eval_modulus(T& result, V const& v)
  129. {
  130. T t;
  131. t = v;
  132. eval_modulus(result, t);
  133. }
  134. template <class T, class V>
  135. inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value&& is_convertible<V, T>::value>::type
  136. eval_modulus(T& result, V const& v)
  137. {
  138. T t(v);
  139. eval_modulus(result, t);
  140. }
  141. template <class T, class V>
  142. inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
  143. eval_bitwise_and(T& result, V const& v)
  144. {
  145. T t;
  146. t = v;
  147. eval_bitwise_and(result, t);
  148. }
  149. template <class T, class V>
  150. inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
  151. eval_bitwise_and(T& result, V const& v)
  152. {
  153. T t(v);
  154. eval_bitwise_and(result, t);
  155. }
  156. template <class T, class V>
  157. inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
  158. eval_bitwise_or(T& result, V const& v)
  159. {
  160. T t;
  161. t = v;
  162. eval_bitwise_or(result, t);
  163. }
  164. template <class T, class V>
  165. inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
  166. eval_bitwise_or(T& result, V const& v)
  167. {
  168. T t(v);
  169. eval_bitwise_or(result, t);
  170. }
  171. template <class T, class V>
  172. inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
  173. eval_bitwise_xor(T& result, V const& v)
  174. {
  175. T t;
  176. t = v;
  177. eval_bitwise_xor(result, t);
  178. }
  179. template <class T, class V>
  180. inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
  181. eval_bitwise_xor(T& result, V const& v)
  182. {
  183. T t(v);
  184. eval_bitwise_xor(result, t);
  185. }
  186. template <class T, class V>
  187. inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && !is_convertible<V, T>::value>::type
  188. eval_complement(T& result, V const& v)
  189. {
  190. T t;
  191. t = v;
  192. eval_complement(result, t);
  193. }
  194. template <class T, class V>
  195. inline typename enable_if_c<is_convertible<V, number<T, et_on> >::value && is_convertible<V, T>::value>::type
  196. eval_complement(T& result, V const& v)
  197. {
  198. T t(v);
  199. eval_complement(result, t);
  200. }
  201. //
  202. // Default versions of 3-arg arithmetic functions, these mostly just forward to the 2 arg versions:
  203. //
  204. template <class T, class U, class V>
  205. void eval_add(T& t, const U& u, const V& v);
  206. template <class T>
  207. inline void eval_add_default(T& t, const T& u, const T& v)
  208. {
  209. if(&t == &v)
  210. {
  211. eval_add(t, u);
  212. }
  213. else if(&t == &u)
  214. {
  215. eval_add(t, v);
  216. }
  217. else
  218. {
  219. t = u;
  220. eval_add(t, v);
  221. }
  222. }
  223. template <class T, class U>
  224. inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_add_default(T& t, const T& u, const U& v)
  225. {
  226. T vv;
  227. vv = v;
  228. eval_add(t, u, vv);
  229. }
  230. template <class T, class U>
  231. inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_add_default(T& t, const T& u, const U& v)
  232. {
  233. T vv(v);
  234. eval_add(t, u, vv);
  235. }
  236. template <class T, class U>
  237. inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type eval_add_default(T& t, const U& u, const T& v)
  238. {
  239. eval_add(t, v, u);
  240. }
  241. template <class T, class U, class V>
  242. inline void eval_add_default(T& t, const U& u, const V& v)
  243. {
  244. if(is_same<T, V>::value && ((void*)&t == (void*)&v))
  245. {
  246. eval_add(t, u);
  247. }
  248. else
  249. {
  250. t = u;
  251. eval_add(t, v);
  252. }
  253. }
  254. template <class T, class U, class V>
  255. inline void eval_add(T& t, const U& u, const V& v)
  256. {
  257. eval_add_default(t, u, v);
  258. }
  259. template <class T, class U, class V>
  260. void eval_subtract(T& t, const U& u, const V& v);
  261. template <class T>
  262. inline void eval_subtract_default(T& t, const T& u, const T& v)
  263. {
  264. if((&t == &v) && is_signed_number<T>::value)
  265. {
  266. eval_subtract(t, u);
  267. t.negate();
  268. }
  269. else if(&t == &u)
  270. {
  271. eval_subtract(t, v);
  272. }
  273. else
  274. {
  275. t = u;
  276. eval_subtract(t, v);
  277. }
  278. }
  279. template <class T, class U>
  280. inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_subtract_default(T& t, const T& u, const U& v)
  281. {
  282. T vv;
  283. vv = v;
  284. eval_subtract(t, u, vv);
  285. }
  286. template <class T, class U>
  287. inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_subtract_default(T& t, const T& u, const U& v)
  288. {
  289. T vv(v);
  290. eval_subtract(t, u, vv);
  291. }
  292. template <class T, class U>
  293. inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_signed_number<T>::value>::type eval_subtract_default(T& t, const U& u, const T& v)
  294. {
  295. eval_subtract(t, v, u);
  296. t.negate();
  297. }
  298. template <class T, class U>
  299. inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_unsigned_number<T>::value>::type eval_subtract_default(T& t, const U& u, const T& v)
  300. {
  301. T temp(u);
  302. eval_subtract(t, temp, v);
  303. }
  304. template <class T, class U, class V>
  305. inline void eval_subtract_default(T& t, const U& u, const V& v)
  306. {
  307. if(is_same<T, V>::value && ((void*)&t == (void*)&v))
  308. {
  309. eval_subtract(t, u);
  310. t.negate();
  311. }
  312. else
  313. {
  314. t = u;
  315. eval_subtract(t, v);
  316. }
  317. }
  318. template <class T, class U, class V>
  319. inline void eval_subtract(T& t, const U& u, const V& v)
  320. {
  321. eval_subtract_default(t, u, v);
  322. }
  323. template <class T>
  324. inline void eval_multiply_default(T& t, const T& u, const T& v)
  325. {
  326. if(&t == &v)
  327. {
  328. eval_multiply(t, u);
  329. }
  330. else if(&t == &u)
  331. {
  332. eval_multiply(t, v);
  333. }
  334. else
  335. {
  336. t = u;
  337. eval_multiply(t, v);
  338. }
  339. }
  340. template <class T, class U>
  341. inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_multiply_default(T& t, const T& u, const U& v)
  342. {
  343. T vv;
  344. vv = v;
  345. eval_multiply(t, u, vv);
  346. }
  347. template <class T, class U>
  348. inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_multiply_default(T& t, const T& u, const U& v)
  349. {
  350. T vv(v);
  351. eval_multiply(t, u, vv);
  352. }
  353. template <class T, class U>
  354. inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type eval_multiply_default(T& t, const U& u, const T& v)
  355. {
  356. eval_multiply(t, v, u);
  357. }
  358. template <class T, class U, class V>
  359. inline void eval_multiply_default(T& t, const U& u, const V& v)
  360. {
  361. if(is_same<T, V>::value && ((void*)&t == (void*)&v))
  362. {
  363. eval_multiply(t, u);
  364. }
  365. else
  366. {
  367. t = u;
  368. eval_multiply(t, v);
  369. }
  370. }
  371. template <class T, class U, class V>
  372. inline void eval_multiply(T& t, const U& u, const V& v)
  373. {
  374. eval_multiply_default(t, u, v);
  375. }
  376. template <class T, class U, class V, class X>
  377. inline typename disable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v, const X& x)
  378. {
  379. if((void*)&x == (void*)&t)
  380. {
  381. T z;
  382. z = x;
  383. eval_multiply_add(t, u, v, z);
  384. }
  385. else
  386. {
  387. eval_multiply(t, u, v);
  388. eval_add(t, x);
  389. }
  390. }
  391. template <class T, class U, class V, class X>
  392. inline typename enable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_add(T& t, const U& u, const V& v, const X& x)
  393. {
  394. eval_multiply_add(t, v, u, x);
  395. }
  396. template <class T, class U, class V, class X>
  397. inline typename disable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_subtract(T& t, const U& u, const V& v, const X& x)
  398. {
  399. if((void*)&x == (void*)&t)
  400. {
  401. T z;
  402. z = x;
  403. eval_multiply_subtract(t, u, v, z);
  404. }
  405. else
  406. {
  407. eval_multiply(t, u, v);
  408. eval_subtract(t, x);
  409. }
  410. }
  411. template <class T, class U, class V, class X>
  412. inline typename enable_if_c<!is_same<T, U>::value && is_same<T, V>::value>::type eval_multiply_subtract(T& t, const U& u, const V& v, const X& x)
  413. {
  414. eval_multiply_subtract(t, v, u, x);
  415. }
  416. template <class T, class U, class V>
  417. void eval_divide(T& t, const U& u, const V& v);
  418. template <class T>
  419. inline void eval_divide_default(T& t, const T& u, const T& v)
  420. {
  421. if(&t == &u)
  422. eval_divide(t, v);
  423. else if(&t == &v)
  424. {
  425. T temp;
  426. eval_divide(temp, u, v);
  427. temp.swap(t);
  428. }
  429. else
  430. {
  431. t = u;
  432. eval_divide(t, v);
  433. }
  434. }
  435. template <class T, class U>
  436. inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_divide_default(T& t, const T& u, const U& v)
  437. {
  438. T vv;
  439. vv = v;
  440. eval_divide(t, u, vv);
  441. }
  442. template <class T, class U>
  443. inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_divide_default(T& t, const T& u, const U& v)
  444. {
  445. T vv(v);
  446. eval_divide(t, u, vv);
  447. }
  448. template <class T, class U>
  449. inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_divide_default(T& t, const U& u, const T& v)
  450. {
  451. T uu;
  452. uu = u;
  453. eval_divide(t, uu, v);
  454. }
  455. template <class T, class U>
  456. inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_divide_default(T& t, const U& u, const T& v)
  457. {
  458. T uu(u);
  459. eval_divide(t, uu, v);
  460. }
  461. template <class T, class U, class V>
  462. inline void eval_divide_default(T& t, const U& u, const V& v)
  463. {
  464. if(is_same<T, V>::value && ((void*)&t == (void*)&v))
  465. {
  466. T temp(u);
  467. eval_divide(temp, v);
  468. t = temp;
  469. }
  470. else
  471. {
  472. t = u;
  473. eval_divide(t, v);
  474. }
  475. }
  476. template <class T, class U, class V>
  477. inline void eval_divide(T& t, const U& u, const V& v)
  478. {
  479. eval_divide_default(t, u, v);
  480. }
  481. template <class T, class U, class V>
  482. void eval_modulus(T& t, const U& u, const V& v);
  483. template <class T>
  484. inline void eval_modulus_default(T& t, const T& u, const T& v)
  485. {
  486. if(&t == &u)
  487. eval_modulus(t, v);
  488. else if(&t == &v)
  489. {
  490. T temp;
  491. eval_modulus(temp, u, v);
  492. temp.swap(t);
  493. }
  494. else
  495. {
  496. t = u;
  497. eval_modulus(t, v);
  498. }
  499. }
  500. template <class T, class U>
  501. inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_modulus_default(T& t, const T& u, const U& v)
  502. {
  503. T vv;
  504. vv = v;
  505. eval_modulus(t, u, vv);
  506. }
  507. template <class T, class U>
  508. inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_modulus_default(T& t, const T& u, const U& v)
  509. {
  510. T vv(v);
  511. eval_modulus(t, u, vv);
  512. }
  513. template <class T, class U>
  514. inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_modulus_default(T& t, const U& u, const T& v)
  515. {
  516. T uu;
  517. uu = u;
  518. eval_modulus(t, uu, v);
  519. }
  520. template <class T, class U>
  521. inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_modulus_default(T& t, const U& u, const T& v)
  522. {
  523. T uu(u);
  524. eval_modulus(t, uu, v);
  525. }
  526. template <class T, class U, class V>
  527. inline void eval_modulus_default(T& t, const U& u, const V& v)
  528. {
  529. if(is_same<T, V>::value && ((void*)&t == (void*)&v))
  530. {
  531. T temp(u);
  532. eval_modulus(temp, v);
  533. t = temp;
  534. }
  535. else
  536. {
  537. t = u;
  538. eval_modulus(t, v);
  539. }
  540. }
  541. template <class T, class U, class V>
  542. inline void eval_modulus(T& t, const U& u, const V& v)
  543. {
  544. eval_modulus_default(t, u, v);
  545. }
  546. template <class T, class U, class V>
  547. void eval_bitwise_and(T& t, const U& u, const V& v);
  548. template <class T>
  549. inline void eval_bitwise_and_default(T& t, const T& u, const T& v)
  550. {
  551. if(&t == &v)
  552. {
  553. eval_bitwise_and(t, u);
  554. }
  555. else if(&t == &u)
  556. {
  557. eval_bitwise_and(t, v);
  558. }
  559. else
  560. {
  561. t = u;
  562. eval_bitwise_and(t, v);
  563. }
  564. }
  565. template <class T, class U>
  566. inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_bitwise_and_default(T& t, const T& u, const U& v)
  567. {
  568. T vv;
  569. vv = v;
  570. eval_bitwise_and(t, u, vv);
  571. }
  572. template <class T, class U>
  573. inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_bitwise_and_default(T& t, const T& u, const U& v)
  574. {
  575. T vv(v);
  576. eval_bitwise_and(t, u, vv);
  577. }
  578. template <class T, class U>
  579. inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type eval_bitwise_and_default(T& t, const U& u, const T& v)
  580. {
  581. eval_bitwise_and(t, v, u);
  582. }
  583. template <class T, class U, class V>
  584. inline void eval_bitwise_and_default(T& t, const U& u, const V& v)
  585. {
  586. if(is_same<T, V>::value && ((void*)&t == (void*)&v))
  587. {
  588. eval_bitwise_and(t, u);
  589. }
  590. else
  591. {
  592. t = u;
  593. eval_bitwise_and(t, v);
  594. }
  595. }
  596. template <class T, class U, class V>
  597. inline void eval_bitwise_and(T& t, const U& u, const V& v)
  598. {
  599. eval_bitwise_and_default(t, u, v);
  600. }
  601. template <class T, class U, class V>
  602. void eval_bitwise_or(T& t, const U& u, const V& v);
  603. template <class T>
  604. inline void eval_bitwise_or_default(T& t, const T& u, const T& v)
  605. {
  606. if(&t == &v)
  607. {
  608. eval_bitwise_or(t, u);
  609. }
  610. else if(&t == &u)
  611. {
  612. eval_bitwise_or(t, v);
  613. }
  614. else
  615. {
  616. t = u;
  617. eval_bitwise_or(t, v);
  618. }
  619. }
  620. template <class T, class U>
  621. inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_bitwise_or_default(T& t, const T& u, const U& v)
  622. {
  623. T vv;
  624. vv = v;
  625. eval_bitwise_or(t, u, vv);
  626. }
  627. template <class T, class U>
  628. inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_bitwise_or_default(T& t, const T& u, const U& v)
  629. {
  630. T vv(v);
  631. eval_bitwise_or(t, u, vv);
  632. }
  633. template <class T, class U>
  634. inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type eval_bitwise_or_default(T& t, const U& u, const T& v)
  635. {
  636. eval_bitwise_or(t, v, u);
  637. }
  638. template <class T, class U, class V>
  639. inline void eval_bitwise_or_default(T& t, const U& u, const V& v)
  640. {
  641. if(is_same<T, V>::value && ((void*)&t == (void*)&v))
  642. {
  643. eval_bitwise_or(t, u);
  644. }
  645. else
  646. {
  647. t = u;
  648. eval_bitwise_or(t, v);
  649. }
  650. }
  651. template <class T, class U, class V>
  652. inline void eval_bitwise_or(T& t, const U& u, const V& v)
  653. {
  654. eval_bitwise_or_default(t, u, v);
  655. }
  656. template <class T, class U, class V>
  657. void eval_bitwise_xor(T& t, const U& u, const V& v);
  658. template <class T>
  659. inline void eval_bitwise_xor_default(T& t, const T& u, const T& v)
  660. {
  661. if(&t == &v)
  662. {
  663. eval_bitwise_xor(t, u);
  664. }
  665. else if(&t == &u)
  666. {
  667. eval_bitwise_xor(t, v);
  668. }
  669. else
  670. {
  671. t = u;
  672. eval_bitwise_xor(t, v);
  673. }
  674. }
  675. template <class T, class U>
  676. inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_bitwise_xor_default(T& t, const T& u, const U& v)
  677. {
  678. T vv;
  679. vv = v;
  680. eval_bitwise_xor(t, u, vv);
  681. }
  682. template <class T, class U>
  683. inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_convertible<U, T>::value>::type eval_bitwise_xor_default(T& t, const T& u, const U& v)
  684. {
  685. T vv(v);
  686. eval_bitwise_xor(t, u, vv);
  687. }
  688. template <class T, class U>
  689. inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type eval_bitwise_xor_default(T& t, const U& u, const T& v)
  690. {
  691. eval_bitwise_xor(t, v, u);
  692. }
  693. template <class T, class U, class V>
  694. inline void eval_bitwise_xor_default(T& t, const U& u, const V& v)
  695. {
  696. if(is_same<T, V>::value && ((void*)&t == (void*)&v))
  697. {
  698. eval_bitwise_xor(t, u);
  699. }
  700. else
  701. {
  702. t = u;
  703. eval_bitwise_xor(t, v);
  704. }
  705. }
  706. template <class T, class U, class V>
  707. inline void eval_bitwise_xor(T& t, const U& u, const V& v)
  708. {
  709. eval_bitwise_xor_default(t, u, v);
  710. }
  711. template <class T>
  712. inline void eval_increment(T& val)
  713. {
  714. typedef typename mpl::front<typename T::unsigned_types>::type ui_type;
  715. eval_add(val, static_cast<ui_type>(1u));
  716. }
  717. template <class T>
  718. inline void eval_decrement(T& val)
  719. {
  720. typedef typename mpl::front<typename T::unsigned_types>::type ui_type;
  721. eval_subtract(val, static_cast<ui_type>(1u));
  722. }
  723. template <class T, class V>
  724. inline void eval_left_shift(T& result, const T& arg, const V val)
  725. {
  726. result = arg;
  727. eval_left_shift(result, val);
  728. }
  729. template <class T, class V>
  730. inline void eval_right_shift(T& result, const T& arg, const V val)
  731. {
  732. result = arg;
  733. eval_right_shift(result, val);
  734. }
  735. template <class T>
  736. inline bool eval_is_zero(const T& val)
  737. {
  738. typedef typename mpl::front<typename T::unsigned_types>::type ui_type;
  739. return val.compare(static_cast<ui_type>(0)) == 0;
  740. }
  741. template <class T>
  742. inline int eval_get_sign(const T& val)
  743. {
  744. typedef typename mpl::front<typename T::unsigned_types>::type ui_type;
  745. return val.compare(static_cast<ui_type>(0));
  746. }
  747. template <class T, class V>
  748. inline void assign_components_imp(T& result, const V& v1, const V& v2, const mpl::int_<number_kind_rational>&)
  749. {
  750. result = v1;
  751. T t;
  752. t = v2;
  753. eval_divide(result, t);
  754. }
  755. template <class T, class V>
  756. inline void assign_components(T& result, const V& v1, const V& v2)
  757. {
  758. return assign_components_imp(result, v1, v2, typename number_category<T>::type());
  759. }
  760. template <class R, int b>
  761. struct has_enough_bits
  762. {
  763. template <class T>
  764. struct type : public mpl::and_<mpl::not_<is_same<R, T> >, mpl::bool_<std::numeric_limits<T>::digits >= b> >{};
  765. };
  766. template <class R>
  767. struct terminal
  768. {
  769. terminal(const R& v) : value(v){}
  770. terminal(){}
  771. terminal& operator = (R val) { value = val; return *this; }
  772. R value;
  773. operator R()const { return value; }
  774. };
  775. template<class R, class B>
  776. struct calculate_next_larger_type
  777. {
  778. // Find which list we're looking through:
  779. typedef typename mpl::if_<
  780. is_signed<R>,
  781. typename B::signed_types,
  782. typename mpl::if_<
  783. is_unsigned<R>,
  784. typename B::unsigned_types,
  785. typename B::float_types
  786. >::type
  787. >::type list_type;
  788. // A predicate to find a type with enough bits:
  789. typedef typename has_enough_bits<R, std::numeric_limits<R>::digits>::template type<mpl::_> pred_type;
  790. // See if the last type is in the list, if so we have to start after this:
  791. typedef typename mpl::find_if<
  792. list_type,
  793. is_same<R, mpl::_>
  794. >::type start_last;
  795. // Where we're starting from, either the start of the sequence or the last type found:
  796. typedef typename mpl::if_<is_same<start_last, typename mpl::end<list_type>::type>, typename mpl::begin<list_type>::type, start_last>::type start_seq;
  797. // The range we're searching:
  798. typedef mpl::iterator_range<start_seq, typename mpl::end<list_type>::type> range;
  799. // Find the next type:
  800. typedef typename mpl::find_if<
  801. range,
  802. pred_type
  803. >::type iter_type;
  804. // Either the next type, or a "terminal" to indicate we've run out of types to search:
  805. typedef typename mpl::eval_if<
  806. is_same<typename mpl::end<list_type>::type, iter_type>,
  807. mpl::identity<terminal<R> >,
  808. mpl::deref<iter_type>
  809. >::type type;
  810. };
  811. template <class R, class T>
  812. inline bool check_in_range(const T& t)
  813. {
  814. // Can t fit in an R?
  815. if(std::numeric_limits<R>::is_specialized && std::numeric_limits<R>::is_bounded && (t > (std::numeric_limits<R>::max)()))
  816. return true;
  817. return false;
  818. }
  819. template <class R, class T>
  820. inline bool check_in_range(const terminal<T>&)
  821. {
  822. return false;
  823. }
  824. template <class R, class B>
  825. inline void eval_convert_to(R* result, const B& backend)
  826. {
  827. typedef typename calculate_next_larger_type<R, B>::type next_type;
  828. next_type n;
  829. eval_convert_to(&n, backend);
  830. if(check_in_range<R>(n))
  831. {
  832. *result = (std::numeric_limits<R>::max)();
  833. }
  834. else
  835. *result = static_cast<R>(n);
  836. }
  837. template <class R, class B>
  838. inline void eval_convert_to(terminal<R>* result, const B& backend)
  839. {
  840. //
  841. // We ran out of types to try for the conversion, try
  842. // a lexical_cast and hope for the best:
  843. //
  844. result->value = boost::lexical_cast<R>(backend.str(0, std::ios_base::fmtflags(0)));
  845. }
  846. template <class B>
  847. inline void eval_convert_to(std::string* result, const B& backend)
  848. {
  849. *result = backend.str(0, std::ios_base::fmtflags(0));
  850. }
  851. //
  852. // Functions:
  853. //
  854. template <class T>
  855. void eval_abs(T& result, const T& arg)
  856. {
  857. typedef typename T::signed_types type_list;
  858. typedef typename mpl::front<type_list>::type front;
  859. result = arg;
  860. if(arg.compare(front(0)) < 0)
  861. result.negate();
  862. }
  863. template <class T>
  864. void eval_fabs(T& result, const T& arg)
  865. {
  866. BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The fabs function is only valid for floating point types.");
  867. typedef typename T::signed_types type_list;
  868. typedef typename mpl::front<type_list>::type front;
  869. result = arg;
  870. if(arg.compare(front(0)) < 0)
  871. result.negate();
  872. }
  873. template <class Backend>
  874. inline int eval_fpclassify(const Backend& arg)
  875. {
  876. BOOST_STATIC_ASSERT_MSG(number_category<Backend>::value == number_kind_floating_point, "The fpclassify function is only valid for floating point types.");
  877. return eval_is_zero(arg) ? FP_ZERO : FP_NORMAL;
  878. }
  879. template <class T>
  880. inline void eval_fmod(T& result, const T& a, const T& b)
  881. {
  882. BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The fmod function is only valid for floating point types.");
  883. if((&result == &a) || (&result == &b))
  884. {
  885. T temp;
  886. eval_fmod(temp, a, b);
  887. result = temp;
  888. return;
  889. }
  890. T n;
  891. eval_divide(result, a, b);
  892. if(eval_get_sign(result) < 0)
  893. eval_ceil(n, result);
  894. else
  895. eval_floor(n, result);
  896. eval_multiply(n, b);
  897. eval_subtract(result, a, n);
  898. }
  899. template<class T, class A>
  900. inline typename enable_if<is_arithmetic<A>, void>::type eval_fmod(T& result, const T& x, const A& a)
  901. {
  902. typedef typename boost::multiprecision::detail::canonical<A, T>::type canonical_type;
  903. typedef typename mpl::if_<is_same<A, canonical_type>, T, canonical_type>::type cast_type;
  904. cast_type c;
  905. c = a;
  906. eval_fmod(result, x, c);
  907. }
  908. template<class T, class A>
  909. inline typename enable_if<is_arithmetic<A>, void>::type eval_fmod(T& result, const A& x, const T& a)
  910. {
  911. typedef typename boost::multiprecision::detail::canonical<A, T>::type canonical_type;
  912. typedef typename mpl::if_<is_same<A, canonical_type>, T, canonical_type>::type cast_type;
  913. cast_type c;
  914. c = x;
  915. eval_fmod(result, c, a);
  916. }
  917. template <class T>
  918. inline void eval_trunc(T& result, const T& a)
  919. {
  920. BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The trunc function is only valid for floating point types.");
  921. int c = eval_fpclassify(a);
  922. if(c == (int)FP_NAN || c == (int)FP_INFINITE)
  923. {
  924. result = boost::math::policies::raise_rounding_error("boost::multiprecision::trunc<%1%>(%1%)", 0, number<T>(a), number<T>(a), boost::math::policies::policy<>()).backend();
  925. return;
  926. }
  927. if(eval_get_sign(a) < 0)
  928. eval_ceil(result, a);
  929. else
  930. eval_floor(result, a);
  931. }
  932. template <class T>
  933. inline void eval_round(T& result, const T& a)
  934. {
  935. BOOST_STATIC_ASSERT_MSG(number_category<T>::value == number_kind_floating_point, "The round function is only valid for floating point types.");
  936. typedef typename boost::multiprecision::detail::canonical<float, T>::type fp_type;
  937. int c = eval_fpclassify(a);
  938. if((c == (int)FP_NAN) || (c == (int)FP_INFINITE))
  939. {
  940. result = boost::math::policies::raise_rounding_error("boost::multiprecision::round<%1%>(%1%)", 0, number<T>(a), number<T>(a), boost::math::policies::policy<>()).backend();
  941. return;
  942. }
  943. if(eval_get_sign(a) < 0)
  944. {
  945. eval_subtract(result, a, fp_type(0.5f));
  946. eval_ceil(result, result);
  947. }
  948. else
  949. {
  950. eval_add(result, a, fp_type(0.5f));
  951. eval_floor(result, result);
  952. }
  953. }
  954. template <class B>
  955. void eval_lcm(B& result, const B& a, const B& b);
  956. template <class B>
  957. void eval_gcd(B& result, const B& a, const B& b);
  958. template <class T, class Arithmetic>
  959. inline typename enable_if<is_integral<Arithmetic> >::type eval_gcd(T& result, const T& a, const Arithmetic& b)
  960. {
  961. typedef typename boost::multiprecision::detail::canonical<Arithmetic, T>::type si_type;
  962. using default_ops::eval_gcd;
  963. T t;
  964. t = static_cast<si_type>(b);
  965. eval_gcd(result, a, t);
  966. }
  967. template <class T, class Arithmetic>
  968. inline typename enable_if<is_integral<Arithmetic> >::type eval_gcd(T& result, const Arithmetic& a, const T& b)
  969. {
  970. eval_gcd(result, b, a);
  971. }
  972. template <class T, class Arithmetic>
  973. inline typename enable_if<is_integral<Arithmetic> >::type eval_lcm(T& result, const T& a, const Arithmetic& b)
  974. {
  975. typedef typename boost::multiprecision::detail::canonical<Arithmetic, T>::type si_type;
  976. using default_ops::eval_lcm;
  977. T t;
  978. t = static_cast<si_type>(b);
  979. eval_lcm(result, a, t);
  980. }
  981. template <class T, class Arithmetic>
  982. inline typename enable_if<is_integral<Arithmetic> >::type eval_lcm(T& result, const Arithmetic& a, const T& b)
  983. {
  984. eval_lcm(result, b, a);
  985. }
  986. template <class T>
  987. inline unsigned eval_lsb(const T& val)
  988. {
  989. typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
  990. int c = eval_get_sign(val);
  991. if(c == 0)
  992. {
  993. BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
  994. }
  995. if(c < 0)
  996. {
  997. BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
  998. }
  999. unsigned result = 0;
  1000. T mask, t;
  1001. mask = ui_type(1);
  1002. do
  1003. {
  1004. eval_bitwise_and(t, mask, val);
  1005. ++result;
  1006. eval_left_shift(mask, 1);
  1007. }
  1008. while(eval_is_zero(t));
  1009. return --result;
  1010. }
  1011. template <class T>
  1012. inline int eval_msb(const T& val)
  1013. {
  1014. int c = eval_get_sign(val);
  1015. if(c == 0)
  1016. {
  1017. BOOST_THROW_EXCEPTION(std::range_error("No bits were set in the operand."));
  1018. }
  1019. if(c < 0)
  1020. {
  1021. BOOST_THROW_EXCEPTION(std::range_error("Testing individual bits in negative values is not supported - results are undefined."));
  1022. }
  1023. //
  1024. // This implementation is really really rubbish - it does
  1025. // a linear scan for the most-significant-bit. We should really
  1026. // do a binary search, but as none of our backends actually needs
  1027. // this implementation, we'll leave it for now. In fact for most
  1028. // backends it's likely that there will always be a more efficient
  1029. // native implementation possible.
  1030. //
  1031. unsigned result = 0;
  1032. T t(val);
  1033. while(!eval_is_zero(t))
  1034. {
  1035. eval_right_shift(t, 1);
  1036. ++result;
  1037. }
  1038. return --result;
  1039. }
  1040. template <class T>
  1041. inline bool eval_bit_test(const T& val, unsigned index)
  1042. {
  1043. typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
  1044. T mask, t;
  1045. mask = ui_type(1);
  1046. eval_left_shift(mask, index);
  1047. eval_bitwise_and(t, mask, val);
  1048. return !eval_is_zero(t);
  1049. }
  1050. template <class T>
  1051. inline void eval_bit_set(T& val, unsigned index)
  1052. {
  1053. typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
  1054. T mask;
  1055. mask = ui_type(1);
  1056. eval_left_shift(mask, index);
  1057. eval_bitwise_or(val, mask);
  1058. }
  1059. template <class T>
  1060. inline void eval_bit_flip(T& val, unsigned index)
  1061. {
  1062. typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
  1063. T mask;
  1064. mask = ui_type(1);
  1065. eval_left_shift(mask, index);
  1066. eval_bitwise_xor(val, mask);
  1067. }
  1068. template <class T>
  1069. inline void eval_bit_unset(T& val, unsigned index)
  1070. {
  1071. typedef typename boost::multiprecision::detail::canonical<unsigned, T>::type ui_type;
  1072. T mask, t;
  1073. mask = ui_type(1);
  1074. eval_left_shift(mask, index);
  1075. eval_bitwise_and(t, mask, val);
  1076. if(!eval_is_zero(t))
  1077. eval_bitwise_xor(val, mask);
  1078. }
  1079. template <class B>
  1080. void eval_integer_sqrt(B& s, B& r, const B& x)
  1081. {
  1082. //
  1083. // This is slow bit-by-bit integer square root, see for example
  1084. // http://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Binary_numeral_system_.28base_2.29
  1085. // There are better methods such as http://hal.inria.fr/docs/00/07/28/54/PDF/RR-3805.pdf
  1086. // and http://hal.inria.fr/docs/00/07/21/13/PDF/RR-4475.pdf which should be implemented
  1087. // at some point.
  1088. //
  1089. typedef typename boost::multiprecision::detail::canonical<unsigned char, B>::type ui_type;
  1090. s = ui_type(0u);
  1091. if(eval_get_sign(x) == 0)
  1092. {
  1093. r = ui_type(0u);
  1094. return;
  1095. }
  1096. int g = eval_msb(x);
  1097. if(g == 0)
  1098. {
  1099. r = ui_type(1);
  1100. return;
  1101. }
  1102. B t;
  1103. r = x;
  1104. g /= 2;
  1105. int org_g = g;
  1106. eval_bit_set(s, g);
  1107. eval_bit_set(t, 2 * g);
  1108. eval_subtract(r, x, t);
  1109. --g;
  1110. if(eval_get_sign(r) == 0)
  1111. return;
  1112. int msbr = eval_msb(r);
  1113. do
  1114. {
  1115. if(msbr >= org_g + g + 1)
  1116. {
  1117. t = s;
  1118. eval_left_shift(t, g + 1);
  1119. eval_bit_set(t, 2 * g);
  1120. if(t.compare(r) <= 0)
  1121. {
  1122. eval_bit_set(s, g);
  1123. eval_subtract(r, t);
  1124. if(eval_get_sign(r) == 0)
  1125. return;
  1126. msbr = eval_msb(r);
  1127. }
  1128. }
  1129. --g;
  1130. }
  1131. while(g >= 0);
  1132. }
  1133. //
  1134. // These have to implemented by the backend, declared here so that our macro generated code compiles OK.
  1135. //
  1136. template <class T>
  1137. typename enable_if_c<sizeof(T) == 0>::type eval_floor();
  1138. template <class T>
  1139. typename enable_if_c<sizeof(T) == 0>::type eval_ceil();
  1140. template <class T>
  1141. typename enable_if_c<sizeof(T) == 0>::type eval_trunc();
  1142. template <class T>
  1143. typename enable_if_c<sizeof(T) == 0>::type eval_sqrt();
  1144. template <class T>
  1145. typename enable_if_c<sizeof(T) == 0>::type eval_ldexp();
  1146. template <class T>
  1147. typename enable_if_c<sizeof(T) == 0>::type eval_frexp();
  1148. //
  1149. // eval_logb and eval_scalbn simply assume base 2 and forward to
  1150. // eval_ldexp and eval_frexp:
  1151. //
  1152. template <class B>
  1153. inline typename B::exponent_type eval_ilogb(const B& val)
  1154. {
  1155. BOOST_STATIC_ASSERT_MSG(!std::numeric_limits<number<B> >::is_specialized || (std::numeric_limits<number<B> >::radix == 2), "The default implementation of ilogb requires a base 2 number type");
  1156. typename B::exponent_type e;
  1157. B result;
  1158. eval_frexp(result, val, &e);
  1159. return e - 1;
  1160. }
  1161. template <class B>
  1162. inline void eval_logb(B& result, const B& val)
  1163. {
  1164. typedef typename boost::mpl::if_c<boost::is_same<boost::intmax_t, long>::value, boost::long_long_type, boost::intmax_t>::type max_t;
  1165. result = static_cast<max_t>(eval_ilogb(val));
  1166. }
  1167. template <class B, class A>
  1168. inline void eval_scalbn(B& result, const B& val, A e)
  1169. {
  1170. BOOST_STATIC_ASSERT_MSG(!std::numeric_limits<number<B> >::is_specialized || (std::numeric_limits<number<B> >::radix == 2), "The default implementation of scalbn requires a base 2 number type");
  1171. eval_ldexp(result, val, static_cast<typename B::exponent_type>(e));
  1172. }
  1173. //
  1174. // These functions are implemented in separate files, but expanded inline here,
  1175. // DO NOT CHANGE THE ORDER OF THESE INCLUDES:
  1176. //
  1177. #include <boost/multiprecision/detail/functions/constants.hpp>
  1178. #include <boost/multiprecision/detail/functions/pow.hpp>
  1179. #include <boost/multiprecision/detail/functions/trig.hpp>
  1180. }
  1181. } // namespace multiprecision
  1182. namespace math{
  1183. //
  1184. // Default versions of floating point classification routines:
  1185. //
  1186. template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
  1187. inline int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
  1188. {
  1189. using multiprecision::default_ops::eval_fpclassify;
  1190. return eval_fpclassify(arg.backend());
  1191. }
  1192. template <class tag, class A1, class A2, class A3, class A4>
  1193. inline int fpclassify BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
  1194. {
  1195. typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
  1196. return (fpclassify)(value_type(arg));
  1197. }
  1198. template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
  1199. inline bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
  1200. {
  1201. int v = (fpclassify)(arg);
  1202. return (v != (int)FP_INFINITE) && (v != (int)FP_NAN);
  1203. }
  1204. template <class tag, class A1, class A2, class A3, class A4>
  1205. inline bool isfinite BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
  1206. {
  1207. typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
  1208. return (isfinite)(value_type(arg));
  1209. }
  1210. template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
  1211. inline bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
  1212. {
  1213. return (fpclassify)(arg) == (int)FP_NAN;
  1214. }
  1215. template <class tag, class A1, class A2, class A3, class A4>
  1216. inline bool isnan BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
  1217. {
  1218. typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
  1219. return (isnan)(value_type(arg));
  1220. }
  1221. template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
  1222. inline bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
  1223. {
  1224. return (fpclassify)(arg) == (int)FP_INFINITE;
  1225. }
  1226. template <class tag, class A1, class A2, class A3, class A4>
  1227. inline bool isinf BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
  1228. {
  1229. typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
  1230. return (isinf)(value_type(arg));
  1231. }
  1232. template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
  1233. inline bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::number<Backend, ExpressionTemplates>& arg)
  1234. {
  1235. return (fpclassify)(arg) == (int)FP_NORMAL;
  1236. }
  1237. template <class tag, class A1, class A2, class A3, class A4>
  1238. inline bool isnormal BOOST_PREVENT_MACRO_SUBSTITUTION(const multiprecision::detail::expression<tag, A1, A2, A3, A4>& arg)
  1239. {
  1240. typedef typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type value_type;
  1241. return (isnormal)(value_type(arg));
  1242. }
  1243. } // namespace math
  1244. namespace multiprecision{
  1245. template <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
  1246. inline number<B1, ET1>& add(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
  1247. {
  1248. BOOST_STATIC_ASSERT_MSG((is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
  1249. BOOST_STATIC_ASSERT_MSG((is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
  1250. using default_ops::eval_add;
  1251. eval_add(result.backend(), a.backend(), b.backend());
  1252. return result;
  1253. }
  1254. template <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
  1255. inline number<B1, ET1>& subtract(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
  1256. {
  1257. BOOST_STATIC_ASSERT_MSG((is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
  1258. BOOST_STATIC_ASSERT_MSG((is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
  1259. using default_ops::eval_subtract;
  1260. eval_subtract(result.backend(), a.backend(), b.backend());
  1261. return result;
  1262. }
  1263. template <class B1, class B2, class B3, expression_template_option ET1, expression_template_option ET2, expression_template_option ET3>
  1264. inline number<B1, ET1>& multiply(number<B1, ET1>& result, const number<B2, ET2>& a, const number<B3, ET3>& b)
  1265. {
  1266. BOOST_STATIC_ASSERT_MSG((is_convertible<B2, B1>::value), "No conversion to the target of a mixed precision addition exists");
  1267. BOOST_STATIC_ASSERT_MSG((is_convertible<B3, B1>::value), "No conversion to the target of a mixed precision addition exists");
  1268. using default_ops::eval_multiply;
  1269. eval_multiply(result.backend(), a.backend(), b.backend());
  1270. return result;
  1271. }
  1272. template <class B, expression_template_option ET, class I>
  1273. inline typename enable_if_c<is_integral<I>::value, number<B, ET>&>::type
  1274. add(number<B, ET>& result, const I& a, const I& b)
  1275. {
  1276. using default_ops::eval_add;
  1277. typedef typename detail::canonical<I, B>::type canonical_type;
  1278. eval_add(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
  1279. return result;
  1280. }
  1281. template <class B, expression_template_option ET, class I>
  1282. inline typename enable_if_c<is_integral<I>::value, number<B, ET>&>::type
  1283. subtract(number<B, ET>& result, const I& a, const I& b)
  1284. {
  1285. using default_ops::eval_subtract;
  1286. typedef typename detail::canonical<I, B>::type canonical_type;
  1287. eval_subtract(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
  1288. return result;
  1289. }
  1290. template <class B, expression_template_option ET, class I>
  1291. inline typename enable_if_c<is_integral<I>::value, number<B, ET>&>::type
  1292. multiply(number<B, ET>& result, const I& a, const I& b)
  1293. {
  1294. using default_ops::eval_multiply;
  1295. typedef typename detail::canonical<I, B>::type canonical_type;
  1296. eval_multiply(result.backend(), static_cast<canonical_type>(a), static_cast<canonical_type>(b));
  1297. return result;
  1298. }
  1299. template <class tag, class A1, class A2, class A3, class A4, class Policy>
  1300. inline typename detail::expression<tag, A1, A2, A3, A4>::result_type trunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
  1301. {
  1302. typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
  1303. return BOOST_MP_MOVE(trunc(number_type(v), pol));
  1304. }
  1305. template <class Backend, expression_template_option ExpressionTemplates, class Policy>
  1306. inline number<Backend, ExpressionTemplates> trunc(const number<Backend, ExpressionTemplates>& v, const Policy&)
  1307. {
  1308. using default_ops::eval_trunc;
  1309. number<Backend, ExpressionTemplates> result;
  1310. eval_trunc(result.backend(), v.backend());
  1311. return BOOST_MP_MOVE(result);
  1312. }
  1313. template <class tag, class A1, class A2, class A3, class A4, class Policy>
  1314. inline int itrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
  1315. {
  1316. typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
  1317. number_type r = trunc(v, pol);
  1318. if((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !(boost::math::isfinite)(v))
  1319. return boost::math::policies::raise_rounding_error("boost::multiprecision::itrunc<%1%>(%1%)", 0, number_type(v), 0, pol);
  1320. return r.template convert_to<int>();
  1321. }
  1322. template <class tag, class A1, class A2, class A3, class A4>
  1323. inline int itrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
  1324. {
  1325. return itrunc(v, boost::math::policies::policy<>());
  1326. }
  1327. template <class Backend, expression_template_option ExpressionTemplates, class Policy>
  1328. inline int itrunc(const number<Backend, ExpressionTemplates>& v, const Policy& pol)
  1329. {
  1330. number<Backend, ExpressionTemplates> r = trunc(v, pol);
  1331. if((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !(boost::math::isfinite)(v))
  1332. return boost::math::policies::raise_rounding_error("boost::multiprecision::itrunc<%1%>(%1%)", 0, v, 0, pol);
  1333. return r.template convert_to<int>();
  1334. }
  1335. template <class Backend, expression_template_option ExpressionTemplates>
  1336. inline int itrunc(const number<Backend, ExpressionTemplates>& v)
  1337. {
  1338. return itrunc(v, boost::math::policies::policy<>());
  1339. }
  1340. template <class tag, class A1, class A2, class A3, class A4, class Policy>
  1341. inline long ltrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
  1342. {
  1343. typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
  1344. number_type r = trunc(v, pol);
  1345. if((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !(boost::math::isfinite)(v))
  1346. return boost::math::policies::raise_rounding_error("boost::multiprecision::ltrunc<%1%>(%1%)", 0, number_type(v), 0L, pol);
  1347. return r.template convert_to<long>();
  1348. }
  1349. template <class tag, class A1, class A2, class A3, class A4>
  1350. inline long ltrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
  1351. {
  1352. return ltrunc(v, boost::math::policies::policy<>());
  1353. }
  1354. template <class T, expression_template_option ExpressionTemplates, class Policy>
  1355. inline long ltrunc(const number<T, ExpressionTemplates>& v, const Policy& pol)
  1356. {
  1357. number<T, ExpressionTemplates> r = trunc(v, pol);
  1358. if((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !(boost::math::isfinite)(v))
  1359. return boost::math::policies::raise_rounding_error("boost::multiprecision::ltrunc<%1%>(%1%)", 0, v, 0L, pol);
  1360. return r.template convert_to<long>();
  1361. }
  1362. template <class T, expression_template_option ExpressionTemplates>
  1363. inline long ltrunc(const number<T, ExpressionTemplates>& v)
  1364. {
  1365. return ltrunc(v, boost::math::policies::policy<>());
  1366. }
  1367. #ifndef BOOST_NO_LONG_LONG
  1368. template <class tag, class A1, class A2, class A3, class A4, class Policy>
  1369. inline boost::long_long_type lltrunc(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
  1370. {
  1371. typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
  1372. number_type r = trunc(v, pol);
  1373. if((r > (std::numeric_limits<boost::long_long_type>::max)()) || r < (std::numeric_limits<boost::long_long_type>::min)() || !(boost::math::isfinite)(v))
  1374. return boost::math::policies::raise_rounding_error("boost::multiprecision::lltrunc<%1%>(%1%)", 0, number_type(v), 0LL, pol);
  1375. return r.template convert_to<boost::long_long_type>();
  1376. }
  1377. template <class tag, class A1, class A2, class A3, class A4>
  1378. inline boost::long_long_type lltrunc(const detail::expression<tag, A1, A2, A3, A4>& v)
  1379. {
  1380. return lltrunc(v, boost::math::policies::policy<>());
  1381. }
  1382. template <class T, expression_template_option ExpressionTemplates, class Policy>
  1383. inline boost::long_long_type lltrunc(const number<T, ExpressionTemplates>& v, const Policy& pol)
  1384. {
  1385. number<T, ExpressionTemplates> r = trunc(v, pol);
  1386. if((r > (std::numeric_limits<boost::long_long_type>::max)()) || r < (std::numeric_limits<boost::long_long_type>::min)() || !(boost::math::isfinite)(v))
  1387. return boost::math::policies::raise_rounding_error("boost::multiprecision::lltrunc<%1%>(%1%)", 0, v, 0LL, pol);
  1388. return r.template convert_to<boost::long_long_type>();
  1389. }
  1390. template <class T, expression_template_option ExpressionTemplates>
  1391. inline boost::long_long_type lltrunc(const number<T, ExpressionTemplates>& v)
  1392. {
  1393. return lltrunc(v, boost::math::policies::policy<>());
  1394. }
  1395. #endif
  1396. template <class tag, class A1, class A2, class A3, class A4, class Policy>
  1397. inline typename detail::expression<tag, A1, A2, A3, A4>::result_type round(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
  1398. {
  1399. typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
  1400. return BOOST_MP_MOVE(round(static_cast<number_type>(v), pol));
  1401. }
  1402. template <class T, expression_template_option ExpressionTemplates, class Policy>
  1403. inline number<T, ExpressionTemplates> round(const number<T, ExpressionTemplates>& v, const Policy&)
  1404. {
  1405. using default_ops::eval_round;
  1406. number<T, ExpressionTemplates> result;
  1407. eval_round(result.backend(), v.backend());
  1408. return BOOST_MP_MOVE(result);
  1409. }
  1410. template <class tag, class A1, class A2, class A3, class A4, class Policy>
  1411. inline int iround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
  1412. {
  1413. typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
  1414. number_type r = round(v, pol);
  1415. if((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !(boost::math::isfinite)(v))
  1416. return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, number_type(v), 0, pol);
  1417. return r.template convert_to<int>();
  1418. }
  1419. template <class tag, class A1, class A2, class A3, class A4>
  1420. inline int iround(const detail::expression<tag, A1, A2, A3, A4>& v)
  1421. {
  1422. return iround(v, boost::math::policies::policy<>());
  1423. }
  1424. template <class T, expression_template_option ExpressionTemplates, class Policy>
  1425. inline int iround(const number<T, ExpressionTemplates>& v, const Policy& pol)
  1426. {
  1427. number<T, ExpressionTemplates> r = round(v, pol);
  1428. if((r > (std::numeric_limits<int>::max)()) || r < (std::numeric_limits<int>::min)() || !(boost::math::isfinite)(v))
  1429. return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, v, 0, pol);
  1430. return r.template convert_to<int>();
  1431. }
  1432. template <class T, expression_template_option ExpressionTemplates>
  1433. inline int iround(const number<T, ExpressionTemplates>& v)
  1434. {
  1435. return iround(v, boost::math::policies::policy<>());
  1436. }
  1437. template <class tag, class A1, class A2, class A3, class A4, class Policy>
  1438. inline long lround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
  1439. {
  1440. typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
  1441. number_type r = round(v, pol);
  1442. if((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !(boost::math::isfinite)(v))
  1443. return boost::math::policies::raise_rounding_error("boost::multiprecision::lround<%1%>(%1%)", 0, number_type(v), 0L, pol);
  1444. return r.template convert_to<long>();
  1445. }
  1446. template <class tag, class A1, class A2, class A3, class A4>
  1447. inline long lround(const detail::expression<tag, A1, A2, A3, A4>& v)
  1448. {
  1449. return lround(v, boost::math::policies::policy<>());
  1450. }
  1451. template <class T, expression_template_option ExpressionTemplates, class Policy>
  1452. inline long lround(const number<T, ExpressionTemplates>& v, const Policy& pol)
  1453. {
  1454. number<T, ExpressionTemplates> r = round(v, pol);
  1455. if((r > (std::numeric_limits<long>::max)()) || r < (std::numeric_limits<long>::min)() || !(boost::math::isfinite)(v))
  1456. return boost::math::policies::raise_rounding_error("boost::multiprecision::lround<%1%>(%1%)", 0, v, 0L, pol);
  1457. return r.template convert_to<long>();
  1458. }
  1459. template <class T, expression_template_option ExpressionTemplates>
  1460. inline long lround(const number<T, ExpressionTemplates>& v)
  1461. {
  1462. return lround(v, boost::math::policies::policy<>());
  1463. }
  1464. #ifndef BOOST_NO_LONG_LONG
  1465. template <class tag, class A1, class A2, class A3, class A4, class Policy>
  1466. inline boost::long_long_type llround(const detail::expression<tag, A1, A2, A3, A4>& v, const Policy& pol)
  1467. {
  1468. typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
  1469. number_type r = round(v, pol);
  1470. if((r > (std::numeric_limits<boost::long_long_type>::max)()) || r < (std::numeric_limits<boost::long_long_type>::min)() || !(boost::math::isfinite)(v))
  1471. return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, number_type(v), 0LL, pol);
  1472. return r.template convert_to<boost::long_long_type>();
  1473. }
  1474. template <class tag, class A1, class A2, class A3, class A4>
  1475. inline boost::long_long_type llround(const detail::expression<tag, A1, A2, A3, A4>& v)
  1476. {
  1477. return llround(v, boost::math::policies::policy<>());
  1478. }
  1479. template <class T, expression_template_option ExpressionTemplates, class Policy>
  1480. inline boost::long_long_type llround(const number<T, ExpressionTemplates>& v, const Policy& pol)
  1481. {
  1482. number<T, ExpressionTemplates> r = round(v, pol);
  1483. if((r > (std::numeric_limits<boost::long_long_type>::max)()) || r < (std::numeric_limits<boost::long_long_type>::min)() || !(boost::math::isfinite)(v))
  1484. return boost::math::policies::raise_rounding_error("boost::multiprecision::iround<%1%>(%1%)", 0, v, 0LL, pol);
  1485. return r.template convert_to<boost::long_long_type>();
  1486. }
  1487. template <class T, expression_template_option ExpressionTemplates>
  1488. inline boost::long_long_type llround(const number<T, ExpressionTemplates>& v)
  1489. {
  1490. return llround(v, boost::math::policies::policy<>());
  1491. }
  1492. #endif
  1493. //
  1494. // frexp does not return an expression template since we require the
  1495. // integer argument to be evaluated even if the returned value is
  1496. // not assigned to anything...
  1497. //
  1498. template <class T, expression_template_option ExpressionTemplates>
  1499. inline typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, short* pint)
  1500. {
  1501. using default_ops::eval_frexp;
  1502. number<T, ExpressionTemplates> result;
  1503. eval_frexp(result.backend(), v.backend(), pint);
  1504. return BOOST_MP_MOVE(result);
  1505. }
  1506. template <class tag, class A1, class A2, class A3, class A4>
  1507. inline typename enable_if_c<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
  1508. frexp(const detail::expression<tag, A1, A2, A3, A4>& v, short* pint)
  1509. {
  1510. typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
  1511. return BOOST_MP_MOVE(frexp(static_cast<number_type>(v), pint));
  1512. }
  1513. template <class T, expression_template_option ExpressionTemplates>
  1514. inline typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, int* pint)
  1515. {
  1516. using default_ops::eval_frexp;
  1517. number<T, ExpressionTemplates> result;
  1518. eval_frexp(result.backend(), v.backend(), pint);
  1519. return BOOST_MP_MOVE(result);
  1520. }
  1521. template <class tag, class A1, class A2, class A3, class A4>
  1522. inline typename enable_if_c<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
  1523. frexp(const detail::expression<tag, A1, A2, A3, A4>& v, int* pint)
  1524. {
  1525. typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
  1526. return BOOST_MP_MOVE(frexp(static_cast<number_type>(v), pint));
  1527. }
  1528. template <class T, expression_template_option ExpressionTemplates>
  1529. inline typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, long* pint)
  1530. {
  1531. using default_ops::eval_frexp;
  1532. number<T, ExpressionTemplates> result;
  1533. eval_frexp(result.backend(), v.backend(), pint);
  1534. return BOOST_MP_MOVE(result);
  1535. }
  1536. template <class tag, class A1, class A2, class A3, class A4>
  1537. inline typename enable_if_c<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
  1538. frexp(const detail::expression<tag, A1, A2, A3, A4>& v, long* pint)
  1539. {
  1540. typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
  1541. return BOOST_MP_MOVE(frexp(static_cast<number_type>(v), pint));
  1542. }
  1543. template <class T, expression_template_option ExpressionTemplates>
  1544. inline typename enable_if_c<number_category<T>::value == number_kind_floating_point, number<T, ExpressionTemplates> >::type frexp(const number<T, ExpressionTemplates>& v, boost::long_long_type* pint)
  1545. {
  1546. using default_ops::eval_frexp;
  1547. number<T, ExpressionTemplates> result;
  1548. eval_frexp(result.backend(), v.backend(), pint);
  1549. return BOOST_MP_MOVE(result);
  1550. }
  1551. template <class tag, class A1, class A2, class A3, class A4>
  1552. inline typename enable_if_c<number_category<typename detail::expression<tag, A1, A2, A3, A4>::result_type>::value == number_kind_floating_point, typename detail::expression<tag, A1, A2, A3, A4>::result_type>::type
  1553. frexp(const detail::expression<tag, A1, A2, A3, A4>& v, boost::long_long_type* pint)
  1554. {
  1555. typedef typename detail::expression<tag, A1, A2, A3, A4>::result_type number_type;
  1556. return BOOST_MP_MOVE(frexp(static_cast<number_type>(v), pint));
  1557. }
  1558. template <class B, expression_template_option ExpressionTemplates>
  1559. inline typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, ExpressionTemplates> >::type
  1560. sqrt(const number<B, ExpressionTemplates>& x)
  1561. {
  1562. using default_ops::eval_integer_sqrt;
  1563. number<B, ExpressionTemplates> s, r;
  1564. eval_integer_sqrt(s.backend(), r.backend(), x.backend());
  1565. return s;
  1566. }
  1567. template <class B, expression_template_option ExpressionTemplates>
  1568. inline typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, ExpressionTemplates> >::type
  1569. sqrt(const number<B, ExpressionTemplates>& x, number<B, ExpressionTemplates>& r)
  1570. {
  1571. using default_ops::eval_integer_sqrt;
  1572. number<B, ExpressionTemplates> s;
  1573. eval_integer_sqrt(s.backend(), r.backend(), x.backend());
  1574. return s;
  1575. }
  1576. #define UNARY_OP_FUNCTOR(func, category)\
  1577. namespace detail{\
  1578. template <class Backend> \
  1579. struct BOOST_JOIN(func, _funct)\
  1580. {\
  1581. void operator()(Backend& result, const Backend& arg)const\
  1582. {\
  1583. using default_ops::BOOST_JOIN(eval_,func);\
  1584. BOOST_JOIN(eval_,func)(result, arg);\
  1585. }\
  1586. };\
  1587. \
  1588. }\
  1589. \
  1590. template <class tag, class A1, class A2, class A3, class A4> \
  1591. inline typename enable_if_c<number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category,\
  1592. detail::expression<\
  1593. detail::function\
  1594. , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
  1595. , detail::expression<tag, A1, A2, A3, A4> > \
  1596. >::type \
  1597. func(const detail::expression<tag, A1, A2, A3, A4>& arg)\
  1598. {\
  1599. return detail::expression<\
  1600. detail::function\
  1601. , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
  1602. , detail::expression<tag, A1, A2, A3, A4> \
  1603. > (\
  1604. detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>() \
  1605. , arg \
  1606. );\
  1607. }\
  1608. template <class Backend> \
  1609. inline typename enable_if_c<number_category<Backend>::value == category,\
  1610. detail::expression<\
  1611. detail::function\
  1612. , detail::BOOST_JOIN(func, _funct)<Backend> \
  1613. , number<Backend, et_on> > \
  1614. >::type \
  1615. func(const number<Backend, et_on>& arg)\
  1616. {\
  1617. return detail::expression<\
  1618. detail::function\
  1619. , detail::BOOST_JOIN(func, _funct)<Backend> \
  1620. , number<Backend, et_on> \
  1621. >(\
  1622. detail::BOOST_JOIN(func, _funct)<Backend>() \
  1623. , arg \
  1624. );\
  1625. }\
  1626. template <class Backend> \
  1627. inline typename boost::enable_if_c<\
  1628. boost::multiprecision::number_category<Backend>::value == category,\
  1629. number<Backend, et_off> >::type \
  1630. func(const number<Backend, et_off>& arg)\
  1631. {\
  1632. number<Backend, et_off> result;\
  1633. using default_ops::BOOST_JOIN(eval_,func);\
  1634. BOOST_JOIN(eval_,func)(result.backend(), arg.backend());\
  1635. return BOOST_MP_MOVE(result);\
  1636. }
  1637. #define BINARY_OP_FUNCTOR(func, category)\
  1638. namespace detail{\
  1639. template <class Backend> \
  1640. struct BOOST_JOIN(func, _funct)\
  1641. {\
  1642. void operator()(Backend& result, const Backend& arg, const Backend& a)const\
  1643. {\
  1644. using default_ops:: BOOST_JOIN(eval_,func);\
  1645. BOOST_JOIN(eval_,func)(result, arg, a);\
  1646. }\
  1647. template <class Arithmetic> \
  1648. void operator()(Backend& result, const Backend& arg, const Arithmetic& a)const\
  1649. {\
  1650. using default_ops:: BOOST_JOIN(eval_,func);\
  1651. BOOST_JOIN(eval_,func)(result, arg, a);\
  1652. }\
  1653. template <class Arithmetic> \
  1654. void operator()(Backend& result, const Arithmetic& arg, const Backend& a)const\
  1655. {\
  1656. using default_ops:: BOOST_JOIN(eval_,func);\
  1657. BOOST_JOIN(eval_,func)(result, arg, a);\
  1658. }\
  1659. };\
  1660. \
  1661. }\
  1662. template <class Backend> \
  1663. inline typename enable_if_c<number_category<Backend>::value == category,\
  1664. detail::expression<\
  1665. detail::function\
  1666. , detail::BOOST_JOIN(func, _funct)<Backend> \
  1667. , number<Backend, et_on> \
  1668. , number<Backend, et_on> > \
  1669. >::type \
  1670. func(const number<Backend, et_on>& arg, const number<Backend, et_on>& a)\
  1671. {\
  1672. return detail::expression<\
  1673. detail::function\
  1674. , detail::BOOST_JOIN(func, _funct)<Backend> \
  1675. , number<Backend, et_on> \
  1676. , number<Backend, et_on> \
  1677. >(\
  1678. detail::BOOST_JOIN(func, _funct)<Backend>() \
  1679. , arg,\
  1680. a\
  1681. );\
  1682. }\
  1683. template <class Backend, class tag, class A1, class A2, class A3, class A4> \
  1684. inline typename enable_if_c<\
  1685. (number_category<Backend>::value == category) && (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category),\
  1686. detail::expression<\
  1687. detail::function\
  1688. , detail::BOOST_JOIN(func, _funct)<Backend> \
  1689. , number<Backend, et_on> \
  1690. , detail::expression<tag, A1, A2, A3, A4> > \
  1691. >::type \
  1692. func(const number<Backend, et_on>& arg, const detail::expression<tag, A1, A2, A3, A4>& a)\
  1693. {\
  1694. return detail::expression<\
  1695. detail::function\
  1696. , detail::BOOST_JOIN(func, _funct)<Backend> \
  1697. , number<Backend, et_on> \
  1698. , detail::expression<tag, A1, A2, A3, A4> \
  1699. >(\
  1700. detail::BOOST_JOIN(func, _funct)<Backend>() \
  1701. , arg,\
  1702. a\
  1703. );\
  1704. }\
  1705. template <class tag, class A1, class A2, class A3, class A4, class Backend> \
  1706. inline typename enable_if_c<\
  1707. (number_category<Backend>::value == category) && (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category),\
  1708. detail::expression<\
  1709. detail::function\
  1710. , detail::BOOST_JOIN(func, _funct)<Backend> \
  1711. , detail::expression<tag, A1, A2, A3, A4> \
  1712. , number<Backend, et_on> > \
  1713. >::type \
  1714. func(const detail::expression<tag, A1, A2, A3, A4>& arg, const number<Backend, et_on>& a)\
  1715. {\
  1716. return detail::expression<\
  1717. detail::function\
  1718. , detail::BOOST_JOIN(func, _funct)<Backend> \
  1719. , detail::expression<tag, A1, A2, A3, A4> \
  1720. , number<Backend, et_on> \
  1721. >(\
  1722. detail::BOOST_JOIN(func, _funct)<Backend>() \
  1723. , arg,\
  1724. a\
  1725. );\
  1726. }\
  1727. template <class tag, class A1, class A2, class A3, class A4, class tagb, class A1b, class A2b, class A3b, class A4b> \
  1728. inline typename enable_if_c<\
  1729. (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category) && (number_category<detail::expression<tagb, A1b, A2b, A3b, A4b> >::value == category),\
  1730. detail::expression<\
  1731. detail::function\
  1732. , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
  1733. , detail::expression<tag, A1, A2, A3, A4> \
  1734. , detail::expression<tagb, A1b, A2b, A3b, A4b> > \
  1735. >::type \
  1736. func(const detail::expression<tag, A1, A2, A3, A4>& arg, const detail::expression<tagb, A1b, A2b, A3b, A4b>& a)\
  1737. {\
  1738. return detail::expression<\
  1739. detail::function\
  1740. , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
  1741. , detail::expression<tag, A1, A2, A3, A4> \
  1742. , detail::expression<tagb, A1b, A2b, A3b, A4b> \
  1743. >(\
  1744. detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>() \
  1745. , arg,\
  1746. a\
  1747. );\
  1748. }\
  1749. template <class Backend, class Arithmetic> \
  1750. inline typename enable_if_c<\
  1751. is_arithmetic<Arithmetic>::value && (number_category<Backend>::value == category),\
  1752. detail::expression<\
  1753. detail::function\
  1754. , detail::BOOST_JOIN(func, _funct)<Backend> \
  1755. , number<Backend, et_on> \
  1756. , Arithmetic\
  1757. > \
  1758. >::type \
  1759. func(const number<Backend, et_on>& arg, const Arithmetic& a)\
  1760. {\
  1761. return detail::expression<\
  1762. detail::function\
  1763. , detail::BOOST_JOIN(func, _funct)<Backend> \
  1764. , number<Backend, et_on> \
  1765. , Arithmetic\
  1766. >(\
  1767. detail::BOOST_JOIN(func, _funct)<Backend>() \
  1768. , arg,\
  1769. a\
  1770. );\
  1771. }\
  1772. template <class tag, class A1, class A2, class A3, class A4, class Arithmetic> \
  1773. inline typename enable_if_c<\
  1774. is_arithmetic<Arithmetic>::value && (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category),\
  1775. detail::expression<\
  1776. detail::function\
  1777. , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
  1778. , detail::expression<tag, A1, A2, A3, A4> \
  1779. , Arithmetic\
  1780. > \
  1781. >::type \
  1782. func(const detail::expression<tag, A1, A2, A3, A4>& arg, const Arithmetic& a)\
  1783. {\
  1784. return detail::expression<\
  1785. detail::function\
  1786. , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
  1787. , detail::expression<tag, A1, A2, A3, A4> \
  1788. , Arithmetic\
  1789. >(\
  1790. detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>() \
  1791. , arg,\
  1792. a\
  1793. );\
  1794. }\
  1795. template <class Backend, class Arithmetic> \
  1796. inline typename enable_if_c<\
  1797. is_arithmetic<Arithmetic>::value && (number_category<Backend>::value == category),\
  1798. detail::expression<\
  1799. detail::function\
  1800. , detail::BOOST_JOIN(func, _funct)<Backend> \
  1801. , Arithmetic \
  1802. , number<Backend, et_on> \
  1803. > \
  1804. >::type \
  1805. func(const Arithmetic& arg, const number<Backend, et_on>& a)\
  1806. {\
  1807. return detail::expression<\
  1808. detail::function\
  1809. , detail::BOOST_JOIN(func, _funct)<Backend> \
  1810. , Arithmetic \
  1811. , number<Backend, et_on> \
  1812. >(\
  1813. detail::BOOST_JOIN(func, _funct)<Backend>() \
  1814. , arg,\
  1815. a\
  1816. );\
  1817. }\
  1818. template <class tag, class A1, class A2, class A3, class A4, class Arithmetic> \
  1819. inline typename enable_if_c<\
  1820. is_arithmetic<Arithmetic>::value && (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category),\
  1821. detail::expression<\
  1822. detail::function\
  1823. , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
  1824. , Arithmetic \
  1825. , detail::expression<tag, A1, A2, A3, A4> \
  1826. > \
  1827. >::type \
  1828. func(const Arithmetic& arg, const detail::expression<tag, A1, A2, A3, A4>& a)\
  1829. {\
  1830. return detail::expression<\
  1831. detail::function\
  1832. , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
  1833. , Arithmetic \
  1834. , detail::expression<tag, A1, A2, A3, A4> \
  1835. >(\
  1836. detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>() \
  1837. , arg,\
  1838. a\
  1839. );\
  1840. }\
  1841. template <class Backend> \
  1842. inline typename enable_if_c<(number_category<Backend>::value == category),\
  1843. number<Backend, et_off> >::type \
  1844. func(const number<Backend, et_off>& arg, const number<Backend, et_off>& a)\
  1845. {\
  1846. number<Backend, et_off> result;\
  1847. using default_ops:: BOOST_JOIN(eval_,func);\
  1848. BOOST_JOIN(eval_,func)(result.backend(), arg.backend(), a.backend());\
  1849. return BOOST_MP_MOVE(result);\
  1850. }\
  1851. template <class Backend, class Arithmetic> \
  1852. inline typename enable_if_c<\
  1853. is_arithmetic<Arithmetic>::value && (number_category<Backend>::value == category),\
  1854. number<Backend, et_off> \
  1855. >::type \
  1856. func(const number<Backend, et_off>& arg, const Arithmetic& a)\
  1857. {\
  1858. typedef typename detail::canonical<Arithmetic, Backend>::type canonical_type;\
  1859. number<Backend, et_off> result;\
  1860. using default_ops:: BOOST_JOIN(eval_,func);\
  1861. BOOST_JOIN(eval_,func)(result.backend(), arg.backend(), static_cast<canonical_type>(a));\
  1862. return BOOST_MP_MOVE(result);\
  1863. }\
  1864. template <class Backend, class Arithmetic> \
  1865. inline typename enable_if_c<\
  1866. is_arithmetic<Arithmetic>::value && (number_category<Backend>::value == category),\
  1867. number<Backend, et_off> \
  1868. >::type \
  1869. func(const Arithmetic& a, const number<Backend, et_off>& arg)\
  1870. {\
  1871. typedef typename detail::canonical<Arithmetic, Backend>::type canonical_type;\
  1872. number<Backend, et_off> result;\
  1873. using default_ops:: BOOST_JOIN(eval_,func);\
  1874. BOOST_JOIN(eval_,func)(result.backend(), static_cast<canonical_type>(a), arg.backend());\
  1875. return BOOST_MP_MOVE(result);\
  1876. }\
  1877. #define HETERO_BINARY_OP_FUNCTOR_B(func, Arg2, category)\
  1878. template <class tag, class A1, class A2, class A3, class A4> \
  1879. inline typename enable_if_c<\
  1880. (number_category<detail::expression<tag, A1, A2, A3, A4> >::value == category),\
  1881. detail::expression<\
  1882. detail::function\
  1883. , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
  1884. , detail::expression<tag, A1, A2, A3, A4> \
  1885. , Arg2> \
  1886. >::type \
  1887. func(const detail::expression<tag, A1, A2, A3, A4>& arg, Arg2 const& a)\
  1888. {\
  1889. return detail::expression<\
  1890. detail::function\
  1891. , detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type> \
  1892. , detail::expression<tag, A1, A2, A3, A4> \
  1893. , Arg2\
  1894. >(\
  1895. detail::BOOST_JOIN(func, _funct)<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>() \
  1896. , arg, a \
  1897. );\
  1898. }\
  1899. template <class Backend> \
  1900. inline typename enable_if_c<\
  1901. (number_category<Backend>::value == category),\
  1902. detail::expression<\
  1903. detail::function\
  1904. , detail::BOOST_JOIN(func, _funct)<Backend> \
  1905. , number<Backend, et_on> \
  1906. , Arg2> \
  1907. >::type \
  1908. func(const number<Backend, et_on>& arg, Arg2 const& a)\
  1909. {\
  1910. return detail::expression<\
  1911. detail::function\
  1912. , detail::BOOST_JOIN(func, _funct)<Backend> \
  1913. , number<Backend, et_on> \
  1914. , Arg2\
  1915. >(\
  1916. detail::BOOST_JOIN(func, _funct)<Backend>() \
  1917. , arg,\
  1918. a\
  1919. );\
  1920. }\
  1921. template <class Backend> \
  1922. inline typename enable_if_c<\
  1923. (number_category<Backend>::value == category),\
  1924. number<Backend, et_off> >::type \
  1925. func(const number<Backend, et_off>& arg, Arg2 const& a)\
  1926. {\
  1927. number<Backend, et_off> result;\
  1928. using default_ops:: BOOST_JOIN(eval_,func);\
  1929. BOOST_JOIN(eval_,func)(result.backend(), arg.backend(), a);\
  1930. return BOOST_MP_MOVE(result);\
  1931. }\
  1932. #define HETERO_BINARY_OP_FUNCTOR(func, Arg2, category)\
  1933. namespace detail{\
  1934. template <class Backend> \
  1935. struct BOOST_JOIN(func, _funct)\
  1936. {\
  1937. template <class Arg>\
  1938. void operator()(Backend& result, Backend const& arg, Arg a)const\
  1939. {\
  1940. using default_ops:: BOOST_JOIN(eval_,func);\
  1941. BOOST_JOIN(eval_,func)(result, arg, a);\
  1942. }\
  1943. };\
  1944. \
  1945. }\
  1946. \
  1947. HETERO_BINARY_OP_FUNCTOR_B(func, Arg2, category)
  1948. namespace detail{
  1949. template <class Backend>
  1950. struct abs_funct
  1951. {
  1952. void operator()(Backend& result, const Backend& arg)const
  1953. {
  1954. using default_ops::eval_abs;
  1955. eval_abs(result, arg);
  1956. }
  1957. };
  1958. }
  1959. template <class tag, class A1, class A2, class A3, class A4>
  1960. inline detail::expression<
  1961. detail::function
  1962. , detail::abs_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>
  1963. , detail::expression<tag, A1, A2, A3, A4> >
  1964. abs(const detail::expression<tag, A1, A2, A3, A4>& arg)
  1965. {
  1966. return detail::expression<
  1967. detail::function
  1968. , detail::abs_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>
  1969. , detail::expression<tag, A1, A2, A3, A4>
  1970. > (
  1971. detail::abs_funct<typename detail::backend_type<detail::expression<tag, A1, A2, A3, A4> >::type>()
  1972. , arg
  1973. );
  1974. }
  1975. template <class Backend>
  1976. inline detail::expression<
  1977. detail::function
  1978. , detail::abs_funct<Backend>
  1979. , number<Backend, et_on> >
  1980. abs(const number<Backend, et_on>& arg)
  1981. {
  1982. return detail::expression<
  1983. detail::function
  1984. , detail::abs_funct<Backend>
  1985. , number<Backend, et_on>
  1986. >(
  1987. detail::abs_funct<Backend>()
  1988. , arg
  1989. );
  1990. }
  1991. template <class Backend>
  1992. inline number<Backend, et_off>
  1993. abs(const number<Backend, et_off>& arg)
  1994. {
  1995. number<Backend, et_off> result;
  1996. using default_ops::eval_abs;
  1997. eval_abs(result.backend(), arg.backend());
  1998. return BOOST_MP_MOVE(result);
  1999. }
  2000. UNARY_OP_FUNCTOR(fabs, number_kind_floating_point)
  2001. UNARY_OP_FUNCTOR(sqrt, number_kind_floating_point)
  2002. UNARY_OP_FUNCTOR(floor, number_kind_floating_point)
  2003. UNARY_OP_FUNCTOR(ceil, number_kind_floating_point)
  2004. UNARY_OP_FUNCTOR(trunc, number_kind_floating_point)
  2005. UNARY_OP_FUNCTOR(round, number_kind_floating_point)
  2006. UNARY_OP_FUNCTOR(exp, number_kind_floating_point)
  2007. UNARY_OP_FUNCTOR(log, number_kind_floating_point)
  2008. UNARY_OP_FUNCTOR(log10, number_kind_floating_point)
  2009. UNARY_OP_FUNCTOR(cos, number_kind_floating_point)
  2010. UNARY_OP_FUNCTOR(sin, number_kind_floating_point)
  2011. UNARY_OP_FUNCTOR(tan, number_kind_floating_point)
  2012. UNARY_OP_FUNCTOR(asin, number_kind_floating_point)
  2013. UNARY_OP_FUNCTOR(acos, number_kind_floating_point)
  2014. UNARY_OP_FUNCTOR(atan, number_kind_floating_point)
  2015. UNARY_OP_FUNCTOR(cosh, number_kind_floating_point)
  2016. UNARY_OP_FUNCTOR(sinh, number_kind_floating_point)
  2017. UNARY_OP_FUNCTOR(tanh, number_kind_floating_point)
  2018. HETERO_BINARY_OP_FUNCTOR(ldexp, short, number_kind_floating_point)
  2019. //HETERO_BINARY_OP_FUNCTOR(frexp, short*, number_kind_floating_point)
  2020. HETERO_BINARY_OP_FUNCTOR_B(ldexp, int, number_kind_floating_point)
  2021. //HETERO_BINARY_OP_FUNCTOR_B(frexp, int*, number_kind_floating_point)
  2022. HETERO_BINARY_OP_FUNCTOR_B(ldexp, long, number_kind_floating_point)
  2023. //HETERO_BINARY_OP_FUNCTOR_B(frexp, long*, number_kind_floating_point)
  2024. HETERO_BINARY_OP_FUNCTOR_B(ldexp, boost::long_long_type, number_kind_floating_point)
  2025. //HETERO_BINARY_OP_FUNCTOR_B(frexp, boost::long_long_type*, number_kind_floating_point)
  2026. BINARY_OP_FUNCTOR(pow, number_kind_floating_point)
  2027. BINARY_OP_FUNCTOR(fmod, number_kind_floating_point)
  2028. BINARY_OP_FUNCTOR(atan2, number_kind_floating_point)
  2029. UNARY_OP_FUNCTOR(logb, number_kind_floating_point)
  2030. HETERO_BINARY_OP_FUNCTOR(scalbn, short, number_kind_floating_point)
  2031. HETERO_BINARY_OP_FUNCTOR_B(scalbn, int, number_kind_floating_point)
  2032. HETERO_BINARY_OP_FUNCTOR_B(scalbn, long, number_kind_floating_point)
  2033. HETERO_BINARY_OP_FUNCTOR_B(scalbn, boost::long_long_type, number_kind_floating_point)
  2034. //
  2035. // Integer functions:
  2036. //
  2037. BINARY_OP_FUNCTOR(gcd, number_kind_integer)
  2038. BINARY_OP_FUNCTOR(lcm, number_kind_integer)
  2039. HETERO_BINARY_OP_FUNCTOR_B(pow, unsigned, number_kind_integer)
  2040. #undef BINARY_OP_FUNCTOR
  2041. #undef UNARY_OP_FUNCTOR
  2042. //
  2043. // ilogb:
  2044. //
  2045. template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
  2046. inline typename enable_if_c<number_category<Backend>::value == number_kind_floating_point, typename Backend::exponent_type>::type
  2047. ilogb(const multiprecision::number<Backend, ExpressionTemplates>& val)
  2048. {
  2049. using default_ops::eval_ilogb;
  2050. return eval_ilogb(val.backend());
  2051. }
  2052. template <class tag, class A1, class A2, class A3, class A4>
  2053. inline typename enable_if_c<number_category<detail::expression<tag, A1, A2, A3, A4> >::value == number_kind_floating_point, typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type::backend_type::exponent_type>::type
  2054. ilogb(const detail::expression<tag, A1, A2, A3, A4>& val)
  2055. {
  2056. using default_ops::eval_ilogb;
  2057. typename multiprecision::detail::expression<tag, A1, A2, A3, A4>::result_type arg(val);
  2058. return eval_ilogb(arg.backend());
  2059. }
  2060. } //namespace multiprecision
  2061. namespace math{
  2062. //
  2063. // Overload of Boost.Math functions that find the wrong overload when used with number:
  2064. //
  2065. namespace detail{
  2066. template <class T> T sinc_pi_imp(T);
  2067. template <class T> T sinhc_pi_imp(T);
  2068. }
  2069. template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
  2070. inline multiprecision::number<Backend, ExpressionTemplates> sinc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x)
  2071. {
  2072. return BOOST_MP_MOVE(detail::sinc_pi_imp(x));
  2073. }
  2074. template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class Policy>
  2075. inline multiprecision::number<Backend, ExpressionTemplates> sinc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x, const Policy&)
  2076. {
  2077. return BOOST_MP_MOVE(detail::sinc_pi_imp(x));
  2078. }
  2079. template <class Backend, multiprecision::expression_template_option ExpressionTemplates>
  2080. inline multiprecision::number<Backend, ExpressionTemplates> sinhc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x)
  2081. {
  2082. return BOOST_MP_MOVE(detail::sinhc_pi_imp(x));
  2083. }
  2084. template <class Backend, multiprecision::expression_template_option ExpressionTemplates, class Policy>
  2085. inline multiprecision::number<Backend, ExpressionTemplates> sinhc_pi(const multiprecision::number<Backend, ExpressionTemplates>& x, const Policy&)
  2086. {
  2087. return BOOST_MP_MOVE(boost::math::sinhc_pi(x));
  2088. }
  2089. #ifdef BOOST_MSVC
  2090. #pragma warning(pop)
  2091. #endif
  2092. } // namespace math
  2093. } // namespace boost
  2094. //
  2095. // This has to come last of all:
  2096. //
  2097. #include <boost/multiprecision/detail/no_et_ops.hpp>
  2098. #include <boost/multiprecision/detail/et_ops.hpp>
  2099. //
  2100. // min/max overloads:
  2101. //
  2102. #include <boost/multiprecision/detail/min_max.hpp>
  2103. #endif