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