    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.FunctionEvaluationException;
    024    import org.apache.commons.math.exception.MathUnsupportedOperationException;
    025    import org.apache.commons.math.exception.DimensionMismatchException;
    026    import org.apache.commons.math.analysis.BinaryFunction;
    027    import org.apache.commons.math.analysis.ComposableFunction;
    028    import org.apache.commons.math.analysis.UnivariateRealFunction;
    029    import org.apache.commons.math.exception.util.LocalizedFormats;
    030    import org.apache.commons.math.util.FastMath;
    031
    032    /**
    033     * This class provides default basic implementations for many methods in the
    034     * {@link RealVector} interface.
    035     * @version $Revision: 1070725 $ $Date: 2011-02-15 02:31:12 +0100 (mar. 15 f??vr. 2011) $
    036     * @since 2.1
    037     */
    038    public abstract class AbstractRealVector implements RealVector {
    039
    040        /**
    041         * Check if instance and specified vectors have the same dimension.
    042         * @param v vector to compare instance with
    043         * @exception DimensionMismatchException if the vectors do not
    044         * have the same dimension
    045         */
    046        protected void checkVectorDimensions(RealVector v) {
    047            checkVectorDimensions(v.getDimension());
    048        }
    049
    050        /**
    051         * Check if instance dimension is equal to some expected value.
    052         *
    053         * @param n expected dimension.
    054         * @exception DimensionMismatchException if the dimension is
    055         * inconsistent with vector size
    056         */
    057        protected void checkVectorDimensions(int n)
    058            throws DimensionMismatchException {
    059            int d = getDimension();
    060            if (d != n) {
    061                throw new DimensionMismatchException(d, n);
    062            }
    063        }
    064
    065        /**
    066         * Check if an index is valid.
    067         * @param index index to check
    068         * @exception MatrixIndexException if index is not valid
    069         */
    070        protected void checkIndex(final int index)
    071            throws MatrixIndexException {
    072            if (index < 0 || index >= getDimension()) {
    073                throw new MatrixIndexException(LocalizedFormats.INDEX_OUT_OF_RANGE,
    074                                               index, 0, getDimension() - 1);
    075            }
    076        }
    077
    078        /** {@inheritDoc} */
    079        public void setSubVector(int index, RealVector v) throws MatrixIndexException {
    080            checkIndex(index);
    081            checkIndex(index + v.getDimension() - 1);
    082            setSubVector(index, v.getData());
    083        }
    084
    085        /** {@inheritDoc} */
    086        public void setSubVector(int index, double[] v) throws MatrixIndexException {
    087            checkIndex(index);
    088            checkIndex(index + v.length - 1);
    089            for (int i = 0; i < v.length; i++) {
    090                setEntry(i + index, v[i]);
    091            }
    092        }
    093
    094        /** {@inheritDoc} */
    095        public RealVector add(double[] v) throws IllegalArgumentException {
    096            double[] result = v.clone();
    097            Iterator<Entry> it = sparseIterator();
    098            Entry e;
    099            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    }