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