no_et_ops.hpp 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Copyright 2012 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_MP_NO_ET_OPS_HPP
  6. #define BOOST_MP_NO_ET_OPS_HPP
  7. #ifdef BOOST_MSVC
  8. #pragma warning(push)
  9. #pragma warning(disable : 4714)
  10. #endif
  11. namespace boost {
  12. namespace multiprecision {
  13. //
  14. // Operators for non-expression template enabled number.
  15. // NOTE: this is not a complete header - really just a suffix to default_ops.hpp.
  16. // NOTE: these operators have to be defined after the methods in default_ops.hpp.
  17. //
  18. template <class B>
  19. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator-(const number<B, et_off>& v)
  20. {
  21. BOOST_STATIC_ASSERT_MSG(is_signed_number<B>::value, "Negating an unsigned type results in ill-defined behavior.");
  22. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(v);
  23. number<B, et_off> result(v);
  24. result.backend().negate();
  25. return result;
  26. }
  27. template <class B>
  28. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator~(const number<B, et_off>& v)
  29. {
  30. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(v);
  31. number<B, et_off> result;
  32. eval_complement(result.backend(), v.backend());
  33. return result;
  34. }
  35. //
  36. // Addition:
  37. //
  38. template <class B>
  39. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator+(const number<B, et_off>& a, const number<B, et_off>& b)
  40. {
  41. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  42. number<B, et_off> result;
  43. using default_ops::eval_add;
  44. eval_add(result.backend(), a.backend(), b.backend());
  45. return result;
  46. }
  47. template <class B, class V>
  48. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
  49. operator+(const number<B, et_off>& a, const V& b)
  50. {
  51. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a);
  52. number<B, et_off> result;
  53. using default_ops::eval_add;
  54. eval_add(result.backend(), a.backend(), number<B, et_off>::canonical_value(b));
  55. return result;
  56. }
  57. template <class V, class B>
  58. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
  59. operator+(const V& a, const number<B, et_off>& b)
  60. {
  61. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(b);
  62. number<B, et_off> result;
  63. using default_ops::eval_add;
  64. eval_add(result.backend(), b.backend(), number<B, et_off>::canonical_value(a));
  65. return result;
  66. }
  67. //
  68. // Subtraction:
  69. //
  70. template <class B>
  71. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator-(const number<B, et_off>& a, const number<B, et_off>& b)
  72. {
  73. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  74. number<B, et_off> result;
  75. using default_ops::eval_subtract;
  76. eval_subtract(result.backend(), a.backend(), b.backend());
  77. return result;
  78. }
  79. template <class B, class V>
  80. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
  81. operator-(const number<B, et_off>& a, const V& b)
  82. {
  83. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a);
  84. number<B, et_off> result;
  85. using default_ops::eval_subtract;
  86. eval_subtract(result.backend(), a.backend(), number<B, et_off>::canonical_value(b));
  87. return result;
  88. }
  89. template <class V, class B>
  90. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
  91. operator-(const V& a, const number<B, et_off>& b)
  92. {
  93. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(b);
  94. number<B, et_off> result;
  95. using default_ops::eval_subtract;
  96. eval_subtract(result.backend(), number<B, et_off>::canonical_value(a), b.backend());
  97. return result;
  98. }
  99. //
  100. // Multiply:
  101. //
  102. template <class B>
  103. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator*(const number<B, et_off>& a, const number<B, et_off>& b)
  104. {
  105. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  106. number<B, et_off> result;
  107. using default_ops::eval_multiply;
  108. eval_multiply(result.backend(), a.backend(), b.backend());
  109. return result;
  110. }
  111. template <class B, class V>
  112. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
  113. operator*(const number<B, et_off>& a, const V& b)
  114. {
  115. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a);
  116. number<B, et_off> result;
  117. using default_ops::eval_multiply;
  118. eval_multiply(result.backend(), a.backend(), number<B, et_off>::canonical_value(b));
  119. return result;
  120. }
  121. template <class V, class B>
  122. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
  123. operator*(const V& a, const number<B, et_off>& b)
  124. {
  125. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(b);
  126. number<B, et_off> result;
  127. using default_ops::eval_multiply;
  128. eval_multiply(result.backend(), b.backend(), number<B, et_off>::canonical_value(a));
  129. return result;
  130. }
  131. //
  132. // divide:
  133. //
  134. template <class B>
  135. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator/(const number<B, et_off>& a, const number<B, et_off>& b)
  136. {
  137. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  138. number<B, et_off> result;
  139. using default_ops::eval_divide;
  140. eval_divide(result.backend(), a.backend(), b.backend());
  141. return result;
  142. }
  143. template <class B, class V>
  144. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
  145. operator/(const number<B, et_off>& a, const V& b)
  146. {
  147. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a);
  148. number<B, et_off> result;
  149. using default_ops::eval_divide;
  150. eval_divide(result.backend(), a.backend(), number<B, et_off>::canonical_value(b));
  151. return result;
  152. }
  153. template <class V, class B>
  154. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
  155. operator/(const V& a, const number<B, et_off>& b)
  156. {
  157. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(b);
  158. number<B, et_off> result;
  159. using default_ops::eval_divide;
  160. eval_divide(result.backend(), number<B, et_off>::canonical_value(a), b.backend());
  161. return result;
  162. }
  163. //
  164. // modulus:
  165. //
  166. template <class B>
  167. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator%(const number<B, et_off>& a, const number<B, et_off>& b)
  168. {
  169. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  170. number<B, et_off> result;
  171. using default_ops::eval_modulus;
  172. eval_modulus(result.backend(), a.backend(), b.backend());
  173. return result;
  174. }
  175. template <class B, class V>
  176. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
  177. operator%(const number<B, et_off>& a, const V& b)
  178. {
  179. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a);
  180. number<B, et_off> result;
  181. using default_ops::eval_modulus;
  182. eval_modulus(result.backend(), a.backend(), number<B, et_off>::canonical_value(b));
  183. return result;
  184. }
  185. template <class V, class B>
  186. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
  187. operator%(const V& a, const number<B, et_off>& b)
  188. {
  189. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(b);
  190. number<B, et_off> result;
  191. using default_ops::eval_modulus;
  192. eval_modulus(result.backend(), number<B, et_off>::canonical_value(a), b.backend());
  193. return result;
  194. }
  195. //
  196. // Bitwise or:
  197. //
  198. template <class B>
  199. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator|(const number<B, et_off>& a, const number<B, et_off>& b)
  200. {
  201. number<B, et_off> result;
  202. using default_ops::eval_bitwise_or;
  203. eval_bitwise_or(result.backend(), a.backend(), b.backend());
  204. return result;
  205. }
  206. template <class B, class V>
  207. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
  208. operator|(const number<B, et_off>& a, const V& b)
  209. {
  210. number<B, et_off> result;
  211. using default_ops::eval_bitwise_or;
  212. eval_bitwise_or(result.backend(), a.backend(), number<B, et_off>::canonical_value(b));
  213. return result;
  214. }
  215. template <class V, class B>
  216. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
  217. operator|(const V& a, const number<B, et_off>& b)
  218. {
  219. number<B, et_off> result;
  220. using default_ops::eval_bitwise_or;
  221. eval_bitwise_or(result.backend(), b.backend(), number<B, et_off>::canonical_value(a));
  222. return result;
  223. }
  224. //
  225. // Bitwise xor:
  226. //
  227. template <class B>
  228. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator^(const number<B, et_off>& a, const number<B, et_off>& b)
  229. {
  230. number<B, et_off> result;
  231. using default_ops::eval_bitwise_xor;
  232. eval_bitwise_xor(result.backend(), a.backend(), b.backend());
  233. return result;
  234. }
  235. template <class B, class V>
  236. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
  237. operator^(const number<B, et_off>& a, const V& b)
  238. {
  239. number<B, et_off> result;
  240. using default_ops::eval_bitwise_xor;
  241. eval_bitwise_xor(result.backend(), a.backend(), number<B, et_off>::canonical_value(b));
  242. return result;
  243. }
  244. template <class V, class B>
  245. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
  246. operator^(const V& a, const number<B, et_off>& b)
  247. {
  248. number<B, et_off> result;
  249. using default_ops::eval_bitwise_xor;
  250. eval_bitwise_xor(result.backend(), b.backend(), number<B, et_off>::canonical_value(a));
  251. return result;
  252. }
  253. //
  254. // Bitwise and:
  255. //
  256. template <class B>
  257. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator&(const number<B, et_off>& a, const number<B, et_off>& b)
  258. {
  259. number<B, et_off> result;
  260. using default_ops::eval_bitwise_and;
  261. eval_bitwise_and(result.backend(), a.backend(), b.backend());
  262. return result;
  263. }
  264. template <class B, class V>
  265. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
  266. operator&(const number<B, et_off>& a, const V& b)
  267. {
  268. number<B, et_off> result;
  269. using default_ops::eval_bitwise_and;
  270. eval_bitwise_and(result.backend(), a.backend(), number<B, et_off>::canonical_value(b));
  271. return result;
  272. }
  273. template <class V, class B>
  274. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
  275. operator&(const V& a, const number<B, et_off>& b)
  276. {
  277. number<B, et_off> result;
  278. using default_ops::eval_bitwise_and;
  279. eval_bitwise_and(result.backend(), b.backend(), number<B, et_off>::canonical_value(a));
  280. return result;
  281. }
  282. //
  283. // shifts:
  284. //
  285. template <class B, class I>
  286. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_integral<I>::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
  287. operator<<(const number<B, et_off>& a, const I& b)
  288. {
  289. number<B, et_off> result(a);
  290. using default_ops::eval_left_shift;
  291. detail::check_shift_range(b, mpl::bool_<(sizeof(I) > sizeof(std::size_t))>(), mpl::bool_<is_signed<I>::value>());
  292. eval_left_shift(result.backend(), b);
  293. return result;
  294. }
  295. template <class B, class I>
  296. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_integral<I>::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
  297. operator>>(const number<B, et_off>& a, const I& b)
  298. {
  299. number<B, et_off> result(a);
  300. using default_ops::eval_right_shift;
  301. detail::check_shift_range(b, mpl::bool_<(sizeof(I) > sizeof(std::size_t))>(), mpl::bool_<is_signed<I>::value>());
  302. eval_right_shift(result.backend(), b);
  303. return result;
  304. }
  305. #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !(defined(__GNUC__) && ((__GNUC__ == 4) && (__GNUC_MINOR__ < 5)))
  306. //
  307. // If we have rvalue references go all over again with rvalue ref overloads and move semantics.
  308. // Note that while it would be tempting to implement these so they return an rvalue reference
  309. // (and indeed this would be optimally efficient), this is unsafe due to users propensity to
  310. // write:
  311. //
  312. // const T& t = a * b;
  313. //
  314. // which would lead to a dangling reference if we didn't return by value. Of course move
  315. // semantics help a great deal in return by value, so performance is still pretty good...
  316. //
  317. template <class B>
  318. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator-(number<B, et_off>&& v)
  319. {
  320. BOOST_STATIC_ASSERT_MSG(is_signed_number<B>::value, "Negating an unsigned type results in ill-defined behavior.");
  321. v.backend().negate();
  322. return static_cast<number<B, et_off>&&>(v);
  323. }
  324. template <class B>
  325. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator~(number<B, et_off>&& v)
  326. {
  327. eval_complement(v.backend(), v.backend());
  328. return static_cast<number<B, et_off>&&>(v);
  329. }
  330. //
  331. // Addition:
  332. //
  333. template <class B>
  334. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator+(number<B, et_off>&& a, const number<B, et_off>& b)
  335. {
  336. using default_ops::eval_add;
  337. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  338. eval_add(a.backend(), b.backend());
  339. return static_cast<number<B, et_off>&&>(a);
  340. }
  341. template <class B>
  342. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator+(const number<B, et_off>& a, number<B, et_off>&& b)
  343. {
  344. using default_ops::eval_add;
  345. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  346. eval_add(b.backend(), a.backend());
  347. return static_cast<number<B, et_off>&&>(b);
  348. }
  349. template <class B>
  350. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator+(number<B, et_off>&& a, number<B, et_off>&& b)
  351. {
  352. using default_ops::eval_add;
  353. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  354. eval_add(a.backend(), b.backend());
  355. return static_cast<number<B, et_off>&&>(a);
  356. }
  357. template <class B, class V>
  358. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
  359. operator+(number<B, et_off>&& a, const V& b)
  360. {
  361. using default_ops::eval_add;
  362. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  363. eval_add(a.backend(), number<B, et_off>::canonical_value(b));
  364. return static_cast<number<B, et_off>&&>(a);
  365. }
  366. template <class V, class B>
  367. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
  368. operator+(const V& a, number<B, et_off>&& b)
  369. {
  370. using default_ops::eval_add;
  371. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  372. eval_add(b.backend(), number<B, et_off>::canonical_value(a));
  373. return static_cast<number<B, et_off>&&>(b);
  374. }
  375. //
  376. // Subtraction:
  377. //
  378. template <class B>
  379. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator-(number<B, et_off>&& a, const number<B, et_off>& b)
  380. {
  381. using default_ops::eval_subtract;
  382. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  383. eval_subtract(a.backend(), b.backend());
  384. return static_cast<number<B, et_off>&&>(a);
  385. }
  386. template <class B>
  387. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_signed_number<B>, number<B, et_off> >::type operator-(const number<B, et_off>& a, number<B, et_off>&& b)
  388. {
  389. using default_ops::eval_subtract;
  390. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  391. eval_subtract(b.backend(), a.backend());
  392. b.backend().negate();
  393. return static_cast<number<B, et_off>&&>(b);
  394. }
  395. template <class B>
  396. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator-(number<B, et_off>&& a, number<B, et_off>&& b)
  397. {
  398. using default_ops::eval_subtract;
  399. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  400. eval_subtract(a.backend(), b.backend());
  401. return static_cast<number<B, et_off>&&>(a);
  402. }
  403. template <class B, class V>
  404. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
  405. operator-(number<B, et_off>&& a, const V& b)
  406. {
  407. using default_ops::eval_subtract;
  408. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  409. eval_subtract(a.backend(), number<B, et_off>::canonical_value(b));
  410. return static_cast<number<B, et_off>&&>(a);
  411. }
  412. template <class V, class B>
  413. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<(is_compatible_arithmetic_type<V, number<B, et_off> >::value && is_signed_number<B>::value), number<B, et_off> >::type
  414. operator-(const V& a, number<B, et_off>&& b)
  415. {
  416. using default_ops::eval_subtract;
  417. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  418. eval_subtract(b.backend(), number<B, et_off>::canonical_value(a));
  419. b.backend().negate();
  420. return static_cast<number<B, et_off>&&>(b);
  421. }
  422. //
  423. // Multiply:
  424. //
  425. template <class B>
  426. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator*(number<B, et_off>&& a, const number<B, et_off>& b)
  427. {
  428. using default_ops::eval_multiply;
  429. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  430. eval_multiply(a.backend(), b.backend());
  431. return static_cast<number<B, et_off>&&>(a);
  432. }
  433. template <class B>
  434. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator*(const number<B, et_off>& a, number<B, et_off>&& b)
  435. {
  436. using default_ops::eval_multiply;
  437. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  438. eval_multiply(b.backend(), a.backend());
  439. return static_cast<number<B, et_off>&&>(b);
  440. }
  441. template <class B>
  442. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator*(number<B, et_off>&& a, number<B, et_off>&& b)
  443. {
  444. using default_ops::eval_multiply;
  445. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  446. eval_multiply(a.backend(), b.backend());
  447. return static_cast<number<B, et_off>&&>(a);
  448. }
  449. template <class B, class V>
  450. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
  451. operator*(number<B, et_off>&& a, const V& b)
  452. {
  453. using default_ops::eval_multiply;
  454. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  455. eval_multiply(a.backend(), number<B, et_off>::canonical_value(b));
  456. return static_cast<number<B, et_off>&&>(a);
  457. }
  458. template <class V, class B>
  459. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
  460. operator*(const V& a, number<B, et_off>&& b)
  461. {
  462. using default_ops::eval_multiply;
  463. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  464. eval_multiply(b.backend(), number<B, et_off>::canonical_value(a));
  465. return static_cast<number<B, et_off>&&>(b);
  466. }
  467. //
  468. // divide:
  469. //
  470. template <class B>
  471. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator/(number<B, et_off>&& a, const number<B, et_off>& b)
  472. {
  473. using default_ops::eval_divide;
  474. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  475. eval_divide(a.backend(), b.backend());
  476. return static_cast<number<B, et_off>&&>(a);
  477. }
  478. template <class B, class V>
  479. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >, number<B, et_off> >::type
  480. operator/(number<B, et_off>&& a, const V& b)
  481. {
  482. using default_ops::eval_divide;
  483. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  484. eval_divide(a.backend(), number<B, et_off>::canonical_value(b));
  485. return static_cast<number<B, et_off>&&>(a);
  486. }
  487. //
  488. // modulus:
  489. //
  490. template <class B>
  491. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator%(number<B, et_off>&& a, const number<B, et_off>& b)
  492. {
  493. using default_ops::eval_modulus;
  494. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  495. eval_modulus(a.backend(), b.backend());
  496. return static_cast<number<B, et_off>&&>(a);
  497. }
  498. template <class B, class V>
  499. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
  500. operator%(number<B, et_off>&& a, const V& b)
  501. {
  502. using default_ops::eval_modulus;
  503. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  504. eval_modulus(a.backend(), number<B, et_off>::canonical_value(b));
  505. return static_cast<number<B, et_off>&&>(a);
  506. }
  507. //
  508. // Bitwise or:
  509. //
  510. template <class B>
  511. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator|(number<B, et_off>&& a, const number<B, et_off>& b)
  512. {
  513. using default_ops::eval_bitwise_or;
  514. eval_bitwise_or(a.backend(), b.backend());
  515. return static_cast<number<B, et_off>&&>(a);
  516. }
  517. template <class B>
  518. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator|(const number<B, et_off>& a, number<B, et_off>&& b)
  519. {
  520. using default_ops::eval_bitwise_or;
  521. eval_bitwise_or(b.backend(), a.backend());
  522. return static_cast<number<B, et_off>&&>(b);
  523. }
  524. template <class B>
  525. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator|(number<B, et_off>&& a, number<B, et_off>&& b)
  526. {
  527. using default_ops::eval_bitwise_or;
  528. eval_bitwise_or(a.backend(), b.backend());
  529. return static_cast<number<B, et_off>&&>(a);
  530. }
  531. template <class B, class V>
  532. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
  533. operator|(number<B, et_off>&& a, const V& b)
  534. {
  535. using default_ops::eval_bitwise_or;
  536. eval_bitwise_or(a.backend(), number<B, et_off>::canonical_value(b));
  537. return static_cast<number<B, et_off>&&>(a);
  538. }
  539. template <class V, class B>
  540. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
  541. operator|(const V& a, number<B, et_off>&& b)
  542. {
  543. using default_ops::eval_bitwise_or;
  544. eval_bitwise_or(b.backend(), number<B, et_off>::canonical_value(a));
  545. return static_cast<number<B, et_off>&&>(b);
  546. }
  547. //
  548. // Bitwise xor:
  549. //
  550. template <class B>
  551. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator^(number<B, et_off>&& a, const number<B, et_off>& b)
  552. {
  553. using default_ops::eval_bitwise_xor;
  554. eval_bitwise_xor(a.backend(), b.backend());
  555. return static_cast<number<B, et_off>&&>(a);
  556. }
  557. template <class B>
  558. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator^(const number<B, et_off>& a, number<B, et_off>&& b)
  559. {
  560. using default_ops::eval_bitwise_xor;
  561. eval_bitwise_xor(b.backend(), a.backend());
  562. return static_cast<number<B, et_off>&&>(b);
  563. }
  564. template <class B>
  565. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator^(number<B, et_off>&& a, number<B, et_off>&& b)
  566. {
  567. using default_ops::eval_bitwise_xor;
  568. eval_bitwise_xor(a.backend(), b.backend());
  569. return static_cast<number<B, et_off>&&>(a);
  570. }
  571. template <class B, class V>
  572. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
  573. operator^(number<B, et_off>&& a, const V& b)
  574. {
  575. using default_ops::eval_bitwise_xor;
  576. eval_bitwise_xor(a.backend(), number<B, et_off>::canonical_value(b));
  577. return static_cast<number<B, et_off>&&>(a);
  578. }
  579. template <class V, class B>
  580. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
  581. operator^(const V& a, number<B, et_off>&& b)
  582. {
  583. using default_ops::eval_bitwise_xor;
  584. eval_bitwise_xor(b.backend(), number<B, et_off>::canonical_value(a));
  585. return static_cast<number<B, et_off>&&>(b);
  586. }
  587. //
  588. // Bitwise and:
  589. //
  590. template <class B>
  591. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator&(number<B, et_off>&& a, const number<B, et_off>& b)
  592. {
  593. using default_ops::eval_bitwise_and;
  594. eval_bitwise_and(a.backend(), b.backend());
  595. return static_cast<number<B, et_off>&&>(a);
  596. }
  597. template <class B>
  598. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator&(const number<B, et_off>& a, number<B, et_off>&& b)
  599. {
  600. using default_ops::eval_bitwise_and;
  601. eval_bitwise_and(b.backend(), a.backend());
  602. return static_cast<number<B, et_off>&&>(b);
  603. }
  604. template <class B>
  605. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator&(number<B, et_off>&& a, number<B, et_off>&& b)
  606. {
  607. using default_ops::eval_bitwise_and;
  608. eval_bitwise_and(a.backend(), b.backend());
  609. return static_cast<number<B, et_off>&&>(a);
  610. }
  611. template <class B, class V>
  612. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
  613. operator&(number<B, et_off>&& a, const V& b)
  614. {
  615. using default_ops::eval_bitwise_and;
  616. eval_bitwise_and(a.backend(), number<B, et_off>::canonical_value(b));
  617. return static_cast<number<B, et_off>&&>(a);
  618. }
  619. template <class V, class B>
  620. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
  621. operator&(const V& a, number<B, et_off>&& b)
  622. {
  623. using default_ops::eval_bitwise_and;
  624. eval_bitwise_and(b.backend(), number<B, et_off>::canonical_value(a));
  625. return static_cast<number<B, et_off>&&>(b);
  626. }
  627. //
  628. // shifts:
  629. //
  630. template <class B, class I>
  631. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_integral<I>::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
  632. operator<<(number<B, et_off>&& a, const I& b)
  633. {
  634. using default_ops::eval_left_shift;
  635. eval_left_shift(a.backend(), b);
  636. return static_cast<number<B, et_off>&&>(a);
  637. }
  638. template <class B, class I>
  639. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename enable_if_c<is_integral<I>::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
  640. operator>>(number<B, et_off>&& a, const I& b)
  641. {
  642. using default_ops::eval_right_shift;
  643. eval_right_shift(a.backend(), b);
  644. return static_cast<number<B, et_off>&&>(a);
  645. }
  646. #endif
  647. }} // namespace boost::multiprecision
  648. #ifdef BOOST_MSVC
  649. #pragma warning(pop)
  650. #endif
  651. #endif // BOOST_MP_NO_ET_OPS_HPP