001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.math.linear;
018    
019    import java.io.Serializable;
020    import java.lang.reflect.Array;
021    import java.util.Arrays;
022    
023    import org.apache.commons.math.Field;
024    import org.apache.commons.math.FieldElement;
025    import org.apache.commons.math.exception.ZeroException;
026    import org.apache.commons.math.exception.NullArgumentException;
027    import org.apache.commons.math.exception.OutOfRangeException;
028    import org.apache.commons.math.exception.DimensionMismatchException;
029    import org.apache.commons.math.exception.NumberIsTooLargeException;
030    import org.apache.commons.math.exception.util.LocalizedFormats;
031    
032    /**
033     * This class implements the {@link FieldVector} interface with a {@link FieldElement} array.
034     * @param <T> the type of the field elements
035     * @version $Id: ArrayFieldVector.java 1178172 2011-10-02 10:11:43Z luc $
036     * @since 2.0
037     */
038    public class ArrayFieldVector<T extends FieldElement<T>> implements FieldVector<T>, Serializable {
039        /** Serializable version identifier. */
040        private static final long serialVersionUID = 7648186910365927050L;
041        /** Entries of the vector. */
042        protected T[] data;
043        /** Field to which the elements belong. */
044        private final Field<T> field;
045    
046        /**
047         * Build a 0-length vector.
048         * Zero-length vectors may be used to initialized construction of vectors
049         * by data gathering. We start with zero-length and use either the {@link
050         * #ArrayFieldVector(ArrayFieldVector, ArrayFieldVector)} constructor
051         * or one of the {@code append} methods ({@link #add(FieldVector)} or
052         * {@link #append(ArrayFieldVector)}) to gather data into this vector.
053         *
054         * @param field field to which the elements belong
055         */
056        public ArrayFieldVector(final Field<T> field) {
057            this(field, 0);
058        }
059    
060        /**
061         * Construct a vector of zeroes.
062         *
063         * @param field Field to which the elements belong.
064         * @param size Size of the vector.
065         */
066        public ArrayFieldVector(Field<T> field, int size) {
067            this.field = field;
068            data = buildArray(size);
069            Arrays.fill(data, field.getZero());
070        }
071    
072        /**
073         * Construct a vector with preset values.
074         *
075         * @param size Size of the vector.
076         * @param preset All entries will be set with this value.
077         */
078        public ArrayFieldVector(int size, T preset) {
079            this(preset.getField(), size);
080            Arrays.fill(data, preset);
081        }
082    
083        /**
084         * Construct a vector from an array, copying the input array.
085         * This constructor needs a non-empty {@code d} array to retrieve
086         * the field from its first element. This implies it cannot build
087         * 0 length vectors. To build vectors from any size, one should
088         * use the {@link #ArrayFieldVector(Field, FieldElement[])} constructor.
089         *
090         * @param d Array.
091         * @throws NullArgumentException if {@code d} is {@code null}.
092         * @throws ZeroException if {@code d} is empty.
093         * @see #ArrayFieldVector(Field, FieldElement[])
094         */
095        public ArrayFieldVector(T[] d) {
096            if (d == null) {
097                throw new NullArgumentException();
098            }
099            try {
100                field = d[0].getField();
101                data = d.clone();
102            } catch (ArrayIndexOutOfBoundsException e) {
103                throw new ZeroException(LocalizedFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT);
104            }
105        }
106    
107        /**
108         * Construct a vector from an array, copying the input array.
109         *
110         * @param field Field to which the elements belong.
111         * @param d Array.
112         * @throws NullArgumentException if {@code d} is {@code null}.
113         * @see #ArrayFieldVector(FieldElement[])
114         */
115        public ArrayFieldVector(Field<T> field, T[] d) {
116            if (d == null) {
117                throw new NullArgumentException();
118            }
119            this.field = field;
120            data = d.clone();
121        }
122    
123        /**
124         * Create a new ArrayFieldVector using the input array as the underlying
125         * data array.
126         * If an array is built specially in order to be embedded in a
127         * ArrayFieldVector and not used directly, the {@code copyArray} may be
128         * set to {@code false}. This will prevent the copying and improve
129         * performance as no new array will be built and no data will be copied.
130         * This constructor needs a non-empty {@code d} array to retrieve
131         * the field from its first element. This implies it cannot build
132         * 0 length vectors. To build vectors from any size, one should
133         * use the {@link #ArrayFieldVector(Field, FieldElement[], boolean)}
134         * constructor.
135         *
136         * @param d Data for the new vector.
137         * @param copyArray If {@code true}, the input array will be copied,
138         * otherwise it will be referenced.
139         * @throws NullArgumentException if {@code d} is {@code null}.
140         * @throws ZeroException if {@code d} is empty.
141         * @see #ArrayFieldVector(FieldElement[])
142         * @see #ArrayFieldVector(Field, FieldElement[], boolean)
143         */
144        public ArrayFieldVector(T[] d, boolean copyArray) {
145            if (d == null) {
146                throw new NullArgumentException();
147            }
148            if (d.length == 0) {
149                throw new ZeroException(LocalizedFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT);
150            }
151            field = d[0].getField();
152            data = copyArray ? d.clone() :  d;
153        }
154    
155        /**
156         * Create a new ArrayFieldVector using the input array as the underlying
157         * data array.
158         * If an array is built specially in order to be embedded in a
159         * ArrayFieldVector and not used directly, the {@code copyArray} may be
160         * set to {@code false}. This will prevent the copying and improve
161         * performance as no new array will be built and no data will be copied.
162         *
163         * @param field Field to which the elements belong.
164         * @param d Data for the new vector.
165         * @param copyArray If {@code true}, the input array will be copied,
166         * otherwise it will be referenced.
167         * @throws NullArgumentException if {@code d} is {@code null}.
168         * @see #ArrayFieldVector(FieldElement[], boolean)
169         */
170        public ArrayFieldVector(Field<T> field, T[] d, boolean copyArray) {
171            if (d == null) {
172                throw new NullArgumentException();
173            }
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            if (d == null) {
190                throw new NullArgumentException();
191            }
192            if (d.length < pos + size) {
193                throw new NumberIsTooLargeException(pos + size, d.length, true);
194            }
195            field = d[0].getField();
196            data = buildArray(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            if (d == null) {
213                throw new NullArgumentException();
214            }
215            if (d.length < pos + size) {
216                throw new NumberIsTooLargeException(pos + size, d.length, true);
217            }
218            this.field = field;
219            data = buildArray(size);
220            System.arraycopy(d, pos, data, 0, size);
221        }
222    
223        /**
224         * Construct a vector from another vector, using a deep copy.
225         *
226         * @param v Vector to copy.
227         * @throws NullArgumentException if {@code v} is {@code null}.
228         */
229        public ArrayFieldVector(FieldVector<T> v) {
230            if (v == null) {
231                throw new NullArgumentException();
232            }
233            field = v.getField();
234            data = buildArray(v.getDimension());
235            for (int i = 0; i < data.length; ++i) {
236                data[i] = v.getEntry(i);
237            }
238        }
239    
240        /**
241         * Construct a vector from another vector, using a deep copy.
242         *
243         * @param v Vector to copy.
244         * @throws NullArgumentException if {@code v} is {@code null}.
245         */
246        public ArrayFieldVector(ArrayFieldVector<T> v) {
247            if (v == null) {
248                throw new NullArgumentException();
249            }
250            field = v.getField();
251            data = v.data.clone();
252        }
253    
254        /**
255         * Construct a vector from another vector.
256         *
257         * @param v Vector to copy.
258         * @param deep If {@code true} perform a deep copy, otherwise perform
259         * a shallow copy
260         * @throws NullArgumentException if {@code v} is {@code null}.
261         */
262        public ArrayFieldVector(ArrayFieldVector<T> v, boolean deep) {
263            if (v == null) {
264                throw new NullArgumentException();
265            }
266            field = v.getField();
267            data = deep ? v.data.clone() : v.data;
268        }
269    
270        /**
271         * Construct a vector by appending one vector to another vector.
272         *
273         * @param v1 First vector (will be put in front of the new vector).
274         * @param v2 Second vector (will be put at back of the new vector).
275         * @throws NullArgumentException if {@code v1} or {@code v2} is
276         * {@code null}.
277         */
278        public ArrayFieldVector(ArrayFieldVector<T> v1, ArrayFieldVector<T> v2) {
279            if (v1 == null ||
280                v2 == null) {
281                throw new NullArgumentException();
282            }
283            field = v1.getField();
284            data = buildArray(v1.data.length + v2.data.length);
285            System.arraycopy(v1.data, 0, data, 0, v1.data.length);
286            System.arraycopy(v2.data, 0, data, v1.data.length, v2.data.length);
287        }
288    
289        /**
290         * Construct a vector by appending one vector to another vector.
291         *
292         * @param v1 First vector (will be put in front of the new vector).
293         * @param v2 Second vector (will be put at back of the new vector).
294         * @throws NullArgumentException if {@code v1} or {@code v2} is
295         * {@code null}.
296         */
297        public ArrayFieldVector(ArrayFieldVector<T> v1, T[] v2) {
298            if (v1 == null ||
299                v2 == null) {
300                throw new NullArgumentException();
301            }
302            field = v1.getField();
303            data = buildArray(v1.data.length + v2.length);
304            System.arraycopy(v1.data, 0, data, 0, v1.data.length);
305            System.arraycopy(v2, 0, data, v1.data.length, v2.length);
306        }
307    
308        /**
309         * Construct a vector by appending one vector to another vector.
310         *
311         * @param v1 First vector (will be put in front of the new vector).
312         * @param v2 Second vector (will be put at back of the new vector).
313         * @throws NullArgumentException if {@code v1} or {@code v2} is
314         * {@code null}.
315         */
316        public ArrayFieldVector(T[] v1, ArrayFieldVector<T> v2) {
317            if (v1 == null ||
318                v2 == null) {
319                throw new NullArgumentException();
320            }
321            field = v2.getField();
322            data = buildArray(v1.length + v2.data.length);
323            System.arraycopy(v1, 0, data, 0, v1.length);
324            System.arraycopy(v2.data, 0, data, v1.length, v2.data.length);
325        }
326    
327        /**
328         * Construct a vector by appending one vector to another vector.
329         * This constructor needs at least one non-empty array to retrieve
330         * the field from its first element. This implies it cannot build
331         * 0 length vectors. To build vectors from any size, one should
332         * use the {@link #ArrayFieldVector(Field, FieldElement[], FieldElement[])}
333         * constructor.
334         *
335         * @param v1 First vector (will be put in front of the new vector).
336         * @param v2 Second vector (will be put at back of the new vector).
337         * @throws NullArgumentException if {@code v1} or {@code v2} is
338         * {@code null}.
339         * @throws ZeroException if both arrays are empty.
340         * @see #ArrayFieldVector(Field, FieldElement[], FieldElement[])
341         */
342        public ArrayFieldVector(T[] v1, T[] v2) {
343            if (v1 == null ||
344                v2 == null) {
345                throw new NullArgumentException();
346            }
347            if (v1.length + v2.length == 0) {
348                throw new ZeroException(LocalizedFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT);
349            }
350            data = buildArray(v1.length + v2.length);
351            System.arraycopy(v1, 0, data, 0, v1.length);
352            System.arraycopy(v2, 0, data, v1.length, v2.length);
353            field = data[0].getField();
354        }
355    
356        /**
357         * Construct a vector by appending one vector to another vector.
358         *
359         * @param field Field to which the elements belong.
360         * @param v1 First vector (will be put in front of the new vector).
361         * @param v2 Second vector (will be put at back of the new vector).
362         * @throws NullArgumentException if {@code v1} or {@code v2} is
363         * {@code null}.
364         * @throws ZeroException if both arrays are empty.
365         * @see #ArrayFieldVector(FieldElement[], FieldElement[])
366         */
367        public ArrayFieldVector(Field<T> field, T[] v1, T[] v2) {
368            if (v1.length + v2.length == 0) {
369                throw new ZeroException(LocalizedFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT);
370            }
371            data = buildArray(v1.length + v2.length);
372            System.arraycopy(v1, 0, data, 0, v1.length);
373            System.arraycopy(v2, 0, data, v1.length, v2.length);
374            this.field = field;
375        }
376    
377        /**
378         * Build an array of elements.
379         *
380         * @param length Size of the array to build.
381         * @return a new array.
382         */
383        @SuppressWarnings("unchecked") // field is of type T
384        private T[] buildArray(final int length) {
385            return (T[]) Array.newInstance(field.getRuntimeClass(), length);
386        }
387    
388        /** {@inheritDoc} */
389        public Field<T> getField() {
390            return field;
391        }
392    
393        /** {@inheritDoc} */
394        public FieldVector<T> copy() {
395            return new ArrayFieldVector<T>(this, true);
396        }
397    
398        /** {@inheritDoc} */
399        public FieldVector<T> add(FieldVector<T> v) {
400            try {
401                return add((ArrayFieldVector<T>) v);
402            } catch (ClassCastException cce) {
403                checkVectorDimensions(v);
404                T[] out = buildArray(data.length);
405                for (int i = 0; i < data.length; i++) {
406                    out[i] = data[i].add(v.getEntry(i));
407                }
408                return new ArrayFieldVector<T>(field, out, false);
409            }
410        }
411    
412        /**
413         * Compute the sum of this and v.
414         * @param v vector to be added
415         * @return this + v
416         * @throws IllegalArgumentException if v is not the same size as this
417         */
418        public ArrayFieldVector<T> add(ArrayFieldVector<T> v) {
419            checkVectorDimensions(v.data.length);
420            T[] out = buildArray(data.length);
421            for (int i = 0; i < data.length; i++) {
422                out[i] = data[i].add(v.data[i]);
423            }
424            return new ArrayFieldVector<T>(field, out, false);
425        }
426    
427        /** {@inheritDoc} */
428        public FieldVector<T> subtract(FieldVector<T> v) {
429            try {
430                return subtract((ArrayFieldVector<T>) v);
431            } catch (ClassCastException cce) {
432                checkVectorDimensions(v);
433                T[] out = buildArray(data.length);
434                for (int i = 0; i < data.length; i++) {
435                    out[i] = data[i].subtract(v.getEntry(i));
436                }
437                return new ArrayFieldVector<T>(field, out, false);
438            }
439        }
440    
441        /**
442         * Compute this minus v.
443         * @param v vector to be subtracted
444         * @return this + v
445         * @throws IllegalArgumentException if v is not the same size as this
446         */
447        public ArrayFieldVector<T> subtract(ArrayFieldVector<T> v) {
448            checkVectorDimensions(v.data.length);
449            T[] out = buildArray(data.length);
450            for (int i = 0; i < data.length; i++) {
451                out[i] = data[i].subtract(v.data[i]);
452            }
453            return new ArrayFieldVector<T>(field, out, false);
454        }
455    
456        /** {@inheritDoc} */
457        public FieldVector<T> mapAdd(T d) {
458            T[] out = buildArray(data.length);
459            for (int i = 0; i < data.length; i++) {
460                out[i] = data[i].add(d);
461            }
462            return new ArrayFieldVector<T>(field, out, false);
463        }
464    
465        /** {@inheritDoc} */
466        public FieldVector<T> mapAddToSelf(T d) {
467            for (int i = 0; i < data.length; i++) {
468                data[i] = data[i].add(d);
469            }
470            return this;
471        }
472    
473        /** {@inheritDoc} */
474        public FieldVector<T> mapSubtract(T d) {
475            T[] out = buildArray(data.length);
476            for (int i = 0; i < data.length; i++) {
477                out[i] = data[i].subtract(d);
478            }
479            return new ArrayFieldVector<T>(field, out, false);
480        }
481    
482        /** {@inheritDoc} */
483        public FieldVector<T> mapSubtractToSelf(T d) {
484            for (int i = 0; i < data.length; i++) {
485                data[i] = data[i].subtract(d);
486            }
487            return this;
488        }
489    
490        /** {@inheritDoc} */
491        public FieldVector<T> mapMultiply(T d) {
492            T[] out = buildArray(data.length);
493            for (int i = 0; i < data.length; i++) {
494                out[i] = data[i].multiply(d);
495            }
496            return new ArrayFieldVector<T>(field, out, false);
497        }
498    
499        /** {@inheritDoc} */
500        public FieldVector<T> mapMultiplyToSelf(T d) {
501            for (int i = 0; i < data.length; i++) {
502                data[i] = data[i].multiply(d);
503            }
504            return this;
505        }
506    
507        /** {@inheritDoc} */
508        public FieldVector<T> mapDivide(T d) {
509            T[] out = buildArray(data.length);
510            for (int i = 0; i < data.length; i++) {
511                out[i] = data[i].divide(d);
512            }
513            return new ArrayFieldVector<T>(field, out, false);
514        }
515    
516        /** {@inheritDoc} */
517        public FieldVector<T> mapDivideToSelf(T d) {
518            for (int i = 0; i < data.length; i++) {
519                data[i] = data[i].divide(d);
520            }
521            return this;
522        }
523    
524        /** {@inheritDoc} */
525        public FieldVector<T> mapInv() {
526            T[] out = buildArray(data.length);
527            final T one = field.getOne();
528            for (int i = 0; i < data.length; i++) {
529                out[i] = one.divide(data[i]);
530            }
531            return new ArrayFieldVector<T>(field, out, false);
532        }
533    
534        /** {@inheritDoc} */
535        public FieldVector<T> mapInvToSelf() {
536            final T one = field.getOne();
537            for (int i = 0; i < data.length; i++) {
538                data[i] = one.divide(data[i]);
539            }
540            return this;
541        }
542    
543        /** {@inheritDoc} */
544        public FieldVector<T> ebeMultiply(FieldVector<T> v) {
545            try {
546                return ebeMultiply((ArrayFieldVector<T>) v);
547            } catch (ClassCastException cce) {
548                checkVectorDimensions(v);
549                T[] out = buildArray(data.length);
550                for (int i = 0; i < data.length; i++) {
551                    out[i] = data[i].multiply(v.getEntry(i));
552                }
553                return new ArrayFieldVector<T>(field, out, false);
554            }
555        }
556    
557        /**
558         * Element-by-element multiplication.
559         * @param v vector by which instance elements must be multiplied
560         * @return a vector containing this[i] * v[i] for all i
561         * @exception IllegalArgumentException if v is not the same size as this
562         */
563        public ArrayFieldVector<T> ebeMultiply(ArrayFieldVector<T> v) {
564            checkVectorDimensions(v.data.length);
565            T[] out = buildArray(data.length);
566            for (int i = 0; i < data.length; i++) {
567                out[i] = data[i].multiply(v.data[i]);
568            }
569            return new ArrayFieldVector<T>(field, out, false);
570        }
571    
572        /** {@inheritDoc} */
573        public FieldVector<T> ebeDivide(FieldVector<T> v) {
574            try {
575                return ebeDivide((ArrayFieldVector<T>) v);
576            } catch (ClassCastException cce) {
577                checkVectorDimensions(v);
578                T[] out = buildArray(data.length);
579                for (int i = 0; i < data.length; i++) {
580                    out[i] = data[i].divide(v.getEntry(i));
581                }
582                return new ArrayFieldVector<T>(field, out, false);
583            }
584        }
585    
586        /**
587         * Element-by-element division.
588         * @param v vector by which instance elements must be divided
589         * @return a vector containing this[i] / v[i] for all i
590         * @throws IllegalArgumentException if v is not the same size as this
591         */
592        public ArrayFieldVector<T> ebeDivide(ArrayFieldVector<T> v) {
593            checkVectorDimensions(v.data.length);
594            T[] out = buildArray(data.length);
595            for (int i = 0; i < data.length; i++) {
596                    out[i] = data[i].divide(v.data[i]);
597            }
598            return new ArrayFieldVector<T>(field, out, false);
599        }
600    
601        /** {@inheritDoc} */
602        public T[] getData() {
603            return data.clone();
604        }
605    
606        /**
607         * Returns a reference to the underlying data array.
608         * <p>Does not make a fresh copy of the underlying data.</p>
609         * @return array of entries
610         */
611        public T[] getDataRef() {
612            return data;
613        }
614    
615        /** {@inheritDoc} */
616        public T dotProduct(FieldVector<T> v) {
617            try {
618                return dotProduct((ArrayFieldVector<T>) v);
619            } catch (ClassCastException cce) {
620                checkVectorDimensions(v);
621                T dot = field.getZero();
622                for (int i = 0; i < data.length; i++) {
623                    dot = dot.add(data[i].multiply(v.getEntry(i)));
624                }
625                return dot;
626            }
627        }
628    
629        /**
630         * Compute the dot product.
631         * @param v vector with which dot product should be computed
632         * @return the scalar dot product between instance and v
633         * @exception IllegalArgumentException if v is not the same size as this
634         */
635        public T dotProduct(ArrayFieldVector<T> v) {
636            checkVectorDimensions(v.data.length);
637            T dot = field.getZero();
638            for (int i = 0; i < data.length; i++) {
639                dot = dot.add(data[i].multiply(v.data[i]));
640            }
641            return dot;
642        }
643    
644        /** {@inheritDoc} */
645        public FieldVector<T> projection(FieldVector<T> v) {
646            return v.mapMultiply(dotProduct(v).divide(v.dotProduct(v)));
647        }
648    
649       /** Find the orthogonal projection of this vector onto another vector.
650         * @param v vector onto which instance must be projected
651         * @return projection of the instance onto v
652         * @throws IllegalArgumentException if v is not the same size as this
653         */
654        public ArrayFieldVector<T> projection(ArrayFieldVector<T> v) {
655            return (ArrayFieldVector<T>) v.mapMultiply(dotProduct(v).divide(v.dotProduct(v)));
656        }
657    
658        /** {@inheritDoc} */
659        public FieldMatrix<T> outerProduct(FieldVector<T> v) {
660            try {
661                return outerProduct((ArrayFieldVector<T>) v);
662            } catch (ClassCastException cce) {
663                final int m = data.length;
664                final int n = v.getDimension();
665                final FieldMatrix<T> out = new Array2DRowFieldMatrix<T>(field, m, n);
666                for (int i = 0; i < m; i++) {
667                    for (int j = 0; j < n; j++) {
668                        out.setEntry(i, j, data[i].multiply(v.getEntry(j)));
669                    }
670                }
671                return out;
672            }
673        }
674    
675        /**
676         * Compute the outer product.
677         * @param v vector with which outer product should be computed
678         * @return the square matrix outer product between instance and v
679         * @exception IllegalArgumentException if v is not the same size as this
680         */
681        public FieldMatrix<T> outerProduct(ArrayFieldVector<T> v) {
682            final int m = data.length;
683            final int n = v.data.length;
684            final FieldMatrix<T> out = new Array2DRowFieldMatrix<T>(field, m, n);
685            for (int i = 0; i < m; i++) {
686                for (int j = 0; j < n; j++) {
687                    out.setEntry(i, j, data[i].multiply(v.data[j]));
688                }
689            }
690            return out;
691        }
692    
693        /** {@inheritDoc} */
694        public T getEntry(int index) {
695            return data[index];
696        }
697    
698        /** {@inheritDoc} */
699        public int getDimension() {
700            return data.length;
701        }
702    
703        /** {@inheritDoc} */
704        public FieldVector<T> append(FieldVector<T> v) {
705            try {
706                return append((ArrayFieldVector<T>) v);
707            } catch (ClassCastException cce) {
708                return new ArrayFieldVector<T>(this,new ArrayFieldVector<T>(v));
709            }
710        }
711    
712        /**
713         * Construct a vector by appending a vector to this vector.
714         * @param v vector to append to this one.
715         * @return a new vector
716         */
717        public ArrayFieldVector<T> append(ArrayFieldVector<T> v) {
718            return new ArrayFieldVector<T>(this, v);
719        }
720    
721        /** {@inheritDoc} */
722        public FieldVector<T> append(T in) {
723            final T[] out = buildArray(data.length + 1);
724            System.arraycopy(data, 0, out, 0, data.length);
725            out[data.length] = in;
726            return new ArrayFieldVector<T>(field, out, false);
727        }
728    
729        /** {@inheritDoc} */
730        public FieldVector<T> getSubVector(int index, int n) {
731            ArrayFieldVector<T> out = new ArrayFieldVector<T>(field, n);
732            try {
733                System.arraycopy(data, index, out.data, 0, n);
734            } catch (IndexOutOfBoundsException e) {
735                checkIndex(index);
736                checkIndex(index + n - 1);
737            }
738            return out;
739        }
740    
741        /** {@inheritDoc} */
742        public void setEntry(int index, T value) {
743            try {
744                data[index] = value;
745            } catch (IndexOutOfBoundsException e) {
746                checkIndex(index);
747            }
748        }
749    
750        /** {@inheritDoc} */
751        public void setSubVector(int index, FieldVector<T> v) {
752            try {
753                try {
754                    set(index, (ArrayFieldVector<T>) v);
755                } catch (ClassCastException cce) {
756                    for (int i = index; i < index + v.getDimension(); ++i) {
757                        data[i] = v.getEntry(i-index);
758                    }
759                }
760            } catch (IndexOutOfBoundsException e) {
761                checkIndex(index);
762                checkIndex(index + v.getDimension() - 1);
763            }
764        }
765    
766        /**
767         * Set a set of consecutive elements.
768         *
769         * @param index index of first element to be set.
770         * @param v vector containing the values to set.
771         * @throws OutOfRangeException if the index is
772         * inconsistent with vector size
773         */
774        public void set(int index, ArrayFieldVector<T> v) {
775            try {
776                System.arraycopy(v.data, 0, data, index, v.data.length);
777            } catch (IndexOutOfBoundsException e) {
778                checkIndex(index);
779                checkIndex(index + v.data.length - 1);
780            }
781        }
782    
783        /** {@inheritDoc} */
784        public void set(T value) {
785            Arrays.fill(data, value);
786        }
787    
788        /** {@inheritDoc} */
789        public T[] toArray(){
790            return data.clone();
791        }
792    
793        /**
794         * Check if instance and specified vectors have the same dimension.
795         * @param v vector to compare instance with
796         * @exception IllegalArgumentException if the vectors do not
797         * have the same dimension
798         */
799        protected void checkVectorDimensions(FieldVector<T> v) {
800            checkVectorDimensions(v.getDimension());
801        }
802    
803        /**
804         * Check if instance dimension is equal to some expected value.
805         *
806         * @param n Expected dimension.
807         * @throws OutOfRangeException if the dimension is
808         * inconsistent with this vector size.
809         */
810        protected void checkVectorDimensions(int n) {
811            if (data.length != n) {
812                throw new DimensionMismatchException(data.length, n);
813            }
814        }
815    
816        /**
817         * Test for the equality of two vectors.
818         *
819         * @param other Object to test for equality.
820         * @return {@code true} if two vector objects are equal, {@code false}
821         * otherwise.
822         */
823        @Override
824        public boolean equals(Object other) {
825            if (this == other) {
826                return true;
827            }
828            if (other == null) {
829                return false;
830            }
831    
832            try {
833                @SuppressWarnings("unchecked") // May fail, but we ignore ClassCastException
834                    FieldVector<T> rhs = (FieldVector<T>) other;
835                if (data.length != rhs.getDimension()) {
836                    return false;
837                }
838    
839                for (int i = 0; i < data.length; ++i) {
840                    if (!data[i].equals(rhs.getEntry(i))) {
841                        return false;
842                    }
843                }
844                return true;
845            } catch (ClassCastException ex) {
846                // ignore exception
847                return false;
848            }
849        }
850    
851        /**
852         * Get a hashCode for the real vector.
853         * <p>All NaN values have the same hash code.</p>
854         * @return a hash code value for this object
855         */
856        @Override
857        public int hashCode() {
858            int h = 3542;
859            for (final T a : data) {
860                h = h ^ a.hashCode();
861            }
862            return h;
863        }
864    
865        /**
866         * Check if an index is valid.
867         *
868         * @param index Index to check.
869         * @exception OutOfRangeException if the index is not valid.
870         */
871        private void checkIndex(final int index) {
872            if (index < 0 || index >= getDimension()) {
873                throw new OutOfRangeException(LocalizedFormats.INDEX,
874                                              index, 0, getDimension() - 1);
875            }
876        }
877    }