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