    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    }