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