001/*
002 * $Id$
003 */
004
005package edu.jas.vector;
006
007
008import java.io.Serializable;
009import java.util.ArrayList;
010import java.util.Iterator;
011import java.util.List;
012
013import org.apache.logging.log4j.LogManager;
014import org.apache.logging.log4j.Logger;
015
016import edu.jas.structure.RingElem;
017
018
019/**
020 * Basic linear algebra methods. Implements Basic linear algebra computations
021 * and tests. <b>Note:</b> will use wrong method dispatch in JRE when used with
022 * GenSolvablePolynomial.
023 * @param <C> coefficient type
024 * @author Heinz Kredel
025 */
026
027public class BasicLinAlg<C extends RingElem<C>> implements Serializable {
028
029
030    private static final Logger logger = LogManager.getLogger(BasicLinAlg.class);
031
032
033    //private static final boolean debug = logger.isDebugEnabled();
034
035
036    /**
037     * Constructor.
038     */
039    public BasicLinAlg() {
040    }
041
042
043    /**
044     * Scalar product of vectors of ring elements.
045     * @param G a ring element list.
046     * @param F a ring element list.
047     * @return the scalar product of G and F.
048     */
049    public C scalarProduct(List<C> G, List<C> F) {
050        C sp = null;
051        Iterator<C> it = G.iterator();
052        Iterator<C> jt = F.iterator();
053        while (it.hasNext() && jt.hasNext()) {
054            C pi = it.next();
055            C pj = jt.next();
056            if (pi == null || pj == null) {
057                continue;
058            }
059            if (sp == null) {
060                sp = pi.multiply(pj);
061            } else {
062                sp = sp.sum(pi.multiply(pj));
063            }
064        }
065        if (it.hasNext() || jt.hasNext()) {
066            logger.error("scalarProduct wrong sizes");
067        }
068        return sp;
069    }
070
071
072    /**
073     * Scalar product of vectors and a matrix of ring elements.
074     * @param G a ring element list.
075     * @param F a list of ring element lists.
076     * @return the scalar product of G and F.
077     */
078    public List<C> leftScalarProduct(List<C> G, List<List<C>> F) {
079        List<C> sp = null; //new ArrayList<C>(G.size());
080        Iterator<C> it = G.iterator();
081        Iterator<List<C>> jt = F.iterator();
082        while (it.hasNext() && jt.hasNext()) {
083            C pi = it.next();
084            List<C> pj = jt.next();
085            if (pi == null || pj == null) {
086                continue;
087            }
088            List<C> s = scalarProduct(pi, pj);
089            if (sp == null) {
090                sp = s;
091            } else {
092                sp = vectorAdd(sp, s);
093            }
094        }
095        if (it.hasNext() || jt.hasNext()) {
096            logger.error("scalarProduct wrong sizes");
097        }
098        return sp;
099    }
100
101
102    /**
103     * Scalar product of vectors and a matrix of ring elements.
104     * @param G a ring element list.
105     * @param F a list of ring element lists.
106     * @return the right scalar product of G and F.
107     */
108    public List<C> rightScalarProduct(List<C> G, List<List<C>> F) {
109        List<C> sp = null; //new ArrayList<C>(G.size());
110        Iterator<C> it = G.iterator();
111        Iterator<List<C>> jt = F.iterator();
112        while (it.hasNext() && jt.hasNext()) {
113            C pi = it.next();
114            List<C> pj = jt.next();
115            if (pi == null || pj == null) {
116                continue;
117            }
118            List<C> s = scalarProduct(pj, pi);
119            if (sp == null) {
120                sp = s;
121            } else {
122                sp = vectorAdd(sp, s);
123            }
124        }
125        if (it.hasNext() || jt.hasNext()) {
126            logger.error("scalarProduct wrong sizes");
127        }
128        return sp;
129    }
130
131
132    /**
133     * Addition of vectors of ring elements.
134     * @param a a ring element list.
135     * @param b a ring element list.
136     * @return a+b, the vector sum of a and b.
137     */
138
139    public List<C> vectorAdd(List<C> a, List<C> b) {
140        if (a == null) {
141            return b;
142        }
143        if (b == null) {
144            return a;
145        }
146        List<C> V = new ArrayList<C>(a.size());
147        Iterator<C> it = a.iterator();
148        Iterator<C> jt = b.iterator();
149        while (it.hasNext() && jt.hasNext()) {
150            C pi = it.next();
151            C pj = jt.next();
152            C p = pi.sum(pj);
153            V.add(p);
154        }
155        //System.out.println("vectorAdd" + V);
156        if (it.hasNext() || jt.hasNext()) {
157            logger.error("vectorAdd wrong sizes");
158        }
159        return V;
160    }
161
162
163    /**
164     * Test vector of zero ring elements.
165     * @param a a ring element list.
166     * @return true, if all polynomial in a are zero, else false.
167     */
168    public boolean isZero(List<C> a) {
169        if (a == null) {
170            return true;
171        }
172        for (C pi : a) {
173            if (pi == null) {
174                continue;
175            }
176            if (!pi.isZERO()) {
177                return false;
178            }
179        }
180        return true;
181    }
182
183
184    /**
185     * Scalar product of ring element with vector of ring elements.
186     * @param p a ring element.
187     * @param F a ring element list.
188     * @return the scalar product of p and F.
189     */
190    public List<C> scalarProduct(C p, List<C> F) {
191        List<C> V = new ArrayList<C>(F.size());
192        for (C pi : F) {
193            if (p != null) {
194                pi = p.multiply(pi);
195            } else {
196                pi = null;
197            }
198            V.add(pi);
199        }
200        return V;
201    }
202
203
204    /**
205     * Scalar product of vector of ring element with ring element.
206     * @param F a ring element list.
207     * @param p a ring element.
208     * @return the scalar product of F and p.
209     */
210    public List<C> scalarProduct(List<C> F, C p) {
211        List<C> V = new ArrayList<C>(F.size());
212        for (C pi : F) {
213            if (pi != null) {
214                pi = pi.multiply(p);
215            }
216            V.add(pi);
217        }
218        return V;
219    }
220
221
222    /**
223     * Product of a vector and a matrix of ring elements.
224     * @param G a vectors of ring elements.
225     * @param F a matrix of ring element lists.
226     * @return the left product of G and F.
227     */
228    public GenVector<C> leftProduct(GenVector<C> G, GenMatrix<C> F) {
229        ArrayList<C> sp = new ArrayList<C>(G.val.size());
230        Iterator<ArrayList<C>> jt = F.matrix.iterator();
231        while (jt.hasNext()) {
232            ArrayList<C> pj = jt.next();
233            if (pj == null) {
234                continue;
235            }
236            C s = scalarProduct(G.val, pj);
237            sp.add(s);
238        }
239        return new GenVector<C>(G.modul, sp);
240    }
241
242
243    /**
244     * Product of a vector and a matrix of ring elements.
245     * @param G a vector of element list.
246     * @param F a matrix of ring element lists.
247     * @return the right product of G and F.
248     */
249    public GenVector<C> rightProduct(GenVector<C> G, GenMatrix<C> F) {
250        ArrayList<C> sp = new ArrayList<C>(G.val.size());
251        Iterator<ArrayList<C>> jt = F.matrix.iterator();
252        while (jt.hasNext()) {
253            ArrayList<C> pj = jt.next();
254            if (pj == null) {
255                continue;
256            }
257            C s = scalarProduct(pj, G.val);
258            sp.add(s);
259        }
260        return new GenVector<C>(G.modul, sp);
261    }
262
263}