2012-01-22

Implementacja klasy wielomian

Oto moja implementacja klasy wielomian, umożliwia znajdowanie miejsc zerowych metodą bezpośrednią i metodą Sturma.

public struct Polynomial
{
    public static readonly Polynomial ZERO = new Polynomial(0.0);
    public static readonly Polynomial ONE = new Polynomial(1.0);

    private int m_order;
    private readonly double[] m_coeffs;

    public Polynomial(Polynomial a_poly)
    {
        m_coeffs = new double[a_poly.m_order + 1];
        m_order = a_poly.m_order;

        Array.Copy(a_poly.m_coeffs, m_coeffs, m_coeffs.Length);
    }

    private Polynomial(int a_order)
    {
        Debug.Assert(a_order >= 0);

        m_order = a_order;
        m_coeffs = new double[m_order + 1];
                
        Check();
    }

    public Polynomial(double a_c0)
    {
        m_coeffs = new double[1];
        m_order = 0;
        m_coeffs[0] = a_c0;

        Check();
    }

    public Polynomial(double a_c0, double a_c1)
    {
        m_coeffs = new double[2];
        m_order = 1;
        m_coeffs[0] = a_c0;
        m_coeffs[1] = a_c1;

        OptimizeOrder();

        Check();
    }

    public Polynomial(double a_c0, double a_c1, double a_c2)
    {
        m_coeffs = new double[3];
        m_order = 2;
        m_coeffs[0] = a_c0;
        m_coeffs[1] = a_c1;
        m_coeffs[2] = a_c2;

        OptimizeOrder();

        Check();
    }

    public Polynomial(double a_c0, double a_c1, double a_c2, double a_c3)
    {
        m_coeffs = new double[4];
        m_order = 3;
        m_coeffs[0] = a_c0;
        m_coeffs[1] = a_c1;
        m_coeffs[2] = a_c2;
        m_coeffs[3] = a_c3;

        OptimizeOrder();

        Check();
    }

    public Polynomial(double a_c0, double a_c1, double a_c2, double a_c3, 
        double a_c4)
    {
        m_coeffs = new double[5];
        m_order = 4;
        m_coeffs[0] = a_c0;
        m_coeffs[1] = a_c1;
        m_coeffs[2] = a_c2;
        m_coeffs[3] = a_c3;
        m_coeffs[4] = a_c4;

        OptimizeOrder();

        Check();
    }

    public Polynomial(double a_c0, double a_c1, double a_c2, double a_c3, 
        double a_c4, double a_c5)
    {
        m_coeffs = new double[6];
        m_order = 5;
        m_coeffs[0] = a_c0;
        m_coeffs[1] = a_c1;
        m_coeffs[2] = a_c2;
        m_coeffs[3] = a_c3;
        m_coeffs[4] = a_c4;
        m_coeffs[5] = a_c5;

        OptimizeOrder();

        Check();
    }

    public Polynomial(double a_c0, double a_c1, double a_c2, double a_c3, 
        double a_c4, double a_c5, double a_c6)
    {
        m_coeffs = new double[7];
        m_order = 6;
        m_coeffs[0] = a_c0;
        m_coeffs[1] = a_c1;
        m_coeffs[2] = a_c2;
        m_coeffs[3] = a_c3;
        m_coeffs[4] = a_c4;
        m_coeffs[5] = a_c5;
        m_coeffs[6] = a_c6;

        OptimizeOrder();

        Check();
    }

    public Polynomial(params double[] a_coeffs)
    {
        Debug.Assert(a_coeffs.Length > 0);

        m_coeffs = new double[a_coeffs.Length];
        m_order = m_coeffs.Length - 1;
        Array.Copy(a_coeffs, m_coeffs, m_coeffs.Length);

        OptimizeOrder();

        Check();
    }

    public override bool Equals(object a_obj)
    {
        if (a_obj == null)
            return false;

        if (!typeof(Polynomial).Equals(a_obj.GetType()))
            return false;
        Polynomial poly = (Polynomial)a_obj;

        if (m_order != poly.m_order)
            return false;

        for (int i = 0; i <= m_order; i++)
        {
            if (m_coeffs[i] != poly.m_coeffs[i])
                return false;
        }

        return true;
    }

    public bool Equals(Polynomial a_poly)
    {
        if (m_order != a_poly.m_order)
            return false;

        for (int i = 0; i <= m_order; i++)
        {
            if (m_coeffs[i] != a_poly.m_coeffs[i])
                return false;
        }

        return true;
    }

    public bool IsAlmostRelativeEquals(Polynomial a_poly, 
        double a_precision = Constants.DOUBLE_PRECISION)
    {
        if (a_poly.m_order > m_order)
        {
            for (int i = m_order + 1; i <= a_poly.m_order; i++)
            {
                if (!a_poly.m_coeffs[i].IsAlmostRelativeEquals(0, a_precision))
                    return false;
            }
        }

        if (m_order > a_poly.m_order)
        {
            for (int i = a_poly.m_order + 1; i <= m_order; i++)
            {
                if (!m_coeffs[i].IsAlmostRelativeEquals(0, a_precision))
                    return false;
            }
        }

        for (int i = 0; i <= Math.Min(m_order, a_poly.m_order); i++)
        {
            if (!m_coeffs[i].IsAlmostRelativeEquals(a_poly.m_coeffs[i],
                a_precision))
            {
                return false;
            }
        }

        return true;
    }

    public bool IsAlmostEquals(Polynomial a_poly, 
        double a_precision = Constants.DOUBLE_PRECISION)
    {
        if (a_poly.m_order > m_order)
        {
            for (int i = m_order + 1; i <= a_poly.m_order; i++)
            {
                if (!a_poly.m_coeffs[i].IsAlmostEquals(0, a_precision))
                    return false;
            }
        }

        if (m_order > a_poly.m_order)
        {
            for (int i = a_poly.m_order + 1; i <= m_order; i++)
            {
                if (!m_coeffs[i].IsAlmostEquals(0, a_precision))
                    return false;
            }
        }

        for (int i = 0; i <= Math.Min(m_order, a_poly.m_order); i++)
        {
            if (!m_coeffs[i].IsAlmostEquals(a_poly.m_coeffs[i], a_precision))
                return false;
        }

        return true;
    }

    //

    public override int GetHashCode()
    {
        return ArrayExtensions.GetHashCode(m_coeffs);
    }

    public static bool operator !=(Polynomial a_a, Polynomial a_b)
    {
        if (a_a.m_order != a_b.m_order)
            return true;

        for (int i = 0; i <= a_a.m_order; i++)
        {
            if (a_a.m_coeffs[i] != a_b.m_coeffs[i])
                return true;
        }

        return false;
    }

    public static bool operator ==(Polynomial a_a, Polynomial a_b)
    {
        if (a_a.m_order != a_b.m_order)
            return false;

        for (int i = 0; i <= a_a.m_order; i++)
        {
            if (a_a.m_coeffs[i] != a_b.m_coeffs[i])
                return false;
        }

        return true;
    }

    [Conditional("DEBUG")]
    private void Check()
    {
        for (int i = 0; i <= m_order; i++)
            Debug.Assert(m_coeffs[i].IsNumber());

        Debug.Assert(m_order >= 0);
        Debug.Assert(m_coeffs.Length >= 1);
    }

    public int Order
    {
        get
        {
            return m_order;
        }
    }

    public double this[int a_index]
    {
        get
        {
            if (a_index > m_order)
                throw new IndexOutOfRangeException();

            return m_coeffs[a_index];
        }
        private set
        {
            if (a_index > m_order)
                throw new IndexOutOfRangeException();

            m_coeffs[a_index] = value;

            OptimizeOrder();

            Check();
        }
    }

    public double LeadCoefficient
    {
        get
        {
            return m_coeffs[m_order];
        }
    }

    public double LastCoefficient
    {
        get
        {
            return m_coeffs[0];
        }
    }

    public Polynomial Normalize()
    {
        if (m_order == 0)
            return Polynomial.ONE;

        double div = m_coeffs[m_order];

        if (div == 1)
            return this;

        Polynomial result = new Polynomial(this);

        for (int i = 0; i < result.m_order; i++)
            result.m_coeffs[i] /= div;

        result.m_coeffs[m_order] = 1;

        return result;  
    }

