polynomial.hpp

Back to Polynomials

pastel/math/polynomial/

#ifndef PASTELMATH_POLYNOMIAL_HPP
#define PASTELMATH_POLYNOMIAL_HPP

#include "pastel/math/polynomial/polynomial.h"

namespace Pastel
{

    template <typename Real>
    Polynomial<Real>::Polynomial(integer size)
        : data_(size, Real(0))
        , epsilon_(0.001)
    {
    }

    template <typename Real>
    void Polynomial<Real>::swap(Polynomial& that)
    {
        data_.swap(that.data_);
    }

    template <typename Real>
    void Polynomial<Real>::setSize(integer size)
    {
        ENSURE_OP(size, >=, 1);

        data_.resize(size, Real(0));
    }

    template <typename Real>
    integer Polynomial<Real>::size() const
    {
        return data_.size();
    }

    template <typename Real>
    void Polynomial<Real>::trim()
    {
        setSize(degree() + 1);
    }

    template <typename Real>
    void Polynomial<Real>::set(
        integer index, const Real& that)
    {
        PENSURE_OP(index, >=, 0);

        if (index >= data_.size())
        {
            data_.resize(index + 1, Real(0));
        }

        data_[index] = that;
    }

    template <typename Real>
    Real Polynomial<Real>::operator()(
        const Real& x) const
    {
        integer n = size();
        Real result = data_[n - 1];

        for (integer i = n - 2;i >= 0;--i)
        {

            result *= x;
            result += data_[i];
        }

        return result;
    }

    template <typename Real>
    Real& Polynomial<Real>::operator[](
        integer index)
    {
        PENSURE2(index >= 0 && index < size(), index, size());
        return data_[index];
    }

    template <typename Real>
    const Real& Polynomial<Real>::operator[](
        integer index) const
    {
        PENSURE2(index >= 0 && index < size(), index, size());
        return data_[index];
    }

    template <typename Real>
    Polynomial<Real>& Polynomial<Real>::operator+=(
        const Real& that)
    {
        data_[0] += that;

        return *this;
    }

    template <typename Real>
    Polynomial<Real>& Polynomial<Real>::operator-=(
        const Real& that)
    {
        data_[0] -= that;

        return *this;
    }

    template <typename Real>
    Polynomial<Real>& Polynomial<Real>::operator*=(
        const Real& that)
    {
        integer n = size();
        for (integer i = 0;i < n;++i)
        {

            data_[i] *= that;
        }

        return *this;
    }

    template <typename Real>
    Polynomial<Real>& Polynomial<Real>::operator/=(
        const Real& that)
    {
        return (*this *= inverse(that));
    }

    template <typename Real>
    Polynomial<Real>& Polynomial<Real>::operator+=(
        const Polynomial& that)
    {
        if (that.size() > size())
        {
            data_.resize(that.size(), Real(0));
        }

        integer n = std::min(size(), that.size());
        for (integer i = 0;i < n;++i)
        {
            data_[i] += that.data_[i];
        }

        return *this;
    }

    template <typename Real>
    Polynomial<Real>& Polynomial<Real>::operator-=(
        const Polynomial& that)
    {
        if (that.size() > size())
        {
            data_.resize(that.size(), Real(0));
        }

        integer n = std::min(size(), that.size());
        for (integer i = 0;i < n;++i)
        {
            data_[i] -= that.data_[i];
        }

        return *this;
    }

    template <typename Real>
    Polynomial<Real>& Polynomial<Real>::operator*=(
        const Polynomial& that)
    {
        Polynomial result(size() + that.size());

        integer n = size();
        integer m = that.size();

        for (integer i = 0;i < n;++i)
        {
            for (integer k = 0;k < m;++k)
            {

                result[i + k] += data_[i] * that.data_[k];
            }
        }

        swap(result);

        return *this;
    }

    template <typename Real>
    Polynomial<Real>& Polynomial<Real>::operator<<=(
        integer index)
    {
        PENSURE_OP(index, >=, 0);

        integer n = degree();
        if (n + index >= size())
        {
            setSize(n + index + 1);
        }

        for (integer i = n + index;i >= index;--i)
        {
            data_[i] = data_[i - index];
        }
        for (integer i = index - 1;i >= 0;--i)
        {
            data_[i] = 0;
        }

        return *this;
    }

    template <typename Real>
    Polynomial<Real>& Polynomial<Real>::operator>>=(
        integer index)
    {
        PENSURE_OP(index, >=, 0);

        integer n = size();

        for (integer i = 0;i < n - index;++i)
        {
            data_[i] = data_[i + index];
        }
        for (integer i = n - index;i < n;++i)
        {
            data_[i] = 0;
        }

        return *this;
    }

    template <typename Real>
    bool Polynomial<Real>::operator==(
        const Polynomial& that) const
    {
        integer n = degree();
        integer m = that.degree();

        if (n != m)
        {
            return false;
        }

        for (integer i = 0;i < n;++i)
        {
            if (abs(data_[i] - that.data_[i]) > epsilon_)
            {
                return false;
            }
        }

        return true;
    }

    template <typename Real>

    void Polynomial<Real>::setEpsilon(const Real& epsilon)
    {
        epsilon_ = epsilon;
    }

    template <typename Real>
    const Real& Polynomial<Real>::epsilon() const
    {
        return epsilon_;
    }

    template <typename Real>
    integer Polynomial<Real>::degree() const
    {
        integer n = size();
        for (integer i = n - 1;i >= 1;--i)
        {
            if (abs(data_[i]) > epsilon_)
            {
                return i;
            }
        }

        return 0;
    }

}

#endif