001/* 002 * $Id: Quotient.java 5934 2018-09-30 11:23:44Z kredel $ 003 */ 004 005package edu.jas.poly; 006 007 008import org.apache.logging.log4j.Logger; 009import org.apache.logging.log4j.LogManager; 010 011import edu.jas.structure.GcdRingElem; 012import edu.jas.structure.QuotPair; 013import edu.jas.structure.RingElem; 014 015 016/** 017 * Quotient element based on RingElem pairs. Objects of this class are 018 * immutable. 019 * @author Heinz Kredel 020 */ 021public class Quotient<C extends RingElem<C>> implements RingElem<Quotient<C>>, QuotPair<C> { 022 023 024 private static final Logger logger = LogManager.getLogger(Quotient.class); 025 026 027 private static final boolean debug = logger.isDebugEnabled(); 028 029 030 /** 031 * Quotient class factory data structure. 032 */ 033 public final QuotientRing<C> ring; 034 035 036 /** 037 * Numerator part of the element data structure. 038 */ 039 public final C num; 040 041 042 /** 043 * Denominator part of the element data structure. 044 */ 045 public final C den; 046 047 048 /** 049 * The constructor creates a Quotient object from a ring factory. 050 * @param r ring factory. 051 */ 052 public Quotient(QuotientRing<C> r) { 053 this(r, r.ring.getZERO()); 054 } 055 056 057 /** 058 * The constructor creates a Quotient object from a ring factory and a 059 * numerator element. The denominator is assumed to be 1. 060 * @param r ring factory. 061 * @param n numerator. 062 */ 063 public Quotient(QuotientRing<C> r, C n) { 064 this(r, n, r.ring.getONE(), true); 065 } 066 067 068 /** 069 * The constructor creates a Quotient object from a ring factory and a 070 * numerator and denominator element. 071 * @param r ring factory. 072 * @param n numerator. 073 * @param d denominator. 074 */ 075 public Quotient(QuotientRing<C> r, C n, C d) { 076 this(r, n, d, false); 077 } 078 079 080 /** 081 * The constructor creates a Quotient object from a ring factory and a 082 * numerator and denominator element. 083 * @param r ring factory. 084 * @param n numerator. 085 * @param d denominator. 086 * @param isred true if gcd(n,d) == 1, else false. 087 */ 088 @SuppressWarnings("unchecked") 089 protected Quotient(QuotientRing<C> r, C n, 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 num = n; 100 den = d; 101 return; 102 } 103 // must reduce to lowest terms 104 if (n instanceof GcdRingElem && d instanceof GcdRingElem) { 105 GcdRingElem ng = (GcdRingElem) n; 106 GcdRingElem dg = (GcdRingElem) d; 107 C gcd = (C) ng.gcd(dg); 108 if (debug) { 109 logger.info("gcd = " + gcd); 110 } 111 //RingElem<C> gcd = ring.ring.getONE(); 112 if (gcd.isONE()) { 113 num = n; 114 den = d; 115 } else { 116 num = n.divide(gcd); 117 den = d.divide(gcd); 118 } 119 // } else { // univariate polynomial? 120 } else { 121 logger.warn("gcd = ????: " + n.getClass() + ", " + d.getClass()); 122 num = n; 123 den = d; 124 } 125 } 126 127 128 /** 129 * Get the corresponding element factory. 130 * @return factory for this Element. 131 * @see edu.jas.structure.Element#factory() 132 */ 133 public QuotientRing<C> factory() { 134 return ring; 135 } 136 137 138 /** 139 * Numerator. 140 * @see edu.jas.structure.QuotPair#numerator() 141 */ 142 public C numerator() { 143 return num; 144 } 145 146 147 /** 148 * Denominator. 149 * @see edu.jas.structure.QuotPair#denominator() 150 */ 151 public C denominator() { 152 return den; 153 } 154 155 156 /** 157 * Is Quotient a constant. Not implemented. 158 * @throws UnsupportedOperationException. 159 */ 160 public boolean isConstant() { 161 throw new UnsupportedOperationException("isConstant not implemented"); 162 } 163 164 165 /** 166 * Clone this. 167 * @see java.lang.Object#clone() 168 */ 169 @Override 170 public Quotient<C> copy() { 171 return new Quotient<C>(ring, num, den, true); 172 } 173 174 175 /** 176 * Is Quotient zero. 177 * @return If this is 0 then true is returned, else false. 178 * @see edu.jas.structure.RingElem#isZERO() 179 */ 180 public boolean isZERO() { 181 return num.isZERO(); 182 } 183 184 185 /** 186 * Is Quotient one. 187 * @return If this is 1 then true is returned, else false. 188 * @see edu.jas.structure.RingElem#isONE() 189 */ 190 public boolean isONE() { 191 return num.equals(den); 192 } 193 194 195 /** 196 * Is Quotient unit. 197 * @return If this is a unit then true is returned, else false. 198 * @see edu.jas.structure.RingElem#isUnit() 199 */ 200 public boolean isUnit() { 201 if (num.isZERO()) { 202 return false; 203 } 204 return true; 205 } 206 207 208 /** 209 * Get the String representation as RingElem. 210 * @see java.lang.Object#toString() 211 */ 212 @Override 213 public String toString() { 214 return "Quotient[ " + num.toString() + " / " + den.toString() + " ]"; 215 } 216 217 218 /** 219 * Get a scripting compatible string representation. 220 * @return script compatible representation for this Element. 221 * @see edu.jas.structure.Element#toScript() 222 */ 223 @Override 224 public String toScript() { 225 // Python case 226 return "Quotient( " + num.toScript() + " , " + den.toScript() + " )"; 227 } 228 229 230 /** 231 * Get a scripting compatible string representation of the factory. 232 * @return script compatible representation for this ElemFactory. 233 * @see edu.jas.structure.Element#toScriptFactory() 234 */ 235 @Override 236 public String toScriptFactory() { 237 // Python case 238 return factory().toScript(); 239 } 240 241 242 /** 243 * Quotient comparison. 244 * @param b Quotient. 245 * @return sign(this-b). 246 */ 247 @Override 248 public int compareTo(Quotient<C> b) { 249 if (b == null || b.isZERO()) { 250 return this.signum(); 251 } 252 C r = num.multiply(b.den); 253 C s = den.multiply(b.num); 254 C x = r.subtract(s); 255 return x.signum(); 256 } 257 258 259 /** 260 * Comparison with any other object. 261 * @see java.lang.Object#equals(java.lang.Object) 262 */ 263 @Override 264 @SuppressWarnings("unchecked") 265 public boolean equals(Object b) { 266 if (b == null) { 267 return false; 268 } 269 if (!(b instanceof Quotient)) { 270 return false; 271 } 272 Quotient<C> a = (Quotient<C>) b; 273 return (0 == compareTo(a)); 274 } 275 276 277 /** 278 * Hash code for this local. 279 * @see java.lang.Object#hashCode() 280 */ 281 @Override 282 public int hashCode() { 283 int h; 284 h = ring.hashCode(); 285 h = 37 * h + num.hashCode(); 286 h = 37 * h + den.hashCode(); 287 return h; 288 } 289 290 291 /** 292 * Quotient absolute value. 293 * @return the absolute value of this. 294 * @see edu.jas.structure.RingElem#abs() 295 */ 296 public Quotient<C> abs() { 297 return new Quotient<C>(ring, num.abs(), den, true); 298 } 299 300 301 /** 302 * Quotient summation. 303 * @param S Quotient. 304 * @return this+S. 305 */ 306 public Quotient<C> sum(Quotient<C> S) { 307 if (S == null || S.isZERO()) { 308 return this; 309 } 310 C n = num.multiply(S.den); 311 n = n.sum(den.multiply(S.num)); 312 C d = den.multiply(S.den); 313 return new Quotient<C>(ring, n, d, false); 314 } 315 316 317 /** 318 * Quotient negate. 319 * @return -this. 320 * @see edu.jas.structure.RingElem#negate() 321 */ 322 public Quotient<C> negate() { 323 return new Quotient<C>(ring, num.negate(), den, true); 324 } 325 326 327 /** 328 * Quotient signum. 329 * @see edu.jas.structure.RingElem#signum() 330 * @return signum(this). 331 */ 332 public int signum() { 333 return num.signum(); 334 } 335 336 337 /** 338 * Quotient subtraction. 339 * @param S Quotient. 340 * @return this-S. 341 */ 342 public Quotient<C> subtract(Quotient<C> S) { 343 if (S == null || S.isZERO()) { 344 return this; 345 } 346 C n = num.multiply(S.den); 347 n = n.subtract(den.multiply(S.num)); 348 C d = den.multiply(S.den); 349 return new Quotient<C>(ring, n, d, false); 350 } 351 352 353 /** 354 * Quotient division. 355 * @param S Quotient. 356 * @return this/S. 357 */ 358 public Quotient<C> divide(Quotient<C> S) { 359 return multiply(S.inverse()); 360 } 361 362 363 /** 364 * Quotient inverse. 365 * @see edu.jas.structure.RingElem#inverse() 366 * @return S with S = 1/this. 367 */ 368 public Quotient<C> inverse() { 369 return new Quotient<C>(ring, den, num, true); 370 } 371 372 373 /** 374 * Quotient remainder. 375 * @param S Quotient. 376 * @return this - (this/S)*S. 377 */ 378 public Quotient<C> remainder(Quotient<C> S) { 379 if (num.isZERO()) { 380 throw new ArithmeticException("element not invertible " + this); 381 } 382 return ring.getZERO(); 383 } 384 385 386 /** 387 * Quotient and remainder by division of this by S. 388 * @param S a Quotient 389 * @return [this/S, this - (this/S)*S]. 390 */ 391 @SuppressWarnings("unchecked") 392 public Quotient<C>[] quotientRemainder(Quotient<C> S) { 393 return new Quotient[] { divide(S), remainder(S) }; 394 } 395 396 397 /** 398 * Quotient multiplication. 399 * @param S Quotient. 400 * @return this*S. 401 */ 402 public Quotient<C> multiply(Quotient<C> S) { 403 if (S == null || S.isZERO()) { 404 return S; 405 } 406 if (num.isZERO()) { 407 return this; 408 } 409 if (S.isONE()) { 410 return this; 411 } 412 if (this.isONE()) { 413 return S; 414 } 415 C n = num.multiply(S.num); 416 C d = den.multiply(S.den); 417 return new Quotient<C>(ring, n, d, false); 418 } 419 420 421 /** 422 * Quotient monic. 423 * @return this with monic value part. 424 */ 425 public Quotient<C> monic() { 426 logger.info("monic not implemented"); 427 return this; 428 } 429 430 431 /** 432 * Greatest common divisor. <b>Note:</b> If not defined, throws 433 * UnsupportedOperationException. 434 * @param b other element. 435 * @return gcd(this,b). 436 */ 437 public Quotient<C> gcd(Quotient<C> b) { 438 if (b == null || b.isZERO()) { 439 return this; 440 } 441 if (this.isZERO()) { 442 return b; 443 } 444 if (num instanceof GcdRingElem && den instanceof GcdRingElem && b.num instanceof GcdRingElem 445 && b.den instanceof GcdRingElem) { 446 return ring.getONE(); 447 } 448 throw new UnsupportedOperationException("gcd not implemented " + num.getClass().getName()); 449 } 450 451 452 /** 453 * Extended greatest common divisor. <b>Note:</b> If not defined, throws 454 * UnsupportedOperationException. 455 * @param b other element. 456 * @return [ gcd(this,b), c1, c2 ] with c1*this + c2*b = gcd(this,b). 457 */ 458 public Quotient<C>[] egcd(Quotient<C> b) { 459 @SuppressWarnings("unchecked") 460 Quotient<C>[] ret = (Quotient<C>[]) new Quotient[3]; 461 ret[0] = null; 462 ret[1] = null; 463 ret[2] = null; 464 if (b == null || b.isZERO()) { 465 ret[0] = this; 466 return ret; 467 } 468 if (this.isZERO()) { 469 ret[0] = b; 470 return ret; 471 } 472 if (num instanceof GcdRingElem && den instanceof GcdRingElem && b.num instanceof GcdRingElem 473 && b.den instanceof GcdRingElem) { 474 Quotient<C> two = ring.fromInteger(2); 475 ret[0] = ring.getONE(); 476 ret[1] = (this.multiply(two)).inverse(); 477 ret[2] = (b.multiply(two)).inverse(); 478 return ret; 479 } 480 throw new UnsupportedOperationException("egcd not implemented " + num.getClass().getName()); 481 } 482 483}