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