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 }