{{py:

implementation_specific_values = [
    # Values are the following ones:
    #
    # name_suffix, INPUT_DTYPE_t, INPUT_DTYPE
    ('64', 'DistanceMetric64', 'float64_t'),
    ('32', 'DistanceMetric32', 'float32_t')
]

}}
from ...utils._typedefs cimport float64_t, float32_t, int32_t, intp_t
from ...metrics._dist_metrics cimport DistanceMetric64, DistanceMetric32, DistanceMetric

{{for name_suffix, DistanceMetric, INPUT_DTYPE_t in implementation_specific_values}}


cdef class DatasetsPair{{name_suffix}}:
    cdef:
        {{DistanceMetric}} distance_metric
        intp_t n_features

    cdef intp_t n_samples_X(self) noexcept nogil

    cdef intp_t n_samples_Y(self) noexcept nogil

    cdef float64_t dist(self, intp_t i, intp_t j) noexcept nogil

    cdef float64_t surrogate_dist(self, intp_t i, intp_t j) noexcept nogil


cdef class DenseDenseDatasetsPair{{name_suffix}}(DatasetsPair{{name_suffix}}):
    cdef:
        const {{INPUT_DTYPE_t}}[:, ::1] X
        const {{INPUT_DTYPE_t}}[:, ::1] Y


cdef class SparseSparseDatasetsPair{{name_suffix}}(DatasetsPair{{name_suffix}}):
    cdef:
        const {{INPUT_DTYPE_t}}[:] X_data
        const int32_t[::1] X_indices
        const int32_t[::1] X_indptr

        const {{INPUT_DTYPE_t}}[:] Y_data
        const int32_t[::1] Y_indices
        const int32_t[::1] Y_indptr


cdef class SparseDenseDatasetsPair{{name_suffix}}(DatasetsPair{{name_suffix}}):
    cdef:
        const {{INPUT_DTYPE_t}}[:] X_data
        const int32_t[::1] X_indices
        const int32_t[::1] X_indptr

        const {{INPUT_DTYPE_t}}[:] Y_data
        const int32_t[::1] Y_indices
        intp_t n_Y


cdef class DenseSparseDatasetsPair{{name_suffix}}(DatasetsPair{{name_suffix}}):
    cdef:
        # As distance metrics are commutative, we can simply rely
        # on the implementation of SparseDenseDatasetsPair and
        # swap arguments.
        DatasetsPair{{name_suffix}} datasets_pair

{{endfor}}
