mp_number_archetypes.hpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  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 https://www.boost.org/LICENSE_1_0.txt
  5. #ifndef BOOST_MATH_CONCEPTS_ER_HPP
  6. #define BOOST_MATH_CONCEPTS_ER_HPP
  7. #include <iostream>
  8. #include <sstream>
  9. #include <iomanip>
  10. #include <cmath>
  11. #include <boost/cstdint.hpp>
  12. #include <boost/multiprecision/number.hpp>
  13. #include <boost/math/special_functions/fpclassify.hpp>
  14. #include <boost/mpl/list.hpp>
  15. #include <boost/container_hash/hash.hpp>
  16. namespace boost {
  17. namespace multiprecision {
  18. namespace concepts {
  19. #ifdef BOOST_MSVC
  20. #pragma warning(push)
  21. #pragma warning(disable : 4244)
  22. #endif
  23. struct number_backend_float_architype
  24. {
  25. typedef mpl::list<boost::long_long_type> signed_types;
  26. typedef mpl::list<boost::ulong_long_type> unsigned_types;
  27. typedef mpl::list<long double> float_types;
  28. typedef int exponent_type;
  29. number_backend_float_architype()
  30. {
  31. m_value = 0;
  32. std::cout << "Default construct" << std::endl;
  33. }
  34. number_backend_float_architype(const number_backend_float_architype& o)
  35. {
  36. std::cout << "Copy construct" << std::endl;
  37. m_value = o.m_value;
  38. }
  39. number_backend_float_architype& operator=(const number_backend_float_architype& o)
  40. {
  41. m_value = o.m_value;
  42. std::cout << "Assignment (" << m_value << ")" << std::endl;
  43. return *this;
  44. }
  45. number_backend_float_architype& operator=(boost::ulong_long_type i)
  46. {
  47. m_value = i;
  48. std::cout << "UInt Assignment (" << i << ")" << std::endl;
  49. return *this;
  50. }
  51. number_backend_float_architype& operator=(boost::long_long_type i)
  52. {
  53. m_value = i;
  54. std::cout << "Int Assignment (" << i << ")" << std::endl;
  55. return *this;
  56. }
  57. number_backend_float_architype& operator=(long double d)
  58. {
  59. m_value = d;
  60. std::cout << "long double Assignment (" << d << ")" << std::endl;
  61. return *this;
  62. }
  63. number_backend_float_architype& operator=(const char* s)
  64. {
  65. #ifndef BOOST_NO_EXCEPTIONS
  66. try
  67. {
  68. #endif
  69. m_value = boost::lexical_cast<long double>(s);
  70. #ifndef BOOST_NO_EXCEPTIONS
  71. }
  72. catch (const std::exception&)
  73. {
  74. BOOST_THROW_EXCEPTION(std::runtime_error(std::string("Unable to parse input string: \"") + s + std::string("\" as a valid floating point number.")));
  75. }
  76. #endif
  77. std::cout << "const char* Assignment (" << s << ")" << std::endl;
  78. return *this;
  79. }
  80. void swap(number_backend_float_architype& o)
  81. {
  82. std::cout << "Swapping (" << m_value << " with " << o.m_value << ")" << std::endl;
  83. std::swap(m_value, o.m_value);
  84. }
  85. std::string str(std::streamsize digits, std::ios_base::fmtflags f) const
  86. {
  87. std::stringstream ss;
  88. ss.flags(f);
  89. if (digits)
  90. ss.precision(digits);
  91. else
  92. ss.precision(std::numeric_limits<long double>::digits10 + 3);
  93. boost::intmax_t i = m_value;
  94. boost::uintmax_t u = m_value;
  95. if (!(f & std::ios_base::scientific) && m_value == i)
  96. ss << i;
  97. else if (!(f & std::ios_base::scientific) && m_value == u)
  98. ss << u;
  99. else
  100. ss << m_value;
  101. std::string s = ss.str();
  102. std::cout << "Converting to string (" << s << ")" << std::endl;
  103. return s;
  104. }
  105. void negate()
  106. {
  107. std::cout << "Negating (" << m_value << ")" << std::endl;
  108. m_value = -m_value;
  109. }
  110. int compare(const number_backend_float_architype& o) const
  111. {
  112. std::cout << "Comparison" << std::endl;
  113. return m_value > o.m_value ? 1 : (m_value < o.m_value ? -1 : 0);
  114. }
  115. int compare(boost::long_long_type i) const
  116. {
  117. std::cout << "Comparison with int" << std::endl;
  118. return m_value > i ? 1 : (m_value < i ? -1 : 0);
  119. }
  120. int compare(boost::ulong_long_type i) const
  121. {
  122. std::cout << "Comparison with unsigned" << std::endl;
  123. return m_value > i ? 1 : (m_value < i ? -1 : 0);
  124. }
  125. int compare(long double d) const
  126. {
  127. std::cout << "Comparison with long double" << std::endl;
  128. return m_value > d ? 1 : (m_value < d ? -1 : 0);
  129. }
  130. long double m_value;
  131. };
  132. inline void eval_add(number_backend_float_architype& result, const number_backend_float_architype& o)
  133. {
  134. std::cout << "Addition (" << result.m_value << " += " << o.m_value << ")" << std::endl;
  135. result.m_value += o.m_value;
  136. }
  137. inline void eval_subtract(number_backend_float_architype& result, const number_backend_float_architype& o)
  138. {
  139. std::cout << "Subtraction (" << result.m_value << " -= " << o.m_value << ")" << std::endl;
  140. result.m_value -= o.m_value;
  141. }
  142. inline void eval_multiply(number_backend_float_architype& result, const number_backend_float_architype& o)
  143. {
  144. std::cout << "Multiplication (" << result.m_value << " *= " << o.m_value << ")" << std::endl;
  145. result.m_value *= o.m_value;
  146. }
  147. inline void eval_divide(number_backend_float_architype& result, const number_backend_float_architype& o)
  148. {
  149. std::cout << "Division (" << result.m_value << " /= " << o.m_value << ")" << std::endl;
  150. result.m_value /= o.m_value;
  151. }
  152. inline void eval_convert_to(boost::ulong_long_type* result, const number_backend_float_architype& val)
  153. {
  154. *result = static_cast<boost::ulong_long_type>(val.m_value);
  155. }
  156. inline void eval_convert_to(boost::long_long_type* result, const number_backend_float_architype& val)
  157. {
  158. *result = static_cast<boost::long_long_type>(val.m_value);
  159. }
  160. inline void eval_convert_to(long double* result, number_backend_float_architype& val)
  161. {
  162. *result = val.m_value;
  163. }
  164. inline void eval_frexp(number_backend_float_architype& result, const number_backend_float_architype& arg, int* exp)
  165. {
  166. result = std::frexp(arg.m_value, exp);
  167. }
  168. inline void eval_ldexp(number_backend_float_architype& result, const number_backend_float_architype& arg, int exp)
  169. {
  170. result = std::ldexp(arg.m_value, exp);
  171. }
  172. inline void eval_floor(number_backend_float_architype& result, const number_backend_float_architype& arg)
  173. {
  174. result = std::floor(arg.m_value);
  175. }
  176. inline void eval_ceil(number_backend_float_architype& result, const number_backend_float_architype& arg)
  177. {
  178. result = std::ceil(arg.m_value);
  179. }
  180. inline void eval_sqrt(number_backend_float_architype& result, const number_backend_float_architype& arg)
  181. {
  182. result = std::sqrt(arg.m_value);
  183. }
  184. inline int eval_fpclassify(const number_backend_float_architype& arg)
  185. {
  186. return (boost::math::fpclassify)(arg.m_value);
  187. }
  188. inline std::size_t hash_value(const number_backend_float_architype& v)
  189. {
  190. boost::hash<long double> hasher;
  191. return hasher(v.m_value);
  192. }
  193. typedef boost::multiprecision::number<number_backend_float_architype> mp_number_float_architype;
  194. } // namespace concepts
  195. template <>
  196. struct number_category<concepts::number_backend_float_architype> : public mpl::int_<number_kind_floating_point>
  197. {};
  198. }} // namespace boost::multiprecision
  199. namespace std {
  200. template <boost::multiprecision::expression_template_option ExpressionTemplates>
  201. class numeric_limits<boost::multiprecision::number<boost::multiprecision::concepts::number_backend_float_architype, ExpressionTemplates> > : public std::numeric_limits<long double>
  202. {
  203. typedef std::numeric_limits<long double> base_type;
  204. typedef boost::multiprecision::number<boost::multiprecision::concepts::number_backend_float_architype, ExpressionTemplates> number_type;
  205. public:
  206. static number_type(min)() BOOST_NOEXCEPT { return (base_type::min)(); }
  207. static number_type(max)() BOOST_NOEXCEPT { return (base_type::max)(); }
  208. static number_type lowest() BOOST_NOEXCEPT { return -(max)(); }
  209. static number_type epsilon() BOOST_NOEXCEPT { return base_type::epsilon(); }
  210. static number_type round_error() BOOST_NOEXCEPT { return base_type::round_error(); }
  211. static number_type infinity() BOOST_NOEXCEPT { return base_type::infinity(); }
  212. static number_type quiet_NaN() BOOST_NOEXCEPT { return base_type::quiet_NaN(); }
  213. static number_type signaling_NaN() BOOST_NOEXCEPT { return base_type::signaling_NaN(); }
  214. static number_type denorm_min() BOOST_NOEXCEPT { return base_type::denorm_min(); }
  215. };
  216. } // namespace std
  217. #ifdef BOOST_MSVC
  218. #pragma warning(pop)
  219. #endif
  220. #endif