def hashable_rows(data, digits=None):
    if len(data) == 0:
        return np.array([])
    as_int = float_to_int(data, digits=digits)
    if len(as_int.shape) == 1:
        return as_int
    if len(as_int.shape) == 2 and as_int.shape[1] <= 4:
        precision = int(np.floor(64 / as_int.shape[1]))
        if np.abs(as_int).max() < 2**(precision - 1):
            hashable = np.zeros(len(as_int), dtype=np.int64)
            for offset, column in enumerate(as_int.astype(np.int64).T):
                np.bitwise_xor(hashable,
                               column << (offset * precision),
                               out=hashable)
            return hashable
    dtype = np.dtype((np.void, as_int.dtype.itemsize * as_int.shape[1]))
    hashable = np.ascontiguousarray(as_int).view(dtype).reshape(-1)
    return hashable