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