View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.math4.legacy.linear;
18  
19  import java.io.Serializable;
20  import java.util.Arrays;
21  
22  import org.apache.commons.math4.legacy.core.Field;
23  import org.apache.commons.math4.legacy.core.FieldElement;
24  import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
25  import org.apache.commons.math4.legacy.exception.MathArithmeticException;
26  import org.apache.commons.math4.legacy.exception.NotPositiveException;
27  import org.apache.commons.math4.legacy.exception.NullArgumentException;
28  import org.apache.commons.math4.legacy.exception.NumberIsTooLargeException;
29  import org.apache.commons.math4.legacy.exception.NumberIsTooSmallException;
30  import org.apache.commons.math4.legacy.exception.OutOfRangeException;
31  import org.apache.commons.math4.legacy.exception.ZeroException;
32  import org.apache.commons.math4.legacy.exception.util.LocalizedFormats;
33  import org.apache.commons.math4.legacy.core.MathArrays;
34  
35  /**
36   * This class implements the {@link FieldVector} interface with a {@link FieldElement} array.
37   * @param <T> the type of the field elements
38   * @since 2.0
39   */
40  public class ArrayFieldVector<T extends FieldElement<T>> implements FieldVector<T>, Serializable {
41      /** Serializable version identifier. */
42      private static final long serialVersionUID = 7648186910365927050L;
43  
44      /** Entries of the vector. */
45      private T[] data;
46  
47      /** Field to which the elements belong. */
48      private final Field<T> field;
49  
50      /**
51       * Build a 0-length vector.
52       * Zero-length vectors may be used to initialize construction of vectors
53       * by data gathering. We start with zero-length and use either the {@link
54       * #ArrayFieldVector(FieldVector, FieldVector)} constructor
55       * or one of the {@code append} methods ({@link #add(FieldVector)} or
56       * {@link #append(ArrayFieldVector)}) to gather data into this vector.
57       *
58       * @param field field to which the elements belong
59       */
60      public ArrayFieldVector(final Field<T> field) {
61          this(field, 0);
62      }
63  
64      /**
65       * Construct a vector of zeroes.
66       *
67       * @param field Field to which the elements belong.
68       * @param size Size of the vector.
69       */
70      public ArrayFieldVector(Field<T> field, int size) {
71          this.field = field;
72          this.data  = MathArrays.buildArray(field, size);
73      }
74  
75      /**
76       * Construct a vector with preset values.
77       *
78       * @param size Size of the vector.
79       * @param preset All entries will be set with this value.
80       */
81      public ArrayFieldVector(int size, T preset) {
82          this(preset.getField(), size);
83          Arrays.fill(data, preset);
84      }
85  
86      /**
87       * Construct a vector from an array, copying the input array.
88       * This constructor needs a non-empty {@code d} array to retrieve
89       * the field from its first element. This implies it cannot build
90       * 0 length vectors. To build vectors from any size, one should
91       * use the {@link #ArrayFieldVector(Field, FieldElement[])} constructor.
92       *
93       * @param d Array.
94       * @throws NullArgumentException if {@code d} is {@code null}.
95       * @throws ZeroException if {@code d} is empty.
96       * @see #ArrayFieldVector(Field, FieldElement[])
97       */
98      public ArrayFieldVector(T[] d)
99              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 }