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