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