/// <summary>
 /// Create a new polynomial by copy
 /// </summary>
 /// <param name="copy">A polynomial to copy from.</param>
 public Polynomial(
     Polynomial copy
     )
 {
     this.order = copy.order;
     this.coefficients = new double[copy.coefficients.Length];
     Array.Copy(
         copy.coefficients,
         this.coefficients,
         Math.Min(this.coefficients.Length, copy.coefficients.Length)
         );
 }
 /// <summary>Subtract anoter polynomial inplace from this polynomial.</summary>
 /// <remarks>This method operates inplace and thus alters this instance.</remarks>
 public void SubtractInplace(
     Polynomial polynomial
     )
 {
     EnsureSupportForOrder(polynomial.Order);
     int len = Math.Min(order, polynomial.order) + 1;
     for(int i = 0; i < len; i++)
     {
         coefficients[i] -= polynomial.coefficients[i];
     }
 }
        /// <summary>
        /// Multiply two small polynomials.
        /// </summary>
        public Polynomial MultiplySlow(
            Polynomial polynomial
            )
        {
            double[] coeff = new double[1 + Order + polynomial.Order];
            for(int i = 0; i <= order; i++)
            {
                for(int j = 0; j <= polynomial.order; j++)
                {
                    coeff[i + j] += coefficients[i] * polynomial.coefficients[j];
                }
            }

            return new Polynomial(coeff);
        }
        /// <summary>
        /// Multiply two polynomials.
        /// </summary>
        /// <remarks>
        /// If both polynomials have an order > 3, the faster karatsua algorithm is used.
        /// </remarks>
        public Polynomial Multiply(
            Polynomial polynomial
            )
        {
            int orderMin = Math.Min(Order, polynomial.Order);
            if(orderMin > 3)
            {
                int orderMax = Math.Max(Order, polynomial.Order);
                this.EnsureSupportForOrder(orderMax);
                polynomial.EnsureSupportForOrder(orderMax);

                return MultiplyKaratsuba(
                    this.coefficients,
                    polynomial.coefficients,
                    this.order,
                    polynomial.order,
                    SizeOfOrder(orderMax),
                    0
                    );
            }
            else
            {
                double[] coeff = new double[1 + Order + polynomial.Order];
                for(int i = 0; i <= order; i++)
                {
                    for(int j = 0; j <= polynomial.order; j++)
                    {
                        coeff[i + j] += coefficients[i] * polynomial.coefficients[j];
                    }
                }

                return new Polynomial(coeff);
            }
        }
 /// <summary>
 /// Divides this polynomial with anoter polynomial.
 /// </summary>
 public Rational Divide(
     Polynomial polynomial
     )
 {
     return new Rational(Clone(), polynomial.Clone());
 }
 /// <summary>
 /// Check whether this polynomial is equal to another polynomial.
 /// </summary>
 public bool Equals(
     Polynomial polynomial
     )
 {
     return CompareTo(polynomial) == 0;
 }
        /// <summary>
        /// Check whether two polynomials are equal.
        /// </summary>
        public static bool Equals(
            Polynomial polynomial1,
            Polynomial polynomial2
            )
        {
            if(polynomial1 == null)
            {
                return polynomial2 == null;
            }

            return polynomial1.Equals(polynomial2);
        }
        /// <summary>
        /// Compare this polynomial to another polynomial.
        /// </summary>
        public int CompareTo(
            Polynomial polynomial
            )
        {
            int i = this.Order;
            int j = polynomial.Order;

            if(i > j)
            {
                return 1;
            }

            if(j > i)
            {
                return -1;
            }

            while(i >= 0)
            {
                if(this.coefficients[i] > polynomial.coefficients[i])
                {
                    return 1;
                }

                if(this.coefficients[i] < polynomial.coefficients[i])
                {
                    return -1;
                }

                i--;
            }

            return 0;
        }
 /// <summary>
 /// Negate a polynomial.
 /// </summary>
 public static Polynomial operator -(
     Polynomial polynomial
     )
 {
     Polynomial ret = new Polynomial(polynomial);
     ret.NegateInplace();
     return ret;
 }
 /// <summary>
 /// Stretch a polynomial with a real number quotient.
 /// </summary>
 /// <remarks>
 /// The quotient must not be null.
 /// </remarks>
 /// <exception cref="System.DivideByZeroException" />
 public static Polynomial operator /(
     Polynomial polynomial,
     double n
     )
 {
     Polynomial ret = new Polynomial(polynomial);
     ret.DivideInplace(n);
     return ret;
 }
 /// <summary>
 /// Subtract a real number from a polynomial.
 /// </summary>
 public static Polynomial operator -(
     Polynomial polynomial,
     double n
     )
 {
     Polynomial ret = new Polynomial(polynomial);
     ret.SubtractInplace(n);
     return ret;
 }
 /// <summary>
 /// Subtract a polynomial from another polynomial.
 /// </summary>
 public static Polynomial operator -(
     Polynomial polynomial1,
     Polynomial polynomial2
     )
 {
     Polynomial ret = new Polynomial(polynomial1);
     ret.SubtractInplace(polynomial2);
     return ret;
 }
 /// <summary>
 /// Add a polynomial to a real number.
 /// </summary>
 public static Polynomial operator +(
     double n,
     Polynomial polynomial
     )
 {
     Polynomial ret = new Polynomial(polynomial);
     ret.AddInplace(n);
     return ret;
 }
 /// <summary>
 /// Add a polynomials to a polynomial.
 /// </summary>
 public static Polynomial operator +(
     Polynomial polynomial1,
     Polynomial polynomial2
     )
 {
     Polynomial ret = new Polynomial(polynomial1);
     ret.AddInplace(polynomial2);
     return ret;
 }
 /// <summary>
 /// Stretch a polynomial with a real number factor.
 /// </summary>
 public static Polynomial operator *(
     double n,
     Polynomial polynomial
     )
 {
     Polynomial ret = new Polynomial(polynomial);
     ret.MultiplyInplace(n);
     return ret;
 }