123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598 |
- #pragma once
- #include <Mathematics/Logger.h>
- #include <algorithm>
- #include <initializer_list>
- #include <vector>
- namespace WwiseGTE
- {
- template <typename Real>
- class Polynomial1
- {
- public:
-
-
-
-
-
-
-
- Polynomial1(unsigned int degree = 0)
- :
- mCoefficient(degree + 1, (Real)0)
- {
- }
- Polynomial1(std::initializer_list<Real> values)
- {
-
-
-
- mCoefficient.resize(values.size());
- std::copy(values.begin(), values.end(), mCoefficient.begin());
- EliminateLeadingZeros();
- }
-
-
-
- void SetDegree(unsigned int degree)
- {
- mCoefficient.resize(degree + 1);
- }
-
- void SetCoefficients(Real value)
- {
- std::fill(mCoefficient.begin(), mCoefficient.end(), value);
- }
-
- inline unsigned int GetDegree() const
- {
-
- return static_cast<unsigned int>(mCoefficient.size() - 1);
- }
- inline Real const& operator[](unsigned int i) const
- {
- return mCoefficient[i];
- }
- inline Real& operator[](unsigned int i)
- {
- return mCoefficient[i];
- }
-
- inline bool operator==(Polynomial1<Real> const& p) const
- {
- return mCoefficient == p.mCoefficient;
- }
- inline bool operator!=(Polynomial1<Real> const& p) const
- {
- return mCoefficient != p.mCoefficient;
- }
- inline bool operator< (Polynomial1<Real> const& p) const
- {
- return mCoefficient < p.mCoefficient;
- }
- inline bool operator<=(Polynomial1<Real> const& p) const
- {
- return mCoefficient <= p.mCoefficient;
- }
- inline bool operator> (Polynomial1<Real> const& p) const
- {
- return mCoefficient > p.mCoefficient;
- }
- inline bool operator>=(Polynomial1<Real> const& p) const
- {
- return mCoefficient >= p.mCoefficient;
- }
-
-
- Real operator()(Real t) const
- {
- int i = static_cast<int>(mCoefficient.size());
- Real result = mCoefficient[--i];
- for (--i; i >= 0; --i)
- {
- result *= t;
- result += mCoefficient[i];
- }
- return result;
- }
-
- Polynomial1 GetDerivative() const
- {
- unsigned int const degree = GetDegree();
- if (degree > 0)
- {
- Polynomial1 result(degree - 1);
- for (unsigned int i0 = 0, i1 = 1; i0 < degree; ++i0, ++i1)
- {
- result.mCoefficient[i0] = mCoefficient[i1] * (Real)i1;
- }
- return result;
- }
- else
- {
- Polynomial1 result(0);
- result[0] = (Real)0;
- return result;
- }
- }
-
- Polynomial1 GetInversion() const
- {
- unsigned int const degree = GetDegree();
- Polynomial1 result(degree);
- for (unsigned int i = 0; i <= degree; ++i)
- {
- result.mCoefficient[i] = mCoefficient[degree - i];
- }
- return result;
- }
-
- Polynomial1 GetTranslation(Real t0) const
- {
- Polynomial1<Real> factor{ -t0, (Real)1 };
- unsigned int const degree = GetDegree();
- Polynomial1 result{ mCoefficient[degree] };
- for (unsigned int i = 1, j = degree - 1; i <= degree; ++i, --j)
- {
- result = mCoefficient[j] + factor * result;
- }
- return result;
- }
-
-
-
-
-
-
-
-
-
- void EliminateLeadingZeros()
- {
- size_t size = mCoefficient.size();
- if (size > 1)
- {
- Real const zero = (Real)0;
- int leading;
- for (leading = static_cast<int>(size) - 1; leading > 0; --leading)
- {
- if (mCoefficient[leading] != zero)
- {
- break;
- }
- }
- mCoefficient.resize(++leading);
- }
- }
-
-
-
-
-
- void Divide(Polynomial1 const& divisor, Polynomial1& quotient, Polynomial1& remainder) const
- {
- Real const zero = (Real)0;
- int divisorDegree = static_cast<int>(divisor.GetDegree());
- int quotientDegree = static_cast<int>(GetDegree()) - divisorDegree;
- if (quotientDegree >= 0)
- {
- quotient.SetDegree(quotientDegree);
-
- Polynomial1 tmp = *this;
-
- Real inv = ((Real)1) / divisor[divisorDegree];
- for (int i = quotientDegree; i >= 0; --i)
- {
- int j = divisorDegree + i;
- quotient[i] = inv * tmp[j];
- for (j--; j >= i; j--)
- {
- tmp[j] -= quotient[i] * divisor[j - i];
- }
- }
-
- if (divisorDegree >= 1)
- {
- int remainderDegree = divisorDegree - 1;
- while (remainderDegree > 0 && tmp[remainderDegree] == zero)
- {
- --remainderDegree;
- }
- remainder.SetDegree(remainderDegree);
- for (int i = 0; i <= remainderDegree; ++i)
- {
- remainder[i] = tmp[i];
- }
- }
- else
- {
- remainder.SetDegree(0);
- remainder[0] = zero;
- }
- }
- else
- {
- quotient.SetDegree(0);
- quotient[0] = zero;
- remainder = *this;
- }
- }
-
- void MakeMonic()
- {
- EliminateLeadingZeros();
- Real const one(1);
- if (mCoefficient.back() != one)
- {
- unsigned int degree = GetDegree();
- Real invLeading = one / mCoefficient.back();
- mCoefficient.back() = one;
- for (unsigned int i = 0; i < degree; ++i)
- {
- mCoefficient[i] *= invLeading;
- }
- }
- }
- protected:
-
- std::vector<Real> mCoefficient;
- };
-
-
-
- template <typename Real>
- Polynomial1<Real> GreatestCommonDivisor(Polynomial1<Real> const& p0, Polynomial1<Real> const& p1)
- {
-
- Polynomial1<Real> a, b;
- if (p0.GetDegree() >= p1.GetDegree())
- {
- a = p0;
- b = p1;
- }
- else
- {
- a = p1;
- b = p0;
- }
- Polynomial1<Real> const zero{ (Real)0 };
- if (a == zero || b == zero)
- {
- return (a != zero ? a : zero);
- }
-
-
- a.MakeMonic();
- b.MakeMonic();
- Polynomial1<Real> q, r;
- for (;;)
- {
- a.Divide(b, q, r);
- if (r != zero)
- {
-
- a = b;
- b = r;
- b.MakeMonic();
- }
- else
- {
- b.MakeMonic();
- break;
- }
- }
- return b;
- }
-
-
-
- template <typename Real>
- void SquareFreeFactorization(Polynomial1<Real> const& f, std::vector<Polynomial1<Real>>& factors)
- {
-
-
- Polynomial1<Real> fder = f.GetDerivative();
- Polynomial1<Real> a, b, c, d, q, r;
- a = GreatestCommonDivisor(f, fder);
- f.Divide(a, b, r);
- fder.Divide(a, c, r);
- d = c - b.GetDerivative();
- do
- {
- a = GreatestCommonDivisor(b, d);
- factors.emplace_back(a);
- b.Divide(a, q, r);
- b = std::move(q);
- d.Divide(a, c, r);
- d = c - b.GetDerivative();
- } while (b.GetDegree() > 0);
- }
-
- template <typename Real>
- Polynomial1<Real> operator+(Polynomial1<Real> const& p)
- {
- return p;
- }
- template <typename Real>
- Polynomial1<Real> operator-(Polynomial1<Real> const& p)
- {
- unsigned int const degree = p.GetDegree();
- Polynomial1<Real> result(degree);
- for (unsigned int i = 0; i <= degree; ++i)
- {
- result[i] = -p[i];
- }
- return result;
- }
-
- template <typename Real>
- Polynomial1<Real> operator+(Polynomial1<Real> const& p0, Polynomial1<Real> const& p1)
- {
- unsigned int const p0Degree = p0.GetDegree(), p1Degree = p1.GetDegree();
- unsigned int i;
- if (p0Degree >= p1Degree)
- {
- Polynomial1<Real> result(p0Degree);
- for (i = 0; i <= p1Degree; ++i)
- {
- result[i] = p0[i] + p1[i];
- }
- for (; i <= p0Degree; ++i)
- {
- result[i] = p0[i];
- }
- result.EliminateLeadingZeros();
- return result;
- }
- else
- {
- Polynomial1<Real> result(p1Degree);
- for (i = 0; i <= p0Degree; ++i)
- {
- result[i] = p0[i] + p1[i];
- }
- for (; i <= p1Degree; ++i)
- {
- result[i] = p1[i];
- }
- result.EliminateLeadingZeros();
- return result;
- }
- }
- template <typename Real>
- Polynomial1<Real> operator-(Polynomial1<Real> const& p0, Polynomial1<Real> const& p1)
- {
- unsigned int const p0Degree = p0.GetDegree(), p1Degree = p1.GetDegree();
- unsigned int i;
- if (p0Degree >= p1Degree)
- {
- Polynomial1<Real> result(p0Degree);
- for (i = 0; i <= p1Degree; ++i)
- {
- result[i] = p0[i] - p1[i];
- }
- for (; i <= p0Degree; ++i)
- {
- result[i] = p0[i];
- }
- result.EliminateLeadingZeros();
- return result;
- }
- else
- {
- Polynomial1<Real> result(p1Degree);
- for (i = 0; i <= p0Degree; ++i)
- {
- result[i] = p0[i] - p1[i];
- }
- for (; i <= p1Degree; ++i)
- {
- result[i] = -p1[i];
- }
- result.EliminateLeadingZeros();
- return result;
- }
- }
- template <typename Real>
- Polynomial1<Real> operator*(Polynomial1<Real> const& p0, Polynomial1<Real> const& p1)
- {
- unsigned int const p0Degree = p0.GetDegree(), p1Degree = p1.GetDegree();
- Polynomial1<Real> result(p0Degree + p1Degree);
- result.SetCoefficients((Real)0);
- for (unsigned int i0 = 0; i0 <= p0Degree; ++i0)
- {
- for (unsigned int i1 = 0; i1 <= p1Degree; ++i1)
- {
- result[i0 + i1] += p0[i0] * p1[i1];
- }
- }
- return result;
- }
- template <typename Real>
- Polynomial1<Real> operator+(Polynomial1<Real> const& p, Real scalar)
- {
- unsigned int const degree = p.GetDegree();
- Polynomial1<Real> result(degree);
- result[0] = p[0] + scalar;
- for (unsigned int i = 1; i <= degree; ++i)
- {
- result[i] = p[i];
- }
- return result;
- }
- template <typename Real>
- Polynomial1<Real> operator+(Real scalar, Polynomial1<Real> const& p)
- {
- unsigned int const degree = p.GetDegree();
- Polynomial1<Real> result(degree);
- result[0] = p[0] + scalar;
- for (unsigned int i = 1; i <= degree; ++i)
- {
- result[i] = p[i];
- }
- return result;
- }
- template <typename Real>
- Polynomial1<Real> operator-(Polynomial1<Real> const& p, Real scalar)
- {
- unsigned int const degree = p.GetDegree();
- Polynomial1<Real> result(degree);
- result[0] = p[0] - scalar;
- for (unsigned int i = 1; i <= degree; ++i)
- {
- result[i] = p[i];
- }
- return result;
- }
- template <typename Real>
- Polynomial1<Real> operator-(Real scalar, Polynomial1<Real> const& p)
- {
- unsigned int const degree = p.GetDegree();
- Polynomial1<Real> result(degree);
- result[0] = scalar - p[0];
- for (unsigned int i = 1; i <= degree; ++i)
- {
- result[i] = -p[i];
- }
- return result;
- }
- template <typename Real>
- Polynomial1<Real> operator*(Polynomial1<Real> const& p, Real scalar)
- {
- unsigned int const degree = p.GetDegree();
- Polynomial1<Real> result(degree);
- for (unsigned int i = 0; i <= degree; ++i)
- {
- result[i] = scalar * p[i];
- }
- return result;
- }
- template <typename Real>
- Polynomial1<Real> operator*(Real scalar, Polynomial1<Real> const& p)
- {
- unsigned int const degree = p.GetDegree();
- Polynomial1<Real> result(degree);
- for (unsigned int i = 0; i <= degree; ++i)
- {
- result[i] = scalar * p[i];
- }
- return result;
- }
- template <typename Real>
- Polynomial1<Real> operator/(Polynomial1<Real> const& p, Real scalar)
- {
- LogAssert(scalar != (Real)0, "Division by zero.");
- unsigned int const degree = p.GetDegree();
- Real invScalar = (Real)1 / scalar;
- Polynomial1<Real> result(degree);
- for (unsigned int i = 0; i <= degree; ++i)
- {
- result[i] = invScalar * p[i];
- }
- return result;
- }
- template <typename Real>
- Polynomial1<Real>& operator+=(Polynomial1<Real>& p0, Polynomial1<Real> const& p1)
- {
- p0 = p0 + p1;
- return p0;
- }
- template <typename Real>
- Polynomial1<Real>& operator-=(Polynomial1<Real>& p0, Polynomial1<Real> const& p1)
- {
- p0 = p0 - p1;
- return p0;
- }
- template <typename Real>
- Polynomial1<Real>& operator*=(Polynomial1<Real>& p0, Polynomial1<Real> const& p1)
- {
- p0 = p0 * p1;
- return p0;
- }
- template <typename Real>
- Polynomial1<Real>& operator+=(Polynomial1<Real>& p, Real scalar)
- {
- p[0] += scalar;
- return p;
- }
- template <typename Real>
- Polynomial1<Real>& operator-=(Polynomial1<Real>& p, Real scalar)
- {
- p[0] -= scalar;
- return p;
- }
- template <typename Real>
- Polynomial1<Real>& operator*=(Polynomial1<Real>& p, Real scalar)
- {
- p = p * scalar;
- return p;
- }
- template <typename Real>
- Polynomial1<Real> & operator/=(Polynomial1<Real>& p, Real scalar)
- {
- p = p / scalar;
- return p;
- }
- }
|