001 /*
002 * $Id: GCDFactory.java 3676 2011-07-02 10:51:16Z kredel $
003 */
004
005 package edu.jas.ufd;
006
007
008 import org.apache.log4j.Logger;
009
010 import edu.jas.arith.BigInteger;
011 import edu.jas.arith.BigRational;
012 import edu.jas.arith.ModInteger;
013 import edu.jas.arith.ModIntegerRing;
014 import edu.jas.arith.ModLong;
015 import edu.jas.arith.ModLongRing;
016 import edu.jas.kern.ComputerThreads;
017 import edu.jas.structure.GcdRingElem;
018 import edu.jas.structure.RingFactory;
019
020
021 /**
022 * Greatest common divisor algorithms factory. Select appropriate GCD engine
023 * based on the coefficient types.
024 * @todo Base decision also an degree vectors and number of variables of
025 * polynomials. Incorporate also number of CPUs / threads available (done
026 * with GCDProxy).
027 * @author Heinz Kredel
028 * @usage To create objects that implement the
029 * <code>GreatestCommonDivisor</code> interface use the
030 * <code>GCDFactory</code>. It will select an appropriate implementation
031 * based on the types of polynomial coefficients C. There are two methods
032 * to obtain an implementation: <code>getProxy()</code> and
033 * <code>getImplementation()</code>. <code>getImplementation()</code>
034 * returns an object of a class which implements the
035 * <code>GreatestCommonDivisor</code> interface. <code>getProxy()</code>
036 * returns a proxy object of a class which implements the
037 * <code>GreatestCommonDivisor</code>r interface. The proxy will run two
038 * implementations in parallel, return the first computed result and
039 * cancel the second running task. On systems with one CPU the computing
040 * time will be two times the time of the fastest algorithm
041 * implmentation. On systems with more than two CPUs the computing time
042 * will be the time of the fastest algorithm implmentation.
043 *
044 * <pre>
045 * GreatestCommonDivisor<CT> engine;
046 * engine = GCDFactory.<CT> getImplementation(cofac);
047 * or engine = GCDFactory.<CT> getProxy(cofac);
048 * c = engine.gcd(a, b);
049 * </pre>
050 *
051 * For example, if the coefficient type is BigInteger, the usage looks
052 * like
053 *
054 * <pre>
055 * BigInteger cofac = new BigInteger();
056 * GreatestCommonDivisor<BigInteger> engine;
057 * engine = GCDFactory.getImplementation(cofac);
058 * or engine = GCDFactory.getProxy(cofac);
059 * c = engine.gcd(a, b);
060 * </pre>
061 *
062 * @see edu.jas.ufd.GreatestCommonDivisor#gcd(edu.jas.poly.GenPolynomial P,
063 * edu.jas.poly.GenPolynomial S)
064 */
065
066 public class GCDFactory {
067
068
069 private static final Logger logger = Logger.getLogger(GCDFactory.class);
070
071
072 /**
073 * Protected factory constructor.
074 */
075 protected GCDFactory() {
076 }
077
078
079 /**
080 * Determine suitable implementation of gcd algorithms, case ModLong.
081 * @param fac ModLongRing.
082 * @return gcd algorithm implementation.
083 */
084 public static GreatestCommonDivisorAbstract<ModLong> getImplementation(ModLongRing fac) {
085 GreatestCommonDivisorAbstract<ModLong> ufd;
086 if (fac.isField()) {
087 ufd = new GreatestCommonDivisorModEval<ModLong>();
088 return ufd;
089 }
090 ufd = new GreatestCommonDivisorSubres<ModLong>();
091 return ufd;
092 }
093
094
095 /**
096 * Determine suitable proxy for gcd algorithms, case ModLong.
097 * @param fac ModLongRing.
098 * @return gcd algorithm implementation.
099 */
100 public static GreatestCommonDivisorAbstract<ModLong> getProxy(ModLongRing fac) {
101 GreatestCommonDivisorAbstract<ModLong> ufd1, ufd2;
102 ufd1 = new GreatestCommonDivisorSubres<ModLong>();
103 if (fac.isField()) {
104 ufd2 = new GreatestCommonDivisorModEval<ModLong>();
105 } else {
106 ufd2 = new GreatestCommonDivisorSimple<ModLong>();
107 }
108 return new GCDProxy<ModLong>(ufd1, ufd2);
109 }
110
111
112 /**
113 * Determine suitable implementation of gcd algorithms, case ModInteger.
114 * @param fac ModIntegerRing.
115 * @return gcd algorithm implementation.
116 */
117 public static GreatestCommonDivisorAbstract<ModInteger> getImplementation(ModIntegerRing fac) {
118 GreatestCommonDivisorAbstract<ModInteger> ufd;
119 if (fac.isField()) {
120 ufd = new GreatestCommonDivisorModEval<ModInteger>();
121 return ufd;
122 }
123 ufd = new GreatestCommonDivisorSubres<ModInteger>();
124 return ufd;
125 }
126
127
128 /**
129 * Determine suitable proxy for gcd algorithms, case ModInteger.
130 * @param fac ModIntegerRing.
131 * @return gcd algorithm implementation.
132 */
133 public static GreatestCommonDivisorAbstract<ModInteger> getProxy(ModIntegerRing fac) {
134 GreatestCommonDivisorAbstract<ModInteger> ufd1, ufd2;
135 ufd1 = new GreatestCommonDivisorSubres<ModInteger>();
136 if (fac.isField()) {
137 ufd2 = new GreatestCommonDivisorModEval<ModInteger>();
138 } else {
139 ufd2 = new GreatestCommonDivisorSimple<ModInteger>();
140 }
141 return new GCDProxy<ModInteger>(ufd1, ufd2);
142 }
143
144
145 /**
146 * Determine suitable implementation of gcd algorithms, case BigInteger.
147 * @param fac BigInteger.
148 * @return gcd algorithm implementation.
149 */
150 public static GreatestCommonDivisorAbstract<BigInteger> getImplementation(BigInteger fac) {
151 GreatestCommonDivisorAbstract<BigInteger> ufd;
152 if (true) {
153 ufd = new GreatestCommonDivisorModular<ModLong>(); // dummy type
154 } else {
155 ufd = new GreatestCommonDivisorSubres<BigInteger>();
156 }
157 return ufd;
158 }
159
160
161 /**
162 * Determine suitable procy for gcd algorithms, case BigInteger.
163 * @param fac BigInteger.
164 * @return gcd algorithm implementation.
165 */
166 public static GreatestCommonDivisorAbstract<BigInteger> getProxy(BigInteger fac) {
167 GreatestCommonDivisorAbstract<BigInteger> ufd1, ufd2;
168 ufd1 = new GreatestCommonDivisorSubres<BigInteger>();
169 ufd2 = new GreatestCommonDivisorModular<ModLong>(); // dummy type
170 return new GCDProxy<BigInteger>(ufd1, ufd2);
171 }
172
173
174 /**
175 * Determine suitable implementation of gcd algorithms, case BigRational.
176 * @param fac BigRational.
177 * @return gcd algorithm implementation.
178 */
179 public static GreatestCommonDivisorAbstract<BigRational> getImplementation(BigRational fac) {
180 GreatestCommonDivisorAbstract<BigRational> ufd;
181 ufd = new GreatestCommonDivisorPrimitive<BigRational>();
182 return ufd;
183 }
184
185
186 /**
187 * Determine suitable proxy for gcd algorithms, case BigRational.
188 * @param fac BigRational.
189 * @return gcd algorithm implementation.
190 */
191 public static GreatestCommonDivisorAbstract<BigRational> getProxy(BigRational fac) {
192 GreatestCommonDivisorAbstract<BigRational> ufd1, ufd2;
193 ufd1 = new GreatestCommonDivisorSubres<BigRational>();
194 ufd2 = new GreatestCommonDivisorSimple<BigRational>();
195 return new GCDProxy<BigRational>(ufd1, ufd2);
196 }
197
198
199 /**
200 * Determine suitable implementation of gcd algorithms, other cases.
201 * @param fac RingFactory<C>.
202 * @return gcd algorithm implementation.
203 */
204 @SuppressWarnings("unchecked")
205 public static <C extends GcdRingElem<C>> GreatestCommonDivisorAbstract<C> getImplementation(
206 RingFactory<C> fac) {
207 GreatestCommonDivisorAbstract/*raw type<C>*/ufd;
208 logger.debug("fac = " + fac.getClass().getName());
209 int t = 0;
210 Object ofac = fac;
211 if (ofac instanceof BigInteger) {
212 t = 1;
213 }
214 if (ofac instanceof ModIntegerRing) {
215 t = 2;
216 }
217 if (ofac instanceof BigRational) {
218 t = 3;
219 }
220 if (ofac instanceof ModLongRing) {
221 t = 4;
222 }
223 //System.out.println("gt = " + t);
224 if (t == 1) {
225 ufd = new GreatestCommonDivisorModular/*<BigInteger>*/();
226 //ufd = new GreatestCommonDivisorSubres<BigInteger>();
227 //ufd = new GreatestCommonDivisorModular/*<BigInteger>*/(true);
228 } else if (t == 2) {
229 ufd = new GreatestCommonDivisorModEval<ModInteger>();
230 } else if (t == 3) {
231 ufd = new GreatestCommonDivisorSubres<C>();
232 } else if (t == 4) {
233 ufd = new GreatestCommonDivisorModEval<ModLong>();
234 } else {
235 if (fac.isField()) {
236 ufd = new GreatestCommonDivisorSimple<C>();
237 } else {
238 ufd = new GreatestCommonDivisorSubres<C>();
239 }
240 }
241 logger.debug("implementation = " + ufd);
242 return ufd;
243 }
244
245
246 /**
247 * Determine suitable proxy for gcd algorithms, other cases.
248 * @param fac RingFactory<C>.
249 * @return gcd algorithm implementation. <b>Note:</b> This method contains a
250 * hack for Google app engine to not use threads.
251 * @see edu.jas.kern.ComputerThreads#NO_THREADS
252 */
253 @SuppressWarnings("unchecked")
254 public static <C extends GcdRingElem<C>> GreatestCommonDivisorAbstract<C> getProxy(RingFactory<C> fac) {
255 if (ComputerThreads.NO_THREADS) { // hack for Google app engine
256 return GCDFactory.<C> getImplementation(fac);
257 }
258 GreatestCommonDivisorAbstract/*raw type<C>*/ufd;
259 logger.debug("fac = " + fac.getClass().getName());
260 int t = 0;
261 Object ofac = fac;
262 if (ofac instanceof BigInteger) {
263 t = 1;
264 }
265 if (ofac instanceof ModIntegerRing) {
266 t = 2;
267 }
268 if (ofac instanceof BigRational) {
269 t = 3;
270 }
271 if (ofac instanceof ModLongRing) {
272 t = 4;
273 }
274 //System.out.println("t = " + t);
275 if (t == 1) {
276 ufd = new GCDProxy<BigInteger>(new GreatestCommonDivisorSubres<BigInteger>(),
277 new GreatestCommonDivisorModular/*<BigInteger>*/());
278 // new GreatestCommonDivisorModular/*<BigInteger>*/(true) );
279 } else if (t == 2) {
280 ufd = new GCDProxy<ModInteger>(new GreatestCommonDivisorSubres<ModInteger>(),
281 new GreatestCommonDivisorModEval<ModInteger>());
282 } else if (t == 3) {
283 ufd = new GCDProxy<C>(new GreatestCommonDivisorSubres<C>(), new GreatestCommonDivisorSimple<C>());
284 } else if (t == 4) {
285 ufd = new GCDProxy<ModLong>(new GreatestCommonDivisorSubres<ModLong>(),
286 new GreatestCommonDivisorModEval<ModLong>());
287 } else {
288 if (fac.isField()) {
289 ufd = new GCDProxy<C>(new GreatestCommonDivisorSimple<C>(),
290 new GreatestCommonDivisorSubres<C>());
291 } else {
292 ufd = new GCDProxy<C>(new GreatestCommonDivisorSubres<C>(),
293 new GreatestCommonDivisorPrimitive<C>());
294 }
295 }
296 logger.debug("ufd = " + ufd);
297 return ufd;
298 }
299
300 }