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.math.linear;
018
019 import java.io.Serializable;
020 import java.lang.reflect.Array;
021 import java.util.Arrays;
022
023 import org.apache.commons.math.Field;
024 import org.apache.commons.math.FieldElement;
025 import org.apache.commons.math.exception.ZeroException;
026 import org.apache.commons.math.exception.NullArgumentException;
027 import org.apache.commons.math.exception.OutOfRangeException;
028 import org.apache.commons.math.exception.DimensionMismatchException;
029 import org.apache.commons.math.exception.NumberIsTooLargeException;
030 import org.apache.commons.math.exception.util.LocalizedFormats;
031
032 /**
033 * This class implements the {@link FieldVector} interface with a {@link FieldElement} array.
034 * @param <T> the type of the field elements
035 * @version $Id: ArrayFieldVector.java 1178172 2011-10-02 10:11:43Z luc $
036 * @since 2.0
037 */
038 public class ArrayFieldVector<T extends FieldElement<T>> implements FieldVector<T>, Serializable {
039 /** Serializable version identifier. */
040 private static final long serialVersionUID = 7648186910365927050L;
041 /** Entries of the vector. */
042 protected T[] data;
043 /** Field to which the elements belong. */
044 private final Field<T> field;
045
046 /**
047 * Build a 0-length vector.
048 * Zero-length vectors may be used to initialized construction of vectors
049 * by data gathering. We start with zero-length and use either the {@link
050 * #ArrayFieldVector(ArrayFieldVector, ArrayFieldVector)} constructor
051 * or one of the {@code append} methods ({@link #add(FieldVector)} or
052 * {@link #append(ArrayFieldVector)}) to gather data into this vector.
053 *
054 * @param field field to which the elements belong
055 */
056 public ArrayFieldVector(final Field<T> field) {
057 this(field, 0);
058 }
059
060 /**
061 * Construct a vector of zeroes.
062 *
063 * @param field Field to which the elements belong.
064 * @param size Size of the vector.
065 */
066 public ArrayFieldVector(Field<T> field, int size) {
067 this.field = field;
068 data = buildArray(size);
069 Arrays.fill(data, field.getZero());
070 }
071
072 /**
073 * Construct a vector with preset values.
074 *
075 * @param size Size of the vector.
076 * @param preset All entries will be set with this value.
077 */
078 public ArrayFieldVector(int size, T preset) {
079 this(preset.getField(), size);
080 Arrays.fill(data, preset);
081 }
082
083 /**
084 * Construct a vector from an array, copying the input array.
085 * This constructor needs a non-empty {@code d} array to retrieve
086 * the field from its first element. This implies it cannot build
087 * 0 length vectors. To build vectors from any size, one should
088 * use the {@link #ArrayFieldVector(Field, FieldElement[])} constructor.
089 *
090 * @param d Array.
091 * @throws NullArgumentException if {@code d} is {@code null}.
092 * @throws ZeroException if {@code d} is empty.
093 * @see #ArrayFieldVector(Field, FieldElement[])
094 */
095 public ArrayFieldVector(T[] d) {
096 if (d == null) {
097 throw new NullArgumentException();
098 }
099 try {
100 field = d[0].getField();
101 data = d.clone();
102 } catch (ArrayIndexOutOfBoundsException e) {
103 throw new ZeroException(LocalizedFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT);
104 }
105 }
106
107 /**
108 * Construct a vector from an array, copying the input array.
109 *
110 * @param field Field to which the elements belong.
111 * @param d Array.
112 * @throws NullArgumentException if {@code d} is {@code null}.
113 * @see #ArrayFieldVector(FieldElement[])
114 */
115 public ArrayFieldVector(Field<T> field, T[] d) {
116 if (d == null) {
117 throw new NullArgumentException();
118 }
119 this.field = field;
120 data = d.clone();
121 }
122
123 /**
124 * Create a new ArrayFieldVector using the input array as the underlying
125 * data array.
126 * If an array is built specially in order to be embedded in a
127 * ArrayFieldVector and not used directly, the {@code copyArray} may be
128 * set to {@code false}. This will prevent the copying and improve
129 * performance as no new array will be built and no data will be copied.
130 * This constructor needs a non-empty {@code d} array to retrieve
131 * the field from its first element. This implies it cannot build
132 * 0 length vectors. To build vectors from any size, one should
133 * use the {@link #ArrayFieldVector(Field, FieldElement[], boolean)}
134 * constructor.
135 *
136 * @param d Data for the new vector.
137 * @param copyArray If {@code true}, the input array will be copied,
138 * otherwise it will be referenced.
139 * @throws NullArgumentException if {@code d} is {@code null}.
140 * @throws ZeroException if {@code d} is empty.
141 * @see #ArrayFieldVector(FieldElement[])
142 * @see #ArrayFieldVector(Field, FieldElement[], boolean)
143 */
144 public ArrayFieldVector(T[] d, boolean copyArray) {
145 if (d == null) {
146 throw new NullArgumentException();
147 }
148 if (d.length == 0) {
149 throw new ZeroException(LocalizedFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT);
150 }
151 field = d[0].getField();
152 data = copyArray ? d.clone() : d;
153 }
154
155 /**
156 * Create a new ArrayFieldVector using the input array as the underlying
157 * data array.
158 * If an array is built specially in order to be embedded in a
159 * ArrayFieldVector and not used directly, the {@code copyArray} may be
160 * set to {@code false}. This will prevent the copying and improve
161 * performance as no new array will be built and no data will be copied.
162 *
163 * @param field Field to which the elements belong.
164 * @param d Data for the new vector.
165 * @param copyArray If {@code true}, the input array will be copied,
166 * otherwise it will be referenced.
167 * @throws NullArgumentException if {@code d} is {@code null}.
168 * @see #ArrayFieldVector(FieldElement[], boolean)
169 */
170 public ArrayFieldVector(Field<T> field, T[] d, boolean copyArray) {
171 if (d == null) {
172 throw new NullArgumentException();
173 }
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 if (d == null) {
190 throw new NullArgumentException();
191 }
192 if (d.length < pos + size) {
193 throw new NumberIsTooLargeException(pos + size, d.length, true);
194 }
195 field = d[0].getField();
196 data = buildArray(size);
197 System.arraycopy(d, pos, data, 0, size);
198 }
199
200 /**
201 * Construct a vector from part of a array.
202 *
203 * @param field Field to which the elements belong.
204 * @param d Array.
205 * @param pos Position of the first entry.
206 * @param size Number of entries to copy.
207 * @throws NullArgumentException if {@code d} is {@code null}.
208 * @throws NumberIsTooLargeException if the size of {@code d} is less
209 * than {@code pos + size}.
210 */
211 public ArrayFieldVector(Field<T> field, T[] d, int pos, int size) {
212 if (d == null) {
213 throw new NullArgumentException();
214 }
215 if (d.length < pos + size) {
216 throw new NumberIsTooLargeException(pos + size, d.length, true);
217 }
218 this.field = field;
219 data = buildArray(size);
220 System.arraycopy(d, pos, data, 0, size);
221 }
222
223 /**
224 * Construct a vector from another vector, using a deep copy.
225 *
226 * @param v Vector to copy.
227 * @throws NullArgumentException if {@code v} is {@code null}.
228 */
229 public ArrayFieldVector(FieldVector<T> v) {
230 if (v == null) {
231 throw new NullArgumentException();
232 }
233 field = v.getField();
234 data = buildArray(v.getDimension());
235 for (int i = 0; i < data.length; ++i) {
236 data[i] = v.getEntry(i);
237 }
238 }
239
240 /**
241 * Construct a vector from another vector, using a deep copy.
242 *
243 * @param v Vector to copy.
244 * @throws NullArgumentException if {@code v} is {@code null}.
245 */
246 public ArrayFieldVector(ArrayFieldVector<T> v) {
247 if (v == null) {
248 throw new NullArgumentException();
249 }
250 field = v.getField();
251 data = v.data.clone();
252 }
253
254 /**
255 * Construct a vector from another vector.
256 *
257 * @param v Vector to copy.
258 * @param deep If {@code true} perform a deep copy, otherwise perform
259 * a shallow copy
260 * @throws NullArgumentException if {@code v} is {@code null}.
261 */
262 public ArrayFieldVector(ArrayFieldVector<T> v, boolean deep) {
263 if (v == null) {
264 throw new NullArgumentException();
265 }
266 field = v.getField();
267 data = deep ? v.data.clone() : v.data;
268 }
269
270 /**
271 * Construct a vector by appending one vector to another vector.
272 *
273 * @param v1 First vector (will be put in front of the new vector).
274 * @param v2 Second vector (will be put at back of the new vector).
275 * @throws NullArgumentException if {@code v1} or {@code v2} is
276 * {@code null}.
277 */
278 public ArrayFieldVector(ArrayFieldVector<T> v1, ArrayFieldVector<T> v2) {
279 if (v1 == null ||
280 v2 == null) {
281 throw new NullArgumentException();
282 }
283 field = v1.getField();
284 data = buildArray(v1.data.length + v2.data.length);
285 System.arraycopy(v1.data, 0, data, 0, v1.data.length);
286 System.arraycopy(v2.data, 0, data, v1.data.length, v2.data.length);
287 }
288
289 /**
290 * Construct a vector by appending one vector to another vector.
291 *
292 * @param v1 First vector (will be put in front of the new vector).
293 * @param v2 Second vector (will be put at back of the new vector).
294 * @throws NullArgumentException if {@code v1} or {@code v2} is
295 * {@code null}.
296 */
297 public ArrayFieldVector(ArrayFieldVector<T> v1, T[] v2) {
298 if (v1 == null ||
299 v2 == null) {
300 throw new NullArgumentException();
301 }
302 field = v1.getField();
303 data = buildArray(v1.data.length + v2.length);
304 System.arraycopy(v1.data, 0, data, 0, v1.data.length);
305 System.arraycopy(v2, 0, data, v1.data.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, ArrayFieldVector<T> v2) {
317 if (v1 == null ||
318 v2 == null) {
319 throw new NullArgumentException();
320 }
321 field = v2.getField();
322 data = buildArray(v1.length + v2.data.length);
323 System.arraycopy(v1, 0, data, 0, v1.length);
324 System.arraycopy(v2.data, 0, data, v1.length, v2.data.length);
325 }
326
327 /**
328 * Construct a vector by appending one vector to another vector.
329 * This constructor needs at least one non-empty array to retrieve
330 * the field from its first element. This implies it cannot build
331 * 0 length vectors. To build vectors from any size, one should
332 * use the {@link #ArrayFieldVector(Field, FieldElement[], FieldElement[])}
333 * constructor.
334 *
335 * @param v1 First vector (will be put in front of the new vector).
336 * @param v2 Second vector (will be put at back of the new vector).
337 * @throws NullArgumentException if {@code v1} or {@code v2} is
338 * {@code null}.
339 * @throws ZeroException if both arrays are empty.
340 * @see #ArrayFieldVector(Field, FieldElement[], FieldElement[])
341 */
342 public ArrayFieldVector(T[] v1, T[] v2) {
343 if (v1 == null ||
344 v2 == null) {
345 throw new NullArgumentException();
346 }
347 if (v1.length + v2.length == 0) {
348 throw new ZeroException(LocalizedFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT);
349 }
350 data = buildArray(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 ZeroException if both arrays are empty.
365 * @see #ArrayFieldVector(FieldElement[], FieldElement[])
366 */
367 public ArrayFieldVector(Field<T> field, T[] v1, T[] v2) {
368 if (v1.length + v2.length == 0) {
369 throw new ZeroException(LocalizedFormats.VECTOR_MUST_HAVE_AT_LEAST_ONE_ELEMENT);
370 }
371 data = buildArray(v1.length + v2.length);
372 System.arraycopy(v1, 0, data, 0, v1.length);
373 System.arraycopy(v2, 0, data, v1.length, v2.length);
374 this.field = field;
375 }
376
377 /**
378 * Build an array of elements.
379 *
380 * @param length Size of the array to build.
381 * @return a new array.
382 */
383 @SuppressWarnings("unchecked") // field is of type T
384 private T[] buildArray(final int length) {
385 return (T[]) Array.newInstance(field.getRuntimeClass(), length);
386 }
387
388 /** {@inheritDoc} */
389 public Field<T> getField() {
390 return field;
391 }
392
393 /** {@inheritDoc} */
394 public FieldVector<T> copy() {
395 return new ArrayFieldVector<T>(this, true);
396 }
397
398 /** {@inheritDoc} */
399 public FieldVector<T> add(FieldVector<T> v) {
400 try {
401 return add((ArrayFieldVector<T>) v);
402 } catch (ClassCastException cce) {
403 checkVectorDimensions(v);
404 T[] out = buildArray(data.length);
405 for (int i = 0; i < data.length; i++) {
406 out[i] = data[i].add(v.getEntry(i));
407 }
408 return new ArrayFieldVector<T>(field, out, false);
409 }
410 }
411
412 /**
413 * Compute the sum of this and v.
414 * @param v vector to be added
415 * @return this + v
416 * @throws IllegalArgumentException if v is not the same size as this
417 */
418 public ArrayFieldVector<T> add(ArrayFieldVector<T> v) {
419 checkVectorDimensions(v.data.length);
420 T[] out = buildArray(data.length);
421 for (int i = 0; i < data.length; i++) {
422 out[i] = data[i].add(v.data[i]);
423 }
424 return new ArrayFieldVector<T>(field, out, false);
425 }
426
427 /** {@inheritDoc} */
428 public FieldVector<T> subtract(FieldVector<T> v) {
429 try {
430 return subtract((ArrayFieldVector<T>) v);
431 } catch (ClassCastException cce) {
432 checkVectorDimensions(v);
433 T[] out = buildArray(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<T>(field, out, false);
438 }
439 }
440
441 /**
442 * Compute this minus v.
443 * @param v vector to be subtracted
444 * @return this + v
445 * @throws IllegalArgumentException if v is not the same size as this
446 */
447 public ArrayFieldVector<T> subtract(ArrayFieldVector<T> v) {
448 checkVectorDimensions(v.data.length);
449 T[] out = buildArray(data.length);
450 for (int i = 0; i < data.length; i++) {
451 out[i] = data[i].subtract(v.data[i]);
452 }
453 return new ArrayFieldVector<T>(field, out, false);
454 }
455
456 /** {@inheritDoc} */
457 public FieldVector<T> mapAdd(T d) {
458 T[] out = buildArray(data.length);
459 for (int i = 0; i < data.length; i++) {
460 out[i] = data[i].add(d);
461 }
462 return new ArrayFieldVector<T>(field, out, false);
463 }
464
465 /** {@inheritDoc} */
466 public FieldVector<T> mapAddToSelf(T d) {
467 for (int i = 0; i < data.length; i++) {
468 data[i] = data[i].add(d);
469 }
470 return this;
471 }
472
473 /** {@inheritDoc} */
474 public FieldVector<T> mapSubtract(T d) {
475 T[] out = buildArray(data.length);
476 for (int i = 0; i < data.length; i++) {
477 out[i] = data[i].subtract(d);
478 }
479 return new ArrayFieldVector<T>(field, out, false);
480 }
481
482 /** {@inheritDoc} */
483 public FieldVector<T> mapSubtractToSelf(T d) {
484 for (int i = 0; i < data.length; i++) {
485 data[i] = data[i].subtract(d);
486 }
487 return this;
488 }
489
490 /** {@inheritDoc} */
491 public FieldVector<T> mapMultiply(T d) {
492 T[] out = buildArray(data.length);
493 for (int i = 0; i < data.length; i++) {
494 out[i] = data[i].multiply(d);
495 }
496 return new ArrayFieldVector<T>(field, out, false);
497 }
498
499 /** {@inheritDoc} */
500 public FieldVector<T> mapMultiplyToSelf(T d) {
501 for (int i = 0; i < data.length; i++) {
502 data[i] = data[i].multiply(d);
503 }
504 return this;
505 }
506
507 /** {@inheritDoc} */
508 public FieldVector<T> mapDivide(T d) {
509 T[] out = buildArray(data.length);
510 for (int i = 0; i < data.length; i++) {
511 out[i] = data[i].divide(d);
512 }
513 return new ArrayFieldVector<T>(field, out, false);
514 }
515
516 /** {@inheritDoc} */
517 public FieldVector<T> mapDivideToSelf(T d) {
518 for (int i = 0; i < data.length; i++) {
519 data[i] = data[i].divide(d);
520 }
521 return this;
522 }
523
524 /** {@inheritDoc} */
525 public FieldVector<T> mapInv() {
526 T[] out = buildArray(data.length);
527 final T one = field.getOne();
528 for (int i = 0; i < data.length; i++) {
529 out[i] = one.divide(data[i]);
530 }
531 return new ArrayFieldVector<T>(field, out, false);
532 }
533
534 /** {@inheritDoc} */
535 public FieldVector<T> mapInvToSelf() {
536 final T one = field.getOne();
537 for (int i = 0; i < data.length; i++) {
538 data[i] = one.divide(data[i]);
539 }
540 return this;
541 }
542
543 /** {@inheritDoc} */
544 public FieldVector<T> ebeMultiply(FieldVector<T> v) {
545 try {
546 return ebeMultiply((ArrayFieldVector<T>) v);
547 } catch (ClassCastException cce) {
548 checkVectorDimensions(v);
549 T[] out = buildArray(data.length);
550 for (int i = 0; i < data.length; i++) {
551 out[i] = data[i].multiply(v.getEntry(i));
552 }
553 return new ArrayFieldVector<T>(field, out, false);
554 }
555 }
556
557 /**
558 * Element-by-element multiplication.
559 * @param v vector by which instance elements must be multiplied
560 * @return a vector containing this[i] * v[i] for all i
561 * @exception IllegalArgumentException if v is not the same size as this
562 */
563 public ArrayFieldVector<T> ebeMultiply(ArrayFieldVector<T> v) {
564 checkVectorDimensions(v.data.length);
565 T[] out = buildArray(data.length);
566 for (int i = 0; i < data.length; i++) {
567 out[i] = data[i].multiply(v.data[i]);
568 }
569 return new ArrayFieldVector<T>(field, out, false);
570 }
571
572 /** {@inheritDoc} */
573 public FieldVector<T> ebeDivide(FieldVector<T> v) {
574 try {
575 return ebeDivide((ArrayFieldVector<T>) v);
576 } catch (ClassCastException cce) {
577 checkVectorDimensions(v);
578 T[] out = buildArray(data.length);
579 for (int i = 0; i < data.length; i++) {
580 out[i] = data[i].divide(v.getEntry(i));
581 }
582 return new ArrayFieldVector<T>(field, out, false);
583 }
584 }
585
586 /**
587 * Element-by-element division.
588 * @param v vector by which instance elements must be divided
589 * @return a vector containing this[i] / v[i] for all i
590 * @throws IllegalArgumentException if v is not the same size as this
591 */
592 public ArrayFieldVector<T> ebeDivide(ArrayFieldVector<T> v) {
593 checkVectorDimensions(v.data.length);
594 T[] out = buildArray(data.length);
595 for (int i = 0; i < data.length; i++) {
596 out[i] = data[i].divide(v.data[i]);
597 }
598 return new ArrayFieldVector<T>(field, out, false);
599 }
600
601 /** {@inheritDoc} */
602 public T[] getData() {
603 return data.clone();
604 }
605
606 /**
607 * Returns a reference to the underlying data array.
608 * <p>Does not make a fresh copy of the underlying data.</p>
609 * @return array of entries
610 */
611 public T[] getDataRef() {
612 return data;
613 }
614
615 /** {@inheritDoc} */
616 public T dotProduct(FieldVector<T> v) {
617 try {
618 return dotProduct((ArrayFieldVector<T>) v);
619 } catch (ClassCastException cce) {
620 checkVectorDimensions(v);
621 T dot = field.getZero();
622 for (int i = 0; i < data.length; i++) {
623 dot = dot.add(data[i].multiply(v.getEntry(i)));
624 }
625 return dot;
626 }
627 }
628
629 /**
630 * Compute the dot product.
631 * @param v vector with which dot product should be computed
632 * @return the scalar dot product between instance and v
633 * @exception IllegalArgumentException if v is not the same size as this
634 */
635 public T dotProduct(ArrayFieldVector<T> v) {
636 checkVectorDimensions(v.data.length);
637 T dot = field.getZero();
638 for (int i = 0; i < data.length; i++) {
639 dot = dot.add(data[i].multiply(v.data[i]));
640 }
641 return dot;
642 }
643
644 /** {@inheritDoc} */
645 public FieldVector<T> projection(FieldVector<T> v) {
646 return v.mapMultiply(dotProduct(v).divide(v.dotProduct(v)));
647 }
648
649 /** Find the orthogonal projection of this vector onto another vector.
650 * @param v vector onto which instance must be projected
651 * @return projection of the instance onto v
652 * @throws IllegalArgumentException if v is not the same size as this
653 */
654 public ArrayFieldVector<T> projection(ArrayFieldVector<T> v) {
655 return (ArrayFieldVector<T>) v.mapMultiply(dotProduct(v).divide(v.dotProduct(v)));
656 }
657
658 /** {@inheritDoc} */
659 public FieldMatrix<T> outerProduct(FieldVector<T> v) {
660 try {
661 return outerProduct((ArrayFieldVector<T>) v);
662 } catch (ClassCastException cce) {
663 final int m = data.length;
664 final int n = v.getDimension();
665 final FieldMatrix<T> out = new Array2DRowFieldMatrix<T>(field, m, n);
666 for (int i = 0; i < m; i++) {
667 for (int j = 0; j < n; j++) {
668 out.setEntry(i, j, data[i].multiply(v.getEntry(j)));
669 }
670 }
671 return out;
672 }
673 }
674
675 /**
676 * Compute the outer product.
677 * @param v vector with which outer product should be computed
678 * @return the square matrix outer product between instance and v
679 * @exception IllegalArgumentException if v is not the same size as this
680 */
681 public FieldMatrix<T> outerProduct(ArrayFieldVector<T> v) {
682 final int m = data.length;
683 final int n = v.data.length;
684 final FieldMatrix<T> out = new Array2DRowFieldMatrix<T>(field, m, n);
685 for (int i = 0; i < m; i++) {
686 for (int j = 0; j < n; j++) {
687 out.setEntry(i, j, data[i].multiply(v.data[j]));
688 }
689 }
690 return out;
691 }
692
693 /** {@inheritDoc} */
694 public T getEntry(int index) {
695 return data[index];
696 }
697
698 /** {@inheritDoc} */
699 public int getDimension() {
700 return data.length;
701 }
702
703 /** {@inheritDoc} */
704 public FieldVector<T> append(FieldVector<T> v) {
705 try {
706 return append((ArrayFieldVector<T>) v);
707 } catch (ClassCastException cce) {
708 return new ArrayFieldVector<T>(this,new ArrayFieldVector<T>(v));
709 }
710 }
711
712 /**
713 * Construct a vector by appending a vector to this vector.
714 * @param v vector to append to this one.
715 * @return a new vector
716 */
717 public ArrayFieldVector<T> append(ArrayFieldVector<T> v) {
718 return new ArrayFieldVector<T>(this, v);
719 }
720
721 /** {@inheritDoc} */
722 public FieldVector<T> append(T in) {
723 final T[] out = buildArray(data.length + 1);
724 System.arraycopy(data, 0, out, 0, data.length);
725 out[data.length] = in;
726 return new ArrayFieldVector<T>(field, out, false);
727 }
728
729 /** {@inheritDoc} */
730 public FieldVector<T> getSubVector(int index, int n) {
731 ArrayFieldVector<T> out = new ArrayFieldVector<T>(field, n);
732 try {
733 System.arraycopy(data, index, out.data, 0, n);
734 } catch (IndexOutOfBoundsException e) {
735 checkIndex(index);
736 checkIndex(index + n - 1);
737 }
738 return out;
739 }
740
741 /** {@inheritDoc} */
742 public void setEntry(int index, T value) {
743 try {
744 data[index] = value;
745 } catch (IndexOutOfBoundsException e) {
746 checkIndex(index);
747 }
748 }
749
750 /** {@inheritDoc} */
751 public void setSubVector(int index, FieldVector<T> v) {
752 try {
753 try {
754 set(index, (ArrayFieldVector<T>) v);
755 } catch (ClassCastException cce) {
756 for (int i = index; i < index + v.getDimension(); ++i) {
757 data[i] = v.getEntry(i-index);
758 }
759 }
760 } catch (IndexOutOfBoundsException e) {
761 checkIndex(index);
762 checkIndex(index + v.getDimension() - 1);
763 }
764 }
765
766 /**
767 * Set a set of consecutive elements.
768 *
769 * @param index index of first element to be set.
770 * @param v vector containing the values to set.
771 * @throws OutOfRangeException if the index is
772 * inconsistent with vector size
773 */
774 public void set(int index, ArrayFieldVector<T> v) {
775 try {
776 System.arraycopy(v.data, 0, data, index, v.data.length);
777 } catch (IndexOutOfBoundsException e) {
778 checkIndex(index);
779 checkIndex(index + v.data.length - 1);
780 }
781 }
782
783 /** {@inheritDoc} */
784 public void set(T value) {
785 Arrays.fill(data, value);
786 }
787
788 /** {@inheritDoc} */
789 public T[] toArray(){
790 return data.clone();
791 }
792
793 /**
794 * Check if instance and specified vectors have the same dimension.
795 * @param v vector to compare instance with
796 * @exception IllegalArgumentException if the vectors do not
797 * have the same dimension
798 */
799 protected void checkVectorDimensions(FieldVector<T> v) {
800 checkVectorDimensions(v.getDimension());
801 }
802
803 /**
804 * Check if instance dimension is equal to some expected value.
805 *
806 * @param n Expected dimension.
807 * @throws OutOfRangeException if the dimension is
808 * inconsistent with this vector size.
809 */
810 protected void checkVectorDimensions(int n) {
811 if (data.length != n) {
812 throw new DimensionMismatchException(data.length, n);
813 }
814 }
815
816 /**
817 * Test for the equality of two vectors.
818 *
819 * @param other Object to test for equality.
820 * @return {@code true} if two vector objects are equal, {@code false}
821 * otherwise.
822 */
823 @Override
824 public boolean equals(Object other) {
825 if (this == other) {
826 return true;
827 }
828 if (other == null) {
829 return false;
830 }
831
832 try {
833 @SuppressWarnings("unchecked") // May fail, but we ignore ClassCastException
834 FieldVector<T> rhs = (FieldVector<T>) other;
835 if (data.length != rhs.getDimension()) {
836 return false;
837 }
838
839 for (int i = 0; i < data.length; ++i) {
840 if (!data[i].equals(rhs.getEntry(i))) {
841 return false;
842 }
843 }
844 return true;
845 } catch (ClassCastException ex) {
846 // ignore exception
847 return false;
848 }
849 }
850
851 /**
852 * Get a hashCode for the real vector.
853 * <p>All NaN values have the same hash code.</p>
854 * @return a hash code value for this object
855 */
856 @Override
857 public int hashCode() {
858 int h = 3542;
859 for (final T a : data) {
860 h = h ^ a.hashCode();
861 }
862 return h;
863 }
864
865 /**
866 * Check if an index is valid.
867 *
868 * @param index Index to check.
869 * @exception OutOfRangeException if the index is not valid.
870 */
871 private void checkIndex(final int index) {
872 if (index < 0 || index >= getDimension()) {
873 throw new OutOfRangeException(LocalizedFormats.INDEX,
874 index, 0, getDimension() - 1);
875 }
876 }
877 }