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