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