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    }