001/* 002 * $Id: SGCDFactory.java 5872 2018-07-20 16:01:46Z kredel $ 003 */ 004 005package edu.jas.fd; 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 * Solvable greatest common divisor algorithms factory. Select appropriate SGCD 024 * engine 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> 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 * implementation. On systems with more than two CPUs the computing time 040 * will be the time of the fastest algorithm implementation. 041 * 042 * <pre> 043 * GreatestCommonDivisor<CT> engine; 044 * engine = SGCDFactory.<CT> getImplementation(cofac); 045 * or engine = SGCDFactory.<CT> getProxy(cofac); 046 * c = engine.leftGcd(a, b); 047 * </pre> 048 * 049 * For example, if the coefficient type is <code>BigInteger</code>, the 050 * usage looks like 051 * 052 * <pre> 053 * BigInteger cofac = new BigInteger(); 054 * GreatestCommonDivisor<BigInteger> engine; 055 * engine = SGCDFactory.getImplementation(cofac); 056 * or engine = SGCDFactory.getProxy(cofac); 057 * c = engine.leftGcd(a, b); 058 * </pre> 059 * 060 * @see edu.jas.fd.GreatestCommonDivisor#leftGcd(edu.jas.poly.GenSolvablePolynomial 061 * P, edu.jas.poly.GenSolvablePolynomial S) 062 */ 063 064public class SGCDFactory { 065 066 067 private static final Logger logger = LogManager.getLogger(SGCDFactory.class); 068 069 070 /** 071 * Protected factory constructor. 072 */ 073 protected SGCDFactory() { 074 } 075 076 077 /** 078 * Determine suitable implementation of gcd algorithms, case ModLong. 079 * @param fac ModLongRing. 080 * @return gcd algorithm implementation. 081 */ 082 public static GreatestCommonDivisorAbstract<ModLong> getImplementation(ModLongRing fac) { 083 GreatestCommonDivisorAbstract<ModLong> ufd; 084 if (fac.isField()) { 085 ufd = new GreatestCommonDivisorSimple<ModLong>(fac); 086 return ufd; 087 } 088 ufd = new GreatestCommonDivisorPrimitive<ModLong>(fac); 089 return ufd; 090 } 091 092 093 /** 094 * Determine suitable proxy for gcd algorithms, case ModLong. 095 * @param fac ModLongRing. 096 * @return gcd algorithm implementation. 097 */ 098 public static GreatestCommonDivisorAbstract<ModLong> getProxy(ModLongRing fac) { 099 GreatestCommonDivisorAbstract<ModLong> ufd1, ufd2; 100 ufd1 = new GreatestCommonDivisorPrimitive<ModLong>(fac); 101 if (fac.isField()) { 102 ufd2 = new GreatestCommonDivisorSimple<ModLong>(fac); 103 } else { 104 ufd2 = new GreatestCommonDivisorSyzygy<ModLong>(fac); 105 } 106 return new SGCDParallelProxy<ModLong>(fac, ufd1, ufd2); 107 } 108 109 110 /** 111 * Determine suitable implementation of gcd algorithms, case ModInteger. 112 * @param fac ModIntegerRing. 113 * @return gcd algorithm implementation. 114 */ 115 public static GreatestCommonDivisorAbstract<ModInteger> getImplementation(ModIntegerRing fac) { 116 GreatestCommonDivisorAbstract<ModInteger> ufd; 117 if (fac.isField()) { 118 ufd = new GreatestCommonDivisorSimple<ModInteger>(fac); 119 return ufd; 120 } 121 ufd = new GreatestCommonDivisorPrimitive<ModInteger>(fac); 122 return ufd; 123 } 124 125 126 /** 127 * Determine suitable proxy for gcd algorithms, case ModInteger. 128 * @param fac ModIntegerRing. 129 * @return gcd algorithm implementation. 130 */ 131 public static GreatestCommonDivisorAbstract<ModInteger> getProxy(ModIntegerRing fac) { 132 GreatestCommonDivisorAbstract<ModInteger> ufd1, ufd2; 133 ufd1 = new GreatestCommonDivisorPrimitive<ModInteger>(fac); 134 if (fac.isField()) { 135 ufd2 = new GreatestCommonDivisorSimple<ModInteger>(fac); 136 } else { 137 ufd2 = new GreatestCommonDivisorSyzygy<ModInteger>(fac); 138 } 139 return new SGCDParallelProxy<ModInteger>(fac, ufd1, ufd2); 140 } 141 142 143 /** 144 * Determine suitable implementation of gcd algorithms, case BigInteger. 145 * @param fac BigInteger. 146 * @return gcd algorithm implementation. 147 */ 148 @SuppressWarnings("unused") 149 public static GreatestCommonDivisorAbstract<BigInteger> getImplementation(BigInteger fac) { 150 GreatestCommonDivisorAbstract<BigInteger> ufd; 151 if (true) { 152 ufd = new GreatestCommonDivisorPrimitive<BigInteger>(fac); 153 } else { 154 ufd = new GreatestCommonDivisorSimple<BigInteger>(fac); 155 } 156 return ufd; 157 } 158 159 160 /** 161 * Determine suitable proxy for gcd algorithms, case BigInteger. 162 * @param fac BigInteger. 163 * @return gcd algorithm implementation. 164 */ 165 public static GreatestCommonDivisorAbstract<BigInteger> getProxy(BigInteger fac) { 166 if (fac == null) { 167 throw new IllegalArgumentException("fac == null not supported"); 168 } 169 GreatestCommonDivisorAbstract<BigInteger> ufd1, ufd2; 170 ufd1 = new GreatestCommonDivisorPrimitive<BigInteger>(fac); 171 ufd2 = new GreatestCommonDivisorSyzygy<BigInteger>(fac); 172 return new SGCDParallelProxy<BigInteger>(fac, ufd1, ufd2); 173 } 174 175 176 /** 177 * Determine suitable implementation of gcd algorithms, case BigRational. 178 * @param fac BigRational. 179 * @return gcd algorithm implementation. 180 */ 181 public static GreatestCommonDivisorAbstract<BigRational> getImplementation(BigRational fac) { 182 if (fac == null) { 183 throw new IllegalArgumentException("fac == null not supported"); 184 } 185 GreatestCommonDivisorAbstract<BigRational> ufd; 186 ufd = new GreatestCommonDivisorPrimitive<BigRational>(fac); 187 return ufd; 188 } 189 190 191 /** 192 * Determine suitable proxy for gcd algorithms, case BigRational. 193 * @param fac BigRational. 194 * @return gcd algorithm implementation. 195 */ 196 public static GreatestCommonDivisorAbstract<BigRational> getProxy(BigRational fac) { 197 if (fac == null) { 198 throw new IllegalArgumentException("fac == null not supported"); 199 } 200 GreatestCommonDivisorAbstract<BigRational> ufd1, ufd2; 201 ufd1 = new GreatestCommonDivisorPrimitive<BigRational>(fac); 202 ufd2 = new GreatestCommonDivisorSimple<BigRational>(fac); 203 return new SGCDParallelProxy<BigRational>(fac, ufd1, ufd2); 204 } 205 206 207 /** 208 * Determine suitable implementation of gcd algorithms, other cases. 209 * @param fac RingFactory<C>. 210 * @return gcd algorithm implementation. 211 */ 212 @SuppressWarnings("unchecked") 213 public static <C extends GcdRingElem<C>> GreatestCommonDivisorAbstract<C> getImplementation( 214 RingFactory<C> fac) { 215 GreatestCommonDivisorAbstract/*raw type<C>*/ ufd; 216 logger.debug("fac = " + fac.getClass().getName()); 217 Object ofac = fac; 218 if (ofac instanceof BigInteger) { 219 ufd = new GreatestCommonDivisorPrimitive<C>(fac); 220 } else if (ofac instanceof ModIntegerRing) { 221 if (fac.isField()) { 222 ufd = new GreatestCommonDivisorSimple<C>(fac); 223 } else { 224 ufd = new GreatestCommonDivisorPrimitive<C>(fac); 225 } 226 } else if (ofac instanceof ModLongRing) { 227 if (fac.isField()) { 228 ufd = new GreatestCommonDivisorSimple<C>(fac); 229 } else { 230 ufd = new GreatestCommonDivisorPrimitive<C>(fac); 231 } 232 } else if (ofac instanceof BigRational) { 233 ufd = new GreatestCommonDivisorSimple<C>(fac); 234 } else { 235 if (fac.isField()) { 236 ufd = new GreatestCommonDivisorSimple<C>(fac); 237 } else { 238 ufd = new GreatestCommonDivisorPrimitive<C>(fac); 239 } 240 } 241 logger.debug("implementation = " + ufd); 242 return ufd; 243 } 244 245 246 /** 247 * Determine suitable proxy for gcd algorithms, other cases. 248 * @param fac RingFactory<C>. 249 * @return gcd algorithm implementation. <b>Note:</b> This method contains a 250 * hack for Google app engine to not use threads. 251 * @see edu.jas.kern.ComputerThreads#NO_THREADS 252 */ 253 @SuppressWarnings("unchecked") 254 public static <C extends GcdRingElem<C>> GreatestCommonDivisorAbstract<C> getProxy(RingFactory<C> fac) { 255 if (ComputerThreads.NO_THREADS) { // hack for Google app engine 256 return SGCDFactory.<C> getImplementation(fac); 257 } 258 GreatestCommonDivisorAbstract/*raw type<C>*/ ufd; 259 logger.debug("fac = " + fac.getClass().getName()); 260 Object ofac = fac; 261 if (ofac instanceof BigInteger) { 262 ufd = new SGCDParallelProxy<C>(fac, new GreatestCommonDivisorSimple<C>(fac), 263 new GreatestCommonDivisorPrimitive<C>(fac)); 264 } else if (ofac instanceof ModIntegerRing) { 265 ufd = new SGCDParallelProxy<C>(fac, new GreatestCommonDivisorSimple<C>(fac), 266 new GreatestCommonDivisorPrimitive<C>(fac)); 267 } else if (ofac instanceof ModLongRing) { 268 ufd = new SGCDParallelProxy<C>(fac, new GreatestCommonDivisorSimple<C>(fac), 269 new GreatestCommonDivisorPrimitive<C>(fac)); 270 } else if (ofac instanceof BigRational) { 271 ufd = new SGCDParallelProxy<C>(fac, new GreatestCommonDivisorPrimitive<C>(fac), 272 new GreatestCommonDivisorSimple<C>(fac)); 273 } else { 274 if (fac.isField()) { 275 ufd = new SGCDParallelProxy<C>(fac, new GreatestCommonDivisorSimple<C>(fac), 276 new GreatestCommonDivisorPrimitive<C>(fac)); 277 } else { 278 ufd = new SGCDParallelProxy<C>(fac, new GreatestCommonDivisorSyzygy<C>(fac), 279 new GreatestCommonDivisorPrimitive<C>(fac)); 280 } 281 } 282 logger.debug("ufd = " + ufd); 283 return ufd; 284 } 285 286}