/** * GenPolynomial absolute factorization of a irreducible polynomial. * * @param P irreducible! GenPolynomial. * @return factors container: [p_1,...,p_k] with P = prod_{i=1, ..., k} p_i in K(alpha)[x] for * suitable alpha and p_i irreducible over L[x], where K \subset K(alpha) \subset L is an * algebraically closed field over K. <b>Note:</b> K(alpha) not yet minimal. */ public Factors<C> factorsAbsoluteIrreducible(GenPolynomial<C> P) { if (P == null) { throw new RuntimeException(this.getClass().getName() + " P == null"); } if (P.isZERO()) { return new Factors<C>(P); } GenPolynomialRing<C> pfac = P.ring; // K[x] if (pfac.nvar <= 1) { return baseFactorsAbsoluteIrreducible(P); } if (!pfac.coFac.isField()) { throw new RuntimeException("only for field coefficients"); } List<GenPolynomial<C>> factors = new ArrayList<GenPolynomial<C>>(); if (P.degree() <= 1) { return new Factors<C>(P); } // find field extension K(alpha) GenPolynomial<C> up = P; RingFactory<C> cf = pfac.coFac; long cr = cf.characteristic().longValue(); // char might be larger if (cr == 0L) { cr = Long.MAX_VALUE; } long rp = 0L; for (int i = 0; i < (pfac.nvar - 1); i++) { rp = 0L; GenPolynomialRing<C> nfac = pfac.contract(1); String[] vn = new String[] {pfac.getVars()[pfac.nvar - 1]}; GenPolynomialRing<GenPolynomial<C>> rfac = new GenPolynomialRing<GenPolynomial<C>>(nfac, 1, pfac.tord, vn); GenPolynomial<GenPolynomial<C>> upr = PolyUtil.<C>recursive(rfac, up); // System.out.println("upr = " + upr); GenPolynomial<C> ep; do { if (rp >= cr) { throw new RuntimeException("elements of prime field exhausted: " + cr); } C r = cf.fromInteger(rp); // cf.random(rp); // System.out.println("r = " + r); ep = PolyUtil.<C>evaluateMain(nfac, upr, r); // System.out.println("ep = " + ep); rp++; } while (!isSquarefree(ep) /*todo: || ep.degree() <= 1*/); // max deg up = ep; pfac = nfac; } up = up.monic(); if (debug) { logger.info("P(" + rp + ") = " + up); // System.out.println("up = " + up); } if (debug && !isSquarefree(up)) { throw new RuntimeException("not irreducible up = " + up); } if (up.degree(0) <= 1) { return new Factors<C>(P); } // find irreducible factor of up List<GenPolynomial<C>> UF = baseFactorsSquarefree(up); // System.out.println("UF = " + UF); FactorsList<C> aUF = baseFactorsAbsoluteSquarefree(up); // System.out.println("aUF = " + aUF); AlgebraicNumberRing<C> arfac = aUF.findExtensionField(); // System.out.println("arfac = " + arfac); long e = up.degree(0); // search factor polynomial with smallest degree for (int i = 0; i < UF.size(); i++) { GenPolynomial<C> upi = UF.get(i); long d = upi.degree(0); if (1 <= d && d <= e) { up = upi; e = up.degree(0); } } if (up.degree(0) <= 1) { return new Factors<C>(P); } if (debug) { logger.info("field extension by " + up); } List<GenPolynomial<AlgebraicNumber<C>>> afactors = new ArrayList<GenPolynomial<AlgebraicNumber<C>>>(); // setup field extension K(alpha) // String[] vars = new String[] { "z_" + Math.abs(up.hashCode() % 1000) }; String[] vars = pfac.newVars("z_"); pfac = pfac.clone(); String[] ovars = pfac.setVars(vars); // side effects! GenPolynomial<C> aup = pfac.copy(up); // hack to exchange the variables // AlgebraicNumberRing<C> afac = new AlgebraicNumberRing<C>(aup,true); // since irreducible AlgebraicNumberRing<C> afac = arfac; int depth = afac.depth(); // System.out.println("afac = " + afac); GenPolynomialRing<AlgebraicNumber<C>> pafac = new GenPolynomialRing<AlgebraicNumber<C>>(afac, P.ring.nvar, P.ring.tord, P.ring.getVars()); // System.out.println("pafac = " + pafac); // convert to K(alpha) GenPolynomial<AlgebraicNumber<C>> Pa = PolyUtil.<C>convertToRecAlgebraicCoefficients(depth, pafac, P); // System.out.println("Pa = " + Pa); // factor over K(alpha) FactorAbstract<AlgebraicNumber<C>> engine = FactorFactory.<C>getImplementation(afac); afactors = engine.factorsSquarefree(Pa); if (debug) { logger.info("K(alpha) factors multi = " + afactors); // System.out.println("K(alpha) factors = " + afactors); } if (afactors.size() <= 1) { return new Factors<C>(P); } // normalize first factor to monic GenPolynomial<AlgebraicNumber<C>> p1 = afactors.get(0); AlgebraicNumber<C> p1c = p1.leadingBaseCoefficient(); if (!p1c.isONE()) { GenPolynomial<AlgebraicNumber<C>> p2 = afactors.get(1); afactors.remove(p1); afactors.remove(p2); p1 = p1.divide(p1c); p2 = p2.multiply(p1c); afactors.add(p1); afactors.add(p2); } // recursion for splitting field // find minimal field extension K(beta) \subset K(alpha) return new Factors<C>(P, afac, Pa, afactors); }
/** * GenPolynomial base absolute factorization of a irreducible polynomial. * * @param P irreducible! univariate GenPolynomial. * @return factors container: [p_1,...,p_k] with P = prod_{i=1, ..., k} p_i in K(alpha)[x] for * suitable alpha and p_i irreducible over L[x], where K \subset K(alpha) \subset L is an * algebraically closed field over K. <b>Note:</b> K(alpha) not yet minimal. */ public Factors<C> baseFactorsAbsoluteIrreducible(GenPolynomial<C> P) { if (P == null) { throw new RuntimeException(this.getClass().getName() + " P == null"); } if (P.isZERO()) { return new Factors<C>(P); } // System.out.println("\nP_base_irred = " + P); GenPolynomialRing<C> pfac = P.ring; // K[x] if (pfac.nvar > 1) { // System.out.println("facs_base_irred: univ"); throw new RuntimeException("only for univariate polynomials"); } if (!pfac.coFac.isField()) { // System.out.println("facs_base_irred: field"); throw new RuntimeException("only for field coefficients"); } if (P.degree(0) <= 1) { return new Factors<C>(P); } // setup field extension K(alpha) where alpha = z_xx // String[] vars = new String[] { "z_" + Math.abs(P.hashCode() % 1000) }; String[] vars = pfac.newVars("z_"); pfac = pfac.clone(); vars = pfac.setVars(vars); GenPolynomial<C> aP = pfac.copy(P); // hack to exchange the variables AlgebraicNumberRing<C> afac = new AlgebraicNumberRing<C>(aP, true); // since irreducible if (logger.isInfoEnabled()) { logger.info("K(alpha) = " + afac); logger.info("K(alpha) = " + afac.toScript()); // System.out.println("K(alpha) = " + afac); } GenPolynomialRing<AlgebraicNumber<C>> pafac = new GenPolynomialRing<AlgebraicNumber<C>>(afac, aP.ring.nvar, aP.ring.tord, /*old*/ vars); // convert to K(alpha) GenPolynomial<AlgebraicNumber<C>> Pa = PolyUtil.<C>convertToAlgebraicCoefficients(pafac, P); if (logger.isInfoEnabled()) { logger.info("P over K(alpha) = " + Pa); // logger.info("P over K(alpha) = " + Pa.toScript()); // System.out.println("P in K(alpha) = " + Pa); } // factor over K(alpha) FactorAbstract<AlgebraicNumber<C>> engine = FactorFactory.<C>getImplementation(afac); // System.out.println("K(alpha) engine = " + engine); List<GenPolynomial<AlgebraicNumber<C>>> factors = engine.baseFactorsSquarefree(Pa); // System.out.println("factors = " + factors); if (logger.isInfoEnabled()) { logger.info("factors over K(alpha) = " + factors); // System.out.println("factors over K(alpha) = " + factors); } List<GenPolynomial<AlgebraicNumber<C>>> faca = new ArrayList<GenPolynomial<AlgebraicNumber<C>>>(factors.size()); ; List<Factors<AlgebraicNumber<C>>> facar = new ArrayList<Factors<AlgebraicNumber<C>>>(); for (GenPolynomial<AlgebraicNumber<C>> fi : factors) { if (fi.degree(0) <= 1) { faca.add(fi); } else { // System.out.println("fi.deg > 1 = " + fi); FactorAbsolute<AlgebraicNumber<C>> aengine = (FactorAbsolute<AlgebraicNumber<C>>) FactorFactory.<C>getImplementation(afac); Factors<AlgebraicNumber<C>> fif = aengine.baseFactorsAbsoluteIrreducible(fi); // System.out.println("fif = " + fif); facar.add(fif); } } if (facar.size() == 0) { facar = null; } // find minimal field extension K(beta) \subset K(alpha) return new Factors<C>(P, afac, Pa, faca, facar); }