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