blob: e39c9ceefa91582c116383ffdd478265874f5918 [file] [log] [blame]
Raymonddee08492015-04-02 10:43:13 -07001/*
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}