001/*
002 * $Id$
003 */
004
005package edu.jas.ufd;
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.poly.AlgebraicNumber;
015import edu.jas.poly.AlgebraicNumberRing;
016import edu.jas.poly.Complex;
017import edu.jas.poly.ComplexRing;
018import edu.jas.poly.GenPolynomial;
019import edu.jas.poly.GenPolynomialRing;
020import edu.jas.poly.TermOrder;
021import edu.jas.poly.PolyUtil;
022import edu.jas.structure.GcdRingElem;
023import edu.jas.structure.RingFactory;
024
025
026/**
027 * Complex coefficients factorization algorithms. This class implements
028 * factorization methods for polynomials over Complex numbers via the algebraic
029 * number C(i) over rational numbers or over (prime) modular integers. <b>Note:</b>
030 * Decomposition to linear factors is only via absolute factorization since
031 * Complex are not the analytic complex numbers.
032 * @author Heinz Kredel
033 * @param <C> coefficient type
034 */
035
036public class FactorComplex<C extends GcdRingElem<C>> extends FactorAbsolute<Complex<C>> {
037
038
039    private static final Logger logger = LogManager.getLogger(FactorComplex.class);
040
041
042    private static final boolean debug = logger.isDebugEnabled();
043
044
045    /**
046     * Factorization engine for algebraic coefficients.
047     */
048    public final FactorAbstract<AlgebraicNumber<C>> factorAlgeb;
049
050
051    /**
052     * Complex algebraic factory.
053     */
054    public final AlgebraicNumberRing<C> afac;
055
056
057    /**
058     * No argument constructor. <b>Note:</b> can't use this constructor.
059     */
060    protected FactorComplex() {
061        throw new IllegalArgumentException("don't use this constructor");
062    }
063
064
065    /**
066     * Constructor.
067     * @param fac complex number factory.
068     */
069    public FactorComplex(RingFactory<Complex<C>> fac) { // why is this constructor required?
070        this((ComplexRing<C>) fac);
071    }
072
073
074    /**
075     * Constructor.
076     * @param fac complex number factory.
077     */
078    public FactorComplex(ComplexRing<C> fac) {
079        super(fac);
080        this.afac = fac.algebraicRing();
081        this.factorAlgeb = FactorFactory.<C> getImplementation(afac);
082    }
083
084
085    /**
086     * Constructor.
087     * @param fac complex number factory.
088     * @param factorAlgeb factorization engine for polynomials over algebraic coefficients.
089     */
090    public FactorComplex(ComplexRing<C> fac, FactorAbstract<AlgebraicNumber<C>> factorAlgeb) {
091        super(fac);
092        this.afac = fac.algebraicRing();
093        this.factorAlgeb = factorAlgeb;
094    }
095
096
097    /**
098     * GenPolynomial base factorization of a squarefree polynomial.
099     * @param P squarefree GenPolynomial&lt;AlgebraicNumber&lt;C&gt;&gt;.
100     * @return [p_1,...,p_k] with P = prod_{i=1, ..., k} p_i.
101     */
102    @Override
103    public List<GenPolynomial<Complex<C>>> baseFactorsSquarefree(GenPolynomial<Complex<C>> P) {
104        if (P == null) {
105            throw new IllegalArgumentException(this.getClass().getName() + " P == null");
106        }
107        List<GenPolynomial<Complex<C>>> factors = new ArrayList<GenPolynomial<Complex<C>>>();
108        if (P.isZERO()) {
109            return factors;
110        }
111        if (P.isONE()) {
112            factors.add(P);
113            return factors;
114        }
115        GenPolynomialRing<Complex<C>> pfac = P.ring; // CC[x]
116        if (pfac.nvar > 1) {
117            throw new IllegalArgumentException("only for univariate polynomials");
118        }
119        ComplexRing<C> cfac = (ComplexRing<C>) pfac.coFac;
120        if (!afac.ring.coFac.equals(cfac.ring)) {
121            throw new IllegalArgumentException("coefficient rings do not match");
122        }
123        Complex<C> ldcf = P.leadingBaseCoefficient();
124        if (!ldcf.isONE()) {
125            P = P.monic();
126            factors.add(pfac.getONE().multiply(ldcf));
127        }
128        //System.out.println("\nP = " + P);
129        GenPolynomialRing<AlgebraicNumber<C>> pafac = new GenPolynomialRing<AlgebraicNumber<C>>(afac, pfac);
130        GenPolynomial<AlgebraicNumber<C>> A = PolyUtil.<C> algebraicFromComplex(pafac, P);
131        //System.out.println("A = " + A);
132        List<GenPolynomial<AlgebraicNumber<C>>> afactors = factorAlgeb.baseFactorsSquarefree(A);
133        if (debug) {
134            logger.info("complex afactors = {}", afactors);
135        }
136        for (GenPolynomial<AlgebraicNumber<C>> pa : afactors) {
137            GenPolynomial<Complex<C>> pc = PolyUtil.<C> complexFromAlgebraic(pfac, pa);
138            factors.add(pc);
139        }
140        //System.out.println("cfactors = " + factors);
141        return factors;
142    }
143
144
145    /**
146     * GenPolynomial factorization of a squarefree polynomial.
147     * @param P squarefree GenPolynomial&lt;AlgebraicNumber&lt;C&gt;&gt;.
148     * @return [p_1,...,p_k] with P = prod_{i=1, ..., k} p_i.
149     */
150    @Override
151    public List<GenPolynomial<Complex<C>>> factorsSquarefree(GenPolynomial<Complex<C>> P) {
152        if (P == null) {
153            throw new IllegalArgumentException(this.getClass().getName() + " P == null");
154        }
155        List<GenPolynomial<Complex<C>>> factors = new ArrayList<GenPolynomial<Complex<C>>>();
156        if (P.isZERO()) {
157            return factors;
158        }
159        if (P.isONE()) {
160            factors.add(P);
161            return factors;
162        }
163        GenPolynomialRing<Complex<C>> pfac = P.ring; // CC[x]
164        if (pfac.nvar <= 1) {
165            throw new IllegalArgumentException("only for multivariate polynomials");
166        }
167        ComplexRing<C> cfac = (ComplexRing<C>) pfac.coFac;
168        if (!afac.ring.coFac.equals(cfac.ring)) {
169            throw new IllegalArgumentException("coefficient rings do not match");
170        }
171        Complex<C> ldcf = P.leadingBaseCoefficient();
172        if (!ldcf.isONE()) {
173            P = P.monic();
174            factors.add(pfac.getONE().multiply(ldcf));
175        }
176        //System.out.println("\nP = " + P);
177        GenPolynomialRing<AlgebraicNumber<C>> pafac = new GenPolynomialRing<AlgebraicNumber<C>>(afac, pfac);
178        GenPolynomial<AlgebraicNumber<C>> A = PolyUtil.<C> algebraicFromComplex(pafac, P);
179        //System.out.println("A = " + A);
180        List<GenPolynomial<AlgebraicNumber<C>>> afactors = factorAlgeb.factorsSquarefree(A);
181        if (debug) {
182            logger.info("complex afactors = {}", afactors);
183        }
184        for (GenPolynomial<AlgebraicNumber<C>> pa : afactors) {
185            GenPolynomial<Complex<C>> pc = PolyUtil.<C> complexFromAlgebraic(pfac, pa);
186            factors.add(pc);
187        }
188        //System.out.println("cfactors = " + factors);
189        return factors;
190    }
191
192}