/*
 * $Id$
 */

package edu.jas.ufd;


import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import org.apache.log4j.Logger;

import edu.jas.poly.AlgebraicNumber;
import edu.jas.poly.AlgebraicNumberRing;
import edu.jas.poly.GenPolynomial;
import edu.jas.poly.GenPolynomialRing;
import edu.jas.poly.PolyUtil;
import edu.jas.structure.GcdRingElem;
import edu.jas.structure.Power;
import edu.jas.structure.RingFactory;


/**
 * Squarefree decomposition for coefficient fields of characteristic p.
 * @author Heinz Kredel
 */

public abstract class SquarefreeFieldCharP> extends SquarefreeAbstract {


    private static final Logger logger = Logger.getLogger(SquarefreeFieldCharP.class);


    private final boolean debug = logger.isDebugEnabled();


    /*
     * Squarefree engine for characteristic p base coefficients.
     */
    //protected final SquarefreeAbstract rengine;


    /**
     * Factory for finite field of characteristic p coefficients.
     */
    protected final RingFactory coFac;


    /**
     * Factory for a algebraic extension of a finite field of characteristic p
     * coefficients. If coFac is an algebraic extension, then
     * aCoFac is equal to coFac, else
     * aCoFac is null.
     */
    protected final AlgebraicNumberRing aCoFac;


    /**
     * Factory for a transcendental extension of a finite field of
     * characteristic p coefficients. If coFac is an transcendental
     * extension, then qCoFac is equal to coFac, else
     * qCoFac is null.
     */
    protected final QuotientRing qCoFac;


