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 package org.apache.commons.math.linear; 18 19 import java.io.Serializable; 20 import java.util.Arrays; 21 import java.util.Iterator; 22 23 import org.apache.commons.math.MathRuntimeException; 24 import org.apache.commons.math.exception.util.LocalizedFormats; 25 import org.apache.commons.math.util.MathUtils; 26 import org.apache.commons.math.util.FastMath; 27 28 /** 29 * This class implements the {@link RealVector} interface with a double array. 30 * @version $Revision: 1003993 $ $Date: 2010-10-03 18:39:16 +0200 (dim. 03 oct. 2010) $ 31 * @since 2.0 32 */ 33 public class ArrayRealVector extends AbstractRealVector implements Serializable { 34 35 /** Serializable version identifier. */ 36 private static final long serialVersionUID = -1097961340710804027L; 37 38 /** Default format. */ 39 private static final RealVectorFormat DEFAULT_FORMAT = 40 RealVectorFormat.getInstance(); 41 42 /** Entries of the vector. */ 43 protected double data[]; 44 45 /** 46 * Build a 0-length vector. 47 * <p>Zero-length vectors may be used to initialized construction of vectors 48 * by data gathering. We start with zero-length and use either the {@link 49 * #ArrayRealVector(ArrayRealVector, ArrayRealVector)} constructor 50 * or one of the <code>append</code> method ({@link #append(double)}, {@link 51 * #append(double[])}, {@link #append(ArrayRealVector)}) to gather data 52 * into this vector.</p> 53 */ 54 public ArrayRealVector() { 55 data = new double[0]; 56 } 57 58 /** 59 * Construct a (size)-length vector of zeros. 60 * @param size size of the vector 61 */ 62 public ArrayRealVector(int size) { 63 data = new double[size]; 64 } 65 66 /** 67 * Construct an (size)-length vector with preset values. 68 * @param size size of the vector 69 * @param preset fill the vector with this scalar value 70 */ 71 public ArrayRealVector(int size, double preset) { 72 data = new double[size]; 73 Arrays.fill(data, preset); 74 } 75 76 /** 77 * Construct a vector from an array, copying the input array. 78 * @param d array of doubles. 79 */ 80 public ArrayRealVector(double[] d) { 81 data = d.clone(); 82 } 83 84 /** 85 * Create a new ArrayRealVector using the input array as the underlying 86 * data array. 87 * <p>If an array is built specially in order to be embedded in a 88 * ArrayRealVector and not used directly, the <code>copyArray</code> may be 89 * set to <code>false</code. This will prevent the copying and improve 90 * performance as no new array will be built and no data will be copied.</p> 91 * @param d data for new vector 92 * @param copyArray if true, the input array will be copied, otherwise 93 * it will be referenced 94 * @see #ArrayRealVector(double[]) 95 */ 96 public ArrayRealVector(double[] d, boolean copyArray) { 97 data = copyArray ? d.clone() : d; 98 } 99 100 /** 101 * Construct a vector from part of a array. 102 * @param d array of doubles. 103 * @param pos position of first entry 104 * @param size number of entries to copy 105 */ 106 public ArrayRealVector(double[] d, int pos, int size) { 107 if (d.length < pos + size) { 108 throw MathRuntimeException.createIllegalArgumentException( 109 LocalizedFormats.POSITION_SIZE_MISMATCH_INPUT_ARRAY, pos, size, d.length); 110 } 111 data = new double[size]; 112 System.arraycopy(d, pos, data, 0, size); 113 } 114 115 /** 116 * Construct a vector from an array. 117 * @param d array of Doubles. 118 */ 119 public ArrayRealVector(Double[] d) { 120 data = new double[d.length]; 121 for (int i = 0; i < d.length; i++) { 122 data[i] = d[i].doubleValue(); 123 } 124 } 125 126 /** 127 * Construct a vector from part of a Double array 128 * @param d array of Doubles. 129 * @param pos position of first entry 130 * @param size number of entries to copy 131 */ 132 public ArrayRealVector(Double[] d, int pos, int size) { 133 if (d.length < pos + size) { 134 throw MathRuntimeException.createIllegalArgumentException( 135 LocalizedFormats.POSITION_SIZE_MISMATCH_INPUT_ARRAY, pos, size, d.length); 136 } 137 data = new double[size]; 138 for (int i = pos; i < pos + size; i++) { 139 data[i-pos] = d[i].doubleValue(); 140 } 141 } 142 143 /** 144 * Construct a vector from another vector, using a deep copy. 145 * @param v vector to copy 146 */ 147 public ArrayRealVector(RealVector v) { 148 data = new double[v.getDimension()]; 149 for (int i = 0; i < data.length; ++i) { 150 data[i] = v.getEntry(i); 151 } 152 } 153 154 /** 155 * Construct a vector from another vector, using a deep copy. 156 * @param v vector to copy 157 */ 158 public ArrayRealVector(ArrayRealVector v) { 159 this(v, true); 160 } 161 162 /** 163 * Construct a vector from another vector. 164 * @param v vector to copy 165 * @param deep if true perform a deep copy otherwise perform a shallow copy 166 */ 167 public ArrayRealVector(ArrayRealVector v, boolean deep) { 168 data = deep ? v.data.clone() : v.data; 169 } 170 171 /** 172 * Construct a vector by appending one vector to another vector. 173 * @param v1 first vector (will be put in front of the new vector) 174 * @param v2 second vector (will be put at back of the new vector) 175 */ 176 public ArrayRealVector(ArrayRealVector v1, ArrayRealVector v2) { 177 data = new double[v1.data.length + v2.data.length]; 178 System.arraycopy(v1.data, 0, data, 0, v1.data.length); 179 System.arraycopy(v2.data, 0, data, v1.data.length, v2.data.length); 180 } 181 182 /** 183 * Construct a vector by appending one vector to another vector. 184 * @param v1 first vector (will be put in front of the new vector) 185 * @param v2 second vector (will be put at back of the new vector) 186 */ 187 public ArrayRealVector(ArrayRealVector v1, RealVector v2) { 188 final int l1 = v1.data.length; 189 final int l2 = v2.getDimension(); 190 data = new double[l1 + l2]; 191 System.arraycopy(v1.data, 0, data, 0, l1); 192 for (int i = 0; i < l2; ++i) { 193 data[l1 + i] = v2.getEntry(i); 194 } 195 } 196 197 /** 198 * Construct a vector by appending one vector to another vector. 199 * @param v1 first vector (will be put in front of the new vector) 200 * @param v2 second vector (will be put at back of the new vector) 201 */ 202 public ArrayRealVector(RealVector v1, ArrayRealVector v2) { 203 final int l1 = v1.getDimension(); 204 final int l2 = v2.data.length; 205 data = new double[l1 + l2]; 206 for (int i = 0; i < l1; ++i) { 207 data[i] = v1.getEntry(i); 208 } 209 System.arraycopy(v2.data, 0, data, l1, l2); 210 } 211 212 /** 213 * Construct a vector by appending one vector to another vector. 214 * @param v1 first vector (will be put in front of the new vector) 215 * @param v2 second vector (will be put at back of the new vector) 216 */ 217 public ArrayRealVector(ArrayRealVector v1, double[] v2) { 218 final int l1 = v1.getDimension(); 219 final int l2 = v2.length; 220 data = new double[l1 + l2]; 221 System.arraycopy(v1.data, 0, data, 0, l1); 222 System.arraycopy(v2, 0, data, l1, l2); 223 } 224 225 /** 226 * Construct a vector by appending one vector to another vector. 227 * @param v1 first vector (will be put in front of the new vector) 228 * @param v2 second vector (will be put at back of the new vector) 229 */ 230 public ArrayRealVector(double[] v1, ArrayRealVector v2) { 231 final int l1 = v1.length; 232 final int l2 = v2.getDimension(); 233 data = new double[l1 + l2]; 234 System.arraycopy(v1, 0, data, 0, l1); 235 System.arraycopy(v2.data, 0, data, l1, l2); 236 } 237 238 /** 239 * Construct a vector by appending one vector to another vector. 240 * @param v1 first vector (will be put in front of the new vector) 241 * @param v2 second vector (will be put at back of the new vector) 242 */ 243 public ArrayRealVector(double[] v1, double[] v2) { 244 final int l1 = v1.length; 245 final int l2 = v2.length; 246 data = new double[l1 + l2]; 247 System.arraycopy(v1, 0, data, 0, l1); 248 System.arraycopy(v2, 0, data, l1, l2); 249 } 250 251 /** {@inheritDoc} */ 252 @Override 253 public AbstractRealVector copy() { 254 return new ArrayRealVector(this, true); 255 } 256 257 /** {@inheritDoc} */ 258 @Override 259 public RealVector add(RealVector v) 260 throws IllegalArgumentException { 261 if (v instanceof ArrayRealVector) { 262 return add((ArrayRealVector) v); 263 } else { 264 checkVectorDimensions(v); 265 double[] out = data.clone(); 266 Iterator<Entry> it = v.sparseIterator(); 267 Entry e; 268 while (it.hasNext() && (e = it.next()) != null) { 269 out[e.getIndex()] += e.getValue(); 270 } 271 return new ArrayRealVector(out, false); 272 } 273 } 274 275 /** {@inheritDoc} */ 276 @Override 277 public RealVector add(double[] v) 278 throws IllegalArgumentException { 279 checkVectorDimensions(v.length); 280 double[] out = data.clone(); 281 for (int i = 0; i < data.length; i++) { 282 out[i] += v[i]; 283 } 284 return new ArrayRealVector(out, false); 285 } 286 287 /** 288 * Compute the sum of this and v. 289 * @param v vector to be added 290 * @return this + v 291 * @throws IllegalArgumentException if v is not the same size as this 292 */ 293 public ArrayRealVector add(ArrayRealVector v) 294 throws IllegalArgumentException { 295 return (ArrayRealVector) add(v.data); 296 } 297 298 /** {@inheritDoc} */ 299 @Override 300 public RealVector subtract(RealVector v) 301 throws IllegalArgumentException { 302 if (v instanceof ArrayRealVector) { 303 return subtract((ArrayRealVector) v); 304 } else { 305 checkVectorDimensions(v); 306 double[] out = data.clone(); 307 Iterator<Entry> it = v.sparseIterator(); 308 Entry e; 309 while(it.hasNext() && (e = it.next()) != null) { 310 out[e.getIndex()] -= e.getValue(); 311 } 312 return new ArrayRealVector(out, false); 313 } 314 } 315 316 /** {@inheritDoc} */ 317 @Override 318 public RealVector subtract(double[] v) 319 throws IllegalArgumentException { 320 checkVectorDimensions(v.length); 321 double[] out = data.clone(); 322 for (int i = 0; i < data.length; i++) { 323 out[i] -= v[i]; 324 } 325 return new ArrayRealVector(out, false); 326 } 327 328 /** 329 * Compute this minus v. 330 * @param v vector to be subtracted 331 * @return this + v 332 * @throws IllegalArgumentException if v is not the same size as this 333 */ 334 public ArrayRealVector subtract(ArrayRealVector v) 335 throws IllegalArgumentException { 336 return (ArrayRealVector) subtract(v.data); 337 } 338 339 /** {@inheritDoc} */ 340 @Override 341 public RealVector mapAddToSelf(double d) { 342 for (int i = 0; i < data.length; i++) { 343 data[i] = data[i] + d; 344 } 345 return this; 346 } 347 348 /** {@inheritDoc} */ 349 @Override 350 public RealVector mapSubtractToSelf(double d) { 351 for (int i = 0; i < data.length; i++) { 352 data[i] = data[i] - d; 353 } 354 return this; 355 } 356 357 /** {@inheritDoc} */ 358 @Override 359 public RealVector mapMultiplyToSelf(double d) { 360 for (int i = 0; i < data.length; i++) { 361 data[i] = data[i] * d; 362 } 363 return this; 364 } 365 366 /** {@inheritDoc} */ 367 @Override 368 public RealVector mapDivideToSelf(double d) { 369 for (int i = 0; i < data.length; i++) { 370 data[i] = data[i] / d; 371 } 372 return this; 373 } 374 375 /** {@inheritDoc} */ 376 @Override 377 public RealVector mapPowToSelf(double d) { 378 for (int i = 0; i < data.length; i++) { 379 data[i] = FastMath.pow(data[i], d); 380 } 381 return this; 382 } 383 384 /** {@inheritDoc} */ 385 @Override 386 public RealVector mapExpToSelf() { 387 for (int i = 0; i < data.length; i++) { 388 data[i] = FastMath.exp(data[i]); 389 } 390 return this; 391 } 392 393 /** {@inheritDoc} */ 394 @Override 395 public RealVector mapExpm1ToSelf() { 396 for (int i = 0; i < data.length; i++) { 397 data[i] = FastMath.expm1(data[i]); 398 } 399 return this; 400 } 401 402 /** {@inheritDoc} */ 403 @Override 404 public RealVector mapLogToSelf() { 405 for (int i = 0; i < data.length; i++) { 406 data[i] = FastMath.log(data[i]); 407 } 408 return this; 409 } 410 411 /** {@inheritDoc} */ 412 @Override 413 public RealVector mapLog10ToSelf() { 414 for (int i = 0; i < data.length; i++) { 415 data[i] = FastMath.log10(data[i]); 416 } 417 return this; 418 } 419 420 /** {@inheritDoc} */ 421 @Override 422 public RealVector mapLog1pToSelf() { 423 for (int i = 0; i < data.length; i++) { 424 data[i] = FastMath.log1p(data[i]); 425 } 426 return this; 427 } 428 429 /** {@inheritDoc} */ 430 @Override 431 public RealVector mapCoshToSelf() { 432 for (int i = 0; i < data.length; i++) { 433 data[i] = FastMath.cosh(data[i]); 434 } 435 return this; 436 } 437 438 /** {@inheritDoc} */ 439 @Override 440 public RealVector mapSinhToSelf() { 441 for (int i = 0; i < data.length; i++) { 442 data[i] = FastMath.sinh(data[i]); 443 } 444 return this; 445 } 446 447 /** {@inheritDoc} */ 448 @Override 449 public RealVector mapTanhToSelf() { 450 for (int i = 0; i < data.length; i++) { 451 data[i] = FastMath.tanh(data[i]); 452 } 453 return this; 454 } 455 456 /** {@inheritDoc} */ 457 @Override 458 public RealVector mapCosToSelf() { 459 for (int i = 0; i < data.length; i++) { 460 data[i] = FastMath.cos(data[i]); 461 } 462 return this; 463 } 464 465 /** {@inheritDoc} */ 466 @Override 467 public RealVector mapSinToSelf() { 468 for (int i = 0; i < data.length; i++) { 469 data[i] = FastMath.sin(data[i]); 470 } 471 return this; 472 } 473 474 /** {@inheritDoc} */ 475 @Override 476 public RealVector mapTanToSelf() { 477 for (int i = 0; i < data.length; i++) { 478 data[i] = FastMath.tan(data[i]); 479 } 480 return this; 481 } 482 483 /** {@inheritDoc} */ 484 @Override 485 public RealVector mapAcosToSelf() { 486 for (int i = 0; i < data.length; i++) { 487 data[i] = FastMath.acos(data[i]); 488 } 489 return this; 490 } 491 492 /** {@inheritDoc} */ 493 @Override 494 public RealVector mapAsinToSelf() { 495 for (int i = 0; i < data.length; i++) { 496 data[i] = FastMath.asin(data[i]); 497 } 498 return this; 499 } 500 501 /** {@inheritDoc} */ 502 @Override 503 public RealVector mapAtanToSelf() { 504 for (int i = 0; i < data.length; i++) { 505 data[i] = FastMath.atan(data[i]); 506 } 507 return this; 508 } 509 510 /** {@inheritDoc} */ 511 @Override 512 public RealVector mapInvToSelf() { 513 for (int i = 0; i < data.length; i++) { 514 data[i] = 1.0 / data[i]; 515 } 516 return this; 517 } 518 519 /** {@inheritDoc} */ 520 @Override 521 public RealVector mapAbsToSelf() { 522 for (int i = 0; i < data.length; i++) { 523 data[i] = FastMath.abs(data[i]); 524 } 525 return this; 526 } 527 528 /** {@inheritDoc} */ 529 @Override 530 public RealVector mapSqrtToSelf() { 531 for (int i = 0; i < data.length; i++) { 532 data[i] = FastMath.sqrt(data[i]); 533 } 534 return this; 535 } 536 537 /** {@inheritDoc} */ 538 @Override 539 public RealVector mapCbrtToSelf() { 540 for (int i = 0; i < data.length; i++) { 541 data[i] = FastMath.cbrt(data[i]); 542 } 543 return this; 544 } 545 546 /** {@inheritDoc} */ 547 @Override 548 public RealVector mapCeilToSelf() { 549 for (int i = 0; i < data.length; i++) { 550 data[i] = FastMath.ceil(data[i]); 551 } 552 return this; 553 } 554 555 /** {@inheritDoc} */ 556 @Override 557 public RealVector mapFloorToSelf() { 558 for (int i = 0; i < data.length; i++) { 559 data[i] = FastMath.floor(data[i]); 560 } 561 return this; 562 } 563 564 /** {@inheritDoc} */ 565 @Override 566 public RealVector mapRintToSelf() { 567 for (int i = 0; i < data.length; i++) { 568 data[i] = FastMath.rint(data[i]); 569 } 570 return this; 571 } 572 573 /** {@inheritDoc} */ 574 @Override 575 public RealVector mapSignumToSelf() { 576 for (int i = 0; i < data.length; i++) { 577 data[i] = FastMath.signum(data[i]); 578 } 579 return this; 580 } 581 582 /** {@inheritDoc} */ 583 @Override 584 public RealVector mapUlpToSelf() { 585 for (int i = 0; i < data.length; i++) { 586 data[i] = FastMath.ulp(data[i]); 587 } 588 return this; 589 } 590 591 /** {@inheritDoc} */ 592 public RealVector ebeMultiply(RealVector v) 593 throws IllegalArgumentException { 594 if (v instanceof ArrayRealVector) { 595 return ebeMultiply((ArrayRealVector) v); 596 } else { 597 checkVectorDimensions(v); 598 double[] out = data.clone(); 599 for (int i = 0; i < data.length; i++) { 600 out[i] *= v.getEntry(i); 601 } 602 return new ArrayRealVector(out, false); 603 } 604 } 605 606 /** {@inheritDoc} */ 607 @Override 608 public RealVector ebeMultiply(double[] v) 609 throws IllegalArgumentException { 610 checkVectorDimensions(v.length); 611 double[] out = data.clone(); 612 for (int i = 0; i < data.length; i++) { 613 out[i] *= v[i]; 614 } 615 return new ArrayRealVector(out, false); 616 } 617 618 /** 619 * Element-by-element multiplication. 620 * @param v vector by which instance elements must be multiplied 621 * @return a vector containing this[i] * v[i] for all i 622 * @exception IllegalArgumentException if v is not the same size as this 623 */ 624 public ArrayRealVector ebeMultiply(ArrayRealVector v) 625 throws IllegalArgumentException { 626 return (ArrayRealVector) ebeMultiply(v.data); 627 } 628 629 /** {@inheritDoc} */ 630 public RealVector ebeDivide(RealVector v) 631 throws IllegalArgumentException { 632 if (v instanceof ArrayRealVector) { 633 return ebeDivide((ArrayRealVector) v); 634 } else { 635 checkVectorDimensions(v); 636 double[] out = data.clone(); 637 for (int i = 0; i < data.length; i++) { 638 out[i] /= v.getEntry(i); 639 } 640 return new ArrayRealVector(out, false); 641 } 642 } 643 644 /** {@inheritDoc} */ 645 @Override 646 public RealVector ebeDivide(double[] v) 647 throws IllegalArgumentException { 648 checkVectorDimensions(v.length); 649 double[] out = data.clone(); 650 for (int i = 0; i < data.length; i++) { 651 out[i] /= v[i]; 652 } 653 return new ArrayRealVector(out, false); 654 } 655 656 /** 657 * Element-by-element division. 658 * @param v vector by which instance elements must be divided 659 * @return a vector containing this[i] / v[i] for all i 660 * @throws IllegalArgumentException if v is not the same size as this 661 */ 662 public ArrayRealVector ebeDivide(ArrayRealVector v) 663 throws IllegalArgumentException { 664 return (ArrayRealVector) ebeDivide(v.data); 665 } 666 667 /** {@inheritDoc} */ 668 @Override 669 public double[] getData() { 670 return data.clone(); 671 } 672 673 /** 674 * Returns a reference to the underlying data array. 675 * <p>Does not make a fresh copy of the underlying data.</p> 676 * @return array of entries 677 */ 678 public double[] getDataRef() { 679 return data; 680 } 681 682 /** {@inheritDoc} */ 683 @Override 684 public double dotProduct(RealVector v) 685 throws IllegalArgumentException { 686 if (v instanceof ArrayRealVector) { 687 return dotProduct((ArrayRealVector) v); 688 } else { 689 checkVectorDimensions(v); 690 double dot = 0; 691 Iterator<Entry> it = v.sparseIterator(); 692 Entry e; 693 while(it.hasNext() && (e = it.next()) != null) { 694 dot += data[e.getIndex()] * e.getValue(); 695 } 696 return dot; 697 } 698 } 699 700 /** {@inheritDoc} */ 701 @Override 702 public double dotProduct(double[] v) 703 throws IllegalArgumentException { 704 checkVectorDimensions(v.length); 705 double dot = 0; 706 for (int i = 0; i < data.length; i++) { 707 dot += data[i] * v[i]; 708 } 709 return dot; 710 } 711 712 /** 713 * Compute the dot product. 714 * @param v vector with which dot product should be computed 715 * @return the scalar dot product between instance and v 716 * @exception IllegalArgumentException if v is not the same size as this 717 */ 718 public double dotProduct(ArrayRealVector v) 719 throws IllegalArgumentException { 720 return dotProduct(v.data); 721 } 722 723 /** {@inheritDoc} */ 724 @Override 725 public double getNorm() { 726 double sum = 0; 727 for (double a : data) { 728 sum += a * a; 729 } 730 return FastMath.sqrt(sum); 731 } 732 733 /** {@inheritDoc} */ 734 @Override 735 public double getL1Norm() { 736 double sum = 0; 737 for (double a : data) { 738 sum += FastMath.abs(a); 739 } 740 return sum; 741 } 742 743 /** {@inheritDoc} */ 744 @Override 745 public double getLInfNorm() { 746 double max = 0; 747 for (double a : data) { 748 max = FastMath.max(max, FastMath.abs(a)); 749 } 750 return max; 751 } 752 753 /** {@inheritDoc} */ 754 @Override 755 public double getDistance(RealVector v) 756 throws IllegalArgumentException { 757 if (v instanceof ArrayRealVector) { 758 return getDistance((ArrayRealVector) v); 759 } else { 760 checkVectorDimensions(v); 761 double sum = 0; 762 for (int i = 0; i < data.length; ++i) { 763 final double delta = data[i] - v.getEntry(i); 764 sum += delta * delta; 765 } 766 return FastMath.sqrt(sum); 767 } 768 } 769 770 /** {@inheritDoc} */ 771 @Override 772 public double getDistance(double[] v) 773 throws IllegalArgumentException { 774 checkVectorDimensions(v.length); 775 double sum = 0; 776 for (int i = 0; i < data.length; ++i) { 777 final double delta = data[i] - v[i]; 778 sum += delta * delta; 779 } 780 return FastMath.sqrt(sum); 781 } 782 783 /** 784 * Distance between two vectors. 785 * <p>This method computes the distance consistent with the 786 * L<sub>2</sub> norm, i.e. the square root of the sum of 787 * elements differences, or euclidian distance.</p> 788 * @param v vector to which distance is requested 789 * @return distance between two vectors. 790 * @exception IllegalArgumentException if v is not the same size as this 791 * @see #getDistance(RealVector) 792 * @see #getL1Distance(ArrayRealVector) 793 * @see #getLInfDistance(ArrayRealVector) 794 * @see #getNorm() 795 */ 796 public double getDistance(ArrayRealVector v) 797 throws IllegalArgumentException { 798 return getDistance(v.data); 799 } 800 801 /** {@inheritDoc} */ 802 @Override 803 public double getL1Distance(RealVector v) 804 throws IllegalArgumentException { 805 if (v instanceof ArrayRealVector) { 806 return getL1Distance((ArrayRealVector) v); 807 } else { 808 checkVectorDimensions(v); 809 double sum = 0; 810 for (int i = 0; i < data.length; ++i) { 811 final double delta = data[i] - v.getEntry(i); 812 sum += FastMath.abs(delta); 813 } 814 return sum; 815 } 816 } 817 818 /** {@inheritDoc} */ 819 @Override 820 public double getL1Distance(double[] v) 821 throws IllegalArgumentException { 822 checkVectorDimensions(v.length); 823 double sum = 0; 824 for (int i = 0; i < data.length; ++i) { 825 final double delta = data[i] - v[i]; 826 sum += FastMath.abs(delta); 827 } 828 return sum; 829 } 830 831 /** 832 * Distance between two vectors. 833 * <p>This method computes the distance consistent with 834 * L<sub>1</sub> norm, i.e. the sum of the absolute values of 835 * elements differences.</p> 836 * @param v vector to which distance is requested 837 * @return distance between two vectors. 838 * @exception IllegalArgumentException if v is not the same size as this 839 * @see #getDistance(RealVector) 840 * @see #getL1Distance(ArrayRealVector) 841 * @see #getLInfDistance(ArrayRealVector) 842 * @see #getNorm() 843 */ 844 public double getL1Distance(ArrayRealVector v) 845 throws IllegalArgumentException { 846 return getL1Distance(v.data); 847 } 848 849 /** {@inheritDoc} */ 850 @Override 851 public double getLInfDistance(RealVector v) 852 throws IllegalArgumentException { 853 if (v instanceof ArrayRealVector) { 854 return getLInfDistance((ArrayRealVector) v); 855 } else { 856 checkVectorDimensions(v); 857 double max = 0; 858 for (int i = 0; i < data.length; ++i) { 859 final double delta = data[i] - v.getEntry(i); 860 max = FastMath.max(max, FastMath.abs(delta)); 861 } 862 return max; 863 } 864 } 865 866 /** {@inheritDoc} */ 867 @Override 868 public double getLInfDistance(double[] v) 869 throws IllegalArgumentException { 870 checkVectorDimensions(v.length); 871 double max = 0; 872 for (int i = 0; i < data.length; ++i) { 873 final double delta = data[i] - v[i]; 874 max = FastMath.max(max, FastMath.abs(delta)); 875 } 876 return max; 877 } 878 879 /** 880 * Distance between two vectors. 881 * <p>This method computes the distance consistent with 882 * L<sub>∞</sub> norm, i.e. the max of the absolute values of 883 * elements differences.</p> 884 * @param v vector to which distance is requested 885 * @return distance between two vectors. 886 * @exception IllegalArgumentException if v is not the same size as this 887 * @see #getDistance(RealVector) 888 * @see #getL1Distance(ArrayRealVector) 889 * @see #getLInfDistance(ArrayRealVector) 890 * @see #getNorm() 891 */ 892 public double getLInfDistance(ArrayRealVector v) 893 throws IllegalArgumentException { 894 return getLInfDistance(v.data); 895 } 896 897 /** {@inheritDoc} */ 898 @Override 899 public RealVector unitVector() throws ArithmeticException { 900 final double norm = getNorm(); 901 if (norm == 0) { 902 throw MathRuntimeException.createArithmeticException(LocalizedFormats.ZERO_NORM); 903 } 904 return mapDivide(norm); 905 } 906 907 /** {@inheritDoc} */ 908 @Override 909 public void unitize() throws ArithmeticException { 910 final double norm = getNorm(); 911 if (norm == 0) { 912 throw MathRuntimeException.createArithmeticException(LocalizedFormats.CANNOT_NORMALIZE_A_ZERO_NORM_VECTOR); 913 } 914 mapDivideToSelf(norm); 915 } 916 917 /** {@inheritDoc} */ 918 public RealVector projection(RealVector v) { 919 return v.mapMultiply(dotProduct(v) / v.dotProduct(v)); 920 } 921 922 /** {@inheritDoc} */ 923 @Override 924 public RealVector projection(double[] v) { 925 return projection(new ArrayRealVector(v, false)); 926 } 927 928 /** Find the orthogonal projection of this vector onto another vector. 929 * @param v vector onto which instance must be projected 930 * @return projection of the instance onto v 931 * @throws IllegalArgumentException if v is not the same size as this 932 */ 933 public ArrayRealVector projection(ArrayRealVector v) { 934 return (ArrayRealVector) v.mapMultiply(dotProduct(v) / v.dotProduct(v)); 935 } 936 937 /** {@inheritDoc} */ 938 @Override 939 public RealMatrix outerProduct(RealVector v) 940 throws IllegalArgumentException { 941 if (v instanceof ArrayRealVector) { 942 return outerProduct((ArrayRealVector) v); 943 } else { 944 checkVectorDimensions(v); 945 final int m = data.length; 946 final RealMatrix out = MatrixUtils.createRealMatrix(m, m); 947 for (int i = 0; i < data.length; i++) { 948 for (int j = 0; j < data.length; j++) { 949 out.setEntry(i, j, data[i] * v.getEntry(j)); 950 } 951 } 952 return out; 953 } 954 } 955 956 /** 957 * Compute the outer product. 958 * @param v vector with which outer product should be computed 959 * @return the square matrix outer product between instance and v 960 * @exception IllegalArgumentException if v is not the same size as this 961 */ 962 public RealMatrix outerProduct(ArrayRealVector v) 963 throws IllegalArgumentException { 964 return outerProduct(v.data); 965 } 966 967 /** {@inheritDoc} */ 968 @Override 969 public RealMatrix outerProduct(double[] v) 970 throws IllegalArgumentException { 971 checkVectorDimensions(v.length); 972 final int m = data.length; 973 final RealMatrix out = MatrixUtils.createRealMatrix(m, m); 974 for (int i = 0; i < data.length; i++) { 975 for (int j = 0; j < data.length; j++) { 976 out.setEntry(i, j, data[i] * v[j]); 977 } 978 } 979 return out; 980 } 981 982 /** {@inheritDoc} */ 983 public double getEntry(int index) throws MatrixIndexException { 984 return data[index]; 985 } 986 987 /** {@inheritDoc} */ 988 public int getDimension() { 989 return data.length; 990 } 991 992 /** {@inheritDoc} */ 993 public RealVector append(RealVector v) { 994 try { 995 return new ArrayRealVector(this, (ArrayRealVector) v); 996 } catch (ClassCastException cce) { 997 return new ArrayRealVector(this, v); 998 } 999 } 1000 1001 /** 1002 * Construct a vector by appending a vector to this vector. 1003 * @param v vector to append to this one. 1004 * @return a new vector 1005 */ 1006 public ArrayRealVector append(ArrayRealVector v) { 1007 return new ArrayRealVector(this, v); 1008 } 1009 1010 /** {@inheritDoc} */ 1011 public RealVector append(double in) { 1012 final double[] out = new double[data.length + 1]; 1013 System.arraycopy(data, 0, out, 0, data.length); 1014 out[data.length] = in; 1015 return new ArrayRealVector(out, false); 1016 } 1017 1018 /** {@inheritDoc} */ 1019 public RealVector append(double[] in) { 1020 return new ArrayRealVector(this, in); 1021 } 1022 1023 /** {@inheritDoc} */ 1024 public RealVector getSubVector(int index, int n) { 1025 ArrayRealVector out = new ArrayRealVector(n); 1026 try { 1027 System.arraycopy(data, index, out.data, 0, n); 1028 } catch (IndexOutOfBoundsException e) { 1029 checkIndex(index); 1030 checkIndex(index + n - 1); 1031 } 1032 return out; 1033 } 1034 1035 /** {@inheritDoc} */ 1036 public void setEntry(int index, double value) { 1037 try { 1038 data[index] = value; 1039 } catch (IndexOutOfBoundsException e) { 1040 checkIndex(index); 1041 } 1042 } 1043 1044 /** {@inheritDoc} */ 1045 @Override 1046 public void setSubVector(int index, RealVector v) { 1047 try { 1048 try { 1049 set(index, (ArrayRealVector) v); 1050 } catch (ClassCastException cce) { 1051 for (int i = index; i < index + v.getDimension(); ++i) { 1052 data[i] = v.getEntry(i-index); 1053 } 1054 } 1055 } catch (IndexOutOfBoundsException e) { 1056 checkIndex(index); 1057 checkIndex(index + v.getDimension() - 1); 1058 } 1059 } 1060 1061 /** {@inheritDoc} */ 1062 @Override 1063 public void setSubVector(int index, double[] v) { 1064 try { 1065 System.arraycopy(v, 0, data, index, v.length); 1066 } catch (IndexOutOfBoundsException e) { 1067 checkIndex(index); 1068 checkIndex(index + v.length - 1); 1069 } 1070 } 1071 1072 /** 1073 * Set a set of consecutive elements. 1074 * 1075 * @param index index of first element to be set. 1076 * @param v vector containing the values to set. 1077 * @exception MatrixIndexException if the index is 1078 * inconsistent with vector size 1079 */ 1080 public void set(int index, ArrayRealVector v) 1081 throws MatrixIndexException { 1082 setSubVector(index, v.data); 1083 } 1084 1085 /** {@inheritDoc} */ 1086 @Override 1087 public void set(double value) { 1088 Arrays.fill(data, value); 1089 } 1090 1091 /** {@inheritDoc} */ 1092 @Override 1093 public double[] toArray(){ 1094 return data.clone(); 1095 } 1096 1097 /** {@inheritDoc} */ 1098 @Override 1099 public String toString(){ 1100 return DEFAULT_FORMAT.format(this); 1101 } 1102 1103 /** 1104 * Check if instance and specified vectors have the same dimension. 1105 * @param v vector to compare instance with 1106 * @exception IllegalArgumentException if the vectors do not 1107 * have the same dimension 1108 */ 1109 @Override 1110 protected void checkVectorDimensions(RealVector v) 1111 throws IllegalArgumentException { 1112 checkVectorDimensions(v.getDimension()); 1113 } 1114 1115 /** 1116 * Check if instance dimension is equal to some expected value. 1117 * 1118 * @param n expected dimension. 1119 * @exception IllegalArgumentException if the dimension is 1120 * inconsistent with vector size 1121 */ 1122 @Override 1123 protected void checkVectorDimensions(int n) 1124 throws IllegalArgumentException { 1125 if (data.length != n) { 1126 throw MathRuntimeException.createIllegalArgumentException( 1127 LocalizedFormats.VECTOR_LENGTH_MISMATCH, 1128 data.length, n); 1129 } 1130 } 1131 1132 /** 1133 * Returns true if any coordinate of this vector is NaN; false otherwise 1134 * @return true if any coordinate of this vector is NaN; false otherwise 1135 */ 1136 public boolean isNaN() { 1137 for (double v : data) { 1138 if (Double.isNaN(v)) { 1139 return true; 1140 } 1141 } 1142 return false; 1143 } 1144 1145 /** 1146 * Returns true if any coordinate of this vector is infinite and none are NaN; 1147 * false otherwise 1148 * @return true if any coordinate of this vector is infinite and none are NaN; 1149 * false otherwise 1150 */ 1151 public boolean isInfinite() { 1152 1153 if (isNaN()) { 1154 return false; 1155 } 1156 1157 for (double v : data) { 1158 if (Double.isInfinite(v)) { 1159 return true; 1160 } 1161 } 1162 1163 return false; 1164 1165 } 1166 1167 /** 1168 * Test for the equality of two real vectors. 1169 * <p> 1170 * If all coordinates of two real vectors are exactly the same, and none are 1171 * <code>Double.NaN</code>, the two real vectors are considered to be equal. 1172 * </p> 1173 * <p> 1174 * <code>NaN</code> coordinates are considered to affect globally the vector 1175 * and be equals to each other - i.e, if either (or all) coordinates of the 1176 * real vector are equal to <code>Double.NaN</code>, the real vector is equal to 1177 * a vector with all <code>Double.NaN</code> coordinates. 1178 * </p> 1179 * 1180 * @param other Object to test for equality to this 1181 * @return true if two vector objects are equal, false if 1182 * object is null, not an instance of RealVector, or 1183 * not equal to this RealVector instance 1184 * 1185 */ 1186 @Override 1187 public boolean equals(Object other) { 1188 1189 if (this == other) { 1190 return true; 1191 } 1192 1193 if (other == null || !(other instanceof RealVector)) { 1194 return false; 1195 } 1196 1197 1198 RealVector rhs = (RealVector) other; 1199 if (data.length != rhs.getDimension()) { 1200 return false; 1201 } 1202 1203 if (rhs.isNaN()) { 1204 return this.isNaN(); 1205 } 1206 1207 for (int i = 0; i < data.length; ++i) { 1208 if (data[i] != rhs.getEntry(i)) { 1209 return false; 1210 } 1211 } 1212 return true; 1213 } 1214 1215 /** 1216 * Get a hashCode for the real vector. 1217 * <p>All NaN values have the same hash code.</p> 1218 * @return a hash code value for this object 1219 */ 1220 @Override 1221 public int hashCode() { 1222 if (isNaN()) { 1223 return 9; 1224 } 1225 return MathUtils.hash(data); 1226 } 1227 1228 } 1229