ENH: spatial: reimplement cdist_cosine using np.dot

This uses `np.dot` instead of a custom dot product routine for computing `cdist(A, B, 'cosine')`. It also uses `np.einsum`, if available, to get the space complexity to a strict O(*mn*) when the dtypes are both `double`, instead of O(*mn* + *mk* + *nl*) for *m*, *k* = `A.shape`, *n*, *l* = `B.shape`.

I also tried doing the whole thing with `einsum` only:

    1 - np.einsum('ij,jk,i,k->ik', XA, XB.T, 1/normsA, 1/normsB)

... but that was much slower.

Tackling the corresponding `pdist` is much harder and out of scope for this PR.
I don't believe in "ask forgiveness, not permission": if any bug in the `try` block causes an `AttributeError`, that bug will be hidden instead of out in the open where we can fix it. Explicit is better than implicit and that all (especially the part about being Dutch ;).