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