/** * 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; }
/** * 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; }
/** * 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; }
/** * 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 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; }
/** * 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; }
/** * 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(); }
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); }