constexpr_test_cpp_int_6.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. // (C) Copyright John Maddock 2019.
  2. // Use, modification and distribution are subject to the
  3. // Boost 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. #include "boost/multiprecision/cpp_int.hpp"
  6. #include "test.hpp"
  7. template <class T, unsigned Order>
  8. struct const_polynomial
  9. {
  10. public:
  11. T data[Order + 1];
  12. public:
  13. constexpr const_polynomial(T val = 0) : data{val} {}
  14. constexpr const_polynomial(const const_polynomial&) = default;
  15. constexpr const_polynomial(const std::initializer_list<T>& init) : data{}
  16. {
  17. if (init.size() > Order + 1)
  18. throw std::range_error("Too many initializers in list");
  19. for (unsigned i = 0; i < init.size(); ++i)
  20. data[i] = init.begin()[i];
  21. }
  22. constexpr T& operator[](std::size_t N)
  23. {
  24. return data[N];
  25. }
  26. constexpr const T& operator[](std::size_t N) const
  27. {
  28. return data[N];
  29. }
  30. template <class U>
  31. constexpr T operator()(U val) const
  32. {
  33. T result = data[Order];
  34. for (unsigned i = Order; i > 0; --i)
  35. {
  36. result *= val;
  37. result += data[i - 1];
  38. }
  39. return result;
  40. }
  41. constexpr const_polynomial<T, Order - 1> derivative() const
  42. {
  43. const_polynomial<T, Order - 1> result;
  44. for (unsigned i = 1; i <= Order; ++i)
  45. {
  46. result[i - 1] = (*this)[i] * i;
  47. }
  48. return result;
  49. }
  50. constexpr const_polynomial operator-()
  51. {
  52. const_polynomial t(*this);
  53. for (unsigned i = 0; i <= Order; ++i)
  54. t[i] = -t[i];
  55. return t;
  56. }
  57. template <class U>
  58. constexpr const_polynomial& operator*=(U val)
  59. {
  60. for (unsigned i = 0; i <= Order; ++i)
  61. data[i] = data[i] * val;
  62. return *this;
  63. }
  64. template <class U>
  65. constexpr const_polynomial& operator/=(U val)
  66. {
  67. for (unsigned i = 0; i <= Order; ++i)
  68. data[i] = data[i] / val;
  69. return *this;
  70. }
  71. template <class U>
  72. constexpr const_polynomial& operator+=(U val)
  73. {
  74. data[0] += val;
  75. return *this;
  76. }
  77. template <class U>
  78. constexpr const_polynomial& operator-=(U val)
  79. {
  80. data[0] -= val;
  81. return *this;
  82. }
  83. };
  84. template <class T, unsigned Order1, unsigned Order2>
  85. inline constexpr const_polynomial<T, (Order1 > Order2 ? Order1 : Order2)> operator+(const const_polynomial<T, Order1>& a, const const_polynomial<T, Order2>& b)
  86. {
  87. if
  88. constexpr(Order1 > Order2)
  89. {
  90. const_polynomial<T, Order1> result(a);
  91. for (unsigned i = 0; i <= Order2; ++i)
  92. result[i] += b[i];
  93. return result;
  94. }
  95. else
  96. {
  97. const_polynomial<T, Order2> result(b);
  98. for (unsigned i = 0; i <= Order1; ++i)
  99. result[i] += a[i];
  100. return result;
  101. }
  102. }
  103. template <class T, unsigned Order1, unsigned Order2>
  104. inline constexpr const_polynomial<T, (Order1 > Order2 ? Order1 : Order2)> operator-(const const_polynomial<T, Order1>& a, const const_polynomial<T, Order2>& b)
  105. {
  106. if
  107. constexpr(Order1 > Order2)
  108. {
  109. const_polynomial<T, Order1> result(a);
  110. for (unsigned i = 0; i <= Order2; ++i)
  111. result[i] -= b[i];
  112. return result;
  113. }
  114. else
  115. {
  116. const_polynomial<T, Order2> result(b);
  117. for (unsigned i = 0; i <= Order1; ++i)
  118. result[i] = a[i] - b[i];
  119. return result;
  120. }
  121. }
  122. template <class T, unsigned Order1, unsigned Order2>
  123. inline constexpr const_polynomial<T, Order1 + Order2> operator*(const const_polynomial<T, Order1>& a, const const_polynomial<T, Order2>& b)
  124. {
  125. const_polynomial<T, Order1 + Order2> result;
  126. for (unsigned i = 0; i <= Order1; ++i)
  127. {
  128. for (unsigned j = 0; j <= Order2; ++j)
  129. {
  130. result[i + j] += a[i] * b[j];
  131. }
  132. }
  133. return result;
  134. }
  135. template <class T, unsigned Order, class U>
  136. inline constexpr const_polynomial<T, Order> operator*(const const_polynomial<T, Order>& a, const U& b)
  137. {
  138. const_polynomial<T, Order> result(a);
  139. for (unsigned i = 0; i <= Order; ++i)
  140. {
  141. result[i] *= b;
  142. }
  143. return result;
  144. }
  145. template <class U, class T, unsigned Order>
  146. inline constexpr const_polynomial<T, Order> operator*(const U& b, const const_polynomial<T, Order>& a)
  147. {
  148. const_polynomial<T, Order> result(a);
  149. for (unsigned i = 0; i <= Order; ++i)
  150. {
  151. result[i] *= b;
  152. }
  153. return result;
  154. }
  155. template <class T, unsigned Order, class U>
  156. inline constexpr const_polynomial<T, Order> operator/(const const_polynomial<T, Order>& a, const U& b)
  157. {
  158. const_polynomial<T, Order> result;
  159. for (unsigned i = 0; i <= Order; ++i)
  160. {
  161. result[i] /= b;
  162. }
  163. return result;
  164. }
  165. template <class T, unsigned Order>
  166. class hermite_polynomial
  167. {
  168. const_polynomial<T, Order> m_data;
  169. public:
  170. constexpr hermite_polynomial() : m_data(hermite_polynomial<T, Order - 1>().data() * const_polynomial<T, 1>{0, 2} - hermite_polynomial<T, Order - 1>().data().derivative())
  171. {
  172. }
  173. constexpr const const_polynomial<T, Order>& data() const
  174. {
  175. return m_data;
  176. }
  177. constexpr const T& operator[](std::size_t N) const
  178. {
  179. return m_data[N];
  180. }
  181. template <class U>
  182. constexpr T operator()(U val) const
  183. {
  184. return m_data(val);
  185. }
  186. };
  187. template <class T>
  188. class hermite_polynomial<T, 0>
  189. {
  190. const_polynomial<T, 0> m_data;
  191. public:
  192. constexpr hermite_polynomial() : m_data{1} {}
  193. constexpr const const_polynomial<T, 0>& data() const
  194. {
  195. return m_data;
  196. }
  197. constexpr const T& operator[](std::size_t N) const
  198. {
  199. return m_data[N];
  200. }
  201. template <class U>
  202. constexpr T operator()(U val)
  203. {
  204. return m_data(val);
  205. }
  206. };
  207. template <class T>
  208. class hermite_polynomial<T, 1>
  209. {
  210. const_polynomial<T, 1> m_data;
  211. public:
  212. constexpr hermite_polynomial() : m_data{0, 2} {}
  213. constexpr const const_polynomial<T, 1>& data() const
  214. {
  215. return m_data;
  216. }
  217. constexpr const T& operator[](std::size_t N) const
  218. {
  219. return m_data[N];
  220. }
  221. template <class U>
  222. constexpr T operator()(U val)
  223. {
  224. return m_data(val);
  225. }
  226. };
  227. int main()
  228. {
  229. using namespace boost::multiprecision::literals;
  230. typedef boost::multiprecision::checked_int1024_t int_backend;
  231. // 8192 x^13 - 319488 x^11 + 4392960 x^9 - 26357760 x^7 + 69189120 x^5 - 69189120 x^3 + 17297280 x
  232. constexpr hermite_polynomial<int_backend, 13> h;
  233. static_assert(h[0] == 0);
  234. static_assert(h[1] == 17297280);
  235. static_assert(h[2] == 0);
  236. static_assert(h[3] == -69189120);
  237. static_assert(h[4] == 0);
  238. static_assert(h[5] == 69189120);
  239. static_assert(h[6] == 0);
  240. static_assert(h[7] == -26357760);
  241. static_assert(h[8] == 0);
  242. static_assert(h[9] == 4392960);
  243. static_assert(h[10] == 0);
  244. static_assert(h[11] == -319488);
  245. static_assert(h[12] == 0);
  246. static_assert(h[13] == 8192);
  247. return boost::report_errors();
  248. }