    public double Evaluate(double a_x)
    {
        double r = m_coeffs[m_order];

        for (int i = m_order - 1; i >= 0; i--)
            r = m_coeffs[i] + r * a_x;

        return r;
    }

    private void OptimizeOrder()
    {
        while (m_order > 0 && (m_coeffs[m_order] == 0.0))
            m_order--;
    }

    public static Polynomial operator * (Polynomial a_left, double a_right)
    {
        Polynomial result = new Polynomial(a_left);

        for (int i = 0; i <= result.m_order; i++)
            result.m_coeffs[i] *= a_right;

        result.OptimizeOrder();

        return result;
    }

    public static Polynomial operator * (double a_left, Polynomial a_right)
    {
        Polynomial result = new Polynomial(a_right);

        for (int i = 0; i <= result.m_order; i++)
            result.m_coeffs[i] *= a_left;

        result.OptimizeOrder();

        return result;
    }

    public static Polynomial operator /(Polynomial a_left, double a_right)
    {
        Polynomial result = new Polynomial(a_left);

        for (int i = 0; i <= result.m_order; i++)
            result.m_coeffs[i] /= a_right;

        result.OptimizeOrder();

        return result;
    }

    public Polynomial Differentiate()
    {
        if (m_order == 0)
            return Polynomial.ZERO;

        Polynomial result = new Polynomial(m_order - 1);

        for (int i = 1; i <= m_order; i++)
            result.m_coeffs[i - 1] += i * m_coeffs[i];

        return result;
    }

    public static Polynomial operator *(Polynomial a_u, Polynomial a_v)
    {
        Polynomial result = new Polynomial(a_u.m_order + a_v.m_order);

        for (int i = 0; i <= a_u.m_order; i++)
            for (int j = 0; j <= a_v.m_order; j++)
                result.m_coeffs[i + j] += a_u.m_coeffs[i] * a_v.m_coeffs[j];

        result.OptimizeOrder();

        return result;
    }

    public static Polynomial operator +(Polynomial a_u, Polynomial a_v)
    {
        if (a_u.m_order == a_v.m_order)
        {
            Polynomial result = new Polynomial(a_u.m_order);

            for (int i = 0; i <= a_u.m_order; i++)
                result.m_coeffs[i] = a_u.m_coeffs[i] + a_v.m_coeffs[i];

            result.OptimizeOrder();

            return result;
        }
        else if (a_u.m_order < a_v.m_order)
        {
            Polynomial result = new Polynomial(a_v.m_order);

            for (int i = a_u.m_order + 1; i <= a_v.m_order; i++)
                result.m_coeffs[i] = a_v.m_coeffs[i];

            for (int i = 0; i <= a_u.m_order; i++)
                result.m_coeffs[i] = a_u.m_coeffs[i] + a_v.m_coeffs[i];

            result.OptimizeOrder();

            return result;
        }
        else
        {
            Polynomial result = new Polynomial(a_u.m_order);

            for (int i = a_v.m_order + 1; i <= a_u.m_order; i++)
                result.m_coeffs[i] = a_u.m_coeffs[i];

            for (int i = 0; i <= a_v.m_order; i++)
                result.m_coeffs[i] = a_u.m_coeffs[i] + a_v.m_coeffs[i];

            result.OptimizeOrder();

            return result;
        }
    }

    public static Polynomial operator -(Polynomial a_poly)
    {
        Polynomial result = new Polynomial(a_poly.m_order);

        for (int i = 0; i <= result.m_order; i++)
            result.m_coeffs[i] = -a_poly.m_coeffs[i];

        return result;
    }

    public static Polynomial operator -(Polynomial a_u, Polynomial a_v)
    {
        if (a_u.m_order == a_v.m_order)
        {
            Polynomial result = new Polynomial(a_u.m_order);

            for (int i = 0; i <= a_u.m_order; i++)
                result.m_coeffs[i] = a_u.m_coeffs[i] - a_v.m_coeffs[i];

            result.OptimizeOrder();

            return result;
        }
        else if (a_u.m_order < a_v.m_order)
        {
            Polynomial result = new Polynomial(a_v.m_order);

            for (int i = a_u.m_order + 1; i <= a_v.m_order; i++)
                result.m_coeffs[i] = -a_v.m_coeffs[i];

            for (int i = 0; i <= a_u.m_order; i++)
                result.m_coeffs[i] = a_u.m_coeffs[i] - a_v.m_coeffs[i];

            result.OptimizeOrder();

            return result;
        }
        else
        {
            Polynomial result = new Polynomial(a_u.m_order);

            for (int i = a_v.m_order + 1; i <= a_u.m_order; i++)
                result.m_coeffs[i] = a_u.m_coeffs[i];

            for (int i = 0; i <= a_v.m_order; i++)
                result.m_coeffs[i] = a_u.m_coeffs[i] - a_v.m_coeffs[i];

            result.OptimizeOrder();

            return result;
        }
    }

    public static Polynomial operator %(Polynomial a_u, Polynomial a_v)
    {
        if (a_u.m_order < a_v.m_order)
            return a_u;

        Polynomial reminder = new Polynomial(a_u);

        while (reminder.m_order >= a_v.m_order)
        {
            double d = reminder.LeadCoefficient / a_v.LeadCoefficient;

            for (int j = 0; j <= a_v.m_order; j++)
            {
                reminder.m_coeffs[reminder.m_order - a_v.m_order + j] -=
                    a_v.m_coeffs[j] * d;
            }

            if (reminder.m_order > 0)
                reminder.m_order--;
            else
                break;
        }

        reminder.OptimizeOrder();
        reminder.Check();

        return reminder;
    }

    public static Polynomial operator /(Polynomial a_u, Polynomial a_v)
    {
        Polynomial reminder = new Polynomial(a_u);

        if (a_u.m_order < a_v.m_order)
            return Polynomial.ZERO;

        Polynomial result = new Polynomial(a_u.m_order - a_v.m_order);

        while (reminder.m_order >= a_v.m_order)
        {
            double d = reminder.LeadCoefficient / a_v.LeadCoefficient;
            result.m_coeffs[reminder.m_order - a_v.m_order] = d;

            for (int j = 0; j <= a_v.m_order; j++)
            {
                reminder.m_coeffs[reminder.m_order - a_v.m_order + j] -=
                    a_v.m_coeffs[j] * d;
            }

            reminder.m_order--;
        }

        result.OptimizeOrder();
        result.Check();

        return result;
    }

    public static Polynomial GCD(Polynomial a_a, Polynomial a_b, 
        double a_precision = Constants.DOUBLE_PRECISION)
    {
        if (a_a.Order < a_b.Order)
        {
            Polynomial t = a_b;
            a_b = a_a;
            a_a = t;
        }

        while (!a_b.IsAlmostEquals(Polynomial.ZERO, a_precision))
        {
            Polynomial t = a_b;

            a_b = a_a % a_b;
            a_a = t;
        }

        if (a_a.LeadCoefficient < 0)
            a_a = -a_a;

        return a_a.Normalize();
    }

    public static Polynomial DivRem(Polynomial a_divider, Polynomial a_divisor, 
        out Polynomial a_reminder)
    {
        a_reminder = new Polynomial(a_divider);

        if (a_divider.m_order < a_divisor.m_order)
            return Polynomial.ZERO;

        Polynomial result = new Polynomial(a_reminder.m_order - a_divisor.m_order);

        while (a_reminder.m_order >= a_divisor.m_order)
        {
            double d = a_reminder.LeadCoefficient / a_divisor.LeadCoefficient;
            result.m_coeffs[a_reminder.m_order - a_divisor.m_order] = d;

            for (int j = 0; j <= a_divisor.m_order; j++)
            {
                a_reminder.m_coeffs[a_reminder.m_order - a_divisor.m_order + j] -=
                    a_divisor.m_coeffs[j] * d;
            }

            if (a_reminder.m_order > 0)
                a_reminder.m_order--;
            else
                break;
        }

        result.OptimizeOrder();
        result.Check();

        a_reminder.OptimizeOrder();
        a_reminder.Check();

        return result;
    }

    public override string ToString()
    {
        string coeffs = "";

        for (int i = 0; i <= m_order; i++)
        {
            coeffs += m_coeffs[i].ToString(CultureInfo.InvariantCulture);

            if (i != m_order)
                coeffs += ", ";
        }

        return String.Format("Order: {0}, Coeffs: {1}", m_order, coeffs);
    }

