public double distance(SparseVector a, SparseVector b) {
   //		double ret = a.dotProduct (b) /
   //								 Math.sqrt (a.dotProduct (a) * b.dotProduct (b));
   // gmann : twoNorm() more efficient than a.dotProduct(a)
   double ret = a.dotProduct(b) / (a.twoNorm() * b.twoNorm());
   return 1.0 - ret;
 }
  public double distance(SparseVector a, int hashCodeA, SparseVector b, int hashCodeB) {
    Double cachedA = (Double) hash.get(new Integer(hashCodeA));
    Double cachedB = (Double) hash.get(new Integer(hashCodeB));
    if (a == null || b == null) return 1.0;
    if (cachedA == null) {
      cachedA = new Double(a.dotProduct(a));
      hash.put(new Integer(hashCodeA), cachedA);
    }
    if (cachedB == null) {
      cachedB = new Double(b.dotProduct(b));
      hash.put(new Integer(hashCodeB), cachedB);
    }
    double ab = a.dotProduct(b);

    if (cachedA == null || cachedB == null) {
      throw new IllegalStateException("cachedValues null");
    }
    double ret = a.dotProduct(b) / Math.sqrt(cachedA.doubleValue() * cachedB.doubleValue());
    return 1.0 - ret;
  }