001/*
002 * $Id: FactorRealAlgebraic.java 5872 2018-07-20 16:01:46Z kredel $
003 */
004
005package edu.jas.ufdroot;
006
007
008import java.util.ArrayList;
009import java.util.List;
010
011import org.apache.logging.log4j.Logger;
012import org.apache.logging.log4j.LogManager; 
013
014import edu.jas.arith.Rational;
015import edu.jas.poly.AlgebraicNumber;
016import edu.jas.poly.GenPolynomial;
017import edu.jas.poly.GenPolynomialRing;
018import edu.jas.root.PolyUtilRoot;
019import edu.jas.root.RealAlgebraicNumber;
020import edu.jas.root.RealAlgebraicRing;
021import edu.jas.structure.GcdRingElem;
022import edu.jas.ufd.FactorAbstract;
023import edu.jas.ufd.FactorFactory;
024
025
026/**
027 * Real algebraic number coefficients factorization algorithms. This class
028 * implements factorization methods for polynomials over real algebraic numbers
029 * from package
030 * 
031 * <pre>
032 * edu.jas.root
033 * </pre>
034 * 
035 * .
036 * @param <C> coefficient type
037 * @author Heinz Kredel
038 */
039
040public class FactorRealAlgebraic<C extends GcdRingElem<C> & Rational> extends
041                FactorAbstract<RealAlgebraicNumber<C>> {
042
043
044    // TODO: is absolute possible? and what does it mean?
045    //FactorAbsolute<AlgebraicNumber<C>>
046    //FactorAbstract<AlgebraicNumber<C>>
047
048
049    private static final Logger logger = LogManager.getLogger(FactorRealAlgebraic.class);
050
051
052    //private static final boolean debug = logger.isInfoEnabled();
053
054
055    /**
056     * Factorization engine for base coefficients.
057     */
058    public final FactorAbstract<AlgebraicNumber<C>> factorAlgebraic;
059
060
061    /**
062     * No argument constructor. <b>Note:</b> can't use this constructor.
063     */
064    protected FactorRealAlgebraic() {
065        throw new IllegalArgumentException("don't use this constructor");
066    }
067
068
069    /**
070     * Constructor.
071     * @param fac algebraic number factory.
072     */
073    public FactorRealAlgebraic(RealAlgebraicRing<C> fac) {
074        this(fac, FactorFactory.<AlgebraicNumber<C>> getImplementation(fac.algebraic));
075    }
076
077
078    /**
079     * Constructor.
080     * @param fac algebraic number factory.
081     * @param factorAlgebraic factorization engine for polynomials over base
082     *            coefficients.
083     */
084    public FactorRealAlgebraic(RealAlgebraicRing<C> fac, FactorAbstract<AlgebraicNumber<C>> factorAlgebraic) {
085        super(fac);
086        this.factorAlgebraic = factorAlgebraic;
087    }
088
089
090    /**
091     * GenPolynomial base factorization of a squarefree polynomial.
092     * @param P squarefree GenPolynomial&lt;RealAlgebraicNumber&lt;C&gt;&gt;.
093     * @return [p_1,...,p_k] with P = prod_{i=1, ..., k} p_i.
094     */
095    @Override
096    public List<GenPolynomial<RealAlgebraicNumber<C>>> baseFactorsSquarefree(
097                    GenPolynomial<RealAlgebraicNumber<C>> P) {
098        if (P == null) {
099            throw new IllegalArgumentException(this.getClass().getName() + " P == null");
100        }
101        List<GenPolynomial<RealAlgebraicNumber<C>>> factors = new ArrayList<GenPolynomial<RealAlgebraicNumber<C>>>();
102        if (P.isZERO()) {
103            return factors;
104        }
105        if (P.isONE()) {
106            factors.add(P);
107            return factors;
108        }
109        GenPolynomialRing<RealAlgebraicNumber<C>> pfac = P.ring; // Q(alpha)[x]
110        if (pfac.nvar > 1) {
111            throw new IllegalArgumentException("only for univariate polynomials");
112        }
113        RealAlgebraicRing<C> rfac = (RealAlgebraicRing<C>) pfac.coFac;
114
115        RealAlgebraicNumber<C> ldcf = P.leadingBaseCoefficient();
116        if (!ldcf.isONE()) {
117            P = P.monic();
118            factors.add(pfac.getONE().multiply(ldcf));
119        }
120        //System.out.println("\nP = " + P);
121        GenPolynomialRing<AlgebraicNumber<C>> afac = new GenPolynomialRing<AlgebraicNumber<C>>(
122                        rfac.algebraic, pfac);
123        GenPolynomial<AlgebraicNumber<C>> A = PolyUtilRoot.<C> algebraicFromRealCoefficients(afac, P);
124        // factor A:
125        List<GenPolynomial<AlgebraicNumber<C>>> afactors = factorAlgebraic.baseFactorsSquarefree(A);
126        for (GenPolynomial<AlgebraicNumber<C>> a : afactors) {
127            GenPolynomial<RealAlgebraicNumber<C>> p = PolyUtilRoot.<C> realFromAlgebraicCoefficients(pfac, a);
128            factors.add(p);
129        }
130        logger.info("real algebraic factors = " + factors);
131        return factors;
132    }
133
134}