-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpolynomial.cpp
More file actions
185 lines (149 loc) · 4.76 KB
/
polynomial.cpp
File metadata and controls
185 lines (149 loc) · 4.76 KB
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
#include <polynomial.hpp>
Polynomial::Polynomial(std::vector<double> coefficients)
{
if (coefficients.size() == 0)
throw std::invalid_argument("There is no coefficient for this polynomial");
coefficients_ = coefficients;
order_ = coefficients_.size() - 1;
// check if the polynomial is null
for (double& coef : coefficients_)
{
if (coef == 0)
null_coeff_nb_++;
}
if (null_coeff_nb_ == order_ + 1)
throw std::invalid_argument("Can not instanciate a null polynomial (no operation to do on it)");
// find the first non null coefficient index
while (coefficients_[first_non_null_coef_index_] == 0)
{
first_non_null_coef_index_++;
}
}
Polynomial::Polynomial(const Polynomial& other)
{
this->coefficients_ = other.coefficients_;
this->roots_ = other.roots_;
this->first_non_null_coef_index_ = other.first_non_null_coef_index_;
this->order_ = other.order_;
this->null_coeff_nb_ = other.null_coeff_nb_;
}
double Polynomial::evaluate(const double& x)
{
double value = 0;
for (int i = 0; i <= order_; i++)
value += coefficients_[order_ - i] * std::pow(x, i);
return value;
}
void Polynomial::normalize()
{
double first_non_null_coeff = coefficients_[first_non_null_coef_index_];
for (double& element : coefficients_)
element /= first_non_null_coeff;
}
Eigen::VectorXcd Polynomial::compute_roots()
{
if (order_ == 0)
return Eigen::VectorXcd();
// construct the companion matrix for the polynomial (dynamic size)
Eigen::MatrixXd companion_matrix(order_, order_);
companion_matrix.setZero();
for (std::size_t i = 0; i < order_ - 1; i++)
companion_matrix(i + 1, i) = 1;
for (std::size_t i = 0; i < order_; i++)
companion_matrix(0, i) = -coefficients_[i+1] / coefficients_[first_non_null_coef_index_];
// solve for the eigen values that correspond to the roots of the monic polynomial
Eigen::EigenSolver<Eigen::MatrixXd> solver(companion_matrix);
Eigen::VectorXcd roots_= solver.eigenvalues();
return roots_;
}
Eigen::MatrixXd Polynomial::get_companion_matrix() const
{
Eigen::MatrixXd companion_matrix(order_, order_);
companion_matrix.setZero();
for (std::size_t i = 0; i < order_ - 1; i++)
companion_matrix(i + 1, i) = 1;
for (std::size_t i = 0; i < order_; i++)
companion_matrix(0, i) = -coefficients_[i + 1] / coefficients_[0];
return companion_matrix;
}
const double& Polynomial::get_coefficient(const std::size_t& index) const
{
if (0 <= index && index <= order_)
return coefficients_[index];
else
throw std::invalid_argument("The specified index is out of bounds");
}
std::ostream& operator<<(std::ostream& os, const Polynomial& polynomial)
{
os << std::setprecision(15);
os << "| Polynomial object at adress " << &polynomial << "\n";
os << "| Polynomial order: " << polynomial.order_ << "\n";
os << "| First non null coefficient index: " << polynomial.first_non_null_coef_index_ << "\n";
os << "| Number of null coefficients: " << polynomial.null_coeff_nb_ << "\n";
os << "| P(x) = ";
for (std::size_t i = 0; i < polynomial.order_ ; i++)
{
os << polynomial.coefficients_[i] << " * x^" << polynomial.order_ - i << " + ";
}
os << polynomial.coefficients_[polynomial.order_] << "\n";
return os;
}
double& Polynomial::operator[](std::size_t index)
{
if (0 <= index && index <= order_) \
{
return coefficients_[index];
}
else
{
throw std::out_of_range("Index out of range");
}
}
const double& Polynomial::operator[](std::size_t index) const {
if (0 <= index && index <= order_) \
{
return coefficients_[index];
}
else
{
throw std::out_of_range("Index out of range");
}
}
Polynomial& Polynomial::operator=(const Polynomial& other)
{
if (this == &other)
return *this;
this->coefficients_ = other.coefficients_;
this->roots_ = other.roots_;
this->first_non_null_coef_index_ = other.first_non_null_coef_index_;
this->order_ = other.first_non_null_coef_index_;
this->null_coeff_nb_ = other.null_coeff_nb_;
// Return a reference to the current object
return *this;
}
bool Polynomial::is_approx(const Polynomial& other, const double tolerance)
{
if (this == &other)
return true;
if (this->order_ != other.order_)
return false;
for (std::size_t i = 0; i < this->order_; i++)
if (this->coefficients_[i] - other.coefficients_[i] > tolerance)
return false;
return true;
}
bool Polynomial::operator==(const Polynomial& other)
{
if (this == &other)
return true;
if (this->order_ != other.order_)
return false;
for (std::size_t i = 0; i < this->order_; i++)
if (this->coefficients_[i] - other.coefficients_[i] > TOLERANCE)
return false;
return true;
}
bool Polynomial::operator!=(const Polynomial& other)
{
return !(*this==other);
}