1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
|
cimport numpy as cnp
from libcpp.memory cimport shared_ptr
from libcpp.vector cimport vector
from cython cimport final
from ...utils._typedefs cimport ITYPE_t, DTYPE_t
cnp.import_array()
######################
## std::vector to np.ndarray coercion
# As type covariance is not supported for C++ containers via Cython,
# we need to redefine fused types.
ctypedef fused vector_DITYPE_t:
vector[ITYPE_t]
vector[DTYPE_t]
ctypedef fused vector_vector_DITYPE_t:
vector[vector[ITYPE_t]]
vector[vector[DTYPE_t]]
cdef cnp.ndarray[object, ndim=1] coerce_vectors_to_nd_arrays(
shared_ptr[vector_vector_DITYPE_t] vecs
)
#####################
{{for name_suffix in ['64', '32']}}
from ._base cimport BaseDistancesReduction{{name_suffix}}
from ._middle_term_computer cimport MiddleTermComputer{{name_suffix}}
cdef class RadiusNeighbors{{name_suffix}}(BaseDistancesReduction{{name_suffix}}):
"""float{{name_suffix}} implementation of the RadiusNeighbors."""
cdef:
DTYPE_t radius
# DistanceMetric{{name_suffix}} compute rank-preserving surrogate distance via rdist
# which are proxies necessitating less computations.
# We get the equivalent for the radius to be able to compare it against
# vectors' rank-preserving surrogate distances.
DTYPE_t r_radius
# Neighbors indices and distances are returned as np.ndarrays of np.ndarrays.
#
# For this implementation, we want resizable buffers which we will wrap
# into numpy arrays at the end. std::vector comes as a handy container
# for interacting efficiently with resizable buffers.
#
# Though it is possible to access their buffer address with
# std::vector::data, they can't be stolen: buffers lifetime
# is tied to their std::vector and are deallocated when
# std::vectors are.
#
# To solve this, we dynamically allocate std::vectors and then
# encapsulate them in a StdVectorSentinel responsible for
# freeing them when the associated np.ndarray is freed.
#
# Shared pointers (defined via shared_ptr) are use for safer memory management.
# Unique pointers (defined via unique_ptr) can't be used as datastructures
# are shared across threads for parallel_on_X; see _parallel_on_X_init_chunk.
shared_ptr[vector[vector[ITYPE_t]]] neigh_indices
shared_ptr[vector[vector[DTYPE_t]]] neigh_distances
# Used as array of pointers to private datastructures used in threads.
vector[shared_ptr[vector[vector[ITYPE_t]]]] neigh_indices_chunks
vector[shared_ptr[vector[vector[DTYPE_t]]]] neigh_distances_chunks
bint sort_results
@final
cdef void _merge_vectors(
self,
ITYPE_t idx,
ITYPE_t num_threads,
) nogil
cdef class EuclideanRadiusNeighbors{{name_suffix}}(RadiusNeighbors{{name_suffix}}):
"""EuclideanDistance-specialisation of RadiusNeighbors{{name_suffix}}."""
cdef:
MiddleTermComputer{{name_suffix}} middle_term_computer
const DTYPE_t[::1] X_norm_squared
const DTYPE_t[::1] Y_norm_squared
bint use_squared_distances
{{endfor}}
|