001/*
002 * $Id: AlgebraicNumberRing.java 4057 2012-07-26 20:35:44Z kredel $
003 */
004
005package edu.jas.poly;
006
007
008import java.io.Reader;
009import java.util.ArrayList;
010import java.util.Iterator;
011import java.util.List;
012import java.util.Random;
013
014import org.apache.log4j.Logger;
015
016import edu.jas.kern.Scripting;
017import edu.jas.structure.RingElem;
018import edu.jas.structure.RingFactory;
019import edu.jas.util.CartesianProduct;
020import edu.jas.util.CartesianProductInfinite;
021
022
023/**
024 * Algebraic number factory class based on GenPolynomial with RingElem
025 * interface. Objects of this class are immutable.
026 * @author Heinz Kredel
027 */
028
029public class AlgebraicNumberRing<C extends RingElem<C>> implements RingFactory<AlgebraicNumber<C>>,
030                Iterable<AlgebraicNumber<C>> {
031
032
033    /**
034     * Ring part of the factory data structure.
035     */
036    public final GenPolynomialRing<C> ring;
037
038
039    /**
040     * Module part of the factory data structure.
041     */
042    public final GenPolynomial<C> modul;
043
044
045    /**
046     * Indicator if this ring is a field
047     */
048    protected int isField = -1; // initially unknown
049
050
051    private static final Logger logger = Logger.getLogger(AlgebraicNumberRing.class);
052
053
054    //  private final boolean debug = logger.isDebugEnabled();
055
056
057    /**
058     * The constructor creates a AlgebraicNumber factory object from a
059     * GenPolynomial objects module.
060     * @param m module GenPolynomial<C>.
061     */
062    public AlgebraicNumberRing(GenPolynomial<C> m) {
063        ring = m.ring;
064        modul = m; // assert m != 0
065        if (ring.nvar > 1) {
066            throw new IllegalArgumentException("only univariate polynomials allowed");
067        }
068    }
069
070
071    /**
072     * The constructor creates a AlgebraicNumber factory object from a
073     * GenPolynomial objects module.
074     * @param m module GenPolynomial<C>.
075     * @param isField indicator if m is prime.
076     */
077    public AlgebraicNumberRing(GenPolynomial<C> m, boolean isField) {
078        ring = m.ring;
079        modul = m; // assert m != 0
080        this.isField = (isField ? 1 : 0);
081        if (ring.nvar > 1) {
082            throw new IllegalArgumentException("only univariate polynomials allowed");
083        }
084    }
085
086
087    /**
088     * Get the module part.
089     * @return modul.
090     */
091    public GenPolynomial<C> getModul() {
092        return modul;
093    }
094
095
096    /**
097     * Copy AlgebraicNumber element c.
098     * @param c algebraic number to copy.
099     * @return a copy of c.
100     */
101    public AlgebraicNumber<C> copy(AlgebraicNumber<C> c) {
102        return new AlgebraicNumber<C>(this, c.val);
103    }
104
105
106    /**
107     * Get the zero element.
108     * @return 0 as AlgebraicNumber.
109     */
110    public AlgebraicNumber<C> getZERO() {
111        return new AlgebraicNumber<C>(this, ring.getZERO());
112    }
113
114
115    /**
116     * Get the one element.
117     * @return 1 as AlgebraicNumber.
118     */
119    public AlgebraicNumber<C> getONE() {
120        return new AlgebraicNumber<C>(this, ring.getONE());
121    }
122
123
124    /**
125     * Get the generating element.
126     * @return alpha as AlgebraicNumber.
127     */
128    public AlgebraicNumber<C> getGenerator() {
129        return new AlgebraicNumber<C>(this, ring.univariate(0));
130    }
131
132
133    /**
134     * Get a list of the generating elements.
135     * @return list of generators for the algebraic structure.
136     * @see edu.jas.structure.ElemFactory#generators()
137     */
138    public List<AlgebraicNumber<C>> generators() {
139        List<GenPolynomial<C>> gc = ring.generators();
140        List<AlgebraicNumber<C>> gens = new ArrayList<AlgebraicNumber<C>>(gc.size());
141        for (GenPolynomial<C> g : gc) {
142            gens.add(new AlgebraicNumber<C>(this, g));
143        }
144        return gens;
145    }
146
147
148    /**
149     * Is this structure finite or infinite.
150     * @return true if this structure is finite, else false.
151     * @see edu.jas.structure.ElemFactory#isFinite()
152     */
153    public boolean isFinite() {
154        return ring.coFac.isFinite();
155    }
156
157
158    /**
159     * Query if this ring is commutative.
160     * @return true if this ring is commutative, else false.
161     */
162    public boolean isCommutative() {
163        return ring.isCommutative();
164    }
165
166
167    /**
168     * Query if this ring is associative.
169     * @return true if this ring is associative, else false.
170     */
171    public boolean isAssociative() {
172        return ring.isAssociative();
173    }
174
175
176    /**
177     * Query if this ring is a field.
178     * @return true if modul is prime, else false.
179     */
180    public boolean isField() {
181        if (isField > 0) {
182            return true;
183        }
184        if (isField == 0) {
185            return false;
186        }
187        if (!ring.coFac.isField()) {
188            isField = 0;
189            return false;
190        }
191        return false;
192    }
193
194
195    /**
196     * Set field property of this ring.
197     * @param field true, if this ring is determined to be a field, false, if it
198     *            is determined that it is not a field.
199     */
200    public void setField(boolean field) {
201        if (isField > 0 && field) {
202            return;
203        }
204        if (isField == 0 && !field) {
205            return;
206        }
207        if (field) {
208            isField = 1;
209        } else {
210            isField = 0;
211        }
212        return;
213    }
214
215
216    /**
217     * Get the internal field indicator.
218     * @return internal field indicator.
219     */
220    public int getField() {
221        return isField;
222    }
223
224
225    /**
226     * Characteristic of this ring.
227     * @return characteristic of this ring.
228     */
229    public java.math.BigInteger characteristic() {
230        return ring.characteristic();
231    }
232
233
234    /**
235     * Get a AlgebraicNumber element from a BigInteger value.
236     * @param a BigInteger.
237     * @return a AlgebraicNumber.
238     */
239    public AlgebraicNumber<C> fillFromInteger(java.math.BigInteger a) {
240        if (characteristic().signum() == 0) {
241            return new AlgebraicNumber<C>(this, ring.fromInteger(a));
242        }
243        java.math.BigInteger p = characteristic();
244        java.math.BigInteger b = a;
245        GenPolynomial<C> v = ring.getZERO();
246        GenPolynomial<C> x = ring.univariate(0, 1L);
247        GenPolynomial<C> t = ring.getONE();
248        do {
249            java.math.BigInteger[] qr = b.divideAndRemainder(p);
250            java.math.BigInteger q = qr[0];
251            java.math.BigInteger r = qr[1];
252            //System.out.println("q = " + q + ", r = " +r);
253            GenPolynomial<C> rp = ring.fromInteger(r);
254            v = v.sum(t.multiply(rp));
255            t = t.multiply(x);
256            b = q;
257        } while (!b.equals(java.math.BigInteger.ZERO));
258        AlgebraicNumber<C> an = new AlgebraicNumber<C>(this, v);
259        logger.info("fill(" + a + ") = " + v + ", mod: " + an);
260        //RuntimeException e = new RuntimeException("hihihi");
261        //e.printStackTrace();
262        return an;
263    }
264
265
266    /**
267     * Get a AlgebraicNumber element from a long value.
268     * @param a long.
269     * @return a AlgebraicNumber.
270     */
271    public AlgebraicNumber<C> fillFromInteger(long a) {
272        return fillFromInteger(new java.math.BigInteger("" + a));
273    }
274
275
276    /**
277     * Get a AlgebraicNumber element from a BigInteger value.
278     * @param a BigInteger.
279     * @return a AlgebraicNumber.
280     */
281    public AlgebraicNumber<C> fromInteger(java.math.BigInteger a) {
282        return new AlgebraicNumber<C>(this, ring.fromInteger(a));
283    }
284
285
286    /**
287     * Get a AlgebraicNumber element from a long value.
288     * @param a long.
289     * @return a AlgebraicNumber.
290     */
291    public AlgebraicNumber<C> fromInteger(long a) {
292        return new AlgebraicNumber<C>(this, ring.fromInteger(a));
293        //         if ( characteristic().signum() == 0 ) {
294        //         }
295        //         return fromInteger( new java.math.BigInteger(""+a) );
296    }
297
298
299    /**
300     * Get the String representation as RingFactory.
301     * @see java.lang.Object#toString()
302     */
303    @Override
304    public String toString() {
305        return "AlgebraicNumberRing[ " + modul.toString() + " | isField=" + isField + " :: "
306                        + ring.toString() + " ]";
307    }
308
309
310    /**
311     * Get a scripting compatible string representation.
312     * @return script compatible representation for this ElemFactory.
313     * @see edu.jas.structure.ElemFactory#toScript()
314     */
315    //JAVA6only: @Override
316    public String toScript() {
317        StringBuffer s = new StringBuffer();
318        s.append("AN(");
319        s.append(modul.toScript());
320        switch (Scripting.getLang()) {
321        case Ruby:
322            s.append((isField() ? ",true" : ",false"));
323            break;
324        case Python:
325        default:
326            s.append((isField() ? ",True" : ",False"));
327        }
328        s.append(",");
329        s.append(ring.toScript());
330        s.append(")");
331        return s.toString();
332    }
333
334
335    /**
336     * Comparison with any other object.
337     * @see java.lang.Object#equals(java.lang.Object)
338     */
339    @Override
340    @SuppressWarnings("unchecked")
341    // not jet working
342    public boolean equals(Object b) {
343        if (!(b instanceof AlgebraicNumberRing)) {
344            return false;
345        }
346        AlgebraicNumberRing<C> a = null;
347        try {
348            a = (AlgebraicNumberRing<C>) b;
349        } catch (ClassCastException e) {
350        }
351        if (a == null) {
352            return false;
353        }
354        return modul.equals(a.modul);
355    }
356
357
358    /**
359     * Hash code for this AlgebraicNumber.
360     * @see java.lang.Object#hashCode()
361     */
362    @Override
363    public int hashCode() {
364        return 37 * modul.hashCode() + ring.hashCode();
365    }
366
367
368    /**
369     * AlgebraicNumber random.
370     * @param n such that 0 &le; v &le; (2<sup>n</sup>-1).
371     * @return a random integer mod modul.
372     */
373    public AlgebraicNumber<C> random(int n) {
374        GenPolynomial<C> x = ring.random(n).monic();
375        return new AlgebraicNumber<C>(this, x);
376    }
377
378
379    /**
380     * AlgebraicNumber random.
381     * @param n such that 0 &le; v &le; (2<sup>n</sup>-1).
382     * @param rnd is a source for random bits.
383     * @return a random integer mod modul.
384     */
385    public AlgebraicNumber<C> random(int n, Random rnd) {
386        GenPolynomial<C> x = ring.random(n, rnd).monic();
387        return new AlgebraicNumber<C>(this, x);
388    }
389
390
391    /**
392     * Parse AlgebraicNumber from String.
393     * @param s String.
394     * @return AlgebraicNumber from s.
395     */
396    public AlgebraicNumber<C> parse(String s) {
397        GenPolynomial<C> x = ring.parse(s);
398        return new AlgebraicNumber<C>(this, x);
399    }
400
401
402    /**
403     * Parse AlgebraicNumber from Reader.
404     * @param r Reader.
405     * @return next AlgebraicNumber from r.
406     */
407    public AlgebraicNumber<C> parse(Reader r) {
408        GenPolynomial<C> x = ring.parse(r);
409        return new AlgebraicNumber<C>(this, x);
410    }
411
412
413    /**
414     * AlgebraicNumber chinese remainder algorithm. Assert deg(c.modul) >=
415     * deg(a.modul) and c.modul * a.modul = this.modul.
416     * @param c AlgebraicNumber.
417     * @param ci inverse of c.modul in ring of a.
418     * @param a other AlgebraicNumber.
419     * @return S, with S mod c.modul == c and S mod a.modul == a.
420     */
421    public AlgebraicNumber<C> chineseRemainder(AlgebraicNumber<C> c, AlgebraicNumber<C> ci,
422                    AlgebraicNumber<C> a) {
423        if (true) { // debug
424            if (c.ring.modul.compareTo(a.ring.modul) < 1) {
425                System.out.println("AlgebraicNumber error " + c + ", " + a);
426            }
427        }
428        AlgebraicNumber<C> b = new AlgebraicNumber<C>(a.ring, c.val);
429        // c mod a.modul
430        // c( tbcf(a.modul) ) if deg(a.modul)==1
431        AlgebraicNumber<C> d = a.subtract(b); // a-c mod a.modul
432        if (d.isZERO()) {
433            return new AlgebraicNumber<C>(this, c.val);
434        }
435        b = d.multiply(ci); // b = (a-c)*ci mod a.modul
436        // (c.modul*b)+c mod this.modul = c mod c.modul = 
437        // (c.modul*ci*(a-c)+c) mod a.modul = a mod a.modul
438        GenPolynomial<C> s = c.ring.modul.multiply(b.val);
439        s = s.sum(c.val);
440        return new AlgebraicNumber<C>(this, s);
441    }
442
443
444    /**
445     * AlgebraicNumber interpolation algorithm. Assert deg(c.modul) >=
446     * deg(A.modul) and c.modul * A.modul = this.modul. Special case with
447     * deg(A.modul) == 1. Similar algorithm as chinese remainder algortihm.
448     * @param c AlgebraicNumber.
449     * @param ci inverse of (c.modul)(a) in ring of A.
450     * @param am trailing base coefficient of modul of other AlgebraicNumber A.
451     * @param a value of other AlgebraicNumber A.
452     * @return S, with S(c) == c and S(A) == a.
453     */
454    public AlgebraicNumber<C> interpolate(AlgebraicNumber<C> c, C ci, C am, C a) {
455        C b = PolyUtil.<C> evaluateMain(ring.coFac /*a*/, c.val, am);
456        // c mod a.modul
457        // c( tbcf(a.modul) ) if deg(a.modul)==1
458        C d = a.subtract(b); // a-c mod a.modul
459        if (d.isZERO()) {
460            return new AlgebraicNumber<C>(this, c.val);
461        }
462        b = d.multiply(ci); // b = (a-c)*ci mod a.modul
463        // (c.modul*b)+c mod this.modul = c mod c.modul = 
464        // (c.modul*ci*(a-c)+c) mod a.modul = a mod a.modul
465        GenPolynomial<C> s = c.ring.modul.multiply(b);
466        s = s.sum(c.val);
467        return new AlgebraicNumber<C>(this, s);
468    }
469
470
471    /**
472     * Depth of extension field tower.
473     * @return number of nested algebraic extension fields
474     */
475    @SuppressWarnings("unchecked")
476    public int depth() {
477        AlgebraicNumberRing<C> arr = this;
478        int depth = 1;
479        RingFactory<C> cf = arr.ring.coFac;
480        if (cf instanceof AlgebraicNumberRing) {
481            arr = (AlgebraicNumberRing<C>) (Object) cf;
482            depth += arr.depth();
483        }
484        return depth;
485    }
486
487
488    /**
489     * Degree of extension field.
490     * @return degree of this algebraic extension field
491     */
492    public long extensionDegree() {
493        long degree = modul.degree(0);
494        return degree;
495    }
496
497
498    /**
499     * Total degree of nested extension fields.
500     * @return degree of tower of algebraic extension fields
501     */
502    @SuppressWarnings("unchecked")
503    public long totalExtensionDegree() {
504        long degree = modul.degree(0);
505        AlgebraicNumberRing<C> arr = this;
506        RingFactory<C> cf = arr.ring.coFac;
507        if (cf instanceof AlgebraicNumberRing) {
508            arr = (AlgebraicNumberRing<C>) (Object) cf;
509            if (degree == 0L) {
510                degree = arr.totalExtensionDegree();
511            } else {
512                degree *= arr.totalExtensionDegree();
513            }
514        }
515        return degree;
516    }
517
518
519    /**
520     * Get a AlgebraicNumber iterator. <b>Note: </b> Only for finite field
521     * coefficients or fields which are iterable.
522     * @return a iterator over all algebraic numbers in this ring.
523     */
524    public Iterator<AlgebraicNumber<C>> iterator() {
525        return new AlgebraicNumberIterator<C>(this);
526    }
527
528}
529
530
531/**
532 * Algebraic number iterator.
533 * @author Heinz Kredel
534 */
535class AlgebraicNumberIterator<C extends RingElem<C>> implements Iterator<AlgebraicNumber<C>> {
536
537
538    /**
539     * data structure.
540     */
541    final Iterator<List<C>> iter;
542
543
544    final List<GenPolynomial<C>> powers;
545
546
547    final AlgebraicNumberRing<C> aring;
548
549
550    private static final Logger logger = Logger.getLogger(AlgebraicNumberIterator.class);
551
552
553    //  private final boolean debug = logger.isDebugEnabled();
554
555
556    /**
557     * CartesianProduct iterator constructor.
558     * @param aring AlgebraicNumberRing components of the Cartesian product.
559     */
560    public AlgebraicNumberIterator(AlgebraicNumberRing<C> aring) {
561        RingFactory<C> cf = aring.ring.coFac;
562        this.aring = aring;
563        long d = aring.modul.degree(0);
564        //System.out.println("d = " + d);
565        powers = new ArrayList<GenPolynomial<C>>((int) d);
566        for (long j = d - 1; j >= 0L; j--) {
567            powers.add(aring.ring.univariate(0, j));
568        }
569        //System.out.println("powers = " + powers);
570        if (!(cf instanceof Iterable)) {
571            throw new IllegalArgumentException("only for iterable coefficients implemented");
572        }
573        List<Iterable<C>> comps = new ArrayList<Iterable<C>>((int) d);
574        Iterable<C> cfi = (Iterable<C>) cf;
575        for (long j = 0L; j < d; j++) {
576            comps.add(cfi);
577        }
578        if (cf.isFinite()) {
579            CartesianProduct<C> tuples = new CartesianProduct<C>(comps);
580            iter = tuples.iterator();
581        } else {
582            CartesianProductInfinite<C> tuples = new CartesianProductInfinite<C>(comps);
583            iter = tuples.iterator();
584        }
585        if (logger.isInfoEnabled()) {
586            logger.info("iterator for degree " + d + ", finite = " + cf.isFinite());
587        }
588    }
589
590
591    /**
592     * Test for availability of a next tuple.
593     * @return true if the iteration has more tuples, else false.
594     */
595    public boolean hasNext() {
596        return iter.hasNext();
597    }
598
599
600    /**
601     * Get next tuple.
602     * @return next tuple.
603     */
604    public AlgebraicNumber<C> next() {
605        List<C> coeffs = iter.next();
606        //System.out.println("coeffs = " + coeffs);
607        GenPolynomial<C> pol = aring.ring.getZERO();
608        int i = 0;
609        for (GenPolynomial<C> f : powers) {
610            C c = coeffs.get(i++);
611            if (c.isZERO()) {
612                continue;
613            }
614            pol = pol.sum(f.multiply(c));
615        }
616        return new AlgebraicNumber<C>(aring, pol);
617    }
618
619
620    /**
621     * Remove a tuple if allowed.
622     */
623    public void remove() {
624        throw new UnsupportedOperationException("cannnot remove tuples");
625    }
626
627}