001    /*
002     * $Id: GCDProxy.java 3222 2010-07-10 14:41:18Z kredel $
003     */
004    
005    package edu.jas.ufd;
006    
007    
008    import java.util.ArrayList;
009    import java.util.List;
010    import java.util.concurrent.Callable;
011    import java.util.concurrent.ExecutionException;
012    import java.util.concurrent.ExecutorService;
013    
014    import org.apache.log4j.Logger;
015    
016    import edu.jas.kern.ComputerThreads;
017    import edu.jas.kern.PreemptingException;
018    import edu.jas.poly.GenPolynomial;
019    import edu.jas.structure.GcdRingElem;
020    
021    
022    /**
023     * Greatest common divisor parallel proxy.
024     * @author Heinz Kredel
025     */
026    
027    public class GCDProxy<C extends GcdRingElem<C>> extends GreatestCommonDivisorAbstract<C> {
028    
029    
030        //       implements GreatestCommonDivisor<C> {
031    
032        private static final Logger logger = Logger.getLogger(GCDProxy.class);
033    
034    
035        private final boolean debug = logger.isDebugEnabled(); //logger.isInfoEnabled();
036    
037    
038        /**
039         * GCD engines.
040         */
041        public final GreatestCommonDivisorAbstract<C> e1;
042    
043    
044        public final GreatestCommonDivisorAbstract<C> e2;
045    
046    
047        /**
048         * Thread pool.
049         */
050        protected ExecutorService pool;
051    
052    
053        /**
054         * Proxy constructor.
055         */
056        public GCDProxy(GreatestCommonDivisorAbstract<C> e1, GreatestCommonDivisorAbstract<C> e2) {
057            this.e1 = e1;
058            this.e2 = e2;
059            if (pool == null) {
060                pool = ComputerThreads.getPool();
061                //System.out.println("pool 2 = "+pool);
062            }
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. Uses pseudoRemainder for
078         * remainder.
079         * @param P univariate GenPolynomial.
080         * @param S univariate GenPolynomial.
081         * @return gcd(P,S).
082         */
083        @Override
084        public GenPolynomial<C> baseGcd(final GenPolynomial<C> P, final GenPolynomial<C> S) {
085            if ( debug ) {
086                if ( ComputerThreads.NO_THREADS ) {
087                    throw new RuntimeException("this should not happen");
088                }
089            }
090            if (S == null || S.isZERO()) {
091                return P;
092            }
093            if (P == null || P.isZERO()) {
094                return S;
095            }
096            // parallel case
097            GenPolynomial<C> g = null;
098            //Callable<GenPolynomial<C>> c0;
099            //Callable<GenPolynomial<C>> c1;
100            List<Callable<GenPolynomial<C>>> cs = new ArrayList<Callable<GenPolynomial<C>>>(2);
101            cs.add(new Callable<GenPolynomial<C>>() {
102    
103    
104                public GenPolynomial<C> call() {
105                    try {
106                        //System.out.println("starting e1 " + e1.getClass().getName());
107                        GenPolynomial<C> g = e1.baseGcd(P, S);
108                        if (debug) {
109                            logger.info("GCDProxy done e1 " + e1.getClass().getName());
110                        }
111                        return g;
112                    } catch (PreemptingException e) {
113                        throw new RuntimeException("GCDProxy e1 pre " + e);
114                        //return P.ring.getONE();
115                    } catch (Exception e) {
116                        //e.printStackTrace();
117                        logger.info("GCDProxy e1 " + e);
118                        logger.info("GCDProxy P = " + P);
119                        logger.info("GCDProxy S = " + S);
120                        throw new RuntimeException("GCDProxy e1 " + e);
121                        //return P.ring.getONE();
122                    }
123                }
124            });
125            cs.add(new Callable<GenPolynomial<C>>() {
126    
127    
128                public GenPolynomial<C> call() {
129                    try {
130                        //System.out.println("starting e2 " + e2.getClass().getName());
131                        GenPolynomial<C> g = e2.baseGcd(P, S);
132                        if (debug) {
133                            logger.info("GCDProxy done e2 " + e2.getClass().getName());
134                        }
135                        return g;
136                    } catch (PreemptingException e) {
137                        throw new RuntimeException("GCDProxy e2 pre " + e);
138                        //return P.ring.getONE();
139                    } catch (Exception e) {
140                        //e.printStackTrace();
141                        logger.info("GCDProxy e2 " + e);
142                        logger.info("GCDProxy P = " + P);
143                        logger.info("GCDProxy S = " + S);
144                        throw new RuntimeException("GCDProxy e2 " + e);
145                        //return P.ring.getONE();
146                    }
147                }
148            });
149            try {
150                g = pool.invokeAny(cs);
151            } catch (InterruptedException ignored) {
152                logger.info("InterruptedException " + ignored);
153                Thread.currentThread().interrupt();
154            } catch (ExecutionException e) {
155                logger.info("ExecutionException " + e);
156                Thread.currentThread().interrupt();
157            }
158            return g;
159        }
160    
161    
162        /**
163         * Univariate GenPolynomial recursive greatest common divisor. Uses
164         * pseudoRemainder for remainder.
165         * @param P univariate recursive GenPolynomial.
166         * @param S univariate recursive GenPolynomial.
167         * @return gcd(P,S).
168         */
169        @Override
170        public GenPolynomial<GenPolynomial<C>> recursiveUnivariateGcd(final GenPolynomial<GenPolynomial<C>> P,
171                final GenPolynomial<GenPolynomial<C>> S) {
172            if ( debug ) {
173                if ( ComputerThreads.NO_THREADS ) {
174                    throw new RuntimeException("this should not happen");
175                }
176            }
177            if (S == null || S.isZERO()) {
178                return P;
179            }
180            if (P == null || P.isZERO()) {
181                return S;
182            }
183            // parallel case
184            GenPolynomial<GenPolynomial<C>> g = null;
185            //Callable<GenPolynomial<GenPolynomial<C>>> c0;
186            //Callable<GenPolynomial<GenPolynomial<C>>> c1;
187            List<Callable<GenPolynomial<GenPolynomial<C>>>> cs = new ArrayList<Callable<GenPolynomial<GenPolynomial<C>>>>(
188                    2);
189            cs.add(new Callable<GenPolynomial<GenPolynomial<C>>>() {
190    
191    
192                public GenPolynomial<GenPolynomial<C>> call() {
193                    try {
194                        GenPolynomial<GenPolynomial<C>> g = e1.recursiveUnivariateGcd(P, S);
195                        if (debug) {
196                            logger.info("GCDProxy done e1 " + e1.getClass().getName());
197                        }
198                        return g;
199                    } catch (PreemptingException e) {
200                        throw new RuntimeException("GCDProxy e1 pre " + e);
201                        //return P.ring.getONE();
202                    } catch (Exception e) {
203                        //e.printStackTrace();
204                        logger.info("GCDProxy e1 " + e);
205                        logger.info("GCDProxy P = " + P);
206                        logger.info("GCDProxy S = " + S);
207                        throw new RuntimeException("GCDProxy e1 " + e);
208                        //return P.ring.getONE();
209                    }
210                }
211            });
212            cs.add(new Callable<GenPolynomial<GenPolynomial<C>>>() {
213    
214    
215                public GenPolynomial<GenPolynomial<C>> call() {
216                    try {
217                        GenPolynomial<GenPolynomial<C>> g = e2.recursiveUnivariateGcd(P, S);
218                        if (debug) {
219                            logger.info("GCDProxy done e2 " + e2.getClass().getName());
220                        }
221                        return g;
222                    } catch (PreemptingException e) {
223                        throw new RuntimeException("GCDProxy e2 pre " + e);
224                        //return P.ring.getONE();
225                    } catch (Exception e) {
226                        //e.printStackTrace();
227                        logger.info("GCDProxy e2 " + e);
228                        logger.info("GCDProxy P = " + P);
229                        logger.info("GCDProxy S = " + S);
230                        throw new RuntimeException("GCDProxy e2 " + e);
231                        //return P.ring.getONE();
232                    }
233                }
234            });
235            try {
236                g = pool.invokeAny(cs);
237            } catch (InterruptedException ignored) {
238                logger.info("InterruptedException " + ignored);
239                Thread.currentThread().interrupt();
240            } catch (ExecutionException e) {
241                logger.info("ExecutionException " + e);
242                Thread.currentThread().interrupt();
243            }
244            return g;
245        }
246    
247    
248        /**
249         * GenPolynomial greatest common divisor. Main entry driver method.
250         * @param P GenPolynomial.
251         * @param S GenPolynomial.
252         * @return gcd(P,S).
253         */
254        @Override
255        public GenPolynomial<C> gcd(final GenPolynomial<C> P, final GenPolynomial<C> S) {
256            if ( debug ) {
257                if ( ComputerThreads.NO_THREADS ) {
258                    throw new RuntimeException("this should not happen");
259                }
260            }
261            if (S == null || S.isZERO()) {
262                return P;
263            }
264            if (P == null || P.isZERO()) {
265                return S;
266            }
267            // parallel case
268            GenPolynomial<C> g = null;
269            //Callable<GenPolynomial<C>> c0;
270            //Callable<GenPolynomial<C>> c1;
271            List<Callable<GenPolynomial<C>>> cs = new ArrayList<Callable<GenPolynomial<C>>>(2);
272            cs.add(new Callable<GenPolynomial<C>>() {
273    
274    
275                public GenPolynomial<C> call() {
276                    try {
277                        //System.out.println("starting e1 " + e1.getClass().getName());
278                        GenPolynomial<C> g = e1.gcd(P, S);
279                        if (debug) {
280                            logger.info("GCDProxy done e1 " + e1.getClass().getName());
281                        }
282                        return g;
283                    } catch (PreemptingException e) {
284                        throw new RuntimeException("GCDProxy e1 pre " + e);
285                        //return P.ring.getONE();
286                    } catch (Exception e) {
287                        //e.printStackTrace();
288                        logger.info("GCDProxy e1 " + e);
289                        logger.info("GCDProxy P = " + P);
290                        logger.info("GCDProxy S = " + S);
291                        throw new RuntimeException("GCDProxy e1 " + e);
292                        //return P.ring.getONE();
293                    }
294                }
295            });
296            cs.add(new Callable<GenPolynomial<C>>() {
297    
298    
299                public GenPolynomial<C> call() {
300                    try {
301                        //System.out.println("starting e2 " + e2.getClass().getName());
302                        GenPolynomial<C> g = e2.gcd(P, S);
303                        if (debug) {
304                            logger.info("GCDProxy done e2 " + e2.getClass().getName());
305                        }
306                        return g;
307                    } catch (PreemptingException e) {
308                        throw new RuntimeException("GCDProxy e2 pre " + e);
309                        //return P.ring.getONE();
310                    } catch (Exception e) {
311                        //e.printStackTrace();
312                        logger.info("GCDProxy e2 " + e);
313                        logger.info("GCDProxy P = " + P);
314                        logger.info("GCDProxy S = " + S);
315                        throw new RuntimeException("GCDProxy e2 " + e);
316                        //return P.ring.getONE();
317                    }
318                }
319            });
320            try {
321                g = pool.invokeAny(cs);
322            } catch (InterruptedException ignored) {
323                logger.info("InterruptedException " + ignored);
324                Thread.currentThread().interrupt();
325            } catch (ExecutionException e) {
326                logger.info("ExecutionException " + e);
327                Thread.currentThread().interrupt();
328            }
329            return g;
330        }
331    
332    }