public static <E> double dotProduct(Counter<E> c1, Counter<E> c2) {
    double dotProd = 0.0;
    if (c1.size() > c2.size()) {
      Counter<E> tmpCnt = c1;
      c1 = c2;
      c2 = tmpCnt;
    }
    for (E key : c1.keySet()) {
      double count1 = c1.getCount(key);
      if (Double.isNaN(count1) || Double.isInfinite(count1)) {
        throw new RuntimeException("Counters.dotProduct infinite or NaN value for key: " + key + '\t' + c1.getCount(key) + '\t' + c2.getCount(key));
      }
      if (count1 != 0.0) {
        double count2 = c2.getCount(key);
        if (Double.isNaN(count2) || Double.isInfinite(count2)) {
          throw new RuntimeException("Counters.dotProduct infinite or NaN value for key: " + key + '\t' + c1.getCount(key) + '\t' + c2.getCount(key));
        }
        if (count2 != 0.0) {
          // this is the inner product
          dotProd += (count1 * count2);
        }
      }
    }
    return dotProd;
  }
public static < E > double dotProduct ( Counter < E > c1 , Counter < E > c2 ) { double dotProd = 0.0 ; if ( c1 . size ( ) > c2 . size ( ) ) { Counter < E > tmpCnt = c1 ; c1 = c2 ; c2 = tmpCnt ; } for ( E key : c1 . keySet ( ) ) { double count1 = c1 . getCount ( key ) ; if ( Double . isNaN ( count1 ) || Double . isInfinite ( count1 ) ) { throw new RuntimeException ( "Counters.dotProduct infinite or NaN value for key: " + key + '\t' + c1 . getCount ( key ) + '\t' + c2 . getCount ( key ) ) ; } if ( count1 != 0.0 ) { double count2 = c2 . getCount ( key ) ; if ( Double . isNaN ( count2 ) || Double . isInfinite ( count2 ) ) { throw new RuntimeException ( "Counters.dotProduct infinite or NaN value for key: " + key + '\t' + c1 . getCount ( key ) + '\t' + c2 . getCount ( key ) ) ; } if ( count2 != 0.0 ) { dotProd += ( count1 * count2 ) ; } } } return dotProd ; }
Returns the product of c1 and c2.

@return The product of c1 and c2.