1#include "include/polynomial.h"
7#include "include/polynomial.h"
9Polynomial::Polynomial(
const std::vector<double>& coeffs)
10 : coefficients(coeffs)
15Polynomial::Polynomial(
double constant)
17 coefficients.push_back(constant);
20void Polynomial::removeLeadingZeros()
22 while (coefficients.size() > 1 && std::abs(coefficients.back()) < 1e-10) {
23 coefficients.pop_back();
25 if (coefficients.empty()) {
26 coefficients.push_back(0);
30int Polynomial::degree()
const
32 return static_cast<int>(coefficients.size()) - 1;
35double Polynomial::getCoeff(
int i)
const
37 if (i < 0 || i >=
static_cast<int>(coefficients.size())) {
40 return coefficients[i];
43void Polynomial::setCoeff(
int i,
double val)
48 if (i >=
static_cast<int>(coefficients.size())) {
49 coefficients.resize(i + 1, 0);
51 coefficients[i] = val;
55int Polynomial::getDegree()
const
62 int maxDegree = std::max(degree(), other.degree());
63 std::vector<double> result(maxDegree + 1, 0);
65 for (
int i = 0; i <= maxDegree; i++) {
66 result[i] = getCoeff(i) + other.getCoeff(i);
74 int maxDegree = std::max(degree(), other.degree());
75 std::vector<double> result(maxDegree + 1, 0);
77 for (
int i = 0; i <= maxDegree; i++) {
78 result[i] = getCoeff(i) - other.getCoeff(i);
86 if (degree() == 0 && std::abs(getCoeff(0)) < 1e-10) {
89 if (other.degree() == 0 && std::abs(other.getCoeff(0)) < 1e-10) {
93 int resultDegree = degree() + other.degree();
94 std::vector<double> result(resultDegree + 1, 0);
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);
105std::pair<Polynomial, Polynomial> Polynomial::divide(
108 if (divisor.degree() == 0 && std::abs(divisor.getCoeff(0)) < 1e-10) {
109 throw std::runtime_error(
"Division by zero polynomial");
115 while (dividend.degree() >= divisor.degree()
116 && !(dividend.degree() == 0 && std::abs(dividend.getCoeff(0)) < 1e-10))
119 dividend.coefficients.back() / divisor.coefficients.back();
120 int degreeDiff = dividend.degree() - divisor.degree();
122 std::vector<double> termCoeffs(degreeDiff + 1, 0);
123 termCoeffs[degreeDiff] = leadCoeff;
126 quotient = quotient + term;
127 dividend = dividend - (term * divisor);
130 return {quotient, dividend};
138 while (!(b.degree() == 0 && std::abs(b.getCoeff(0)) < 1e-10)) {
139 auto division = a.divide(b);
153 std::vector<double> result(degree(), 0);
154 for (
int i = 1; i <= degree(); i++) {
155 result[i - 1] = i * getCoeff(i);
163 std::vector<double> result(degree() + 2, 0);
164 for (
int i = 0; i <= degree(); i++) {
165 result[i + 1] = getCoeff(i) / (i + 1);
170double Polynomial::evaluate(
double x)
const
172 if (coefficients.empty()) {
176 double result = coefficients[0];
179 for (
size_t i = 1; i < coefficients.size(); i++) {
181 result += coefficients[i] * x_power;
187std::complex<double> Polynomial::evaluate(std::complex<double> x)
const
189 if (coefficients.empty()) {
190 return std::complex<double>(0, 0);
193 std::complex<double> result(coefficients[0], coefficients[1]);
194 std::complex<double> xPower(1, 1);
196 for (
size_t i = 1; i < coefficients.size(); i++) {
198 result += coefficients[i] * xPower;
204std::vector<std::complex<double>> Polynomial::roots()
const
206 std::vector<std::complex<double>> 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);
217 double discriminant = b * b - 4 * a * c;
218 if (discriminant >= 0) {
220 std::complex<double>((-b + std::sqrt(discriminant)) / (2 * a), 0));
222 std::complex<double>((-b - std::sqrt(discriminant)) / (2 * a), 0));
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)));
234std::vector<Polynomial> Polynomial::factor()
const
236 std::vector<Polynomial> factors;
239 factors.push_back(*
this);
244 for (
const auto& root : r) {
245 if (std::abs(root.imag()) < 1e-10) {
246 std::vector<double> linearCoeffs = {-root.real(), 1};
251 if (factors.empty()) {
252 factors.push_back(*
this);
258std::string Polynomial::toString()
const
260 if (coefficients.empty()
261 || (coefficients.size() == 1 && std::abs(coefficients[0]) < 1e-10))
266 std::ostringstream oss;
269 for (
int i = degree(); i >= 0; i--) {
270 double coeff = getCoeff(i);
271 if (std::abs(coeff) < 1e-10) {
276 oss << (coeff > 0 ?
" + " :
" - ");
277 coeff = std::abs(coeff);
278 }
else if (coeff < 0) {
283 if (i == 0 || std::abs(coeff - 1) > 1e-10) {
285 }
else if (i > 0 && std::abs(coeff - 1) < 1e-10 && first && coeff < 0) {
302Polynomial Polynomial::lagrangeInterpolation(
const std::vector<double>& x,
303 const std::vector<double>& y)
305 if (x.size() != y.size()) {
306 throw std::runtime_error(
"x and y vectors must have the same size");
312 for (
int i = 0; i < n; i++) {
315 for (
int j = 0; j < n; j++) {
317 std::vector<double> linearCoeffs = {-x[j], 1};
330Polynomial Polynomial::newtonInterpolation(
const std::vector<double>& x,
331 const std::vector<double>& y)
333 if (x.size() != y.size()) {
334 throw std::runtime_error(
"x and y vectors must have the same size");
338 std::vector<std::vector<double>> dividedDiffs(n, std::vector<double>(n, 0));
340 for (
int i = 0; i < n; i++) {
341 dividedDiffs[i][0] = y[i];
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])
353 for (
int i = 1; i < n; i++) {
356 for (
int j = 0; j < i; j++) {
357 std::vector<double> linearCoeffs = {-x[j], 1};
361 result = result + term;