File size: 4,378 Bytes
7885a28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
{{py:

implementation_specific_values = [
    # Values are the following ones:
    #
    # name_suffix, INPUT_DTYPE_t, INPUT_DTYPE
    ('64', 'float64_t', 'np.float64'),
    ('32', 'float32_t', 'np.float32')
]

}}
from libc.math cimport sqrt, exp

from ..utils._typedefs cimport float64_t, float32_t, int32_t, intp_t

cdef class DistanceMetric:
    pass

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

######################################################################
# Inline distance functions
#
#  We use these for the default (euclidean) case so that they can be
#  inlined.  This leads to faster computation for the most common case
cdef inline float64_t euclidean_dist{{name_suffix}}(
    const {{INPUT_DTYPE_t}}* x1,
    const {{INPUT_DTYPE_t}}* x2,
    intp_t size,
) except -1 nogil:
    cdef float64_t tmp, d=0
    cdef intp_t j
    for j in range(size):
        tmp = <float64_t> (x1[j] - x2[j])
        d += tmp * tmp
    return sqrt(d)


cdef inline float64_t euclidean_rdist{{name_suffix}}(
    const {{INPUT_DTYPE_t}}* x1,
    const {{INPUT_DTYPE_t}}* x2,
    intp_t size,
) except -1 nogil:
    cdef float64_t tmp, d=0
    cdef intp_t j
    for j in range(size):
        tmp = <float64_t>(x1[j] - x2[j])
        d += tmp * tmp
    return d


cdef inline float64_t euclidean_dist_to_rdist{{name_suffix}}(const {{INPUT_DTYPE_t}} dist) except -1 nogil:
    return dist * dist


cdef inline float64_t euclidean_rdist_to_dist{{name_suffix}}(const {{INPUT_DTYPE_t}} dist) except -1 nogil:
    return sqrt(dist)


######################################################################
# DistanceMetric{{name_suffix}} base class
cdef class DistanceMetric{{name_suffix}}(DistanceMetric):
    # The following attributes are required for a few of the subclasses.
    # we must define them here so that cython's limited polymorphism will work.
    # Because we don't expect to instantiate a lot of these objects, the
    # extra memory overhead of this setup should not be an issue.
    cdef float64_t p
    cdef const float64_t[::1] vec
    cdef const float64_t[:, ::1] mat
    cdef intp_t size
    cdef object func
    cdef object kwargs

    cdef {{INPUT_DTYPE_t}} dist(
        self,
        const {{INPUT_DTYPE_t}}* x1,
        const {{INPUT_DTYPE_t}}* x2,
        intp_t size,
    ) except -1 nogil

    cdef {{INPUT_DTYPE_t}} rdist(
        self,
        const {{INPUT_DTYPE_t}}* x1,
        const {{INPUT_DTYPE_t}}* x2,
        intp_t size,
    ) except -1 nogil

    cdef {{INPUT_DTYPE_t}} dist_csr(
        self,
        const {{INPUT_DTYPE_t}}* x1_data,
        const int32_t* x1_indices,
        const {{INPUT_DTYPE_t}}* x2_data,
        const int32_t* x2_indices,
        const int32_t x1_start,
        const int32_t x1_end,
        const int32_t x2_start,
        const int32_t x2_end,
        const intp_t size,
    ) except -1 nogil

    cdef {{INPUT_DTYPE_t}} rdist_csr(
        self,
        const {{INPUT_DTYPE_t}}* x1_data,
        const int32_t* x1_indices,
        const {{INPUT_DTYPE_t}}* x2_data,
        const int32_t* x2_indices,
        const int32_t x1_start,
        const int32_t x1_end,
        const int32_t x2_start,
        const int32_t x2_end,
        const intp_t size,
    ) except -1 nogil

    cdef int pdist(
        self,
        const {{INPUT_DTYPE_t}}[:, ::1] X,
        {{INPUT_DTYPE_t}}[:, ::1] D,
    ) except -1

    cdef int cdist(
        self,
        const {{INPUT_DTYPE_t}}[:, ::1] X,
        const {{INPUT_DTYPE_t}}[:, ::1] Y,
        {{INPUT_DTYPE_t}}[:, ::1] D,
    ) except -1

    cdef int pdist_csr(
        self,
        const {{INPUT_DTYPE_t}}* x1_data,
        const int32_t[::1] x1_indices,
        const int32_t[::1] x1_indptr,
        const intp_t size,
        {{INPUT_DTYPE_t}}[:, ::1] D,
    ) except -1 nogil

    cdef int cdist_csr(
        self,
        const {{INPUT_DTYPE_t}}* x1_data,
        const int32_t[::1] x1_indices,
        const int32_t[::1] x1_indptr,
        const {{INPUT_DTYPE_t}}* x2_data,
        const int32_t[::1] x2_indices,
        const int32_t[::1] x2_indptr,
        const intp_t size,
        {{INPUT_DTYPE_t}}[:, ::1] D,
    ) except -1 nogil

    cdef {{INPUT_DTYPE_t}} _rdist_to_dist(self, {{INPUT_DTYPE_t}} rdist) except -1 nogil

    cdef {{INPUT_DTYPE_t}} _dist_to_rdist(self, {{INPUT_DTYPE_t}} dist) except -1 nogil

{{endfor}}