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