001/* 002 * $Id: SGCDFactory.java 6010 2020-04-01 10:39:15Z kredel $ 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 GreatestCommonDivisorAbstract<ModLong> ufd; 085 if (fac.isField()) { 086 ufd = new GreatestCommonDivisorSimple<ModLong>(fac); 087 return ufd; 088 } 089 ufd = new GreatestCommonDivisorPrimitive<ModLong>(fac); 090 return ufd; 091 } 092 093 094 /** 095 * Determine suitable proxy for gcd algorithms, case ModLong. 096 * @param fac ModLongRing. 097 * @return gcd algorithm implementation. 098 */ 099 public static GreatestCommonDivisorAbstract<ModLong> getProxy(ModLongRing fac) { 100 GreatestCommonDivisorAbstract<ModLong> ufd1, ufd2; 101 ufd1 = new GreatestCommonDivisorPrimitive<ModLong>(fac); 102 if (fac.isField()) { 103 ufd2 = new GreatestCommonDivisorSimple<ModLong>(fac); 104 } else { 105 ufd2 = new GreatestCommonDivisorSyzygy<ModLong>(fac); 106 } 107 return new SGCDParallelProxy<ModLong>(fac, ufd1, ufd2); 108 } 109 110 111 /** 112 * Determine suitable implementation of gcd algorithms, case ModInteger. 113 * @param fac ModIntegerRing. 114 * @return gcd algorithm implementation. 115 */ 116 public static GreatestCommonDivisorAbstract<ModInteger> getImplementation(ModIntegerRing fac) { 117 GreatestCommonDivisorAbstract<ModInteger> ufd; 118 if (fac.isField()) { 119 ufd = new GreatestCommonDivisorSimple<ModInteger>(fac); 120 return ufd; 121 } 122 ufd = new GreatestCommonDivisorPrimitive<ModInteger>(fac); 123 return ufd; 124 } 125 126 127 /** 128 * Determine suitable proxy for gcd algorithms, case ModInteger. 129 * @param fac ModIntegerRing. 130 * @return gcd algorithm implementation. 131 */ 132 public static GreatestCommonDivisorAbstract<ModInteger> getProxy(ModIntegerRing fac) { 133 GreatestCommonDivisorAbstract<ModInteger> ufd1, ufd2; 134 ufd1 = new GreatestCommonDivisorPrimitive<ModInteger>(fac); 135 if (fac.isField()) { 136 ufd2 = new GreatestCommonDivisorSimple<ModInteger>(fac); 137 } else { 138 ufd2 = new GreatestCommonDivisorSyzygy<ModInteger>(fac); 139 } 140 return new SGCDParallelProxy<ModInteger>(fac, ufd1, ufd2); 141 } 142 143 144 /** 145 * Determine suitable implementation of gcd algorithms, case BigInteger. 146 * @param fac BigInteger. 147 * @return gcd algorithm implementation. 148 */ 149 @SuppressWarnings("unused") 150 public static GreatestCommonDivisorAbstract<BigInteger> getImplementation(BigInteger fac) { 151 GreatestCommonDivisorAbstract<BigInteger> ufd; 152 if (true) { 153 ufd = new GreatestCommonDivisorPrimitive<BigInteger>(fac); 154 } else { 155 ufd = new GreatestCommonDivisorSimple<BigInteger>(fac); 156 } 157 return ufd; 158 } 159 160 161 /** 162 * Determine suitable proxy for gcd algorithms, case BigInteger. 163 * @param fac BigInteger. 164 * @return gcd algorithm implementation. 165 */ 166 public static GreatestCommonDivisorAbstract<BigInteger> getProxy(BigInteger fac) { 167 if (fac == null) { 168 throw new IllegalArgumentException("fac == null not supported"); 169 } 170 GreatestCommonDivisorAbstract<BigInteger> ufd1, ufd2; 171 ufd1 = new GreatestCommonDivisorPrimitive<BigInteger>(fac); 172 ufd2 = new GreatestCommonDivisorSyzygy<BigInteger>(fac); 173 return new SGCDParallelProxy<BigInteger>(fac, ufd1, ufd2); 174 } 175 176 177 /** 178 * Determine suitable implementation of gcd algorithms, case BigRational. 179 * @param fac BigRational. 180 * @return gcd algorithm implementation. 181 */ 182 public static GreatestCommonDivisorAbstract<BigRational> getImplementation(BigRational fac) { 183 if (fac == null) { 184 throw new IllegalArgumentException("fac == null not supported"); 185 } 186 GreatestCommonDivisorAbstract<BigRational> ufd; 187 ufd = new GreatestCommonDivisorPrimitive<BigRational>(fac); 188 return ufd; 189 } 190 191 192 /** 193 * Determine suitable proxy for gcd algorithms, case BigRational. 194 * @param fac BigRational. 195 * @return gcd algorithm implementation. 196 */ 197 public static GreatestCommonDivisorAbstract<BigRational> getProxy(BigRational fac) { 198 if (fac == null) { 199 throw new IllegalArgumentException("fac == null not supported"); 200 } 201 GreatestCommonDivisorAbstract<BigRational> ufd1, ufd2; 202 ufd1 = new GreatestCommonDivisorPrimitive<BigRational>(fac); 203 ufd2 = new GreatestCommonDivisorSimple<BigRational>(fac); 204 return new SGCDParallelProxy<BigRational>(fac, ufd1, ufd2); 205 } 206 207 208 /** 209 * Determine suitable implementation of gcd algorithms, other cases. 210 * @param fac RingFactory<C>. 211 * @return gcd algorithm implementation. 212 */ 213 @SuppressWarnings("unchecked") 214 public static <C extends GcdRingElem<C>> GreatestCommonDivisorAbstract<C> getImplementation( 215 RingFactory<C> fac) { 216 GreatestCommonDivisorAbstract/*raw type<C>*/ ufd; 217 logger.debug("fac = " + fac.getClass().getName()); 218 Object ofac = fac; 219 if (ofac instanceof BigInteger) { 220 ufd = new GreatestCommonDivisorPrimitive<C>(fac); 221 } else if (ofac instanceof ModIntegerRing) { 222 if (fac.isField()) { 223 ufd = new GreatestCommonDivisorSimple<C>(fac); 224 } else { 225 ufd = new GreatestCommonDivisorPrimitive<C>(fac); 226 } 227 } else if (ofac instanceof ModLongRing) { 228 if (fac.isField()) { 229 ufd = new GreatestCommonDivisorSimple<C>(fac); 230 } else { 231 ufd = new GreatestCommonDivisorPrimitive<C>(fac); 232 } 233 } else if (ofac instanceof BigRational) { 234 ufd = new GreatestCommonDivisorSimple<C>(fac); 235 } else { 236 if (fac.isField()) { 237 ufd = new GreatestCommonDivisorSimple<C>(fac); 238 } else { 239 ufd = new GreatestCommonDivisorPrimitive<C>(fac); 240 } 241 } 242 logger.debug("implementation = " + ufd); 243 return ufd; 244 } 245 246 247 /** 248 * Determine suitable proxy for gcd algorithms, other cases. 249 * @param fac RingFactory<C>. 250 * @return gcd algorithm implementation. <b>Note:</b> This method contains a 251 * hack for Google app engine to not use threads. 252 * @see edu.jas.kern.ComputerThreads#NO_THREADS 253 */ 254 @SuppressWarnings("unchecked") 255 public static <C extends GcdRingElem<C>> GreatestCommonDivisorAbstract<C> getProxy(RingFactory<C> fac) { 256 if (ComputerThreads.NO_THREADS) { // hack for Google app engine 257 return SGCDFactory.<C> getImplementation(fac); 258 } 259 GreatestCommonDivisorAbstract/*raw type<C>*/ ufd; 260 logger.debug("fac = " + fac.getClass().getName()); 261 Object ofac = fac; 262 if (ofac instanceof BigInteger) { 263 ufd = new SGCDParallelProxy<C>(fac, new GreatestCommonDivisorSimple<C>(fac), 264 new GreatestCommonDivisorPrimitive<C>(fac)); 265 } else if (ofac instanceof ModIntegerRing) { 266 ufd = new SGCDParallelProxy<C>(fac, new GreatestCommonDivisorSimple<C>(fac), 267 new GreatestCommonDivisorPrimitive<C>(fac)); 268 } else if (ofac instanceof ModLongRing) { 269 ufd = new SGCDParallelProxy<C>(fac, new GreatestCommonDivisorSimple<C>(fac), 270 new GreatestCommonDivisorPrimitive<C>(fac)); 271 } else if (ofac instanceof BigRational) { 272 ufd = new SGCDParallelProxy<C>(fac, new GreatestCommonDivisorPrimitive<C>(fac), 273 new GreatestCommonDivisorSimple<C>(fac)); 274 } else { 275 if (fac.isField()) { 276 ufd = new SGCDParallelProxy<C>(fac, new GreatestCommonDivisorSimple<C>(fac), 277 new GreatestCommonDivisorPrimitive<C>(fac)); 278 } else { 279 ufd = new SGCDParallelProxy<C>(fac, new GreatestCommonDivisorSyzygy<C>(fac), 280 new GreatestCommonDivisorPrimitive<C>(fac)); 281 } 282 } 283 logger.debug("ufd = " + ufd); 284 return ufd; 285 } 286 287}