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 import java.util.NoSuchElementException;
022
023 import org.apache.commons.math.exception.MathUnsupportedOperationException;
024 import org.apache.commons.math.exception.DimensionMismatchException;
025 import org.apache.commons.math.exception.OutOfRangeException;
026 import org.apache.commons.math.exception.MathArithmeticException;
027 import org.apache.commons.math.analysis.FunctionUtils;
028 import org.apache.commons.math.analysis.function.Add;
029 import org.apache.commons.math.analysis.function.Multiply;
030 import org.apache.commons.math.analysis.function.Divide;
031 import org.apache.commons.math.analysis.UnivariateRealFunction;
032 import org.apache.commons.math.exception.util.LocalizedFormats;
033 import org.apache.commons.math.util.FastMath;
034
035 /**
036 * Class defining a real-valued vector with basic algebraic operations.
037 * <p>
038 * vector element indexing is 0-based -- e.g., {@code getEntry(0)}
039 * returns the first element of the vector.
040 * </p>
041 * <p>
042 * The {@code code map} and {@code mapToSelf} methods operate
043 * on vectors element-wise, i.e. they perform the same operation (adding a scalar,
044 * applying a function ...) on each element in turn. The {@code map}
045 * versions create a new vector to hold the result and do not change the instance.
046 * The {@code mapToSelf} version uses the instance itself to store the
047 * results, so the instance is changed by this method. In all cases, the result
048 * vector is returned by the methods, allowing the <i>fluent API</i>
049 * style, like this:
050 * </p>
051 * <pre>
052 * RealVector result = v.mapAddToSelf(3.4).mapToSelf(new Tan()).mapToSelf(new Power(2.3));
053 * </pre>
054 *
055 * @version $Id: RealVector.java 1185398 2011-10-17 22:10:42Z erans $
056 * @since 2.1
057 */
058 public abstract class RealVector {
059 /**
060 * Returns the size of the vector.
061 *
062 * @return the size of this vector.
063 */
064 public abstract int getDimension();
065
066 /**
067 * Return the entry at the specified index.
068 *
069 * @param index Index location of entry to be fetched.
070 * @return the vector entry at {@code index}.
071 * @throws org.apache.commons.math.exception.OutOfRangeException
072 * if the index is not valid.
073 * @see #setEntry(int, double)
074 */
075 public abstract double getEntry(int index);
076
077 /**
078 * Set a single element.
079 *
080 * @param index element index.
081 * @param value new value for the element.
082 * @throws org.apache.commons.math.exception.OutOfRangeException
083 * if the index is not valid.
084 * @see #getEntry(int)
085 */
086 public abstract void setEntry(int index, double value);
087
088 /**
089 * Change an entry at the specified index.
090 *
091 * @param index Index location of entry to be set.
092 * @param increment Value to add to the vector entry.
093 * @throws org.apache.commons.math.exception.OutOfRangeException if
094 * the index is not valid.
095 * @since 3.0
096 */
097 public void addToEntry(int index, double increment) {
098 setEntry(index, getEntry(index) + increment);
099 }
100
101 /**
102 * Construct a new vector by appending a vector to this vector.
103 *
104 * @param v vector to append to this one.
105 * @return a new vector.
106 */
107 public abstract RealVector append(RealVector v);
108
109 /**
110 * Construct a new vector by appending a double to this vector.
111 *
112 * @param d double to append.
113 * @return a new vector.
114 */
115 public abstract RealVector append(double d);
116
117 /**
118 * Get a subvector from consecutive elements.
119 *
120 * @param index index of first element.
121 * @param n number of elements to be retrieved.
122 * @return a vector containing n elements.
123 * @throws org.apache.commons.math.exception.OutOfRangeException
124 * if the index is not valid.
125 */
126 public abstract RealVector getSubVector(int index, int n);
127
128 /**
129 * Set a sequence of consecutive elements.
130 *
131 * @param index index of first element to be set.
132 * @param v vector containing the values to set.
133 * @throws org.apache.commons.math.exception.OutOfRangeException
134 * if the index is not valid.
135 */
136 public abstract void setSubVector(int index, RealVector v);
137
138 /**
139 * Check whether any coordinate of this vector is {@code NaN}.
140 *
141 * @return {@code true} if any coordinate of this vector is {@code NaN},
142 * {@code false} otherwise.
143 */
144 public abstract boolean isNaN();
145
146 /**
147 * Check whether any coordinate of this vector is infinite and none are {@code NaN}.
148 *
149 * @return {@code true} if any coordinate of this vector is infinite and
150 * none are {@code NaN}, {@code false} otherwise.
151 */
152 public abstract boolean isInfinite();
153
154 /**
155 * Check if instance and specified vectors have the same dimension.
156 *
157 * @param v Vector to compare instance with.
158 * @throws DimensionMismatchException if the vectors do not
159 * have the same dimension.
160 */
161 protected void checkVectorDimensions(RealVector v) {
162 checkVectorDimensions(v.getDimension());
163 }
164
165 /**
166 * Check if instance dimension is equal to some expected value.
167 *
168 * @param n Expected dimension.
169 * @throws DimensionMismatchException if the dimension is
170 * inconsistent with the vector size.
171 */
172 protected void checkVectorDimensions(int n) {
173 int d = getDimension();
174 if (d != n) {
175 throw new DimensionMismatchException(d, n);
176 }
177 }
178
179 /**
180 * Check if an index is valid.
181 *
182 * @param index Index to check.
183 * @exception OutOfRangeException if {@code index} is not valid.
184 */
185 protected void checkIndex(final int index) {
186 if (index < 0 ||
187 index >= getDimension()) {
188 throw new OutOfRangeException(LocalizedFormats.INDEX,
189 index, 0, getDimension() - 1);
190 }
191 }
192
193 /**
194 * Compute the sum of this vector and {@code v}.
195 * Returns a new vector. Does not change instance data.
196 *
197 * @param v Vector to be added.
198 * @return {@code this} + {@code v}.
199 * @throws org.apache.commons.math.exception.DimensionMismatchException
200 * if {@code v} is not the same size as this vector.
201 */
202 public RealVector add(RealVector v) {
203 RealVector result = v.copy();
204 Iterator<Entry> it = sparseIterator();
205 Entry e;
206 while (it.hasNext() && (e = it.next()) != null) {
207 final int index = e.getIndex();
208 result.setEntry(index, e.getValue() + result.getEntry(index));
209 }
210 return result;
211 }
212
213 /**
214 * Subtract {@code v} from this vector.
215 * Returns a new vector. Does not change instance data.
216 *
217 * @param v Vector to be subtracted.
218 * @return {@code this} - {@code v}.
219 * @throws org.apache.commons.math.exception.DimensionMismatchException
220 * if {@code v} is not the same size as this vector.
221 */
222 public RealVector subtract(RealVector v) {
223 RealVector result = v.copy();
224 Iterator<Entry> it = sparseIterator();
225 Entry e;
226 while (it.hasNext() && (e = it.next()) != null) {
227 final int index = e.getIndex();
228 result.setEntry(index, e.getValue() - result.getEntry(index));
229 }
230 return result;
231 }
232
233 /**
234 * Add a value to each entry.
235 * Returns a new vector. Does not change instance data.
236 *
237 * @param d Value to be added to each entry.
238 * @return {@code this} + {@code d}.
239 */
240 public RealVector mapAdd(double d) {
241 return copy().mapAddToSelf(d);
242 }
243
244 /**
245 * Add a value to each entry.
246 * The instance is changed in-place.
247 *
248 * @param d Value to be added to each entry.
249 * @return {@code this}.
250 */
251 public RealVector mapAddToSelf(double d) {
252 if (d != 0) {
253 return mapToSelf(FunctionUtils.fix2ndArgument(new Add(), d));
254 }
255 return this;
256 }
257
258 /**
259 * Returns a (deep) copy of this vector.
260 *
261 * @return a vector copy.
262 */
263 public abstract RealVector copy();
264
265 /**
266 * Compute the dot product of this vector with {@code v}.
267 *
268 * @param v Vector with which dot product should be computed
269 * @return the scalar dot product between this instance and {@code v}.
270 * @throws org.apache.commons.math.exception.DimensionMismatchException
271 * if {@code v} is not the same size as this vector.
272 */
273 public double dotProduct(RealVector v) {
274 checkVectorDimensions(v);
275 double d = 0;
276 Iterator<Entry> it = sparseIterator();
277 Entry e;
278 while (it.hasNext() && (e = it.next()) != null) {
279 d += e.getValue() * v.getEntry(e.getIndex());
280 }
281 return d;
282 }
283
284 /**
285 * Computes the cosine of the angle between this vector and the
286 * argument.
287 *
288 * @param v Vector.
289 * @return the cosine of the angle between this vector and {@code v}.
290 */
291 public double cosine(RealVector v) {
292 final double norm = getNorm();
293 final double vNorm = v.getNorm();
294
295 if (norm == 0 ||
296 vNorm == 0) {
297 throw new MathArithmeticException(LocalizedFormats.ZERO_NORM);
298 }
299 return dotProduct(v) / (norm * vNorm);
300 }
301
302 /**
303 * Element-by-element division.
304 *
305 * @param v Vector by which instance elements must be divided.
306 * @return a vector containing this[i] / v[i] for all i.
307 * @throws org.apache.commons.math.exception.DimensionMismatchException
308 * if {@code v} is not the same size as this vector.
309 */
310 public abstract RealVector ebeDivide(RealVector v);
311
312 /**
313 * Element-by-element multiplication.
314 *
315 * @param v Vector by which instance elements must be multiplied
316 * @return a vector containing this[i] * v[i] for all i.
317 * @throws org.apache.commons.math.exception.DimensionMismatchException
318 * if {@code v} is not the same size as this vector.
319 */
320 public abstract RealVector ebeMultiply(RealVector v);
321
322 /**
323 * Distance between two vectors.
324 * <p>This method computes the distance consistent with the
325 * L<sub>2</sub> norm, i.e. the square root of the sum of
326 * element differences, or Euclidian distance.</p>
327 *
328 * @param v Vector to which distance is requested.
329 * @return the distance between two vectors.
330 * @throws org.apache.commons.math.exception.DimensionMismatchException
331 * if {@code v} is not the same size as this vector.
332 * @see #getL1Distance(RealVector)
333 * @see #getLInfDistance(RealVector)
334 * @see #getNorm()
335 */
336 public double getDistance(RealVector v) {
337 checkVectorDimensions(v);
338 double d = 0;
339 Iterator<Entry> it = iterator();
340 Entry e;
341 while (it.hasNext() && (e = it.next()) != null) {
342 final double diff = e.getValue() - v.getEntry(e.getIndex());
343 d += diff * diff;
344 }
345 return FastMath.sqrt(d);
346 }
347
348 /**
349 * Returns the L<sub>2</sub> norm of the vector.
350 * <p>The L<sub>2</sub> norm is the root of the sum of
351 * the squared elements.</p>
352 *
353 * @return the norm.
354 * @see #getL1Norm()
355 * @see #getLInfNorm()
356 * @see #getDistance(RealVector)
357 */
358 public double getNorm() {
359 double sum = 0;
360 Iterator<Entry> it = sparseIterator();
361 Entry e;
362 while (it.hasNext() && (e = it.next()) != null) {
363 final double value = e.getValue();
364 sum += value * value;
365 }
366 return FastMath.sqrt(sum);
367 }
368
369 /**
370 * Returns the L<sub>1</sub> norm of the vector.
371 * <p>The L<sub>1</sub> norm is the sum of the absolute
372 * values of the elements.</p>
373 *
374 * @return the norm.
375 * @see #getNorm()
376 * @see #getLInfNorm()
377 * @see #getL1Distance(RealVector)
378 */
379 public double getL1Norm() {
380 double norm = 0;
381 Iterator<Entry> it = sparseIterator();
382 Entry e;
383 while (it.hasNext() && (e = it.next()) != null) {
384 norm += FastMath.abs(e.getValue());
385 }
386 return norm;
387 }
388
389 /**
390 * Returns the L<sub>∞</sub> norm of the vector.
391 * <p>The L<sub>∞</sub> norm is the max of the absolute
392 * values of the elements.</p>
393 *
394 * @return the norm.
395 * @see #getNorm()
396 * @see #getL1Norm()
397 * @see #getLInfDistance(RealVector)
398 */
399 public double getLInfNorm() {
400 double norm = 0;
401 Iterator<Entry> it = sparseIterator();
402 Entry e;
403 while (it.hasNext() && (e = it.next()) != null) {
404 norm = FastMath.max(norm, FastMath.abs(e.getValue()));
405 }
406 return norm;
407 }
408
409 /**
410 * Distance between two vectors.
411 * <p>This method computes the distance consistent with
412 * L<sub>1</sub> norm, i.e. the sum of the absolute values of
413 * the elements differences.</p>
414 *
415 * @param v Vector to which distance is requested.
416 * @return the distance between two vectors.
417 * @throws org.apache.commons.math.exception.DimensionMismatchException
418 * if {@code v} is not the same size as this vector.
419 */
420 public double getL1Distance(RealVector v) {
421 checkVectorDimensions(v);
422 double d = 0;
423 Iterator<Entry> it = iterator();
424 Entry e;
425 while (it.hasNext() && (e = it.next()) != null) {
426 d += FastMath.abs(e.getValue() - v.getEntry(e.getIndex()));
427 }
428 return d;
429 }
430
431 /**
432 * Distance between two vectors.
433 * <p>This method computes the distance consistent with
434 * L<sub>∞</sub> norm, i.e. the max of the absolute values of
435 * element differences.</p>
436 *
437 * @param v Vector to which distance is requested.
438 * @return the distance between two vectors.
439 * @throws org.apache.commons.math.exception.DimensionMismatchException
440 * if {@code v} is not the same size as this vector.
441 * @see #getDistance(RealVector)
442 * @see #getL1Distance(RealVector)
443 * @see #getLInfNorm()
444 */
445 public double getLInfDistance(RealVector v) {
446 checkVectorDimensions(v);
447 double d = 0;
448 Iterator<Entry> it = iterator();
449 Entry e;
450 while (it.hasNext() && (e = it.next()) != null) {
451 d = FastMath.max(FastMath.abs(e.getValue() - v.getEntry(e.getIndex())), d);
452 }
453 return d;
454 }
455
456 /**
457 * Get the index of the minimum entry.
458 *
459 * @return the index of the minimum entry or -1 if vector length is 0
460 * or all entries are {@code NaN}.
461 */
462 public int getMinIndex() {
463 int minIndex = -1;
464 double minValue = Double.POSITIVE_INFINITY;
465 Iterator<Entry> iterator = iterator();
466 while (iterator.hasNext()) {
467 final Entry entry = iterator.next();
468 if (entry.getValue() <= minValue) {
469 minIndex = entry.getIndex();
470 minValue = entry.getValue();
471 }
472 }
473 return minIndex;
474 }
475
476 /**
477 * Get the value of the minimum entry.
478 *
479 * @return the value of the minimum entry or {@code NaN} if all
480 * entries are {@code NaN}.
481 */
482 public double getMinValue() {
483 final int minIndex = getMinIndex();
484 return minIndex < 0 ? Double.NaN : getEntry(minIndex);
485 }
486
487 /**
488 * Get the index of the maximum entry.
489 *
490 * @return the index of the maximum entry or -1 if vector length is 0
491 * or all entries are {@code NaN}
492 */
493 public int getMaxIndex() {
494 int maxIndex = -1;
495 double maxValue = Double.NEGATIVE_INFINITY;
496 Iterator<Entry> iterator = iterator();
497 while (iterator.hasNext()) {
498 final Entry entry = iterator.next();
499 if (entry.getValue() >= maxValue) {
500 maxIndex = entry.getIndex();
501 maxValue = entry.getValue();
502 }
503 }
504 return maxIndex;
505 }
506
507 /**
508 * Get the value of the maximum entry.
509 *
510 * @return the value of the maximum entry or {@code NaN} if all
511 * entries are {@code NaN}.
512 */
513 public double getMaxValue() {
514 final int maxIndex = getMaxIndex();
515 return maxIndex < 0 ? Double.NaN : getEntry(maxIndex);
516 }
517
518
519 /**
520 * Multiply each entry by the argument. Returns a new vector.
521 * Does not change instance data.
522 *
523 * @param d Multiplication factor.
524 * @return {@code this} * {@code d}.
525 */
526 public RealVector mapMultiply(double d) {
527 return copy().mapMultiplyToSelf(d);
528 }
529
530 /**
531 * Multiply each entry.
532 * The instance is changed in-place.
533 *
534 * @param d Multiplication factor.
535 * @return {@code this}.
536 */
537 public RealVector mapMultiplyToSelf(double d){
538 return mapToSelf(FunctionUtils.fix2ndArgument(new Multiply(), d));
539 }
540
541 /**
542 * Subtract a value from each entry. Returns a new vector.
543 * Does not change instance data.
544 *
545 * @param d Value to be subtracted.
546 * @return {@code this} - {@code d}.
547 */
548 public RealVector mapSubtract(double d) {
549 return copy().mapSubtractToSelf(d);
550 }
551
552 /**
553 * Subtract a value from each entry.
554 * The instance is changed in-place.
555 *
556 * @param d Value to be subtracted.
557 * @return {@code this}.
558 */
559 public RealVector mapSubtractToSelf(double d){
560 return mapAddToSelf(-d);
561 }
562
563 /**
564 * Divide each entry by the argument. Returns a new vector.
565 * Does not change instance data.
566 *
567 * @param d Value to divide by.
568 * @return {@code this} / {@code d}.
569 */
570 public RealVector mapDivide(double d) {
571 return copy().mapDivideToSelf(d);
572 }
573
574 /**
575 * Divide each entry by the argument.
576 * The instance is changed in-place.
577 *
578 * @param d Value to divide by.
579 * @return {@code this}.
580 */
581 public RealVector mapDivideToSelf(double d){
582 return mapToSelf(FunctionUtils.fix2ndArgument(new Divide(), d));
583 }
584
585 /**
586 * Compute the outer product.
587 *
588 * @param v Vector with which outer product should be computed.
589 * @return the matrix outer product between this instance and {@code v}.
590 */
591 public RealMatrix outerProduct(RealVector v) {
592 RealMatrix product;
593 if (v instanceof SparseRealVector || this instanceof SparseRealVector) {
594 product = new OpenMapRealMatrix(this.getDimension(),
595 v.getDimension());
596 } else {
597 product = new Array2DRowRealMatrix(this.getDimension(),
598 v.getDimension());
599 }
600 Iterator<Entry> thisIt = sparseIterator();
601 Entry thisE = null;
602 while (thisIt.hasNext() && (thisE = thisIt.next()) != null) {
603 Iterator<Entry> otherIt = v.sparseIterator();
604 Entry otherE = null;
605 while (otherIt.hasNext() && (otherE = otherIt.next()) != null) {
606 product.setEntry(thisE.getIndex(), otherE.getIndex(),
607 thisE.getValue() * otherE.getValue());
608 }
609 }
610
611 return product;
612
613 }
614
615 /**
616 * Find the orthogonal projection of this vector onto another vector.
617 *
618 * @param v vector onto which instance must be projected.
619 * @return projection of the instance onto {@code v}.
620 * @throws org.apache.commons.math.exception.DimensionMismatchException
621 * if {@code v} is not the same size as this vector.
622 */
623 public abstract RealVector projection(RealVector v);
624
625 /**
626 * Set all elements to a single value.
627 *
628 * @param value Single value to set for all elements.
629 */
630 public void set(double value) {
631 Iterator<Entry> it = iterator();
632 Entry e = null;
633 while (it.hasNext() && (e = it.next()) != null) {
634 e.setValue(value);
635 }
636 }
637
638 /**
639 * Convert the vector to an array of {@code double}s.
640 * The array is independent from this vector data: the elements
641 * are copied.
642 *
643 * @return an array containing a copy of the vector elements.
644 */
645 public double[] toArray() {
646 int dim = getDimension();
647 double[] values = new double[dim];
648 for (int i = 0; i < dim; i++) {
649 values[i] = getEntry(i);
650 }
651 return values;
652 }
653
654 /**
655 * Creates a unit vector pointing in the direction of this vector.
656 * The instance is not changed by this method.
657 *
658 * @return a unit vector pointing in direction of this vector.
659 * @throws ArithmeticException if the norm is {@code null}.
660 */
661 public RealVector unitVector() {
662 RealVector copy = copy();
663 copy.unitize();
664 return copy;
665 }
666
667 /**
668 * Converts this vector into a unit vector.
669 * The instance itself is changed by this method.
670 *
671 * @throws org.apache.commons.math.exception.MathArithmeticException
672 * if the norm is zero.
673 */
674 public void unitize() {
675 mapDivideToSelf(getNorm());
676 }
677
678 /**
679 * Create a sparse iterator over the vector, which may omit some entries.
680 * Specialized implementations may choose to not iterate over all
681 * dimensions, either because those values are unset, or are equal
682 * to defaultValue(), or are small enough to be ignored for the
683 * purposes of iteration. No guarantees are made about order of iteration.
684 * In dense implementations, this method will often delegate to
685 * {@link #iterator()}.
686 *
687 * @return a sparse iterator.
688 */
689 public Iterator<Entry> sparseIterator() {
690 return new SparseEntryIterator();
691 }
692
693 /**
694 * Generic dense iterator. Iteration is in increasing order
695 * of the vector index.
696 *
697 * @return a dense iterator.
698 */
699 public Iterator<Entry> iterator() {
700 final int dim = getDimension();
701 return new Iterator<Entry>() {
702
703 /** Current index. */
704 private int i = 0;
705
706 /** Current entry. */
707 private Entry e = new Entry();
708
709 /** {@inheritDoc} */
710 public boolean hasNext() {
711 return i < dim;
712 }
713
714 /** {@inheritDoc} */
715 public Entry next() {
716 e.setIndex(i++);
717 return e;
718 }
719
720 /** {@inheritDoc} */
721 public void remove() {
722 throw new MathUnsupportedOperationException();
723 }
724 };
725 }
726
727 /**
728 * Acts as if implemented as:
729 * <pre>
730 * return copy().mapToSelf(function);
731 * </pre>
732 * Returns a new vector. Does not change instance data.
733 *
734 * @param function Function to apply to each entry.
735 * @return a new vector.
736 */
737 public RealVector map(UnivariateRealFunction function) {
738 return copy().mapToSelf(function);
739 }
740
741 /**
742 * Acts as if it is implemented as:
743 * <pre>
744 * Entry e = null;
745 * for(Iterator<Entry> it = iterator(); it.hasNext(); e = it.next()) {
746 * e.setValue(function.value(e.getValue()));
747 * }
748 * </pre>
749 * Entries of this vector are modified in-place by this method.
750 *
751 * @param function Function to apply to each entry.
752 * @return a reference to this vector.
753 */
754 public RealVector mapToSelf(UnivariateRealFunction function) {
755 Iterator<Entry> it = (function.value(0) == 0) ? sparseIterator() : iterator();
756 Entry e;
757 while (it.hasNext() && (e = it.next()) != null) {
758 e.setValue(function.value(e.getValue()));
759 }
760 return this;
761 }
762
763 /**
764 * Returns a new vector representing {@code a * this + b * y}, the linear
765 * combination of {@code this} and {@code y}.
766 * Returns a new vector. Does not change instance data.
767 *
768 * @param a Coefficient of {@code this}.
769 * @param b Coefficient of {@code y}.
770 * @param y Vector with which {@code this} is linearly combined.
771 * @return a vector containing {@code a * this[i] + b * y[i]} for all
772 * {@code i}.
773 * @throws org.apache.commons.math.exception.DimensionMismatchException
774 * if {@code y} is not the same size as this vector.
775 */
776 public RealVector combine(double a, double b, RealVector y) {
777 return copy().combineToSelf(a, b, y);
778 }
779
780 /**
781 * Updates {@code this} with the linear combination of {@code this} and
782 * {@code y}.
783 *
784 * @param a Weight of {@code this}.
785 * @param b Weight of {@code y}.
786 * @param y Vector with which {@code this} is linearly combined.
787 * @return {@code this}, with components equal to
788 * {@code a * this[i] + b * y[i]} for all {@code i}.
789 * @throws org.apache.commons.math.exception.DimensionMismatchException
790 * if {@code y} is not the same size as this vector.
791 */
792 public RealVector combineToSelf(double a, double b, RealVector y) {
793 checkVectorDimensions(y);
794 for (int i = 0; i < getDimension(); i++) {
795 final double xi = getEntry(i);
796 final double yi = y.getEntry(i);
797 setEntry(i, a * xi + b * yi);
798 }
799 return this;
800 }
801
802 /**
803 * An entry in the vector.
804 */
805 protected class Entry {
806 /** Index of this entry. */
807 private int index;
808
809 /** Simple constructor. */
810 public Entry() {
811 setIndex(0);
812 }
813
814 /**
815 * Get the value of the entry.
816 *
817 * @return the value of the entry.
818 */
819 public double getValue() {
820 return getEntry(getIndex());
821 }
822
823 /**
824 * Set the value of the entry.
825 *
826 * @param value New value for the entry.
827 */
828 public void setValue(double value) {
829 setEntry(getIndex(), value);
830 }
831
832 /**
833 * Get the index of the entry.
834 *
835 * @return the index of the entry.
836 */
837 public int getIndex() {
838 return index;
839 }
840
841 /**
842 * Set the index of the entry.
843 *
844 * @param index New index for the entry.
845 */
846 public void setIndex(int index) {
847 this.index = index;
848 }
849 }
850
851 /**
852 * This class should rarely be used, but is here to provide
853 * a default implementation of sparseIterator(), which is implemented
854 * by walking over the entries, skipping those whose values are the default one.
855 *
856 * Concrete subclasses which are SparseVector implementations should
857 * make their own sparse iterator, rather than using this one.
858 *
859 * This implementation might be useful for ArrayRealVector, when expensive
860 * operations which preserve the default value are to be done on the entries,
861 * and the fraction of non-default values is small (i.e. someone took a
862 * SparseVector, and passed it into the copy-constructor of ArrayRealVector)
863 */
864 protected class SparseEntryIterator implements Iterator<Entry> {
865 /** Dimension of the vector. */
866 private final int dim;
867 /** Last entry returned by {@link #next()}. */
868 private Entry current;
869 /** Next entry for {@link #next()} to return. */
870 private Entry next;
871
872 /** Simple constructor. */
873 protected SparseEntryIterator() {
874 dim = getDimension();
875 current = new Entry();
876 next = new Entry();
877 if (next.getValue() == 0) {
878 advance(next);
879 }
880 }
881
882 /**
883 * Advance an entry up to the next nonzero one.
884 *
885 * @param e entry to advance.
886 */
887 protected void advance(Entry e) {
888 if (e == null) {
889 return;
890 }
891 do {
892 e.setIndex(e.getIndex() + 1);
893 } while (e.getIndex() < dim && e.getValue() == 0);
894 if (e.getIndex() >= dim) {
895 e.setIndex(-1);
896 }
897 }
898
899 /** {@inheritDoc} */
900 public boolean hasNext() {
901 return next.getIndex() >= 0;
902 }
903
904 /** {@inheritDoc} */
905 public Entry next() {
906 int index = next.getIndex();
907 if (index < 0) {
908 throw new NoSuchElementException();
909 }
910 current.setIndex(index);
911 advance(next);
912 return current;
913 }
914
915 /** {@inheritDoc} */
916 public void remove() {
917 throw new MathUnsupportedOperationException();
918 }
919 }
920
921 /**
922 * Returns an unmodifiable view of the specified vector.
923 * The returned vector has read-only access. An attempt to modify it will
924 * result in a {@link MathUnsupportedOperationException}. However, the
925 * returned vector is <em>not</em> immutable, since any modification of
926 * {@code v} will also change the returned view.
927 * For example, in the following piece of code
928 * <pre>
929 * RealVector v = new ArrayRealVector(2);
930 * RealVector w = RealVector.unmodifiableRealVector(v);
931 * v.setEntry(0, 1.2);
932 * v.setEntry(1, -3.4);
933 * </pre>
934 * the changes will be seen in the {@code w} view of {@code v}.
935 *
936 * @param v Vector for which an unmodifiable view is to be returned.
937 * @return an unmodifiable view of {@code v}.
938 */
939 public static RealVector unmodifiableRealVector(final RealVector v) {
940 /**
941 * This anonymous class is an implementation of {@link RealVector}
942 * with read-only access.
943 * It wraps any {@link RealVector}, and exposes all methods which
944 * do not modify it. Invoking methods which should normally result
945 * in the modification of the calling {@link RealVector} results in
946 * a {@link MathUnsupportedOperationException}. It should be noted
947 * that {@link UnmodifiableVector} is <em>not</em> immutable.
948 */
949 return new RealVector() {
950 /** {@inheritDoc} */
951 @Override
952 public RealVector mapToSelf(UnivariateRealFunction function) {
953 throw new MathUnsupportedOperationException();
954 }
955
956 /** {@inheritDoc} */
957 @Override
958 public RealVector map(UnivariateRealFunction function) {
959 return v.map(function);
960 }
961
962 /** {@inheritDoc} */
963 @Override
964 public Iterator<Entry> iterator() {
965 final Iterator<Entry> i = v.iterator();
966 return new Iterator<Entry>() {
967 /** The current entry. */
968 private final UnmodifiableEntry e = new UnmodifiableEntry();
969
970 /** {@inheritDoc} */
971 public boolean hasNext() {
972 return i.hasNext();
973 }
974
975 /** {@inheritDoc} */
976 public Entry next() {
977 e.setIndex(i.next().getIndex());
978 return e;
979 }
980
981 /** {@inheritDoc} */
982 public void remove() {
983 throw new MathUnsupportedOperationException();
984 }
985 };
986 }
987
988 /** {@inheritDoc} */
989 @Override
990 public Iterator<Entry> sparseIterator() {
991 final Iterator<Entry> i = v.sparseIterator();
992
993 return new Iterator<Entry>() {
994 /** The current entry. */
995 private final UnmodifiableEntry e = new UnmodifiableEntry();
996
997 /** {@inheritDoc} */
998 public boolean hasNext() {
999 return i.hasNext();
1000 }
1001
1002 /** {@inheritDoc} */
1003 public Entry next() {
1004 e.setIndex(i.next().getIndex());
1005 return e;
1006 }
1007
1008 /** {@inheritDoc} */
1009 public void remove() {
1010 throw new MathUnsupportedOperationException();
1011 }
1012 };
1013 }
1014
1015 /** {@inheritDoc} */
1016 @Override
1017 public RealVector copy() {
1018 return v.copy();
1019 }
1020
1021 /** {@inheritDoc} */
1022 @Override
1023 public RealVector add(RealVector w) {
1024 return v.add(w);
1025 }
1026
1027 /** {@inheritDoc} */
1028 @Override
1029 public RealVector subtract(RealVector w) {
1030 return v.subtract(w);
1031 }
1032
1033 /** {@inheritDoc} */
1034 @Override
1035 public RealVector mapAdd(double d) {
1036 return v.mapAdd(d);
1037 }
1038
1039 /** {@inheritDoc} */
1040 @Override
1041 public RealVector mapAddToSelf(double d) {
1042 throw new MathUnsupportedOperationException();
1043 }
1044
1045 /** {@inheritDoc} */
1046 @Override
1047 public RealVector mapSubtract(double d) {
1048 return v.mapSubtract(d);
1049 }
1050
1051 /** {@inheritDoc} */
1052 @Override
1053 public RealVector mapSubtractToSelf(double d) {
1054 throw new MathUnsupportedOperationException();
1055 }
1056
1057 /** {@inheritDoc} */
1058 @Override
1059 public RealVector mapMultiply(double d) {
1060 return v.mapMultiply(d);
1061 }
1062
1063 /** {@inheritDoc} */
1064 @Override
1065 public RealVector mapMultiplyToSelf(double d) {
1066 throw new MathUnsupportedOperationException();
1067 }
1068
1069 /** {@inheritDoc} */
1070 @Override
1071 public RealVector mapDivide(double d) {
1072 return v.mapDivide(d);
1073 }
1074
1075 /** {@inheritDoc} */
1076 @Override
1077 public RealVector mapDivideToSelf(double d) {
1078 throw new MathUnsupportedOperationException();
1079 }
1080
1081 /** {@inheritDoc} */
1082 @Override
1083 public RealVector ebeMultiply(RealVector w) {
1084 return v.ebeMultiply(w);
1085 }
1086
1087 /** {@inheritDoc} */
1088 @Override
1089 public RealVector ebeDivide(RealVector w) {
1090 return v.ebeDivide(w);
1091 }
1092
1093 /** {@inheritDoc} */
1094 @Override
1095 public double dotProduct(RealVector w) {
1096 return v.dotProduct(w);
1097 }
1098
1099 /** {@inheritDoc} */
1100 @Override
1101 public double cosine(RealVector w) {
1102 return v.cosine(w);
1103 }
1104
1105 /** {@inheritDoc} */
1106 @Override
1107 public double getNorm() {
1108 return v.getNorm();
1109 }
1110
1111 /** {@inheritDoc} */
1112 @Override
1113 public double getL1Norm() {
1114 return v.getL1Norm();
1115 }
1116
1117 /** {@inheritDoc} */
1118 @Override
1119 public double getLInfNorm() {
1120 return v.getLInfNorm();
1121 }
1122
1123 /** {@inheritDoc} */
1124 @Override
1125 public double getDistance(RealVector w) {
1126 return v.getDistance(w);
1127 }
1128
1129 /** {@inheritDoc} */
1130 @Override
1131 public double getL1Distance(RealVector w) {
1132 return v.getL1Distance(w);
1133 }
1134
1135 /** {@inheritDoc} */
1136 @Override
1137 public double getLInfDistance(RealVector w) {
1138 return v.getLInfDistance(w);
1139 }
1140
1141 /** {@inheritDoc} */
1142 @Override
1143 public RealVector unitVector() {
1144 return v.unitVector();
1145 }
1146
1147 /** {@inheritDoc} */
1148 @Override
1149 public void unitize() {
1150 throw new MathUnsupportedOperationException();
1151 }
1152
1153 /** {@inheritDoc} */
1154 @Override
1155 public RealVector projection(RealVector w) {
1156 return v.projection(w);
1157 }
1158
1159 /** {@inheritDoc} */
1160 @Override
1161 public RealMatrix outerProduct(RealVector w) {
1162 return v.outerProduct(w);
1163 }
1164
1165 /** {@inheritDoc} */
1166 @Override
1167 public double getEntry(int index) {
1168 return v.getEntry(index);
1169 }
1170
1171 /** {@inheritDoc} */
1172 @Override
1173 public void setEntry(int index, double value) {
1174 throw new MathUnsupportedOperationException();
1175 }
1176
1177 /** {@inheritDoc} */
1178 @Override
1179 public void addToEntry(int index, double value) {
1180 throw new MathUnsupportedOperationException();
1181 }
1182
1183 /** {@inheritDoc} */
1184 @Override
1185 public int getDimension() {
1186 return v.getDimension();
1187 }
1188
1189 /** {@inheritDoc} */
1190 @Override
1191 public RealVector append(RealVector w) {
1192 return v.append(w);
1193 }
1194
1195 /** {@inheritDoc} */
1196 @Override
1197 public RealVector append(double d) {
1198 return v.append(d);
1199 }
1200
1201 /** {@inheritDoc} */
1202 @Override
1203 public RealVector getSubVector(int index, int n) {
1204 return v.getSubVector(index, n);
1205 }
1206
1207 /** {@inheritDoc} */
1208 @Override
1209 public void setSubVector(int index, RealVector w) {
1210 throw new MathUnsupportedOperationException();
1211 }
1212
1213 /** {@inheritDoc} */
1214 @Override
1215 public void set(double value) {
1216 throw new MathUnsupportedOperationException();
1217 }
1218
1219 /** {@inheritDoc} */
1220 @Override
1221 public double[] toArray() {
1222 return v.toArray();
1223 }
1224
1225 /** {@inheritDoc} */
1226 @Override
1227 public boolean isNaN() {
1228 return v.isNaN();
1229 }
1230
1231 /** {@inheritDoc} */
1232 @Override
1233 public boolean isInfinite() {
1234 return v.isInfinite();
1235 }
1236
1237 /** {@inheritDoc} */
1238 @Override
1239 public RealVector combine(double a, double b, RealVector y) {
1240 return v.combine(a, b, y);
1241 }
1242
1243 /** {@inheritDoc} */
1244 @Override
1245 public RealVector combineToSelf(double a, double b, RealVector y) {
1246 throw new MathUnsupportedOperationException();
1247 }
1248
1249 /** An entry in the vector. */
1250 class UnmodifiableEntry extends Entry {
1251 /** {@inheritDoc} */
1252 @Override
1253 public double getValue() {
1254 return v.getEntry(getIndex());
1255 }
1256
1257 /** {@inheritDoc} */
1258 @Override
1259 public void setValue(double value) {
1260 throw new MathUnsupportedOperationException();
1261 }
1262 }
1263 };
1264 }
1265 }