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 */ 017package org.apache.commons.math4.legacy.linear; 018 019import java.io.Serializable; 020import java.util.Arrays; 021 022import org.apache.commons.math4.legacy.core.Field; 023import org.apache.commons.math4.legacy.core.FieldElement; 024import org.apache.commons.math4.legacy.exception.DimensionMismatchException; 025import org.apache.commons.math4.legacy.exception.MathArithmeticException; 026import org.apache.commons.math4.legacy.exception.NotPositiveException; 027import org.apache.commons.math4.legacy.exception.NullArgumentException; 028import org.apache.commons.math4.legacy.exception.NumberIsTooLargeException; 029import org.apache.commons.math4.legacy.exception.NumberIsTooSmallException; 030import org.apache.commons.math4.legacy.exception.OutOfRangeException; 031import org.apache.commons.math4.legacy.exception.ZeroException; 032import org.apache.commons.math4.legacy.exception.util.LocalizedFormats; 033import org.apache.commons.math4.legacy.core.MathArrays; 034 035/** 036 * This class implements the {@link FieldVector} interface with a {@link FieldElement} array. 037 * @param <T> the type of the field elements 038 * @since 2.0 039 */ 040public class ArrayFieldVector<T extends FieldElement<T>> implements FieldVector<T>, Serializable { 041 /** Serializable version identifier. */ 042 private static final long serialVersionUID = 7648186910365927050L; 043 044 /** Entries of the vector. */ 045 private T[] data; 046 047 /** Field to which the elements belong. */ 048 private final Field<T> field; 049 050 /** 051 * Build a 0-length vector. 052 * Zero-length vectors may be used to initialize construction of vectors 053 * by data gathering. We start with zero-length and use either the {@link 054 * #ArrayFieldVector(FieldVector, FieldVector)} constructor 055 * or one of the {@code append} methods ({@link #add(FieldVector)} or 056 * {@link #append(ArrayFieldVector)}) to gather data into this vector. 057 * 058 * @param field field to which the elements belong 059 */ 060 public ArrayFieldVector(final Field<T> field) { 061 this(field, 0); 062 } 063 064 /** 065 * Construct a vector of zeroes. 066 * 067 * @param field Field to which the elements belong. 068 * @param size Size of the vector. 069 */ 070 public ArrayFieldVector(Field<T> field, int size) { 071 this.field = field; 072 this.data = MathArrays.buildArray(field, size); 073 } 074 075 /** 076 * Construct a vector with preset values. 077 * 078 * @param size Size of the vector. 079 * @param preset All entries will be set with this value. 080 */ 081 public ArrayFieldVector(int size, T preset) { 082 this(preset.getField(), size); 083 Arrays.fill(data, preset); 084 } 085 086 /** 087 * Construct a vector from an array, copying the input array. 088 * This constructor needs a non-empty {@code d} array to retrieve 089 * the field from its first element. This implies it cannot build 090 * 0 length vectors. To build vectors from any size, one should 091 * use the {@link #ArrayFieldVector(Field, FieldElement[])} constructor. 092 * 093 * @param d Array. 094 * @throws NullArgumentException if {@code d} is {@code null}. 095 * @throws ZeroException if {@code d} is empty. 096 * @see #ArrayFieldVector(Field, FieldElement[]) 097 */ 098 public ArrayFieldVector(T[] d) 099 throws NullArgumentException, ZeroException { 100 NullArgumentException.check(d); 101 try { 102 field = d[0].getField(); 103 data = d.clone(); 104 } catch (ArrayIndexOutOfBoundsException e) { 105 throw new ZeroException(LocalizedFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT); 106 } 107 } 108 109 /** 110 * Construct a vector from an array, copying the input array. 111 * 112 * @param field Field to which the elements belong. 113 * @param d Array. 114 * @throws NullArgumentException if {@code d} is {@code null}. 115 * @see #ArrayFieldVector(FieldElement[]) 116 */ 117 public ArrayFieldVector(Field<T> field, T[] d) 118 throws NullArgumentException { 119 NullArgumentException.check(d); 120 this.field = field; 121 data = d.clone(); 122 } 123 124 /** 125 * Create a new ArrayFieldVector using the input array as the underlying 126 * data array. 127 * If an array is built specially in order to be embedded in a 128 * ArrayFieldVector and not used directly, the {@code copyArray} may be 129 * set to {@code false}. This will prevent the copying and improve 130 * performance as no new array will be built and no data will be copied. 131 * This constructor needs a non-empty {@code d} array to retrieve 132 * the field from its first element. This implies it cannot build 133 * 0 length vectors. To build vectors from any size, one should 134 * use the {@link #ArrayFieldVector(Field, FieldElement[], boolean)} 135 * constructor. 136 * 137 * @param d Data for the new vector. 138 * @param copyArray If {@code true}, the input array will be copied, 139 * otherwise it will be referenced. 140 * @throws NullArgumentException if {@code d} is {@code null}. 141 * @throws ZeroException if {@code d} is empty. 142 * @see #ArrayFieldVector(FieldElement[]) 143 * @see #ArrayFieldVector(Field, FieldElement[], boolean) 144 */ 145 public ArrayFieldVector(T[] d, boolean copyArray) 146 throws NullArgumentException, ZeroException { 147 NullArgumentException.check(d); 148 if (d.length == 0) { 149 throw new ZeroException(LocalizedFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT); 150 } 151 field = d[0].getField(); 152 data = copyArray ? d.clone() : d; 153 } 154 155 /** 156 * Create a new ArrayFieldVector using the input array as the underlying 157 * data array. 158 * If an array is built specially in order to be embedded in a 159 * ArrayFieldVector and not used directly, the {@code copyArray} may be 160 * set to {@code false}. This will prevent the copying and improve 161 * performance as no new array will be built and no data will be copied. 162 * 163 * @param field Field to which the elements belong. 164 * @param d Data for the new vector. 165 * @param copyArray If {@code true}, the input array will be copied, 166 * otherwise it will be referenced. 167 * @throws NullArgumentException if {@code d} is {@code null}. 168 * @see #ArrayFieldVector(FieldElement[], boolean) 169 */ 170 public ArrayFieldVector(Field<T> field, T[] d, boolean copyArray) 171 throws NullArgumentException { 172 NullArgumentException.check(d); 173 this.field = field; 174 data = copyArray ? d.clone() : d; 175 } 176 177 /** 178 * Construct a vector from part of a array. 179 * 180 * @param d Array. 181 * @param pos Position of the first entry. 182 * @param size Number of entries to copy. 183 * @throws NullArgumentException if {@code d} is {@code null}. 184 * @throws NumberIsTooLargeException if the size of {@code d} is less 185 * than {@code pos + size}. 186 */ 187 public ArrayFieldVector(T[] d, int pos, int size) 188 throws NullArgumentException, NumberIsTooLargeException { 189 NullArgumentException.check(d); 190 if (d.length < pos + size) { 191 throw new NumberIsTooLargeException(pos + size, d.length, true); 192 } 193 field = d[0].getField(); 194 data = MathArrays.buildArray(field, size); 195 System.arraycopy(d, pos, data, 0, size); 196 } 197 198 /** 199 * Construct a vector from part of a array. 200 * 201 * @param field Field to which the elements belong. 202 * @param d Array. 203 * @param pos Position of the first entry. 204 * @param size Number of entries to copy. 205 * @throws NullArgumentException if {@code d} is {@code null}. 206 * @throws NumberIsTooLargeException if the size of {@code d} is less 207 * than {@code pos + size}. 208 */ 209 public ArrayFieldVector(Field<T> field, T[] d, int pos, int size) 210 throws NullArgumentException, NumberIsTooLargeException { 211 NullArgumentException.check(d); 212 if (d.length < pos + size) { 213 throw new NumberIsTooLargeException(pos + size, d.length, true); 214 } 215 this.field = field; 216 data = MathArrays.buildArray(field, size); 217 System.arraycopy(d, pos, data, 0, size); 218 } 219 220 /** 221 * Construct a vector from another vector, using a deep copy. 222 * 223 * @param v Vector to copy. 224 * @throws NullArgumentException if {@code v} is {@code null}. 225 */ 226 public ArrayFieldVector(FieldVector<T> v) 227 throws NullArgumentException { 228 NullArgumentException.check(v); 229 field = v.getField(); 230 data = MathArrays.buildArray(field, v.getDimension()); 231 for (int i = 0; i < data.length; ++i) { 232 data[i] = v.getEntry(i); 233 } 234 } 235 236 /** 237 * Construct a vector from another vector, using a deep copy. 238 * 239 * @param v Vector to copy. 240 * @throws NullArgumentException if {@code v} is {@code null}. 241 */ 242 public ArrayFieldVector(ArrayFieldVector<T> v) 243 throws NullArgumentException { 244 NullArgumentException.check(v); 245 field = v.getField(); 246 data = v.data.clone(); 247 } 248 249 /** 250 * Construct a vector from another vector. 251 * 252 * @param v Vector to copy. 253 * @param deep If {@code true} perform a deep copy, otherwise perform 254 * a shallow copy 255 * @throws NullArgumentException if {@code v} is {@code null}. 256 */ 257 public ArrayFieldVector(ArrayFieldVector<T> v, boolean deep) 258 throws NullArgumentException { 259 NullArgumentException.check(v); 260 field = v.getField(); 261 data = deep ? v.data.clone() : v.data; 262 } 263 264 /** 265 * Construct a vector by appending one vector to another vector. 266 * 267 * @param v1 First vector (will be put in front of the new vector). 268 * @param v2 Second vector (will be put at back of the new vector). 269 * @throws NullArgumentException if {@code v1} or {@code v2} is 270 * {@code null}. 271 * @since 3.2 272 */ 273 public ArrayFieldVector(FieldVector<T> v1, FieldVector<T> v2) 274 throws NullArgumentException { 275 NullArgumentException.check(v1); 276 NullArgumentException.check(v2); 277 field = v1.getField(); 278 final T[] v1Data = 279 (v1 instanceof ArrayFieldVector) ? ((ArrayFieldVector<T>) v1).data : v1.toArray(); 280 final T[] v2Data = 281 (v2 instanceof ArrayFieldVector) ? ((ArrayFieldVector<T>) v2).data : v2.toArray(); 282 data = MathArrays.buildArray(field, v1Data.length + v2Data.length); 283 System.arraycopy(v1Data, 0, data, 0, v1Data.length); 284 System.arraycopy(v2Data, 0, data, v1Data.length, v2Data.length); 285 } 286 287 /** 288 * Construct a vector by appending one vector to another vector. 289 * 290 * @param v1 First vector (will be put in front of the new vector). 291 * @param v2 Second vector (will be put at back of the new vector). 292 * @throws NullArgumentException if {@code v1} or {@code v2} is 293 * {@code null}. 294 * @since 3.2 295 */ 296 public ArrayFieldVector(FieldVector<T> v1, T[] v2) 297 throws NullArgumentException { 298 NullArgumentException.check(v1); 299 NullArgumentException.check(v2); 300 field = v1.getField(); 301 final T[] v1Data = 302 (v1 instanceof ArrayFieldVector) ? ((ArrayFieldVector<T>) v1).data : v1.toArray(); 303 data = MathArrays.buildArray(field, v1Data.length + v2.length); 304 System.arraycopy(v1Data, 0, data, 0, v1Data.length); 305 System.arraycopy(v2, 0, data, v1Data.length, v2.length); 306 } 307 308 /** 309 * Construct a vector by appending one vector to another vector. 310 * 311 * @param v1 First vector (will be put in front of the new vector). 312 * @param v2 Second vector (will be put at back of the new vector). 313 * @throws NullArgumentException if {@code v1} or {@code v2} is 314 * {@code null}. 315 * @since 3.2 316 */ 317 public ArrayFieldVector(T[] v1, FieldVector<T> v2) 318 throws NullArgumentException { 319 NullArgumentException.check(v1); 320 NullArgumentException.check(v2); 321 field = v2.getField(); 322 final T[] v2Data = 323 (v2 instanceof ArrayFieldVector) ? ((ArrayFieldVector<T>) v2).data : v2.toArray(); 324 data = MathArrays.buildArray(field, v1.length + v2Data.length); 325 System.arraycopy(v1, 0, data, 0, v1.length); 326 System.arraycopy(v2Data, 0, data, v1.length, v2Data.length); 327 } 328 329 /** 330 * Construct a vector by appending one vector to another vector. 331 * This constructor needs at least one non-empty array to retrieve 332 * the field from its first element. This implies it cannot build 333 * 0 length vectors. To build vectors from any size, one should 334 * use the {@link #ArrayFieldVector(Field, FieldElement[], FieldElement[])} 335 * constructor. 336 * 337 * @param v1 First vector (will be put in front of the new vector). 338 * @param v2 Second vector (will be put at back of the new vector). 339 * @throws NullArgumentException if {@code v1} or {@code v2} is 340 * {@code null}. 341 * @throws ZeroException if both arrays are empty. 342 * @see #ArrayFieldVector(Field, FieldElement[], FieldElement[]) 343 */ 344 public ArrayFieldVector(T[] v1, T[] v2) 345 throws NullArgumentException, ZeroException { 346 NullArgumentException.check(v1); 347 NullArgumentException.check(v2); 348 if (v1.length + v2.length == 0) { 349 throw new ZeroException(LocalizedFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT); 350 } 351 data = MathArrays.buildArray(v1[0].getField(), v1.length + v2.length); 352 System.arraycopy(v1, 0, data, 0, v1.length); 353 System.arraycopy(v2, 0, data, v1.length, v2.length); 354 field = data[0].getField(); 355 } 356 357 /** 358 * Construct a vector by appending one vector to another vector. 359 * 360 * @param field Field to which the elements belong. 361 * @param v1 First vector (will be put in front of the new vector). 362 * @param v2 Second vector (will be put at back of the new vector). 363 * @throws NullArgumentException if {@code v1} or {@code v2} is 364 * {@code null}. 365 * @throws ZeroException if both arrays are empty. 366 * @see #ArrayFieldVector(FieldElement[], FieldElement[]) 367 */ 368 public ArrayFieldVector(Field<T> field, T[] v1, T[] v2) 369 throws NullArgumentException, ZeroException { 370 NullArgumentException.check(v1); 371 NullArgumentException.check(v2); 372 if (v1.length + v2.length == 0) { 373 throw new ZeroException(LocalizedFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT); 374 } 375 data = MathArrays.buildArray(field, v1.length + v2.length); 376 System.arraycopy(v1, 0, data, 0, v1.length); 377 System.arraycopy(v2, 0, data, v1.length, v2.length); 378 this.field = field; 379 } 380 381 /** {@inheritDoc} */ 382 @Override 383 public Field<T> getField() { 384 return field; 385 } 386 387 /** {@inheritDoc} */ 388 @Override 389 public FieldVector<T> copy() { 390 return new ArrayFieldVector<>(this, true); 391 } 392 393 /** {@inheritDoc} */ 394 @Override 395 public FieldVector<T> add(FieldVector<T> v) 396 throws DimensionMismatchException { 397 if (v instanceof ArrayFieldVector) { 398 return add((ArrayFieldVector<T>) v); 399 } 400 401 checkVectorDimensions(v); 402 T[] out = MathArrays.buildArray(field, data.length); 403 for (int i = 0; i < data.length; i++) { 404 out[i] = data[i].add(v.getEntry(i)); 405 } 406 return new ArrayFieldVector<>(field, out, false); 407 } 408 409 /** 410 * Compute the sum of {@code this} and {@code v}. 411 * @param v vector to be added 412 * @return {@code this + v} 413 * @throws DimensionMismatchException if {@code v} is not the same size as 414 * {@code this} 415 */ 416 public ArrayFieldVector<T> add(ArrayFieldVector<T> v) 417 throws DimensionMismatchException { 418 checkVectorDimensions(v.data.length); 419 T[] out = MathArrays.buildArray(field, data.length); 420 for (int i = 0; i < data.length; i++) { 421 out[i] = data[i].add(v.data[i]); 422 } 423 return new ArrayFieldVector<>(field, out, false); 424 } 425 426 /** {@inheritDoc} */ 427 @Override 428 public FieldVector<T> subtract(FieldVector<T> v) 429 throws DimensionMismatchException { 430 if (v instanceof ArrayFieldVector) { 431 return subtract((ArrayFieldVector<T>) v); 432 } 433 434 checkVectorDimensions(v); 435 T[] out = MathArrays.buildArray(field, data.length); 436 for (int i = 0; i < data.length; i++) { 437 out[i] = data[i].subtract(v.getEntry(i)); 438 } 439 return new ArrayFieldVector<>(field, out, false); 440 } 441 442 /** 443 * Compute {@code this} minus {@code v}. 444 * @param v vector to be subtracted 445 * @return {@code this - v} 446 * @throws DimensionMismatchException if {@code v} is not the same size as 447 * {@code this} 448 */ 449 public ArrayFieldVector<T> subtract(ArrayFieldVector<T> v) 450 throws DimensionMismatchException { 451 checkVectorDimensions(v.data.length); 452 T[] out = MathArrays.buildArray(field, data.length); 453 for (int i = 0; i < data.length; i++) { 454 out[i] = data[i].subtract(v.data[i]); 455 } 456 return new ArrayFieldVector<>(field, out, false); 457 } 458 459 /** {@inheritDoc} */ 460 @Override 461 public FieldVector<T> mapAdd(T d) throws NullArgumentException { 462 T[] out = MathArrays.buildArray(field, data.length); 463 for (int i = 0; i < data.length; i++) { 464 out[i] = data[i].add(d); 465 } 466 return new ArrayFieldVector<>(field, out, false); 467 } 468 469 /** {@inheritDoc} */ 470 @Override 471 public FieldVector<T> mapAddToSelf(T d) throws NullArgumentException { 472 for (int i = 0; i < data.length; i++) { 473 data[i] = data[i].add(d); 474 } 475 return this; 476 } 477 478 /** {@inheritDoc} */ 479 @Override 480 public FieldVector<T> mapSubtract(T d) throws NullArgumentException { 481 T[] out = MathArrays.buildArray(field, data.length); 482 for (int i = 0; i < data.length; i++) { 483 out[i] = data[i].subtract(d); 484 } 485 return new ArrayFieldVector<>(field, out, false); 486 } 487 488 /** {@inheritDoc} */ 489 @Override 490 public FieldVector<T> mapSubtractToSelf(T d) throws NullArgumentException { 491 for (int i = 0; i < data.length; i++) { 492 data[i] = data[i].subtract(d); 493 } 494 return this; 495 } 496 497 /** {@inheritDoc} */ 498 @Override 499 public FieldVector<T> mapMultiply(T d) throws NullArgumentException { 500 T[] out = MathArrays.buildArray(field, data.length); 501 for (int i = 0; i < data.length; i++) { 502 out[i] = data[i].multiply(d); 503 } 504 return new ArrayFieldVector<>(field, out, false); 505 } 506 507 /** {@inheritDoc} */ 508 @Override 509 public FieldVector<T> mapMultiplyToSelf(T d) throws NullArgumentException { 510 for (int i = 0; i < data.length; i++) { 511 data[i] = data[i].multiply(d); 512 } 513 return this; 514 } 515 516 /** {@inheritDoc} */ 517 @Override 518 public FieldVector<T> mapDivide(T d) 519 throws NullArgumentException, MathArithmeticException { 520 NullArgumentException.check(d); 521 T[] out = MathArrays.buildArray(field, data.length); 522 for (int i = 0; i < data.length; i++) { 523 out[i] = data[i].divide(d); 524 } 525 return new ArrayFieldVector<>(field, out, false); 526 } 527 528 /** {@inheritDoc} */ 529 @Override 530 public FieldVector<T> mapDivideToSelf(T d) 531 throws NullArgumentException, MathArithmeticException { 532 NullArgumentException.check(d); 533 for (int i = 0; i < data.length; i++) { 534 data[i] = data[i].divide(d); 535 } 536 return this; 537 } 538 539 /** {@inheritDoc} */ 540 @Override 541 public FieldVector<T> mapInv() throws MathArithmeticException { 542 T[] out = MathArrays.buildArray(field, data.length); 543 final T one = field.getOne(); 544 for (int i = 0; i < data.length; i++) { 545 try { 546 out[i] = one.divide(data[i]); 547 } catch (final MathArithmeticException e) { 548 throw new MathArithmeticException(LocalizedFormats.INDEX, i); 549 } 550 } 551 return new ArrayFieldVector<>(field, out, false); 552 } 553 554 /** {@inheritDoc} */ 555 @Override 556 public FieldVector<T> mapInvToSelf() throws MathArithmeticException { 557 final T one = field.getOne(); 558 for (int i = 0; i < data.length; i++) { 559 try { 560 data[i] = one.divide(data[i]); 561 } catch (final MathArithmeticException e) { 562 throw new MathArithmeticException(LocalizedFormats.INDEX, i); 563 } 564 } 565 return this; 566 } 567 568 /** {@inheritDoc} */ 569 @Override 570 public FieldVector<T> ebeMultiply(FieldVector<T> v) 571 throws DimensionMismatchException { 572 if (v instanceof ArrayFieldVector) { 573 return ebeMultiply((ArrayFieldVector<T>) v); 574 } 575 576 checkVectorDimensions(v); 577 T[] out = MathArrays.buildArray(field, data.length); 578 for (int i = 0; i < data.length; i++) { 579 out[i] = data[i].multiply(v.getEntry(i)); 580 } 581 return new ArrayFieldVector<>(field, out, false); 582 } 583 584 /** 585 * Element-by-element multiplication. 586 * @param v vector by which instance elements must be multiplied 587 * @return a vector containing {@code this[i] * v[i]} for all {@code i} 588 * @throws DimensionMismatchException if {@code v} is not the same size as 589 * {@code this} 590 */ 591 public ArrayFieldVector<T> ebeMultiply(ArrayFieldVector<T> v) 592 throws DimensionMismatchException { 593 checkVectorDimensions(v.data.length); 594 T[] out = MathArrays.buildArray(field, data.length); 595 for (int i = 0; i < data.length; i++) { 596 out[i] = data[i].multiply(v.data[i]); 597 } 598 return new ArrayFieldVector<>(field, out, false); 599 } 600 601 /** {@inheritDoc} */ 602 @Override 603 public FieldVector<T> ebeDivide(FieldVector<T> v) 604 throws DimensionMismatchException, MathArithmeticException { 605 if (v instanceof ArrayFieldVector) { 606 return ebeDivide((ArrayFieldVector<T>) v); 607 } 608 609 checkVectorDimensions(v); 610 T[] out = MathArrays.buildArray(field, data.length); 611 for (int i = 0; i < data.length; i++) { 612 try { 613 out[i] = data[i].divide(v.getEntry(i)); 614 } catch (final MathArithmeticException e) { 615 throw new MathArithmeticException(LocalizedFormats.INDEX, i); 616 } 617 } 618 return new ArrayFieldVector<>(field, out, false); 619 } 620 621 /** 622 * Element-by-element division. 623 * @param v vector by which instance elements must be divided 624 * @return a vector containing {@code this[i] / v[i]} for all {@code i} 625 * @throws DimensionMismatchException if {@code v} is not the same size as 626 * {@code this} 627 * @throws MathArithmeticException if one entry of {@code v} is zero. 628 */ 629 public ArrayFieldVector<T> ebeDivide(ArrayFieldVector<T> v) 630 throws DimensionMismatchException, MathArithmeticException { 631 checkVectorDimensions(v.data.length); 632 T[] out = MathArrays.buildArray(field, data.length); 633 for (int i = 0; i < data.length; i++) { 634 try { 635 out[i] = data[i].divide(v.data[i]); 636 } catch (final MathArithmeticException e) { 637 throw new MathArithmeticException(LocalizedFormats.INDEX, i); 638 } 639 } 640 return new ArrayFieldVector<>(field, out, false); 641 } 642 643 /** 644 * Returns a reference to the underlying data array. 645 * <p>Does not make a fresh copy of the underlying data.</p> 646 * @return array of entries 647 */ 648 public T[] getDataRef() { 649 return data; 650 } 651 652 /** {@inheritDoc} */ 653 @Override 654 public T dotProduct(FieldVector<T> v) 655 throws DimensionMismatchException { 656 if (v instanceof ArrayFieldVector) { 657 return dotProduct((ArrayFieldVector<T>) v); 658 } 659 660 checkVectorDimensions(v); 661 T dot = field.getZero(); 662 for (int i = 0; i < data.length; i++) { 663 dot = dot.add(data[i].multiply(v.getEntry(i))); 664 } 665 return dot; 666 } 667 668 /** 669 * Compute the dot product. 670 * @param v vector with which dot product should be computed 671 * @return the scalar dot product of {@code this} and {@code v} 672 * @throws DimensionMismatchException if {@code v} is not the same size as 673 * {@code this} 674 */ 675 public T dotProduct(ArrayFieldVector<T> v) 676 throws DimensionMismatchException { 677 checkVectorDimensions(v.data.length); 678 T dot = field.getZero(); 679 for (int i = 0; i < data.length; i++) { 680 dot = dot.add(data[i].multiply(v.data[i])); 681 } 682 return dot; 683 } 684 685 /** {@inheritDoc} */ 686 @Override 687 public FieldVector<T> projection(FieldVector<T> v) 688 throws DimensionMismatchException, MathArithmeticException { 689 return v.mapMultiply(dotProduct(v).divide(v.dotProduct(v))); 690 } 691 692 /** Find the orthogonal projection of this vector onto another vector. 693 * @param v vector onto which {@code this} must be projected 694 * @return projection of {@code this} onto {@code v} 695 * @throws DimensionMismatchException if {@code v} is not the same size as 696 * {@code this} 697 * @throws MathArithmeticException if {@code v} is the null vector. 698 */ 699 public ArrayFieldVector<T> projection(ArrayFieldVector<T> v) 700 throws DimensionMismatchException, MathArithmeticException { 701 return (ArrayFieldVector<T>) v.mapMultiply(dotProduct(v).divide(v.dotProduct(v))); 702 } 703 704 /** {@inheritDoc} */ 705 @Override 706 public FieldMatrix<T> outerProduct(FieldVector<T> v) { 707 if (v instanceof ArrayFieldVector) { 708 return outerProduct((ArrayFieldVector<T>) v); 709 } 710 711 final int m = data.length; 712 final int n = v.getDimension(); 713 final FieldMatrix<T> out = new Array2DRowFieldMatrix<>(field, m, n); 714 for (int i = 0; i < m; i++) { 715 for (int j = 0; j < n; j++) { 716 out.setEntry(i, j, data[i].multiply(v.getEntry(j))); 717 } 718 } 719 return out; 720 } 721 722 /** 723 * Compute the outer product. 724 * @param v vector with which outer product should be computed 725 * @return the matrix outer product between instance and v 726 */ 727 public FieldMatrix<T> outerProduct(ArrayFieldVector<T> v) { 728 final int m = data.length; 729 final int n = v.data.length; 730 final FieldMatrix<T> out = new Array2DRowFieldMatrix<>(field, m, n); 731 for (int i = 0; i < m; i++) { 732 for (int j = 0; j < n; j++) { 733 out.setEntry(i, j, data[i].multiply(v.data[j])); 734 } 735 } 736 return out; 737 } 738 739 /** {@inheritDoc} */ 740 @Override 741 public T getEntry(int index) { 742 return data[index]; 743 } 744 745 /** {@inheritDoc} */ 746 @Override 747 public int getDimension() { 748 return data.length; 749 } 750 751 /** {@inheritDoc} */ 752 @Override 753 public FieldVector<T> append(FieldVector<T> v) { 754 if (v instanceof ArrayFieldVector) { 755 return append((ArrayFieldVector<T>) v); 756 } 757 758 return new ArrayFieldVector<>(this,new ArrayFieldVector<>(v)); 759 } 760 761 /** 762 * Construct a vector by appending a vector to this vector. 763 * @param v vector to append to this one. 764 * @return a new vector 765 */ 766 public ArrayFieldVector<T> append(ArrayFieldVector<T> v) { 767 return new ArrayFieldVector<>(this, v); 768 } 769 770 /** {@inheritDoc} */ 771 @Override 772 public FieldVector<T> append(T in) { 773 final T[] out = MathArrays.buildArray(field, data.length + 1); 774 System.arraycopy(data, 0, out, 0, data.length); 775 out[data.length] = in; 776 return new ArrayFieldVector<>(field, out, false); 777 } 778 779 /** {@inheritDoc} */ 780 @Override 781 public FieldVector<T> getSubVector(int index, int n) 782 throws OutOfRangeException, NotPositiveException { 783 if (n < 0) { 784 throw new NotPositiveException(LocalizedFormats.NUMBER_OF_ELEMENTS_SHOULD_BE_POSITIVE, n); 785 } 786 ArrayFieldVector<T> out = new ArrayFieldVector<>(field, n); 787 try { 788 System.arraycopy(data, index, out.data, 0, n); 789 } catch (IndexOutOfBoundsException e) { 790 checkIndex(index); 791 checkIndex(index + n - 1); 792 } 793 return out; 794 } 795 796 /** {@inheritDoc} */ 797 @Override 798 public void setEntry(int index, T value) { 799 try { 800 data[index] = value; 801 } catch (IndexOutOfBoundsException e) { 802 checkIndex(index); 803 } 804 } 805 806 /** {@inheritDoc} */ 807 @Override 808 public void setSubVector(int index, FieldVector<T> v) throws OutOfRangeException { 809 try { 810 if (v instanceof ArrayFieldVector) { 811 set(index, (ArrayFieldVector<T>) v); 812 } else { 813 for (int i = index; i < index + v.getDimension(); ++i) { 814 data[i] = v.getEntry(i-index); 815 } 816 } 817 } catch (IndexOutOfBoundsException e) { 818 checkIndex(index); 819 checkIndex(index + v.getDimension() - 1); 820 } 821 } 822 823 /** 824 * Set a set of consecutive elements. 825 * 826 * @param index index of first element to be set. 827 * @param v vector containing the values to set. 828 * @throws OutOfRangeException if the index is invalid. 829 */ 830 public void set(int index, ArrayFieldVector<T> v) throws OutOfRangeException { 831 try { 832 System.arraycopy(v.data, 0, data, index, v.data.length); 833 } catch (IndexOutOfBoundsException e) { 834 checkIndex(index); 835 checkIndex(index + v.data.length - 1); 836 } 837 } 838 839 /** {@inheritDoc} */ 840 @Override 841 public void set(T value) { 842 Arrays.fill(data, value); 843 } 844 845 /** {@inheritDoc} */ 846 @Override 847 public T[] toArray(){ 848 return data.clone(); 849 } 850 851 /** 852 * Check if instance and specified vectors have the same dimension. 853 * @param v vector to compare instance with 854 * @exception DimensionMismatchException if the vectors do not 855 * have the same dimensions 856 */ 857 protected void checkVectorDimensions(FieldVector<T> v) 858 throws DimensionMismatchException { 859 checkVectorDimensions(v.getDimension()); 860 } 861 862 /** 863 * Check if instance dimension is equal to some expected value. 864 * 865 * @param n Expected dimension. 866 * @throws DimensionMismatchException if the dimension is not equal to the 867 * size of {@code this} vector. 868 */ 869 protected void checkVectorDimensions(int n) 870 throws DimensionMismatchException { 871 if (data.length != n) { 872 throw new DimensionMismatchException(data.length, n); 873 } 874 } 875 876 /** 877 * Visits (but does not alter) all entries of this vector in default order 878 * (increasing index). 879 * 880 * @param visitor the visitor to be used to process the entries of this 881 * vector 882 * @return the value returned by {@link FieldVectorPreservingVisitor#end()} 883 * at the end of the walk 884 * @since 3.3 885 */ 886 public T walkInDefaultOrder(final FieldVectorPreservingVisitor<T> visitor) { 887 final int dim = getDimension(); 888 visitor.start(dim, 0, dim - 1); 889 for (int i = 0; i < dim; i++) { 890 visitor.visit(i, getEntry(i)); 891 } 892 return visitor.end(); 893 } 894 895 /** 896 * Visits (but does not alter) some entries of this vector in default order 897 * (increasing index). 898 * 899 * @param visitor visitor to be used to process the entries of this vector 900 * @param start the index of the first entry to be visited 901 * @param end the index of the last entry to be visited (inclusive) 902 * @return the value returned by {@link FieldVectorPreservingVisitor#end()} 903 * at the end of the walk 904 * @throws NumberIsTooSmallException if {@code end < start}. 905 * @throws OutOfRangeException if the indices are not valid. 906 * @since 3.3 907 */ 908 public T walkInDefaultOrder(final FieldVectorPreservingVisitor<T> visitor, 909 final int start, final int end) 910 throws NumberIsTooSmallException, OutOfRangeException { 911 checkIndices(start, end); 912 visitor.start(getDimension(), start, end); 913 for (int i = start; i <= end; i++) { 914 visitor.visit(i, getEntry(i)); 915 } 916 return visitor.end(); 917 } 918 919 /** 920 * Visits (but does not alter) all entries of this vector in optimized 921 * order. The order in which the entries are visited is selected so as to 922 * lead to the most efficient implementation; it might depend on the 923 * concrete implementation of this abstract class. 924 * 925 * @param visitor the visitor to be used to process the entries of this 926 * vector 927 * @return the value returned by {@link FieldVectorPreservingVisitor#end()} 928 * at the end of the walk 929 * @since 3.3 930 */ 931 public T walkInOptimizedOrder(final FieldVectorPreservingVisitor<T> visitor) { 932 return walkInDefaultOrder(visitor); 933 } 934 935 /** 936 * Visits (but does not alter) some entries of this vector in optimized 937 * order. The order in which the entries are visited is selected so as to 938 * lead to the most efficient implementation; it might depend on the 939 * concrete implementation of this abstract class. 940 * 941 * @param visitor visitor to be used to process the entries of this vector 942 * @param start the index of the first entry to be visited 943 * @param end the index of the last entry to be visited (inclusive) 944 * @return the value returned by {@link FieldVectorPreservingVisitor#end()} 945 * at the end of the walk 946 * @throws NumberIsTooSmallException if {@code end < start}. 947 * @throws OutOfRangeException if the indices are not valid. 948 * @since 3.3 949 */ 950 public T walkInOptimizedOrder(final FieldVectorPreservingVisitor<T> visitor, 951 final int start, final int end) 952 throws NumberIsTooSmallException, OutOfRangeException { 953 return walkInDefaultOrder(visitor, start, end); 954 } 955 956 /** 957 * Visits (and possibly alters) all entries of this vector in default order 958 * (increasing index). 959 * 960 * @param visitor the visitor to be used to process and modify the entries 961 * of this vector 962 * @return the value returned by {@link FieldVectorChangingVisitor#end()} 963 * at the end of the walk 964 * @since 3.3 965 */ 966 public T walkInDefaultOrder(final FieldVectorChangingVisitor<T> visitor) { 967 final int dim = getDimension(); 968 visitor.start(dim, 0, dim - 1); 969 for (int i = 0; i < dim; i++) { 970 setEntry(i, visitor.visit(i, getEntry(i))); 971 } 972 return visitor.end(); 973 } 974 975 /** 976 * Visits (and possibly alters) some entries of this vector in default order 977 * (increasing index). 978 * 979 * @param visitor visitor to be used to process the entries of this vector 980 * @param start the index of the first entry to be visited 981 * @param end the index of the last entry to be visited (inclusive) 982 * @return the value returned by {@link FieldVectorChangingVisitor#end()} 983 * at the end of the walk 984 * @throws NumberIsTooSmallException if {@code end < start}. 985 * @throws OutOfRangeException if the indices are not valid. 986 * @since 3.3 987 */ 988 public T walkInDefaultOrder(final FieldVectorChangingVisitor<T> visitor, 989 final int start, final int end) 990 throws NumberIsTooSmallException, OutOfRangeException { 991 checkIndices(start, end); 992 visitor.start(getDimension(), start, end); 993 for (int i = start; i <= end; i++) { 994 setEntry(i, visitor.visit(i, getEntry(i))); 995 } 996 return visitor.end(); 997 } 998 999 /** 1000 * Visits (and possibly alters) all entries of this vector in optimized 1001 * order. The order in which the entries are visited is selected so as to 1002 * lead to the most efficient implementation; it might depend on the 1003 * concrete implementation of this abstract class. 1004 * 1005 * @param visitor the visitor to be used to process the entries of this 1006 * vector 1007 * @return the value returned by {@link FieldVectorChangingVisitor#end()} 1008 * at the end of the walk 1009 * @since 3.3 1010 */ 1011 public T walkInOptimizedOrder(final FieldVectorChangingVisitor<T> visitor) { 1012 return walkInDefaultOrder(visitor); 1013 } 1014 1015 /** 1016 * Visits (and possibly change) some entries of this vector in optimized 1017 * order. The order in which the entries are visited is selected so as to 1018 * lead to the most efficient implementation; it might depend on the 1019 * concrete implementation of this abstract class. 1020 * 1021 * @param visitor visitor to be used to process the entries of this vector 1022 * @param start the index of the first entry to be visited 1023 * @param end the index of the last entry to be visited (inclusive) 1024 * @return the value returned by {@link FieldVectorChangingVisitor#end()} 1025 * at the end of the walk 1026 * @throws NumberIsTooSmallException if {@code end < start}. 1027 * @throws OutOfRangeException if the indices are not valid. 1028 * @since 3.3 1029 */ 1030 public T walkInOptimizedOrder(final FieldVectorChangingVisitor<T> visitor, 1031 final int start, final int end) 1032 throws NumberIsTooSmallException, OutOfRangeException { 1033 return walkInDefaultOrder(visitor, start, end); 1034 } 1035 1036 /** 1037 * Test for the equality of two vectors. 1038 * 1039 * @param other Object to test for equality. 1040 * @return {@code true} if two vector objects are equal, {@code false} 1041 * otherwise. 1042 */ 1043 @Override 1044 public boolean equals(Object other) { 1045 if (this == other) { 1046 return true; 1047 } 1048 if (other == null) { 1049 return false; 1050 } 1051 1052 if (!(other instanceof FieldVector)) { 1053 return false; 1054 } 1055 1056 FieldVector rhs = (FieldVector) other; 1057 if (data.length != rhs.getDimension()) { 1058 return false; 1059 } 1060 1061 for (int i = 0; i < data.length; ++i) { 1062 if (!data[i].equals(rhs.getEntry(i))) { 1063 return false; 1064 } 1065 } 1066 return true; 1067 } 1068 1069 /** 1070 * Get a hashCode for the real vector. 1071 * <p>All NaN values have the same hash code.</p> 1072 * @return a hash code value for this object 1073 */ 1074 @Override 1075 public int hashCode() { 1076 int h = 3542; 1077 for (final T a : data) { 1078 h ^= a.hashCode(); 1079 } 1080 return h; 1081 } 1082 1083 /** 1084 * Check if an index is valid. 1085 * 1086 * @param index Index to check. 1087 * @exception OutOfRangeException if the index is not valid. 1088 */ 1089 private void checkIndex(final int index) throws OutOfRangeException { 1090 if (index < 0 || index >= getDimension()) { 1091 throw new OutOfRangeException(LocalizedFormats.INDEX, 1092 index, 0, getDimension() - 1); 1093 } 1094 } 1095 1096 /** 1097 * Checks that the indices of a subvector are valid. 1098 * 1099 * @param start the index of the first entry of the subvector 1100 * @param end the index of the last entry of the subvector (inclusive) 1101 * @throws OutOfRangeException if {@code start} of {@code end} are not valid 1102 * @throws NumberIsTooSmallException if {@code end < start} 1103 * @since 3.3 1104 */ 1105 private void checkIndices(final int start, final int end) 1106 throws NumberIsTooSmallException, OutOfRangeException { 1107 final int dim = getDimension(); 1108 if (start < 0 || start >= dim) { 1109 throw new OutOfRangeException(LocalizedFormats.INDEX, start, 0, 1110 dim - 1); 1111 } 1112 if (end < 0 || end >= dim) { 1113 throw new OutOfRangeException(LocalizedFormats.INDEX, end, 0, 1114 dim - 1); 1115 } 1116 if (end < start) { 1117 throw new NumberIsTooSmallException(LocalizedFormats.INITIAL_ROW_AFTER_FINAL_ROW, 1118 end, start, false); 1119 } 1120 } 1121}