366 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			366 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| 
								 | 
							
								///////////////////////////////////////////////////////////////
							 | 
						||
| 
								 | 
							
								//  Copyright 2011 John Maddock. Distributed under the Boost
							 | 
						||
| 
								 | 
							
								//  Software License, Version 1.0. (See accompanying file
							 | 
						||
| 
								 | 
							
								//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef BOOST_MATH_RATIONAL_ADAPTER_HPP
							 | 
						||
| 
								 | 
							
								#define BOOST_MATH_RATIONAL_ADAPTER_HPP
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <iostream>
							 | 
						||
| 
								 | 
							
								#include <iomanip>
							 | 
						||
| 
								 | 
							
								#include <sstream>
							 | 
						||
| 
								 | 
							
								#include <boost/cstdint.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/functional/hash_fwd.hpp>
							 | 
						||
| 
								 | 
							
								#include <boost/multiprecision/number.hpp>
							 | 
						||
| 
								 | 
							
								#ifdef BOOST_MSVC
							 | 
						||
| 
								 | 
							
								#  pragma warning(push)
							 | 
						||
| 
								 | 
							
								#  pragma warning(disable:4512 4127)
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								#include <boost/rational.hpp>
							 | 
						||
| 
								 | 
							
								#ifdef BOOST_MSVC
							 | 
						||
