001/* 002 * $Id: GreatestCommonDivisorAbstract.java 5280 2015-07-30 16:18:15Z kredel $ 003 */ 004 005package edu.jas.fd; 006 007 008import java.util.ArrayList; 009import java.util.Arrays; 010import java.util.List; 011 012import org.apache.log4j.Logger; 013 014import edu.jas.gbufd.SolvableSyzygyAbstract; 015import edu.jas.gbufd.SolvableSyzygySeq; 016import edu.jas.poly.GenPolynomial; 017import edu.jas.poly.GenSolvablePolynomial; 018import edu.jas.poly.GenSolvablePolynomialRing; 019import edu.jas.poly.PolyUtil; 020import edu.jas.poly.RecSolvablePolynomial; 021import edu.jas.poly.RecSolvablePolynomialRing; 022import edu.jas.structure.GcdRingElem; 023import edu.jas.structure.RingFactory; 024import edu.jas.ufd.GCDFactory; 025 026 027/** 028 * (Non-unique) factorization domain greatest common divisor common algorithms. 029 * @param <C> coefficient type 030 * @author Heinz Kredel 031 */ 032 033public abstract class GreatestCommonDivisorAbstract<C extends GcdRingElem<C>> implements 034 GreatestCommonDivisor<C> { 035 036 037 private static final Logger logger = Logger.getLogger(GreatestCommonDivisorAbstract.class); 038 039 040 private final boolean debug = true; // logger.isDebugEnabled(); 041 042 043 /** 044 * Engine for syzygy computation. 045 */ 046 final SolvableSyzygyAbstract<C> syz; 047 048 049 /* 050 * Engine for commutative gcd computation. 051 */ 052 //edu.jas.ufd.GreatestCommonDivisorAbstract<C> cgcd; 053 054 055 /** 056 * Constructor. 057 * @param cf coefficient ring. 058 */ 059 public GreatestCommonDivisorAbstract(RingFactory<C> cf) { 060 syz = new SolvableSyzygySeq<C>(cf); 061 //cgcd = GCDFactory.<C> getImplementation(pfac.coFac); 062 } 063 064 065 /** 066 * Get the String representation. 067 * @see java.lang.Object#toString() 068 */ 069 @Override 070 public String toString() { 071 return getClass().getName(); 072 } 073 074 075 /** 076 * GenSolvablePolynomial base coefficient content. 077 * @param P GenSolvablePolynomial. 078 * @return cont(P) with pp(P)*cont(P) = P. 079 */ 080 public C leftBaseContent(GenSolvablePolynomial<C> P) { 081 if (P == null) { 082 throw new IllegalArgumentException("P == null"); 083 } 084 if (P.isZERO()) { 085 return P.ring.getZEROCoefficient(); 086 } 087 C d = null; 088 for (C c : P.getMap().values()) { 089 if (d == null) { 090 d = c; 091 } else { 092 d = d.gcd(c); 093 } 094 if (d.isONE()) { 095 return d; 096 } 097 } 098 if (d.signum() < 0) { 099 d = d.negate(); 100 } 101 return d; 102 } 103 104 105 /** 106 * GenSolvablePolynomial right base coefficient content. 107 * @param P GenSolvablePolynomial. 108 * @return cont(P) with cont(P)*pp(P) = P. 109 */ 110 public C rightBaseContent(GenSolvablePolynomial<C> P) { 111 if (P == null) { 112 throw new IllegalArgumentException("P == null"); 113 } 114 if (P.isZERO()) { 115 return P.ring.getZEROCoefficient(); 116 } 117 C d = null; 118 for (C c : P.getMap().values()) { 119 if (d == null) { 120 d = c; 121 } else { 122 d = d.gcd(c); // TODO does not exist 123 } 124 if (d.isONE()) { 125 return d; 126 } 127 } 128 if (d.signum() < 0) { 129 d = d.negate(); 130 } 131 return d; 132 } 133 134 135 /** 136 * GenSolvablePolynomial base coefficient primitive part. 137 * @param P GenSolvablePolynomial. 138 * @return pp(P) with pp(P)*cont(P) = P. 139 */ 140 public GenSolvablePolynomial<C> leftBasePrimitivePart(GenSolvablePolynomial<C> P) { 141 if (P == null) { 142 throw new IllegalArgumentException("P == null"); 143 } 144 if (P.isZERO()) { 145 return P; 146 } 147 C d = leftBaseContent(P); 148 if (d.isONE()) { 149 return P; 150 } 151 GenSolvablePolynomial<C> pp = (GenSolvablePolynomial<C>) P.divide(d); 152 if (debug) { 153 GenSolvablePolynomial<C> p = pp.multiply(d); 154 if (!p.equals(P)) { 155 throw new ArithmeticException("pp(p)*cont(p) != p: "); 156 } 157 } 158 return pp; 159 } 160 161 162 /** 163 * GenSolvablePolynomial right base coefficient primitive part. 164 * @param P GenSolvablePolynomial. 165 * @return pp(P) with cont(P)*pp(P) = P. 166 */ 167 public GenSolvablePolynomial<C> rightBasePrimitivePart(GenSolvablePolynomial<C> P) { 168 if (P == null) { 169 throw new IllegalArgumentException("P == null"); 170 } 171 if (P.isZERO()) { 172 return P; 173 } 174 C d = rightBaseContent(P); 175 if (d.isONE()) { 176 return P; 177 } 178 GenSolvablePolynomial<C> pp = (GenSolvablePolynomial<C>) P.divide(d); // TODO 179 if (debug) { 180 GenSolvablePolynomial<C> p = pp.multiplyLeft(d); 181 if (!p.equals(P)) { 182 throw new ArithmeticException("pp(p)*cont(p) != p: "); 183 } 184 } 185 return pp; 186 } 187 188 189 /** 190 * Univariate GenSolvablePolynomial greatest common divisor. Uses sparse 191 * pseudoRemainder for remainder. 192 * @param P univariate GenSolvablePolynomial. 193 * @param S univariate GenSolvablePolynomial. 194 * @return gcd(P,S) with P = P'*gcd(P,S) and S = S'*gcd(P,S). 195 */ 196 public abstract GenSolvablePolynomial<C> leftBaseGcd(GenSolvablePolynomial<C> P, 197 GenSolvablePolynomial<C> S); 198 199 200 /** 201 * Univariate GenSolvablePolynomial right greatest common divisor. Uses 202 * sparse pseudoRemainder for remainder. 203 * @param P univariate GenSolvablePolynomial. 204 * @param S univariate GenSolvablePolynomial. 205 * @return gcd(P,S) with P = gcd(P,S)*P' and S = gcd(P,S)*S'. 206 */ 207 public abstract GenSolvablePolynomial<C> rightBaseGcd(GenSolvablePolynomial<C> P, 208 GenSolvablePolynomial<C> S); 209 210 211 /** 212 * GenSolvablePolynomial commuting recursive content. 213 * @param P recursive GenSolvablePolynomial with commuting main and 214 * coefficient variables. 215 * @return cont(P) with cont(P)*pp(P) = pp(P)*cont(P). 216 */ 217 public GenSolvablePolynomial<C> recursiveContent(GenSolvablePolynomial<GenPolynomial<C>> P) { 218 if (P == null) { 219 throw new IllegalArgumentException("P == null"); 220 } 221 if (P instanceof RecSolvablePolynomial) { 222 RecSolvablePolynomialRing<C> rfac = (RecSolvablePolynomialRing<C>) P.ring; 223 if (!rfac.coeffTable.isEmpty()) { 224 throw new IllegalArgumentException("P is a RecSolvablePolynomial, use recursiveContent()"); 225 } 226 } 227 if (P.isZERO()) { 228 return (GenSolvablePolynomial<C>) P.ring.getZEROCoefficient(); 229 } 230 if (P.isONE()) { 231 return (GenSolvablePolynomial<C>) P.ring.getONECoefficient(); 232 } 233 if (P.leadingBaseCoefficient().isONE()) { 234 return (GenSolvablePolynomial<C>) P.ring.getONECoefficient(); 235 } 236 //GenSolvablePolynomial<GenPolynomial<C>> p = P; 237 GenSolvablePolynomial<C> d = null; 238 for (GenPolynomial<C> cp : P.getMap().values()) { 239 GenSolvablePolynomial<C> c = (GenSolvablePolynomial<C>) cp; 240 if (d == null) { 241 d = c; 242 } else { 243 d = leftGcd(d, c); // go to recursion 244 } 245 if (d.isONE()) { 246 return d; 247 } 248 } 249 return (GenSolvablePolynomial<C>) d.abs(); 250 } 251 252 253 /** 254 * GenSolvablePolynomial right recursive content. 255 * @param P recursive GenSolvablePolynomial. 256 * @return cont(P) with pp(P)*cont(P) = P. 257 */ 258 public GenSolvablePolynomial<C> rightRecursiveContent(GenSolvablePolynomial<GenPolynomial<C>> P) { 259 if (P == null) { 260 throw new IllegalArgumentException("P != null"); 261 } 262 if (P.isZERO()) { 263 return (GenSolvablePolynomial<C>) P.ring.getZEROCoefficient(); 264 } 265 if (P.leadingBaseCoefficient().isONE()) { 266 return (GenSolvablePolynomial<C>) P.ring.getONECoefficient(); 267 } 268 GenSolvablePolynomial<C> d = null, cs = null; 269 GenSolvablePolynomial<GenPolynomial<C>> Pr = P.rightRecursivePolynomial(); 270 logger.info("RI-recCont: P = " + P + ", right(P) = " + Pr); 271 for (GenPolynomial<C> c : Pr.getMap().values()) { 272 cs = (GenSolvablePolynomial<C>) c; 273 if (d == null) { 274 d = cs; 275 } else { 276 d = leftGcd(d, cs); // go to recursion 277 logger.info("RI-recCont: cs = " + cs + ", d = " + d); 278 } 279 if (d.isONE()) { 280 return d; 281 } 282 } 283 return (GenSolvablePolynomial<C>) d.abs(); 284 } 285 286 287 /** 288 * GenSolvablePolynomial right recursive primitive part. 289 * @param P recursive GenSolvablePolynomial. 290 * @return pp(P) with pp(P)*cont(P) = P. 291 */ 292 public GenSolvablePolynomial<GenPolynomial<C>> rightRecursivePrimitivePart( 293 GenSolvablePolynomial<GenPolynomial<C>> P) { 294 if (P == null) { 295 throw new IllegalArgumentException("P == null"); 296 } 297 if (P.isZERO()) { 298 return P; 299 } 300 GenSolvablePolynomial<C> d = rightRecursiveContent(P); 301 if (d.isONE()) { 302 return P; 303 } 304 GenSolvablePolynomial<GenPolynomial<C>> pp; 305 pp = FDUtil.<C> recursiveDivideRightEval(P, d); 306 if (false) { // not checkable 307 if (!P.equals(pp.multiply(d))) { 308 System.out.println("RI-ppart, P = " + P); 309 System.out.println("RI-ppart, cont(P) = " + d); 310 System.out.println("RI-ppart, pp(P) = " + pp); 311 System.out.println("RI-ppart, pp(P)c(P) = " + pp.multiply(d)); 312 throw new RuntimeException("RI-primitivePart: P != pp(P)*cont(P)"); 313 } 314 } 315 return pp; 316 } 317 318 319 /** 320 * GenSolvablePolynomial left recursive content. 321 * @param P recursive GenSolvablePolynomial. 322 * @return cont(P) with cont(P)*pp(P) = P. 323 */ 324 public GenSolvablePolynomial<C> leftRecursiveContent(GenSolvablePolynomial<GenPolynomial<C>> P) { 325 if (P == null) { 326 throw new IllegalArgumentException("P != null"); 327 } 328 if (P.isZERO()) { 329 return (GenSolvablePolynomial<C>) P.ring.getZEROCoefficient(); 330 } 331 if (P.leadingBaseCoefficient().isONE()) { 332 return (GenSolvablePolynomial<C>) P.ring.getONECoefficient(); 333 } 334 GenSolvablePolynomial<C> d = null, cs = null; 335 GenSolvablePolynomial<GenPolynomial<C>> Pr = P; //FDUtil.<C> rightRecursivePolynomial(P); 336 logger.info("recCont: P = " + P + ", right(P) = " + Pr); 337 for (GenPolynomial<C> c : Pr.getMap().values()) { 338 cs = (GenSolvablePolynomial<C>) c; 339 if (d == null) { 340 d = cs; 341 } else { 342 d = rightGcd(d, cs); // go to recursion 343 logger.info("recCont: cs = " + cs + ", d = " + d); 344 } 345 if (d.isONE()) { 346 return d; 347 } 348 } 349 return (GenSolvablePolynomial<C>) d.abs(); 350 } 351 352 353 /** 354 * GenSolvablePolynomial left recursive primitive part. 355 * @param P recursive GenSolvablePolynomial. 356 * @return pp(P) with cont(P)*pp(P) = P. 357 */ 358 public GenSolvablePolynomial<GenPolynomial<C>> leftRecursivePrimitivePart( 359 GenSolvablePolynomial<GenPolynomial<C>> P) { 360 if (P == null) { 361 throw new IllegalArgumentException("P == null"); 362 } 363 if (P.isZERO()) { 364 return P; 365 } 366 GenSolvablePolynomial<C> d = leftRecursiveContent(P); 367 if (d.isONE()) { 368 return P; 369 } 370 GenSolvablePolynomial<GenPolynomial<C>> pp; 371 pp = FDUtil.<C> recursiveDivide(P, d); 372 if (false) { // not checkable 373 if (!P.equals(pp.multiplyLeft(d))) { 374 System.out.println("ppart, P = " + P); 375 System.out.println("ppart, cont(P) = " + d); 376 System.out.println("ppart, pp(P) = " + pp); 377 System.out.println("ppart, pp(P)c(P) = " + pp.multiplyLeft(d)); 378 throw new RuntimeException("primitivePart: P != cont(P)*pp(P)"); 379 } 380 } 381 return pp; 382 } 383 384 385 /** 386 * GenSolvablePolynomial base recursive content. 387 * @param P recursive GenSolvablePolynomial. 388 * @return baseCont(P) with pp(P)*cont(P) = P. 389 */ 390 public C baseRecursiveContent(GenSolvablePolynomial<GenPolynomial<C>> P) { 391 if (P == null) { 392 throw new IllegalArgumentException("P == null"); 393 } 394 if (P.isZERO()) { 395 GenSolvablePolynomialRing<C> cf = (GenSolvablePolynomialRing<C>) P.ring.coFac; 396 return cf.coFac.getZERO(); 397 } 398 C d = null; 399 for (GenPolynomial<C> cp : P.getMap().values()) { 400 GenSolvablePolynomial<C> c = (GenSolvablePolynomial<C>) cp; 401 C cc = leftBaseContent(c); 402 if (d == null) { 403 d = cc; 404 } else { 405 d = gcd(d, cc); 406 } 407 if (d.isONE()) { 408 return d; 409 } 410 } 411 return d.abs(); 412 } 413 414 415 /** 416 * GenSolvablePolynomial base recursive primitive part. 417 * @param P recursive GenSolvablePolynomial. 418 * @return basePP(P) with pp(P)*cont(P) = P. 419 */ 420 public GenSolvablePolynomial<GenPolynomial<C>> baseRecursivePrimitivePart( 421 GenSolvablePolynomial<GenPolynomial<C>> P) { 422 if (P == null) { 423 throw new IllegalArgumentException("P == null"); 424 } 425 if (P.isZERO()) { 426 return P; 427 } 428 C d = baseRecursiveContent(P); 429 if (d.isONE()) { 430 return P; 431 } 432 GenSolvablePolynomial<GenPolynomial<C>> pp = (GenSolvablePolynomial<GenPolynomial<C>>) PolyUtil 433 .<C> baseRecursiveDivide(P, d); 434 return pp; 435 } 436 437 438 /** 439 * GenSolvablePolynomial left recursive greatest common divisor. Uses 440 * pseudoRemainder for remainder. 441 * @param P recursive GenSolvablePolynomial. 442 * @param S recursive GenSolvablePolynomial. 443 * @return gcd(P,S) with P = P'*gcd(P,S)*p and S = S'*gcd(P,S)*s, where 444 * deg_main(p) = deg_main(s) == 0. 445 */ 446 public GenSolvablePolynomial<GenPolynomial<C>> leftRecursiveGcd( 447 GenSolvablePolynomial<GenPolynomial<C>> P, GenSolvablePolynomial<GenPolynomial<C>> S) { 448 if (S == null || S.isZERO()) { 449 return P; 450 } 451 if (P == null || P.isZERO()) { 452 return S; 453 } 454 if (P.ring.nvar == 1) { 455 return leftRecursiveUnivariateGcd(P, S); 456 } 457 // distributed polynomials gcd 458 GenSolvablePolynomialRing<GenPolynomial<C>> rfac = P.ring; 459 GenSolvablePolynomialRing<C> dfac; 460 if (rfac instanceof RecSolvablePolynomialRing) { 461 RecSolvablePolynomialRing<C> rf = (RecSolvablePolynomialRing<C>) rfac; 462 dfac = RecSolvablePolynomialRing.<C> distribute(rf); 463 } else { 464 GenSolvablePolynomialRing<C> df = (GenSolvablePolynomialRing) rfac; 465 dfac = df.distribute(); 466 } 467 GenSolvablePolynomial<C> Pd = (GenSolvablePolynomial<C>) PolyUtil.<C> distribute(dfac, P); 468 GenSolvablePolynomial<C> Sd = (GenSolvablePolynomial<C>) PolyUtil.<C> distribute(dfac, S); 469 GenSolvablePolynomial<C> Dd = leftGcd(Pd, Sd); 470 // convert to recursive 471 GenSolvablePolynomial<GenPolynomial<C>> C = (GenSolvablePolynomial<GenPolynomial<C>>) PolyUtil 472 .<C> recursive(rfac, Dd); 473 return C; 474 } 475 476 477 /** 478 * GenSolvablePolynomial right recursive greatest common divisor. Uses 479 * pseudoRemainder for remainder. 480 * @param P recursive GenSolvablePolynomial. 481 * @param S recursive GenSolvablePolynomial. 482 * @return gcd(P,S) with P = p*gcd(P,S)*P' and S = s*gcd(P,S)*S', where 483 * deg_main(p) = deg_main(s) == 0. 484 */ 485 public GenSolvablePolynomial<GenPolynomial<C>> rightRecursiveGcd( 486 GenSolvablePolynomial<GenPolynomial<C>> P, GenSolvablePolynomial<GenPolynomial<C>> S) { 487 if (S == null || S.isZERO()) { 488 return P; 489 } 490 if (P == null || P.isZERO()) { 491 return S; 492 } 493 if (P.ring.nvar == 1) { 494 return rightRecursiveUnivariateGcd(P, S); 495 } 496 // distributed polynomials gcd 497 GenSolvablePolynomialRing<GenPolynomial<C>> rfac = P.ring; 498 GenSolvablePolynomialRing<C> dfac; 499 if (rfac instanceof RecSolvablePolynomialRing) { 500 RecSolvablePolynomialRing<C> rf = (RecSolvablePolynomialRing<C>) rfac; 501 dfac = RecSolvablePolynomialRing.<C> distribute(rf); 502 } else { 503 GenSolvablePolynomialRing<C> df = (GenSolvablePolynomialRing) rfac; 504 dfac = df.distribute(); 505 } 506 GenSolvablePolynomial<C> Pd = (GenSolvablePolynomial<C>) PolyUtil.<C> distribute(dfac, P); 507 GenSolvablePolynomial<C> Sd = (GenSolvablePolynomial<C>) PolyUtil.<C> distribute(dfac, S); 508 GenSolvablePolynomial<C> Dd = rightGcd(Pd, Sd); 509 // convert to recursive 510 GenSolvablePolynomial<GenPolynomial<C>> C = (GenSolvablePolynomial<GenPolynomial<C>>) PolyUtil 511 .<C> recursive(rfac, Dd); 512 return C; 513 } 514 515 516 /** 517 * Univariate GenSolvablePolynomial recursive greatest common divisor. Uses 518 * pseudoRemainder for remainder. 519 * @param P univariate recursive GenSolvablePolynomial. 520 * @param S univariate recursive GenSolvablePolynomial. 521 * @return gcd(P,S) with P = P'*gcd(P,S)*p and S = S'*gcd(P,S)*s, where 522 * deg_main(p) = deg_main(s) == 0. 523 */ 524 public abstract GenSolvablePolynomial<GenPolynomial<C>> leftRecursiveUnivariateGcd( 525 GenSolvablePolynomial<GenPolynomial<C>> P, GenSolvablePolynomial<GenPolynomial<C>> S); 526 527 528 /** 529 * Univariate GenSolvablePolynomial right recursive greatest common divisor. 530 * Uses pseudoRemainder for remainder. 531 * @param P univariate recursive GenSolvablePolynomial. 532 * @param S univariate recursive GenSolvablePolynomial. 533 * @return gcd(P,S) with P = p*gcd(P,S)*P' and S = s*gcd(P,S)*S', where 534 * deg_main(p) = deg_main(s) == 0. 535 */ 536 public abstract GenSolvablePolynomial<GenPolynomial<C>> rightRecursiveUnivariateGcd( 537 GenSolvablePolynomial<GenPolynomial<C>> P, GenSolvablePolynomial<GenPolynomial<C>> S); 538 539 540 /** 541 * GenSolvablePolynomial right content. 542 * @param P GenSolvablePolynomial. 543 * @return cont(P) with pp(P)*cont(P) = P. 544 */ 545 public GenSolvablePolynomial<C> rightContent(GenSolvablePolynomial<C> P) { 546 if (P == null) { 547 throw new IllegalArgumentException("P == null"); 548 } 549 GenSolvablePolynomialRing<C> pfac = P.ring; 550 if (pfac.nvar <= 1) { 551 // baseContent not possible by return type 552 throw new IllegalArgumentException("use baseContent() for univariate polynomials"); 553 } 554 GenSolvablePolynomialRing<GenPolynomial<C>> rfac // = (RecSolvablePolynomialRing<C>) 555 = pfac.recursive(1); 556 557 GenSolvablePolynomial<GenPolynomial<C>> Pr = (RecSolvablePolynomial<C>) PolyUtil.<C> recursive(rfac, 558 P); 559 GenSolvablePolynomial<C> D = rightRecursiveContent(Pr); 560 return D; 561 } 562 563 564 /** 565 * GenSolvablePolynomial right primitive part. 566 * @param P GenSolvablePolynomial. 567 * @return pp(P) with pp(P)*cont(P) = P. 568 */ 569 public GenSolvablePolynomial<C> rightPrimitivePart(GenSolvablePolynomial<C> P) { 570 if (P == null) { 571 throw new IllegalArgumentException("P == null"); 572 } 573 if (P.isZERO()) { 574 return P; 575 } 576 GenSolvablePolynomialRing<C> pfac = P.ring; 577 if (pfac.nvar <= 1) { 578 return leftBasePrimitivePart(P); 579 } 580 GenSolvablePolynomialRing<GenPolynomial<C>> rfac = /*(RecSolvablePolynomialRing<C>)*/pfac 581 .recursive(1); 582 583 GenSolvablePolynomial<GenPolynomial<C>> Pr = (RecSolvablePolynomial<C>) PolyUtil.<C> recursive(rfac, 584 P); 585 GenSolvablePolynomial<GenPolynomial<C>> PP = rightRecursivePrimitivePart(Pr); 586 587 GenSolvablePolynomial<C> D = (GenSolvablePolynomial<C>) PolyUtil.<C> distribute(pfac, PP); 588 return D; 589 } 590 591 592 /** 593 * GenSolvablePolynomial left content. 594 * @param P GenSolvablePolynomial. 595 * @return cont(P) with cont(P)*pp(P) = P. 596 */ 597 public GenSolvablePolynomial<C> leftContent(GenSolvablePolynomial<C> P) { 598 if (P == null) { 599 throw new IllegalArgumentException("P == null"); 600 } 601 GenSolvablePolynomialRing<C> pfac = P.ring; 602 if (pfac.nvar <= 1) { 603 // baseContent not possible by return type 604 throw new IllegalArgumentException("use baseContent() for univariate polynomials"); 605 } 606 GenSolvablePolynomialRing<GenPolynomial<C>> rfac // = (RecSolvablePolynomialRing<C>) 607 = pfac.recursive(1); 608 609 GenSolvablePolynomial<GenPolynomial<C>> Pr = (RecSolvablePolynomial<C>) PolyUtil.<C> recursive(rfac, 610 P); 611 GenSolvablePolynomial<C> D = leftRecursiveContent(Pr); 612 return D; 613 } 614 615 616 /** 617 * GenSolvablePolynomial left primitive part. 618 * @param P GenSolvablePolynomial. 619 * @return pp(P) with cont(P)*pp(P) = P. 620 */ 621 public GenSolvablePolynomial<C> leftPrimitivePart(GenSolvablePolynomial<C> P) { 622 if (P == null) { 623 throw new IllegalArgumentException("P == null"); 624 } 625 if (P.isZERO()) { 626 return P; 627 } 628 GenSolvablePolynomialRing<C> pfac = P.ring; 629 if (pfac.nvar <= 1) { 630 return leftBasePrimitivePart(P); 631 } 632 GenSolvablePolynomialRing<GenPolynomial<C>> rfac = /*(RecSolvablePolynomialRing<C>)*/pfac 633 .recursive(1); 634 635 GenSolvablePolynomial<GenPolynomial<C>> Pr = (RecSolvablePolynomial<C>) PolyUtil.<C> recursive(rfac, 636 P); 637 GenSolvablePolynomial<GenPolynomial<C>> PP = leftRecursivePrimitivePart(Pr); 638 639 GenSolvablePolynomial<C> D = (GenSolvablePolynomial<C>) PolyUtil.<C> distribute(pfac, PP); 640 return D; 641 } 642 643 644 /** 645 * GenSolvablePolynomial division. Indirection to GenSolvablePolynomial 646 * method. 647 * @param a GenSolvablePolynomial. 648 * @param b coefficient. 649 * @return a/b with a = a'*b. 650 */ 651 public GenSolvablePolynomial<C> divide(GenSolvablePolynomial<C> a, C b) { 652 if (b == null || b.isZERO()) { 653 throw new IllegalArgumentException("division by zero"); 654 655 } 656 if (a == null || a.isZERO()) { 657 return a; 658 } 659 return (GenSolvablePolynomial<C>) a.divide(b); 660 } 661 662 663 /** 664 * Coefficient greatest common divisor. Indirection to coefficient method. 665 * @param a coefficient. 666 * @param b coefficient. 667 * @return gcd(a,b) with a = a'*gcd(a,b) and b = b'*gcd(a,b). 668 */ 669 public C gcd(C a, C b) { 670 if (b == null || b.isZERO()) { 671 return a; 672 } 673 if (a == null || a.isZERO()) { 674 return b; 675 } 676 return a.gcd(b); 677 } 678 679 680 /** 681 * GenSolvablePolynomial greatest common divisor. 682 * @param P GenSolvablePolynomial. 683 * @param S GenSolvablePolynomial. 684 * @return gcd(P,S) with P = P'*gcd(P,S)*p and S = S'*gcd(P,S)*s, where 685 * deg_main(p) = deg_main(s) == 0. 686 */ 687 public GenSolvablePolynomial<C> leftGcd(GenSolvablePolynomial<C> P, GenSolvablePolynomial<C> S) { 688 if (S == null || S.isZERO()) { 689 return P; 690 } 691 if (P == null || P.isZERO()) { 692 return S; 693 } 694 if (P.isONE()) { 695 return P; 696 } 697 if (S.isONE()) { 698 return S; 699 } 700 GenSolvablePolynomialRing<C> pfac = P.ring; 701 if (pfac.nvar <= 1) { 702 GenSolvablePolynomial<C> T = leftBaseGcd(P, S); 703 return T; 704 } 705 GenSolvablePolynomialRing<GenPolynomial<C>> rfac = pfac.recursive(1); //RecSolvablePolynomialRing<C> 706 GenSolvablePolynomial<GenPolynomial<C>> Pr, Sr, Dr, er, fr; 707 Pr = (RecSolvablePolynomial<C>) PolyUtil.<C> recursive(rfac, P); 708 Sr = (RecSolvablePolynomial<C>) PolyUtil.<C> recursive(rfac, S); 709 Dr = leftRecursiveUnivariateGcd(Pr, Sr); 710 GenSolvablePolynomial<C> D = (GenSolvablePolynomial<C>) PolyUtil.<C> distribute(pfac, Dr); 711 if (false) { // not checkable 712 GenSolvablePolynomial<C> ps = FDUtil.<C> leftBaseSparsePseudoRemainder(P, D); 713 GenSolvablePolynomial<C> ss = FDUtil.<C> leftBaseSparsePseudoRemainder(S, D); 714 if (!ps.isZERO() || !ss.isZERO()) { 715 System.out.println("fullGcd, D = " + D); 716 System.out.println("fullGcd, P = " + P); 717 System.out.println("fullGcd, S = " + S); 718 System.out.println("fullGcd, ps = " + ps); 719 System.out.println("fullGcd, ss = " + ss); 720 ss = FDUtil.<C> rightBaseSparsePseudoRemainder(S, D); 721 System.out.println("fullGcd, ss = " + ss); 722 if (!ss.isZERO()) { 723 throw new RuntimeException("fullGcd: not divisible"); 724 } 725 } 726 logger.info("fullGcd(P,S) okay: D = " + D + ", P = " + P + ", S = " + S); 727 } 728 return D; 729 } 730 731 732 /** 733 * GenSolvablePolynomial left least common multiple. 734 * @param P GenSolvablePolynomial. 735 * @param S GenSolvablePolynomial. 736 * @return lcm(P,S) with lcm(P,S) = P'*P = S'*S. 737 */ 738 public GenSolvablePolynomial<C> leftLcm(GenSolvablePolynomial<C> P, GenSolvablePolynomial<C> S) { 739 GenSolvablePolynomial<C>[] oc = leftOreCond(P, S); 740 return oc[0].multiply(P); 741 } 742 743 744 /** 745 * GenSolvablePolynomial right greatest common divisor. 746 * @param P GenSolvablePolynomial. 747 * @param S GenSolvablePolynomial. 748 * @return gcd(P,S) with P = p*gcd(P,S)*P' and S = s*gcd(P,S)*S', where 749 * deg_main(p) = deg_main(s) == 0. 750 */ 751 public GenSolvablePolynomial<C> rightGcd(GenSolvablePolynomial<C> P, GenSolvablePolynomial<C> S) { 752 if (S == null || S.isZERO()) { 753 return P; 754 } 755 if (P == null || P.isZERO()) { 756 return S; 757 } 758 if (P.isONE()) { 759 return P; 760 } 761 if (S.isONE()) { 762 return S; 763 } 764 GenSolvablePolynomialRing<C> pfac = P.ring; 765 if (pfac.nvar <= 1) { 766 GenSolvablePolynomial<C> T = rightBaseGcd(P, S); 767 return T; 768 } 769 GenSolvablePolynomialRing<GenPolynomial<C>> rfac = pfac.recursive(1); //RecSolvablePolynomialRing<C> 770 GenSolvablePolynomial<GenPolynomial<C>> Pr, Sr, Dr; 771 Pr = (RecSolvablePolynomial<C>) PolyUtil.<C> recursive(rfac, P); 772 Sr = (RecSolvablePolynomial<C>) PolyUtil.<C> recursive(rfac, S); 773 Dr = rightRecursiveUnivariateGcd(Pr, Sr); 774 GenSolvablePolynomial<C> D = (GenSolvablePolynomial<C>) PolyUtil.<C> distribute(pfac, Dr); 775 if (false) { // not checkable 776 GenSolvablePolynomial<C> ps = FDUtil.<C> rightBaseSparsePseudoRemainder(P, D); 777 GenSolvablePolynomial<C> ss = FDUtil.<C> rightBaseSparsePseudoRemainder(S, D); 778 if (!ps.isZERO() || !ss.isZERO()) { 779 System.out.println("RI-fullGcd, D = " + D); 780 System.out.println("RI-fullGcd, P = " + P); 781 System.out.println("RI-fullGcd, S = " + S); 782 System.out.println("RI-fullGcd, ps = " + ps); 783 System.out.println("RI-fullGcd, ss = " + ss); 784 throw new RuntimeException("RI-fullGcd: not divisible"); 785 } 786 logger.info("RI-fullGcd(P,S) okay: D = " + D); 787 } 788 return D; 789 } 790 791 792 /** 793 * GenSolvablePolynomial right least common multiple. 794 * @param P GenSolvablePolynomial. 795 * @param S GenSolvablePolynomial. 796 * @return lcm(P,S) with lcm(P,S) = P*P' = S*S'. 797 */ 798 public GenSolvablePolynomial<C> rightLcm(GenSolvablePolynomial<C> P, GenSolvablePolynomial<C> S) { 799 GenSolvablePolynomial<C>[] oc = rightOreCond(P, S); 800 return P.multiply(oc[0]); 801 } 802 803 804 /** 805 * List of GenSolvablePolynomials left greatest common divisor. 806 * @param A non empty list of GenSolvablePolynomials. 807 * @return gcd(A_i) with A_i = A'_i*gcd(A_i)*a_i, where deg_main(a_i) == 0. 808 */ 809 public GenSolvablePolynomial<C> leftGcd(List<GenSolvablePolynomial<C>> A) { 810 if (A == null || A.isEmpty()) { 811 throw new IllegalArgumentException("A may not be empty"); 812 } 813 GenSolvablePolynomial<C> g = A.get(0); 814 for (int i = 1; i < A.size(); i++) { 815 GenSolvablePolynomial<C> f = A.get(i); 816 g = leftGcd(g, f); 817 } 818 return g; 819 } 820 821 822 /** 823 * GenSolvablePolynomial co-prime list. 824 * @param A list of GenSolvablePolynomials. 825 * @return B with gcd(b,c) = 1 for all b != c in B and for all non-constant 826 * a in A there exists b in B with b|a. B does not contain zero or 827 * constant polynomials. 828 */ 829 public List<GenSolvablePolynomial<C>> leftCoPrime(List<GenSolvablePolynomial<C>> A) { 830 if (A == null || A.isEmpty()) { 831 return A; 832 } 833 List<GenSolvablePolynomial<C>> B = new ArrayList<GenSolvablePolynomial<C>>(A.size()); 834 // make a coprime to rest of list 835 GenSolvablePolynomial<C> a = A.get(0); 836 //System.out.println("a = " + a); 837 if (!a.isZERO() && !a.isConstant()) { 838 for (int i = 1; i < A.size(); i++) { 839 GenSolvablePolynomial<C> b = A.get(i); 840 GenSolvablePolynomial<C> g = (GenSolvablePolynomial<C>) leftGcd(a, b).abs(); 841 if (!g.isONE()) { 842 a = FDUtil.<C> leftBasePseudoQuotient(a, g); 843 b = FDUtil.<C> leftBasePseudoQuotient(b, g); 844 GenSolvablePolynomial<C> gp = (GenSolvablePolynomial<C>) leftGcd(a, g); //.abs(); 845 while (!gp.isONE()) { 846 a = FDUtil.<C> leftBasePseudoQuotient(a, gp); 847 g = FDUtil.<C> leftBasePseudoQuotient(g, gp); 848 B.add(g); // gcd(a,g) == 1 849 g = gp; 850 gp = (GenSolvablePolynomial<C>) leftGcd(a, gp); //.abs(); 851 } 852 if (!g.isZERO() && !g.isConstant() /*&& !B.contains(g)*/) { 853 B.add(g); // gcd(a,g) == 1 854 } 855 } 856 if (!b.isZERO() && !b.isConstant()) { 857 B.add(b); // gcd(a,b) == 1 858 } 859 } 860 } else { 861 B.addAll(A.subList(1, A.size())); 862 } 863 // make rest coprime 864 B = leftCoPrime(B); 865 //System.out.println("B = " + B); 866 if (!a.isZERO() && !a.isConstant() /*&& !B.contains(a)*/) { 867 a = (GenSolvablePolynomial<C>) a.abs(); 868 B.add(a); 869 } 870 return B; 871 } 872 873 874 /** 875 * GenSolvablePolynomial left co-prime list. 876 * @param A list of GenSolvablePolynomials. 877 * @return B with gcd(b,c) = 1 for all b != c in B and for all non-constant 878 * a in A there exists b in B with b|a. B does not contain zero or 879 * constant polynomials. 880 */ 881 public List<GenSolvablePolynomial<C>> leftCoPrimeRec(List<GenSolvablePolynomial<C>> A) { 882 if (A == null || A.isEmpty()) { 883 return A; 884 } 885 List<GenSolvablePolynomial<C>> B = new ArrayList<GenSolvablePolynomial<C>>(); 886 // make a co-prime to rest of list 887 for (GenSolvablePolynomial<C> a : A) { 888 //System.out.println("a = " + a); 889 B = leftCoPrime(a, B); 890 //System.out.println("B = " + B); 891 } 892 return B; 893 } 894 895 896 /** 897 * GenSolvablePolynomial left co-prime list. 898 * @param a GenSolvablePolynomial. 899 * @param P co-prime list of GenSolvablePolynomials. 900 * @return B with gcd(b,c) = 1 for all b != c in B and for non-constant a 901 * there exists b in P with b|a. B does not contain zero or constant 902 * polynomials. 903 */ 904 public List<GenSolvablePolynomial<C>> leftCoPrime(GenSolvablePolynomial<C> a, 905 List<GenSolvablePolynomial<C>> P) { 906 if (a == null || a.isZERO() || a.isConstant()) { 907 return P; 908 } 909 List<GenSolvablePolynomial<C>> B = new ArrayList<GenSolvablePolynomial<C>>(P.size() + 1); 910 // make a coprime to elements of the list P 911 for (int i = 0; i < P.size(); i++) { 912 GenSolvablePolynomial<C> b = P.get(i); 913 GenSolvablePolynomial<C> g = (GenSolvablePolynomial<C>) leftGcd(a, b); //.abs(); 914 if (!g.isONE()) { 915 a = FDUtil.<C> leftBasePseudoQuotient(a, g); 916 b = FDUtil.<C> leftBasePseudoQuotient(b, g); 917 // make g co-prime to new a, g is co-prime to c != b in P, B 918 GenSolvablePolynomial<C> gp = (GenSolvablePolynomial<C>) leftGcd(a, g); //.abs(); 919 while (!gp.isONE()) { 920 a = FDUtil.<C> leftBasePseudoQuotient(a, gp); 921 g = FDUtil.<C> leftBasePseudoQuotient(g, gp); 922 if (!g.isZERO() && !g.isConstant() /*&& !B.contains(g)*/) { 923 B.add(g); // gcd(a,g) == 1 and gcd(g,c) == 1 for c != b in P, B 924 } 925 g = gp; 926 gp = (GenSolvablePolynomial<C>) leftGcd(a, gp); //.abs(); 927 } 928 // make new g co-prime to new b 929 gp = (GenSolvablePolynomial<C>) leftGcd(b, g); //.abs(); 930 while (!gp.isONE()) { 931 b = FDUtil.<C> leftBasePseudoQuotient(b, gp); 932 g = FDUtil.<C> leftBasePseudoQuotient(g, gp); 933 if (!g.isZERO() && !g.isConstant() /*&& !B.contains(g)*/) { 934 B.add(g); // gcd(a,g) == 1 and gcd(g,c) == 1 for c != b in P, B 935 } 936 g = gp; 937 gp = (GenSolvablePolynomial<C>) leftGcd(b, gp); //.abs(); 938 } 939 if (!g.isZERO() && !g.isConstant() /*&& !B.contains(g)*/) { 940 B.add(g); // gcd(a,g) == 1 and gcd(g,c) == 1 for c != b in P, B 941 } 942 } 943 if (!b.isZERO() && !b.isConstant() /*&& !B.contains(b)*/) { 944 B.add(b); // gcd(a,b) == 1 and gcd(b,c) == 1 for c != b in P, B 945 } 946 } 947 if (!a.isZERO() && !a.isConstant() /*&& !B.contains(a)*/) { 948 B.add(a); 949 } 950 return B; 951 } 952 953 954 /** 955 * GenSolvablePolynomial test for co-prime list. 956 * @param A list of GenSolvablePolynomials. 957 * @return true if gcd(b,c) = 1 for all b != c in B, else false. 958 */ 959 public boolean isLeftCoPrime(List<GenSolvablePolynomial<C>> A) { 960 if (A == null || A.isEmpty()) { 961 return true; 962 } 963 if (A.size() == 1) { 964 return true; 965 } 966 for (int i = 0; i < A.size(); i++) { 967 GenSolvablePolynomial<C> a = A.get(i); 968 for (int j = i + 1; j < A.size(); j++) { 969 GenSolvablePolynomial<C> b = A.get(j); 970 GenSolvablePolynomial<C> g = leftGcd(a, b); 971 if (!g.isONE()) { 972 System.out.println("not co-prime, a: " + a); 973 System.out.println("not co-prime, b: " + b); 974 System.out.println("not co-prime, g: " + g); 975 return false; 976 } 977 } 978 } 979 return true; 980 } 981 982 983 /** 984 * GenSolvablePolynomial test for left co-prime list of given list. 985 * @param A list of GenSolvablePolynomials. 986 * @param P list of co-prime GenSolvablePolynomials. 987 * @return true if isCoPrime(P) and for all a in A exists p in P with p | a, 988 * else false. 989 */ 990 public boolean isLeftCoPrime(List<GenSolvablePolynomial<C>> P, List<GenSolvablePolynomial<C>> A) { 991 if (!isLeftCoPrime(P)) { 992 return false; 993 } 994 if (A == null || A.isEmpty()) { 995 return true; 996 } 997 for (GenSolvablePolynomial<C> q : A) { 998 if (q.isZERO() || q.isConstant()) { 999 continue; 1000 } 1001 boolean divides = false; 1002 for (GenSolvablePolynomial<C> p : P) { 1003 GenSolvablePolynomial<C> a = FDUtil.<C> leftBaseSparsePseudoRemainder(q, p); 1004 if (a.isZERO()) { // p divides q 1005 divides = true; 1006 break; 1007 } 1008 } 1009 if (!divides) { 1010 System.out.println("no divisor for: " + q); 1011 return false; 1012 } 1013 } 1014 return true; 1015 } 1016 1017 1018 /** 1019 * Univariate GenSolvablePolynomial extended greatest common divisor. Uses 1020 * sparse pseudoRemainder for remainder. 1021 * @param P univariate GenSolvablePolynomial. 1022 * @param S univariate GenSolvablePolynomial. 1023 * @return [ gcd(P,S), a, b ] with a*P + b*S = gcd(P,S). 1024 */ 1025 @SuppressWarnings("unchecked") 1026 public GenSolvablePolynomial<C>[] baseExtendedGcd(GenSolvablePolynomial<C> P, GenSolvablePolynomial<C> S) { 1027 //return P.egcd(S); 1028 GenSolvablePolynomial<C>[] hegcd = baseHalfExtendedGcd(P, S); 1029 GenSolvablePolynomial<C>[] ret = (GenSolvablePolynomial<C>[]) new GenSolvablePolynomial[3]; 1030 ret[0] = hegcd[0]; 1031 ret[1] = hegcd[1]; 1032 GenSolvablePolynomial<C> x = (GenSolvablePolynomial<C>) hegcd[0].subtract(hegcd[1].multiply(P)); 1033 GenSolvablePolynomial<C>[] qr = FDUtil.<C> leftBasePseudoQuotientRemainder(x, S); 1034 // assert qr[1].isZERO() 1035 ret[2] = qr[0]; 1036 return ret; 1037 } 1038 1039 1040 /** 1041 * Univariate GenSolvablePolynomial half extended greatest comon divisor. 1042 * Uses sparse pseudoRemainder for remainder. 1043 * @param S GenSolvablePolynomial. 1044 * @return [ gcd(P,S), a ] with a*P + b*S = gcd(P,S). 1045 */ 1046 @SuppressWarnings("unchecked") 1047 public GenSolvablePolynomial<C>[] baseHalfExtendedGcd(GenSolvablePolynomial<C> P, 1048 GenSolvablePolynomial<C> S) { 1049 if (P == null || S == null) { 1050 throw new IllegalArgumentException("null P or S not allowed"); 1051 } 1052 GenSolvablePolynomial<C>[] ret = (GenSolvablePolynomial<C>[]) new GenSolvablePolynomial[2]; 1053 ret[0] = null; 1054 ret[1] = null; 1055 if (S.isZERO()) { 1056 ret[0] = P; 1057 ret[1] = P.ring.getONE(); 1058 return ret; 1059 } 1060 if (P.isZERO()) { 1061 ret[0] = S; 1062 ret[1] = S.ring.getZERO(); 1063 return ret; 1064 } 1065 if (P.ring.nvar != 1) { 1066 throw new IllegalArgumentException("for univariate polynomials only " + P.ring); 1067 } 1068 GenSolvablePolynomial<C> q = P; 1069 GenSolvablePolynomial<C> r = S; 1070 GenSolvablePolynomial<C> c1 = P.ring.getONE().copy(); 1071 GenSolvablePolynomial<C> d1 = P.ring.getZERO().copy(); 1072 while (!r.isZERO()) { 1073 GenSolvablePolynomial<C>[] qr = FDUtil.<C> leftBasePseudoQuotientRemainder(q, r); 1074 //q.divideAndRemainder(r); 1075 q = qr[0]; 1076 GenSolvablePolynomial<C> x = (GenSolvablePolynomial<C>) c1.subtract(q.multiply(d1)); 1077 c1 = d1; 1078 d1 = x; 1079 q = r; 1080 r = qr[1]; 1081 } 1082 // normalize ldcf(q) to 1, i.e. make monic 1083 C g = q.leadingBaseCoefficient(); 1084 if (g.isUnit()) { 1085 C h = g.inverse(); 1086 q = q.multiply(h); 1087 c1 = c1.multiply(h); 1088 } 1089 //assert ( ((c1.multiply(P)).remainder(S).equals(q) )); 1090 ret[0] = q; 1091 ret[1] = c1; 1092 return ret; 1093 } 1094 1095 1096 /** 1097 * Univariate GenSolvablePolynomial greatest common divisor diophantine 1098 * version. 1099 * @param P univariate GenSolvablePolynomial. 1100 * @param S univariate GenSolvablePolynomial. 1101 * @param c univariate GenSolvablePolynomial. 1102 * @return [ a, b ] with a*P + b*S = c and deg(a) < deg(S). 1103 */ 1104 @SuppressWarnings("unchecked") 1105 public GenSolvablePolynomial<C>[] baseGcdDiophant(GenSolvablePolynomial<C> P, GenSolvablePolynomial<C> S, 1106 GenSolvablePolynomial<C> c) { 1107 GenSolvablePolynomial<C>[] egcd = baseExtendedGcd(P, S); 1108 GenSolvablePolynomial<C> g = egcd[0]; 1109 GenSolvablePolynomial<C>[] qr = FDUtil.<C> leftBasePseudoQuotientRemainder(c, g); 1110 if (!qr[1].isZERO()) { 1111 throw new ArithmeticException("not solvable, r = " + qr[1] + ", c = " + c + ", g = " + g); 1112 } 1113 GenSolvablePolynomial<C> q = qr[0]; 1114 GenSolvablePolynomial<C> a = egcd[1].multiply(q); 1115 GenSolvablePolynomial<C> b = egcd[2].multiply(q); 1116 if (!a.isZERO() && a.degree(0) >= S.degree(0)) { 1117 qr = FDUtil.<C> leftBasePseudoQuotientRemainder(a, S); 1118 a = qr[1]; 1119 b = (GenSolvablePolynomial<C>) b.sum(P.multiply(qr[0])); 1120 } 1121 GenSolvablePolynomial<C>[] ret = (GenSolvablePolynomial<C>[]) new GenSolvablePolynomial[2]; 1122 ret[0] = a; 1123 ret[1] = b; 1124 if (debug) { 1125 GenSolvablePolynomial<C> y = (GenSolvablePolynomial<C>) ret[0].multiply(P) 1126 .sum(ret[1].multiply(S)); 1127 if (!y.equals(c)) { 1128 System.out.println("P = " + P); 1129 System.out.println("S = " + S); 1130 System.out.println("c = " + c); 1131 System.out.println("a = " + a); 1132 System.out.println("b = " + b); 1133 System.out.println("y = " + y); 1134 throw new ArithmeticException("not diophant, x = " + y.subtract(c)); 1135 } 1136 } 1137 return ret; 1138 } 1139 1140 1141 /** 1142 * Coefficient left Ore condition. Generators for the left Ore condition of 1143 * two coefficients. 1144 * @param a coefficient. 1145 * @param b coefficient. 1146 * @return [oa, ob] = leftOreCond(a,b), with oa*a == ob*b. 1147 */ 1148 public C[] leftOreCond(C a, C b) { 1149 if (a == null || a.isZERO() || b == null || b.isZERO()) { 1150 throw new IllegalArgumentException("a and b must be non zero"); 1151 } 1152 C[] oc = (C[]) new GcdRingElem[2]; 1153 if (a instanceof GenSolvablePolynomial && b instanceof GenSolvablePolynomial) { 1154 GenSolvablePolynomial ap = (GenSolvablePolynomial) a; 1155 GenSolvablePolynomial bp = (GenSolvablePolynomial) b; 1156 GenSolvablePolynomial[] ocp = leftOreCond(ap, bp); 1157 oc[0] = (C) ocp[0]; 1158 oc[1] = (C) ocp[1]; 1159 return oc; 1160 } 1161 RingFactory<C> rf = (RingFactory<C>) a.factory(); 1162 if (a.equals(b)) { // required because of rationals gcd 1163 oc[0] = rf.getONE(); 1164 oc[1] = rf.getONE(); 1165 return oc; 1166 } 1167 if (a.equals(b.negate())) { // required because of rationals gcd 1168 oc[0] = rf.getONE(); 1169 oc[1] = rf.getONE().negate(); 1170 return oc; 1171 } 1172 if (rf.isCommutative()) { 1173 logger.info("left Ore condition on coefficients, commutative case: " + a + ", " + b); 1174 C gcd = a.gcd(b); 1175 if (gcd.isONE()) { 1176 oc[0] = b; 1177 oc[1] = a; 1178 return oc; 1179 } 1180 C p = a.multiply(b); 1181 C lcm = p.divide(gcd); 1182 oc[0] = lcm.divide(a); 1183 oc[1] = lcm.divide(b); 1184 logger.info("Ore multiple: lcm=" + lcm + ", gcd=" + gcd + ", " + Arrays.toString(oc)); 1185 return oc; 1186 } 1187 if (rf.isField()) { // non-commutative 1188 logger.info("left Ore condition on coefficients, field case: " + a + ", " + b); 1189 //C gcd = a.gcd(b); // always one 1190 //C lcm = rf.getONE(); 1191 oc[0] = a.inverse(); //lcm.divide(a); 1192 oc[1] = b.inverse(); //lcm.divide(b); 1193 logger.info("Ore multiple: " + Arrays.toString(oc)); 1194 return oc; 1195 } 1196 throw new UnsupportedOperationException("leftOreCond not implemented for " + rf.getClass() 1197 + ", rf = " + rf.toScript()); 1198 //return oc; 1199 } 1200 1201 1202 /** 1203 * Left Ore condition. Generators for the left Ore condition of two solvable 1204 * polynomials. 1205 * @param a solvable polynomial 1206 * @param b solvable polynomial 1207 * @return [p,q] with p*a = q*b 1208 */ 1209 public GenSolvablePolynomial<C>[] leftOreCond(GenSolvablePolynomial<C> a, GenSolvablePolynomial<C> b) { 1210 if (a == null || a.isZERO() || b == null || b.isZERO()) { 1211 throw new IllegalArgumentException("a and b must be non zero"); 1212 } 1213 GenSolvablePolynomialRing<C> pfac = a.ring; 1214 GenSolvablePolynomial<C>[] oc = (GenSolvablePolynomial<C>[]) new GenSolvablePolynomial[2]; 1215 if (a.equals(b)) { 1216 oc[0] = pfac.getONE(); 1217 oc[1] = pfac.getONE(); 1218 return oc; 1219 } 1220 if (a.equals(b.negate())) { 1221 oc[0] = pfac.getONE(); 1222 oc[1] = (GenSolvablePolynomial<C>) pfac.getONE().negate(); 1223 return oc; 1224 } 1225 if (pfac.isCommutative()) { 1226 logger.info("left Ore condition, polynomial commutative case: " + a + ", " + b); 1227 edu.jas.ufd.GreatestCommonDivisorAbstract<C> cgcd = GCDFactory.<C> getImplementation(pfac.coFac); 1228 GenSolvablePolynomial<C> lcm = (GenSolvablePolynomial<C>) cgcd.lcm(a, b); 1229 //oc[0] = FDUtil.<C> basePseudoQuotient(lcm, a); 1230 //oc[1] = FDUtil.<C> basePseudoQuotient(lcm, b); 1231 oc[0] = (GenSolvablePolynomial<C>) PolyUtil.<C> basePseudoDivide(lcm, a); 1232 oc[1] = (GenSolvablePolynomial<C>) PolyUtil.<C> basePseudoDivide(lcm, b); 1233 logger.info("Ore multiple: " + lcm + ", " + Arrays.toString(oc)); 1234 return oc; 1235 } 1236 oc = syz.leftOreCond(a, b); 1237 //logger.info("Ore multiple: " + oc[0].multiply(a) + ", " + Arrays.toString(oc)); 1238 return oc; 1239 } 1240 1241 1242 /** 1243 * Coefficient rigth Ore condition. Generators for the right Ore condition 1244 * of two coefficients. 1245 * @param a coefficient. 1246 * @param b coefficient. 1247 * @return [oa, ob] = rightOreCond(a,b), with a*oa == b*ob. 1248 */ 1249 public C[] rightOreCond(C a, C b) { 1250 if (a == null || a.isZERO() || b == null || b.isZERO()) { 1251 throw new IllegalArgumentException("a and b must be non zero"); 1252 } 1253 C[] oc = (C[]) new GcdRingElem[2]; 1254 if (a instanceof GenSolvablePolynomial && b instanceof GenSolvablePolynomial) { 1255 GenSolvablePolynomial ap = (GenSolvablePolynomial) a; 1256 GenSolvablePolynomial bp = (GenSolvablePolynomial) b; 1257 GenSolvablePolynomial[] ocp = rightOreCond(ap, bp); 1258 oc[0] = (C) ocp[0]; 1259 oc[1] = (C) ocp[1]; 1260 return oc; 1261 } 1262 RingFactory<C> rf = (RingFactory<C>) a.factory(); 1263 if (a.equals(b)) { // required because of rationals gcd 1264 oc[0] = rf.getONE(); 1265 oc[1] = rf.getONE(); 1266 return oc; 1267 } 1268 if (a.equals(b.negate())) { // required because of rationals gcd 1269 oc[0] = rf.getONE(); 1270 oc[1] = rf.getONE().negate(); 1271 return oc; 1272 } 1273 if (rf.isCommutative()) { 1274 logger.info("right Ore condition on coefficients, commutative case: " + a + ", " + b); 1275 C gcd = a.gcd(b); 1276 if (gcd.isONE()) { 1277 oc[0] = b; 1278 oc[1] = a; 1279 return oc; 1280 } 1281 C p = a.multiply(b); 1282 C lcm = p.divide(gcd); 1283 oc[0] = lcm.divide(a); 1284 oc[1] = lcm.divide(b); 1285 logger.info("Ore multiple: " + lcm + ", " + Arrays.toString(oc)); 1286 return oc; 1287 } 1288 if (rf.isField()) { // non-commutative 1289 logger.info("right Ore condition on coefficients, field case: " + a + ", " + b); 1290 //C gcd = a.gcd(b); // always one 1291 //C lcm = rf.getONE(); 1292 oc[0] = a.inverse(); //lcm.divide(a); 1293 oc[1] = b.inverse(); //lcm.divide(b); 1294 logger.info("Ore multiple: " + Arrays.toString(oc)); 1295 return oc; 1296 } 1297 throw new UnsupportedOperationException("rightOreCond not implemented for " + rf.getClass() 1298 + ", rf = " + rf.toScript()); 1299 //return oc; 1300 } 1301 1302 1303 /** 1304 * Right Ore condition. Generators for the right Ore condition of two 1305 * solvable polynomials. 1306 * @param a solvable polynomial 1307 * @param b solvable polynomial 1308 * @return [p,q] with a*p = b*q 1309 */ 1310 public GenSolvablePolynomial<C>[] rightOreCond(GenSolvablePolynomial<C> a, GenSolvablePolynomial<C> b) { 1311 if (a == null || a.isZERO() || b == null || b.isZERO()) { 1312 throw new IllegalArgumentException("a and b must be non zero"); 1313 } 1314 GenSolvablePolynomialRing<C> pfac = a.ring; 1315 GenSolvablePolynomial<C>[] oc = (GenSolvablePolynomial<C>[]) new GenSolvablePolynomial[2]; 1316 if (a.equals(b)) { 1317 oc[0] = pfac.getONE(); 1318 oc[1] = pfac.getONE(); 1319 return oc; 1320 } 1321 if (a.equals(b.negate())) { 1322 oc[0] = pfac.getONE(); 1323 oc[1] = (GenSolvablePolynomial<C>) pfac.getONE().negate(); 1324 return oc; 1325 } 1326 if (pfac.isCommutative()) { 1327 logger.info("right Ore condition, polynomial commutative case: " + a + ", " + b); 1328 edu.jas.ufd.GreatestCommonDivisorAbstract<C> cgcd = GCDFactory.<C> getImplementation(pfac.coFac); 1329 GenSolvablePolynomial<C> lcm = (GenSolvablePolynomial<C>) cgcd.lcm(a, b); 1330 //oc[0] = FDUtil.<C> basePseudoQuotient(lcm, a); 1331 //oc[1] = FDUtil.<C> basePseudoQuotient(lcm, b); 1332 oc[0] = (GenSolvablePolynomial<C>) PolyUtil.<C> basePseudoDivide(lcm, a); 1333 oc[1] = (GenSolvablePolynomial<C>) PolyUtil.<C> basePseudoDivide(lcm, b); 1334 logger.info("Ore multiple: " + lcm + ", " + Arrays.toString(oc)); 1335 return oc; 1336 } 1337 oc = syz.rightOreCond(a, b); 1338 //logger.info("Ore multiple: " + oc[0].multiply(a) + ", " + Arrays.toString(oc)); 1339 return oc; 1340 } 1341 1342}