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
18package org.apache.commons.math.linear;
19
20import java.util.Iterator;
21import java.util.NoSuchElementException;
22
23import org.apache.commons.math.FunctionEvaluationException;
24import org.apache.commons.math.exception.MathUnsupportedOperationException;
25import org.apache.commons.math.exception.DimensionMismatchException;
26import org.apache.commons.math.analysis.BinaryFunction;
27import org.apache.commons.math.analysis.ComposableFunction;
28import org.apache.commons.math.analysis.UnivariateRealFunction;
29import org.apache.commons.math.exception.util.LocalizedFormats;
30import org.apache.commons.math.util.FastMath;
31
32/**
33 * This class provides default basic implementations for many methods in the
34 * {@link RealVector} interface.
35 * @version $Revision: 1070725 $ $Date: 2011-02-15 02:31:12 +0100 (mar. 15 févr. 2011) $
36 * @since 2.1
37 */
38public abstract class AbstractRealVector implements RealVector {
39
40    /**
41     * Check if instance and specified vectors have the same dimension.
42     * @param v vector to compare instance with
43     * @exception DimensionMismatchException if the vectors do not
44     * have the same dimension
45     */
46    protected void checkVectorDimensions(RealVector v) {
47        checkVectorDimensions(v.getDimension());
48    }
49
50    /**
51     * Check if instance dimension is equal to some expected value.
52     *
53     * @param n expected dimension.
54     * @exception DimensionMismatchException if the dimension is
55     * inconsistent with vector size
56     */
57    protected void checkVectorDimensions(int n)
58        throws DimensionMismatchException {
59        int d = getDimension();
60        if (d != n) {
61            throw new DimensionMismatchException(d, n);
62        }
63    }
64
65    /**
66     * Check if an index is valid.
67     * @param index index to check
68     * @exception MatrixIndexException if index is not valid
69     */
70    protected void checkIndex(final int index)
71        throws MatrixIndexException {
72        if (index < 0 || index >= getDimension()) {
73            throw new MatrixIndexException(LocalizedFormats.INDEX_OUT_OF_RANGE,
74                                           index, 0, getDimension() - 1);
75        }
76    }
77
78    /** {@inheritDoc} */
79    public void setSubVector(int index, RealVector v) throws MatrixIndexException {
80        checkIndex(index);
81        checkIndex(index + v.getDimension() - 1);
82        setSubVector(index, v.getData());
83    }
84
85    /** {@inheritDoc} */
86    public void setSubVector(int index, double[] v) throws MatrixIndexException {
87        checkIndex(index);
88        checkIndex(index + v.length - 1);
89        for (int i = 0; i < v.length; i++) {
90            setEntry(i + index, v[i]);
91        }
92    }
93
94    /** {@inheritDoc} */
95    public RealVector add(double[] v) throws IllegalArgumentException {
96        double[] result = v.clone();
97        Iterator<Entry> it = sparseIterator();
98        Entry e;
99        while (it.hasNext() && (e = it.next()) != null) {
100            result[e.getIndex()] += e.getValue();
101        }
102        return new ArrayRealVector(result, false);
103    }
104
105    /** {@inheritDoc} */
106    public RealVector add(RealVector v) throws IllegalArgumentException {
107        if (v instanceof ArrayRealVector) {
108            double[] values = ((ArrayRealVector)v).getDataRef();
109            return add(values);
110        }
111        RealVector result = v.copy();
112        Iterator<Entry> it = sparseIterator();
113        Entry e;
114        while (it.hasNext() && (e = it.next()) != null) {
115            final int index = e.getIndex();
116            result.setEntry(index, e.getValue() + result.getEntry(index));
117        }
118        return result;
119    }
120
121    /** {@inheritDoc} */
122    public RealVector subtract(double[] v) throws IllegalArgumentException {
123        double[] result = v.clone();
124        Iterator<Entry> it = sparseIterator();
125        Entry e;
126        while (it.hasNext() && (e = it.next()) != null) {
127            final int index = e.getIndex();
128            result[index] = e.getValue() - result[index];
129        }
130        return new ArrayRealVector(result, false);
131    }
132
133    /** {@inheritDoc} */
134    public RealVector subtract(RealVector v) throws IllegalArgumentException {
135        if (v instanceof ArrayRealVector) {
136            double[] values = ((ArrayRealVector)v).getDataRef();
137            return add(values);
138        }
139        RealVector result = v.copy();
140        Iterator<Entry> it = sparseIterator();
141        Entry e;
142        while (it.hasNext() && (e = it.next()) != null) {
143            final int index = e.getIndex();
144            v.setEntry(index, e.getValue() - result.getEntry(index));
145        }
146        return result;
147    }
148
149    /** {@inheritDoc} */
150    public RealVector mapAdd(double d) {
151        return copy().mapAddToSelf(d);
152    }
153
154    /** {@inheritDoc} */
155    public RealVector mapAddToSelf(double d) {
156        if (d != 0) {
157            try {
158                return mapToSelf(BinaryFunction.ADD.fix1stArgument(d));
159            } catch (FunctionEvaluationException e) {
160                throw new IllegalArgumentException(e);
161            }
162        }
163        return this;
164    }
165
166    /** {@inheritDoc} */
167    public abstract AbstractRealVector copy();
168
169    /** {@inheritDoc} */
170    public double dotProduct(double[] v) throws IllegalArgumentException {
171        return dotProduct(new ArrayRealVector(v, false));
172    }
173
174    /** {@inheritDoc} */
175    public double dotProduct(RealVector v) throws IllegalArgumentException {
176        checkVectorDimensions(v);
177        double d = 0;
178        Iterator<Entry> it = sparseIterator();
179        Entry e;
180        while (it.hasNext() && (e = it.next()) != null) {
181            d += e.getValue() * v.getEntry(e.getIndex());
182        }
183        return d;
184    }
185
186    /** {@inheritDoc} */
187    public RealVector ebeDivide(double[] v) throws IllegalArgumentException {
188        return ebeDivide(new ArrayRealVector(v, false));
189    }
190
191    /** {@inheritDoc} */
192    public RealVector ebeMultiply(double[] v) throws IllegalArgumentException {
193        return ebeMultiply(new ArrayRealVector(v, false));
194    }
195
196    /** {@inheritDoc} */
197    public double getDistance(RealVector v) throws IllegalArgumentException {
198        checkVectorDimensions(v);
199        double d = 0;
200        Iterator<Entry> it = iterator();
201        Entry e;
202        while (it.hasNext() && (e = it.next()) != null) {
203            final double diff = e.getValue() - v.getEntry(e.getIndex());
204            d += diff * diff;
205        }
206        return FastMath.sqrt(d);
207    }
208
209    /** {@inheritDoc} */
210    public double getNorm() {
211        double sum = 0;
212        Iterator<Entry> it = sparseIterator();
213        Entry e;
214        while (it.hasNext() && (e = it.next()) != null) {
215            final double value = e.getValue();
216            sum += value * value;
217        }
218        return FastMath.sqrt(sum);
219    }
220
221    /** {@inheritDoc} */
222    public double getL1Norm() {
223        double norm = 0;
224        Iterator<Entry> it = sparseIterator();
225        Entry e;
226        while (it.hasNext() && (e = it.next()) != null) {
227            norm += FastMath.abs(e.getValue());
228        }
229        return norm;
230    }
231
232    /** {@inheritDoc} */
233    public double getLInfNorm() {
234        double norm = 0;
235        Iterator<Entry> it = sparseIterator();
236        Entry e;
237        while (it.hasNext() && (e = it.next()) != null) {
238            norm = FastMath.max(norm, FastMath.abs(e.getValue()));
239        }
240        return norm;
241    }
242
243    /** {@inheritDoc} */
244    public double getDistance(double[] v) throws IllegalArgumentException {
245        return getDistance(new ArrayRealVector(v,false));
246    }
247
248    /** {@inheritDoc} */
249    public double getL1Distance(RealVector v) throws IllegalArgumentException {
250        checkVectorDimensions(v);
251        double d = 0;
252        Iterator<Entry> it = iterator();
253        Entry e;
254        while (it.hasNext() && (e = it.next()) != null) {
255            d += FastMath.abs(e.getValue() - v.getEntry(e.getIndex()));
256        }
257        return d;
258    }
259
260    /** {@inheritDoc} */
261    public double getL1Distance(double[] v) throws IllegalArgumentException {
262        checkVectorDimensions(v.length);
263        double d = 0;
264        Iterator<Entry> it = iterator();
265        Entry e;
266        while (it.hasNext() && (e = it.next()) != null) {
267            d += FastMath.abs(e.getValue() - v[e.getIndex()]);
268        }
269        return d;
270    }
271
272    /** {@inheritDoc} */
273    public double getLInfDistance(RealVector v) throws IllegalArgumentException {
274        checkVectorDimensions(v);
275        double d = 0;
276        Iterator<Entry> it = iterator();
277        Entry e;
278        while (it.hasNext() && (e = it.next()) != null) {
279            d = FastMath.max(FastMath.abs(e.getValue() - v.getEntry(e.getIndex())), d);
280        }
281        return d;
282    }
283
284    /** {@inheritDoc} */
285    public double getLInfDistance(double[] v) throws IllegalArgumentException {
286        checkVectorDimensions(v.length);
287        double d = 0;
288        Iterator<Entry> it = iterator();
289        Entry e;
290        while (it.hasNext() && (e = it.next()) != null) {
291            d = FastMath.max(FastMath.abs(e.getValue() - v[e.getIndex()]), d);
292        }
293        return d;
294    }
295
296    /** Get the index of the minimum entry.
297     * @return index of the minimum entry or -1 if vector length is 0
298     * or all entries are NaN
299     */
300    public int getMinIndex() {
301        int minIndex    = -1;
302        double minValue = Double.POSITIVE_INFINITY;
303        Iterator<Entry> iterator = iterator();
304        while (iterator.hasNext()) {
305            final Entry entry = iterator.next();
306            if (entry.getValue() <= minValue) {
307                minIndex = entry.getIndex();
308                minValue = entry.getValue();
309            }
310        }
311        return minIndex;
312    }
313
314    /** Get the value of the minimum entry.
315     * @return value of the minimum entry or NaN if all entries are NaN
316     */
317    public double getMinValue() {
318        final int minIndex = getMinIndex();
319        return minIndex < 0 ? Double.NaN : getEntry(minIndex);
320    }
321
322    /** Get the index of the maximum entry.
323     * @return index of the maximum entry or -1 if vector length is 0
324     * or all entries are NaN
325     */
326    public int getMaxIndex() {
327        int maxIndex    = -1;
328        double maxValue = Double.NEGATIVE_INFINITY;
329        Iterator<Entry> iterator = iterator();
330        while (iterator.hasNext()) {
331            final Entry entry = iterator.next();
332            if (entry.getValue() >= maxValue) {
333                maxIndex = entry.getIndex();
334                maxValue = entry.getValue();
335            }
336        }
337        return maxIndex;
338    }
339
340    /** Get the value of the maximum entry.
341     * @return value of the maximum entry or NaN if all entries are NaN
342     */
343    public double getMaxValue() {
344        final int maxIndex = getMaxIndex();
345        return maxIndex < 0 ? Double.NaN : getEntry(maxIndex);
346    }
347
348    /** {@inheritDoc} */
349    public RealVector mapAbs() {
350        return copy().mapAbsToSelf();
351    }
352
353    /** {@inheritDoc} */
354    public RealVector mapAbsToSelf() {
355        try {
356            return mapToSelf(ComposableFunction.ABS);
357        } catch (FunctionEvaluationException e) {
358            throw new IllegalArgumentException(e);
359        }
360    }
361
362    /** {@inheritDoc} */
363    public RealVector mapAcos() {
364        return copy().mapAcosToSelf();
365    }
366
367    /** {@inheritDoc} */
368    public RealVector mapAcosToSelf() {
369        try {
370            return mapToSelf(ComposableFunction.ACOS);
371        } catch (FunctionEvaluationException e) {
372            throw new IllegalArgumentException(e);
373        }
374    }
375
376    /** {@inheritDoc} */
377    public RealVector mapAsin() {
378        return copy().mapAsinToSelf();
379    }
380
381    /** {@inheritDoc} */
382    public RealVector mapAsinToSelf() {
383        try {
384            return mapToSelf(ComposableFunction.ASIN);
385        } catch (FunctionEvaluationException e) {
386            throw new IllegalArgumentException(e);
387        }
388    }
389
390    /** {@inheritDoc} */
391    public RealVector mapAtan() {
392        return copy().mapAtanToSelf();
393    }
394
395    /** {@inheritDoc} */
396    public RealVector mapAtanToSelf() {
397        try {
398            return mapToSelf(ComposableFunction.ATAN);
399        } catch (FunctionEvaluationException e) {
400            throw new IllegalArgumentException(e);
401        }
402    }
403
404    /** {@inheritDoc} */
405    public RealVector mapCbrt() {
406        return copy().mapCbrtToSelf();
407    }
408
409    /** {@inheritDoc} */
410    public RealVector mapCbrtToSelf() {
411        try {
412            return mapToSelf(ComposableFunction.CBRT);
413        } catch (FunctionEvaluationException e) {
414            throw new IllegalArgumentException(e);
415        }
416    }
417
418    /** {@inheritDoc} */
419    public RealVector mapCeil() {
420        return copy().mapCeilToSelf();
421    }
422
423    /** {@inheritDoc} */
424    public RealVector mapCeilToSelf() {
425        try {
426            return mapToSelf(ComposableFunction.CEIL);
427        } catch (FunctionEvaluationException e) {
428            throw new IllegalArgumentException(e);
429        }
430    }
431
432    /** {@inheritDoc} */
433    public RealVector mapCos() {
434        return copy().mapCosToSelf();
435    }
436
437    /** {@inheritDoc} */
438    public RealVector mapCosToSelf() {
439        try {
440            return mapToSelf(ComposableFunction.COS);
441        } catch (FunctionEvaluationException e) {
442            throw new IllegalArgumentException(e);
443        }
444    }
445
446    /** {@inheritDoc} */
447    public RealVector mapCosh() {
448        return copy().mapCoshToSelf();
449    }
450
451    /** {@inheritDoc} */
452    public RealVector mapCoshToSelf() {
453        try {
454            return mapToSelf(ComposableFunction.COSH);
455        } catch (FunctionEvaluationException e) {
456            throw new IllegalArgumentException(e);
457        }
458    }
459
460    /** {@inheritDoc} */
461    public RealVector mapDivide(double d) {
462        return copy().mapDivideToSelf(d);
463    }
464
465    /** {@inheritDoc} */
466    public RealVector mapDivideToSelf(double d){
467        try {
468            return mapToSelf(BinaryFunction.DIVIDE.fix2ndArgument(d));
469        } catch (FunctionEvaluationException e) {
470            throw new IllegalArgumentException(e);
471        }
472    }
473
474    /** {@inheritDoc} */
475    public RealVector mapExp() {
476        return copy().mapExpToSelf();
477    }
478
479    /** {@inheritDoc} */
480    public RealVector mapExpToSelf() {
481        try {
482            return mapToSelf(ComposableFunction.EXP);
483        } catch (FunctionEvaluationException e) {
484            throw new IllegalArgumentException(e);
485        }
486    }
487
488    /** {@inheritDoc} */
489    public RealVector mapExpm1() {
490        return copy().mapExpm1ToSelf();
491    }
492
493    /** {@inheritDoc} */
494    public RealVector mapExpm1ToSelf() {
495        try {
496            return mapToSelf(ComposableFunction.EXPM1);
497        } catch (FunctionEvaluationException e) {
498            throw new IllegalArgumentException(e);
499        }
500    }
501
502    /** {@inheritDoc} */
503    public RealVector mapFloor() {
504        return copy().mapFloorToSelf();
505    }
506
507    /** {@inheritDoc} */
508    public RealVector mapFloorToSelf() {
509        try {
510            return mapToSelf(ComposableFunction.FLOOR);
511        } catch (FunctionEvaluationException e) {
512            throw new IllegalArgumentException(e);
513        }
514    }
515
516    /** {@inheritDoc} */
517    public RealVector mapInv() {
518        return copy().mapInvToSelf();
519    }
520
521    /** {@inheritDoc} */
522    public RealVector mapInvToSelf() {
523        try {
524            return mapToSelf(ComposableFunction.INVERT);
525        } catch (FunctionEvaluationException e) {
526            throw new IllegalArgumentException(e);
527        }
528    }
529
530    /** {@inheritDoc} */
531    public RealVector mapLog() {
532        return copy().mapLogToSelf();
533    }
534
535    /** {@inheritDoc} */
536    public RealVector mapLogToSelf() {
537        try {
538            return mapToSelf(ComposableFunction.LOG);
539        } catch (FunctionEvaluationException e) {
540            throw new IllegalArgumentException(e);
541        }
542    }
543
544    /** {@inheritDoc} */
545    public RealVector mapLog10() {
546        return copy().mapLog10ToSelf();
547    }
548
549    /** {@inheritDoc} */
550    public RealVector mapLog10ToSelf() {
551        try {
552            return mapToSelf(ComposableFunction.LOG10);
553        } catch (FunctionEvaluationException e) {
554            throw new IllegalArgumentException(e);
555        }
556    }
557
558    /** {@inheritDoc} */
559    public RealVector mapLog1p() {
560        return copy().mapLog1pToSelf();
561    }
562
563    /** {@inheritDoc} */
564    public RealVector mapLog1pToSelf() {
565        try {
566            return mapToSelf(ComposableFunction.LOG1P);
567        } catch (FunctionEvaluationException e) {
568            throw new IllegalArgumentException(e);
569        }
570    }
571
572    /** {@inheritDoc} */
573    public RealVector mapMultiply(double d) {
574        return copy().mapMultiplyToSelf(d);
575    }
576
577    /** {@inheritDoc} */
578    public RealVector mapMultiplyToSelf(double d){
579        try {
580            return mapToSelf(BinaryFunction.MULTIPLY.fix1stArgument(d));
581        } catch (FunctionEvaluationException e) {
582            throw new IllegalArgumentException(e);
583        }
584    }
585
586    /** {@inheritDoc} */
587    public RealVector mapPow(double d) {
588        return copy().mapPowToSelf(d);
589    }
590
591    /** {@inheritDoc} */
592    public RealVector mapPowToSelf(double d){
593        try {
594            return mapToSelf(BinaryFunction.POW.fix2ndArgument(d));
595        } catch (FunctionEvaluationException e) {
596            throw new IllegalArgumentException(e);
597        }
598    }
599
600    /** {@inheritDoc} */
601    public RealVector mapRint() {
602        return copy().mapRintToSelf();
603    }
604
605    /** {@inheritDoc} */
606    public RealVector mapRintToSelf() {
607        try {
608            return mapToSelf(ComposableFunction.RINT);
609        } catch (FunctionEvaluationException e) {
610            throw new IllegalArgumentException(e);
611        }
612    }
613
614    /** {@inheritDoc} */
615    public RealVector mapSignum() {
616        return copy().mapSignumToSelf();
617    }
618
619    /** {@inheritDoc} */
620    public RealVector mapSignumToSelf() {
621        try {
622            return mapToSelf(ComposableFunction.SIGNUM);
623        } catch (FunctionEvaluationException e) {
624            throw new IllegalArgumentException(e);
625        }
626    }
627
628    /** {@inheritDoc} */
629    public RealVector mapSin() {
630        return copy().mapSinToSelf();
631    }
632
633    /** {@inheritDoc} */
634    public RealVector mapSinToSelf() {
635        try {
636            return mapToSelf(ComposableFunction.SIN);
637        } catch (FunctionEvaluationException e) {
638            throw new IllegalArgumentException(e);
639        }
640    }
641
642    /** {@inheritDoc} */
643    public RealVector mapSinh() {
644        return copy().mapSinhToSelf();
645    }
646
647    /** {@inheritDoc} */
648    public RealVector mapSinhToSelf() {
649        try {
650            return mapToSelf(ComposableFunction.SINH);
651        } catch (FunctionEvaluationException e) {
652            throw new IllegalArgumentException(e);
653        }
654    }
655
656    /** {@inheritDoc} */
657    public RealVector mapSqrt() {
658        return copy().mapSqrtToSelf();
659    }
660
661    /** {@inheritDoc} */
662    public RealVector mapSqrtToSelf() {
663        try {
664            return mapToSelf(ComposableFunction.SQRT);
665        } catch (FunctionEvaluationException e) {
666            throw new IllegalArgumentException(e);
667        }
668    }
669
670    /** {@inheritDoc} */
671    public RealVector mapSubtract(double d) {
672        return copy().mapSubtractToSelf(d);
673    }
674
675    /** {@inheritDoc} */
676    public RealVector mapSubtractToSelf(double d){
677        return mapAddToSelf(-d);
678    }
679
680    /** {@inheritDoc} */
681    public RealVector mapTan() {
682        return copy().mapTanToSelf();
683    }
684
685    /** {@inheritDoc} */
686    public RealVector mapTanToSelf() {
687        try {
688            return mapToSelf(ComposableFunction.TAN);
689        } catch (FunctionEvaluationException e) {
690            throw new IllegalArgumentException(e);
691        }
692    }
693
694    /** {@inheritDoc} */
695    public RealVector mapTanh() {
696        return copy().mapTanhToSelf();
697    }
698
699    /** {@inheritDoc} */
700    public RealVector mapTanhToSelf() {
701        try {
702            return mapToSelf(ComposableFunction.TANH);
703        } catch (FunctionEvaluationException e) {
704            throw new IllegalArgumentException(e);
705        }
706    }
707
708    /** {@inheritDoc} */
709    public RealVector mapUlp() {
710        return copy().mapUlpToSelf();
711    }
712
713    /** {@inheritDoc} */
714    public RealVector mapUlpToSelf() {
715        try {
716            return mapToSelf(ComposableFunction.ULP);
717        } catch (FunctionEvaluationException e) {
718            throw new IllegalArgumentException(e);
719        }
720    }
721
722    /** {@inheritDoc} */
723    public RealMatrix outerProduct(RealVector v) throws IllegalArgumentException {
724        RealMatrix product;
725        if (v instanceof SparseRealVector || this instanceof SparseRealVector) {
726            product = new OpenMapRealMatrix(this.getDimension(), v.getDimension());
727        } else {
728            product = new Array2DRowRealMatrix(this.getDimension(), v.getDimension());
729        }
730        Iterator<Entry> thisIt = sparseIterator();
731        Entry thisE = null;
732        while (thisIt.hasNext() && (thisE = thisIt.next()) != null) {
733            Iterator<Entry> otherIt = v.sparseIterator();
734            Entry otherE = null;
735            while (otherIt.hasNext() && (otherE = otherIt.next()) != null) {
736                product.setEntry(thisE.getIndex(), otherE.getIndex(),
737                                 thisE.getValue() * otherE.getValue());
738            }
739        }
740
741        return product;
742
743    }
744
745    /** {@inheritDoc} */
746    public RealMatrix outerProduct(double[] v) throws IllegalArgumentException {
747        return outerProduct(new ArrayRealVector(v, false));
748    }
749
750    /** {@inheritDoc} */
751    public RealVector projection(double[] v) throws IllegalArgumentException {
752        return projection(new ArrayRealVector(v, false));
753    }
754
755    /** {@inheritDoc} */
756    public void set(double value) {
757        Iterator<Entry> it = iterator();
758        Entry e = null;
759        while (it.hasNext() && (e = it.next()) != null) {
760            e.setValue(value);
761        }
762    }
763
764    /** {@inheritDoc} */
765    public double[] toArray() {
766        int dim = getDimension();
767        double[] values = new double[dim];
768        for (int i = 0; i < dim; i++) {
769            values[i] = getEntry(i);
770        }
771        return values;
772    }
773
774    /** {@inheritDoc} */
775    public double[] getData() {
776        return toArray();
777    }
778
779    /** {@inheritDoc} */
780    public RealVector unitVector() {
781        RealVector copy = copy();
782        copy.unitize();
783        return copy;
784    }
785
786    /** {@inheritDoc} */
787    public void unitize() {
788        mapDivideToSelf(getNorm());
789    }
790
791    /** {@inheritDoc} */
792    public Iterator<Entry> sparseIterator() {
793        return new SparseEntryIterator();
794    }
795
796    /** {@inheritDoc} */
797    public Iterator<Entry> iterator() {
798        final int dim = getDimension();
799        return new Iterator<Entry>() {
800
801            /** Current index. */
802            private int i = 0;
803
804            /** Current entry. */
805            private EntryImpl e = new EntryImpl();
806
807            /** {@inheritDoc} */
808            public boolean hasNext() {
809                return i < dim;
810            }
811
812            /** {@inheritDoc} */
813            public Entry next() {
814                e.setIndex(i++);
815                return e;
816            }
817
818            /** {@inheritDoc} */
819            public void remove() {
820                throw new MathUnsupportedOperationException();
821            }
822        };
823    }
824
825    /** {@inheritDoc} */
826    public RealVector map(UnivariateRealFunction function) throws FunctionEvaluationException {
827        return copy().mapToSelf(function);
828    }
829
830    /** {@inheritDoc} */
831    public RealVector mapToSelf(UnivariateRealFunction function) throws FunctionEvaluationException {
832        Iterator<Entry> it = (function.value(0) == 0) ? sparseIterator() : iterator();
833        Entry e;
834        while (it.hasNext() && (e = it.next()) != null) {
835            e.setValue(function.value(e.getValue()));
836        }
837        return this;
838    }
839
840    /** An entry in the vector. */
841    protected class EntryImpl extends Entry {
842
843        /** Simple constructor. */
844        public EntryImpl() {
845            setIndex(0);
846        }
847
848        /** {@inheritDoc} */
849        @Override
850        public double getValue() {
851            return getEntry(getIndex());
852        }
853
854        /** {@inheritDoc} */
855        @Override
856        public void setValue(double newValue) {
857            setEntry(getIndex(), newValue);
858        }
859    }
860
861    /**
862     * This class should rare be used, but is here to provide
863     * a default implementation of sparseIterator(), which is implemented
864     * by walking over the entries, skipping those whose values are the default one.
865     *
866     * Concrete subclasses which are SparseVector implementations should
867     * make their own sparse iterator, not use this one.
868     *
869     * This implementation might be useful for ArrayRealVector, when expensive
870     * operations which preserve the default value are to be done on the entries,
871     * and the fraction of non-default values is small (i.e. someone took a
872     * SparseVector, and passed it into the copy-constructor of ArrayRealVector)
873     */
874    protected class SparseEntryIterator implements Iterator<Entry> {
875
876        /** Dimension of the vector. */
877        private final int dim;
878
879        /** last entry returned by {@link #next()} */
880        private EntryImpl current;
881
882        /** Next entry for {@link #next()} to return. */
883        private EntryImpl next;
884
885        /** Simple constructor. */
886        protected SparseEntryIterator() {
887            dim = getDimension();
888            current = new EntryImpl();
889            next = new EntryImpl();
890            if (next.getValue() == 0) {
891                advance(next);
892            }
893        }
894
895        /** Advance an entry up to the next nonzero one.
896         * @param e entry to advance
897         */
898        protected void advance(EntryImpl e) {
899            if (e == null) {
900                return;
901            }
902            do {
903                e.setIndex(e.getIndex() + 1);
904            } while (e.getIndex() < dim && e.getValue() == 0);
905            if (e.getIndex() >= dim) {
906                e.setIndex(-1);
907            }
908        }
909
910        /** {@inheritDoc} */
911        public boolean hasNext() {
912            return next.getIndex() >= 0;
913        }
914
915        /** {@inheritDoc} */
916        public Entry next() {
917            int index = next.getIndex();
918            if (index < 0) {
919                throw new NoSuchElementException();
920            }
921            current.setIndex(index);
922            advance(next);
923            return current;
924        }
925
926        /** {@inheritDoc} */
927        public void remove() {
928            throw new MathUnsupportedOperationException();
929        }
930    }
931
932}
933