public static IComplexPolynomial Pow(IComplexPolynomial poly, int exponent)
        {
            if (exponent < 0)
            {
                throw new NotImplementedException("Raising a polynomial to a negative exponent not supported. Build this functionality if it is needed.");
            }
            else if (exponent == 0)
            {
                return(new ComplexPolynomial(new ComplexTerm[] { new ComplexTerm(1, 0) }));
            }
            else if (exponent == 1)
            {
                return(poly.Clone());
            }
            else if (exponent == 2)
            {
                return(Square(poly));
            }

            IComplexPolynomial total = ComplexPolynomial.Square(poly);

            int counter = exponent - 2;

            while (counter != 0)
            {
                total    = ComplexPolynomial.Multiply(total, poly);
                counter -= 1;
            }

            return(total);
        }
        public void TestParse()
        {
            string expectedFirst  = "7*X^2 + 3*X - 2";
            string expectedSecond = "2*X - 2";
            string expectedThird  = "X^4 + 8*X^3 + 21*X^2 + 22*X + 8";
            string expectedFourth = "X^4 + 8*X^3 + 21*X^2 + 22*X + 8";
            string expectedFifth  = "X^3 + 6*X^2 + 11*X + 6";

            IComplexPolynomial firstPoly   = ComplexPolynomial.Parse(expectedFirst);
            IComplexPolynomial secondPoly  = ComplexPolynomial.Parse(expectedSecond);
            IComplexPolynomial thirdPoly   = ComplexPolynomial.Parse(expectedThird);
            IComplexPolynomial firstFourth = ComplexPolynomial.Parse(expectedFourth);
            IComplexPolynomial firstFifth  = ComplexPolynomial.Parse(expectedFifth);

            string actualFirst  = firstPoly.ToString();
            string actualSecond = secondPoly.ToString();
            string actualThird  = thirdPoly.ToString();
            string actualFouth  = firstFourth.ToString();
            string actualFifth  = firstFifth.ToString();

            Assert.AreEqual(expectedFirst, actualFirst, $"Test Parse({expectedFirst})");
            Assert.AreEqual(expectedSecond, actualSecond, $"Test Parse({expectedSecond})");
            Assert.AreEqual(expectedThird, actualThird, $"Test Parse({expectedThird})");
            Assert.AreEqual(expectedFourth, actualFouth, $"Test Parse({expectedFourth})");
            Assert.AreEqual(expectedFifth, actualFifth, $"Test Parse({expectedFifth})");
        }
        public static void MakeCoefficientsSmaller(IComplexPolynomial polynomial, Complex polynomialBase, Complex maxCoefficientSize = default(Complex))
        {
            Complex maxSize = maxCoefficientSize;

            if (maxSize == default(Complex))
            {
                maxSize = polynomialBase;
            }

            int pos = 0;
            int deg = polynomial.Degree;

            while (pos < deg)
            {
                if (pos + 1 > deg)
                {
                    return;
                }

                if (Complex.Abs(polynomial[pos]) > Complex.Abs(maxSize) &&
                    Complex.Abs(polynomial[pos]) > Complex.Abs(polynomial[pos + 1]))
                {
                    Complex diff = polynomial[pos] - maxSize;

                    Complex toAdd    = (diff / polynomialBase) + 1;
                    Complex toRemove = toAdd * polynomialBase;

                    polynomial[pos]     -= toRemove;
                    polynomial[pos + 1] += toAdd;
                }

                pos++;
            }
        }
        public static IComplexPolynomial GCD(IComplexPolynomial left, IComplexPolynomial right)
        {
            IComplexPolynomial a = left.Clone();
            IComplexPolynomial b = right.Clone();

            if (b.Degree > a.Degree)
            {
                IComplexPolynomial swap = b;
                b = a;
                a = swap;
            }

            while (!(b.Degree == 0 || (b.Terms[0].CoEfficient.Real == 1 && b.Terms[0].CoEfficient.Imaginary == 0)))
            {
                IComplexPolynomial temp = a.Clone();
                a = b.Clone();
                b = ComplexPolynomial.Mod(temp, b);
            }

            if (a.Degree == 0)
            {
                return(ComplexPolynomial.One);
            }
            else
            {
                return(a);
            }
        }
        public static IComplexPolynomial GCD(IComplexPolynomial left, IComplexPolynomial right, Complex modulus)
        {
            IComplexPolynomial a = left.Clone();
            IComplexPolynomial b = right.Clone();

            if (b.Degree > a.Degree)
            {
                IComplexPolynomial swap = b;
                b = a;
                a = swap;
            }

            while (!(b.Terms.Length == 0 || b.Terms[0].CoEfficient == 0))
            {
                IComplexPolynomial temp = a;
                a = b;
                b = ComplexPolynomial.ModMod(temp, b, modulus);
            }

            if (a.Degree == 0)
            {
                return(ComplexPolynomial.One);
            }
            else
            {
                return(a);
            }
        }
        public static IComplexPolynomial GCDMod(IComplexPolynomial left, IComplexPolynomial right, Complex polynomialBase)
        {
            IComplexPolynomial a = left.Clone();
            IComplexPolynomial b = right.Clone();


            Swap(ref a, ref b);

            while (a.Degree != b.Degree)
            {
                IComplexPolynomial smallerA = ComplexPolynomial.ReduceDegree(a, polynomialBase);
                a = smallerA;

                Swap(ref a, ref b);
            }

            while (a.Degree != 1)
            {
                IComplexPolynomial smallerA = ComplexPolynomial.ReduceDegree(a, polynomialBase);
                IComplexPolynomial smallerB = ComplexPolynomial.ReduceDegree(b, polynomialBase);

                a = smallerA;
                b = smallerB;

                Swap(ref a, ref b);
            }

            while (a.Degree >= 1)
            {
                Swap(ref a, ref b);

                var bSign = b.Terms.Last().CoEfficient.Sign();
                if (bSign < 0)
                {
                    break;
                }

                while (!(b.Terms.Length == 0 || b.Terms[0].CoEfficient == 0 || a.CompareTo(b) < 0))
                {
                    var aSign = a.Terms.Last().CoEfficient.Sign();
                    bSign = b.Terms.Last().CoEfficient.Sign();

                    if (aSign < 0 || bSign < 0)
                    {
                        break;
                    }

                    a = ComplexPolynomial.Subtract(a, b);
                }
            }

            if (a.Degree == 0)
            {
                return(ComplexPolynomial.One);
            }
            else
            {
                return(a);
            }
        }
        public static IComplexPolynomial Add(IComplexPolynomial left, IComplexPolynomial right)
        {
            if (left == null)
            {
                throw new ArgumentNullException(nameof(left));
            }
            if (right == null)
            {
                throw new ArgumentNullException(nameof(right));
            }

            Complex[] terms = new Complex[Math.Max(left.Degree, right.Degree) + 1];
            for (int i = 0; i < terms.Length; i++)
            {
                Complex l   = left[i];
                Complex r   = right[i];
                Complex ttl = (l + r);

                terms[i] = ttl;
            }

            IComplexPolynomial result = new ComplexPolynomial(ComplexTerm.GetTerms(terms.ToArray()));

            return(result);
        }
        /*
         * public static bool IsIrreducibleOverField(IPoly f, Complex m, Complex p)
         * {
         * IPoly splittingField = new ComplexPoly(
         *  new PolyTerm[] {
         *      new PolyTerm(  1, (int)Complex.Abs(p)),
         *      new PolyTerm( -1, 1)
         *  });
         *
         * IPoly reducedField = ComplexPoly.ModMod(splittingField, f, p);
         *
         * if (!EisensteinsIrreducibilityCriterion(reducedField, p))
         * {
         * return false;
         * }
         *
         * Complex fieldValue = reducedField.Evaluate(m);
         *
         * IPoly gcd = ComplexPoly.GCDMod(f, reducedField, m);
         * return (gcd.CompareTo(ComplexPoly.One) == 0);
         * }
         *
         * public static bool IsIrreducibleOverP(IPoly poly, Complex p)
         * {
         * List<Complex> coefficients = poly.Terms.Select(t => t.CoEfficient).ToList();
         *
         * Complex leadingCoefficient = coefficients.Last();
         * Complex constantCoefficient = coefficients.First();
         *
         * coefficients.Remove(leadingCoefficient);
         * coefficients.Remove(constantCoefficient);
         *
         * Complex leadingRemainder = -1;
         * Complex.DivRem(leadingCoefficient, p, out leadingRemainder);
         *
         * Complex constantRemainder = -1;
         * Complex.DivRem(constantCoefficient, p.Square(), out constantRemainder);
         *
         * bool result = (leadingRemainder != 0); // p does not divide leading coefficient
         *
         * result &= (constantRemainder != 0);    // p^2 does not divide constant coefficient
         *
         * coefficients.Add(p);
         * result &= (Maths.GCD(coefficients) == 1);
         *
         * return result;
         * }
         */

        #endregion

        public static void Swap(ref IComplexPolynomial a, ref IComplexPolynomial b)
        {
            if (b.CompareTo(a) > 0)
            {
                IComplexPolynomial swap = b;
                b = a;
                a = swap;
            }
        }
        public static IComplexPolynomial MakeMonic(IComplexPolynomial polynomial, Complex polynomialBase)
        {
            int deg = polynomial.Degree;
            IComplexPolynomial result = new ComplexPolynomial(polynomial.Terms.ToArray());

            if (Complex.Abs(result.Terms[deg].CoEfficient) > 1)
            {
                Complex toAdd = (result.Terms[deg].CoEfficient - 1) * polynomialBase;
                result.Terms[deg].CoEfficient      = 1;
                result.Terms[deg - 1].CoEfficient += toAdd;
            }
            return(result);
        }
        public static IComplexPolynomial MultiplyMod(IComplexPolynomial poly, Complex multiplier, Complex mod)
        {
            IComplexPolynomial result = poly.Clone();

            foreach (IComplexTerm term in result.Terms)
            {
                Complex newCoefficient = term.CoEfficient;
                if (newCoefficient != 0)
                {
                    newCoefficient   = (newCoefficient * multiplier);
                    term.CoEfficient = (newCoefficient.Mod(mod));
                }
            }

            return(result);
        }
        public void TestDerivative()
        {
            string expected = "576*X + 36";

            IComplexPolynomial first  = ComplexPolynomial.Parse("288*X^2 + 36*X - 2");
            IComplexPolynomial result = ComplexPolynomial.GetDerivativePolynomial(first);
            string             actual = result.ToString();

            TestContext.WriteLine("Test Derivative:");
            TestContext.WriteLine($"f' where f(x) = ({first})");
            TestContext.WriteLine("");
            TestContext.WriteLine($"Expected: {expected}");
            TestContext.WriteLine($"Actual   = {actual}");

            Assert.AreEqual(expected, actual, $"Test Derivative");
        }
        public void TestAddition()
        {
            string expected = "24*X - 1";

            IComplexPolynomial first  = ComplexPolynomial.Parse("12*X + 2");
            IComplexPolynomial second = ComplexPolynomial.Parse("12*X - 3");

            IComplexPolynomial result = ComplexPolynomial.Add(first, second);
            string             actual = result.ToString();

            TestContext.WriteLine("Test Addition:");
            TestContext.WriteLine($"({first}) + ({second})");
            TestContext.WriteLine($"Expected: {expected}");
            TestContext.WriteLine($"Actual:    {actual}");

            Assert.AreEqual(expected, actual, $"Test Addition");
        }
        public void TestSquare()
        {
            string expected = "144*X^2 + 24*X + 1";

            IComplexPolynomial first = ComplexPolynomial.Parse("12*X + 1");

            IComplexPolynomial result = ComplexPolynomial.Square(first);
            string             actual = result.ToString();

            TestContext.WriteLine("Test Square:");
            TestContext.WriteLine($"({first})^2");
            TestContext.WriteLine("");
            TestContext.WriteLine($"Expected: {expected}");
            TestContext.WriteLine($"Actual   = {actual}");

            Assert.AreEqual(expected, actual, $"Test Square");
        }
        public static IComplexPolynomial Modulus(IComplexPolynomial poly, Complex mod)
        {
            IComplexPolynomial  clone = poly.Clone();
            List <IComplexTerm> terms = new List <IComplexTerm>();

            foreach (IComplexTerm term in clone.Terms)
            {
                Complex remainder = Complex.Divide(term.CoEfficient, mod);

                terms.Add(new ComplexTerm(remainder, term.Exponent));
            }

            // Recalculate the degree
            IComplexTerm[]     termArray = terms.SkipWhile(t => t.CoEfficient.Sign() == 0).ToArray();
            IComplexPolynomial result    = new ComplexPolynomial(termArray);

            return(result);
        }
        public static IComplexPolynomial Sum(IEnumerable <IComplexPolynomial> polys)
        {
            IComplexPolynomial result = null;

            foreach (IComplexPolynomial p in polys)
            {
                if (result == null)
                {
                    result = p;
                }
                else
                {
                    result = ComplexPolynomial.Add(result, p);
                }
            }

            return(result);
        }
        public void TestDivide()
        {
            string expected = "24*X - 1";

            IComplexPolynomial first  = ComplexPolynomial.Parse("288*X^2 + 36*X - 2");
            IComplexPolynomial second = ComplexPolynomial.Parse("12*X + 2");

            IComplexPolynomial result = ComplexPolynomial.Divide(first, second);
            string             actual = result.ToString();

            TestContext.WriteLine("Test Divide:");
            TestContext.WriteLine($"({first}) / ({second})");
            TestContext.WriteLine("");
            TestContext.WriteLine($"Expected: {expected}");
            TestContext.WriteLine($"Actual   = {actual}");

            Assert.AreEqual(expected, actual, $"Test Divide");
        }
        public static IComplexPolynomial ReduceDegree(IComplexPolynomial polynomial, Complex polynomialBase)
        {
            List <Complex> coefficients       = polynomial.Terms.Select(t => t.CoEfficient).ToList();
            Complex        leadingCoefficient = coefficients.Last();

            coefficients.Remove(leadingCoefficient);

            Complex toAdd = (leadingCoefficient * polynomialBase);

            leadingCoefficient = coefficients.Last();

            Complex newLeadingCoefficient = leadingCoefficient + toAdd;

            coefficients.Remove(leadingCoefficient);
            coefficients.Add(newLeadingCoefficient);

            return(new ComplexPolynomial(ComplexTerm.GetTerms(coefficients.ToArray())));
        }
        public void TestMultiply()
        {
            string expected = "144*X^2 - 12*X - 6";

            IComplexPolynomial first  = ComplexPolynomial.Parse("12*X + 2");
            IComplexPolynomial second = ComplexPolynomial.Parse("12*X - 3");

            IComplexPolynomial result = ComplexPolynomial.Multiply(first, second);
            string             actual = result.ToString();

            TestContext.WriteLine("Test Multiply:");
            TestContext.WriteLine($"({first}) * ({second})");
            TestContext.WriteLine("");
            TestContext.WriteLine($"Expected: {expected}");
            TestContext.WriteLine($"Actual   = {actual}");


            Assert.AreEqual(expected, actual, $"Test Multiply");
        }
        public void TestSubtraction()
        {
            string expected = "7*X^2 + X";

            IComplexPolynomial first  = ComplexPolynomial.Parse("7*X^2 + 3*X - 2");
            IComplexPolynomial second = ComplexPolynomial.Parse("2*X - 2");

            IComplexPolynomial result = ComplexPolynomial.Subtract(first, second);
            string             actual = result.ToString();

            TestContext.WriteLine("Test Subtraction:");
            TestContext.WriteLine($"({first}) - ({second})");
            TestContext.WriteLine("");
            TestContext.WriteLine($"Expected: {expected}");
            TestContext.WriteLine($"Actual   = {actual}");


            Assert.AreEqual(expected, actual, $"Test Subtraction");
        }
        public static IComplexPolynomial Mod(IComplexPolynomial poly, IComplexPolynomial mod)
        {
            int sortOrder = mod.CompareTo(poly);

            if (sortOrder > 0)
            {
                return(poly.Clone());
            }
            else if (sortOrder == 0)
            {
                return(ComplexPolynomial.Zero);
            }

            IComplexPolynomial remainder = new ComplexPolynomial();

            Divide(poly, mod, out remainder);

            return(remainder);
        }
        public void TestFromRoots()
        {
            Complex oneTwelvth          = new Complex(1d / 12d, 0);
            Complex minusOneTwelvth     = Complex.Negate(oneTwelvth);
            Complex imaginaryOneTwelvth = new Complex(0, 1d / 12d);
            Complex imaginaryTwelve     = new Complex(0, 12);

            IComplexPolynomial poly3 = ComplexPolynomial.FromRoots(oneTwelvth, imaginaryOneTwelvth, 12);

            string expected = "X^3 + (-12.08333 - 0.08333𝐢)*X^2 + (1 + 1.00694444444444𝐢)*X + (0 - 0.08333𝐢)";
            string actual   = poly3.ToString();

            TestContext.WriteLine($"Expecting: {expected}");
            TestContext.WriteLine($"Actual:    {actual}");

            TestContext.WriteLine(actual);

            Assert.AreEqual(expected, actual);
        }
        public static IComplexPolynomial GetDerivativePolynomial(IComplexPolynomial poly)
        {
            int d = 0;
            List <IComplexTerm> terms = new List <IComplexTerm>();

            foreach (IComplexTerm term in poly.Terms)
            {
                d = term.Exponent - 1;
                if (d < 0)
                {
                    continue;
                }
                terms.Add(new ComplexTerm(term.CoEfficient * term.Exponent, d));
            }

            IComplexPolynomial result = new ComplexPolynomial(terms.ToArray());

            return(result);
        }
        public int CompareTo(IComplexPolynomial other)
        {
            if (other == null)
            {
                throw new ArgumentException();
            }

            if (other.Degree != this.Degree)
            {
                if (other.Degree > this.Degree)
                {
                    return(-1);
                }
                else
                {
                    return(1);
                }
            }
            else
            {
                int counter = this.Degree;

                while (counter >= 0)
                {
                    Complex thisCoefficient  = this[counter];
                    Complex otherCoefficient = other[counter];

                    if (Complex.Abs(thisCoefficient) < Complex.Abs(otherCoefficient))
                    {
                        return(-1);
                    }
                    else if (Complex.Abs(thisCoefficient) > Complex.Abs(otherCoefficient))
                    {
                        return(1);
                    }

                    counter--;
                }

                return(0);
            }
        }
        public static IComplexPolynomial DivideMod(IComplexPolynomial left, IComplexPolynomial right, Complex mod, out IComplexPolynomial remainder)
        {
            if (left == null)
            {
                throw new ArgumentNullException(nameof(left));
            }
            if (right == null)
            {
                throw new ArgumentNullException(nameof(right));
            }
            if (right.Degree > left.Degree || right.CompareTo(left) == 1)
            {
                remainder = ComplexPolynomial.Zero; return(left);
            }

            int     rightDegree       = right.Degree;
            int     quotientDegree    = (left.Degree - rightDegree) + 1;
            Complex leadingCoefficent = right[rightDegree].Clone().Mod(mod);

            IComplexPolynomial rem      = left.Clone();
            IComplexPolynomial quotient = ComplexPolynomial.Zero;

            // The leading coefficient is the only number we ever divide by
            // (so if right is monic, polynomial division does not involve division at all!)
            for (int i = quotientDegree - 1; i >= 0; i--)
            {
                quotient[i]          = Complex.Divide(rem[rightDegree + i], leadingCoefficent).Mod(mod);
                rem[rightDegree + i] = Complex.Zero;

                for (int j = rightDegree + i - 1; j >= i; j--)
                {
                    rem[j] = Complex.Subtract(rem[j], Complex.Multiply(quotient[i], right[j - i]).Mod(mod)).Mod(mod);
                }
            }

            // Remove zeros
            rem.RemoveZeros();
            quotient.RemoveZeros();

            remainder = rem;
            return(quotient);
        }
        public void TestGCD()
        {
            string polyString1 = "X^2 + 7*X + 6";
            string polyString2 = "X^2 - 5*X - 6";
            string expected    = "X + 1";

            IComplexPolynomial first  = ComplexPolynomial.Parse(polyString1);
            IComplexPolynomial second = ComplexPolynomial.Parse(polyString2);

            IComplexPolynomial result = ComplexPolynomial.GCD(first, second);
            string             actual = result.ToString();

            TestContext.WriteLine("Test GCD:");
            TestContext.WriteLine($"GCD({first}, {second})");
            TestContext.WriteLine("");
            TestContext.WriteLine($"Expected: {expected}");
            TestContext.WriteLine($"Actual   = {actual}");

            Assert.AreEqual(expected, actual, $"Test GCD");
        }
        public static IComplexPolynomial PowMod(IComplexPolynomial poly, Complex exp, Complex mod)
        {
            IComplexPolynomial result = poly.Clone();

            foreach (IComplexTerm term in result.Terms)
            {
                Complex newCoefficient = term.CoEfficient;
                if (newCoefficient != 0)
                {
                    newCoefficient = Complex.Pow(newCoefficient, exp).Mod(mod);
                    if (newCoefficient.Sign() == -1)
                    {
                        throw new Exception("Complex.ModPow returned negative number");
                    }
                    term.CoEfficient = newCoefficient;
                }
            }

            return(result);
        }
        public static IComplexPolynomial ExtendedGCD(IComplexPolynomial left, IComplexPolynomial right, Complex mod)
        {
            IComplexPolynomial rem = ComplexPolynomial.Two;
            IComplexPolynomial a   = left.Clone();
            IComplexPolynomial b   = right.Clone();
            IComplexPolynomial c   = ComplexPolynomial.Zero;


            while (c.CompareTo(ComplexPolynomial.Zero) != 0 && rem.CompareTo(ComplexPolynomial.Zero) != 0 && rem.CompareTo(ComplexPolynomial.One) != 0)
            {
                c = ComplexPolynomial.Divide(a, b, out rem);

                a = b;
                b = rem;
            }

            if (rem.CompareTo(ComplexPolynomial.Zero) != 0 || rem.CompareTo(ComplexPolynomial.One) != 0)
            {
                return(ComplexPolynomial.One);
            }

            return(rem);
        }
        /*
         * public static IPoly ExponentiateMod(IPoly startPoly, Complex s2, IPoly f, Complex p)
         * {
         * IPoly result = ComplexPoly.One;
         * if (s2 == 0) { return result; }
         *
         * IPoly A = startPoly.Clone();
         *
         * byte[] byteArray = s2.ToByteArray();
         * bool[] bitArray = new BitArray(byteArray).Cast<bool>().ToArray();
         *
         * // Remove trailing zeros ?
         * if (bitArray[0] == true)
         * {
         * result = startPoly;
         * }
         *
         * int i = 1;
         * int t = bitArray.Length;
         * while (i < t)
         * {
         * A = ComplexPoly.ModMod(ComplexPoly.Square(A), f, p);
         * if (bitArray[i] == true)
         * {
         *  result = ComplexPoly.ModMod(ComplexPoly.Multiply(A, result), f, p);
         * }
         * i++;
         * }
         *
         * return result;
         * }
         */

        #endregion

        public static IComplexPolynomial ModPow(IComplexPolynomial poly, Complex exponent, IComplexPolynomial modulus)
        {
            //if (exponent.Sign() == -1)
            //{
            //	throw new NotImplementedException("Raising a polynomial to a negative exponent not supported. Build this functionality if it is needed.");
            //}
            if (exponent == Complex.Zero)
            {
                return(ComplexPolynomial.One);
            }
            else if (exponent == Complex.One)
            {
                return(poly.Clone());
            }
            else if (exponent == 2)
            {
                return(ComplexPolynomial.Square(poly));
            }

            IComplexPolynomial total = ComplexPolynomial.Square(poly);

            Complex counter = exponent - 2;

            while (counter != 0)
            {
                total = Multiply(poly, total);

                if (total.CompareTo(modulus) < 0)
                {
                    total = ComplexPolynomial.Mod(total, modulus);
                }

                counter -= 1;
            }

            return(total);
        }
        public static IComplexPolynomial Multiply(IComplexPolynomial left, IComplexPolynomial right)
        {
            if (left == null)
            {
                throw new ArgumentNullException(nameof(left));
            }
            if (right == null)
            {
                throw new ArgumentNullException(nameof(right));
            }

            Complex[] terms = new Complex[left.Degree + right.Degree + 1];

            for (int i = 0; i <= left.Degree; i++)
            {
                for (int j = 0; j <= right.Degree; j++)
                {
                    terms[(i + j)] += Complex.Multiply(left[i], right[j]);
                }
            }

            IComplexTerm[] newTerms = ComplexTerm.GetTerms(terms);
            return(new ComplexPolynomial(newTerms));
        }
        public static string FormatString(IComplexPolynomial polynomial)
        {
            List <string> stringTerms = new List <string>();
            int           degree      = polynomial.Terms.Length;

            while (--degree >= 0)
            {
                string       termString = "";
                IComplexTerm term       = polynomial.Terms[degree];

                if (term.CoEfficient == 0)
                {
                    if (term.Exponent == 0)
                    {
                        if (stringTerms.Count == 0)
                        {
                            stringTerms.Add("0");
                        }
                    }
                    continue;
                }
                else
                {
                    termString = $"{term.CoEfficient.FormatString()}";
                }

                switch (term.Exponent)
                {
                case 0:
                    stringTerms.Add($"{term.CoEfficient.FormatString()}");
                    break;

                case 1:
                    if (term.CoEfficient == 1)
                    {
                        stringTerms.Add("X");
                    }
                    else if (term.CoEfficient == -1)
                    {
                        stringTerms.Add("-X");
                    }
                    else
                    {
                        stringTerms.Add($"{term.CoEfficient.FormatString()}*X");
                    }
                    break;

                default:
                    if (term.CoEfficient == 1)
                    {
                        stringTerms.Add($"X^{term.Exponent}");
                    }
                    else if (term.CoEfficient == -1)
                    {
                        stringTerms.Add($"-X^{term.Exponent}");
                    }
                    else
                    {
                        stringTerms.Add($"{term.CoEfficient.FormatString()}*X^{term.Exponent}");
                    }
                    break;
                }
            }
            return(string.Join(" + ", stringTerms).Replace(" + -", " - "));
        }