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 */
17package org.apache.commons.math.linear;
18
19import java.io.Serializable;
20import java.util.Arrays;
21import java.util.Iterator;
22
23import org.apache.commons.math.MathRuntimeException;
24import org.apache.commons.math.exception.util.LocalizedFormats;
25import org.apache.commons.math.util.MathUtils;
26import 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 */
33public 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