sokobo
Loading...
Searching...
No Matches
polynomial.cpp
1#include "include/polynomial.h"
2#include <algorithm>
3#include <cmath>
4#include <sstream>
5#include <stdexcept>
6
7#include "include/polynomial.h"
8
9Polynomial::Polynomial(const std::vector<double>& coeffs)
10 : coefficients(coeffs)
11{
12 removeLeadingZeros();
13}
14
15Polynomial::Polynomial(double constant)
16{
17 coefficients.push_back(constant);
18}
19
20void Polynomial::removeLeadingZeros()
21{
22 while (coefficients.size() > 1 && std::abs(coefficients.back()) < 1e-10) {
23 coefficients.pop_back();
24 }
25 if (coefficients.empty()) {
26 coefficients.push_back(0);
27 }
28}
29
30int Polynomial::degree() const
31{
32 return static_cast<int>(coefficients.size()) - 1;
33}
34
35double Polynomial::getCoeff(int i) const
36{
37 if (i < 0 || i >= static_cast<int>(coefficients.size())) {
38 return 0;
39 }
40 return coefficients[i];
41}
42
43void Polynomial::setCoeff(int i, double val)
44{
45 if (i < 0) {
46 return;
47 }
48 if (i >= static_cast<int>(coefficients.size())) {
49 coefficients.resize(i + 1, 0);
50 }
51 coefficients[i] = val;
52 removeLeadingZeros();
53}
54
55int Polynomial::getDegree() const
56{
57 return 0;
58}
59
60Polynomial Polynomial::operator+(const Polynomial& other) const
61{
62 int maxDegree = std::max(degree(), other.degree());
63 std::vector<double> result(maxDegree + 1, 0);
64
65 for (int i = 0; i <= maxDegree; i++) {
66 result[i] = getCoeff(i) + other.getCoeff(i);
67 }
68
69 return Polynomial(result);
70}
71
72Polynomial Polynomial::operator-(const Polynomial& other) const
73{
74 int maxDegree = std::max(degree(), other.degree());
75 std::vector<double> result(maxDegree + 1, 0);
76
77 for (int i = 0; i <= maxDegree; i++) {
78 result[i] = getCoeff(i) - other.getCoeff(i);
79 }
80
81 return Polynomial(result);
82}
83
84Polynomial Polynomial::operator*(const Polynomial& other) const
85{
86 if (degree() == 0 && std::abs(getCoeff(0)) < 1e-10) {
87 return Polynomial(0);
88 }
89 if (other.degree() == 0 && std::abs(other.getCoeff(0)) < 1e-10) {
90 return Polynomial(0);
91 }
92
93 int resultDegree = degree() + other.degree();
94 std::vector<double> result(resultDegree + 1, 0);
95
96 for (int i = 0; i <= degree(); i++) {
97 for (int j = 0; j <= other.degree(); j++) {
98 result[i + j] += getCoeff(i) * other.getCoeff(j);
99 }
100 }
101
102 return Polynomial(result);
103}
104
105std::pair<Polynomial, Polynomial> Polynomial::divide(
106 const Polynomial& divisor) const
107{
108 if (divisor.degree() == 0 && std::abs(divisor.getCoeff(0)) < 1e-10) {
109 throw std::runtime_error("Division by zero polynomial");
110 }
111
112 Polynomial dividend = *this;
113 Polynomial quotient(0);
114
115 while (dividend.degree() >= divisor.degree()
116 && !(dividend.degree() == 0 && std::abs(dividend.getCoeff(0)) < 1e-10))
117 {
118 double leadCoeff =
119 dividend.coefficients.back() / divisor.coefficients.back();
120 int degreeDiff = dividend.degree() - divisor.degree();
121
122 std::vector<double> termCoeffs(degreeDiff + 1, 0);
123 termCoeffs[degreeDiff] = leadCoeff;
124 Polynomial term(termCoeffs);
125
126 quotient = quotient + term;
127 dividend = dividend - (term * divisor);
128 }
129
130 return {quotient, dividend};
131}
132
133Polynomial Polynomial::gcd(const Polynomial& other) const
134{
135 Polynomial a = *this;
136 Polynomial b = other;
137
138 while (!(b.degree() == 0 && std::abs(b.getCoeff(0)) < 1e-10)) {
139 auto division = a.divide(b);
140 a = b;
141 b = division.second;
142 }
143
144 return a;
145}
146
147Polynomial Polynomial::derivative() const
148{
149 if (degree() == 0) {
150 return Polynomial(0);
151 }
152
153 std::vector<double> result(degree(), 0);
154 for (int i = 1; i <= degree(); i++) {
155 result[i - 1] = i * getCoeff(i);
156 }
157
158 return Polynomial(result);
159}
160
161Polynomial Polynomial::integral() const
162{
163 std::vector<double> result(degree() + 2, 0);
164 for (int i = 0; i <= degree(); i++) {
165 result[i + 1] = getCoeff(i) / (i + 1);
166 }
167 return Polynomial(result);
168}
169
170double Polynomial::evaluate(double x) const
171{
172 if (coefficients.empty()) {
173 return 0;
174 }
175
176 double result = coefficients[0];
177 double x_power = 1;
178
179 for (size_t i = 1; i < coefficients.size(); i++) {
180 x_power *= x;
181 result += coefficients[i] * x_power;
182 }
183
184 return result;
185}
186
187std::complex<double> Polynomial::evaluate(std::complex<double> x) const
188{
189 if (coefficients.empty()) {
190 return std::complex<double>(0, 0);
191 }
192
193 std::complex<double> result(coefficients[0], coefficients[1]);
194 std::complex<double> xPower(1, 1);
195
196 for (size_t i = 1; i < coefficients.size(); i++) {
197 xPower *= x;
198 result += coefficients[i] * xPower;
199 }
200
201 return result;
202}
203
204std::vector<std::complex<double>> Polynomial::roots() const
205{
206 std::vector<std::complex<double>> result;
207
208 if (degree() == 0) {
209 return result;
210 } if (degree() == 1) {
211 result.push_back(std::complex<double>(-getCoeff(0) / getCoeff(1), 0));
212 } else if (degree() == 2) {
213 double a = getCoeff(2);
214 double b = getCoeff(1);
215 double c = getCoeff(0);
216
217 double discriminant = b * b - 4 * a * c;
218 if (discriminant >= 0) {
219 result.push_back(
220 std::complex<double>((-b + std::sqrt(discriminant)) / (2 * a), 0));
221 result.push_back(
222 std::complex<double>((-b - std::sqrt(discriminant)) / (2 * a), 0));
223 } else {
224 result.push_back(std::complex<double>(
225 -b / (2 * a), std::sqrt(-discriminant) / (2 * a)));
226 result.push_back(std::complex<double>(
227 -b / (2 * a), -std::sqrt(-discriminant) / (2 * a)));
228 }
229 }
230
231 return result;
232}
233
234std::vector<Polynomial> Polynomial::factor() const
235{
236 std::vector<Polynomial> factors;
237
238 if (degree() <= 1) {
239 factors.push_back(*this);
240 return factors;
241 }
242
243 auto r = roots();
244 for (const auto& root : r) {
245 if (std::abs(root.imag()) < 1e-10) {
246 std::vector<double> linearCoeffs = {-root.real(), 1};
247 factors.push_back(Polynomial(linearCoeffs));
248 }
249 }
250
251 if (factors.empty()) {
252 factors.push_back(*this);
253 }
254
255 return factors;
256}
257
258std::string Polynomial::toString() const
259{
260 if (coefficients.empty()
261 || (coefficients.size() == 1 && std::abs(coefficients[0]) < 1e-10))
262 {
263 return "0";
264 }
265
266 std::ostringstream oss;
267 bool first = true;
268
269 for (int i = degree(); i >= 0; i--) {
270 double coeff = getCoeff(i);
271 if (std::abs(coeff) < 1e-10) {
272 continue;
273 }
274
275 if (!first) {
276 oss << (coeff > 0 ? " + " : " - ");
277 coeff = std::abs(coeff);
278 } else if (coeff < 0) {
279 oss << "-";
280 coeff = -coeff;
281 }
282
283 if (i == 0 || std::abs(coeff - 1) > 1e-10) {
284 oss << coeff;
285 } else if (i > 0 && std::abs(coeff - 1) < 1e-10 && first && coeff < 0) {
286 oss << "1";
287 }
288
289 if (i > 0) {
290 oss << "x";
291 if (i > 1) {
292 oss << "^" << i;
293 }
294 }
295
296 first = false;
297 }
298
299 return oss.str();
300}
301
302Polynomial Polynomial::lagrangeInterpolation(const std::vector<double>& x,
303 const std::vector<double>& y)
304{
305 if (x.size() != y.size()) {
306 throw std::runtime_error("x and y vectors must have the same size");
307 }
308
309 int n = x.size();
310 Polynomial result(0);
311
312 for (int i = 0; i < n; i++) {
313 Polynomial li(1);
314
315 for (int j = 0; j < n; j++) {
316 if (i != j) {
317 std::vector<double> linearCoeffs = {-x[j], 1};
318 Polynomial linear(linearCoeffs);
319 li = li * linear;
320 li = li * Polynomial(1.0 / (x[i] - x[j]));
321 }
322 }
323
324 result = result + (li * Polynomial(y[i]));
325 }
326
327 return result;
328}
329
330Polynomial Polynomial::newtonInterpolation(const std::vector<double>& x,
331 const std::vector<double>& y)
332{
333 if (x.size() != y.size()) {
334 throw std::runtime_error("x and y vectors must have the same size");
335 }
336
337 int n = x.size();
338 std::vector<std::vector<double>> dividedDiffs(n, std::vector<double>(n, 0));
339
340 for (int i = 0; i < n; i++) {
341 dividedDiffs[i][0] = y[i];
342 }
343
344 for (int j = 1; j < n; j++) {
345 for (int i = 0; i < n - j; i++) {
346 dividedDiffs[i][j] = (dividedDiffs[i + 1][j - 1] - dividedDiffs[i][j - 1])
347 / (x[i + j] - x[i]);
348 }
349 }
350
351 Polynomial result(dividedDiffs[0][0]);
352
353 for (int i = 1; i < n; i++) {
354 Polynomial term(dividedDiffs[0][i]);
355
356 for (int j = 0; j < i; j++) {
357 std::vector<double> linearCoeffs = {-x[j], 1};
358 term = term * Polynomial(linearCoeffs);
359 }
360
361 result = result + term;
362 }
363
364 return result;
365}