001    /*
002     * $Id: FactorComplex.java 3364 2010-10-24 12:56:06Z kredel $
003     */
004    
005    package edu.jas.ufd;
006    
007    
008    import java.util.ArrayList;
009    import java.util.List;
010    
011    import org.apache.log4j.Logger;
012    
013    import edu.jas.poly.AlgebraicNumber;
014    import edu.jas.poly.AlgebraicNumberRing;
015    import edu.jas.poly.Complex;
016    import edu.jas.poly.ComplexRing;
017    import edu.jas.poly.GenPolynomial;
018    import edu.jas.poly.GenPolynomialRing;
019    import edu.jas.poly.TermOrder;
020    import edu.jas.poly.PolyUtil;
021    import edu.jas.structure.GcdRingElem;
022    import edu.jas.structure.RingFactory;
023    
024    
025    /**
026     * Complex coefficients factorization algorithms. This class implements
027     * factorization methods for polynomials over Complex numbers via the algebraic
028     * number C(i) over rational numbers or over (prime) modular integers. <b>Note:</b>
029     * Decomposition to linear factors is only via absolute factorization since
030     * Complex are not the analytic complex numbers.
031     * @author Heinz Kredel
032     * @param <C> coefficient type
033     */
034    
035    public class FactorComplex<C extends GcdRingElem<C>> extends FactorAbsolute<Complex<C>> {
036    
037    
038        private static final Logger logger = Logger.getLogger(FactorComplex.class);
039    
040    
041        private final boolean debug = logger.isDebugEnabled();
042    
043    
044        /**
045         * Factorization engine for algebraic coefficients.
046         */
047        public final FactorAbstract<AlgebraicNumber<C>> factorAlgeb;
048    
049    
050        /**
051         * Complex algebraic factory.
052         */
053        public final AlgebraicNumberRing<C> afac;
054    
055    
056        /**
057         * No argument constructor. <b>Note:</b> can't use this constructor.
058         */
059        protected FactorComplex() {
060            throw new IllegalArgumentException("don't use this constructor");
061        }
062    
063    
064        /**
065         * Constructor.
066         * @param fac complex number factory.
067         */
068        public FactorComplex(RingFactory<Complex<C>> fac) { // why is this constructor required?
069            this((ComplexRing<C>) fac);
070        }
071    
072    
073        /**
074         * Constructor.
075         * @param fac complex number factory.
076         */
077        public FactorComplex(ComplexRing<C> fac) {
078            super(fac);
079            GenPolynomialRing<C> pfac = new GenPolynomialRing<C>(fac.ring, 1, new TermOrder(TermOrder.INVLEX),
080                    new String[] { "I" });
081            GenPolynomial<C> I = pfac.univariate(0, 2L).sum(pfac.getONE());
082            afac = new AlgebraicNumberRing<C>(I, true); // must indicate field
083            this.factorAlgeb = FactorFactory.<C> getImplementation(afac);
084        }
085    
086    
087        /**
088         * GenPolynomial base factorization of a squarefree polynomial.
089         * @param P squarefree GenPolynomial&lt;AlgebraicNumber&lt;C&gt;&gt;.
090         * @return [p_1,...,p_k] with P = prod_{i=1, ..., k} p_i.
091         */
092        @Override
093        public List<GenPolynomial<Complex<C>>> baseFactorsSquarefree(GenPolynomial<Complex<C>> P) {
094            if (P == null) {
095                throw new IllegalArgumentException(this.getClass().getName() + " P == null");
096            }
097            List<GenPolynomial<Complex<C>>> factors = new ArrayList<GenPolynomial<Complex<C>>>();
098            if (P.isZERO()) {
099                return factors;
100            }
101            if (P.isONE()) {
102                factors.add(P);
103                return factors;
104            }
105            GenPolynomialRing<Complex<C>> pfac = P.ring; // CC[x]
106            if (pfac.nvar > 1) {
107                throw new IllegalArgumentException("only for univariate polynomials");
108            }
109            ComplexRing<C> cfac = (ComplexRing<C>) pfac.coFac;
110            if (!afac.ring.coFac.equals(cfac.ring)) {
111                throw new IllegalArgumentException("coefficient rings do not match");
112            }
113            Complex<C> ldcf = P.leadingBaseCoefficient();
114            if (!ldcf.isONE()) {
115                P = P.monic();
116                factors.add(pfac.getONE().multiply(ldcf));
117            }
118            //System.out.println("\nP = " + P);
119            GenPolynomialRing<AlgebraicNumber<C>> pafac = new GenPolynomialRing<AlgebraicNumber<C>>(afac, pfac);
120            GenPolynomial<AlgebraicNumber<C>> A = PolyUtil.<C> algebraicFromComplex(pafac, P);
121            //System.out.println("A = " + A);
122            List<GenPolynomial<AlgebraicNumber<C>>> afactors = factorAlgeb.baseFactorsSquarefree(A);
123            if (debug) {
124                // System.out.println("complex afactors = " + afactors);
125                logger.info("complex afactors = " + afactors);
126            }
127            for (GenPolynomial<AlgebraicNumber<C>> pa : afactors) {
128                GenPolynomial<Complex<C>> pc = PolyUtil.<C> complexFromAlgebraic(pfac, pa);
129                factors.add(pc);
130            }
131            //System.out.println("cfactors = " + factors);
132            return factors;
133        }
134    
135    }