001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.commons.math3.linear;
018
019 import java.io.Serializable;
020 import java.lang.reflect.Array;
021 import java.util.Arrays;
022
023 import org.apache.commons.math3.Field;
024 import org.apache.commons.math3.FieldElement;
025 import org.apache.commons.math3.exception.MathArithmeticException;
026 import org.apache.commons.math3.exception.NotPositiveException;
027 import org.apache.commons.math3.exception.ZeroException;
028 import org.apache.commons.math3.exception.NullArgumentException;
029 import org.apache.commons.math3.exception.OutOfRangeException;
030 import org.apache.commons.math3.exception.DimensionMismatchException;
031 import org.apache.commons.math3.exception.NumberIsTooLargeException;
032 import org.apache.commons.math3.exception.util.LocalizedFormats;
033
034 /**
035 * This class implements the {@link FieldVector} interface with a {@link FieldElement} array.
036 * @param <T> the type of the field elements
037 * @version $Id: ArrayFieldVector.java 1416643 2012-12-03 19:37:14Z tn $
038 * @since 2.0
039 */
040 public 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(ArrayFieldVector, ArrayFieldVector)} 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 data = buildArray(size);
073 Arrays.fill(data, field.getZero());
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 if (d == null) {
102 throw new NullArgumentException();
103 }
104 try {
105 field = d[0].getField();
106 data = d.clone();
107 } catch (ArrayIndexOutOfBoundsException e) {
108 throw new ZeroException(LocalizedFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT);
109 }
110 }
111
112 /**
113 * Construct a vector from an array, copying the input array.
114 *
115 * @param field Field to which the elements belong.
116 * @param d Array.
117 * @throws NullArgumentException if {@code d} is {@code null}.
118 * @see #ArrayFieldVector(FieldElement[])
119 */
120 public ArrayFieldVector(Field<T> field, T[] d)
121 throws NullArgumentException {
122 if (d == null) {
123 throw new NullArgumentException();
124 }
125 this.field = field;
126 data = d.clone();
127 }
128
129 /**
130 * Create a new ArrayFieldVector using the input array as the underlying
131 * data array.
132 * If an array is built specially in order to be embedded in a
133 * ArrayFieldVector and not used directly, the {@code copyArray} may be
134 * set to {@code false}. This will prevent the copying and improve
135 * performance as no new array will be built and no data will be copied.
136 * This constructor needs a non-empty {@code d} array to retrieve
137 * the field from its first element. This implies it cannot build
138 * 0 length vectors. To build vectors from any size, one should
139 * use the {@link #ArrayFieldVector(Field, FieldElement[], boolean)}
140 * constructor.
141 *
142 * @param d Data for the new vector.
143 * @param copyArray If {@code true}, the input array will be copied,
144 * otherwise it will be referenced.
145 * @throws NullArgumentException if {@code d} is {@code null}.
146 * @throws ZeroException if {@code d} is empty.
147 * @see #ArrayFieldVector(FieldElement[])
148 * @see #ArrayFieldVector(Field, FieldElement[], boolean)
149 */
150 public ArrayFieldVector(T[] d, boolean copyArray)
151 throws NullArgumentException, ZeroException {
152 if (d == null) {
153 throw new NullArgumentException();
154 }
155 if (d.length == 0) {
156 throw new ZeroException(LocalizedFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT);
157 }
158 field = d[0].getField();
159 data = copyArray ? d.clone() : d;
160 }
161
162 /**
163 * Create a new ArrayFieldVector using the input array as the underlying
164 * data array.
165 * If an array is built specially in order to be embedded in a
166 * ArrayFieldVector and not used directly, the {@code copyArray} may be
167 * set to {@code false}. This will prevent the copying and improve
168 * performance as no new array will be built and no data will be copied.
169 *
170 * @param field Field to which the elements belong.
171 * @param d Data for the new vector.
172 * @param copyArray If {@code true}, the input array will be copied,
173 * otherwise it will be referenced.
174 * @throws NullArgumentException if {@code d} is {@code null}.
175 * @see #ArrayFieldVector(FieldElement[], boolean)
176 */
177 public ArrayFieldVector(Field<T> field, T[] d, boolean copyArray)
178 throws NullArgumentException {
179 if (d == null) {
180 throw new NullArgumentException();
181 }
182 this.field = field;
183 data = copyArray ? d.clone() : d;
184 }
185
186 /**
187 * Construct a vector from part of a array.
188 *
189 * @param d Array.
190 * @param pos Position of the first entry.
191 * @param size Number of entries to copy.
192 * @throws NullArgumentException if {@code d} is {@code null}.
193 * @throws NumberIsTooLargeException if the size of {@code d} is less
194 * than {@code pos + size}.
195 */
196 public ArrayFieldVector(T[] d, int pos, int size)
197 throws NullArgumentException, NumberIsTooLargeException {
198 if (d == null) {
199 throw new NullArgumentException();
200 }
201 if (d.length < pos + size) {
202 throw new NumberIsTooLargeException(pos + size, d.length, true);
203 }
204 field = d[0].getField();
205 data = buildArray(size);
206 System.arraycopy(d, pos, data, 0, size);
207 }
208
209 /**
210 * Construct a vector from part of a array.
211 *
212 * @param field Field to which the elements belong.
213 * @param d Array.
214 * @param pos Position of the first entry.
215 * @param size Number of entries to copy.
216 * @throws NullArgumentException if {@code d} is {@code null}.
217 * @throws NumberIsTooLargeException if the size of {@code d} is less
218 * than {@code pos + size}.
219 */
220 public ArrayFieldVector(Field<T> field, T[] d, int pos, int size)
221 throws NullArgumentException, NumberIsTooLargeException {
222 if (d == null) {
223 throw new NullArgumentException();
224 }
225 if (d.length < pos + size) {
226 throw new NumberIsTooLargeException(pos + size, d.length, true);
227 }
228 this.field = field;
229 data = buildArray(size);
230 System.arraycopy(d, pos, data, 0, size);
231 }
232
233 /**
234 * Construct a vector from another vector, using a deep copy.
235 *
236 * @param v Vector to copy.
237 * @throws NullArgumentException if {@code v} is {@code null}.
238 */
239 public ArrayFieldVector(FieldVector<T> v)
240 throws NullArgumentException {
241 if (v == null) {
242 throw new NullArgumentException();
243 }
244 field = v.getField();
245 data = buildArray(v.getDimension());
246 for (int i = 0; i < data.length; ++i) {
247 data[i] = v.getEntry(i);
248 }
249 }
250
251 /**
252 * Construct a vector from another vector, using a deep copy.
253 *
254 * @param v Vector to copy.
255 * @throws NullArgumentException if {@code v} is {@code null}.
256 */
257 public ArrayFieldVector(ArrayFieldVector<T> v)
258 throws NullArgumentException {
259 if (v == null) {
260 throw new NullArgumentException();
261 }
262 field = v.getField();
263 data = v.data.clone();
264 }
265
266 /**
267 * Construct a vector from another vector.
268 *
269 * @param v Vector to copy.
270 * @param deep If {@code true} perform a deep copy, otherwise perform
271 * a shallow copy
272 * @throws NullArgumentException if {@code v} is {@code null}.
273 */
274 public ArrayFieldVector(ArrayFieldVector<T> v, boolean deep)
275 throws NullArgumentException {
276 if (v == null) {
277 throw new NullArgumentException();
278 }
279 field = v.getField();
280 data = deep ? v.data.clone() : v.data;
281 }
282
283 /**
284 * Construct a vector by appending one vector to another vector.
285 *
286 * @param v1 First vector (will be put in front of the new vector).
287 * @param v2 Second vector (will be put at back of the new vector).
288 * @throws NullArgumentException if {@code v1} or {@code v2} is
289 * {@code null}.
290 */
291 public ArrayFieldVector(ArrayFieldVector<T> v1, ArrayFieldVector<T> v2)
292 throws NullArgumentException {
293 if (v1 == null || v2 == null) {
294 throw new NullArgumentException();
295 }
296 field = v1.getField();
297 data = buildArray(v1.data.length + v2.data.length);
298 System.arraycopy(v1.data, 0, data, 0, v1.data.length);
299 System.arraycopy(v2.data, 0, data, v1.data.length, v2.data.length);
300 }
301
302 /**
303 * Construct a vector by appending one vector to another vector.
304 *
305 * @param v1 First vector (will be put in front of the new vector).
306 * @param v2 Second vector (will be put at back of the new vector).
307 * @throws NullArgumentException if {@code v1} or {@code v2} is
308 * {@code null}.
309 */
310 public ArrayFieldVector(ArrayFieldVector<T> v1, T[] v2)
311 throws NullArgumentException {
312 if (v1 == null || v2 == null) {
313 throw new NullArgumentException();
314 }
315 field = v1.getField();
316 data = buildArray(v1.data.length + v2.length);
317 System.arraycopy(v1.data, 0, data, 0, v1.data.length);
318 System.arraycopy(v2, 0, data, v1.data.length, v2.length);
319 }
320
321 /**
322 * Construct a vector by appending one vector to another vector.
323 *
324 * @param v1 First vector (will be put in front of the new vector).
325 * @param v2 Second vector (will be put at back of the new vector).
326 * @throws NullArgumentException if {@code v1} or {@code v2} is
327 * {@code null}.
328 */
329 public ArrayFieldVector(T[] v1, ArrayFieldVector<T> v2)
330 throws NullArgumentException {
331 if (v1 == null || v2 == null) {
332 throw new NullArgumentException();
333 }
334 field = v2.getField();
335 data = buildArray(v1.length + v2.data.length);
336 System.arraycopy(v1, 0, data, 0, v1.length);
337 System.arraycopy(v2.data, 0, data, v1.length, v2.data.length);
338 }
339
340 /**
341 * Construct a vector by appending one vector to another vector.
342 * This constructor needs at least one non-empty array to retrieve
343 * the field from its first element. This implies it cannot build
344 * 0 length vectors. To build vectors from any size, one should
345 * use the {@link #ArrayFieldVector(Field, FieldElement[], FieldElement[])}
346 * constructor.
347 *
348 * @param v1 First vector (will be put in front of the new vector).
349 * @param v2 Second vector (will be put at back of the new vector).
350 * @throws NullArgumentException if {@code v1} or {@code v2} is
351 * {@code null}.
352 * @throws ZeroException if both arrays are empty.
353 * @see #ArrayFieldVector(Field, FieldElement[], FieldElement[])
354 */
355 public ArrayFieldVector(T[] v1, T[] v2)
356 throws NullArgumentException, ZeroException {
357 if (v1 == null || v2 == null) {
358 throw new NullArgumentException();
359 }
360 if (v1.length + v2.length == 0) {
361 throw new ZeroException(LocalizedFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT);
362 }
363 data = buildArray(v1.length + v2.length);
364 System.arraycopy(v1, 0, data, 0, v1.length);
365 System.arraycopy(v2, 0, data, v1.length, v2.length);
366 field = data[0].getField();
367 }
368
369 /**
370 * Construct a vector by appending one vector to another vector.
371 *
372 * @param field Field to which the elements belong.
373 * @param v1 First vector (will be put in front of the new vector).
374 * @param v2 Second vector (will be put at back of the new vector).
375 * @throws NullArgumentException if {@code v1} or {@code v2} is
376 * {@code null}.
377 * @throws ZeroException if both arrays are empty.
378 * @see #ArrayFieldVector(FieldElement[], FieldElement[])
379 */
380 public ArrayFieldVector(Field<T> field, T[] v1, T[] v2)
381 throws NullArgumentException, ZeroException {
382 if (v1 == null || v2 == null) {
383 throw new NullArgumentException();
384 }
385 if (v1.length + v2.length == 0) {
386 throw new ZeroException(LocalizedFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT);
387 }
388 data = buildArray(v1.length + v2.length);
389 System.arraycopy(v1, 0, data, 0, v1.length);
390 System.arraycopy(v2, 0, data, v1.length, v2.length);
391 this.field = field;
392 }
393
394 /**
395 * Build an array of elements.
396 *
397 * @param length Size of the array to build.
398 * @return a new array.
399 */
400 @SuppressWarnings("unchecked") // field is of type T
401 private T[] buildArray(final int length) {
402 return (T[]) Array.newInstance(field.getRuntimeClass(), length);
403 }
404
405 /** {@inheritDoc} */
406 public Field<T> getField() {
407 return field;
408 }
409
410 /** {@inheritDoc} */
411 public FieldVector<T> copy() {
412 return new ArrayFieldVector<T>(this, true);
413 }
414
415 /** {@inheritDoc} */
416 public FieldVector<T> add(FieldVector<T> v)
417 throws DimensionMismatchException {
418 try {
419 return add((ArrayFieldVector<T>) v);
420 } catch (ClassCastException cce) {
421 checkVectorDimensions(v);
422 T[] out = buildArray(data.length);
423 for (int i = 0; i < data.length; i++) {
424 out[i] = data[i].add(v.getEntry(i));
425 }
426 return new ArrayFieldVector<T>(field, out, false);
427 }
428 }
429
430 /**
431 * Compute the sum of {@code this} and {@code v}.
432 * @param v vector to be added
433 * @return {@code this + v}
434 * @throws DimensionMismatchException if {@code v} is not the same size as
435 * {@code this}
436 */
437 public ArrayFieldVector<T> add(ArrayFieldVector<T> v)
438 throws DimensionMismatchException {
439 checkVectorDimensions(v.data.length);
440 T[] out = buildArray(data.length);
441 for (int i = 0; i < data.length; i++) {
442 out[i] = data[i].add(v.data[i]);
443 }
444 return new ArrayFieldVector<T>(field, out, false);
445 }
446
447 /** {@inheritDoc} */
448 public FieldVector<T> subtract(FieldVector<T> v)
449 throws DimensionMismatchException {
450 try {
451 return subtract((ArrayFieldVector<T>) v);
452 } catch (ClassCastException cce) {
453 checkVectorDimensions(v);
454 T[] out = buildArray(data.length);
455 for (int i = 0; i < data.length; i++) {
456 out[i] = data[i].subtract(v.getEntry(i));
457 }
458 return new ArrayFieldVector<T>(field, out, false);
459 }
460 }
461
462 /**
463 * Compute {@code this} minus {@code v}.
464 * @param v vector to be subtracted
465 * @return {@code this - v}
466 * @throws DimensionMismatchException if {@code v} is not the same size as
467 * {@code this}
468 */
469 public ArrayFieldVector<T> subtract(ArrayFieldVector<T> v)
470 throws DimensionMismatchException {
471 checkVectorDimensions(v.data.length);
472 T[] out = buildArray(data.length);
473 for (int i = 0; i < data.length; i++) {
474 out[i] = data[i].subtract(v.data[i]);
475 }
476 return new ArrayFieldVector<T>(field, out, false);
477 }
478
479 /** {@inheritDoc} */
480 public FieldVector<T> mapAdd(T d) throws NullArgumentException {
481 T[] out = buildArray(data.length);
482 for (int i = 0; i < data.length; i++) {
483 out[i] = data[i].add(d);
484 }
485 return new ArrayFieldVector<T>(field, out, false);
486 }
487
488 /** {@inheritDoc} */
489 public FieldVector<T> mapAddToSelf(T d) throws NullArgumentException {
490 for (int i = 0; i < data.length; i++) {
491 data[i] = data[i].add(d);
492 }
493 return this;
494 }
495
496 /** {@inheritDoc} */
497 public FieldVector<T> mapSubtract(T d) throws NullArgumentException {
498 T[] out = buildArray(data.length);
499 for (int i = 0; i < data.length; i++) {
500 out[i] = data[i].subtract(d);
501 }
502 return new ArrayFieldVector<T>(field, out, false);
503 }
504
505 /** {@inheritDoc} */
506 public FieldVector<T> mapSubtractToSelf(T d) throws NullArgumentException {
507 for (int i = 0; i < data.length; i++) {
508 data[i] = data[i].subtract(d);
509 }
510 return this;
511 }
512
513 /** {@inheritDoc} */
514 public FieldVector<T> mapMultiply(T d) throws NullArgumentException {
515 T[] out = buildArray(data.length);
516 for (int i = 0; i < data.length; i++) {
517 out[i] = data[i].multiply(d);
518 }
519 return new ArrayFieldVector<T>(field, out, false);
520 }
521
522 /** {@inheritDoc} */
523 public FieldVector<T> mapMultiplyToSelf(T d) throws NullArgumentException {
524 for (int i = 0; i < data.length; i++) {
525 data[i] = data[i].multiply(d);
526 }
527 return this;
528 }
529
530 /** {@inheritDoc} */
531 public FieldVector<T> mapDivide(T d)
532 throws NullArgumentException, MathArithmeticException {
533 if (d == null) {
534 throw new NullArgumentException();
535 }
536 T[] out = buildArray(data.length);
537 for (int i = 0; i < data.length; i++) {
538 out[i] = data[i].divide(d);
539 }
540 return new ArrayFieldVector<T>(field, out, false);
541 }
542
543 /** {@inheritDoc} */
544 public FieldVector<T> mapDivideToSelf(T d)
545 throws NullArgumentException, MathArithmeticException {
546 if (d == null) {
547 throw new NullArgumentException();
548 }
549 for (int i = 0; i < data.length; i++) {
550 data[i] = data[i].divide(d);
551 }
552 return this;
553 }
554
555 /** {@inheritDoc} */
556 public FieldVector<T> mapInv() throws MathArithmeticException {
557 T[] out = buildArray(data.length);
558 final T one = field.getOne();
559 for (int i = 0; i < data.length; i++) {
560 try {
561 out[i] = one.divide(data[i]);
562 } catch (final MathArithmeticException e) {
563 throw new MathArithmeticException(LocalizedFormats.INDEX, i);
564 }
565 }
566 return new ArrayFieldVector<T>(field, out, false);
567 }
568
569 /** {@inheritDoc} */
570 public FieldVector<T> mapInvToSelf() throws MathArithmeticException {
571 final T one = field.getOne();
572 for (int i = 0; i < data.length; i++) {
573 try {
574 data[i] = one.divide(data[i]);
575 } catch (final MathArithmeticException e) {
576 throw new MathArithmeticException(LocalizedFormats.INDEX, i);
577 }
578 }
579 return this;
580 }
581
582 /** {@inheritDoc} */
583 public FieldVector<T> ebeMultiply(FieldVector<T> v)
584 throws DimensionMismatchException {
585 try {
586 return ebeMultiply((ArrayFieldVector<T>) v);
587 } catch (ClassCastException cce) {
588 checkVectorDimensions(v);
589 T[] out = buildArray(data.length);
590 for (int i = 0; i < data.length; i++) {
591 out[i] = data[i].multiply(v.getEntry(i));
592 }
593 return new ArrayFieldVector<T>(field, out, false);
594 }
595 }
596
597 /**
598 * Element-by-element multiplication.
599 * @param v vector by which instance elements must be multiplied
600 * @return a vector containing {@code this[i] * v[i]} for all {@code i}
601 * @throws DimensionMismatchException if {@code v} is not the same size as
602 * {@code this}
603 */
604 public ArrayFieldVector<T> ebeMultiply(ArrayFieldVector<T> v)
605 throws DimensionMismatchException {
606 checkVectorDimensions(v.data.length);
607 T[] out = buildArray(data.length);
608 for (int i = 0; i < data.length; i++) {
609 out[i] = data[i].multiply(v.data[i]);
610 }
611 return new ArrayFieldVector<T>(field, out, false);
612 }
613
614 /** {@inheritDoc} */
615 public FieldVector<T> ebeDivide(FieldVector<T> v)
616 throws DimensionMismatchException, MathArithmeticException {
617 try {
618 return ebeDivide((ArrayFieldVector<T>) v);
619 } catch (ClassCastException cce) {
620 checkVectorDimensions(v);
621 T[] out = buildArray(data.length);
622 for (int i = 0; i < data.length; i++) {
623 try {
624 out[i] = data[i].divide(v.getEntry(i));
625 } catch (final MathArithmeticException e) {
626 throw new MathArithmeticException(LocalizedFormats.INDEX, i);
627 }
628 }
629 return new ArrayFieldVector<T>(field, out, false);
630 }
631 }
632
633 /**
634 * Element-by-element division.
635 * @param v vector by which instance elements must be divided
636 * @return a vector containing {@code this[i] / v[i]} for all {@code i}
637 * @throws DimensionMismatchException if {@code v} is not the same size as
638 * {@code this}
639 * @throws MathArithmeticException if one entry of {@code v} is zero.
640 */
641 public ArrayFieldVector<T> ebeDivide(ArrayFieldVector<T> v)
642 throws DimensionMismatchException, MathArithmeticException {
643 checkVectorDimensions(v.data.length);
644 T[] out = buildArray(data.length);
645 for (int i = 0; i < data.length; i++) {
646 try {
647 out[i] = data[i].divide(v.data[i]);
648 } catch (final MathArithmeticException e) {
649 throw new MathArithmeticException(LocalizedFormats.INDEX, i);
650 }
651 }
652 return new ArrayFieldVector<T>(field, out, false);
653 }
654
655 /** {@inheritDoc} */
656 public T[] getData() {
657 return data.clone();
658 }
659
660 /**
661 * Returns a reference to the underlying data array.
662 * <p>Does not make a fresh copy of the underlying data.</p>
663 * @return array of entries
664 */
665 public T[] getDataRef() {
666 return data;
667 }
668
669 /** {@inheritDoc} */
670 public T dotProduct(FieldVector<T> v)
671 throws DimensionMismatchException {
672 try {
673 return dotProduct((ArrayFieldVector<T>) v);
674 } catch (ClassCastException cce) {
675 checkVectorDimensions(v);
676 T dot = field.getZero();
677 for (int i = 0; i < data.length; i++) {
678 dot = dot.add(data[i].multiply(v.getEntry(i)));
679 }
680 return dot;
681 }
682 }
683
684 /**
685 * Compute the dot product.
686 * @param v vector with which dot product should be computed
687 * @return the scalar dot product of {@code this} and {@code v}
688 * @throws DimensionMismatchException if {@code v} is not the same size as
689 * {@code this}
690 */
691 public T dotProduct(ArrayFieldVector<T> v)
692 throws DimensionMismatchException {
693 checkVectorDimensions(v.data.length);
694 T dot = field.getZero();
695 for (int i = 0; i < data.length; i++) {
696 dot = dot.add(data[i].multiply(v.data[i]));
697 }
698 return dot;
699 }
700
701 /** {@inheritDoc} */
702 public FieldVector<T> projection(FieldVector<T> v)
703 throws DimensionMismatchException, MathArithmeticException {
704 return v.mapMultiply(dotProduct(v).divide(v.dotProduct(v)));
705 }
706
707 /** Find the orthogonal projection of this vector onto another vector.
708 * @param v vector onto which {@code this} must be projected
709 * @return projection of {@code this} onto {@code v}
710 * @throws DimensionMismatchException if {@code v} is not the same size as
711 * {@code this}
712 * @throws MathArithmeticException if {@code v} is the null vector.
713 */
714 public ArrayFieldVector<T> projection(ArrayFieldVector<T> v)
715 throws DimensionMismatchException, MathArithmeticException {
716 return (ArrayFieldVector<T>) v.mapMultiply(dotProduct(v).divide(v.dotProduct(v)));
717 }
718
719 /** {@inheritDoc} */
720 public FieldMatrix<T> outerProduct(FieldVector<T> v) {
721 try {
722 return outerProduct((ArrayFieldVector<T>) v);
723 } catch (ClassCastException cce) {
724 final int m = data.length;
725 final int n = v.getDimension();
726 final FieldMatrix<T> out = new Array2DRowFieldMatrix<T>(field, m, n);
727 for (int i = 0; i < m; i++) {
728 for (int j = 0; j < n; j++) {
729 out.setEntry(i, j, data[i].multiply(v.getEntry(j)));
730 }
731 }
732 return out;
733 }
734 }
735
736 /**
737 * Compute the outer product.
738 * @param v vector with which outer product should be computed
739 * @return the matrix outer product between instance and v
740 */
741 public FieldMatrix<T> outerProduct(ArrayFieldVector<T> v) {
742 final int m = data.length;
743 final int n = v.data.length;
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.data[j]));
748 }
749 }
750 return out;
751 }
752
753 /** {@inheritDoc} */
754 public T getEntry(int index) {
755 return data[index];
756 }
757
758 /** {@inheritDoc} */
759 public int getDimension() {
760 return data.length;
761 }
762
763 /** {@inheritDoc} */
764 public FieldVector<T> append(FieldVector<T> v) {
765 try {
766 return append((ArrayFieldVector<T>) v);
767 } catch (ClassCastException cce) {
768 return new ArrayFieldVector<T>(this,new ArrayFieldVector<T>(v));
769 }
770 }
771
772 /**
773 * Construct a vector by appending a vector to this vector.
774 * @param v vector to append to this one.
775 * @return a new vector
776 */
777 public ArrayFieldVector<T> append(ArrayFieldVector<T> v) {
778 return new ArrayFieldVector<T>(this, v);
779 }
780
781 /** {@inheritDoc} */
782 public FieldVector<T> append(T in) {
783 final T[] out = buildArray(data.length + 1);
784 System.arraycopy(data, 0, out, 0, data.length);
785 out[data.length] = in;
786 return new ArrayFieldVector<T>(field, out, false);
787 }
788
789 /** {@inheritDoc} */
790 public FieldVector<T> getSubVector(int index, int n)
791 throws OutOfRangeException, NotPositiveException {
792 if (n < 0) {
793 throw new NotPositiveException(LocalizedFormats.NUMBER_OF_ELEMENTS_SHOULD_BE_POSITIVE, n);
794 }
795 ArrayFieldVector<T> out = new ArrayFieldVector<T>(field, n);
796 try {
797 System.arraycopy(data, index, out.data, 0, n);
798 } catch (IndexOutOfBoundsException e) {
799 checkIndex(index);
800 checkIndex(index + n - 1);
801 }
802 return out;
803 }
804
805 /** {@inheritDoc} */
806 public void setEntry(int index, T value) {
807 try {
808 data[index] = value;
809 } catch (IndexOutOfBoundsException e) {
810 checkIndex(index);
811 }
812 }
813
814 /** {@inheritDoc} */
815 public void setSubVector(int index, FieldVector<T> v) throws OutOfRangeException {
816 try {
817 try {
818 set(index, (ArrayFieldVector<T>) v);
819 } catch (ClassCastException cce) {
820 for (int i = index; i < index + v.getDimension(); ++i) {
821 data[i] = v.getEntry(i-index);
822 }
823 }
824 } catch (IndexOutOfBoundsException e) {
825 checkIndex(index);
826 checkIndex(index + v.getDimension() - 1);
827 }
828 }
829
830 /**
831 * Set a set of consecutive elements.
832 *
833 * @param index index of first element to be set.
834 * @param v vector containing the values to set.
835 * @throws OutOfRangeException if the index is invalid.
836 */
837 public void set(int index, ArrayFieldVector<T> v) throws OutOfRangeException {
838 try {
839 System.arraycopy(v.data, 0, data, index, v.data.length);
840 } catch (IndexOutOfBoundsException e) {
841 checkIndex(index);
842 checkIndex(index + v.data.length - 1);
843 }
844 }
845
846 /** {@inheritDoc} */
847 public void set(T value) {
848 Arrays.fill(data, value);
849 }
850
851 /** {@inheritDoc} */
852 public T[] toArray(){
853 return data.clone();
854 }
855
856 /**
857 * Check if instance and specified vectors have the same dimension.
858 * @param v vector to compare instance with
859 * @exception DimensionMismatchException if the vectors do not
860 * have the same dimensions
861 */
862 protected void checkVectorDimensions(FieldVector<T> v)
863 throws DimensionMismatchException {
864 checkVectorDimensions(v.getDimension());
865 }
866
867 /**
868 * Check if instance dimension is equal to some expected value.
869 *
870 * @param n Expected dimension.
871 * @throws DimensionMismatchException if the dimension is not equal to the
872 * size of {@code this} vector.
873 */
874 protected void checkVectorDimensions(int n)
875 throws DimensionMismatchException {
876 if (data.length != n) {
877 throw new DimensionMismatchException(data.length, n);
878 }
879 }
880
881 /**
882 * Test for the equality of two vectors.
883 *
884 * @param other Object to test for equality.
885 * @return {@code true} if two vector objects are equal, {@code false}
886 * otherwise.
887 */
888 @Override
889 public boolean equals(Object other) {
890 if (this == other) {
891 return true;
892 }
893 if (other == null) {
894 return false;
895 }
896
897 try {
898 @SuppressWarnings("unchecked") // May fail, but we ignore ClassCastException
899 FieldVector<T> rhs = (FieldVector<T>) other;
900 if (data.length != rhs.getDimension()) {
901 return false;
902 }
903
904 for (int i = 0; i < data.length; ++i) {
905 if (!data[i].equals(rhs.getEntry(i))) {
906 return false;
907 }
908 }
909 return true;
910 } catch (ClassCastException ex) {
911 // ignore exception
912 return false;
913 }
914 }
915
916 /**
917 * Get a hashCode for the real vector.
918 * <p>All NaN values have the same hash code.</p>
919 * @return a hash code value for this object
920 */
921 @Override
922 public int hashCode() {
923 int h = 3542;
924 for (final T a : data) {
925 h = h ^ a.hashCode();
926 }
927 return h;
928 }
929
930 /**
931 * Check if an index is valid.
932 *
933 * @param index Index to check.
934 * @exception OutOfRangeException if the index is not valid.
935 */
936 private void checkIndex(final int index) throws OutOfRangeException {
937 if (index < 0 || index >= getDimension()) {
938 throw new OutOfRangeException(LocalizedFormats.INDEX,
939 index, 0, getDimension() - 1);
940 }
941 }
942 }