1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
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]
*/
|