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