001/*
002 * $Id$
003 */
004
005package edu.jas.poly;
006
007
008import java.io.Serializable;
009import java.util.ArrayList;
010import java.util.List;
011
012import org.apache.logging.log4j.Logger;
013import org.apache.logging.log4j.LogManager; 
014
015import edu.jas.kern.Scripting;
016import edu.jas.structure.RingElem;
017import edu.jas.vector.GenVector;
018import edu.jas.vector.GenVectorModul;
019
020
021/**
022 * List of vectors of polynomials. Mainly for storage and printing / toString
023 * and conversions to other representations.
024 * @author Heinz Kredel
025 */
026
027public class ModuleList<C extends RingElem<C>> implements Serializable {
028
029
030    /**
031     * The factory for the solvable polynomial ring.
032     */
033    public final GenPolynomialRing<C> ring;
034
035
036    /**
037     * The data structure is a List of Lists of polynomials.
038     */
039    public final List<List<GenPolynomial<C>>> list;
040
041
042    /**
043     * Number of rows in the data structure.
044     */
045    public final int rows; // -1 is undefined
046
047
048    /**
049     * Number of columns in the data structure.
050     */
051    public final int cols; // -1 is undefined
052
053
054    private static final Logger logger = LogManager.getLogger(ModuleList.class);
055
056
057    /**
058     * Constructor.
059     * @param r polynomial ring factory.
060     * @param l list of list of polynomials.
061     */
062    public ModuleList(GenPolynomialRing<C> r, List<List<GenPolynomial<C>>> l) {
063        ring = r;
064        list = ModuleList.<C> padCols(r, l);
065        if (list == null) {
066            rows = -1;
067            cols = -1;
068        } else {
069            rows = list.size();
070            if (rows > 0) {
071                cols = list.get(0).size();
072            } else {
073                cols = -1;
074            }
075        }
076    }
077
078
079    /**
080     * Constructor.
081     * @param r solvable polynomial ring factory.
082     * @param l list of list of solvable polynomials.
083     */
084    public ModuleList(GenSolvablePolynomialRing<C> r, List<List<GenSolvablePolynomial<C>>> l) {
085        this(r, ModuleList.<C> castToList(l));
086    }
087
088
089    /**
090     * Constructor.
091     * @param r polynomial ring factory.
092     * @param l list of vectors of polynomials.
093     */
094    public ModuleList(GenVectorModul<GenPolynomial<C>> r, List<GenVector<GenPolynomial<C>>> l) {
095        this((GenPolynomialRing<C>) r.coFac, ModuleList.<C> vecToList(l));
096    }
097
098
099    /**
100     * Comparison with any other object.
101     * @see java.lang.Object#equals(java.lang.Object)
102     */
103    @Override
104    @SuppressWarnings("unchecked")
105    // not jet working
106    public boolean equals(Object m) {
107        if (m == null) {
108            return false;
109        }
110        if (!(m instanceof ModuleList)) {
111            //System.out.println("ModuleList");
112            return false;
113        }
114        ModuleList<C> ml = (ModuleList<C>) m;
115        if (!ring.equals(ml.ring)) {
116            //System.out.println("Ring");
117            return false;
118        }
119        if (list == ml.list) {
120            return true;
121        }
122        if (list == null || ml.list == null) {
123            //System.out.println("List, null");
124            return false;
125        }
126        if (list.size() != ml.list.size()) {
127            //System.out.println("List, size");
128            return false;
129        }
130        // compare sorted lists
131        List otl = OrderedModuleList.sort(ring, list);
132        List oml = OrderedModuleList.sort(ring, ml.list);
133        if (!otl.equals(oml)) {
134            return false;
135        }
136        return true;
137    }
138
139
140    /**
141     * Hash code for this module list.
142     * @see java.lang.Object#hashCode()
143     */
144    @Override
145    public int hashCode() {
146        int h;
147        h = ring.hashCode();
148        h = 37 * h + (list == null ? 0 : list.hashCode());
149        return h;
150    }
151
152
153    /**
154     * Test if list is empty.
155     * @return true if this is empty, else false.
156     */
157    public boolean isEmpty() {
158        if (list == null) {
159            return true;
160        }
161        if (rows <= 0) {
162            return true;
163        }
164        return false;
165    }
166
167
168    /**
169     * Test all elements are zero.
170     * @return true if all elements are zero, else false.
171     */
172    public boolean isZERO() {
173        if (list == null) {
174            return true;
175        }
176        if (rows <= 0) {
177            return true;
178        }
179        for (List<GenPolynomial<C>> row : list) {
180            for (GenPolynomial<C> oa : row) {
181                if (!oa.isZERO()) {
182                    return false;
183                }
184            }
185        }       
186        return true;
187    }
188
189
190    /**
191     * String representation of the module list.
192     * @see java.lang.Object#toString()
193     */
194    @Override
195    //@SuppressWarnings("unchecked") 
196    public String toString() {
197        StringBuffer erg = new StringBuffer();
198        String[] vars = null;
199        if (ring != null) {
200            erg.append(ring.toString());
201            vars = ring.getVars();
202        }
203        if (list == null) {
204            erg.append(")");
205            return erg.toString();
206        }
207        boolean first = true;
208        erg.append("(\n");
209        for (List<GenPolynomial<C>> row : list) {
210            if (first) {
211                first = false;
212            } else {
213                erg.append(",\n");
214            }
215            boolean ifirst = true;
216            erg.append(" ( ");
217            String os;
218            for (GenPolynomial<C> oa : row) {
219                if (oa == null) {
220                    os = "0";
221                } else if (vars != null) {
222                    os = oa.toString(vars);
223                } else {
224                    os = oa.toString();
225                }
226                if (ifirst) {
227                    ifirst = false;
228                } else {
229                    erg.append(", ");
230                    if (os.length() > 100) {
231                        erg.append("\n");
232                    }
233                }
234                erg.append(os);
235            }
236            erg.append(" )");
237        }
238        erg.append("\n)");
239        return erg.toString();
240    }
241
242
243    /**
244     * Get a scripting compatible string representation.
245     * @return script compatible representation for this ModuleList.
246     */
247    public String toScript() {
248        StringBuffer s = new StringBuffer();
249        if (ring instanceof GenSolvablePolynomialRing) {
250            s.append("Solvable");
251        }
252        switch (Scripting.getLang()) {
253        case Ruby:
254            s.append("SubModule.new(");
255            break;
256        case Python:
257        default:
258            s.append("SubModule(");
259        }
260        if (ring != null) {
261            s.append(ring.toScript());
262        }
263        if (list == null) {
264            s.append(")");
265            return s.toString();
266        }
267        switch (Scripting.getLang()) {
268        case Ruby:
269            s.append(",\"\",[");
270            break;
271        case Python:
272        default:
273            s.append(",list=[");
274        }
275        boolean first = true;
276        for (List<GenPolynomial<C>> row : list) {
277            if (first) {
278                first = false;
279            } else {
280                s.append(",");
281            }
282            boolean ifirst = true;
283            s.append(" ( ");
284            String os;
285            for (GenPolynomial<C> oa : row) {
286                if (oa == null) {
287                    os = "0";
288                } else {
289                    os = oa.toScript();
290                }
291                if (ifirst) {
292                    ifirst = false;
293                } else {
294                    s.append(", ");
295                }
296                s.append(os);
297            }
298            s.append(" )");
299        }
300        s.append(" ])");
301        return s.toString();
302    }
303
304
305    /**
306     * Pad columns and remove zero rows. Make all rows have the same number of
307     * columns.
308     * @param ring polynomial ring factory.
309     * @param l list of list of polynomials.
310     * @return list of list of polynomials with same number of columns.
311     */
312    public static <C extends RingElem<C>> List<List<GenPolynomial<C>>> padCols(GenPolynomialRing<C> ring,
313                    List<List<GenPolynomial<C>>> l) {
314        if (l == null) {
315            return l;
316        }
317        int mcols = 0;
318        int rs = 0;
319        for (List<GenPolynomial<C>> row : l) {
320            if (row != null) {
321                rs++;
322                if (row.size() > mcols) {
323                    mcols = row.size();
324                }
325            }
326        }
327        List<List<GenPolynomial<C>>> norm = new ArrayList<List<GenPolynomial<C>>>(rs);
328        for (List<GenPolynomial<C>> row : l) {
329            if (row != null) {
330                List<GenPolynomial<C>> rn = new ArrayList<GenPolynomial<C>>(row);
331                while (rn.size() < mcols) {
332                    rn.add(ring.getZERO());
333                }
334                norm.add(rn);
335            }
336        }
337        return norm;
338    }
339
340
341    /**
342     * Get PolynomialList. Embed module in a polynomial ring.
343     * @see edu.jas.poly.PolynomialList
344     * @return polynomial list corresponding to this.
345     */
346    public PolynomialList<C> getPolynomialList() {
347        return getPolynomialList(false);
348    }
349
350    
351    /**
352     * Get PolynomialList. Embed module in a polynomial ring.
353     * @see edu.jas.poly.PolynomialList
354     * @param top true for TOP term order, false for POT term order.
355     * @return polynomial list corresponding to this.
356     */
357    public PolynomialList<C> getPolynomialList(boolean top) {
358        GenPolynomialRing<C> pfac = ring.extend(cols, top);
359        logger.debug("extended ring = {}", pfac);
360        //System.out.println("extended ring = " + pfac);
361        return getPolynomialList(pfac);
362    }
363
364
365    /**
366     * Get PolynomialList. Embed module in a polynomial ring.
367     * @see edu.jas.poly.PolynomialList
368     * @param pfac polynomial ring.
369     * @return polynomial list corresponding to pfac and this.
370     */
371    public PolynomialList<C> getPolynomialList(GenPolynomialRing<C> pfac) {
372        List<GenPolynomial<C>> pols = null;
373        if (list == null) { // rows < 0
374            return new PolynomialList<C>(pfac, pols);
375        }
376        pols = new ArrayList<GenPolynomial<C>>(rows);
377        if (rows == 0) { // nothing to do
378            return new PolynomialList<C>(pfac, pols);
379        }
380        GenPolynomial<C> zero = pfac.getZERO();
381        GenPolynomial<C> d = null;
382        for (List<GenPolynomial<C>> r : list) {
383            GenPolynomial<C> ext = zero;
384            //int m = cols-1;
385            int m = 0;
386            for (GenPolynomial<C> c : r) {
387                d = c.extend(pfac, m, 1l);
388                ext = ext.sum(d);
389                m++;
390            }
391            pols.add(ext);
392        }
393        return new PolynomialList<C>(pfac, pols);
394    }
395
396
397    /**
398     * Get list as List of GenSolvablePolynomials. Required because no List
399     * casts allowed. Equivalent to cast
400     * (List&lt;List&lt;GenSolvablePolynomial&lt;C&gt;&gt;&gt;) list.
401     * @return list of solvable polynomial lists from this.
402     */
403    public List<List<GenSolvablePolynomial<C>>> castToSolvableList() {
404        List<List<GenSolvablePolynomial<C>>> slist = null;
405        if (list == null) {
406            return slist;
407        }
408        slist = new ArrayList<List<GenSolvablePolynomial<C>>>(list.size());
409        for (List<GenPolynomial<C>> row : list) {
410            List<GenSolvablePolynomial<C>> srow = new ArrayList<GenSolvablePolynomial<C>>(row.size());
411            for (GenPolynomial<C> p : row) {
412                if (!(p instanceof GenSolvablePolynomial)) {
413                    throw new RuntimeException("no solvable polynomial " + p);
414                }
415                GenSolvablePolynomial<C> s = (GenSolvablePolynomial<C>) p;
416                srow.add(s);
417            }
418            slist.add(srow);
419        }
420        return slist;
421    }
422
423
424    /**
425     * Get a solvable polynomials list as List of GenPolynomials. Required
426     * because no List casts allowed. Equivalent to cast
427     * (List&lt;List&lt;GenPolynomial&lt;C&gt;&gt;&gt;) list.
428     * @param slist list of solvable polynomial lists.
429     * @return list of polynomial lists from slist.
430     */
431    public static <C extends RingElem<C>> List<List<GenPolynomial<C>>> castToList(
432                    List<List<GenSolvablePolynomial<C>>> slist) {
433        List<List<GenPolynomial<C>>> list = null;
434        if (slist == null) {
435            return list;
436        }
437        list = new ArrayList<List<GenPolynomial<C>>>(slist.size());
438        for (List<GenSolvablePolynomial<C>> srow : slist) {
439            List<GenPolynomial<C>> row = new ArrayList<GenPolynomial<C>>(srow.size());
440            for (GenSolvablePolynomial<C> s : srow) {
441                row.add(s);
442            }
443            list.add(row);
444        }
445        return list;
446    }
447
448
449    /**
450     * Get a list of vectors as List of list of GenPolynomials.
451     * @param vlist list of vectors of polynomials.
452     * @return list of polynomial lists from vlist.
453     */
454    public static <C extends RingElem<C>> List<List<GenPolynomial<C>>> vecToList(
455                    List<GenVector<GenPolynomial<C>>> vlist) {
456        List<List<GenPolynomial<C>>> list = null;
457        if (vlist == null) {
458            return list;
459        }
460        list = new ArrayList<List<GenPolynomial<C>>>(vlist.size());
461        for (GenVector<GenPolynomial<C>> srow : vlist) {
462            List<GenPolynomial<C>> row = srow.val;
463            list.add(row);
464        }
465        return list;
466    }
467
468}