@Override
    public double dotProduct(Vector v) {
        verifyMatchingDimensions(v);

        if (v instanceof DenseVector) {
            @SuppressWarnings("unchecked") // checked w. instanceof
            double[] vValues = ((DenseVector)v).mValues;
            double sum = 0.0;
            int[] keys1 = mKeys;
            float[] vals1 = mValues;
            for (int i = 0; i < keys1.length; ++i)
                sum += vals1[i] * vValues[keys1[i]];
            return sum;
        }

        if (v instanceof SparseFloatVector) {
            SparseFloatVector spv = (SparseFloatVector) v;
            int[] keys1 = mKeys;
            float[] vals1 = mValues;
            int[] keys2 = spv.mKeys;
            float[] vals2 = spv.mValues;

            double sum = 0.0;
            int index1 = 0;
            int index2 = 0;
            while (index1 < keys1.length && index2 < keys2.length) {
                int comp = keys1[index1] - keys2[index2];
                if (comp == 0)
                    sum += vals1[index1++] * vals2[index2++];
                else if (comp < 0)
                    ++index1;
                else
                    ++index2;
            }
            return sum;
        } 

        // general case
        double sum = 0.0;
        int[] keys1 = mKeys;
        float[] vals1 = mValues;
        for (int i = 0; i < keys1.length; ++i)
            sum += vals1[i] * v.value(keys1[i]);
        return sum;
    }