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