| 
								 | 
							
								#  pragma warning(pop)
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace boost{
							 | 
						||
| 
								 | 
							
								namespace multiprecision{
							 | 
						||
| 
								 | 
							
								namespace backends{
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <class IntBackend>
							 | 
						||
| 
								 | 
							
								struct rational_adaptor
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   typedef number<IntBackend>                integer_type;
							 | 
						||
| 
								 | 
							
								   typedef boost::rational<integer_type>        rational_type;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   typedef typename IntBackend::signed_types    signed_types;
							 | 
						||
| 
								 | 
							
								   typedef typename IntBackend::unsigned_types  unsigned_types;
							 | 
						||
| 
								 | 
							
								   typedef typename IntBackend::float_types     float_types;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   rational_adaptor() BOOST_MP_NOEXCEPT_IF(noexcept(rational_type())) {}
							 | 
						||
| 
								 | 
							
								   rational_adaptor(const rational_adaptor& o) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<rational_type&>() = std::declval<const rational_type&>()))
							 | 
						||
| 
								 | 
							
								   {
							 | 
						||
| 
								 | 
							
								      m_value = o.m_value;
							 | 
						||
| 
								 | 
							
								   }
							 | 
						||
| 
								 | 
							
								   rational_adaptor(const IntBackend& o) BOOST_MP_NOEXCEPT_IF(noexcept(rational_type(std::declval<const IntBackend&>()))) : m_value(o) {}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   template <class U>
							 | 
						||
| 
								 | 
							
								   rational_adaptor(const U& u, typename enable_if_c<is_convertible<U, IntBackend>::value>::type* = 0) 
							 | 
						||
| 
								 | 
							
								      : m_value(static_cast<integer_type>(u)){}
							 | 
						||
| 
								 | 
							
								   template <class U>
							 | 
						||
| 
								 | 
							
								   explicit rational_adaptor(const U& u, 
							 | 
						||
| 
								 | 
							
								      typename enable_if_c<
							 | 
						||
| 
								 | 
							
								         boost::multiprecision::detail::is_explicitly_convertible<U, IntBackend>::value && !is_convertible<U, IntBackend>::value
							 | 
						||
| 
								 | 
							
								      >::type* = 0) 
							 | 
						||
| 
								 | 
							
								      : m_value(IntBackend(u)){}
							 | 
						||
| 
								 | 
							
								   template <class U>
							 | 
						||
| 
								 | 
							
								   typename enable_if_c<(boost::multiprecision::detail::is_explicitly_convertible<U, IntBackend>::value && !is_arithmetic<U>::value), rational_adaptor&>::type operator = (const U& u) 
							 | 
						||
| 
								 | 
							
								   {
							 | 
						||
| 
								 | 
							
								      m_value = IntBackend(u);
							 | 
						||
| 
								 | 
							
								      return *this;
							 | 
						||
| 
								 | 
							
								   }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
							 | 
						||
| 
								 | 
							
								   rational_adaptor(rational_adaptor&& o) BOOST_MP_NOEXCEPT_IF(noexcept(rational_type(std::declval<rational_type>()))) : m_value(static_cast<rational_type&&>(o.m_value)) {}
							 | 
						||
| 
								 | 
							
								   rational_adaptor(IntBackend&& o) BOOST_MP_NOEXCEPT_IF(noexcept(rational_type(std::declval<IntBackend>()))) : m_value(static_cast<IntBackend&&>(o)) {}
							 | 
						||
| 
								 | 
							
								   rational_adaptor& operator = (rational_adaptor&& o) BOOST_MP_NOEXCEPT_IF(noexcept(std::declval<rational_type&>() = std::declval<rational_type>()))
							 | 
						||
| 
								 | 
							
								   {
							 | 
						||
| 
								 | 
							
								      m_value = static_cast<rational_type&&>(o.m_value);
							 | 
						||
| 
								 | 
							
								      return *this;
							 | 
						||
| 
								 | 
							
								   }
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								   rational_adaptor& operator = (const rational_adaptor& o)
							 | 
						||
| 
								 | 
							
								   {
							 | 
						||
| 
								 | 
							
								      m_value = o.m_value;
							 | 
						||
| 
								 | 
							
								      return *this;
							 | 
						||
| 
								 | 
							
								   }
							 | 
						||
| 
								 | 
							
								   rational_adaptor& operator = (const IntBackend& o)
							 | 
						||
| 
								 | 
							
								   {
							 | 
						||
| 
								 | 
							
								      m_value = o;
							 | 
						||
| 
								 | 
							
								      return *this;
							 | 
						||
| 
								 | 
							
								   }
							 | 
						||
| 
								 | 
							
								   template <class Int>
							 | 
						||
| 
								 | 
							
								   typename enable_if<is_integral<Int>, rational_adaptor&>::type operator = (Int i)
							 | 
						||
| 
								 | 
							
								   {
							 | 
						||
| 
								 | 
							
								      m_value = i;
							 | 
						||
| 
								 | 
							
								      return *this;
							 | 
						||
| 
								 | 
							
								   }
							 | 
						||
| 
								 | 
							
								   template <class Float>
							 | 
						||
| 
								 | 
							
								   typename enable_if<is_floating_point<Float>, rational_adaptor&>::type operator = (Float i)
							 | 
						||
| 
								 | 
							
								   {
							 | 
						||
| 
								 | 
							
								      int e;
							 | 
						||
| 
								 | 
							
								      Float f = std::frexp(i, &e);
							 | 
						||
| 
								 | 
							
								      f = std::ldexp(f, std::numeric_limits<Float>::digits);
							 | 
						||
| 
								 | 
							
								      e -= std::numeric_limits<Float>::digits;
							 | 
						||
| 
								 | 
							
								      integer_type num(f);
							 | 
						||
| 
								 | 
							
								      integer_type denom(1u);
							 | 
						||
| 
								 | 
							
								      if(e > 0)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								         num <<= e;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      else if(e < 0)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								         denom <<= -e;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      m_value.assign(num, denom);
							 | 
						||
| 
								 | 
							
								      return *this;
							 | 
						||
| 
								 | 
							
								   }
							 | 
						||
| 
								 | 
							
								   rational_adaptor& operator = (const char* s)
							 | 
						||
| 
								 | 
							
								   {
							 | 
						||
| 
								 | 
							
								      std::string s1;
							 | 
						||
| 
								 | 
							
								      multiprecision::number<IntBackend> v1, v2;
							 | 
						||
| 
								 | 
							
								      char c;
							 | 
						||
| 
								 | 
							
								      bool have_hex = false;
							 | 
						||
| 
								 | 
							
								      const char* p = s; // saved for later
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      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'))))
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								         if(c == 'x' || c == 'X')
							 | 
						||
| 
								 | 
							
								            have_hex = true;
							 | 
						||
| 
								 | 
							
								         s1.append(1, c);
							 | 
						||
| 
								 | 
							
								         ++s;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      v1.assign(s1);
							 | 
						||
| 
								 | 
							
								      s1.erase();
							 | 
						||
| 
								 | 
							
								      if(c == '/')
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								         ++s;
							 | 
						||
| 
								 | 
							
								         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'))))
							 | 
						||
| 
								 | 
							
								         {
							 | 
						||
| 
								 | 
							
								            if(c == 'x' || c == 'X')
							 | 
						||
| 
								 | 
							
								               have_hex = true;
							 | 
						||
| 
								 | 
							
								            s1.append(1, c);
							 | 
						||
| 
								 | 
							
								            ++s;
							 | 
						||
| 
								 | 
							
								         }
							 | 
						||
| 
								 | 
							
								         v2.assign(s1);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      else
							 | 
						||
| 
								 | 
							
								         v2 = 1;
							 | 
						||
| 
								 | 
							
								      if(*s)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								         BOOST_THROW_EXCEPTION(std::runtime_error(std::string("Could not parse the string \"") + p + std::string("\" as a valid rational number.")));
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      data().assign(v1, v2);
							 | 
						||
| 
								 | 
							
								      return *this;
							 | 
						||
| 
								 | 
							
								   }
							 | 
						||
| 
								 | 
							
								   void swap(rational_adaptor& o)
							 | 
						||
| 
								 | 
							
								   {
							 | 
						||
| 
								 | 
							
								      std::swap(m_value, o.m_value);
							 | 
						||
| 
								 | 
							
								   }
							 | 
						||
| 
								 | 
							
								   std::string str(std::streamsize digits, std::ios_base::fmtflags f)const
							 | 
						||
| 
								 | 
							
								   {
							 | 
						||
| 
								 | 
							
								      //
							 | 
						||
| 
								 | 
							
								      // We format the string ourselves so we can match what GMP's mpq type does:
							 | 
						||
| 
								 | 
							
								      //
							 | 
						||
| 
								 | 
							
								      std::string result = data().numerator().str(digits, f);
							 | 
						||
| 
								 | 
							
								      if(data().denominator() != 1)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								         result.append(1, '/');
							 | 
						||
| 
								 | 
							
								         result.append(data().denominator().str(digits, f));
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      return result;
							 | 
						||
| 
								 | 
							
								   }
							 | 
						||
| 
								 | 
							
								   void negate()
							 | 
						||
| 
								 | 
							
								   {
							 | 
						||
| 
								 | 
							
								      m_value = -m_value;
							 | 
						||
| 
								 | 
							
								   }
							 | 
						||
| 
								 | 
							
								   int compare(const rational_adaptor& o)const
							 | 
						||
| 
								 | 
							
								   {
							 | 
						||
| 
								 | 
							
								      return m_value > o.m_value ? 1 : (m_value < o.m_value ? -1 : 0);
							 | 
						||
| 
								 | 
							
								   }
							 | 
						||
| 
								 | 
							
								   template <class Arithmatic>
							 | 
						||
| 
								 | 
							
								   typename enable_if_c<is_arithmetic<Arithmatic>::value && !is_floating_point<Arithmatic>::value, int>::type compare(Arithmatic i)const
							 | 
						||
| 
								 | 
							
								   {
							 | 
						||
| 
								 | 
							
								      return m_value > i ? 1 : (m_value < i ? -1 : 0);
							 | 
						||
| 
								 | 
							
								   }
							 | 
						||
| 
								 | 
							
								   template <class Arithmatic>
							 | 
						||
| 
								 | 
							
								   typename enable_if_c<is_floating_point<Arithmatic>::value, int>::type compare(Arithmatic i)const
							 | 
						||
| 
								 | 
							
								   {
							 | 
						||
| 
								 | 
							
								      rational_adaptor r;
							 | 
						||
| 
								 | 
							
								      r = i;
							 | 
						||
| 
								 | 
							
								      return this->compare(r);
							 | 
						||
| 
								 | 
							
								   }
							 | 
						||
| 
								 | 
							
								   rational_type& data() { return m_value; }
							 | 
						||
| 
								 | 
							
								   const rational_type& data()const { return m_value; }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								   template <class Archive>
							 | 
						||
| 
								 | 
							
								   void serialize(Archive& ar, const mpl::true_&)
							 | 
						||
| 
								 | 
							
								   {
							 | 
						||
| 
								 | 
							
								      // Saving
							 | 
						||
| 
								 | 
							
								      integer_type n(m_value.numerator()), d(m_value.denominator());
							 | 
						||
| 
								 | 
							
								      ar & n;
							 | 
						||
| 
								 | 
							
								      ar & d;
							 | 
						||
| 
								 | 
							
								   }
							 | 
						||
| 
								 | 
							
								   template <class Archive>
							 | 
						||
| 
								 | 
							
								   void serialize(Archive& ar, const mpl::false_&)
							 | 
						||
| 
								 | 
							
								   {
							 | 
						||
| 
								 | 
							
								      // Loading
							 | 
						||
| 
								 | 
							
								      integer_type n, d;
							 | 
						||
| 
								 | 
							
								      ar & n;
							 | 
						||
| 
								 | 
							
								      ar & d;
							 | 
						||
| 
								 | 
							
								      m_value.assign(n, d);
							 | 
						||
| 
								 | 
							
								   }
							 | 
						||
| 
								 | 
							
								   template <class Archive>
							 | 
						||
| 
								 | 
							
								   void serialize(Archive& ar, const unsigned int /*version*/)
							 | 
						||
| 
								 | 
							
								   {
							 | 
						||
| 
								 | 
							
								      typedef typename Archive::is_saving tag;
							 | 
						||
| 
								 | 
							
								      serialize(ar, tag());
							 | 
						||
| 
								 | 
							
								   }
							 | 
						||
| 
								 | 
							
								private:
							 | 
						||
| 
								 | 
							
								   rational_type m_value;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <class IntBackend>
							 | 
						||
| 
								 | 
							
								inline void eval_add(rational_adaptor<IntBackend>& result, const rational_adaptor<IntBackend>& o)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   result.data() += o.data();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								template <class IntBackend>
							 | 
						||
| 
								 | 
							
								inline void eval_subtract(rational_adaptor<IntBackend>& result, const rational_adaptor<IntBackend>& o)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   result.data() -= o.data();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								template <class IntBackend>
							 | 
						||
| 
								 | 
							
								inline void eval_multiply(rational_adaptor<IntBackend>& result, const rational_adaptor<IntBackend>& o)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   result.data() *= o.data();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								template <class IntBackend>
							 | 
						||
| 
								 | 
							
								inline void eval_divide(rational_adaptor<IntBackend>& result, const rational_adaptor<IntBackend>& o)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   using default_ops::eval_is_zero;
							 | 
						||
| 
								 | 
							
								   if(eval_is_zero(o))
							 | 
						||
| 
								 | 
							
								   {
							 | 
						||
| 
								 | 
							
								      BOOST_THROW_EXCEPTION(std::overflow_error("Divide by zero."));
							 | 
						||
| 
								 | 
							
								   }
							 | 
						||
| 
								 | 
							
								   result.data() /= o.data();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <class R, class IntBackend>
							 | 
						||
| 
								 | 
							
								inline typename enable_if_c<number_category<R>::value == number_kind_floating_point>::type eval_convert_to(R* result, const rational_adaptor<IntBackend>& backend)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   //
							 | 
						||
| 
								 | 
							
								   // The generic conversion is as good as anything we can write here:
							 | 
						||
| 
								 | 
							
								   //
							 | 
						||
| 
								 | 
							
								   ::boost::multiprecision::detail::generic_convert_rational_to_float(*result, backend);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <class R, class IntBackend>
							 | 
						||
| 
								 | 
							
								inline typename enable_if_c<(number_category<R>::value != number_kind_integer) && (number_category<R>::value != number_kind_floating_point)>::type eval_convert_to(R* result, const rational_adaptor<IntBackend>& backend)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   typedef typename component_type<number<rational_adaptor<IntBackend> > >::type comp_t;
							 | 
						||
| 
								 | 
							
								   comp_t num(backend.data().numerator());
							 | 
						||
| 
								 | 
							
								   comp_t denom(backend.data().denominator());
							 | 
						||
| 
								 | 
							
								   *result = num.template convert_to<R>();
							 | 
						||
| 
								 | 
							
								   *result /= denom.template convert_to<R>();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <class R, class IntBackend>
							 | 
						||
| 
								 | 
							
								inline typename enable_if_c<number_category<R>::value == number_kind_integer>::type eval_convert_to(R* result, const rational_adaptor<IntBackend>& backend)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   typedef typename component_type<number<rational_adaptor<IntBackend> > >::type comp_t;
							 | 
						||
| 
								 | 
							
								   comp_t t = backend.data().numerator();
							 | 
						||
| 
								 | 
							
								   t /= backend.data().denominator();
							 | 
						||
| 
								 | 
							
								   *result = t.template convert_to<R>();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <class IntBackend>
							 | 
						||
| 
								 | 
							
								inline bool eval_is_zero(const rational_adaptor<IntBackend>& val)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   return eval_is_zero(val.data().numerator().backend());
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								template <class IntBackend>
							 | 
						||
| 
								 | 
							
								inline int eval_get_sign(const rational_adaptor<IntBackend>& val)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   return eval_get_sign(val.data().numerator().backend());
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template<class IntBackend, class V>
							 | 
						||
| 
								 | 
							
								inline void assign_components(rational_adaptor<IntBackend>& result, const V& v1, const V& v2)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   result.data().assign(v1, v2);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <class IntBackend>
							 | 
						||
| 
								 | 
							
								inline std::size_t hash_value(const rational_adaptor<IntBackend>& val)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   std::size_t result = hash_value(val.data().numerator());
							 | 
						||
| 
								 | 
							
								   boost::hash_combine(result, val.data().denominator());
							 | 
						||
| 
								 | 
							
								   return result;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								} // namespace backends
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template<class IntBackend>
							 | 
						||
