diff options
Diffstat (limited to 'src/boost/libs/math/example/polynomial_arithmetic.cpp')
-rw-r--r-- | src/boost/libs/math/example/polynomial_arithmetic.cpp | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/src/boost/libs/math/example/polynomial_arithmetic.cpp b/src/boost/libs/math/example/polynomial_arithmetic.cpp new file mode 100644 index 00000000..78efd06d --- /dev/null +++ b/src/boost/libs/math/example/polynomial_arithmetic.cpp @@ -0,0 +1,237 @@ +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt +// or copy at http://www.boost.org/LICENSE_1_0.txt) + +// Copyright Jeremy W. Murphy 2015. + +// This file is written to be included from a Quickbook .qbk document. +// It can be compiled by the C++ compiler, and run. Any output can +// also be added here as comment or included or pasted in elsewhere. +// Caution: this file contains Quickbook markup as well as code +// and comments: don't change any of the special comment markups! + +//[polynomial_arithmetic_0 +/*`First include the essential polynomial header (and others) to make the example: +*/ +#include <boost/math/tools/polynomial.hpp> +//] [polynomial_arithmetic_0 + +#include <boost/array.hpp> +#include <boost/lexical_cast.hpp> +#include <boost/assert.hpp> + +#include <iostream> +#include <stdexcept> +#include <cmath> +#include <string> +#include <utility> + +//[polynomial_arithmetic_1 +/*`and some using statements are convenient: +*/ + +using std::string; +using std::exception; +using std::cout; +using std::abs; +using std::pair; + +using namespace boost::math; +using namespace boost::math::tools; // for polynomial +using boost::lexical_cast; + +//] [/polynomial_arithmetic_1] + +template <typename T> +string sign_str(T const &x) +{ + return x < 0 ? "-" : "+"; +} + +template <typename T> +string inner_coefficient(T const &x) +{ + string result(" " + sign_str(x) + " "); + if (abs(x) != T(1)) + result += lexical_cast<string>(abs(x)); + return result; +} + +/*! Output in formula format. +For example: from a polynomial in Boost container storage [ 10, -6, -4, 3 ] +show as human-friendly formula notation: 3x^3 - 4x^2 - 6x + 10. +*/ +template <typename T> +string formula_format(polynomial<T> const &a) +{ + string result; + if (a.size() == 0) + result += lexical_cast<string>(T(0)); + else + { + // First one is a special case as it may need unary negate. + unsigned i = a.size() - 1; + if (a[i] < 0) + result += "-"; + if (abs(a[i]) != T(1)) + result += lexical_cast<string>(abs(a[i])); + + if (i > 0) + { + result += "x"; + if (i > 1) + { + result += "^" + lexical_cast<string>(i); + i--; + for (; i != 1; i--) + if (a[i]) + result += inner_coefficient(a[i]) + "x^" + lexical_cast<string>(i); + + if (a[i]) + result += inner_coefficient(a[i]) + "x"; + } + i--; + + if (a[i]) + result += " " + sign_str(a[i]) + " " + lexical_cast<string>(abs(a[i])); + } + } + return result; +} // string formula_format(polynomial<T> const &a) + + +int main() +{ + cout << "Example: Polynomial arithmetic.\n\n"; + + try + { +//[polynomial_arithmetic_2 +/*`Store the coefficients in a convenient way to access them, +then create some polynomials using construction from an iterator range, +and finally output in a 'pretty' formula format. + +[tip Although we might conventionally write a polynomial from left to right +in descending order of degree, Boost.Math stores in [*ascending order of degree].] + + Read/write for humans: 3x^3 - 4x^2 - 6x + 10 + Boost polynomial storage: [ 10, -6, -4, 3 ] +*/ + boost::array<double, 4> const d3a = {{10, -6, -4, 3}}; + polynomial<double> const a(d3a.begin(), d3a.end()); + + // With C++11 and later, you can also use initializer_list construction. + polynomial<double> const b{{-2.0, 1.0}}; + + // formula_format() converts from Boost storage to human notation. + cout << "a = " << formula_format(a) + << "\nb = " << formula_format(b) << "\n\n"; + +//] [/polynomial_arithmetic_2] + +//[polynomial_arithmetic_3 + // Now we can do arithmetic with the usual infix operators: + - * / and %. + polynomial<double> s = a + b; + cout << "a + b = " << formula_format(s) << "\n"; + polynomial<double> d = a - b; + cout << "a - b = " << formula_format(d) << "\n"; + polynomial<double> p = a * b; + cout << "a * b = " << formula_format(p) << "\n"; + polynomial<double> q = a / b; + cout << "a / b = " << formula_format(q) << "\n"; + polynomial<double> r = a % b; + cout << "a % b = " << formula_format(r) << "\n"; +//] [/polynomial_arithmetic_3] + +//[polynomial_arithmetic_4 +/*` +Division is a special case where you can calculate two for the price of one. + +Actually, quotient and remainder are always calculated together due to the nature +of the algorithm: the infix operators return one result and throw the other +away. + +If you are doing a lot of division and want both the quotient and remainder, then +you don't want to do twice the work necessary. + +In that case you can call the underlying function, [^quotient_remainder], +to get both results together as a pair. +*/ + pair< polynomial<double>, polynomial<double> > result; + result = quotient_remainder(a, b); +// Reassure ourselves that the result is the same. + BOOST_ASSERT(result.first == q); + BOOST_ASSERT(result.second == r); +//] [/polynomial_arithmetic_4] +//[polynomial_arithmetic_5 + /* +We can use the right and left shift operators to add and remove a factor of x. +This has the same semantics as left and right shift for integers where it is a +factor of 2. x is the smallest prime factor of a polynomial as is 2 for integers. +*/ + cout << "Right and left shift operators.\n"; + cout << "\n" << formula_format(p) << "\n"; + cout << "... right shift by 1 ...\n"; + p >>= 1; + cout << formula_format(p) << "\n"; + cout << "... left shift by 2 ...\n"; + p <<= 2; + cout << formula_format(p) << "\n"; + +/* +We can also give a meaning to odd and even for a polynomial that is consistent +with these operations: a polynomial is odd if it has a non-zero constant value, +even otherwise. That is: + x^2 + 1 odd + x^2 even + */ + cout << std::boolalpha; + cout << "\nPrint whether a polynomial is odd.\n"; + cout << formula_format(s) << " odd? " << odd(s) << "\n"; + // We cheekily use the internal details to subtract the constant, making it even. + s -= s.data().front(); + cout << formula_format(s) << " odd? " << odd(s) << "\n"; + // And of course you can check if it is even: + cout << formula_format(s) << " even? " << even(s) << "\n"; + + + //] [/polynomial_arithmetic_5] + //[polynomial_arithmetic_6] + /* For performance and convenience, we can test whether a polynomial is zero + * by implicitly converting to bool with the same semantics as int. */ + polynomial<double> zero; // Default construction is 0. + cout << "zero: " << (zero ? "not zero" : "zero") << "\n"; + cout << "r: " << (r ? "not zero" : "zero") << "\n"; + /* We can also set a polynomial to zero without needing a another zero + * polynomial to assign to it. */ + r.set_zero(); + cout << "r: " << (r ? "not zero" : "zero") << "\n"; + //] [/polynomial_arithmetic_6] +} +catch (exception const &e) +{ + cout << "\nMessage from thrown exception was:\n " << e.what() << "\n"; +} +} // int main() + +/* +//[polynomial_output_1 + +a = 3x^3 - 4x^2 - 6x + 10 +b = x - 2 + +//] [/polynomial_output_1] + + +//[polynomial_output_2 + +a + b = 3x^3 - 4x^2 - 5x + 8 +a - b = 3x^3 - 4x^2 - 7x + 12 +a * b = 3x^4 - 10x^3 + 2x^2 + 22x - 20 +a / b = 3x^2 + 2x - 2 +a % b = 6 + +//] [/polynomial_output_2] + +*/ |