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