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