polynomial_arithmetic.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. // Use, modification and distribution are subject to the
  2. // Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE_1_0.txt
  4. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. // Copyright Jeremy W. Murphy 2015.
  6. // This file is written to be included from a Quickbook .qbk document.
  7. // It can be compiled by the C++ compiler, and run. Any output can
  8. // also be added here as comment or included or pasted in elsewhere.
  9. // Caution: this file contains Quickbook markup as well as code
  10. // and comments: don't change any of the special comment markups!
  11. //[polynomial_arithmetic_0
  12. /*`First include the essential polynomial header (and others) to make the example:
  13. */
  14. #include <boost/math/tools/polynomial.hpp>
  15. //] [polynomial_arithmetic_0
  16. #include <boost/array.hpp>
  17. #include <boost/lexical_cast.hpp>
  18. #include <boost/assert.hpp>
  19. #include <iostream>
  20. #include <stdexcept>
  21. #include <cmath>
  22. #include <string>
  23. #include <utility>
  24. //[polynomial_arithmetic_1
  25. /*`and some using statements are convenient:
  26. */
  27. using std::string;
  28. using std::exception;
  29. using std::cout;
  30. using std::abs;
  31. using std::pair;
  32. using namespace boost::math;
  33. using namespace boost::math::tools; // for polynomial
  34. using boost::lexical_cast;
  35. //] [/polynomial_arithmetic_1]
  36. template <typename T>
  37. string sign_str(T const &x)
  38. {
  39. return x < 0 ? "-" : "+";
  40. }
  41. template <typename T>
  42. string inner_coefficient(T const &x)
  43. {
  44. string result(" " + sign_str(x) + " ");
  45. if (abs(x) != T(1))
  46. result += lexical_cast<string>(abs(x));
  47. return result;
  48. }
  49. /*! Output in formula format.
  50. For example: from a polynomial in Boost container storage [ 10, -6, -4, 3 ]
  51. show as human-friendly formula notation: 3x^3 - 4x^2 - 6x + 10.
  52. */
  53. template <typename T>
  54. string formula_format(polynomial<T> const &a)
  55. {
  56. string result;
  57. if (a.size() == 0)
  58. result += lexical_cast<string>(T(0));
  59. else
  60. {
  61. // First one is a special case as it may need unary negate.
  62. unsigned i = a.size() - 1;
  63. if (a[i] < 0)
  64. result += "-";
  65. if (abs(a[i]) != T(1))
  66. result += lexical_cast<string>(abs(a[i]));
  67. if (i > 0)
  68. {
  69. result += "x";
  70. if (i > 1)
  71. {
  72. result += "^" + lexical_cast<string>(i);
  73. i--;
  74. for (; i != 1; i--)
  75. if (a[i])
  76. result += inner_coefficient(a[i]) + "x^" + lexical_cast<string>(i);
  77. if (a[i])
  78. result += inner_coefficient(a[i]) + "x";
  79. }
  80. i--;
  81. if (a[i])
  82. result += " " + sign_str(a[i]) + " " + lexical_cast<string>(abs(a[i]));
  83. }
  84. }
  85. return result;
  86. } // string formula_format(polynomial<T> const &a)
  87. int main()
  88. {
  89. cout << "Example: Polynomial arithmetic.\n\n";
  90. try
  91. {
  92. //[polynomial_arithmetic_2
  93. /*`Store the coefficients in a convenient way to access them,
  94. then create some polynomials using construction from an iterator range,
  95. and finally output in a 'pretty' formula format.
  96. [tip Although we might conventionally write a polynomial from left to right
  97. in descending order of degree, Boost.Math stores in [*ascending order of degree].]
  98. Read/write for humans: 3x^3 - 4x^2 - 6x + 10
  99. Boost polynomial storage: [ 10, -6, -4, 3 ]
  100. */
  101. boost::array<double, 4> const d3a = {{10, -6, -4, 3}};
  102. polynomial<double> const a(d3a.begin(), d3a.end());
  103. // With C++11 and later, you can also use initializer_list construction.
  104. polynomial<double> const b{{-2.0, 1.0}};
  105. // formula_format() converts from Boost storage to human notation.
  106. cout << "a = " << formula_format(a)
  107. << "\nb = " << formula_format(b) << "\n\n";
  108. //] [/polynomial_arithmetic_2]
  109. //[polynomial_arithmetic_3
  110. // Now we can do arithmetic with the usual infix operators: + - * / and %.
  111. polynomial<double> s = a + b;
  112. cout << "a + b = " << formula_format(s) << "\n";
  113. polynomial<double> d = a - b;
  114. cout << "a - b = " << formula_format(d) << "\n";
  115. polynomial<double> p = a * b;
  116. cout << "a * b = " << formula_format(p) << "\n";
  117. polynomial<double> q = a / b;
  118. cout << "a / b = " << formula_format(q) << "\n";
  119. polynomial<double> r = a % b;
  120. cout << "a % b = " << formula_format(r) << "\n";
  121. //] [/polynomial_arithmetic_3]
  122. //[polynomial_arithmetic_4
  123. /*`
  124. Division is a special case where you can calculate two for the price of one.
  125. Actually, quotient and remainder are always calculated together due to the nature
  126. of the algorithm: the infix operators return one result and throw the other
  127. away.
  128. If you are doing a lot of division and want both the quotient and remainder, then
  129. you don't want to do twice the work necessary.
  130. In that case you can call the underlying function, [^quotient_remainder],
  131. to get both results together as a pair.
  132. */
  133. pair< polynomial<double>, polynomial<double> > result;
  134. result = quotient_remainder(a, b);
  135. // Reassure ourselves that the result is the same.
  136. BOOST_ASSERT(result.first == q);
  137. BOOST_ASSERT(result.second == r);
  138. //] [/polynomial_arithmetic_4]
  139. //[polynomial_arithmetic_5
  140. /*
  141. We can use the right and left shift operators to add and remove a factor of x.
  142. This has the same semantics as left and right shift for integers where it is a
  143. factor of 2. x is the smallest prime factor of a polynomial as is 2 for integers.
  144. */
  145. cout << "Right and left shift operators.\n";
  146. cout << "\n" << formula_format(p) << "\n";
  147. cout << "... right shift by 1 ...\n";
  148. p >>= 1;
  149. cout << formula_format(p) << "\n";
  150. cout << "... left shift by 2 ...\n";
  151. p <<= 2;
  152. cout << formula_format(p) << "\n";
  153. /*
  154. We can also give a meaning to odd and even for a polynomial that is consistent
  155. with these operations: a polynomial is odd if it has a non-zero constant value,
  156. even otherwise. That is:
  157. x^2 + 1 odd
  158. x^2 even
  159. */
  160. cout << std::boolalpha;
  161. cout << "\nPrint whether a polynomial is odd.\n";
  162. cout << formula_format(s) << " odd? " << odd(s) << "\n";
  163. // We cheekily use the internal details to subtract the constant, making it even.
  164. s -= s.data().front();
  165. cout << formula_format(s) << " odd? " << odd(s) << "\n";
  166. // And of course you can check if it is even:
  167. cout << formula_format(s) << " even? " << even(s) << "\n";
  168. //] [/polynomial_arithmetic_5]
  169. //[polynomial_arithmetic_6]
  170. /* For performance and convenience, we can test whether a polynomial is zero
  171. * by implicitly converting to bool with the same semantics as int. */
  172. polynomial<double> zero; // Default construction is 0.
  173. cout << "zero: " << (zero ? "not zero" : "zero") << "\n";
  174. cout << "r: " << (r ? "not zero" : "zero") << "\n";
  175. /* We can also set a polynomial to zero without needing a another zero
  176. * polynomial to assign to it. */
  177. r.set_zero();
  178. cout << "r: " << (r ? "not zero" : "zero") << "\n";
  179. //] [/polynomial_arithmetic_6]
  180. }
  181. catch (exception const &e)
  182. {
  183. cout << "\nMessage from thrown exception was:\n " << e.what() << "\n";
  184. }
  185. } // int main()
  186. /*
  187. //[polynomial_output_1
  188. a = 3x^3 - 4x^2 - 6x + 10
  189. b = x - 2
  190. //] [/polynomial_output_1]
  191. //[polynomial_output_2
  192. a + b = 3x^3 - 4x^2 - 5x + 8
  193. a - b = 3x^3 - 4x^2 - 7x + 12
  194. a * b = 3x^4 - 10x^3 + 2x^2 + 22x - 20
  195. a / b = 3x^2 + 2x - 2
  196. a % b = 6
  197. //] [/polynomial_output_2]
  198. */