1dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond/*
2dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Licensed to the Apache Software Foundation (ASF) under one or more
3dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * contributor license agreements.  See the NOTICE file distributed with
4dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * this work for additional information regarding copyright ownership.
5dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * The ASF licenses this file to You under the Apache License, Version 2.0
6dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * (the "License"); you may not use this file except in compliance with
7dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * the License.  You may obtain a copy of the License at
8dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond *
9dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond *      http://www.apache.org/licenses/LICENSE-2.0
10dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond *
11dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * Unless required by applicable law or agreed to in writing, software
12dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * distributed under the License is distributed on an "AS IS" BASIS,
13dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * See the License for the specific language governing permissions and
15dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * limitations under the License.
16dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */
17dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondpackage org.apache.commons.math.linear;
18dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
19dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport java.io.Serializable;
20dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport java.lang.reflect.Array;
21dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
22dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.Field;
23dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.FieldElement;
24dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.MathRuntimeException;
25dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.exception.util.LocalizedFormats;
26dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondimport org.apache.commons.math.util.OpenIntToFieldHashMap;
27dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
28dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond/**
29dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * This class implements the {@link FieldVector} interface with a {@link OpenIntToFieldHashMap} backing store.
30dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @param <T> the type of the field elements
31dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @version $Revision: 983921 $ $Date: 2010-08-10 12:46:06 +0200 (mar. 10 août 2010) $
32dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond * @since 2.0
33dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond */
34dee0849a9704d532af0b550146cbafbaa6ee1d19Raymondpublic class SparseFieldVector<T extends FieldElement<T>> implements FieldVector<T>, Serializable {
35dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
36dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
37dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *  Serial version id
38dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
39dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private static final long serialVersionUID = 7841233292190413362L;
40dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Field to which the elements belong. */
41dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private final Field<T> field;
42dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Entries of the vector. */
43dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private final OpenIntToFieldHashMap<T> entries;
44dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Dimension of the vector. */
45dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private final int virtualSize;
46dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
47dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
48dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Build a 0-length vector.
49dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * <p>Zero-length vectors may be used to initialize construction of vectors
50dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * by data gathering. We start with zero-length and use either the {@link
51dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * #SparseFieldVector(SparseFieldVector, int)} constructor
52dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * or one of the <code>append</code> method ({@link #append(FieldElement)},
53dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * {@link #append(FieldElement[])}, {@link #append(FieldVector)},
54dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * {@link #append(SparseFieldVector)}) to gather data into this vector.</p>
55dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param field field to which the elements belong
56dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
57dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public SparseFieldVector(Field<T> field) {
58dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        this(field, 0);
59dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
60dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
61dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
62dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
63dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Construct a (dimension)-length vector of zeros.
64dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param field field to which the elements belong
65dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param dimension Size of the vector
66dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
67dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public SparseFieldVector(Field<T> field, int dimension) {
68dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        this.field = field;
69dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        virtualSize = dimension;
70dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        entries = new OpenIntToFieldHashMap<T>(field);
71dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
72dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
73dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
74dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Build a resized vector, for use with append.
75dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param v The original vector
76dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param resize The amount to resize it
77dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
78dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    protected SparseFieldVector(SparseFieldVector<T> v, int resize) {
79dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        field = v.field;
80dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        virtualSize = v.getDimension() + resize;
81dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        entries = new OpenIntToFieldHashMap<T>(v.entries);
82dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
83dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
84dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
85dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
86dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Build a vector with known the sparseness (for advanced use only).
87dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param field field to which the elements belong
88dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param dimension The size of the vector
89dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param expectedSize The expected number of non-zero entries
90dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
91dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public SparseFieldVector(Field<T> field, int dimension, int expectedSize) {
92dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        this.field = field;
93dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        virtualSize = dimension;
94dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        entries = new OpenIntToFieldHashMap<T>(field,expectedSize);
95dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
96dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
97dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
98dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Create from a Field array.
99dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Only non-zero entries will be stored
100dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param field field to which the elements belong
101dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param values The set of values to create from
102dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
103dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public SparseFieldVector(Field<T> field, T[] values) {
104dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        this.field = field;
105dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        virtualSize = values.length;
106dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        entries = new OpenIntToFieldHashMap<T>(field);
107dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        for (int key = 0; key < values.length; key++) {
108dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            T value = values[key];
109dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            entries.put(key, value);
110dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
111dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
112dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
113dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
114dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
115dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
116dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Copy constructor.
117dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param v The instance to copy from
118dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
119dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public SparseFieldVector(SparseFieldVector<T> v) {
120dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        field = v.field;
121dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        virtualSize = v.getDimension();
122dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        entries = new OpenIntToFieldHashMap<T>(v.getEntries());
123dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
124dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
125dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
126dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Get the entries of this instance.
127dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return entries of this instance
128dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
129dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private OpenIntToFieldHashMap<T> getEntries() {
130dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return entries;
131dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
132dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
133dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
134dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Optimized method to add sparse vectors.
135dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param v vector to add
136dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return The sum of <code>this</code> and <code>v</code>
137dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws IllegalArgumentException If the dimensions don't match
138dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
139dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public FieldVector<T> add(SparseFieldVector<T> v) throws IllegalArgumentException {
140dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        checkVectorDimensions(v.getDimension());
141dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        SparseFieldVector<T> res = (SparseFieldVector<T>)copy();
142dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        OpenIntToFieldHashMap<T>.Iterator iter = v.getEntries().iterator();
143dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        while (iter.hasNext()) {
144dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            iter.advance();
145dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            int key = iter.key();
146dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            T value = iter.value();
147dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (entries.containsKey(key)) {
148dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                res.setEntry(key, entries.get(key).add(value));
149dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            } else {
150dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                res.setEntry(key, value);
151dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
152dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
153dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return res;
154dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
155dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
156dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
157dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
158dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** {@inheritDoc} */
159dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public FieldVector<T> add(T[] v) throws IllegalArgumentException {
160dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        checkVectorDimensions(v.length);
161dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        SparseFieldVector<T> res = new SparseFieldVector<T>(field,getDimension());
162dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        for (int i = 0; i < v.length; i++) {
163dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            res.setEntry(i, v[i].add(getEntry(i)));
164dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
165dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return res;
166dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
167dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
168dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
169dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Construct a vector by appending a vector to this vector.
170dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param v vector to append to this one.
171dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return a new vector
172dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
173dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public FieldVector<T> append(SparseFieldVector<T> v) {
174dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        SparseFieldVector<T> res = new SparseFieldVector<T>(this, v.getDimension());
175dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        OpenIntToFieldHashMap<T>.Iterator iter = v.entries.iterator();
176dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        while (iter.hasNext()) {
177dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            iter.advance();
178dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            res.setEntry(iter.key() + virtualSize, iter.value());
179dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
180dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return res;
181dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
182dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
183dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** {@inheritDoc} */
184dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public FieldVector<T> append(FieldVector<T> v) {
185dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (v instanceof SparseFieldVector<?>) {
186dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return append((SparseFieldVector<T>) v);
187dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else {
188dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return append(v.toArray());
189dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
190dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
191dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
192dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** {@inheritDoc} */
193dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public FieldVector<T> append(T d) {
194dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        FieldVector<T> res = new SparseFieldVector<T>(this, 1);
195dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        res.setEntry(virtualSize, d);
196dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return res;
197dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     }
198dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
199dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** {@inheritDoc} */
200dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public FieldVector<T> append(T[] a) {
201dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        FieldVector<T> res = new SparseFieldVector<T>(this, a.length);
202dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        for (int i = 0; i < a.length; i++) {
203dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            res.setEntry(i + virtualSize, a[i]);
204dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
205dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return res;
206dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     }
207dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
208dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** {@inheritDoc} */
209dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public FieldVector<T> copy() {
210dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return new SparseFieldVector<T>(this);
211dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   }
212dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
213dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** {@inheritDoc} */
214dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public T dotProduct(FieldVector<T> v) throws IllegalArgumentException {
215dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        checkVectorDimensions(v.getDimension());
216dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        T res = field.getZero();
217dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        OpenIntToFieldHashMap<T>.Iterator iter = entries.iterator();
218dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        while (iter.hasNext()) {
219dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            iter.advance();
220dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            res = res.add(v.getEntry(iter.key()).multiply(iter.value()));
221dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
222dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return res;
223dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
224dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
225dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** {@inheritDoc} */
226dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public T dotProduct(T[] v) throws IllegalArgumentException {
227dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        checkVectorDimensions(v.length);
228dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        T res = field.getZero();
229dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        OpenIntToFieldHashMap<T>.Iterator iter = entries.iterator();
230dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        while (iter.hasNext()) {
231dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            int idx = iter.key();
232dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            T value = field.getZero();
233dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (idx < v.length) {
234dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                value = v[idx];
235dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
236dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            res = res.add(value.multiply(iter.value()));
237dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
238dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return res;
239dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     }
240dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
241dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** {@inheritDoc} */
242dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public FieldVector<T> ebeDivide(FieldVector<T> v)
243dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        throws IllegalArgumentException {
244dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        checkVectorDimensions(v.getDimension());
245dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        SparseFieldVector<T> res = new SparseFieldVector<T>(this);
246dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        OpenIntToFieldHashMap<T>.Iterator iter = res.entries.iterator();
247dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        while (iter.hasNext()) {
248dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            iter.advance();
249dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            res.setEntry(iter.key(), iter.value().divide(v.getEntry(iter.key())));
250dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
251dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return res;
252dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
253dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
254dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** {@inheritDoc} */
255dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public FieldVector<T> ebeDivide(T[] v) throws IllegalArgumentException {
256dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        checkVectorDimensions(v.length);
257dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        SparseFieldVector<T> res = new SparseFieldVector<T>(this);
258dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        OpenIntToFieldHashMap<T>.Iterator iter = res.entries.iterator();
259dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        while (iter.hasNext()) {
260dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            iter.advance();
261dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            res.setEntry(iter.key(), iter.value().divide(v[iter.key()]));
262dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
263dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return res;
264dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
265dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
266dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** {@inheritDoc} */
267dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public FieldVector<T> ebeMultiply(FieldVector<T> v)throws IllegalArgumentException {
268dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        checkVectorDimensions(v.getDimension());
269dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        SparseFieldVector<T> res = new SparseFieldVector<T>(this);
270dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        OpenIntToFieldHashMap<T>.Iterator iter = res.entries.iterator();
271dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        while (iter.hasNext()) {
272dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            iter.advance();
273dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            res.setEntry(iter.key(), iter.value().multiply(v.getEntry(iter.key())));
274dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
275dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return res;
276dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
277dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
278dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** {@inheritDoc} */
279dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     public FieldVector<T> ebeMultiply(T[] v) throws IllegalArgumentException {
280dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        checkVectorDimensions(v.length);
281dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        SparseFieldVector<T> res = new SparseFieldVector<T>(this);
282dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        OpenIntToFieldHashMap<T>.Iterator iter = res.entries.iterator();
283dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        while (iter.hasNext()) {
284dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            iter.advance();
285dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            res.setEntry(iter.key(), iter.value().multiply(v[iter.key()]));
286dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
287dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return res;
288dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
289dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
290dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     /** {@inheritDoc} */
291dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     public T[] getData() {
292dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        T[] res = buildArray(virtualSize);
293dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        OpenIntToFieldHashMap<T>.Iterator iter = entries.iterator();
294dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        while (iter.hasNext()) {
295dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            iter.advance();
296dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            res[iter.key()] = iter.value();
297dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
298dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return res;
299dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     }
300dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
301dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     /** {@inheritDoc} */
302dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     public int getDimension() {
303dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return virtualSize;
304dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
305dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
306dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     /** {@inheritDoc} */
307dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     public T getEntry(int index) throws MatrixIndexException {
308dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        checkIndex(index);
309dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return entries.get(index);
310dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   }
311dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
312dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     /** {@inheritDoc} */
313dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     public Field<T> getField() {
314dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return field;
315dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
316dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
317dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     /** {@inheritDoc} */
318dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     public FieldVector<T> getSubVector(int index, int n)
319dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            throws MatrixIndexException {
320dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        checkIndex(index);
321dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        checkIndex(index + n - 1);
322dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        SparseFieldVector<T> res = new SparseFieldVector<T>(field,n);
323dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        int end = index + n;
324dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        OpenIntToFieldHashMap<T>.Iterator iter = entries.iterator();
325dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        while (iter.hasNext()) {
326dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            iter.advance();
327dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            int key = iter.key();
328dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (key >= index && key < end) {
329dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                res.setEntry(key - index, iter.value());
330dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
331dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
332dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return res;
333dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
334dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
335dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     /** {@inheritDoc} */
336dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     public FieldVector<T> mapAdd(T d) {
337dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return copy().mapAddToSelf(d);
338dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   }
339dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
340dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     /** {@inheritDoc} */
341dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     public FieldVector<T> mapAddToSelf(T d) {
342dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        for (int i = 0; i < virtualSize; i++) {
343dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            setEntry(i, getEntry(i).add(d));
344dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
345dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return this;
346dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
347dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
348dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     /** {@inheritDoc} */
349dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     public FieldVector<T> mapDivide(T d) {
350dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return copy().mapDivideToSelf(d);
351dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
352dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
353dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     /** {@inheritDoc} */
354dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     public FieldVector<T> mapDivideToSelf(T d) {
355dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        OpenIntToFieldHashMap<T>.Iterator iter = entries.iterator();
356dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        while (iter.hasNext()) {
357dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            iter.advance();
358dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            entries.put(iter.key(), iter.value().divide(d));
359dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
360dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return this;
361dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   }
362dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
363dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     /** {@inheritDoc} */
364dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     public FieldVector<T> mapInv() {
365dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return copy().mapInvToSelf();
366dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   }
367dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
368dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     /** {@inheritDoc} */
369dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     public FieldVector<T> mapInvToSelf() {
370dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        for (int i = 0; i < virtualSize; i++) {
371dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            setEntry(i, field.getOne().divide(getEntry(i)));
372dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
373dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return this;
374dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   }
375dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
376dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     /** {@inheritDoc} */
377dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     public FieldVector<T> mapMultiply(T d) {
378dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return copy().mapMultiplyToSelf(d);
379dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
380dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
381dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     /** {@inheritDoc} */
382dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     public FieldVector<T> mapMultiplyToSelf(T d) {
383dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        OpenIntToFieldHashMap<T>.Iterator iter = entries.iterator();
384dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        while (iter.hasNext()) {
385dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            iter.advance();
386dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            entries.put(iter.key(), iter.value().multiply(d));
387dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
388dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return this;
389dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   }
390dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
391dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     /** {@inheritDoc} */
392dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     public FieldVector<T> mapSubtract(T d) {
393dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return copy().mapSubtractToSelf(d);
394dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
395dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
396dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     /** {@inheritDoc} */
397dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     public FieldVector<T> mapSubtractToSelf(T d) {
398dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return mapAddToSelf(field.getZero().subtract(d));
399dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
400dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
401dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     /**
402dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      * Optimized method to compute outer product when both vectors are sparse.
403dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      * @param v vector with which outer product should be computed
404dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      * @return the square matrix outer product between instance and v
405dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      * @throws IllegalArgumentException if v is not the same size as {@code this}
406dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond      */
407dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public FieldMatrix<T> outerProduct(SparseFieldVector<T> v)
408dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            throws IllegalArgumentException {
409dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        checkVectorDimensions(v.getDimension());
410dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        SparseFieldMatrix<T> res = new SparseFieldMatrix<T>(field, virtualSize, virtualSize);
411dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        OpenIntToFieldHashMap<T>.Iterator iter = entries.iterator();
412dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        while (iter.hasNext()) {
413dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            iter.advance();
414dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            OpenIntToFieldHashMap<T>.Iterator iter2 = v.entries.iterator();
415dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            while (iter2.hasNext()) {
416dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                iter2.advance();
417dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                res.setEntry(iter.key(), iter2.key(), iter.value().multiply(iter2.value()));
418dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
419dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
420dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return res;
421dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
422dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
423dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** {@inheritDoc} */
424dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public FieldMatrix<T> outerProduct(T[] v) throws IllegalArgumentException {
425dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        checkVectorDimensions(v.length);
426dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        FieldMatrix<T> res = new SparseFieldMatrix<T>(field, virtualSize, virtualSize);
427dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        OpenIntToFieldHashMap<T>.Iterator iter = entries.iterator();
428dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        while (iter.hasNext()) {
429dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            iter.advance();
430dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            int row = iter.key();
431dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            FieldElement<T>value = iter.value();
432dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            for (int col = 0; col < virtualSize; col++) {
433dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                res.setEntry(row, col, value.multiply(v[col]));
434dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
435dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
436dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return res;
437dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     }
438dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
439dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** {@inheritDoc} */
440dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public FieldMatrix<T> outerProduct(FieldVector<T> v)
441dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    throws IllegalArgumentException {
442dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if(v instanceof SparseFieldVector<?>)
443dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return outerProduct((SparseFieldVector<T>)v);
444dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        else
445dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return outerProduct(v.toArray());
446dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
447dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
448dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** {@inheritDoc} */
449dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public FieldVector<T> projection(FieldVector<T> v)
450dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    throws IllegalArgumentException {
451dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        checkVectorDimensions(v.getDimension());
452dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return v.mapMultiply(dotProduct(v).divide(v.dotProduct(v)));
453dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
454dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
455dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** {@inheritDoc} */
456dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public FieldVector<T> projection(T[] v) throws IllegalArgumentException {
457dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        checkVectorDimensions(v.length);
458dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return projection(new SparseFieldVector<T>(field,v));
459dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
460dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
461dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** {@inheritDoc} */
462dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public void set(T value) {
463dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        for (int i = 0; i < virtualSize; i++) {
464dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            setEntry(i, value);
465dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
466dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
467dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
468dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** {@inheritDoc} */
469dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public void setEntry(int index, T value) throws MatrixIndexException {
470dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        checkIndex(index);
471dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        entries.put(index, value);
472dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond   }
473dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
474dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** {@inheritDoc} */
475dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public void setSubVector(int index, FieldVector<T> v)
476dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            throws MatrixIndexException {
477dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        checkIndex(index);
478dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        checkIndex(index + v.getDimension() - 1);
479dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        setSubVector(index, v.getData());
480dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
481dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
482dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** {@inheritDoc} */
483dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public void setSubVector(int index, T[] v) throws MatrixIndexException {
484dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        checkIndex(index);
485dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        checkIndex(index + v.length - 1);
486dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        for (int i = 0; i < v.length; i++) {
487dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            setEntry(i + index, v[i]);
488dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
489dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
490dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
491dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
492dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
493dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Optimized method to subtract SparseRealVectors.
494dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param v The vector to subtract from <code>this</code>
495dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return The difference of <code>this</code> and <code>v</code>
496dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @throws IllegalArgumentException If the dimensions don't match
497dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
498dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public SparseFieldVector<T> subtract(SparseFieldVector<T> v) throws IllegalArgumentException{
499dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        checkVectorDimensions(v.getDimension());
500dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        SparseFieldVector<T> res = (SparseFieldVector<T>)copy();
501dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        OpenIntToFieldHashMap<T>.Iterator iter = v.getEntries().iterator();
502dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        while (iter.hasNext()) {
503dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            iter.advance();
504dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            int key = iter.key();
505dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (entries.containsKey(key)) {
506dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                res.setEntry(key, entries.get(key).subtract(iter.value()));
507dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            } else {
508dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                res.setEntry(key, field.getZero().subtract(iter.value()));
509dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
510dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
511dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return res;
512dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
513dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
514dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** {@inheritDoc} */
515dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public FieldVector<T> subtract(FieldVector<T> v)
516dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond           throws IllegalArgumentException {
517dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if(v instanceof SparseFieldVector<?>)
518dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return subtract((SparseFieldVector<T>)v);
519dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        else
520dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return subtract(v.toArray());
521dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
522dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
523dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** {@inheritDoc} */
524dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public FieldVector<T> subtract(T[] v) throws IllegalArgumentException {
525dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        checkVectorDimensions(v.length);
526dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        SparseFieldVector<T> res = new SparseFieldVector<T>(this);
527dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        for (int i = 0; i < v.length; i++) {
528dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (entries.containsKey(i)) {
529dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                res.setEntry(i, entries.get(i).subtract(v[i]));
530dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            } else {
531dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                res.setEntry(i, field.getZero().subtract(v[i]));
532dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
533dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
534dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return res;
535dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
536dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
537dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** {@inheritDoc} */
538dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public T[] toArray() {
539dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return getData();
540dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
541dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
542dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
543dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Check if an index is valid.
544dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
545dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param index
546dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *            index to check
547dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @exception MatrixIndexException
548dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *                if index is not valid
549dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
550dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private void checkIndex(final int index) throws MatrixIndexException {
551dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (index < 0 || index >= getDimension()) {
552dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            throw new MatrixIndexException(LocalizedFormats.INDEX_OUT_OF_RANGE,
553dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                                           index, 0, getDimension() - 1);
554dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
555dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
556dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
557dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /**
558dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * Check if instance dimension is equal to some expected value.
559dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *
560dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param n
561dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *            expected dimension.
562dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @exception IllegalArgumentException
563dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     *                if the dimension is inconsistent with vector size
564dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
565dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    protected void checkVectorDimensions(int n) throws IllegalArgumentException {
566dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (getDimension() != n) {
567dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            throw MathRuntimeException.createIllegalArgumentException(
568dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    LocalizedFormats.VECTOR_LENGTH_MISMATCH,
569dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                    getDimension(), n);
570dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
571dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
572dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
573dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
574dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** {@inheritDoc} */
575dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public FieldVector<T> add(FieldVector<T> v) throws IllegalArgumentException {
576dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (v instanceof SparseFieldVector<?>) {
577dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return add((SparseFieldVector<T>)v);
578dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else {
579dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return add(v.toArray());
580dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
581dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
582dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
583dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** Build an array of elements.
584dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @param length size of the array to build
585dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     * @return a new array
586dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond     */
587dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    @SuppressWarnings("unchecked") // field is type T
588dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    private T[] buildArray(final int length) {
589dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return (T[]) Array.newInstance(field.getZero().getClass(), length);
590dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
591dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
592dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
593dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** {@inheritDoc} */
594dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    @Override
595dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public int hashCode() {
596dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        final int prime = 31;
597dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        int result = 1;
598dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        result = prime * result + ((field == null) ? 0 : field.hashCode());
599dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        result = prime * result + virtualSize;
600dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        OpenIntToFieldHashMap<T>.Iterator iter = entries.iterator();
601dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        while (iter.hasNext()) {
602dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            iter.advance();
603dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            int temp = iter.value().hashCode();
604dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            result = prime * result + temp;
605dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
606dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return result;
607dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
608dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
609dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
610dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    /** {@inheritDoc} */
611dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    @Override
612dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    public boolean equals(Object obj) {
613dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
614dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (this == obj) {
615dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return true;
616dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
617dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
618dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (!(obj instanceof SparseFieldVector<?>)) {
619dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return false;
620dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
621dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
622dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        @SuppressWarnings("unchecked") // OK, because "else if" check below ensures that
623dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                                       // other must be the same type as this
624dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        SparseFieldVector<T> other = (SparseFieldVector<T>) obj;
625dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (field == null) {
626dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (other.field != null) {
627dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return false;
628dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
629dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        } else if (!field.equals(other.field)) {
630dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return false;
631dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
632dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        if (virtualSize != other.virtualSize) {
633dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            return false;
634dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
635dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
636dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        OpenIntToFieldHashMap<T>.Iterator iter = entries.iterator();
637dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        while (iter.hasNext()) {
638dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            iter.advance();
639dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            T test = other.getEntry(iter.key());
640dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (!test.equals(iter.value())) {
641dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return false;
642dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
643dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
644dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        iter = other.getEntries().iterator();
645dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        while (iter.hasNext()) {
646dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            iter.advance();
647dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            T test = iter.value();
648dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            if (!test.equals(getEntry(iter.key()))) {
649dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond                return false;
650dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond            }
651dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        }
652dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond        return true;
653dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond    }
654dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
655dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
656dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond
657dee0849a9704d532af0b550146cbafbaa6ee1d19Raymond}
658