001 /* 002 * $Id: Quotient.java 3356 2010-10-23 16:41:01Z kredel $ 003 */ 004 005 package edu.jas.ufd; 006 007 008 import org.apache.log4j.Logger; 009 010 import edu.jas.kern.PrettyPrint; 011 import edu.jas.poly.GenPolynomial; 012 import 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 */ 020 public 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> clone() { 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 } else { 169 return true; 170 } 171 } 172 173 174 /** 175 * Is Qoutient a constant. 176 * @return true, if this has constant numerator and denominator, else false. 177 */ 178 public boolean isConstant() { 179 return num.isConstant() && den.isConstant(); 180 } 181 182 183 /** 184 * Get the String representation as RingElem. 185 * @see java.lang.Object#toString() 186 */ 187 @Override 188 public String toString() { 189 if (PrettyPrint.isTrue()) { 190 String s = "{ " + num.toString(ring.ring.getVars()); 191 if (!den.isONE()) { 192 s += " | " + den.toString(ring.ring.getVars()); 193 } 194 return s + " }"; 195 } else { 196 return "Quotient[ " + num.toString() + " | " + den.toString() + " ]"; 197 } 198 } 199 200 201 /** 202 * Get a scripting compatible string representation. 203 * @return script compatible representation for this Element. 204 * @see edu.jas.structure.Element#toScript() 205 */ 206 //JAVA6only: @Override 207 public String toScript() { 208 // Python case 209 if (den.isONE()) { 210 return num.toScript(); 211 } else { 212 return num.toScript() + " / " + den.toScript(); 213 } 214 } 215 216 217 /** 218 * Get a scripting compatible string representation of the factory. 219 * @return script compatible representation for this ElemFactory. 220 * @see edu.jas.structure.Element#toScriptFactory() 221 */ 222 //JAVA6only: @Override 223 public String toScriptFactory() { 224 // Python case 225 return factory().toScript(); 226 } 227 228 229 /** 230 * Quotient comparison. 231 * @param b Quotient. 232 * @return sign(this-b). 233 */ 234 //JAVA6only: @Override 235 public int compareTo(Quotient<C> b) { 236 if (b == null || b.isZERO()) { 237 return this.signum(); 238 } 239 if (this.isZERO()) { 240 return -b.signum(); 241 } 242 int s1 = num.signum(); 243 int s2 = b.num.signum(); 244 int t = (s1 - s2) / 2; 245 if (t != 0) { 246 return t; 247 } 248 GenPolynomial<C> r = num.multiply(b.den); 249 GenPolynomial<C> s = den.multiply(b.num); 250 //GenPolynomial<C> x = r.subtract( s ); 251 //return x.signum(); 252 return r.compareTo(s); 253 } 254 255 256 /** 257 * Comparison with any other object. 258 * @see java.lang.Object#equals(java.lang.Object) 259 */ 260 @SuppressWarnings("unchecked") 261 // not jet working 262 @Override 263 public boolean equals(Object b) { 264 if (!(b instanceof Quotient)) { 265 return false; 266 } 267 Quotient<C> a = null; 268 try { 269 a = (Quotient<C>) b; 270 } catch (ClassCastException e) { 271 } 272 if (a == null) { 273 return false; 274 } 275 //return ( 0 == compareTo( a ) ); 276 return num.equals(a.num) && den.equals(a.den); 277 } 278 279 280 /** 281 * Hash code for this local. 282 * @see java.lang.Object#hashCode() 283 */ 284 @Override 285 public int hashCode() { 286 int h; 287 h = ring.hashCode(); 288 h = 37 * h + num.hashCode(); 289 h = 37 * h + den.hashCode(); 290 return h; 291 } 292 293 294 /** 295 * Quotient absolute value. 296 * @return the absolute value of this. 297 * @see edu.jas.structure.RingElem#abs() 298 */ 299 public Quotient<C> abs() { 300 return new Quotient<C>(ring, num.abs(), den, true); 301 } 302 303 304 /** 305 * Quotient summation. 306 * @param S Quotient. 307 * @return this+S. 308 */ 309 public Quotient<C> sum(Quotient<C> S) { 310 if (S == null || S.isZERO()) { 311 return this; 312 } 313 if (this.isZERO()) { 314 return S; 315 } 316 GenPolynomial<C> n; 317 if (den.isONE() && S.den.isONE()) { 318 n = num.sum(S.num); 319 return new Quotient<C>(ring, n); 320 } 321 if (den.isONE()) { 322 n = num.multiply(S.den); 323 n = n.sum(S.num); 324 return new Quotient<C>(ring, n, S.den, true); 325 } 326 if (S.den.isONE()) { 327 n = S.num.multiply(den); 328 n = n.sum(num); 329 return new Quotient<C>(ring, n, den, true); 330 } 331 GenPolynomial<C> d; 332 GenPolynomial<C> sd; 333 GenPolynomial<C> g; 334 g = ring.gcd(den, S.den); 335 if (g.isONE()) { 336 d = den; 337 sd = S.den; 338 } else { 339 d = ring.divide(den, g); 340 sd = ring.divide(S.den, g); 341 } 342 n = num.multiply(sd); 343 n = n.sum(d.multiply(S.num)); 344 if (n.isZERO()) { 345 return ring.getZERO(); 346 } 347 GenPolynomial<C> f; 348 GenPolynomial<C> dd; 349 dd = den; 350 if (!g.isONE()) { 351 f = ring.gcd(n, g); 352 if (!f.isONE()) { 353 n = ring.divide(n, f); 354 dd = ring.divide(den, f); 355 } 356 } 357 d = dd.multiply(sd); 358 return new Quotient<C>(ring, n, d, true); 359 } 360 361 362 /** 363 * Quotient negate. 364 * @return -this. 365 * @see edu.jas.structure.RingElem#negate() 366 */ 367 public Quotient<C> negate() { 368 return new Quotient<C>(ring, num.negate(), den, true); 369 } 370 371 372 /** 373 * Quotient signum. 374 * @see edu.jas.structure.RingElem#signum() 375 * @return signum(this). 376 */ 377 public int signum() { 378 return num.signum(); 379 } 380 381 382 /** 383 * Quotient subtraction. 384 * @param S Quotient. 385 * @return this-S. 386 */ 387 public Quotient<C> subtract(Quotient<C> S) { 388 return sum(S.negate()); 389 } 390 391 392 /** 393 * Quotient division. 394 * @param S Quotient. 395 * @return this/S. 396 */ 397 public Quotient<C> divide(Quotient<C> S) { 398 return multiply(S.inverse()); 399 } 400 401 402 /** 403 * Quotient inverse. 404 * @see edu.jas.structure.RingElem#inverse() 405 * @return S with S = 1/this. 406 */ 407 public Quotient<C> inverse() { 408 return new Quotient<C>(ring, den, num, true); 409 } 410 411 412 /** 413 * Quotient remainder. 414 * @param S Quotient. 415 * @return this - (this/S)*S. 416 */ 417 public Quotient<C> remainder(Quotient<C> S) { 418 if (num.isZERO()) { 419 throw new ArithmeticException("element not invertible " + this); 420 } 421 return ring.getZERO(); 422 } 423 424 425 /** 426 * Quotient multiplication. 427 * @param S Quotient. 428 * @return this*S. 429 */ 430 public Quotient<C> multiply(Quotient<C> S) { 431 if (S == null || S.isZERO()) { 432 return S; 433 } 434 if (num.isZERO()) { 435 return this; 436 } 437 if (S.isONE()) { 438 return this; 439 } 440 if (this.isONE()) { 441 return S; 442 } 443 GenPolynomial<C> n; 444 if (den.isONE() && S.den.isONE()) { 445 n = num.multiply(S.num); 446 return new Quotient<C>(ring, n); 447 } 448 GenPolynomial<C> g; 449 GenPolynomial<C> d; 450 if (den.isONE()) { 451 g = ring.gcd(num, S.den); 452 n = ring.divide(num, g); 453 d = ring.divide(S.den, g); 454 n = n.multiply(S.num); 455 return new Quotient<C>(ring, n, d, true); 456 } 457 if (S.den.isONE()) { 458 g = ring.gcd(S.num, den); 459 n = ring.divide(S.num, g); 460 d = ring.divide(den, g); 461 n = n.multiply(num); 462 return new Quotient<C>(ring, n, d, true); 463 } 464 GenPolynomial<C> f; 465 GenPolynomial<C> sd; 466 GenPolynomial<C> sn; 467 g = ring.gcd(num, S.den); 468 n = ring.divide(num, g); 469 sd = ring.divide(S.den, g); 470 f = ring.gcd(den, S.num); 471 d = ring.divide(den, f); 472 sn = ring.divide(S.num, f); 473 n = n.multiply(sn); 474 d = d.multiply(sd); 475 return new Quotient<C>(ring, n, d, true); 476 } 477 478 479 /** 480 * Quotient multiplication by GenPolynomial. 481 * @param b GenPolynomial<C>. 482 * @return this*b. 483 */ 484 public Quotient<C> multiply(GenPolynomial<C> b) { 485 if (b == null || b.isZERO()) { 486 return ring.getZERO(); 487 } 488 if (num.isZERO()) { 489 return this; 490 } 491 if (b.isONE()) { 492 return this; 493 } 494 GenPolynomial<C> gcd = ring.gcd(b, den); 495 GenPolynomial<C> d = den; 496 if (!gcd.isONE()) { 497 b = ring.divide(b, gcd); 498 d = ring.divide(d, gcd); 499 } 500 if (this.isONE()) { 501 return new Quotient<C>(ring, b, d, true); 502 } 503 GenPolynomial<C> n = num.multiply(b); 504 return new Quotient<C>(ring, n, d, true); 505 } 506 507 508 /** 509 * Quotient multiplication by coefficient. 510 * @param b coefficient. 511 * @return this*b. 512 */ 513 public Quotient<C> multiply(C b) { 514 if (b == null || b.isZERO()) { 515 return ring.getZERO(); 516 } 517 if (num.isZERO()) { 518 return this; 519 } 520 if (b.isONE()) { 521 return this; 522 } 523 GenPolynomial<C> n = num.multiply(b); 524 return new Quotient<C>(ring, n, den, true); 525 } 526 527 528 /** 529 * Quotient monic. 530 * @return this with monic value part. 531 */ 532 public Quotient<C> monic() { 533 if (num.isZERO()) { 534 return this; 535 } 536 C lbc = num.leadingBaseCoefficient(); 537 if (!lbc.isUnit()) { 538 return this; 539 } 540 lbc = lbc.inverse(); 541 lbc = lbc.abs(); 542 GenPolynomial<C> n = num.multiply(lbc); 543 GenPolynomial<C> d = den.multiply(lbc); 544 return new Quotient<C>(ring, n, d, true); 545 } 546 547 548 /** 549 * Greatest common divisor. 550 * @param b other element. 551 * @return gcd(this,b). 552 */ 553 public Quotient<C> gcd(Quotient<C> b) { 554 if (b == null || b.isZERO()) { 555 return this; 556 } 557 if (this.isZERO()) { 558 return b; 559 } 560 return ring.getONE(); 561 } 562 563 564 /** 565 * Extended greatest common divisor. 566 * @param b other element. 567 * @return [ gcd(this,b), c1, c2 ] with c1*this + c2*b = gcd(this,b). 568 */ 569 @SuppressWarnings("unchecked") 570 public Quotient<C>[] egcd(Quotient<C> b) { 571 Quotient<C>[] ret = (Quotient<C>[]) new Quotient[3]; 572 ret[0] = null; 573 ret[1] = null; 574 ret[2] = null; 575 if (b == null || b.isZERO()) { 576 ret[0] = this; 577 return ret; 578 } 579 if (this.isZERO()) { 580 ret[0] = b; 581 return ret; 582 } 583 GenPolynomial<C> two = ring.ring.fromInteger(2); 584 ret[0] = ring.getONE(); 585 ret[1] = (this.multiply(two)).inverse(); 586 ret[2] = (b.multiply(two)).inverse(); 587 return ret; 588 } 589 }