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