001/*
002 * $Id$
003 */
004
005package edu.jas.root;
006
007
008import java.math.BigInteger;
009
010import edu.jas.arith.BigDecimal;
011import edu.jas.arith.BigRational;
012import edu.jas.arith.Rational;
013import edu.jas.kern.PrettyPrint;
014import edu.jas.poly.AlgebraicNumber;
015import edu.jas.poly.GenPolynomial;
016import edu.jas.structure.GcdRingElem;
017import edu.jas.structure.NotInvertibleException;
018
019
020/**
021 * Real algebraic number class based on AlgebraicNumber. Objects of this class
022 * are immutable.
023 * @author Heinz Kredel
024 */
025
026public class RealAlgebraicNumber<C extends GcdRingElem<C> & Rational>
027                /*extends AlgebraicNumber<C>*/
028                implements GcdRingElem<RealAlgebraicNumber<C>>, Rational {
029
030
031    /**
032     * Representing AlgebraicNumber.
033     */
034    public final AlgebraicNumber<C> number;
035
036
037    /**
038     * Ring part of the data structure.
039     */
040    public final RealAlgebraicRing<C> ring;
041
042
043    /**
044     * The constructor creates a RealAlgebraicNumber object from
045     * RealAlgebraicRing modul and a GenPolynomial value.
046     * @param r ring RealAlgebraicRing<C>.
047     * @param a value GenPolynomial<C>.
048     */
049    public RealAlgebraicNumber(RealAlgebraicRing<C> r, GenPolynomial<C> a) {
050        number = new AlgebraicNumber<C>(r.algebraic, a);
051        ring = r;
052    }
053
054
055    /**
056     * The constructor creates a RealAlgebraicNumber object from
057     * RealAlgebraicRing modul and a AlgebraicNumber value.
058     * @param r ring RealAlgebraicRing<C>.
059     * @param a value AlgebraicNumber<C>.
060     */
061    public RealAlgebraicNumber(RealAlgebraicRing<C> r, AlgebraicNumber<C> a) {
062        number = a;
063        ring = r;
064    }
065
066
067    /**
068     * The constructor creates a RealAlgebraicNumber object from a GenPolynomial
069     * object module.
070     * @param r ring RealAlgebraicRing<C>.
071     */
072    public RealAlgebraicNumber(RealAlgebraicRing<C> r) {
073        this(r, r.algebraic.getZERO());
074    }
075
076
077    /**
078     * Get the corresponding element factory.
079     * @return factory for this Element.
080     * @see edu.jas.structure.Element#factory()
081     */
082    public RealAlgebraicRing<C> factory() {
083        return ring;
084    }
085
086
087    /**
088     * Copy this.
089     * @see edu.jas.structure.Element#copy()
090     */
091    @Override
092    public RealAlgebraicNumber<C> copy() {
093        return new RealAlgebraicNumber<C>(ring, number);
094    }
095
096
097    /**
098     * Return a BigRational approximation of this Element.
099     * @return a BigRational approximation of this.
100     * @see edu.jas.arith.Rational#getRational()
101     */
102    public BigRational getRational() {
103        return magnitude();
104    }
105
106
107    /**
108     * Is RealAlgebraicNumber zero.
109     * @return If this is 0 then true is returned, else false.
110     * @see edu.jas.structure.RingElem#isZERO()
111     */
112    public boolean isZERO() {
113        return number.isZERO();
114        //return magnitude().isZERO();
115    }
116
117
118    /**
119     * Is RealAlgebraicNumber one.
120     * @return If this is 1 then true is returned, else false.
121     * @see edu.jas.structure.RingElem#isONE()
122     */
123    public boolean isONE() {
124        return number.isONE();
125    }
126
127
128    /**
129     * Is RealAlgebraicNumber unit.
130     * @return If this is a unit then true is returned, else false.
131     * @see edu.jas.structure.RingElem#isUnit()
132     */
133    public boolean isUnit() {
134        return number.isUnit();
135    }
136
137
138    /**
139     * Is RealAlgebraicNumber a root of unity.
140     * @return true if |this**i| == 1, for some 0 &lt; i &le; deg(modul), else
141     *         false.
142     */
143    public boolean isRootOfUnity() {
144        return number.isRootOfUnity();
145    }
146
147
148    /**
149     * Get the String representation as RingElem.
150     * @see java.lang.Object#toString()
151     */
152    @Override
153    public String toString() {
154        if (PrettyPrint.isTrue()) {
155            return "{ " + number.toString() + " }";
156        }
157        return "Real" + number.toString();
158    }
159
160
161    /**
162     * Get a scripting compatible string representation.
163     * @return script compatible representation for this Element.
164     * @see edu.jas.structure.Element#toScript()
165     */
166    @Override
167    public String toScript() {
168        // Python case
169        return number.toScript();
170    }
171
172
173    /**
174     * Get a scripting compatible string representation of the factory.
175     * @return script compatible representation for this ElemFactory.
176     * @see edu.jas.structure.Element#toScriptFactory()
177     */
178    @Override
179    public String toScriptFactory() {
180        // Python case
181        return factory().toScript();
182    }
183
184
185    /**
186     * RealAlgebraicNumber comparison.
187     * @param b RealAlgebraicNumber.
188     * @return real sign(this-b).
189     */
190    @Override
191    public int compareTo(RealAlgebraicNumber<C> b) {
192        int s = 0;
193        if (number.ring != b.number.ring) { // avoid compareTo if possible
194            s = number.ring.modul.compareTo(b.number.ring.modul);
195            System.out.println("s_mod = " + s);
196        }
197        if (s != 0) {
198            return s;
199        }
200        s = this.subtract(b).signum(); // avoid subtract if possible
201        //System.out.println("s_real = " + s);
202        return s;
203    }
204
205
206    /**
207     * RealAlgebraicNumber comparison.
208     * @param b AlgebraicNumber.
209     * @return polynomial sign(this-b).
210     */
211    public int compareTo(AlgebraicNumber<C> b) {
212        int s = number.compareTo(b);
213        System.out.println("s_algeb = " + s);
214        return s;
215    }
216
217
218    /**
219     * Comparison with any other object.
220     * @see java.lang.Object#equals(java.lang.Object)
221     */
222    @Override
223    @SuppressWarnings("unchecked")
224    public boolean equals(Object b) {
225        if (b == null) {
226            return false;
227        }
228        if (!(b instanceof RealAlgebraicNumber)) {
229            return false;
230        }
231        RealAlgebraicNumber<C> a = (RealAlgebraicNumber<C>) b;
232        if (!ring.equals(a.ring)) {
233            return false;
234        }
235        return number.equals(a.number);
236    }
237
238
239    /**
240     * Hash code for this RealAlgebraicNumber.
241     * @see java.lang.Object#hashCode()
242     */
243    @Override
244    public int hashCode() {
245        return 37 * number.val.hashCode() + ring.hashCode();
246    }
247
248
249    /**
250     * RealAlgebraicNumber absolute value.
251     * @return the absolute value of this.
252     * @see edu.jas.structure.RingElem#abs()
253     */
254    public RealAlgebraicNumber<C> abs() {
255        if (this.signum() < 0) {
256            return new RealAlgebraicNumber<C>(ring, number.negate());
257        }
258        return this;
259    }
260
261
262    /**
263     * RealAlgebraicNumber summation.
264     * @param S RealAlgebraicNumber.
265     * @return this+S.
266     */
267    public RealAlgebraicNumber<C> sum(RealAlgebraicNumber<C> S) {
268        return new RealAlgebraicNumber<C>(ring, number.sum(S.number));
269    }
270
271
272    /**
273     * RealAlgebraicNumber summation.
274     * @param c coefficient.
275     * @return this+c.
276     */
277    public RealAlgebraicNumber<C> sum(GenPolynomial<C> c) {
278        return new RealAlgebraicNumber<C>(ring, number.sum(c));
279    }
280
281
282    /**
283     * RealAlgebraicNumber summation.
284     * @param c polynomial.
285     * @return this+c.
286     */
287    public RealAlgebraicNumber<C> sum(C c) {
288        return new RealAlgebraicNumber<C>(ring, number.sum(c));
289    }
290
291
292    /**
293     * RealAlgebraicNumber negate.
294     * @return -this.
295     * @see edu.jas.structure.RingElem#negate()
296     */
297    public RealAlgebraicNumber<C> negate() {
298        return new RealAlgebraicNumber<C>(ring, number.negate());
299    }
300
301
302    /**
303     * RealAlgebraicNumber signum. <b>Note: </b> Modifies ring.root eventually.
304     * @see edu.jas.structure.RingElem#signum()
305     * @return real signum(this).
306     */
307    public int signum() {
308        Interval<C> v = ring.engine.invariantSignInterval(ring.root, ring.algebraic.modul, number.val);
309        ring.setRoot(v);
310        return ring.engine.realIntervalSign(v, ring.algebraic.modul, number.val);
311    }
312
313
314    /**
315     * RealAlgebraicNumber half interval.
316     */
317    public void halfInterval() {
318        Interval<C> v = ring.engine.halfInterval(ring.root, ring.algebraic.modul);
319        //System.out.println("old v = " + ring.root + ", new v = " + v);
320        ring.setRoot(v);
321    }
322
323
324    /**
325     * RealAlgebraicNumber floor.
326     * @return floor of this.
327     */
328    public BigInteger floor() {
329        BigRational f = magnitude();
330        BigInteger fi = f.floor(); // todo: ensure int not in interval
331        return fi;
332    }
333
334
335    /**
336     * RealAlgebraicNumber magnitude.
337     * @return |this|.
338     */
339    public BigRational magnitude() {
340        Interval<C> v = ring.engine.invariantMagnitudeInterval(ring.root, ring.algebraic.modul, number.val,
341                        ring.getEps());
342        //System.out.println("old v = " + ring.root + ", new v = " + v);
343        ring.setRoot(v);
344        C ev = ring.engine.realIntervalMagnitude(v, ring.algebraic.modul, number.val); //, ring.eps);
345        //Interval<C> ev = ring.engine.realIntervalMagnitudeInterval(v, ring.algebraic.modul, number.val);
346        BigRational er = ev.getRational(); //middle().
347        return er;
348    }
349
350
351    /**
352     * RealAlgebraicNumber magnitude.
353     * @return |this| as big decimal.
354     */
355    public BigDecimal decimalMagnitude() {
356        return new BigDecimal(magnitude());
357    }
358
359
360    /**
361     * RealAlgebraicNumber subtraction.
362     * @param S RealAlgebraicNumber.
363     * @return this-S.
364     */
365    public RealAlgebraicNumber<C> subtract(RealAlgebraicNumber<C> S) {
366        return new RealAlgebraicNumber<C>(ring, number.subtract(S.number));
367    }
368
369
370    /**
371     * RealAlgebraicNumber division.
372     * @param S RealAlgebraicNumber.
373     * @return this/S.
374     */
375    public RealAlgebraicNumber<C> divide(RealAlgebraicNumber<C> S) {
376        return multiply(S.inverse());
377    }
378
379
380    /**
381     * RealAlgebraicNumber inverse.
382     * @see edu.jas.structure.RingElem#inverse()
383     * @throws NotInvertibleException if the element is not invertible.
384     * @return S with S = 1/this if defined.
385     */
386    public RealAlgebraicNumber<C> inverse() {
387        return new RealAlgebraicNumber<C>(ring, number.inverse());
388    }
389
390
391    /**
392     * RealAlgebraicNumber remainder.
393     * @param S RealAlgebraicNumber.
394     * @return this - (this/S)*S.
395     */
396    public RealAlgebraicNumber<C> remainder(RealAlgebraicNumber<C> S) {
397        return new RealAlgebraicNumber<C>(ring, number.remainder(S.number));
398    }
399
400
401    /**
402     * Quotient and remainder by division of this by S.
403     * @param S a RealAlgebraicNumber
404     * @return [this/S, this - (this/S)*S].
405     */
406    @SuppressWarnings("unchecked")
407    public RealAlgebraicNumber<C>[] quotientRemainder(RealAlgebraicNumber<C> S) {
408        return new RealAlgebraicNumber[] { divide(S), remainder(S) };
409    }
410
411
412    /**
413     * RealAlgebraicNumber multiplication.
414     * @param S RealAlgebraicNumber.
415     * @return this*S.
416     */
417    public RealAlgebraicNumber<C> multiply(RealAlgebraicNumber<C> S) {
418        return new RealAlgebraicNumber<C>(ring, number.multiply(S.number));
419    }
420
421
422    /**
423     * RealAlgebraicNumber multiplication.
424     * @param c coefficient.
425     * @return this*c.
426     */
427    public RealAlgebraicNumber<C> multiply(C c) {
428        return new RealAlgebraicNumber<C>(ring, number.multiply(c));
429    }
430
431
432    /**
433     * RealAlgebraicNumber multiplication.
434     * @param c polynomial.
435     * @return this*c.
436     */
437    public RealAlgebraicNumber<C> multiply(GenPolynomial<C> c) {
438        return new RealAlgebraicNumber<C>(ring, number.multiply(c));
439    }
440
441
442    /**
443     * RealAlgebraicNumber monic.
444     * @return this with monic value part.
445     */
446    public RealAlgebraicNumber<C> monic() {
447        return new RealAlgebraicNumber<C>(ring, number.monic());
448    }
449
450
451    /**
452     * RealAlgebraicNumber greatest common divisor.
453     * @param S RealAlgebraicNumber.
454     * @return gcd(this,S).
455     */
456    public RealAlgebraicNumber<C> gcd(RealAlgebraicNumber<C> S) {
457        return new RealAlgebraicNumber<C>(ring, number.gcd(S.number));
458    }
459
460
461    /**
462     * RealAlgebraicNumber extended greatest common divisor.
463     * @param S RealAlgebraicNumber.
464     * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S).
465     */
466    @SuppressWarnings("unchecked")
467    public RealAlgebraicNumber<C>[] egcd(RealAlgebraicNumber<C> S) {
468        AlgebraicNumber<C>[] aret = number.egcd(S.number);
469        RealAlgebraicNumber<C>[] ret = new RealAlgebraicNumber[3];
470        ret[0] = new RealAlgebraicNumber<C>(ring, aret[0]);
471        ret[1] = new RealAlgebraicNumber<C>(ring, aret[1]);
472        ret[2] = new RealAlgebraicNumber<C>(ring, aret[2]);
473        return ret;
474    }
475
476}