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(" + -", " - ")); }