    /**
     * Constructor.
     */
    @SuppressWarnings("unchecked")
    public SquarefreeFieldCharP(RingFactory fac) {
        super(GCDFactory. 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) oFac; //  is not correct
            //rengine = (SquarefreeAbstract) SquarefreeFactory.getImplementation(aCoFac.ring);
            qCoFac = null;
        } else {
            aCoFac = null;
            if (oFac instanceof QuotientRing) {
                qCoFac = (QuotientRing) oFac; //  is not correct
                //rengine = (SquarefreeAbstract) SquarefreeFactory.getImplementation(qCoFac.ring);
            } else {
                qCoFac = null;
                //rengine = null; //(SquarefreeAbstract) SquarefreeFactory.getImplementation(oFac);
            }
        }
    }


    /**
     * Get the String representation.
     * @see java.lang.Object#toString()
     */
    @Override
    public String toString() {
        return getClass().getName() + " with " + engine + " over " + coFac;
    }


    /**
     * GenPolynomial polynomial greatest squarefree divisor.
     * @param P GenPolynomial.
     * @return squarefree(pp(P)).
     */
    @Override
    public GenPolynomial baseSquarefreePart(GenPolynomial P) {
        if (P == null || P.isZERO()) {
            return P;
        }
        GenPolynomialRing pfac = P.ring;
        if (pfac.nvar > 1) {
            throw new IllegalArgumentException(this.getClass().getName() + " only for univariate polynomials");
        }
        // just for the moment:
        GenPolynomial s = pfac.getONE();
        SortedMap, Long> factors = baseSquarefreeFactors(P);
        logger.info("sqfPart,factors = " + factors);
        for (GenPolynomial sp : factors.keySet()) {
            s = s.multiply(sp);
        }
        return s.monic();
    }


    /**
     * 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, Long> baseSquarefreeFactors(GenPolynomial A) {
        SortedMap, Long> sfactors = new TreeMap, Long>();
        if (A == null || A.isZERO()) {
            return sfactors;
        }
        GenPolynomialRing pfac = A.ring;
        if (A.isConstant()) {
            C coeff = A.leadingBaseCoefficient();
            //System.out.println("coeff = " + coeff + " @ " + coeff.factory());
            SortedMap rfactors = squarefreeFactors(coeff);
            //System.out.println("rfactors,const = " + rfactors);
            if (rfactors != null && rfactors.size() > 0) {
                for (Map.Entry me : rfactors.entrySet()) {
                    C c = me.getKey();
                    if (!c.isONE()) {
                        GenPolynomial 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 rfactors = squarefreeFactors(ldbcf);
            //System.out.println("rfactors,ldbcf = " + rfactors);
            if (rfactors != null && rfactors.size() > 0) {
                for (Map.Entry me : rfactors.entrySet()) {
                    C c = me.getKey();
                    if (!c.isONE()) {
                        GenPolynomial cr = pfac.getONE().multiply(c);
                        Long rk = me.getValue(); //rfactors.get(c);
                        sfactors.put(cr, rk);
                    }
                }
            } else {
                GenPolynomial f1 = pfac.getONE().multiply(ldbcf);
                //System.out.println("gcda sqf f1 = " + f1);
                sfactors.put(f1, 1L);
            }
            ldbcf = pfac.coFac.getONE();
        }
        GenPolynomial T0 = A;
        long e = 1L;
        GenPolynomial Tp;
        GenPolynomial T = null;
        GenPolynomial 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. baseDeriviative(T0);
                T = engine.baseGcd(T0, Tp);
                T = T.monic();
                V = PolyUtil. 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. 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. basePseudoDivide(T, V);
                System.out.println("k = " + k);
                //System.out.println("T = " + T);
                k++;
            }
            GenPolynomial W = engine.baseGcd(T, V);
            W = W.monic();
            GenPolynomial z = PolyUtil. basePseudoDivide(V, W);
            //System.out.println("W = " + W);
            //System.out.println("z = " + z);
            V = W;
            T = PolyUtil. 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 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;
    }


    /**
     * GenPolynomial recursive univariate polynomial greatest squarefree
     * divisor.
     * @param P recursive univariate GenPolynomial.
     * @return squarefree(pp(P)).
     */
    @Override
    public GenPolynomial> recursiveUnivariateSquarefreePart(GenPolynomial> P) {
        if (P == null || P.isZERO()) {
            return P;
        }
        GenPolynomialRing> pfac = P.ring;
        if (pfac.nvar > 1) {
            throw new IllegalArgumentException(this.getClass().getName()
                            + " only for multivariate polynomials");
        }
        // just for the moment:
        GenPolynomial> s = pfac.getONE();

        SortedMap>, Long> factors = recursiveUnivariateSquarefreeFactors(P);
        if (logger.isInfoEnabled()) {
            logger.info("sqfPart,factors = " + factors);
        }
        for (GenPolynomial> sp : factors.keySet()) {
            s = s.multiply(sp);
        }
        return PolyUtil. monic(s);
    }


    /**
     * GenPolynomial recursive univariate polynomial squarefree factorization.
     * @param P recursive univariate 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>, Long> recursiveUnivariateSquarefreeFactors(
                    GenPolynomial> P) {
        SortedMap>, Long> sfactors = new TreeMap>, Long>();
        if (P == null || P.isZERO()) {
            return sfactors;
        }
        GenPolynomialRing> pfac = P.ring;
        if (pfac.nvar > 1) {
            // recursiveContent not possible by return type
            throw new IllegalArgumentException(this.getClass().getName() + " only for univariate polynomials");
        }
        // if base coefficient ring is a field, make monic
        GenPolynomialRing cfac = (GenPolynomialRing) pfac.coFac;
        C ldbcf = P.leadingBaseCoefficient().leadingBaseCoefficient();
        if (!ldbcf.isONE()) {
            GenPolynomial lc = cfac.getONE().multiply(ldbcf);
            GenPolynomial> pl = pfac.getONE().multiply(lc);
            sfactors.put(pl, 1L);
            C li = ldbcf.inverse();
            //System.out.println("li = " + li);
            P = P.multiply(cfac.getONE().multiply(li));
            //System.out.println("P,monic = " + P);
            ldbcf = P.leadingBaseCoefficient().leadingBaseCoefficient();
            if (debug) {
                logger.debug("new ldbcf: " + ldbcf);
            }
        }
        // factors of content
        GenPolynomial Pc = engine.recursiveContent(P);
        if (logger.isInfoEnabled()) {
            logger.info("Pc = " + Pc);
        }
        Pc = Pc.monic();
        if (!Pc.isONE()) {
            P = PolyUtil. coefficientPseudoDivide(P, Pc);
        }
        SortedMap, Long> rsf = squarefreeFactors(Pc);
        if (logger.isInfoEnabled()) {
            logger.info("rsf = " + rsf);
        }
        // add factors of content
        for (Map.Entry, Long> me : rsf.entrySet()) {
            GenPolynomial c = me.getKey();
            if (!c.isONE()) {
                GenPolynomial> cr = pfac.getONE().multiply(c);
                Long rk = me.getValue(); //rsf.get(c);
                sfactors.put(cr, rk);
            }
        }

        // factors of recursive polynomial
        GenPolynomial> T0 = P;
        long e = 1L;
        GenPolynomial> Tp;
        GenPolynomial> T = null;
        GenPolynomial> V = null;
        long k = 0L;
        long mp = 0L;
        boolean init = true;
        while (true) {
            if (init) {
                if (T0.isConstant() || T0.isZERO()) {
                    break;
                }
                Tp = PolyUtil. recursiveDeriviative(T0);
                T = engine.recursiveUnivariateGcd(T0, Tp);
                T = PolyUtil. monic(T);
                V = PolyUtil. recursivePseudoDivide(T0, T);
                //System.out.println("iT0 = " + T0);
                //System.out.println("iTp = " + Tp);
                //System.out.println("iT = " + T);
                //System.out.println("iV = " + V);
                k = 0L;
                mp = 0L;
                init = false;
            }
            if (V.isConstant()) {
                mp = pfac.characteristic().longValue(); // assert != 0
                //T0 = PolyUtil. recursiveModRoot(T,mp);
                T0 = recursiveUnivariateRootCharacteristic(T);
                logger.info("char root: T0r = " + T0 + ", Tr = " + T);
                if (T0 == null) {
                    //break;
                    T0 = pfac.getZERO();
                }
                e = e * mp;
                init = true;
                //continue;
            }
            k++;
            if (mp != 0L && k % mp == 0L) {
                T = PolyUtil. recursivePseudoDivide(T, V);
                System.out.println("k = " + k);
                //System.out.println("T = " + T);
                k++;
            }
            GenPolynomial> W = engine.recursiveUnivariateGcd(T, V);
            W = PolyUtil. monic(W);
            GenPolynomial> z = PolyUtil. recursivePseudoDivide(V, W);
            //System.out.println("W = " + W);
            //System.out.println("z = " + z);
            V = W;
            T = PolyUtil. recursivePseudoDivide(T, V);
            //System.out.println("V = " + V);
            //System.out.println("T = " + T);
            //was: if ( z.degree(0) > 0 ) {
            if (!z.isONE() && !z.isZERO()) {
                z = PolyUtil. monic(z);
                logger.info("z,put = " + z);
                sfactors.put(z, (e * k));
            }
        }
        logger.info("exit char root: T0 = " + T0 + ", T = " + T);
        if (sfactors.size() == 0) {
            sfactors.put(pfac.getONE(), 1L);
        }
        return sfactors;
    }


    /**
     * GenPolynomial greatest squarefree divisor.
     * @param P GenPolynomial.
     * @return squarefree(pp(P)).
     */
    @Override
    public GenPolynomial squarefreePart(GenPolynomial P) {
        if (P == null) {
            throw new IllegalArgumentException(this.getClass().getName() + " P != null");
        }
        if (P.isZERO()) {
            return P;
        }
        GenPolynomialRing pfac = P.ring;
        if (pfac.nvar <= 1) {
            return baseSquarefreePart(P);
        }
        // just for the moment:
        GenPolynomial s = pfac.getONE();
        SortedMap, Long> factors = squarefreeFactors(P);
        if (logger.isInfoEnabled()) {
            logger.info("sqfPart,factors = " + factors);
        }
        for (GenPolynomial sp : factors.keySet()) {
            if (sp.isConstant()) {
                continue;
            }
            s = s.multiply(sp);
        }
        return s.monic();
    }


    /**
     * GenPolynomial squarefree factorization.
     * @param P 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, Long> squarefreeFactors(GenPolynomial P) {
        if (P == null) {
            throw new IllegalArgumentException(this.getClass().getName() + " P != null");
        }
        GenPolynomialRing pfac = P.ring;
        if (pfac.nvar <= 1) {
            return baseSquarefreeFactors(P);
        }
        SortedMap, Long> sfactors = new TreeMap, Long>();
        if (P.isZERO()) {
            return sfactors;
        }
        GenPolynomialRing cfac = pfac.contract(1);
        GenPolynomialRing> rfac = new GenPolynomialRing>(cfac, 1);

        GenPolynomial> Pr = PolyUtil. recursive(rfac, P);
        SortedMap>, Long> PP = recursiveUnivariateSquarefreeFactors(Pr);

        for (Map.Entry>, Long> m : PP.entrySet()) {
            Long i = m.getValue();
            GenPolynomial> Dr = m.getKey();
            GenPolynomial D = PolyUtil. distribute(pfac, Dr);
            sfactors.put(D, i);
        }
        return sfactors;
    }


    /**
     * 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 squarefreeFactors(C coeff) {
        if (coeff == null) {
            return null;
        }
        SortedMap factors = new TreeMap();
        RingFactory cfac = (RingFactory) coeff.factory();
        if (aCoFac != null) {
            AlgebraicNumber an = (AlgebraicNumber) (Object) coeff;
            if (cfac.isFinite()) {
                SquarefreeFiniteFieldCharP reng = (SquarefreeFiniteFieldCharP) SquarefreeFactory
                                .getImplementation(cfac);
                SortedMap rfactors = reng.rootCharacteristic(coeff); // ??
                logger.info("rfactors,finite = " + rfactors);
                factors.putAll(rfactors);
                //return factors;
            } else {
                SquarefreeInfiniteAlgebraicFieldCharP reng = (SquarefreeInfiniteAlgebraicFieldCharP) SquarefreeFactory
                                .getImplementation(cfac);
                SortedMap, Long> rfactors = reng.squarefreeFactors(an);
                logger.info("rfactors,infinite,algeb = " + rfactors);
                for (Map.Entry, Long> me : rfactors.entrySet()) {
                    AlgebraicNumber 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 q = (Quotient) (Object) coeff;
            SquarefreeInfiniteFieldCharP reng = (SquarefreeInfiniteFieldCharP) SquarefreeFactory
                            .getImplementation(cfac);
            SortedMap, Long> rfactors = reng.squarefreeFactors(q);
            logger.info("rfactors,infinite = " + rfactors);
            for (Map.Entry, Long> me : rfactors.entrySet()) {
                Quotient 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 reng = (SquarefreeFiniteFieldCharP) SquarefreeFactory
                            .getImplementation(cfac);
            SortedMap rfactors = reng.rootCharacteristic(coeff); // ??
            logger.info("rfactors,finite = " + rfactors);
            factors.putAll(rfactors);
            //return factors;
        } else {
            logger.warn("case " + cfac + " not implemented");
        }
        return factors;
    }


    /* --------- char-th roots --------------------- */


    /**
     * GenPolynomial char-th root univariate polynomial.
     * @param P GenPolynomial.
     * @return char-th_rootOf(P), or null if no char-th root.
     */
    public abstract GenPolynomial baseRootCharacteristic(GenPolynomial P);


    /**
     * GenPolynomial char-th root univariate polynomial with polynomial
     * coefficients.
     * @param P recursive univariate GenPolynomial.
     * @return char-th_rootOf(P), or null if P is no char-th root.
     */
    public abstract GenPolynomial> recursiveUnivariateRootCharacteristic(
                    GenPolynomial> P);


    /**
     * 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 P, SortedMap, 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 t = P.ring.getONE();
        long p = P.ring.characteristic().longValue();
        for (Map.Entry, Long> me : F.entrySet()) {
            GenPolynomial f = me.getKey();
            Long E = me.getValue(); //F.get(f);
            long e = E.longValue();
            GenPolynomial g = Power.> positivePower(f, e);
            if (!f.isConstant()) {
                g = Power.> 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;
    }


    /**
     * Recursive polynomial is char-th root.
     * @param P recursive 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 isRecursiveCharRoot(GenPolynomial> P,
                    SortedMap>, 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> t = P.ring.getONE();
        long p = P.ring.characteristic().longValue();
        for (Map.Entry>, Long> me : F.entrySet()) {
            GenPolynomial> f = me.getKey();
            Long E = me.getValue(); //F.get(f);
            long e = E.longValue();
            GenPolynomial> g = Power.>> positivePower(f, e);
            if (!f.isConstant()) {
                g = Power.>> 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;
    }


    /**
     * Recursive polynomial is char-th root.
     * @param P recursive polynomial.
     * @param r = recursive polynomial.
     * @return true if P = r**p, else false.
     */
    public boolean isRecursiveCharRoot(GenPolynomial> P, GenPolynomial> r) {
        if (P == null || r == null) {
            throw new IllegalArgumentException("P and r may not be null");
        }
        if (P.isZERO() && r.isZERO()) {
            return true;
        }
        long p = P.ring.characteristic().longValue();
        GenPolynomial> t = Power.>> positivePower(r, p);

        boolean f = P.equals(t) || P.equals(t.negate());
        if (!f) {
            System.out.println("\nisCharRoot: " + 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("\nisCharRoot: " + f);
            System.out.println("P = " + P);
            System.out.println("t = " + t);
        }
        return f;
    }

}

 

Ads help maintain this website.