rational_adaptor.hpp 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289
  1. ///////////////////////////////////////////////////////////////
  2. // Copyright 2020 John Maddock. Distributed under the Boost
  3. // Software License, Version 1.0. (See accompanying file
  4. // LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt
  5. #ifndef BOOST_MP_RATIONAL_ADAPTOR_HPP
  6. #define BOOST_MP_RATIONAL_ADAPTOR_HPP
  7. #include <boost/multiprecision/number.hpp>
  8. #include <boost/multiprecision/detail/hash.hpp>
  9. #include <boost/multiprecision/detail/float128_functions.hpp>
  10. #include <boost/multiprecision/detail/no_exceptions_support.hpp>
  11. namespace boost {
  12. namespace multiprecision {
  13. namespace backends {
  14. template <class Backend>
  15. struct rational_adaptor
  16. {
  17. //
  18. // Each backend need to declare 3 type lists which declare the types
  19. // with which this can interoperate. These lists must at least contain
  20. // the widest type in each category - so "long long" must be the final
  21. // type in the signed_types list for example. Any narrower types if not
  22. // present in the list will get promoted to the next wider type that is
  23. // in the list whenever mixed arithmetic involving that type is encountered.
  24. //
  25. typedef typename Backend::signed_types signed_types;
  26. typedef typename Backend::unsigned_types unsigned_types;
  27. typedef typename Backend::float_types float_types;
  28. typedef typename std::tuple_element<0, unsigned_types>::type ui_type;
  29. static Backend get_one()
  30. {
  31. Backend t;
  32. t = static_cast<ui_type>(1);
  33. return t;
  34. }
  35. static Backend get_zero()
  36. {
  37. Backend t;
  38. t = static_cast<ui_type>(0);
  39. return t;
  40. }
  41. static const Backend& one()
  42. {
  43. static const Backend result(get_one());
  44. return result;
  45. }
  46. static const Backend& zero()
  47. {
  48. static const Backend result(get_zero());
  49. return result;
  50. }
  51. void normalize()
  52. {
  53. using default_ops::eval_gcd;
  54. using default_ops::eval_eq;
  55. using default_ops::eval_divide;
  56. using default_ops::eval_get_sign;
  57. int s = eval_get_sign(m_denom);
  58. if(s == 0)
  59. {
  60. BOOST_MP_THROW_EXCEPTION(std::overflow_error("Integer division by zero"));
  61. }
  62. else if (s < 0)
  63. {
  64. m_num.negate();
  65. m_denom.negate();
  66. }
  67. Backend g, t;
  68. eval_gcd(g, m_num, m_denom);
  69. if (!eval_eq(g, one()))
  70. {
  71. eval_divide(t, m_num, g);
  72. m_num.swap(t);
  73. eval_divide(t, m_denom, g);
  74. m_denom = std::move(t);
  75. }
  76. }
  77. // We must have a default constructor:
  78. rational_adaptor()
  79. : m_num(zero()), m_denom(one()) {}
  80. rational_adaptor(const rational_adaptor& o) : m_num(o.m_num), m_denom(o.m_denom) {}
  81. rational_adaptor(rational_adaptor&& o) = default;
  82. // Optional constructors, we can make this type slightly more efficient
  83. // by providing constructors from any type we can handle natively.
  84. // These will also cause number<> to be implicitly constructible
  85. // from these types unless we make such constructors explicit.
  86. //
  87. template <class Arithmetic>
  88. rational_adaptor(const Arithmetic& val, typename std::enable_if<std::is_constructible<Backend, Arithmetic>::value && !std::is_floating_point<Arithmetic>::value>::type const* = nullptr)
  89. : m_num(val), m_denom(one()) {}
  90. //
  91. // Pass-through 2-arg construction of components:
  92. //
  93. template <class T, class U>
  94. rational_adaptor(const T& a, const U& b, typename std::enable_if<std::is_constructible<Backend, T const&>::value && std::is_constructible<Backend, U const&>::value>::type const* = nullptr)
  95. : m_num(a), m_denom(b)
  96. {
  97. normalize();
  98. }
  99. template <class T, class U>
  100. rational_adaptor(T&& a, const U& b, typename std::enable_if<std::is_constructible<Backend, T>::value && std::is_constructible<Backend, U>::value>::type const* = nullptr)
  101. : m_num(static_cast<T&&>(a)), m_denom(b)
  102. {
  103. normalize();
  104. }
  105. template <class T, class U>
  106. rational_adaptor(T&& a, U&& b, typename std::enable_if<std::is_constructible<Backend, T>::value && std::is_constructible<Backend, U>::value>::type const* = nullptr)
  107. : m_num(static_cast<T&&>(a)), m_denom(static_cast<U&&>(b))
  108. {
  109. normalize();
  110. }
  111. template <class T, class U>
  112. rational_adaptor(const T& a, U&& b, typename std::enable_if<std::is_constructible<Backend, T>::value && std::is_constructible<Backend, U>::value>::type const* = nullptr)
  113. : m_num(a), m_denom(static_cast<U&&>(b))
  114. {
  115. normalize();
  116. }
  117. //
  118. // In the absense of converting constructors, operator= takes the strain.
  119. // In addition to the usual suspects, there must be one operator= for each type
  120. // listed in signed_types, unsigned_types, and float_types plus a string constructor.
  121. //
  122. rational_adaptor& operator=(const rational_adaptor& o) = default;
  123. rational_adaptor& operator=(rational_adaptor&& o) = default;
  124. template <class Arithmetic>
  125. inline typename std::enable_if<!std::is_floating_point<Arithmetic>::value, rational_adaptor&>::type operator=(const Arithmetic& i)
  126. {
  127. m_num = i;
  128. m_denom = one();
  129. return *this;
  130. }
  131. rational_adaptor& operator=(const char* s)
  132. {
  133. using default_ops::eval_eq;
  134. std::string s1;
  135. multiprecision::number<Backend> v1, v2;
  136. char c;
  137. bool have_hex = false;
  138. const char* p = s; // saved for later
  139. while ((0 != (c = *s)) && (c == 'x' || c == 'X' || c == '-' || c == '+' || (c >= '0' && c <= '9') || (have_hex && (c >= 'a' && c <= 'f')) || (have_hex && (c >= 'A' && c <= 'F'))))
  140. {
  141. if (c == 'x' || c == 'X')
  142. have_hex = true;
  143. s1.append(1, c);
  144. ++s;
  145. }
  146. v1.assign(s1);
  147. s1.erase();
  148. if (c == '/')
  149. {
  150. ++s;
  151. while ((0 != (c = *s)) && (c == 'x' || c == 'X' || c == '-' || c == '+' || (c >= '0' && c <= '9') || (have_hex && (c >= 'a' && c <= 'f')) || (have_hex && (c >= 'A' && c <= 'F'))))
  152. {
  153. if (c == 'x' || c == 'X')
  154. have_hex = true;
  155. s1.append(1, c);
  156. ++s;
  157. }
  158. v2.assign(s1);
  159. }
  160. else
  161. v2 = 1;
  162. if (*s)
  163. {
  164. BOOST_MP_THROW_EXCEPTION(std::runtime_error(std::string("Could not parse the string \"") + p + std::string("\" as a valid rational number.")));
  165. }
  166. multiprecision::number<Backend> gcd;
  167. eval_gcd(gcd.backend(), v1.backend(), v2.backend());
  168. if (!eval_eq(gcd.backend(), one()))
  169. {
  170. v1 /= gcd;
  171. v2 /= gcd;
  172. }
  173. num() = std::move(std::move(v1).backend());
  174. denom() = std::move(std::move(v2).backend());
  175. return *this;
  176. }
  177. template <class Float>
  178. typename std::enable_if<std::is_floating_point<Float>::value, rational_adaptor&>::type operator=(Float i)
  179. {
  180. using default_ops::eval_eq;
  181. BOOST_MP_FLOAT128_USING using std::floor; using std::frexp; using std::ldexp;
  182. int e;
  183. Float f = frexp(i, &e);
  184. #ifdef BOOST_HAS_FLOAT128
  185. f = ldexp(f, std::is_same<float128_type, Float>::value ? 113 : std::numeric_limits<Float>::digits);
  186. e -= std::is_same<float128_type, Float>::value ? 113 : std::numeric_limits<Float>::digits;
  187. #else
  188. f = ldexp(f, std::numeric_limits<Float>::digits);
  189. e -= std::numeric_limits<Float>::digits;
  190. #endif
  191. number<Backend> num(f);
  192. number<Backend> denom(1u);
  193. if (e > 0)
  194. {
  195. num <<= e;
  196. }
  197. else if (e < 0)
  198. {
  199. denom <<= -e;
  200. }
  201. number<Backend> gcd;
  202. eval_gcd(gcd.backend(), num.backend(), denom.backend());
  203. if (!eval_eq(gcd.backend(), one()))
  204. {
  205. num /= gcd;
  206. denom /= gcd;
  207. }
  208. this->num() = std::move(std::move(num).backend());
  209. this->denom() = std::move(std::move(denom).backend());
  210. return *this;
  211. }
  212. void swap(rational_adaptor& o)
  213. {
  214. m_num.swap(o.m_num);
  215. m_denom.swap(o.m_denom);
  216. }
  217. std::string str(std::streamsize digits, std::ios_base::fmtflags f) const
  218. {
  219. using default_ops::eval_eq;
  220. //
  221. // We format the string ourselves so we can match what GMP's mpq type does:
  222. //
  223. std::string result = num().str(digits, f);
  224. if (!eval_eq(denom(), one()))
  225. {
  226. result.append(1, '/');
  227. result.append(denom().str(digits, f));
  228. }
  229. return result;
  230. }
  231. void negate()
  232. {
  233. m_num.negate();
  234. }
  235. int compare(const rational_adaptor& o) const
  236. {
  237. std::ptrdiff_t s1 = eval_get_sign(*this);
  238. std::ptrdiff_t s2 = eval_get_sign(o);
  239. if (s1 != s2)
  240. {
  241. return s1 < s2 ? -1 : 1;
  242. }
  243. else if (s1 == 0)
  244. return 0; // both zero.
  245. bool neg = false;
  246. if (s1 >= 0)
  247. {
  248. s1 = eval_msb(num()) + eval_msb(o.denom());
  249. s2 = eval_msb(o.num()) + eval_msb(denom());
  250. }
  251. else
  252. {
  253. Backend t(num());
  254. t.negate();
  255. s1 = eval_msb(t) + eval_msb(o.denom());
  256. t = o.num();
  257. t.negate();
  258. s2 = eval_msb(t) + eval_msb(denom());
  259. neg = true;
  260. }
  261. s1 -= s2;
  262. if (s1 < -1)
  263. return neg ? 1 : -1;
  264. else if (s1 > 1)
  265. return neg ? -1 : 1;
  266. Backend t1, t2;
  267. eval_multiply(t1, num(), o.denom());
  268. eval_multiply(t2, o.num(), denom());
  269. return t1.compare(t2);
  270. }
  271. //
  272. // Comparison with arithmetic types, default just constructs a temporary:
  273. //
  274. template <class A>
  275. typename std::enable_if<boost::multiprecision::detail::is_arithmetic<A>::value, int>::type compare(A i) const
  276. {
  277. rational_adaptor t;
  278. t = i; // Note: construct directly from i if supported.
  279. return compare(t);
  280. }
  281. Backend& num() { return m_num; }
  282. const Backend& num()const { return m_num; }
  283. Backend& denom() { return m_denom; }
  284. const Backend& denom()const { return m_denom; }
  285. #ifndef BOOST_MP_STANDALONE
  286. template <class Archive>
  287. void serialize(Archive& ar, const std::integral_constant<bool, true>&)
  288. {
  289. // Saving
  290. number<Backend> n(num()), d(denom());
  291. ar& boost::make_nvp("numerator", n);
  292. ar& boost::make_nvp("denominator", d);
  293. }
  294. template <class Archive>
  295. void serialize(Archive& ar, const std::integral_constant<bool, false>&)
  296. {
  297. // Loading
  298. number<Backend> n, d;
  299. ar& boost::make_nvp("numerator", n);
  300. ar& boost::make_nvp("denominator", d);
  301. num() = n.backend();
  302. denom() = d.backend();
  303. }
  304. template <class Archive>
  305. void serialize(Archive& ar, const unsigned int /*version*/)
  306. {
  307. using tag = typename Archive::is_saving;
  308. using saving_tag = std::integral_constant<bool, tag::value>;
  309. serialize(ar, saving_tag());
  310. }
  311. #endif // BOOST_MP_STANDALONE
  312. private:
  313. Backend m_num, m_denom;
  314. };
  315. //
  316. // Helpers:
  317. //
  318. template <class T>
  319. inline constexpr typename std::enable_if<std::numeric_limits<T>::is_specialized && !std::numeric_limits<T>::is_signed, bool>::type
  320. is_minus_one(const T&)
  321. {
  322. return false;
  323. }
  324. template <class T>
  325. inline constexpr typename std::enable_if<!std::numeric_limits<T>::is_specialized || std::numeric_limits<T>::is_signed, bool>::type
  326. is_minus_one(const T& val)
  327. {
  328. return val == -1;
  329. }
  330. //
  331. // Required non-members:
  332. //
  333. template <class Backend>
  334. inline void eval_add(rational_adaptor<Backend>& a, const rational_adaptor<Backend>& b)
  335. {
  336. eval_add_subtract_imp(a, a, b, true);
  337. }
  338. template <class Backend>
  339. inline void eval_subtract(rational_adaptor<Backend>& a, const rational_adaptor<Backend>& b)
  340. {
  341. eval_add_subtract_imp(a, a, b, false);
  342. }
  343. template <class Backend>
  344. inline void eval_multiply(rational_adaptor<Backend>& a, const rational_adaptor<Backend>& b)
  345. {
  346. eval_multiply_imp(a, a, b.num(), b.denom());
  347. }
  348. template <class Backend>
  349. void eval_divide(rational_adaptor<Backend>& a, const rational_adaptor<Backend>& b)
  350. {
  351. using default_ops::eval_divide;
  352. rational_adaptor<Backend> t;
  353. eval_divide(t, a, b);
  354. a = std::move(t);
  355. }
  356. //
  357. // Conversions:
  358. //
  359. template <class R, class IntBackend>
  360. inline typename std::enable_if<number_category<R>::value == number_kind_floating_point>::type eval_convert_to(R* result, const rational_adaptor<IntBackend>& backend)
  361. {
  362. //
  363. // The generic conversion is as good as anything we can write here:
  364. //
  365. ::boost::multiprecision::detail::generic_convert_rational_to_float(*result, backend);
  366. }
  367. template <class R, class IntBackend>
  368. inline typename std::enable_if<(number_category<R>::value != number_kind_integer) && (number_category<R>::value != number_kind_floating_point) && !std::is_enum<R>::value>::type eval_convert_to(R* result, const rational_adaptor<IntBackend>& backend)
  369. {
  370. using default_ops::eval_convert_to;
  371. R d;
  372. eval_convert_to(result, backend.num());
  373. eval_convert_to(&d, backend.denom());
  374. *result /= d;
  375. }
  376. template <class R, class Backend>
  377. inline typename std::enable_if<number_category<R>::value == number_kind_integer>::type eval_convert_to(R* result, const rational_adaptor<Backend>& backend)
  378. {
  379. using default_ops::eval_divide;
  380. using default_ops::eval_convert_to;
  381. Backend t;
  382. eval_divide(t, backend.num(), backend.denom());
  383. eval_convert_to(result, t);
  384. }
  385. //
  386. // Hashing support, not strictly required, but it is used in our tests:
  387. //
  388. template <class Backend>
  389. inline std::size_t hash_value(const rational_adaptor<Backend>& arg)
  390. {
  391. std::size_t result = hash_value(arg.num());
  392. std::size_t result2 = hash_value(arg.denom());
  393. boost::multiprecision::detail::hash_combine(result, result2);
  394. return result;
  395. }
  396. //
  397. // assign_components:
  398. //
  399. template <class Backend>
  400. void assign_components(rational_adaptor<Backend>& result, Backend const& a, Backend const& b)
  401. {
  402. using default_ops::eval_gcd;
  403. using default_ops::eval_divide;
  404. using default_ops::eval_eq;
  405. using default_ops::eval_is_zero;
  406. using default_ops::eval_get_sign;
  407. if (eval_is_zero(b))
  408. {
  409. BOOST_MP_THROW_EXCEPTION(std::overflow_error("Integer division by zero"));
  410. }
  411. Backend g;
  412. eval_gcd(g, a, b);
  413. if (eval_eq(g, rational_adaptor<Backend>::one()))
  414. {
  415. result.num() = a;
  416. result.denom() = b;
  417. }
  418. else
  419. {
  420. eval_divide(result.num(), a, g);
  421. eval_divide(result.denom(), b, g);
  422. }
  423. if (eval_get_sign(result.denom()) < 0)
  424. {
  425. result.num().negate();
  426. result.denom().negate();
  427. }
  428. }
  429. //
  430. // Again for arithmetic types, overload for whatever arithmetic types are directly supported:
  431. //
  432. template <class Backend, class Arithmetic1, class Arithmetic2>
  433. inline void assign_components(rational_adaptor<Backend>& result, const Arithmetic1& a, typename std::enable_if<std::is_arithmetic<Arithmetic1>::value && std::is_arithmetic<Arithmetic2>::value, const Arithmetic2&>::type b)
  434. {
  435. using default_ops::eval_gcd;
  436. using default_ops::eval_divide;
  437. using default_ops::eval_eq;
  438. if (b == 0)
  439. {
  440. BOOST_MP_THROW_EXCEPTION(std::overflow_error("Integer division by zero"));
  441. }
  442. Backend g;
  443. result.num() = a;
  444. eval_gcd(g, result.num(), b);
  445. if (eval_eq(g, rational_adaptor<Backend>::one()))
  446. {
  447. result.denom() = b;
  448. }
  449. else
  450. {
  451. eval_divide(result.num(), g);
  452. eval_divide(result.denom(), b, g);
  453. }
  454. if (eval_get_sign(result.denom()) < 0)
  455. {
  456. result.num().negate();
  457. result.denom().negate();
  458. }
  459. }
  460. template <class Backend, class Arithmetic1, class Arithmetic2>
  461. inline void assign_components(rational_adaptor<Backend>& result, const Arithmetic1& a, typename std::enable_if<!std::is_arithmetic<Arithmetic1>::value || !std::is_arithmetic<Arithmetic2>::value, const Arithmetic2&>::type b)
  462. {
  463. using default_ops::eval_gcd;
  464. using default_ops::eval_divide;
  465. using default_ops::eval_eq;
  466. Backend g;
  467. result.num() = a;
  468. result.denom() = b;
  469. if (eval_get_sign(result.denom()) == 0)
  470. {
  471. BOOST_MP_THROW_EXCEPTION(std::overflow_error("Integer division by zero"));
  472. }
  473. eval_gcd(g, result.num(), result.denom());
  474. if (!eval_eq(g, rational_adaptor<Backend>::one()))
  475. {
  476. eval_divide(result.num(), g);
  477. eval_divide(result.denom(), g);
  478. }
  479. if (eval_get_sign(result.denom()) < 0)
  480. {
  481. result.num().negate();
  482. result.denom().negate();
  483. }
  484. }
  485. //
  486. // Optional comparison operators:
  487. //
  488. template <class Backend>
  489. inline bool eval_is_zero(const rational_adaptor<Backend>& arg)
  490. {
  491. using default_ops::eval_is_zero;
  492. return eval_is_zero(arg.num());
  493. }
  494. template <class Backend>
  495. inline int eval_get_sign(const rational_adaptor<Backend>& arg)
  496. {
  497. using default_ops::eval_get_sign;
  498. return eval_get_sign(arg.num());
  499. }
  500. template <class Backend>
  501. inline bool eval_eq(const rational_adaptor<Backend>& a, const rational_adaptor<Backend>& b)
  502. {
  503. using default_ops::eval_eq;
  504. return eval_eq(a.num(), b.num()) && eval_eq(a.denom(), b.denom());
  505. }
  506. template <class Backend, class Arithmetic>
  507. inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value&& std::is_integral<Arithmetic>::value, bool>::type
  508. eval_eq(const rational_adaptor<Backend>& a, Arithmetic b)
  509. {
  510. using default_ops::eval_eq;
  511. return eval_eq(a.denom(), rational_adaptor<Backend>::one()) && eval_eq(a.num(), b);
  512. }
  513. template <class Backend, class Arithmetic>
  514. inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value&& std::is_integral<Arithmetic>::value, bool>::type
  515. eval_eq(Arithmetic b, const rational_adaptor<Backend>& a)
  516. {
  517. using default_ops::eval_eq;
  518. return eval_eq(a.denom(), rational_adaptor<Backend>::one()) && eval_eq(a.num(), b);
  519. }
  520. //
  521. // Arithmetic operations, starting with addition:
  522. //
  523. template <class Backend, class Arithmetic>
  524. void eval_add_subtract_imp(rational_adaptor<Backend>& result, const Arithmetic& arg, bool isaddition)
  525. {
  526. using default_ops::eval_multiply;
  527. using default_ops::eval_divide;
  528. using default_ops::eval_add;
  529. using default_ops::eval_gcd;
  530. Backend t;
  531. eval_multiply(t, result.denom(), arg);
  532. if (isaddition)
  533. eval_add(result.num(), t);
  534. else
  535. eval_subtract(result.num(), t);
  536. //
  537. // There is no need to re-normalize here, we have
  538. // (a + bm) / b
  539. // and gcd(a + bm, b) = gcd(a, b) = 1
  540. //
  541. /*
  542. eval_gcd(t, result.num(), result.denom());
  543. if (!eval_eq(t, rational_adaptor<Backend>::one()) != 0)
  544. {
  545. Backend t2;
  546. eval_divide(t2, result.num(), t);
  547. t2.swap(result.num());
  548. eval_divide(t2, result.denom(), t);
  549. t2.swap(result.denom());
  550. }
  551. */
  552. }
  553. template <class Backend, class Arithmetic>
  554. inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && (std::is_integral<Arithmetic>::value || std::is_same<Arithmetic, Backend>::value)>::type
  555. eval_add(rational_adaptor<Backend>& result, const Arithmetic& arg)
  556. {
  557. eval_add_subtract_imp(result, arg, true);
  558. }
  559. template <class Backend, class Arithmetic>
  560. inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && (std::is_integral<Arithmetic>::value || std::is_same<Arithmetic, Backend>::value)>::type
  561. eval_subtract(rational_adaptor<Backend>& result, const Arithmetic& arg)
  562. {
  563. eval_add_subtract_imp(result, arg, false);
  564. }
  565. template <class Backend>
  566. void eval_add_subtract_imp(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, const rational_adaptor<Backend>& b, bool isaddition)
  567. {
  568. using default_ops::eval_eq;
  569. using default_ops::eval_multiply;
  570. using default_ops::eval_divide;
  571. using default_ops::eval_add;
  572. using default_ops::eval_subtract;
  573. //
  574. // Let a = an/ad
  575. // b = bn/bd
  576. // g = gcd(ad, bd)
  577. // result = rn/rd
  578. //
  579. // Then:
  580. // rn = an * (bd/g) + bn * (ad/g)
  581. // rd = ad * (bd/g)
  582. // = (ad/g) * (bd/g) * g
  583. //
  584. // And the whole thing can then be rescaled by
  585. // gcd(rn, g)
  586. //
  587. Backend gcd, t1, t2, t3, t4;
  588. //
  589. // Begin by getting the gcd of the 2 denominators:
  590. //
  591. eval_gcd(gcd, a.denom(), b.denom());
  592. //
  593. // Do we have gcd > 1:
  594. //
  595. if (!eval_eq(gcd, rational_adaptor<Backend>::one()))
  596. {
  597. //
  598. // Scale the denominators by gcd, and put the results in t1 and t2:
  599. //
  600. eval_divide(t1, b.denom(), gcd);
  601. eval_divide(t2, a.denom(), gcd);
  602. //
  603. // multiply the numerators by the scale denominators and put the results in t3, t4:
  604. //
  605. eval_multiply(t3, a.num(), t1);
  606. eval_multiply(t4, b.num(), t2);
  607. //
  608. // Add them up:
  609. //
  610. if (isaddition)
  611. eval_add(t3, t4);
  612. else
  613. eval_subtract(t3, t4);
  614. //
  615. // Get the gcd of gcd and our numerator (t3):
  616. //
  617. eval_gcd(t4, t3, gcd);
  618. if (eval_eq(t4, rational_adaptor<Backend>::one()))
  619. {
  620. result.num() = t3;
  621. eval_multiply(result.denom(), t1, a.denom());
  622. }
  623. else
  624. {
  625. //
  626. // Uncommon case where gcd is not 1, divide the numerator
  627. // and the denominator terms by the new gcd. Note we perform division
  628. // on the existing gcd value as this is the smallest of the 3 denominator
  629. // terms we'll be multiplying together, so there's a good chance it's a
  630. // single limb value already:
  631. //
  632. eval_divide(result.num(), t3, t4);
  633. eval_divide(t3, gcd, t4);
  634. eval_multiply(t4, t1, t2);
  635. eval_multiply(result.denom(), t4, t3);
  636. }
  637. }
  638. else
  639. {
  640. //
  641. // Most common case (approx 60%) where gcd is one:
  642. //
  643. eval_multiply(t1, a.num(), b.denom());
  644. eval_multiply(t2, a.denom(), b.num());
  645. if (isaddition)
  646. eval_add(result.num(), t1, t2);
  647. else
  648. eval_subtract(result.num(), t1, t2);
  649. eval_multiply(result.denom(), a.denom(), b.denom());
  650. }
  651. }
  652. template <class Backend>
  653. inline void eval_add(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, const rational_adaptor<Backend>& b)
  654. {
  655. eval_add_subtract_imp(result, a, b, true);
  656. }
  657. template <class Backend>
  658. inline void eval_subtract(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, const rational_adaptor<Backend>& b)
  659. {
  660. eval_add_subtract_imp(result, a, b, false);
  661. }
  662. template <class Backend, class Arithmetic>
  663. void eval_add_subtract_imp(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, const Arithmetic& b, bool isaddition)
  664. {
  665. using default_ops::eval_add;
  666. using default_ops::eval_subtract;
  667. using default_ops::eval_multiply;
  668. if (&result == &a)
  669. return eval_add_subtract_imp(result, b, isaddition);
  670. eval_multiply(result.num(), a.denom(), b);
  671. if (isaddition)
  672. eval_add(result.num(), a.num());
  673. else
  674. BOOST_IF_CONSTEXPR(std::numeric_limits<Backend>::is_signed == false)
  675. {
  676. Backend t;
  677. eval_subtract(t, a.num(), result.num());
  678. result.num() = std::move(t);
  679. }
  680. else
  681. {
  682. eval_subtract(result.num(), a.num());
  683. result.negate();
  684. }
  685. result.denom() = a.denom();
  686. //
  687. // There is no need to re-normalize here, we have
  688. // (a + bm) / b
  689. // and gcd(a + bm, b) = gcd(a, b) = 1
  690. //
  691. }
  692. template <class Backend, class Arithmetic>
  693. inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && (std::is_integral<Arithmetic>::value || std::is_same<Arithmetic, Backend>::value)>::type
  694. eval_add(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, const Arithmetic& b)
  695. {
  696. eval_add_subtract_imp(result, a, b, true);
  697. }
  698. template <class Backend, class Arithmetic>
  699. inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && (std::is_integral<Arithmetic>::value || std::is_same<Arithmetic, Backend>::value)>::type
  700. eval_subtract(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, const Arithmetic& b)
  701. {
  702. eval_add_subtract_imp(result, a, b, false);
  703. }
  704. //
  705. // Multiplication:
  706. //
  707. template <class Backend>
  708. void eval_multiply_imp(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, const Backend& b_num, const Backend& b_denom)
  709. {
  710. using default_ops::eval_multiply;
  711. using default_ops::eval_divide;
  712. using default_ops::eval_gcd;
  713. using default_ops::eval_get_sign;
  714. using default_ops::eval_eq;
  715. Backend gcd_left, gcd_right, t1, t2;
  716. eval_gcd(gcd_left, a.num(), b_denom);
  717. eval_gcd(gcd_right, b_num, a.denom());
  718. //
  719. // Unit gcd's are the most likely case:
  720. //
  721. bool b_left = eval_eq(gcd_left, rational_adaptor<Backend>::one());
  722. bool b_right = eval_eq(gcd_right, rational_adaptor<Backend>::one());
  723. if (b_left && b_right)
  724. {
  725. eval_multiply(result.num(), a.num(), b_num);
  726. eval_multiply(result.denom(), a.denom(), b_denom);
  727. }
  728. else if (b_left)
  729. {
  730. eval_divide(t2, b_num, gcd_right);
  731. eval_multiply(result.num(), a.num(), t2);
  732. eval_divide(t1, a.denom(), gcd_right);
  733. eval_multiply(result.denom(), t1, b_denom);
  734. }
  735. else if (b_right)
  736. {
  737. eval_divide(t1, a.num(), gcd_left);
  738. eval_multiply(result.num(), t1, b_num);
  739. eval_divide(t2, b_denom, gcd_left);
  740. eval_multiply(result.denom(), a.denom(), t2);
  741. }
  742. else
  743. {
  744. eval_divide(t1, a.num(), gcd_left);
  745. eval_divide(t2, b_num, gcd_right);
  746. eval_multiply(result.num(), t1, t2);
  747. eval_divide(t1, a.denom(), gcd_right);
  748. eval_divide(t2, b_denom, gcd_left);
  749. eval_multiply(result.denom(), t1, t2);
  750. }
  751. //
  752. // We may have b_denom negative if this is actually division, if so just correct things now:
  753. //
  754. if (eval_get_sign(b_denom) < 0)
  755. {
  756. result.num().negate();
  757. result.denom().negate();
  758. }
  759. }
  760. template <class Backend>
  761. void eval_multiply(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, const rational_adaptor<Backend>& b)
  762. {
  763. using default_ops::eval_multiply;
  764. if (&a == &b)
  765. {
  766. // squaring, gcd's are 1:
  767. eval_multiply(result.num(), a.num(), b.num());
  768. eval_multiply(result.denom(), a.denom(), b.denom());
  769. return;
  770. }
  771. eval_multiply_imp(result, a, b.num(), b.denom());
  772. }
  773. template <class Backend, class Arithmetic>
  774. void eval_multiply_imp(Backend& result_num, Backend& result_denom, Arithmetic arg)
  775. {
  776. if (arg == 0)
  777. {
  778. result_num = rational_adaptor<Backend>::zero();
  779. result_denom = rational_adaptor<Backend>::one();
  780. return;
  781. }
  782. else if (arg == 1)
  783. return;
  784. using default_ops::eval_multiply;
  785. using default_ops::eval_divide;
  786. using default_ops::eval_gcd;
  787. using default_ops::eval_convert_to;
  788. Backend gcd, t;
  789. Arithmetic integer_gcd;
  790. eval_gcd(gcd, result_denom, arg);
  791. eval_convert_to(&integer_gcd, gcd);
  792. arg /= integer_gcd;
  793. if (boost::multiprecision::detail::unsigned_abs(arg) > 1)
  794. {
  795. eval_multiply(t, result_num, arg);
  796. result_num = std::move(t);
  797. }
  798. else if (is_minus_one(arg))
  799. result_num.negate();
  800. if (integer_gcd > 1)
  801. {
  802. eval_divide(t, result_denom, integer_gcd);
  803. result_denom = std::move(t);
  804. }
  805. }
  806. template <class Backend>
  807. void eval_multiply_imp(Backend& result_num, Backend& result_denom, Backend arg)
  808. {
  809. using default_ops::eval_multiply;
  810. using default_ops::eval_divide;
  811. using default_ops::eval_gcd;
  812. using default_ops::eval_convert_to;
  813. using default_ops::eval_is_zero;
  814. using default_ops::eval_eq;
  815. using default_ops::eval_get_sign;
  816. if (eval_is_zero(arg))
  817. {
  818. result_num = rational_adaptor<Backend>::zero();
  819. result_denom = rational_adaptor<Backend>::one();
  820. return;
  821. }
  822. else if (eval_eq(arg, rational_adaptor<Backend>::one()))
  823. return;
  824. Backend gcd, t;
  825. eval_gcd(gcd, result_denom, arg);
  826. if (!eval_eq(gcd, rational_adaptor<Backend>::one()))
  827. {
  828. eval_divide(t, arg, gcd);
  829. arg = t;
  830. }
  831. else
  832. t = arg;
  833. if (eval_get_sign(arg) < 0)
  834. t.negate();
  835. if (!eval_eq(t, rational_adaptor<Backend>::one()))
  836. {
  837. eval_multiply(t, result_num, arg);
  838. result_num = std::move(t);
  839. }
  840. else if (eval_get_sign(arg) < 0)
  841. result_num.negate();
  842. if (!eval_eq(gcd, rational_adaptor<Backend>::one()))
  843. {
  844. eval_divide(t, result_denom, gcd);
  845. result_denom = std::move(t);
  846. }
  847. }
  848. template <class Backend, class Arithmetic>
  849. inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && (std::is_integral<Arithmetic>::value || std::is_same<Arithmetic, Backend>::value)>::type
  850. eval_multiply(rational_adaptor<Backend>& result, const Arithmetic& arg)
  851. {
  852. eval_multiply_imp(result.num(), result.denom(), arg);
  853. }
  854. template <class Backend, class Arithmetic>
  855. typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && std::is_integral<Arithmetic>::value>::type
  856. eval_multiply_imp(rational_adaptor<Backend>& result, const Backend& a_num, const Backend& a_denom, Arithmetic b)
  857. {
  858. if (b == 0)
  859. {
  860. result.num() = rational_adaptor<Backend>::zero();
  861. result.denom() = rational_adaptor<Backend>::one();
  862. return;
  863. }
  864. else if (b == 1)
  865. {
  866. result.num() = a_num;
  867. result.denom() = a_denom;
  868. return;
  869. }
  870. using default_ops::eval_multiply;
  871. using default_ops::eval_divide;
  872. using default_ops::eval_gcd;
  873. using default_ops::eval_convert_to;
  874. Backend gcd;
  875. Arithmetic integer_gcd;
  876. eval_gcd(gcd, a_denom, b);
  877. eval_convert_to(&integer_gcd, gcd);
  878. b /= integer_gcd;
  879. if (boost::multiprecision::detail::unsigned_abs(b) > 1)
  880. eval_multiply(result.num(), a_num, b);
  881. else if (is_minus_one(b))
  882. {
  883. result.num() = a_num;
  884. result.num().negate();
  885. }
  886. else
  887. result.num() = a_num;
  888. if (integer_gcd > 1)
  889. eval_divide(result.denom(), a_denom, integer_gcd);
  890. else
  891. result.denom() = a_denom;
  892. }
  893. template <class Backend>
  894. inline void eval_multiply_imp(rational_adaptor<Backend>& result, const Backend& a_num, const Backend& a_denom, const Backend& b)
  895. {
  896. result.num() = a_num;
  897. result.denom() = a_denom;
  898. eval_multiply_imp(result.num(), result.denom(), b);
  899. }
  900. template <class Backend, class Arithmetic>
  901. inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && (std::is_integral<Arithmetic>::value || std::is_same<Arithmetic, Backend>::value)>::type
  902. eval_multiply(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, const Arithmetic& b)
  903. {
  904. if (&result == &a)
  905. return eval_multiply(result, b);
  906. eval_multiply_imp(result, a.num(), a.denom(), b);
  907. }
  908. template <class Backend, class Arithmetic>
  909. inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && (std::is_integral<Arithmetic>::value || std::is_same<Arithmetic, Backend>::value)>::type
  910. eval_multiply(rational_adaptor<Backend>& result, const Arithmetic& b, const rational_adaptor<Backend>& a)
  911. {
  912. return eval_multiply(result, a, b);
  913. }
  914. //
  915. // Division:
  916. //
  917. template <class Backend>
  918. inline void eval_divide(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, const rational_adaptor<Backend>& b)
  919. {
  920. using default_ops::eval_multiply;
  921. using default_ops::eval_get_sign;
  922. if (eval_get_sign(b.num()) == 0)
  923. {
  924. BOOST_MP_THROW_EXCEPTION(std::overflow_error("Integer division by zero"));
  925. return;
  926. }
  927. if (&a == &b)
  928. {
  929. // Huh? Really?
  930. result.num() = result.denom() = rational_adaptor<Backend>::one();
  931. return;
  932. }
  933. if (&result == &b)
  934. {
  935. rational_adaptor<Backend> t(b);
  936. return eval_divide(result, a, t);
  937. }
  938. eval_multiply_imp(result, a, b.denom(), b.num());
  939. }
  940. template <class Backend, class Arithmetic>
  941. inline typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && (std::is_integral<Arithmetic>::value || std::is_same<Arithmetic, Backend>::value)>::type
  942. eval_divide(rational_adaptor<Backend>& result, const Arithmetic& b, const rational_adaptor<Backend>& a)
  943. {
  944. using default_ops::eval_get_sign;
  945. if (eval_get_sign(a.num()) == 0)
  946. {
  947. BOOST_MP_THROW_EXCEPTION(std::overflow_error("Integer division by zero"));
  948. return;
  949. }
  950. if (&a == &result)
  951. {
  952. eval_multiply_imp(result.denom(), result.num(), b);
  953. result.num().swap(result.denom());
  954. }
  955. else
  956. eval_multiply_imp(result, a.denom(), a.num(), b);
  957. if (eval_get_sign(result.denom()) < 0)
  958. {
  959. result.num().negate();
  960. result.denom().negate();
  961. }
  962. }
  963. template <class Backend, class Arithmetic>
  964. typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && std::is_integral<Arithmetic>::value>::type
  965. eval_divide(rational_adaptor<Backend>& result, Arithmetic arg)
  966. {
  967. if (arg == 0)
  968. {
  969. BOOST_MP_THROW_EXCEPTION(std::overflow_error("Integer division by zero"));
  970. return;
  971. }
  972. else if (arg == 1)
  973. return;
  974. else if (is_minus_one(arg))
  975. {
  976. result.negate();
  977. return;
  978. }
  979. if (eval_get_sign(result) == 0)
  980. {
  981. return;
  982. }
  983. using default_ops::eval_multiply;
  984. using default_ops::eval_gcd;
  985. using default_ops::eval_convert_to;
  986. using default_ops::eval_divide;
  987. Backend gcd, t;
  988. Arithmetic integer_gcd;
  989. eval_gcd(gcd, result.num(), arg);
  990. eval_convert_to(&integer_gcd, gcd);
  991. arg /= integer_gcd;
  992. eval_multiply(t, result.denom(), boost::multiprecision::detail::unsigned_abs(arg));
  993. result.denom() = std::move(t);
  994. if (arg < 0)
  995. {
  996. result.num().negate();
  997. }
  998. if (integer_gcd > 1)
  999. {
  1000. eval_divide(t, result.num(), integer_gcd);
  1001. result.num() = std::move(t);
  1002. }
  1003. }
  1004. template <class Backend>
  1005. void eval_divide(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, Backend arg)
  1006. {
  1007. using default_ops::eval_multiply;
  1008. using default_ops::eval_gcd;
  1009. using default_ops::eval_convert_to;
  1010. using default_ops::eval_divide;
  1011. using default_ops::eval_is_zero;
  1012. using default_ops::eval_eq;
  1013. using default_ops::eval_get_sign;
  1014. if (eval_is_zero(arg))
  1015. {
  1016. BOOST_MP_THROW_EXCEPTION(std::overflow_error("Integer division by zero"));
  1017. return;
  1018. }
  1019. else if (eval_eq(a, rational_adaptor<Backend>::one()) || (eval_get_sign(a) == 0))
  1020. {
  1021. if (&result != &a)
  1022. result = a;
  1023. result.denom() = arg;
  1024. return;
  1025. }
  1026. Backend gcd, u_arg, t;
  1027. eval_gcd(gcd, a.num(), arg);
  1028. bool has_unit_gcd = eval_eq(gcd, rational_adaptor<Backend>::one());
  1029. if (!has_unit_gcd)
  1030. {
  1031. eval_divide(u_arg, arg, gcd);
  1032. arg = u_arg;
  1033. }
  1034. else
  1035. u_arg = arg;
  1036. if (eval_get_sign(u_arg) < 0)
  1037. u_arg.negate();
  1038. eval_multiply(t, a.denom(), u_arg);
  1039. result.denom() = std::move(t);
  1040. if (!has_unit_gcd)
  1041. {
  1042. eval_divide(t, a.num(), gcd);
  1043. result.num() = std::move(t);
  1044. }
  1045. else if (&result != &a)
  1046. result.num() = a.num();
  1047. if (eval_get_sign(arg) < 0)
  1048. {
  1049. result.num().negate();
  1050. }
  1051. }
  1052. template <class Backend>
  1053. void eval_divide(rational_adaptor<Backend>& result, const Backend& arg)
  1054. {
  1055. eval_divide(result, result, arg);
  1056. }
  1057. template <class Backend, class Arithmetic>
  1058. typename std::enable_if<std::is_convertible<Arithmetic, Backend>::value && std::is_integral<Arithmetic>::value>::type
  1059. eval_divide(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& a, Arithmetic arg)
  1060. {
  1061. if (&result == &a)
  1062. return eval_divide(result, arg);
  1063. if (arg == 0)
  1064. {
  1065. BOOST_MP_THROW_EXCEPTION(std::overflow_error("Integer division by zero"));
  1066. return;
  1067. }
  1068. else if (arg == 1)
  1069. {
  1070. result = a;
  1071. return;
  1072. }
  1073. else if (is_minus_one(arg))
  1074. {
  1075. result = a;
  1076. result.num().negate();
  1077. return;
  1078. }
  1079. if (eval_get_sign(a) == 0)
  1080. {
  1081. result = a;
  1082. return;
  1083. }
  1084. using default_ops::eval_multiply;
  1085. using default_ops::eval_divide;
  1086. using default_ops::eval_gcd;
  1087. using default_ops::eval_convert_to;
  1088. Backend gcd;
  1089. Arithmetic integer_gcd;
  1090. eval_gcd(gcd, a.num(), arg);
  1091. eval_convert_to(&integer_gcd, gcd);
  1092. arg /= integer_gcd;
  1093. eval_multiply(result.denom(), a.denom(), boost::multiprecision::detail::unsigned_abs(arg));
  1094. if (integer_gcd > 1)
  1095. {
  1096. eval_divide(result.num(), a.num(), integer_gcd);
  1097. }
  1098. else
  1099. result.num() = a.num();
  1100. if (arg < 0)
  1101. {
  1102. result.num().negate();
  1103. }
  1104. }
  1105. //
  1106. // Increment and decrement:
  1107. //
  1108. template <class Backend>
  1109. inline void eval_increment(rational_adaptor<Backend>& arg)
  1110. {
  1111. using default_ops::eval_add;
  1112. eval_add(arg.num(), arg.denom());
  1113. }
  1114. template <class Backend>
  1115. inline void eval_decrement(rational_adaptor<Backend>& arg)
  1116. {
  1117. using default_ops::eval_subtract;
  1118. eval_subtract(arg.num(), arg.denom());
  1119. }
  1120. //
  1121. // abs:
  1122. //
  1123. template <class Backend>
  1124. inline void eval_abs(rational_adaptor<Backend>& result, const rational_adaptor<Backend>& arg)
  1125. {
  1126. using default_ops::eval_abs;
  1127. eval_abs(result.num(), arg.num());
  1128. result.denom() = arg.denom();
  1129. }
  1130. } // namespace backends
  1131. //
  1132. // Define a category for this number type, one of:
  1133. //
  1134. // number_kind_integer
  1135. // number_kind_floating_point
  1136. // number_kind_rational
  1137. // number_kind_fixed_point
  1138. // number_kind_complex
  1139. //
  1140. template<class Backend>
  1141. struct number_category<rational_adaptor<Backend> > : public std::integral_constant<int, number_kind_rational>
  1142. {};
  1143. template <class Backend, expression_template_option ExpressionTemplates>
  1144. struct component_type<number<rational_adaptor<Backend>, ExpressionTemplates> >
  1145. {
  1146. typedef number<Backend, ExpressionTemplates> type;
  1147. };
  1148. template <class IntBackend, expression_template_option ET>
  1149. inline number<IntBackend, ET> numerator(const number<rational_adaptor<IntBackend>, ET>& val)
  1150. {
  1151. return val.backend().num();
  1152. }
  1153. template <class IntBackend, expression_template_option ET>
  1154. inline number<IntBackend, ET> denominator(const number<rational_adaptor<IntBackend>, ET>& val)
  1155. {
  1156. return val.backend().denom();
  1157. }
  1158. template <class Backend>
  1159. struct is_unsigned_number<rational_adaptor<Backend> > : public is_unsigned_number<Backend>
  1160. {};
  1161. }} // namespace boost::multiprecision
  1162. namespace std {
  1163. template <class IntBackend, boost::multiprecision::expression_template_option ExpressionTemplates>
  1164. class numeric_limits<boost::multiprecision::number<boost::multiprecision::rational_adaptor<IntBackend>, ExpressionTemplates> > : public std::numeric_limits<boost::multiprecision::number<IntBackend, ExpressionTemplates> >
  1165. {
  1166. using base_type = std::numeric_limits<boost::multiprecision::number<IntBackend> >;
  1167. using number_type = boost::multiprecision::number<boost::multiprecision::rational_adaptor<IntBackend> >;
  1168. public:
  1169. static constexpr bool is_integer = false;
  1170. static constexpr bool is_exact = true;
  1171. static constexpr number_type(min)() { return (base_type::min)(); }
  1172. static constexpr number_type(max)() { return (base_type::max)(); }
  1173. static constexpr number_type lowest() { return -(max)(); }
  1174. static constexpr number_type epsilon() { return base_type::epsilon(); }
  1175. static constexpr number_type round_error() { return epsilon() / 2; }
  1176. static constexpr number_type infinity() { return base_type::infinity(); }
  1177. static constexpr number_type quiet_NaN() { return base_type::quiet_NaN(); }
  1178. static constexpr number_type signaling_NaN() { return base_type::signaling_NaN(); }
  1179. static constexpr number_type denorm_min() { return base_type::denorm_min(); }
  1180. };
  1181. template <class IntBackend, boost::multiprecision::expression_template_option ExpressionTemplates>
  1182. constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::rational_adaptor<IntBackend>, ExpressionTemplates> >::is_integer;
  1183. template <class IntBackend, boost::multiprecision::expression_template_option ExpressionTemplates>
  1184. constexpr bool numeric_limits<boost::multiprecision::number<boost::multiprecision::rational_adaptor<IntBackend>, ExpressionTemplates> >::is_exact;
  1185. } // namespace std
  1186. #endif