Home | History | Annotate | Download | only in linear
      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 fvr. 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      */
     46     protected void checkVectorDimensions(RealVector v) {
     47         checkVectorDimensions(v.getDimension());
     48     }
     49 
     50     /**
     51      * Check if instance dimension is equal to some expected value.
     52      *
     53      * @param n expected dimension.
     54      * @exception DimensionMismatchException if the dimension is
     55      * inconsistent with vector size
     56      */
     57     protected void checkVectorDimensions(int n)
     58         throws DimensionMismatchException {
     59         int d = getDimension();
     60         if (d != n) {
     61             throw new DimensionMismatchException(d, n);
     62         }
     63     }
     64 
     65     /**
     66      * Check if an index is valid.
     67      * @param index index to check
     68      * @exception MatrixIndexException if index is not valid
     69      */
     70     protected void checkIndex(final int index)
     71         throws MatrixIndexException {
     72         if (index < 0 || index >= getDimension()) {
     73             throw new MatrixIndexException(LocalizedFormats.INDEX_OUT_OF_RANGE,
     74                                            index, 0, getDimension() - 1);
     75         }
     76     }
     77 
     78     /** {@inheritDoc} */
     79     public void setSubVector(int index, RealVector v) throws MatrixIndexException {
     80         checkIndex(index);
     81         checkIndex(index + v.getDimension() - 1);
     82         setSubVector(index, v.getData());
     83     }
     84 
     85     /** {@inheritDoc} */
     86     public void setSubVector(int index, double[] v) throws MatrixIndexException {
     87         checkIndex(index);
     88         checkIndex(index + v.length - 1);
     89         for (int i = 0; i < v.length; i++) {
     90             setEntry(i + index, v[i]);
     91         }
     92     }
     93 
     94     /** {@inheritDoc} */
     95     public RealVector add(double[] v) throws IllegalArgumentException {
     96         double[] result = v.clone();
     97         Iterator<Entry> it = sparseIterator();
     98         Entry e;
     99         while (it.hasNext() && (e = it.next()) != null) {
    100             result[e.getIndex()] += e.getValue();
    101         }
    102         return new ArrayRealVector(result, false);
    103     }
    104 
    105     /** {@inheritDoc} */
    106     public RealVector add(RealVector v) throws IllegalArgumentException {
    107         if (v instanceof ArrayRealVector) {
    108             double[] values = ((ArrayRealVector)v).getDataRef();
    109             return add(values);
    110         }
    111         RealVector result = v.copy();
    112         Iterator<Entry> it = sparseIterator();
    113         Entry e;
    114         while (it.hasNext() && (e = it.next()) != null) {
    115             final int index = e.getIndex();
    116             result.setEntry(index, e.getValue() + result.getEntry(index));
    117         }
    118         return result;
    119     }
    120 
    121     /** {@inheritDoc} */
    122     public RealVector subtract(double[] v) throws IllegalArgumentException {
    123         double[] result = v.clone();
    124         Iterator<Entry> it = sparseIterator();
    125         Entry e;
    126         while (it.hasNext() && (e = it.next()) != null) {
    127             final int index = e.getIndex();
    128             result[index] = e.getValue() - result[index];
    129         }
    130         return new ArrayRealVector(result, false);
    131     }
    132 
    133     /** {@inheritDoc} */
    134     public RealVector subtract(RealVector v) throws IllegalArgumentException {
    135         if (v instanceof ArrayRealVector) {
    136             double[] values = ((ArrayRealVector)v).getDataRef();
    137             return add(values);
    138         }
    139         RealVector result = v.copy();
    140         Iterator<Entry> it = sparseIterator();
    141         Entry e;
    142         while (it.hasNext() && (e = it.next()) != null) {
    143             final int index = e.getIndex();
    144             v.setEntry(index, e.getValue() - result.getEntry(index));
    145         }
    146         return result;
    147     }
    148 
    149     /** {@inheritDoc} */
    150     public RealVector mapAdd(double d) {
    151         return copy().mapAddToSelf(d);
    152     }
    153 
    154     /** {@inheritDoc} */
    155     public RealVector mapAddToSelf(double d) {
    156         if (d != 0) {
    157             try {
    158                 return mapToSelf(BinaryFunction.ADD.fix1stArgument(d));
    159             } catch (FunctionEvaluationException e) {
    160                 throw new IllegalArgumentException(e);
    161             }
    162         }
    163         return this;
    164     }
    165 
    166     /** {@inheritDoc} */
    167     public abstract AbstractRealVector copy();
    168 
    169     /** {@inheritDoc} */
    170     public double dotProduct(double[] v) throws IllegalArgumentException {
    171         return dotProduct(new ArrayRealVector(v, false));
    172     }
    173 
    174     /** {@inheritDoc} */
    175     public double dotProduct(RealVector v) throws IllegalArgumentException {
    176         checkVectorDimensions(v);
    177         double d = 0;
    178         Iterator<Entry> it = sparseIterator();
    179         Entry e;
    180         while (it.hasNext() && (e = it.next()) != null) {
    181             d += e.getValue() * v.getEntry(e.getIndex());
    182         }
    183         return d;
    184     }
    185 
    186     /** {@inheritDoc} */
    187     public RealVector ebeDivide(double[] v) throws IllegalArgumentException {
    188         return ebeDivide(new ArrayRealVector(v, false));
    189     }
    190 
    191     /** {@inheritDoc} */
    192     public RealVector ebeMultiply(double[] v) throws IllegalArgumentException {
    193         return ebeMultiply(new ArrayRealVector(v, false));
    194     }
    195 
    196     /** {@inheritDoc} */
    197     public double getDistance(RealVector v) throws IllegalArgumentException {
    198         checkVectorDimensions(v);
    199         double d = 0;
    200         Iterator<Entry> it = iterator();
    201         Entry e;
    202         while (it.hasNext() && (e = it.next()) != null) {
    203             final double diff = e.getValue() - v.getEntry(e.getIndex());
    204             d += diff * diff;
    205         }
    206         return FastMath.sqrt(d);
    207     }
    208 
    209     /** {@inheritDoc} */
    210     public double getNorm() {
    211         double sum = 0;
    212         Iterator<Entry> it = sparseIterator();
    213         Entry e;
    214         while (it.hasNext() && (e = it.next()) != null) {
    215             final double value = e.getValue();
    216             sum += value * value;
    217         }
    218         return FastMath.sqrt(sum);
    219     }
    220 
    221     /** {@inheritDoc} */
    222     public double getL1Norm() {
    223         double norm = 0;
    224         Iterator<Entry> it = sparseIterator();
    225         Entry e;
    226         while (it.hasNext() && (e = it.next()) != null) {
    227             norm += FastMath.abs(e.getValue());
    228         }
    229         return norm;
    230     }
    231 
    232     /** {@inheritDoc} */
    233     public double getLInfNorm() {
    234         double norm = 0;
    235         Iterator<Entry> it = sparseIterator();
    236         Entry e;
    237         while (it.hasNext() && (e = it.next()) != null) {
    238             norm = FastMath.max(norm, FastMath.abs(e.getValue()));
    239         }
    240         return norm;
    241     }
    242 
    243     /** {@inheritDoc} */
    244     public double getDistance(double[] v) throws IllegalArgumentException {
    245         return getDistance(new ArrayRealVector(v,false));
    246     }
    247 
    248     /** {@inheritDoc} */
    249     public double getL1Distance(RealVector v) throws IllegalArgumentException {
    250         checkVectorDimensions(v);
    251         double d = 0;
    252         Iterator<Entry> it = iterator();
    253         Entry e;
    254         while (it.hasNext() && (e = it.next()) != null) {
    255             d += FastMath.abs(e.getValue() - v.getEntry(e.getIndex()));
    256         }
    257         return d;
    258     }
    259 
    260     /** {@inheritDoc} */
    261     public double getL1Distance(double[] v) throws IllegalArgumentException {
    262         checkVectorDimensions(v.length);
    263         double d = 0;
    264         Iterator<Entry> it = iterator();
    265         Entry e;
    266         while (it.hasNext() && (e = it.next()) != null) {
    267             d += FastMath.abs(e.getValue() - v[e.getIndex()]);
    268         }
    269         return d;
    270     }
    271 
    272     /** {@inheritDoc} */
    273     public double getLInfDistance(RealVector v) throws IllegalArgumentException {
    274         checkVectorDimensions(v);
    275         double d = 0;
    276         Iterator<Entry> it = iterator();
    277         Entry e;
    278         while (it.hasNext() && (e = it.next()) != null) {
    279             d = FastMath.max(FastMath.abs(e.getValue() - v.getEntry(e.getIndex())), d);
    280         }
    281         return d;
    282     }
    283 
    284     /** {@inheritDoc} */
    285     public double getLInfDistance(double[] v) throws IllegalArgumentException {
    286         checkVectorDimensions(v.length);
    287         double d = 0;
    288         Iterator<Entry> it = iterator();
    289         Entry e;
    290         while (it.hasNext() && (e = it.next()) != null) {
    291             d = FastMath.max(FastMath.abs(e.getValue() - v[e.getIndex()]), d);
    292         }
    293         return d;
    294     }
    295 
    296     /** Get the index of the minimum entry.
    297      * @return index of the minimum entry or -1 if vector length is 0
    298      * or all entries are NaN
    299      */
    300     public int getMinIndex() {
    301         int minIndex    = -1;
    302         double minValue = Double.POSITIVE_INFINITY;
    303         Iterator<Entry> iterator = iterator();
    304         while (iterator.hasNext()) {
    305             final Entry entry = iterator.next();
    306             if (entry.getValue() <= minValue) {
    307                 minIndex = entry.getIndex();
    308                 minValue = entry.getValue();
    309             }
    310         }
    311         return minIndex;
    312     }
    313 
    314     /** Get the value of the minimum entry.
    315      * @return value of the minimum entry or NaN if all entries are NaN
    316      */
    317     public double getMinValue() {
    318         final int minIndex = getMinIndex();
    319         return minIndex < 0 ? Double.NaN : getEntry(minIndex);
    320     }
    321 
    322     /** Get the index of the maximum entry.
    323      * @return index of the maximum entry or -1 if vector length is 0
    324      * or all entries are NaN
    325      */
    326     public int getMaxIndex() {
    327         int maxIndex    = -1;
    328         double maxValue = Double.NEGATIVE_INFINITY;
    329         Iterator<Entry> iterator = iterator();
    330         while (iterator.hasNext()) {
    331             final Entry entry = iterator.next();
    332             if (entry.getValue() >= maxValue) {
    333                 maxIndex = entry.getIndex();
    334                 maxValue = entry.getValue();
    335             }
    336         }
    337         return maxIndex;
    338     }
    339 
    340     /** Get the value of the maximum entry.
    341      * @return value of the maximum entry or NaN if all entries are NaN
    342      */
    343     public double getMaxValue() {
    344         final int maxIndex = getMaxIndex();
    345         return maxIndex < 0 ? Double.NaN : getEntry(maxIndex);
    346     }
    347 
    348     /** {@inheritDoc} */
    349     public RealVector mapAbs() {
    350         return copy().mapAbsToSelf();
    351     }
    352 
    353     /** {@inheritDoc} */
    354     public RealVector mapAbsToSelf() {
    355         try {
    356             return mapToSelf(ComposableFunction.ABS);
    357         } catch (FunctionEvaluationException e) {
    358             throw new IllegalArgumentException(e);
    359         }
    360     }
    361 
    362     /** {@inheritDoc} */
    363     public RealVector mapAcos() {
    364         return copy().mapAcosToSelf();
    365     }
    366 
    367     /** {@inheritDoc} */
    368     public RealVector mapAcosToSelf() {
    369         try {
    370             return mapToSelf(ComposableFunction.ACOS);
    371         } catch (FunctionEvaluationException e) {
    372             throw new IllegalArgumentException(e);
    373         }
    374     }
    375 
    376     /** {@inheritDoc} */
    377     public RealVector mapAsin() {
    378         return copy().mapAsinToSelf();
    379     }
    380 
    381     /** {@inheritDoc} */
    382     public RealVector mapAsinToSelf() {
    383         try {
    384             return mapToSelf(ComposableFunction.ASIN);
    385         } catch (FunctionEvaluationException e) {
    386             throw new IllegalArgumentException(e);
    387         }
    388     }
    389 
    390     /** {@inheritDoc} */
    391     public RealVector mapAtan() {
    392         return copy().mapAtanToSelf();
    393     }
    394 
    395     /** {@inheritDoc} */
    396     public RealVector mapAtanToSelf() {
    397         try {
    398             return mapToSelf(ComposableFunction.ATAN);
    399         } catch (FunctionEvaluationException e) {
    400             throw new IllegalArgumentException(e);
    401         }
    402     }
    403 
    404     /** {@inheritDoc} */
    405     public RealVector mapCbrt() {
    406         return copy().mapCbrtToSelf();
    407     }
    408 
    409     /** {@inheritDoc} */
    410     public RealVector mapCbrtToSelf() {
    411         try {
    412             return mapToSelf(ComposableFunction.CBRT);
    413         } catch (FunctionEvaluationException e) {
    414             throw new IllegalArgumentException(e);
    415         }
    416     }
    417 
    418     /** {@inheritDoc} */
    419     public RealVector mapCeil() {
    420         return copy().mapCeilToSelf();
    421     }
    422 
    423     /** {@inheritDoc} */
    424     public RealVector mapCeilToSelf() {
    425         try {
    426             return mapToSelf(ComposableFunction.CEIL);
    427         } catch (FunctionEvaluationException e) {
    428             throw new IllegalArgumentException(e);
    429         }
    430     }
    431 
    432     /** {@inheritDoc} */
    433     public RealVector mapCos() {
    434         return copy().mapCosToSelf();
    435     }
    436 
    437     /** {@inheritDoc} */
    438     public RealVector mapCosToSelf() {
    439         try {
    440             return mapToSelf(ComposableFunction.COS);
    441         } catch (FunctionEvaluationException e) {
    442             throw new IllegalArgumentException(e);
    443         }
    444     }
    445 
    446     /** {@inheritDoc} */
    447     public RealVector mapCosh() {
    448         return copy().mapCoshToSelf();
    449     }
    450 
    451     /** {@inheritDoc} */
    452     public RealVector mapCoshToSelf() {
    453         try {
    454             return mapToSelf(ComposableFunction.COSH);
    455         } catch (FunctionEvaluationException e) {
    456             throw new IllegalArgumentException(e);
    457         }
    458     }
    459 
    460     /** {@inheritDoc} */
    461     public RealVector mapDivide(double d) {
    462         return copy().mapDivideToSelf(d);
    463     }
    464 
    465     /** {@inheritDoc} */
    466     public RealVector mapDivideToSelf(double d){
    467         try {
    468             return mapToSelf(BinaryFunction.DIVIDE.fix2ndArgument(d));
    469         } catch (FunctionEvaluationException e) {
    470             throw new IllegalArgumentException(e);
    471         }
    472     }
    473 
    474     /** {@inheritDoc} */
    475     public RealVector mapExp() {
    476         return copy().mapExpToSelf();
    477     }
    478 
    479     /** {@inheritDoc} */
    480     public RealVector mapExpToSelf() {
    481         try {
    482             return mapToSelf(ComposableFunction.EXP);
    483         } catch (FunctionEvaluationException e) {
    484             throw new IllegalArgumentException(e);
    485         }
    486     }
    487 
    488     /** {@inheritDoc} */
    489     public RealVector mapExpm1() {
    490         return copy().mapExpm1ToSelf();
    491     }
    492 
    493     /** {@inheritDoc} */
    494     public RealVector mapExpm1ToSelf() {
    495         try {
    496             return mapToSelf(ComposableFunction.EXPM1);
    497         } catch (FunctionEvaluationException e) {
    498             throw new IllegalArgumentException(e);
    499         }
    500     }
    501 
    502     /** {@inheritDoc} */
    503     public RealVector mapFloor() {
    504         return copy().mapFloorToSelf();
    505     }
    506 
    507     /** {@inheritDoc} */
    508     public RealVector mapFloorToSelf() {
    509         try {
    510             return mapToSelf(ComposableFunction.FLOOR);
    511         } catch (FunctionEvaluationException e) {
    512             throw new IllegalArgumentException(e);
    513         }
    514     }
    515 
    516     /** {@inheritDoc} */
    517     public RealVector mapInv() {
    518         return copy().mapInvToSelf();
    519     }
    520 
    521     /** {@inheritDoc} */
    522     public RealVector mapInvToSelf() {
    523         try {
    524             return mapToSelf(ComposableFunction.INVERT);
    525         } catch (FunctionEvaluationException e) {
    526             throw new IllegalArgumentException(e);
    527         }
    528     }
    529 
    530     /** {@inheritDoc} */
    531     public RealVector mapLog() {
    532         return copy().mapLogToSelf();
    533     }
    534 
    535     /** {@inheritDoc} */
    536     public RealVector mapLogToSelf() {
    537         try {
    538             return mapToSelf(ComposableFunction.LOG);
    539         } catch (FunctionEvaluationException e) {
    540             throw new IllegalArgumentException(e);
    541         }
    542     }
    543 
    544     /** {@inheritDoc} */
    545     public RealVector mapLog10() {
    546         return copy().mapLog10ToSelf();
    547     }
    548 
    549     /** {@inheritDoc} */
    550     public RealVector mapLog10ToSelf() {
    551         try {
    552             return mapToSelf(ComposableFunction.LOG10);
    553         } catch (FunctionEvaluationException e) {
    554             throw new IllegalArgumentException(e);
    555         }
    556     }
    557 
    558     /** {@inheritDoc} */
    559     public RealVector mapLog1p() {
    560         return copy().mapLog1pToSelf();
    561     }
    562 
    563     /** {@inheritDoc} */
    564     public RealVector mapLog1pToSelf() {
    565         try {
    566             return mapToSelf(ComposableFunction.LOG1P);
    567         } catch (FunctionEvaluationException e) {
    568             throw new IllegalArgumentException(e);
    569         }
    570     }
    571 
    572     /** {@inheritDoc} */
    573     public RealVector mapMultiply(double d) {
    574         return copy().mapMultiplyToSelf(d);
    575     }
    576 
    577     /** {@inheritDoc} */
    578     public RealVector mapMultiplyToSelf(double d){
    579         try {
    580             return mapToSelf(BinaryFunction.MULTIPLY.fix1stArgument(d));
    581         } catch (FunctionEvaluationException e) {
    582             throw new IllegalArgumentException(e);
    583         }
    584     }
    585 
    586     /** {@inheritDoc} */
    587     public RealVector mapPow(double d) {
    588         return copy().mapPowToSelf(d);
    589     }
    590 
    591     /** {@inheritDoc} */
    592     public RealVector mapPowToSelf(double d){
    593         try {
    594             return mapToSelf(BinaryFunction.POW.fix2ndArgument(d));
    595         } catch (FunctionEvaluationException e) {
    596             throw new IllegalArgumentException(e);
    597         }
    598     }
    599 
    600     /** {@inheritDoc} */
    601     public RealVector mapRint() {
    602         return copy().mapRintToSelf();
    603     }
    604 
    605     /** {@inheritDoc} */
    606     public RealVector mapRintToSelf() {
    607         try {
    608             return mapToSelf(ComposableFunction.RINT);
    609         } catch (FunctionEvaluationException e) {
    610             throw new IllegalArgumentException(e);
    611         }
    612     }
    613 
    614     /** {@inheritDoc} */
    615     public RealVector mapSignum() {
    616         return copy().mapSignumToSelf();
    617     }
    618 
    619     /** {@inheritDoc} */
    620     public RealVector mapSignumToSelf() {
    621         try {
    622             return mapToSelf(ComposableFunction.SIGNUM);
    623         } catch (FunctionEvaluationException e) {
    624             throw new IllegalArgumentException(e);
    625         }
    626     }
    627 
    628     /** {@inheritDoc} */
    629     public RealVector mapSin() {
    630         return copy().mapSinToSelf();
    631     }
    632 
    633     /** {@inheritDoc} */
    634     public RealVector mapSinToSelf() {
    635         try {
    636             return mapToSelf(ComposableFunction.SIN);
    637         } catch (FunctionEvaluationException e) {
    638             throw new IllegalArgumentException(e);
    639         }
    640     }
    641 
    642     /** {@inheritDoc} */
    643     public RealVector mapSinh() {
    644         return copy().mapSinhToSelf();
    645     }
    646 
    647     /** {@inheritDoc} */
    648     public RealVector mapSinhToSelf() {
    649         try {
    650             return mapToSelf(ComposableFunction.SINH);
    651         } catch (FunctionEvaluationException e) {
    652             throw new IllegalArgumentException(e);
    653         }
    654     }
    655 
    656     /** {@inheritDoc} */
    657     public RealVector mapSqrt() {
    658         return copy().mapSqrtToSelf();
    659     }
    660 
    661     /** {@inheritDoc} */
    662     public RealVector mapSqrtToSelf() {
    663         try {
    664             return mapToSelf(ComposableFunction.SQRT);
    665         } catch (FunctionEvaluationException e) {
    666             throw new IllegalArgumentException(e);
    667         }
    668     }
    669 
    670     /** {@inheritDoc} */
    671     public RealVector mapSubtract(double d) {
    672         return copy().mapSubtractToSelf(d);
    673     }
    674 
    675     /** {@inheritDoc} */
    676     public RealVector mapSubtractToSelf(double d){
    677         return mapAddToSelf(-d);
    678     }
    679 
    680     /** {@inheritDoc} */
    681     public RealVector mapTan() {
    682         return copy().mapTanToSelf();
    683     }
    684 
    685     /** {@inheritDoc} */
    686     public RealVector mapTanToSelf() {
    687         try {
    688             return mapToSelf(ComposableFunction.TAN);
    689         } catch (FunctionEvaluationException e) {
    690             throw new IllegalArgumentException(e);
    691         }
    692     }
    693 
    694     /** {@inheritDoc} */
    695     public RealVector mapTanh() {
    696         return copy().mapTanhToSelf();
    697     }
    698 
    699     /** {@inheritDoc} */
    700     public RealVector mapTanhToSelf() {
    701         try {
    702             return mapToSelf(ComposableFunction.TANH);
    703         } catch (FunctionEvaluationException e) {
    704             throw new IllegalArgumentException(e);
    705         }
    706     }
    707 
    708     /** {@inheritDoc} */
    709     public RealVector mapUlp() {
    710         return copy().mapUlpToSelf();
    711     }
    712 
    713     /** {@inheritDoc} */
    714     public RealVector mapUlpToSelf() {
    715         try {
    716             return mapToSelf(ComposableFunction.ULP);
    717         } catch (FunctionEvaluationException e) {
    718             throw new IllegalArgumentException(e);
    719         }
    720     }
    721 
    722     /** {@inheritDoc} */
    723     public RealMatrix outerProduct(RealVector v) throws IllegalArgumentException {
    724         RealMatrix product;
    725         if (v instanceof SparseRealVector || this instanceof SparseRealVector) {
    726             product = new OpenMapRealMatrix(this.getDimension(), v.getDimension());
    727         } else {
    728             product = new Array2DRowRealMatrix(this.getDimension(), v.getDimension());
    729         }
    730         Iterator<Entry> thisIt = sparseIterator();
    731         Entry thisE = null;
    732         while (thisIt.hasNext() && (thisE = thisIt.next()) != null) {
    733             Iterator<Entry> otherIt = v.sparseIterator();
    734             Entry otherE = null;
    735             while (otherIt.hasNext() && (otherE = otherIt.next()) != null) {
    736                 product.setEntry(thisE.getIndex(), otherE.getIndex(),
    737                                  thisE.getValue() * otherE.getValue());
    738             }
    739         }
    740 
    741         return product;
    742 
    743     }
    744 
    745     /** {@inheritDoc} */
    746     public RealMatrix outerProduct(double[] v) throws IllegalArgumentException {
    747         return outerProduct(new ArrayRealVector(v, false));
    748     }
    749 
    750     /** {@inheritDoc} */
    751     public RealVector projection(double[] v) throws IllegalArgumentException {
    752         return projection(new ArrayRealVector(v, false));
    753     }
    754 
    755     /** {@inheritDoc} */
    756     public void set(double value) {
    757         Iterator<Entry> it = iterator();
    758         Entry e = null;
    759         while (it.hasNext() && (e = it.next()) != null) {
    760             e.setValue(value);
    761         }
    762     }
    763 
    764     /** {@inheritDoc} */
    765     public double[] toArray() {
    766         int dim = getDimension();
    767         double[] values = new double[dim];
    768         for (int i = 0; i < dim; i++) {
    769             values[i] = getEntry(i);
    770         }
    771         return values;
    772     }
    773 
    774     /** {@inheritDoc} */
    775     public double[] getData() {
    776         return toArray();
    777     }
    778 
    779     /** {@inheritDoc} */
    780     public RealVector unitVector() {
    781         RealVector copy = copy();
    782         copy.unitize();
    783         return copy;
    784     }
    785 
    786     /** {@inheritDoc} */
    787     public void unitize() {
    788         mapDivideToSelf(getNorm());
    789     }
    790 
    791     /** {@inheritDoc} */
    792     public Iterator<Entry> sparseIterator() {
    793         return new SparseEntryIterator();
    794     }
    795 
    796     /** {@inheritDoc} */
    797     public Iterator<Entry> iterator() {
    798         final int dim = getDimension();
    799         return new Iterator<Entry>() {
    800 
    801             /** Current index. */
    802             private int i = 0;
    803 
    804             /** Current entry. */
    805             private EntryImpl e = new EntryImpl();
    806 
    807             /** {@inheritDoc} */
    808             public boolean hasNext() {
    809                 return i < dim;
    810             }
    811 
    812             /** {@inheritDoc} */
    813             public Entry next() {
    814                 e.setIndex(i++);
    815                 return e;
    816             }
    817 
    818             /** {@inheritDoc} */
    819             public void remove() {
    820                 throw new MathUnsupportedOperationException();
    821             }
    822         };
    823     }
    824 
    825     /** {@inheritDoc} */
    826     public RealVector map(UnivariateRealFunction function) throws FunctionEvaluationException {
    827         return copy().mapToSelf(function);
    828     }
    829 
    830     /** {@inheritDoc} */
    831     public RealVector mapToSelf(UnivariateRealFunction function) throws FunctionEvaluationException {
    832         Iterator<Entry> it = (function.value(0) == 0) ? sparseIterator() : iterator();
    833         Entry e;
    834         while (it.hasNext() && (e = it.next()) != null) {
    835             e.setValue(function.value(e.getValue()));
    836         }
    837         return this;
    838     }
    839 
    840     /** An entry in the vector. */
    841     protected class EntryImpl extends Entry {
    842 
    843         /** Simple constructor. */
    844         public EntryImpl() {
    845             setIndex(0);
    846         }
    847 
    848         /** {@inheritDoc} */
    849         @Override
    850         public double getValue() {
    851             return getEntry(getIndex());
    852         }
    853 
    854         /** {@inheritDoc} */
    855         @Override
    856         public void setValue(double newValue) {
    857             setEntry(getIndex(), newValue);
    858         }
    859     }
    860 
    861     /**
    862      * This class should rare be used, but is here to provide
    863      * a default implementation of sparseIterator(), which is implemented
    864      * by walking over the entries, skipping those whose values are the default one.
    865      *
    866      * Concrete subclasses which are SparseVector implementations should
    867      * make their own sparse iterator, not use this one.
    868      *
    869      * This implementation might be useful for ArrayRealVector, when expensive
    870      * operations which preserve the default value are to be done on the entries,
    871      * and the fraction of non-default values is small (i.e. someone took a
    872      * SparseVector, and passed it into the copy-constructor of ArrayRealVector)
    873      */
    874     protected class SparseEntryIterator implements Iterator<Entry> {
    875 
    876         /** Dimension of the vector. */
    877         private final int dim;
    878 
    879         /** last entry returned by {@link #next()} */
    880         private EntryImpl current;
    881 
    882         /** Next entry for {@link #next()} to return. */
    883         private EntryImpl next;
    884 
    885         /** Simple constructor. */
    886         protected SparseEntryIterator() {
    887             dim = getDimension();
    888             current = new EntryImpl();
    889             next = new EntryImpl();
    890             if (next.getValue() == 0) {
    891                 advance(next);
    892             }
    893         }
    894 
    895         /** Advance an entry up to the next nonzero one.
    896          * @param e entry to advance
    897          */
    898         protected void advance(EntryImpl e) {
    899             if (e == null) {
    900                 return;
    901             }
    902             do {
    903                 e.setIndex(e.getIndex() + 1);
    904             } while (e.getIndex() < dim && e.getValue() == 0);
    905             if (e.getIndex() >= dim) {
    906                 e.setIndex(-1);
    907             }
    908         }
    909 
    910         /** {@inheritDoc} */
    911         public boolean hasNext() {
    912             return next.getIndex() >= 0;
    913         }
    914 
    915         /** {@inheritDoc} */
    916         public Entry next() {
    917             int index = next.getIndex();
    918             if (index < 0) {
    919                 throw new NoSuchElementException();
    920             }
    921             current.setIndex(index);
    922             advance(next);
    923             return current;
    924         }
    925 
    926         /** {@inheritDoc} */
    927         public void remove() {
    928             throw new MathUnsupportedOperationException();
    929         }
    930     }
    931 
    932 }
    933