001/* 002 * $Id$ 003 */ 004 005package edu.jas.fd; 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.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 * Solvable greatest common divisor algorithms factory. Select appropriate SGCD 024 * engine based on the coefficient types. 025 * <p> 026 * <b>Usage:</b> To create objects that implement the 027 * <code>GreatestCommonDivisor</code> interface use the 028 * <code>SGCDFactory</code>. It will select an appropriate implementation based 029 * on the types of polynomial coefficients C. There are two methods to obtain an 030 * implementation: <code>getProxy()</code> and <code>getImplementation()</code>. 031 * <code>getImplementation()</code> returns an object of a class which 032 * implements the <code>GreatestCommonDivisor</code> interface. 033 * <code>getProxy()</code> returns a proxy object of a class which implements 034 * the <code>GreatestCommonDivisor</code> interface. The proxy will run two 035 * implementations in parallel, return the first computed result and cancel the 036 * second running task. On systems with one CPU the computing time will be two 037 * times the time of the fastest algorithm implementation. On systems with more 038 * than two CPUs the computing time will be the time of the fastest algorithm 039 * implementation. 040 * 041 * <pre> 042 * GreatestCommonDivisor<CT> engine; 043 * engine = SGCDFactory.<CT> getImplementation(cofac); 044 * or engine = SGCDFactory.<CT> getProxy(cofac); 045 * c = engine.leftGcd(a, b); 046 * </pre> 047 * <p> 048 * For example, if the coefficient type is <code>BigInteger</code>, the usage 049 * looks like 050 * 051 * <pre> 052 * BigInteger cofac = new BigInteger(); 053 * GreatestCommonDivisor<BigInteger> engine; 054 * engine = SGCDFactory.getImplementation(cofac); 055 * or engine = SGCDFactory.getProxy(cofac); 056 * c = engine.leftGcd(a, b); 057 * </pre> 058 * 059 * @author Heinz Kredel 060 * 061 * @see edu.jas.fd.GreatestCommonDivisor#leftGcd(edu.jas.poly.GenSolvablePolynomial 062 * P, edu.jas.poly.GenSolvablePolynomial S) 063 */ 064 065public class SGCDFactory { 066 067 068 private static final Logger logger = LogManager.getLogger(SGCDFactory.class); 069 070 071 /** 072 * Protected factory constructor. 073 */ 074 protected SGCDFactory() { 075 } 076 077 078 /** 079 * Determine suitable implementation of gcd algorithms, case ModLong. 080 * @param fac ModLongRing. 081 * @return gcd algorithm implementation. 082 */ 083 public static GreatestCommonDivisorAbstract<ModLong> getImplementation(ModLongRing fac) { 084 logger.info("fac = {}", fac.getClass().getName()); 085 GreatestCommonDivisorAbstract<ModLong> ufd; 086 if (fac.isField()) { 087 ufd = new GreatestCommonDivisorSimple<ModLong>(fac); 088 return ufd; 089 } 090 ufd = new GreatestCommonDivisorPrimitive<ModLong>(fac); 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 logger.info("fac = {}", fac.getClass().getName()); 102 GreatestCommonDivisorAbstract<ModLong> ufd1, ufd2; 103 ufd1 = new GreatestCommonDivisorPrimitive<ModLong>(fac); 104 if (fac.isField()) { 105 ufd2 = new GreatestCommonDivisorSimple<ModLong>(fac); 106 } else { 107 ufd2 = new GreatestCommonDivisorSyzygy<ModLong>(fac); 108 } 109 return new SGCDParallelProxy<ModLong>(fac, ufd1, ufd2); 110 } 111 112 113 /** 114 * Determine suitable implementation of gcd algorithms, case ModInteger. 115 * @param fac ModIntegerRing. 116 * @return gcd algorithm implementation. 117 */ 118 public static GreatestCommonDivisorAbstract<ModInteger> getImplementation(ModIntegerRing fac) { 119 logger.info("fac = {}", fac.getClass().getName()); 120 GreatestCommonDivisorAbstract<ModInteger> ufd; 121 if (fac.isField()) { 122 ufd = new GreatestCommonDivisorSimple<ModInteger>(fac); 123 return ufd; 124 } 125 ufd = new GreatestCommonDivisorPrimitive<ModInteger>(fac); 126 return ufd; 127 } 128 129 130 /** 131 * Determine suitable proxy for gcd algorithms, case ModInteger. 132 * @param fac ModIntegerRing. 133 * @return gcd algorithm implementation. 134 */ 135 public static GreatestCommonDivisorAbstract<ModInteger> getProxy(ModIntegerRing fac) { 136 logger.info("fac = {}", fac.getClass().getName()); 137 GreatestCommonDivisorAbstract<ModInteger> ufd1, ufd2; 138 ufd1 = new GreatestCommonDivisorPrimitive<ModInteger>(fac); 139 if (fac.isField()) { 140 ufd2 = new GreatestCommonDivisorSimple<ModInteger>(fac); 141 } else { 142 ufd2 = new GreatestCommonDivisorSyzygy<ModInteger>(fac); 143 } 144 return new SGCDParallelProxy<ModInteger>(fac, 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 logger.info("fac = {}", fac.getClass().getName()); 157 if (!fac.isField()) { // = false 158 ufd = new GreatestCommonDivisorPrimitive<BigInteger>(fac); 159 } else { 160 ufd = new GreatestCommonDivisorSimple<BigInteger>(fac); 161 } 162 return ufd; 163 } 164 165 166 /** 167 * Determine suitable proxy 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 logger.info("fac = {}", fac.getClass().getName()); 176 GreatestCommonDivisorAbstract<BigInteger> ufd1, ufd2; 177 ufd1 = new GreatestCommonDivisorPrimitive<BigInteger>(fac); 178 ufd2 = new GreatestCommonDivisorSyzygy<BigInteger>(fac); 179 return new SGCDParallelProxy<BigInteger>(fac, 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 logger.info("fac = {}", fac.getClass().getName()); 193 GreatestCommonDivisorAbstract<BigRational> ufd; 194 if (fac.isField()) { // = true 195 ufd = new GreatestCommonDivisorSimple<BigRational>(fac); 196 return ufd; 197 } 198 ufd = new GreatestCommonDivisorPrimitive<BigRational>(fac); 199 return ufd; 200 } 201 202 203 /** 204 * Determine suitable proxy for gcd algorithms, case BigRational. 205 * @param fac BigRational. 206 * @return gcd algorithm implementation. 207 */ 208 public static GreatestCommonDivisorAbstract<BigRational> getProxy(BigRational fac) { 209 if (fac == null) { 210 throw new IllegalArgumentException("fac == null not supported"); 211 } 212 logger.info("fac = {}", fac.getClass().getName()); 213 GreatestCommonDivisorAbstract<BigRational> ufd1, ufd2; 214 ufd1 = new GreatestCommonDivisorPrimitive<BigRational>(fac); 215 ufd2 = new GreatestCommonDivisorSimple<BigRational>(fac); 216 return new SGCDParallelProxy<BigRational>(fac, ufd1, ufd2); 217 } 218 219 220 /** 221 * Determine suitable implementation of gcd algorithms, other cases. 222 * @param fac RingFactory<C>. 223 * @return gcd algorithm implementation. 224 */ 225 @SuppressWarnings("unchecked") 226 public static <C extends GcdRingElem<C>> GreatestCommonDivisorAbstract<C> getImplementation( 227 RingFactory<C> fac) { 228 //System.out.println("SGCDFactory: " + fac.getClass().getName()); 229 GreatestCommonDivisorAbstract/*raw type<C>*/ ufd; 230 logger.info("fac = {}", fac.getClass().getName()); 231 Object ofac = fac; 232 if (ofac instanceof BigInteger) { 233 ufd = new GreatestCommonDivisorPrimitive<C>(fac); 234 } else if (ofac instanceof ModIntegerRing) { 235 if (fac.isField()) { 236 ufd = new GreatestCommonDivisorSimple<C>(fac); 237 } else { 238 ufd = new GreatestCommonDivisorPrimitive<C>(fac); 239 } 240 } else if (ofac instanceof ModLongRing) { 241 if (fac.isField()) { 242 ufd = new GreatestCommonDivisorSimple<C>(fac); 243 } else { 244 ufd = new GreatestCommonDivisorPrimitive<C>(fac); 245 } 246 } else if (ofac instanceof BigRational) { 247 ufd = new GreatestCommonDivisorSimple<C>(fac); 248 } else { 249 if (fac.isField()) { 250 ufd = new GreatestCommonDivisorSimple<C>(fac); 251 } else { 252 ufd = new GreatestCommonDivisorPrimitive<C>(fac); 253 } 254 } 255 //System.out.println("SGCDFactory: " + ufd.getClass().getName()); 256 logger.debug("implementation = {}", ufd); 257 return ufd; 258 } 259 260 261 /** 262 * Determine fake implementation of gcd algorithms, other cases. 263 * @param fac RingFactory<C>. 264 * @return fake gcd algorithm implementation. 265 */ 266 @SuppressWarnings("unchecked") 267 public static <C extends GcdRingElem<C>> GreatestCommonDivisorAbstract<C> getFakeImplementation( 268 RingFactory<C> fac) { 269 GreatestCommonDivisorAbstract/*raw type<C>*/ ufd; 270 logger.info("fac = {}", fac.getClass().getName()); 271 //Object ofac = fac; 272 ufd = new GreatestCommonDivisorFake<C>(fac); 273 if (!(fac instanceof BigRational)) { 274 //System.out.println("SGCDFactory: " + fac.getClass().getName()); 275 //System.out.println("SGCDFactory: " + ufd.getClass().getName()); 276 } 277 logger.debug("implementation = {}", ufd); 278 return ufd; 279 } 280 281 282 /** 283 * Determine suitable proxy for gcd algorithms, other cases. 284 * @param fac RingFactory<C>. 285 * @return gcd algorithm implementation. <b>Note:</b> This method contains a 286 * hack for Google app engine to not use threads. 287 * @see edu.jas.kern.ComputerThreads#NO_THREADS 288 */ 289 @SuppressWarnings("unchecked") 290 public static <C extends GcdRingElem<C>> GreatestCommonDivisorAbstract<C> getProxy(RingFactory<C> fac) { 291 if (ComputerThreads.NO_THREADS) { // hack for Google app engine 292 return SGCDFactory.<C> getImplementation(fac); 293 } 294 GreatestCommonDivisorAbstract/*raw type<C>*/ ufd; 295 logger.info("fac = {}", fac.getClass().getName()); 296 Object ofac = fac; 297 if (ofac instanceof BigInteger) { 298 ufd = new SGCDParallelProxy<C>(fac, new GreatestCommonDivisorSimple<C>(fac), 299 new GreatestCommonDivisorPrimitive<C>(fac)); 300 } else if (ofac instanceof ModIntegerRing) { 301 ufd = new SGCDParallelProxy<C>(fac, new GreatestCommonDivisorSimple<C>(fac), 302 new GreatestCommonDivisorPrimitive<C>(fac)); 303 } else if (ofac instanceof ModLongRing) { 304 ufd = new SGCDParallelProxy<C>(fac, new GreatestCommonDivisorSimple<C>(fac), 305 new GreatestCommonDivisorPrimitive<C>(fac)); 306 } else if (ofac instanceof BigRational) { 307 ufd = new SGCDParallelProxy<C>(fac, new GreatestCommonDivisorPrimitive<C>(fac), 308 new GreatestCommonDivisorSimple<C>(fac)); 309 } else { 310 if (fac.isField()) { 311 ufd = new SGCDParallelProxy<C>(fac, new GreatestCommonDivisorSimple<C>(fac), 312 new GreatestCommonDivisorPrimitive<C>(fac)); 313 } else { 314 ufd = new SGCDParallelProxy<C>(fac, new GreatestCommonDivisorSyzygy<C>(fac), 315 new GreatestCommonDivisorPrimitive<C>(fac)); 316 } 317 } 318 logger.debug("ufd = {}", ufd); 319 return ufd; 320 } 321 322}