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    *      https://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  
18  /*
19   * This is not the original file distributed by the Apache Software Foundation
20   * It has been modified by the Hipparchus project
21   */
22  package org.hipparchus.linear;
23  
24  import java.io.Serializable;
25  import java.util.Arrays;
26  
27  import org.hipparchus.Field;
28  import org.hipparchus.FieldElement;
29  import org.hipparchus.exception.LocalizedCoreFormats;
30  import org.hipparchus.exception.MathIllegalArgumentException;
31  import org.hipparchus.exception.MathRuntimeException;
32  import org.hipparchus.exception.NullArgumentException;
33  import org.hipparchus.util.MathArrays;
34  import org.hipparchus.util.MathUtils;
35  
36  /**
37   * This class implements the {@link FieldVector} interface with a {@link FieldElement} array.
38   * @param <T> the type of the field elements
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 MathIllegalArgumentException if {@code d} is empty.
96       * @see #ArrayFieldVector(Field, FieldElement[])
97       */
98      public ArrayFieldVector(T[] d)
99              throws MathIllegalArgumentException, NullArgumentException {
100         MathUtils.checkNotNull(d);
101         try {
102             field = d[0].getField();
103             data = d.clone();
104         } catch (ArrayIndexOutOfBoundsException e) {
105             throw new MathIllegalArgumentException(e, LocalizedCoreFormats.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         MathUtils.checkNotNull(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 MathIllegalArgumentException 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 MathIllegalArgumentException, NullArgumentException {
147         MathUtils.checkNotNull(d);
148         if (d.length == 0) {
149             throw new MathIllegalArgumentException(LocalizedCoreFormats.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         MathUtils.checkNotNull(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 MathIllegalArgumentException 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 MathIllegalArgumentException, NullArgumentException {
189         MathUtils.checkNotNull(d);
190         if (d.length < pos + size) {
191             throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_LARGE,
192                                                    pos + size, d.length);
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 MathIllegalArgumentException 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 MathIllegalArgumentException, NullArgumentException {
212         MathUtils.checkNotNull(d);
213         if (d.length < pos + size) {
214             throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_LARGE,
215                                                    pos + size, d.length);
216         }
217         this.field = field;
218         data = MathArrays.buildArray(field, size);
219         System.arraycopy(d, pos, data, 0, size);
220     }
221 
222     /**
223      * Construct a vector from another vector, using a deep copy.
224      *
225      * @param v Vector to copy.
226      * @throws NullArgumentException if {@code v} is {@code null}.
227      */
228     public ArrayFieldVector(FieldVector<T> v)
229             throws NullArgumentException {
230         MathUtils.checkNotNull(v);
231         field = v.getField();
232         data = MathArrays.buildArray(field, v.getDimension());
233         for (int i = 0; i < data.length; ++i) {
234             data[i] = v.getEntry(i);
235         }
236     }
237 
238     /**
239      * Construct a vector from another vector, using a deep copy.
240      *
241      * @param v Vector to copy.
242      * @throws NullArgumentException if {@code v} is {@code null}.
243      */
244     public ArrayFieldVector(ArrayFieldVector<T> v)
245             throws NullArgumentException {
246         MathUtils.checkNotNull(v);
247         field = v.getField();
248         data = v.data.clone();
249     }
250 
251     /**
252      * Construct a vector from another vector.
253      *
254      * @param v Vector to copy.
255      * @param deep If {@code true} perform a deep copy, otherwise perform
256      * a shallow copy
257      * @throws NullArgumentException if {@code v} is {@code null}.
258      */
259     public ArrayFieldVector(ArrayFieldVector<T> v, boolean deep)
260             throws NullArgumentException {
261         MathUtils.checkNotNull(v);
262         field = v.getField();
263         data = deep ? v.data.clone() : v.data;
264     }
265 
266     /**
267      * Construct a vector by appending one vector to another vector.
268      *
269      * @param v1 First vector (will be put in front of the new vector).
270      * @param v2 Second vector (will be put at back of the new vector).
271      * @throws NullArgumentException if {@code v1} or {@code v2} is
272      * {@code null}.
273      */
274     public ArrayFieldVector(FieldVector<T> v1, FieldVector<T> v2)
275             throws NullArgumentException {
276         MathUtils.checkNotNull(v1);
277         MathUtils.checkNotNull(v2);
278         field = v1.getField();
279         final T[] v1Data =
280                 (v1 instanceof ArrayFieldVector) ? ((ArrayFieldVector<T>) v1).data : v1.toArray();
281         final T[] v2Data =
282                 (v2 instanceof ArrayFieldVector) ? ((ArrayFieldVector<T>) v2).data : v2.toArray();
283         data = MathArrays.buildArray(field, v1Data.length + v2Data.length);
284         System.arraycopy(v1Data, 0, data, 0, v1Data.length);
285         System.arraycopy(v2Data, 0, data, v1Data.length, v2Data.length);
286     }
287 
288     /**
289      * Construct a vector by appending one vector to another vector.
290      *
291      * @param v1 First vector (will be put in front of the new vector).
292      * @param v2 Second vector (will be put at back of the new vector).
293      * @throws NullArgumentException if {@code v1} or {@code v2} is
294      * {@code null}.
295      */
296     public ArrayFieldVector(FieldVector<T> v1, T[] v2)
297             throws NullArgumentException {
298         MathUtils.checkNotNull(v1);
299         MathUtils.checkNotNull(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      */
316     public ArrayFieldVector(T[] v1, FieldVector<T> v2)
317             throws NullArgumentException {
318         MathUtils.checkNotNull(v1);
319         MathUtils.checkNotNull(v2);
320         field = v2.getField();
321         final T[] v2Data =
322                 (v2 instanceof ArrayFieldVector) ? ((ArrayFieldVector<T>) v2).data : v2.toArray();
323         data = MathArrays.buildArray(field, v1.length + v2Data.length);
324         System.arraycopy(v1, 0, data, 0, v1.length);
325         System.arraycopy(v2Data, 0, data, v1.length, v2Data.length);
326     }
327 
328     /**
329      * Construct a vector by appending one vector to another vector.
330      * This constructor needs at least one non-empty array to retrieve
331      * the field from its first element. This implies it cannot build
332      * 0 length vectors. To build vectors from any size, one should
333      * use the {@link #ArrayFieldVector(Field, FieldElement[], FieldElement[])}
334      * constructor.
335      *
336      * @param v1 First vector (will be put in front of the new vector).
337      * @param v2 Second vector (will be put at back of the new vector).
338      * @throws NullArgumentException if {@code v1} or {@code v2} is
339      * {@code null}.
340      * @throws MathIllegalArgumentException if both arrays are empty.
341      * @see #ArrayFieldVector(Field, FieldElement[], FieldElement[])
342      */
343     public ArrayFieldVector(T[] v1, T[] v2)
344             throws MathIllegalArgumentException, NullArgumentException {
345         MathUtils.checkNotNull(v1);
346         MathUtils.checkNotNull(v2);
347         if (v1.length + v2.length == 0) {
348             throw new MathIllegalArgumentException(LocalizedCoreFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT);
349         }
350         data = MathArrays.buildArray(v1[0].getField(), v1.length + v2.length);
351         System.arraycopy(v1, 0, data, 0, v1.length);
352         System.arraycopy(v2, 0, data, v1.length, v2.length);
353         field = data[0].getField();
354     }
355 
356     /**
357      * Construct a vector by appending one vector to another vector.
358      *
359      * @param field Field to which the elements belong.
360      * @param v1 First vector (will be put in front of the new vector).
361      * @param v2 Second vector (will be put at back of the new vector).
362      * @throws NullArgumentException if {@code v1} or {@code v2} is
363      * {@code null}.
364      * @throws MathIllegalArgumentException if both arrays are empty.
365      * @see #ArrayFieldVector(FieldElement[], FieldElement[])
366      */
367     public ArrayFieldVector(Field<T> field, T[] v1, T[] v2)
368             throws MathIllegalArgumentException, NullArgumentException {
369         MathUtils.checkNotNull(v1);
370         MathUtils.checkNotNull(v2);
371         if (v1.length + v2.length == 0) {
372             throw new MathIllegalArgumentException(LocalizedCoreFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT);
373         }
374         data = MathArrays.buildArray(field, v1.length + v2.length);
375         System.arraycopy(v1, 0, data, 0, v1.length);
376         System.arraycopy(v2, 0, data, v1.length, v2.length);
377         this.field = field;
378     }
379 
380     /** {@inheritDoc} */
381     @Override
382     public Field<T> getField() {
383         return field;
384     }
385 
386     /** {@inheritDoc} */
387     @Override
388     public FieldVector<T> copy() {
389         return new ArrayFieldVector<T>(this, true);
390     }
391 
392     /** {@inheritDoc} */
393     @Override
394     public FieldVector<T> add(FieldVector<T> v)
395         throws MathIllegalArgumentException {
396         if (v instanceof ArrayFieldVector) {
397             return add((ArrayFieldVector<T>) v);
398         } else {
399             checkVectorDimensions(v);
400             T[] out = MathArrays.buildArray(field, data.length);
401             for (int i = 0; i < data.length; i++) {
402                 out[i] = data[i].add(v.getEntry(i));
403             }
404             return new ArrayFieldVector<T>(field, out, false);
405         }
406     }
407 
408     /**
409      * Compute the sum of {@code this} and {@code v}.
410      * @param v vector to be added
411      * @return {@code this + v}
412      * @throws MathIllegalArgumentException if {@code v} is not the same size as
413      * {@code this}
414      */
415     public ArrayFieldVector<T> add(ArrayFieldVector<T> v)
416         throws MathIllegalArgumentException {
417         checkVectorDimensions(v.data.length);
418         T[] out = MathArrays.buildArray(field, data.length);
419         for (int i = 0; i < data.length; i++) {
420             out[i] = data[i].add(v.data[i]);
421         }
422         return new ArrayFieldVector<T>(field, out, false);
423     }
424 
425     /** {@inheritDoc} */
426     @Override
427     public FieldVector<T> subtract(FieldVector<T> v)
428         throws MathIllegalArgumentException {
429         if (v instanceof ArrayFieldVector) {
430             return subtract((ArrayFieldVector<T>) v);
431         } else {
432             checkVectorDimensions(v);
433             T[] out = MathArrays.buildArray(field, data.length);
434             for (int i = 0; i < data.length; i++) {
435                 out[i] = data[i].subtract(v.getEntry(i));
436             }
437             return new ArrayFieldVector<T>(field, out, false);
438         }
439     }
440 
441     /**
442      * Compute {@code this} minus {@code v}.
443      * @param v vector to be subtracted
444      * @return {@code this - v}
445      * @throws MathIllegalArgumentException if {@code v} is not the same size as
446      * {@code this}
447      */
448     public ArrayFieldVector<T> subtract(ArrayFieldVector<T> v)
449         throws MathIllegalArgumentException {
450         checkVectorDimensions(v.data.length);
451         T[] out = MathArrays.buildArray(field, data.length);
452         for (int i = 0; i < data.length; i++) {
453             out[i] = data[i].subtract(v.data[i]);
454         }
455         return new ArrayFieldVector<T>(field, out, false);
456     }
457 
458     /** {@inheritDoc} */
459     @Override
460     public FieldVector<T> mapAdd(T d) throws NullArgumentException {
461         T[] out = MathArrays.buildArray(field, data.length);
462         for (int i = 0; i < data.length; i++) {
463             out[i] = data[i].add(d);
464         }
465         return new ArrayFieldVector<T>(field, out, false);
466     }
467 
468     /** {@inheritDoc} */
469     @Override
470     public FieldVector<T> mapAddToSelf(T d) throws NullArgumentException {
471         for (int i = 0; i < data.length; i++) {
472             data[i] = data[i].add(d);
473         }
474         return this;
475     }
476 
477     /** {@inheritDoc} */
478     @Override
479     public FieldVector<T> mapSubtract(T d) throws NullArgumentException {
480         T[] out = MathArrays.buildArray(field, data.length);
481         for (int i = 0; i < data.length; i++) {
482             out[i] = data[i].subtract(d);
483         }
484         return new ArrayFieldVector<T>(field, out, false);
485     }
486 
487     /** {@inheritDoc} */
488     @Override
489     public FieldVector<T> mapSubtractToSelf(T d) throws NullArgumentException {
490         for (int i = 0; i < data.length; i++) {
491             data[i] = data[i].subtract(d);
492         }
493         return this;
494     }
495 
496     /** {@inheritDoc} */
497     @Override
498     public FieldVector<T> mapMultiply(T d) throws NullArgumentException {
499         T[] out = MathArrays.buildArray(field, data.length);
500         for (int i = 0; i < data.length; i++) {
501             out[i] = data[i].multiply(d);
502         }
503         return new ArrayFieldVector<T>(field, out, false);
504     }
505 
506     /** {@inheritDoc} */
507     @Override
508     public FieldVector<T> mapMultiplyToSelf(T d) throws NullArgumentException {
509         for (int i = 0; i < data.length; i++) {
510             data[i] = data[i].multiply(d);
511         }
512         return this;
513     }
514 
515     /** {@inheritDoc} */
516     @Override
517     public FieldVector<T> mapDivide(T d)
518         throws NullArgumentException, MathRuntimeException {
519         MathUtils.checkNotNull(d);
520         T[] out = MathArrays.buildArray(field, data.length);
521         for (int i = 0; i < data.length; i++) {
522             out[i] = data[i].divide(d);
523         }
524         return new ArrayFieldVector<T>(field, out, false);
525     }
526 
527     /** {@inheritDoc} */
528     @Override
529     public FieldVector<T> mapDivideToSelf(T d)
530         throws NullArgumentException, MathRuntimeException {
531         MathUtils.checkNotNull(d);
532         for (int i = 0; i < data.length; i++) {
533             data[i] = data[i].divide(d);
534         }
535         return this;
536     }
537 
538     /** {@inheritDoc} */
539     @Override
540     public FieldVector<T> mapInv() throws MathRuntimeException {
541         T[] out = MathArrays.buildArray(field, data.length);
542         final T one = field.getOne();
543         for (int i = 0; i < data.length; i++) {
544             try {
545                 out[i] = one.divide(data[i]);
546             } catch (final MathRuntimeException e) {
547                 throw new MathRuntimeException(e, LocalizedCoreFormats.INDEX, i);
548             }
549         }
550         return new ArrayFieldVector<T>(field, out, false);
551     }
552 
553     /** {@inheritDoc} */
554     @Override
555     public FieldVector<T> mapInvToSelf() throws MathRuntimeException {
556         final T one = field.getOne();
557         for (int i = 0; i < data.length; i++) {
558             try {
559                 data[i] = one.divide(data[i]);
560             } catch (final MathRuntimeException e) {
561                 throw new MathRuntimeException(e, LocalizedCoreFormats.INDEX, i);
562             }
563         }
564         return this;
565     }
566 
567     /** {@inheritDoc} */
568     @Override
569     public FieldVector<T> ebeMultiply(FieldVector<T> v)
570         throws MathIllegalArgumentException {
571         if (v instanceof ArrayFieldVector) {
572             return ebeMultiply((ArrayFieldVector<T>) v);
573         } else {
574             checkVectorDimensions(v);
575             T[] out = MathArrays.buildArray(field, data.length);
576             for (int i = 0; i < data.length; i++) {
577                 out[i] = data[i].multiply(v.getEntry(i));
578             }
579             return new ArrayFieldVector<T>(field, out, false);
580         }
581     }
582 
583     /**
584      * Element-by-element multiplication.
585      * @param v vector by which instance elements must be multiplied
586      * @return a vector containing {@code this[i] * v[i]} for all {@code i}
587      * @throws MathIllegalArgumentException if {@code v} is not the same size as
588      * {@code this}
589      */
590     public ArrayFieldVector<T> ebeMultiply(ArrayFieldVector<T> v)
591         throws MathIllegalArgumentException {
592         checkVectorDimensions(v.data.length);
593         T[] out = MathArrays.buildArray(field, data.length);
594         for (int i = 0; i < data.length; i++) {
595             out[i] = data[i].multiply(v.data[i]);
596         }
597         return new ArrayFieldVector<T>(field, out, false);
598     }
599 
600     /** {@inheritDoc} */
601     @Override
602     public FieldVector<T> ebeDivide(FieldVector<T> v)
603         throws MathIllegalArgumentException, MathRuntimeException {
604         if (v instanceof ArrayFieldVector) {
605             return ebeDivide((ArrayFieldVector<T>) v);
606         } else {
607             checkVectorDimensions(v);
608             T[] out = MathArrays.buildArray(field, data.length);
609             for (int i = 0; i < data.length; i++) {
610                 try {
611                     out[i] = data[i].divide(v.getEntry(i));
612                 } catch (final MathRuntimeException e) {
613                     throw new MathRuntimeException(e, LocalizedCoreFormats.INDEX, i);
614                 }
615             }
616             return new ArrayFieldVector<T>(field, out, false);
617         }
618     }
619 
620     /**
621      * Element-by-element division.
622      * @param v vector by which instance elements must be divided
623      * @return a vector containing {@code this[i] / v[i]} for all {@code i}
624      * @throws MathIllegalArgumentException if {@code v} is not the same size as
625      * {@code this}
626      * @throws MathRuntimeException if one entry of {@code v} is zero.
627      */
628     public ArrayFieldVector<T> ebeDivide(ArrayFieldVector<T> v)
629         throws MathIllegalArgumentException, MathRuntimeException {
630         checkVectorDimensions(v.data.length);
631         T[] out = MathArrays.buildArray(field, data.length);
632         for (int i = 0; i < data.length; i++) {
633             try {
634                 out[i] = data[i].divide(v.data[i]);
635             } catch (final MathRuntimeException e) {
636                 throw new MathRuntimeException(e, LocalizedCoreFormats.INDEX, i);
637             }
638         }
639         return new ArrayFieldVector<T>(field, out, false);
640     }
641 
642     /**
643      * Returns a reference to the underlying data array.
644      * <p>Does not make a fresh copy of the underlying data.</p>
645      * @return array of entries
646      */
647     public T[] getDataRef() {
648         return data; // NOPMD - returning an internal array is intentional and documented here
649     }
650 
651     /** {@inheritDoc} */
652     @Override
653     public T dotProduct(FieldVector<T> v)
654         throws MathIllegalArgumentException {
655         if (v instanceof ArrayFieldVector) {
656             return dotProduct((ArrayFieldVector<T>) v);
657         } else {
658             checkVectorDimensions(v);
659             T dot = field.getZero();
660             for (int i = 0; i < data.length; i++) {
661                 dot = dot.add(data[i].multiply(v.getEntry(i)));
662             }
663             return dot;
664         }
665     }
666 
667     /**
668      * Compute the dot product.
669      * @param v vector with which dot product should be computed
670      * @return the scalar dot product of {@code this} and {@code v}
671      * @throws MathIllegalArgumentException if {@code v} is not the same size as
672      * {@code this}
673      */
674     public T dotProduct(ArrayFieldVector<T> v)
675         throws MathIllegalArgumentException {
676         checkVectorDimensions(v.data.length);
677         T dot = field.getZero();
678         for (int i = 0; i < data.length; i++) {
679             dot = dot.add(data[i].multiply(v.data[i]));
680         }
681         return dot;
682     }
683 
684     /** {@inheritDoc} */
685     @Override
686     public FieldVector<T> projection(FieldVector<T> v)
687         throws MathIllegalArgumentException, MathRuntimeException {
688         return v.mapMultiply(dotProduct(v).divide(v.dotProduct(v)));
689     }
690 
691     /** Find the orthogonal projection of this vector onto another vector.
692      * @param v vector onto which {@code this} must be projected
693      * @return projection of {@code this} onto {@code v}
694      * @throws MathIllegalArgumentException if {@code v} is not the same size as
695      * {@code this}
696      * @throws MathRuntimeException if {@code v} is the null vector.
697      */
698     public ArrayFieldVector<T> projection(ArrayFieldVector<T> v)
699         throws MathIllegalArgumentException, MathRuntimeException {
700         return (ArrayFieldVector<T>) v.mapMultiply(dotProduct(v).divide(v.dotProduct(v)));
701     }
702 
703     /** {@inheritDoc} */
704     @Override
705     public FieldMatrix<T> outerProduct(FieldVector<T> v) {
706         if (v instanceof ArrayFieldVector) {
707             return outerProduct((ArrayFieldVector<T>) v);
708         } else {
709             final int m = data.length;
710             final int n = v.getDimension();
711             final FieldMatrix<T> out = new Array2DRowFieldMatrix<>(field, m, n);
712             for (int i = 0; i < m; i++) {
713                 for (int j = 0; j < n; j++) {
714                     out.setEntry(i, j, data[i].multiply(v.getEntry(j)));
715                 }
716             }
717             return out;
718         }
719     }
720 
721     /**
722      * Compute the outer product.
723      * @param v vector with which outer product should be computed
724      * @return the matrix outer product between instance and v
725      */
726     public FieldMatrix<T> outerProduct(ArrayFieldVector<T> v) {
727         final int m = data.length;
728         final int n = v.data.length;
729         final FieldMatrix<T> out = new Array2DRowFieldMatrix<>(field, m, n);
730         for (int i = 0; i < m; i++) {
731             for (int j = 0; j < n; j++) {
732                 out.setEntry(i, j, data[i].multiply(v.data[j]));
733             }
734         }
735         return out;
736     }
737 
738     /** {@inheritDoc} */
739     @Override
740     public T getEntry(int index) {
741         return data[index];
742     }
743 
744     /** {@inheritDoc} */
745     @Override
746     public int getDimension() {
747         return data.length;
748     }
749 
750     /** {@inheritDoc} */
751     @Override
752     public FieldVector<T> append(FieldVector<T> v) {
753         if (v instanceof ArrayFieldVector) {
754             return append((ArrayFieldVector<T>) v);
755         } else {
756             return new ArrayFieldVector<T>(this,new ArrayFieldVector<T>(v));
757         }
758     }
759 
760     /**
761      * Construct a vector by appending a vector to this vector.
762      * @param v vector to append to this one.
763      * @return a new vector
764      */
765     public ArrayFieldVector<T> append(ArrayFieldVector<T> v) {
766         return new ArrayFieldVector<T>(this, v);
767     }
768 
769     /** {@inheritDoc} */
770     @Override
771     public FieldVector<T> append(T in) {
772         final T[] out = MathArrays.buildArray(field, data.length + 1);
773         System.arraycopy(data, 0, out, 0, data.length);
774         out[data.length] = in;
775         return new ArrayFieldVector<T>(field, out, false);
776     }
777 
778     /** {@inheritDoc} */
779     @Override
780     public FieldVector<T> getSubVector(int index, int n)
781         throws MathIllegalArgumentException {
782         if (n < 0) {
783             throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_OF_ELEMENTS_SHOULD_BE_POSITIVE, n);
784         }
785         ArrayFieldVector<T> out = new ArrayFieldVector<>(field, n);
786         try {
787             System.arraycopy(data, index, out.data, 0, n);
788         } catch (IndexOutOfBoundsException e) {
789             checkIndex(index);
790             checkIndex(index + n - 1);
791         }
792         return out;
793     }
794 
795     /** {@inheritDoc} */
796     @Override
797     public void setEntry(int index, T value) {
798         try {
799             data[index] = value;
800         } catch (IndexOutOfBoundsException e) {
801             checkIndex(index);
802         }
803     }
804 
805     /** {@inheritDoc} */
806     @Override
807     public void setSubVector(int index, FieldVector<T> v) throws MathIllegalArgumentException {
808         try {
809             if (v instanceof ArrayFieldVector) {
810                 set(index, (ArrayFieldVector<T>) v);
811             } else {
812                 for (int i = index; i < index + v.getDimension(); ++i) {
813                     data[i] = v.getEntry(i-index);
814                 }
815             }
816         } catch (IndexOutOfBoundsException e) {
817             checkIndex(index);
818             checkIndex(index + v.getDimension() - 1);
819         }
820     }
821 
822     /**
823      * Set a set of consecutive elements.
824      *
825      * @param index index of first element to be set.
826      * @param v vector containing the values to set.
827      * @throws MathIllegalArgumentException if the index is invalid.
828      */
829     public void set(int index, ArrayFieldVector<T> v) throws MathIllegalArgumentException {
830         try {
831             System.arraycopy(v.data, 0, data, index, v.data.length);
832         } catch (IndexOutOfBoundsException e) {
833             checkIndex(index);
834             checkIndex(index + v.data.length - 1);
835         }
836     }
837 
838     /** {@inheritDoc} */
839     @Override
840     public void set(T value) {
841         Arrays.fill(data, value);
842     }
843 
844     /** {@inheritDoc} */
845     @Override
846     public T[] toArray(){
847         return data.clone();
848     }
849 
850     /**
851      * Check if instance and specified vectors have the same dimension.
852      * @param v vector to compare instance with
853      * @exception MathIllegalArgumentException if the vectors do not
854      * have the same dimensions
855      */
856     protected void checkVectorDimensions(FieldVector<T> v)
857         throws MathIllegalArgumentException {
858         checkVectorDimensions(v.getDimension());
859     }
860 
861     /**
862      * Check if instance dimension is equal to some expected value.
863      *
864      * @param n Expected dimension.
865      * @throws MathIllegalArgumentException if the dimension is not equal to the
866      * size of {@code this} vector.
867      */
868     protected void checkVectorDimensions(int n)
869         throws MathIllegalArgumentException {
870         if (data.length != n) {
871             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
872                                                    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      */
885     public T walkInDefaultOrder(final FieldVectorPreservingVisitor<T> visitor) {
886         final int dim = getDimension();
887         visitor.start(dim, 0, dim - 1);
888         for (int i = 0; i < dim; i++) {
889             visitor.visit(i, getEntry(i));
890         }
891         return visitor.end();
892     }
893 
894     /**
895      * Visits (but does not alter) some entries of this vector in default order
896      * (increasing index).
897      *
898      * @param visitor visitor to be used to process the entries of this vector
899      * @param start the index of the first entry to be visited
900      * @param end the index of the last entry to be visited (inclusive)
901      * @return the value returned by {@link FieldVectorPreservingVisitor#end()}
902      * at the end of the walk
903      * @throws MathIllegalArgumentException if {@code end < start}.
904      * @throws MathIllegalArgumentException if the indices are not valid.
905      */
906     public T walkInDefaultOrder(final FieldVectorPreservingVisitor<T> visitor,
907                                 final int start, final int end)
908         throws MathIllegalArgumentException {
909         checkIndices(start, end);
910         visitor.start(getDimension(), start, end);
911         for (int i = start; i <= end; i++) {
912             visitor.visit(i, getEntry(i));
913         }
914         return visitor.end();
915     }
916 
917     /**
918      * Visits (but does not alter) all entries of this vector in optimized
919      * order. The order in which the entries are visited is selected so as to
920      * lead to the most efficient implementation; it might depend on the
921      * concrete implementation of this abstract class.
922      *
923      * @param visitor the visitor to be used to process the entries of this
924      * vector
925      * @return the value returned by {@link FieldVectorPreservingVisitor#end()}
926      * at the end of the walk
927      */
928     public T walkInOptimizedOrder(final FieldVectorPreservingVisitor<T> visitor) {
929         return walkInDefaultOrder(visitor);
930     }
931 
932     /**
933      * Visits (but does not alter) some entries of this vector in optimized
934      * order. The order in which the entries are visited is selected so as to
935      * lead to the most efficient implementation; it might depend on the
936      * concrete implementation of this abstract class.
937      *
938      * @param visitor visitor to be used to process the entries of this vector
939      * @param start the index of the first entry to be visited
940      * @param end the index of the last entry to be visited (inclusive)
941      * @return the value returned by {@link FieldVectorPreservingVisitor#end()}
942      * at the end of the walk
943      * @throws MathIllegalArgumentException if {@code end < start}.
944      * @throws MathIllegalArgumentException if the indices are not valid.
945      */
946     public T walkInOptimizedOrder(final FieldVectorPreservingVisitor<T> visitor,
947                                   final int start, final int end)
948         throws MathIllegalArgumentException {
949         return walkInDefaultOrder(visitor, start, end);
950     }
951 
952     /**
953      * Visits (and possibly alters) all entries of this vector in default order
954      * (increasing index).
955      *
956      * @param visitor the visitor to be used to process and modify the entries
957      * of this vector
958      * @return the value returned by {@link FieldVectorChangingVisitor#end()}
959      * at the end of the walk
960      */
961     public T walkInDefaultOrder(final FieldVectorChangingVisitor<T> visitor) {
962         final int dim = getDimension();
963         visitor.start(dim, 0, dim - 1);
964         for (int i = 0; i < dim; i++) {
965             setEntry(i, visitor.visit(i, getEntry(i)));
966         }
967         return visitor.end();
968     }
969 
970     /**
971      * Visits (and possibly alters) some entries of this vector in default order
972      * (increasing index).
973      *
974      * @param visitor visitor to be used to process the entries of this vector
975      * @param start the index of the first entry to be visited
976      * @param end the index of the last entry to be visited (inclusive)
977      * @return the value returned by {@link FieldVectorChangingVisitor#end()}
978      * at the end of the walk
979      * @throws MathIllegalArgumentException if {@code end < start}.
980      * @throws MathIllegalArgumentException if the indices are not valid.
981      */
982     public T walkInDefaultOrder(final FieldVectorChangingVisitor<T> visitor,
983                                 final int start, final int end)
984         throws MathIllegalArgumentException {
985         checkIndices(start, end);
986         visitor.start(getDimension(), start, end);
987         for (int i = start; i <= end; i++) {
988             setEntry(i, visitor.visit(i, getEntry(i)));
989         }
990         return visitor.end();
991     }
992 
993     /**
994      * Visits (and possibly alters) all entries of this vector in optimized
995      * order. The order in which the entries are visited is selected so as to
996      * lead to the most efficient implementation; it might depend on the
997      * concrete implementation of this abstract class.
998      *
999      * @param visitor the visitor to be used to process the entries of this
1000      * vector
1001      * @return the value returned by {@link FieldVectorChangingVisitor#end()}
1002      * at the end of the walk
1003      */
1004     public T walkInOptimizedOrder(final FieldVectorChangingVisitor<T> visitor) {
1005         return walkInDefaultOrder(visitor);
1006     }
1007 
1008     /**
1009      * Visits (and possibly change) some entries of this vector in optimized
1010      * order. The order in which the entries are visited is selected so as to
1011      * lead to the most efficient implementation; it might depend on the
1012      * concrete implementation of this abstract class.
1013      *
1014      * @param visitor visitor to be used to process the entries of this vector
1015      * @param start the index of the first entry to be visited
1016      * @param end the index of the last entry to be visited (inclusive)
1017      * @return the value returned by {@link FieldVectorChangingVisitor#end()}
1018      * at the end of the walk
1019      * @throws MathIllegalArgumentException if {@code end < start}.
1020      * @throws MathIllegalArgumentException if the indices are not valid.
1021      */
1022     public T walkInOptimizedOrder(final FieldVectorChangingVisitor<T> visitor,
1023                                   final int start, final int end)
1024         throws MathIllegalArgumentException {
1025         return walkInDefaultOrder(visitor, start, end);
1026     }
1027     /** {@inheritDoc}
1028      * @since 2.0
1029      */
1030     @Override
1031     public String toString() {
1032         final StringBuilder builder = new StringBuilder();
1033         builder.append('{');
1034         for (int i = 0; i < data.length; ++i) {
1035             if (i > 0) {
1036                 builder.append("; ");
1037             }
1038             builder.append(data[i].toString());
1039         }
1040         builder.append('}');
1041         return builder.toString();
1042     }
1043 
1044     /**
1045      * Test for the equality of two vectors.
1046      *
1047      * @param other Object to test for equality.
1048      * @return {@code true} if two vector objects are equal, {@code false}
1049      * otherwise.
1050      */
1051     @Override
1052     public boolean equals(Object other) {
1053         if (this == other) {
1054             return true;
1055         }
1056         if (other == null) {
1057             return false;
1058         }
1059 
1060         try {
1061             @SuppressWarnings("unchecked") // May fail, but we ignore ClassCastException
1062             FieldVector<T> rhs = (FieldVector<T>) other;
1063             if (data.length != rhs.getDimension()) {
1064                 return false;
1065             }
1066 
1067             for (int i = 0; i < data.length; ++i) {
1068                 if (!data[i].equals(rhs.getEntry(i))) {
1069                     return false;
1070                 }
1071             }
1072             return true;
1073         } catch (ClassCastException ex) {
1074             // ignore exception
1075             return false;
1076         }
1077     }
1078 
1079     /**
1080      * Get a hashCode for the real vector.
1081      * <p>All NaN values have the same hash code.</p>
1082      * @return a hash code value for this object
1083      */
1084     @Override
1085     public int hashCode() {
1086         int h = 3542;
1087         for (final T a : data) {
1088             h ^= a.hashCode();
1089         }
1090         return h;
1091     }
1092 
1093     /**
1094      * Check if an index is valid.
1095      *
1096      * @param index Index to check.
1097      * @exception MathIllegalArgumentException if the index is not valid.
1098      */
1099     private void checkIndex(final int index) throws MathIllegalArgumentException {
1100         if (index < 0 || index >= getDimension()) {
1101             throw new MathIllegalArgumentException(LocalizedCoreFormats.INDEX,
1102                                           index, 0, getDimension() - 1);
1103         }
1104     }
1105 
1106     /**
1107      * Checks that the indices of a subvector are valid.
1108      *
1109      * @param start the index of the first entry of the subvector
1110      * @param end the index of the last entry of the subvector (inclusive)
1111      * @throws MathIllegalArgumentException if {@code start} of {@code end} are not valid
1112      * @throws MathIllegalArgumentException if {@code end < start}
1113      */
1114     private void checkIndices(final int start, final int end)
1115         throws MathIllegalArgumentException {
1116         final int dim = getDimension();
1117         if ((start < 0) || (start >= dim)) {
1118             throw new MathIllegalArgumentException(LocalizedCoreFormats.INDEX, start, 0,
1119                                           dim - 1);
1120         }
1121         if ((end < 0) || (end >= dim)) {
1122             throw new MathIllegalArgumentException(LocalizedCoreFormats.INDEX, end, 0,
1123                                           dim - 1);
1124         }
1125         if (end < start) {
1126             throw new MathIllegalArgumentException(LocalizedCoreFormats.INITIAL_ROW_AFTER_FINAL_ROW,
1127                                                 end, start, false);
1128         }
1129     }
1130 
1131 }