Home | History | Annotate | Download | only in linear
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one or more
      3  * contributor license agreements.  See the NOTICE file distributed with
      4  * this work for additional information regarding copyright ownership.
      5  * The ASF licenses this file to You under the Apache License, Version 2.0
      6  * (the "License"); you may not use this file except in compliance with
      7  * the License.  You may obtain a copy of the License at
      8  *
      9  *      http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 package org.apache.commons.math.linear;
     18 
     19 import java.io.Serializable;
     20 import java.util.Arrays;
     21 import java.util.Iterator;
     22 
     23 import org.apache.commons.math.MathRuntimeException;
     24 import org.apache.commons.math.exception.util.LocalizedFormats;
     25 import org.apache.commons.math.util.MathUtils;
     26 import org.apache.commons.math.util.FastMath;
     27 
     28 /**
     29  * This class implements the {@link RealVector} interface with a double array.
     30  * @version $Revision: 1003993 $ $Date: 2010-10-03 18:39:16 +0200 (dim. 03 oct. 2010) $
     31  * @since 2.0
     32  */
     33 public class ArrayRealVector extends AbstractRealVector implements Serializable {
     34 
     35     /** Serializable version identifier. */
     36     private static final long serialVersionUID = -1097961340710804027L;
     37 
     38     /** Default format. */
     39     private static final RealVectorFormat DEFAULT_FORMAT =
     40         RealVectorFormat.getInstance();
     41 
     42     /** Entries of the vector. */
     43     protected double data[];
     44 
     45     /**
     46      * Build a 0-length vector.
     47      * <p>Zero-length vectors may be used to initialized construction of vectors
     48      * by data gathering. We start with zero-length and use either the {@link
     49      * #ArrayRealVector(ArrayRealVector, ArrayRealVector)} constructor
     50      * or one of the <code>append</code> method ({@link #append(double)}, {@link
     51      * #append(double[])}, {@link #append(ArrayRealVector)}) to gather data
     52      * into this vector.</p>
     53      */
     54     public ArrayRealVector() {
     55         data = new double[0];
     56     }
     57 
     58     /**
     59      * Construct a (size)-length vector of zeros.
     60      * @param size size of the vector
     61      */
     62     public ArrayRealVector(int size) {
     63         data = new double[size];
     64     }
     65 
     66     /**
     67      * Construct an (size)-length vector with preset values.
     68      * @param size size of the vector
     69      * @param preset fill the vector with this scalar value
     70      */
     71     public ArrayRealVector(int size, double preset) {
     72         data = new double[size];
     73         Arrays.fill(data, preset);
     74     }
     75 
     76     /**
     77      * Construct a vector from an array, copying the input array.
     78      * @param d array of doubles.
     79      */
     80     public ArrayRealVector(double[] d) {
     81         data = d.clone();
     82     }
     83 
     84     /**
     85      * Create a new ArrayRealVector using the input array as the underlying
     86      * data array.
     87      * <p>If an array is built specially in order to be embedded in a
     88      * ArrayRealVector and not used directly, the <code>copyArray</code> may be
     89      * set to <code>false</code. This will prevent the copying and improve
     90      * performance as no new array will be built and no data will be copied.</p>
     91      * @param d data for new vector
     92      * @param copyArray if true, the input array will be copied, otherwise
     93      * it will be referenced
     94      * @see #ArrayRealVector(double[])
     95      */
     96     public ArrayRealVector(double[] d, boolean copyArray) {
     97         data = copyArray ? d.clone() :  d;
     98     }
     99 
    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 }
   1229