001/*
002 * $Id: BasicLinAlg.java 5872 2018-07-20 16:01:46Z kredel $
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.Logger;
014import org.apache.logging.log4j.LogManager; 
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}