Files
tech5/source/shared/idlib/math/polynomial.h
T
2026-08-08 19:30:03 -07:00

106 lines
3.9 KiB
C++

#pragma once
#include "idlib/math/complex.h"
#include <algorithm>
#include <cassert>
#include <cmath>
#include <new>
class idPolynomial {
public:
int degree;
int allocated;
float* coefficient;
idPolynomial() : degree(-1), allocated(0), coefficient(nullptr) {}
explicit idPolynomial(const int newDegree) : idPolynomial() { Zero(newDegree); }
idPolynomial(const idPolynomial& other) : idPolynomial() { *this = other; }
~idPolynomial() { delete[] coefficient; }
idPolynomial& operator=(const idPolynomial& other) {
if (this != &other) {
Resize(other.degree, false);
std::copy(other.coefficient, other.coefficient + other.degree + 1,
coefficient);
}
return *this;
}
float operator[](const int index) const {
assert(index >= 0 && index <= degree); return coefficient[index];
}
float& operator[](const int index) {
assert(index >= 0 && index <= degree); return coefficient[index];
}
void Zero() { if (coefficient != nullptr) std::fill(coefficient, coefficient + degree + 1, 0.0f); }
void Zero(const int newDegree) { Resize(newDegree, false); Zero(); }
int GetDimension() const { return degree + 1; }
int GetDegree() const { return degree; }
float GetValue(const float x) const {
float result = 0.0f;
for (int index = degree; index >= 0; --index) result = result * x + coefficient[index];
return result;
}
idComplex GetValue(const idComplex& x) const {
idComplex result(0.0f, 0.0f);
for (int index = degree; index >= 0; --index)
result = result * x + coefficient[index];
return result;
}
idPolynomial GetDerivative() const {
idPolynomial result((std::max)(degree - 1, 0));
if (degree <= 0) { result[0] = 0.0f; return result; }
for (int index = 1; index <= degree; ++index)
result[index - 1] = coefficient[index] * static_cast<float>(index);
return result;
}
idPolynomial GetAntiDerivative() const {
idPolynomial result(degree + 1);
result[0] = 0.0f;
for (int index = 0; index <= degree; ++index)
result[index + 1] = coefficient[index] / static_cast<float>(index + 1);
return result;
}
bool Compare(const idPolynomial& other) const {
if (degree != other.degree) return false;
for (int index = 0; index <= degree; ++index)
if (coefficient[index] != other.coefficient[index]) return false;
return true;
}
bool Compare(const idPolynomial& other, const float epsilon) const {
if (degree != other.degree) return false;
for (int index = 0; index <= degree; ++index)
if (std::fabs(coefficient[index] - other.coefficient[index]) > epsilon) return false;
return true;
}
bool operator==(const idPolynomial& other) const { return Compare(other); }
bool operator!=(const idPolynomial& other) const { return !Compare(other); }
private:
void Resize(const int newDegree, const bool keep) {
assert(newDegree >= 0);
const int required = newDegree + 1;
if (required > allocated) {
const int newAllocated = (required + 3) & ~3;
float* replacement = new float[newAllocated];
std::fill(replacement, replacement + newAllocated, 0.0f);
if (keep && coefficient != nullptr) {
std::copy(coefficient,
coefficient + (std::min)(degree + 1, required), replacement);
}
delete[] coefficient;
coefficient = replacement;
allocated = newAllocated;
} else if (!keep && coefficient != nullptr) {
std::fill(coefficient, coefficient + allocated, 0.0f);
}
degree = newDegree;
}
};
#if defined(_WIN32) && !defined(_WIN64)
static_assert(sizeof(idPolynomial) == 12, "Recovered idPolynomial ABI changed");
#endif