001/* 002 * $Id$ 003 */ 004 005package edu.jas.poly; 006 007 008import java.util.Map; 009import java.util.Set; 010import java.util.SortedMap; 011 012import org.apache.logging.log4j.LogManager; 013import org.apache.logging.log4j.Logger; 014 015import edu.jas.structure.NotInvertibleException; 016import edu.jas.structure.RingElem; 017 018 019/** 020 * GenSolvablePolynomial generic solvable polynomials implementing RingElem. 021 * n-variate ordered solvable polynomials over C. Objects of this class are 022 * intended to be immutable. The implementation is based on TreeMap respectively 023 * SortedMap from exponents to coefficients by extension of GenPolybomial. Only 024 * the coefficients are modeled with generic types, the exponents are fixed to 025 * ExpVector with long, int, short entries (@see edu.jas.poly.ExpVector 026 * StorUnit). 027 * @param <C> coefficient type 028 * @author Heinz Kredel 029 */ 030 031public class GenSolvablePolynomial<C extends RingElem<C>> extends GenPolynomial<C> { 032 033 034 //not possible: implements RingElem< GenSolvablePolynomial<C> > { 035 036 037 private static final Logger logger = LogManager.getLogger(GenSolvablePolynomial.class); 038 039 040 private static final boolean debug = false; //logger.isDebugEnabled(); 041 042 043 /** 044 * The factory for the solvable polynomial ring. Hides super.ring. 045 */ 046 public final GenSolvablePolynomialRing<C> ring; 047 048 049 /** 050 * Constructor for zero GenSolvablePolynomial. 051 * @param r solvable polynomial ring factory. 052 */ 053 public GenSolvablePolynomial(GenSolvablePolynomialRing<C> r) { 054 super(r); 055 ring = r; 056 } 057 058 059 /** 060 * Constructor for GenSolvablePolynomial. 061 * @param r solvable polynomial ring factory. 062 * @param c coefficient. 063 * @param e exponent. 064 */ 065 public GenSolvablePolynomial(GenSolvablePolynomialRing<C> r, C c, ExpVector e) { 066 this(r); 067 if (c != null && !c.isZERO()) { 068 val.put(e, c); 069 } 070 } 071 072 073 /** 074 * Constructor for GenSolvablePolynomial. 075 * @param r solvable polynomial ring factory. 076 * @param c coefficient. 077 */ 078 public GenSolvablePolynomial(GenSolvablePolynomialRing<C> r, C c) { 079 this(r, c, r.evzero); 080 } 081 082 083 /** 084 * Constructor for GenSolvablePolynomial. 085 * @param r solvable polynomial ring factory. 086 * @param v the SortedMap of some other (solvable) polynomial. 087 */ 088 protected GenSolvablePolynomial(GenSolvablePolynomialRing<C> r, SortedMap<ExpVector, C> v) { 089 this(r); 090 if (v.size() > 0) { 091 GenPolynomialRing.creations++; 092 val.putAll(v); // assume val is empty and no zero coefficients in v 093 } 094 } 095 096 097 /** 098 * Get the corresponding element factory. 099 * @return factory for this Element. 100 * @see edu.jas.structure.Element#factory() 101 */ 102 @Override 103 public GenSolvablePolynomialRing<C> factory() { 104 return ring; 105 } 106 107 108 /** 109 * Clone this GenSolvablePolynomial. 110 * @see java.lang.Object#clone() 111 */ 112 @Override 113 public GenSolvablePolynomial<C> copy() { 114 return new GenSolvablePolynomial<C>(ring, this.val); 115 } 116 117 118 /** 119 * Comparison with any other object. 120 * @see java.lang.Object#equals(java.lang.Object) 121 */ 122 @Override 123 public boolean equals(Object B) { 124 if (!(B instanceof GenSolvablePolynomial)) { 125 return false; 126 } 127 return super.equals(B); 128 } 129 130 131 /** 132 * Hash code for this polynomial. 133 * @see java.lang.Object#hashCode() 134 */ 135 @Override 136 public int hashCode() { 137 return super.hashCode(); 138 } 139 140 141 /** 142 * GenSolvablePolynomial multiplication. 143 * @param Bp GenSolvablePolynomial. 144 * @return this*Bp, where * denotes solvable multiplication. 145 */ 146 // cannot @Override 147 @SuppressWarnings("unchecked") 148 public GenSolvablePolynomial<C> multiply(GenSolvablePolynomial<C> Bp) { 149 if (Bp == null || Bp.isZERO()) { 150 return ring.getZERO(); 151 } 152 if (this.isZERO()) { 153 return this; 154 } 155 assert (ring.nvar == Bp.ring.nvar); 156 if (debug) { 157 logger.debug("ring = " + ring); 158 } 159 if (this instanceof RecSolvablePolynomial && Bp instanceof RecSolvablePolynomial) { 160 //throw new RuntimeException("wrong method dispatch in JRE "); 161 logger.info("warn: wrong method dispatch in JRE Rec.multiply(Rec Bp) - trying to fix"); 162 RecSolvablePolynomial T = (RecSolvablePolynomial) this; // no <C> 163 RecSolvablePolynomial Sp = (RecSolvablePolynomial) Bp; 164 return T.multiply(Sp); 165 } 166 if (this instanceof QLRSolvablePolynomial && Bp instanceof QLRSolvablePolynomial) { 167 //throw new RuntimeException("wrong method dispatch in JRE "); 168 logger.info("warn: wrong method dispatch in JRE QLR.multiply(QLR Bp) - trying to fix"); 169 QLRSolvablePolynomial T = (QLRSolvablePolynomial) this; // no <C> 170 QLRSolvablePolynomial Sp = (QLRSolvablePolynomial) Bp; 171 return T.multiply(Sp); 172 } 173 final boolean commute = ring.table.isEmpty(); 174 GenSolvablePolynomial<C> Cp = ring.getZERO().copy(); // needed for doPutToMap and doAddTo 175 ExpVector Z = ring.evzero; 176 177 GenSolvablePolynomial<C> C1 = null; 178 GenSolvablePolynomial<C> C2 = null; 179 Map<ExpVector, C> A = val; 180 Map<ExpVector, C> B = Bp.val; 181 Set<Map.Entry<ExpVector, C>> Bk = B.entrySet(); 182 for (Map.Entry<ExpVector, C> y : A.entrySet()) { 183 C a = y.getValue(); 184 ExpVector e = y.getKey(); 185 if (debug) 186 logger.debug("e = " + e); 187 int[] ep = e.dependencyOnVariables(); 188 int el1 = ring.nvar + 1; 189 if (ep.length > 0) { 190 el1 = ep[0]; 191 } 192 int el1s = ring.nvar + 1 - el1; 193 for (Map.Entry<ExpVector, C> x : Bk) { 194 C b = x.getValue(); 195 ExpVector f = x.getKey(); 196 if (debug) 197 logger.debug("f = " + f); 198 int[] fp = f.dependencyOnVariables(); 199 int fl1 = 0; 200 if (fp.length > 0) { 201 fl1 = fp[fp.length - 1]; 202 } 203 int fl1s = ring.nvar + 1 - fl1; 204 if (debug) { 205 logger.debug("el1s = " + el1s + " fl1s = " + fl1s); 206 } 207 GenSolvablePolynomial<C> Cs = null; 208 if (commute || el1s <= fl1s) { // symmetric 209 ExpVector g = e.sum(f); 210 Cs = ring.valueOf(g); // symmetric! 211 //no: Cs = new GenSolvablePolynomial<C>(ring, one, g); 212 //System.out.println("Cs(sym) = " + Cs + ", g = " + g); 213 } else { // unsymmetric 214 // split e = e1 * e2, f = f1 * f2 215 ExpVector e1 = e.subst(el1, 0); 216 ExpVector e2 = Z.subst(el1, e.getVal(el1)); 217 ExpVector e4; 218 ExpVector f1 = f.subst(fl1, 0); 219 ExpVector f2 = Z.subst(fl1, f.getVal(fl1)); 220 TableRelation<C> rel = ring.table.lookup(e2, f2); 221 //logger.info("relation = " + rel); 222 Cs = rel.p; // do not clone() 223 if (rel.f != null) { 224 C2 = ring.valueOf(rel.f); 225 Cs = Cs.multiply(C2); 226 if (rel.e == null) { 227 e4 = e2; 228 } else { 229 e4 = e2.subtract(rel.e); 230 } 231 ring.table.update(e4, f2, Cs); 232 } 233 if (rel.e != null) { 234 C1 = ring.valueOf(rel.e); 235 Cs = C1.multiply(Cs); 236 ring.table.update(e2, f2, Cs); 237 } 238 if (!f1.isZERO()) { 239 C2 = ring.valueOf(f1); 240 Cs = Cs.multiply(C2); 241 //ring.table.update(?,f1,Cs) 242 } 243 if (!e1.isZERO()) { 244 C1 = ring.valueOf(e1); 245 Cs = C1.multiply(Cs); 246 //ring.table.update(e1,?,Cs) 247 } 248 } 249 //System.out.println("Cs = " + Cs + ", a = " + a + ", b = " + b); 250 Cs = Cs.multiply(a, b); // now non-symmetric // Cs.multiply(c); is symmetric! 251 Cp.doAddTo(Cs); 252 } 253 } 254 return Cp; 255 } 256 257 258 /** 259 * GenSolvablePolynomial left and right multiplication. Product with two 260 * polynomials. 261 * @param S GenSolvablePolynomial. 262 * @param T GenSolvablePolynomial. 263 * @return S*this*T. 264 */ 265 // new method, @NoOverride 266 public GenSolvablePolynomial<C> multiply(GenSolvablePolynomial<C> S, GenSolvablePolynomial<C> T) { 267 if (S.isZERO() || T.isZERO() || this.isZERO()) { 268 return ring.getZERO(); 269 } 270 if (S.isONE()) { 271 return multiply(T); 272 } 273 if (T.isONE()) { 274 return S.multiply(this); 275 } 276 return S.multiply(this).multiply(T); 277 } 278 279 280 /** 281 * GenSolvablePolynomial multiplication. Product with coefficient ring 282 * element. 283 * @param b coefficient. 284 * @return this*b, where * is coefficient multiplication. 285 */ 286 @Override 287 @SuppressWarnings({ "cast", "unchecked" }) 288 public GenSolvablePolynomial<C> multiply(C b) { 289 GenSolvablePolynomial<C> Cp = ring.getZERO(); 290 if (b == null || b.isZERO()) { 291 return Cp; 292 } 293 if (this instanceof RecSolvablePolynomial && b instanceof GenSolvablePolynomial) { 294 //throw new RuntimeException("wrong method dispatch in JRE "); 295 logger.info("warn: wrong method dispatch in JRE Rec.multiply(b) - trying to fix"); 296 RecSolvablePolynomial T = (RecSolvablePolynomial) this; // no <C> 297 GenSolvablePolynomial Sp = (GenSolvablePolynomial) b; 298 return (GenSolvablePolynomial<C>) T.recMultiply(Sp); 299 } 300 if (this instanceof QLRSolvablePolynomial && b instanceof GenSolvablePolynomial) { 301 //throw new RuntimeException("wrong method dispatch in JRE "); 302 logger.info("warn: wrong method dispatch in JRE QLR.multiply(Bp) - trying to fix"); 303 QLRSolvablePolynomial T = (QLRSolvablePolynomial) this; // no <C> 304 GenSolvablePolynomial Sp = (GenSolvablePolynomial) b; 305 return (GenSolvablePolynomial<C>) T.multiply(Sp); 306 } 307 Cp = Cp.copy(); 308 Map<ExpVector, C> Cm = Cp.val; 309 Map<ExpVector, C> Am = val; 310 for (Map.Entry<ExpVector, C> y : Am.entrySet()) { 311 ExpVector e = y.getKey(); 312 C a = y.getValue(); 313 C c = a.multiply(b); 314 if (!c.isZERO()) { 315 Cm.put(e, c); 316 } 317 } 318 return Cp; 319 } 320 321 322 /** 323 * GenSolvablePolynomial left and right multiplication. Product with 324 * coefficient ring element. 325 * @param b coefficient. 326 * @param c coefficient. 327 * @return b*this*c, where * is coefficient multiplication. 328 */ 329 // new method, @NoOverride 330 @SuppressWarnings({ "cast", "unchecked" }) 331 public GenSolvablePolynomial<C> multiply(C b, C c) { 332 GenSolvablePolynomial<C> Cp = ring.getZERO(); 333 if (b == null || b.isZERO()) { 334 return Cp; 335 } 336 if (c == null || c.isZERO()) { 337 return Cp; 338 } 339 if (this instanceof RecSolvablePolynomial && b instanceof GenSolvablePolynomial 340 && c instanceof GenSolvablePolynomial) { 341 //throw new RuntimeException("wrong method dispatch in JRE "); 342 logger.info("warn: wrong method dispatch in JRE Rec.multiply(b,c) - trying to fix"); 343 RecSolvablePolynomial T = (RecSolvablePolynomial) this; // no <C> 344 GenSolvablePolynomial Bp = (GenSolvablePolynomial) b; 345 GenSolvablePolynomial Dp = (GenSolvablePolynomial) c; 346 return (GenSolvablePolynomial<C>) T.multiply(Bp, Dp); 347 } 348 if (this instanceof QLRSolvablePolynomial && b instanceof GenSolvablePolynomial 349 && c instanceof GenSolvablePolynomial) { 350 //throw new RuntimeException("wrong method dispatch in JRE "); 351 logger.info("warn: wrong method dispatch in JRE QLR.multiply(b,c) - trying to fix"); 352 QLRSolvablePolynomial T = (QLRSolvablePolynomial) this; // no <C> 353 GenSolvablePolynomial Bp = (GenSolvablePolynomial) b; 354 GenSolvablePolynomial Dp = (GenSolvablePolynomial) c; 355 return (GenSolvablePolynomial<C>) T.multiply(Bp, Dp); 356 } 357 Cp = Cp.copy(); 358 Map<ExpVector, C> Cm = Cp.val; 359 Map<ExpVector, C> Am = val; 360 for (Map.Entry<ExpVector, C> y : Am.entrySet()) { 361 ExpVector e = y.getKey(); 362 C a = y.getValue(); 363 C d = b.multiply(a).multiply(c); 364 if (!d.isZERO()) { 365 Cm.put(e, d); 366 } 367 } 368 return Cp; 369 } 370 371 372 /** 373 * GenSolvablePolynomial multiplication. Product with exponent vector. 374 * @param e exponent. 375 * @return this * x<sup>e</sup>, where * denotes solvable multiplication. 376 */ 377 @Override 378 public GenSolvablePolynomial<C> multiply(ExpVector e) { 379 if (e == null || e.isZERO()) { 380 return this; 381 } 382 C b = ring.getONECoefficient(); 383 return multiply(b, e); 384 } 385 386 387 /** 388 * GenSolvablePolynomial left and right multiplication. Product with 389 * exponent vector. 390 * @param e exponent. 391 * @param f exponent. 392 * @return x<sup>e</sup> * this * x<sup>f</sup>, where * denotes solvable 393 * multiplication. 394 */ 395 // new method, @NoOverride 396 public GenSolvablePolynomial<C> multiply(ExpVector e, ExpVector f) { 397 if (e == null || e.isZERO()) { 398 return this; 399 } 400 if (f == null || f.isZERO()) { 401 return this; 402 } 403 C b = ring.getONECoefficient(); 404 return multiply(b, e, b, f); 405 } 406 407 408 /** 409 * GenSolvablePolynomial multiplication. Product with ring element and 410 * exponent vector. 411 * @param b coefficient. 412 * @param e exponent. 413 * @return this * b x<sup>e</sup>, where * denotes solvable multiplication. 414 */ 415 @Override 416 public GenSolvablePolynomial<C> multiply(C b, ExpVector e) { 417 if (b == null || b.isZERO()) { 418 return ring.getZERO(); 419 } 420 GenSolvablePolynomial<C> Cp = ring.valueOf(b, e); //new GenSolvablePolynomial<C>(ring, b, e); 421 return multiply(Cp); 422 } 423 424 425 /** 426 * GenSolvablePolynomial left and right multiplication. Product with ring 427 * element and exponent vector. 428 * @param b coefficient. 429 * @param e exponent. 430 * @param c coefficient. 431 * @param f exponent. 432 * @return b x<sup>e</sup> * this * c x<sup>f</sup>, where * denotes 433 * solvable multiplication. 434 */ 435 // new method, @NoOverride 436 public GenSolvablePolynomial<C> multiply(C b, ExpVector e, C c, ExpVector f) { 437 if (b == null || b.isZERO()) { 438 return ring.getZERO(); 439 } 440 if (c == null || c.isZERO()) { 441 return ring.getZERO(); 442 } 443 GenSolvablePolynomial<C> Cp = ring.valueOf(b, e); //new GenSolvablePolynomial<C>(ring, b, e); 444 GenSolvablePolynomial<C> Dp = ring.valueOf(c, f); //new GenSolvablePolynomial<C>(ring, c, f); 445 return multiply(Cp, Dp); 446 } 447 448 449 /** 450 * GenSolvablePolynomial multiplication. Left product with ring element and 451 * exponent vector. 452 * @param b coefficient. 453 * @param e exponent. 454 * @return b x<sup>e</sup> * this, where * denotes solvable multiplication. 455 */ 456 public GenSolvablePolynomial<C> multiplyLeft(C b, ExpVector e) { 457 if (b == null || b.isZERO()) { 458 return ring.getZERO(); 459 } 460 GenSolvablePolynomial<C> Cp = ring.valueOf(b, e); 461 return Cp.multiply(this); 462 } 463 464 465 /** 466 * GenSolvablePolynomial multiplication. Left product with exponent vector. 467 * @param e exponent. 468 * @return x<sup>e</sup> * this, where * denotes solvable multiplication. 469 */ 470 public GenSolvablePolynomial<C> multiplyLeft(ExpVector e) { 471 if (e == null || e.isZERO()) { 472 return this; 473 } 474 C b = ring.getONECoefficient(); 475 return multiplyLeft(b, e); 476 } 477 478 479 /** 480 * GenSolvablePolynomial multiplication. Left product with coefficient ring 481 * element. 482 * @param b coefficient. 483 * @return b*this, where * is coefficient multiplication. 484 */ 485 @Override 486 public GenSolvablePolynomial<C> multiplyLeft(C b) { 487 GenSolvablePolynomial<C> Cp = ring.getZERO(); 488 if (b == null || b.isZERO()) { 489 return Cp; 490 } 491 Cp = Cp.copy(); 492 Map<ExpVector, C> Cm = Cp.val; //getMap(); 493 Map<ExpVector, C> Am = val; 494 for (Map.Entry<ExpVector, C> y : Am.entrySet()) { 495 ExpVector e = y.getKey(); 496 C a = y.getValue(); 497 C c = b.multiply(a); 498 if (!c.isZERO()) { 499 Cm.put(e, c); 500 } 501 } 502 return Cp; 503 } 504 505 506 /** 507 * GenSolvablePolynomial multiplication. Left product with 'monomial'. 508 * @param m 'monomial'. 509 * @return m * this, where * denotes solvable multiplication. 510 */ 511 // new method, @NoOverride 512 public GenSolvablePolynomial<C> multiplyLeft(Map.Entry<ExpVector, C> m) { 513 if (m == null) { 514 return ring.getZERO(); 515 } 516 return multiplyLeft(m.getValue(), m.getKey()); 517 } 518 519 520 /** 521 * GenSolvablePolynomial multiplication. Product with 'monomial'. 522 * @param m 'monomial'. 523 * @return this * m, where * denotes solvable multiplication. 524 */ 525 @Override 526 public GenSolvablePolynomial<C> multiply(Map.Entry<ExpVector, C> m) { 527 if (m == null) { 528 return ring.getZERO(); 529 } 530 return multiply(m.getValue(), m.getKey()); 531 } 532 533 534 /** 535 * GenSolvablePolynomial subtract a multiple. 536 * @param a coefficient. 537 * @param S GenSolvablePolynomial. 538 * @return this - a * S. 539 */ 540 public GenSolvablePolynomial<C> subtractMultiple(C a, GenSolvablePolynomial<C> S) { 541 if (a == null || a.isZERO()) { 542 return this; 543 } 544 if (S == null || S.isZERO()) { 545 return this; 546 } 547 if (this.isZERO()) { 548 return S.multiplyLeft(a.negate()); 549 } 550 assert (ring.nvar == S.ring.nvar); 551 GenSolvablePolynomial<C> n = this.copy(); 552 SortedMap<ExpVector, C> nv = n.val; 553 SortedMap<ExpVector, C> sv = S.val; 554 for (Map.Entry<ExpVector, C> me : sv.entrySet()) { 555 ExpVector f = me.getKey(); 556 C y = me.getValue(); // assert y != null 557 y = a.multiply(y); 558 C x = nv.get(f); 559 if (x != null) { 560 x = x.subtract(y); 561 if (!x.isZERO()) { 562 nv.put(f, x); 563 } else { 564 nv.remove(f); 565 } 566 } else if (!y.isZERO()) { 567 nv.put(f, y.negate()); 568 } 569 } 570 return n; 571 } 572 573 574 /** 575 * GenSolvablePolynomial subtract a multiple. 576 * @param a coefficient. 577 * @param e exponent. 578 * @param S GenSolvablePolynomial. 579 * @return this - a * x<sup>e</sup> * S. 580 */ 581 public GenSolvablePolynomial<C> subtractMultiple(C a, ExpVector e, GenSolvablePolynomial<C> S) { 582 if (a == null || a.isZERO()) { 583 return this; 584 } 585 if (S == null || S.isZERO()) { 586 return this; 587 } 588 if (this.isZERO()) { 589 return S.multiplyLeft(a.negate(), e); 590 } 591 assert (ring.nvar == S.ring.nvar); 592 GenSolvablePolynomial<C> n = this.copy(); 593 SortedMap<ExpVector, C> nv = n.val; 594 GenSolvablePolynomial<C> s = S.multiplyLeft(e); 595 SortedMap<ExpVector, C> sv = s.val; 596 for (Map.Entry<ExpVector, C> me : sv.entrySet()) { 597 ExpVector f = me.getKey(); 598 //f = e.sum(f); 599 C y = me.getValue(); // assert y != null 600 y = a.multiply(y); 601 C x = nv.get(f); 602 if (x != null) { 603 x = x.subtract(y); 604 if (!x.isZERO()) { 605 nv.put(f, x); 606 } else { 607 nv.remove(f); 608 } 609 } else if (!y.isZERO()) { 610 nv.put(f, y.negate()); 611 } 612 } 613 return n; 614 } 615 616 617 /** 618 * GenSolvablePolynomial scale and subtract a multiple. 619 * @param b scale factor. 620 * @param a coefficient. 621 * @param S GenSolvablePolynomial. 622 * @return b * this - a * S. 623 */ 624 public GenSolvablePolynomial<C> scaleSubtractMultiple(C b, C a, GenSolvablePolynomial<C> S) { 625 if (a == null || S == null) { 626 return this.multiplyLeft(b); 627 } 628 if (a.isZERO() || S.isZERO()) { 629 return this.multiplyLeft(b); 630 } 631 if (this.isZERO() || b == null || b.isZERO()) { 632 return S.multiplyLeft(a.negate()); 633 } 634 if (b.isONE()) { 635 return subtractMultiple(a, S); 636 } 637 assert (ring.nvar == S.ring.nvar); 638 GenSolvablePolynomial<C> n = this.multiplyLeft(b); 639 SortedMap<ExpVector, C> nv = n.val; 640 SortedMap<ExpVector, C> sv = S.val; 641 for (Map.Entry<ExpVector, C> me : sv.entrySet()) { 642 ExpVector f = me.getKey(); 643 //f = e.sum(f); 644 C y = me.getValue(); // assert y != null 645 y = a.multiply(y); // now y can be zero 646 C x = nv.get(f); 647 if (x != null) { 648 x = x.subtract(y); 649 if (!x.isZERO()) { 650 nv.put(f, x); 651 } else { 652 nv.remove(f); 653 } 654 } else if (!y.isZERO()) { 655 nv.put(f, y.negate()); 656 } 657 } 658 return n; 659 } 660 661 662 /** 663 * GenSolvablePolynomial scale and subtract a multiple. 664 * @param b scale factor. 665 * @param a coefficient. 666 * @param e exponent. 667 * @param S GenSolvablePolynomial. 668 * @return b * this - a * x<sup>e</sup> * S. 669 */ 670 public GenSolvablePolynomial<C> scaleSubtractMultiple(C b, C a, ExpVector e, GenSolvablePolynomial<C> S) { 671 if (a == null || S == null) { 672 return this.multiplyLeft(b); 673 } 674 if (a.isZERO() || S.isZERO()) { 675 return this.multiplyLeft(b); 676 } 677 if (this.isZERO() || b == null || b.isZERO()) { 678 return S.multiplyLeft(a.negate(), e); 679 } 680 if (b.isONE()) { 681 return subtractMultiple(a, e, S); 682 } 683 assert (ring.nvar == S.ring.nvar); 684 GenSolvablePolynomial<C> n = this.multiplyLeft(b); 685 SortedMap<ExpVector, C> nv = n.val; 686 GenSolvablePolynomial<C> s = S.multiplyLeft(e); 687 SortedMap<ExpVector, C> sv = s.val; 688 for (Map.Entry<ExpVector, C> me : sv.entrySet()) { 689 ExpVector f = me.getKey(); 690 //f = e.sum(f); 691 C y = me.getValue(); // assert y != null 692 y = a.multiply(y); // now y can be zero 693 C x = nv.get(f); 694 if (x != null) { 695 x = x.subtract(y); 696 if (!x.isZERO()) { 697 nv.put(f, x); 698 } else { 699 nv.remove(f); 700 } 701 } else if (!y.isZERO()) { 702 nv.put(f, y.negate()); 703 } 704 } 705 return n; 706 } 707 708 709 /** 710 * GenSolvablePolynomial scale and subtract a multiple. 711 * @param b scale factor. 712 * @param g scale exponent. 713 * @param a coefficient. 714 * @param e exponent. 715 * @param S GenSolvablePolynomial. 716 * @return a * x<sup>g</sup> * this - a * x<sup>e</sup> * S. 717 */ 718 public GenSolvablePolynomial<C> scaleSubtractMultiple(C b, ExpVector g, C a, ExpVector e, 719 GenSolvablePolynomial<C> S) { 720 if (a == null || S == null) { 721 return this.multiplyLeft(b, g); 722 } 723 if (a.isZERO() || S.isZERO()) { 724 return this.multiplyLeft(b, g); 725 } 726 if (this.isZERO() || b == null || b.isZERO()) { 727 return S.multiplyLeft(a.negate(), e); 728 } 729 if (b.isONE() && g.isZERO()) { 730 return subtractMultiple(a, e, S); 731 } 732 assert (ring.nvar == S.ring.nvar); 733 GenSolvablePolynomial<C> n = this.multiplyLeft(b, g); 734 SortedMap<ExpVector, C> nv = n.val; 735 GenSolvablePolynomial<C> s = S.multiplyLeft(e); 736 SortedMap<ExpVector, C> sv = s.val; 737 for (Map.Entry<ExpVector, C> me : sv.entrySet()) { 738 ExpVector f = me.getKey(); 739 //f = e.sum(f); 740 C y = me.getValue(); // assert y != null 741 y = a.multiply(y); // y can be zero now 742 C x = nv.get(f); 743 if (x != null) { 744 x = x.subtract(y); 745 if (!x.isZERO()) { 746 nv.put(f, x); 747 } else { 748 nv.remove(f); 749 } 750 } else if (!y.isZERO()) { 751 nv.put(f, y.negate()); 752 } 753 } 754 return n; 755 } 756 757 758 /** 759 * GenSolvablePolynomial left monic, i.e. leadingCoefficient == 1. If 760 * leadingCoefficient is not invertible returns this abs value. 761 * @return monic(this). 762 */ 763 @Override 764 public GenSolvablePolynomial<C> monic() { 765 if (this.isZERO()) { 766 return this; 767 } 768 C lc = leadingBaseCoefficient(); 769 if (!lc.isUnit()) { 770 return (GenSolvablePolynomial<C>) this.abs(); 771 } 772 try { 773 C lm = lc.inverse(); 774 //System.out.println("lm = "+lm); 775 return (GenSolvablePolynomial<C>) multiplyLeft(lm).abs(); 776 } catch (NotInvertibleException e) { 777 logger.info("monic not invertible " + lc); 778 //e.printStackTrace(); 779 } 780 return this; 781 } 782 783 784 /** 785 * GenSolvablePolynomial left division. Fails, if exact division by leading 786 * base coefficient is not possible. Meaningful only for univariate 787 * polynomials over fields, but works in any case. 788 * @param S nonzero GenSolvablePolynomial with invertible leading 789 * coefficient. 790 * @return quotient with this = quotient * S + remainder and deg(remainder) 791 * < deg(S) or remiander = 0. 792 * @see edu.jas.poly.PolyUtil#baseSparsePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial) 793 */ 794 // cannot @Override 795 @SuppressWarnings({ "unchecked" }) 796 public GenSolvablePolynomial<C> divide(GenSolvablePolynomial<C> S) { 797 return quotientRemainder(S)[0]; 798 } 799 800 801 /** 802 * GenSolvablePolynomial remainder by left division. Fails, if exact 803 * division by leading base coefficient is not possible. Meaningful only for 804 * univariate polynomials over fields, but works in any case. 805 * @param S nonzero GenSolvablePolynomial with invertible leading 806 * coefficient. 807 * @return remainder with this = quotient * S + remainder and deg(remainder) 808 * < deg(S) or remiander = 0. 809 * @see edu.jas.poly.PolyUtil#baseSparsePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial) 810 */ 811 // cannot @Override 812 @SuppressWarnings({ "unchecked" }) 813 public GenSolvablePolynomial<C> remainder(GenSolvablePolynomial<C> S) { 814 return quotientRemainder(S)[1]; 815 } 816 817 818 /** 819 * GenSolvablePolynomial left division with remainder. Fails, if exact 820 * division by leading base coefficient is not possible. Meaningful only for 821 * univariate polynomials over fields, but works in any case. 822 * @param S nonzero GenSolvablePolynomial with invertible leading 823 * coefficient. 824 * @return [ quotient , remainder ] with this = quotient * S + remainder and 825 * deg(remainder) < deg(S) or remiander = 0. 826 * @see edu.jas.poly.PolyUtil#baseSparsePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial) 827 */ 828 // cannot @Override 829 @SuppressWarnings({ "unchecked" }) 830 public GenSolvablePolynomial<C>[] quotientRemainder(GenSolvablePolynomial<C> S) { 831 if (S == null || S.isZERO()) { 832 throw new ArithmeticException("division by zero"); 833 } 834 C c = S.leadingBaseCoefficient(); 835 if (!c.isUnit()) { 836 throw new ArithmeticException("lbcf not invertible " + c); 837 } 838 C ci = c.inverse(); 839 assert (ring.nvar == S.ring.nvar); 840 ExpVector e = S.leadingExpVector(); 841 GenSolvablePolynomial<C> h; 842 GenSolvablePolynomial<C> q = ring.getZERO().copy(); 843 GenSolvablePolynomial<C> r = this.copy(); 844 while (!r.isZERO()) { 845 ExpVector f = r.leadingExpVector(); 846 if (f.multipleOf(e)) { 847 C a = r.leadingBaseCoefficient(); 848 //System.out.println("FDQR: f = " + f + ", a = " + a); 849 f = f.subtract(e); 850 //a = ci.multiply(a); // multiplyLeft 851 a = a.multiply(ci); // this is correct! 852 q = (GenSolvablePolynomial<C>) q.sum(a, f); 853 h = S.multiplyLeft(a, f); 854 if (!h.leadingBaseCoefficient().equals(r.leadingBaseCoefficient())) { 855 throw new RuntimeException("something is wrong: r = " + r + ", h = " + h); 856 } 857 r = (GenSolvablePolynomial<C>) r.subtract(h); 858 } else { 859 break; 860 } 861 } 862 GenSolvablePolynomial<C>[] ret = new GenSolvablePolynomial[2]; 863 ret[0] = q; 864 ret[1] = r; 865 return ret; 866 } 867 868 869 /** 870 * GenSolvablePolynomial right division. Fails, if exact division by leading 871 * base coefficient is not possible. Meaningful only for univariate 872 * polynomials over fields, but works in any case. 873 * @param S nonzero GenSolvablePolynomial with invertible leading 874 * coefficient. 875 * @return quotient with this = S * quotient + remainder and deg(remainder) 876 * < deg(S) or remiander = 0. 877 * @see edu.jas.poly.PolyUtil#baseSparsePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial) 878 */ 879 @SuppressWarnings({ "unchecked" }) 880 public GenSolvablePolynomial<C> rightDivide(GenSolvablePolynomial<C> S) { 881 return rightQuotientRemainder(S)[0]; 882 } 883 884 885 /** 886 * GenSolvablePolynomial remainder by right division. Fails, if exact 887 * division by leading base coefficient is not possible. Meaningful only for 888 * univariate polynomials over fields, but works in any case. 889 * @param S nonzero GenSolvablePolynomial with invertible leading 890 * coefficient. 891 * @return remainder with this = S * quotient + remainder and deg(remainder) 892 * < deg(S) or remiander = 0. 893 * @see edu.jas.poly.PolyUtil#baseSparsePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial) 894 */ 895 @SuppressWarnings({ "unchecked" }) 896 public GenSolvablePolynomial<C> rightRemainder(GenSolvablePolynomial<C> S) { 897 return rightQuotientRemainder(S)[1]; 898 } 899 900 901 /** 902 * GenSolvablePolynomial right division with remainder. Fails, if exact 903 * division by leading base coefficient is not possible. Meaningful only for 904 * univariate polynomials over fields, but works in any case. 905 * @param S nonzero GenSolvablePolynomial with invertible leading 906 * coefficient. 907 * @return [ quotient , remainder ] with this = S * quotient + remainder and 908 * deg(remainder) < deg(S) or remainder = 0. 909 * @see edu.jas.poly.PolyUtil#baseSparsePseudoRemainder(edu.jas.poly.GenPolynomial,edu.jas.poly.GenPolynomial) 910 */ 911 @SuppressWarnings({ "unchecked" }) 912 public GenSolvablePolynomial<C>[] rightQuotientRemainder(GenSolvablePolynomial<C> S) { 913 if (S == null || S.isZERO()) { 914 throw new ArithmeticException("division by zero"); 915 } 916 C c = S.leadingBaseCoefficient(); 917 if (!c.isUnit()) { 918 throw new ArithmeticException("lbcf not invertible " + c); 919 } 920 C ci = c.inverse(); 921 assert (ring.nvar == S.ring.nvar); 922 ExpVector e = S.leadingExpVector(); 923 GenSolvablePolynomial<C> h; 924 GenSolvablePolynomial<C> q = ring.getZERO().copy(); 925 GenSolvablePolynomial<C> r = this.copy(); 926 while (!r.isZERO()) { 927 ExpVector f = r.leadingExpVector(); 928 if (f.multipleOf(e)) { 929 C a = r.leadingBaseCoefficient(); 930 //System.out.println("FDQR: f = " + f + ", a = " + a); 931 f = f.subtract(e); 932 //a = a.multiplyLeft(ci); // not existing 933 a = ci.multiply(a); // this is correct! 934 q = (GenSolvablePolynomial<C>) q.sum(a, f); 935 h = S.multiply(a, f); 936 if (!h.leadingBaseCoefficient().equals(r.leadingBaseCoefficient())) { 937 throw new RuntimeException("something is wrong: r = " + r + ", h = " + h); 938 } 939 r = (GenSolvablePolynomial<C>) r.subtract(h); 940 } else { 941 break; 942 } 943 } 944 GenSolvablePolynomial<C>[] ret = new GenSolvablePolynomial[2]; 945 ret[0] = q; 946 ret[1] = r; 947 return ret; 948 } 949 950 951 /** 952 * RecSolvablePolynomial right coefficients from left coefficients. 953 * <b>Note:</b> R is represented as a polynomial with left coefficients, the 954 * implementation can at the moment not distinguish between left and right 955 * coefficients. 956 * @return R = sum( X<sup>i</sup> b<sub>i</sub> ), with P = 957 * sum(a<sub>i</sub> X<sup>i</sup> ) and eval(sum(X<sup>i</sup> 958 * b<sub>i</sub>)) == sum(a<sub>i</sub> X<sup>i</sup>) 959 */ 960 @SuppressWarnings({ "unchecked" }) 961 public GenSolvablePolynomial<C> rightRecursivePolynomial() { 962 if (this.isONE() || this.isZERO()) { 963 return this; 964 } 965 if (!(this instanceof RecSolvablePolynomial)) { 966 return this; 967 } 968 RecSolvablePolynomialRing<C> rfac = (RecSolvablePolynomialRing<C>) ring; 969 if (rfac.coeffTable.isEmpty()) { 970 return this; 971 } 972 RecSolvablePolynomial<C> p = (RecSolvablePolynomial<C>) this; 973 RecSolvablePolynomial<C> R = (RecSolvablePolynomial<C>) p.rightRecursivePolynomial(); 974 return (GenSolvablePolynomial<C>) R; 975 } 976 977 978 /** 979 * Evaluate RecSolvablePolynomial as right coefficients polynomial. 980 * <b>Note:</b> R is represented as a polynomial with left coefficients, the 981 * implementation can at the moment not distinguish between left and right 982 * coefficients. 983 * @return this as evaluated polynomial R. R = sum( X<sup>i</sup> 984 * b<sub>i</sub> ), this = sum(a<sub>i</sub> X<sup>i</sup> ) = 985 * eval(sum(X<sup>i</sup> b<sub>i</sub>)) 986 */ 987 @SuppressWarnings({ "unchecked" }) 988 public GenSolvablePolynomial<C> evalAsRightRecursivePolynomial() { 989 if (this.isONE() || this.isZERO()) { 990 return this; 991 } 992 if (!(this instanceof RecSolvablePolynomial)) { 993 return this; 994 } 995 RecSolvablePolynomialRing<C> rfac = (RecSolvablePolynomialRing<C>) ring; 996 if (rfac.coeffTable.isEmpty()) { 997 return this; 998 } 999 RecSolvablePolynomial<C> p = (RecSolvablePolynomial<C>) this; 1000 RecSolvablePolynomial<C> R = (RecSolvablePolynomial<C>) p.evalAsRightRecursivePolynomial(); 1001 return (GenSolvablePolynomial<C>) R; 1002 } 1003 1004 1005 /** 1006 * Test RecSolvablePolynomial right coefficients polynomial. <b>Note:</b> R 1007 * is represented as a polynomial with left coefficients, the implementation 1008 * can at the moment not distinguish between left and right coefficients. 1009 * @param R GenSolvablePolynomial with right coefficients. 1010 * @return true, if R is polynomial with right coefficients of this. R = 1011 * sum( X<sup>i</sup> b<sub>i</sub> ), with this = sum(a<sub>i</sub> 1012 * X<sup>i</sup> ) and eval(sum(X<sup>i</sup> b<sub>i</sub>)) == 1013 * sum(a<sub>i</sub> X<sup>i</sup>) 1014 */ 1015 @SuppressWarnings({ "unchecked" }) 1016 public boolean isRightRecursivePolynomial(GenSolvablePolynomial<C> R) { 1017 if (this.isZERO()) { 1018 return R.isZERO(); 1019 } 1020 if (this.isONE()) { 1021 return R.isONE(); 1022 } 1023 if (!(this instanceof RecSolvablePolynomial)) { 1024 return !(R instanceof RecSolvablePolynomial); 1025 } 1026 if (!(R instanceof RecSolvablePolynomial)) { 1027 return false; 1028 } 1029 RecSolvablePolynomialRing<C> rfac = (RecSolvablePolynomialRing<C>) ring; 1030 if (rfac.coeffTable.isEmpty()) { 1031 RecSolvablePolynomialRing<C> rf = (RecSolvablePolynomialRing<C>) R.ring; 1032 return rf.coeffTable.isEmpty(); 1033 } 1034 RecSolvablePolynomial<C> p = (RecSolvablePolynomial<C>) this; 1035 RecSolvablePolynomial<C> q = (RecSolvablePolynomial<C>) R; 1036 return p.isRightRecursivePolynomial(q); 1037 } 1038 1039}