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.lang.reflect.Array; 21 import java.util.Arrays; 22 23 import org.apache.commons.math.Field; 24 import org.apache.commons.math.FieldElement; 25 import org.apache.commons.math.MathRuntimeException; 26 import org.apache.commons.math.exception.util.LocalizedFormats; 27 28 /** 29 * This class implements the {@link FieldVector} interface with a {@link FieldElement} array. 30 * @param <T> the type of the field elements 31 * @version $Revision: 1003997 $ $Date: 2010-10-03 18:45:55 +0200 (dim. 03 oct. 2010) $ 32 * @since 2.0 33 */ 34 public class ArrayFieldVector<T extends FieldElement<T>> implements FieldVector<T>, Serializable { 35 36 /** Serializable version identifier. */ 37 private static final long serialVersionUID = 7648186910365927050L; 38 39 /** Entries of the vector. */ 40 protected T[] data; 41 42 /** Field to which the elements belong. */ 43 private final Field<T> field; 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 * #ArrayFieldVector(ArrayFieldVector, ArrayFieldVector)} constructor 50 * or one of the <code>append</code> methods ({@link #append(FieldElement[])}, 51 * {@link #add(FieldVector)}, {@link #append(ArrayFieldVector)}) to gather data 52 * into this vector.</p> 53 * @param field field to which the elements belong 54 */ 55 public ArrayFieldVector(final Field<T> field) { 56 this(field, 0); 57 } 58 59 /** 60 * Construct a (size)-length vector of zeros. 61 * @param field field to which the elements belong 62 * @param size size of the vector 63 */ 64 public ArrayFieldVector(Field<T> field, int size) { 65 this.field = field; 66 data = buildArray(size); 67 Arrays.fill(data, field.getZero()); 68 } 69 70 /** 71 * Construct an (size)-length vector with preset values. 72 * @param size size of the vector 73 * @param preset fill the vector with this scalar value 74 */ 75 public ArrayFieldVector(int size, T preset) { 76 this(preset.getField(), size); 77 Arrays.fill(data, preset); 78 } 79 80 /** 81 * Construct a vector from an array, copying the input array. 82 * <p> 83 * This constructor needs a non-empty {@code d} array to retrieve 84 * the field from its first element. This implies it cannot build 85 * 0 length vectors. To build vectors from any size, one should 86 * use the {@link #ArrayFieldVector(Field, FieldElement[])} constructor. 87 * </p> 88 * @param d array of Ts. 89 * @throws IllegalArgumentException if <code>d</code> is empty 90 * @see #ArrayFieldVector(Field, FieldElement[]) 91 */ 92 public ArrayFieldVector(T[] d) 93 throws IllegalArgumentException { 94 try { 95 field = d[0].getField(); 96 data = d.clone(); 97 } catch (ArrayIndexOutOfBoundsException e) { 98 throw MathRuntimeException.createIllegalArgumentException( 99 LocalizedFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT); 100 } 101 } 102 103 /** 104 * Construct a vector from an array, copying the input array. 105 * @param field field to which the elements belong 106 * @param d array of Ts. 107 * @see #ArrayFieldVector(FieldElement[]) 108 */ 109 public ArrayFieldVector(Field<T> field, T[] d) { 110 this.field = field; 111 data = d.clone(); 112 } 113 114 /** 115 * Create a new ArrayFieldVector using the input array as the underlying 116 * data array. 117 * <p>If an array is built specially in order to be embedded in a 118 * ArrayFieldVector and not used directly, the <code>copyArray</code> may be 119 * set to <code>false</code. This will prevent the copying and improve 120 * performance as no new array will be built and no data will be copied.</p> 121 * <p> 122 * This constructor needs a non-empty {@code d} array to retrieve 123 * the field from its first element. This implies it cannot build 124 * 0 length vectors. To build vectors from any size, one should 125 * use the {@link #ArrayFieldVector(Field, FieldElement[], boolean)} constructor. 126 * </p> 127 * @param d data for new vector 128 * @param copyArray if true, the input array will be copied, otherwise 129 * it will be referenced 130 * @throws IllegalArgumentException if <code>d</code> is empty 131 * @throws NullPointerException if <code>d</code> is null 132 * @see #ArrayFieldVector(FieldElement[]) 133 * @see #ArrayFieldVector(Field, FieldElement[], boolean) 134 */ 135 public ArrayFieldVector(T[] d, boolean copyArray) 136 throws NullPointerException, IllegalArgumentException { 137 if (d.length == 0) { 138 throw MathRuntimeException.createIllegalArgumentException( 139 LocalizedFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT); 140 } 141 field = d[0].getField(); 142 data = copyArray ? d.clone() : d; 143 } 144 145 /** 146 * Create a new ArrayFieldVector using the input array as the underlying 147 * data array. 148 * <p>If an array is built specially in order to be embedded in a 149 * ArrayFieldVector and not used directly, the <code>copyArray</code> may be 150 * set to <code>false</code. This will prevent the copying and improve 151 * performance as no new array will be built and no data will be copied.</p> 152 * @param field field to which the elements belong 153 * @param d data for new vector 154 * @param copyArray if true, the input array will be copied, otherwise 155 * it will be referenced 156 * @see #ArrayFieldVector(FieldElement[], boolean) 157 */ 158 public ArrayFieldVector(Field<T> field, T[] d, boolean copyArray) { 159 this.field = field; 160 data = copyArray ? d.clone() : d; 161 } 162 163 /** 164 * Construct a vector from part of a array. 165 * @param d array of Ts. 166 * @param pos position of first entry 167 * @param size number of entries to copy 168 */ 169 public ArrayFieldVector(T[] d, int pos, int size) { 170 if (d.length < pos + size) { 171 throw MathRuntimeException.createIllegalArgumentException( 172 LocalizedFormats.POSITION_SIZE_MISMATCH_INPUT_ARRAY, 173 pos, size, d.length); 174 } 175 field = d[0].getField(); 176 data = buildArray(size); 177 System.arraycopy(d, pos, data, 0, size); 178 } 179 180 /** 181 * Construct a vector from another vector, using a deep copy. 182 * @param v vector to copy 183 */ 184 public ArrayFieldVector(FieldVector<T> v) { 185 field = v.getField(); 186 data = buildArray(v.getDimension()); 187 for (int i = 0; i < data.length; ++i) { 188 data[i] = v.getEntry(i); 189 } 190 } 191 192 /** 193 * Construct a vector from another vector, using a deep copy. 194 * @param v vector to copy 195 */ 196 public ArrayFieldVector(ArrayFieldVector<T> v) { 197 field = v.getField(); 198 data = v.data.clone(); 199 } 200 201 /** 202 * Construct a vector from another vector. 203 * @param v vector to copy 204 * @param deep if true perform a deep copy otherwise perform a shallow copy 205 */ 206 public ArrayFieldVector(ArrayFieldVector<T> v, boolean deep) { 207 field = v.getField(); 208 data = deep ? v.data.clone() : v.data; 209 } 210 211 /** 212 * Construct a vector by appending one vector to another vector. 213 * @param v1 first vector (will be put in front of the new vector) 214 * @param v2 second vector (will be put at back of the new vector) 215 */ 216 public ArrayFieldVector(ArrayFieldVector<T> v1, ArrayFieldVector<T> v2) { 217 field = v1.getField(); 218 data = buildArray(v1.data.length + v2.data.length); 219 System.arraycopy(v1.data, 0, data, 0, v1.data.length); 220 System.arraycopy(v2.data, 0, data, v1.data.length, v2.data.length); 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 ArrayFieldVector(ArrayFieldVector<T> v1, T[] v2) { 229 field = v1.getField(); 230 data = buildArray(v1.data.length + v2.length); 231 System.arraycopy(v1.data, 0, data, 0, v1.data.length); 232 System.arraycopy(v2, 0, data, v1.data.length, v2.length); 233 } 234 235 /** 236 * Construct a vector by appending one vector to another vector. 237 * @param v1 first vector (will be put in front of the new vector) 238 * @param v2 second vector (will be put at back of the new vector) 239 */ 240 public ArrayFieldVector(T[] v1, ArrayFieldVector<T> v2) { 241 field = v2.getField(); 242 data = buildArray(v1.length + v2.data.length); 243 System.arraycopy(v1, 0, data, 0, v1.length); 244 System.arraycopy(v2.data, 0, data, v1.length, v2.data.length); 245 } 246 247 /** 248 * Construct a vector by appending one vector to another vector. 249 * <p> 250 * This constructor needs at least one non-empty array to retrieve 251 * the field from its first element. This implies it cannot build 252 * 0 length vectors. To build vectors from any size, one should 253 * use the {@link #ArrayFieldVector(Field, FieldElement[], FieldElement[])} constructor. 254 * </p> 255 * @param v1 first vector (will be put in front of the new vector) 256 * @param v2 second vector (will be put at back of the new vector) 257 * @exception IllegalArgumentException if both vectors are empty 258 * @see #ArrayFieldVector(Field, FieldElement[], FieldElement[]) 259 */ 260 public ArrayFieldVector(T[] v1, T[] v2) { 261 try { 262 data = buildArray(v1.length + v2.length); 263 System.arraycopy(v1, 0, data, 0, v1.length); 264 System.arraycopy(v2, 0, data, v1.length, v2.length); 265 field = data[0].getField(); 266 } catch (ArrayIndexOutOfBoundsException e) { 267 throw MathRuntimeException.createIllegalArgumentException( 268 LocalizedFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT); 269 } 270 } 271 272 /** 273 * Construct a vector by appending one vector to another vector. 274 * @param field field to which the elements belong 275 * @param v1 first vector (will be put in front of the new vector) 276 * @param v2 second vector (will be put at back of the new vector) 277 * @see #ArrayFieldVector(FieldElement[], FieldElement[]) 278 */ 279 public ArrayFieldVector(Field<T> field, T[] v1, T[] v2) { 280 if (v1.length + v2.length == 0) { 281 throw MathRuntimeException.createIllegalArgumentException( 282 LocalizedFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT); 283 } 284 data = buildArray(v1.length + v2.length); 285 System.arraycopy(v1, 0, data, 0, v1.length); 286 System.arraycopy(v2, 0, data, v1.length, v2.length); 287 this.field = data[0].getField(); 288 } 289 290 /** Build an array of elements. 291 * @param length size of the array to build 292 * @return a new array 293 */ 294 @SuppressWarnings("unchecked") // field is of type T 295 private T[] buildArray(final int length) { 296 return (T[]) Array.newInstance(field.getZero().getClass(), length); 297 } 298 299 /** {@inheritDoc} */ 300 public Field<T> getField() { 301 return field; 302 } 303 304 /** {@inheritDoc} */ 305 public FieldVector<T> copy() { 306 return new ArrayFieldVector<T>(this, true); 307 } 308 309 /** {@inheritDoc} */ 310 public FieldVector<T> add(FieldVector<T> v) throws IllegalArgumentException { 311 try { 312 return add((ArrayFieldVector<T>) v); 313 } catch (ClassCastException cce) { 314 checkVectorDimensions(v); 315 T[] out = buildArray(data.length); 316 for (int i = 0; i < data.length; i++) { 317 out[i] = data[i].add(v.getEntry(i)); 318 } 319 return new ArrayFieldVector<T>(out); 320 } 321 } 322 323 /** {@inheritDoc} */ 324 public FieldVector<T> add(T[] v) throws IllegalArgumentException { 325 checkVectorDimensions(v.length); 326 T[] out = buildArray(data.length); 327 for (int i = 0; i < data.length; i++) { 328 out[i] = data[i].add(v[i]); 329 } 330 return new ArrayFieldVector<T>(out); 331 } 332 333 /** 334 * Compute the sum of this and v. 335 * @param v vector to be added 336 * @return this + v 337 * @throws IllegalArgumentException if v is not the same size as this 338 */ 339 public ArrayFieldVector<T> add(ArrayFieldVector<T> v) 340 throws IllegalArgumentException { 341 return (ArrayFieldVector<T>) add(v.data); 342 } 343 344 /** {@inheritDoc} */ 345 public FieldVector<T> subtract(FieldVector<T> v) throws IllegalArgumentException { 346 try { 347 return subtract((ArrayFieldVector<T>) v); 348 } catch (ClassCastException cce) { 349 checkVectorDimensions(v); 350 T[] out = buildArray(data.length); 351 for (int i = 0; i < data.length; i++) { 352 out[i] = data[i].subtract(v.getEntry(i)); 353 } 354 return new ArrayFieldVector<T>(out); 355 } 356 } 357 358 /** {@inheritDoc} */ 359 public FieldVector<T> subtract(T[] v) throws IllegalArgumentException { 360 checkVectorDimensions(v.length); 361 T[] out = buildArray(data.length); 362 for (int i = 0; i < data.length; i++) { 363 out[i] = data[i].subtract(v[i]); 364 } 365 return new ArrayFieldVector<T>(out); 366 } 367 368 /** 369 * Compute this minus v. 370 * @param v vector to be subtracted 371 * @return this + v 372 * @throws IllegalArgumentException if v is not the same size as this 373 */ 374 public ArrayFieldVector<T> subtract(ArrayFieldVector<T> v) 375 throws IllegalArgumentException { 376 return (ArrayFieldVector<T>) subtract(v.data); 377 } 378 379 /** {@inheritDoc} */ 380 public FieldVector<T> mapAdd(T d) { 381 T[] out = buildArray(data.length); 382 for (int i = 0; i < data.length; i++) { 383 out[i] = data[i].add(d); 384 } 385 return new ArrayFieldVector<T>(out); 386 } 387 388 /** {@inheritDoc} */ 389 public FieldVector<T> mapAddToSelf(T d) { 390 for (int i = 0; i < data.length; i++) { 391 data[i] = data[i].add(d); 392 } 393 return this; 394 } 395 396 /** {@inheritDoc} */ 397 public FieldVector<T> mapSubtract(T d) { 398 T[] out = buildArray(data.length); 399 for (int i = 0; i < data.length; i++) { 400 out[i] = data[i].subtract(d); 401 } 402 return new ArrayFieldVector<T>(out); 403 } 404 405 /** {@inheritDoc} */ 406 public FieldVector<T> mapSubtractToSelf(T d) { 407 for (int i = 0; i < data.length; i++) { 408 data[i] = data[i].subtract(d); 409 } 410 return this; 411 } 412 413 /** {@inheritDoc} */ 414 public FieldVector<T> mapMultiply(T d) { 415 T[] out = buildArray(data.length); 416 for (int i = 0; i < data.length; i++) { 417 out[i] = data[i].multiply(d); 418 } 419 return new ArrayFieldVector<T>(out); 420 } 421 422 /** {@inheritDoc} */ 423 public FieldVector<T> mapMultiplyToSelf(T d) { 424 for (int i = 0; i < data.length; i++) { 425 data[i] = data[i].multiply(d); 426 } 427 return this; 428 } 429 430 /** {@inheritDoc} */ 431 public FieldVector<T> mapDivide(T d) { 432 T[] out = buildArray(data.length); 433 for (int i = 0; i < data.length; i++) { 434 out[i] = data[i].divide(d); 435 } 436 return new ArrayFieldVector<T>(out); 437 } 438 439 /** {@inheritDoc} */ 440 public FieldVector<T> mapDivideToSelf(T d) { 441 for (int i = 0; i < data.length; i++) { 442 data[i] = data[i].divide(d); 443 } 444 return this; 445 } 446 447 /** {@inheritDoc} */ 448 public FieldVector<T> mapInv() { 449 T[] out = buildArray(data.length); 450 final T one = field.getOne(); 451 for (int i = 0; i < data.length; i++) { 452 out[i] = one.divide(data[i]); 453 } 454 return new ArrayFieldVector<T>(out); 455 } 456 457 /** {@inheritDoc} */ 458 public FieldVector<T> mapInvToSelf() { 459 final T one = field.getOne(); 460 for (int i = 0; i < data.length; i++) { 461 data[i] = one.divide(data[i]); 462 } 463 return this; 464 } 465 466 /** {@inheritDoc} */ 467 public FieldVector<T> ebeMultiply(FieldVector<T> v) 468 throws IllegalArgumentException { 469 try { 470 return ebeMultiply((ArrayFieldVector<T>) v); 471 } catch (ClassCastException cce) { 472 checkVectorDimensions(v); 473 T[] out = buildArray(data.length); 474 for (int i = 0; i < data.length; i++) { 475 out[i] = data[i].multiply(v.getEntry(i)); 476 } 477 return new ArrayFieldVector<T>(out); 478 } 479 } 480 481 /** {@inheritDoc} */ 482 public FieldVector<T> ebeMultiply(T[] v) 483 throws IllegalArgumentException { 484 checkVectorDimensions(v.length); 485 T[] out = buildArray(data.length); 486 for (int i = 0; i < data.length; i++) { 487 out[i] = data[i].multiply(v[i]); 488 } 489 return new ArrayFieldVector<T>(out); 490 } 491 492 /** 493 * Element-by-element multiplication. 494 * @param v vector by which instance elements must be multiplied 495 * @return a vector containing this[i] * v[i] for all i 496 * @exception IllegalArgumentException if v is not the same size as this 497 */ 498 public ArrayFieldVector<T> ebeMultiply(ArrayFieldVector<T> v) 499 throws IllegalArgumentException { 500 return (ArrayFieldVector<T>) ebeMultiply(v.data); 501 } 502 503 /** {@inheritDoc} */ 504 public FieldVector<T> ebeDivide(FieldVector<T> v) 505 throws IllegalArgumentException { 506 try { 507 return ebeDivide((ArrayFieldVector<T>) v); 508 } catch (ClassCastException cce) { 509 checkVectorDimensions(v); 510 T[] out = buildArray(data.length); 511 for (int i = 0; i < data.length; i++) { 512 out[i] = data[i].divide(v.getEntry(i)); 513 } 514 return new ArrayFieldVector<T>(out); 515 } 516 } 517 518 /** {@inheritDoc} */ 519 public FieldVector<T> ebeDivide(T[] v) 520 throws IllegalArgumentException { 521 checkVectorDimensions(v.length); 522 T[] out = buildArray(data.length); 523 for (int i = 0; i < data.length; i++) { 524 out[i] = data[i].divide(v[i]); 525 } 526 return new ArrayFieldVector<T>(out); 527 } 528 529 /** 530 * Element-by-element division. 531 * @param v vector by which instance elements must be divided 532 * @return a vector containing this[i] / v[i] for all i 533 * @throws IllegalArgumentException if v is not the same size as this 534 */ 535 public ArrayFieldVector<T> ebeDivide(ArrayFieldVector<T> v) 536 throws IllegalArgumentException { 537 return (ArrayFieldVector<T>) ebeDivide(v.data); 538 } 539 540 /** {@inheritDoc} */ 541 public T[] getData() { 542 return data.clone(); 543 } 544 545 /** 546 * Returns a reference to the underlying data array. 547 * <p>Does not make a fresh copy of the underlying data.</p> 548 * @return array of entries 549 */ 550 public T[] getDataRef() { 551 return data; 552 } 553 554 /** {@inheritDoc} */ 555 public T dotProduct(FieldVector<T> v) 556 throws IllegalArgumentException { 557 try { 558 return dotProduct((ArrayFieldVector<T>) v); 559 } catch (ClassCastException cce) { 560 checkVectorDimensions(v); 561 T dot = field.getZero(); 562 for (int i = 0; i < data.length; i++) { 563 dot = dot.add(data[i].multiply(v.getEntry(i))); 564 } 565 return dot; 566 } 567 } 568 569 /** {@inheritDoc} */ 570 public T dotProduct(T[] v) 571 throws IllegalArgumentException { 572 checkVectorDimensions(v.length); 573 T dot = field.getZero(); 574 for (int i = 0; i < data.length; i++) { 575 dot = dot.add(data[i].multiply(v[i])); 576 } 577 return dot; 578 } 579 580 /** 581 * Compute the dot product. 582 * @param v vector with which dot product should be computed 583 * @return the scalar dot product between instance and v 584 * @exception IllegalArgumentException if v is not the same size as this 585 */ 586 public T dotProduct(ArrayFieldVector<T> v) 587 throws IllegalArgumentException { 588 return dotProduct(v.data); 589 } 590 591 /** {@inheritDoc} */ 592 public FieldVector<T> projection(FieldVector<T> v) { 593 return v.mapMultiply(dotProduct(v).divide(v.dotProduct(v))); 594 } 595 596 /** {@inheritDoc} */ 597 public FieldVector<T> projection(T[] v) { 598 return projection(new ArrayFieldVector<T>(v, false)); 599 } 600 601 /** Find the orthogonal projection of this vector onto another vector. 602 * @param v vector onto which instance must be projected 603 * @return projection of the instance onto v 604 * @throws IllegalArgumentException if v is not the same size as this 605 */ 606 public ArrayFieldVector<T> projection(ArrayFieldVector<T> v) { 607 return (ArrayFieldVector<T>) v.mapMultiply(dotProduct(v).divide(v.dotProduct(v))); 608 } 609 610 /** {@inheritDoc} */ 611 public FieldMatrix<T> outerProduct(FieldVector<T> v) 612 throws IllegalArgumentException { 613 try { 614 return outerProduct((ArrayFieldVector<T>) v); 615 } catch (ClassCastException cce) { 616 checkVectorDimensions(v); 617 final int m = data.length; 618 final FieldMatrix<T> out = new Array2DRowFieldMatrix<T>(field, m, m); 619 for (int i = 0; i < data.length; i++) { 620 for (int j = 0; j < data.length; j++) { 621 out.setEntry(i, j, data[i].multiply(v.getEntry(j))); 622 } 623 } 624 return out; 625 } 626 } 627 628 /** 629 * Compute the outer product. 630 * @param v vector with which outer product should be computed 631 * @return the square matrix outer product between instance and v 632 * @exception IllegalArgumentException if v is not the same size as this 633 */ 634 public FieldMatrix<T> outerProduct(ArrayFieldVector<T> v) 635 throws IllegalArgumentException { 636 return outerProduct(v.data); 637 } 638 639 /** {@inheritDoc} */ 640 public FieldMatrix<T> outerProduct(T[] v) 641 throws IllegalArgumentException { 642 checkVectorDimensions(v.length); 643 final int m = data.length; 644 final FieldMatrix<T> out = new Array2DRowFieldMatrix<T>(field, m, m); 645 for (int i = 0; i < data.length; i++) { 646 for (int j = 0; j < data.length; j++) { 647 out.setEntry(i, j, data[i].multiply(v[j])); 648 } 649 } 650 return out; 651 } 652 653 /** {@inheritDoc} */ 654 public T getEntry(int index) throws MatrixIndexException { 655 return data[index]; 656 } 657 658 /** {@inheritDoc} */ 659 public int getDimension() { 660 return data.length; 661 } 662 663 /** {@inheritDoc} */ 664 public FieldVector<T> append(FieldVector<T> v) { 665 try { 666 return append((ArrayFieldVector<T>) v); 667 } catch (ClassCastException cce) { 668 return new ArrayFieldVector<T>(this,new ArrayFieldVector<T>(v)); 669 } 670 } 671 672 /** 673 * Construct a vector by appending a vector to this vector. 674 * @param v vector to append to this one. 675 * @return a new vector 676 */ 677 public ArrayFieldVector<T> append(ArrayFieldVector<T> v) { 678 return new ArrayFieldVector<T>(this, v); 679 } 680 681 /** {@inheritDoc} */ 682 public FieldVector<T> append(T in) { 683 final T[] out = buildArray(data.length + 1); 684 System.arraycopy(data, 0, out, 0, data.length); 685 out[data.length] = in; 686 return new ArrayFieldVector<T>(out); 687 } 688 689 /** {@inheritDoc} */ 690 public FieldVector<T> append(T[] in) { 691 return new ArrayFieldVector<T>(this, in); 692 } 693 694 /** {@inheritDoc} */ 695 public FieldVector<T> getSubVector(int index, int n) { 696 ArrayFieldVector<T> out = new ArrayFieldVector<T>(field, n); 697 try { 698 System.arraycopy(data, index, out.data, 0, n); 699 } catch (IndexOutOfBoundsException e) { 700 checkIndex(index); 701 checkIndex(index + n - 1); 702 } 703 return out; 704 } 705 706 /** {@inheritDoc} */ 707 public void setEntry(int index, T value) { 708 try { 709 data[index] = value; 710 } catch (IndexOutOfBoundsException e) { 711 checkIndex(index); 712 } 713 } 714 715 /** {@inheritDoc} */ 716 public void setSubVector(int index, FieldVector<T> v) { 717 try { 718 try { 719 set(index, (ArrayFieldVector<T>) v); 720 } catch (ClassCastException cce) { 721 for (int i = index; i < index + v.getDimension(); ++i) { 722 data[i] = v.getEntry(i-index); 723 } 724 } 725 } catch (IndexOutOfBoundsException e) { 726 checkIndex(index); 727 checkIndex(index + v.getDimension() - 1); 728 } 729 } 730 731 /** {@inheritDoc} */ 732 public void setSubVector(int index, T[] v) { 733 try { 734 System.arraycopy(v, 0, data, index, v.length); 735 } catch (IndexOutOfBoundsException e) { 736 checkIndex(index); 737 checkIndex(index + v.length - 1); 738 } 739 } 740 741 /** 742 * Set a set of consecutive elements. 743 * 744 * @param index index of first element to be set. 745 * @param v vector containing the values to set. 746 * @exception MatrixIndexException if the index is 747 * inconsistent with vector size 748 */ 749 public void set(int index, ArrayFieldVector<T> v) 750 throws MatrixIndexException { 751 setSubVector(index, v.data); 752 } 753 754 /** {@inheritDoc} */ 755 public void set(T value) { 756 Arrays.fill(data, value); 757 } 758 759 /** {@inheritDoc} */ 760 public T[] toArray(){ 761 return data.clone(); 762 } 763 764 /** 765 * Check if instance and specified vectors have the same dimension. 766 * @param v vector to compare instance with 767 * @exception IllegalArgumentException if the vectors do not 768 * have the same dimension 769 */ 770 protected void checkVectorDimensions(FieldVector<T> v) 771 throws IllegalArgumentException { 772 checkVectorDimensions(v.getDimension()); 773 } 774 775 /** 776 * Check if instance dimension is equal to some expected value. 777 * 778 * @param n expected dimension. 779 * @exception IllegalArgumentException if the dimension is 780 * inconsistent with vector size 781 */ 782 protected void checkVectorDimensions(int n) 783 throws IllegalArgumentException { 784 if (data.length != n) { 785 throw MathRuntimeException.createIllegalArgumentException( 786 LocalizedFormats.VECTOR_LENGTH_MISMATCH, 787 data.length, n); 788 } 789 } 790 791 /** 792 * Test for the equality of two real vectors. 793 * <p> 794 * If all coordinates of two real vectors are exactly the same, and none are 795 * <code>Double.NaN</code>, the two real vectors are considered to be equal. 796 * </p> 797 * <p> 798 * <code>NaN</code> coordinates are considered to affect globally the vector 799 * and be equals to each other - i.e, if either (or all) coordinates of the 800 * real vector are equal to <code>Double.NaN</code>, the real vector is equal to 801 * a vector with all <code>Double.NaN</code> coordinates. 802 * </p> 803 * 804 * @param other Object to test for equality to this 805 * @return true if two 3D vector objects are equal, false if 806 * object is null, not an instance of Vector3D, or 807 * not equal to this Vector3D instance 808 * 809 */ 810 @Override 811 public boolean equals(Object other) { 812 813 if (this == other) { 814 return true; 815 } 816 817 if (other == null) { 818 return false; 819 } 820 821 try { 822 @SuppressWarnings("unchecked") // May fail, but we ignore ClassCastException 823 FieldVector<T> rhs = (FieldVector<T>) other; 824 if (data.length != rhs.getDimension()) { 825 return false; 826 } 827 828 for (int i = 0; i < data.length; ++i) { 829 if (!data[i].equals(rhs.getEntry(i))) { 830 return false; 831 } 832 } 833 return true; 834 835 } catch (ClassCastException ex) { 836 // ignore exception 837 return false; 838 } 839 840 } 841 842 /** 843 * Get a hashCode for the real vector. 844 * <p>All NaN values have the same hash code.</p> 845 * @return a hash code value for this object 846 */ 847 @Override 848 public int hashCode() { 849 int h = 3542; 850 for (final T a : data) { 851 h = h ^ a.hashCode(); 852 } 853 return h; 854 } 855 856 /** 857 * Check if an index is valid. 858 * @param index index to check 859 * @exception MatrixIndexException if index is not valid 860 */ 861 private void checkIndex(final int index) 862 throws MatrixIndexException { 863 if (index < 0 || index >= getDimension()) { 864 throw new MatrixIndexException(LocalizedFormats.INDEX_OUT_OF_RANGE, 865 index, 0, getDimension() - 1); 866 } 867 } 868 869 } 870