001/* 002 * $Id: GreatestCommonDivisorPrimitive.java 5543 2016-07-24 18:45:47Z kredel $ 003 */ 004 005package edu.jas.fd; 006 007 008import org.apache.log4j.Logger; 009 010import edu.jas.poly.GenPolynomial; 011import edu.jas.poly.GenSolvablePolynomial; 012import edu.jas.poly.PolyUtil; 013import edu.jas.structure.GcdRingElem; 014import edu.jas.structure.RingFactory; 015 016 017/** 018 * (Non-unique) factorization domain greatest common divisor common algorithms 019 * with primitive polynomial remainder sequence. 020 * @param <C> coefficient type 021 * @author Heinz Kredel 022 */ 023 024public class GreatestCommonDivisorPrimitive<C extends GcdRingElem<C>> extends 025 GreatestCommonDivisorAbstract<C> { 026 027 028 private static final Logger logger = Logger.getLogger(GreatestCommonDivisorPrimitive.class); 029 030 031 private static final boolean debug = logger.isDebugEnabled(); 032 033 034 /** 035 * Constructor. 036 * @param cf coefficient ring. 037 */ 038 public GreatestCommonDivisorPrimitive(RingFactory<C> cf) { 039 super(cf); 040 } 041 042 043 /** 044 * Univariate GenSolvablePolynomial greatest common divisor. Uses 045 * pseudoRemainder for remainder. 046 * @param P univariate GenSolvablePolynomial. 047 * @param S univariate GenSolvablePolynomial. 048 * @return gcd(P,S) with P = P'*gcd(P,S) and S = S'*gcd(P,S). 049 */ 050 @Override 051 public GenSolvablePolynomial<C> leftBaseGcd(GenSolvablePolynomial<C> P, GenSolvablePolynomial<C> S) { 052 if (S == null || S.isZERO()) { 053 return P; 054 } 055 if (P == null || P.isZERO()) { 056 return S; 057 } 058 if (P.ring.nvar > 1) { 059 throw new IllegalArgumentException(this.getClass().getName() + " no univariate polynomial"); 060 } 061 boolean field = P.ring.coFac.isField(); 062 long e = P.degree(0); 063 long f = S.degree(0); 064 GenSolvablePolynomial<C> q; 065 GenSolvablePolynomial<C> r; 066 if (f > e) { 067 r = P; 068 q = S; 069 long g = f; 070 f = e; 071 e = g; 072 } else { 073 q = P; 074 r = S; 075 } 076 if (debug) { 077 logger.debug("degrees: e = " + e + ", f = " + f); 078 } 079 C c; 080 if (field) { 081 r = r.monic(); 082 q = q.monic(); 083 c = P.ring.getONECoefficient(); 084 } else { 085 r = (GenSolvablePolynomial<C>) r.abs(); 086 q = (GenSolvablePolynomial<C>) q.abs(); 087 C a = rightBaseContent(r); 088 C b = rightBaseContent(q); 089 r = divide(r, a); // indirection 090 q = divide(q, b); // indirection 091 c = gcd(a, b); // indirection 092 } 093 //System.out.println("baseCont: gcd(cont) = " + b); 094 if (r.isONE()) { 095 return r.multiply(c); 096 } 097 if (q.isONE()) { 098 return q.multiply(c); 099 } 100 GenSolvablePolynomial<C> x; 101 //System.out.println("baseGCD: q = " + q); 102 //System.out.println("baseGCD: r = " + r); 103 while (!r.isZERO()) { 104 x = FDUtil.<C> leftBaseSparsePseudoRemainder(q, r); 105 q = r; 106 if (field) { 107 r = x.monic(); 108 } else { 109 r = leftBasePrimitivePart(x); 110 } 111 //System.out.println("baseGCD: q = " + q); 112 //System.out.println("baseGCD: r = " + r); 113 } 114 return (GenSolvablePolynomial<C>) (q.multiply(c)).abs(); 115 } 116 117 118 /** 119 * Univariate GenSolvablePolynomial right greatest common divisor. Uses 120 * pseudoRemainder for remainder. 121 * @param P univariate GenSolvablePolynomial. 122 * @param S univariate GenSolvablePolynomial. 123 * @return gcd(P,S) with P = gcd(P,S)*P' and S = gcd(P,S)*S'. 124 */ 125 @Override 126 public GenSolvablePolynomial<C> rightBaseGcd(GenSolvablePolynomial<C> P, GenSolvablePolynomial<C> S) { 127 if (S == null || S.isZERO()) { 128 return P; 129 } 130 if (P == null || P.isZERO()) { 131 return S; 132 } 133 if (P.ring.nvar > 1) { 134 throw new IllegalArgumentException(this.getClass().getName() + " no univariate polynomial"); 135 } 136 boolean field = P.ring.coFac.isField(); 137 long e = P.degree(0); 138 long f = S.degree(0); 139 GenSolvablePolynomial<C> q; 140 GenSolvablePolynomial<C> r; 141 if (f > e) { 142 r = P; 143 q = S; 144 long g = f; 145 f = e; 146 e = g; 147 } else { 148 q = P; 149 r = S; 150 } 151 if (debug) { 152 logger.debug("degrees: e = " + e + ", f = " + f); 153 } 154 C c; 155 if (field) { 156 r = r.monic(); 157 q = q.monic(); 158 c = P.ring.getONECoefficient(); 159 } else { 160 r = (GenSolvablePolynomial<C>) r.abs(); 161 q = (GenSolvablePolynomial<C>) q.abs(); 162 C a = leftBaseContent(r); 163 C b = leftBaseContent(q); 164 r = divide(r, a); // indirection 165 q = divide(q, b); // indirection 166 c = gcd(a, b); // indirection 167 } 168 //System.out.println("baseCont: gcd(cont) = " + b); 169 if (r.isONE()) { 170 return r.multiply(c); 171 } 172 if (q.isONE()) { 173 return q.multiply(c); 174 } 175 GenSolvablePolynomial<C> x; 176 //System.out.println("baseGCD: q = " + q); 177 //System.out.println("baseGCD: r = " + r); 178 while (!r.isZERO()) { 179 x = FDUtil.<C> rightBaseSparsePseudoRemainder(q, r); 180 q = r; 181 if (field) { 182 r = x.monic(); 183 } else { 184 r = rightBasePrimitivePart(x); 185 } 186 //System.out.println("baseGCD: q = " + q); 187 //System.out.println("baseGCD: r = " + r); 188 } 189 return (GenSolvablePolynomial<C>) (q.multiplyLeft(c)).abs(); 190 } 191 192 193 /** 194 * Univariate GenSolvablePolynomial left recursive greatest common divisor. 195 * Uses pseudoRemainder for remainder. 196 * @param P univariate recursive GenSolvablePolynomial. 197 * @param S univariate recursive GenSolvablePolynomial. 198 * @return gcd(P,S) with P = P'*gcd(P,S)*p and S = S'*gcd(P,S)*s, where 199 * deg_main(p) = deg_main(s) == 0. 200 */ 201 @Override 202 public GenSolvablePolynomial<GenPolynomial<C>> leftRecursiveUnivariateGcd( 203 GenSolvablePolynomial<GenPolynomial<C>> P, GenSolvablePolynomial<GenPolynomial<C>> S) { 204 if (S == null || S.isZERO()) { 205 return P; 206 } 207 if (P == null || P.isZERO()) { 208 return S; 209 } 210 if (P.ring.nvar > 1) { 211 throw new IllegalArgumentException("no univariate polynomial"); 212 } 213 boolean field = P.leadingBaseCoefficient().ring.coFac.isField(); 214 long e = P.degree(0); 215 long f = S.degree(0); 216 GenSolvablePolynomial<GenPolynomial<C>> q, r, x, qs, rs; 217 if (f > e) { 218 r = P; 219 q = S; 220 long g = f; 221 f = e; 222 e = g; 223 } else if (f < e) { 224 q = P; 225 r = S; 226 } else { // f == e 227 if (P.leadingBaseCoefficient().degree() > S.leadingBaseCoefficient().degree()) { 228 q = P; 229 r = S; 230 } else { 231 r = P; 232 q = S; 233 } 234 } 235 if (debug) { 236 logger.debug("degrees: e = " + e + ", f = " + f); 237 } 238 if (field) { 239 r = PolyUtil.<C> monic(r); 240 q = PolyUtil.<C> monic(q); 241 } else { 242 r = (GenSolvablePolynomial<GenPolynomial<C>>) r.abs(); 243 q = (GenSolvablePolynomial<GenPolynomial<C>>) q.abs(); 244 } 245 GenSolvablePolynomial<C> a = rightRecursiveContent(r); 246 rs = FDUtil.<C> recursiveLeftDivide(r, a); 247 if (debug) { 248 logger.info("recCont a = " + a + ", r = " + r); 249 logger.info("recCont r/a = " + rs + ", r%a = " + r.subtract(rs.multiply(a))); 250 if (!r.equals(rs.multiply(a))) { 251 System.out.println("recGcd, r = " + r); 252 System.out.println("recGcd, cont(r) = " + a); 253 System.out.println("recGcd, pp(r) = " + rs); 254 System.out.println("recGcd, pp(r)c(r) = " + rs.multiply(a)); 255 System.out.println("recGcd, c(r)pp(r) = " + rs.multiplyLeft(a)); 256 throw new RuntimeException("recGcd, pp: not divisible"); 257 } 258 } 259 r = rs; 260 GenSolvablePolynomial<C> b = rightRecursiveContent(q); 261 qs = FDUtil.<C> recursiveLeftDivide(q, b); 262 if (debug) { 263 logger.info("recCont b = " + b + ", q = " + q); 264 logger.info("recCont q/b = " + qs + ", q%b = " + q.subtract(qs.multiply(b))); 265 if (!q.equals(qs.multiply(b))) { 266 System.out.println("recGcd, q = " + q); 267 System.out.println("recGcd, cont(q) = " + b); 268 System.out.println("recGcd, pp(q) = " + qs); 269 System.out.println("recGcd, pp(q)c(q) = " + qs.multiply(b)); 270 System.out.println("recGcd, c(q)pp(q) = " + qs.multiplyLeft(b)); 271 throw new RuntimeException("recGcd, pp: not divisible"); 272 } 273 } 274 q = qs; 275 //no: GenSolvablePolynomial<C> c = leftGcd(a, b); // go to recursion 276 GenSolvablePolynomial<C> c = rightGcd(a, b); // go to recursion 277 logger.info("Gcd(contents) c = " + c + ", a = " + a + ", b = " + b); 278 if (r.isONE()) { 279 return r.multiply(c); 280 } 281 if (q.isONE()) { 282 return q.multiply(c); 283 } 284 if (debug) { 285 logger.info("r.ring = " + r.ring.toScript()); 286 } 287 while (!r.isZERO()) { 288 x = FDUtil.<C> recursiveSparsePseudoRemainder(q, r); 289 q = r; 290 r = rightRecursivePrimitivePart(x); 291 if (field) { 292 r = PolyUtil.<C> monic(r); 293 } 294 } 295 if (debug) { 296 logger.info("gcd(pp) = " + q + ", ring = " + P.ring.toScript()); 297 } 298 q = (GenSolvablePolynomial<GenPolynomial<C>>) q.multiply(c).abs(); 299 return q; 300 } 301 302 303 /** 304 * Univariate GenSolvablePolynomial right recursive greatest common divisor. 305 * Uses pseudoRemainder for remainder. 306 * @param P univariate recursive GenSolvablePolynomial. 307 * @param S univariate recursive GenSolvablePolynomial. 308 * @return gcd(P,S) with P = p*gcd(P,S)*P' and S = s*gcd(P,S)*S', where 309 * deg_main(p) = deg_main(s) == 0. 310 */ 311 @Override 312 public GenSolvablePolynomial<GenPolynomial<C>> rightRecursiveUnivariateGcd( 313 GenSolvablePolynomial<GenPolynomial<C>> P, GenSolvablePolynomial<GenPolynomial<C>> S) { 314 if (S == null || S.isZERO()) { 315 return P; 316 } 317 if (P == null || P.isZERO()) { 318 return S; 319 } 320 if (P.ring.nvar > 1) { 321 throw new IllegalArgumentException("no univariate polynomial"); 322 } 323 boolean field = P.leadingBaseCoefficient().ring.coFac.isField(); 324 long e = P.degree(0); 325 long f = S.degree(0); 326 GenSolvablePolynomial<GenPolynomial<C>> q, r, x, qs, rs; 327 if (f > e) { 328 r = P; 329 q = S; 330 long g = f; 331 f = e; 332 e = g; 333 } else if (f < e) { 334 q = P; 335 r = S; 336 } else { // f == e 337 if (P.leadingBaseCoefficient().degree() > S.leadingBaseCoefficient().degree()) { 338 q = P; 339 r = S; 340 } else { 341 r = P; 342 q = S; 343 } 344 } 345 if (debug) { 346 logger.debug("RI-degrees: e = " + e + ", f = " + f); 347 } 348 if (field) { 349 r = PolyUtil.<C> monic(r); 350 q = PolyUtil.<C> monic(q); 351 } else { 352 r = (GenSolvablePolynomial<GenPolynomial<C>>) r.abs(); 353 q = (GenSolvablePolynomial<GenPolynomial<C>>) q.abs(); 354 } 355 GenSolvablePolynomial<C> a = leftRecursiveContent(r); 356 rs = FDUtil.<C> recursiveRightDivide(r, a); 357 if (debug) { 358 logger.info("RI-recCont a = " + a + ", r = " + r); 359 logger.info("RI-recCont r/a = " + r + ", r%a = " + r.subtract(rs.multiplyLeft(a))); 360 if (!r.equals(rs.multiplyLeft(a))) { 361 System.out.println("RI-recGcd, r = " + r); 362 System.out.println("RI-recGcd, cont(r) = " + a); 363 System.out.println("RI-recGcd, pp(r) = " + rs); 364 System.out.println("RI-recGcd, c(r)pp(r) = " + rs.multiplyLeft(a)); 365 throw new RuntimeException("RI-recGcd, pp: not divisible"); 366 } 367 } 368 r = rs; 369 GenSolvablePolynomial<C> b = leftRecursiveContent(q); 370 qs = FDUtil.<C> recursiveRightDivide(q, b); 371 if (debug) { 372 logger.info("RI-recCont b = " + b + ", q = " + q); 373 logger.info("RI-recCont q/b = " + qs + ", q%b = " + q.subtract(qs.multiplyLeft(b))); 374 if (!q.equals(qs.multiplyLeft(b))) { 375 System.out.println("RI-recGcd, q = " + q); 376 System.out.println("RI-recGcd, cont(q) = " + b); 377 System.out.println("RI-recGcd, pp(q) = " + qs); 378 System.out.println("RI-recGcd, c(q)pp(q) = " + qs.multiplyLeft(b)); 379 throw new RuntimeException("RI-recGcd, pp: not divisible"); 380 } 381 } 382 q = qs; 383 //no: GenSolvablePolynomial<C> c = rightGcd(a, b); // go to recursion 384 GenSolvablePolynomial<C> c = leftGcd(a, b); // go to recursion 385 logger.info("RI-Gcd(contents) c = " + c + ", a = " + a + ", b = " + b); 386 if (r.isONE()) { 387 return r.multiplyLeft(c); 388 } 389 if (q.isONE()) { 390 return q.multiplyLeft(c); 391 } 392 if (debug) { 393 logger.info("RI-r.ring = " + r.ring.toScript()); 394 } 395 while (!r.isZERO()) { 396 x = FDUtil.<C> recursiveRightSparsePseudoRemainder(q, r); 397 q = r; 398 r = leftRecursivePrimitivePart(x); 399 if (field) { 400 r = PolyUtil.<C> monic(r); 401 } 402 } 403 if (debug) { 404 logger.info("RI-gcd(pp) = " + q + ", ring = " + P.ring.toScript()); 405 } 406 q = (GenSolvablePolynomial<GenPolynomial<C>>) q.multiplyLeft(c).abs(); 407 return q; 408 } 409 410}