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    *      https://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  
18  /*
19   * This is not the original file distributed by the Apache Software Foundation
20   * It has been modified by the Hipparchus project
21   */
22  package org.hipparchus.linear;
23  
24  import java.io.Serializable;
25  import java.util.Arrays;
26  import java.util.Iterator;
27  
28  import org.hipparchus.analysis.UnivariateFunction;
29  import org.hipparchus.exception.LocalizedCoreFormats;
30  import org.hipparchus.exception.MathIllegalArgumentException;
31  import org.hipparchus.exception.NullArgumentException;
32  import org.hipparchus.util.FastMath;
33  import org.hipparchus.util.MathUtils;
34  
35  /**
36   * This class implements the {@link RealVector} interface with a double array.
37   */
38  public class ArrayRealVector extends RealVector implements Serializable {
39      /** Serializable version identifier. */
40      private static final long serialVersionUID = -1097961340710804027L;
41      /** Default format. */
42      private static final RealVectorFormat DEFAULT_FORMAT = RealVectorFormat.getRealVectorFormat();
43  
44      /** Entries of the vector. */
45      private double data[];
46  
47      /**
48       * Build a 0-length vector.
49       * Zero-length vectors may be used to initialized construction of vectors
50       * by data gathering. We start with zero-length and use either the {@link
51       * #ArrayRealVector(ArrayRealVector, ArrayRealVector)} constructor
52       * or one of the {@code append} method ({@link #append(double)},
53       * {@link #append(ArrayRealVector)}) to gather data into this vector.
54       */
55      public ArrayRealVector() {
56          data = new double[0];
57      }
58  
59      /**
60       * Construct a vector of zeroes.
61       *
62       * @param size Size of the vector.
63       */
64      public ArrayRealVector(int size) {
65          data = new double[size];
66      }
67  
68      /**
69       * Construct a vector with preset values.
70       *
71       * @param size Size of the vector
72       * @param preset All entries will be set with this value.
73       */
74      public ArrayRealVector(int size, double preset) {
75          data = new double[size];
76          Arrays.fill(data, preset);
77      }
78  
79      /**
80       * Construct a vector from an array, copying the input array.
81       *
82       * @param d Array.
83       */
84      public ArrayRealVector(double[] d) {
85          data = d.clone();
86      }
87  
88      /**
89       * Create a new ArrayRealVector using the input array as the underlying
90       * data array.
91       * If an array is built specially in order to be embedded in a
92       * ArrayRealVector and not used directly, the {@code copyArray} may be
93       * set to {@code false}. This will prevent the copying and improve
94       * performance as no new array will be built and no data will be copied.
95       *
96       * @param d Data for the new vector.
97       * @param copyArray if {@code true}, the input array will be copied,
98       * otherwise it will be referenced.
99       * @throws NullArgumentException if {@code d} is {@code null}.
100      * @see #ArrayRealVector(double[])
101      */
102     public ArrayRealVector(double[] d, boolean copyArray)
103         throws NullArgumentException {
104         if (d == null) {
105             throw new NullArgumentException();
106         }
107         data = copyArray ? d.clone() :  d;
108     }
109 
110     /**
111      * Construct a vector from part of a array.
112      *
113      * @param d Array.
114      * @param pos Position of first entry.
115      * @param size Number of entries to copy.
116      * @throws NullArgumentException if {@code d} is {@code null}.
117      * @throws MathIllegalArgumentException if the size of {@code d} is less
118      * than {@code pos + size}.
119      */
120     public ArrayRealVector(double[] d, int pos, int size)
121         throws MathIllegalArgumentException, NullArgumentException {
122         if (d == null) {
123             throw new NullArgumentException();
124         }
125         if (d.length < pos + size) {
126             throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_LARGE,
127                                                    pos + size, d.length);
128         }
129         data = new double[size];
130         System.arraycopy(d, pos, data, 0, size);
131     }
132 
133     /**
134      * Construct a vector from an array.
135      *
136      * @param d Array of {@code Double}s.
137      */
138     public ArrayRealVector(Double[] d) {
139         data = new double[d.length];
140         for (int i = 0; i < d.length; i++) {
141             data[i] = d[i].doubleValue();
142         }
143     }
144 
145     /**
146      * Construct a vector from part of an array.
147      *
148      * @param d Array.
149      * @param pos Position of first entry.
150      * @param size Number of entries to copy.
151      * @throws NullArgumentException if {@code d} is {@code null}.
152      * @throws MathIllegalArgumentException if the size of {@code d} is less
153      * than {@code pos + size}.
154      */
155     public ArrayRealVector(Double[] d, int pos, int size)
156         throws MathIllegalArgumentException, NullArgumentException {
157         if (d == null) {
158             throw new NullArgumentException();
159         }
160         if (d.length < pos + size) {
161             throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_LARGE,
162                                                    pos + size, d.length);
163         }
164         data = new double[size];
165         for (int i = pos; i < pos + size; i++) {
166             data[i - pos] = d[i].doubleValue();
167         }
168     }
169 
170     /**
171      * Construct a vector from another vector, using a deep copy.
172      *
173      * @param v vector to copy.
174      * @throws NullArgumentException if {@code v} is {@code null}.
175      */
176     public ArrayRealVector(RealVector v) throws NullArgumentException {
177         if (v == null) {
178             throw new NullArgumentException();
179         }
180         data = new double[v.getDimension()];
181         for (int i = 0; i < data.length; ++i) {
182             data[i] = v.getEntry(i);
183         }
184     }
185 
186     /**
187      * Construct a vector from another vector, using a deep copy.
188      *
189      * @param v Vector to copy.
190      * @throws NullArgumentException if {@code v} is {@code null}.
191      */
192     public ArrayRealVector(ArrayRealVector v) throws NullArgumentException {
193         this(v, true);
194     }
195 
196     /**
197      * Construct a vector from another vector.
198      *
199      * @param v Vector to copy.
200      * @param deep If {@code true} perform a deep copy, otherwise perform a
201      * shallow copy.
202      */
203     public ArrayRealVector(ArrayRealVector v, boolean deep) {
204         data = deep ? v.data.clone() : v.data;
205     }
206 
207     /**
208      * Construct a vector by appending one vector to another vector.
209      * @param v1 First vector (will be put in front of the new vector).
210      * @param v2 Second vector (will be put at back of the new vector).
211      */
212     public ArrayRealVector(ArrayRealVector v1, ArrayRealVector v2) {
213         data = new double[v1.data.length + v2.data.length];
214         System.arraycopy(v1.data, 0, data, 0, v1.data.length);
215         System.arraycopy(v2.data, 0, data, v1.data.length, v2.data.length);
216     }
217 
218     /**
219      * Construct a vector by appending one vector to another vector.
220      * @param v1 First vector (will be put in front of the new vector).
221      * @param v2 Second vector (will be put at back of the new vector).
222      */
223     public ArrayRealVector(ArrayRealVector v1, RealVector v2) {
224         final int l1 = v1.data.length;
225         final int l2 = v2.getDimension();
226         data = new double[l1 + l2];
227         System.arraycopy(v1.data, 0, data, 0, l1);
228         for (int i = 0; i < l2; ++i) {
229             data[l1 + i] = v2.getEntry(i);
230         }
231     }
232 
233     /**
234      * Construct a vector by appending one vector to another vector.
235      * @param v1 First vector (will be put in front of the new vector).
236      * @param v2 Second vector (will be put at back of the new vector).
237      */
238     public ArrayRealVector(RealVector v1, ArrayRealVector v2) {
239         final int l1 = v1.getDimension();
240         final int l2 = v2.data.length;
241         data = new double[l1 + l2];
242         for (int i = 0; i < l1; ++i) {
243             data[i] = v1.getEntry(i);
244         }
245         System.arraycopy(v2.data, 0, data, l1, l2);
246     }
247 
248     /**
249      * Construct a vector by appending one vector to another vector.
250      * @param v1 First vector (will be put in front of the new vector).
251      * @param v2 Second vector (will be put at back of the new vector).
252      */
253     public ArrayRealVector(ArrayRealVector v1, double[] v2) {
254         final int l1 = v1.getDimension();
255         final int l2 = v2.length;
256         data = new double[l1 + l2];
257         System.arraycopy(v1.data, 0, data, 0, l1);
258         System.arraycopy(v2, 0, data, l1, l2);
259     }
260 
261     /**
262      * Construct a vector by appending one vector to another vector.
263      * @param v1 First vector (will be put in front of the new vector).
264      * @param v2 Second vector (will be put at back of the new vector).
265      */
266     public ArrayRealVector(double[] v1, ArrayRealVector v2) {
267         final int l1 = v1.length;
268         final int l2 = v2.getDimension();
269         data = new double[l1 + l2];
270         System.arraycopy(v1, 0, data, 0, l1);
271         System.arraycopy(v2.data, 0, data, l1, l2);
272     }
273 
274     /**
275      * Construct a vector by appending one vector to another vector.
276      * @param v1 first vector (will be put in front of the new vector)
277      * @param v2 second vector (will be put at back of the new vector)
278      */
279     public ArrayRealVector(double[] v1, double[] v2) {
280         final int l1 = v1.length;
281         final int l2 = v2.length;
282         data = new double[l1 + l2];
283         System.arraycopy(v1, 0, data, 0, l1);
284         System.arraycopy(v2, 0, data, l1, l2);
285     }
286 
287     /** {@inheritDoc} */
288     @Override
289     public ArrayRealVector copy() {
290         return new ArrayRealVector(this, true);
291     }
292 
293     /** {@inheritDoc} */
294     @Override
295     public ArrayRealVector add(RealVector v)
296         throws MathIllegalArgumentException {
297         if (v instanceof ArrayRealVector) {
298             final double[] vData = ((ArrayRealVector) v).data;
299             final int dim = vData.length;
300             checkVectorDimensions(dim);
301             ArrayRealVector result = new ArrayRealVector(dim);
302             double[] resultData = result.data;
303             for (int i = 0; i < dim; i++) {
304                 resultData[i] = data[i] + vData[i];
305             }
306             return result;
307         } else {
308             checkVectorDimensions(v);
309             double[] out = data.clone();
310             Iterator<Entry> it = v.iterator();
311             while (it.hasNext()) {
312                 final Entry e = it.next();
313                 out[e.getIndex()] += e.getValue();
314             }
315             return new ArrayRealVector(out, false);
316         }
317     }
318 
319     /** {@inheritDoc} */
320     @Override
321     public ArrayRealVector subtract(RealVector v)
322         throws MathIllegalArgumentException {
323         if (v instanceof ArrayRealVector) {
324             final double[] vData = ((ArrayRealVector) v).data;
325             final int dim = vData.length;
326             checkVectorDimensions(dim);
327             ArrayRealVector result = new ArrayRealVector(dim);
328             double[] resultData = result.data;
329             for (int i = 0; i < dim; i++) {
330                 resultData[i] = data[i] - vData[i];
331             }
332             return result;
333         } else {
334             checkVectorDimensions(v);
335             double[] out = data.clone();
336             Iterator<Entry> it = v.iterator();
337             while (it.hasNext()) {
338                 final Entry e = it.next();
339                 out[e.getIndex()] -= e.getValue();
340             }
341             return new ArrayRealVector(out, false);
342         }
343     }
344 
345     /** {@inheritDoc} */
346     @Override
347     public ArrayRealVector map(UnivariateFunction function) {
348         return copy().mapToSelf(function);
349     }
350 
351     /** {@inheritDoc} */
352     @Override
353     public ArrayRealVector mapToSelf(UnivariateFunction function) {
354         for (int i = 0; i < data.length; i++) {
355             data[i] = function.value(data[i]);
356         }
357         return this;
358     }
359 
360     /** {@inheritDoc} */
361     @Override
362     public RealVector mapAddToSelf(double d) {
363         for (int i = 0; i < data.length; i++) {
364             data[i] += d;
365         }
366         return this;
367     }
368 
369     /** {@inheritDoc} */
370     @Override
371     public RealVector mapSubtractToSelf(double d) {
372         for (int i = 0; i < data.length; i++) {
373             data[i] -= d;
374         }
375         return this;
376     }
377 
378     /** {@inheritDoc} */
379     @Override
380     public RealVector mapMultiplyToSelf(double d) {
381         for (int i = 0; i < data.length; i++) {
382             data[i] *= d;
383         }
384         return this;
385     }
386 
387     /** {@inheritDoc} */
388     @Override
389     public RealVector mapDivideToSelf(double d) {
390         for (int i = 0; i < data.length; i++) {
391             data[i] /= d;
392         }
393         return this;
394     }
395 
396     /** {@inheritDoc} */
397     @Override
398     public ArrayRealVector ebeMultiply(RealVector v)
399         throws MathIllegalArgumentException {
400         if (v instanceof ArrayRealVector) {
401             final double[] vData = ((ArrayRealVector) v).data;
402             final int dim = vData.length;
403             checkVectorDimensions(dim);
404             ArrayRealVector result = new ArrayRealVector(dim);
405             double[] resultData = result.data;
406             for (int i = 0; i < dim; i++) {
407                 resultData[i] = data[i] * vData[i];
408             }
409             return result;
410         } else {
411             checkVectorDimensions(v);
412             double[] out = data.clone();
413             for (int i = 0; i < data.length; i++) {
414                 out[i] *= v.getEntry(i);
415             }
416             return new ArrayRealVector(out, false);
417         }
418     }
419 
420     /** {@inheritDoc} */
421     @Override
422     public ArrayRealVector ebeDivide(RealVector v)
423         throws MathIllegalArgumentException {
424         if (v instanceof ArrayRealVector) {
425             final double[] vData = ((ArrayRealVector) v).data;
426             final int dim = vData.length;
427             checkVectorDimensions(dim);
428             ArrayRealVector result = new ArrayRealVector(dim);
429             double[] resultData = result.data;
430             for (int i = 0; i < dim; i++) {
431                 resultData[i] = data[i] / vData[i];
432             }
433             return result;
434         } else {
435             checkVectorDimensions(v);
436             double[] out = data.clone();
437             for (int i = 0; i < data.length; i++) {
438                 out[i] /= v.getEntry(i);
439             }
440             return new ArrayRealVector(out, false);
441         }
442     }
443 
444     /**
445      * Get a reference to the underlying data array.
446      * This method does not make a fresh copy of the underlying data.
447      *
448      * @return the array of entries.
449      */
450     public double[] getDataRef() {
451         return data; // NOPMD - returning an internal array is intentional and documented here
452     }
453 
454     /** {@inheritDoc} */
455     @Override
456     public double dotProduct(RealVector v) throws MathIllegalArgumentException {
457         if (v instanceof ArrayRealVector) {
458             final double[] vData = ((ArrayRealVector) v).data;
459             checkVectorDimensions(vData.length);
460             double dot = 0;
461             for (int i = 0; i < data.length; i++) {
462                 dot += data[i] * vData[i];
463             }
464             return dot;
465         }
466         return super.dotProduct(v);
467     }
468 
469     /** {@inheritDoc} */
470     @Override
471     public double getNorm() {
472         double sum = 0;
473         for (double a : data) {
474             sum += a * a;
475         }
476         return FastMath.sqrt(sum);
477     }
478 
479     /** {@inheritDoc} */
480     @Override
481     public double getL1Norm() {
482         double sum = 0;
483         for (double a : data) {
484             sum += FastMath.abs(a);
485         }
486         return sum;
487     }
488 
489     /** {@inheritDoc} */
490     @Override
491     public double getLInfNorm() {
492         double max = 0;
493         for (double a : data) {
494             max = FastMath.max(max, FastMath.abs(a));
495         }
496         return max;
497     }
498 
499     /** {@inheritDoc} */
500     @Override
501     public double getDistance(RealVector v) throws MathIllegalArgumentException {
502         if (v instanceof ArrayRealVector) {
503             final double[] vData = ((ArrayRealVector) v).data;
504             checkVectorDimensions(vData.length);
505             double sum = 0;
506             for (int i = 0; i < data.length; ++i) {
507                 final double delta = data[i] - vData[i];
508                 sum += delta * delta;
509             }
510             return FastMath.sqrt(sum);
511         } else {
512             checkVectorDimensions(v);
513             double sum = 0;
514             for (int i = 0; i < data.length; ++i) {
515                 final double delta = data[i] - v.getEntry(i);
516                 sum += delta * delta;
517             }
518             return FastMath.sqrt(sum);
519         }
520     }
521 
522     /** {@inheritDoc} */
523     @Override
524     public double getL1Distance(RealVector v)
525         throws MathIllegalArgumentException {
526         if (v instanceof ArrayRealVector) {
527             final double[] vData = ((ArrayRealVector) v).data;
528             checkVectorDimensions(vData.length);
529             double sum = 0;
530             for (int i = 0; i < data.length; ++i) {
531                 final double delta = data[i] - vData[i];
532                 sum += FastMath.abs(delta);
533             }
534             return sum;
535         } else {
536             checkVectorDimensions(v);
537             double sum = 0;
538             for (int i = 0; i < data.length; ++i) {
539                 final double delta = data[i] - v.getEntry(i);
540                 sum += FastMath.abs(delta);
541             }
542             return sum;
543         }
544     }
545 
546     /** {@inheritDoc} */
547     @Override
548     public double getLInfDistance(RealVector v)
549         throws MathIllegalArgumentException {
550         if (v instanceof ArrayRealVector) {
551             final double[] vData = ((ArrayRealVector) v).data;
552             checkVectorDimensions(vData.length);
553             double max = 0;
554             for (int i = 0; i < data.length; ++i) {
555                 final double delta = data[i] - vData[i];
556                 max = FastMath.max(max, FastMath.abs(delta));
557             }
558             return max;
559         } else {
560             checkVectorDimensions(v);
561             double max = 0;
562             for (int i = 0; i < data.length; ++i) {
563                 final double delta = data[i] - v.getEntry(i);
564                 max = FastMath.max(max, FastMath.abs(delta));
565             }
566             return max;
567         }
568     }
569 
570     /** {@inheritDoc} */
571     @Override
572     public RealMatrix outerProduct(RealVector v) {
573         if (v instanceof ArrayRealVector) {
574             final double[] vData = ((ArrayRealVector) v).data;
575             final int m = data.length;
576             final int n = vData.length;
577             final RealMatrix out = MatrixUtils.createRealMatrix(m, n);
578             for (int i = 0; i < m; i++) {
579                 for (int j = 0; j < n; j++) {
580                     out.setEntry(i, j, data[i] * vData[j]);
581                 }
582             }
583             return out;
584         } else {
585             final int m = data.length;
586             final int n = v.getDimension();
587             final RealMatrix out = MatrixUtils.createRealMatrix(m, n);
588             for (int i = 0; i < m; i++) {
589                 for (int j = 0; j < n; j++) {
590                     out.setEntry(i, j, data[i] * v.getEntry(j));
591                 }
592             }
593             return out;
594         }
595     }
596 
597     /** {@inheritDoc} */
598     @Override
599     public double getEntry(int index) throws MathIllegalArgumentException {
600         try {
601             return data[index];
602         } catch (IndexOutOfBoundsException e) {
603             throw new MathIllegalArgumentException(e, LocalizedCoreFormats.INDEX, index, 0, getDimension() - 1);
604         }
605     }
606 
607     /** {@inheritDoc} */
608     @Override
609     public int getDimension() {
610         return data.length;
611     }
612 
613     /** {@inheritDoc} */
614     @Override
615     public RealVector append(RealVector v) {
616         if (v instanceof ArrayRealVector) {
617             return new ArrayRealVector(this, (ArrayRealVector) v);
618         } else {
619             return new ArrayRealVector(this, v);
620         }
621     }
622 
623     /**
624      * Construct a vector by appending a vector to this vector.
625      *
626      * @param v Vector to append to this one.
627      * @return a new vector.
628      */
629     public ArrayRealVector append(ArrayRealVector v) {
630         return new ArrayRealVector(this, v);
631     }
632 
633     /** {@inheritDoc} */
634     @Override
635     public RealVector append(double in) {
636         final double[] out = new double[data.length + 1];
637         System.arraycopy(data, 0, out, 0, data.length);
638         out[data.length] = in;
639         return new ArrayRealVector(out, false);
640     }
641 
642     /** {@inheritDoc} */
643     @Override
644     public RealVector getSubVector(int index, int n)
645         throws MathIllegalArgumentException {
646         if (n < 0) {
647             throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_OF_ELEMENTS_SHOULD_BE_POSITIVE, n);
648         }
649         ArrayRealVector out = new ArrayRealVector(n);
650         try {
651             System.arraycopy(data, index, out.data, 0, n);
652         } catch (IndexOutOfBoundsException e) {
653             checkIndex(index);
654             checkIndex(index + n - 1);
655         }
656         return out;
657     }
658 
659     /** {@inheritDoc} */
660     @Override
661     public void setEntry(int index, double value) throws MathIllegalArgumentException {
662         try {
663             data[index] = value;
664         } catch (IndexOutOfBoundsException e) {
665             checkIndex(index);
666         }
667     }
668 
669     /** {@inheritDoc} */
670     @Override
671     public void addToEntry(int index, double increment)
672         throws MathIllegalArgumentException {
673         try {
674         data[index] += increment;
675         } catch(IndexOutOfBoundsException e){
676             throw new MathIllegalArgumentException(e, LocalizedCoreFormats.INDEX, index, 0, data.length - 1);
677         }
678     }
679 
680     /** {@inheritDoc} */
681     @Override
682     public void setSubVector(int index, RealVector v)
683         throws MathIllegalArgumentException {
684         if (v instanceof ArrayRealVector) {
685             setSubVector(index, ((ArrayRealVector) v).data);
686         } else {
687             try {
688                 for (int i = index; i < index + v.getDimension(); ++i) {
689                     data[i] = v.getEntry(i - index);
690                 }
691             } catch (IndexOutOfBoundsException e) {
692                 checkIndex(index);
693                 checkIndex(index + v.getDimension() - 1);
694             }
695         }
696     }
697 
698     /**
699      * Set a set of consecutive elements.
700      *
701      * @param index Index of first element to be set.
702      * @param v Vector containing the values to set.
703      * @throws MathIllegalArgumentException if the index is inconsistent with the vector
704      * size.
705      */
706     public void setSubVector(int index, double[] v)
707         throws MathIllegalArgumentException {
708         try {
709             System.arraycopy(v, 0, data, index, v.length);
710         } catch (IndexOutOfBoundsException e) {
711             checkIndex(index);
712             checkIndex(index + v.length - 1);
713         }
714     }
715 
716     /** {@inheritDoc} */
717     @Override
718     public void set(double value) {
719         Arrays.fill(data, value);
720     }
721 
722     /** {@inheritDoc} */
723     @Override
724     public double[] toArray(){
725         return data.clone();
726     }
727 
728     /** {@inheritDoc} */
729     @Override
730     public String toString(){
731         return DEFAULT_FORMAT.format(this);
732     }
733 
734     /**
735      * Check if instance and specified vectors have the same dimension.
736      *
737      * @param v Vector to compare instance with.
738      * @throws MathIllegalArgumentException if the vectors do not
739      * have the same dimension.
740      */
741     @Override
742     protected void checkVectorDimensions(RealVector v)
743         throws MathIllegalArgumentException {
744         checkVectorDimensions(v.getDimension());
745     }
746 
747     /**
748      * Check if instance dimension is equal to some expected value.
749      *
750      * @param n Expected dimension.
751      * @throws MathIllegalArgumentException if the dimension is
752      * inconsistent with vector size.
753      */
754     @Override
755     protected void checkVectorDimensions(int n)
756         throws MathIllegalArgumentException {
757         if (data.length != n) {
758             throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
759                                                    data.length, n);
760         }
761     }
762 
763     /**
764      * Check if any coordinate of this vector is {@code NaN}.
765      *
766      * @return {@code true} if any coordinate of this vector is {@code NaN},
767      * {@code false} otherwise.
768      */
769     @Override
770     public boolean isNaN() {
771         for (double v : data) {
772             if (Double.isNaN(v)) {
773                 return true;
774             }
775         }
776         return false;
777     }
778 
779     /**
780      * Check whether any coordinate of this vector is infinite and none
781      * are {@code NaN}.
782      *
783      * @return {@code true} if any coordinate of this vector is infinite and
784      * none are {@code NaN}, {@code false} otherwise.
785      */
786     @Override
787     public boolean isInfinite() {
788         if (isNaN()) {
789             return false;
790         }
791 
792         for (double v : data) {
793             if (Double.isInfinite(v)) {
794                 return true;
795             }
796         }
797 
798         return false;
799     }
800 
801     /** {@inheritDoc} */
802     @Override
803     public boolean equals(Object other) {
804         if (this == other) {
805             return true;
806         }
807 
808         if (!(other instanceof RealVector)) {
809             return false;
810         }
811 
812         RealVector rhs = (RealVector) other;
813         if (data.length != rhs.getDimension()) {
814             return false;
815         }
816 
817         if (rhs.isNaN()) {
818             return this.isNaN();
819         }
820 
821         for (int i = 0; i < data.length; ++i) {
822             if (data[i] != rhs.getEntry(i)) {
823                 return false;
824             }
825         }
826         return true;
827     }
828 
829     /**
830      * {@inheritDoc} All {@code NaN} values have the same hash code.
831      */
832     @Override
833     public int hashCode() {
834         if (isNaN()) {
835             return 9;
836         }
837         return MathUtils.hash(data);
838     }
839 
840     /** {@inheritDoc} */
841     @Override
842     public ArrayRealVector combine(double a, double b, RealVector y)
843         throws MathIllegalArgumentException {
844         return copy().combineToSelf(a, b, y);
845     }
846 
847     /** {@inheritDoc} */
848     @Override
849     public ArrayRealVector combineToSelf(double a, double b, RealVector y)
850         throws MathIllegalArgumentException {
851         if (y instanceof ArrayRealVector) {
852             final double[] yData = ((ArrayRealVector) y).data;
853             checkVectorDimensions(yData.length);
854             for (int i = 0; i < this.data.length; i++) {
855                 data[i] = a * data[i] + b * yData[i];
856             }
857         } else {
858             checkVectorDimensions(y);
859             for (int i = 0; i < this.data.length; i++) {
860                 data[i] = a * data[i] + b * y.getEntry(i);
861             }
862         }
863         return this;
864     }
865 
866     /** {@inheritDoc} */
867     @Override
868     public double walkInDefaultOrder(final RealVectorPreservingVisitor visitor) {
869         visitor.start(data.length, 0, data.length - 1);
870         for (int i = 0; i < data.length; i++) {
871             visitor.visit(i, data[i]);
872         }
873         return visitor.end();
874     }
875 
876     /** {@inheritDoc} */
877     @Override
878     public double walkInDefaultOrder(final RealVectorPreservingVisitor visitor,
879         final int start, final int end) throws MathIllegalArgumentException {
880         checkIndices(start, end);
881         visitor.start(data.length, start, end);
882         for (int i = start; i <= end; i++) {
883             visitor.visit(i, data[i]);
884         }
885         return visitor.end();
886     }
887 
888     /**
889      * {@inheritDoc}
890      *
891      * In this implementation, the optimized order is the default order.
892      */
893     @Override
894     public double walkInOptimizedOrder(final RealVectorPreservingVisitor visitor) {
895         return walkInDefaultOrder(visitor);
896     }
897 
898     /**
899      * {@inheritDoc}
900      *
901      * In this implementation, the optimized order is the default order.
902      */
903     @Override
904     public double walkInOptimizedOrder(final RealVectorPreservingVisitor visitor,
905         final int start, final int end) throws MathIllegalArgumentException {
906         return walkInDefaultOrder(visitor, start, end);
907     }
908 
909     /** {@inheritDoc} */
910     @Override
911     public double walkInDefaultOrder(final RealVectorChangingVisitor visitor) {
912         visitor.start(data.length, 0, data.length - 1);
913         for (int i = 0; i < data.length; i++) {
914             data[i] = visitor.visit(i, data[i]);
915         }
916         return visitor.end();
917     }
918 
919     /** {@inheritDoc} */
920     @Override
921     public double walkInDefaultOrder(final RealVectorChangingVisitor visitor,
922         final int start, final int end) throws MathIllegalArgumentException {
923         checkIndices(start, end);
924         visitor.start(data.length, start, end);
925         for (int i = start; i <= end; i++) {
926             data[i] = visitor.visit(i, data[i]);
927         }
928         return visitor.end();
929     }
930 
931     /**
932      * {@inheritDoc}
933      *
934      * In this implementation, the optimized order is the default order.
935      */
936     @Override
937     public double walkInOptimizedOrder(final RealVectorChangingVisitor visitor) {
938         return walkInDefaultOrder(visitor);
939     }
940 
941     /**
942      * {@inheritDoc}
943      *
944      * In this implementation, the optimized order is the default order.
945      */
946     @Override
947     public double walkInOptimizedOrder(final RealVectorChangingVisitor visitor,
948         final int start, final int end) throws MathIllegalArgumentException {
949         return walkInDefaultOrder(visitor, start, end);
950     }
951 }