    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.util.Arrays;
    021    import java.util.Iterator;
    022
    023    import org.apache.commons.math.MathRuntimeException;
    024    import org.apache.commons.math.exception.util.LocalizedFormats;
    025    import org.apache.commons.math.util.MathUtils;
    026    import org.apache.commons.math.util.FastMath;
    027
    028    /**
    029     * This class implements the {@link RealVector} interface with a double array.
    030     * @version $Revision: 1003993 $ $Date: 2010-10-03 18:39:16 +0200 (dim. 03 oct. 2010) $
    031     * @since 2.0
    032     */
    033    public class ArrayRealVector extends AbstractRealVector implements Serializable {
    034
    035        /** Serializable version identifier. */
    036        private static final long serialVersionUID = -1097961340710804027L;
    037
    038        /** Default format. */
    039        private static final RealVectorFormat DEFAULT_FORMAT =
    040            RealVectorFormat.getInstance();
    041
    042        /** Entries of the vector. */
    043        protected double data[];
    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         * #ArrayRealVector(ArrayRealVector, ArrayRealVector)} constructor
    050         * or one of the <code>append</code> method ({@link #append(double)}, {@link
    051         * #append(double[])}, {@link #append(ArrayRealVector)}) to gather data
    052         * into this vector.</p>
    053         */
    054        public ArrayRealVector() {
    055            data = new double[0];
    056        }
    057
    058        /**
    059         * Construct a (size)-length vector of zeros.
    060         * @param size size of the vector
    061         */
    062        public ArrayRealVector(int size) {
    063            data = new double[size];
    064        }
    065
    066        /**
    067         * Construct an (size)-length vector with preset values.
    068         * @param size size of the vector
    069         * @param preset fill the vector with this scalar value
    070         */
    071        public ArrayRealVector(int size, double preset) {
    072            data = new double[size];
    073            Arrays.fill(data, preset);
    074        }
    075
    076        /**
    077         * Construct a vector from an array, copying the input array.
    078         * @param d array of doubles.
    079         */
    080        public ArrayRealVector(double[] d) {
    081            data = d.clone();
    082        }
    083
    084        /**
    085         * Create a new ArrayRealVector using the input array as the underlying
    086         * data array.
    087         * <p>If an array is built specially in order to be embedded in a
    088         * ArrayRealVector and not used directly, the <code>copyArray</code> may be
    089         * set to <code>false</code. This will prevent the copying and improve
    090         * performance as no new array will be built and no data will be copied.</p>
    091         * @param d data for new vector
    092         * @param copyArray if true, the input array will be copied, otherwise
    093         * it will be referenced
    094         * @see #ArrayRealVector(double[])
    095         */
    096        public ArrayRealVector(double[] d, boolean copyArray) {
    097            data = copyArray ? d.clone() :  d;
    098        }
    099
    100        /**
    101         * Construct a vector from part of a array.
    102         * @param d array of doubles.
    103         * @param pos position of first entry
    104         * @param size number of entries to copy
    105         */
    106        public ArrayRealVector(double[] d, int pos, int size) {
    107            if (d.length < pos + size) {
    108                throw MathRuntimeException.createIllegalArgumentException(
    109                      LocalizedFormats.POSITION_SIZE_MISMATCH_INPUT_ARRAY, pos, size, d.length);
    110            }
    111            data = new double[size];
    112            System.arraycopy(d, pos, data, 0, size);
    113        }
    114
    115        /**
    116         * Construct a vector from an array.
    117         * @param d array of Doubles.
    118         */
    119        public ArrayRealVector(Double[] d) {
    120            data = new double[d.length];
    121            for (int i = 0; i < d.length; i++) {
    122                data[i] = d[i].doubleValue();
    123            }
    124        }
    125
    126        /**
    127         * Construct a vector from part of a Double array
    128         * @param d array of Doubles.
    129         * @param pos position of first entry
    130         * @param size number of entries to copy
    131         */
    132        public ArrayRealVector(Double[] d, int pos, int size) {
    133            if (d.length < pos + size) {
    134                throw MathRuntimeException.createIllegalArgumentException(
    135                      LocalizedFormats.POSITION_SIZE_MISMATCH_INPUT_ARRAY, pos, size, d.length);
    136            }
    137            data = new double[size];
    138            for (int i = pos; i < pos + size; i++) {
    139                data[i-pos] = d[i].doubleValue();
    140            }
    141        }
    142
    143        /**
    144         * Construct a vector from another vector, using a deep copy.
    145         * @param v vector to copy
    146         */
    147        public ArrayRealVector(RealVector v) {
    148            data = new double[v.getDimension()];
    149            for (int i = 0; i < data.length; ++i) {
    150                data[i] = v.getEntry(i);
    151            }
    152        }
    153
    154        /**
    155         * Construct a vector from another vector, using a deep copy.
    156         * @param v vector to copy
    157         */
    158        public ArrayRealVector(ArrayRealVector v) {
    159            this(v, true);
    160        }
    161
    162        /**
    163         * Construct a vector from another vector.
    164         * @param v vector to copy
    165         * @param deep if true perform a deep copy otherwise perform a shallow copy
    166         */
    167        public ArrayRealVector(ArrayRealVector v, boolean deep) {
    168            data = deep ? v.data.clone() : v.data;
    169        }
    170
    171        /**
    172         * Construct a vector by appending one vector to another vector.
    173         * @param v1 first vector (will be put in front of the new vector)
    174         * @param v2 second vector (will be put at back of the new vector)
    175         */
    176        public ArrayRealVector(ArrayRealVector v1, ArrayRealVector v2) {
    177            data = new double[v1.data.length + v2.data.length];
    178            System.arraycopy(v1.data, 0, data, 0, v1.data.length);
    179            System.arraycopy(v2.data, 0, data, v1.data.length, v2.data.length);
    180        }
    181
    182        /**
    183         * Construct a vector by appending one vector to another vector.
    184         * @param v1 first vector (will be put in front of the new vector)
    185         * @param v2 second vector (will be put at back of the new vector)
    186         */
    187        public ArrayRealVector(ArrayRealVector v1, RealVector v2) {
    188            final int l1 = v1.data.length;
    189            final int l2 = v2.getDimension();
    190            data = new double[l1 + l2];
    191            System.arraycopy(v1.data, 0, data, 0, l1);
    192            for (int i = 0; i < l2; ++i) {
    193                data[l1 + i] = v2.getEntry(i);
    194            }
    195        }
    196
    197        /**
    198         * Construct a vector by appending one vector to another vector.
    199         * @param v1 first vector (will be put in front of the new vector)
    200         * @param v2 second vector (will be put at back of the new vector)
    201         */
    202        public ArrayRealVector(RealVector v1, ArrayRealVector v2) {
    203            final int l1 = v1.getDimension();
    204            final int l2 = v2.data.length;
    205            data = new double[l1 + l2];
    206            for (int i = 0; i < l1; ++i) {
    207                data[i] = v1.getEntry(i);
    208            }
    209            System.arraycopy(v2.data, 0, data, l1, l2);
    210        }
    211
    212        /**
    213         * Construct a vector by appending one vector to another vector.
    214         * @param v1 first vector (will be put in front of the new vector)
    215         * @param v2 second vector (will be put at back of the new vector)
    216         */
    217        public ArrayRealVector(ArrayRealVector v1, double[] v2) {
    218            final int l1 = v1.getDimension();
    219            final int l2 = v2.length;
    220            data = new double[l1 + l2];
    221            System.arraycopy(v1.data, 0, data, 0, l1);
    222            System.arraycopy(v2, 0, data, l1, l2);
    223        }
    224
    225        /**
    226         * Construct a vector by appending one vector to another vector.
    227         * @param v1 first vector (will be put in front of the new vector)
    228         * @param v2 second vector (will be put at back of the new vector)
    229         */
    230        public ArrayRealVector(double[] v1, ArrayRealVector v2) {
    231            final int l1 = v1.length;
    232            final int l2 = v2.getDimension();
    233            data = new double[l1 + l2];
    234            System.arraycopy(v1, 0, data, 0, l1);
    235            System.arraycopy(v2.data, 0, data, l1, l2);
    236        }
    237
    238        /**
    239         * Construct a vector by appending one vector to another vector.
    240         * @param v1 first vector (will be put in front of the new vector)
    241         * @param v2 second vector (will be put at back of the new vector)
    242         */
    243        public ArrayRealVector(double[] v1, double[] v2) {
    244            final int l1 = v1.length;
    245            final int l2 = v2.length;
    246            data = new double[l1 + l2];
    247            System.arraycopy(v1, 0, data, 0, l1);
    248            System.arraycopy(v2, 0, data, l1, l2);
    249        }
    250
    251        /** {@inheritDoc} */
    252        @Override
    253        public AbstractRealVector copy() {
    254            return new ArrayRealVector(this, true);
    255        }
    256
    257        /** {@inheritDoc} */
    258        @Override
    259        public RealVector add(RealVector v)
    260            throws IllegalArgumentException {
    261            if (v instanceof ArrayRealVector) {
    262                return add((ArrayRealVector) v);
    263            } else {
    264                checkVectorDimensions(v);
    265                double[] out = data.clone();
    266                Iterator<Entry> it = v.sparseIterator();
    267                Entry e;
    268                while (it.hasNext() && (e = it.next()) != null) {
    269                    out[e.getIndex()] += e.getValue();
    270                }
    271                return new ArrayRealVector(out, false);
    272            }
    273        }
    274
    275        /** {@inheritDoc} */
    276        @Override
    277        public RealVector add(double[] v)
    278            throws IllegalArgumentException {
    279            checkVectorDimensions(v.length);
    280            double[] out = data.clone();
    281            for (int i = 0; i < data.length; i++) {
    282                out[i] += v[i];
    283            }
    284            return new ArrayRealVector(out, false);
    285        }
    286
    287        /**
    288         * Compute the sum of this and v.
    289         * @param v vector to be added
    290         * @return this + v
    291         * @throws IllegalArgumentException if v is not the same size as this
    292         */
    293        public ArrayRealVector add(ArrayRealVector v)
    294            throws IllegalArgumentException {
    295            return (ArrayRealVector) add(v.data);
    296        }
    297
    298        /** {@inheritDoc} */
    299        @Override
    300        public RealVector subtract(RealVector v)
    301            throws IllegalArgumentException {
    302            if (v instanceof ArrayRealVector) {
    303                return subtract((ArrayRealVector) v);
    304            } else {
    305                checkVectorDimensions(v);
    306                double[] out = data.clone();
    307                Iterator<Entry> it = v.sparseIterator();
    308                Entry e;
    309                while(it.hasNext() && (e = it.next()) != null) {
    310                    out[e.getIndex()] -= e.getValue();
    311                }
    312                return new ArrayRealVector(out, false);
    313            }
    314        }
    315
    316        /** {@inheritDoc} */
    317        @Override
    318        public RealVector subtract(double[] v)
    319            throws IllegalArgumentException {
    320            checkVectorDimensions(v.length);
    321            double[] out = data.clone();
    322            for (int i = 0; i < data.length; i++) {
    323                out[i] -= v[i];
    324            }
    325            return new ArrayRealVector(out, false);
    326        }
    327
    328        /**
    329         * Compute this minus v.
    330         * @param v vector to be subtracted
    331         * @return this + v
    332         * @throws IllegalArgumentException if v is not the same size as this
    333         */
    334        public ArrayRealVector subtract(ArrayRealVector v)
    335            throws IllegalArgumentException {
    336            return (ArrayRealVector) subtract(v.data);
    337        }
    338
    339        /** {@inheritDoc} */
    340        @Override
    341        public RealVector mapAddToSelf(double d) {
    342            for (int i = 0; i < data.length; i++) {
    343                data[i] = data[i] + d;
    344            }
    345            return this;
    346        }
    347
    348        /** {@inheritDoc} */
    349        @Override
    350        public RealVector mapSubtractToSelf(double d) {
    351            for (int i = 0; i < data.length; i++) {
    352                data[i] = data[i] - d;
    353            }
    354            return this;
    355        }
    356
    357        /** {@inheritDoc} */
    358        @Override
    359        public RealVector mapMultiplyToSelf(double d) {
    360            for (int i = 0; i < data.length; i++) {
    361                data[i] = data[i] * d;
    362            }
    363            return this;
    364        }
    365
    366        /** {@inheritDoc} */
    367        @Override
    368        public RealVector mapDivideToSelf(double d) {
    369            for (int i = 0; i < data.length; i++) {
    370                data[i] = data[i] / d;
    371            }
    372            return this;
    373        }
    374
    375        /** {@inheritDoc} */
    376        @Override
    377        public RealVector mapPowToSelf(double d) {
    378            for (int i = 0; i < data.length; i++) {
    379                data[i] = FastMath.pow(data[i], d);
    380            }
    381            return this;
    382        }
    383
    384        /** {@inheritDoc} */
    385        @Override
    386        public RealVector mapExpToSelf() {
    387            for (int i = 0; i < data.length; i++) {
    388                data[i] = FastMath.exp(data[i]);
    389            }
    390            return this;
    391        }
    392
    393        /** {@inheritDoc} */
    394        @Override
    395        public RealVector mapExpm1ToSelf() {
    396            for (int i = 0; i < data.length; i++) {
    397                data[i] = FastMath.expm1(data[i]);
    398            }
    399            return this;
    400        }
    401
    402        /** {@inheritDoc} */
    403        @Override
    404        public RealVector mapLogToSelf() {
    405            for (int i = 0; i < data.length; i++) {
    406                data[i] = FastMath.log(data[i]);
    407            }
    408            return this;
    409        }
    410
    411        /** {@inheritDoc} */
    412        @Override
    413        public RealVector mapLog10ToSelf() {
    414            for (int i = 0; i < data.length; i++) {
    415                data[i] = FastMath.log10(data[i]);
    416            }
    417            return this;
    418        }
    419
    420        /** {@inheritDoc} */
    421        @Override
    422        public RealVector mapLog1pToSelf() {
    423            for (int i = 0; i < data.length; i++) {
    424                data[i] = FastMath.log1p(data[i]);
    425            }
    426            return this;
    427        }
    428
    429        /** {@inheritDoc} */
    430        @Override
    431        public RealVector mapCoshToSelf() {
    432            for (int i = 0; i < data.length; i++) {
    433                data[i] = FastMath.cosh(data[i]);
    434            }
    435            return this;
    436        }
    437
    438        /** {@inheritDoc} */
    439        @Override
    440        public RealVector mapSinhToSelf() {
    441            for (int i = 0; i < data.length; i++) {
    442                data[i] = FastMath.sinh(data[i]);
    443            }
    444            return this;
    445        }
    446
    447        /** {@inheritDoc} */
    448        @Override
    449        public RealVector mapTanhToSelf() {
    450            for (int i = 0; i < data.length; i++) {
    451                data[i] = FastMath.tanh(data[i]);
    452            }
    453            return this;
    454        }
    455
    456        /** {@inheritDoc} */
    457        @Override
    458        public RealVector mapCosToSelf() {
    459            for (int i = 0; i < data.length; i++) {
    460                data[i] = FastMath.cos(data[i]);
    461            }
    462            return this;
    463        }
    464
    465        /** {@inheritDoc} */
    466        @Override
    467        public RealVector mapSinToSelf() {
    468            for (int i = 0; i < data.length; i++) {
    469                data[i] = FastMath.sin(data[i]);
    470            }
    471            return this;
    472        }
    473
    474        /** {@inheritDoc} */
    475        @Override
    476        public RealVector mapTanToSelf() {
    477            for (int i = 0; i < data.length; i++) {
    478                data[i] = FastMath.tan(data[i]);
    479            }
    480            return this;
    481        }
    482
    483        /** {@inheritDoc} */
    484        @Override
    485        public RealVector mapAcosToSelf() {
    486            for (int i = 0; i < data.length; i++) {
    487                data[i] = FastMath.acos(data[i]);
    488            }
    489            return this;
    490        }
    491
    492        /** {@inheritDoc} */
    493        @Override
    494        public RealVector mapAsinToSelf() {
    495            for (int i = 0; i < data.length; i++) {
    496                data[i] = FastMath.asin(data[i]);
    497            }
    498            return this;
    499        }
    500
    501        /** {@inheritDoc} */
    502        @Override
    503        public RealVector mapAtanToSelf() {
    504            for (int i = 0; i < data.length; i++) {
    505                data[i] = FastMath.atan(data[i]);
    506            }
    507            return this;
    508        }
    509
    510        /** {@inheritDoc} */
    511        @Override
    512        public RealVector mapInvToSelf() {
    513            for (int i = 0; i < data.length; i++) {
    514                data[i] = 1.0 / data[i];
    515            }
    516            return this;
    517        }
    518
    519        /** {@inheritDoc} */
    520        @Override
    521        public RealVector mapAbsToSelf() {
    522            for (int i = 0; i < data.length; i++) {
    523                data[i] = FastMath.abs(data[i]);
    524            }
    525            return this;
    526        }
    527
    528        /** {@inheritDoc} */
    529        @Override
    530        public RealVector mapSqrtToSelf() {
    531            for (int i = 0; i < data.length; i++) {
    532                data[i] = FastMath.sqrt(data[i]);
    533            }
    534            return this;
    535        }
    536
    537        /** {@inheritDoc} */
    538        @Override
    539        public RealVector mapCbrtToSelf() {
    540            for (int i = 0; i < data.length; i++) {
    541                data[i] = FastMath.cbrt(data[i]);
    542            }
    543            return this;
    544        }
    545
    546        /** {@inheritDoc} */
    547        @Override
    548        public RealVector mapCeilToSelf() {
    549            for (int i = 0; i < data.length; i++) {
    550                data[i] = FastMath.ceil(data[i]);
    551            }
    552            return this;
    553        }
    554
    555        /** {@inheritDoc} */
    556        @Override
    557        public RealVector mapFloorToSelf() {
    558            for (int i = 0; i < data.length; i++) {
    559                data[i] = FastMath.floor(data[i]);
    560            }
    561            return this;
    562        }
    563
    564        /** {@inheritDoc} */
    565        @Override
    566        public RealVector mapRintToSelf() {
    567            for (int i = 0; i < data.length; i++) {
    568                data[i] = FastMath.rint(data[i]);
    569            }
    570            return this;
    571        }
    572
    573        /** {@inheritDoc} */
    574        @Override
    575        public RealVector mapSignumToSelf() {
    576            for (int i = 0; i < data.length; i++) {
    577                data[i] = FastMath.signum(data[i]);
    578            }
    579            return this;
    580        }
    581
    582        /** {@inheritDoc} */
    583        @Override
    584        public RealVector mapUlpToSelf() {
    585            for (int i = 0; i < data.length; i++) {
    586                data[i] = FastMath.ulp(data[i]);
    587            }
    588            return this;
    589        }
    590
    591        /** {@inheritDoc} */
    592        public RealVector ebeMultiply(RealVector v)
    593            throws IllegalArgumentException {
    594            if (v instanceof ArrayRealVector) {
    595                return ebeMultiply((ArrayRealVector) v);
    596            } else {
    597                checkVectorDimensions(v);
    598                double[] out = data.clone();
    599                for (int i = 0; i < data.length; i++) {
    600                    out[i] *= v.getEntry(i);
    601                }
    602                return new ArrayRealVector(out, false);
    603            }
    604        }
    605
    606        /** {@inheritDoc} */
    607        @Override
    608        public RealVector ebeMultiply(double[] v)
    609            throws IllegalArgumentException {
    610            checkVectorDimensions(v.length);
    611            double[] out = data.clone();
    612            for (int i = 0; i < data.length; i++) {
    613                out[i] *= v[i];
    614            }
    615            return new ArrayRealVector(out, false);
    616        }
    617
    618        /**
    619         * Element-by-element multiplication.
    620         * @param v vector by which instance elements must be multiplied
    621         * @return a vector containing this[i] * v[i] for all i
    622         * @exception IllegalArgumentException if v is not the same size as this
    623         */
    624        public ArrayRealVector ebeMultiply(ArrayRealVector v)
    625            throws IllegalArgumentException {
    626            return (ArrayRealVector) ebeMultiply(v.data);
    627        }
    628
    629        /** {@inheritDoc} */
    630        public RealVector ebeDivide(RealVector v)
    631            throws IllegalArgumentException {
    632            if (v instanceof ArrayRealVector) {
    633                return ebeDivide((ArrayRealVector) v);
    634            } else {
    635                checkVectorDimensions(v);
    636                double[] out = data.clone();
    637                for (int i = 0; i < data.length; i++) {
    638                    out[i] /= v.getEntry(i);
    639                }
    640                return new ArrayRealVector(out, false);
    641            }
    642        }
    643
    644        /** {@inheritDoc} */
    645        @Override
    646        public RealVector ebeDivide(double[] v)
    647            throws IllegalArgumentException {
    648            checkVectorDimensions(v.length);
    649            double[] out = data.clone();
    650            for (int i = 0; i < data.length; i++) {
    651                    out[i] /= v[i];
    652            }
    653            return new ArrayRealVector(out, false);
    654        }
    655
    656        /**
    657         * Element-by-element division.
    658         * @param v vector by which instance elements must be divided
    659         * @return a vector containing this[i] / v[i] for all i
    660         * @throws IllegalArgumentException if v is not the same size as this
    661         */
    662        public ArrayRealVector ebeDivide(ArrayRealVector v)
    663            throws IllegalArgumentException {
    664            return (ArrayRealVector) ebeDivide(v.data);
    665        }
    666
    667        /** {@inheritDoc} */
    668        @Override
    669        public double[] getData() {
    670            return data.clone();
    671        }
    672
    673        /**
    674         * Returns a reference to the underlying data array.
    675         * <p>Does not make a fresh copy of the underlying data.</p>
    676         * @return array of entries
    677         */
    678        public double[] getDataRef() {
    679            return data;
    680        }
    681
    682        /** {@inheritDoc} */
    683        @Override
    684        public double dotProduct(RealVector v)
    685            throws IllegalArgumentException {
    686            if (v instanceof ArrayRealVector) {
    687                return dotProduct((ArrayRealVector) v);
    688            } else {
    689                checkVectorDimensions(v);
    690                double dot = 0;
    691                Iterator<Entry> it = v.sparseIterator();
    692                Entry e;
    693                while(it.hasNext() && (e = it.next()) != null) {
    694                    dot += data[e.getIndex()] * e.getValue();
    695                }
    696                return dot;
    697            }
    698        }
    699
    700        /** {@inheritDoc} */
    701        @Override
    702        public double dotProduct(double[] v)
    703            throws IllegalArgumentException {
    704            checkVectorDimensions(v.length);
    705            double dot = 0;
    706            for (int i = 0; i < data.length; i++) {
    707                dot += data[i] * v[i];
    708            }
    709            return dot;
    710        }
    711
    712        /**
    713         * Compute the dot product.
    714         * @param v vector with which dot product should be computed
    715         * @return the scalar dot product between instance and v
    716         * @exception IllegalArgumentException if v is not the same size as this
    717         */
    718        public double dotProduct(ArrayRealVector v)
    719            throws IllegalArgumentException {
    720            return dotProduct(v.data);
    721        }
    722
    723        /** {@inheritDoc} */
    724        @Override
    725        public double getNorm() {
    726            double sum = 0;
    727            for (double a : data) {
    728                sum += a * a;
    729            }
    730            return FastMath.sqrt(sum);
    731        }
    732
    733        /** {@inheritDoc} */
    734        @Override
    735        public double getL1Norm() {
    736            double sum = 0;
    737            for (double a : data) {
    738                sum += FastMath.abs(a);
    739            }
    740            return sum;
    741        }
    742
    743        /** {@inheritDoc} */
    744        @Override
    745        public double getLInfNorm() {
    746            double max = 0;
    747            for (double a : data) {
    748                max = FastMath.max(max, FastMath.abs(a));
    749            }
    750            return max;
    751        }
    752
    753        /** {@inheritDoc} */
    754        @Override
    755        public double getDistance(RealVector v)
    756            throws IllegalArgumentException {
    757            if (v instanceof ArrayRealVector) {
    758                return getDistance((ArrayRealVector) v);
    759            } else {
    760                checkVectorDimensions(v);
    761                double sum = 0;
    762                for (int i = 0; i < data.length; ++i) {
    763                    final double delta = data[i] - v.getEntry(i);
    764                    sum += delta * delta;
    765                }
    766                return FastMath.sqrt(sum);
    767            }
    768        }
    769
    770        /** {@inheritDoc} */
    771        @Override
    772        public double getDistance(double[] v)
    773            throws IllegalArgumentException {
    774            checkVectorDimensions(v.length);
    775            double sum = 0;
    776            for (int i = 0; i < data.length; ++i) {
    777                final double delta = data[i] - v[i];
    778                sum += delta * delta;
    779            }
    780            return FastMath.sqrt(sum);
    781        }
    782
    783       /**
    784         * Distance between two vectors.
    785         * <p>This method computes the distance consistent with the
    786         * L<sub>2</sub> norm, i.e. the square root of the sum of
    787         * elements differences, or euclidian distance.</p>
    788         * @param v vector to which distance is requested
    789         * @return distance between two vectors.
    790         * @exception IllegalArgumentException if v is not the same size as this
    791         * @see #getDistance(RealVector)
    792         * @see #getL1Distance(ArrayRealVector)
    793         * @see #getLInfDistance(ArrayRealVector)
    794         * @see #getNorm()
    795         */
    796        public double getDistance(ArrayRealVector v)
    797            throws IllegalArgumentException {
    798            return getDistance(v.data);
    799        }
    800
    801        /** {@inheritDoc} */
    802        @Override
    803        public double getL1Distance(RealVector v)
    804            throws IllegalArgumentException {
    805            if (v instanceof ArrayRealVector) {
    806                return getL1Distance((ArrayRealVector) v);
    807            } else {
    808                checkVectorDimensions(v);
    809                double sum = 0;
    810                for (int i = 0; i < data.length; ++i) {
    811                    final double delta = data[i] - v.getEntry(i);
    812                    sum += FastMath.abs(delta);
    813                }
    814                return sum;
    815            }
    816        }
    817
    818        /** {@inheritDoc} */
    819        @Override
    820        public double getL1Distance(double[] v)
    821            throws IllegalArgumentException {
    822            checkVectorDimensions(v.length);
    823            double sum = 0;
    824            for (int i = 0; i < data.length; ++i) {
    825                final double delta = data[i] - v[i];
    826                sum += FastMath.abs(delta);
    827            }
    828            return sum;
    829        }
    830
    831        /**
    832         * Distance between two vectors.
    833         * <p>This method computes the distance consistent with
    834         * L<sub>1</sub> norm, i.e. the sum of the absolute values of
    835         * elements differences.</p>
    836         * @param v vector to which distance is requested
    837         * @return distance between two vectors.
    838         * @exception IllegalArgumentException if v is not the same size as this
    839         * @see #getDistance(RealVector)
    840         * @see #getL1Distance(ArrayRealVector)
    841         * @see #getLInfDistance(ArrayRealVector)
    842         * @see #getNorm()
    843         */
    844        public double getL1Distance(ArrayRealVector v)
    845            throws IllegalArgumentException {
    846            return getL1Distance(v.data);
    847        }
    848
    849        /** {@inheritDoc} */
    850        @Override
    851        public double getLInfDistance(RealVector v)
    852            throws IllegalArgumentException {
    853            if (v instanceof ArrayRealVector) {
    854                return getLInfDistance((ArrayRealVector) v);
    855            } else {
    856                checkVectorDimensions(v);
    857                double max = 0;
    858                for (int i = 0; i < data.length; ++i) {
    859                    final double delta = data[i] - v.getEntry(i);
    860                    max = FastMath.max(max, FastMath.abs(delta));
    861                }
    862                return max;
    863            }
    864        }
    865
    866        /** {@inheritDoc} */
    867        @Override
    868        public double getLInfDistance(double[] v)
    869            throws IllegalArgumentException {
    870            checkVectorDimensions(v.length);
    871            double max = 0;
    872            for (int i = 0; i < data.length; ++i) {
    873                final double delta = data[i] - v[i];
    874                max = FastMath.max(max, FastMath.abs(delta));
    875            }
    876            return max;
    877        }
    878
    879        /**
    880         * Distance between two vectors.
    881         * <p>This method computes the distance consistent with
    882         * L<sub>&infin;</sub> norm, i.e. the max of the absolute values of
    883         * elements differences.</p>
    884         * @param v vector to which distance is requested
    885         * @return distance between two vectors.
    886         * @exception IllegalArgumentException if v is not the same size as this
    887         * @see #getDistance(RealVector)
    888         * @see #getL1Distance(ArrayRealVector)
    889         * @see #getLInfDistance(ArrayRealVector)
    890         * @see #getNorm()
    891         */
    892        public double getLInfDistance(ArrayRealVector v)
    893            throws IllegalArgumentException {
    894            return getLInfDistance(v.data);
    895        }
    896
    897        /** {@inheritDoc} */
    898        @Override
    899        public RealVector unitVector() throws ArithmeticException {
    900            final double norm = getNorm();
    901            if (norm == 0) {
    902                throw MathRuntimeException.createArithmeticException(LocalizedFormats.ZERO_NORM);
    903            }
    904            return mapDivide(norm);
    905        }
    906
    907        /** {@inheritDoc} */
    908        @Override
    909        public void unitize() throws ArithmeticException {
    910            final double norm = getNorm();
    911            if (norm == 0) {
    912                throw MathRuntimeException.createArithmeticException(LocalizedFormats.CANNOT_NORMALIZE_A_ZERO_NORM_VECTOR);
    913            }
    914            mapDivideToSelf(norm);
    915        }
    916
    917        /** {@inheritDoc} */
    918        public RealVector projection(RealVector v) {
    919            return v.mapMultiply(dotProduct(v) / v.dotProduct(v));
    920        }
    921
    922        /** {@inheritDoc} */
    923        @Override
    924        public RealVector projection(double[] v) {
    925            return projection(new ArrayRealVector(v, false));
    926        }
    927
    928       /** Find the orthogonal projection of this vector onto another vector.
    929         * @param v vector onto which instance must be projected
    930         * @return projection of the instance onto v
    931         * @throws IllegalArgumentException if v is not the same size as this
    932         */
    933        public ArrayRealVector projection(ArrayRealVector v) {
    934            return (ArrayRealVector) v.mapMultiply(dotProduct(v) / v.dotProduct(v));
    935        }
    936
    937        /** {@inheritDoc} */
    938        @Override
    939        public RealMatrix outerProduct(RealVector v)
    940            throws IllegalArgumentException {
    941            if (v instanceof ArrayRealVector) {
    942                return outerProduct((ArrayRealVector) v);
    943            } else {
    944                checkVectorDimensions(v);
    945                final int m = data.length;
    946                final RealMatrix out = MatrixUtils.createRealMatrix(m, m);
    947                for (int i = 0; i < data.length; i++) {
    948                    for (int j = 0; j < data.length; j++) {
    949                        out.setEntry(i, j, data[i] * v.getEntry(j));
    950                    }
    951                }
    952                return out;
    953            }
    954        }
    955
    956        /**
    957         * Compute the outer product.
    958         * @param v vector with which outer product should be computed
    959         * @return the square matrix outer product between instance and v
    960         * @exception IllegalArgumentException if v is not the same size as this
    961         */
    962        public RealMatrix outerProduct(ArrayRealVector v)
    963            throws IllegalArgumentException {
    964            return outerProduct(v.data);
    965        }
    966
    967        /** {@inheritDoc} */
    968        @Override
    969        public RealMatrix outerProduct(double[] v)
    970            throws IllegalArgumentException {
    971            checkVectorDimensions(v.length);
    972            final int m = data.length;
    973            final RealMatrix out = MatrixUtils.createRealMatrix(m, m);
    974            for (int i = 0; i < data.length; i++) {
    975                for (int j = 0; j < data.length; j++) {
    976                    out.setEntry(i, j, data[i] * v[j]);
    977                }
    978            }
    979            return out;
    980        }
    981
    982        /** {@inheritDoc} */
    983        public double getEntry(int index) throws MatrixIndexException {
    984            return data[index];
    985        }
    986
    987        /** {@inheritDoc} */
    988        public int getDimension() {
    989            return data.length;
    990        }
    991
    992        /** {@inheritDoc} */
    993        public RealVector append(RealVector v) {
    994            try {
    995                return new ArrayRealVector(this, (ArrayRealVector) v);
    996            } catch (ClassCastException cce) {
    997                return new ArrayRealVector(this, v);
    998            }
    999        }
    1000
    1001        /**
    1002         * Construct a vector by appending a vector to this vector.
    1003         * @param v vector to append to this one.
    1004         * @return a new vector
    1005         */
    1006        public ArrayRealVector append(ArrayRealVector v) {
    1007            return new ArrayRealVector(this, v);
    1008        }
    1009
    1010        /** {@inheritDoc} */
    1011        public RealVector append(double in) {
    1012            final double[] out = new double[data.length + 1];
    1013            System.arraycopy(data, 0, out, 0, data.length);
    1014            out[data.length] = in;
    1015            return new ArrayRealVector(out, false);
    1016        }
    1017
    1018        /** {@inheritDoc} */
    1019        public RealVector append(double[] in) {
    1020            return new ArrayRealVector(this, in);
    1021        }
    1022
    1023        /** {@inheritDoc} */
    1024        public RealVector getSubVector(int index, int n) {
    1025            ArrayRealVector out = new ArrayRealVector(n);
    1026            try {
    1027                System.arraycopy(data, index, out.data, 0, n);
    1028            } catch (IndexOutOfBoundsException e) {
    1029                checkIndex(index);
    1030                checkIndex(index + n - 1);
    1031            }
    1032            return out;
    1033        }
    1034
    1035        /** {@inheritDoc} */
    1036        public void setEntry(int index, double value) {
    1037            try {
    1038                data[index] = value;
    1039            } catch (IndexOutOfBoundsException e) {
    1040                checkIndex(index);
    1041            }
    1042        }
    1043
    1044        /** {@inheritDoc} */
    1045        @Override
    1046        public void setSubVector(int index, RealVector v) {
    1047            try {
    1048                try {
    1049                    set(index, (ArrayRealVector) v);
    1050                } catch (ClassCastException cce) {
    1051                    for (int i = index; i < index + v.getDimension(); ++i) {
    1052                        data[i] = v.getEntry(i-index);
    1053                    }
    1054                }
    1055            } catch (IndexOutOfBoundsException e) {
    1056                checkIndex(index);
    1057                checkIndex(index + v.getDimension() - 1);
    1058            }
    1059        }
    1060
    1061        /** {@inheritDoc} */
    1062        @Override
    1063        public void setSubVector(int index, double[] v) {
    1064            try {
    1065                System.arraycopy(v, 0, data, index, v.length);
    1066            } catch (IndexOutOfBoundsException e) {
    1067                checkIndex(index);
    1068                checkIndex(index + v.length - 1);
    1069            }
    1070        }
    1071
    1072        /**
    1073         * Set a set of consecutive elements.
    1074         *
    1075         * @param index index of first element to be set.
    1076         * @param v vector containing the values to set.
    1077         * @exception MatrixIndexException if the index is
    1078         * inconsistent with vector size
    1079         */
    1080        public void set(int index, ArrayRealVector v)
    1081            throws MatrixIndexException {
    1082            setSubVector(index, v.data);
    1083        }
    1084
    1085        /** {@inheritDoc} */
    1086        @Override
    1087        public void set(double value) {
    1088            Arrays.fill(data, value);
    1089        }
    1090
    1091        /** {@inheritDoc} */
    1092        @Override
    1093        public double[] toArray(){
    1094            return data.clone();
    1095        }
    1096
    1097        /** {@inheritDoc} */
    1098        @Override
    1099        public String toString(){
    1100            return DEFAULT_FORMAT.format(this);
    1101        }
    1102
    1103        /**
    1104         * Check if instance and specified vectors have the same dimension.
    1105         * @param v vector to compare instance with
    1106         * @exception IllegalArgumentException if the vectors do not
    1107         * have the same dimension
    1108         */
    1109        @Override
    1110        protected void checkVectorDimensions(RealVector v)
    1111            throws IllegalArgumentException {
    1112            checkVectorDimensions(v.getDimension());
    1113        }
    1114
    1115        /**
    1116         * Check if instance dimension is equal to some expected value.
    1117         *
    1118         * @param n expected dimension.
    1119         * @exception IllegalArgumentException if the dimension is
    1120         * inconsistent with vector size
    1121         */
    1122        @Override
    1123        protected void checkVectorDimensions(int n)
    1124            throws IllegalArgumentException {
    1125            if (data.length != n) {
    1126                throw MathRuntimeException.createIllegalArgumentException(
    1127                        LocalizedFormats.VECTOR_LENGTH_MISMATCH,
    1128                        data.length, n);
    1129            }
    1130        }
    1131
    1132        /**
    1133         * Returns true if any coordinate of this vector is NaN; false otherwise
    1134         * @return  true if any coordinate of this vector is NaN; false otherwise
    1135         */
    1136        public boolean isNaN() {
    1137            for (double v : data) {
    1138                if (Double.isNaN(v)) {
    1139                    return true;
    1140                }
    1141            }
    1142            return false;
    1143        }
    1144
    1145        /**
    1146         * Returns true if any coordinate of this vector is infinite and none are NaN;
    1147         * false otherwise
    1148         * @return  true if any coordinate of this vector is infinite and none are NaN;
    1149         * false otherwise
    1150         */
    1151        public boolean isInfinite() {
    1152
    1153            if (isNaN()) {
    1154                return false;
    1155            }
    1156
    1157            for (double v : data) {
    1158                if (Double.isInfinite(v)) {
    1159                    return true;
    1160                }
    1161            }
    1162
    1163            return false;
    1164
    1165        }
    1166
    1167        /**
    1168         * Test for the equality of two real vectors.
    1169         * <p>
    1170         * If all coordinates of two real vectors are exactly the same, and none are
    1171         * <code>Double.NaN</code>, the two real vectors are considered to be equal.
    1172         * </p>
    1173         * <p>
    1174         * <code>NaN</code> coordinates are considered to affect globally the vector
    1175         * and be equals to each other - i.e, if either (or all) coordinates of the
    1176         * real vector are equal to <code>Double.NaN</code>, the real vector is equal to
    1177         * a vector with all <code>Double.NaN</code> coordinates.
    1178         * </p>
    1179         *
    1180         * @param other Object to test for equality to this
    1181         * @return true if two vector objects are equal, false if
    1182         *         object is null, not an instance of RealVector, or
    1183         *         not equal to this RealVector instance
    1184         *
    1185         */
    1186        @Override
    1187        public boolean equals(Object other) {
    1188
    1189          if (this == other) {
    1190            return true;
    1191          }
    1192
    1193          if (other == null || !(other instanceof RealVector)) {
    1194            return false;
    1195          }
    1196
    1197
    1198          RealVector rhs = (RealVector) other;
    1199          if (data.length != rhs.getDimension()) {
    1200            return false;
    1201          }
    1202
    1203          if (rhs.isNaN()) {
    1204            return this.isNaN();
    1205          }
    1206
    1207          for (int i = 0; i < data.length; ++i) {
    1208            if (data[i] != rhs.getEntry(i)) {
    1209              return false;
    1210            }
    1211          }
    1212          return true;
    1213        }
    1214
    1215        /**
    1216         * Get a hashCode for the real vector.
    1217         * <p>All NaN values have the same hash code.</p>
    1218         * @return a hash code value for this object
    1219         */
    1220        @Override
    1221        public int hashCode() {
    1222            if (isNaN()) {
    1223                return 9;
    1224            }
    1225            return MathUtils.hash(data);
    1226        }
    1227
    1228    }