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