    public static Polynomial operator ^(Polynomial a_left, int a_right)
    {
        if (a_right < 0)
        {
            Debug.Fail("");
            return Polynomial.ZERO;
        }

        if (a_right == 0)
            return Polynomial.ONE;

        Polynomial result = new Polynomial(a_left);

        while (a_right > 1)
        {
            a_right--;
            result *= a_left;
        }

        return result;
    }

    public Polynomial RemoveZeroes()
    {
        Polynomial result = new Polynomial(this);

        while (result.m_order > 0 && (result.m_coeffs[0].IsAlmostEquals(0)))
        {
            for (int i = 1; i <= result.m_order; i++)
                result[i - 1] = result[i];

            result.m_order--;
        }

        return result;
    }

    public IEnumerable<double> Coeffs
    {
        get
        {
            return m_coeffs;
        }
    }
}

I testy:

[TestMethod]
public void Polynomial_Test()
{
    Polynomial p_1 = new Polynomial(-1.0, 1.0) * 2;
    Polynomial p_2 = new Polynomial(-2.0, 1.0) * -0.3;
    Polynomial p_3 = new Polynomial(-3.0, 1.0) * -3;
    Polynomial p_4 = new Polynomial(-4.0, 1.0) * 0.2;
    Polynomial p_5 = new Polynomial(-5.0, 1.0) * 1.2;
    Polynomial p_6 = new Polynomial(-6.0, 1.0) * -3.2;

    // Constructors.

    {
        Polynomial p = new Polynomial();
        Assert.IsTrue(p.Order == 0);
    }

    {
        Polynomial p = new Polynomial(1.2);
        Assert.IsTrue(p.Order == 0);
        Assert.IsTrue(p[0].IsAlmostEquals(1.2));
        Assert.IsTrue(p.LeadCoefficient.IsAlmostEquals(1.2));
        Assert.IsTrue(p.LastCoefficient.IsAlmostEquals(1.2));
    }

    {
        Polynomial p = new Polynomial(1.3, 1.2);
        Assert.IsTrue(p.Order == 1);
        Assert.IsTrue(p[1].IsAlmostEquals(1.2));
        Assert.IsTrue(p[0].IsAlmostEquals(1.3));
        Assert.IsTrue(p.LeadCoefficient.IsAlmostEquals(1.2));
        Assert.IsTrue(p.LastCoefficient.IsAlmostEquals(1.3));
    }

    {
        Polynomial p = new Polynomial(1.4, 1.3, 1.2);
        Assert.IsTrue(p.Order == 2);
        Assert.IsTrue(p[2].IsAlmostEquals(1.2));
        Assert.IsTrue(p[1].IsAlmostEquals(1.3));
        Assert.IsTrue(p[0].IsAlmostEquals(1.4));
        Assert.IsTrue(p.LeadCoefficient.IsAlmostEquals(1.2));
        Assert.IsTrue(p.LastCoefficient.IsAlmostEquals(1.4));
    }

    {
        Polynomial p = new Polynomial(1.5, 1.4, 1.3, 1.2);
        Assert.IsTrue(p.Order == 3);
        Assert.IsTrue(p[3].IsAlmostEquals(1.2));
        Assert.IsTrue(p[2].IsAlmostEquals(1.3));
        Assert.IsTrue(p[1].IsAlmostEquals(1.4));
        Assert.IsTrue(p[0].IsAlmostEquals(1.5));
        Assert.IsTrue(p.LeadCoefficient.IsAlmostEquals(1.2));
        Assert.IsTrue(p.LastCoefficient.IsAlmostEquals(1.5));
    }

    {
        Polynomial p = new Polynomial(1.6, 1.5, 1.4, 1.3, 1.2);
        Assert.IsTrue(p.Order == 4);
        Assert.IsTrue(p[4].IsAlmostEquals(1.2));
        Assert.IsTrue(p[3].IsAlmostEquals(1.3));
        Assert.IsTrue(p[2].IsAlmostEquals(1.4));
        Assert.IsTrue(p[1].IsAlmostEquals(1.5));
        Assert.IsTrue(p[0].IsAlmostEquals(1.6));
        Assert.IsTrue(p.LeadCoefficient.IsAlmostEquals(1.2));
        Assert.IsTrue(p.LastCoefficient.IsAlmostEquals(1.6));
    }

    {
        Polynomial p = new Polynomial(1.7, 1.6, 1.5, 1.4, 1.3, 1.2, 1.21, 1.22);
        Assert.IsTrue(p.Order == 7);
        Assert.IsTrue(p[7].IsAlmostEquals(1.22));
        Assert.IsTrue(p[6].IsAlmostEquals(1.21));
        Assert.IsTrue(p[5].IsAlmostEquals(1.2));
        Assert.IsTrue(p[4].IsAlmostEquals(1.3));
        Assert.IsTrue(p[3].IsAlmostEquals(1.4));
        Assert.IsTrue(p[2].IsAlmostEquals(1.5));
        Assert.IsTrue(p[1].IsAlmostEquals(1.6));
        Assert.IsTrue(p[0].IsAlmostEquals(1.7));
        Assert.IsTrue(p.LeadCoefficient.IsAlmostEquals(1.22));
        Assert.IsTrue(p.LastCoefficient.IsAlmostEquals(1.7));
    }

    {
        Polynomial p = new Polynomial(new double[] { 1.7, 1.6, 1.5, 1.4, 1.3, 1.2 });
        Assert.IsTrue(p.Order == 5);
        Assert.IsTrue(p[5].IsAlmostEquals(1.2));
        Assert.IsTrue(p[4].IsAlmostEquals(1.3));
        Assert.IsTrue(p[3].IsAlmostEquals(1.4));
        Assert.IsTrue(p[2].IsAlmostEquals(1.5));
        Assert.IsTrue(p[1].IsAlmostEquals(1.6));
        Assert.IsTrue(p[0].IsAlmostEquals(1.7));
        Assert.IsTrue(p.LeadCoefficient.IsAlmostEquals(1.2));
        Assert.IsTrue(p.LastCoefficient.IsAlmostEquals(1.7));
    }

    {
        Polynomial p = new Polynomial(1.6, 1.5, 1.4, 1.3, 0);
        Assert.IsTrue(p.Order == 3);
        Assert.IsTrue(p[3].IsAlmostEquals(1.3));
        Assert.IsTrue(p[2].IsAlmostEquals(1.4));
        Assert.IsTrue(p[1].IsAlmostEquals(1.5));
        Assert.IsTrue(p[0].IsAlmostEquals(1.6));
        Assert.IsTrue(p.LeadCoefficient.IsAlmostEquals(1.3));
        Assert.IsTrue(p.LastCoefficient.IsAlmostEquals(1.6));
    }

    {
        Polynomial p = new Polynomial(0.0);
        Assert.IsTrue(p.Order == 0);
        Assert.IsTrue(p[0].IsAlmostEquals(0.0));
        Assert.IsTrue(p.LeadCoefficient.IsAlmostEquals(0.0));
        Assert.IsTrue(p.LastCoefficient.IsAlmostEquals(0.0));
    }

    // Equals(obj), Equals(Polynomial), ==, !=

    {
        Polynomial p1 = new Polynomial(1.6, 1.5, -1.4, 1.3, 1.2);
        Polynomial p2 = new Polynomial(1.6, 1.5, -1.4, 1.3, 1.2);

        Assert.IsTrue(p1 == p2);
        Assert.IsTrue(p2 == p1);
        Assert.IsFalse(p1 != p2);
        Assert.IsFalse(p2 != p1);
        Assert.AreEqual(p1, p2);
        Assert.AreEqual(p2, p1);
        Assert.AreEqual((object)p1, (object)p2);
        Assert.AreEqual((object)p2, (object)p1);

        Assert.AreEqual(new Polynomial(1.6, 1.5, -1.4, 1.3, 1.2), p1);
        Assert.AreEqual(new Polynomial(1.6, 1.5, -1.4, 1.3, 1.2), p2);
    }

    {
        Polynomial p1 = new Polynomial(1.6, 1.5, 1.4, 1.3, -1.21);
        Polynomial p2 = new Polynomial(1.6, 1.5, 1.4, 1.3, -1.2);

        Assert.IsFalse(p1 == p2);
        Assert.IsFalse(p2 == p1);
        Assert.IsTrue(p1 != p2);
        Assert.IsTrue(p2 != p1);
        Assert.AreNotEqual(p1, p2);
        Assert.AreNotEqual(p2, p1);
        Assert.AreNotEqual((object)p1, (object)p2);
        Assert.AreNotEqual((object)p2, (object)p1);
    }

    {
        Polynomial p1 = new Polynomial(1.6, 1.5, 1.4, 1.3);
        Polynomial p2 = new Polynomial(1.6, 1.5, 1.4, 1.3, 1.2);

        Assert.IsFalse(p1 == p2);
        Assert.IsFalse(p2 == p1);
        Assert.IsTrue(p1 != p2);
        Assert.IsTrue(p2 != p1);
        Assert.AreNotEqual(p1, p2);
        Assert.AreNotEqual(p2, p1);
        Assert.AreNotEqual((object)p1, (object)p2);
        Assert.AreNotEqual((object)p2, (object)p1);
    }

    {
        Polynomial p1 = new Polynomial(1.6, 1.5, -1.4, -1.3);
        Polynomial p2 = new Polynomial(1.6, 1.5, -1.4, -1.3, 0);

        Assert.IsTrue(p1 == p2);
        Assert.IsTrue(p2 == p1);
        Assert.IsFalse(p1 != p2);
        Assert.IsFalse(p2 != p1);
        Assert.AreEqual(p1, p2);
        Assert.AreEqual(p2, p1);
        Assert.AreEqual((object)p1, (object)p2);
        Assert.AreEqual((object)p2, (object)p1);
    }

    {
        Polynomial p1 = new Polynomial(1.6, 1.5, 1.4, 1.3, 1.2);
        Polynomial p2 = new Polynomial(1.6 / 1.2, 1.5 / 1.2, 1.4 / 1.2, 1.3 / 1.2, 1);

        Assert.IsFalse(p1 == p2);
        Assert.IsFalse(p2 == p1);
        Assert.IsTrue(p1 != p2);
        Assert.IsTrue(p2 != p1);
        Assert.AreNotEqual(p1, p2);
        Assert.AreNotEqual(p2, p1);
        Assert.AreNotEqual((object)p1, (object)p2);
        Assert.AreNotEqual((object)p2, (object)p1);
    }

    // Copying constructor.

    {
        Polynomial p1 = new Polynomial(1.6, 1.5, -1.4, 1.3, 1.2);
        Polynomial p2 = new Polynomial(p1);

        Assert.AreEqual(p1, p2);
        Assert.AreEqual(new Polynomial(1.6, 1.5, -1.4, 1.3, 1.2), p1);
    }

    // IsAlmostRelativeEquals

    {
        Polynomial p1 = new Polynomial(0);
        Polynomial p2 = new Polynomial(1);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == false);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == p2.IsAlmostRelativeEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(0);
        Polynomial p2 = new Polynomial(0);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == true);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == p2.IsAlmostRelativeEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(0);
        Polynomial p2 = new Polynomial(Constants.DOUBLE_PRECISION / 2);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == true);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == p2.IsAlmostRelativeEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(0);
        Polynomial p2 = new Polynomial(Constants.DOUBLE_PRECISION * 2);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == false);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == p2.IsAlmostRelativeEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(1);
        Polynomial p2 = new Polynomial(Constants.DOUBLE_PRECISION / 2);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == false);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == p2.IsAlmostRelativeEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(1);
        Polynomial p2 = new Polynomial(Constants.DOUBLE_PRECISION * 2);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == false);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == p2.IsAlmostRelativeEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(1);
        Polynomial p2 = new Polynomial(1 + Constants.DOUBLE_PRECISION / 2);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == true);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == p2.IsAlmostRelativeEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(1);
        Polynomial p2 = new Polynomial(1 + Constants.DOUBLE_PRECISION * 2);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == false);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == p2.IsAlmostRelativeEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(1, 0);
        Polynomial p2 = new Polynomial(1);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == true);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == p2.IsAlmostRelativeEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(1, 0, 0);
        Polynomial p2 = new Polynomial(1);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == true);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == p2.IsAlmostRelativeEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(1, 0, 0);
        Polynomial p2 = new Polynomial(1, 0);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == true);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == p2.IsAlmostRelativeEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(1, 0, 0);
        Polynomial p2 = new Polynomial(1, 0, 0);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == true);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == p2.IsAlmostRelativeEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(2, 3);
        Polynomial p2 = new Polynomial(2, 3);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == true);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == p2.IsAlmostRelativeEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(2, 3, 0);
        Polynomial p2 = new Polynomial(2, 3);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == true);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == p2.IsAlmostRelativeEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(2, 3, 0, 0);
        Polynomial p2 = new Polynomial(2, 3);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == true);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == p2.IsAlmostRelativeEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(2, 3, 0, 0);
        Polynomial p2 = new Polynomial(2, 3);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == true);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == p2.IsAlmostRelativeEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(2, 3, 0, Constants.DOUBLE_PRECISION / 2);
        Polynomial p2 = new Polynomial(2, 3);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == true);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == p2.IsAlmostRelativeEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(2, 3, 0, Constants.DOUBLE_PRECISION * 2);
        Polynomial p2 = new Polynomial(2, 3);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == false);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == p2.IsAlmostRelativeEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(1 / Constants.DOUBLE_PRECISION, 3);
        Polynomial p2 = new Polynomial(1 / Constants.DOUBLE_PRECISION - 0.5, 3);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == true);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == p2.IsAlmostRelativeEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(1 / Constants.DOUBLE_PRECISION, 3);
        Polynomial p2 = new Polynomial(1 / Constants.DOUBLE_PRECISION - 2, 3);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == false);
        Assert.IsTrue(p1.IsAlmostRelativeEquals(p2) == p2.IsAlmostRelativeEquals(p1));
    }

    // IsAlmostEquals.

    {
        Polynomial p1 = new Polynomial(0);
        Polynomial p2 = new Polynomial(1);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == false);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == p2.IsAlmostEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(0);
        Polynomial p2 = new Polynomial(0);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == true);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == p2.IsAlmostEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(0);
        Polynomial p2 = new Polynomial(Constants.DOUBLE_PRECISION / 2);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == true);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == p2.IsAlmostEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(0);
        Polynomial p2 = new Polynomial(Constants.DOUBLE_PRECISION * 2);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == false);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == p2.IsAlmostEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(1);
        Polynomial p2 = new Polynomial(Constants.DOUBLE_PRECISION / 2);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == false);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == p2.IsAlmostEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(1);
        Polynomial p2 = new Polynomial(Constants.DOUBLE_PRECISION * 2);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == false);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == p2.IsAlmostEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(1);
        Polynomial p2 = new Polynomial(1 + Constants.DOUBLE_PRECISION / 2);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == true);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == p2.IsAlmostEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(1);
        Polynomial p2 = new Polynomial(1 + Constants.DOUBLE_PRECISION * 2);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == false);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == p2.IsAlmostEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(1, 0);
        Polynomial p2 = new Polynomial(1);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == true);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == p2.IsAlmostEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(1, 0, 0);
        Polynomial p2 = new Polynomial(1);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == true);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == p2.IsAlmostEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(1, 0, 0);
        Polynomial p2 = new Polynomial(1, 0);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == true);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == p2.IsAlmostEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(1, 0, 0);
        Polynomial p2 = new Polynomial(1, 0, 0);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == true);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == p2.IsAlmostEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(2, 3);
        Polynomial p2 = new Polynomial(2, 3);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == true);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == p2.IsAlmostEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(2, 3, 0);
        Polynomial p2 = new Polynomial(2, 3);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == true);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == p2.IsAlmostEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(2, 3, 0, 0);
        Polynomial p2 = new Polynomial(2, 3);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == true);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == p2.IsAlmostEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(2, 3, 0, 0);
        Polynomial p2 = new Polynomial(2, 3);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == true);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == p2.IsAlmostEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(2, 3, 0, Constants.DOUBLE_PRECISION / 2);
        Polynomial p2 = new Polynomial(2, 3);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == true);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == p2.IsAlmostEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(2, 3, 0, Constants.DOUBLE_PRECISION * 2);
        Polynomial p2 = new Polynomial(2, 3);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == false);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == p2.IsAlmostEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(1 / Constants.DOUBLE_PRECISION, 3);
        Polynomial p2 = new Polynomial(1 / Constants.DOUBLE_PRECISION - 0.5, 3);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == false);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == p2.IsAlmostEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(1 / Constants.DOUBLE_PRECISION, 3);
        Polynomial p2 = new Polynomial(1 / Constants.DOUBLE_PRECISION - 2, 3);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == false);
        Assert.IsTrue(p1.IsAlmostEquals(p2) == p2.IsAlmostEquals(p1));
    }

    {
        Polynomial p1 = new Polynomial(1 / 1e-6, 3);
        Polynomial p2 = new Polynomial(1 / 1e-6 - 0.5 * 1e-6, 3);
        Assert.IsTrue(p1.IsAlmostEquals(p2, 1e-6) == true);
        Assert.IsTrue(p1.IsAlmostEquals(p2, 1e-6) == p2.IsAlmostEquals(p1, 1e-6));
    }

    {
        Polynomial p1 = new Polynomial(1 / 1e-6, 3);
        Polynomial p2 = new Polynomial(1 / 1e-6 - 2 * 1e-6, 3);
        Assert.IsTrue(p1.IsAlmostEquals(p2, 1e-6) == false);
        Assert.IsTrue(p1.IsAlmostEquals(p2, 1e-6) == p2.IsAlmostEquals(p1, 1e-6));
    }

    // Evaluate.

    {
        AreAlmostRelativeEquals(2.0, new Polynomial(2).Evaluate(2.1));
        AreAlmostRelativeEquals(7.2, new Polynomial(3, 2).Evaluate(2.1));
        AreAlmostRelativeEquals(19.12, new Polynomial(4, 3, 2).Evaluate(2.1));
        AreAlmostRelativeEquals(28.352000000000004, new Polynomial(5, -4, 3, 2).Evaluate(2.1));
        AreAlmostRelativeEquals(100.81920000000001, new Polynomial(6, 5, 4, 3, 2).Evaluate(2.1));
        AreAlmostRelativeEquals(-6.0, new Polynomial(-6, 5, 4, -3, 2).Evaluate(0));
        AreAlmostRelativeEquals(24.253200000000003, new Polynomial(6, 5, 4, 3, 2).Evaluate(-2.1));
        AreAlmostRelativeEquals(17.807100000000005, new Polynomial(6 / 2, 5 / 2, 4 / 2, 3 / 2, 1).Evaluate(-2.1));
        AreAlmostRelativeEquals(45.152, new Polynomial(5, 4, 3, 2, 0).Evaluate(2.1));
        AreAlmostRelativeEquals(19.12, new Polynomial(4, 3, 2, 0, 0).Evaluate(2.1));

        Polynomial p = new Polynomial(4, 3, 2, 0, 0);
        double x = p.Evaluate(4.4);
        Assert.AreEqual(new Polynomial(4, 3, 2, 0, 0), p);
    }

    // Diffrentatie.

    {
        AreAlmostRelativeEquals(0.0, new Polynomial().Differentiate().Evaluate(2.1));
        AreAlmostRelativeEquals(0, new Polynomial(2).Differentiate().Evaluate(2.1));
        AreAlmostRelativeEquals(2.0, new Polynomial(-3, 2).Differentiate().Evaluate(2.1));
        AreAlmostRelativeEquals(11.4, new Polynomial(4, 3, 2).Differentiate().Evaluate(2.1));
        AreAlmostRelativeEquals(17.860000000000003, new Polynomial(5, 4, -3, 2).Differentiate().Evaluate(2.1));
        AreAlmostRelativeEquals(135.57800000000003, new Polynomial(6, 5, 4, 3, 2).Differentiate().Evaluate(2.1));
        AreAlmostRelativeEquals(5, new Polynomial(6, 5, 4, -3, 2).Differentiate().Evaluate(0));
        AreAlmostRelativeEquals(-46.198000000000008, new Polynomial(6, 5, 4, 3, 2).Differentiate().Evaluate(-2.1));
        AreAlmostRelativeEquals(-30.214000000000006, new Polynomial(6 / 2, 5 / 2, 4 / 2, 3 / 2, 1).Differentiate().Evaluate(-2.1));
        AreAlmostRelativeEquals(43.06, new Polynomial(5, 4, 3, 2, 0).Differentiate().Evaluate(2.1));
        AreAlmostRelativeEquals(11.4, new Polynomial(4, 3, 2, 0, 0).Differentiate().Evaluate(2.1));

        Polynomial p = new Polynomial(6, 5, 4, -3, 2);
        Polynomial d = p.Differentiate();
        Assert.AreEqual(new Polynomial(6, 5, 4, -3, 2), p);
    }

    // Normalize.

    {
        Polynomial p1 = new Polynomial(1.6, 1.5, 1.4, 1.3, 1.2).Normalize();
        Polynomial p2 = new Polynomial(1.6 / 1.2, 1.5 / 1.2, 1.4 / 1.2, 1.3 / 1.2, 1);

        Assert.AreEqual(p1, p2);
    }

    {
        Polynomial p = new Polynomial(1.6, 1.5, 1.4, 1.3, -1.2);
        Polynomial p1 = p.Normalize();
        Polynomial p2 = new Polynomial(1.6 / -1.2, 1.5 / -1.2, 1.4 / -1.2, 1.3 / -1.2, 1);

        Assert.AreEqual(p1, p2);
        Assert.AreEqual(p, new Polynomial(1.6, 1.5, 1.4, 1.3, -1.2));
    }

    {
        Polynomial p1 = new Polynomial(1.6, 1.5, 1.4, 1.3, 0).Normalize();
        Polynomial p2 = new Polynomial(1.6, 1.5, 1.4, 1.3, 0);

        Assert.AreNotEqual(p1, p2);
    }

    {
        Polynomial p1 = new Polynomial(1.6, 1.5, -1.4, 1.3, 0).Normalize();
        Polynomial p2 = new Polynomial(1.6 / 1.3, 1.5 / 1.3, -1.4 / 1.3, 1);

        Assert.AreEqual(p1, p2);
    }

    // operator / , DivRem(Rem)

    {
        Polynomial p1 = new Polynomial(1.6, 1.5, 1.4, 1.3, 1.2);
        Polynomial p2 = new Polynomial(1.6, 1.5, 1.4, 1.3, 1.2);

        Polynomial p3 = p1 / p2;
        Polynomial rem;
        Polynomial p4 = Polynomial.DivRem(p1, p2, out rem);

        Assert.AreEqual(p3, p4);
        AreAlmostRelativeEquals(new Polynomial(1.0), p3);

        Assert.AreEqual(new Polynomial(1.6, 1.5, 1.4, 1.3, 1.2), p1);
        Assert.AreEqual(new Polynomial(1.6, 1.5, 1.4, 1.3, 1.2), p2);
    }

    {
        Polynomial p1 = new Polynomial(1.6, 1.5, 1.4, 1.3, 1.2);
        Polynomial p2 = new Polynomial(1.6, 1.5, 1.4, 1.3);

        Polynomial p3 = p1 / p2;
        Polynomial rem;
        Polynomial p4 = Polynomial.DivRem(p1, p2, out rem);

        Assert.AreEqual(p3, p4);
        AreAlmostRelativeEquals(new Polynomial(0.0059171597633137594, 0.923076923076923), p3);
    }

    {
        Polynomial p1 = new Polynomial(1.6, 1.5, 1.4, 1.3, 1.2);
        Polynomial p2 = new Polynomial(1.6, 1.5, 1.4);

        Polynomial p3 = p1 / p2;
        Polynomial rem;
        Polynomial p4 = Polynomial.DivRem(p1, p2, out rem);

        Assert.AreEqual(p3, p4);
        AreAlmostRelativeEquals(new Polynomial(0.00947521865889193, 0.010204081632653, 0.857142857142857), p3);
    }

    {
        Polynomial p1 = new Polynomial(1.6, 1.5, 1.4, -1.3, 1.2);
        Polynomial p2 = new Polynomial(1.6, 1.5);

        Polynomial p3 = p1 / p2;
        Polynomial rem;
        Polynomial p4 = Polynomial.DivRem(p1, p2, out rem);

        Assert.AreEqual(p3, p4);
        AreAlmostRelativeEquals(new Polynomial(-1.95253333333333, 2.768, -1.72, 0.8), p3);
    }

    {
        Polynomial p1 = new Polynomial(1.6, 1.5, -1.4, 1.3, 1.2);
        Polynomial p2 = new Polynomial(1.6);

        Polynomial p3 = p1 / p2;
        Polynomial rem;
        Polynomial p4 = Polynomial.DivRem(p1, p2, out rem);

        Assert.AreEqual(p3, p4);
        AreAlmostRelativeEquals(new Polynomial(1, 0.9375, -0.875, 0.8125, 0.75), p3);
    }

    {
        Polynomial p1 = new Polynomial(1.6, 1.5, 1.4, 1.3);
        Polynomial p2 = new Polynomial(1.6, 1.5, 1.4, 1.3, 1.2);

        Polynomial p3 = p1 / p2;
        Polynomial rem;
        Polynomial p4 = Polynomial.DivRem(p1, p2, out rem);

        Assert.AreEqual(p3, p4);
        AreAlmostRelativeEquals(Polynomial.ZERO, p3);
    }

    {
        Polynomial p1 = new Polynomial(1.6, 1.5, 1.4, 1.3, 0);
        Polynomial p2 = new Polynomial(1.6, 1.5, 1.4, 1.3);

        Polynomial p3 = p1 / p2;
        Polynomial rem;
        Polynomial p4 = Polynomial.DivRem(p1, p2, out rem);

        Assert.AreEqual(p3, p4);
        AreAlmostRelativeEquals(new Polynomial(1.0), p3);
    }

    // operator %, DivRem(div)

    {
        Polynomial p1 = new Polynomial(1.6, 1.5, 1.4, 1.3, 1.2);
        Polynomial p2 = new Polynomial(1.6, 1.5, 1.4, 1.3, 1.2);

        Polynomial p3 = p1 % p2;
        Polynomial rem;
        Polynomial.DivRem(p1, p2, out rem);

        Assert.AreEqual(p3, rem);
        AreAlmostRelativeEquals(Polynomial.ZERO, p3);
    }

    {
        Polynomial p1 = new Polynomial(1.6, 1.5, 1.4, 1.3, 1.2);
        Polynomial p2 = new Polynomial(1.6, 1.5, 1.4, 1.3);

        Polynomial p3 = p1 % p2;
        Polynomial rem;
        Polynomial.DivRem(p1, p2, out rem);

        Assert.AreEqual(p3, rem);
        AreAlmostRelativeEquals(new Polynomial(1.5905325443787, 0.0142011834319524, 0.00710059171597607), p3);
    }

    {
        Polynomial p1 = new Polynomial(1.6, 1.5, -1.4, 1.3, 1.2);
        Polynomial p2 = new Polynomial(1.6, 1.5, 1.4);

        Polynomial p3 = p1 % p2;
        Polynomial rem;
        Polynomial.DivRem(p1, p2, out rem);

        Assert.AreEqual(p3, rem);
        AreAlmostRelativeEquals(new Polynomial(4.78483965014577, 4.46946064139942), p3);
    }

    {
        Polynomial p1 = new Polynomial(1.6, 1.5, -1.4, 1.3, 1.2);
        Polynomial p2 = new Polynomial(1.6, 1.5);

        Polynomial p3 = p1 % p2;
        Polynomial rem;
        Polynomial.DivRem(p1, p2, out rem);

        Assert.AreEqual(p3, rem);
        AreAlmostRelativeEquals(new Polynomial(-1.61716148148148), p3);
    }

    {
        Polynomial p1 = new Polynomial(1.6, 1.5, 1.4, 1.3, 1.2);
        Polynomial p2 = new Polynomial(1.6);

        Polynomial p3 = p1 % p2;
        Polynomial rem;
        Polynomial.DivRem(p1, p2, out rem);

        Assert.AreEqual(p3, rem);
        AreAlmostRelativeEquals(Polynomial.ZERO, p3);
    }

    {
        Polynomial p1 = new Polynomial(1.6, 1.5, 1.4, 1.3);
        Polynomial p2 = new Polynomial(1.6, 1.5, 1.4, 1.3, 1.2);

        Polynomial p3 = p1 % p2;
        Polynomial rem;
        Polynomial.DivRem(p1, p2, out rem);

        Assert.AreEqual(p3, rem);
        AreAlmostRelativeEquals(new Polynomial(1.6, 1.5, 1.4, 1.3), p3);

        Assert.AreEqual(new Polynomial(1.6, 1.5, 1.4, 1.3), p1);
        Assert.AreEqual(new Polynomial(1.6, 1.5, 1.4, 1.3, 1.2), p2);
    }

    {
        Polynomial p1 = new Polynomial(1.6, 1.5, 1.4, 1.3, 0);
        Polynomial p2 = new Polynomial(1.6, 1.5, 1.4, 1.3);

        Polynomial p3 = p1 % p2;
        Polynomial rem;
        Polynomial.DivRem(p1, p2, out rem);

        Assert.AreEqual(p3, rem);
        AreAlmostRelativeEquals(Polynomial.ZERO, p3);
    }

    // operator * polynomials
    {
        Polynomial p1 = Polynomial.ZERO;
        Polynomial p2 = Polynomial.ZERO;

        Polynomial p3 = p1 * p2;
        Polynomial p4 = p2 * p1;

        Assert.AreEqual(p3, p4);
        AreAlmostRelativeEquals(Polynomial.ZERO, p3);
    }

    {
        Polynomial p1 = Polynomial.ZERO;
        Polynomial p2 = new Polynomial(1.6, 1.5, 1.4, 1.3);

        Polynomial p3 = p1 * p2;
        Polynomial p4 = p2 * p1;

        Assert.AreEqual(p3, p4);
        AreAlmostRelativeEquals(Polynomial.ZERO, p3);
    }

    {
        Polynomial p1 = new Polynomial(1.5);
        Polynomial p2 = new Polynomial(1.3);

        Polynomial p3 = p1 * p2;
        Polynomial p4 = p2 * p1;

        Assert.AreEqual(p3, p4);
        AreAlmostRelativeEquals(new Polynomial(1.95), p3);
    }

    {
        Polynomial p1 = new Polynomial(1.5);
        Polynomial p2 = new Polynomial(1.4, 1.3);

        Polynomial p3 = p1 * p2;
        Polynomial p4 = p2 * p1;

        Assert.AreEqual(p3, p4);
        AreAlmostRelativeEquals(new Polynomial(2.1, 1.95), p3);
    }

    {
        Polynomial p1 = new Polynomial(1.4, 1.5);
        Polynomial p2 = new Polynomial(1.6, 1.3);

        Polynomial p3 = p1 * p2;
        Polynomial p4 = p2 * p1;

        Assert.AreEqual(p3, p4);
        AreAlmostRelativeEquals(new Polynomial(2.24, 4.22, 1.95), p3);
    }

    {
        Polynomial p1 = new Polynomial(-0.9, 1.3, 1.4, 1.5);
        Polynomial p2 = new Polynomial(1.6, 1.3);

        Polynomial p3 = p1 * p2;
        Polynomial p4 = p2 * p1;

        Assert.AreEqual(p3, p4);
        AreAlmostRelativeEquals(new Polynomial(-1.44, 0.91, 3.93, 4.22, 1.95), p3);

        Assert.AreEqual(p1, new Polynomial(-0.9, 1.3, 1.4, 1.5));
        Assert.AreEqual(p2, new Polynomial(1.6, 1.3));
    }

    {
        Polynomial p1 = new Polynomial(0.9, 1.3, 1.4, 1.5);
        Polynomial p2 = new Polynomial(1.6, 1.3);

        Polynomial p3 = p1 * p2;
        Polynomial p4 = p2 * p1;

        Assert.AreEqual(p3, p4);
        AreAlmostRelativeEquals(new Polynomial(1.44, 3.25, 3.93, 4.22, 1.95), p3);
    }

    {
        Polynomial p1 = new Polynomial(-1.3, 1.4, 1.5);
        Polynomial p2 = new Polynomial(1.2, -1.6, 1.3);

        Polynomial p3 = p1 * p2;
        Polynomial p4 = p2 * p1;

        Assert.AreEqual(p3, p4);
        AreAlmostRelativeEquals(new Polynomial(-1.56, 3.76, -2.13, -0.580000000000001, 1.95), p3);
    }

    // operator +  
    {
        Polynomial p1 = Polynomial.ZERO;
        Polynomial p2 = Polynomial.ZERO;

        Polynomial p3 = p1 + p2;
        Polynomial p4 = p2 + p1;

        Assert.AreEqual(p3, p4);
        AreAlmostRelativeEquals(Polynomial.ZERO, p3);
    }

    {
        Polynomial p1 = Polynomial.ZERO;
        Polynomial p2 = new Polynomial(1.6, 1.5, 1.4, 1.3);

        Polynomial p3 = p1 + p2;
        Polynomial p4 = p2 + p1;

        Assert.AreEqual(p3, p4);
        AreAlmostRelativeEquals(new Polynomial(1.6, 1.5, 1.4, 1.3), p3);
    }

    {
        Polynomial p1 = new Polynomial(1.5);
        Polynomial p2 = new Polynomial(-1.3);

        Polynomial p3 = p1 + p2;
        Polynomial p4 = p2 + p1;

        Assert.AreEqual(p3, p4);
        AreAlmostRelativeEquals(new Polynomial(0.19999999999999996), p3);
    }

    {
        Polynomial p1 = new Polynomial(1.7, -1.6, 1.5);
        Polynomial p2 = new Polynomial(0.3, -0.2, 0.1, 1.4, 1.3);

        Polynomial p3 = p1 + p2;
        Polynomial p4 = p2 + p1;

        Assert.AreEqual(p3, p4);
        AreAlmostRelativeEquals(new Polynomial(2, -1.8, 1.6, 1.4, 1.3), p3);

        Assert.AreEqual(new Polynomial(1.7, -1.6, 1.5), p1);
        Assert.AreEqual(new Polynomial(0.3, -0.2, 0.1, 1.4, 1.3), p2);
    }

    {
        Polynomial p1 = new Polynomial(0.3, 0.2, -0.1, 1.4, 1.3);
        Polynomial p2 = new Polynomial(-0.5, 0.4, 0.3, 2.4, 2.3);

        Polynomial p3 = p1 + p2;
        Polynomial p4 = p2 + p1;

        Assert.AreEqual(p3, p4);
        AreAlmostRelativeEquals(new Polynomial(-0.2, 0.6, 0.2, 3.8, 3.6), p3);
    }

    {
        Polynomial p1 = new Polynomial(0.3, 0.2, -0.1, 1.4, 1.3);
        Polynomial p2 = -new Polynomial(0.3, 0.2, -0.1, 1.4, 1.3);

        Polynomial p3 = p1 + p2;
        Polynomial p4 = p2 + p1;

        Assert.AreEqual(p3, p4);
        AreAlmostRelativeEquals(Polynomial.ZERO, p3);
    }

    // operator -
    {
        Polynomial p1 = Polynomial.ZERO;
        Polynomial p2 = Polynomial.ZERO;

        Polynomial p3 = p1 - p2;
        Polynomial p4 = p2 - p1;

        AreAlmostRelativeEquals(Polynomial.ZERO, p3);
        AreAlmostRelativeEquals(Polynomial.ZERO, p4);
    }

    {
        Polynomial p1 = Polynomial.ZERO;
        Polynomial p2 = new Polynomial(1.6, 1.5, 1.4, 1.3);

        Polynomial p3 = p1 - p2;
        Polynomial p4 = p2 - p1;

        AreAlmostRelativeEquals(new Polynomial(-1.6, -1.5, -1.4, -1.3), p3);
        AreAlmostRelativeEquals(-new Polynomial(-1.6, -1.5, -1.4, -1.3), p4);
    }

    {
        Polynomial p1 = new Polynomial(1.5);
        Polynomial p2 = new Polynomial(-1.3);

        Polynomial p3 = p1 - p2;
        Polynomial p4 = p2 - p1;

        AreAlmostRelativeEquals(new Polynomial(2.8), p3);
        AreAlmostRelativeEquals(-new Polynomial(2.8), p4);
    }

    {
        Polynomial p1 = new Polynomial(1.7, -1.6, 1.5);
        Polynomial p2 = new Polynomial(0.3, -0.2, 0.1, 1.4, 1.3);

        Polynomial p3 = p1 - p2;
        Polynomial p4 = p2 - p1;

        AreAlmostRelativeEquals(new Polynomial(1.4, -1.4, 1.4, -1.4, -1.3), p3);
        AreAlmostRelativeEquals(-new Polynomial(1.4, -1.4, 1.4, -1.4, -1.3), p4);

        Assert.AreEqual(new Polynomial(1.7, -1.6, 1.5), p1);
        Assert.AreEqual(new Polynomial(0.3, -0.2, 0.1, 1.4, 1.3), p2);
    }

    {
        Polynomial p1 = new Polynomial(0.3, 0.2, -0.1, 1.4, 1.3);
        Polynomial p2 = new Polynomial(-0.5, 0.4, 0.3, 2.4, 2.3);

        Polynomial p3 = p1 - p2;
        Polynomial p4 = p2 - p1;

        AreAlmostRelativeEquals(new Polynomial(0.8, -0.2, -0.4, -1, -1), p3);
        AreAlmostRelativeEquals(-new Polynomial(0.8, -0.2, -0.4, -1, -1), p4);
    }

    {
        Polynomial p1 = new Polynomial(1.3, 1.4, -0.1, 0.2, 0.3);
        Polynomial p2 = new Polynomial(1.3, 1.4, -0.1, 0.2, 0.3);

        Polynomial p3 = p1 - p2;
        Polynomial p4 = p2 - p1;

        AreAlmostRelativeEquals(Polynomial.ZERO, p3);
        AreAlmostRelativeEquals(Polynomial.ZERO, p4);
    }

    // operator - unary

    {
        Polynomial p = Polynomial.ZERO;
        AreAlmostRelativeEquals(p, - -p);
        AreAlmostRelativeEquals(-p, Polynomial.ZERO - p);
    }

    {
        Polynomial p = new Polynomial(1.0);
        AreAlmostRelativeEquals(p, - -p);
        AreAlmostRelativeEquals(-p, Polynomial.ZERO - p);
    }

    {
        Polynomial p = new Polynomial(6.7, -4.5, 3.4, -2.0);
        AreAlmostRelativeEquals(p, - -p);
        AreAlmostRelativeEquals(-p, Polynomial.ZERO - p);

        Polynomial pp = -p;
        Assert.AreEqual(new Polynomial(6.7, -4.5, 3.4, -2.0), p);
    }

    // operator * const

    {
        Polynomial p1 = Polynomial.ZERO * 6;
        Polynomial p2 = 6 * Polynomial.ZERO;

        AreAlmostRelativeEquals(Polynomial.ZERO, p1);
        AreAlmostRelativeEquals(p1, p2);
    }

    {
        Polynomial p1 = new Polynomial(1.0) * 5;
        Polynomial p2 = 5 * new Polynomial(1.0);

        AreAlmostRelativeEquals(new Polynomial(5.0), p1);
        AreAlmostRelativeEquals(p1, p2);
    }

    {
        Polynomial p = new Polynomial(6.7, -4.5, 3.4, -2.0);
        Polynomial p1 = p * -2;
        Polynomial p2 = -2 * new Polynomial(6.7, -4.5, 3.4, -2.0);

        AreAlmostRelativeEquals(new Polynomial(-13.4, 9, -6.8, 4.0), p1);
        AreAlmostRelativeEquals(p1, p2);
        Assert.AreEqual(new Polynomial(6.7, -4.5, 3.4, -2.0), p);
    }

    {
        Polynomial p = new Polynomial(6.7, -4.5, 3.4, -2.0) * 0;

        AreAlmostRelativeEquals(Polynomial.ZERO, p);
    }

    // operator / const

    {
        Polynomial p = Polynomial.ZERO / 6;

        AreAlmostRelativeEquals(Polynomial.ZERO, p);
    }

    {
        Polynomial p = new Polynomial(5.0) / 5;

        AreAlmostRelativeEquals(new Polynomial(1.0), p);
    }

    {
        Polynomial pp = new Polynomial(-13.4, 9, -6.8, 4.0);
        Polynomial p = pp / -2;

        AreAlmostRelativeEquals(new Polynomial(6.7, -4.5, 3.4, -2.0), p);
        Assert.AreEqual(new Polynomial(-13.4, 9, -6.8, 4.0), pp);
    }

    {
        Polynomial p = new Polynomial(-13.4, 9, -6.8, 4.0) / Double.PositiveInfinity;

        AreAlmostRelativeEquals(Polynomial.ZERO, p);
    }

    // Pow 

    {
        Polynomial p1 = p_1;
        Polynomial p2 = p1 ^ 0;

        AreAlmostRelativeEquals(Polynomial.ONE, p2);
    }

    {
        Polynomial p1 = p_1;
        Polynomial p2 = p1 ^ 1;

        AreAlmostRelativeEquals(p_1, p2);
    }

    {
        Polynomial p1 = p_1 * p_1;
        Polynomial p2 = p1 ^ 1;

        AreAlmostRelativeEquals(p_1 * p_1, p2);
    }

    {
        Polynomial p1 = p_1 * p_1;
        Polynomial p2 = p1 ^ 2;

        AreAlmostRelativeEquals(p_1 * p_1 * p_1 * p_1, p2);
    }

    {
        Polynomial p1 = p_1;
        Polynomial p2 = p1 ^ 4;

        AreAlmostRelativeEquals(p_1 * p_1 * p_1 * p_1, p2);
    }

    // GCD

    {
        Polynomial A = p_1;
        Polynomial B = p_2;
        Polynomial GCD = Polynomial.GCD(A, B);
        Polynomial expected = Polynomial.ONE;

        AreAlmostRelativeEquals(expected, GCD);
    }

    {
        Polynomial A = p_2;
        Polynomial B = p_1;
        Polynomial GCD = Polynomial.GCD(A, B);
        Polynomial expected = Polynomial.ONE;

        AreAlmostRelativeEquals(expected, GCD);
    }

    {
        Polynomial A = p_1;
        Polynomial B = p_1;
        Polynomial GCD = Polynomial.GCD(A, B);
        Polynomial expected = p_1.Normalize();

        AreAlmostRelativeEquals(expected, GCD);
    }

    {
        Polynomial A = p_1;
        Polynomial B = Polynomial.ZERO;
        Polynomial GCD = Polynomial.GCD(A, B);
        Polynomial expected = p_1.Normalize();

        AreAlmostRelativeEquals(expected, GCD);
    }

    {
        Polynomial A = p_1;
        Polynomial B = Polynomial.ONE;
        Polynomial GCD = Polynomial.GCD(A, B);
        Polynomial expected = Polynomial.ONE;

        AreAlmostRelativeEquals(expected, GCD);
    }

    {
        Polynomial A = Polynomial.ZERO;
        Polynomial B = p_2;
        Polynomial GCD = Polynomial.GCD(A, B);
        Polynomial expected = p_2.Normalize();

        AreAlmostRelativeEquals(expected, GCD);
    }

    {
        Polynomial A = Polynomial.ONE;
        Polynomial B = p_2;
        Polynomial GCD = Polynomial.GCD(A, B);
        Polynomial expected = Polynomial.ONE;

        AreAlmostRelativeEquals(expected, GCD);
    }

    {
        Polynomial A = p_1 * p_1;
        Polynomial B = p_1;
        Polynomial GCD = Polynomial.GCD(A, B);
        Polynomial expected = p_1.Normalize();

        AreAlmostRelativeEquals(expected, GCD);
    }

    {
        Polynomial A = 2 * p_1 * p_1;
        Polynomial B = p_1;
        Polynomial GCD = Polynomial.GCD(A, B);
        Polynomial expected = p_1.Normalize();

        AreAlmostRelativeEquals(expected, GCD);
    }

    {
        Polynomial A = 2 * p_1 * p_1;
        Polynomial B = 2 * p_1;
        Polynomial GCD = Polynomial.GCD(A, B);
        Polynomial expected = p_1.Normalize();

        AreAlmostRelativeEquals(expected, GCD);
    }

    {
        Polynomial A = p_1 ^ 3;
        Polynomial B = p_1 ^ 4;
        Polynomial GCD = Polynomial.GCD(A, B);
        Polynomial expected = (p_1 ^ 3).Normalize();

        AreAlmostRelativeEquals(expected, GCD);
    }

    {
        Polynomial A = p_1 * p_2 * p_2 * p_2;
        Polynomial B = A.Differentiate();
        Polynomial GCD = Polynomial.GCD(A, B);
        Polynomial expected = (p_2 * p_2).Normalize();

        AreAlmostRelativeEquals(expected, GCD);
    }

    {
        Polynomial A = p_1 * p_1 * p_2 * p_2;
        Polynomial B = A.Differentiate();
        Polynomial GCD = Polynomial.GCD(A, B);
        Polynomial expected = (p_1 * p_2).Normalize();

        AreAlmostRelativeEquals(expected, GCD);
    }

    {
        Polynomial A = p_1 * p_2 * (p_4 ^ 3);
        Polynomial B = p_1 * (p_2 ^ 2) * (p_3 ^ 3) * (p_4 ^ 4);
        Polynomial GCD = Polynomial.GCD(A, B, 1e-9);
        Polynomial expected = (p_1 * p_2 * (p_4 ^ 3)).Normalize();

        AreAlmostRelativeEquals(expected, GCD);
    }

    {
        Polynomial A = p_1 * p_2 * (p_4 ^ 3);
        Polynomial B = A.Differentiate();
        Polynomial GCD = Polynomial.GCD(A, B);
        Polynomial expected = (p_4 ^ 2).Normalize();

        AreAlmostRelativeEquals(expected, GCD);
    }

    {
        Polynomial A = p_1 * p_2 * (p_4 ^ 2) * (p_5 ^ 3) * (p_6 ^ 2);
        Polynomial B = p_1 * (p_2 ^ 2) * (p_4 ^ 3) * (p_5 ^ 2) * (p_6 ^ 2);
        Polynomial GCD = Polynomial.GCD(A, B, 1e-7);
        Polynomial expected = (p_1 * p_2 * (p_4 ^ 2) * (p_5 ^ 2) * (p_6 ^ 2)).Normalize();

        AreAlmostRelativeEquals(expected, GCD);
    }

    {
        Polynomial A = p_1 * p_2 * (p_4 ^ 2) * (p_5 ^ 2);
        Polynomial B = A.Differentiate();
        Polynomial GCD = Polynomial.GCD(A, B, 1e-11);
        Polynomial expected = (p_4 * p_5).Normalize();

        AreAlmostRelativeEquals(expected, GCD);
    }

    {
        Polynomial A = p_1 * p_2 * (p_4 ^ 2) * (p_5 ^ 3);
        Polynomial B = A.Differentiate();
        Polynomial GCD = Polynomial.GCD(A, B, 1e-9);
        Polynomial expected = (p_4 * (p_5 ^ 2)).Normalize();

        AreAlmostRelativeEquals(expected, GCD, 1e-11);
    }

    // RemoveZeroes.

    {
        Polynomial p1 = new Polynomial(Constants.DOUBLE_PRECISION / 10);
        Polynomial p2 = p1.RemoveZeroes();

        AreAlmostRelativeEquals(p1, p2);
    }

    {
        Polynomial p1 = new Polynomial(Constants.DOUBLE_PRECISION / 10, 1);
        Polynomial p2 = p1.RemoveZeroes();

        AreAlmostRelativeEquals(new Polynomial(1), p2);
    }

    {
        Polynomial p1 = new Polynomial(Constants.DOUBLE_PRECISION / 10, Constants.DOUBLE_PRECISION / 10, 2, 4);
        Polynomial p2 = p1.RemoveZeroes();

        AreAlmostRelativeEquals(new Polynomial(2, 4), p2);
    }

    {
        Polynomial p1 = new Polynomial(Constants.DOUBLE_PRECISION / 10, Constants.DOUBLE_PRECISION * 10, 2, 4);
        Polynomial p2 = p1.RemoveZeroes();

        AreAlmostRelativeEquals(new Polynomial(Constants.DOUBLE_PRECISION * 10, 2, 4), p2);
    }
}

Brak komentarzy:

Prześlij komentarz