no_et_ops.hpp 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659
  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. static_assert(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 std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value, 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 std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && !is_equivalent_number_type<V, B>::value, 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 std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value, 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 std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && !is_equivalent_number_type<V, B>::value, 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 std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value, 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 std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && !is_equivalent_number_type<V, B>::value, 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 std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value, 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 std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && !is_equivalent_number_type<V, B>::value, 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 std::enable_if<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 std::enable_if<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 std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer) && !is_equivalent_number_type<V, B>::value, 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 std::enable_if<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 std::enable_if<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 std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer) && !is_equivalent_number_type<V, B>::value, 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 std::enable_if<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 std::enable_if<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 std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer) && !is_equivalent_number_type<V, B>::value, 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 std::enable_if<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 std::enable_if<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 std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer) && !is_equivalent_number_type<V, B>::value, 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 std::enable_if<boost::multiprecision::detail::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, std::integral_constant<bool, (sizeof(I) > sizeof(std::size_t))>(), std::integral_constant<bool, boost::multiprecision::detail::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 std::enable_if<boost::multiprecision::detail::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, std::integral_constant<bool, (sizeof(I) > sizeof(std::size_t))>(), std::integral_constant<bool, boost::multiprecision::detail::is_signed<I>::value>());
  302. eval_right_shift(result.backend(), b);
  303. return result;
  304. }
  305. //
  306. // If we have rvalue references go all over again with rvalue ref overloads and move semantics.
  307. // Note that while it would be tempting to implement these so they return an rvalue reference
  308. // (and indeed this would be optimally efficient), this is unsafe due to users propensity to
  309. // write:
  310. //
  311. // const T& t = a * b;
  312. //
  313. // which would lead to a dangling reference if we didn't return by value. Of course move
  314. // semantics help a great deal in return by value, so performance is still pretty good...
  315. //
  316. template <class B>
  317. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator-(number<B, et_off>&& v)
  318. {
  319. static_assert(is_signed_number<B>::value, "Negating an unsigned type results in ill-defined behavior.");
  320. v.backend().negate();
  321. return static_cast<number<B, et_off>&&>(v);
  322. }
  323. template <class B>
  324. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator~(number<B, et_off>&& v)
  325. {
  326. eval_complement(v.backend(), v.backend());
  327. return static_cast<number<B, et_off>&&>(v);
  328. }
  329. //
  330. // Addition:
  331. //
  332. template <class B>
  333. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator+(number<B, et_off>&& a, const number<B, et_off>& b)
  334. {
  335. using default_ops::eval_add;
  336. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  337. eval_add(a.backend(), b.backend());
  338. return static_cast<number<B, et_off>&&>(a);
  339. }
  340. template <class B>
  341. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator+(const number<B, et_off>& a, number<B, et_off>&& b)
  342. {
  343. using default_ops::eval_add;
  344. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  345. eval_add(b.backend(), a.backend());
  346. return static_cast<number<B, et_off>&&>(b);
  347. }
  348. template <class B>
  349. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator+(number<B, et_off>&& a, number<B, et_off>&& b)
  350. {
  351. using default_ops::eval_add;
  352. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  353. eval_add(a.backend(), b.backend());
  354. return static_cast<number<B, et_off>&&>(a);
  355. }
  356. template <class B, class V>
  357. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value, number<B, et_off> >::type
  358. operator+(number<B, et_off>&& a, const V& b)
  359. {
  360. using default_ops::eval_add;
  361. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  362. eval_add(a.backend(), number<B, et_off>::canonical_value(b));
  363. return static_cast<number<B, et_off>&&>(a);
  364. }
  365. template <class V, class B>
  366. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && !is_equivalent_number_type<V, B>::value, number<B, et_off> >::type
  367. operator+(const V& a, number<B, et_off>&& b)
  368. {
  369. using default_ops::eval_add;
  370. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  371. eval_add(b.backend(), number<B, et_off>::canonical_value(a));
  372. return static_cast<number<B, et_off>&&>(b);
  373. }
  374. //
  375. // Subtraction:
  376. //
  377. template <class B>
  378. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator-(number<B, et_off>&& a, const number<B, et_off>& b)
  379. {
  380. using default_ops::eval_subtract;
  381. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  382. eval_subtract(a.backend(), b.backend());
  383. return static_cast<number<B, et_off>&&>(a);
  384. }
  385. template <class B>
  386. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_signed_number<B>::value, number<B, et_off> >::type operator-(const number<B, et_off>& a, number<B, et_off>&& b)
  387. {
  388. using default_ops::eval_subtract;
  389. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  390. eval_subtract(b.backend(), a.backend());
  391. b.backend().negate();
  392. return static_cast<number<B, et_off>&&>(b);
  393. }
  394. template <class B>
  395. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator-(number<B, et_off>&& a, number<B, et_off>&& b)
  396. {
  397. using default_ops::eval_subtract;
  398. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  399. eval_subtract(a.backend(), b.backend());
  400. return static_cast<number<B, et_off>&&>(a);
  401. }
  402. template <class B, class V>
  403. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value, number<B, et_off> >::type
  404. operator-(number<B, et_off>&& a, const V& b)
  405. {
  406. using default_ops::eval_subtract;
  407. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  408. eval_subtract(a.backend(), number<B, et_off>::canonical_value(b));
  409. return static_cast<number<B, et_off>&&>(a);
  410. }
  411. template <class V, class B>
  412. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<(is_compatible_arithmetic_type<V, number<B, et_off> >::value && is_signed_number<B>::value) && !is_equivalent_number_type<V, B>::value, number<B, et_off> >::type
  413. operator-(const V& a, number<B, et_off>&& b)
  414. {
  415. using default_ops::eval_subtract;
  416. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  417. eval_subtract(b.backend(), number<B, et_off>::canonical_value(a));
  418. b.backend().negate();
  419. return static_cast<number<B, et_off>&&>(b);
  420. }
  421. //
  422. // Multiply:
  423. //
  424. template <class B>
  425. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator*(number<B, et_off>&& a, const number<B, et_off>& b)
  426. {
  427. using default_ops::eval_multiply;
  428. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  429. eval_multiply(a.backend(), b.backend());
  430. return static_cast<number<B, et_off>&&>(a);
  431. }
  432. template <class B>
  433. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator*(const number<B, et_off>& a, number<B, et_off>&& b)
  434. {
  435. using default_ops::eval_multiply;
  436. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  437. eval_multiply(b.backend(), a.backend());
  438. return static_cast<number<B, et_off>&&>(b);
  439. }
  440. template <class B>
  441. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator*(number<B, et_off>&& a, number<B, et_off>&& b)
  442. {
  443. using default_ops::eval_multiply;
  444. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  445. eval_multiply(a.backend(), b.backend());
  446. return static_cast<number<B, et_off>&&>(a);
  447. }
  448. template <class B, class V>
  449. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value, number<B, et_off> >::type
  450. operator*(number<B, et_off>&& a, const V& b)
  451. {
  452. using default_ops::eval_multiply;
  453. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  454. eval_multiply(a.backend(), number<B, et_off>::canonical_value(b));
  455. return static_cast<number<B, et_off>&&>(a);
  456. }
  457. template <class V, class B>
  458. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && !is_equivalent_number_type<V, B>::value, number<B, et_off> >::type
  459. operator*(const V& a, number<B, et_off>&& b)
  460. {
  461. using default_ops::eval_multiply;
  462. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  463. eval_multiply(b.backend(), number<B, et_off>::canonical_value(a));
  464. return static_cast<number<B, et_off>&&>(b);
  465. }
  466. //
  467. // divide:
  468. //
  469. template <class B>
  470. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number<B, et_off> operator/(number<B, et_off>&& a, const number<B, et_off>& b)
  471. {
  472. using default_ops::eval_divide;
  473. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  474. eval_divide(a.backend(), b.backend());
  475. return static_cast<number<B, et_off>&&>(a);
  476. }
  477. template <class B, class V>
  478. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value, number<B, et_off> >::type
  479. operator/(number<B, et_off>&& a, const V& b)
  480. {
  481. using default_ops::eval_divide;
  482. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  483. eval_divide(a.backend(), number<B, et_off>::canonical_value(b));
  484. return static_cast<number<B, et_off>&&>(a);
  485. }
  486. //
  487. // modulus:
  488. //
  489. template <class B>
  490. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator%(number<B, et_off>&& a, const number<B, et_off>& b)
  491. {
  492. using default_ops::eval_modulus;
  493. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  494. eval_modulus(a.backend(), b.backend());
  495. return static_cast<number<B, et_off>&&>(a);
  496. }
  497. template <class B, class V>
  498. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
  499. operator%(number<B, et_off>&& a, const V& b)
  500. {
  501. using default_ops::eval_modulus;
  502. detail::scoped_default_precision<multiprecision::number<B, et_off> > precision_guard(a, b);
  503. eval_modulus(a.backend(), number<B, et_off>::canonical_value(b));
  504. return static_cast<number<B, et_off>&&>(a);
  505. }
  506. //
  507. // Bitwise or:
  508. //
  509. template <class B>
  510. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator|(number<B, et_off>&& a, const number<B, et_off>& b)
  511. {
  512. using default_ops::eval_bitwise_or;
  513. eval_bitwise_or(a.backend(), b.backend());
  514. return static_cast<number<B, et_off>&&>(a);
  515. }
  516. template <class B>
  517. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator|(const number<B, et_off>& a, number<B, et_off>&& b)
  518. {
  519. using default_ops::eval_bitwise_or;
  520. eval_bitwise_or(b.backend(), a.backend());
  521. return static_cast<number<B, et_off>&&>(b);
  522. }
  523. template <class B>
  524. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator|(number<B, et_off>&& a, number<B, et_off>&& b)
  525. {
  526. using default_ops::eval_bitwise_or;
  527. eval_bitwise_or(a.backend(), b.backend());
  528. return static_cast<number<B, et_off>&&>(a);
  529. }
  530. template <class B, class V>
  531. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
  532. operator|(number<B, et_off>&& a, const V& b)
  533. {
  534. using default_ops::eval_bitwise_or;
  535. eval_bitwise_or(a.backend(), number<B, et_off>::canonical_value(b));
  536. return static_cast<number<B, et_off>&&>(a);
  537. }
  538. template <class V, class B>
  539. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer) && !is_equivalent_number_type<V, B>::value, number<B, et_off> >::type
  540. operator|(const V& a, number<B, et_off>&& b)
  541. {
  542. using default_ops::eval_bitwise_or;
  543. eval_bitwise_or(b.backend(), number<B, et_off>::canonical_value(a));
  544. return static_cast<number<B, et_off>&&>(b);
  545. }
  546. //
  547. // Bitwise xor:
  548. //
  549. template <class B>
  550. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator^(number<B, et_off>&& a, const number<B, et_off>& b)
  551. {
  552. using default_ops::eval_bitwise_xor;
  553. eval_bitwise_xor(a.backend(), b.backend());
  554. return static_cast<number<B, et_off>&&>(a);
  555. }
  556. template <class B>
  557. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator^(const number<B, et_off>& a, number<B, et_off>&& b)
  558. {
  559. using default_ops::eval_bitwise_xor;
  560. eval_bitwise_xor(b.backend(), a.backend());
  561. return static_cast<number<B, et_off>&&>(b);
  562. }
  563. template <class B>
  564. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator^(number<B, et_off>&& a, number<B, et_off>&& b)
  565. {
  566. using default_ops::eval_bitwise_xor;
  567. eval_bitwise_xor(a.backend(), b.backend());
  568. return static_cast<number<B, et_off>&&>(a);
  569. }
  570. template <class B, class V>
  571. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
  572. operator^(number<B, et_off>&& a, const V& b)
  573. {
  574. using default_ops::eval_bitwise_xor;
  575. eval_bitwise_xor(a.backend(), number<B, et_off>::canonical_value(b));
  576. return static_cast<number<B, et_off>&&>(a);
  577. }
  578. template <class V, class B>
  579. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer) && !is_equivalent_number_type<V, B>::value, number<B, et_off> >::type
  580. operator^(const V& a, number<B, et_off>&& b)
  581. {
  582. using default_ops::eval_bitwise_xor;
  583. eval_bitwise_xor(b.backend(), number<B, et_off>::canonical_value(a));
  584. return static_cast<number<B, et_off>&&>(b);
  585. }
  586. //
  587. // Bitwise and:
  588. //
  589. template <class B>
  590. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator&(number<B, et_off>&& a, const number<B, et_off>& b)
  591. {
  592. using default_ops::eval_bitwise_and;
  593. eval_bitwise_and(a.backend(), b.backend());
  594. return static_cast<number<B, et_off>&&>(a);
  595. }
  596. template <class B>
  597. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator&(const number<B, et_off>& a, number<B, et_off>&& b)
  598. {
  599. using default_ops::eval_bitwise_and;
  600. eval_bitwise_and(b.backend(), a.backend());
  601. return static_cast<number<B, et_off>&&>(b);
  602. }
  603. template <class B>
  604. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<number_category<B>::value == number_kind_integer, number<B, et_off> >::type operator&(number<B, et_off>&& a, number<B, et_off>&& b)
  605. {
  606. using default_ops::eval_bitwise_and;
  607. eval_bitwise_and(a.backend(), b.backend());
  608. return static_cast<number<B, et_off>&&>(a);
  609. }
  610. template <class B, class V>
  611. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
  612. operator&(number<B, et_off>&& a, const V& b)
  613. {
  614. using default_ops::eval_bitwise_and;
  615. eval_bitwise_and(a.backend(), number<B, et_off>::canonical_value(b));
  616. return static_cast<number<B, et_off>&&>(a);
  617. }
  618. template <class V, class B>
  619. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<is_compatible_arithmetic_type<V, number<B, et_off> >::value && (number_category<B>::value == number_kind_integer) && !is_equivalent_number_type<V, B>::value, number<B, et_off> >::type
  620. operator&(const V& a, number<B, et_off>&& b)
  621. {
  622. using default_ops::eval_bitwise_and;
  623. eval_bitwise_and(b.backend(), number<B, et_off>::canonical_value(a));
  624. return static_cast<number<B, et_off>&&>(b);
  625. }
  626. //
  627. // shifts:
  628. //
  629. template <class B, class I>
  630. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
  631. operator<<(number<B, et_off>&& a, const I& b)
  632. {
  633. using default_ops::eval_left_shift;
  634. eval_left_shift(a.backend(), b);
  635. return static_cast<number<B, et_off>&&>(a);
  636. }
  637. template <class B, class I>
  638. BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR typename std::enable_if<boost::multiprecision::detail::is_integral<I>::value && (number_category<B>::value == number_kind_integer), number<B, et_off> >::type
  639. operator>>(number<B, et_off>&& a, const I& b)
  640. {
  641. using default_ops::eval_right_shift;
  642. eval_right_shift(a.backend(), b);
  643. return static_cast<number<B, et_off>&&>(a);
  644. }
  645. }
  646. } // namespace boost::multiprecision
  647. #ifdef BOOST_MSVC
  648. #pragma warning(pop)
  649. #endif
  650. #endif // BOOST_MP_NO_ET_OPS_HPP