001/* 002 * $Id$ 003 */ 004 005package edu.jas.fd; 006 007 008import org.apache.logging.log4j.Logger; 009import org.apache.logging.log4j.LogManager; 010 011import edu.jas.poly.GenPolynomial; 012import edu.jas.poly.GenSolvablePolynomial; 013import edu.jas.poly.PolyUtil; 014import edu.jas.structure.GcdRingElem; 015import edu.jas.structure.RingFactory; 016 017 018/** 019 * (Non-unique) factorization domain greatest common divisor common algorithms 020 * with monic polynomial remainder sequence. If C is a field, then the monic PRS 021 * (on coefficients) is computed otherwise no simplifications in the reduction 022 * are made. 023 * @param <C> coefficient type 024 * @author Heinz Kredel 025 */ 026 027public class GreatestCommonDivisorSimple<C extends GcdRingElem<C>> extends GreatestCommonDivisorAbstract<C> { 028 029 030 private static final Logger logger = LogManager.getLogger(GreatestCommonDivisorSimple.class); 031 032 033 private static final boolean debug = logger.isDebugEnabled(); 034 035 036 /** 037 * Constructor. 038 * @param cf coefficient ring. 039 */ 040 public GreatestCommonDivisorSimple(RingFactory<C> cf) { 041 super(cf); 042 } 043 044 045 /** 046 * Univariate GenSolvablePolynomial greatest common divisor. Uses 047 * pseudoRemainder for remainder. 048 * @param P univariate GenSolvablePolynomial. 049 * @param S univariate GenSolvablePolynomial. 050 * @return gcd(P,S) with P = P'*gcd(P,S) and S = S'*gcd(P,S). 051 */ 052 @Override 053 public GenSolvablePolynomial<C> leftBaseGcd(GenSolvablePolynomial<C> P, GenSolvablePolynomial<C> S) { 054 if (S == null || S.isZERO()) { 055 return P; 056 } 057 if (P == null || P.isZERO()) { 058 return S; 059 } 060 if (P.ring.nvar > 1) { 061 throw new IllegalArgumentException(this.getClass().getName() + " no univariate polynomial"); 062 } 063 boolean field = P.ring.coFac.isField(); 064 long e = P.degree(0); 065 long f = S.degree(0); 066 GenSolvablePolynomial<C> q; 067 GenSolvablePolynomial<C> r; 068 if (f > e) { 069 r = P; 070 q = S; 071 long g = f; 072 f = e; 073 e = g; 074 } else { 075 q = P; 076 r = S; 077 } 078 logger.debug("degrees: e = {}, f = {}", e, f); 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 = x; 110 } 111 //System.out.println("baseGCD: q = " + q); 112 //System.out.println("baseGCD: r = " + r); 113 } 114 ///q = leftBasePrimitivePart(q); 115 q = rightBasePrimitivePart(q); 116 return (GenSolvablePolynomial<C>) (q.multiply(c)).abs(); 117 } 118 119 120 /** 121 * Univariate GenSolvablePolynomial right greatest common divisor. Uses 122 * pseudoRemainder for remainder. 123 * @param P univariate GenSolvablePolynomial. 124 * @param S univariate GenSolvablePolynomial. 125 * @return gcd(P,S) with P = gcd(P,S)*P' and S = gcd(P,S)*S'. 126 */ 127 @Override 128 public GenSolvablePolynomial<C> rightBaseGcd(GenSolvablePolynomial<C> P, GenSolvablePolynomial<C> S) { 129 if (S == null || S.isZERO()) { 130 return P; 131 } 132 if (P == null || P.isZERO()) { 133 return S; 134 } 135 if (P.ring.nvar > 1) { 136 throw new IllegalArgumentException(this.getClass().getName() + " no univariate polynomial"); 137 } 138 boolean field = P.ring.coFac.isField(); 139 long e = P.degree(0); 140 long f = S.degree(0); 141 GenSolvablePolynomial<C> q; 142 GenSolvablePolynomial<C> r; 143 if (f > e) { 144 r = P; 145 q = S; 146 long g = f; 147 f = e; 148 e = g; 149 } else { 150 q = P; 151 r = S; 152 } 153 logger.debug("degrees: e = {}, f = {}", e, f); 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 = x; 185 } 186 //System.out.println("baseGCD: q = " + q); 187 //System.out.println("baseGCD: r = " + r); 188 } 189 ///q = rightBasePrimitivePart(q); 190 q = leftBasePrimitivePart(q); 191 return (GenSolvablePolynomial<C>) (q.multiplyLeft(c)).abs(); 192 } 193 194 195 /** 196 * Univariate GenSolvablePolynomial left recursive greatest common divisor. 197 * Uses pseudoRemainder for remainder. 198 * @param P univariate recursive GenSolvablePolynomial. 199 * @param S univariate recursive GenSolvablePolynomial. 200 * @return gcd(P,S) with P = P'*gcd(P,S)*p and S = S'*gcd(P,S)*s, where 201 * deg_main(p) = deg_main(s) == 0. 202 */ 203 @Override 204 public GenSolvablePolynomial<GenPolynomial<C>> leftRecursiveUnivariateGcd( 205 GenSolvablePolynomial<GenPolynomial<C>> P, GenSolvablePolynomial<GenPolynomial<C>> S) { 206 if (S == null || S.isZERO()) { 207 return P; 208 } 209 if (P == null || P.isZERO()) { 210 return S; 211 } 212 if (P.ring.nvar > 1) { 213 throw new IllegalArgumentException("no univariate polynomial"); 214 } 215 boolean field = P.leadingBaseCoefficient().ring.coFac.isField(); 216 long e = P.degree(0); 217 long f = S.degree(0); 218 GenSolvablePolynomial<GenPolynomial<C>> q, r, x, qs, rs, qp, rp; 219 if (f > e) { 220 r = P; 221 q = S; 222 long g = f; 223 f = e; 224 e = g; 225 } else if (f < e) { 226 q = P; 227 r = S; 228 } else { // f == e 229 if (P.leadingBaseCoefficient().degree() > S.leadingBaseCoefficient().degree()) { 230 q = P; 231 r = S; 232 } else { 233 r = P; 234 q = S; 235 } 236 } 237 logger.debug("degrees: e = {}, f = {}", e, f); 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> recursiveDivideRightEval(r, a); 247 rs = FDUtil.<C> recursiveLeftDivide(r, a); 248 //rs = FDUtil.<C> recursiveRightDivide(r, a); 249 if (debug) { 250 logger.info("recCont a = {}, r = {}", a, r); 251 logger.info("recCont r/a = {}, r%a = {}", rs, r.subtract(rs.multiply(a))); 252 if (!r.equals(rs.multiply(a))) { 253 if (!rs.multiplyLeft(a).equals(r)) { 254 System.out.println("recGcd, r = " + r); 255 System.out.println("recGcd, cont(r) = " + a); 256 System.out.println("recGcd, pp(r) = " + rs); 257 System.out.println("recGcd, pp(r)c(r) = " + rs.multiply(a)); 258 System.out.println("recGcd, c(r)pp(r) = " + rs.multiplyLeft(a)); 259 throw new RuntimeException("recGcd, pp: not divisible"); 260 } 261 } 262 } 263 r = rs; 264 GenSolvablePolynomial<C> b = rightRecursiveContent(q); 265 ///qs = FDUtil.<C> recursiveDivideRightEval(q, b); 266 qs = FDUtil.<C> recursiveLeftDivide(q, b); 267 //qs = FDUtil.<C> recursiveRightDivide(q, b); 268 if (debug) { 269 logger.info("recCont b = {}, q = {}", b, q); 270 logger.info("recCont q/b = {}, q%b = {}", qs, q.subtract(qs.multiply(b))); 271 if (!q.equals(qs.multiply(b))) { 272 if (!qs.multiplyLeft(b).equals(q)) { 273 System.out.println("recGcd, q = " + q); 274 System.out.println("recGcd, cont(q) = " + b); 275 System.out.println("recGcd, pp(q) = " + qs); 276 System.out.println("recGcd, pp(q)c(q) = " + qs.multiply(b)); 277 System.out.println("recGcd, c(q)pp(q) = " + qs.multiplyLeft(b)); 278 throw new RuntimeException("recGcd, pp: not divisible"); 279 } 280 } 281 } 282 q = qs; 283 logger.info("Gcd(content).ring = {}, a = {}, b = {}", a.ring.toScript(), a, b); 284 //no: GenSolvablePolynomial<C> c = leftGcd(a, b); // go to recursion 285 GenSolvablePolynomial<C> c = rightGcd(a, b); // go to recursion 286 logger.info("Gcd(contents) c = {}, a = {}, b = {}", c, a, b); 287 if (r.isONE()) { 288 return r.multiply(c); 289 } 290 if (q.isONE()) { 291 return q.multiply(c); 292 } 293 if (debug) { 294 logger.info("r.ring = {}", r.ring.toScript()); 295 logger.info("gcd-loop, start: q = {}, r = {}", q, r); 296 } 297 while (!r.isZERO()) { 298 x = FDUtil.<C> recursiveSparsePseudoRemainder(q, r); 299 q = r; 300 if (field) { 301 r = PolyUtil.<C> monic(x); 302 } else { 303 r = x; 304 } 305 if (debug) { 306 logger.info("gcd-loop, rem: q = {}, r = {}", q, r); 307 } 308 } 309 if (debug) { 310 logger.info("gcd(div) = {}, rs = {}, qs = {}", q, rs, qs); 311 rp = FDUtil.<C> recursiveSparsePseudoRemainder(rs, q); 312 qp = FDUtil.<C> recursiveSparsePseudoRemainder(qs, q); 313 if (!qp.isZERO() || !rp.isZERO()) { 314 logger.info("gcd(div): rem(r,g) = {}, rem(q,g) = {}", rp, qp); 315 rp = FDUtil.<C> recursivePseudoQuotient(rs, q); 316 qp = FDUtil.<C> recursivePseudoQuotient(qs, q); 317 logger.info("gcd(div): r/g = {}, q/g = {}", rp, qp); 318 throw new RuntimeException("recGcd, div: not divisible"); 319 } 320 } 321 qp = q; 322 q = rightRecursivePrimitivePart(q); 323 if (!qp.equals(q)) { 324 logger.info("gcd(pp) = {}, qp = {}", q, qp); 325 } 326 q = (GenSolvablePolynomial<GenPolynomial<C>>) q.multiply(c).abs(); 327 return q; 328 } 329 330 331 /** 332 * Univariate GenSolvablePolynomial right recursive greatest common divisor. 333 * Uses pseudoRemainder for remainder. 334 * @param P univariate recursive GenSolvablePolynomial. 335 * @param S univariate recursive GenSolvablePolynomial. 336 * @return gcd(P,S) with P = p*gcd(P,S)*P' and S = s*gcd(P,S)*S', where 337 * deg_main(p) = deg_main(s) == 0. 338 */ 339 @Override 340 public GenSolvablePolynomial<GenPolynomial<C>> rightRecursiveUnivariateGcd( 341 GenSolvablePolynomial<GenPolynomial<C>> P, GenSolvablePolynomial<GenPolynomial<C>> S) { 342 if (S == null || S.isZERO()) { 343 return P; 344 } 345 if (P == null || P.isZERO()) { 346 return S; 347 } 348 if (P.ring.nvar > 1) { 349 throw new IllegalArgumentException("no univariate polynomial"); 350 } 351 boolean field = P.leadingBaseCoefficient().ring.coFac.isField(); 352 long e = P.degree(0); 353 long f = S.degree(0); 354 GenSolvablePolynomial<GenPolynomial<C>> q, r, x, qs, rs, qp, rp; 355 if (f > e) { 356 r = P; 357 q = S; 358 long g = f; 359 f = e; 360 e = g; 361 } else if (f < e) { 362 q = P; 363 r = S; 364 } else { // f == e 365 if (P.leadingBaseCoefficient().degree() > S.leadingBaseCoefficient().degree()) { 366 q = P; 367 r = S; 368 } else { 369 r = P; 370 q = S; 371 } 372 } 373 if (debug) { 374 logger.debug("RI-degrees: e = {}, f = {}", e, f); 375 } 376 if (field) { 377 r = PolyUtil.<C> monic(r); 378 q = PolyUtil.<C> monic(q); 379 } else { 380 r = (GenSolvablePolynomial<GenPolynomial<C>>) r.abs(); 381 q = (GenSolvablePolynomial<GenPolynomial<C>>) q.abs(); 382 } 383 GenSolvablePolynomial<C> a = leftRecursiveContent(r); 384 rs = FDUtil.<C> recursiveRightDivide(r, a); 385 //no: rs = FDUtil.<C> recursiveLeftDivide(r, a); 386 //no: rs = FDUtil.<C> recursiveRightPseudoQuotient(r, a); 387 if (debug) { 388 logger.info("RI-recCont a = {}, r = {}", a, r); 389 logger.info("RI-recCont r/a = {}, r%a = {}", r, r.subtract(rs.multiplyLeft(a))); 390 if (!r.equals(rs.multiplyLeft(a))) { // Left 391 System.out.println("RI-recGcd, r = " + r); 392 System.out.println("RI-recGcd, cont(r) = " + a); 393 System.out.println("RI-recGcd, pp(r) = " + rs); 394 System.out.println("RI-recGcd, pp(r)c(r) = " + rs.multiply(a)); 395 System.out.println("RI-recGcd, c(r)pp(r) = " + rs.multiplyLeft(a)); 396 throw new RuntimeException("RI-recGcd, pp: not divisible"); 397 } 398 } 399 r = rs; 400 GenSolvablePolynomial<C> b = leftRecursiveContent(q); 401 qs = FDUtil.<C> recursiveRightDivide(q, b); 402 if (debug) { 403 logger.info("RI-recCont b = {}, q = {}", b, q); 404 logger.info("RI-recCont q/b = {}, q%b = {}", qs, q.subtract(qs.multiplyLeft(b))); 405 if (!q.equals(qs.multiplyLeft(b))) { // Left 406 System.out.println("RI-recGcd, q = " + q); 407 System.out.println("RI-recGcd, cont(q) = " + b); 408 System.out.println("RI-recGcd, pp(q) = " + qs); 409 System.out.println("RI-recGcd, pp(q)c(q) = " + qs.multiply(b)); 410 System.out.println("RI-recGcd, c(q)pp(q) = " + qs.multiplyLeft(b)); 411 throw new RuntimeException("RI-recGcd, pp: not divisible"); 412 } 413 } 414 q = qs; 415 //no: GenSolvablePolynomial<C> c = rightGcd(a, b); // go to recursion 416 GenSolvablePolynomial<C> c = leftGcd(a, b); // go to recursion 417 logger.info("RI-Gcd(contents) c = {}, a = {}, b = {}", c, a, b); 418 if (r.isONE()) { 419 return r.multiplyLeft(c); 420 } 421 if (q.isONE()) { 422 return q.multiplyLeft(c); 423 } 424 if (debug) { 425 logger.info("RI-r.ring = {}", r.ring.toScript()); 426 logger.info("RI-gcd-loop, start: q = {}, r = {}", q, r); 427 } 428 while (!r.isZERO()) { 429 x = FDUtil.<C> recursiveRightSparsePseudoRemainder(q, r); 430 q = r; 431 if (field) { 432 r = PolyUtil.<C> monic(x); 433 } else { 434 r = x; 435 } 436 if (debug) { 437 logger.info("RI-gcd-loop, rem: q = {}, r = {}", q, r); 438 } 439 } 440 if (debug) { 441 logger.info("RI-gcd(div) = {}, rs = {}, qs = {}", q, rs, qs); 442 rp = FDUtil.<C> recursiveRightSparsePseudoRemainder(rs, q); 443 qp = FDUtil.<C> recursiveRightSparsePseudoRemainder(qs, q); 444 if (!qp.isZERO() || !rp.isZERO()) { 445 logger.info("RI-gcd(div): rem(r,g) = {}, rem(q,g) = {}", rp, qp); 446 rp = FDUtil.<C> recursivePseudoQuotient(rs, q); 447 qp = FDUtil.<C> recursivePseudoQuotient(qs, q); 448 logger.info("RI-gcd(div): r/g = {}, q/g = {}", rp, qp); 449 //logger.info("gcd(div): rp*g = {}, qp*g = {}", rp.multiply(q), qp.multiply(q)); 450 throw new RuntimeException("recGcd, div: not divisible"); 451 } 452 } 453 qp = q; 454 logger.info("RI-recGcd(P,S) pre pp okay: qp = {}", qp); 455 //q = rightRecursivePrimitivePart(q); 456 q = leftRecursivePrimitivePart(q); // sic 457 if (!qp.equals(q)) { 458 logger.info("RI-gcd(pp) = {}, qp = {}", q, qp); // + ", ring = {}", P.ring.toScript()); 459 } 460 q = (GenSolvablePolynomial<GenPolynomial<C>>) q.multiplyLeft(c).abs(); 461 return q; 462 } 463 464}