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.util.Arrays;
021 import java.util.Iterator;
022
023 import org.apache.commons.math.MathRuntimeException;
024 import org.apache.commons.math.util.MathUtils;
025
026 /**
027 * This class implements the {@link RealVector} interface with a double array.
028 * @version $Revision: 902203 $ $Date: 2010-01-22 13:27:41 -0500 (Fri, 22 Jan 2010) $
029 * @since 2.0
030 */
031 public class ArrayRealVector extends AbstractRealVector implements Serializable {
032
033 /** Message for non fitting position and size. */
034 private static final String NON_FITTING_POSITION_AND_SIZE_MESSAGE =
035 "position {0} and size {1} don't fit to the size of the input array {2}";
036
037 /** Serializable version identifier. */
038 private static final long serialVersionUID = -1097961340710804027L;
039
040 /** Default format. */
041 private static final RealVectorFormat DEFAULT_FORMAT =
042 RealVectorFormat.getInstance();
043
044 /** Entries of the vector. */
045 protected double data[];
046
047 /**
048 * Build a 0-length vector.
049 * <p>Zero-length vectors may be used to initialized construction of vectors
050 * by data gathering. We start with zero-length and use either the {@link
051 * #ArrayRealVector(ArrayRealVector, ArrayRealVector)} constructor
052 * or one of the <code>append</code> method ({@link #append(double)}, {@link
053 * #append(double[])}, {@link #append(ArrayRealVector)}) to gather data
054 * into this vector.</p>
055 */
056 public ArrayRealVector() {
057 data = new double[0];
058 }
059
060 /**
061 * Construct a (size)-length vector of zeros.
062 * @param size size of the vector
063 */
064 public ArrayRealVector(int size) {
065 data = new double[size];
066 }
067
068 /**
069 * Construct an (size)-length vector with preset values.
070 * @param size size of the vector
071 * @param preset fill the vector with this scalar value
072 */
073 public ArrayRealVector(int size, double preset) {
074 data = new double[size];
075 Arrays.fill(data, preset);
076 }
077
078 /**
079 * Construct a vector from an array, copying the input array.
080 * @param d array of doubles.
081 */
082 public ArrayRealVector(double[] d) {
083 data = d.clone();
084 }
085
086 /**
087 * Create a new ArrayRealVector using the input array as the underlying
088 * data array.
089 * <p>If an array is built specially in order to be embedded in a
090 * ArrayRealVector and not used directly, the <code>copyArray</code> may be
091 * set to <code>false</code. This will prevent the copying and improve
092 * performance as no new array will be built and no data will be copied.</p>
093 * @param d data for new vector
094 * @param copyArray if true, the input array will be copied, otherwise
095 * it will be referenced
096 * @throws IllegalArgumentException if <code>d</code> is empty
097 * @throws NullPointerException if <code>d</code> is null
098 * @see #ArrayRealVector(double[])
099 */
100 public ArrayRealVector(double[] d, boolean copyArray)
101 throws NullPointerException, IllegalArgumentException {
102 if (d == null) {
103 throw new NullPointerException();
104 }
105 if (d.length == 0) {
106 throw MathRuntimeException.createIllegalArgumentException("vector must have at least one element");
107 }
108 data = copyArray ? d.clone() : d;
109 }
110
111 /**
112 * Construct a vector from part of a array.
113 * @param d array of doubles.
114 * @param pos position of first entry
115 * @param size number of entries to copy
116 */
117 public ArrayRealVector(double[] d, int pos, int size) {
118 if (d.length < pos + size) {
119 throw MathRuntimeException.createIllegalArgumentException(
120 NON_FITTING_POSITION_AND_SIZE_MESSAGE, pos, size, d.length);
121 }
122 data = new double[size];
123 System.arraycopy(d, pos, data, 0, size);
124 }
125
126 /**
127 * Construct a vector from an array.
128 * @param d array of Doubles.
129 */
130 public ArrayRealVector(Double[] d) {
131 data = new double[d.length];
132 for (int i = 0; i < d.length; i++) {
133 data[i] = d[i].doubleValue();
134 }
135 }
136
137 /**
138 * Construct a vector from part of a Double array
139 * @param d array of Doubles.
140 * @param pos position of first entry
141 * @param size number of entries to copy
142 */
143 public ArrayRealVector(Double[] d, int pos, int size) {
144 if (d.length < pos + size) {
145 throw MathRuntimeException.createIllegalArgumentException(
146 NON_FITTING_POSITION_AND_SIZE_MESSAGE, pos, size, d.length);
147 }
148 data = new double[size];
149 for (int i = pos; i < pos + size; i++) {
150 data[i-pos] = d[i].doubleValue();
151 }
152 }
153
154 /**
155 * Construct a vector from another vector, using a deep copy.
156 * @param v vector to copy
157 */
158 public ArrayRealVector(RealVector v) {
159 data = new double[v.getDimension()];
160 for (int i = 0; i < data.length; ++i) {
161 data[i] = v.getEntry(i);
162 }
163 }
164
165 /**
166 * Construct a vector from another vector, using a deep copy.
167 * @param v vector to copy
168 */
169 public ArrayRealVector(ArrayRealVector v) {
170 this(v, true);
171 }
172
173 /**
174 * Construct a vector from another vector.
175 * @param v vector to copy
176 * @param deep if true perform a deep copy otherwise perform a shallow copy
177 */
178 public ArrayRealVector(ArrayRealVector v, boolean deep) {
179 data = deep ? v.data.clone() : v.data;
180 }
181
182 /**
183 * Construct a vector by appending one vector to another vector.
184 * @param v1 first vector (will be put in front of the new vector)
185 * @param v2 second vector (will be put at back of the new vector)
186 */
187 public ArrayRealVector(ArrayRealVector v1, ArrayRealVector v2) {
188 data = new double[v1.data.length + v2.data.length];
189 System.arraycopy(v1.data, 0, data, 0, v1.data.length);
190 System.arraycopy(v2.data, 0, data, v1.data.length, v2.data.length);
191 }
192
193 /**
194 * Construct a vector by appending one vector to another vector.
195 * @param v1 first vector (will be put in front of the new vector)
196 * @param v2 second vector (will be put at back of the new vector)
197 */
198 public ArrayRealVector(ArrayRealVector v1, RealVector v2) {
199 final int l1 = v1.data.length;
200 final int l2 = v2.getDimension();
201 data = new double[l1 + l2];
202 System.arraycopy(v1.data, 0, data, 0, l1);
203 for (int i = 0; i < l2; ++i) {
204 data[l1 + i] = v2.getEntry(i);
205 }
206 }
207
208 /**
209 * Construct a vector by appending one vector to another vector.
210 * @param v1 first vector (will be put in front of the new vector)
211 * @param v2 second vector (will be put at back of the new vector)
212 */
213 public ArrayRealVector(RealVector v1, ArrayRealVector v2) {
214 final int l1 = v1.getDimension();
215 final int l2 = v2.data.length;
216 data = new double[l1 + l2];
217 for (int i = 0; i < l1; ++i) {
218 data[i] = v1.getEntry(i);
219 }
220 System.arraycopy(v2.data, 0, data, l1, l2);
221 }
222
223 /**
224 * Construct a vector by appending one vector to another vector.
225 * @param v1 first vector (will be put in front of the new vector)
226 * @param v2 second vector (will be put at back of the new vector)
227 */
228 public ArrayRealVector(ArrayRealVector v1, double[] v2) {
229 final int l1 = v1.getDimension();
230 final int l2 = v2.length;
231 data = new double[l1 + l2];
232 System.arraycopy(v1.data, 0, data, 0, l1);
233 System.arraycopy(v2, 0, data, l1, l2);
234 }
235
236 /**
237 * Construct a vector by appending one vector to another vector.
238 * @param v1 first vector (will be put in front of the new vector)
239 * @param v2 second vector (will be put at back of the new vector)
240 */
241 public ArrayRealVector(double[] v1, ArrayRealVector v2) {
242 final int l1 = v1.length;
243 final int l2 = v2.getDimension();
244 data = new double[l1 + l2];
245 System.arraycopy(v1, 0, data, 0, l1);
246 System.arraycopy(v2.data, 0, data, l1, l2);
247 }
248
249 /**
250 * Construct a vector by appending one vector to another vector.
251 * @param v1 first vector (will be put in front of the new vector)
252 * @param v2 second vector (will be put at back of the new vector)
253 */
254 public ArrayRealVector(double[] v1, double[] v2) {
255 final int l1 = v1.length;
256 final int l2 = v2.length;
257 data = new double[l1 + l2];
258 System.arraycopy(v1, 0, data, 0, l1);
259 System.arraycopy(v2, 0, data, l1, l2);
260 }
261
262 /** {@inheritDoc} */
263 @Override
264 public AbstractRealVector copy() {
265 return new ArrayRealVector(this, true);
266 }
267
268 /** {@inheritDoc} */
269 @Override
270 public RealVector add(RealVector v)
271 throws IllegalArgumentException {
272 if (v instanceof ArrayRealVector) {
273 return add((ArrayRealVector) v);
274 } else {
275 checkVectorDimensions(v);
276 double[] out = data.clone();
277 Iterator<Entry> it = v.sparseIterator();
278 Entry e;
279 while (it.hasNext() && (e = it.next()) != null) {
280 out[e.getIndex()] += e.getValue();
281 }
282 return new ArrayRealVector(out, false);
283 }
284 }
285
286 /** {@inheritDoc} */
287 @Override
288 public RealVector add(double[] v)
289 throws IllegalArgumentException {
290 checkVectorDimensions(v.length);
291 double[] out = data.clone();
292 for (int i = 0; i < data.length; i++) {
293 out[i] += v[i];
294 }
295 return new ArrayRealVector(out, false);
296 }
297
298 /**
299 * Compute the sum of this and v.
300 * @param v vector to be added
301 * @return this + v
302 * @throws IllegalArgumentException if v is not the same size as this
303 */
304 public ArrayRealVector add(ArrayRealVector v)
305 throws IllegalArgumentException {
306 return (ArrayRealVector) add(v.data);
307 }
308
309 /** {@inheritDoc} */
310 @Override
311 public RealVector subtract(RealVector v)
312 throws IllegalArgumentException {
313 if (v instanceof ArrayRealVector) {
314 return subtract((ArrayRealVector) v);
315 } else {
316 checkVectorDimensions(v);
317 double[] out = data.clone();
318 Iterator<Entry> it = v.sparseIterator();
319 Entry e;
320 while(it.hasNext() && (e = it.next()) != null) {
321 out[e.getIndex()] -= e.getValue();
322 }
323 return new ArrayRealVector(out, false);
324 }
325 }
326
327 /** {@inheritDoc} */
328 @Override
329 public RealVector subtract(double[] v)
330 throws IllegalArgumentException {
331 checkVectorDimensions(v.length);
332 double[] out = data.clone();
333 for (int i = 0; i < data.length; i++) {
334 out[i] -= v[i];
335 }
336 return new ArrayRealVector(out, false);
337 }
338
339 /**
340 * Compute this minus v.
341 * @param v vector to be subtracted
342 * @return this + v
343 * @throws IllegalArgumentException if v is not the same size as this
344 */
345 public ArrayRealVector subtract(ArrayRealVector v)
346 throws IllegalArgumentException {
347 return (ArrayRealVector) subtract(v.data);
348 }
349
350 /** {@inheritDoc} */
351 @Override
352 public RealVector mapAddToSelf(double d) {
353 for (int i = 0; i < data.length; i++) {
354 data[i] = data[i] + d;
355 }
356 return this;
357 }
358
359 /** {@inheritDoc} */
360 @Override
361 public RealVector mapSubtractToSelf(double d) {
362 for (int i = 0; i < data.length; i++) {
363 data[i] = data[i] - d;
364 }
365 return this;
366 }
367
368 /** {@inheritDoc} */
369 @Override
370 public RealVector mapMultiplyToSelf(double d) {
371 for (int i = 0; i < data.length; i++) {
372 data[i] = data[i] * d;
373 }
374 return this;
375 }
376
377 /** {@inheritDoc} */
378 @Override
379 public RealVector mapDivideToSelf(double d) {
380 for (int i = 0; i < data.length; i++) {
381 data[i] = data[i] / d;
382 }
383 return this;
384 }
385
386 /** {@inheritDoc} */
387 @Override
388 public RealVector mapPowToSelf(double d) {
389 for (int i = 0; i < data.length; i++) {
390 data[i] = Math.pow(data[i], d);
391 }
392 return this;
393 }
394
395 /** {@inheritDoc} */
396 @Override
397 public RealVector mapExpToSelf() {
398 for (int i = 0; i < data.length; i++) {
399 data[i] = Math.exp(data[i]);
400 }
401 return this;
402 }
403
404 /** {@inheritDoc} */
405 @Override
406 public RealVector mapExpm1ToSelf() {
407 for (int i = 0; i < data.length; i++) {
408 data[i] = Math.expm1(data[i]);
409 }
410 return this;
411 }
412
413 /** {@inheritDoc} */
414 @Override
415 public RealVector mapLogToSelf() {
416 for (int i = 0; i < data.length; i++) {
417 data[i] = Math.log(data[i]);
418 }
419 return this;
420 }
421
422 /** {@inheritDoc} */
423 @Override
424 public RealVector mapLog10ToSelf() {
425 for (int i = 0; i < data.length; i++) {
426 data[i] = Math.log10(data[i]);
427 }
428 return this;
429 }
430
431 /** {@inheritDoc} */
432 @Override
433 public RealVector mapLog1pToSelf() {
434 for (int i = 0; i < data.length; i++) {
435 data[i] = Math.log1p(data[i]);
436 }
437 return this;
438 }
439
440 /** {@inheritDoc} */
441 @Override
442 public RealVector mapCoshToSelf() {
443 for (int i = 0; i < data.length; i++) {
444 data[i] = Math.cosh(data[i]);
445 }
446 return this;
447 }
448
449 /** {@inheritDoc} */
450 @Override
451 public RealVector mapSinhToSelf() {
452 for (int i = 0; i < data.length; i++) {
453 data[i] = Math.sinh(data[i]);
454 }
455 return this;
456 }
457
458 /** {@inheritDoc} */
459 @Override
460 public RealVector mapTanhToSelf() {
461 for (int i = 0; i < data.length; i++) {
462 data[i] = Math.tanh(data[i]);
463 }
464 return this;
465 }
466
467 /** {@inheritDoc} */
468 @Override
469 public RealVector mapCosToSelf() {
470 for (int i = 0; i < data.length; i++) {
471 data[i] = Math.cos(data[i]);
472 }
473 return this;
474 }
475
476 /** {@inheritDoc} */
477 @Override
478 public RealVector mapSinToSelf() {
479 for (int i = 0; i < data.length; i++) {
480 data[i] = Math.sin(data[i]);
481 }
482 return this;
483 }
484
485 /** {@inheritDoc} */
486 @Override
487 public RealVector mapTanToSelf() {
488 for (int i = 0; i < data.length; i++) {
489 data[i] = Math.tan(data[i]);
490 }
491 return this;
492 }
493
494 /** {@inheritDoc} */
495 @Override
496 public RealVector mapAcosToSelf() {
497 for (int i = 0; i < data.length; i++) {
498 data[i] = Math.acos(data[i]);
499 }
500 return this;
501 }
502
503 /** {@inheritDoc} */
504 @Override
505 public RealVector mapAsinToSelf() {
506 for (int i = 0; i < data.length; i++) {
507 data[i] = Math.asin(data[i]);
508 }
509 return this;
510 }
511
512 /** {@inheritDoc} */
513 @Override
514 public RealVector mapAtanToSelf() {
515 for (int i = 0; i < data.length; i++) {
516 data[i] = Math.atan(data[i]);
517 }
518 return this;
519 }
520
521 /** {@inheritDoc} */
522 @Override
523 public RealVector mapInvToSelf() {
524 for (int i = 0; i < data.length; i++) {
525 data[i] = 1.0 / data[i];
526 }
527 return this;
528 }
529
530 /** {@inheritDoc} */
531 @Override
532 public RealVector mapAbsToSelf() {
533 for (int i = 0; i < data.length; i++) {
534 data[i] = Math.abs(data[i]);
535 }
536 return this;
537 }
538
539 /** {@inheritDoc} */
540 @Override
541 public RealVector mapSqrtToSelf() {
542 for (int i = 0; i < data.length; i++) {
543 data[i] = Math.sqrt(data[i]);
544 }
545 return this;
546 }
547
548 /** {@inheritDoc} */
549 @Override
550 public RealVector mapCbrtToSelf() {
551 for (int i = 0; i < data.length; i++) {
552 data[i] = Math.cbrt(data[i]);
553 }
554 return this;
555 }
556
557 /** {@inheritDoc} */
558 @Override
559 public RealVector mapCeilToSelf() {
560 for (int i = 0; i < data.length; i++) {
561 data[i] = Math.ceil(data[i]);
562 }
563 return this;
564 }
565
566 /** {@inheritDoc} */
567 @Override
568 public RealVector mapFloorToSelf() {
569 for (int i = 0; i < data.length; i++) {
570 data[i] = Math.floor(data[i]);
571 }
572 return this;
573 }
574
575 /** {@inheritDoc} */
576 @Override
577 public RealVector mapRintToSelf() {
578 for (int i = 0; i < data.length; i++) {
579 data[i] = Math.rint(data[i]);
580 }
581 return this;
582 }
583
584 /** {@inheritDoc} */
585 @Override
586 public RealVector mapSignumToSelf() {
587 for (int i = 0; i < data.length; i++) {
588 data[i] = Math.signum(data[i]);
589 }
590 return this;
591 }
592
593 /** {@inheritDoc} */
594 @Override
595 public RealVector mapUlpToSelf() {
596 for (int i = 0; i < data.length; i++) {
597 data[i] = Math.ulp(data[i]);
598 }
599 return this;
600 }
601
602 /** {@inheritDoc} */
603 public RealVector ebeMultiply(RealVector v)
604 throws IllegalArgumentException {
605 if (v instanceof ArrayRealVector) {
606 return ebeMultiply((ArrayRealVector) v);
607 } else {
608 checkVectorDimensions(v);
609 double[] out = data.clone();
610 for (int i = 0; i < data.length; i++) {
611 out[i] *= v.getEntry(i);
612 }
613 return new ArrayRealVector(out, false);
614 }
615 }
616
617 /** {@inheritDoc} */
618 @Override
619 public RealVector ebeMultiply(double[] v)
620 throws IllegalArgumentException {
621 checkVectorDimensions(v.length);
622 double[] out = data.clone();
623 for (int i = 0; i < data.length; i++) {
624 out[i] *= v[i];
625 }
626 return new ArrayRealVector(out, false);
627 }
628
629 /**
630 * Element-by-element multiplication.
631 * @param v vector by which instance elements must be multiplied
632 * @return a vector containing this[i] * v[i] for all i
633 * @exception IllegalArgumentException if v is not the same size as this
634 */
635 public ArrayRealVector ebeMultiply(ArrayRealVector v)
636 throws IllegalArgumentException {
637 return (ArrayRealVector) ebeMultiply(v.data);
638 }
639
640 /** {@inheritDoc} */
641 public RealVector ebeDivide(RealVector v)
642 throws IllegalArgumentException {
643 if (v instanceof ArrayRealVector) {
644 return ebeDivide((ArrayRealVector) v);
645 } else {
646 checkVectorDimensions(v);
647 double[] out = data.clone();
648 for (int i = 0; i < data.length; i++) {
649 out[i] /= v.getEntry(i);
650 }
651 return new ArrayRealVector(out, false);
652 }
653 }
654
655 /** {@inheritDoc} */
656 @Override
657 public RealVector ebeDivide(double[] v)
658 throws IllegalArgumentException {
659 checkVectorDimensions(v.length);
660 double[] out = data.clone();
661 for (int i = 0; i < data.length; i++) {
662 out[i] /= v[i];
663 }
664 return new ArrayRealVector(out, false);
665 }
666
667 /**
668 * Element-by-element division.
669 * @param v vector by which instance elements must be divided
670 * @return a vector containing this[i] / v[i] for all i
671 * @throws IllegalArgumentException if v is not the same size as this
672 */
673 public ArrayRealVector ebeDivide(ArrayRealVector v)
674 throws IllegalArgumentException {
675 return (ArrayRealVector) ebeDivide(v.data);
676 }
677
678 /** {@inheritDoc} */
679 @Override
680 public double[] getData() {
681 return data.clone();
682 }
683
684 /**
685 * Returns a reference to the underlying data array.
686 * <p>Does not make a fresh copy of the underlying data.</p>
687 * @return array of entries
688 */
689 public double[] getDataRef() {
690 return data;
691 }
692
693 /** {@inheritDoc} */
694 @Override
695 public double dotProduct(RealVector v)
696 throws IllegalArgumentException {
697 if (v instanceof ArrayRealVector) {
698 return dotProduct((ArrayRealVector) v);
699 } else {
700 checkVectorDimensions(v);
701 double dot = 0;
702 Iterator<Entry> it = v.sparseIterator();
703 Entry e;
704 while(it.hasNext() && (e = it.next()) != null) {
705 dot += data[e.getIndex()] * e.getValue();
706 }
707 return dot;
708 }
709 }
710
711 /** {@inheritDoc} */
712 @Override
713 public double dotProduct(double[] v)
714 throws IllegalArgumentException {
715 checkVectorDimensions(v.length);
716 double dot = 0;
717 for (int i = 0; i < data.length; i++) {
718 dot += data[i] * v[i];
719 }
720 return dot;
721 }
722
723 /**
724 * Compute the dot product.
725 * @param v vector with which dot product should be computed
726 * @return the scalar dot product between instance and v
727 * @exception IllegalArgumentException if v is not the same size as this
728 */
729 public double dotProduct(ArrayRealVector v)
730 throws IllegalArgumentException {
731 return dotProduct(v.data);
732 }
733
734 /** {@inheritDoc} */
735 @Override
736 public double getNorm() {
737 double sum = 0;
738 for (double a : data) {
739 sum += a * a;
740 }
741 return Math.sqrt(sum);
742 }
743
744 /** {@inheritDoc} */
745 @Override
746 public double getL1Norm() {
747 double sum = 0;
748 for (double a : data) {
749 sum += Math.abs(a);
750 }
751 return sum;
752 }
753
754 /** {@inheritDoc} */
755 @Override
756 public double getLInfNorm() {
757 double max = 0;
758 for (double a : data) {
759 max = Math.max(max, Math.abs(a));
760 }
761 return max;
762 }
763
764 /** {@inheritDoc} */
765 @Override
766 public double getDistance(RealVector v)
767 throws IllegalArgumentException {
768 if (v instanceof ArrayRealVector) {
769 return getDistance((ArrayRealVector) v);
770 } else {
771 checkVectorDimensions(v);
772 double sum = 0;
773 for (int i = 0; i < data.length; ++i) {
774 final double delta = data[i] - v.getEntry(i);
775 sum += delta * delta;
776 }
777 return Math.sqrt(sum);
778 }
779 }
780
781 /** {@inheritDoc} */
782 @Override
783 public double getDistance(double[] v)
784 throws IllegalArgumentException {
785 checkVectorDimensions(v.length);
786 double sum = 0;
787 for (int i = 0; i < data.length; ++i) {
788 final double delta = data[i] - v[i];
789 sum += delta * delta;
790 }
791 return Math.sqrt(sum);
792 }
793
794 /**
795 * Distance between two vectors.
796 * <p>This method computes the distance consistent with the
797 * L<sub>2</sub> norm, i.e. the square root of the sum of
798 * elements differences, or euclidian distance.</p>
799 * @param v vector to which distance is requested
800 * @return distance between two vectors.
801 * @exception IllegalArgumentException if v is not the same size as this
802 * @see #getDistance(RealVector)
803 * @see #getL1Distance(ArrayRealVector)
804 * @see #getLInfDistance(ArrayRealVector)
805 * @see #getNorm()
806 */
807 public double getDistance(ArrayRealVector v)
808 throws IllegalArgumentException {
809 return getDistance(v.data);
810 }
811
812 /** {@inheritDoc} */
813 @Override
814 public double getL1Distance(RealVector v)
815 throws IllegalArgumentException {
816 if (v instanceof ArrayRealVector) {
817 return getL1Distance((ArrayRealVector) v);
818 } else {
819 checkVectorDimensions(v);
820 double sum = 0;
821 for (int i = 0; i < data.length; ++i) {
822 final double delta = data[i] - v.getEntry(i);
823 sum += Math.abs(delta);
824 }
825 return sum;
826 }
827 }
828
829 /** {@inheritDoc} */
830 @Override
831 public double getL1Distance(double[] v)
832 throws IllegalArgumentException {
833 checkVectorDimensions(v.length);
834 double sum = 0;
835 for (int i = 0; i < data.length; ++i) {
836 final double delta = data[i] - v[i];
837 sum += Math.abs(delta);
838 }
839 return sum;
840 }
841
842 /**
843 * Distance between two vectors.
844 * <p>This method computes the distance consistent with
845 * L<sub>1</sub> norm, i.e. the sum of the absolute values of
846 * elements differences.</p>
847 * @param v vector to which distance is requested
848 * @return distance between two vectors.
849 * @exception IllegalArgumentException if v is not the same size as this
850 * @see #getDistance(RealVector)
851 * @see #getL1Distance(ArrayRealVector)
852 * @see #getLInfDistance(ArrayRealVector)
853 * @see #getNorm()
854 */
855 public double getL1Distance(ArrayRealVector v)
856 throws IllegalArgumentException {
857 return getL1Distance(v.data);
858 }
859
860 /** {@inheritDoc} */
861 @Override
862 public double getLInfDistance(RealVector v)
863 throws IllegalArgumentException {
864 if (v instanceof ArrayRealVector) {
865 return getLInfDistance((ArrayRealVector) v);
866 } else {
867 checkVectorDimensions(v);
868 double max = 0;
869 for (int i = 0; i < data.length; ++i) {
870 final double delta = data[i] - v.getEntry(i);
871 max = Math.max(max, Math.abs(delta));
872 }
873 return max;
874 }
875 }
876
877 /** {@inheritDoc} */
878 @Override
879 public double getLInfDistance(double[] v)
880 throws IllegalArgumentException {
881 checkVectorDimensions(v.length);
882 double max = 0;
883 for (int i = 0; i < data.length; ++i) {
884 final double delta = data[i] - v[i];
885 max = Math.max(max, Math.abs(delta));
886 }
887 return max;
888 }
889
890 /**
891 * Distance between two vectors.
892 * <p>This method computes the distance consistent with
893 * L<sub>∞</sub> norm, i.e. the max of the absolute values of
894 * elements differences.</p>
895 * @param v vector to which distance is requested
896 * @return distance between two vectors.
897 * @exception IllegalArgumentException if v is not the same size as this
898 * @see #getDistance(RealVector)
899 * @see #getL1Distance(ArrayRealVector)
900 * @see #getLInfDistance(ArrayRealVector)
901 * @see #getNorm()
902 */
903 public double getLInfDistance(ArrayRealVector v)
904 throws IllegalArgumentException {
905 return getLInfDistance(v.data);
906 }
907
908 /** {@inheritDoc} */
909 @Override
910 public RealVector unitVector() throws ArithmeticException {
911 final double norm = getNorm();
912 if (norm == 0) {
913 throw MathRuntimeException.createArithmeticException("zero norm");
914 }
915 return mapDivide(norm);
916 }
917
918 /** {@inheritDoc} */
919 @Override
920 public void unitize() throws ArithmeticException {
921 final double norm = getNorm();
922 if (norm == 0) {
923 throw MathRuntimeException.createArithmeticException("cannot normalize a zero norm vector");
924 }
925 mapDivideToSelf(norm);
926 }
927
928 /** {@inheritDoc} */
929 public RealVector projection(RealVector v) {
930 return v.mapMultiply(dotProduct(v) / v.dotProduct(v));
931 }
932
933 /** {@inheritDoc} */
934 @Override
935 public RealVector projection(double[] v) {
936 return projection(new ArrayRealVector(v, false));
937 }
938
939 /** Find the orthogonal projection of this vector onto another vector.
940 * @param v vector onto which instance must be projected
941 * @return projection of the instance onto v
942 * @throws IllegalArgumentException if v is not the same size as this
943 */
944 public ArrayRealVector projection(ArrayRealVector v) {
945 return (ArrayRealVector) v.mapMultiply(dotProduct(v) / v.dotProduct(v));
946 }
947
948 /** {@inheritDoc} */
949 @Override
950 public RealMatrix outerProduct(RealVector v)
951 throws IllegalArgumentException {
952 if (v instanceof ArrayRealVector) {
953 return outerProduct((ArrayRealVector) v);
954 } else {
955 checkVectorDimensions(v);
956 final int m = data.length;
957 final RealMatrix out = MatrixUtils.createRealMatrix(m, m);
958 for (int i = 0; i < data.length; i++) {
959 for (int j = 0; j < data.length; j++) {
960 out.setEntry(i, j, data[i] * v.getEntry(j));
961 }
962 }
963 return out;
964 }
965 }
966
967 /**
968 * Compute the outer product.
969 * @param v vector with which outer product should be computed
970 * @return the square matrix outer product between instance and v
971 * @exception IllegalArgumentException if v is not the same size as this
972 */
973 public RealMatrix outerProduct(ArrayRealVector v)
974 throws IllegalArgumentException {
975 return outerProduct(v.data);
976 }
977
978 /** {@inheritDoc} */
979 @Override
980 public RealMatrix outerProduct(double[] v)
981 throws IllegalArgumentException {
982 checkVectorDimensions(v.length);
983 final int m = data.length;
984 final RealMatrix out = MatrixUtils.createRealMatrix(m, m);
985 for (int i = 0; i < data.length; i++) {
986 for (int j = 0; j < data.length; j++) {
987 out.setEntry(i, j, data[i] * v[j]);
988 }
989 }
990 return out;
991 }
992
993 /** {@inheritDoc} */
994 public double getEntry(int index) throws MatrixIndexException {
995 return data[index];
996 }
997
998 /** {@inheritDoc} */
999 public int getDimension() {
1000 return data.length;
1001 }
1002
1003 /** {@inheritDoc} */
1004 public RealVector append(RealVector v) {
1005 try {
1006 return new ArrayRealVector(this, (ArrayRealVector) v);
1007 } catch (ClassCastException cce) {
1008 return new ArrayRealVector(this, v);
1009 }
1010 }
1011
1012 /**
1013 * Construct a vector by appending a vector to this vector.
1014 * @param v vector to append to this one.
1015 * @return a new vector
1016 */
1017 public ArrayRealVector append(ArrayRealVector v) {
1018 return new ArrayRealVector(this, v);
1019 }
1020
1021 /** {@inheritDoc} */
1022 public RealVector append(double in) {
1023 final double[] out = new double[data.length + 1];
1024 System.arraycopy(data, 0, out, 0, data.length);
1025 out[data.length] = in;
1026 return new ArrayRealVector(out, false);
1027 }
1028
1029 /** {@inheritDoc} */
1030 public RealVector append(double[] in) {
1031 return new ArrayRealVector(this, in);
1032 }
1033
1034 /** {@inheritDoc} */
1035 public RealVector getSubVector(int index, int n) {
1036 ArrayRealVector out = new ArrayRealVector(n);
1037 try {
1038 System.arraycopy(data, index, out.data, 0, n);
1039 } catch (IndexOutOfBoundsException e) {
1040 checkIndex(index);
1041 checkIndex(index + n - 1);
1042 }
1043 return out;
1044 }
1045
1046 /** {@inheritDoc} */
1047 public void setEntry(int index, double value) {
1048 try {
1049 data[index] = value;
1050 } catch (IndexOutOfBoundsException e) {
1051 checkIndex(index);
1052 }
1053 }
1054
1055 /** {@inheritDoc} */
1056 @Override
1057 public void setSubVector(int index, RealVector v) {
1058 try {
1059 try {
1060 set(index, (ArrayRealVector) v);
1061 } catch (ClassCastException cce) {
1062 for (int i = index; i < index + v.getDimension(); ++i) {
1063 data[i] = v.getEntry(i-index);
1064 }
1065 }
1066 } catch (IndexOutOfBoundsException e) {
1067 checkIndex(index);
1068 checkIndex(index + v.getDimension() - 1);
1069 }
1070 }
1071
1072 /** {@inheritDoc} */
1073 @Override
1074 public void setSubVector(int index, double[] v) {
1075 try {
1076 System.arraycopy(v, 0, data, index, v.length);
1077 } catch (IndexOutOfBoundsException e) {
1078 checkIndex(index);
1079 checkIndex(index + v.length - 1);
1080 }
1081 }
1082
1083 /**
1084 * Set a set of consecutive elements.
1085 *
1086 * @param index index of first element to be set.
1087 * @param v vector containing the values to set.
1088 * @exception MatrixIndexException if the index is
1089 * inconsistent with vector size
1090 */
1091 public void set(int index, ArrayRealVector v)
1092 throws MatrixIndexException {
1093 setSubVector(index, v.data);
1094 }
1095
1096 /** {@inheritDoc} */
1097 @Override
1098 public void set(double value) {
1099 Arrays.fill(data, value);
1100 }
1101
1102 /** {@inheritDoc} */
1103 @Override
1104 public double[] toArray(){
1105 return data.clone();
1106 }
1107
1108 /** {@inheritDoc} */
1109 @Override
1110 public String toString(){
1111 return DEFAULT_FORMAT.format(this);
1112 }
1113
1114 /**
1115 * Check if instance and specified vectors have the same dimension.
1116 * @param v vector to compare instance with
1117 * @exception IllegalArgumentException if the vectors do not
1118 * have the same dimension
1119 */
1120 @Override
1121 protected void checkVectorDimensions(RealVector v)
1122 throws IllegalArgumentException {
1123 checkVectorDimensions(v.getDimension());
1124 }
1125
1126 /**
1127 * Check if instance dimension is equal to some expected value.
1128 *
1129 * @param n expected dimension.
1130 * @exception IllegalArgumentException if the dimension is
1131 * inconsistent with vector size
1132 */
1133 @Override
1134 protected void checkVectorDimensions(int n)
1135 throws IllegalArgumentException {
1136 if (data.length != n) {
1137 throw MathRuntimeException.createIllegalArgumentException(
1138 "vector length mismatch: got {0} but expected {1}",
1139 data.length, n);
1140 }
1141 }
1142
1143 /**
1144 * Returns true if any coordinate of this vector is NaN; false otherwise
1145 * @return true if any coordinate of this vector is NaN; false otherwise
1146 */
1147 public boolean isNaN() {
1148 for (double v : data) {
1149 if (Double.isNaN(v)) {
1150 return true;
1151 }
1152 }
1153 return false;
1154 }
1155
1156 /**
1157 * Returns true if any coordinate of this vector is infinite and none are NaN;
1158 * false otherwise
1159 * @return true if any coordinate of this vector is infinite and none are NaN;
1160 * false otherwise
1161 */
1162 public boolean isInfinite() {
1163
1164 if (isNaN()) {
1165 return false;
1166 }
1167
1168 for (double v : data) {
1169 if (Double.isInfinite(v)) {
1170 return true;
1171 }
1172 }
1173
1174 return false;
1175
1176 }
1177
1178 /**
1179 * Test for the equality of two real vectors.
1180 * <p>
1181 * If all coordinates of two real vectors are exactly the same, and none are
1182 * <code>Double.NaN</code>, the two real vectors are considered to be equal.
1183 * </p>
1184 * <p>
1185 * <code>NaN</code> coordinates are considered to affect globally the vector
1186 * and be equals to each other - i.e, if either (or all) coordinates of the
1187 * real vector are equal to <code>Double.NaN</code>, the real vector is equal to
1188 * a vector with all <code>Double.NaN</code> coordinates.
1189 * </p>
1190 *
1191 * @param other Object to test for equality to this
1192 * @return true if two vector objects are equal, false if
1193 * object is null, not an instance of RealVector, or
1194 * not equal to this RealVector instance
1195 *
1196 */
1197 @Override
1198 public boolean equals(Object other) {
1199
1200 if (this == other) {
1201 return true;
1202 }
1203
1204 if (other == null || !(other instanceof RealVector)) {
1205 return false;
1206 }
1207
1208
1209 RealVector rhs = (RealVector) other;
1210 if (data.length != rhs.getDimension()) {
1211 return false;
1212 }
1213
1214 if (rhs.isNaN()) {
1215 return this.isNaN();
1216 }
1217
1218 for (int i = 0; i < data.length; ++i) {
1219 if (data[i] != rhs.getEntry(i)) {
1220 return false;
1221 }
1222 }
1223 return true;
1224 }
1225
1226 /**
1227 * Get a hashCode for the real vector.
1228 * <p>All NaN values have the same hash code.</p>
1229 * @return a hash code value for this object
1230 */
1231 @Override
1232 public int hashCode() {
1233 if (isNaN()) {
1234 return 9;
1235 }
1236 return MathUtils.hash(data);
1237 }
1238
1239 }