001/* 002 * $Id$ 003 */ 004 005package edu.jas.application; 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.poly.ExpVector; 016import edu.jas.poly.GenSolvablePolynomial; 017import edu.jas.poly.RecSolvablePolynomial; 018import edu.jas.poly.TableRelation; 019import edu.jas.structure.GcdRingElem; 020 021 022/** 023 * ResidueSolvablePolynomial generic solvable polynomials with solvable residue 024 * coefficients implementing RingElem. n-variate ordered solvable polynomials 025 * over solvable residue coefficients. Objects of this class are intended to be 026 * immutable. The implementation is based on TreeMap respectively SortedMap from 027 * exponents to coefficients by extension of GenPolynomial. 028 * @param <C> coefficient type 029 * @author Heinz Kredel 030 */ 031 032public class ResidueSolvablePolynomial<C extends GcdRingElem<C>> extends 033 GenSolvablePolynomial<SolvableResidue<C>> { 034 035 036 /** 037 * The factory for the recursive solvable polynomial ring. Hides super.ring. 038 */ 039 public final ResidueSolvablePolynomialRing<C> ring; 040 041 042 private static final Logger logger = LogManager.getLogger(ResidueSolvablePolynomial.class); 043 044 045 private static final boolean debug = logger.isDebugEnabled(); 046 047 048 /** 049 * Constructor for zero ResidueSolvablePolynomial. 050 * @param r solvable polynomial ring factory. 051 */ 052 public ResidueSolvablePolynomial(ResidueSolvablePolynomialRing<C> r) { 053 super(r); 054 ring = r; 055 } 056 057 058 /** 059 * Constructor for ResidueSolvablePolynomial. 060 * @param r solvable polynomial ring factory. 061 * @param e exponent. 062 */ 063 public ResidueSolvablePolynomial(ResidueSolvablePolynomialRing<C> r, ExpVector e) { 064 this(r); 065 val.put(e, ring.getONECoefficient()); 066 } 067 068 069 /** 070 * Constructor for ResidueSolvablePolynomial. 071 * @param r solvable polynomial ring factory. 072 * @param c coefficient polynomial. 073 * @param e exponent. 074 */ 075 public ResidueSolvablePolynomial(ResidueSolvablePolynomialRing<C> r, SolvableResidue<C> c, ExpVector e) { 076 this(r); 077 if (c != null && !c.isZERO()) { 078 val.put(e, c); 079 } 080 } 081 082 083 /** 084 * Constructor for ResidueSolvablePolynomial. 085 * @param r solvable polynomial ring factory. 086 * @param c coefficient polynomial. 087 */ 088 public ResidueSolvablePolynomial(ResidueSolvablePolynomialRing<C> r, SolvableResidue<C> c) { 089 this(r, c, r.evzero); 090 } 091 092 093 /** 094 * Constructor for ResidueSolvablePolynomial. 095 * @param r solvable polynomial ring factory. 096 * @param S solvable polynomial. 097 */ 098 public ResidueSolvablePolynomial(ResidueSolvablePolynomialRing<C> r, 099 GenSolvablePolynomial<SolvableResidue<C>> S) { 100 this(r, S.getMap()); 101 } 102 103 104 /** 105 * Constructor for ResidueSolvablePolynomial. 106 * @param r solvable polynomial ring factory. 107 * @param v the SortedMap of some other (solvable) polynomial. 108 */ 109 protected ResidueSolvablePolynomial(ResidueSolvablePolynomialRing<C> r, 110 SortedMap<ExpVector, SolvableResidue<C>> v) { 111 this(r); 112 val.putAll(v); // assume no zero coefficients 113 } 114 115 116 /** 117 * Get the corresponding element factory. 118 * @return factory for this Element. 119 * @see edu.jas.structure.Element#factory() 120 */ 121 @Override 122 public ResidueSolvablePolynomialRing<C> factory() { 123 return ring; 124 } 125 126 127 /** 128 * Clone this ResidueSolvablePolynomial. 129 * @see java.lang.Object#clone() 130 */ 131 @Override 132 public ResidueSolvablePolynomial<C> copy() { 133 return new ResidueSolvablePolynomial<C>(ring, this.val); 134 } 135 136 137 /** 138 * Comparison with any other object. 139 * @see java.lang.Object#equals(java.lang.Object) 140 */ 141 @Override 142 public boolean equals(Object B) { 143 if (!(B instanceof ResidueSolvablePolynomial)) { 144 return false; 145 } 146 return super.equals(B); 147 } 148 149 150 /** 151 * Hash code for this polynomial. 152 * @see java.lang.Object#hashCode() 153 */ 154 @Override 155 public int hashCode() { 156 return super.hashCode(); 157 } 158 159 160 /** 161 * ResidueSolvablePolynomial multiplication. 162 * @param Bp ResidueSolvablePolynomial. 163 * @return this*Bp, where * denotes solvable multiplication. 164 */ 165 public ResidueSolvablePolynomial<C> multiply(ResidueSolvablePolynomial<C> Bp) { 166 if (Bp == null || Bp.isZERO()) { 167 return ring.getZERO(); 168 } 169 if (this.isZERO()) { 170 return this; 171 } 172 assert (ring.nvar == Bp.ring.nvar); 173 if (debug) { 174 logger.debug("ring = " + ring); 175 } 176 ExpVector Z = ring.evzero; 177 ResidueSolvablePolynomial<C> Dp = ring.getZERO().copy(); 178 ResidueSolvablePolynomial<C> zero = ring.getZERO().copy(); 179 SolvableResidue<C> one = ring.getONECoefficient(); 180 181 //ResidueSolvablePolynomial<C> C1 = null; 182 //ResidueSolvablePolynomial<C> C2 = null; 183 Map<ExpVector, SolvableResidue<C>> A = val; 184 Map<ExpVector, SolvableResidue<C>> B = Bp.val; 185 Set<Map.Entry<ExpVector, SolvableResidue<C>>> Bk = B.entrySet(); 186 for (Map.Entry<ExpVector, SolvableResidue<C>> y : A.entrySet()) { 187 SolvableResidue<C> a = y.getValue(); 188 ExpVector e = y.getKey(); 189 if (debug) 190 logger.info("e = " + e + ", a = " + a); 191 //int[] ep = e.dependencyOnVariables(); 192 //int el1 = ring.nvar + 1; 193 //if (ep.length > 0) { 194 // el1 = ep[0]; 195 //} 196 //int el1s = ring.nvar + 1 - el1; 197 for (Map.Entry<ExpVector, SolvableResidue<C>> x : Bk) { 198 SolvableResidue<C> b = x.getValue(); 199 ExpVector f = x.getKey(); 200 if (debug) 201 logger.info("f = " + f + ", b = " + b); 202 int[] fp = f.dependencyOnVariables(); 203 int fl1 = 0; 204 if (fp.length > 0) { 205 fl1 = fp[fp.length - 1]; 206 } 207 int fl1s = ring.nvar + 1 - fl1; 208 // polynomial coefficient multiplication 209 ResidueSolvablePolynomial<C> Cps = ring.getZERO().copy(); 210 //ResidueSolvablePolynomial<C> Cs = null; 211 if (ring.polCoeff.coeffTable.isEmpty() || b.isConstant() || e.isZERO()) { // symmetric 212 Cps = new ResidueSolvablePolynomial<C>(ring, b, e); 213 if (debug) 214 logger.info("symmetric coeff: b = " + b + ", e = " + e); 215 } else { // unsymmetric 216 if (debug) 217 logger.info("unsymmetric coeff: b = " + b + ", e = " + e); 218 // recursive polynomial coefficient multiplication : e * b.val 219 RecSolvablePolynomial<C> rsp1 = new RecSolvablePolynomial<C>(ring.polCoeff, e); 220 RecSolvablePolynomial<C> rsp2 = new RecSolvablePolynomial<C>(ring.polCoeff, b.val); 221 RecSolvablePolynomial<C> rsp3 = rsp1.multiply(rsp2); 222 Cps = ring.fromPolyCoefficients(rsp3); 223 } 224 if (debug) { 225 logger.info("coeff-poly: Cps = " + Cps); 226 } 227 // polynomial multiplication 228 ResidueSolvablePolynomial<C> Dps = ring.getZERO().copy(); 229 ResidueSolvablePolynomial<C> Ds = null; 230 ResidueSolvablePolynomial<C> D1, D2; 231 if (ring.table.isEmpty() || Cps.isConstant() || f.isZERO()) { // symmetric 232 if (debug) 233 logger.info("symmetric poly: b = " + b + ", e = " + e); 234 ExpVector g = e.sum(f); 235 if (Cps.isConstant()) { 236 Ds = new ResidueSolvablePolynomial<C>(ring, Cps.leadingBaseCoefficient(), g); // symmetric! 237 } else { 238 Ds = Cps.shift(f); // symmetric 239 } 240 } else { // eventually unsymmetric 241 if (debug) 242 logger.info("unsymmetric poly: Cps = " + Cps + ", f = " + f); 243 for (Map.Entry<ExpVector, SolvableResidue<C>> z : Cps.val.entrySet()) { 244 // split g = g1 * g2, f = f1 * f2 245 SolvableResidue<C> c = z.getValue(); 246 ExpVector g = z.getKey(); 247 if (debug) 248 logger.info("g = " + g + ", c = " + c); 249 int[] gp = g.dependencyOnVariables(); 250 int gl1 = ring.nvar + 1; 251 if (gp.length > 0) { 252 gl1 = gp[0]; 253 } 254 int gl1s = ring.nvar + 1 - gl1; 255 if (gl1s <= fl1s) { // symmetric 256 ExpVector h = g.sum(f); 257 if (debug) 258 logger.info("disjoint poly: g = " + g + ", f = " + f + ", h = " + h); 259 Ds = (ResidueSolvablePolynomial<C>) zero.sum(one, h); // symmetric! 260 } else { 261 ExpVector g1 = g.subst(gl1, 0); 262 ExpVector g2 = Z.subst(gl1, g.getVal(gl1)); // bug el1, gl1 263 ExpVector g4; 264 ExpVector f1 = f.subst(fl1, 0); 265 ExpVector f2 = Z.subst(fl1, f.getVal(fl1)); 266 if (debug) 267 logger.info("poly, g1 = " + g1 + ", f1 = " + f1 + ", Dps = " + Dps); 268 if (debug) 269 logger.info("poly, g2 = " + g2 + ", f2 = " + f2); 270 TableRelation<SolvableResidue<C>> rel = ring.table.lookup(g2, f2); 271 if (debug) 272 logger.info("poly, g = " + g + ", f = " + f + ", rel = " + rel); 273 Ds = new ResidueSolvablePolynomial<C>(ring, rel.p); //ring.copy(rel.p); 274 if (rel.f != null) { 275 D2 = new ResidueSolvablePolynomial<C>(ring, one, rel.f); 276 Ds = Ds.multiply(D2); 277 if (rel.e == null) { 278 g4 = g2; 279 } else { 280 g4 = g2.subtract(rel.e); 281 } 282 ring.table.update(g4, f2, Ds); 283 } 284 if (rel.e != null) { 285 D1 = new ResidueSolvablePolynomial<C>(ring, one, rel.e); 286 Ds = D1.multiply(Ds); 287 ring.table.update(g2, f2, Ds); 288 } 289 if (!f1.isZERO()) { 290 D2 = new ResidueSolvablePolynomial<C>(ring, one, f1); 291 Ds = Ds.multiply(D2); 292 //ring.table.update(?,f1,Ds) 293 } 294 if (!g1.isZERO()) { 295 D1 = new ResidueSolvablePolynomial<C>(ring, one, g1); 296 Ds = D1.multiply(Ds); 297 //ring.table.update(e1,?,Ds) 298 } 299 } 300 Ds = Ds.multiplyLeft(c); // assume c commutes with Cs 301 Dps = (ResidueSolvablePolynomial<C>) Dps.sum(Ds); 302 } // end Dps loop 303 Ds = Dps; 304 } 305 Ds = Ds.multiplyLeft(a); // multiply(a,b); // non-symmetric 306 if (debug) 307 logger.debug("Ds = " + Ds); 308 Dp = (ResidueSolvablePolynomial<C>) Dp.sum(Ds); 309 } // end B loop 310 } // end A loop 311 return Dp; 312 } 313 314 315 /** 316 * ResidueSolvablePolynomial left and right multiplication. Product with two 317 * polynomials. 318 * @param S ResidueSolvablePolynomial. 319 * @param T ResidueSolvablePolynomial. 320 * @return S*this*T. 321 */ 322 public ResidueSolvablePolynomial<C> multiply(ResidueSolvablePolynomial<C> S, 323 ResidueSolvablePolynomial<C> T) { 324 if (S.isZERO() || T.isZERO() || this.isZERO()) { 325 return ring.getZERO(); 326 } 327 if (S.isONE()) { 328 return multiply(T); 329 } 330 if (T.isONE()) { 331 return S.multiply(this); 332 } 333 return S.multiply(this).multiply(T); 334 } 335 336 337 /** 338 * ResidueSolvablePolynomial multiplication. Product with coefficient ring 339 * element. 340 * @param b coefficient polynomial. 341 * @return this*b, where * is coefficient multiplication. 342 */ 343 @Override 344 public ResidueSolvablePolynomial<C> multiply(SolvableResidue<C> b) { 345 ResidueSolvablePolynomial<C> Cp = ring.getZERO().copy(); 346 if (b == null || b.isZERO()) { 347 return Cp; 348 } 349 Cp = new ResidueSolvablePolynomial<C>(ring, b, ring.evzero); 350 return multiply(Cp); 351 } 352 353 354 /** 355 * ResidueSolvablePolynomial left and right multiplication. Product with 356 * coefficient ring element. 357 * @param b coefficient polynomial. 358 * @param c coefficient polynomial. 359 * @return b*this*c, where * is coefficient multiplication. 360 */ 361 @Override 362 public ResidueSolvablePolynomial<C> multiply(SolvableResidue<C> b, SolvableResidue<C> c) { 363 ResidueSolvablePolynomial<C> Cp = ring.getZERO().copy(); 364 if (b == null || b.isZERO()) { 365 return Cp; 366 } 367 if (c == null || c.isZERO()) { 368 return Cp; 369 } 370 ResidueSolvablePolynomial<C> Cb = new ResidueSolvablePolynomial<C>(ring, b, ring.evzero); 371 ResidueSolvablePolynomial<C> Cc = new ResidueSolvablePolynomial<C>(ring, c, ring.evzero); 372 return Cb.multiply(this).multiply(Cc); 373 } 374 375 376 /** 377 * ResidueSolvablePolynomial multiplication. Product with exponent vector. 378 * @param e exponent. 379 * @return this * x<sup>e</sup>, where * denotes solvable multiplication. 380 */ 381 @Override 382 public ResidueSolvablePolynomial<C> multiply(ExpVector e) { 383 if (e == null || e.isZERO()) { 384 return this; 385 } 386 SolvableResidue<C> b = ring.getONECoefficient(); 387 return multiply(b, e); 388 } 389 390 391 /** 392 * ResidueSolvablePolynomial left and right multiplication. Product with 393 * exponent vector. 394 * @param e exponent. 395 * @param f exponent. 396 * @return x<sup>e</sup> * this * x<sup>f</sup>, where * denotes solvable 397 * multiplication. 398 */ 399 @Override 400 public ResidueSolvablePolynomial<C> multiply(ExpVector e, ExpVector f) { 401 if (e == null || e.isZERO()) { 402 return this; 403 } 404 if (f == null || f.isZERO()) { 405 return this; 406 } 407 SolvableResidue<C> b = ring.getONECoefficient(); 408 return multiply(b, e, b, f); 409 } 410 411 412 /** 413 * ResidueSolvablePolynomial multiplication. Product with ring element and 414 * exponent vector. 415 * @param b coefficient polynomial. 416 * @param e exponent. 417 * @return this * b x<sup>e</sup>, where * denotes solvable multiplication. 418 */ 419 @Override 420 public ResidueSolvablePolynomial<C> multiply(SolvableResidue<C> b, ExpVector e) { 421 if (b == null || b.isZERO()) { 422 return ring.getZERO(); 423 } 424 ResidueSolvablePolynomial<C> Cp = new ResidueSolvablePolynomial<C>(ring, b, e); 425 return multiply(Cp); 426 } 427 428 429 /** 430 * ResidueSolvablePolynomial left and right multiplication. Product with 431 * ring element and exponent vector. 432 * @param b coefficient polynomial. 433 * @param e exponent. 434 * @param c coefficient polynomial. 435 * @param f exponent. 436 * @return b x<sup>e</sup> * this * c x<sup>f</sup>, where * denotes 437 * solvable multiplication. 438 */ 439 @Override 440 public ResidueSolvablePolynomial<C> multiply(SolvableResidue<C> b, ExpVector e, SolvableResidue<C> c, 441 ExpVector f) { 442 if (b == null || b.isZERO()) { 443 return ring.getZERO(); 444 } 445 if (c == null || c.isZERO()) { 446 return ring.getZERO(); 447 } 448 ResidueSolvablePolynomial<C> Cp = new ResidueSolvablePolynomial<C>(ring, b, e); 449 ResidueSolvablePolynomial<C> Dp = new ResidueSolvablePolynomial<C>(ring, c, f); 450 return multiply(Cp, Dp); 451 } 452 453 454 /** 455 * ResidueSolvablePolynomial multiplication. Left product with ring element 456 * and exponent vector. 457 * @param b coefficient polynomial. 458 * @param e exponent. 459 * @return b x<sup>e</sup> * this, where * denotes solvable multiplication. 460 */ 461 @Override 462 public ResidueSolvablePolynomial<C> multiplyLeft(SolvableResidue<C> b, ExpVector e) { 463 if (b == null || b.isZERO()) { 464 return ring.getZERO(); 465 } 466 ResidueSolvablePolynomial<C> Cp = new ResidueSolvablePolynomial<C>(ring, b, e); 467 return Cp.multiply(this); 468 } 469 470 471 /** 472 * ResidueSolvablePolynomial multiplication. Left product with exponent 473 * vector. 474 * @param e exponent. 475 * @return x<sup>e</sup> * this, where * denotes solvable multiplication. 476 */ 477 @Override 478 public ResidueSolvablePolynomial<C> multiplyLeft(ExpVector e) { 479 if (e == null || e.isZERO()) { 480 return this; 481 } 482 SolvableResidue<C> b = ring.getONECoefficient(); 483 ResidueSolvablePolynomial<C> Cp = new ResidueSolvablePolynomial<C>(ring, b, e); 484 return Cp.multiply(this); 485 } 486 487 488 /** 489 * ResidueSolvablePolynomial multiplication. Left product with coefficient 490 * ring element. 491 * @param b coefficient polynomial. 492 * @return b*this, where * is coefficient multiplication. 493 */ 494 @Override 495 public ResidueSolvablePolynomial<C> multiplyLeft(SolvableResidue<C> b) { 496 ResidueSolvablePolynomial<C> Cp = ring.getZERO().copy(); 497 if (b == null || b.isZERO()) { 498 return Cp; 499 } 500 Map<ExpVector, SolvableResidue<C>> Cm = Cp.val; //getMap(); 501 Map<ExpVector, SolvableResidue<C>> Am = val; 502 SolvableResidue<C> c; 503 for (Map.Entry<ExpVector, SolvableResidue<C>> y : Am.entrySet()) { 504 ExpVector e = y.getKey(); 505 SolvableResidue<C> a = y.getValue(); 506 c = b.multiply(a); 507 if (!c.isZERO()) { 508 Cm.put(e, c); 509 } 510 } 511 return Cp; 512 } 513 514 515 /** 516 * ResidueSolvablePolynomial multiplication. Left product with 'monomial'. 517 * @param m 'monomial'. 518 * @return m * this, where * denotes solvable multiplication. 519 */ 520 @Override 521 public ResidueSolvablePolynomial<C> multiplyLeft(Map.Entry<ExpVector, SolvableResidue<C>> m) { 522 if (m == null) { 523 return ring.getZERO(); 524 } 525 return multiplyLeft(m.getValue(), m.getKey()); 526 } 527 528 529 /** 530 * ResidueSolvablePolynomial multiplication. Product with 'monomial'. 531 * @param m 'monomial'. 532 * @return this * m, where * denotes solvable multiplication. 533 */ 534 @Override 535 public ResidueSolvablePolynomial<C> multiply(Map.Entry<ExpVector, SolvableResidue<C>> m) { 536 if (m == null) { 537 return ring.getZERO(); 538 } 539 return multiply(m.getValue(), m.getKey()); 540 } 541 542 543 /** 544 * ResidueSolvablePolynomial multiplication with exponent vector. 545 * @param f exponent vector. 546 * @return B*f, where * is commutative multiplication. 547 */ 548 protected ResidueSolvablePolynomial<C> shift(ExpVector f) { 549 ResidueSolvablePolynomial<C> C = ring.getZERO().copy(); 550 if (this.isZERO()) { 551 return C; 552 } 553 if (f == null || f.isZERO()) { 554 return this; 555 } 556 Map<ExpVector, SolvableResidue<C>> Cm = C.val; 557 Map<ExpVector, SolvableResidue<C>> Bm = this.val; 558 for (Map.Entry<ExpVector, SolvableResidue<C>> y : Bm.entrySet()) { 559 ExpVector e = y.getKey(); 560 SolvableResidue<C> a = y.getValue(); 561 ExpVector d = e.sum(f); 562 if (!a.isZERO()) { 563 Cm.put(d, a); 564 } 565 } 566 return C; 567 } 568 569}