001    /*
002     * $Id: QuotientRing.java 3670 2011-06-25 19:04:28Z kredel $
003     */
004    
005    package edu.jas.ufd;
006    
007    
008    import java.io.Reader;
009    import java.util.ArrayList;
010    import java.util.List;
011    import java.util.Random;
012    
013    import org.apache.log4j.Logger;
014    
015    import edu.jas.kern.StringUtil;
016    import edu.jas.poly.GenPolynomial;
017    import edu.jas.poly.GenPolynomialRing;
018    import edu.jas.poly.PolyUtil;
019    import edu.jas.structure.GcdRingElem;
020    import edu.jas.structure.RingFactory;
021    
022    
023    /**
024     * Quotient ring factory based on GenPolynomial with RingElem interface. Objects
025     * of this class are immutable.
026     * @author Heinz Kredel
027     */
028    public class QuotientRing<C extends GcdRingElem<C>> implements RingFactory<Quotient<C>> {
029    
030    
031        private static final Logger logger = Logger.getLogger(QuotientRing.class);
032    
033    
034        //private boolean debug = logger.isDebugEnabled();
035    
036    
037        /**
038         * Polynomial ring of the factory.
039         */
040        public final GenPolynomialRing<C> ring;
041    
042    
043        /**
044         * GCD engine of the factory.
045         */
046        public final GreatestCommonDivisor<C> engine;
047    
048    
049        /**
050         * Use GCD of package edu.jas.ufd.
051         */
052        public final boolean ufdGCD;
053    
054    
055        /**
056         * The constructor creates a QuotientRing object from a GenPolynomialRing.
057         * @param r polynomial ring.
058         */
059        public QuotientRing(GenPolynomialRing<C> r) {
060            this(r, true);
061        }
062    
063    
064        /**
065         * The constructor creates a QuotientRing object from a GenPolynomialRing.
066         * @param r polynomial ring.
067         * @param ufdGCD flag, if syzygy or gcd based algorithm used for engine.
068         */
069        public QuotientRing(GenPolynomialRing<C> r, boolean ufdGCD) {
070            ring = r;
071            this.ufdGCD = ufdGCD;
072    //         if (!ufdGCD) {
073    //             engine = null;
074    //             return;
075    //         }
076            engine = GCDFactory.<C> getProxy(ring.coFac);
077        }
078    
079    
080        /**
081         * Divide.
082         * @param n first polynomial.
083         * @param d second polynomial.
084         * @return divide(n,d)
085         */
086        protected GenPolynomial<C> divide(GenPolynomial<C> n, GenPolynomial<C> d) {
087            return PolyUtil.<C> basePseudoDivide(n, d);
088        }
089    
090    
091        /**
092         * Greatest common divisor.
093         * @param n first polynomial.
094         * @param d second polynomial.
095         * @return gcd(n,d)
096         */
097        protected GenPolynomial<C> gcd(GenPolynomial<C> n, GenPolynomial<C> d) {
098            if (ufdGCD) {
099                return engine.gcd(n, d);
100            }
101            return engine.gcd(n, d);
102            //return syzGcd(n, d);
103        }
104    
105    
106        /*
107         * Least common multiple. Just for fun, is not efficient.
108         * @param n first polynomial.
109         * @param d second polynomial.
110         * @return lcm(n,d)
111         */
112    //     protected GenPolynomial<C> syzLcm(GenPolynomial<C> n, GenPolynomial<C> d) {
113    //         List<GenPolynomial<C>> list = new ArrayList<GenPolynomial<C>>(1);
114    //         list.add(n);
115    //         Ideal<C> N = new Ideal<C>(n.ring, list, true);
116    //         list = new ArrayList<GenPolynomial<C>>(1);
117    //         list.add(d);
118    //         Ideal<C> D = new Ideal<C>(n.ring, list, true);
119    //         Ideal<C> L = N.intersect(D);
120    //         if (L.getList().size() != 1) {
121    //             throw new RuntimeException("lcm not uniqe");
122    //         }
123    //         GenPolynomial<C> lcm = L.getList().get(0);
124    //         return lcm;
125    //     }
126    
127    
128        /*
129         * Greatest common divisor. Just for fun, is not efficient.
130         * @param n first polynomial.
131         * @param d second polynomial.
132         * @return gcd(n,d)
133         */
134    //     protected GenPolynomial<C> syzGcd(GenPolynomial<C> n, GenPolynomial<C> d) {
135    //         if (n.isZERO()) {
136    //             return d;
137    //         }
138    //         if (d.isZERO()) {
139    //             return n;
140    //         }
141    //         if (n.isONE()) {
142    //             return n;
143    //         }
144    //         if (d.isONE()) {
145    //             return d;
146    //         }
147    //         GenPolynomial<C> p = n.multiply(d);
148    //         GenPolynomial<C> lcm = syzLcm(n, d);
149    //         GenPolynomial<C> gcd = divide(p, lcm);
150    //         return gcd;
151    //     }
152    
153    
154        /**
155         * Is this structure finite or infinite.
156         * @return true if this structure is finite, else false.
157         * @see edu.jas.structure.ElemFactory#isFinite()
158         */
159        public boolean isFinite() {
160            return false;
161        }
162    
163    
164        /**
165         * Copy Quotient element c.
166         * @param c
167         * @return a copy of c.
168         */
169        public Quotient<C> copy(Quotient<C> c) {
170            return new Quotient<C>(c.ring, c.num, c.den, true);
171        }
172    
173    
174        /**
175         * Get the zero element.
176         * @return 0 as Quotient.
177         */
178        public Quotient<C> getZERO() {
179            return new Quotient<C>(this, ring.getZERO());
180        }
181    
182    
183        /**
184         * Get the one element.
185         * @return 1 as Quotient.
186         */
187        public Quotient<C> getONE() {
188            return new Quotient<C>(this, ring.getONE());
189        }
190    
191    
192        /**
193         * Get a list of the generating elements.
194         * @return list of generators for the algebraic structure.
195         * @see edu.jas.structure.ElemFactory#generators()
196         */
197        public List<Quotient<C>> generators() {
198            List<GenPolynomial<C>> pgens = ring.generators();
199            List<Quotient<C>> gens = new ArrayList<Quotient<C>>(pgens.size());
200            for (GenPolynomial<C> p : pgens) {
201                Quotient<C> q = new Quotient<C>(this, p);
202                gens.add(q);
203            }
204            return gens;
205        }
206    
207    
208        /**
209         * Query if this ring is commutative.
210         * @return true if this ring is commutative, else false.
211         */
212        public boolean isCommutative() {
213            return ring.isCommutative();
214        }
215    
216    
217        /**
218         * Query if this ring is associative.
219         * @return true if this ring is associative, else false.
220         */
221        public boolean isAssociative() {
222            return ring.isAssociative();
223        }
224    
225    
226        /**
227         * Query if this ring is a field.
228         * @return true.
229         */
230        public boolean isField() {
231            return true;
232        }
233    
234    
235        /**
236         * Characteristic of this ring.
237         * @return characteristic of this ring.
238         */
239        public java.math.BigInteger characteristic() {
240            return ring.characteristic();
241        }
242    
243    
244        /**
245         * Get a Quotient element from a BigInteger value.
246         * @param a BigInteger.
247         * @return a Quotient.
248         */
249        public Quotient<C> fromInteger(java.math.BigInteger a) {
250            return new Quotient<C>(this, ring.fromInteger(a));
251        }
252    
253    
254        /**
255         * Get a Quotient element from a long value.
256         * @param a long.
257         * @return a Quotient.
258         */
259        public Quotient<C> fromInteger(long a) {
260            return new Quotient<C>(this, ring.fromInteger(a));
261        }
262    
263    
264        /**
265         * Get the String representation as RingFactory.
266         * @see java.lang.Object#toString()
267         */
268        @Override
269        public String toString() {
270            String s = null;
271            if ( ring.coFac.characteristic().signum() == 0 ) {
272                s = "RatFunc";
273            } else {
274                s = "ModFunc";
275            }
276            return s + "( " + ring.toString() + " )";
277        }
278    
279    
280        /**
281         * Get a scripting compatible string representation.
282         * @return script compatible representation for this ElemFactory.
283         * @see edu.jas.structure.ElemFactory#toScript()
284         */
285        //JAVA6only: @Override
286        public String toScript() {
287            // Python case
288            return "RF(" + ring.toScript() + ")";
289        }
290    
291    
292        /**
293         * Comparison with any other object.
294         * @see java.lang.Object#equals(java.lang.Object)
295         */
296        @Override
297        @SuppressWarnings("unchecked")
298        // not jet working
299        public boolean equals(Object b) {
300            if (!(b instanceof QuotientRing)) {
301                return false;
302            }
303            QuotientRing<C> a = null;
304            try {
305                a = (QuotientRing<C>) b;
306            } catch (ClassCastException e) {
307            }
308            if (a == null) {
309                return false;
310            }
311            return ring.equals(a.ring);
312        }
313    
314    
315        /**
316         * Hash code for this quotient ring.
317         * @see java.lang.Object#hashCode()
318         */
319        @Override
320        public int hashCode() {
321            int h;
322            h = ring.hashCode();
323            return h;
324        }
325    
326    
327        /**
328         * Quotient random.
329         * @param n such that 0 &le; v &le; (2<sup>n</sup>-1).
330         * @return a random residue element.
331         */
332        public Quotient<C> random(int n) {
333            GenPolynomial<C> r = ring.random(n).monic();
334            GenPolynomial<C> s = ring.random(n).monic();
335            while (s.isZERO()) {
336                s = ring.random(n).monic();
337            }
338            return new Quotient<C>(this, r, s, false);
339        }
340    
341    
342        /**
343         * Generate a random residum polynomial.
344         * @param k bitsize of random coefficients.
345         * @param l number of terms.
346         * @param d maximal degree in each variable.
347         * @param q density of nozero exponents.
348         * @return a random residue polynomial.
349         */
350        public Quotient<C> random(int k, int l, int d, float q) {
351            GenPolynomial<C> r = ring.random(k, l, d, q).monic();
352            GenPolynomial<C> s = ring.random(k, l, d, q).monic();
353            while (s.isZERO()) {
354                s = ring.random(k, l, d, q).monic();
355            }
356            return new Quotient<C>(this, r, s, false);
357        }
358    
359    
360        /**
361         * Quotient random.
362         * @param n such that 0 &le; v &le; (2<sup>n</sup>-1).
363         * @param rnd is a source for random bits.
364         * @return a random residue element.
365         */
366        public Quotient<C> random(int n, Random rnd) {
367            GenPolynomial<C> r = ring.random(n, rnd).monic();
368            GenPolynomial<C> s = ring.random(n, rnd).monic();
369            while (s.isZERO()) {
370                s = ring.random(n, rnd).monic();
371            }
372            return new Quotient<C>(this, r, s, false);
373        }
374    
375    
376        /**
377         * Parse Quotient from String. Syntax: "{ polynomial | polynomial }" or
378         * "{ polynomial }" or " polynomial | polynomial " or " polynomial "
379         * @param s String.
380         * @return Quotient from s.
381         */
382        public Quotient<C> parse(String s) {
383            int i = s.indexOf("{");
384            if (i >= 0) {
385                s = s.substring(i + 1);
386            }
387            i = s.lastIndexOf("}");
388            if (i >= 0) {
389                s = s.substring(0, i);
390            }
391            i = s.indexOf("|");
392            if (i < 0) {
393                GenPolynomial<C> n = ring.parse(s);
394                return new Quotient<C>(this, n);
395            }
396            String s1 = s.substring(0, i);
397            String s2 = s.substring(i + 1);
398            GenPolynomial<C> n = ring.parse(s1);
399            GenPolynomial<C> d = ring.parse(s2);
400            return new Quotient<C>(this, n, d);
401        }
402    
403    
404        /**
405         * Parse Quotient from Reader.
406         * @param r Reader.
407         * @return next Quotient from r.
408         */
409        public Quotient<C> parse(Reader r) {
410            String s = StringUtil.nextPairedString(r, '{', '}');
411            return parse(s);
412        }
413    
414    
415        /**
416         * Degree of extension field.
417         * @return degree of this extension field, -1 for transcendental extension.
418         */
419        public long extensionDegree() {
420            long degree = -1L;
421            if (ring.nvar <= 0) {
422                degree = 0L;
423            }
424            return degree;
425        }
426    
427    }