/** * Multiplies the polynomial by another, taking the indices mod N. Does not * change this polynomial but returns the result as a new polynomial.<br> * Both polynomials must have the same number of coefficients. * * @param poly2 the polynomial to multiply by * @return a new polynomial */ public BigIntPolynomial Multiply(BigIntPolynomial poly2) { int N = coeffs.Length; if (poly2.coeffs.Length != N) { throw new InvalidOperationException("MULT: Number of coefficients must be the same"); } BigIntPolynomial c = MultiplyRecursive(poly2); if (c.coeffs.Length > N) { for (int k = N; k < c.coeffs.Length; k++) { c.coeffs[k - N] = c.coeffs[k - N].Add(c.coeffs[k]); } // Shortening the Array BigInteger[] temp = new BigInteger[N]; Array.Copy(c.coeffs, temp, N); c.coeffs = temp; } return(c); }
/** * Generates a random polynomial with <code>numOnes</code> coefficients equal to 1, * <code>numNegOnes</code> coefficients equal to -1, and the rest equal to 0. * * @param N number of coefficients * @param numOnes number of 1's * @param numNegOnes number of -1's * @return a random polynomial. */ static BigIntPolynomial GenerateRandomSmall(int N, int numOnes, int numNegOnes) { List <BigInteger> coeffs = new List <BigInteger>(); for (int i = 0; i < numOnes; i++) { coeffs.Add(BigInteger.ValueOf(1)); } for (int i = 0; i < numNegOnes; i++) { coeffs.Add(BigInteger.ValueOf(-1)); } while (coeffs.Count < N) { coeffs.Add(BigInteger.ValueOf(0)); } Shuffle(coeffs, CryptoServicesRegistrar.GetSecureRandom()); BigIntPolynomial poly = new BigIntPolynomial(N); for (int i = 0; i < coeffs.Count; i++) { poly.coeffs[i] = (BigInteger)coeffs[i]; } return(poly); }
/** * Constructs a <code>IntegerPolynomial</code> from a <code>BigIntPolynomial</code>. The two polynomials are independent of each other. * * @param p the original polynomial */ public IntegerPolynomial(BigIntPolynomial p) { coeffs = new int[p.coeffs.Length]; for (int i = 0; i < p.coeffs.Length; i++) { coeffs[i] = p.coeffs[i].IntValue; } }
public BigIntPolynomial Multiply(BigIntPolynomial b) { BigIntPolynomial c = F1.Multiply(b); c = F2.Multiply(c); c.Add(F3.Multiply(b)); return(c); }
/** * Constructs a <code>BigDecimalPolynomial</code> from a <code>BigIntPolynomial</code>. The two polynomials are independent of each other. * * @param p the original polynomial */ public BigDecimalPolynomial(BigIntPolynomial p) { int N = p.coeffs.Length; coeffs = new decimal[N]; for (int i = 0; i < N; i++) { coeffs[i] = new decimal(p.coeffs[i].IntValue); } }
/** * Rounds all coefficients to the nearest integer. * * @return a new polynomial with <code>BigInteger</code> coefficients */ public BigIntPolynomial round() { int N = coeffs.Length; BigIntPolynomial p = new BigIntPolynomial(N); for (int i = 0; i < N; i++) { p.coeffs[i] = new BigInteger(decimal.Round(coeffs[i], 0, MidpointRounding.AwayFromZero).ToString()); //BigDecimal.ROUND_HALF_EVEN).toBigInteger(); } return(p); }
/** * Subtracts another polynomial which can have a different number of coefficients. * * @param b another polynomial */ public void Sub(BigIntPolynomial b) { if (b.coeffs.Length > coeffs.Length) { int N = coeffs.Length; Array.Copy(coeffs, coeffs, b.coeffs.Length); for (int i = N; i < coeffs.Length; i++) { coeffs[i] = BigInteger.ValueOf(0); } } for (int i = 0; i < b.coeffs.Length; i++) { coeffs[i] = coeffs[i].Subtract(b.coeffs[i]); } }
public BigIntPolynomial Multiply(BigIntPolynomial poly2) { BigInteger[] b = poly2.coeffs; if (b.Length != N) { throw new InvalidOperationException("Number of coefficients must be the same"); } BigInteger[] c = new BigInteger[N]; for (int i = 0; i < N; i++) { c[i] = BigInteger.Zero; } for (int idx = 0; idx != Ones.Length; idx++) { int i = Ones[idx]; int j = N - 1 - i; for (int k = N - 1; k >= 0; k--) { c[k] = c[k].Add(b[j]); j--; if (j < 0) { j = N - 1; } } } for (int idx = 0; idx != NegOnes.Length; idx++) { int i = NegOnes[idx]; int j = N - 1 - i; for (int k = N - 1; k >= 0; k--) { c[k] = c[k].Subtract(b[j]); j--; if (j < 0) { j = N - 1; } } } return(new BigIntPolynomial(c)); }
/** * Adds another polynomial which can have a different number of coefficients. * * @param b another polynomial */ public void Add(BigIntPolynomial b) { if (b.coeffs.Length > coeffs.Length) { int N = coeffs.Length; BigInteger[] temp = new BigInteger[b.coeffs.Length]; Array.Copy(coeffs, temp, coeffs.Length); coeffs = temp; for (int i = N; i < coeffs.Length; i++) { coeffs[i] = BigInteger.ValueOf(0); } } for (int i = 0; i < b.coeffs.Length; i++) { // b.coeffs[i] and coeffs[i] should never be null. If they are, somethings wrong. coeffs[i] = coeffs[i].Add(b.coeffs[i]); } }
/** * Calculates a <code>rho</code> modulo <code>m1*m2</code> from * two resultants whose <code>rho</code>s are modulo <code>m1</code> and <code>m2</code>.<br/> * </code>res</code> is set to <code>null</code>. * * @param modRes1 * @param modRes2 * @return <code>rho</code> modulo <code>modRes1.modulus * modRes2.modulus</code>, and <code>null</code> for </code>res</code>. */ public static ModularResultant CombineRho(ModularResultant modRes1, ModularResultant modRes2) { BigInteger mod1 = modRes1.modulus; BigInteger mod2 = modRes2.modulus; BigInteger prod = mod1.Multiply(mod2); BigIntEuclidean er = BigIntEuclidean.Calculate(mod2, mod1); BigIntPolynomial rho1 = (BigIntPolynomial)modRes1.Rho.Clone(); rho1.Multiply(er.x.Multiply(mod2)); BigIntPolynomial rho2 = (BigIntPolynomial)modRes2.Rho.Clone(); rho2.Multiply(er.y.Multiply(mod1)); rho1.Add(rho2); rho1.Mod(prod); return(new ModularResultant(rho1, null, prod)); }
public override bool Equals(object obj) { if (this == obj) { return(true); } if (obj == null) { return(false); } if (GetType() != obj.GetType()) { return(false); } BigIntPolynomial other = (BigIntPolynomial)obj; if (!Array.Equals(coeffs, other.coeffs)) { return(false); } return(true); }
public Resultant(BigIntPolynomial rho, BigInteger res) { Rho = rho; Res = res; }
/** * Adds another polynomial which can have a different number of coefficients, * and takes the coefficient values mod <code>modulus</code>. * * @param b another polynomial */ void Add(BigIntPolynomial b, BigInteger modulus) { Add(b); Mod(modulus); }
/** * Karazuba multiplication */ private BigIntPolynomial MultiplyRecursive(BigIntPolynomial poly2) { BigInteger[] a = coeffs; BigInteger[] b = poly2.coeffs; int n = poly2.coeffs.Length; if (n <= 1) { BigInteger[] c = new BigInteger[coeffs.Length]; Array.Copy(coeffs, c, coeffs.Length); for (int i = 0; i < coeffs.Length; i++) { c[i] = c[i].Multiply(poly2.coeffs[0]); } return(new BigIntPolynomial(c)); } else { int n1 = n / 2; // TODO: Double Check Conversion (Don't worry too much, it'll explode if wrong)... It Exploded BigInteger[] a1temp = new BigInteger[n1]; BigInteger[] a2temp = new BigInteger[n - n1]; BigInteger[] b1temp = new BigInteger[n1]; BigInteger[] b2temp = new BigInteger[n - n1]; Array.Copy(a, a1temp, n1); Array.Copy(a, n1, a2temp, 0, n - n1); Array.Copy(b, b1temp, n1); Array.Copy(b, n1, b2temp, 0, n - n1); BigIntPolynomial a1 = new BigIntPolynomial(a1temp); BigIntPolynomial a2 = new BigIntPolynomial(a2temp); BigIntPolynomial b1 = new BigIntPolynomial(b1temp); BigIntPolynomial b2 = new BigIntPolynomial(b2temp); BigIntPolynomial A = (BigIntPolynomial)a1.Clone(); A.Add(a2); BigIntPolynomial B = (BigIntPolynomial)b1.Clone(); B.Add(b2); BigIntPolynomial c1 = a1.MultiplyRecursive(b1); BigIntPolynomial c2 = a2.MultiplyRecursive(b2); BigIntPolynomial c3 = A.MultiplyRecursive(B); c3.Sub(c1); c3.Sub(c2); BigIntPolynomial c = new BigIntPolynomial(2 * n - 1); for (int i = 0; i < c1.coeffs.Length; i++) { c.coeffs[i] = c1.coeffs[i]; } for (int i = 0; i < c3.coeffs.Length; i++) { c.coeffs[n1 + i] = c.coeffs[n1 + i].Add(c3.coeffs[i]); } for (int i = 0; i < c2.coeffs.Length; i++) { c.coeffs[2 * n1 + i] = c.coeffs[2 * n1 + i].Add(c2.coeffs[i]); } return(c); } }
public BigIntPolynomial Multiply(BigIntPolynomial poly2) { return(new BigIntPolynomial(this).Multiply(poly2)); }
/** * Multiplies the polynomial by another. Does not change this polynomial * but returns the result as a new polynomial. * * @param poly2 the polynomial to multiply by * @return a new polynomial */ public BigDecimalPolynomial Multiply(BigIntPolynomial poly2) { return(Multiply(new BigDecimalPolynomial(poly2))); }
/** * Resultant of this polynomial with <code>x^n-1</code> using a probabilistic algorithm. * <p> * Unlike EESS, this implementation does not compute all resultants modulo primes * such that their product exceeds the maximum possible resultant, but rather stops * when <code>NUM_EQUAL_RESULTANTS</code> consecutive modular resultants are equal.<br> * This means the return value may be incorrect. Experiments show this happens in * about 1 out of 100 cases when <code>N=439</code> and <code>NUM_EQUAL_RESULTANTS=2</code>, * so the likelyhood of leaving the loop too early is <code>(1/100)^(NUM_EQUAL_RESULTANTS-1)</code>. * <p> * Because of the above, callers must verify the output and try a different polynomial if necessary. * * @return <code>(rho, res)</code> satisfying <code>res = rho*this + t*(x^n-1)</code> for some integer <code>t</code>. */ public Resultant Resultant() { int N = coeffs.Length; // Compute resultants modulo prime numbers. Continue until NUM_EQUAL_RESULTANTS consecutive modular resultants are equal. LinkedList <ModularResultant> modResultants = new LinkedList <ModularResultant>(); BigInteger pProd = Constants.BIGINT_ONE; BigInteger res = Constants.BIGINT_ONE; int numEqual = 1; // number of consecutive modular resultants equal to each other PrimeGenerator primes = new PrimeGenerator(); BigInteger pProd2; BigInteger pProd2n; while (true) { BigInteger prime = primes.nextPrime(); ModularResultant crr = Resultant(prime.IntValue); modResultants.AddLast(crr); //Was just add in Java BigInteger temp = pProd.Multiply(prime); BigIntEuclidean er = BigIntEuclidean.Calculate(prime, pProd); BigInteger resPrev = res; res = res.Multiply(er.x.Multiply(prime)); BigInteger res2 = crr.Res.Multiply(er.y.Multiply(pProd)); res = res.Add(res2).Mod(temp); pProd = temp; pProd2 = pProd.Divide(BigInteger.ValueOf(2)); pProd2n = pProd2.Negate(); if (res.CompareTo(pProd2) > 0) { res = res.Subtract(pProd); } else if (res.CompareTo(pProd2n) < 0) { res = res.Add(pProd); } if (res.Equals(resPrev)) { numEqual++; if (numEqual >= NUM_EQUAL_RESULTANTS) { break; } } else { numEqual = 1; } } // Combine modular rho's to obtain the final rho. // For efficiency, first combine all pairs of small resultants to bigger resultants, // then combine pairs of those, etc. until only one is left. while (modResultants.Count > 1) { ModularResultant modRes1 = modResultants.First.Value; modResultants.RemoveFirst(); ModularResultant modRes2 = modResultants.First.Value; modResultants.RemoveFirst(); ModularResultant modRes3 = ModularResultant.CombineRho(modRes1, modRes2); modResultants.AddLast(modRes3); } BigIntPolynomial rhoP = modResultants.First.Value.Rho; pProd2 = pProd.Divide(BigInteger.ValueOf(2)); pProd2n = pProd2.Negate(); if (res.CompareTo(pProd2) > 0) { res = res.Subtract(pProd); } if (res.CompareTo(pProd2n) < 0) { res = res.Add(pProd); } for (int i = 0; i < N; i++) { BigInteger c = rhoP.coeffs[i]; if (c.CompareTo(pProd2) > 0) { rhoP.coeffs[i] = c.Subtract(pProd); } if (c.CompareTo(pProd2n) < 0) { rhoP.coeffs[i] = c.Add(pProd); } } return(new Resultant(rhoP, res)); }
public ModularResultant(BigIntPolynomial rho, BigInteger res, BigInteger modulus) : base(rho, res) { this.modulus = modulus; }