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