001/*
002 * $Id: AlgebraicNumber.java 4148 2012-08-31 19:49:27Z kredel $
003 */
004
005package edu.jas.poly;
006
007
008import edu.jas.kern.PrettyPrint;
009import edu.jas.structure.RingElem;
010import edu.jas.structure.GcdRingElem;
011import edu.jas.structure.NotInvertibleException;
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     * Clone this.
091     * @see java.lang.Object#clone()
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     * Get the String representation as RingElem.
152     * @see java.lang.Object#toString()
153     */
154    @Override
155    public String toString() {
156        if (PrettyPrint.isTrue()) {
157            return val.toString(ring.ring.vars);
158        }
159        return "AlgebraicNumber[ " + val.toString() + " ]";
160    }
161
162
163    /**
164     * Get a scripting compatible string representation.
165     * @return script compatible representation for this Element.
166     * @see edu.jas.structure.Element#toScript()
167     */
168    //JAVA6only: @Override
169    public String toScript() {
170        // Python case
171        return val.toScript();
172    }
173
174
175    /**
176     * Get a scripting compatible string representation of the factory.
177     * @return script compatible representation for this ElemFactory.
178     * @see edu.jas.structure.Element#toScriptFactory()
179     */
180    //JAVA6only: @Override
181    public String toScriptFactory() {
182        // Python case
183        return factory().toScript();
184    }
185
186
187    /**
188     * AlgebraicNumber comparison.
189     * @param b AlgebraicNumber.
190     * @return sign(this-b).
191     */
192    //JAVA6only: @Override
193    public int compareTo(AlgebraicNumber<C> b) {
194        int s = 0;
195        if (ring.modul != b.ring.modul) { // avoid compareTo if possible
196            s = ring.modul.compareTo(b.ring.modul);
197        }
198        if (s != 0) {
199            return s;
200        }
201        return val.compareTo(b.val);
202    }
203
204
205    /**
206     * Comparison with any other object.
207     * @see java.lang.Object#equals(java.lang.Object)
208     */
209    @Override
210    @SuppressWarnings("unchecked")
211    // not jet working
212    public boolean equals(Object b) {
213        if (!(b instanceof AlgebraicNumber)) {
214            return false;
215        }
216        AlgebraicNumber<C> a = null;
217        try {
218            a = (AlgebraicNumber<C>) b;
219        } catch (ClassCastException e) {
220        }
221        if (a == null) {
222            return false;
223        }
224        if (!ring.equals(a.ring)) {
225            return false;
226        }
227        return (0 == compareTo(a));
228    }
229
230
231    /**
232     * Hash code for this AlgebraicNumber.
233     * @see java.lang.Object#hashCode()
234     */
235    @Override
236    public int hashCode() {
237        return 37 * val.hashCode() + ring.hashCode();
238    }
239
240
241    /**
242     * AlgebraicNumber absolute value.
243     * @return the absolute value of this.
244     * @see edu.jas.structure.RingElem#abs()
245     */
246    public AlgebraicNumber<C> abs() {
247        return new AlgebraicNumber<C>(ring, val.abs());
248    }
249
250
251    /**
252     * AlgebraicNumber summation.
253     * @param S AlgebraicNumber.
254     * @return this+S.
255     */
256    public AlgebraicNumber<C> sum(AlgebraicNumber<C> S) {
257        return new AlgebraicNumber<C>(ring, val.sum(S.val));
258    }
259
260
261    /**
262     * AlgebraicNumber summation.
263     * @param c coefficient.
264     * @return this+c.
265     */
266    public AlgebraicNumber<C> sum(GenPolynomial<C> c) {
267        return new AlgebraicNumber<C>(ring, val.sum(c));
268    }
269
270
271    /**
272     * AlgebraicNumber summation.
273     * @param c polynomial.
274     * @return this+c.
275     */
276    public AlgebraicNumber<C> sum(C c) {
277        return new AlgebraicNumber<C>(ring, val.sum(c));
278    }
279
280
281    /**
282     * AlgebraicNumber negate.
283     * @return -this.
284     * @see edu.jas.structure.RingElem#negate()
285     */
286    public AlgebraicNumber<C> negate() {
287        return new AlgebraicNumber<C>(ring, val.negate());
288    }
289
290
291    /**
292     * AlgebraicNumber signum.
293     * @see edu.jas.structure.RingElem#signum()
294     * @return signum(this).
295     */
296    public int signum() {
297        return val.signum();
298    }
299
300
301    /**
302     * AlgebraicNumber subtraction.
303     * @param S AlgebraicNumber.
304     * @return this-S.
305     */
306    public AlgebraicNumber<C> subtract(AlgebraicNumber<C> S) {
307        return new AlgebraicNumber<C>(ring, val.subtract(S.val));
308    }
309
310
311    /**
312     * AlgebraicNumber division.
313     * @param S AlgebraicNumber.
314     * @return this/S.
315     */
316    public AlgebraicNumber<C> divide(AlgebraicNumber<C> S) {
317        return multiply(S.inverse());
318    }
319
320
321    /**
322     * AlgebraicNumber inverse.
323     * @see edu.jas.structure.RingElem#inverse()
324     * @throws NotInvertibleException if the element is not invertible.
325     * @return S with S = 1/this if defined.
326     */
327    public AlgebraicNumber<C> inverse() {
328        try {
329            return new AlgebraicNumber<C>(ring, val.modInverse(ring.modul));
330        } catch (AlgebraicNotInvertibleException e) {
331            //System.out.println(e);
332            throw e;
333        } catch (NotInvertibleException e) {
334            throw new AlgebraicNotInvertibleException(e + ", val = " + val + ", modul = " + ring.modul + ", gcd = "
335                                                      + val.gcd(ring.modul),e);
336        }
337    }
338
339
340    /**
341     * AlgebraicNumber remainder.
342     * @param S AlgebraicNumber.
343     * @return this - (this/S)*S.
344     */
345    public AlgebraicNumber<C> remainder(AlgebraicNumber<C> S) {
346        if (S == null || S.isZERO()) {
347            throw new ArithmeticException("division by zero");
348        }
349        if (S.isONE()) {
350            return ring.getZERO();
351        }
352        if (S.isUnit()) {
353            return ring.getZERO();
354        }
355        GenPolynomial<C> x = val.remainder(S.val);
356        return new AlgebraicNumber<C>(ring, x);
357    }
358
359
360    /**
361     * AlgebraicNumber multiplication.
362     * @param S AlgebraicNumber.
363     * @return this*S.
364     */
365    public AlgebraicNumber<C> multiply(AlgebraicNumber<C> S) {
366        GenPolynomial<C> x = val.multiply(S.val);
367        return new AlgebraicNumber<C>(ring, x);
368    }
369
370
371    /**
372     * AlgebraicNumber multiplication.
373     * @param c coefficient.
374     * @return this*c.
375     */
376    public AlgebraicNumber<C> multiply(C c) {
377        GenPolynomial<C> x = val.multiply(c);
378        return new AlgebraicNumber<C>(ring, x);
379    }
380
381
382    /**
383     * AlgebraicNumber multiplication.
384     * @param c polynomial.
385     * @return this*c.
386     */
387    public AlgebraicNumber<C> multiply(GenPolynomial<C> c) {
388        GenPolynomial<C> x = val.multiply(c);
389        return new AlgebraicNumber<C>(ring, x);
390    }
391
392
393    /**
394     * AlgebraicNumber monic.
395     * @return this with monic value part.
396     */
397    public AlgebraicNumber<C> monic() {
398        return new AlgebraicNumber<C>(ring, val.monic());
399    }
400
401
402    /**
403     * AlgebraicNumber greatest common divisor.
404     * @param S AlgebraicNumber.
405     * @return gcd(this,S).
406     */
407    public AlgebraicNumber<C> gcd(AlgebraicNumber<C> S) {
408        if (S.isZERO()) {
409            return this;
410        }
411        if (isZERO()) {
412            return S;
413        }
414        if (isUnit() || S.isUnit()) {
415            return ring.getONE();
416        }
417        return new AlgebraicNumber<C>(ring, val.gcd(S.val));
418    }
419
420
421    /**
422     * AlgebraicNumber extended greatest common divisor.
423     * @param S AlgebraicNumber.
424     * @return [ gcd(this,S), a, b ] with a*this + b*S = gcd(this,S).
425     */
426    @SuppressWarnings("unchecked")
427    public AlgebraicNumber<C>[] egcd(AlgebraicNumber<C> S) {
428        AlgebraicNumber<C>[] ret = new AlgebraicNumber[3];
429        ret[0] = null;
430        ret[1] = null;
431        ret[2] = null;
432        if (S == null || S.isZERO()) {
433            ret[0] = this;
434            return ret;
435        }
436        if (isZERO()) {
437            ret[0] = S;
438            return ret;
439        }
440        if (this.isUnit() || S.isUnit()) {
441            ret[0] = ring.getONE();
442            if (this.isUnit() && S.isUnit()) {
443                AlgebraicNumber<C> half = ring.fromInteger(2).inverse();
444                ret[1] = this.inverse().multiply(half);
445                ret[2] = S.inverse().multiply(half);
446                return ret;
447            }
448            if (this.isUnit()) {
449                // oder inverse(S-1)?
450                ret[1] = this.inverse();
451                ret[2] = ring.getZERO();
452                return ret;
453            }
454            // if ( S.isUnit() ) {
455            // oder inverse(this-1)?
456            ret[1] = ring.getZERO();
457            ret[2] = S.inverse();
458            return ret;
459            //}
460        }
461        //System.out.println("this = " + this + ", S = " + S);
462        GenPolynomial<C>[] qr;
463        GenPolynomial<C> q = this.val;
464        GenPolynomial<C> r = S.val;
465        GenPolynomial<C> c1 = ring.ring.getONE();
466        GenPolynomial<C> d1 = ring.ring.getZERO();
467        GenPolynomial<C> c2 = ring.ring.getZERO();
468        GenPolynomial<C> d2 = ring.ring.getONE();
469        GenPolynomial<C> x1;
470        GenPolynomial<C> x2;
471        while (!r.isZERO()) {
472            qr = q.quotientRemainder(r);
473            q = qr[0];
474            x1 = c1.subtract(q.multiply(d1));
475            x2 = c2.subtract(q.multiply(d2));
476            c1 = d1;
477            c2 = d2;
478            d1 = x1;
479            d2 = x2;
480            q = r;
481            r = qr[1];
482        }
483        //System.out.println("q = " + q + "\n c1 = " + c1 + "\n c2 = " + c2);
484        ret[0] = new AlgebraicNumber<C>(ring, q);
485        ret[1] = new AlgebraicNumber<C>(ring, c1);
486        ret[2] = new AlgebraicNumber<C>(ring, c2);
487        return ret;
488    }
489
490}