001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.math3.linear;
018
019import java.io.Serializable;
020import java.util.Arrays;
021
022import org.apache.commons.math3.Field;
023import org.apache.commons.math3.FieldElement;
024import org.apache.commons.math3.exception.DimensionMismatchException;
025import org.apache.commons.math3.exception.MathArithmeticException;
026import org.apache.commons.math3.exception.NotPositiveException;
027import org.apache.commons.math3.exception.NullArgumentException;
028import org.apache.commons.math3.exception.NumberIsTooLargeException;
029import org.apache.commons.math3.exception.NumberIsTooSmallException;
030import org.apache.commons.math3.exception.OutOfRangeException;
031import org.apache.commons.math3.exception.ZeroException;
032import org.apache.commons.math3.exception.util.LocalizedFormats;
033import org.apache.commons.math3.util.MathArrays;
034import org.apache.commons.math3.util.MathUtils;
035
036/**
037 * This class implements the {@link FieldVector} interface with a {@link FieldElement} array.
038 * @param <T> the type of the field elements
039 * @since 2.0
040 */
041public class ArrayFieldVector<T extends FieldElement<T>> implements FieldVector<T>, Serializable {
042    /** Serializable version identifier. */
043    private static final long serialVersionUID = 7648186910365927050L;
044
045    /** Entries of the vector. */
046    private T[] data;
047
048    /** Field to which the elements belong. */
049    private final Field<T> field;
050
051    /**
052     * Build a 0-length vector.
053     * Zero-length vectors may be used to initialize construction of vectors
054     * by data gathering. We start with zero-length and use either the {@link
055     * #ArrayFieldVector(ArrayFieldVector, ArrayFieldVector)} constructor
056     * or one of the {@code append} methods ({@link #add(FieldVector)} or
057     * {@link #append(ArrayFieldVector)}) to gather data into this vector.
058     *
059     * @param field field to which the elements belong
060     */
061    public ArrayFieldVector(final Field<T> field) {
062        this(field, 0);
063    }
064
065    /**
066     * Construct a vector of zeroes.
067     *
068     * @param field Field to which the elements belong.
069     * @param size Size of the vector.
070     */
071    public ArrayFieldVector(Field<T> field, int size) {
072        this.field = field;
073        this.data  = MathArrays.buildArray(field, size);
074    }
075
076    /**
077     * Construct a vector with preset values.
078     *
079     * @param size Size of the vector.
080     * @param preset All entries will be set with this value.
081     */
082    public ArrayFieldVector(int size, T preset) {
083        this(preset.getField(), size);
084        Arrays.fill(data, preset);
085    }
086
087    /**
088     * Construct a vector from an array, copying the input array.
089     * This constructor needs a non-empty {@code d} array to retrieve
090     * the field from its first element. This implies it cannot build
091     * 0 length vectors. To build vectors from any size, one should
092     * use the {@link #ArrayFieldVector(Field, FieldElement[])} constructor.
093     *
094     * @param d Array.
095     * @throws NullArgumentException if {@code d} is {@code null}.
096     * @throws ZeroException if {@code d} is empty.
097     * @see #ArrayFieldVector(Field, FieldElement[])
098     */
099    public ArrayFieldVector(T[] d)
100            throws NullArgumentException, ZeroException {
101        MathUtils.checkNotNull(d);
102        try {
103            field = d[0].getField();
104            data = d.clone();
105        } catch (ArrayIndexOutOfBoundsException e) {
106            throw new ZeroException(LocalizedFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT);
107        }
108    }
109
110    /**
111     * Construct a vector from an array, copying the input array.
112     *
113     * @param field Field to which the elements belong.
114     * @param d Array.
115     * @throws NullArgumentException if {@code d} is {@code null}.
116     * @see #ArrayFieldVector(FieldElement[])
117     */
118    public ArrayFieldVector(Field<T> field, T[] d)
119            throws NullArgumentException {
120        MathUtils.checkNotNull(d);
121        this.field = field;
122        data = d.clone();
123    }
124
125    /**
126     * Create a new ArrayFieldVector using the input array as the underlying
127     * data array.
128     * If an array is built specially in order to be embedded in a
129     * ArrayFieldVector and not used directly, the {@code copyArray} may be
130     * set to {@code false}. This will prevent the copying and improve
131     * performance as no new array will be built and no data will be copied.
132     * This constructor needs a non-empty {@code d} array to retrieve
133     * the field from its first element. This implies it cannot build
134     * 0 length vectors. To build vectors from any size, one should
135     * use the {@link #ArrayFieldVector(Field, FieldElement[], boolean)}
136     * constructor.
137     *
138     * @param d Data for the new vector.
139     * @param copyArray If {@code true}, the input array will be copied,
140     * otherwise it will be referenced.
141     * @throws NullArgumentException if {@code d} is {@code null}.
142     * @throws ZeroException if {@code d} is empty.
143     * @see #ArrayFieldVector(FieldElement[])
144     * @see #ArrayFieldVector(Field, FieldElement[], boolean)
145     */
146    public ArrayFieldVector(T[] d, boolean copyArray)
147            throws NullArgumentException, ZeroException {
148        MathUtils.checkNotNull(d);
149        if (d.length == 0) {
150            throw new ZeroException(LocalizedFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT);
151        }
152        field = d[0].getField();
153        data = copyArray ? d.clone() : d;
154    }
155
156    /**
157     * Create a new ArrayFieldVector using the input array as the underlying
158     * data array.
159     * If an array is built specially in order to be embedded in a
160     * ArrayFieldVector and not used directly, the {@code copyArray} may be
161     * set to {@code false}. This will prevent the copying and improve
162     * performance as no new array will be built and no data will be copied.
163     *
164     * @param field Field to which the elements belong.
165     * @param d Data for the new vector.
166     * @param copyArray If {@code true}, the input array will be copied,
167     * otherwise it will be referenced.
168     * @throws NullArgumentException if {@code d} is {@code null}.
169     * @see #ArrayFieldVector(FieldElement[], boolean)
170     */
171    public ArrayFieldVector(Field<T> field, T[] d, boolean copyArray)
172            throws NullArgumentException {
173        MathUtils.checkNotNull(d);
174        this.field = field;
175        data = copyArray ? d.clone() :  d;
176    }
177
178    /**
179     * Construct a vector from part of a array.
180     *
181     * @param d Array.
182     * @param pos Position of the first entry.
183     * @param size Number of entries to copy.
184     * @throws NullArgumentException if {@code d} is {@code null}.
185     * @throws NumberIsTooLargeException if the size of {@code d} is less
186     * than {@code pos + size}.
187     */
188    public ArrayFieldVector(T[] d, int pos, int size)
189            throws NullArgumentException, NumberIsTooLargeException {
190        MathUtils.checkNotNull(d);
191        if (d.length < pos + size) {
192            throw new NumberIsTooLargeException(pos + size, d.length, true);
193        }
194        field = d[0].getField();
195        data = MathArrays.buildArray(field, size);
196        System.arraycopy(d, pos, data, 0, size);
197    }
198
199    /**
200     * Construct a vector from part of a array.
201     *
202     * @param field Field to which the elements belong.
203     * @param d Array.
204     * @param pos Position of the first entry.
205     * @param size Number of entries to copy.
206     * @throws NullArgumentException if {@code d} is {@code null}.
207     * @throws NumberIsTooLargeException if the size of {@code d} is less
208     * than {@code pos + size}.
209     */
210    public ArrayFieldVector(Field<T> field, T[] d, int pos, int size)
211            throws NullArgumentException, NumberIsTooLargeException {
212        MathUtils.checkNotNull(d);
213        if (d.length < pos + size) {
214            throw new NumberIsTooLargeException(pos + size, d.length, true);
215        }
216        this.field = field;
217        data = MathArrays.buildArray(field, size);
218        System.arraycopy(d, pos, data, 0, size);
219    }
220
221    /**
222     * Construct a vector from another vector, using a deep copy.
223     *
224     * @param v Vector to copy.
225     * @throws NullArgumentException if {@code v} is {@code null}.
226     */
227    public ArrayFieldVector(FieldVector<T> v)
228            throws NullArgumentException {
229        MathUtils.checkNotNull(v);
230        field = v.getField();
231        data = MathArrays.buildArray(field, v.getDimension());
232        for (int i = 0; i < data.length; ++i) {
233            data[i] = v.getEntry(i);
234        }
235    }
236
237    /**
238     * Construct a vector from another vector, using a deep copy.
239     *
240     * @param v Vector to copy.
241     * @throws NullArgumentException if {@code v} is {@code null}.
242     */
243    public ArrayFieldVector(ArrayFieldVector<T> v)
244            throws NullArgumentException {
245        MathUtils.checkNotNull(v);
246        field = v.getField();
247        data = v.data.clone();
248    }
249
250    /**
251     * Construct a vector from another vector.
252     *
253     * @param v Vector to copy.
254     * @param deep If {@code true} perform a deep copy, otherwise perform
255     * a shallow copy
256     * @throws NullArgumentException if {@code v} is {@code null}.
257     */
258    public ArrayFieldVector(ArrayFieldVector<T> v, boolean deep)
259            throws NullArgumentException {
260        MathUtils.checkNotNull(v);
261        field = v.getField();
262        data = deep ? v.data.clone() : v.data;
263    }
264
265    /**
266     * Construct a vector by appending one vector to another vector.
267     *
268     * @param v1 First vector (will be put in front of the new vector).
269     * @param v2 Second vector (will be put at back of the new vector).
270     * @throws NullArgumentException if {@code v1} or {@code v2} is
271     * {@code null}.
272     * @deprecated as of 3.2, replaced by {@link #ArrayFieldVector(FieldVector, FieldVector)}
273     */
274    @Deprecated
275    public ArrayFieldVector(ArrayFieldVector<T> v1, ArrayFieldVector<T> v2)
276            throws NullArgumentException {
277        this((FieldVector<T>) v1, (FieldVector<T>) v2);
278    }
279
280    /**
281     * Construct a vector by appending one vector to another vector.
282     *
283     * @param v1 First vector (will be put in front of the new vector).
284     * @param v2 Second vector (will be put at back of the new vector).
285     * @throws NullArgumentException if {@code v1} or {@code v2} is
286     * {@code null}.
287     * @since 3.2
288     */
289    public ArrayFieldVector(FieldVector<T> v1, FieldVector<T> v2)
290            throws NullArgumentException {
291        MathUtils.checkNotNull(v1);
292        MathUtils.checkNotNull(v2);
293        field = v1.getField();
294        final T[] v1Data =
295                (v1 instanceof ArrayFieldVector) ? ((ArrayFieldVector<T>) v1).data : v1.toArray();
296        final T[] v2Data =
297                (v2 instanceof ArrayFieldVector) ? ((ArrayFieldVector<T>) v2).data : v2.toArray();
298        data = MathArrays.buildArray(field, v1Data.length + v2Data.length);
299        System.arraycopy(v1Data, 0, data, 0, v1Data.length);
300        System.arraycopy(v2Data, 0, data, v1Data.length, v2Data.length);
301    }
302
303    /**
304     * Construct a vector by appending one vector to another vector.
305     *
306     * @param v1 First vector (will be put in front of the new vector).
307     * @param v2 Second vector (will be put at back of the new vector).
308     * @throws NullArgumentException if {@code v1} or {@code v2} is
309     * {@code null}.
310     * @deprecated as of 3.2, replaced by {@link #ArrayFieldVector(FieldVector, FieldElement[])}
311     */
312    @Deprecated
313    public ArrayFieldVector(ArrayFieldVector<T> v1, T[] v2)
314            throws NullArgumentException {
315        this((FieldVector<T>) v1, v2);
316    }
317
318    /**
319     * Construct a vector by appending one vector to another vector.
320     *
321     * @param v1 First vector (will be put in front of the new vector).
322     * @param v2 Second vector (will be put at back of the new vector).
323     * @throws NullArgumentException if {@code v1} or {@code v2} is
324     * {@code null}.
325     * @since 3.2
326     */
327    public ArrayFieldVector(FieldVector<T> v1, T[] v2)
328            throws NullArgumentException {
329        MathUtils.checkNotNull(v1);
330        MathUtils.checkNotNull(v2);
331        field = v1.getField();
332        final T[] v1Data =
333                (v1 instanceof ArrayFieldVector) ? ((ArrayFieldVector<T>) v1).data : v1.toArray();
334        data = MathArrays.buildArray(field, v1Data.length + v2.length);
335        System.arraycopy(v1Data, 0, data, 0, v1Data.length);
336        System.arraycopy(v2, 0, data, v1Data.length, v2.length);
337    }
338
339    /**
340     * Construct a vector by appending one vector to another vector.
341     *
342     * @param v1 First vector (will be put in front of the new vector).
343     * @param v2 Second vector (will be put at back of the new vector).
344     * @throws NullArgumentException if {@code v1} or {@code v2} is
345     * {@code null}.
346     * @deprecated as of 3.2, replaced by {@link #ArrayFieldVector(FieldElement[], FieldVector)}
347     */
348    @Deprecated
349    public ArrayFieldVector(T[] v1, ArrayFieldVector<T> v2)
350            throws NullArgumentException {
351        this(v1, (FieldVector<T>) v2);
352    }
353
354    /**
355     * Construct a vector by appending one vector to another vector.
356     *
357     * @param v1 First vector (will be put in front of the new vector).
358     * @param v2 Second vector (will be put at back of the new vector).
359     * @throws NullArgumentException if {@code v1} or {@code v2} is
360     * {@code null}.
361     * @since 3.2
362     */
363    public ArrayFieldVector(T[] v1, FieldVector<T> v2)
364            throws NullArgumentException {
365        MathUtils.checkNotNull(v1);
366        MathUtils.checkNotNull(v2);
367        field = v2.getField();
368        final T[] v2Data =
369                (v2 instanceof ArrayFieldVector) ? ((ArrayFieldVector<T>) v2).data : v2.toArray();
370        data = MathArrays.buildArray(field, v1.length + v2Data.length);
371        System.arraycopy(v1, 0, data, 0, v1.length);
372        System.arraycopy(v2Data, 0, data, v1.length, v2Data.length);
373    }
374
375    /**
376     * Construct a vector by appending one vector to another vector.
377     * This constructor needs at least one non-empty array to retrieve
378     * the field from its first element. This implies it cannot build
379     * 0 length vectors. To build vectors from any size, one should
380     * use the {@link #ArrayFieldVector(Field, FieldElement[], FieldElement[])}
381     * constructor.
382     *
383     * @param v1 First vector (will be put in front of the new vector).
384     * @param v2 Second vector (will be put at back of the new vector).
385     * @throws NullArgumentException if {@code v1} or {@code v2} is
386     * {@code null}.
387     * @throws ZeroException if both arrays are empty.
388     * @see #ArrayFieldVector(Field, FieldElement[], FieldElement[])
389     */
390    public ArrayFieldVector(T[] v1, T[] v2)
391            throws NullArgumentException, ZeroException {
392        MathUtils.checkNotNull(v1);
393        MathUtils.checkNotNull(v2);
394        if (v1.length + v2.length == 0) {
395            throw new ZeroException(LocalizedFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT);
396        }
397        data = MathArrays.buildArray(v1[0].getField(), v1.length + v2.length);
398        System.arraycopy(v1, 0, data, 0, v1.length);
399        System.arraycopy(v2, 0, data, v1.length, v2.length);
400        field = data[0].getField();
401    }
402
403    /**
404     * Construct a vector by appending one vector to another vector.
405     *
406     * @param field Field to which the elements belong.
407     * @param v1 First vector (will be put in front of the new vector).
408     * @param v2 Second vector (will be put at back of the new vector).
409     * @throws NullArgumentException if {@code v1} or {@code v2} is
410     * {@code null}.
411     * @throws ZeroException if both arrays are empty.
412     * @see #ArrayFieldVector(FieldElement[], FieldElement[])
413     */
414    public ArrayFieldVector(Field<T> field, T[] v1, T[] v2)
415            throws NullArgumentException, ZeroException {
416        MathUtils.checkNotNull(v1);
417        MathUtils.checkNotNull(v2);
418        if (v1.length + v2.length == 0) {
419            throw new ZeroException(LocalizedFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT);
420        }
421        data = MathArrays.buildArray(field, v1.length + v2.length);
422        System.arraycopy(v1, 0, data, 0, v1.length);
423        System.arraycopy(v2, 0, data, v1.length, v2.length);
424        this.field = field;
425    }
426
427    /** {@inheritDoc} */
428    public Field<T> getField() {
429        return field;
430    }
431
432    /** {@inheritDoc} */
433    public FieldVector<T> copy() {
434        return new ArrayFieldVector<T>(this, true);
435    }
436
437    /** {@inheritDoc} */
438    public FieldVector<T> add(FieldVector<T> v)
439        throws DimensionMismatchException {
440        try {
441            return add((ArrayFieldVector<T>) v);
442        } catch (ClassCastException cce) {
443            checkVectorDimensions(v);
444            T[] out = MathArrays.buildArray(field, data.length);
445            for (int i = 0; i < data.length; i++) {
446                out[i] = data[i].add(v.getEntry(i));
447            }
448            return new ArrayFieldVector<T>(field, out, false);
449        }
450    }
451
452    /**
453     * Compute the sum of {@code this} and {@code v}.
454     * @param v vector to be added
455     * @return {@code this + v}
456     * @throws DimensionMismatchException if {@code v} is not the same size as
457     * {@code this}
458     */
459    public ArrayFieldVector<T> add(ArrayFieldVector<T> v)
460        throws DimensionMismatchException {
461        checkVectorDimensions(v.data.length);
462        T[] out = MathArrays.buildArray(field, data.length);
463        for (int i = 0; i < data.length; i++) {
464            out[i] = data[i].add(v.data[i]);
465        }
466        return new ArrayFieldVector<T>(field, out, false);
467    }
468
469    /** {@inheritDoc} */
470    public FieldVector<T> subtract(FieldVector<T> v)
471        throws DimensionMismatchException {
472        try {
473            return subtract((ArrayFieldVector<T>) v);
474        } catch (ClassCastException cce) {
475            checkVectorDimensions(v);
476            T[] out = MathArrays.buildArray(field, data.length);
477            for (int i = 0; i < data.length; i++) {
478                out[i] = data[i].subtract(v.getEntry(i));
479            }
480            return new ArrayFieldVector<T>(field, out, false);
481        }
482    }
483
484    /**
485     * Compute {@code this} minus {@code v}.
486     * @param v vector to be subtracted
487     * @return {@code this - v}
488     * @throws DimensionMismatchException if {@code v} is not the same size as
489     * {@code this}
490     */
491    public ArrayFieldVector<T> subtract(ArrayFieldVector<T> v)
492        throws DimensionMismatchException {
493        checkVectorDimensions(v.data.length);
494        T[] out = MathArrays.buildArray(field, data.length);
495        for (int i = 0; i < data.length; i++) {
496            out[i] = data[i].subtract(v.data[i]);
497        }
498        return new ArrayFieldVector<T>(field, out, false);
499    }
500
501    /** {@inheritDoc} */
502    public FieldVector<T> mapAdd(T d) throws NullArgumentException {
503        T[] out = MathArrays.buildArray(field, data.length);
504        for (int i = 0; i < data.length; i++) {
505            out[i] = data[i].add(d);
506        }
507        return new ArrayFieldVector<T>(field, out, false);
508    }
509
510    /** {@inheritDoc} */
511    public FieldVector<T> mapAddToSelf(T d) throws NullArgumentException {
512        for (int i = 0; i < data.length; i++) {
513            data[i] = data[i].add(d);
514        }
515        return this;
516    }
517
518    /** {@inheritDoc} */
519    public FieldVector<T> mapSubtract(T d) throws NullArgumentException {
520        T[] out = MathArrays.buildArray(field, data.length);
521        for (int i = 0; i < data.length; i++) {
522            out[i] = data[i].subtract(d);
523        }
524        return new ArrayFieldVector<T>(field, out, false);
525    }
526
527    /** {@inheritDoc} */
528    public FieldVector<T> mapSubtractToSelf(T d) throws NullArgumentException {
529        for (int i = 0; i < data.length; i++) {
530            data[i] = data[i].subtract(d);
531        }
532        return this;
533    }
534
535    /** {@inheritDoc} */
536    public FieldVector<T> mapMultiply(T d) throws NullArgumentException {
537        T[] out = MathArrays.buildArray(field, data.length);
538        for (int i = 0; i < data.length; i++) {
539            out[i] = data[i].multiply(d);
540        }
541        return new ArrayFieldVector<T>(field, out, false);
542    }
543
544    /** {@inheritDoc} */
545    public FieldVector<T> mapMultiplyToSelf(T d) throws NullArgumentException {
546        for (int i = 0; i < data.length; i++) {
547            data[i] = data[i].multiply(d);
548        }
549        return this;
550    }
551
552    /** {@inheritDoc} */
553    public FieldVector<T> mapDivide(T d)
554        throws NullArgumentException, MathArithmeticException {
555        MathUtils.checkNotNull(d);
556        T[] out = MathArrays.buildArray(field, data.length);
557        for (int i = 0; i < data.length; i++) {
558            out[i] = data[i].divide(d);
559        }
560        return new ArrayFieldVector<T>(field, out, false);
561    }
562
563    /** {@inheritDoc} */
564    public FieldVector<T> mapDivideToSelf(T d)
565        throws NullArgumentException, MathArithmeticException {
566        MathUtils.checkNotNull(d);
567        for (int i = 0; i < data.length; i++) {
568            data[i] = data[i].divide(d);
569        }
570        return this;
571    }
572
573    /** {@inheritDoc} */
574    public FieldVector<T> mapInv() throws MathArithmeticException {
575        T[] out = MathArrays.buildArray(field, data.length);
576        final T one = field.getOne();
577        for (int i = 0; i < data.length; i++) {
578            try {
579                out[i] = one.divide(data[i]);
580            } catch (final MathArithmeticException e) {
581                throw new MathArithmeticException(LocalizedFormats.INDEX, i);
582            }
583        }
584        return new ArrayFieldVector<T>(field, out, false);
585    }
586
587    /** {@inheritDoc} */
588    public FieldVector<T> mapInvToSelf() throws MathArithmeticException {
589        final T one = field.getOne();
590        for (int i = 0; i < data.length; i++) {
591            try {
592                data[i] = one.divide(data[i]);
593            } catch (final MathArithmeticException e) {
594                throw new MathArithmeticException(LocalizedFormats.INDEX, i);
595            }
596        }
597        return this;
598    }
599
600    /** {@inheritDoc} */
601    public FieldVector<T> ebeMultiply(FieldVector<T> v)
602        throws DimensionMismatchException {
603        try {
604            return ebeMultiply((ArrayFieldVector<T>) v);
605        } catch (ClassCastException cce) {
606            checkVectorDimensions(v);
607            T[] out = MathArrays.buildArray(field, data.length);
608            for (int i = 0; i < data.length; i++) {
609                out[i] = data[i].multiply(v.getEntry(i));
610            }
611            return new ArrayFieldVector<T>(field, out, false);
612        }
613    }
614
615    /**
616     * Element-by-element multiplication.
617     * @param v vector by which instance elements must be multiplied
618     * @return a vector containing {@code this[i] * v[i]} for all {@code i}
619     * @throws DimensionMismatchException if {@code v} is not the same size as
620     * {@code this}
621     */
622    public ArrayFieldVector<T> ebeMultiply(ArrayFieldVector<T> v)
623        throws DimensionMismatchException {
624        checkVectorDimensions(v.data.length);
625        T[] out = MathArrays.buildArray(field, data.length);
626        for (int i = 0; i < data.length; i++) {
627            out[i] = data[i].multiply(v.data[i]);
628        }
629        return new ArrayFieldVector<T>(field, out, false);
630    }
631
632    /** {@inheritDoc} */
633    public FieldVector<T> ebeDivide(FieldVector<T> v)
634        throws DimensionMismatchException, MathArithmeticException {
635        try {
636            return ebeDivide((ArrayFieldVector<T>) v);
637        } catch (ClassCastException cce) {
638            checkVectorDimensions(v);
639            T[] out = MathArrays.buildArray(field, data.length);
640            for (int i = 0; i < data.length; i++) {
641                try {
642                    out[i] = data[i].divide(v.getEntry(i));
643                } catch (final MathArithmeticException e) {
644                    throw new MathArithmeticException(LocalizedFormats.INDEX, i);
645                }
646            }
647            return new ArrayFieldVector<T>(field, out, false);
648        }
649    }
650
651    /**
652     * Element-by-element division.
653     * @param v vector by which instance elements must be divided
654     * @return a vector containing {@code this[i] / v[i]} for all {@code i}
655     * @throws DimensionMismatchException if {@code v} is not the same size as
656     * {@code this}
657     * @throws MathArithmeticException if one entry of {@code v} is zero.
658     */
659    public ArrayFieldVector<T> ebeDivide(ArrayFieldVector<T> v)
660        throws DimensionMismatchException, MathArithmeticException {
661        checkVectorDimensions(v.data.length);
662        T[] out = MathArrays.buildArray(field, data.length);
663        for (int i = 0; i < data.length; i++) {
664            try {
665                out[i] = data[i].divide(v.data[i]);
666            } catch (final MathArithmeticException e) {
667                throw new MathArithmeticException(LocalizedFormats.INDEX, i);
668            }
669        }
670        return new ArrayFieldVector<T>(field, out, false);
671    }
672
673    /** {@inheritDoc} */
674    public T[] getData() {
675        return data.clone();
676    }
677
678    /**
679     * Returns a reference to the underlying data array.
680     * <p>Does not make a fresh copy of the underlying data.</p>
681     * @return array of entries
682     */
683    public T[] getDataRef() {
684        return data;
685    }
686
687    /** {@inheritDoc} */
688    public T dotProduct(FieldVector<T> v)
689        throws DimensionMismatchException {
690        try {
691            return dotProduct((ArrayFieldVector<T>) v);
692        } catch (ClassCastException cce) {
693            checkVectorDimensions(v);
694            T dot = field.getZero();
695            for (int i = 0; i < data.length; i++) {
696                dot = dot.add(data[i].multiply(v.getEntry(i)));
697            }
698            return dot;
699        }
700    }
701
702    /**
703     * Compute the dot product.
704     * @param v vector with which dot product should be computed
705     * @return the scalar dot product of {@code this} and {@code v}
706     * @throws DimensionMismatchException if {@code v} is not the same size as
707     * {@code this}
708     */
709    public T dotProduct(ArrayFieldVector<T> v)
710        throws DimensionMismatchException {
711        checkVectorDimensions(v.data.length);
712        T dot = field.getZero();
713        for (int i = 0; i < data.length; i++) {
714            dot = dot.add(data[i].multiply(v.data[i]));
715        }
716        return dot;
717    }
718
719    /** {@inheritDoc} */
720    public FieldVector<T> projection(FieldVector<T> v)
721        throws DimensionMismatchException, MathArithmeticException {
722        return v.mapMultiply(dotProduct(v).divide(v.dotProduct(v)));
723    }
724
725    /** Find the orthogonal projection of this vector onto another vector.
726     * @param v vector onto which {@code this} must be projected
727     * @return projection of {@code this} onto {@code v}
728     * @throws DimensionMismatchException if {@code v} is not the same size as
729     * {@code this}
730     * @throws MathArithmeticException if {@code v} is the null vector.
731     */
732    public ArrayFieldVector<T> projection(ArrayFieldVector<T> v)
733        throws DimensionMismatchException, MathArithmeticException {
734        return (ArrayFieldVector<T>) v.mapMultiply(dotProduct(v).divide(v.dotProduct(v)));
735    }
736
737    /** {@inheritDoc} */
738    public FieldMatrix<T> outerProduct(FieldVector<T> v) {
739        try {
740            return outerProduct((ArrayFieldVector<T>) v);
741        } catch (ClassCastException cce) {
742            final int m = data.length;
743            final int n = v.getDimension();
744            final FieldMatrix<T> out = new Array2DRowFieldMatrix<T>(field, m, n);
745            for (int i = 0; i < m; i++) {
746                for (int j = 0; j < n; j++) {
747                    out.setEntry(i, j, data[i].multiply(v.getEntry(j)));
748                }
749            }
750            return out;
751        }
752    }
753
754    /**
755     * Compute the outer product.
756     * @param v vector with which outer product should be computed
757     * @return the matrix outer product between instance and v
758     */
759    public FieldMatrix<T> outerProduct(ArrayFieldVector<T> v) {
760        final int m = data.length;
761        final int n = v.data.length;
762        final FieldMatrix<T> out = new Array2DRowFieldMatrix<T>(field, m, n);
763        for (int i = 0; i < m; i++) {
764            for (int j = 0; j < n; j++) {
765                out.setEntry(i, j, data[i].multiply(v.data[j]));
766            }
767        }
768        return out;
769    }
770
771    /** {@inheritDoc} */
772    public T getEntry(int index) {
773        return data[index];
774    }
775
776    /** {@inheritDoc} */
777    public int getDimension() {
778        return data.length;
779    }
780
781    /** {@inheritDoc} */
782    public FieldVector<T> append(FieldVector<T> v) {
783        try {
784            return append((ArrayFieldVector<T>) v);
785        } catch (ClassCastException cce) {
786            return new ArrayFieldVector<T>(this,new ArrayFieldVector<T>(v));
787        }
788    }
789
790    /**
791     * Construct a vector by appending a vector to this vector.
792     * @param v vector to append to this one.
793     * @return a new vector
794     */
795    public ArrayFieldVector<T> append(ArrayFieldVector<T> v) {
796        return new ArrayFieldVector<T>(this, v);
797    }
798
799    /** {@inheritDoc} */
800    public FieldVector<T> append(T in) {
801        final T[] out = MathArrays.buildArray(field, data.length + 1);
802        System.arraycopy(data, 0, out, 0, data.length);
803        out[data.length] = in;
804        return new ArrayFieldVector<T>(field, out, false);
805    }
806
807    /** {@inheritDoc} */
808    public FieldVector<T> getSubVector(int index, int n)
809        throws OutOfRangeException, NotPositiveException {
810        if (n < 0) {
811            throw new NotPositiveException(LocalizedFormats.NUMBER_OF_ELEMENTS_SHOULD_BE_POSITIVE, n);
812        }
813        ArrayFieldVector<T> out = new ArrayFieldVector<T>(field, n);
814        try {
815            System.arraycopy(data, index, out.data, 0, n);
816        } catch (IndexOutOfBoundsException e) {
817            checkIndex(index);
818            checkIndex(index + n - 1);
819        }
820        return out;
821    }
822
823    /** {@inheritDoc} */
824    public void setEntry(int index, T value) {
825        try {
826            data[index] = value;
827        } catch (IndexOutOfBoundsException e) {
828            checkIndex(index);
829        }
830    }
831
832    /** {@inheritDoc} */
833    public void setSubVector(int index, FieldVector<T> v) throws OutOfRangeException {
834        try {
835            try {
836                set(index, (ArrayFieldVector<T>) v);
837            } catch (ClassCastException cce) {
838                for (int i = index; i < index + v.getDimension(); ++i) {
839                    data[i] = v.getEntry(i-index);
840                }
841            }
842        } catch (IndexOutOfBoundsException e) {
843            checkIndex(index);
844            checkIndex(index + v.getDimension() - 1);
845        }
846    }
847
848    /**
849     * Set a set of consecutive elements.
850     *
851     * @param index index of first element to be set.
852     * @param v vector containing the values to set.
853     * @throws OutOfRangeException if the index is invalid.
854     */
855    public void set(int index, ArrayFieldVector<T> v) throws OutOfRangeException {
856        try {
857            System.arraycopy(v.data, 0, data, index, v.data.length);
858        } catch (IndexOutOfBoundsException e) {
859            checkIndex(index);
860            checkIndex(index + v.data.length - 1);
861        }
862    }
863
864    /** {@inheritDoc} */
865    public void set(T value) {
866        Arrays.fill(data, value);
867    }
868
869    /** {@inheritDoc} */
870    public T[] toArray(){
871        return data.clone();
872    }
873
874    /**
875     * Check if instance and specified vectors have the same dimension.
876     * @param v vector to compare instance with
877     * @exception DimensionMismatchException if the vectors do not
878     * have the same dimensions
879     */
880    protected void checkVectorDimensions(FieldVector<T> v)
881        throws DimensionMismatchException {
882        checkVectorDimensions(v.getDimension());
883    }
884
885    /**
886     * Check if instance dimension is equal to some expected value.
887     *
888     * @param n Expected dimension.
889     * @throws DimensionMismatchException if the dimension is not equal to the
890     * size of {@code this} vector.
891     */
892    protected void checkVectorDimensions(int n)
893        throws DimensionMismatchException {
894        if (data.length != n) {
895            throw new DimensionMismatchException(data.length, n);
896        }
897    }
898
899    /**
900     * Visits (but does not alter) all entries of this vector in default order
901     * (increasing index).
902     *
903     * @param visitor the visitor to be used to process the entries of this
904     * vector
905     * @return the value returned by {@link FieldVectorPreservingVisitor#end()}
906     * at the end of the walk
907     * @since 3.3
908     */
909    public T walkInDefaultOrder(final FieldVectorPreservingVisitor<T> visitor) {
910        final int dim = getDimension();
911        visitor.start(dim, 0, dim - 1);
912        for (int i = 0; i < dim; i++) {
913            visitor.visit(i, getEntry(i));
914        }
915        return visitor.end();
916    }
917
918    /**
919     * Visits (but does not alter) some entries of this vector in default order
920     * (increasing index).
921     *
922     * @param visitor visitor to be used to process the entries of this vector
923     * @param start the index of the first entry to be visited
924     * @param end the index of the last entry to be visited (inclusive)
925     * @return the value returned by {@link FieldVectorPreservingVisitor#end()}
926     * at the end of the walk
927     * @throws NumberIsTooSmallException if {@code end < start}.
928     * @throws OutOfRangeException if the indices are not valid.
929     * @since 3.3
930     */
931    public T walkInDefaultOrder(final FieldVectorPreservingVisitor<T> visitor,
932                                final int start, final int end)
933        throws NumberIsTooSmallException, OutOfRangeException {
934        checkIndices(start, end);
935        visitor.start(getDimension(), start, end);
936        for (int i = start; i <= end; i++) {
937            visitor.visit(i, getEntry(i));
938        }
939        return visitor.end();
940    }
941
942    /**
943     * Visits (but does not alter) all entries of this vector in optimized
944     * order. The order in which the entries are visited is selected so as to
945     * lead to the most efficient implementation; it might depend on the
946     * concrete implementation of this abstract class.
947     *
948     * @param visitor the visitor to be used to process the entries of this
949     * vector
950     * @return the value returned by {@link FieldVectorPreservingVisitor#end()}
951     * at the end of the walk
952     * @since 3.3
953     */
954    public T walkInOptimizedOrder(final FieldVectorPreservingVisitor<T> visitor) {
955        return walkInDefaultOrder(visitor);
956    }
957
958    /**
959     * Visits (but does not alter) some entries of this vector in optimized
960     * order. The order in which the entries are visited is selected so as to
961     * lead to the most efficient implementation; it might depend on the
962     * concrete implementation of this abstract class.
963     *
964     * @param visitor visitor to be used to process the entries of this vector
965     * @param start the index of the first entry to be visited
966     * @param end the index of the last entry to be visited (inclusive)
967     * @return the value returned by {@link FieldVectorPreservingVisitor#end()}
968     * at the end of the walk
969     * @throws NumberIsTooSmallException if {@code end < start}.
970     * @throws OutOfRangeException if the indices are not valid.
971     * @since 3.3
972     */
973    public T walkInOptimizedOrder(final FieldVectorPreservingVisitor<T> visitor,
974                                  final int start, final int end)
975        throws NumberIsTooSmallException, OutOfRangeException {
976        return walkInDefaultOrder(visitor, start, end);
977    }
978
979    /**
980     * Visits (and possibly alters) all entries of this vector in default order
981     * (increasing index).
982     *
983     * @param visitor the visitor to be used to process and modify the entries
984     * of this vector
985     * @return the value returned by {@link FieldVectorChangingVisitor#end()}
986     * at the end of the walk
987     * @since 3.3
988     */
989    public T walkInDefaultOrder(final FieldVectorChangingVisitor<T> visitor) {
990        final int dim = getDimension();
991        visitor.start(dim, 0, dim - 1);
992        for (int i = 0; i < dim; i++) {
993            setEntry(i, visitor.visit(i, getEntry(i)));
994        }
995        return visitor.end();
996    }
997
998    /**
999     * Visits (and possibly alters) some entries of this vector in default order
1000     * (increasing index).
1001     *
1002     * @param visitor visitor to be used to process the entries of this vector
1003     * @param start the index of the first entry to be visited
1004     * @param end the index of the last entry to be visited (inclusive)
1005     * @return the value returned by {@link FieldVectorChangingVisitor#end()}
1006     * at the end of the walk
1007     * @throws NumberIsTooSmallException if {@code end < start}.
1008     * @throws OutOfRangeException if the indices are not valid.
1009     * @since 3.3
1010     */
1011    public T walkInDefaultOrder(final FieldVectorChangingVisitor<T> visitor,
1012                                final int start, final int end)
1013        throws NumberIsTooSmallException, OutOfRangeException {
1014        checkIndices(start, end);
1015        visitor.start(getDimension(), start, end);
1016        for (int i = start; i <= end; i++) {
1017            setEntry(i, visitor.visit(i, getEntry(i)));
1018        }
1019        return visitor.end();
1020    }
1021
1022    /**
1023     * Visits (and possibly alters) all entries of this vector in optimized
1024     * order. The order in which the entries are visited is selected so as to
1025     * lead to the most efficient implementation; it might depend on the
1026     * concrete implementation of this abstract class.
1027     *
1028     * @param visitor the visitor to be used to process the entries of this
1029     * vector
1030     * @return the value returned by {@link FieldVectorChangingVisitor#end()}
1031     * at the end of the walk
1032     * @since 3.3
1033     */
1034    public T walkInOptimizedOrder(final FieldVectorChangingVisitor<T> visitor) {
1035        return walkInDefaultOrder(visitor);
1036    }
1037
1038    /**
1039     * Visits (and possibly change) some entries of this vector in optimized
1040     * order. The order in which the entries are visited is selected so as to
1041     * lead to the most efficient implementation; it might depend on the
1042     * concrete implementation of this abstract class.
1043     *
1044     * @param visitor visitor to be used to process the entries of this vector
1045     * @param start the index of the first entry to be visited
1046     * @param end the index of the last entry to be visited (inclusive)
1047     * @return the value returned by {@link FieldVectorChangingVisitor#end()}
1048     * at the end of the walk
1049     * @throws NumberIsTooSmallException if {@code end < start}.
1050     * @throws OutOfRangeException if the indices are not valid.
1051     * @since 3.3
1052     */
1053    public T walkInOptimizedOrder(final FieldVectorChangingVisitor<T> visitor,
1054                                  final int start, final int end)
1055        throws NumberIsTooSmallException, OutOfRangeException {
1056        return walkInDefaultOrder(visitor, start, end);
1057    }
1058
1059    /**
1060     * Test for the equality of two vectors.
1061     *
1062     * @param other Object to test for equality.
1063     * @return {@code true} if two vector objects are equal, {@code false}
1064     * otherwise.
1065     */
1066    @Override
1067    public boolean equals(Object other) {
1068        if (this == other) {
1069            return true;
1070        }
1071        if (other == null) {
1072            return false;
1073        }
1074
1075        try {
1076            @SuppressWarnings("unchecked") // May fail, but we ignore ClassCastException
1077                FieldVector<T> rhs = (FieldVector<T>) other;
1078            if (data.length != rhs.getDimension()) {
1079                return false;
1080            }
1081
1082            for (int i = 0; i < data.length; ++i) {
1083                if (!data[i].equals(rhs.getEntry(i))) {
1084                    return false;
1085                }
1086            }
1087            return true;
1088        } catch (ClassCastException ex) {
1089            // ignore exception
1090            return false;
1091        }
1092    }
1093
1094    /**
1095     * Get a hashCode for the real vector.
1096     * <p>All NaN values have the same hash code.</p>
1097     * @return a hash code value for this object
1098     */
1099    @Override
1100    public int hashCode() {
1101        int h = 3542;
1102        for (final T a : data) {
1103            h ^= a.hashCode();
1104        }
1105        return h;
1106    }
1107
1108    /**
1109     * Check if an index is valid.
1110     *
1111     * @param index Index to check.
1112     * @exception OutOfRangeException if the index is not valid.
1113     */
1114    private void checkIndex(final int index) throws OutOfRangeException {
1115        if (index < 0 || index >= getDimension()) {
1116            throw new OutOfRangeException(LocalizedFormats.INDEX,
1117                                          index, 0, getDimension() - 1);
1118        }
1119    }
1120
1121    /**
1122     * Checks that the indices of a subvector are valid.
1123     *
1124     * @param start the index of the first entry of the subvector
1125     * @param end the index of the last entry of the subvector (inclusive)
1126     * @throws OutOfRangeException if {@code start} of {@code end} are not valid
1127     * @throws NumberIsTooSmallException if {@code end < start}
1128     * @since 3.3
1129     */
1130    private void checkIndices(final int start, final int end)
1131        throws NumberIsTooSmallException, OutOfRangeException {
1132        final int dim = getDimension();
1133        if ((start < 0) || (start >= dim)) {
1134            throw new OutOfRangeException(LocalizedFormats.INDEX, start, 0,
1135                                          dim - 1);
1136        }
1137        if ((end < 0) || (end >= dim)) {
1138            throw new OutOfRangeException(LocalizedFormats.INDEX, end, 0,
1139                                          dim - 1);
1140        }
1141        if (end < start) {
1142            throw new NumberIsTooSmallException(LocalizedFormats.INITIAL_ROW_AFTER_FINAL_ROW,
1143                                                end, start, false);
1144        }
1145    }
1146
1147}