| 
								 | 
							
								struct expression_template_default<backends::rational_adaptor<IntBackend> > : public expression_template_default<IntBackend> {};
							 | 
						||
| 
								 | 
							
								   
							 | 
						||
| 
								 | 
							
								template<class IntBackend>
							 | 
						||
| 
								 | 
							
								struct number_category<backends::rational_adaptor<IntBackend> > : public mpl::int_<number_kind_rational>{};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								using boost::multiprecision::backends::rational_adaptor;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <class T>
							 | 
						||
| 
								 | 
							
								struct component_type<rational_adaptor<T> >
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   typedef number<T> type;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <class IntBackend, expression_template_option ET>
							 | 
						||
| 
								 | 
							
								inline number<IntBackend, ET> numerator(const number<rational_adaptor<IntBackend>, ET>& val)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   return val.backend().data().numerator();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								template <class IntBackend, expression_template_option ET>
							 | 
						||
| 
								 | 
							
								inline number<IntBackend, ET> denominator(const number<rational_adaptor<IntBackend>, ET>& val)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   return val.backend().data().denominator();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifdef BOOST_NO_SFINAE_EXPR
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace detail{
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template<class U, class IntBackend>
							 | 
						||
| 
								 | 
							
								struct is_explicitly_convertible<U, rational_adaptor<IntBackend> > : public is_explicitly_convertible<U, IntBackend> {};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}} // namespaces
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace std{
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <class IntBackend, boost::multiprecision::expression_template_option ExpressionTemplates>
							 | 
						||
| 
								 | 
							
								class numeric_limits<boost::multiprecision::number<boost::multiprecision::rational_adaptor<IntBackend>, ExpressionTemplates> > : public std::numeric_limits<boost::multiprecision::number<IntBackend, ExpressionTemplates> >
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								   typedef std::numeric_limits<boost::multiprecision::number<IntBackend> > base_type;
							 | 
						||
| 
								 | 
							
								   typedef boost::multiprecision::number<boost::multiprecision::rational_adaptor<IntBackend> > number_type;
							 | 
						||
| 
								 | 
							
								public:
							 | 
						||
| 
								 | 
							
								   BOOST_STATIC_CONSTEXPR bool is_integer = false;
							 | 
						||
| 
								 | 
							
								   BOOST_STATIC_CONSTEXPR bool is_exact = true;
							 | 
						||
| 
								 | 
							
								   BOOST_STATIC_CONSTEXPR number_type (min)() { return (base_type::min)(); }
							 | 
						||
| 
								 | 
							
								   BOOST_STATIC_CONSTEXPR number_type (max)() { return (base_type::max)(); }
							 | 
						||
| 
								 | 
							
								   BOOST_STATIC_CONSTEXPR number_type lowest() { return -(max)(); }
							 | 
						||
| 
								 | 
							
								   BOOST_STATIC_CONSTEXPR number_type epsilon() { return base_type::epsilon(); }
							 | 
						||
| 
								 | 
							
								   BOOST_STATIC_CONSTEXPR number_type round_error() { return epsilon() / 2; }
							 | 
						||
| 
								 | 
							
								   BOOST_STATIC_CONSTEXPR number_type infinity() { return base_type::infinity(); }
							 | 
						||
| 
								 | 
							
								   BOOST_STATIC_CONSTEXPR number_type quiet_NaN() { return base_type::quiet_NaN(); }
							 | 
						||
| 
								 | 
							
								   BOOST_STATIC_CONSTEXPR number_type signaling_NaN() { return base_type::signaling_NaN(); }
							 | 
						||
| 
								 | 
							
								   BOOST_STATIC_CONSTEXPR number_type denorm_min() { return base_type::denorm_min(); }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								template <class IntBackend, boost::multiprecision::expression_template_option ExpressionTemplates>
							 | 
						||
| 
								 | 
							
								BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::rational_adaptor<IntBackend>, ExpressionTemplates> >::is_integer;
							 | 
						||
| 
								 | 
							
								template <class IntBackend, boost::multiprecision::expression_template_option ExpressionTemplates>
							 | 
						||
| 
								 | 
							
								BOOST_CONSTEXPR_OR_CONST bool numeric_limits<boost::multiprecision::number<boost::multiprecision::rational_adaptor<IntBackend>, ExpressionTemplates> >::is_exact;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#endif
							 |