1 /**
2 * Author: Damian Eads
3 * Date: September 22, 2007 (moved to new file on June 8, 2008)
4 * Adapted for incorporation into Scipy, April 9, 2008.
5 *
6 * Copyright (c) 2007, Damian Eads. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * - Redistributions of source code must retain the above
12 * copyright notice, this list of conditions and the
13 * following disclaimer.
14 * - Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer
16 * in the documentation and/or other materials provided with the
17 * distribution.
18 * - Neither the name of the author nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 #if !defined(__clang__) && defined(__GNUC__) && defined(__GNUC_MINOR__)
36 #if __GNUC__ >= 5 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
37 /* enable auto-vectorizer */
38 #pragma GCC optimize("tree-vectorize")
39 /* float associativity required to vectorize reductions */
40 #pragma GCC optimize("unsafe-math-optimizations")
41 /* maybe 5% gain, manual unrolling with more accumulators would be better */
42 #pragma GCC optimize("unroll-loops")
43 #endif
44 #endif
45 #include <stdio.h>
46 #include <math.h>
47 #include <stdlib.h>
48 #include <Python.h>
49 #include <numpy/arrayobject.h>
50 #include <numpy/npy_math.h>
51
52 #include "distance_impl.h"
53
54 #define DEFINE_WRAP_CDIST(name, type) \
55 static PyObject * \
56 cdist_ ## name ## _ ## type ## _wrap(PyObject *self, PyObject *args)\
57 { \
58 PyArrayObject *XA_, *XB_, *dm_; \
59 Py_ssize_t mA, mB, n; \
60 double *dm; \
61 const type *XA, *XB; \
62 if (!PyArg_ParseTuple(args, "O!O!O!", \
63 &PyArray_Type, &XA_, &PyArray_Type, &XB_, \
64 &PyArray_Type, &dm_)) { \
65 return NULL; \
66 } \
67 else { \
68 NPY_BEGIN_ALLOW_THREADS; \
69 XA = (const type *)XA_->data; \
70 XB = (const type *)XB_->data; \
71 dm = (double *)dm_->data; \
72 mA = XA_->dimensions[0]; \
73 mB = XB_->dimensions[0]; \
74 n = XA_->dimensions[1]; \
75 cdist_ ## name ## _ ## type(XA, XB, dm, mA, mB, n); \
76 NPY_END_ALLOW_THREADS; \
77 } \
78 return Py_BuildValue("d", 0.); \
79 }
80
DEFINE_WRAP_CDIST(bray_curtis,double)81 DEFINE_WRAP_CDIST(bray_curtis, double)
82 DEFINE_WRAP_CDIST(canberra, double)
83 DEFINE_WRAP_CDIST(chebyshev, double)
84 DEFINE_WRAP_CDIST(city_block, double)
85 DEFINE_WRAP_CDIST(euclidean, double)
86 DEFINE_WRAP_CDIST(jaccard, double)
87 DEFINE_WRAP_CDIST(jensenshannon, double)
88 DEFINE_WRAP_CDIST(sqeuclidean, double)
89
90 DEFINE_WRAP_CDIST(dice, char)
91 DEFINE_WRAP_CDIST(jaccard, char)
92 DEFINE_WRAP_CDIST(kulsinski, char)
93 DEFINE_WRAP_CDIST(rogerstanimoto, char)
94 DEFINE_WRAP_CDIST(russellrao, char)
95 DEFINE_WRAP_CDIST(sokalmichener, char)
96 DEFINE_WRAP_CDIST(sokalsneath, char)
97 DEFINE_WRAP_CDIST(yule, char)
98
99 static PyObject *cdist_hamming_double_wrap(
100 PyObject *self, PyObject *args, PyObject *kwargs)
101 {
102 PyArrayObject *XA_, *XB_, *dm_, *w_;
103 int mA, mB, n;
104 double *dm;
105 const double *XA, *XB, *w;
106 static char *kwlist[] = {"XA", "XB", "dm", "w", NULL};
107 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
108 "O!O!O!O!:cdist_hamming_double_wrap", kwlist,
109 &PyArray_Type, &XA_, &PyArray_Type, &XB_,
110 &PyArray_Type, &dm_,
111 &PyArray_Type, &w_)) {
112 return 0;
113 }
114 else {
115 NPY_BEGIN_ALLOW_THREADS;
116 XA = (const double*)XA_->data;
117 XB = (const double*)XB_->data;
118 w = (const double*)w_->data;
119 dm = (double*)dm_->data;
120 mA = XA_->dimensions[0];
121 mB = XB_->dimensions[0];
122 n = XA_->dimensions[1];
123 cdist_hamming_double(XA, XB, dm, mA, mB, n, w);
124 NPY_END_ALLOW_THREADS;
125 }
126 return Py_BuildValue("d", 0.0);
127 }
128
cdist_hamming_char_wrap(PyObject * self,PyObject * args,PyObject * kwargs)129 static PyObject *cdist_hamming_char_wrap(
130 PyObject *self, PyObject *args, PyObject *kwargs)
131 {
132 PyArrayObject *XA_, *XB_, *dm_, *w_;
133 int mA, mB, n;
134 double *dm;
135 const char *XA, *XB;
136 const double *w;
137 static char *kwlist[] = {"XA", "XB", "dm", "w", NULL};
138 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
139 "O!O!O!O!:cdist_hamming_char_wrap", kwlist,
140 &PyArray_Type, &XA_, &PyArray_Type, &XB_,
141 &PyArray_Type, &dm_,
142 &PyArray_Type, &w_)) {
143 return 0;
144 }
145 else {
146 NPY_BEGIN_ALLOW_THREADS;
147 XA = (const char*)XA_->data;
148 XB = (const char*)XB_->data;
149 w = (const double*)w_->data;
150 dm = (double*)dm_->data;
151 mA = XA_->dimensions[0];
152 mB = XB_->dimensions[0];
153 n = XA_->dimensions[1];
154 cdist_hamming_char(XA, XB, dm, mA, mB, n, w);
155 NPY_END_ALLOW_THREADS;
156 }
157 return Py_BuildValue("d", 0.0);
158 }
159
cdist_cosine_double_wrap(PyObject * self,PyObject * args,PyObject * kwargs)160 static PyObject *cdist_cosine_double_wrap(PyObject *self, PyObject *args,
161 PyObject *kwargs) {
162 PyArrayObject *XA_, *XB_, *dm_;
163 int mA, mB, n, status;
164 double *dm;
165 const double *XA, *XB;
166 static char *kwlist[] = {"XA", "XB", "dm", NULL};
167 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
168 "O!O!O!:cdist_cosine_double_wrap", kwlist,
169 &PyArray_Type, &XA_, &PyArray_Type, &XB_,
170 &PyArray_Type, &dm_))
171 {
172 return 0;
173 }
174 else {
175 NPY_BEGIN_THREADS_DEF;
176 NPY_BEGIN_THREADS;
177 XA = (const double*)XA_->data;
178 XB = (const double*)XB_->data;
179 dm = (double*)dm_->data;
180 mA = XA_->dimensions[0];
181 mB = XB_->dimensions[0];
182 n = XA_->dimensions[1];
183
184 status = cdist_cosine(XA, XB, dm, mA, mB, n);
185 NPY_END_THREADS;
186 if(status < 0)
187 return PyErr_NoMemory();
188 }
189 return Py_BuildValue("d", 0.0);
190 }
191
cdist_mahalanobis_double_wrap(PyObject * self,PyObject * args,PyObject * kwargs)192 static PyObject *cdist_mahalanobis_double_wrap(PyObject *self, PyObject *args,
193 PyObject *kwargs) {
194 PyArrayObject *XA_, *XB_, *covinv_, *dm_;
195 int mA, mB, n, status;
196 double *dm;
197 const double *XA, *XB;
198 const double *covinv;
199 static char *kwlist[] = {"XA", "XB", "dm", "VI", NULL};
200 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
201 "O!O!O!O!:cdist_mahalanobis_double_wrap", kwlist,
202 &PyArray_Type, &XA_, &PyArray_Type, &XB_,
203 &PyArray_Type, &dm_, &PyArray_Type, &covinv_))
204 {
205 return 0;
206 }
207 else {
208 NPY_BEGIN_THREADS_DEF;
209 NPY_BEGIN_THREADS;
210 XA = (const double*)XA_->data;
211 XB = (const double*)XB_->data;
212 covinv = (const double*)covinv_->data;
213 dm = (double*)dm_->data;
214 mA = XA_->dimensions[0];
215 mB = XB_->dimensions[0];
216 n = XA_->dimensions[1];
217
218 status = cdist_mahalanobis(XA, XB, dm, mA, mB, n, covinv);
219 NPY_END_THREADS;
220 if(status < 0)
221 return PyErr_NoMemory();
222 }
223 return Py_BuildValue("d", 0.0);
224 }
225
cdist_minkowski_double_wrap(PyObject * self,PyObject * args,PyObject * kwargs)226 static PyObject *cdist_minkowski_double_wrap(PyObject *self, PyObject *args,
227 PyObject *kwargs)
228 {
229 PyArrayObject *XA_, *XB_, *dm_;
230 int mA, mB, n;
231 double *dm;
232 const double *XA, *XB;
233 double p;
234 static char *kwlist[] = {"XA", "XB", "dm", "p", NULL};
235 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
236 "O!O!O!d:cdist_minkowski_double_wrap", kwlist,
237 &PyArray_Type, &XA_, &PyArray_Type, &XB_,
238 &PyArray_Type, &dm_,
239 &p)) {
240 return 0;
241 }
242 else {
243 NPY_BEGIN_ALLOW_THREADS;
244 XA = (const double*)XA_->data;
245 XB = (const double*)XB_->data;
246 dm = (double*)dm_->data;
247 mA = XA_->dimensions[0];
248 mB = XB_->dimensions[0];
249 n = XA_->dimensions[1];
250 cdist_minkowski(XA, XB, dm, mA, mB, n, p);
251 NPY_END_ALLOW_THREADS;
252 }
253 return Py_BuildValue("d", 0.0);
254 }
255
cdist_seuclidean_double_wrap(PyObject * self,PyObject * args,PyObject * kwargs)256 static PyObject *cdist_seuclidean_double_wrap(PyObject *self, PyObject *args,
257 PyObject *kwargs)
258 {
259 PyArrayObject *XA_, *XB_, *dm_, *var_;
260 int mA, mB, n;
261 double *dm;
262 const double *XA, *XB, *var;
263 static char *kwlist[] = {"XA", "XB", "dm", "V", NULL};
264 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
265 "O!O!O!O!:cdist_seuclidean_double_wrap", kwlist,
266 &PyArray_Type, &XA_, &PyArray_Type, &XB_,
267 &PyArray_Type, &dm_, &PyArray_Type, &var_)) {
268 return 0;
269 }
270 else {
271 NPY_BEGIN_ALLOW_THREADS;
272 XA = (const double*)XA_->data;
273 XB = (const double*)XB_->data;
274 dm = (double*)dm_->data;
275 var = (double*)var_->data;
276 mA = XA_->dimensions[0];
277 mB = XB_->dimensions[0];
278 n = XA_->dimensions[1];
279
280 cdist_seuclidean(XA, XB, var, dm, mA, mB, n);
281 NPY_END_ALLOW_THREADS;
282 }
283 return Py_BuildValue("d", 0.0);
284 }
285
cdist_weighted_chebyshev_double_wrap(PyObject * self,PyObject * args,PyObject * kwargs)286 static PyObject *cdist_weighted_chebyshev_double_wrap(
287 PyObject *self, PyObject *args, PyObject *kwargs)
288 {
289 PyArrayObject *XA_, *XB_, *dm_, *w_;
290 int mA, mB, n;
291 double *dm;
292 const double *XA, *XB, *w;
293 static char *kwlist[] = {"XA", "XB", "dm", "w", NULL};
294 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
295 "O!O!O!O!:cdist_weighted_chebyshev_double_wrap", kwlist,
296 &PyArray_Type, &XA_, &PyArray_Type, &XB_,
297 &PyArray_Type, &dm_,
298 &PyArray_Type, &w_)) {
299 return 0;
300 }
301 else {
302 NPY_BEGIN_ALLOW_THREADS;
303 XA = (const double*)XA_->data;
304 XB = (const double*)XB_->data;
305 w = (const double*)w_->data;
306 dm = (double*)dm_->data;
307 mA = XA_->dimensions[0];
308 mB = XB_->dimensions[0];
309 n = XA_->dimensions[1];
310 cdist_weighted_chebyshev(XA, XB, dm, mA, mB, n, w);
311 NPY_END_ALLOW_THREADS;
312 }
313 return Py_BuildValue("d", 0.0);
314 }
315
cdist_old_weighted_minkowski_double_wrap(PyObject * self,PyObject * args,PyObject * kwargs)316 static PyObject *cdist_old_weighted_minkowski_double_wrap(
317 PyObject *self, PyObject *args, PyObject *kwargs)
318 {
319 PyArrayObject *XA_, *XB_, *dm_, *w_;
320 int mA, mB, n;
321 double *dm;
322 const double *XA, *XB, *w;
323 double p;
324 static char *kwlist[] = {"XA", "XB", "dm", "p", "w", NULL};
325 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
326 "O!O!O!dO!:cdist_old_weighted_minkowski_double_wrap", kwlist,
327 &PyArray_Type, &XA_, &PyArray_Type, &XB_,
328 &PyArray_Type, &dm_,
329 &p,
330 &PyArray_Type, &w_)) {
331 return 0;
332 }
333 else {
334 int res;
335 NPY_BEGIN_ALLOW_THREADS;
336 XA = (const double*)XA_->data;
337 XB = (const double*)XB_->data;
338 w = (const double*)w_->data;
339 dm = (double*)dm_->data;
340 mA = XA_->dimensions[0];
341 mB = XB_->dimensions[0];
342 n = XA_->dimensions[1];
343 res = cdist_old_weighted_minkowski(XA, XB, dm, mA, mB, n, p, w);
344 NPY_END_ALLOW_THREADS;
345
346 if (res) {
347 return PyErr_NoMemory();
348 }
349 }
350 return Py_BuildValue("d", 0.0);
351 }
352
cdist_weighted_minkowski_double_wrap(PyObject * self,PyObject * args,PyObject * kwargs)353 static PyObject *cdist_weighted_minkowski_double_wrap(
354 PyObject *self, PyObject *args, PyObject *kwargs)
355 {
356 PyArrayObject *XA_, *XB_, *dm_, *w_;
357 int mA, mB, n;
358 double *dm;
359 const double *XA, *XB, *w;
360 double p;
361 static char *kwlist[] = {"XA", "XB", "dm", "p", "w", NULL};
362 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
363 "O!O!O!dO!:cdist_weighted_minkowski_double_wrap", kwlist,
364 &PyArray_Type, &XA_, &PyArray_Type, &XB_,
365 &PyArray_Type, &dm_,
366 &p,
367 &PyArray_Type, &w_)) {
368 return 0;
369 }
370 else {
371 NPY_BEGIN_ALLOW_THREADS;
372 XA = (const double*)XA_->data;
373 XB = (const double*)XB_->data;
374 w = (const double*)w_->data;
375 dm = (double*)dm_->data;
376 mA = XA_->dimensions[0];
377 mB = XB_->dimensions[0];
378 n = XA_->dimensions[1];
379 cdist_weighted_minkowski(XA, XB, dm, mA, mB, n, p, w);
380 NPY_END_ALLOW_THREADS;
381 }
382 return Py_BuildValue("d", 0.0);
383 }
384
385 /***************************** pdist ***/
386
387 #define DEFINE_WRAP_PDIST(name, type) \
388 static PyObject * \
389 pdist_ ## name ## _ ## type ## _wrap(PyObject *self, PyObject *args)\
390 { \
391 PyArrayObject *X_, *dm_; \
392 Py_ssize_t m, n; \
393 double *dm; \
394 const type *X; \
395 if (!PyArg_ParseTuple(args, "O!O!", &PyArray_Type, &X_, \
396 &PyArray_Type, &dm_)) { \
397 return NULL; \
398 } \
399 else { \
400 NPY_BEGIN_ALLOW_THREADS; \
401 X = (const type *)X_->data; \
402 dm = (double *)dm_->data; \
403 m = X_->dimensions[0]; \
404 n = X_->dimensions[1]; \
405 pdist_ ## name ## _ ## type(X, dm, m, n); \
406 NPY_END_ALLOW_THREADS; \
407 } \
408 return Py_BuildValue("d", 0.); \
409 }
410
DEFINE_WRAP_PDIST(bray_curtis,double)411 DEFINE_WRAP_PDIST(bray_curtis, double)
412 DEFINE_WRAP_PDIST(canberra, double)
413 DEFINE_WRAP_PDIST(chebyshev, double)
414 DEFINE_WRAP_PDIST(city_block, double)
415 DEFINE_WRAP_PDIST(euclidean, double)
416 DEFINE_WRAP_PDIST(jaccard, double)
417 DEFINE_WRAP_PDIST(jensenshannon, double)
418 DEFINE_WRAP_PDIST(sqeuclidean, double)
419
420 DEFINE_WRAP_PDIST(dice, char)
421 DEFINE_WRAP_PDIST(kulsinski, char)
422 DEFINE_WRAP_PDIST(jaccard, char)
423 DEFINE_WRAP_PDIST(rogerstanimoto, char)
424 DEFINE_WRAP_PDIST(russellrao, char)
425 DEFINE_WRAP_PDIST(sokalmichener, char)
426 DEFINE_WRAP_PDIST(sokalsneath, char)
427 DEFINE_WRAP_PDIST(yule, char)
428
429 static PyObject *pdist_hamming_double_wrap(
430 PyObject *self, PyObject *args, PyObject *kwargs)
431 {
432 PyArrayObject *X_, *dm_, *w_;
433 int m, n;
434 double *dm;
435 const double *X, *w;
436 static char *kwlist[] = {"X", "dm", "w", NULL};
437 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
438 "O!O!O!:pdist_hamming_double_wrap", kwlist,
439 &PyArray_Type, &X_,
440 &PyArray_Type, &dm_,
441 &PyArray_Type, &w_)) {
442 return 0;
443 }
444 else {
445 NPY_BEGIN_ALLOW_THREADS;
446 X = (const double*)X_->data;
447 dm = (double*)dm_->data;
448 w = (const double*)w_->data;
449 m = X_->dimensions[0];
450 n = X_->dimensions[1];
451
452 pdist_hamming_double(X, dm, m, n, w);
453 NPY_END_ALLOW_THREADS;
454 }
455 return Py_BuildValue("d", 0.0);
456 }
457
pdist_hamming_char_wrap(PyObject * self,PyObject * args,PyObject * kwargs)458 static PyObject *pdist_hamming_char_wrap(
459 PyObject *self, PyObject *args, PyObject *kwargs)
460 {
461 PyArrayObject *X_, *dm_, *w_;
462 int m, n;
463 const char *X;
464 const double *w;
465 double *dm;
466 static char *kwlist[] = {"X", "dm", "w", NULL};
467 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
468 "O!O!O!:pdist_hamming_char_wrap", kwlist,
469 &PyArray_Type, &X_,
470 &PyArray_Type, &dm_,
471 &PyArray_Type, &w_)) {
472 return 0;
473 }
474 else {
475 NPY_BEGIN_ALLOW_THREADS;
476 X = (const char*)X_->data;
477 dm = (double*)dm_->data;
478 w = (const double*)w_->data;
479 m = X_->dimensions[0];
480 n = X_->dimensions[1];
481
482 pdist_hamming_char(X, dm, m, n, w);
483 NPY_END_ALLOW_THREADS;
484 }
485 return Py_BuildValue("d", 0.0);
486 }
487
pdist_cosine_double_wrap(PyObject * self,PyObject * args,PyObject * kwargs)488 static PyObject *pdist_cosine_double_wrap(PyObject *self, PyObject *args,
489 PyObject *kwargs)
490 {
491 PyArrayObject *X_, *dm_;
492 int m, n, status;
493 double *dm;
494 const double *X;
495 static char *kwlist[] = {"X", "dm", NULL};
496 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
497 "O!O!:pdist_cosine_double_wrap", kwlist,
498 &PyArray_Type, &X_,
499 &PyArray_Type, &dm_)) {
500 return 0;
501 }
502 else {
503 NPY_BEGIN_THREADS_DEF;
504 NPY_BEGIN_THREADS;
505 X = (const double*)X_->data;
506 dm = (double*)dm_->data;
507 m = X_->dimensions[0];
508 n = X_->dimensions[1];
509
510 status = pdist_cosine(X, dm, m, n);
511 NPY_END_THREADS;
512 if(status < 0)
513 return PyErr_NoMemory();
514 }
515 return Py_BuildValue("d", 0.0);
516 }
517
pdist_mahalanobis_double_wrap(PyObject * self,PyObject * args,PyObject * kwargs)518 static PyObject *pdist_mahalanobis_double_wrap(PyObject *self, PyObject *args,
519 PyObject *kwargs) {
520 PyArrayObject *X_, *covinv_, *dm_;
521 int m, n, status;
522 double *dm;
523 const double *X;
524 const double *covinv;
525 static char *kwlist[] = {"X", "dm", "VI", NULL};
526 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
527 "O!O!O!:pdist_mahalanobis_double_wrap", kwlist,
528 &PyArray_Type, &X_,
529 &PyArray_Type, &dm_,
530 &PyArray_Type, &covinv_)) {
531 return 0;
532 }
533 else {
534 NPY_BEGIN_THREADS_DEF;
535 NPY_BEGIN_THREADS;
536 X = (const double*)X_->data;
537 covinv = (const double*)covinv_->data;
538 dm = (double*)dm_->data;
539 m = X_->dimensions[0];
540 n = X_->dimensions[1];
541
542 status = pdist_mahalanobis(X, dm, m, n, covinv);
543 NPY_END_THREADS;
544 if(status < 0)
545 return PyErr_NoMemory();
546 }
547 return Py_BuildValue("d", 0.0);
548 }
549
pdist_minkowski_double_wrap(PyObject * self,PyObject * args,PyObject * kwargs)550 static PyObject *pdist_minkowski_double_wrap(PyObject *self, PyObject *args,
551 PyObject *kwargs)
552 {
553 PyArrayObject *X_, *dm_;
554 int m, n;
555 double *dm, *X;
556 double p;
557 static char *kwlist[] = {"X", "dm", "p", NULL};
558 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
559 "O!O!d:pdist_minkowski_double_wrap", kwlist,
560 &PyArray_Type, &X_,
561 &PyArray_Type, &dm_,
562 &p)) {
563 return 0;
564 }
565 else {
566 NPY_BEGIN_ALLOW_THREADS;
567 X = (double*)X_->data;
568 dm = (double*)dm_->data;
569 m = X_->dimensions[0];
570 n = X_->dimensions[1];
571
572 pdist_minkowski(X, dm, m, n, p);
573 NPY_END_ALLOW_THREADS;
574 }
575 return Py_BuildValue("d", 0.0);
576 }
577
pdist_seuclidean_double_wrap(PyObject * self,PyObject * args,PyObject * kwargs)578 static PyObject *pdist_seuclidean_double_wrap(PyObject *self, PyObject *args,
579 PyObject *kwargs)
580 {
581 PyArrayObject *X_, *dm_, *var_;
582 int m, n;
583 double *dm;
584 const double *X, *var;
585 static char *kwlist[] = {"X", "dm", "V", NULL};
586 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
587 "O!O!O!:pdist_seuclidean_double_wrap", kwlist,
588 &PyArray_Type, &X_,
589 &PyArray_Type, &dm_,
590 &PyArray_Type, &var_)) {
591 return 0;
592 }
593 else {
594 NPY_BEGIN_ALLOW_THREADS;
595 X = (double*)X_->data;
596 dm = (double*)dm_->data;
597 var = (double*)var_->data;
598 m = X_->dimensions[0];
599 n = X_->dimensions[1];
600
601 pdist_seuclidean(X, var, dm, m, n);
602 NPY_END_ALLOW_THREADS;
603 }
604 return Py_BuildValue("d", 0.0);
605 }
606
pdist_weighted_chebyshev_double_wrap(PyObject * self,PyObject * args,PyObject * kwargs)607 static PyObject *pdist_weighted_chebyshev_double_wrap(
608 PyObject *self, PyObject *args, PyObject *kwargs)
609 {
610 PyArrayObject *X_, *dm_, *w_;
611 int m, n;
612 double *dm, *X, *w;
613 static char *kwlist[] = {"X", "dm", "w", NULL};
614 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
615 "O!O!O!:pdist_weighted_minkowski_double_wrap", kwlist,
616 &PyArray_Type, &X_,
617 &PyArray_Type, &dm_,
618 &PyArray_Type, &w_)) {
619 return 0;
620 }
621 else {
622 NPY_BEGIN_ALLOW_THREADS;
623 X = (double*)X_->data;
624 dm = (double*)dm_->data;
625 w = (double*)w_->data;
626 m = X_->dimensions[0];
627 n = X_->dimensions[1];
628
629 pdist_weighted_chebyshev(X, dm, m, n, w);
630 NPY_END_ALLOW_THREADS;
631 }
632 return Py_BuildValue("d", 0.0);
633 }
634
pdist_old_weighted_minkowski_double_wrap(PyObject * self,PyObject * args,PyObject * kwargs)635 static PyObject *pdist_old_weighted_minkowski_double_wrap(
636 PyObject *self, PyObject *args, PyObject *kwargs)
637 {
638 PyArrayObject *X_, *dm_, *w_;
639 int m, n;
640 double *dm, *X, *w;
641 double p;
642 static char *kwlist[] = {"X", "dm", "p", "w", NULL};
643 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
644 "O!O!dO!:pdist_weighted_minkowski_double_wrap", kwlist,
645 &PyArray_Type, &X_,
646 &PyArray_Type, &dm_,
647 &p,
648 &PyArray_Type, &w_)) {
649 return 0;
650 }
651 else {
652 int res;
653 NPY_BEGIN_ALLOW_THREADS;
654 X = (double*)X_->data;
655 dm = (double*)dm_->data;
656 w = (double*)w_->data;
657 m = X_->dimensions[0];
658 n = X_->dimensions[1];
659
660 res = pdist_old_weighted_minkowski(X, dm, m, n, p, w);
661 NPY_END_ALLOW_THREADS;
662 if (res) {
663 return PyErr_NoMemory();
664 }
665 }
666 return Py_BuildValue("d", 0.0);
667 }
668
pdist_weighted_minkowski_double_wrap(PyObject * self,PyObject * args,PyObject * kwargs)669 static PyObject *pdist_weighted_minkowski_double_wrap(
670 PyObject *self, PyObject *args, PyObject *kwargs)
671 {
672 PyArrayObject *X_, *dm_, *w_;
673 int m, n;
674 double *dm, *X, *w;
675 double p;
676 static char *kwlist[] = {"X", "dm", "p", "w", NULL};
677 if (!PyArg_ParseTupleAndKeywords(args, kwargs,
678 "O!O!dO!:pdist_weighted_minkowski_double_wrap", kwlist,
679 &PyArray_Type, &X_,
680 &PyArray_Type, &dm_,
681 &p,
682 &PyArray_Type, &w_)) {
683 return 0;
684 }
685 else {
686 NPY_BEGIN_ALLOW_THREADS;
687 X = (double*)X_->data;
688 dm = (double*)dm_->data;
689 w = (double*)w_->data;
690 m = X_->dimensions[0];
691 n = X_->dimensions[1];
692
693 pdist_weighted_minkowski(X, dm, m, n, p, w);
694 NPY_END_ALLOW_THREADS;
695 }
696 return Py_BuildValue("d", 0.0);
697 }
698
699
to_squareform_from_vector_wrap(PyObject * self,PyObject * args)700 static PyObject *to_squareform_from_vector_wrap(PyObject *self, PyObject *args)
701 {
702 PyArrayObject *M_, *v_;
703 int n, elsize;
704 if (!PyArg_ParseTuple(args, "O!O!",
705 &PyArray_Type, &M_,
706 &PyArray_Type, &v_)) {
707 return 0;
708 }
709 NPY_BEGIN_ALLOW_THREADS;
710 n = M_->dimensions[0];
711 elsize = M_->descr->elsize;
712 if (elsize == 8) {
713 dist_to_squareform_from_vector_double(
714 (double*)M_->data, (const double*)v_->data, n);
715 } else {
716 dist_to_squareform_from_vector_generic(
717 (char*)M_->data, (const char*)v_->data, n, elsize);
718 }
719 NPY_END_ALLOW_THREADS;
720 return Py_BuildValue("");
721 }
722
to_vector_from_squareform_wrap(PyObject * self,PyObject * args)723 static PyObject *to_vector_from_squareform_wrap(PyObject *self, PyObject *args)
724 {
725 PyArrayObject *M_, *v_;
726 int n, s;
727 char *v;
728 const char *M;
729 if (!PyArg_ParseTuple(args, "O!O!",
730 &PyArray_Type, &M_,
731 &PyArray_Type, &v_)) {
732 return 0;
733 }
734 else {
735 NPY_BEGIN_ALLOW_THREADS;
736 M = (const char*)M_->data;
737 v = (char*)v_->data;
738 n = M_->dimensions[0];
739 s = M_->descr->elsize;
740 dist_to_vector_from_squareform(M, v, n, s);
741 NPY_END_ALLOW_THREADS;
742 }
743 return Py_BuildValue("");
744 }
745
746
747 static PyMethodDef _distanceWrapMethods[] = {
748 {"cdist_braycurtis_double_wrap",
749 cdist_bray_curtis_double_wrap,
750 METH_VARARGS},
751 {"cdist_canberra_double_wrap",
752 cdist_canberra_double_wrap,
753 METH_VARARGS},
754 {"cdist_chebyshev_double_wrap",
755 cdist_chebyshev_double_wrap,
756 METH_VARARGS},
757 {"cdist_cityblock_double_wrap",
758 cdist_city_block_double_wrap,
759 METH_VARARGS},
760 {"cdist_cosine_double_wrap",
761 (PyCFunction) cdist_cosine_double_wrap,
762 METH_VARARGS | METH_KEYWORDS},
763 {"cdist_dice_bool_wrap",
764 cdist_dice_char_wrap,
765 METH_VARARGS},
766 {"cdist_euclidean_double_wrap",
767 cdist_euclidean_double_wrap,
768 METH_VARARGS},
769 {"cdist_sqeuclidean_double_wrap",
770 cdist_sqeuclidean_double_wrap,
771 METH_VARARGS},
772 {"cdist_hamming_double_wrap",
773 (PyCFunction) cdist_hamming_double_wrap,
774 METH_VARARGS | METH_KEYWORDS},
775 {"cdist_hamming_bool_wrap",
776 (PyCFunction) cdist_hamming_char_wrap,
777 METH_VARARGS | METH_KEYWORDS},
778 {"cdist_jaccard_double_wrap",
779 cdist_jaccard_double_wrap,
780 METH_VARARGS},
781 {"cdist_jaccard_bool_wrap",
782 cdist_jaccard_char_wrap,
783 METH_VARARGS},
784 {"cdist_jensenshannon_double_wrap",
785 cdist_jensenshannon_double_wrap,
786 METH_VARARGS},
787 {"cdist_kulsinski_bool_wrap",
788 cdist_kulsinski_char_wrap,
789 METH_VARARGS},
790 {"cdist_mahalanobis_double_wrap",
791 (PyCFunction) cdist_mahalanobis_double_wrap,
792 METH_VARARGS | METH_KEYWORDS},
793 {"cdist_minkowski_double_wrap",
794 (PyCFunction) cdist_minkowski_double_wrap,
795 METH_VARARGS | METH_KEYWORDS},
796 {"cdist_weighted_chebyshev_double_wrap",
797 (PyCFunction) cdist_weighted_chebyshev_double_wrap,
798 METH_VARARGS | METH_KEYWORDS},
799 {"cdist_old_weighted_minkowski_double_wrap",
800 (PyCFunction) cdist_old_weighted_minkowski_double_wrap,
801 METH_VARARGS | METH_KEYWORDS},
802 {"cdist_weighted_minkowski_double_wrap",
803 (PyCFunction) cdist_weighted_minkowski_double_wrap,
804 METH_VARARGS | METH_KEYWORDS},
805 {"cdist_rogerstanimoto_bool_wrap",
806 cdist_rogerstanimoto_char_wrap,
807 METH_VARARGS},
808 {"cdist_russellrao_bool_wrap",
809 cdist_russellrao_char_wrap,
810 METH_VARARGS},
811 {"cdist_seuclidean_double_wrap",
812 (PyCFunction) cdist_seuclidean_double_wrap,
813 METH_VARARGS | METH_KEYWORDS},
814 {"cdist_sokalmichener_bool_wrap",
815 cdist_sokalmichener_char_wrap,
816 METH_VARARGS},
817 {"cdist_sokalsneath_bool_wrap",
818 cdist_sokalsneath_char_wrap,
819 METH_VARARGS},
820 {"cdist_yule_bool_wrap",
821 cdist_yule_char_wrap,
822 METH_VARARGS},
823 {"pdist_braycurtis_double_wrap",
824 pdist_bray_curtis_double_wrap,
825 METH_VARARGS},
826 {"pdist_canberra_double_wrap",
827 pdist_canberra_double_wrap,
828 METH_VARARGS},
829 {"pdist_chebyshev_double_wrap",
830 pdist_chebyshev_double_wrap,
831 METH_VARARGS},
832 {"pdist_cityblock_double_wrap",
833 pdist_city_block_double_wrap,
834 METH_VARARGS},
835 {"pdist_cosine_double_wrap",
836 (PyCFunction) pdist_cosine_double_wrap,
837 METH_VARARGS | METH_KEYWORDS},
838 {"pdist_dice_bool_wrap",
839 pdist_dice_char_wrap,
840 METH_VARARGS},
841 {"pdist_euclidean_double_wrap",
842 pdist_euclidean_double_wrap,
843 METH_VARARGS},
844 {"pdist_sqeuclidean_double_wrap",
845 pdist_sqeuclidean_double_wrap,
846 METH_VARARGS},
847 {"pdist_hamming_double_wrap",
848 (PyCFunction) pdist_hamming_double_wrap,
849 METH_VARARGS | METH_KEYWORDS},
850 {"pdist_hamming_bool_wrap",
851 (PyCFunction) pdist_hamming_char_wrap,
852 METH_VARARGS | METH_KEYWORDS},
853 {"pdist_jaccard_double_wrap",
854 pdist_jaccard_double_wrap,
855 METH_VARARGS},
856 {"pdist_jaccard_bool_wrap",
857 pdist_jaccard_char_wrap,
858 METH_VARARGS},
859 {"pdist_jensenshannon_double_wrap",
860 pdist_jensenshannon_double_wrap,
861 METH_VARARGS},
862 {"pdist_kulsinski_bool_wrap",
863 pdist_kulsinski_char_wrap,
864 METH_VARARGS},
865 {"pdist_mahalanobis_double_wrap",
866 (PyCFunction) pdist_mahalanobis_double_wrap,
867 METH_VARARGS | METH_KEYWORDS},
868 {"pdist_minkowski_double_wrap",
869 (PyCFunction) pdist_minkowski_double_wrap,
870 METH_VARARGS | METH_KEYWORDS},
871 {"pdist_weighted_chebyshev_double_wrap",
872 (PyCFunction) pdist_weighted_chebyshev_double_wrap,
873 METH_VARARGS | METH_KEYWORDS},
874 {"pdist_old_weighted_minkowski_double_wrap",
875 (PyCFunction) pdist_old_weighted_minkowski_double_wrap,
876 METH_VARARGS | METH_KEYWORDS},
877 {"pdist_weighted_minkowski_double_wrap",
878 (PyCFunction) pdist_weighted_minkowski_double_wrap,
879 METH_VARARGS | METH_KEYWORDS},
880 {"pdist_rogerstanimoto_bool_wrap",
881 pdist_rogerstanimoto_char_wrap,
882 METH_VARARGS},
883 {"pdist_russellrao_bool_wrap",
884 pdist_russellrao_char_wrap,
885 METH_VARARGS},
886 {"pdist_seuclidean_double_wrap",
887 (PyCFunction) pdist_seuclidean_double_wrap,
888 METH_VARARGS | METH_KEYWORDS},
889 {"pdist_sokalmichener_bool_wrap",
890 pdist_sokalmichener_char_wrap,
891 METH_VARARGS},
892 {"pdist_sokalsneath_bool_wrap",
893 pdist_sokalsneath_char_wrap,
894 METH_VARARGS},
895 {"pdist_yule_bool_wrap",
896 pdist_yule_char_wrap,
897 METH_VARARGS},
898 {"to_squareform_from_vector_wrap",
899 to_squareform_from_vector_wrap,
900 METH_VARARGS},
901 {"to_vector_from_squareform_wrap",
902 to_vector_from_squareform_wrap,
903 METH_VARARGS},
904 {NULL, NULL} /* Sentinel - marks the end of this structure */
905 };
906
907 static struct PyModuleDef moduledef = {
908 PyModuleDef_HEAD_INIT,
909 "_distance_wrap",
910 NULL,
911 -1,
912 _distanceWrapMethods,
913 NULL,
914 NULL,
915 NULL,
916 NULL
917 };
918
PyInit__distance_wrap(void)919 PyObject *PyInit__distance_wrap(void)
920 {
921 PyObject *m;
922
923 m = PyModule_Create(&moduledef);
924 import_array();
925
926 return m;
927 }
928