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