/**
  * Optimized method to compute the outer product.
  *
  * @param v The vector to comput the outer product on
  * @return The outer product of <code>this</code> and <code>v</code>
  * @throws IllegalArgumentException If the dimensions don't match
  */
 public OpenMapRealMatrix outerproduct(OpenMapRealVector v) throws IllegalArgumentException {
   checkVectorDimensions(v.getDimension());
   OpenMapRealMatrix res = new OpenMapRealMatrix(virtualSize, virtualSize);
   Iterator iter = entries.iterator();
   while (iter.hasNext()) {
     iter.advance();
     Iterator iter2 = v.getEntries().iterator();
     while (iter2.hasNext()) {
       iter2.advance();
       res.setEntry(iter.key(), iter2.key(), iter.value() * iter2.value());
     }
   }
   return res;
 }
 /**
  * Optimized method to add two OpenMapRealVectors.
  *
  * @param v Vector to add with
  * @return The sum of <code>this</code> with <code>v</code>
  * @throws IllegalArgumentException If the dimensions don't match
  */
 public OpenMapRealVector add(OpenMapRealVector v) throws IllegalArgumentException {
   checkVectorDimensions(v.getDimension());
   OpenMapRealVector res = (OpenMapRealVector) copy();
   Iterator iter = v.getEntries().iterator();
   while (iter.hasNext()) {
     iter.advance();
     int key = iter.key();
     if (entries.containsKey(key)) {
       res.setEntry(key, entries.get(key) + iter.value());
     } else {
       res.setEntry(key, iter.value());
     }
   }
   return res;
 }
 /**
  * Distance between two vectors.
  *
  * <p>This method computes the distance consistent with L<sub>1</sub> norm, i.e. the sum of the
  * absolute values of elements differences.
  *
  * @param v vector to which distance is requested
  * @return distance between two vectors.
  */
 public double getL1Distance(OpenMapRealVector v) {
   double max = 0;
   Iterator iter = entries.iterator();
   while (iter.hasNext()) {
     iter.advance();
     double delta = Math.abs(iter.value() - v.getEntry(iter.key()));
     max += delta;
   }
   iter = v.getEntries().iterator();
   while (iter.hasNext()) {
     iter.advance();
     int key = iter.key();
     if (!entries.containsKey(key)) {
       double delta = Math.abs(iter.value());
       max += Math.abs(delta);
     }
   }
   return max;
 }
 /**
  * Optimized method to compute distance.
  *
  * @param v The vector to compute distance to
  * @return The distance from <code>this</code> and <code>v</code>
  * @throws IllegalArgumentException If the dimensions don't match
  */
 public double getDistance(OpenMapRealVector v) throws IllegalArgumentException {
   Iterator iter = entries.iterator();
   double res = 0;
   while (iter.hasNext()) {
     iter.advance();
     int key = iter.key();
     double delta;
     delta = iter.value() - v.getEntry(key);
     res += delta * delta;
   }
   iter = v.getEntries().iterator();
   while (iter.hasNext()) {
     iter.advance();
     int key = iter.key();
     if (!entries.containsKey(key)) {
       final double value = iter.value();
       res += value * value;
     }
   }
   return Math.sqrt(res);
 }
 /**
  * Implementation Note: This performs an exact comparison, and as a result it is possible for
  * {@code a.subtract(b}} to be the zero vector, while {@code a.equals(b) == false}. {@inheritDoc}
  */
 @Override
 public boolean equals(Object obj) {
   if (this == obj) {
     return true;
   }
   if (obj == null) {
     return false;
   }
   if (!(obj instanceof OpenMapRealVector)) {
     return false;
   }
   OpenMapRealVector other = (OpenMapRealVector) obj;
   if (virtualSize != other.virtualSize) {
     return false;
   }
   if (Double.doubleToLongBits(epsilon) != Double.doubleToLongBits(other.epsilon)) {
     return false;
   }
   Iterator iter = entries.iterator();
   while (iter.hasNext()) {
     iter.advance();
     double test = other.getEntry(iter.key());
     if (Double.doubleToLongBits(test) != Double.doubleToLongBits(iter.value())) {
       return false;
     }
   }
   iter = other.getEntries().iterator();
   while (iter.hasNext()) {
     iter.advance();
     double test = iter.value();
     if (Double.doubleToLongBits(test) != Double.doubleToLongBits(getEntry(iter.key()))) {
       return false;
     }
   }
   return true;
 }
 /**
  * Copy constructor.
  *
  * @param v The instance to copy from
  */
 public OpenMapRealVector(OpenMapRealVector v) {
   virtualSize = v.getDimension();
   entries = new OpenIntToDoubleHashMap(v.getEntries());
   epsilon = v.getEpsilon();
 }