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 }