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