/** Constructor. */ @SuppressWarnings("unchecked") public SquarefreeFieldCharP(RingFactory<C> fac) { super(GCDFactory.<C>getProxy(fac)); if (!fac.isField()) { // throw new IllegalArgumentException("fac must be a field"); logger.warn("fac should be a field: " + fac.toScript()); } if (fac.characteristic().signum() == 0) { throw new IllegalArgumentException("characterisic(fac) must be non-zero"); } coFac = fac; Object oFac = coFac; if (oFac instanceof AlgebraicNumberRing) { aCoFac = (AlgebraicNumberRing<C>) oFac; // <C> is not correct // rengine = (SquarefreeAbstract) SquarefreeFactory.getImplementation(aCoFac.ring); qCoFac = null; } else { aCoFac = null; if (oFac instanceof QuotientRing) { qCoFac = (QuotientRing<C>) oFac; // <C> is not correct // rengine = (SquarefreeAbstract) SquarefreeFactory.getImplementation(qCoFac.ring); } else { qCoFac = null; // rengine = null; //(SquarefreeAbstract) SquarefreeFactory.getImplementation(oFac); } } }
/** Test matrix conversions. */ public void testMatrixConversion() { RingFactory<BigRational> z = new BigRational(0); JLAdapterFactory<BigRational> fac = new JLAdapterFactory<BigRational>(z); JLAdapter<BigRational>[][] vec1 = fac.getArray(ll, ll); // System.out.println("vec1 =" + matrixToString(vec1)); RingElem<BigRational>[][] v1 = JLAdapterUtil.<BigRational>fromJLAdapter(vec1); // System.out.println("v1 =" + matrixToString(v1)); JLAdapter<BigRational>[][] vec2 = JLAdapterUtil.<BigRational>toJLAdapterRE(v1); // System.out.println("vec2 =" + matrixToString(vec2)); assertMatrixEquals(vec1, vec2); BigRational[][] v2 = new BigRational[ll][]; for (int i = 0; i < v2.length; i++) { v2[i] = new BigRational[ll]; for (int j = 0; j < v2.length; j++) { v2[i][j] = z.random(kl); } } // System.out.println("v2 =" + matrixToString(v2)); JLAdapter<BigRational>[][] vec3 = JLAdapterUtil.<BigRational>toJLAdapter(v2); // System.out.println("vec1 =" + matrixToString(vec3)); RingElem<BigRational>[][] v3 = JLAdapterUtil.<BigRational>fromJLAdapter(vec3); // System.out.println("v3 =" + matrixToString(v3)); // v3[0][0] = v3[1][1]; assertMatrixEquals(v2, v3); }
/** * Invariant interval for algebraic number magnitude. * * @param iv root isolating interval for f, with f(left) * f(right) < 0. * @param f univariate polynomial, non-zero. * @param g univariate polynomial, gcd(f,g) == 1. * @param eps length limit for interval length. * @return v with v a new interval contained in iv such that |g(a) - g(b)| < eps for a, b in v * in iv. */ public Interval<C> invariantMagnitudeInterval( Interval<C> iv, GenPolynomial<C> f, GenPolynomial<C> g, C eps) { Interval<C> v = iv; if (g == null || g.isZERO()) { return v; } if (g.isConstant()) { return v; } if (f == null || f.isZERO() || f.isConstant()) { // ? return v; } GenPolynomial<C> gp = PolyUtil.<C>baseDeriviative(g); // System.out.println("g = " + g); // System.out.println("gp = " + gp); C B = magnitudeBound(iv, gp); // System.out.println("B = " + B); RingFactory<C> cfac = f.ring.coFac; C two = cfac.fromInteger(2); while (B.multiply(v.length()).compareTo(eps) >= 0) { C c = v.left.sum(v.right); c = c.divide(two); Interval<C> im = new Interval<C>(c, v.right); if (signChange(im, f)) { v = im; } else { v = new Interval<C>(v.left, c); } // System.out.println("v = " + v.toDecimal()); } return v; }
/** * Get the String representation as RingFactory. * * @see java.lang.Object#toString() */ @Override public String toString() { if (nCopies != 0) { String cf = ring.toString(); if (cf.matches("[0-9].*")) { cf = ring.getClass().getSimpleName(); } return "ProductRing[ " + cf + "^" + nCopies + " ]"; } else { StringBuffer sb = new StringBuffer("ProductRing[ "); int i = 0; for (RingFactory<C> f : ringList) { if (i != 0) { sb.append(", "); } String cf = f.toString(); if (cf.matches("[0-9].*")) { cf = f.getClass().getSimpleName(); } sb.append(cf); i++; } sb.append(" ]"); return sb.toString(); } }
/** * Product random. * * @param n such that 0 ≤ v ≤ (2<sup>n</sup>-1). * @param q density of nozero entries. * @param rnd is a source for random bits. * @return a random product element v. */ public Product<C> random(int n, float q, Random rnd) { SortedMap<Integer, C> elem = new TreeMap<Integer, C>(); float d; if (nCopies != 0) { for (int i = 0; i < nCopies; i++) { d = rnd.nextFloat(); if (d < q) { C r = ring.random(n, rnd); if (!r.isZERO()) { elem.put(i, r); } } } } else { int i = 0; for (RingFactory<C> f : ringList) { d = rnd.nextFloat(); if (d < q) { C r = f.random(n, rnd); if (!r.isZERO()) { elem.put(i, r); } } i++; } } return new Product<C>(this, elem); }
/** * Comparison with any other object. * * @see java.lang.Object#equals(java.lang.Object) */ @Override @SuppressWarnings("unchecked") public boolean equals(Object b) { if (!(b instanceof ProductRing)) { return false; } ProductRing<C> a = null; try { a = (ProductRing<C>) b; } catch (ClassCastException e) { } if (a == null) { return false; } if (nCopies != 0) { if (nCopies != a.nCopies || !ring.equals(a.ring)) { return false; } } else { if (ringList.size() != a.ringList.size()) { return false; } int i = 0; for (RingFactory<C> f : ringList) { if (!f.equals(a.ringList.get(i))) { return false; } i++; } } return true; }
/** * Real root bound. With f(M) * f(-M) != 0. * * @param f univariate polynomial. * @return M such that -M < root(f) < M. */ public C realRootBound(GenPolynomial<C> f) { if (f == null) { return null; } RingFactory<C> cfac = f.ring.coFac; C M = cfac.getONE(); if (f.isZERO() || f.isConstant()) { return M; } C a = f.leadingBaseCoefficient().abs(); for (C c : f.getMap().values()) { C d = c.abs().divide(a); if (M.compareTo(d) < 0) { M = d; } } // works also without this case, only for optimization // to use rational number interval end points // can fail if real root is in interval [r,r+1] // for too low precision or too big r, since r is approximation if ((Object) M instanceof RealAlgebraicNumber) { RealAlgebraicNumber Mr = (RealAlgebraicNumber) M; BigRational r = Mr.magnitude(); M = cfac.fromInteger(r.numerator()).divide(cfac.fromInteger(r.denominator())); } M = M.sum(f.ring.coFac.getONE()); // System.out.println("M = " + M); return M; }
/** * Parse interval for a real root from String. * * @param s String, syntax: [left, right] or [mid]. * @return Interval from s. */ public static <C extends RingElem<C> & Rational> Interval<C> parseInterval( RingFactory<C> fac, String s) { int r = s.length(); int el = s.indexOf("["); if (el >= 0) { int ri = s.indexOf("]"); if (ri > 0) { r = ri; } } else { el = -1; } // System.out.println("s = " + s); String iv = s.substring(el + 1, r).trim(); // System.out.println("iv = " + iv); int k = iv.indexOf(","); if (k < 0) { k = s.indexOf(" "); } if (k < 0) { C mid = fac.parse(iv); return new Interval<C>(mid); } // System.out.println("k = " + k + ", len = " + iv.length()); String ls = iv.substring(0, k).trim(); String rs = iv.substring(k + 1, iv.length()).trim(); // System.out.println("ls = " + ls + ", rs = " + rs); C left = fac.parse(ls); C right = fac.parse(rs); if (debug) { logger.debug("Interval: left = " + left + ", right = " + right); } return new Interval<C>(left, right); }
/** Test vector conversions. */ public void testVectorConversion() { RingFactory<BigRational> z = new BigRational(0); JLAdapterFactory<BigRational> fac = new JLAdapterFactory<BigRational>(z); JLAdapter<BigRational>[] vec1 = fac.getArray(ll); // System.out.println("vec1 =" + Arrays.toString(vec1)); RingElem<BigRational>[] v1 = JLAdapterUtil.<BigRational>fromJLAdapter(vec1); // System.out.println("v1 =" + Arrays.toString(v1)); JLAdapter<BigRational>[] vec2 = JLAdapterUtil.<BigRational>toJLAdapterRE(v1); // System.out.println("vec2 =" + Arrays.toString(vec2)); assertTrue("v1[] == v2[] ", Arrays.equals(vec1, vec2)); BigRational[] v2 = new BigRational[ll]; for (int i = 0; i < v2.length; i++) { v2[i] = z.random(kl); } // System.out.println("v2 =" + Arrays.toString(v2)); JLAdapter<BigRational>[] vec3 = JLAdapterUtil.<BigRational>toJLAdapter(v2); // System.out.println("vec3 =" + Arrays.toString(vec3)); RingElem<BigRational>[] v3 = JLAdapterUtil.<BigRational>fromJLAdapter(vec3); // System.out.println("v3 =" + Arrays.toString(v3)); assertTrue("v2[] == v3[] ", Arrays.equals(v2, v3)); }
/** * Refine interval. * * @param iv root isolating interval with f(left) * f(right) < 0. * @param f univariate polynomial, non-zero. * @param eps requested interval length. * @return a new interval v such that |v| < eps. */ public Interval<C> refineInterval(Interval<C> iv, GenPolynomial<C> f, C eps) { if (f == null || f.isZERO() || f.isConstant() || eps == null) { return iv; } if (iv.length().compareTo(eps) < 0) { return iv; } RingFactory<C> cfac = f.ring.coFac; C two = cfac.fromInteger(2); Interval<C> v = iv; while (v.length().compareTo(eps) >= 0) { C c = v.left.sum(v.right); c = c.divide(two); // System.out.println("c = " + c); // c = RootUtil.<C>bisectionPoint(v,f); if (PolyUtil.<C>evaluateMain(cfac, f, c).isZERO()) { v = new Interval<C>(c, c); break; } Interval<C> iv1 = new Interval<C>(v.left, c); if (signChange(iv1, f)) { v = iv1; } else { v = new Interval<C>(c, v.right); } } return v; }
/** * Bi-section point. * * @param iv interval with f(left) * f(right) != 0. * @param f univariate polynomial, non-zero. * @return a point c in the interval iv such that f(c) != 0. */ public C bisectionPoint(Interval<C> iv, GenPolynomial<C> f) { if (f == null) { return null; } RingFactory<C> cfac = f.ring.coFac; C two = cfac.fromInteger(2); C c = iv.left.sum(iv.right); c = c.divide(two); if (f.isZERO() || f.isConstant()) { return c; } C m = PolyUtil.<C>evaluateMain(cfac, f, c); while (m.isZERO()) { C d = iv.left.sum(c); d = d.divide(two); if (d.equals(c)) { d = iv.right.sum(c); d = d.divide(two); if (d.equals(c)) { throw new RuntimeException("should not happen " + iv); } } c = d; m = PolyUtil.<C>evaluateMain(cfac, f, c); // System.out.println("c = " + c); } // System.out.println("c = " + c); return c; }
/** * Coefficient squarefree factorization. * * @param coeff coefficient. * @return [p_1 -> e_1, ..., p_k -> e_k] with P = prod_{i=1,...,k} p_i^{e_i} and p_i * squarefree. */ @Override public SortedMap<C, Long> squarefreeFactors(C coeff) { if (coeff == null) { return null; } SortedMap<C, Long> factors = new TreeMap<C, Long>(); RingFactory<C> cfac = (RingFactory<C>) coeff.factory(); if (aCoFac != null) { AlgebraicNumber<C> an = (AlgebraicNumber<C>) (Object) coeff; if (cfac.isFinite()) { SquarefreeFiniteFieldCharP<C> reng = (SquarefreeFiniteFieldCharP) SquarefreeFactory.getImplementation(cfac); SortedMap<C, Long> rfactors = reng.rootCharacteristic(coeff); // ?? logger.info("rfactors,finite = " + rfactors); factors.putAll(rfactors); // return factors; } else { SquarefreeInfiniteAlgebraicFieldCharP<C> reng = (SquarefreeInfiniteAlgebraicFieldCharP) SquarefreeFactory.getImplementation(cfac); SortedMap<AlgebraicNumber<C>, Long> rfactors = reng.squarefreeFactors(an); logger.info("rfactors,infinite,algeb = " + rfactors); for (Map.Entry<AlgebraicNumber<C>, Long> me : rfactors.entrySet()) { AlgebraicNumber<C> c = me.getKey(); if (!c.isONE()) { C cr = (C) (Object) c; Long rk = me.getValue(); // rfactors.get(c); factors.put(cr, rk); } } } } else if (qCoFac != null) { Quotient<C> q = (Quotient<C>) (Object) coeff; SquarefreeInfiniteFieldCharP<C> reng = (SquarefreeInfiniteFieldCharP) SquarefreeFactory.getImplementation(cfac); SortedMap<Quotient<C>, Long> rfactors = reng.squarefreeFactors(q); logger.info("rfactors,infinite = " + rfactors); for (Map.Entry<Quotient<C>, Long> me : rfactors.entrySet()) { Quotient<C> c = me.getKey(); if (!c.isONE()) { C cr = (C) (Object) c; Long rk = me.getValue(); // rfactors.get(c); factors.put(cr, rk); } } } else if (cfac.isFinite()) { SquarefreeFiniteFieldCharP<C> reng = (SquarefreeFiniteFieldCharP) SquarefreeFactory.getImplementation(cfac); SortedMap<C, Long> rfactors = reng.rootCharacteristic(coeff); // ?? logger.info("rfactors,finite = " + rfactors); factors.putAll(rfactors); // return factors; } else { logger.warn("case " + cfac + " not implemented"); } return factors; }
/** * Real algebraic number magnitude. * * @param iv root isolating interval for f, with f(left) * f(right) < 0, with iv such that * |g(a) - g(b)| < eps for a, b in iv. * @param f univariate polynomial, non-zero. * @param g univariate polynomial, gcd(f,g) == 1. * @param eps length limit for interval length. * @return g(iv) . */ public C realIntervalMagnitude(Interval<C> iv, GenPolynomial<C> f, GenPolynomial<C> g, C eps) { if (g.isZERO() || g.isConstant()) { return g.leadingBaseCoefficient(); } RingFactory<C> cfac = g.ring.coFac; C c = iv.left.sum(iv.right); c = c.divide(cfac.fromInteger(2)); C ev = PolyUtil.<C>evaluateMain(cfac, g, c); // System.out.println("ev = " + ev); return ev; }
/** * Query if this ring is associative. * * @return true if this ring is associative, else false. */ public boolean isAssociative() { if (nCopies != 0) { return ring.isAssociative(); } else { for (RingFactory<C> f : ringList) { if (!f.isAssociative()) { return false; } } return true; } }
/** * Hash code for this product ring. * * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int h = 0; if (nCopies != 0) { h = ring.hashCode(); h = 37 * h + nCopies; } else { for (RingFactory<C> f : ringList) { h = 37 * h + f.hashCode(); } } return h; }
/** * Get an atomic element. * * @param i index. * @return e_i as Product. */ public Product<C> getAtomic(int i) { if (i < 0 || i >= length()) { throw new RuntimeException("index out of bounds " + i); } SortedMap<Integer, C> elem = new TreeMap<Integer, C>(); if (nCopies != 0) { elem.put(i, ring.getONE()); } else { RingFactory<C> f = ringList.get(i); elem.put(i, f.getONE()); } return new Product<C>(this, elem, 1); }
/** * Get the one element. * * @return 1 as Product. */ public Product<C> getONE() { SortedMap<Integer, C> elem = new TreeMap<Integer, C>(); if (nCopies != 0) { for (int i = 0; i < nCopies; i++) { elem.put(i, ring.getONE()); } } else { int i = 0; for (RingFactory<C> f : ringList) { elem.put(i, f.getONE()); i++; } } return new Product<C>(this, elem, 1); }
/** * Get a Product element from a BigInteger value. * * @param a BigInteger. * @return a Product. */ public Product<C> fromInteger(java.math.BigInteger a) { SortedMap<Integer, C> elem = new TreeMap<Integer, C>(); if (nCopies != 0) { C c = ring.fromInteger(a); for (int i = 0; i < nCopies; i++) { elem.put(i, c); } } else { int i = 0; for (RingFactory<C> f : ringList) { elem.put(i, f.fromInteger(a)); i++; } } return new Product<C>(this, elem); }
/** * Real algebraic number sign. * * @param iv root isolating interval for f, with f(left) * f(right) < 0, with iv such that * g(iv) != 0. * @param f univariate polynomial, non-zero. * @param g univariate polynomial, gcd(f,g) == 1. * @return sign(g(iv)) . */ public int realIntervalSign(Interval<C> iv, GenPolynomial<C> f, GenPolynomial<C> g) { if (g == null || g.isZERO()) { return 0; } if (f == null || f.isZERO() || f.isConstant()) { return g.signum(); } if (g.isConstant()) { return g.signum(); } RingFactory<C> cfac = f.ring.coFac; C c = iv.left.sum(iv.right); c = c.divide(cfac.fromInteger(2)); C ev = PolyUtil.<C>evaluateMain(cfac, g, c); // System.out.println("ev = " + ev); return ev.signum(); }
/** * Contains a ring factory. * * @param rf ring factory. * @return true, if rf is contained in this, else false. */ public boolean containsFactory(RingFactory<C> rf) { if (nCopies != 0) { if (ring.equals(rf)) { return true; } return false; // misleading } else { return ringList.contains(rf); } }
/** * Characteristic of this ring. * * @return minimal characteristic of ring component. */ public java.math.BigInteger characteristic() { if (nCopies != 0) { return ring.characteristic(); } else { java.math.BigInteger c = null; java.math.BigInteger d; for (RingFactory<C> f : ringList) { if (c == null) { c = f.characteristic(); } else { d = f.characteristic(); if (c.compareTo(d) > 0) { // c > d c = d; } } } return c; } }
/** * Add a ring factory. * * @param rf new ring factory. */ public synchronized void addFactory(RingFactory<C> rf) { if (nCopies != 0) { if (ring.equals(rf)) { nCopies++; } throw new RuntimeException("wrong RingFactory: " + rf); } else { ringList.add(rf); } }
/** * Query if this ring is a field. * * @return true or false. */ public boolean isField() { if (nCopies != 0) { if (nCopies == 1) { return ring.isField(); } } else { if (ringList.size() == 1) { return ringList.get(0).isField(); } } return false; }
/** * Magnitude bound. * * @param iv interval. * @param f univariate polynomial. * @return B such that |f(c)| < B for c in iv. */ public C magnitudeBound(Interval<C> iv, GenPolynomial<C> f) { if (f == null) { return null; } if (f.isZERO()) { return f.ring.coFac.getONE(); } if (f.isConstant()) { return f.leadingBaseCoefficient().abs(); } GenPolynomial<C> fa = f.map( new UnaryFunctor<C, C>() { public C eval(C a) { return a.abs(); } }); // System.out.println("fa = " + fa); C M = iv.left.abs(); if (M.compareTo(iv.right.abs()) < 0) { M = iv.right.abs(); } // System.out.println("M = " + M); RingFactory<C> cfac = f.ring.coFac; C B = PolyUtil.<C>evaluateMain(cfac, fa, M); // works also without this case, only for optimization // to use rational number interval end points // can fail if real root is in interval [r,r+1] // for too low precision or too big r, since r is approximation if ((Object) B instanceof RealAlgebraicNumber) { RealAlgebraicNumber Br = (RealAlgebraicNumber) B; BigRational r = Br.magnitude(); B = cfac.fromInteger(r.numerator()).divide(cfac.fromInteger(r.denominator())); } // System.out.println("B = " + B); return B; }
public Odds(RingFactory<C> fac) { this.fac = fac; two = fac.fromInteger(2); // System.out.println("two = " + two); }
/** * 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); }