001/*
002 * $Id: GCDProxy.java 4045 2012-07-25 16:48:23Z kredel $
003 */
004
005package edu.jas.ufd;
006
007
008import java.util.ArrayList;
009import java.util.List;
010import java.util.concurrent.Callable;
011import java.util.concurrent.ExecutionException;
012import java.util.concurrent.ExecutorService;
013
014import org.apache.log4j.Logger;
015
016import edu.jas.kern.ComputerThreads;
017import edu.jas.kern.PreemptingException;
018import edu.jas.poly.GenPolynomial;
019import edu.jas.structure.GcdRingElem;
020
021
022/**
023 * Greatest common divisor parallel proxy.  
024 * Executes methods from two implementations in parallel and 
025 * returns the result from the fastest run.
026 * @author Heinz Kredel
027 */
028
029public class GCDProxy<C extends GcdRingElem<C>> extends GreatestCommonDivisorAbstract<C> {
030
031
032    //       implements GreatestCommonDivisor<C> {
033
034    private static final Logger logger = Logger.getLogger(GCDProxy.class);
035
036
037    private final boolean debug = logger.isDebugEnabled(); //logger.isInfoEnabled();
038
039
040    /**
041     * GCD and resultant engines.
042     */
043    public final GreatestCommonDivisorAbstract<C> e1;
044
045
046    public final GreatestCommonDivisorAbstract<C> e2;
047
048
049    /**
050     * Thread pool.
051     */
052    protected transient ExecutorService pool;
053
054
055    /**
056     * Proxy constructor.
057     */
058    public GCDProxy(GreatestCommonDivisorAbstract<C> e1, GreatestCommonDivisorAbstract<C> e2) {
059        this.e1 = e1;
060        this.e2 = e2;
061        pool = ComputerThreads.getPool();
062        //System.out.println("pool 2 = "+pool);
063    }
064
065
066    /**
067     * Get the String representation with gcd engines.
068     * @see java.lang.Object#toString()
069     */
070    @Override
071    public String toString() {
072        return "GCDProxy[ " + e1.getClass().getName() + ", " + e2.getClass().getName() + " ]";
073    }
074
075
076    /**
077     * Univariate GenPolynomial greatest common divisor. 
078     * @param P univariate GenPolynomial.
079     * @param S univariate GenPolynomial.
080     * @return gcd(P,S).
081     */
082    @Override
083    public GenPolynomial<C> baseGcd(final GenPolynomial<C> P, final GenPolynomial<C> S) {
084        if ( debug ) {
085            if ( ComputerThreads.NO_THREADS ) {
086                throw new RuntimeException("this should not happen");
087            }
088        }
089        if (S == null || S.isZERO()) {
090            return P;
091        }
092        if (P == null || P.isZERO()) {
093            return S;
094        }
095        // parallel case
096        GenPolynomial<C> g = null;
097        //Callable<GenPolynomial<C>> c0;
098        //Callable<GenPolynomial<C>> c1;
099        List<Callable<GenPolynomial<C>>> cs = new ArrayList<Callable<GenPolynomial<C>>>(2);
100        cs.add(new Callable<GenPolynomial<C>>() {
101
102
103            public GenPolynomial<C> call() {
104                try {
105                    //System.out.println("starting e1 " + e1.getClass().getName());
106                    GenPolynomial<C> g = e1.baseGcd(P, S);
107                    if (debug) {
108                        logger.info("GCDProxy done e1 " + e1.getClass().getName());
109                    }
110                    return g;
111                } catch (PreemptingException e) {
112                    throw new RuntimeException("GCDProxy e1 pre " + e);
113                    //return P.ring.getONE();
114                } catch (Exception e) {
115                    //e.printStackTrace();
116                    logger.info("GCDProxy e1 " + e);
117                    logger.info("GCDProxy P = " + P);
118                    logger.info("GCDProxy S = " + S);
119                    throw new RuntimeException("GCDProxy e1 " + e);
120                    //return P.ring.getONE();
121                }
122            }
123        });
124        cs.add(new Callable<GenPolynomial<C>>() {
125
126
127            public GenPolynomial<C> call() {
128                try {
129                    //System.out.println("starting e2 " + e2.getClass().getName());
130                    GenPolynomial<C> g = e2.baseGcd(P, S);
131                    if (debug) {
132                        logger.info("GCDProxy done e2 " + e2.getClass().getName());
133                    }
134                    return g;
135                } catch (PreemptingException e) {
136                    throw new RuntimeException("GCDProxy e2 pre " + e);
137                    //return P.ring.getONE();
138                } catch (Exception e) {
139                    //e.printStackTrace();
140                    logger.info("GCDProxy e2 " + e);
141                    logger.info("GCDProxy P = " + P);
142                    logger.info("GCDProxy S = " + S);
143                    throw new RuntimeException("GCDProxy e2 " + e);
144                    //return P.ring.getONE();
145                }
146            }
147        });
148        try {
149            g = pool.invokeAny(cs);
150        } catch (InterruptedException ignored) {
151            logger.info("InterruptedException " + ignored);
152            Thread.currentThread().interrupt();
153        } catch (ExecutionException e) {
154            logger.info("ExecutionException " + e);
155            Thread.currentThread().interrupt();
156        }
157        return g;
158    }
159
160
161    /**
162     * Univariate GenPolynomial recursive greatest common divisor.
163     * @param P univariate recursive GenPolynomial.
164     * @param S univariate recursive GenPolynomial.
165     * @return gcd(P,S).
166     */
167    @Override
168    public GenPolynomial<GenPolynomial<C>> recursiveUnivariateGcd(final GenPolynomial<GenPolynomial<C>> P,
169            final GenPolynomial<GenPolynomial<C>> S) {
170        if ( debug ) {
171            if ( ComputerThreads.NO_THREADS ) {
172                throw new RuntimeException("this should not happen");
173            }
174        }
175        if (S == null || S.isZERO()) {
176            return P;
177        }
178        if (P == null || P.isZERO()) {
179            return S;
180        }
181        // parallel case
182        GenPolynomial<GenPolynomial<C>> g = null;
183        //Callable<GenPolynomial<GenPolynomial<C>>> c0;
184        //Callable<GenPolynomial<GenPolynomial<C>>> c1;
185        List<Callable<GenPolynomial<GenPolynomial<C>>>> cs = new ArrayList<Callable<GenPolynomial<GenPolynomial<C>>>>(
186                2);
187        cs.add(new Callable<GenPolynomial<GenPolynomial<C>>>() {
188
189
190            public GenPolynomial<GenPolynomial<C>> call() {
191                try {
192                    GenPolynomial<GenPolynomial<C>> g = e1.recursiveUnivariateGcd(P, S);
193                    if (debug) {
194                        logger.info("GCDProxy done e1 " + e1.getClass().getName());
195                    }
196                    return g;
197                } catch (PreemptingException e) {
198                    throw new RuntimeException("GCDProxy e1 pre " + e);
199                    //return P.ring.getONE();
200                } catch (Exception e) {
201                    //e.printStackTrace();
202                    logger.info("GCDProxy e1 " + e);
203                    logger.info("GCDProxy P = " + P);
204                    logger.info("GCDProxy S = " + S);
205                    throw new RuntimeException("GCDProxy e1 " + e);
206                    //return P.ring.getONE();
207                }
208            }
209        });
210        cs.add(new Callable<GenPolynomial<GenPolynomial<C>>>() {
211
212
213            public GenPolynomial<GenPolynomial<C>> call() {
214                try {
215                    GenPolynomial<GenPolynomial<C>> g = e2.recursiveUnivariateGcd(P, S);
216                    if (debug) {
217                        logger.info("GCDProxy done e2 " + e2.getClass().getName());
218                    }
219                    return g;
220                } catch (PreemptingException e) {
221                    throw new RuntimeException("GCDProxy e2 pre " + e);
222                    //return P.ring.getONE();
223                } catch (Exception e) {
224                    //e.printStackTrace();
225                    logger.info("GCDProxy e2 " + e);
226                    logger.info("GCDProxy P = " + P);
227                    logger.info("GCDProxy S = " + S);
228                    throw new RuntimeException("GCDProxy e2 " + e);
229                    //return P.ring.getONE();
230                }
231            }
232        });
233        try {
234            g = pool.invokeAny(cs);
235        } catch (InterruptedException ignored) {
236            logger.info("InterruptedException " + ignored);
237            Thread.currentThread().interrupt();
238        } catch (ExecutionException e) {
239            logger.info("ExecutionException " + e);
240            Thread.currentThread().interrupt();
241        }
242        return g;
243    }
244
245
246    /**
247     * GenPolynomial greatest common divisor. 
248     * @param P GenPolynomial.
249     * @param S GenPolynomial.
250     * @return gcd(P,S).
251     */
252    @Override
253    public GenPolynomial<C> gcd(final GenPolynomial<C> P, final GenPolynomial<C> S) {
254        if ( debug ) {
255            if ( ComputerThreads.NO_THREADS ) {
256                throw new RuntimeException("this should not happen");
257            }
258        }
259        if (S == null || S.isZERO()) {
260            return P;
261        }
262        if (P == null || P.isZERO()) {
263            return S;
264        }
265        // parallel case
266        GenPolynomial<C> g = null;
267        //Callable<GenPolynomial<C>> c0;
268        //Callable<GenPolynomial<C>> c1;
269        List<Callable<GenPolynomial<C>>> cs = new ArrayList<Callable<GenPolynomial<C>>>(2);
270        cs.add(new Callable<GenPolynomial<C>>() {
271
272
273            public GenPolynomial<C> call() {
274                try {
275                    //System.out.println("starting e1 " + e1.getClass().getName());
276                    GenPolynomial<C> g = e1.gcd(P, S);
277                    if (debug) {
278                        logger.info("GCDProxy done e1 " + e1.getClass().getName());
279                    }
280                    return g;
281                } catch (PreemptingException e) {
282                    throw new RuntimeException("GCDProxy e1 pre " + e);
283                    //return P.ring.getONE();
284                } catch (Exception e) {
285                    //e.printStackTrace();
286                    logger.info("GCDProxy e1 " + e);
287                    logger.info("GCDProxy P = " + P);
288                    logger.info("GCDProxy S = " + S);
289                    throw new RuntimeException("GCDProxy e1 " + e);
290                    //return P.ring.getONE();
291                }
292            }
293        });
294        cs.add(new Callable<GenPolynomial<C>>() {
295
296
297            public GenPolynomial<C> call() {
298                try {
299                    //System.out.println("starting e2 " + e2.getClass().getName());
300                    GenPolynomial<C> g = e2.gcd(P, S);
301                    if (debug) {
302                        logger.info("GCDProxy done e2 " + e2.getClass().getName());
303                    }
304                    return g;
305                } catch (PreemptingException e) {
306                    throw new RuntimeException("GCDProxy e2 pre " + e);
307                    //return P.ring.getONE();
308                } catch (Exception e) {
309                    //e.printStackTrace();
310                    logger.info("GCDProxy e2 " + e);
311                    logger.info("GCDProxy P = " + P);
312                    logger.info("GCDProxy S = " + S);
313                    throw new RuntimeException("GCDProxy e2 " + e);
314                    //return P.ring.getONE();
315                }
316            }
317        });
318        try {
319            g = pool.invokeAny(cs);
320        } catch (InterruptedException ignored) {
321            logger.info("InterruptedException " + ignored);
322            Thread.currentThread().interrupt();
323        } catch (ExecutionException e) {
324            logger.info("ExecutionException " + e);
325            Thread.currentThread().interrupt();
326        }
327        return g;
328    }
329
330
331    /**
332     * Univariate GenPolynomial resultant. 
333     * @param P univariate GenPolynomial.
334     * @param S univariate GenPolynomial.
335     * @return res(P,S).
336     */
337    @Override
338    public GenPolynomial<C> baseResultant(final GenPolynomial<C> P, final GenPolynomial<C> S) {
339        if ( debug ) {
340            if ( ComputerThreads.NO_THREADS ) {
341                throw new RuntimeException("this should not happen");
342            }
343        }
344        if (S == null || S.isZERO()) {
345            return S;
346        }
347        if (P == null || P.isZERO()) {
348            return P;
349        }
350        // parallel case
351        GenPolynomial<C> g = null;
352        //Callable<GenPolynomial<C>> c0;
353        //Callable<GenPolynomial<C>> c1;
354        List<Callable<GenPolynomial<C>>> cs = new ArrayList<Callable<GenPolynomial<C>>>(2);
355        cs.add(new Callable<GenPolynomial<C>>() {
356
357
358            public GenPolynomial<C> call() {
359                try {
360                    //System.out.println("starting e1 " + e1.getClass().getName());
361                    GenPolynomial<C> g = e1.baseResultant(P, S);
362                    if (debug) {
363                        logger.info("GCDProxy done e1 " + e1.getClass().getName());
364                    }
365                    return g;
366                } catch (PreemptingException e) {
367                    throw new RuntimeException("GCDProxy e1 pre " + e);
368                    //return P.ring.getONE();
369                } catch (Exception e) {
370                    //e.printStackTrace();
371                    logger.info("GCDProxy e1 " + e);
372                    logger.info("GCDProxy P = " + P);
373                    logger.info("GCDProxy S = " + S);
374                    throw new RuntimeException("GCDProxy e1 " + e);
375                    //return P.ring.getONE();
376                }
377            }
378        });
379        cs.add(new Callable<GenPolynomial<C>>() {
380
381
382            public GenPolynomial<C> call() {
383                try {
384                    //System.out.println("starting e2 " + e2.getClass().getName());
385                    GenPolynomial<C> g = e2.baseResultant(P, S);
386                    if (debug) {
387                        logger.info("GCDProxy done e2 " + e2.getClass().getName());
388                    }
389                    return g;
390                } catch (PreemptingException e) {
391                    throw new RuntimeException("GCDProxy e2 pre " + e);
392                    //return P.ring.getONE();
393                } catch (Exception e) {
394                    //e.printStackTrace();
395                    logger.info("GCDProxy e2 " + e);
396                    logger.info("GCDProxy P = " + P);
397                    logger.info("GCDProxy S = " + S);
398                    throw new RuntimeException("GCDProxy e2 " + e);
399                    //return P.ring.getONE();
400                }
401            }
402        });
403        try {
404            g = pool.invokeAny(cs);
405        } catch (InterruptedException ignored) {
406            logger.info("InterruptedException " + ignored);
407            Thread.currentThread().interrupt();
408        } catch (ExecutionException e) {
409            logger.info("ExecutionException " + e);
410            Thread.currentThread().interrupt();
411        }
412        return g;
413    }
414
415
416    /**
417     * Univariate GenPolynomial resultant. 
418     * @param P univariate recursive GenPolynomial.
419     * @param S univariate recursive GenPolynomial.
420     * @return res(P,S).
421     */
422    @Override
423    public GenPolynomial<GenPolynomial<C>> recursiveUnivariateResultant(final GenPolynomial<GenPolynomial<C>> P,
424            final GenPolynomial<GenPolynomial<C>> S) {
425        if ( debug ) {
426            if ( ComputerThreads.NO_THREADS ) {
427                throw new RuntimeException("this should not happen");
428            }
429        }
430        if (S == null || S.isZERO()) {
431            return S;
432        }
433        if (P == null || P.isZERO()) {
434            return P;
435        }
436        // parallel case
437        GenPolynomial<GenPolynomial<C>> g = null;
438        //Callable<GenPolynomial<GenPolynomial<C>>> c0;
439        //Callable<GenPolynomial<GenPolynomial<C>>> c1;
440        List<Callable<GenPolynomial<GenPolynomial<C>>>> cs = new ArrayList<Callable<GenPolynomial<GenPolynomial<C>>>>(
441                2);
442        cs.add(new Callable<GenPolynomial<GenPolynomial<C>>>() {
443
444
445            public GenPolynomial<GenPolynomial<C>> call() {
446                try {
447                    GenPolynomial<GenPolynomial<C>> g = e1.recursiveUnivariateResultant(P, S);
448                    if (debug) {
449                        logger.info("GCDProxy done e1 " + e1.getClass().getName());
450                    }
451                    return g;
452                } catch (PreemptingException e) {
453                    throw new RuntimeException("GCDProxy e1 pre " + e);
454                    //return P.ring.getONE();
455                } catch (Exception e) {
456                    //e.printStackTrace();
457                    logger.info("GCDProxy e1 " + e);
458                    logger.info("GCDProxy P = " + P);
459                    logger.info("GCDProxy S = " + S);
460                    throw new RuntimeException("GCDProxy e1 " + e);
461                    //return P.ring.getONE();
462                }
463            }
464        });
465        cs.add(new Callable<GenPolynomial<GenPolynomial<C>>>() {
466
467
468            public GenPolynomial<GenPolynomial<C>> call() {
469                try {
470                    GenPolynomial<GenPolynomial<C>> g = e2.recursiveUnivariateResultant(P, S);
471                    if (debug) {
472                        logger.info("GCDProxy done e2 " + e2.getClass().getName());
473                    }
474                    return g;
475                } catch (PreemptingException e) {
476                    throw new RuntimeException("GCDProxy e2 pre " + e);
477                    //return P.ring.getONE();
478                } catch (Exception e) {
479                    //e.printStackTrace();
480                    logger.info("GCDProxy e2 " + e);
481                    logger.info("GCDProxy P = " + P);
482                    logger.info("GCDProxy S = " + S);
483                    throw new RuntimeException("GCDProxy e2 " + e);
484                    //return P.ring.getONE();
485                }
486            }
487        });
488        try {
489            g = pool.invokeAny(cs);
490        } catch (InterruptedException ignored) {
491            logger.info("InterruptedException " + ignored);
492            Thread.currentThread().interrupt();
493        } catch (ExecutionException e) {
494            logger.info("ExecutionException " + e);
495            Thread.currentThread().interrupt();
496        }
497        return g;
498    }
499
500
501    /**
502     * GenPolynomial resultant. Main entry driver method.
503     * @param P GenPolynomial.
504     * @param S GenPolynomial.
505     * @return res(P,S).
506     */
507    @Override
508    public GenPolynomial<C> resultant(final GenPolynomial<C> P, final GenPolynomial<C> S) {
509        if ( debug ) {
510            if ( ComputerThreads.NO_THREADS ) {
511                throw new RuntimeException("this should not happen");
512            }
513        }
514        if (S == null || S.isZERO()) {
515            return S;
516        }
517        if (P == null || P.isZERO()) {
518            return P;
519        }
520        // parallel case
521        GenPolynomial<C> g = null;
522        //Callable<GenPolynomial<C>> c0;
523        //Callable<GenPolynomial<C>> c1;
524        List<Callable<GenPolynomial<C>>> cs = new ArrayList<Callable<GenPolynomial<C>>>(2);
525        cs.add(new Callable<GenPolynomial<C>>() {
526
527
528            public GenPolynomial<C> call() {
529                try {
530                    //System.out.println("starting e1 " + e1.getClass().getName());
531                    GenPolynomial<C> g = e1.resultant(P, S);
532                    if (debug) {
533                        logger.info("GCDProxy done e1 " + e1.getClass().getName());
534                    }
535                    return g;
536                } catch (PreemptingException e) {
537                    throw new RuntimeException("GCDProxy e1 pre " + e);
538                    //return P.ring.getONE();
539                } catch (Exception e) {
540                    //e.printStackTrace();
541                    logger.info("GCDProxy e1 " + e);
542                    logger.info("GCDProxy P = " + P);
543                    logger.info("GCDProxy S = " + S);
544                    throw new RuntimeException("GCDProxy e1 " + e);
545                    //return P.ring.getONE();
546                }
547            }
548        });
549        cs.add(new Callable<GenPolynomial<C>>() {
550
551
552            public GenPolynomial<C> call() {
553                try {
554                    //System.out.println("starting e2 " + e2.getClass().getName());
555                    GenPolynomial<C> g = e2.resultant(P, S);
556                    if (debug) {
557                        logger.info("GCDProxy done e2 " + e2.getClass().getName());
558                    }
559                    return g;
560                } catch (PreemptingException e) {
561                    throw new RuntimeException("GCDProxy e2 pre " + e);
562                    //return P.ring.getONE();
563                } catch (Exception e) {
564                    //e.printStackTrace();
565                    logger.info("GCDProxy e2 " + e);
566                    logger.info("GCDProxy P = " + P);
567                    logger.info("GCDProxy S = " + S);
568                    throw new RuntimeException("GCDProxy e2 " + e);
569                    //return P.ring.getONE();
570                }
571            }
572        });
573        try {
574            g = pool.invokeAny(cs);
575        } catch (InterruptedException ignored) {
576            logger.info("InterruptedException " + ignored);
577            Thread.currentThread().interrupt();
578        } catch (ExecutionException e) {
579            logger.info("ExecutionException " + e);
580            Thread.currentThread().interrupt();
581        }
582        return g;
583    }
584
585}