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