/** * 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; }
/** * Real algebraic number sign. * * @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. * @return sign(g(v)), with v a new interval contained in iv such that g(v) != 0. */ public int realSign(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(); } Interval<C> v = invariantSignInterval(iv, f, g); return realIntervalSign(v, f, g); }
/** * Test if x is an approximate real root. * * @param x approximate real root. * @param f univariate polynomial, non-zero. * @param fp univariate polynomial, non-zero, deriviative of f. * @param eps requested interval length. * @return true if x is a decimal approximation of a real v with f(v) = 0 with |d-v| < eps, * else false. */ public boolean isApproximateRoot( BigDecimal x, GenPolynomial<BigDecimal> f, GenPolynomial<BigDecimal> fp, BigDecimal eps) { if (x == null) { throw new IllegalArgumentException("null root not allowed"); } if (f == null || f.isZERO() || f.isConstant() || eps == null) { return true; } BigDecimal dc = BigDecimal.ONE; // only for clarity // f(x) BigDecimal fx = PolyUtil.<BigDecimal>evaluateMain(dc, f, x); // System.out.println("fx = " + fx); if (fx.isZERO()) { return true; } // f'(x) BigDecimal fpx = PolyUtil.<BigDecimal>evaluateMain(dc, fp, x); // f'(d) // System.out.println("fpx = " + fpx); if (fpx.isZERO()) { return false; } BigDecimal d = fx.divide(fpx); if (d.isZERO()) { return true; } if (d.abs().compareTo(eps) <= 0) { return true; } System.out.println("x = " + x); System.out.println("d = " + d); return false; }
/** * Real 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 g(iv) . */ public C realMagnitude(Interval<C> iv, GenPolynomial<C> f, GenPolynomial<C> g, C eps) { if (g.isZERO() || g.isConstant()) { return g.leadingBaseCoefficient(); } Interval<C> v = invariantMagnitudeInterval(iv, f, g, eps); return realIntervalMagnitude(v, f, g, eps); }
/** * 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; }
/** * GenPolynomial greatest squarefree divisor. * * @param P GenPolynomial. * @return squarefree(pp(P)). */ @Override public GenPolynomial<C> squarefreePart(GenPolynomial<C> P) { if (P == null) { throw new IllegalArgumentException(this.getClass().getName() + " P != null"); } if (P.isZERO()) { return P; } GenPolynomialRing<C> pfac = P.ring; if (pfac.nvar <= 1) { return baseSquarefreePart(P); } // just for the moment: GenPolynomial<C> s = pfac.getONE(); SortedMap<GenPolynomial<C>, Long> factors = squarefreeFactors(P); if (logger.isInfoEnabled()) { logger.info("sqfPart,factors = " + factors); } for (GenPolynomial<C> sp : factors.keySet()) { if (sp.isConstant()) { continue; } s = s.multiply(sp); } return s.monic(); }
/** * 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; }
/** * 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(); }
/** * 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; }
/** * Refine intervals. * * @param V list of isolating intervals with f(left) * f(right) < 0. * @param f univariate polynomial, non-zero. * @param eps requested intervals length. * @return a list of new intervals v such that |v| < eps. */ public List<Interval<C>> refineIntervals(List<Interval<C>> V, GenPolynomial<C> f, C eps) { if (f == null || f.isZERO() || f.isConstant() || eps == null) { return V; } List<Interval<C>> IV = new ArrayList<Interval<C>>(); for (Interval<C> v : V) { Interval<C> iv = refineInterval(v, f, eps); IV.add(iv); } return IV; }
/** * Test if x is an approximate real root. * * @param x approximate real root. * @param f univariate polynomial, non-zero. * @param eps requested interval length. * @return true if x is a decimal approximation of a real v with f(v) = 0 with |d-v| < eps, * else false. */ public boolean isApproximateRoot(BigDecimal x, GenPolynomial<C> f, C eps) { if (x == null) { throw new IllegalArgumentException("null root not allowed"); } if (f == null || f.isZERO() || f.isConstant() || eps == null) { return true; } BigDecimal e = new BigDecimal(eps.getRational()); e = e.multiply(new BigDecimal("1000")); // relax BigDecimal dc = BigDecimal.ONE; // polynomials with decimal coefficients GenPolynomialRing<BigDecimal> dfac = new GenPolynomialRing<BigDecimal>(dc, f.ring); GenPolynomial<BigDecimal> df = PolyUtil.<C>decimalFromRational(dfac, f); GenPolynomial<C> fp = PolyUtil.<C>baseDeriviative(f); GenPolynomial<BigDecimal> dfp = PolyUtil.<C>decimalFromRational(dfac, fp); // return isApproximateRoot(x, df, dfp, e); }
/** * 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; }
/** * Polynomial is char-th root. * * @param P polynomial. * @param F = [p_1 -> e_1, ..., p_k -> e_k]. * @return true if P = prod_{i=1,...,k} p_i**(e_i*p), else false. */ public boolean isCharRoot(GenPolynomial<C> P, SortedMap<GenPolynomial<C>, Long> F) { if (P == null || F == null) { throw new IllegalArgumentException("P and F may not be null"); } if (P.isZERO() && F.size() == 0) { return true; } GenPolynomial<C> t = P.ring.getONE(); long p = P.ring.characteristic().longValue(); for (Map.Entry<GenPolynomial<C>, Long> me : F.entrySet()) { GenPolynomial<C> f = me.getKey(); Long E = me.getValue(); // F.get(f); long e = E.longValue(); GenPolynomial<C> g = Power.<GenPolynomial<C>>positivePower(f, e); if (!f.isConstant()) { g = Power.<GenPolynomial<C>>positivePower(g, p); } t = t.multiply(g); } boolean f = P.equals(t) || P.equals(t.negate()); if (!f) { System.out.println("\nfactorization(map): " + f); System.out.println("P = " + P); System.out.println("t = " + t); P = P.monic(); t = t.monic(); f = P.equals(t) || P.equals(t.negate()); if (f) { return f; } System.out.println("\nfactorization(map): " + f); System.out.println("P = " + P); System.out.println("t = " + t); } return f; }
/** * Approximate real root. * * @param iv real root isolating interval with f(left) * f(right) < 0. * @param f univariate polynomial, non-zero. * @param eps requested interval length. * @return a decimal approximation d such that |d-v| < eps, for f(v) = 0, v real. */ public BigDecimal approximateRoot(Interval<C> iv, GenPolynomial<C> f, C eps) throws NoConvergenceException { if (iv == null) { throw new IllegalArgumentException("null interval not allowed"); } BigDecimal d = iv.toDecimal(); if (f == null || f.isZERO() || f.isConstant() || eps == null) { return d; } if (iv.length().compareTo(eps) < 0) { return d; } BigDecimal left = new BigDecimal(iv.left.getRational()); BigDecimal right = new BigDecimal(iv.right.getRational()); BigDecimal e = new BigDecimal(eps.getRational()); BigDecimal q = new BigDecimal("0.25"); // System.out.println("left = " + left); // System.out.println("right = " + right); e = e.multiply(d); // relative error // System.out.println("e = " + e); BigDecimal dc = BigDecimal.ONE; // polynomials with decimal coefficients GenPolynomialRing<BigDecimal> dfac = new GenPolynomialRing<BigDecimal>(dc, f.ring); GenPolynomial<BigDecimal> df = PolyUtil.<C>decimalFromRational(dfac, f); GenPolynomial<C> fp = PolyUtil.<C>baseDeriviative(f); GenPolynomial<BigDecimal> dfp = PolyUtil.<C>decimalFromRational(dfac, fp); // Newton Raphson iteration: x_{n+1} = x_n - f(x_n)/f'(x_n) int i = 0; final int MITER = 50; int dir = 0; while (i++ < MITER) { BigDecimal fx = PolyUtil.<BigDecimal>evaluateMain(dc, df, d); // f(d) if (fx.isZERO()) { return d; } BigDecimal fpx = PolyUtil.<BigDecimal>evaluateMain(dc, dfp, d); // f'(d) if (fpx.isZERO()) { throw new NoConvergenceException("zero deriviative should not happen"); } BigDecimal x = fx.divide(fpx); BigDecimal dx = d.subtract(x); // System.out.println("dx = " + dx); if (d.subtract(dx).abs().compareTo(e) <= 0) { return dx; } while (dx.compareTo(left) < 0 || dx.compareTo(right) > 0) { // dx < left: dx - left < 0 // dx > right: dx - right > 0 // System.out.println("trying to leave interval"); if (i++ > MITER) { // dx > right: dx - right > 0 throw new NoConvergenceException("no convergence after " + i + " steps"); } if (i > MITER / 2 && dir == 0) { BigDecimal sd = new BigDecimal(iv.randomPoint().getRational()); d = sd; x = sd.getZERO(); logger.info("trying new random starting point " + d); i = 0; dir = 1; } if (i > MITER / 2 && dir == 1) { BigDecimal sd = new BigDecimal(iv.randomPoint().getRational()); d = sd; x = sd.getZERO(); logger.info("trying new random starting point " + d); // i = 0; dir = 2; // end } x = x.multiply(q); // x * 1/4 dx = d.subtract(x); // System.out.println(" x = " + x); // System.out.println("dx = " + dx); } d = dx; } throw new NoConvergenceException("no convergence after " + i + " steps"); }
/** * Univariate GenPolynomial algebraic partial fraction decomposition, Rothstein-Trager algorithm. * * @param A univariate GenPolynomial, deg(A) < deg(P). * @param P univariate squarefree GenPolynomial, gcd(A,P) == 1. * @return partial fraction container. */ @Deprecated public PartialFraction<C> baseAlgebraicPartialFractionIrreducible( GenPolynomial<C> A, GenPolynomial<C> P) { if (P == null || P.isZERO()) { throw new RuntimeException(" P == null or P == 0"); } // System.out.println("\nP_base_algeb_part = " + 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"); } List<C> cfactors = new ArrayList<C>(); List<GenPolynomial<C>> cdenom = new ArrayList<GenPolynomial<C>>(); List<AlgebraicNumber<C>> afactors = new ArrayList<AlgebraicNumber<C>>(); List<GenPolynomial<AlgebraicNumber<C>>> adenom = new ArrayList<GenPolynomial<AlgebraicNumber<C>>>(); // P linear if (P.degree(0) <= 1) { cfactors.add(A.leadingBaseCoefficient()); cdenom.add(P); return new PartialFraction<C>(A, P, cfactors, cdenom, afactors, adenom); } // deriviative GenPolynomial<C> Pp = PolyUtil.<C>baseDeriviative(P); // no: Pp = Pp.monic(); // System.out.println("\nP = " + P); // System.out.println("Pp = " + Pp); // Q[t] String[] vars = new String[] {"t"}; GenPolynomialRing<C> cfac = new GenPolynomialRing<C>(pfac.coFac, 1, pfac.tord, vars); GenPolynomial<C> t = cfac.univariate(0); // System.out.println("t = " + t); // Q[x][t] GenPolynomialRing<GenPolynomial<C>> rfac = new GenPolynomialRing<GenPolynomial<C>>(pfac, cfac); // sic // System.out.println("rfac = " + rfac.toScript()); // transform polynomials to bi-variate polynomial GenPolynomial<GenPolynomial<C>> Ac = PolyUfdUtil.<C>introduceLowerVariable(rfac, A); // System.out.println("Ac = " + Ac); GenPolynomial<GenPolynomial<C>> Pc = PolyUfdUtil.<C>introduceLowerVariable(rfac, P); // System.out.println("Pc = " + Pc); GenPolynomial<GenPolynomial<C>> Pcp = PolyUfdUtil.<C>introduceLowerVariable(rfac, Pp); // System.out.println("Pcp = " + Pcp); // Q[t][x] GenPolynomialRing<GenPolynomial<C>> rfac1 = Pc.ring; // System.out.println("rfac1 = " + rfac1.toScript()); // A - t P' GenPolynomial<GenPolynomial<C>> tc = rfac1.getONE().multiply(t); // System.out.println("tc = " + tc); GenPolynomial<GenPolynomial<C>> At = Ac.subtract(tc.multiply(Pcp)); // System.out.println("At = " + At); GreatestCommonDivisorSubres<C> engine = new GreatestCommonDivisorSubres<C>(); // = GCDFactory.<C>getImplementation( cfac.coFac ); GreatestCommonDivisorAbstract<AlgebraicNumber<C>> aengine = null; GenPolynomial<GenPolynomial<C>> Rc = engine.recursiveResultant(Pc, At); // System.out.println("Rc = " + Rc); GenPolynomial<C> res = Rc.leadingBaseCoefficient(); // no: res = res.monic(); // System.out.println("\nres = " + res); SortedMap<GenPolynomial<C>, Long> resfac = baseFactors(res); // System.out.println("resfac = " + resfac + "\n"); for (GenPolynomial<C> r : resfac.keySet()) { // System.out.println("\nr(t) = " + r); if (r.isConstant()) { continue; } // if ( r.degree(0) <= 1L ) { // System.out.println("warning linear factor in resultant ignored"); // continue; // //throw new RuntimeException("input not irreducible"); // } // vars = new String[] { "z_" + Math.abs(r.hashCode() % 1000) }; vars = pfac.newVars("z_"); pfac = pfac.clone(); vars = pfac.setVars(vars); r = pfac.copy(r); // hack to exchange the variables // System.out.println("r(z_) = " + r); AlgebraicNumberRing<C> afac = new AlgebraicNumberRing<C>(r, true); // since irreducible logger.debug("afac = " + afac.toScript()); AlgebraicNumber<C> a = afac.getGenerator(); // no: a = a.negate(); // System.out.println("a = " + a); // K(alpha)[x] GenPolynomialRing<AlgebraicNumber<C>> pafac = new GenPolynomialRing<AlgebraicNumber<C>>(afac, Pc.ring); // System.out.println("pafac = " + pafac.toScript()); // convert to K(alpha)[x] GenPolynomial<AlgebraicNumber<C>> Pa = PolyUtil.<C>convertToAlgebraicCoefficients(pafac, P); // System.out.println("Pa = " + Pa); GenPolynomial<AlgebraicNumber<C>> Pap = PolyUtil.<C>convertToAlgebraicCoefficients(pafac, Pp); // System.out.println("Pap = " + Pap); GenPolynomial<AlgebraicNumber<C>> Aa = PolyUtil.<C>convertToAlgebraicCoefficients(pafac, A); // System.out.println("Aa = " + Aa); // A - a P' GenPolynomial<AlgebraicNumber<C>> Ap = Aa.subtract(Pap.multiply(a)); // System.out.println("Ap = " + Ap); if (aengine == null) { aengine = GCDFactory.<AlgebraicNumber<C>>getImplementation(afac); // System.out.println("aengine = " + aengine); } GenPolynomial<AlgebraicNumber<C>> Ga = aengine.baseGcd(Pa, Ap); // System.out.println("Ga = " + Ga); if (Ga.isConstant()) { // System.out.println("warning constant gcd ignored"); continue; } afactors.add(a); adenom.add(Ga); // quadratic case if (P.degree(0) == 2 && Ga.degree(0) == 1) { GenPolynomial<AlgebraicNumber<C>>[] qra = PolyUtil.<AlgebraicNumber<C>>basePseudoQuotientRemainder(Pa, Ga); GenPolynomial<AlgebraicNumber<C>> Qa = qra[0]; if (!qra[1].isZERO()) { throw new RuntimeException("remainder not zero"); } // System.out.println("Qa = " + Qa); afactors.add(a.negate()); adenom.add(Qa); } if (false && P.degree(0) == 3 && Ga.degree(0) == 1) { GenPolynomial<AlgebraicNumber<C>>[] qra = PolyUtil.<AlgebraicNumber<C>>basePseudoQuotientRemainder(Pa, Ga); GenPolynomial<AlgebraicNumber<C>> Qa = qra[0]; if (!qra[1].isZERO()) { throw new RuntimeException("remainder not zero"); } System.out.println("Qa3 = " + Qa); // afactors.add( a.negate() ); // adenom.add( Qa ); } } return new PartialFraction<C>(A, P, cfactors, cdenom, afactors, adenom); }
/** * GenPolynomial polynomial squarefree factorization. * * @param A GenPolynomial. * @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<GenPolynomial<C>, Long> baseSquarefreeFactors(GenPolynomial<C> A) { SortedMap<GenPolynomial<C>, Long> sfactors = new TreeMap<GenPolynomial<C>, Long>(); if (A == null || A.isZERO()) { return sfactors; } GenPolynomialRing<C> pfac = A.ring; if (A.isConstant()) { C coeff = A.leadingBaseCoefficient(); // System.out.println("coeff = " + coeff + " @ " + coeff.factory()); SortedMap<C, Long> rfactors = squarefreeFactors(coeff); // System.out.println("rfactors,const = " + rfactors); if (rfactors != null && rfactors.size() > 0) { for (Map.Entry<C, Long> me : rfactors.entrySet()) { C c = me.getKey(); if (!c.isONE()) { GenPolynomial<C> cr = pfac.getONE().multiply(c); Long rk = me.getValue(); // rfactors.get(c); sfactors.put(cr, rk); } } } else { sfactors.put(A, 1L); } return sfactors; } if (pfac.nvar > 1) { throw new IllegalArgumentException( this.getClass().getName() + " only for univariate polynomials"); } C ldbcf = A.leadingBaseCoefficient(); if (!ldbcf.isONE()) { A = A.divide(ldbcf); SortedMap<C, Long> rfactors = squarefreeFactors(ldbcf); // System.out.println("rfactors,ldbcf = " + rfactors); if (rfactors != null && rfactors.size() > 0) { for (Map.Entry<C, Long> me : rfactors.entrySet()) { C c = me.getKey(); if (!c.isONE()) { GenPolynomial<C> cr = pfac.getONE().multiply(c); Long rk = me.getValue(); // rfactors.get(c); sfactors.put(cr, rk); } } } else { GenPolynomial<C> f1 = pfac.getONE().multiply(ldbcf); // System.out.println("gcda sqf f1 = " + f1); sfactors.put(f1, 1L); } ldbcf = pfac.coFac.getONE(); } GenPolynomial<C> T0 = A; long e = 1L; GenPolynomial<C> Tp; GenPolynomial<C> T = null; GenPolynomial<C> V = null; long k = 0L; long mp = 0L; boolean init = true; while (true) { // System.out.println("T0 = " + T0); if (init) { if (T0.isConstant() || T0.isZERO()) { break; } Tp = PolyUtil.<C>baseDeriviative(T0); T = engine.baseGcd(T0, Tp); T = T.monic(); V = PolyUtil.<C>basePseudoDivide(T0, T); // System.out.println("iT0 = " + T0); // System.out.println("iTp = " + Tp); // System.out.println("iT = " + T); // System.out.println("iV = " + V); // System.out.println("const(iV) = " + V.isConstant()); k = 0L; mp = 0L; init = false; } if (V.isConstant()) { mp = pfac.characteristic().longValue(); // assert != 0 // T0 = PolyUtil.<C> baseModRoot(T,mp); T0 = baseRootCharacteristic(T); logger.info("char root: T0 = " + T0 + ", T = " + T); if (T0 == null) { // break; T0 = pfac.getZERO(); } e = e * mp; init = true; continue; } k++; if (mp != 0L && k % mp == 0L) { T = PolyUtil.<C>basePseudoDivide(T, V); System.out.println("k = " + k); // System.out.println("T = " + T); k++; } GenPolynomial<C> W = engine.baseGcd(T, V); W = W.monic(); GenPolynomial<C> z = PolyUtil.<C>basePseudoDivide(V, W); // System.out.println("W = " + W); // System.out.println("z = " + z); V = W; T = PolyUtil.<C>basePseudoDivide(T, V); // System.out.println("V = " + V); // System.out.println("T = " + T); if (z.degree(0) > 0) { if (ldbcf.isONE() && !z.leadingBaseCoefficient().isONE()) { z = z.monic(); logger.info("z,monic = " + z); } sfactors.put(z, (e * k)); } } // look, a stupid error: // if ( !ldbcf.isONE() ) { // GenPolynomial<C> f1 = sfactors.firstKey(); // long e1 = sfactors.remove(f1); // System.out.println("gcda sqf c = " + c); // f1 = f1.multiply(c); // //System.out.println("gcda sqf f1e = " + f1); // sfactors.put(f1,e1); // } logger.info("exit char root: T0 = " + T0 + ", T = " + T); return sfactors; }