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