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 * https://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
18 /*
19 * This is not the original file distributed by the Apache Software Foundation
20 * It has been modified by the Hipparchus project
21 */
22 package org.hipparchus.linear;
23
24 import java.io.Serializable;
25 import java.util.Arrays;
26
27 import org.hipparchus.Field;
28 import org.hipparchus.FieldElement;
29 import org.hipparchus.exception.LocalizedCoreFormats;
30 import org.hipparchus.exception.MathIllegalArgumentException;
31 import org.hipparchus.exception.MathRuntimeException;
32 import org.hipparchus.exception.NullArgumentException;
33 import org.hipparchus.util.MathArrays;
34 import org.hipparchus.util.MathUtils;
35
36 /**
37 * This class implements the {@link FieldVector} interface with a {@link FieldElement} array.
38 * @param <T> the type of the field elements
39 */
40 public class ArrayFieldVector<T extends FieldElement<T>> implements FieldVector<T>, Serializable {
41 /** Serializable version identifier. */
42 private static final long serialVersionUID = 7648186910365927050L;
43
44 /** Entries of the vector. */
45 private T[] data;
46
47 /** Field to which the elements belong. */
48 private final Field<T> field;
49
50 /**
51 * Build a 0-length vector.
52 * Zero-length vectors may be used to initialize construction of vectors
53 * by data gathering. We start with zero-length and use either the {@link
54 * #ArrayFieldVector(FieldVector, FieldVector)} constructor
55 * or one of the {@code append} methods ({@link #add(FieldVector)} or
56 * {@link #append(ArrayFieldVector)}) to gather data into this vector.
57 *
58 * @param field field to which the elements belong
59 */
60 public ArrayFieldVector(final Field<T> field) {
61 this(field, 0);
62 }
63
64 /**
65 * Construct a vector of zeroes.
66 *
67 * @param field Field to which the elements belong.
68 * @param size Size of the vector.
69 */
70 public ArrayFieldVector(Field<T> field, int size) {
71 this.field = field;
72 this.data = MathArrays.buildArray(field, size);
73 }
74
75 /**
76 * Construct a vector with preset values.
77 *
78 * @param size Size of the vector.
79 * @param preset All entries will be set with this value.
80 */
81 public ArrayFieldVector(int size, T preset) {
82 this(preset.getField(), size);
83 Arrays.fill(data, preset);
84 }
85
86 /**
87 * Construct a vector from an array, copying the input array.
88 * This constructor needs a non-empty {@code d} array to retrieve
89 * the field from its first element. This implies it cannot build
90 * 0 length vectors. To build vectors from any size, one should
91 * use the {@link #ArrayFieldVector(Field, FieldElement[])} constructor.
92 *
93 * @param d Array.
94 * @throws NullArgumentException if {@code d} is {@code null}.
95 * @throws MathIllegalArgumentException if {@code d} is empty.
96 * @see #ArrayFieldVector(Field, FieldElement[])
97 */
98 public ArrayFieldVector(T[] d)
99 throws MathIllegalArgumentException, NullArgumentException {
100 MathUtils.checkNotNull(d);
101 try {
102 field = d[0].getField();
103 data = d.clone();
104 } catch (ArrayIndexOutOfBoundsException e) {
105 throw new MathIllegalArgumentException(e, LocalizedCoreFormats.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 MathUtils.checkNotNull(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 MathIllegalArgumentException 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 MathIllegalArgumentException, NullArgumentException {
147 MathUtils.checkNotNull(d);
148 if (d.length == 0) {
149 throw new MathIllegalArgumentException(LocalizedCoreFormats.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 MathUtils.checkNotNull(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 MathIllegalArgumentException 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 MathIllegalArgumentException, NullArgumentException {
189 MathUtils.checkNotNull(d);
190 if (d.length < pos + size) {
191 throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_LARGE,
192 pos + size, d.length);
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 MathIllegalArgumentException 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 MathIllegalArgumentException, NullArgumentException {
212 MathUtils.checkNotNull(d);
213 if (d.length < pos + size) {
214 throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_LARGE,
215 pos + size, d.length);
216 }
217 this.field = field;
218 data = MathArrays.buildArray(field, size);
219 System.arraycopy(d, pos, data, 0, size);
220 }
221
222 /**
223 * Construct a vector from another vector, using a deep copy.
224 *
225 * @param v Vector to copy.
226 * @throws NullArgumentException if {@code v} is {@code null}.
227 */
228 public ArrayFieldVector(FieldVector<T> v)
229 throws NullArgumentException {
230 MathUtils.checkNotNull(v);
231 field = v.getField();
232 data = MathArrays.buildArray(field, v.getDimension());
233 for (int i = 0; i < data.length; ++i) {
234 data[i] = v.getEntry(i);
235 }
236 }
237
238 /**
239 * Construct a vector from another vector, using a deep copy.
240 *
241 * @param v Vector to copy.
242 * @throws NullArgumentException if {@code v} is {@code null}.
243 */
244 public ArrayFieldVector(ArrayFieldVector<T> v)
245 throws NullArgumentException {
246 MathUtils.checkNotNull(v);
247 field = v.getField();
248 data = v.data.clone();
249 }
250
251 /**
252 * Construct a vector from another vector.
253 *
254 * @param v Vector to copy.
255 * @param deep If {@code true} perform a deep copy, otherwise perform
256 * a shallow copy
257 * @throws NullArgumentException if {@code v} is {@code null}.
258 */
259 public ArrayFieldVector(ArrayFieldVector<T> v, boolean deep)
260 throws NullArgumentException {
261 MathUtils.checkNotNull(v);
262 field = v.getField();
263 data = deep ? v.data.clone() : v.data;
264 }
265
266 /**
267 * Construct a vector by appending one vector to another vector.
268 *
269 * @param v1 First vector (will be put in front of the new vector).
270 * @param v2 Second vector (will be put at back of the new vector).
271 * @throws NullArgumentException if {@code v1} or {@code v2} is
272 * {@code null}.
273 */
274 public ArrayFieldVector(FieldVector<T> v1, FieldVector<T> v2)
275 throws NullArgumentException {
276 MathUtils.checkNotNull(v1);
277 MathUtils.checkNotNull(v2);
278 field = v1.getField();
279 final T[] v1Data =
280 (v1 instanceof ArrayFieldVector) ? ((ArrayFieldVector<T>) v1).data : v1.toArray();
281 final T[] v2Data =
282 (v2 instanceof ArrayFieldVector) ? ((ArrayFieldVector<T>) v2).data : v2.toArray();
283 data = MathArrays.buildArray(field, v1Data.length + v2Data.length);
284 System.arraycopy(v1Data, 0, data, 0, v1Data.length);
285 System.arraycopy(v2Data, 0, data, v1Data.length, v2Data.length);
286 }
287
288 /**
289 * Construct a vector by appending one vector to another vector.
290 *
291 * @param v1 First vector (will be put in front of the new vector).
292 * @param v2 Second vector (will be put at back of the new vector).
293 * @throws NullArgumentException if {@code v1} or {@code v2} is
294 * {@code null}.
295 */
296 public ArrayFieldVector(FieldVector<T> v1, T[] v2)
297 throws NullArgumentException {
298 MathUtils.checkNotNull(v1);
299 MathUtils.checkNotNull(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 */
316 public ArrayFieldVector(T[] v1, FieldVector<T> v2)
317 throws NullArgumentException {
318 MathUtils.checkNotNull(v1);
319 MathUtils.checkNotNull(v2);
320 field = v2.getField();
321 final T[] v2Data =
322 (v2 instanceof ArrayFieldVector) ? ((ArrayFieldVector<T>) v2).data : v2.toArray();
323 data = MathArrays.buildArray(field, v1.length + v2Data.length);
324 System.arraycopy(v1, 0, data, 0, v1.length);
325 System.arraycopy(v2Data, 0, data, v1.length, v2Data.length);
326 }
327
328 /**
329 * Construct a vector by appending one vector to another vector.
330 * This constructor needs at least one non-empty array to retrieve
331 * the field from its first element. This implies it cannot build
332 * 0 length vectors. To build vectors from any size, one should
333 * use the {@link #ArrayFieldVector(Field, FieldElement[], FieldElement[])}
334 * constructor.
335 *
336 * @param v1 First vector (will be put in front of the new vector).
337 * @param v2 Second vector (will be put at back of the new vector).
338 * @throws NullArgumentException if {@code v1} or {@code v2} is
339 * {@code null}.
340 * @throws MathIllegalArgumentException if both arrays are empty.
341 * @see #ArrayFieldVector(Field, FieldElement[], FieldElement[])
342 */
343 public ArrayFieldVector(T[] v1, T[] v2)
344 throws MathIllegalArgumentException, NullArgumentException {
345 MathUtils.checkNotNull(v1);
346 MathUtils.checkNotNull(v2);
347 if (v1.length + v2.length == 0) {
348 throw new MathIllegalArgumentException(LocalizedCoreFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT);
349 }
350 data = MathArrays.buildArray(v1[0].getField(), v1.length + v2.length);
351 System.arraycopy(v1, 0, data, 0, v1.length);
352 System.arraycopy(v2, 0, data, v1.length, v2.length);
353 field = data[0].getField();
354 }
355
356 /**
357 * Construct a vector by appending one vector to another vector.
358 *
359 * @param field Field to which the elements belong.
360 * @param v1 First vector (will be put in front of the new vector).
361 * @param v2 Second vector (will be put at back of the new vector).
362 * @throws NullArgumentException if {@code v1} or {@code v2} is
363 * {@code null}.
364 * @throws MathIllegalArgumentException if both arrays are empty.
365 * @see #ArrayFieldVector(FieldElement[], FieldElement[])
366 */
367 public ArrayFieldVector(Field<T> field, T[] v1, T[] v2)
368 throws MathIllegalArgumentException, NullArgumentException {
369 MathUtils.checkNotNull(v1);
370 MathUtils.checkNotNull(v2);
371 if (v1.length + v2.length == 0) {
372 throw new MathIllegalArgumentException(LocalizedCoreFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT);
373 }
374 data = MathArrays.buildArray(field, v1.length + v2.length);
375 System.arraycopy(v1, 0, data, 0, v1.length);
376 System.arraycopy(v2, 0, data, v1.length, v2.length);
377 this.field = field;
378 }
379
380 /** {@inheritDoc} */
381 @Override
382 public Field<T> getField() {
383 return field;
384 }
385
386 /** {@inheritDoc} */
387 @Override
388 public FieldVector<T> copy() {
389 return new ArrayFieldVector<>(this, true);
390 }
391
392 /** {@inheritDoc} */
393 @Override
394 public FieldVector<T> add(FieldVector<T> v)
395 throws MathIllegalArgumentException {
396 if (v instanceof ArrayFieldVector) {
397 return add((ArrayFieldVector<T>) v);
398 } else {
399 checkVectorDimensions(v);
400 T[] out = MathArrays.buildArray(field, data.length);
401 for (int i = 0; i < data.length; i++) {
402 out[i] = data[i].add(v.getEntry(i));
403 }
404 return new ArrayFieldVector<>(field, out, false);
405 }
406 }
407
408 /**
409 * Compute the sum of {@code this} and {@code v}.
410 * @param v vector to be added
411 * @return {@code this + v}
412 * @throws MathIllegalArgumentException if {@code v} is not the same size as
413 * {@code this}
414 */
415 public ArrayFieldVector<T> add(ArrayFieldVector<T> v)
416 throws MathIllegalArgumentException {
417 checkVectorDimensions(v.data.length);
418 T[] out = MathArrays.buildArray(field, data.length);
419 for (int i = 0; i < data.length; i++) {
420 out[i] = data[i].add(v.data[i]);
421 }
422 return new ArrayFieldVector<>(field, out, false);
423 }
424
425 /** {@inheritDoc} */
426 @Override
427 public FieldVector<T> subtract(FieldVector<T> v)
428 throws MathIllegalArgumentException {
429 if (v instanceof ArrayFieldVector) {
430 return subtract((ArrayFieldVector<T>) v);
431 } else {
432 checkVectorDimensions(v);
433 T[] out = MathArrays.buildArray(field, data.length);
434 for (int i = 0; i < data.length; i++) {
435 out[i] = data[i].subtract(v.getEntry(i));
436 }
437 return new ArrayFieldVector<>(field, out, false);
438 }
439 }
440
441 /**
442 * Compute {@code this} minus {@code v}.
443 * @param v vector to be subtracted
444 * @return {@code this - v}
445 * @throws MathIllegalArgumentException if {@code v} is not the same size as
446 * {@code this}
447 */
448 public ArrayFieldVector<T> subtract(ArrayFieldVector<T> v)
449 throws MathIllegalArgumentException {
450 checkVectorDimensions(v.data.length);
451 T[] out = MathArrays.buildArray(field, data.length);
452 for (int i = 0; i < data.length; i++) {
453 out[i] = data[i].subtract(v.data[i]);
454 }
455 return new ArrayFieldVector<>(field, out, false);
456 }
457
458 /** {@inheritDoc} */
459 @Override
460 public FieldVector<T> mapAdd(T d) throws NullArgumentException {
461 T[] out = MathArrays.buildArray(field, data.length);
462 for (int i = 0; i < data.length; i++) {
463 out[i] = data[i].add(d);
464 }
465 return new ArrayFieldVector<>(field, out, false);
466 }
467
468 /** {@inheritDoc} */
469 @Override
470 public FieldVector<T> mapAddToSelf(T d) throws NullArgumentException {
471 for (int i = 0; i < data.length; i++) {
472 data[i] = data[i].add(d);
473 }
474 return this;
475 }
476
477 /** {@inheritDoc} */
478 @Override
479 public FieldVector<T> mapSubtract(T d) throws NullArgumentException {
480 T[] out = MathArrays.buildArray(field, data.length);
481 for (int i = 0; i < data.length; i++) {
482 out[i] = data[i].subtract(d);
483 }
484 return new ArrayFieldVector<>(field, out, false);
485 }
486
487 /** {@inheritDoc} */
488 @Override
489 public FieldVector<T> mapSubtractToSelf(T d) throws NullArgumentException {
490 for (int i = 0; i < data.length; i++) {
491 data[i] = data[i].subtract(d);
492 }
493 return this;
494 }
495
496 /** {@inheritDoc} */
497 @Override
498 public FieldVector<T> mapMultiply(T d) throws NullArgumentException {
499 T[] out = MathArrays.buildArray(field, data.length);
500 for (int i = 0; i < data.length; i++) {
501 out[i] = data[i].multiply(d);
502 }
503 return new ArrayFieldVector<>(field, out, false);
504 }
505
506 /** {@inheritDoc} */
507 @Override
508 public FieldVector<T> mapMultiplyToSelf(T d) throws NullArgumentException {
509 for (int i = 0; i < data.length; i++) {
510 data[i] = data[i].multiply(d);
511 }
512 return this;
513 }
514
515 /** {@inheritDoc} */
516 @Override
517 public FieldVector<T> mapDivide(T d)
518 throws NullArgumentException, MathRuntimeException {
519 MathUtils.checkNotNull(d);
520 T[] out = MathArrays.buildArray(field, data.length);
521 for (int i = 0; i < data.length; i++) {
522 out[i] = data[i].divide(d);
523 }
524 return new ArrayFieldVector<>(field, out, false);
525 }
526
527 /** {@inheritDoc} */
528 @Override
529 public FieldVector<T> mapDivideToSelf(T d)
530 throws NullArgumentException, MathRuntimeException {
531 MathUtils.checkNotNull(d);
532 for (int i = 0; i < data.length; i++) {
533 data[i] = data[i].divide(d);
534 }
535 return this;
536 }
537
538 /** {@inheritDoc} */
539 @Override
540 public FieldVector<T> mapInv() throws MathRuntimeException {
541 T[] out = MathArrays.buildArray(field, data.length);
542 final T one = field.getOne();
543 for (int i = 0; i < data.length; i++) {
544 try {
545 out[i] = one.divide(data[i]);
546 } catch (final MathRuntimeException e) {
547 throw new MathRuntimeException(e, LocalizedCoreFormats.INDEX, i);
548 }
549 }
550 return new ArrayFieldVector<>(field, out, false);
551 }
552
553 /** {@inheritDoc} */
554 @Override
555 public FieldVector<T> mapInvToSelf() throws MathRuntimeException {
556 final T one = field.getOne();
557 for (int i = 0; i < data.length; i++) {
558 try {
559 data[i] = one.divide(data[i]);
560 } catch (final MathRuntimeException e) {
561 throw new MathRuntimeException(e, LocalizedCoreFormats.INDEX, i);
562 }
563 }
564 return this;
565 }
566
567 /** {@inheritDoc} */
568 @Override
569 public FieldVector<T> ebeMultiply(FieldVector<T> v)
570 throws MathIllegalArgumentException {
571 if (v instanceof ArrayFieldVector) {
572 return ebeMultiply((ArrayFieldVector<T>) v);
573 } else {
574 checkVectorDimensions(v);
575 T[] out = MathArrays.buildArray(field, data.length);
576 for (int i = 0; i < data.length; i++) {
577 out[i] = data[i].multiply(v.getEntry(i));
578 }
579 return new ArrayFieldVector<>(field, out, false);
580 }
581 }
582
583 /**
584 * Element-by-element multiplication.
585 * @param v vector by which instance elements must be multiplied
586 * @return a vector containing {@code this[i] * v[i]} for all {@code i}
587 * @throws MathIllegalArgumentException if {@code v} is not the same size as
588 * {@code this}
589 */
590 public ArrayFieldVector<T> ebeMultiply(ArrayFieldVector<T> v)
591 throws MathIllegalArgumentException {
592 checkVectorDimensions(v.data.length);
593 T[] out = MathArrays.buildArray(field, data.length);
594 for (int i = 0; i < data.length; i++) {
595 out[i] = data[i].multiply(v.data[i]);
596 }
597 return new ArrayFieldVector<>(field, out, false);
598 }
599
600 /** {@inheritDoc} */
601 @Override
602 public FieldVector<T> ebeDivide(FieldVector<T> v)
603 throws MathRuntimeException {
604 if (v instanceof ArrayFieldVector) {
605 return ebeDivide((ArrayFieldVector<T>) v);
606 } else {
607 checkVectorDimensions(v);
608 T[] out = MathArrays.buildArray(field, data.length);
609 for (int i = 0; i < data.length; i++) {
610 try {
611 out[i] = data[i].divide(v.getEntry(i));
612 } catch (final MathRuntimeException e) {
613 throw new MathRuntimeException(e, LocalizedCoreFormats.INDEX, i);
614 }
615 }
616 return new ArrayFieldVector<>(field, out, false);
617 }
618 }
619
620 /**
621 * Element-by-element division.
622 * @param v vector by which instance elements must be divided
623 * @return a vector containing {@code this[i] / v[i]} for all {@code i}
624 * @throws MathIllegalArgumentException if {@code v} is not the same size as
625 * {@code this}
626 * @throws MathRuntimeException if one entry of {@code v} is zero.
627 */
628 public ArrayFieldVector<T> ebeDivide(ArrayFieldVector<T> v)
629 throws MathIllegalArgumentException, MathRuntimeException {
630 checkVectorDimensions(v.data.length);
631 T[] out = MathArrays.buildArray(field, data.length);
632 for (int i = 0; i < data.length; i++) {
633 try {
634 out[i] = data[i].divide(v.data[i]);
635 } catch (final MathRuntimeException e) {
636 throw new MathRuntimeException(e, LocalizedCoreFormats.INDEX, i);
637 }
638 }
639 return new ArrayFieldVector<>(field, out, false);
640 }
641
642 /**
643 * Returns a reference to the underlying data array.
644 * <p>Does not make a fresh copy of the underlying data.</p>
645 * @return array of entries
646 */
647 public T[] getDataRef() {
648 return data; // NOPMD - returning an internal array is intentional and documented here
649 }
650
651 /** {@inheritDoc} */
652 @Override
653 public T dotProduct(FieldVector<T> v)
654 throws MathIllegalArgumentException {
655 if (v instanceof ArrayFieldVector) {
656 return dotProduct((ArrayFieldVector<T>) v);
657 } else {
658 checkVectorDimensions(v);
659 T dot = field.getZero();
660 for (int i = 0; i < data.length; i++) {
661 dot = dot.add(data[i].multiply(v.getEntry(i)));
662 }
663 return dot;
664 }
665 }
666
667 /**
668 * Compute the dot product.
669 * @param v vector with which dot product should be computed
670 * @return the scalar dot product of {@code this} and {@code v}
671 * @throws MathIllegalArgumentException if {@code v} is not the same size as
672 * {@code this}
673 */
674 public T dotProduct(ArrayFieldVector<T> v)
675 throws MathIllegalArgumentException {
676 checkVectorDimensions(v.data.length);
677 T dot = field.getZero();
678 for (int i = 0; i < data.length; i++) {
679 dot = dot.add(data[i].multiply(v.data[i]));
680 }
681 return dot;
682 }
683
684 /** {@inheritDoc} */
685 @Override
686 public FieldVector<T> projection(FieldVector<T> v)
687 throws MathRuntimeException {
688 return v.mapMultiply(dotProduct(v).divide(v.dotProduct(v)));
689 }
690
691 /** Find the orthogonal projection of this vector onto another vector.
692 * @param v vector onto which {@code this} must be projected
693 * @return projection of {@code this} onto {@code v}
694 * @throws MathIllegalArgumentException if {@code v} is not the same size as
695 * {@code this}
696 * @throws MathRuntimeException if {@code v} is the null vector.
697 */
698 public ArrayFieldVector<T> projection(ArrayFieldVector<T> v)
699 throws MathIllegalArgumentException, MathRuntimeException {
700 return (ArrayFieldVector<T>) v.mapMultiply(dotProduct(v).divide(v.dotProduct(v)));
701 }
702
703 /** {@inheritDoc} */
704 @Override
705 public FieldMatrix<T> outerProduct(FieldVector<T> v) {
706 if (v instanceof ArrayFieldVector) {
707 return outerProduct((ArrayFieldVector<T>) v);
708 } else {
709 final int m = data.length;
710 final int n = v.getDimension();
711 final FieldMatrix<T> out = new Array2DRowFieldMatrix<>(field, m, n);
712 for (int i = 0; i < m; i++) {
713 for (int j = 0; j < n; j++) {
714 out.setEntry(i, j, data[i].multiply(v.getEntry(j)));
715 }
716 }
717 return out;
718 }
719 }
720
721 /**
722 * Compute the outer product.
723 * @param v vector with which outer product should be computed
724 * @return the matrix outer product between instance and v
725 */
726 public FieldMatrix<T> outerProduct(ArrayFieldVector<T> v) {
727 final int m = data.length;
728 final int n = v.data.length;
729 final FieldMatrix<T> out = new Array2DRowFieldMatrix<>(field, m, n);
730 for (int i = 0; i < m; i++) {
731 for (int j = 0; j < n; j++) {
732 out.setEntry(i, j, data[i].multiply(v.data[j]));
733 }
734 }
735 return out;
736 }
737
738 /** {@inheritDoc} */
739 @Override
740 public T getEntry(int index) {
741 return data[index];
742 }
743
744 /** {@inheritDoc} */
745 @Override
746 public int getDimension() {
747 return data.length;
748 }
749
750 /** {@inheritDoc} */
751 @Override
752 public FieldVector<T> append(FieldVector<T> v) {
753 if (v instanceof ArrayFieldVector) {
754 return append((ArrayFieldVector<T>) v);
755 } else {
756 return new ArrayFieldVector<>(this, new ArrayFieldVector<>(v));
757 }
758 }
759
760 /**
761 * Construct a vector by appending a vector to this vector.
762 * @param v vector to append to this one.
763 * @return a new vector
764 */
765 public ArrayFieldVector<T> append(ArrayFieldVector<T> v) {
766 return new ArrayFieldVector<>(this, v);
767 }
768
769 /** {@inheritDoc} */
770 @Override
771 public FieldVector<T> append(T in) {
772 final T[] out = MathArrays.buildArray(field, data.length + 1);
773 System.arraycopy(data, 0, out, 0, data.length);
774 out[data.length] = in;
775 return new ArrayFieldVector<>(field, out, false);
776 }
777
778 /** {@inheritDoc} */
779 @Override
780 public FieldVector<T> getSubVector(int index, int n)
781 throws MathIllegalArgumentException {
782 if (n < 0) {
783 throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_OF_ELEMENTS_SHOULD_BE_POSITIVE, n);
784 }
785 ArrayFieldVector<T> out = new ArrayFieldVector<>(field, n);
786 try {
787 System.arraycopy(data, index, out.data, 0, n);
788 } catch (IndexOutOfBoundsException e) {
789 checkIndex(index);
790 checkIndex(index + n - 1);
791 }
792 return out;
793 }
794
795 /** {@inheritDoc} */
796 @Override
797 public void setEntry(int index, T value) {
798 try {
799 data[index] = value;
800 } catch (IndexOutOfBoundsException e) {
801 checkIndex(index);
802 }
803 }
804
805 /** {@inheritDoc} */
806 @Override
807 public void setSubVector(int index, FieldVector<T> v) throws MathIllegalArgumentException {
808 try {
809 if (v instanceof ArrayFieldVector) {
810 set(index, (ArrayFieldVector<T>) v);
811 } else {
812 for (int i = index; i < index + v.getDimension(); ++i) {
813 data[i] = v.getEntry(i-index);
814 }
815 }
816 } catch (IndexOutOfBoundsException e) {
817 checkIndex(index);
818 checkIndex(index + v.getDimension() - 1);
819 }
820 }
821
822 /**
823 * Set a set of consecutive elements.
824 *
825 * @param index index of first element to be set.
826 * @param v vector containing the values to set.
827 * @throws MathIllegalArgumentException if the index is invalid.
828 */
829 public void set(int index, ArrayFieldVector<T> v) throws MathIllegalArgumentException {
830 try {
831 System.arraycopy(v.data, 0, data, index, v.data.length);
832 } catch (IndexOutOfBoundsException e) {
833 checkIndex(index);
834 checkIndex(index + v.data.length - 1);
835 }
836 }
837
838 /** {@inheritDoc} */
839 @Override
840 public void set(T value) {
841 Arrays.fill(data, value);
842 }
843
844 /** {@inheritDoc} */
845 @Override
846 public T[] toArray(){
847 return data.clone();
848 }
849
850 /**
851 * Check if instance and specified vectors have the same dimension.
852 * @param v vector to compare instance with
853 * @exception MathIllegalArgumentException if the vectors do not
854 * have the same dimensions
855 */
856 protected void checkVectorDimensions(FieldVector<T> v)
857 throws MathIllegalArgumentException {
858 checkVectorDimensions(v.getDimension());
859 }
860
861 /**
862 * Check if instance dimension is equal to some expected value.
863 *
864 * @param n Expected dimension.
865 * @throws MathIllegalArgumentException if the dimension is not equal to the
866 * size of {@code this} vector.
867 */
868 protected void checkVectorDimensions(int n)
869 throws MathIllegalArgumentException {
870 if (data.length != n) {
871 throw new MathIllegalArgumentException(LocalizedCoreFormats.DIMENSIONS_MISMATCH,
872 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 */
885 public T walkInDefaultOrder(final FieldVectorPreservingVisitor<T> visitor) {
886 final int dim = getDimension();
887 visitor.start(dim, 0, dim - 1);
888 for (int i = 0; i < dim; i++) {
889 visitor.visit(i, getEntry(i));
890 }
891 return visitor.end();
892 }
893
894 /**
895 * Visits (but does not alter) some entries of this vector in default order
896 * (increasing index).
897 *
898 * @param visitor visitor to be used to process the entries of this vector
899 * @param start the index of the first entry to be visited
900 * @param end the index of the last entry to be visited (inclusive)
901 * @return the value returned by {@link FieldVectorPreservingVisitor#end()}
902 * at the end of the walk
903 * @throws MathIllegalArgumentException if {@code end < start}.
904 * @throws MathIllegalArgumentException if the indices are not valid.
905 */
906 public T walkInDefaultOrder(final FieldVectorPreservingVisitor<T> visitor,
907 final int start, final int end)
908 throws MathIllegalArgumentException {
909 checkIndices(start, end);
910 visitor.start(getDimension(), start, end);
911 for (int i = start; i <= end; i++) {
912 visitor.visit(i, getEntry(i));
913 }
914 return visitor.end();
915 }
916
917 /**
918 * Visits (but does not alter) all entries of this vector in optimized
919 * order. The order in which the entries are visited is selected so as to
920 * lead to the most efficient implementation; it might depend on the
921 * concrete implementation of this abstract class.
922 *
923 * @param visitor the visitor to be used to process the entries of this
924 * vector
925 * @return the value returned by {@link FieldVectorPreservingVisitor#end()}
926 * at the end of the walk
927 */
928 public T walkInOptimizedOrder(final FieldVectorPreservingVisitor<T> visitor) {
929 return walkInDefaultOrder(visitor);
930 }
931
932 /**
933 * Visits (but does not alter) some entries of this vector in optimized
934 * order. The order in which the entries are visited is selected so as to
935 * lead to the most efficient implementation; it might depend on the
936 * concrete implementation of this abstract class.
937 *
938 * @param visitor visitor to be used to process the entries of this vector
939 * @param start the index of the first entry to be visited
940 * @param end the index of the last entry to be visited (inclusive)
941 * @return the value returned by {@link FieldVectorPreservingVisitor#end()}
942 * at the end of the walk
943 * @throws MathIllegalArgumentException if {@code end < start}.
944 * @throws MathIllegalArgumentException if the indices are not valid.
945 */
946 public T walkInOptimizedOrder(final FieldVectorPreservingVisitor<T> visitor,
947 final int start, final int end)
948 throws MathIllegalArgumentException {
949 return walkInDefaultOrder(visitor, start, end);
950 }
951
952 /**
953 * Visits (and possibly alters) all entries of this vector in default order
954 * (increasing index).
955 *
956 * @param visitor the visitor to be used to process and modify the entries
957 * of this vector
958 * @return the value returned by {@link FieldVectorChangingVisitor#end()}
959 * at the end of the walk
960 */
961 public T walkInDefaultOrder(final FieldVectorChangingVisitor<T> visitor) {
962 final int dim = getDimension();
963 visitor.start(dim, 0, dim - 1);
964 for (int i = 0; i < dim; i++) {
965 setEntry(i, visitor.visit(i, getEntry(i)));
966 }
967 return visitor.end();
968 }
969
970 /**
971 * Visits (and possibly alters) some entries of this vector in default order
972 * (increasing index).
973 *
974 * @param visitor visitor to be used to process the entries of this vector
975 * @param start the index of the first entry to be visited
976 * @param end the index of the last entry to be visited (inclusive)
977 * @return the value returned by {@link FieldVectorChangingVisitor#end()}
978 * at the end of the walk
979 * @throws MathIllegalArgumentException if {@code end < start}.
980 * @throws MathIllegalArgumentException if the indices are not valid.
981 */
982 public T walkInDefaultOrder(final FieldVectorChangingVisitor<T> visitor,
983 final int start, final int end)
984 throws MathIllegalArgumentException {
985 checkIndices(start, end);
986 visitor.start(getDimension(), start, end);
987 for (int i = start; i <= end; i++) {
988 setEntry(i, visitor.visit(i, getEntry(i)));
989 }
990 return visitor.end();
991 }
992
993 /**
994 * Visits (and possibly alters) all entries of this vector in optimized
995 * order. The order in which the entries are visited is selected so as to
996 * lead to the most efficient implementation; it might depend on the
997 * concrete implementation of this abstract class.
998 *
999 * @param visitor the visitor to be used to process the entries of this
1000 * vector
1001 * @return the value returned by {@link FieldVectorChangingVisitor#end()}
1002 * at the end of the walk
1003 */
1004 public T walkInOptimizedOrder(final FieldVectorChangingVisitor<T> visitor) {
1005 return walkInDefaultOrder(visitor);
1006 }
1007
1008 /**
1009 * Visits (and possibly change) some entries of this vector in optimized
1010 * order. The order in which the entries are visited is selected so as to
1011 * lead to the most efficient implementation; it might depend on the
1012 * concrete implementation of this abstract class.
1013 *
1014 * @param visitor visitor to be used to process the entries of this vector
1015 * @param start the index of the first entry to be visited
1016 * @param end the index of the last entry to be visited (inclusive)
1017 * @return the value returned by {@link FieldVectorChangingVisitor#end()}
1018 * at the end of the walk
1019 * @throws MathIllegalArgumentException if {@code end < start}.
1020 * @throws MathIllegalArgumentException if the indices are not valid.
1021 */
1022 public T walkInOptimizedOrder(final FieldVectorChangingVisitor<T> visitor,
1023 final int start, final int end)
1024 throws MathIllegalArgumentException {
1025 return walkInDefaultOrder(visitor, start, end);
1026 }
1027 /** {@inheritDoc}
1028 * @since 2.0
1029 */
1030 @Override
1031 public String toString() {
1032 final StringBuilder builder = new StringBuilder();
1033 builder.append('{');
1034 for (int i = 0; i < data.length; ++i) {
1035 if (i > 0) {
1036 builder.append("; ");
1037 }
1038 builder.append(data[i].toString());
1039 }
1040 builder.append('}');
1041 return builder.toString();
1042 }
1043
1044 /**
1045 * Test for the equality of two vectors.
1046 *
1047 * @param other Object to test for equality.
1048 * @return {@code true} if two vector objects are equal, {@code false}
1049 * otherwise.
1050 */
1051 @Override
1052 public boolean equals(Object other) {
1053 if (this == other) {
1054 return true;
1055 }
1056 if (other == null) {
1057 return false;
1058 }
1059
1060 try {
1061 @SuppressWarnings("unchecked") // May fail, but we ignore ClassCastException
1062 FieldVector<T> rhs = (FieldVector<T>) other;
1063 if (data.length != rhs.getDimension()) {
1064 return false;
1065 }
1066
1067 for (int i = 0; i < data.length; ++i) {
1068 if (!data[i].equals(rhs.getEntry(i))) {
1069 return false;
1070 }
1071 }
1072 return true;
1073 } catch (ClassCastException ex) {
1074 // ignore exception
1075 return false;
1076 }
1077 }
1078
1079 /**
1080 * Get a hashCode for the real vector.
1081 * <p>All NaN values have the same hash code.</p>
1082 * @return a hash code value for this object
1083 */
1084 @Override
1085 public int hashCode() {
1086 int h = 3542;
1087 for (final T a : data) {
1088 h ^= a.hashCode();
1089 }
1090 return h;
1091 }
1092
1093 /**
1094 * Check if an index is valid.
1095 *
1096 * @param index Index to check.
1097 * @exception MathIllegalArgumentException if the index is not valid.
1098 */
1099 private void checkIndex(final int index) throws MathIllegalArgumentException {
1100 if (index < 0 || index >= getDimension()) {
1101 throw new MathIllegalArgumentException(LocalizedCoreFormats.INDEX,
1102 index, 0, getDimension() - 1);
1103 }
1104 }
1105
1106 /**
1107 * Checks that the indices of a subvector are valid.
1108 *
1109 * @param start the index of the first entry of the subvector
1110 * @param end the index of the last entry of the subvector (inclusive)
1111 * @throws MathIllegalArgumentException if {@code start} of {@code end} are not valid
1112 * @throws MathIllegalArgumentException if {@code end < start}
1113 */
1114 private void checkIndices(final int start, final int end)
1115 throws MathIllegalArgumentException {
1116 final int dim = getDimension();
1117 if ((start < 0) || (start >= dim)) {
1118 throw new MathIllegalArgumentException(LocalizedCoreFormats.INDEX, start, 0,
1119 dim - 1);
1120 }
1121 if ((end < 0) || (end >= dim)) {
1122 throw new MathIllegalArgumentException(LocalizedCoreFormats.INDEX, end, 0,
1123 dim - 1);
1124 }
1125 if (end < start) {
1126 throw new MathIllegalArgumentException(LocalizedCoreFormats.INITIAL_ROW_AFTER_FINAL_ROW,
1127 end, start, false);
1128 }
1129 }
1130
1131 }