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