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