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