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