001/* 002 * $Id: GCDFactory.java 3852 2011-12-31 20:03:57Z 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 * @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 066public 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 Object ofac = fac; 210 if (ofac instanceof BigInteger) { 211 ufd = new GreatestCommonDivisorModular<ModInteger>(); 212 //ufd = new GreatestCommonDivisorSubres<BigInteger>(); 213 //ufd = new GreatestCommonDivisorModular<ModInteger>(true); 214 } else if (ofac instanceof ModIntegerRing) { 215 ufd = new GreatestCommonDivisorModEval<ModInteger>(); 216 } else if (ofac instanceof ModLongRing) { 217 ufd = new GreatestCommonDivisorModEval<ModLong>(); 218 } else if (ofac instanceof BigRational) { 219 ufd = new GreatestCommonDivisorSubres<BigRational>(); 220 } else { 221 if (fac.isField()) { 222 ufd = new GreatestCommonDivisorSimple<C>(); 223 } else { 224 ufd = new GreatestCommonDivisorSubres<C>(); 225 } 226 } 227 logger.debug("implementation = " + ufd); 228 return ufd; 229 } 230 231 232 /** 233 * Determine suitable proxy for gcd algorithms, other cases. 234 * @param fac RingFactory<C>. 235 * @return gcd algorithm implementation. <b>Note:</b> This method contains a 236 * hack for Google app engine to not use threads. 237 * @see edu.jas.kern.ComputerThreads#NO_THREADS 238 */ 239 @SuppressWarnings("unchecked") 240 public static <C extends GcdRingElem<C>> GreatestCommonDivisorAbstract<C> getProxy(RingFactory<C> fac) { 241 if (ComputerThreads.NO_THREADS) { // hack for Google app engine 242 return GCDFactory.<C> getImplementation(fac); 243 } 244 GreatestCommonDivisorAbstract/*raw type<C>*/ufd; 245 logger.debug("fac = " + fac.getClass().getName()); 246 Object ofac = fac; 247 if (ofac instanceof BigInteger) { 248 ufd = new GCDProxy<BigInteger>(new GreatestCommonDivisorSubres<BigInteger>(), 249 new GreatestCommonDivisorModular<ModInteger>()); 250 } else if (ofac instanceof ModIntegerRing) { 251 ufd = new GCDProxy<ModInteger>(new GreatestCommonDivisorSimple<ModInteger>(), // Subres 252 new GreatestCommonDivisorModEval<ModInteger>()); 253 } else if (ofac instanceof ModLongRing) { 254 ufd = new GCDProxy<ModLong>(new GreatestCommonDivisorSimple<ModLong>(), // Subres 255 new GreatestCommonDivisorModEval<ModLong>()); 256 } else if (ofac instanceof BigRational) { 257 ufd = new GCDProxy<BigRational>(new GreatestCommonDivisorSubres<BigRational>(), 258 new GreatestCommonDivisorSimple<BigRational>()); 259 } else { 260 if (fac.isField()) { 261 ufd = new GCDProxy<C>(new GreatestCommonDivisorSimple<C>(), 262 new GreatestCommonDivisorSubres<C>()); 263 } else { 264 ufd = new GCDProxy<C>(new GreatestCommonDivisorSubres<C>(), 265 new GreatestCommonDivisorPrimitive<C>()); // no resultant 266 } 267 } 268 logger.debug("ufd = " + ufd); 269 return ufd; 270 } 271 272}