• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 package org.apache.commons.math.linear;
19 
20 import java.util.Iterator;
21 import java.util.NoSuchElementException;
22 
23 import org.apache.commons.math.FunctionEvaluationException;
24 import org.apache.commons.math.exception.MathUnsupportedOperationException;
25 import org.apache.commons.math.exception.DimensionMismatchException;
26 import org.apache.commons.math.analysis.BinaryFunction;
27 import org.apache.commons.math.analysis.ComposableFunction;
28 import org.apache.commons.math.analysis.UnivariateRealFunction;
29 import org.apache.commons.math.exception.util.LocalizedFormats;
30 import 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  */
38 public 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      */
checkVectorDimensions(RealVector v)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      */
checkVectorDimensions(int n)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      */
checkIndex(final int index)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} */
setSubVector(int index, RealVector v)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} */
setSubVector(int index, double[] v)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} */
add(double[] v)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} */
add(RealVector v)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} */
subtract(double[] v)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} */
subtract(RealVector v)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} */
mapAdd(double d)150     public RealVector mapAdd(double d) {
151         return copy().mapAddToSelf(d);
152     }
153 
154     /** {@inheritDoc} */
mapAddToSelf(double d)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} */
copy()167     public abstract AbstractRealVector copy();
168 
169     /** {@inheritDoc} */
dotProduct(double[] v)170     public double dotProduct(double[] v) throws IllegalArgumentException {
171         return dotProduct(new ArrayRealVector(v, false));
172     }
173 
174     /** {@inheritDoc} */
dotProduct(RealVector v)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} */
ebeDivide(double[] v)187     public RealVector ebeDivide(double[] v) throws IllegalArgumentException {
188         return ebeDivide(new ArrayRealVector(v, false));
189     }
190 
191     /** {@inheritDoc} */
ebeMultiply(double[] v)192     public RealVector ebeMultiply(double[] v) throws IllegalArgumentException {
193         return ebeMultiply(new ArrayRealVector(v, false));
194     }
195 
196     /** {@inheritDoc} */
getDistance(RealVector v)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} */
getNorm()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} */
getL1Norm()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} */
getLInfNorm()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} */
getDistance(double[] v)244     public double getDistance(double[] v) throws IllegalArgumentException {
245         return getDistance(new ArrayRealVector(v,false));
246     }
247 
248     /** {@inheritDoc} */
getL1Distance(RealVector v)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} */
getL1Distance(double[] v)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} */
getLInfDistance(RealVector v)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} */
getLInfDistance(double[] v)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      */
getMinIndex()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      */
getMinValue()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      */
getMaxIndex()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      */
getMaxValue()343     public double getMaxValue() {
344         final int maxIndex = getMaxIndex();
345         return maxIndex < 0 ? Double.NaN : getEntry(maxIndex);
346     }
347 
348     /** {@inheritDoc} */
mapAbs()349     public RealVector mapAbs() {
350         return copy().mapAbsToSelf();
351     }
352 
353     /** {@inheritDoc} */
mapAbsToSelf()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} */
mapAcos()363     public RealVector mapAcos() {
364         return copy().mapAcosToSelf();
365     }
366 
367     /** {@inheritDoc} */
mapAcosToSelf()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} */
mapAsin()377     public RealVector mapAsin() {
378         return copy().mapAsinToSelf();
379     }
380 
381     /** {@inheritDoc} */
mapAsinToSelf()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} */
mapAtan()391     public RealVector mapAtan() {
392         return copy().mapAtanToSelf();
393     }
394 
395     /** {@inheritDoc} */
mapAtanToSelf()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} */
mapCbrt()405     public RealVector mapCbrt() {
406         return copy().mapCbrtToSelf();
407     }
408 
409     /** {@inheritDoc} */
mapCbrtToSelf()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} */
mapCeil()419     public RealVector mapCeil() {
420         return copy().mapCeilToSelf();
421     }
422 
423     /** {@inheritDoc} */
mapCeilToSelf()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} */
mapCos()433     public RealVector mapCos() {
434         return copy().mapCosToSelf();
435     }
436 
437     /** {@inheritDoc} */
mapCosToSelf()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} */
mapCosh()447     public RealVector mapCosh() {
448         return copy().mapCoshToSelf();
449     }
450 
451     /** {@inheritDoc} */
mapCoshToSelf()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} */
mapDivide(double d)461     public RealVector mapDivide(double d) {
462         return copy().mapDivideToSelf(d);
463     }
464 
465     /** {@inheritDoc} */
mapDivideToSelf(double d)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} */
mapExp()475     public RealVector mapExp() {
476         return copy().mapExpToSelf();
477     }
478 
479     /** {@inheritDoc} */
mapExpToSelf()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} */
mapExpm1()489     public RealVector mapExpm1() {
490         return copy().mapExpm1ToSelf();
491     }
492 
493     /** {@inheritDoc} */
mapExpm1ToSelf()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} */
mapFloor()503     public RealVector mapFloor() {
504         return copy().mapFloorToSelf();
505     }
506 
507     /** {@inheritDoc} */
mapFloorToSelf()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} */
mapInv()517     public RealVector mapInv() {
518         return copy().mapInvToSelf();
519     }
520 
521     /** {@inheritDoc} */
mapInvToSelf()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} */
mapLog()531     public RealVector mapLog() {
532         return copy().mapLogToSelf();
533     }
534 
535     /** {@inheritDoc} */
mapLogToSelf()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} */
mapLog10()545     public RealVector mapLog10() {
546         return copy().mapLog10ToSelf();
547     }
548 
549     /** {@inheritDoc} */
mapLog10ToSelf()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} */
mapLog1p()559     public RealVector mapLog1p() {
560         return copy().mapLog1pToSelf();
561     }
562 
563     /** {@inheritDoc} */
mapLog1pToSelf()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} */
mapMultiply(double d)573     public RealVector mapMultiply(double d) {
574         return copy().mapMultiplyToSelf(d);
575     }
576 
577     /** {@inheritDoc} */
mapMultiplyToSelf(double d)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} */
mapPow(double d)587     public RealVector mapPow(double d) {
588         return copy().mapPowToSelf(d);
589     }
590 
591     /** {@inheritDoc} */
mapPowToSelf(double d)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} */
mapRint()601     public RealVector mapRint() {
602         return copy().mapRintToSelf();
603     }
604 
605     /** {@inheritDoc} */
mapRintToSelf()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} */
mapSignum()615     public RealVector mapSignum() {
616         return copy().mapSignumToSelf();
617     }
618 
619     /** {@inheritDoc} */
mapSignumToSelf()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} */
mapSin()629     public RealVector mapSin() {
630         return copy().mapSinToSelf();
631     }
632 
633     /** {@inheritDoc} */
mapSinToSelf()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} */
mapSinh()643     public RealVector mapSinh() {
644         return copy().mapSinhToSelf();
645     }
646 
647     /** {@inheritDoc} */
mapSinhToSelf()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} */
mapSqrt()657     public RealVector mapSqrt() {
658         return copy().mapSqrtToSelf();
659     }
660 
661     /** {@inheritDoc} */
mapSqrtToSelf()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} */
mapSubtract(double d)671     public RealVector mapSubtract(double d) {
672         return copy().mapSubtractToSelf(d);
673     }
674 
675     /** {@inheritDoc} */
mapSubtractToSelf(double d)676     public RealVector mapSubtractToSelf(double d){
677         return mapAddToSelf(-d);
678     }
679 
680     /** {@inheritDoc} */
mapTan()681     public RealVector mapTan() {
682         return copy().mapTanToSelf();
683     }
684 
685     /** {@inheritDoc} */
mapTanToSelf()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} */
mapTanh()695     public RealVector mapTanh() {
696         return copy().mapTanhToSelf();
697     }
698 
699     /** {@inheritDoc} */
mapTanhToSelf()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} */
mapUlp()709     public RealVector mapUlp() {
710         return copy().mapUlpToSelf();
711     }
712 
713     /** {@inheritDoc} */
mapUlpToSelf()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} */
outerProduct(RealVector v)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} */
outerProduct(double[] v)746     public RealMatrix outerProduct(double[] v) throws IllegalArgumentException {
747         return outerProduct(new ArrayRealVector(v, false));
748     }
749 
750     /** {@inheritDoc} */
projection(double[] v)751     public RealVector projection(double[] v) throws IllegalArgumentException {
752         return projection(new ArrayRealVector(v, false));
753     }
754 
755     /** {@inheritDoc} */
set(double value)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} */
toArray()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} */
getData()775     public double[] getData() {
776         return toArray();
777     }
778 
779     /** {@inheritDoc} */
unitVector()780     public RealVector unitVector() {
781         RealVector copy = copy();
782         copy.unitize();
783         return copy;
784     }
785 
786     /** {@inheritDoc} */
unitize()787     public void unitize() {
788         mapDivideToSelf(getNorm());
789     }
790 
791     /** {@inheritDoc} */
sparseIterator()792     public Iterator<Entry> sparseIterator() {
793         return new SparseEntryIterator();
794     }
795 
796     /** {@inheritDoc} */
iterator()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} */
map(UnivariateRealFunction function)826     public RealVector map(UnivariateRealFunction function) throws FunctionEvaluationException {
827         return copy().mapToSelf(function);
828     }
829 
830     /** {@inheritDoc} */
mapToSelf(UnivariateRealFunction function)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. */
EntryImpl()844         public EntryImpl() {
845             setIndex(0);
846         }
847 
848         /** {@inheritDoc} */
849         @Override
getValue()850         public double getValue() {
851             return getEntry(getIndex());
852         }
853 
854         /** {@inheritDoc} */
855         @Override
setValue(double newValue)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. */
SparseEntryIterator()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          */
advance(EntryImpl e)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} */
hasNext()911         public boolean hasNext() {
912             return next.getIndex() >= 0;
913         }
914 
915         /** {@inheritDoc} */
next()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} */
remove()927         public void remove() {
928             throw new MathUnsupportedOperationException();
929         }
930     }
931 
932 }
933