001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 package org.apache.commons.math.linear; 019 020 import java.util.Iterator; 021 022 import org.apache.commons.math.FunctionEvaluationException; 023 import org.apache.commons.math.MathRuntimeException; 024 import org.apache.commons.math.analysis.BinaryFunction; 025 import org.apache.commons.math.analysis.UnivariateRealFunction; 026 import org.apache.commons.math.analysis.ComposableFunction; 027 028 /** 029 * This class provides default basic implementations for many methods in the 030 * {@link RealVector} interface with. 031 * @version $Revision: 904231 $ $Date: 2010-01-28 14:42:31 -0500 (Thu, 28 Jan 2010) $ 032 * @since 2.1 033 */ 034 public abstract class AbstractRealVector implements RealVector { 035 036 /** 037 * Check if instance and specified vectors have the same dimension. 038 * @param v vector to compare instance with 039 * @exception IllegalArgumentException if the vectors do not 040 * have the same dimension 041 */ 042 protected void checkVectorDimensions(RealVector v) { 043 checkVectorDimensions(v.getDimension()); 044 } 045 046 /** 047 * Check if instance dimension is equal to some expected value. 048 * 049 * @param n expected dimension. 050 * @exception IllegalArgumentException if the dimension is 051 * inconsistent with vector size 052 */ 053 protected void checkVectorDimensions(int n) 054 throws IllegalArgumentException { 055 double d = getDimension(); 056 if (d != n) { 057 throw MathRuntimeException.createIllegalArgumentException( 058 "vector length mismatch: got {0} but expected {1}", 059 d, n); 060 } 061 } 062 063 /** 064 * Check if an index is valid. 065 * @param index index to check 066 * @exception MatrixIndexException if index is not valid 067 */ 068 protected void checkIndex(final int index) 069 throws MatrixIndexException { 070 if (index < 0 || index >= getDimension()) { 071 throw new MatrixIndexException( 072 "index {0} out of allowed range [{1}, {2}]", 073 index, 0, getDimension() - 1); 074 } 075 } 076 077 /** {@inheritDoc} */ 078 public void setSubVector(int index, RealVector v) throws MatrixIndexException { 079 checkIndex(index); 080 checkIndex(index + v.getDimension() - 1); 081 setSubVector(index, v.getData()); 082 } 083 084 /** {@inheritDoc} */ 085 public void setSubVector(int index, double[] v) throws MatrixIndexException { 086 checkIndex(index); 087 checkIndex(index + v.length - 1); 088 for (int i = 0; i < v.length; i++) { 089 setEntry(i + index, v[i]); 090 } 091 } 092 093 /** {@inheritDoc} */ 094 public RealVector add(double[] v) throws IllegalArgumentException { 095 double[] result = v.clone(); 096 Iterator<Entry> it = sparseIterator(); 097 Entry e; 098 while (it.hasNext() && (e = it.next()) != null) { 099 result[e.getIndex()] += e.getValue(); 100 } 101 return new ArrayRealVector(result, false); 102 } 103 104 /** {@inheritDoc} */ 105 public RealVector add(RealVector v) throws IllegalArgumentException { 106 if (v instanceof ArrayRealVector) { 107 double[] values = ((ArrayRealVector)v).getDataRef(); 108 return add(values); 109 } 110 RealVector result = v.copy(); 111 Iterator<Entry> it = sparseIterator(); 112 Entry e; 113 while (it.hasNext() && (e = it.next()) != null) { 114 final int index = e.getIndex(); 115 result.setEntry(index, e.getValue() + result.getEntry(index)); 116 } 117 return result; 118 } 119 120 /** {@inheritDoc} */ 121 public RealVector subtract(double[] v) throws IllegalArgumentException { 122 double[] result = v.clone(); 123 Iterator<Entry> it = sparseIterator(); 124 Entry e; 125 while (it.hasNext() && (e = it.next()) != null) { 126 final int index = e.getIndex(); 127 result[index] = e.getValue() - result[index]; 128 } 129 return new ArrayRealVector(result, false); 130 } 131 132 /** {@inheritDoc} */ 133 public RealVector subtract(RealVector v) throws IllegalArgumentException { 134 if (v instanceof ArrayRealVector) { 135 double[] values = ((ArrayRealVector)v).getDataRef(); 136 return add(values); 137 } 138 RealVector result = v.copy(); 139 Iterator<Entry> it = sparseIterator(); 140 Entry e; 141 while (it.hasNext() && (e = it.next()) != null) { 142 final int index = e.getIndex(); 143 v.setEntry(index, e.getValue() - result.getEntry(index)); 144 } 145 return result; 146 } 147 148 /** {@inheritDoc} */ 149 public RealVector mapAdd(double d) { 150 return copy().mapAddToSelf(d); 151 } 152 153 /** {@inheritDoc} */ 154 public RealVector mapAddToSelf(double d) { 155 if (d != 0) { 156 try { 157 return mapToSelf(BinaryFunction.ADD.fix1stArgument(d)); 158 } catch (FunctionEvaluationException e) { 159 throw new IllegalArgumentException(e); 160 } 161 } 162 return this; 163 } 164 165 /** {@inheritDoc} */ 166 public abstract AbstractRealVector copy(); 167 168 /** {@inheritDoc} */ 169 public double dotProduct(double[] v) throws IllegalArgumentException { 170 return dotProduct(new ArrayRealVector(v, false)); 171 } 172 173 /** {@inheritDoc} */ 174 public double dotProduct(RealVector v) throws IllegalArgumentException { 175 checkVectorDimensions(v); 176 double d = 0; 177 Iterator<Entry> it = sparseIterator(); 178 Entry e; 179 while (it.hasNext() && (e = it.next()) != null) { 180 d += e.getValue() * v.getEntry(e.getIndex()); 181 } 182 return d; 183 } 184 185 /** {@inheritDoc} */ 186 public RealVector ebeDivide(double[] v) throws IllegalArgumentException { 187 return ebeDivide(new ArrayRealVector(v, false)); 188 } 189 190 /** {@inheritDoc} */ 191 public RealVector ebeMultiply(double[] v) throws IllegalArgumentException { 192 return ebeMultiply(new ArrayRealVector(v, false)); 193 } 194 195 /** {@inheritDoc} */ 196 public double getDistance(RealVector v) throws IllegalArgumentException { 197 checkVectorDimensions(v); 198 double d = 0; 199 Iterator<Entry> it = iterator(); 200 Entry e; 201 while (it.hasNext() && (e = it.next()) != null) { 202 final double diff = e.getValue() - v.getEntry(e.getIndex()); 203 d += diff * diff; 204 } 205 return Math.sqrt(d); 206 } 207 208 /** {@inheritDoc} */ 209 public double getNorm() { 210 double sum = 0; 211 Iterator<Entry> it = sparseIterator(); 212 Entry e; 213 while (it.hasNext() && (e = it.next()) != null) { 214 final double value = e.getValue(); 215 sum += value * value; 216 } 217 return Math.sqrt(sum); 218 } 219 220 /** {@inheritDoc} */ 221 public double getL1Norm() { 222 double norm = 0; 223 Iterator<Entry> it = sparseIterator(); 224 Entry e; 225 while (it.hasNext() && (e = it.next()) != null) { 226 norm += Math.abs(e.getValue()); 227 } 228 return norm; 229 } 230 231 /** {@inheritDoc} */ 232 public double getLInfNorm() { 233 double norm = 0; 234 Iterator<Entry> it = sparseIterator(); 235 Entry e; 236 while (it.hasNext() && (e = it.next()) != null) { 237 norm = Math.max(norm, Math.abs(e.getValue())); 238 } 239 return norm; 240 } 241 242 /** {@inheritDoc} */ 243 public double getDistance(double[] v) throws IllegalArgumentException { 244 return getDistance(new ArrayRealVector(v,false)); 245 } 246 247 /** {@inheritDoc} */ 248 public double getL1Distance(RealVector v) throws IllegalArgumentException { 249 checkVectorDimensions(v); 250 double d = 0; 251 Iterator<Entry> it = iterator(); 252 Entry e; 253 while (it.hasNext() && (e = it.next()) != null) { 254 d += Math.abs(e.getValue() - v.getEntry(e.getIndex())); 255 } 256 return d; 257 } 258 259 /** {@inheritDoc} */ 260 public double getL1Distance(double[] v) throws IllegalArgumentException { 261 checkVectorDimensions(v.length); 262 double d = 0; 263 Iterator<Entry> it = iterator(); 264 Entry e; 265 while (it.hasNext() && (e = it.next()) != null) { 266 d += Math.abs(e.getValue() - v[e.getIndex()]); 267 } 268 return d; 269 } 270 271 /** {@inheritDoc} */ 272 public double getLInfDistance(RealVector v) throws IllegalArgumentException { 273 checkVectorDimensions(v); 274 double d = 0; 275 Iterator<Entry> it = iterator(); 276 Entry e; 277 while (it.hasNext() && (e = it.next()) != null) { 278 d = Math.max(Math.abs(e.getValue() - v.getEntry(e.getIndex())), d); 279 } 280 return d; 281 } 282 283 /** {@inheritDoc} */ 284 public double getLInfDistance(double[] v) throws IllegalArgumentException { 285 checkVectorDimensions(v.length); 286 double d = 0; 287 Iterator<Entry> it = iterator(); 288 Entry e; 289 while (it.hasNext() && (e = it.next()) != null) { 290 d = Math.max(Math.abs(e.getValue() - v[e.getIndex()]), d); 291 } 292 return d; 293 } 294 295 /** Get the index of the minimum entry. 296 * @return index of the minimum entry or -1 if vector length is 0 297 * or all entries are NaN 298 */ 299 public int getMinIndex() { 300 int minIndex = -1; 301 double minValue = Double.POSITIVE_INFINITY; 302 Iterator<Entry> iterator = iterator(); 303 while (iterator.hasNext()) { 304 final Entry entry = iterator.next(); 305 if (entry.getValue() <= minValue) { 306 minIndex = entry.getIndex(); 307 minValue = entry.getValue(); 308 } 309 } 310 return minIndex; 311 } 312 313 /** Get the value of the minimum entry. 314 * @return value of the minimum entry or NaN if all entries are NaN 315 */ 316 public double getMinValue() { 317 final int minIndex = getMinIndex(); 318 return minIndex < 0 ? Double.NaN : getEntry(minIndex); 319 } 320 321 /** Get the index of the maximum entry. 322 * @return index of the maximum entry or -1 if vector length is 0 323 * or all entries are NaN 324 */ 325 public int getMaxIndex() { 326 int maxIndex = -1; 327 double maxValue = Double.NEGATIVE_INFINITY; 328 Iterator<Entry> iterator = iterator(); 329 while (iterator.hasNext()) { 330 final Entry entry = iterator.next(); 331 if (entry.getValue() >= maxValue) { 332 maxIndex = entry.getIndex(); 333 maxValue = entry.getValue(); 334 } 335 } 336 return maxIndex; 337 } 338 339 /** Get the value of the maximum entry. 340 * @return value of the maximum entry or NaN if all entries are NaN 341 */ 342 public double getMaxValue() { 343 final int maxIndex = getMaxIndex(); 344 return maxIndex < 0 ? Double.NaN : getEntry(maxIndex); 345 } 346 347 /** {@inheritDoc} */ 348 public RealVector mapAbs() { 349 return copy().mapAbsToSelf(); 350 } 351 352 /** {@inheritDoc} */ 353 public RealVector mapAbsToSelf() { 354 try { 355 return mapToSelf(ComposableFunction.ABS); 356 } catch (FunctionEvaluationException e) { 357 throw new IllegalArgumentException(e); 358 } 359 } 360 361 /** {@inheritDoc} */ 362 public RealVector mapAcos() { 363 return copy().mapAcosToSelf(); 364 } 365 366 /** {@inheritDoc} */ 367 public RealVector mapAcosToSelf() { 368 try { 369 return mapToSelf(ComposableFunction.ACOS); 370 } catch (FunctionEvaluationException e) { 371 throw new IllegalArgumentException(e); 372 } 373 } 374 375 /** {@inheritDoc} */ 376 public RealVector mapAsin() { 377 return copy().mapAsinToSelf(); 378 } 379 380 /** {@inheritDoc} */ 381 public RealVector mapAsinToSelf() { 382 try { 383 return mapToSelf(ComposableFunction.ASIN); 384 } catch (FunctionEvaluationException e) { 385 throw new IllegalArgumentException(e); 386 } 387 } 388 389 /** {@inheritDoc} */ 390 public RealVector mapAtan() { 391 return copy().mapAtanToSelf(); 392 } 393 394 /** {@inheritDoc} */ 395 public RealVector mapAtanToSelf() { 396 try { 397 return mapToSelf(ComposableFunction.ATAN); 398 } catch (FunctionEvaluationException e) { 399 throw new IllegalArgumentException(e); 400 } 401 } 402 403 /** {@inheritDoc} */ 404 public RealVector mapCbrt() { 405 return copy().mapCbrtToSelf(); 406 } 407 408 /** {@inheritDoc} */ 409 public RealVector mapCbrtToSelf() { 410 try { 411 return mapToSelf(ComposableFunction.CBRT); 412 } catch (FunctionEvaluationException e) { 413 throw new IllegalArgumentException(e); 414 } 415 } 416 417 /** {@inheritDoc} */ 418 public RealVector mapCeil() { 419 return copy().mapCeilToSelf(); 420 } 421 422 /** {@inheritDoc} */ 423 public RealVector mapCeilToSelf() { 424 try { 425 return mapToSelf(ComposableFunction.CEIL); 426 } catch (FunctionEvaluationException e) { 427 throw new IllegalArgumentException(e); 428 } 429 } 430 431 /** {@inheritDoc} */ 432 public RealVector mapCos() { 433 return copy().mapCosToSelf(); 434 } 435 436 /** {@inheritDoc} */ 437 public RealVector mapCosToSelf() { 438 try { 439 return mapToSelf(ComposableFunction.COS); 440 } catch (FunctionEvaluationException e) { 441 throw new IllegalArgumentException(e); 442 } 443 } 444 445 /** {@inheritDoc} */ 446 public RealVector mapCosh() { 447 return copy().mapCoshToSelf(); 448 } 449 450 /** {@inheritDoc} */ 451 public RealVector mapCoshToSelf() { 452 try { 453 return mapToSelf(ComposableFunction.COSH); 454 } catch (FunctionEvaluationException e) { 455 throw new IllegalArgumentException(e); 456 } 457 } 458 459 /** {@inheritDoc} */ 460 public RealVector mapDivide(double d) { 461 return copy().mapDivideToSelf(d); 462 } 463 464 /** {@inheritDoc} */ 465 public RealVector mapDivideToSelf(double d){ 466 try { 467 return mapToSelf(BinaryFunction.DIVIDE.fix2ndArgument(d)); 468 } catch (FunctionEvaluationException e) { 469 throw new IllegalArgumentException(e); 470 } 471 } 472 473 /** {@inheritDoc} */ 474 public RealVector mapExp() { 475 return copy().mapExpToSelf(); 476 } 477 478 /** {@inheritDoc} */ 479 public RealVector mapExpToSelf() { 480 try { 481 return mapToSelf(ComposableFunction.EXP); 482 } catch (FunctionEvaluationException e) { 483 throw new IllegalArgumentException(e); 484 } 485 } 486 487 /** {@inheritDoc} */ 488 public RealVector mapExpm1() { 489 return copy().mapExpm1ToSelf(); 490 } 491 492 /** {@inheritDoc} */ 493 public RealVector mapExpm1ToSelf() { 494 try { 495 return mapToSelf(ComposableFunction.EXPM1); 496 } catch (FunctionEvaluationException e) { 497 throw new IllegalArgumentException(e); 498 } 499 } 500 501 /** {@inheritDoc} */ 502 public RealVector mapFloor() { 503 return copy().mapFloorToSelf(); 504 } 505 506 /** {@inheritDoc} */ 507 public RealVector mapFloorToSelf() { 508 try { 509 return mapToSelf(ComposableFunction.FLOOR); 510 } catch (FunctionEvaluationException e) { 511 throw new IllegalArgumentException(e); 512 } 513 } 514 515 /** {@inheritDoc} */ 516 public RealVector mapInv() { 517 return copy().mapInvToSelf(); 518 } 519 520 /** {@inheritDoc} */ 521 public RealVector mapInvToSelf() { 522 try { 523 return mapToSelf(ComposableFunction.INVERT); 524 } catch (FunctionEvaluationException e) { 525 throw new IllegalArgumentException(e); 526 } 527 } 528 529 /** {@inheritDoc} */ 530 public RealVector mapLog() { 531 return copy().mapLogToSelf(); 532 } 533 534 /** {@inheritDoc} */ 535 public RealVector mapLogToSelf() { 536 try { 537 return mapToSelf(ComposableFunction.LOG); 538 } catch (FunctionEvaluationException e) { 539 throw new IllegalArgumentException(e); 540 } 541 } 542 543 /** {@inheritDoc} */ 544 public RealVector mapLog10() { 545 return copy().mapLog10ToSelf(); 546 } 547 548 /** {@inheritDoc} */ 549 public RealVector mapLog10ToSelf() { 550 try { 551 return mapToSelf(ComposableFunction.LOG10); 552 } catch (FunctionEvaluationException e) { 553 throw new IllegalArgumentException(e); 554 } 555 } 556 557 /** {@inheritDoc} */ 558 public RealVector mapLog1p() { 559 return copy().mapLog1pToSelf(); 560 } 561 562 /** {@inheritDoc} */ 563 public RealVector mapLog1pToSelf() { 564 try { 565 return mapToSelf(ComposableFunction.LOG1P); 566 } catch (FunctionEvaluationException e) { 567 throw new IllegalArgumentException(e); 568 } 569 } 570 571 /** {@inheritDoc} */ 572 public RealVector mapMultiply(double d) { 573 return copy().mapMultiplyToSelf(d); 574 } 575 576 /** {@inheritDoc} */ 577 public RealVector mapMultiplyToSelf(double d){ 578 try { 579 return mapToSelf(BinaryFunction.MULTIPLY.fix1stArgument(d)); 580 } catch (FunctionEvaluationException e) { 581 throw new IllegalArgumentException(e); 582 } 583 } 584 585 /** {@inheritDoc} */ 586 public RealVector mapPow(double d) { 587 return copy().mapPowToSelf(d); 588 } 589 590 /** {@inheritDoc} */ 591 public RealVector mapPowToSelf(double d){ 592 try { 593 return mapToSelf(BinaryFunction.POW.fix2ndArgument(d)); 594 } catch (FunctionEvaluationException e) { 595 throw new IllegalArgumentException(e); 596 } 597 } 598 599 /** {@inheritDoc} */ 600 public RealVector mapRint() { 601 return copy().mapRintToSelf(); 602 } 603 604 /** {@inheritDoc} */ 605 public RealVector mapRintToSelf() { 606 try { 607 return mapToSelf(ComposableFunction.RINT); 608 } catch (FunctionEvaluationException e) { 609 throw new IllegalArgumentException(e); 610 } 611 } 612 613 /** {@inheritDoc} */ 614 public RealVector mapSignum() { 615 return copy().mapSignumToSelf(); 616 } 617 618 /** {@inheritDoc} */ 619 public RealVector mapSignumToSelf() { 620 try { 621 return mapToSelf(ComposableFunction.SIGNUM); 622 } catch (FunctionEvaluationException e) { 623 throw new IllegalArgumentException(e); 624 } 625 } 626 627 /** {@inheritDoc} */ 628 public RealVector mapSin() { 629 return copy().mapSinToSelf(); 630 } 631 632 /** {@inheritDoc} */ 633 public RealVector mapSinToSelf() { 634 try { 635 return mapToSelf(ComposableFunction.SIN); 636 } catch (FunctionEvaluationException e) { 637 throw new IllegalArgumentException(e); 638 } 639 } 640 641 /** {@inheritDoc} */ 642 public RealVector mapSinh() { 643 return copy().mapSinhToSelf(); 644 } 645 646 /** {@inheritDoc} */ 647 public RealVector mapSinhToSelf() { 648 try { 649 return mapToSelf(ComposableFunction.SINH); 650 } catch (FunctionEvaluationException e) { 651 throw new IllegalArgumentException(e); 652 } 653 } 654 655 /** {@inheritDoc} */ 656 public RealVector mapSqrt() { 657 return copy().mapSqrtToSelf(); 658 } 659 660 /** {@inheritDoc} */ 661 public RealVector mapSqrtToSelf() { 662 try { 663 return mapToSelf(ComposableFunction.SQRT); 664 } catch (FunctionEvaluationException e) { 665 throw new IllegalArgumentException(e); 666 } 667 } 668 669 /** {@inheritDoc} */ 670 public RealVector mapSubtract(double d) { 671 return copy().mapSubtractToSelf(d); 672 } 673 674 /** {@inheritDoc} */ 675 public RealVector mapSubtractToSelf(double d){ 676 return mapAddToSelf(-d); 677 } 678 679 /** {@inheritDoc} */ 680 public RealVector mapTan() { 681 return copy().mapTanToSelf(); 682 } 683 684 /** {@inheritDoc} */ 685 public RealVector mapTanToSelf() { 686 try { 687 return mapToSelf(ComposableFunction.TAN); 688 } catch (FunctionEvaluationException e) { 689 throw new IllegalArgumentException(e); 690 } 691 } 692 693 /** {@inheritDoc} */ 694 public RealVector mapTanh() { 695 return copy().mapTanhToSelf(); 696 } 697 698 /** {@inheritDoc} */ 699 public RealVector mapTanhToSelf() { 700 try { 701 return mapToSelf(ComposableFunction.TANH); 702 } catch (FunctionEvaluationException e) { 703 throw new IllegalArgumentException(e); 704 } 705 } 706 707 /** {@inheritDoc} */ 708 public RealVector mapUlp() { 709 return copy().mapUlpToSelf(); 710 } 711 712 /** {@inheritDoc} */ 713 public RealVector mapUlpToSelf() { 714 try { 715 return mapToSelf(ComposableFunction.ULP); 716 } catch (FunctionEvaluationException e) { 717 throw new IllegalArgumentException(e); 718 } 719 } 720 721 /** {@inheritDoc} */ 722 public RealMatrix outerProduct(RealVector v) throws IllegalArgumentException { 723 RealMatrix product; 724 if (v instanceof SparseRealVector || this instanceof SparseRealVector) { 725 product = new OpenMapRealMatrix(this.getDimension(), v.getDimension()); 726 } else { 727 product = new Array2DRowRealMatrix(this.getDimension(), v.getDimension()); 728 } 729 Iterator<Entry> thisIt = sparseIterator(); 730 Entry thisE = null; 731 while (thisIt.hasNext() && (thisE = thisIt.next()) != null) { 732 Iterator<Entry> otherIt = v.sparseIterator(); 733 Entry otherE = null; 734 while (otherIt.hasNext() && (otherE = otherIt.next()) != null) { 735 product.setEntry(thisE.getIndex(), otherE.getIndex(), 736 thisE.getValue() * otherE.getValue()); 737 } 738 } 739 740 return product; 741 742 } 743 744 /** {@inheritDoc} */ 745 public RealMatrix outerProduct(double[] v) throws IllegalArgumentException { 746 return outerProduct(new ArrayRealVector(v, false)); 747 } 748 749 /** {@inheritDoc} */ 750 public RealVector projection(double[] v) throws IllegalArgumentException { 751 return projection(new ArrayRealVector(v, false)); 752 } 753 754 /** {@inheritDoc} */ 755 public void set(double value) { 756 Iterator<Entry> it = iterator(); 757 Entry e = null; 758 while (it.hasNext() && (e = it.next()) != null) { 759 e.setValue(value); 760 } 761 } 762 763 /** {@inheritDoc} */ 764 public double[] toArray() { 765 int dim = getDimension(); 766 double[] values = new double[dim]; 767 for (int i = 0; i < dim; i++) { 768 values[i] = getEntry(i); 769 } 770 return values; 771 } 772 773 /** {@inheritDoc} */ 774 public double[] getData() { 775 return toArray(); 776 } 777 778 /** {@inheritDoc} */ 779 public RealVector unitVector() { 780 RealVector copy = copy(); 781 copy.unitize(); 782 return copy; 783 } 784 785 /** {@inheritDoc} */ 786 public void unitize() { 787 mapDivideToSelf(getNorm()); 788 } 789 790 /** {@inheritDoc} */ 791 public Iterator<Entry> sparseIterator() { 792 return new SparseEntryIterator(); 793 } 794 795 /** {@inheritDoc} */ 796 public Iterator<Entry> iterator() { 797 final int dim = getDimension(); 798 return new Iterator<Entry>() { 799 800 /** Current index. */ 801 private int i = 0; 802 803 /** Current entry. */ 804 private EntryImpl e = new EntryImpl(); 805 806 /** {@inheritDoc} */ 807 public boolean hasNext() { 808 return i < dim; 809 } 810 811 /** {@inheritDoc} */ 812 public Entry next() { 813 e.setIndex(i++); 814 return e; 815 } 816 817 /** {@inheritDoc} */ 818 public void remove() { 819 throw new UnsupportedOperationException("Not supported"); 820 } 821 }; 822 } 823 824 /** {@inheritDoc} */ 825 public RealVector map(UnivariateRealFunction function) throws FunctionEvaluationException { 826 return copy().mapToSelf(function); 827 } 828 829 /** {@inheritDoc} */ 830 public RealVector mapToSelf(UnivariateRealFunction function) throws FunctionEvaluationException { 831 Iterator<Entry> it = (function.value(0) == 0) ? sparseIterator() : iterator(); 832 Entry e; 833 while (it.hasNext() && (e = it.next()) != null) { 834 e.setValue(function.value(e.getValue())); 835 } 836 return this; 837 } 838 839 /** An entry in the vector. */ 840 protected class EntryImpl extends Entry { 841 842 /** Simple constructor. */ 843 public EntryImpl() { 844 setIndex(0); 845 } 846 847 /** {@inheritDoc} */ 848 @Override 849 public double getValue() { 850 return getEntry(getIndex()); 851 } 852 853 /** {@inheritDoc} */ 854 @Override 855 public void setValue(double newValue) { 856 setEntry(getIndex(), newValue); 857 } 858 } 859 860 /** 861 * This class should rare be used, but is here to provide 862 * a default implementation of sparseIterator(), which is implemented 863 * by walking over the entries, skipping those whose values are the default one. 864 * 865 * Concrete subclasses which are SparseVector implementations should 866 * make their own sparse iterator, not use this one. 867 * 868 * This implementation might be useful for ArrayRealVector, when expensive 869 * operations which preserve the default value are to be done on the entries, 870 * and the fraction of non-default values is small (i.e. someone took a 871 * SparseVector, and passed it into the copy-constructor of ArrayRealVector) 872 */ 873 protected class SparseEntryIterator implements Iterator<Entry> { 874 875 /** Dimension of the vector. */ 876 private final int dim; 877 878 /** Temporary entry (reused on each call to {@link #next()}. */ 879 private EntryImpl tmp = new EntryImpl(); 880 881 /** Current entry. */ 882 private EntryImpl current; 883 884 /** Next entry. */ 885 private EntryImpl next; 886 887 /** Simple constructor. */ 888 protected SparseEntryIterator() { 889 dim = getDimension(); 890 current = new EntryImpl(); 891 if (current.getValue() == 0) { 892 advance(current); 893 } 894 if(current.getIndex() >= 0){ 895 // There is at least one non-zero entry 896 next = new EntryImpl(); 897 next.setIndex(current.getIndex()); 898 advance(next); 899 } else { 900 // The vector consists of only zero entries, so deny having a next 901 current = null; 902 } 903 } 904 905 /** Advance an entry up to the next non null one. 906 * @param e entry to advance 907 */ 908 protected void advance(EntryImpl e) { 909 if (e == null) { 910 return; 911 } 912 do { 913 e.setIndex(e.getIndex() + 1); 914 } while (e.getIndex() < dim && e.getValue() == 0); 915 if (e.getIndex() >= dim) { 916 e.setIndex(-1); 917 } 918 } 919 920 /** {@inheritDoc} */ 921 public boolean hasNext() { 922 return current != null; 923 } 924 925 /** {@inheritDoc} */ 926 public Entry next() { 927 tmp.setIndex(current.getIndex()); 928 if (next != null) { 929 current.setIndex(next.getIndex()); 930 advance(next); 931 if (next.getIndex() < 0) { 932 next = null; 933 } 934 } else { 935 current = null; 936 } 937 return tmp; 938 } 939 940 /** {@inheritDoc} */ 941 public void remove() { 942 throw new UnsupportedOperationException("Not supported"); 943 } 944 } 945 946 }