001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    package org.apache.commons.math.linear;
019    
020    import java.util.Iterator;
021    
022    import org.apache.commons.math.FunctionEvaluationException;
023    import org.apache.commons.math.MathRuntimeException;
024    import org.apache.commons.math.analysis.BinaryFunction;
025    import org.apache.commons.math.analysis.UnivariateRealFunction;
026    import org.apache.commons.math.analysis.ComposableFunction;
027    
028    /**
029     * This class provides default basic implementations for many methods in the
030     * {@link RealVector} interface with.
031     * @version $Revision: 904231 $ $Date: 2010-01-28 14:42:31 -0500 (Thu, 28 Jan 2010) $
032     * @since 2.1
033     */
034    public abstract class AbstractRealVector implements RealVector {
035    
036        /**
037         * Check if instance and specified vectors have the same dimension.
038         * @param v vector to compare instance with
039         * @exception IllegalArgumentException if the vectors do not
040         * have the same dimension
041         */
042        protected void checkVectorDimensions(RealVector v) {
043            checkVectorDimensions(v.getDimension());
044        }
045    
046        /**
047         * Check if instance dimension is equal to some expected value.
048         *
049         * @param n expected dimension.
050         * @exception IllegalArgumentException if the dimension is
051         * inconsistent with vector size
052         */
053        protected void checkVectorDimensions(int n)
054            throws IllegalArgumentException {
055            double d = getDimension();
056            if (d != n) {
057                throw MathRuntimeException.createIllegalArgumentException(
058                      "vector length mismatch: got {0} but expected {1}",
059                      d, n);
060            }
061        }
062    
063        /**
064         * Check if an index is valid.
065         * @param index index to check
066         * @exception MatrixIndexException if index is not valid
067         */
068        protected void checkIndex(final int index)
069            throws MatrixIndexException {
070            if (index < 0 || index >= getDimension()) {
071                throw new MatrixIndexException(
072                      "index {0} out of allowed range [{1}, {2}]",
073                      index, 0, getDimension() - 1);
074            }
075        }
076    
077        /** {@inheritDoc} */
078        public void setSubVector(int index, RealVector v) throws MatrixIndexException {
079            checkIndex(index);
080            checkIndex(index + v.getDimension() - 1);
081            setSubVector(index, v.getData());
082        }
083    
084        /** {@inheritDoc} */
085        public void setSubVector(int index, double[] v) throws MatrixIndexException {
086            checkIndex(index);
087            checkIndex(index + v.length - 1);
088            for (int i = 0; i < v.length; i++) {
089                setEntry(i + index, v[i]);
090            }
091        }
092    
093        /** {@inheritDoc} */
094        public RealVector add(double[] v) throws IllegalArgumentException {
095            double[] result = v.clone();
096            Iterator<Entry> it = sparseIterator();
097            Entry e;
098            while (it.hasNext() && (e = it.next()) != null) {
099                result[e.getIndex()] += e.getValue();
100            }
101            return new ArrayRealVector(result, false);
102        }
103    
104        /** {@inheritDoc} */
105        public RealVector add(RealVector v) throws IllegalArgumentException {
106            if (v instanceof ArrayRealVector) {
107                double[] values = ((ArrayRealVector)v).getDataRef();
108                return add(values);
109            }
110            RealVector result = v.copy();
111            Iterator<Entry> it = sparseIterator();
112            Entry e;
113            while (it.hasNext() && (e = it.next()) != null) {
114                final int index = e.getIndex();
115                result.setEntry(index, e.getValue() + result.getEntry(index));
116            }
117            return result;
118        }
119    
120        /** {@inheritDoc} */
121        public RealVector subtract(double[] v) throws IllegalArgumentException {
122            double[] result = v.clone();
123            Iterator<Entry> it = sparseIterator();
124            Entry e;
125            while (it.hasNext() && (e = it.next()) != null) {
126                final int index = e.getIndex();
127                result[index] = e.getValue() - result[index];
128            }
129            return new ArrayRealVector(result, false);
130        }
131    
132        /** {@inheritDoc} */
133        public RealVector subtract(RealVector v) throws IllegalArgumentException {
134            if (v instanceof ArrayRealVector) {
135                double[] values = ((ArrayRealVector)v).getDataRef();
136                return add(values);
137            }
138            RealVector result = v.copy();
139            Iterator<Entry> it = sparseIterator();
140            Entry e;
141            while (it.hasNext() && (e = it.next()) != null) {
142                final int index = e.getIndex();
143                v.setEntry(index, e.getValue() - result.getEntry(index));
144            }
145            return result;
146        }
147    
148        /** {@inheritDoc} */
149        public RealVector mapAdd(double d) {
150            return copy().mapAddToSelf(d);
151        }
152    
153        /** {@inheritDoc} */
154        public RealVector mapAddToSelf(double d) {
155            if (d != 0) {
156                try {
157                    return mapToSelf(BinaryFunction.ADD.fix1stArgument(d));
158                } catch (FunctionEvaluationException e) {
159                    throw new IllegalArgumentException(e);
160                }
161            }
162            return this;
163        }
164    
165        /** {@inheritDoc} */
166        public abstract AbstractRealVector copy();
167    
168        /** {@inheritDoc} */
169        public double dotProduct(double[] v) throws IllegalArgumentException {
170            return dotProduct(new ArrayRealVector(v, false));
171        }
172    
173        /** {@inheritDoc} */
174        public double dotProduct(RealVector v) throws IllegalArgumentException {
175            checkVectorDimensions(v);
176            double d = 0;
177            Iterator<Entry> it = sparseIterator();
178            Entry e;
179            while (it.hasNext() && (e = it.next()) != null) {
180                d += e.getValue() * v.getEntry(e.getIndex());
181            }
182            return d;
183        }
184    
185        /** {@inheritDoc} */
186        public RealVector ebeDivide(double[] v) throws IllegalArgumentException {
187            return ebeDivide(new ArrayRealVector(v, false));
188        }
189    
190        /** {@inheritDoc} */
191        public RealVector ebeMultiply(double[] v) throws IllegalArgumentException {
192            return ebeMultiply(new ArrayRealVector(v, false));
193        }
194    
195        /** {@inheritDoc} */
196        public double getDistance(RealVector v) throws IllegalArgumentException {
197            checkVectorDimensions(v);
198            double d = 0;
199            Iterator<Entry> it = iterator();
200            Entry e;
201            while (it.hasNext() && (e = it.next()) != null) {
202                final double diff = e.getValue() - v.getEntry(e.getIndex());
203                d += diff * diff;
204            }
205            return Math.sqrt(d);
206        }
207    
208        /** {@inheritDoc} */
209        public double getNorm() {
210            double sum = 0;
211            Iterator<Entry> it = sparseIterator();
212            Entry e;
213            while (it.hasNext() && (e = it.next()) != null) {
214                final double value = e.getValue();
215                sum += value * value;
216            }
217            return Math.sqrt(sum);
218        }
219    
220        /** {@inheritDoc} */
221        public double getL1Norm() {
222            double norm = 0;
223            Iterator<Entry> it = sparseIterator();
224            Entry e;
225            while (it.hasNext() && (e = it.next()) != null) {
226                norm += Math.abs(e.getValue());
227            }
228            return norm;
229        }
230    
231        /** {@inheritDoc} */
232        public double getLInfNorm() {
233            double norm = 0;
234            Iterator<Entry> it = sparseIterator();
235            Entry e;
236            while (it.hasNext() && (e = it.next()) != null) {
237                norm = Math.max(norm, Math.abs(e.getValue()));
238            }
239            return norm;
240        }
241    
242        /** {@inheritDoc} */
243        public double getDistance(double[] v) throws IllegalArgumentException {
244            return getDistance(new ArrayRealVector(v,false));
245        }
246    
247        /** {@inheritDoc} */
248        public double getL1Distance(RealVector v) throws IllegalArgumentException {
249            checkVectorDimensions(v);
250            double d = 0;
251            Iterator<Entry> it = iterator();
252            Entry e;
253            while (it.hasNext() && (e = it.next()) != null) {
254                d += Math.abs(e.getValue() - v.getEntry(e.getIndex()));
255            }
256            return d;
257        }
258    
259        /** {@inheritDoc} */
260        public double getL1Distance(double[] v) throws IllegalArgumentException {
261            checkVectorDimensions(v.length);
262            double d = 0;
263            Iterator<Entry> it = iterator();
264            Entry e;
265            while (it.hasNext() && (e = it.next()) != null) {
266                d += Math.abs(e.getValue() - v[e.getIndex()]);
267            }
268            return d;
269        }
270    
271        /** {@inheritDoc} */
272        public double getLInfDistance(RealVector v) throws IllegalArgumentException {
273            checkVectorDimensions(v);
274            double d = 0;
275            Iterator<Entry> it = iterator();
276            Entry e;
277            while (it.hasNext() && (e = it.next()) != null) {
278                d = Math.max(Math.abs(e.getValue() - v.getEntry(e.getIndex())), d);
279            }
280            return d;
281        }
282    
283        /** {@inheritDoc} */
284        public double getLInfDistance(double[] v) throws IllegalArgumentException {
285            checkVectorDimensions(v.length);
286            double d = 0;
287            Iterator<Entry> it = iterator();
288            Entry e;
289            while (it.hasNext() && (e = it.next()) != null) {
290                d = Math.max(Math.abs(e.getValue() - v[e.getIndex()]), d);
291            }
292            return d;
293        }
294    
295        /** Get the index of the minimum entry.
296         * @return index of the minimum entry or -1 if vector length is 0
297         * or all entries are NaN
298         */
299        public int getMinIndex() {
300            int minIndex    = -1;
301            double minValue = Double.POSITIVE_INFINITY;
302            Iterator<Entry> iterator = iterator();
303            while (iterator.hasNext()) {
304                final Entry entry = iterator.next();
305                if (entry.getValue() <= minValue) {
306                    minIndex = entry.getIndex();
307                    minValue = entry.getValue();
308                }
309            }
310            return minIndex;
311        }
312    
313        /** Get the value of the minimum entry.
314         * @return value of the minimum entry or NaN if all entries are NaN
315         */
316        public double getMinValue() {
317            final int minIndex = getMinIndex();
318            return minIndex < 0 ? Double.NaN : getEntry(minIndex);
319        }
320    
321        /** Get the index of the maximum entry.
322         * @return index of the maximum entry or -1 if vector length is 0
323         * or all entries are NaN
324         */
325        public int getMaxIndex() {
326            int maxIndex    = -1;
327            double maxValue = Double.NEGATIVE_INFINITY;
328            Iterator<Entry> iterator = iterator();
329            while (iterator.hasNext()) {
330                final Entry entry = iterator.next();
331                if (entry.getValue() >= maxValue) {
332                    maxIndex = entry.getIndex();
333                    maxValue = entry.getValue();
334                }
335            }
336            return maxIndex;
337        }
338    
339        /** Get the value of the maximum entry.
340         * @return value of the maximum entry or NaN if all entries are NaN
341         */
342        public double getMaxValue() {
343            final int maxIndex = getMaxIndex();
344            return maxIndex < 0 ? Double.NaN : getEntry(maxIndex);
345        }
346    
347        /** {@inheritDoc} */
348        public RealVector mapAbs() {
349            return copy().mapAbsToSelf();
350        }
351    
352        /** {@inheritDoc} */
353        public RealVector mapAbsToSelf() {
354            try {
355                return mapToSelf(ComposableFunction.ABS);
356            } catch (FunctionEvaluationException e) {
357                throw new IllegalArgumentException(e);
358            }
359        }
360    
361        /** {@inheritDoc} */
362        public RealVector mapAcos() {
363            return copy().mapAcosToSelf();
364        }
365    
366        /** {@inheritDoc} */
367        public RealVector mapAcosToSelf() {
368            try {
369                return mapToSelf(ComposableFunction.ACOS);
370            } catch (FunctionEvaluationException e) {
371                throw new IllegalArgumentException(e);
372            }
373        }
374    
375        /** {@inheritDoc} */
376        public RealVector mapAsin() {
377            return copy().mapAsinToSelf();
378        }
379    
380        /** {@inheritDoc} */
381        public RealVector mapAsinToSelf() {
382            try {
383                return mapToSelf(ComposableFunction.ASIN);
384            } catch (FunctionEvaluationException e) {
385                throw new IllegalArgumentException(e);
386            }
387        }
388    
389        /** {@inheritDoc} */
390        public RealVector mapAtan() {
391            return copy().mapAtanToSelf();
392        }
393    
394        /** {@inheritDoc} */
395        public RealVector mapAtanToSelf() {
396            try {
397                return mapToSelf(ComposableFunction.ATAN);
398            } catch (FunctionEvaluationException e) {
399                throw new IllegalArgumentException(e);
400            }
401        }
402    
403        /** {@inheritDoc} */
404        public RealVector mapCbrt() {
405            return copy().mapCbrtToSelf();
406        }
407    
408        /** {@inheritDoc} */
409        public RealVector mapCbrtToSelf() {
410            try {
411                return mapToSelf(ComposableFunction.CBRT);
412            } catch (FunctionEvaluationException e) {
413                throw new IllegalArgumentException(e);
414            }
415        }
416    
417        /** {@inheritDoc} */
418        public RealVector mapCeil() {
419            return copy().mapCeilToSelf();
420        }
421    
422        /** {@inheritDoc} */
423        public RealVector mapCeilToSelf() {
424            try {
425                return mapToSelf(ComposableFunction.CEIL);
426            } catch (FunctionEvaluationException e) {
427                throw new IllegalArgumentException(e);
428            }
429        }
430    
431        /** {@inheritDoc} */
432        public RealVector mapCos() {
433            return copy().mapCosToSelf();
434        }
435    
436        /** {@inheritDoc} */
437        public RealVector mapCosToSelf() {
438            try {
439                return mapToSelf(ComposableFunction.COS);
440            } catch (FunctionEvaluationException e) {
441                throw new IllegalArgumentException(e);
442            }
443        }
444    
445        /** {@inheritDoc} */
446        public RealVector mapCosh() {
447            return copy().mapCoshToSelf();
448        }
449    
450        /** {@inheritDoc} */
451        public RealVector mapCoshToSelf() {
452            try {
453                return mapToSelf(ComposableFunction.COSH);
454            } catch (FunctionEvaluationException e) {
455                throw new IllegalArgumentException(e);
456            }
457        }
458    
459        /** {@inheritDoc} */
460        public RealVector mapDivide(double d) {
461            return copy().mapDivideToSelf(d);
462        }
463    
464        /** {@inheritDoc} */
465        public RealVector mapDivideToSelf(double d){
466            try {
467                return mapToSelf(BinaryFunction.DIVIDE.fix2ndArgument(d));
468            } catch (FunctionEvaluationException e) {
469                throw new IllegalArgumentException(e);
470            }
471        }
472    
473        /** {@inheritDoc} */
474        public RealVector mapExp() {
475            return copy().mapExpToSelf();
476        }
477    
478        /** {@inheritDoc} */
479        public RealVector mapExpToSelf() {
480            try {
481                return mapToSelf(ComposableFunction.EXP);
482            } catch (FunctionEvaluationException e) {
483                throw new IllegalArgumentException(e);
484            }
485        }
486    
487        /** {@inheritDoc} */
488        public RealVector mapExpm1() {
489            return copy().mapExpm1ToSelf();
490        }
491    
492        /** {@inheritDoc} */
493        public RealVector mapExpm1ToSelf() {
494            try {
495                return mapToSelf(ComposableFunction.EXPM1);
496            } catch (FunctionEvaluationException e) {
497                throw new IllegalArgumentException(e);
498            }
499        }
500    
501        /** {@inheritDoc} */
502        public RealVector mapFloor() {
503            return copy().mapFloorToSelf();
504        }
505    
506        /** {@inheritDoc} */
507        public RealVector mapFloorToSelf() {
508            try {
509                return mapToSelf(ComposableFunction.FLOOR);
510            } catch (FunctionEvaluationException e) {
511                throw new IllegalArgumentException(e);
512            }
513        }
514    
515        /** {@inheritDoc} */
516        public RealVector mapInv() {
517            return copy().mapInvToSelf();
518        }
519    
520        /** {@inheritDoc} */
521        public RealVector mapInvToSelf() {
522            try {
523                return mapToSelf(ComposableFunction.INVERT);
524            } catch (FunctionEvaluationException e) {
525                throw new IllegalArgumentException(e);
526            }
527        }
528    
529        /** {@inheritDoc} */
530        public RealVector mapLog() {
531            return copy().mapLogToSelf();
532        }
533    
534        /** {@inheritDoc} */
535        public RealVector mapLogToSelf() {
536            try {
537                return mapToSelf(ComposableFunction.LOG);
538            } catch (FunctionEvaluationException e) {
539                throw new IllegalArgumentException(e);
540            }
541        }
542    
543        /** {@inheritDoc} */
544        public RealVector mapLog10() {
545            return copy().mapLog10ToSelf();
546        }
547    
548        /** {@inheritDoc} */
549        public RealVector mapLog10ToSelf() {
550            try {
551                return mapToSelf(ComposableFunction.LOG10);
552            } catch (FunctionEvaluationException e) {
553                throw new IllegalArgumentException(e);
554            }
555        }
556    
557        /** {@inheritDoc} */
558        public RealVector mapLog1p() {
559            return copy().mapLog1pToSelf();
560        }
561    
562        /** {@inheritDoc} */
563        public RealVector mapLog1pToSelf() {
564            try {
565                return mapToSelf(ComposableFunction.LOG1P);
566            } catch (FunctionEvaluationException e) {
567                throw new IllegalArgumentException(e);
568            }
569        }
570    
571        /** {@inheritDoc} */
572        public RealVector mapMultiply(double d) {
573            return copy().mapMultiplyToSelf(d);
574        }
575    
576        /** {@inheritDoc} */
577        public RealVector mapMultiplyToSelf(double d){
578            try {
579                return mapToSelf(BinaryFunction.MULTIPLY.fix1stArgument(d));
580            } catch (FunctionEvaluationException e) {
581                throw new IllegalArgumentException(e);
582            }
583        }
584    
585        /** {@inheritDoc} */
586        public RealVector mapPow(double d) {
587            return copy().mapPowToSelf(d);
588        }
589    
590        /** {@inheritDoc} */
591        public RealVector mapPowToSelf(double d){
592            try {
593                return mapToSelf(BinaryFunction.POW.fix2ndArgument(d));
594            } catch (FunctionEvaluationException e) {
595                throw new IllegalArgumentException(e);
596            }
597        }
598    
599        /** {@inheritDoc} */
600        public RealVector mapRint() {
601            return copy().mapRintToSelf();
602        }
603    
604        /** {@inheritDoc} */
605        public RealVector mapRintToSelf() {
606            try {
607                return mapToSelf(ComposableFunction.RINT);
608            } catch (FunctionEvaluationException e) {
609                throw new IllegalArgumentException(e);
610            }
611        }
612    
613        /** {@inheritDoc} */
614        public RealVector mapSignum() {
615            return copy().mapSignumToSelf();
616        }
617    
618        /** {@inheritDoc} */
619        public RealVector mapSignumToSelf() {
620            try {
621                return mapToSelf(ComposableFunction.SIGNUM);
622            } catch (FunctionEvaluationException e) {
623                throw new IllegalArgumentException(e);
624            }
625        }
626    
627        /** {@inheritDoc} */
628        public RealVector mapSin() {
629            return copy().mapSinToSelf();
630        }
631    
632        /** {@inheritDoc} */
633        public RealVector mapSinToSelf() {
634            try {
635                return mapToSelf(ComposableFunction.SIN);
636            } catch (FunctionEvaluationException e) {
637                throw new IllegalArgumentException(e);
638            }
639        }
640    
641        /** {@inheritDoc} */
642        public RealVector mapSinh() {
643            return copy().mapSinhToSelf();
644        }
645    
646        /** {@inheritDoc} */
647        public RealVector mapSinhToSelf() {
648            try {
649                return mapToSelf(ComposableFunction.SINH);
650            } catch (FunctionEvaluationException e) {
651                throw new IllegalArgumentException(e);
652            }
653        }
654    
655        /** {@inheritDoc} */
656        public RealVector mapSqrt() {
657            return copy().mapSqrtToSelf();
658        }
659    
660        /** {@inheritDoc} */
661        public RealVector mapSqrtToSelf() {
662            try {
663                return mapToSelf(ComposableFunction.SQRT);
664            } catch (FunctionEvaluationException e) {
665                throw new IllegalArgumentException(e);
666            }
667        }
668    
669        /** {@inheritDoc} */
670        public RealVector mapSubtract(double d) {
671            return copy().mapSubtractToSelf(d);
672        }
673    
674        /** {@inheritDoc} */
675        public RealVector mapSubtractToSelf(double d){
676            return mapAddToSelf(-d);
677        }
678    
679        /** {@inheritDoc} */
680        public RealVector mapTan() {
681            return copy().mapTanToSelf();
682        }
683    
684        /** {@inheritDoc} */
685        public RealVector mapTanToSelf() {
686            try {
687                return mapToSelf(ComposableFunction.TAN);
688            } catch (FunctionEvaluationException e) {
689                throw new IllegalArgumentException(e);
690            }
691        }
692    
693        /** {@inheritDoc} */
694        public RealVector mapTanh() {
695            return copy().mapTanhToSelf();
696        }
697    
698        /** {@inheritDoc} */
699        public RealVector mapTanhToSelf() {
700            try {
701                return mapToSelf(ComposableFunction.TANH);
702            } catch (FunctionEvaluationException e) {
703                throw new IllegalArgumentException(e);
704            }
705        }
706    
707        /** {@inheritDoc} */
708        public RealVector mapUlp() {
709            return copy().mapUlpToSelf();
710        }
711    
712        /** {@inheritDoc} */
713        public RealVector mapUlpToSelf() {
714            try {
715                return mapToSelf(ComposableFunction.ULP);
716            } catch (FunctionEvaluationException e) {
717                throw new IllegalArgumentException(e);
718            }
719        }
720    
721        /** {@inheritDoc} */
722        public RealMatrix outerProduct(RealVector v) throws IllegalArgumentException {
723            RealMatrix product;
724            if (v instanceof SparseRealVector || this instanceof SparseRealVector) {
725                product = new OpenMapRealMatrix(this.getDimension(), v.getDimension());
726            } else {
727                product = new Array2DRowRealMatrix(this.getDimension(), v.getDimension());
728            }
729            Iterator<Entry> thisIt = sparseIterator();
730            Entry thisE = null;
731            while (thisIt.hasNext() && (thisE = thisIt.next()) != null) {
732                Iterator<Entry> otherIt = v.sparseIterator();
733                Entry otherE = null;
734                while (otherIt.hasNext() && (otherE = otherIt.next()) != null) {
735                    product.setEntry(thisE.getIndex(), otherE.getIndex(),
736                                     thisE.getValue() * otherE.getValue());
737                }
738            }
739    
740            return product;
741    
742        }
743    
744        /** {@inheritDoc} */
745        public RealMatrix outerProduct(double[] v) throws IllegalArgumentException {
746            return outerProduct(new ArrayRealVector(v, false));
747        }
748    
749        /** {@inheritDoc} */
750        public RealVector projection(double[] v) throws IllegalArgumentException {
751            return projection(new ArrayRealVector(v, false));
752        }
753    
754        /** {@inheritDoc} */
755        public void set(double value) {
756            Iterator<Entry> it = iterator();
757            Entry e = null;
758            while (it.hasNext() && (e = it.next()) != null) {
759                e.setValue(value);
760            }
761        }
762    
763        /** {@inheritDoc} */
764        public double[] toArray() {
765            int dim = getDimension();
766            double[] values = new double[dim];
767            for (int i = 0; i < dim; i++) {
768                values[i] = getEntry(i);
769            }
770            return values;
771        }
772    
773        /** {@inheritDoc} */
774        public double[] getData() {
775            return toArray();
776        }
777    
778        /** {@inheritDoc} */
779        public RealVector unitVector() {
780            RealVector copy = copy();
781            copy.unitize();
782            return copy;
783        }
784    
785        /** {@inheritDoc} */
786        public void unitize() {
787            mapDivideToSelf(getNorm());
788        }
789    
790        /** {@inheritDoc} */
791        public Iterator<Entry> sparseIterator() {
792            return new SparseEntryIterator();
793        }
794    
795        /** {@inheritDoc} */
796        public Iterator<Entry> iterator() {
797            final int dim = getDimension();
798            return new Iterator<Entry>() {
799    
800                /** Current index. */
801                private int i = 0;
802    
803                /** Current entry. */
804                private EntryImpl e = new EntryImpl();
805    
806                /** {@inheritDoc} */
807                public boolean hasNext() {
808                    return i < dim;
809                }
810    
811                /** {@inheritDoc} */
812                public Entry next() {
813                    e.setIndex(i++);
814                    return e;
815                }
816    
817                /** {@inheritDoc} */
818                public void remove() {
819                    throw new UnsupportedOperationException("Not supported");
820                }
821            };
822        }
823    
824        /** {@inheritDoc} */
825        public RealVector map(UnivariateRealFunction function) throws FunctionEvaluationException {
826            return copy().mapToSelf(function);
827        }
828    
829        /** {@inheritDoc} */
830        public RealVector mapToSelf(UnivariateRealFunction function) throws FunctionEvaluationException {
831            Iterator<Entry> it = (function.value(0) == 0) ? sparseIterator() : iterator();
832            Entry e;
833            while (it.hasNext() && (e = it.next()) != null) {
834                e.setValue(function.value(e.getValue()));
835            }
836            return this;
837        }
838    
839        /** An entry in the vector. */
840        protected class EntryImpl extends Entry {
841    
842            /** Simple constructor. */
843            public EntryImpl() {
844                setIndex(0);
845            }
846    
847            /** {@inheritDoc} */
848            @Override
849            public double getValue() {
850                return getEntry(getIndex());
851            }
852    
853            /** {@inheritDoc} */
854            @Override
855            public void setValue(double newValue) {
856                setEntry(getIndex(), newValue);
857            }
858        }
859    
860        /**
861         * This class should rare be used, but is here to provide
862         * a default implementation of sparseIterator(), which is implemented
863         * by walking over the entries, skipping those whose values are the default one.
864         *
865         * Concrete subclasses which are SparseVector implementations should
866         * make their own sparse iterator, not use this one.
867         *
868         * This implementation might be useful for ArrayRealVector, when expensive
869         * operations which preserve the default value are to be done on the entries,
870         * and the fraction of non-default values is small (i.e. someone took a
871         * SparseVector, and passed it into the copy-constructor of ArrayRealVector)
872         */
873        protected class SparseEntryIterator implements Iterator<Entry> {
874    
875            /** Dimension of the vector. */
876            private final int dim;
877    
878            /** Temporary entry (reused on each call to {@link #next()}. */
879            private EntryImpl tmp = new EntryImpl();
880    
881            /** Current entry. */
882            private EntryImpl current;
883    
884            /** Next entry. */
885            private EntryImpl next;
886    
887            /** Simple constructor. */
888            protected SparseEntryIterator() {
889                dim = getDimension();
890                current = new EntryImpl();
891                if (current.getValue() == 0) {
892                    advance(current);
893                }
894                if(current.getIndex() >= 0){
895                    // There is at least one non-zero entry
896                    next = new EntryImpl();
897                    next.setIndex(current.getIndex());
898                    advance(next);
899                } else {
900                    // The vector consists of only zero entries, so deny having a next
901                    current = null;
902                }
903            }
904    
905            /** Advance an entry up to the next non null one.
906             * @param e entry to advance
907             */
908            protected void advance(EntryImpl e) {
909                if (e == null) {
910                    return;
911                }
912                do {
913                    e.setIndex(e.getIndex() + 1);
914                } while (e.getIndex() < dim && e.getValue() == 0);
915                if (e.getIndex() >= dim) {
916                    e.setIndex(-1);
917                }
918            }
919    
920            /** {@inheritDoc} */
921            public boolean hasNext() {
922                return current != null;
923            }
924    
925            /** {@inheritDoc} */
926            public Entry next() {
927                tmp.setIndex(current.getIndex());
928                if (next != null) {
929                    current.setIndex(next.getIndex());
930                    advance(next);
931                    if (next.getIndex() < 0) {
932                        next = null;
933                    }
934                } else {
935                    current = null;
936                }
937                return tmp;
938            }
939    
940            /** {@inheritDoc} */
941            public void remove() {
942                throw new UnsupportedOperationException("Not supported");
943            }
944        }
945    
946    }