001/*
002 * $Id: RealAlgebraicNumber.java 5929 2018-09-21 20:06:12Z 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        //return magnitude().isZERO();
113    }
114
115
116    /**
117     * Is RealAlgebraicNumber one.
118     * @return If this is 1 then true is returned, else false.
119     * @see edu.jas.structure.RingElem#isONE()
120     */
121    public boolean isONE() {
122        return number.isONE();
123    }
124
125
126    /**
127     * Is RealAlgebraicNumber unit.
128     * @return If this is a unit then true is returned, else false.
129     * @see edu.jas.structure.RingElem#isUnit()
130     */
131    public boolean isUnit() {
132        return number.isUnit();
133    }
134
135
136    /**
137     * Is RealAlgebraicNumber a root of unity.
138     * @return true if |this**i| == 1, for some 0 &lt; i &le; deg(modul), else
139     *         false.
140     */
141    public boolean isRootOfUnity() {
142        return number.isRootOfUnity();
143    }
144
145
146    /**
147     * Get the String representation as RingElem.
148     * @see java.lang.Object#toString()
149     */
150    @Override
151    public String toString() {
152        if (PrettyPrint.isTrue()) {
153            return "{ " + number.toString() + " }";
154        }
155        return "Real" + number.toString();
156    }
157
158
159    /**
160     * Get a scripting compatible string representation.
161     * @return script compatible representation for this Element.
162     * @see edu.jas.structure.Element#toScript()
163     */
164    @Override
165    public String toScript() {
166        // Python case
167        return number.toScript();
168    }
169
170
171    /**
172     * Get a scripting compatible string representation of the factory.
173     * @return script compatible representation for this ElemFactory.
174     * @see edu.jas.structure.Element#toScriptFactory()
175     */
176    @Override
177    public String toScriptFactory() {
178        // Python case
179        return factory().toScript();
180    }
181
182
183    /**
184     * RealAlgebraicNumber comparison.
185     * @param b RealAlgebraicNumber.
186     * @return real sign(this-b).
187     */
188    @Override
189    public int compareTo(RealAlgebraicNumber<C> b) {
190        int s = 0;
191        if (number.ring != b.number.ring) { // avoid compareTo if possible
192            s = number.ring.modul.compareTo(b.number.ring.modul);
193            System.out.println("s_mod = " + s);
194        }
195        if (s != 0) {
196            return s;
197        }
198        s = this.subtract(b).signum(); // avoid subtract if possible
199        //System.out.println("s_real = " + s);
200        return s;
201    }
202
203
204    /**
205     * RealAlgebraicNumber comparison.
206     * @param b AlgebraicNumber.
207     * @return polynomial sign(this-b).
208     */
209    public int compareTo(AlgebraicNumber<C> b) {
210        int s = number.compareTo(b);
211        System.out.println("s_algeb = " + s);
212        return s;
213    }
214
215
216    /**
217     * Comparison with any other object.
218     * @see java.lang.Object#equals(java.lang.Object)
219     */
220    @Override
221    @SuppressWarnings("unchecked")
222    public boolean equals(Object b) {
223        if (b == null) {
224            return false;
225        }
226        if (!(b instanceof RealAlgebraicNumber)) {
227            return false;
228        }
229        RealAlgebraicNumber<C> a = (RealAlgebraicNumber<C>) b;
230        if (!ring.equals(a.ring)) {
231            return false;
232        }
233        return number.equals(a.number);
234    }
235
236
237    /**
238     * Hash code for this RealAlgebraicNumber.
239     * @see java.lang.Object#hashCode()
240     */
241    @Override
242    public int hashCode() {
243        return 37 * number.val.hashCode() + ring.hashCode();
244    }
245
246
247    /**
248     * RealAlgebraicNumber absolute value.
249     * @return the absolute value of this.
250     * @see edu.jas.structure.RingElem#abs()
251     */
252    public RealAlgebraicNumber<C> abs() {
253        if (this.signum() < 0) {
254            return new RealAlgebraicNumber<C>(ring, number.negate());
255        }
256        return this;
257    }
258
259
260    /**
261     * RealAlgebraicNumber summation.
262     * @param S RealAlgebraicNumber.
263     * @return this+S.
264     */
265    public RealAlgebraicNumber<C> sum(RealAlgebraicNumber<C> S) {
266        return new RealAlgebraicNumber<C>(ring, number.sum(S.number));
267    }
268
269
270    /**
271     * RealAlgebraicNumber summation.
272     * @param c coefficient.
273     * @return this+c.
274     */
275    public RealAlgebraicNumber<C> sum(GenPolynomial<C> c) {
276        return new RealAlgebraicNumber<C>(ring, number.sum(c));
277    }
278
279
280    /**
281     * RealAlgebraicNumber summation.
282     * @param c polynomial.
283     * @return this+c.
284     */
285    public RealAlgebraicNumber<C> sum(C c) {
286        return new RealAlgebraicNumber<C>(ring, number.sum(c));
287    }
288
289
290    /**
291     * RealAlgebraicNumber negate.
292     * @return -this.
293     * @see edu.jas.structure.RingElem#negate()
294     */
295    public RealAlgebraicNumber<C> negate() {
296        return new RealAlgebraicNumber<C>(ring, number.negate());
297    }
298
299
300    /**
301     * RealAlgebraicNumber signum. <b>Note: </b> Modifies ring.root eventually.
302     * @see edu.jas.structure.RingElem#signum()
303     * @return real signum(this).
304     */
305    public int signum() {
306        Interval<C> v = ring.engine.invariantSignInterval(ring.root, ring.algebraic.modul, number.val);
307        ring.setRoot(v);
308        return ring.engine.realIntervalSign(v, ring.algebraic.modul, number.val);
309    }
310
311
312    /**
313     * RealAlgebraicNumber half interval.
314     */
315    public void halfInterval() {
316        Interval<C> v = ring.engine.halfInterval(ring.root, ring.algebraic.modul);
317        //System.out.println("old v = " + ring.root + ", new v = " + v);
318        ring.setRoot(v);
319    }
320
321
322    /**
323     * RealAlgebraicNumber magnitude.
324     * @return |this|.
325     */
326    public BigRational magnitude() {
327        Interval<C> v = ring.engine.invariantMagnitudeInterval(ring.root, ring.algebraic.modul, number.val,
328                        ring.getEps());
329        //System.out.println("old v = " + ring.root + ", new v = " + v);
330        ring.setRoot(v);
331        C ev = ring.engine.realIntervalMagnitude(v, ring.algebraic.modul, number.val); //, ring.eps);
332        //if ((Object) ev instanceof Rational) { // always true by type parameter
333        BigRational er = ev.getRational();
334        return er;
335        //}
336        //throw new RuntimeException("Rational expected, but was " + ev.getClass());
337    }
338
339
340    /**
341     * RealAlgebraicNumber magnitude.
342     * @return |this| as big decimal.
343     */
344    public BigDecimal decimalMagnitude() {
345        return new BigDecimal(magnitude());
346    }
347
348
349    /**
350     * RealAlgebraicNumber subtraction.
351     * @param S RealAlgebraicNumber.
352     * @return this-S.
353     */
354    public RealAlgebraicNumber<C> subtract(RealAlgebraicNumber<C> S) {
355        return new RealAlgebraicNumber<C>(ring, number.subtract(S.number));
356    }
357
358
359    /**
360     * RealAlgebraicNumber division.
361     * @param S RealAlgebraicNumber.
362     * @return this/S.
363     */
364    public RealAlgebraicNumber<C> divide(RealAlgebraicNumber<C> S) {
365        return multiply(S.inverse());
366    }
367
368
369    /**
370     * RealAlgebraicNumber inverse.
371     * @see edu.jas.structure.RingElem#inverse()
372     * @throws NotInvertibleException if the element is not invertible.
373     * @return S with S = 1/this if defined.
374     */
375    public RealAlgebraicNumber<C> inverse() {
376        return new RealAlgebraicNumber<C>(ring, number.inverse());
377    }
378
379
380    /**
381     * RealAlgebraicNumber remainder.
382     * @param S RealAlgebraicNumber.
383     * @return this - (this/S)*S.
384     */
385    public RealAlgebraicNumber<C> remainder(RealAlgebraicNumber<C> S) {
386        return new RealAlgebraicNumber<C>(ring, number.remainder(S.number));
387    }
388
389
390    /**
391     * Quotient and remainder by division of this by S.
392     * @param S a RealAlgebraicNumber
393     * @return [this/S, this - (this/S)*S].
394     */
395    @SuppressWarnings("unchecked")
396    public RealAlgebraicNumber<C>[] quotientRemainder(RealAlgebraicNumber<C> S) {
397        return new RealAlgebraicNumber[] { divide(S), remainder(S) };
398    }
399
400
401    /**
402     * RealAlgebraicNumber multiplication.
403     * @param S RealAlgebraicNumber.
404     * @return this*S.
405     */
406    public RealAlgebraicNumber<C> multiply(RealAlgebraicNumber<C> S) {
407        return new RealAlgebraicNumber<C>(ring, number.multiply(S.number));
408    }
409
410
411    /**
412     * RealAlgebraicNumber multiplication.
413     * @param c coefficient.
414     * @return this*c.
415     */
416    public RealAlgebraicNumber<C> multiply(C c) {
417        return new RealAlgebraicNumber<C>(ring, number.multiply(c));
418    }
419
420
421    /**
422     * RealAlgebraicNumber multiplication.
423     * @param c polynomial.
424     * @return this*c.
425     */
426    public RealAlgebraicNumber<C> multiply(GenPolynomial<C> c) {
427        return new RealAlgebraicNumber<C>(ring, number.multiply(c));
428    }
429
430
431    /**
432     * RealAlgebraicNumber monic.
433     * @return this with monic value part.
434     */
435    public RealAlgebraicNumber<C> monic() {
436        return new RealAlgebraicNumber<C>(ring, number.monic());
437    }
438
439
440    /**
441     * RealAlgebraicNumber greatest common divisor.
442     * @param S RealAlgebraicNumber.
443     * @return gcd(this,S).
444     */
445    public RealAlgebraicNumber<C> gcd(RealAlgebraicNumber<C> S) {
446        return new RealAlgebraicNumber<C>(ring, number.gcd(S.number));
447    }
448
449
450    /**
451     * RealAlgebraicNumber extended greatest common divisor.
452     * @param S RealAlgebraicNumber.
453     * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S).
454     */
455    @SuppressWarnings("unchecked")
456    public RealAlgebraicNumber<C>[] egcd(RealAlgebraicNumber<C> S) {
457        AlgebraicNumber<C>[] aret = number.egcd(S.number);
458        RealAlgebraicNumber<C>[] ret = new RealAlgebraicNumber[3];
459        ret[0] = new RealAlgebraicNumber<C>(ring, aret[0]);
460        ret[1] = new RealAlgebraicNumber<C>(ring, aret[1]);
461        ret[2] = new RealAlgebraicNumber<C>(ring, aret[2]);
462        return ret;
463    }
464
465}