001/*
002 * $Id: RootFactory.java 5311 2015-10-25 22:28:29Z kredel $
003 */
004
005package edu.jas.root;
006
007
008import java.util.ArrayList;
009import java.util.List;
010import java.util.Set;
011import java.util.Map;
012
013import edu.jas.arith.Rational;
014import edu.jas.arith.BigRational;
015import edu.jas.poly.Complex;
016import edu.jas.poly.ComplexRing;
017import edu.jas.poly.PolyUtil;
018import edu.jas.poly.GenPolynomial;
019import edu.jas.poly.GenPolynomialRing;
020import edu.jas.structure.GcdRingElem;
021import edu.jas.ufd.FactorAbstract;
022import edu.jas.ufd.FactorFactory;
023import edu.jas.ufd.SquarefreeAbstract;
024import edu.jas.ufd.SquarefreeFactory;
025
026
027/**
028 * Roots factory.
029 * @author Heinz Kredel
030 */
031public class RootFactory {
032
033
034    /**
035     * Is real algebraic number a root of a polynomial.
036     * @param f univariate polynomial.
037     * @param r real algebraic number.
038     * @return true, if f(r) == 0, else false;
039     */
040    public static <C extends GcdRingElem<C> & Rational> 
041           boolean isRoot(GenPolynomial<C> f, RealAlgebraicNumber<C> r) {
042        RealAlgebraicRing<C> rr = r.factory(); 
043        GenPolynomialRing<RealAlgebraicNumber<C>> rfac 
044           = new GenPolynomialRing<RealAlgebraicNumber<C>>(rr,f.factory());
045        GenPolynomial<RealAlgebraicNumber<C>> p;
046        p = PolyUtilRoot.<C> convertToRealCoefficients(rfac,f);
047        RealAlgebraicNumber<C> a = PolyUtil.<RealAlgebraicNumber<C>> evaluateMain(rr,p,r);
048        return a.isZERO();
049    }
050
051
052    /**
053     * Real algebraic numbers.
054     * @param f univariate polynomial.
055     * @return a list of different real algebraic numbers.
056     */
057    public static <C extends GcdRingElem<C> & Rational> 
058           List<RealAlgebraicNumber<C>> realAlgebraicNumbers(GenPolynomial<C> f) {
059        RealRoots<C> rr = new RealRootsSturm<C>();
060        SquarefreeAbstract<C> engine = SquarefreeFactory.<C> getImplementation(f.ring.coFac);
061        Map<GenPolynomial<C>,Long> SF = engine.squarefreeFactors(f);
062        //Set<GenPolynomial<C>> S = SF.keySet();
063        List<RealAlgebraicNumber<C>> list = new ArrayList<RealAlgebraicNumber<C>>();
064        for (Map.Entry<GenPolynomial<C>,Long> me : SF.entrySet()) {
065            GenPolynomial<C> sp = me.getKey();
066            List<Interval<C>> iv = rr.realRoots(sp);
067            for (Interval<C> I : iv) {
068                RealAlgebraicRing<C> rar = new RealAlgebraicRing<C>(sp, I);
069                RealAlgebraicNumber<C> rn = rar.getGenerator();
070                long mult = me.getValue();
071                for ( int i = 0; i < mult; i++ ) {
072                     list.add(rn);
073                }
074            }
075        }
076        return list;
077    }
078
079
080    /**
081     * Real algebraic numbers.
082     * @param f univariate polynomial.
083     * @param eps rational precision.
084     * @return a list of different real algebraic numbers.
085     */
086    public static <C extends GcdRingElem<C> & Rational> 
087           List<RealAlgebraicNumber<C>> realAlgebraicNumbers(GenPolynomial<C> f, BigRational eps) {
088        RealRoots<C> rr = new RealRootsSturm<C>();
089        SquarefreeAbstract<C> engine = SquarefreeFactory.<C> getImplementation(f.ring.coFac);
090        Map<GenPolynomial<C>,Long> SF = engine.squarefreeFactors(f);
091        //Set<GenPolynomial<C>> S = SF.keySet();
092        List<RealAlgebraicNumber<C>> list = new ArrayList<RealAlgebraicNumber<C>>();
093        for (Map.Entry<GenPolynomial<C>,Long> me : SF.entrySet()) {
094            GenPolynomial<C> sp = me.getKey();
095            List<Interval<C>> iv = rr.realRoots(sp,eps);
096            for (Interval<C> I : iv) {
097                RealAlgebraicRing<C> rar = new RealAlgebraicRing<C>(sp, I);
098                rar.setEps(eps);
099                RealAlgebraicNumber<C> rn = rar.getGenerator();
100                long mult = me.getValue();
101                for ( int i = 0; i < mult; i++ ) {
102                     list.add(rn);
103                }
104            }
105        }
106        return list;
107    }
108
109
110    /**
111     * Real algebraic numbers from a field.
112     * @param f univariate polynomial.
113     * @return a list of different real algebraic numbers from a field.
114     */
115    public static <C extends GcdRingElem<C> & Rational> 
116           List<RealAlgebraicNumber<C>> realAlgebraicNumbersField(GenPolynomial<C> f) {
117        RealRoots<C> rr = new RealRootsSturm<C>();
118        FactorAbstract<C> engine = FactorFactory.<C> getImplementation(f.ring.coFac);
119        Map<GenPolynomial<C>,Long> SF = engine.baseFactors(f);
120        //Set<GenPolynomial<C>> S = SF.keySet();
121        List<RealAlgebraicNumber<C>> list = new ArrayList<RealAlgebraicNumber<C>>();
122        for (Map.Entry<GenPolynomial<C>,Long> me : SF.entrySet()) {
123            GenPolynomial<C> sp = me.getKey();
124            List<Interval<C>> iv = rr.realRoots(sp);
125            for (Interval<C> I : iv) {
126                RealAlgebraicRing<C> rar = new RealAlgebraicRing<C>(sp, I, true);//field
127                RealAlgebraicNumber<C> rn = rar.getGenerator();
128                long mult = me.getValue();
129                for ( int i = 0; i < mult; i++ ) {
130                     list.add(rn);
131                }
132            }
133        }
134        return list;
135    }
136
137
138    /**
139     * Real algebraic numbers from a field.
140     * @param f univariate polynomial.
141     * @param eps rational precision.
142     * @return a list of different real algebraic numbers from a field.
143     */
144    public static <C extends GcdRingElem<C> & Rational> 
145           List<RealAlgebraicNumber<C>> realAlgebraicNumbersField(GenPolynomial<C> f, BigRational eps) {
146        RealRoots<C> rr = new RealRootsSturm<C>();
147        FactorAbstract<C> engine = FactorFactory.<C> getImplementation(f.ring.coFac);
148        Map<GenPolynomial<C>,Long> SF = engine.baseFactors(f);
149        //Set<GenPolynomial<C>> S = SF.keySet();
150        List<RealAlgebraicNumber<C>> list = new ArrayList<RealAlgebraicNumber<C>>();
151        for (Map.Entry<GenPolynomial<C>,Long> me : SF.entrySet()) {
152            GenPolynomial<C> sp = me.getKey();
153            List<Interval<C>> iv = rr.realRoots(sp,eps);
154            for (Interval<C> I : iv) {
155                RealAlgebraicRing<C> rar = new RealAlgebraicRing<C>(sp, I, true);//field
156                rar.setEps(eps);
157                RealAlgebraicNumber<C> rn = rar.getGenerator();
158                long mult = me.getValue();
159                for ( int i = 0; i < mult; i++ ) {
160                     list.add(rn);
161                }
162            }
163        }
164        return list;
165    }
166
167
168    /**
169     * Real algebraic numbers from a irreducible polynomial.
170     * @param f univariate irreducible polynomial.
171     * @return a list of different real algebraic numbers from a field.
172     */
173    public static <C extends GcdRingElem<C> & Rational> 
174           List<RealAlgebraicNumber<C>> realAlgebraicNumbersIrred(GenPolynomial<C> f) {
175        RealRoots<C> rr = new RealRootsSturm<C>();
176        List<RealAlgebraicNumber<C>> list = new ArrayList<RealAlgebraicNumber<C>>();
177        List<Interval<C>> iv = rr.realRoots(f);
178        for (Interval<C> I : iv) {
179            RealAlgebraicRing<C> rar = new RealAlgebraicRing<C>(f, I, true);//field
180            RealAlgebraicNumber<C> rn = rar.getGenerator();
181            list.add(rn);
182        }
183        return list;
184    }
185
186
187    /**
188     * Real algebraic numbers from a irreducible polynomial.
189     * @param f univariate irreducible polynomial.
190     * @param eps rational precision.
191     * @return a list of different real algebraic numbers from a field.
192     */
193    public static <C extends GcdRingElem<C> & Rational> 
194           List<RealAlgebraicNumber<C>> realAlgebraicNumbersIrred(GenPolynomial<C> f, BigRational eps) {
195        RealRoots<C> rr = new RealRootsSturm<C>();
196        List<RealAlgebraicNumber<C>> list = new ArrayList<RealAlgebraicNumber<C>>();
197        List<Interval<C>> iv = rr.realRoots(f,eps);
198        for (Interval<C> I : iv) {
199            RealAlgebraicRing<C> rar = new RealAlgebraicRing<C>(f, I, true);//field
200            rar.setEps(eps);
201            RealAlgebraicNumber<C> rn = rar.getGenerator();
202            list.add(rn);
203        }
204        return list;
205    }
206
207
208    /**
209     * Is complex algebraic number a root of a polynomial.
210     * @param f univariate polynomial.
211     * @param r complex algebraic number.
212     * @return true, if f(r) == 0, else false;
213     */
214    public static <C extends GcdRingElem<C> & Rational> 
215           boolean isRoot(GenPolynomial<C> f, ComplexAlgebraicNumber<C> r) {
216        ComplexAlgebraicRing<C> cr = r.factory(); 
217        GenPolynomialRing<ComplexAlgebraicNumber<C>> cfac 
218           = new GenPolynomialRing<ComplexAlgebraicNumber<C>>(cr,f.factory());
219        GenPolynomial<ComplexAlgebraicNumber<C>> p;
220        p = PolyUtilRoot.<C> convertToComplexCoefficients(cfac,f);
221        ComplexAlgebraicNumber<C> a = PolyUtil.<ComplexAlgebraicNumber<C>> evaluateMain(cr,p,r);
222        return a.isZERO();
223    }
224
225
226    /**
227     * Is complex algebraic number a root of a complex polynomial.
228     * @param f univariate complex polynomial.
229     * @param r complex algebraic number.
230     * @return true, if f(r) == 0, else false;
231     */
232    public static <C extends GcdRingElem<C> & Rational> 
233           boolean isRootComplex(GenPolynomial<Complex<C>> f, ComplexAlgebraicNumber<C> r) {
234        ComplexAlgebraicRing<C> cr = r.factory(); 
235        GenPolynomialRing<ComplexAlgebraicNumber<C>> cfac 
236           = new GenPolynomialRing<ComplexAlgebraicNumber<C>>(cr,f.factory());
237        GenPolynomial<ComplexAlgebraicNumber<C>> p;
238        p = PolyUtilRoot.<C> convertToComplexCoefficientsFromComplex(cfac,f);
239        ComplexAlgebraicNumber<C> a = PolyUtil.<ComplexAlgebraicNumber<C>> evaluateMain(cr,p,r);
240        return a.isZERO();
241    }
242
243
244    /**
245     * Complex algebraic numbers.
246     * @param f univariate polynomial.
247     * @return a list of different complex algebraic numbers.
248     */
249    public static <C extends GcdRingElem<C> & Rational> 
250           List<ComplexAlgebraicNumber<C>> complexAlgebraicNumbersComplex(GenPolynomial<Complex<C>> f) {
251        ComplexRoots<C> cr = new ComplexRootsSturm<C>(f.ring.coFac);
252        SquarefreeAbstract<Complex<C>> engine = SquarefreeFactory
253                .<Complex<C>> getImplementation(f.ring.coFac);
254        Map<GenPolynomial<Complex<C>>,Long> SF = engine.squarefreeFactors(f);
255        //Set<GenPolynomial<Complex<C>>> S = SF.keySet();
256        List<ComplexAlgebraicNumber<C>> list = new ArrayList<ComplexAlgebraicNumber<C>>();
257        for (Map.Entry<GenPolynomial<Complex<C>>,Long> me : SF.entrySet()) {
258            GenPolynomial<Complex<C>> sp = me.getKey();
259            List<Rectangle<C>> iv = cr.complexRoots(sp);
260            for (Rectangle<C> I : iv) {
261                ComplexAlgebraicRing<C> car = new ComplexAlgebraicRing<C>(sp, I);
262                ComplexAlgebraicNumber<C> cn = car.getGenerator();
263                long mult = me.getValue();
264                for ( int i = 0; i < mult; i++ ) {
265                     list.add(cn);
266                }
267            }
268        }
269        return list;
270    }
271
272
273    /**
274     * Complex algebraic numbers.
275     * @param f univariate polynomial.
276     * @param eps rational precision.
277     * @return a list of different complex algebraic numbers.
278     */
279    public static <C extends GcdRingElem<C> & Rational> 
280           List<ComplexAlgebraicNumber<C>> complexAlgebraicNumbersComplex(GenPolynomial<Complex<C>> f, BigRational eps) {
281        ComplexRoots<C> cr = new ComplexRootsSturm<C>(f.ring.coFac);
282        SquarefreeAbstract<Complex<C>> engine = SquarefreeFactory
283                .<Complex<C>> getImplementation(f.ring.coFac);
284        Map<GenPolynomial<Complex<C>>,Long> SF = engine.squarefreeFactors(f);
285        //Set<GenPolynomial<Complex<C>>> S = SF.keySet();
286        List<ComplexAlgebraicNumber<C>> list = new ArrayList<ComplexAlgebraicNumber<C>>();
287        for (Map.Entry<GenPolynomial<Complex<C>>,Long> me : SF.entrySet()) {
288            GenPolynomial<Complex<C>> sp = me.getKey();
289            List<Rectangle<C>> iv = cr.complexRoots(sp);
290            for (Rectangle<C> I : iv) {
291                Rectangle<C> Iv = I;
292                try {
293                    Iv = cr.complexRootRefinement(I,sp,eps);
294                } catch (InvalidBoundaryException e) {
295                    e.printStackTrace();
296                }
297                ComplexAlgebraicRing<C> car = new ComplexAlgebraicRing<C>(sp, Iv);
298                car.setEps(eps);
299                ComplexAlgebraicNumber<C> cn = car.getGenerator();
300                long mult = me.getValue();
301                for ( int i = 0; i < mult; i++ ) {
302                     list.add(cn);
303                }
304            }
305        }
306        return list;
307    }
308
309
310    /**
311     * Complex algebraic numbers.
312     * @param f univariate (rational) polynomial.
313     * @return a list of different complex algebraic numbers.
314     */
315    public static <C extends GcdRingElem<C> & Rational> 
316           List<ComplexAlgebraicNumber<C>> complexAlgebraicNumbers(GenPolynomial<C> f) {
317        if ( f.ring.coFac instanceof Complex ) {
318            throw new IllegalArgumentException("f already has Complex coefficients " + f.ring);
319        }
320        if ( f.ring.coFac instanceof ComplexAlgebraicRing ) {
321            throw new UnsupportedOperationException("unsupported ComplexAlgebraicRing coefficients " + f.ring);
322        }
323        ComplexRing<C> cr = new ComplexRing<C>( f.ring.coFac );
324        GenPolynomialRing<Complex<C>> fac = new GenPolynomialRing<Complex<C>>(cr,f.ring);
325        GenPolynomial<Complex<C>> fc = PolyUtil.<C>complexFromAny(fac,f); 
326        return complexAlgebraicNumbersComplex(fc);
327    }
328
329
330    /**
331     * Complex algebraic numbers.
332     * @param f univariate (rational) polynomial.
333     * @param eps rational precision.
334     * @return a list of different complex algebraic numbers.
335     */
336    public static <C extends GcdRingElem<C> & Rational> 
337                             List<ComplexAlgebraicNumber<C>> complexAlgebraicNumbers(GenPolynomial<C> f, BigRational eps) {
338        if ( f.ring.coFac instanceof Complex ) {
339            throw new IllegalArgumentException("f already has Complex coefficients " + f.ring);
340        }
341        if ( f.ring.coFac instanceof ComplexAlgebraicRing ) {
342            throw new UnsupportedOperationException("unsupported ComplexAlgebraicRing coefficients " + f.ring);
343        }
344        ComplexRing<C> cr = new ComplexRing<C>( f.ring.coFac );
345        GenPolynomialRing<Complex<C>> fac = new GenPolynomialRing<Complex<C>>(cr,f.ring);
346        GenPolynomial<Complex<C>> fc = PolyUtil.<C>complexFromAny(fac,f); 
347        return complexAlgebraicNumbersComplex(fc,eps);
348    }
349
350}