View Javadoc

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