@Override
 @SuppressWarnings("unchecked")
 public <M extends Number, O extends Number> Matrix<O> outerProduct(
     Vector<M> y, Vectors.Factory<O> using) {
   if (using == Vectors.AS_INTS) {
     int[][] data2 = new int[n][y.length()];
     for (Map.Entry<Integer, Integer> e : entrySet()) {
       for (int j = 0; j < y.length(); j++) {
         data2[e.getKey()][j] = e.getValue().intValue() * y.intValue(j);
       }
     }
     return (Matrix<O>) new IntArrayMatrix(data2);
   } else if (using == Vectors.AS_REALS) {
     double[][] data2 = new double[n][y.length()];
     for (Map.Entry<Integer, Integer> e : entrySet()) {
       for (int j = 0; j < y.length(); j++) {
         data2[e.getKey()][j] = y.doubleValue(j) * e.getValue().intValue();
       }
     }
     return (Matrix<O>) new DoubleArrayMatrix(data2);
   } else {
     final SparseMatrix<O> matrix = new SparseMatrix<O>(n, y.length(), using);
     for (Map.Entry<Integer, Integer> e : entrySet()) {
       for (Map.Entry<Integer, M> e2 : y.entrySet()) {
         matrix.set(
             e.getKey(), e2.getKey(), e2.getValue().doubleValue() * e.getKey().doubleValue());
       }
     }
     return matrix;
   }
 }
 @Override
 public <M extends Number> void sub(Vector<M> vector) {
   assert (vector.length() == n);
   for (Map.Entry<Integer, M> e : vector.entrySet()) {
     sub(e.getKey(), e.getValue().intValue());
   }
 }
 @Override
 public <M extends Number> double innerProduct(Vector<M> y) {
   assert (n == y.length());
   if (y instanceof RealVector) {
     double[] y2 = ((RealVector) y).data();
     if (defaultValue == 0) {
       double innerProduct = 0;
       for (Map.Entry<Integer, Integer> e : entrySet()) {
         innerProduct += y2[e.getKey()] * e.getValue();
       }
       return innerProduct;
     } else {
       double innerProduct = 0;
       for (int i = 0; i < n; i++) {
         innerProduct += y2[i] * get(i);
       }
       return innerProduct;
     }
   } else if (y instanceof IntVector) {
     int[] y2 = ((IntVector) y).data();
     if (defaultValue == 0) {
       int innerProduct = 0;
       for (Map.Entry<Integer, Integer> e : entrySet()) {
         innerProduct += e.getValue() * y2[e.getKey()];
       }
       return innerProduct;
     } else {
       int innerProduct = 0;
       for (int i = 0; i < n; i++) {
         innerProduct += y2[i] * get(i);
       }
       return innerProduct;
     }
   } else {
     if (defaultValue == 0 || y.defaultValue().intValue() == 0) {
       int innerProduct = 0;
       if (this.size() <= y.size()) {
         for (Map.Entry<Integer, Integer> e : entrySet()) {
           innerProduct += e.getValue() * y.intValue(e.getKey());
         }
         return innerProduct;
       } else {
         for (Map.Entry<Integer, M> e : y.entrySet()) {
           innerProduct += e.getValue().intValue() * this.intValue(e.getKey());
         }
         return innerProduct;
       }
     } else {
       int innerProduct = 0;
       int notBothSparse = 0;
       for (Map.Entry<Integer, Integer> e : entrySet()) {
         innerProduct += e.getValue() * y.intValue(e.getKey());
         notBothSparse++;
       }
       for (Map.Entry<Integer, M> e : y.entrySet()) {
         if (!super.containsKey(e.getKey())) {
           innerProduct += defaultValue * e.getValue().intValue();
           notBothSparse++;
         }
       }
       return innerProduct + (n - notBothSparse) * defaultValue * y.defaultValue().intValue();
     }
   }
 }