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