/**
         * 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));
        }
Beispiel #2
0
 public ModularResultant call()
 {
     return(ModularResultant.CombineRho(modRes1, modRes2));
 }
Beispiel #3
0
        /**
         * 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));
        }
Beispiel #4
0
 public CombineTask(ModularResultant modRes1, ModularResultant modRes2)
 {
     this.modRes1 = modRes1;
     this.modRes2 = modRes2;
 }