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