001/* 002 * $Id: SolvableLocal.java 5267 2015-07-27 17:57:50Z kredel $ 003 */ 004 005package edu.jas.application; 006 007 008import java.util.Arrays; 009 010import org.apache.log4j.Logger; 011 012import edu.jas.gbufd.PolyModUtil; 013import edu.jas.kern.PrettyPrint; 014import edu.jas.poly.ExpVector; 015import edu.jas.poly.GenPolynomial; 016import edu.jas.poly.GenSolvablePolynomial; 017import edu.jas.structure.GcdRingElem; 018import edu.jas.structure.QuotPair; 019 020 021/** 022 * SolvableLocal ring element based on pairs of GenSolvablePolynomial with 023 * GcdRingElem interface. Objects of this class are immutable. 024 * @author Heinz Kredel 025 */ 026public class SolvableLocal<C extends GcdRingElem<C>> implements GcdRingElem<SolvableLocal<C>>, 027 QuotPair<GenPolynomial<C>> { 028 029 030 private static final Logger logger = Logger.getLogger(SolvableLocal.class); 031 032 033 private final boolean debug = logger.isDebugEnabled(); 034 035 036 /** 037 * SolvableLocal class factory data structure. 038 */ 039 public final SolvableLocalRing<C> ring; 040 041 042 /** 043 * Numerator part of the element data structure. 044 */ 045 public final GenSolvablePolynomial<C> num; 046 047 048 /** 049 * Denominator part of the element data structure. 050 */ 051 public final GenSolvablePolynomial<C> den; 052 053 054 /** 055 * Flag to remember if this local element is a unit. -1 is unknown, 1 is 056 * unit, 0 not a unit. 057 */ 058 protected int isunit = -1; // initially unknown 059 060 061 /** 062 * The constructor creates a SolvableLocal object from a ring factory. 063 * @param r ring factory. 064 */ 065 public SolvableLocal(SolvableLocalRing<C> r) { 066 this(r, r.ring.getZERO()); 067 } 068 069 070 /** 071 * The constructor creates a SolvableLocal object from a ring factory and a 072 * numerator polynomial. The denominator is assumed to be 1. 073 * @param r ring factory. 074 * @param n numerator polynomial. 075 */ 076 public SolvableLocal(SolvableLocalRing<C> r, GenSolvablePolynomial<C> n) { 077 this(r, n, r.ring.getONE(), true); 078 } 079 080 081 /** 082 * The constructor creates a SolvableLocal object from a ring factory and a 083 * numerator and denominator polynomial. 084 * @param r ring factory. 085 * @param n numerator polynomial. 086 * @param d denominator polynomial. 087 */ 088 public SolvableLocal(SolvableLocalRing<C> r, GenSolvablePolynomial<C> n, GenSolvablePolynomial<C> d) { 089 this(r, n, d, false); 090 } 091 092 093 /** 094 * The constructor creates a SolvableLocal object from a ring factory and a 095 * numerator and denominator polynomial. 096 * @param r ring factory. 097 * @param n numerator polynomial. 098 * @param d denominator polynomial. 099 * @param isred true if gcd(n,d) == 1, else false. 100 */ 101 protected SolvableLocal(SolvableLocalRing<C> r, GenSolvablePolynomial<C> n, GenSolvablePolynomial<C> d, 102 boolean isred) { 103 if (d == null || d.isZERO()) { 104 throw new IllegalArgumentException("denominator may not be zero"); 105 } 106 ring = r; 107 if (d.signum() < 0) { 108 n = (GenSolvablePolynomial<C>) n.negate(); 109 d = (GenSolvablePolynomial<C>) d.negate(); 110 } 111 if (isred) { 112 num = n; 113 den = d; 114 return; 115 } 116 if (debug) { 117 System.out.println("n = " + n + ", d = " + d); 118 } 119 GenSolvablePolynomial<C> p = ring.ideal.normalform(d); 120 if (p == null || p.isZERO()) { 121 throw new IllegalArgumentException("denominator may not be in ideal, d = " + d); 122 } 123 //d = p; can't do this 124 C lc = d.leadingBaseCoefficient(); 125 if (!lc.isONE() && lc.isUnit()) { 126 lc = lc.inverse(); 127 n = n.multiplyLeft(lc); 128 d = d.multiplyLeft(lc); 129 } 130 if (n.compareTo(d) == 0) { 131 num = ring.ring.getONE(); 132 den = ring.ring.getONE(); 133 return; 134 } 135 if (n.negate().compareTo(d) == 0) { 136 num = (GenSolvablePolynomial<C>) ring.ring.getONE().negate(); 137 den = ring.ring.getONE(); 138 return; 139 } 140 if (n.isZERO()) { 141 num = n; 142 den = ring.ring.getONE(); 143 return; 144 } 145 if (n.isONE()) { 146 num = n; 147 den = d; 148 return; 149 } 150 // must reduce to lowest terms 151 // not perfect, TODO 152 GenSolvablePolynomial<C>[] gcd = PolyModUtil.<C> syzGcdCofactors(r.ring, n, d); 153 if (!gcd[0].isONE()) { 154 logger.info("constructor: gcd = " + Arrays.toString(gcd)); // + ", " + n + ", " +d); 155 n = gcd[1]; 156 d = gcd[2]; 157 // d not in ideal --> gcd not in ideal 158 //p = ring.ideal.normalform( gcd ); 159 //if ( p == null || p.isZERO() ) { // todo: find nonzero factor 160 //} 161 } 162 // not perfect, TODO 163 GenSolvablePolynomial<C>[] simp = ring.engine.leftSimplifier(n, d); 164 logger.info("simp: " + Arrays.toString(simp) + ", " + n + ", " + d); 165 num = simp[0]; 166 den = simp[1]; 167 } 168 169 170 /** 171 * Get the corresponding element factory. 172 * @return factory for this Element. 173 * @see edu.jas.structure.Element#factory() 174 */ 175 public SolvableLocalRing<C> factory() { 176 return ring; 177 } 178 179 180 /** 181 * Numerator. 182 * @see edu.jas.structure.QuotPair#numerator() 183 */ 184 public GenSolvablePolynomial<C> numerator() { 185 return num; 186 } 187 188 189 /** 190 * Denominator. 191 * @see edu.jas.structure.QuotPair#denominator() 192 */ 193 public GenSolvablePolynomial<C> denominator() { 194 return den; 195 } 196 197 198 /** 199 * Clone this. 200 * @see java.lang.Object#clone() 201 */ 202 @Override 203 public SolvableLocal<C> copy() { 204 return new SolvableLocal<C>(ring, num, den, true); 205 } 206 207 208 /** 209 * Is SolvableLocal zero. 210 * @return If this is 0 then true is returned, else false. 211 * @see edu.jas.structure.RingElem#isZERO() 212 */ 213 public boolean isZERO() { 214 return num.isZERO(); 215 } 216 217 218 /** 219 * Is SolvableLocal one. 220 * @return If this is 1 then true is returned, else false. 221 * @see edu.jas.structure.RingElem#isONE() 222 */ 223 public boolean isONE() { 224 return num.compareTo(den) == 0; 225 } 226 227 228 /** 229 * Is SolvableLocal unit. 230 * @return If this is a unit then true is returned, else false. 231 * @see edu.jas.structure.RingElem#isUnit() 232 */ 233 public boolean isUnit() { 234 if (isunit > 0) { 235 return true; 236 } 237 if (isunit == 0) { 238 return false; 239 } 240 // not jet known 241 if (num.isZERO()) { 242 isunit = 0; 243 return false; 244 } 245 GenSolvablePolynomial<C> p = ring.ideal.normalform(num); 246 boolean u = (p != null && !p.isZERO()); 247 if (u) { 248 isunit = 1; 249 } else { 250 isunit = 0; 251 } 252 return u; 253 } 254 255 256 /** 257 * Is Qoutient a constant. 258 * @return true, if this has constant numerator and denominator, else false. 259 */ 260 public boolean isConstant() { 261 return num.isConstant() && den.isConstant(); 262 } 263 264 265 /** 266 * Get the String representation as RingElem. 267 * @see java.lang.Object#toString() 268 */ 269 @Override 270 public String toString() { 271 if (PrettyPrint.isTrue()) { 272 String s = "{ " + num.toString(ring.ring.getVars()); 273 if (den.isONE()) { 274 return s + " }"; 275 } 276 return s + "| " + den.toString(ring.ring.getVars()) + " }"; 277 } 278 return "SolvableLocal[ " + num.toString() + " | " + den.toString() + " ]"; 279 } 280 281 282 /** 283 * Get a scripting compatible string representation. 284 * @return script compatible representation for this Element. 285 * @see edu.jas.structure.Element#toScript() 286 */ 287 @Override 288 public String toScript() { 289 // Python case 290 if (den.isONE()) { 291 return num.toScript(); 292 } 293 return num.toScript() + " / " + den.toScript(); 294 } 295 296 297 /** 298 * Get a scripting compatible string representation of the factory. 299 * @return script compatible representation for this ElemFactory. 300 * @see edu.jas.structure.Element#toScriptFactory() 301 */ 302 @Override 303 public String toScriptFactory() { 304 // Python case 305 return factory().toScript(); 306 } 307 308 309 /** 310 * SolvableLocal comparison. 311 * @param b SolvableLocal. 312 * @return sign(this-b). 313 */ 314 @Override 315 public int compareTo(SolvableLocal<C> b) { 316 if (b == null || b.isZERO()) { 317 return this.signum(); 318 } 319 if (this.isZERO()) { 320 return -b.signum(); 321 } 322 // assume sign(den,b.den) > 0 323 int s1 = num.signum(); 324 int s2 = b.num.signum(); 325 int t = (s1 - s2) / 2; 326 if (t != 0) { 327 System.out.println("compareTo: t = " + t); 328 return t; 329 } 330 if (den.compareTo(b.den) == 0) { 331 return num.compareTo(b.num); 332 } 333 GenSolvablePolynomial<C> r, s; 334 // if (den.isONE()) { } 335 // if (b.den.isONE()) { } 336 GenSolvablePolynomial<C>[] oc = ring.engine.leftOreCond(den, b.den); 337 if (debug) { 338 System.out.println("oc[0] den =<>= oc[1] b.den: (" + oc[0] + ") (" + den + ") = (" + oc[1] 339 + ") (" + b.den + ")"); 340 } 341 //System.out.println("oc[0] = " + oc[0]); 342 //System.out.println("oc[1] = " + oc[1]); 343 r = oc[0].multiply(num); 344 s = oc[1].multiply(b.num); 345 return r.compareTo(s); 346 } 347 348 349 /** 350 * Comparison with any other object. 351 * @see java.lang.Object#equals(java.lang.Object) 352 */ 353 @SuppressWarnings("unchecked") 354 @Override 355 public boolean equals(Object b) { 356 if (!(b instanceof SolvableLocal)) { 357 return false; 358 } 359 SolvableLocal<C> a = null; 360 try { 361 a = (SolvableLocal<C>) b; 362 } catch (ClassCastException e) { 363 } 364 if (a == null) { 365 return false; 366 } 367 return compareTo(a) == 0; 368 } 369 370 371 /** 372 * Hash code for this local. 373 * @see java.lang.Object#hashCode() 374 */ 375 @Override 376 public int hashCode() { 377 int h; 378 h = ring.hashCode(); 379 h = 37 * h + num.hashCode(); 380 h = 37 * h + den.hashCode(); 381 return h; 382 } 383 384 385 /** 386 * SolvableLocal absolute value. 387 * @return the absolute value of this. 388 * @see edu.jas.structure.RingElem#abs() 389 */ 390 public SolvableLocal<C> abs() { 391 return new SolvableLocal<C>(ring, (GenSolvablePolynomial<C>) num.abs(), den, true); 392 } 393 394 395 /** 396 * SolvableLocal summation. 397 * @param S SolvableLocal. 398 * @return this+S. 399 */ 400 public SolvableLocal<C> sum(SolvableLocal<C> S) { 401 if (S == null || S.isZERO()) { 402 return this; 403 } 404 if (this.isZERO()) { 405 return S; 406 } 407 GenSolvablePolynomial<C> n, d, n1, n2; 408 if (den.isONE() && S.den.isONE()) { 409 n = (GenSolvablePolynomial<C>) num.sum(S.num); 410 return new SolvableLocal<C>(ring, n, den, true); 411 } 412 /* wrong: 413 if (den.isONE()) { } 414 if (S.den.isONE()) { } 415 */ 416 if (den.compareTo(S.den) == 0) { // correct ? 417 n = (GenSolvablePolynomial<C>) num.sum(S.num); 418 return new SolvableLocal<C>(ring, n, den, false); 419 } 420 // general case 421 GenSolvablePolynomial<C>[] oc = ring.engine.leftOreCond(den, S.den); 422 if (debug) { 423 System.out.println("oc[0] den =sum= oc[1] S.den: (" + oc[0] + ") (" + den + ") = (" + oc[1] 424 + ") (" + S.den + ")"); 425 } 426 //System.out.println("oc[0] = " + oc[0]); 427 //System.out.println("oc[1] = " + oc[1]); 428 d = oc[0].multiply(den); 429 n1 = oc[0].multiply(num); 430 n2 = oc[1].multiply(S.num); 431 n = (GenSolvablePolynomial<C>) n1.sum(n2); 432 //System.out.println("n = " + n); 433 //System.out.println("d = " + d); 434 return new SolvableLocal<C>(ring, n, d, false); 435 } 436 437 438 /** 439 * SolvableLocal negate. 440 * @return -this. 441 * @see edu.jas.structure.RingElem#negate() 442 */ 443 public SolvableLocal<C> negate() { 444 return new SolvableLocal<C>(ring, (GenSolvablePolynomial<C>) num.negate(), den, true); 445 } 446 447 448 /** 449 * SolvableLocal signum. 450 * @see edu.jas.structure.RingElem#signum() 451 * @return signum(this). 452 */ 453 public int signum() { 454 return num.signum(); 455 } 456 457 458 /** 459 * SolvableLocal subtraction. 460 * @param S SolvableLocal. 461 * @return this-S. 462 */ 463 public SolvableLocal<C> subtract(SolvableLocal<C> S) { 464 return sum(S.negate()); 465 } 466 467 468 /** 469 * SolvableLocal division. 470 * @param S SolvableLocal. 471 * @return this/S. 472 */ 473 public SolvableLocal<C> divide(SolvableLocal<C> S) { 474 return multiply(S.inverse()); 475 } 476 477 478 /** 479 * SolvableLocal inverse. 480 * @see edu.jas.structure.RingElem#inverse() 481 * @return S with S = 1/this if defined. 482 */ 483 public SolvableLocal<C> inverse() { 484 if (isONE()) { 485 return this; 486 } 487 if (isUnit()) { 488 return new SolvableLocal<C>(ring, den, num, true); 489 } 490 throw new ArithmeticException("element not invertible " + this); 491 } 492 493 494 /** 495 * SolvableLocal remainder. 496 * @param S SolvableLocal. 497 * @return this - (this/S)*S. 498 */ 499 public SolvableLocal<C> remainder(SolvableLocal<C> S) { 500 if (S.isUnit()) { 501 return ring.getZERO(); 502 } 503 throw new UnsupportedOperationException("remainder not implemented" + S); 504 } 505 506 507 /** 508 * SolvableLocal multiplication. 509 * @param S SolvableLocal. 510 * @return this*S. 511 */ 512 public SolvableLocal<C> multiply(SolvableLocal<C> S) { 513 if (S == null || S.isZERO()) { 514 return S; 515 } 516 if (num.isZERO()) { 517 return this; 518 } 519 if (S.isONE()) { 520 return this; 521 } 522 if (this.isONE()) { 523 return S; 524 } 525 GenSolvablePolynomial<C> n, d; 526 if (den.isONE() && S.den.isONE()) { 527 n = num.multiply(S.num); 528 return new SolvableLocal<C>(ring, n, den, true); 529 } 530 /* wrong: 531 if (den.isONE()) { } 532 if (S.den.isONE()) { } 533 if ( den.compareTo(S.den) == 0 ) { } 534 */ 535 GenSolvablePolynomial<C>[] oc = ring.engine.leftOreCond(num, S.den); 536 if (debug) { 537 System.out.println("oc[0] num =mult= oc[1] S.den: (" + oc[0] + ") (" + num + ") = (" + oc[1] 538 + ") (" + S.den + ")"); 539 } 540 //System.out.println("oc[0] = " + oc[0]); 541 //System.out.println("oc[1] = " + oc[1]); 542 n = oc[1].multiply(S.num); 543 d = oc[0].multiply(den); 544 return new SolvableLocal<C>(ring, n, d, false); 545 } 546 547 548 /** 549 * SolvableLocal multiplication by GenSolvablePolynomial. 550 * @param b GenSolvablePolynomial. 551 * @return this*b. 552 */ 553 public SolvableLocal<C> multiply(GenSolvablePolynomial<C> b) { 554 if (b == null || b.isZERO()) { 555 return ring.getZERO(); 556 } 557 if (num.isZERO()) { 558 return this; 559 } 560 if (b.isONE()) { 561 return this; 562 } 563 SolvableLocal<C> B = new SolvableLocal<C>(ring, b); 564 return multiply(B); 565 } 566 567 568 /** 569 * SolvableLocal multiplication by coefficient. 570 * @param b coefficient. 571 * @return this*b. 572 */ 573 public SolvableLocal<C> multiply(C b) { 574 if (b == null || b.isZERO()) { 575 return ring.getZERO(); 576 } 577 if (num.isZERO()) { 578 return this; 579 } 580 if (b.isONE()) { 581 return this; 582 } 583 GenSolvablePolynomial<C> B = ring.ring.getONE().multiply(b); 584 return multiply(B); 585 } 586 587 588 /** 589 * SolvableLocal multiplication by exponent. 590 * @param e exponent vector. 591 * @return this*b. 592 */ 593 public SolvableLocal<C> multiply(ExpVector e) { 594 if (e == null || e.isZERO()) { 595 return this; 596 } 597 if (num.isZERO()) { 598 return this; 599 } 600 GenSolvablePolynomial<C> B = ring.ring.getONE().multiply(e); 601 return multiply(B); 602 } 603 604 605 /** 606 * SolvableLocal monic. 607 * @return this with monic value part. 608 */ 609 public SolvableLocal<C> monic() { 610 if (num.isZERO()) { 611 return this; 612 } 613 return this; 614 // non sense: 615 //C lbc = num.leadingBaseCoefficient(); 616 //lbc = lbc.inverse(); 617 //GenSolvablePolynomial<C> n = num.multiply(lbc); 618 //GenSolvablePolynomial<C> d = den.multiply(lbc); 619 //return new SolvableLocal<C>(ring, n, d, true); 620 } 621 622 623 /** 624 * Greatest common divisor. 625 * @param b other element. 626 * @return gcd(this,b). 627 */ 628 public SolvableLocal<C> gcd(SolvableLocal<C> b) { 629 throw new UnsupportedOperationException("gcd not implemented " + this.getClass().getName()); 630 } 631 632 633 /** 634 * Extended greatest common divisor. <b>Note: </b>Not implemented, throws 635 * UnsupportedOperationException. 636 * @param b other element. 637 * @return [ gcd(this,b), c1, c2 ] with c1*this + c2*b = gcd(this,b). 638 */ 639 public SolvableLocal<C>[] egcd(SolvableLocal<C> b) { 640 throw new UnsupportedOperationException("egcd not implemented " + this.getClass().getName()); 641 } 642 643}