diff --git a/sklearn/cluster/_hierarchical.c b/sklearn/cluster/_hierarchical.c
index f62b8ad1c1100cc8d327e084a689e0b51ead9939..ecf30f0ab2fc08c08d843db311e51d1642f57628 100644
--- a/sklearn/cluster/_hierarchical.c
+++ b/sklearn/cluster/_hierarchical.c
@@ -1,6 +1,18 @@
-/* Generated by Cython 0.17.4 on Thu Jan 10 17:59:48 2013 */
+/* Generated by Cython 0.19.1 on Wed Aug  7 14:16:15 2013 */
 
 #define PY_SSIZE_T_CLEAN
+#ifndef CYTHON_USE_PYLONG_INTERNALS
+#ifdef PYLONG_BITS_IN_DIGIT
+#define CYTHON_USE_PYLONG_INTERNALS 0
+#else
+#include "pyconfig.h"
+#ifdef PYLONG_BITS_IN_DIGIT
+#define CYTHON_USE_PYLONG_INTERNALS 1
+#else
+#define CYTHON_USE_PYLONG_INTERNALS 0
+#endif
+#endif
+#endif
 #include "Python.h"
 #ifndef Py_PYTHON_H
     #error Python headers needed to compile C extensions, please install development version of Python.
@@ -116,6 +128,9 @@
 #if (PY_VERSION_HEX < 0x02060000) || (PY_MAJOR_VERSION >= 3)
   #define Py_TPFLAGS_HAVE_NEWBUFFER 0
 #endif
+#if PY_VERSION_HEX < 0x02060000
+  #define Py_TPFLAGS_HAVE_VERSION_TAG 0
+#endif
 #if PY_VERSION_HEX > 0x03030000 && defined(PyUnicode_KIND)
   #define CYTHON_PEP393_ENABLED 1
   #define __Pyx_PyUnicode_READY(op)       (likely(PyUnicode_IS_READY(op)) ? \
@@ -155,6 +170,14 @@
   #define PyBytes_Concat               PyString_Concat
   #define PyBytes_ConcatAndDel         PyString_ConcatAndDel
 #endif
+#if PY_MAJOR_VERSION >= 3
+  #define __Pyx_PyBaseString_Check(obj) PyUnicode_Check(obj)
+  #define __Pyx_PyBaseString_CheckExact(obj) PyUnicode_CheckExact(obj)
+#else
+  #define __Pyx_PyBaseString_Check(obj) (PyString_CheckExact(obj) || PyUnicode_CheckExact(obj) || \
+                                         PyString_Check(obj) || PyUnicode_Check(obj))
+  #define __Pyx_PyBaseString_CheckExact(obj) (Py_TYPE(obj) == &PyBaseString_Type)
+#endif
 #if PY_VERSION_HEX < 0x02060000
   #define PySet_Check(obj)             PyObject_TypeCheck(obj, &PySet_Type)
   #define PyFrozenSet_Check(obj)       PyObject_TypeCheck(obj, &PyFrozenSet_Type)
@@ -227,6 +250,40 @@
   #define __Pyx_NAMESTR(n) (n)
   #define __Pyx_DOCSTR(n)  (n)
 #endif
+#ifndef CYTHON_INLINE
+  #if defined(__GNUC__)
+    #define CYTHON_INLINE __inline__
+  #elif defined(_MSC_VER)
+    #define CYTHON_INLINE __inline
+  #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+    #define CYTHON_INLINE inline
+  #else
+    #define CYTHON_INLINE
+  #endif
+#endif
+#ifndef CYTHON_RESTRICT
+  #if defined(__GNUC__)
+    #define CYTHON_RESTRICT __restrict__
+  #elif defined(_MSC_VER)
+    #define CYTHON_RESTRICT __restrict
+  #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+    #define CYTHON_RESTRICT restrict
+  #else
+    #define CYTHON_RESTRICT
+  #endif
+#endif
+#ifdef NAN
+#define __PYX_NAN() ((float) NAN)
+#else
+static CYTHON_INLINE float __PYX_NAN() {
+  /* Initialize NaN. The sign is irrelevant, an exponent with all bits 1 and
+   a nonzero mantissa means NaN. If the first bit in the mantissa is 1, it is
+   a quiet NaN. */
+  float value;
+  memset(&value, 0xFF, sizeof(value));
+  return value;
+}
+#endif
 
 
 #if PY_MAJOR_VERSION >= 3
@@ -251,6 +308,7 @@
 #include <math.h>
 #define __PYX_HAVE__sklearn__cluster___hierarchical
 #define __PYX_HAVE_API__sklearn__cluster___hierarchical
+#include "string.h"
 #include "stdio.h"
 #include "stdlib.h"
 #include "numpy/arrayobject.h"
@@ -263,21 +321,6 @@
 #define CYTHON_WITHOUT_ASSERTIONS
 #endif
 
-
-/* inline attribute */
-#ifndef CYTHON_INLINE
-  #if defined(__GNUC__)
-    #define CYTHON_INLINE __inline__
-  #elif defined(_MSC_VER)
-    #define CYTHON_INLINE __inline
-  #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
-    #define CYTHON_INLINE inline
-  #else
-    #define CYTHON_INLINE
-  #endif
-#endif
-
-/* unused attribute */
 #ifndef CYTHON_UNUSED
 # if defined(__GNUC__)
 #   if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
@@ -291,30 +334,130 @@
 #   define CYTHON_UNUSED
 # endif
 #endif
-
-typedef struct {PyObject **p; char *s; const long n; const char* encoding; const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; /*proto*/
-
-
-/* Type Conversion Predeclarations */
-
-#define __Pyx_PyBytes_FromUString(s) PyBytes_FromString((char*)s)
-#define __Pyx_PyBytes_AsUString(s)   ((unsigned char*) PyBytes_AsString(s))
-
+typedef struct {PyObject **p; char *s; const Py_ssize_t n; const char* encoding;
+                const char is_unicode; const char is_str; const char intern; } __Pyx_StringTabEntry; /*proto*/
+
+#define __PYX_DEFAULT_STRING_ENCODING_IS_ASCII 0
+#define __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT 0
+#define __PYX_DEFAULT_STRING_ENCODING ""
+#define __Pyx_PyObject_FromString __Pyx_PyBytes_FromString
+#define __Pyx_PyObject_FromStringAndSize __Pyx_PyBytes_FromStringAndSize
+static CYTHON_INLINE char* __Pyx_PyObject_AsString(PyObject*);
+static CYTHON_INLINE char* __Pyx_PyObject_AsStringAndSize(PyObject*, Py_ssize_t* length);
+#define __Pyx_PyBytes_FromString        PyBytes_FromString
+#define __Pyx_PyBytes_FromStringAndSize PyBytes_FromStringAndSize
+static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(char*);
+#if PY_MAJOR_VERSION < 3
+    #define __Pyx_PyStr_FromString        __Pyx_PyBytes_FromString
+    #define __Pyx_PyStr_FromStringAndSize __Pyx_PyBytes_FromStringAndSize
+#else
+    #define __Pyx_PyStr_FromString        __Pyx_PyUnicode_FromString
+    #define __Pyx_PyStr_FromStringAndSize __Pyx_PyUnicode_FromStringAndSize
+#endif
+#define __Pyx_PyObject_AsUString(s)    ((unsigned char*) __Pyx_PyObject_AsString(s))
+#define __Pyx_PyObject_FromUString(s)  __Pyx_PyObject_FromString((char*)s)
+#define __Pyx_PyBytes_FromUString(s)   __Pyx_PyBytes_FromString((char*)s)
+#define __Pyx_PyStr_FromUString(s)     __Pyx_PyStr_FromString((char*)s)
+#define __Pyx_PyUnicode_FromUString(s) __Pyx_PyUnicode_FromString((char*)s)
+#if PY_MAJOR_VERSION < 3
+static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u)
+{
+    const Py_UNICODE *u_end = u;
+    while (*u_end++) ;
+    return u_end - u - 1;
+}
+#else
+#define __Pyx_Py_UNICODE_strlen Py_UNICODE_strlen
+#endif
+#define __Pyx_PyUnicode_FromUnicode(u)       PyUnicode_FromUnicode(u, __Pyx_Py_UNICODE_strlen(u))
+#define __Pyx_PyUnicode_FromUnicodeAndLength PyUnicode_FromUnicode
+#define __Pyx_PyUnicode_AsUnicode            PyUnicode_AsUnicode
 #define __Pyx_Owned_Py_None(b) (Py_INCREF(Py_None), Py_None)
 #define __Pyx_PyBool_FromLong(b) ((b) ? (Py_INCREF(Py_True), Py_True) : (Py_INCREF(Py_False), Py_False))
 static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*);
 static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x);
-
 static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject*);
 static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t);
 static CYTHON_INLINE size_t __Pyx_PyInt_AsSize_t(PyObject*);
-
 #if CYTHON_COMPILING_IN_CPYTHON
 #define __pyx_PyFloat_AsDouble(x) (PyFloat_CheckExact(x) ? PyFloat_AS_DOUBLE(x) : PyFloat_AsDouble(x))
 #else
 #define __pyx_PyFloat_AsDouble(x) PyFloat_AsDouble(x)
 #endif
 #define __pyx_PyFloat_AsFloat(x) ((float) __pyx_PyFloat_AsDouble(x))
+#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII
+static int __Pyx_sys_getdefaultencoding_not_ascii;
+static int __Pyx_init_sys_getdefaultencoding_params() {
+    PyObject* sys = NULL;
+    PyObject* default_encoding = NULL;
+    PyObject* ascii_chars_u = NULL;
+    PyObject* ascii_chars_b = NULL;
+    sys = PyImport_ImportModule("sys");
+    if (sys == NULL) goto bad;
+    default_encoding = PyObject_CallMethod(sys, (char*) (const char*) "getdefaultencoding", NULL);
+    if (default_encoding == NULL) goto bad;
+    if (strcmp(PyBytes_AsString(default_encoding), "ascii") == 0) {
+        __Pyx_sys_getdefaultencoding_not_ascii = 0;
+    } else {
+        const char* default_encoding_c = PyBytes_AS_STRING(default_encoding);
+        char ascii_chars[128];
+        int c;
+        for (c = 0; c < 128; c++) {
+            ascii_chars[c] = c;
+        }
+        __Pyx_sys_getdefaultencoding_not_ascii = 1;
+        ascii_chars_u = PyUnicode_DecodeASCII(ascii_chars, 128, NULL);
+        if (ascii_chars_u == NULL) goto bad;
+        ascii_chars_b = PyUnicode_AsEncodedString(ascii_chars_u, default_encoding_c, NULL);
+        if (ascii_chars_b == NULL || strncmp(ascii_chars, PyBytes_AS_STRING(ascii_chars_b), 128) != 0) {
+            PyErr_Format(
+                PyExc_ValueError,
+                "This module compiled with c_string_encoding=ascii, but default encoding '%s' is not a superset of ascii.",
+                default_encoding_c);
+            goto bad;
+        }
+    }
+    Py_XDECREF(sys);
+    Py_XDECREF(default_encoding);
+    Py_XDECREF(ascii_chars_u);
+    Py_XDECREF(ascii_chars_b);
+    return 0;
+bad:
+    Py_XDECREF(sys);
+    Py_XDECREF(default_encoding);
+    Py_XDECREF(ascii_chars_u);
+    Py_XDECREF(ascii_chars_b);
+    return -1;
+}
+#endif
+#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT && PY_MAJOR_VERSION >= 3
+#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_DecodeUTF8(c_str, size, NULL)
+#else
+#define __Pyx_PyUnicode_FromStringAndSize(c_str, size) PyUnicode_Decode(c_str, size, __PYX_DEFAULT_STRING_ENCODING, NULL)
+#if __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT
+static char* __PYX_DEFAULT_STRING_ENCODING;
+static int __Pyx_init_sys_getdefaultencoding_params() {
+    PyObject* sys = NULL;
+    PyObject* default_encoding = NULL;
+    char* default_encoding_c;
+    sys = PyImport_ImportModule("sys");
+    if (sys == NULL) goto bad;
+    default_encoding = PyObject_CallMethod(sys, (char*) (const char*) "getdefaultencoding", NULL);
+    if (default_encoding == NULL) goto bad;
+    default_encoding_c = PyBytes_AS_STRING(default_encoding);
+    __PYX_DEFAULT_STRING_ENCODING = (char*) malloc(strlen(default_encoding_c));
+    strcpy(__PYX_DEFAULT_STRING_ENCODING, default_encoding_c);
+    Py_DECREF(sys);
+    Py_DECREF(default_encoding);
+    return 0;
+bad:
+    Py_XDECREF(sys);
+    Py_XDECREF(default_encoding);
+    return -1;
+}
+#endif
+#endif
+
 
 #ifdef __GNUC__
   /* Test for GCC > 2.95 */
@@ -329,8 +472,9 @@ static CYTHON_INLINE size_t __Pyx_PyInt_AsSize_t(PyObject*);
   #define likely(x)   (x)
   #define unlikely(x) (x)
 #endif /* __GNUC__ */
-    
+
 static PyObject *__pyx_m;
+static PyObject *__pyx_d;
 static PyObject *__pyx_b;
 static PyObject *__pyx_empty_tuple;
 static PyObject *__pyx_empty_bytes;
@@ -591,27 +735,27 @@ typedef npy_double __pyx_t_5numpy_double_t;
  */
 typedef npy_longdouble __pyx_t_5numpy_longdouble_t;
 
-/* "sklearn/cluster/_hierarchical.pyx":4
- * cimport numpy as np
+/* "sklearn/cluster/_hierarchical.pyx":7
  * cimport cython
+ * 
  * ctypedef np.float64_t DOUBLE             # <<<<<<<<<<<<<<
- * ctypedef np.int_t INT
+ * ctypedef np.npy_intp INTP
  * ctypedef np.int8_t INT8
  */
 typedef __pyx_t_5numpy_float64_t __pyx_t_7sklearn_7cluster_13_hierarchical_DOUBLE;
 
-/* "sklearn/cluster/_hierarchical.pyx":5
- * cimport cython
+/* "sklearn/cluster/_hierarchical.pyx":8
+ * 
  * ctypedef np.float64_t DOUBLE
- * ctypedef np.int_t INT             # <<<<<<<<<<<<<<
+ * ctypedef np.npy_intp INTP             # <<<<<<<<<<<<<<
  * ctypedef np.int8_t INT8
  * 
  */
-typedef __pyx_t_5numpy_int_t __pyx_t_7sklearn_7cluster_13_hierarchical_INT;
+typedef npy_intp __pyx_t_7sklearn_7cluster_13_hierarchical_INTP;
 
-/* "sklearn/cluster/_hierarchical.pyx":6
+/* "sklearn/cluster/_hierarchical.pyx":9
  * ctypedef np.float64_t DOUBLE
- * ctypedef np.int_t INT
+ * ctypedef np.npy_intp INTP
  * ctypedef np.int8_t INT8             # <<<<<<<<<<<<<<
  * 
  * np.import_array()
@@ -729,7 +873,22 @@ typedef npy_cdouble __pyx_t_5numpy_complex_t;
 #define __Pyx_CLEAR(r)    do { PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);} while(0)
 #define __Pyx_XCLEAR(r)   do { if((r) != NULL) {PyObject* tmp = ((PyObject*)(r)); r = NULL; __Pyx_DECREF(tmp);}} while(0)
 
-static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name); /*proto*/
+#if CYTHON_COMPILING_IN_CPYTHON
+static CYTHON_INLINE PyObject* __Pyx_PyObject_GetAttrStr(PyObject* obj, PyObject* attr_name) {
+    PyTypeObject* tp = Py_TYPE(obj);
+    if (likely(tp->tp_getattro))
+        return tp->tp_getattro(obj, attr_name);
+#if PY_MAJOR_VERSION < 3
+    if (likely(tp->tp_getattr))
+        return tp->tp_getattr(obj, PyString_AS_STRING(attr_name));
+#endif
+    return PyObject_GetAttr(obj, attr_name);
+}
+#else
+#define __Pyx_PyObject_GetAttrStr(o,n) PyObject_GetAttr(o,n)
+#endif
+
+static PyObject *__Pyx_GetBuiltinName(PyObject *name); /*proto*/
 
 static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact,
     Py_ssize_t num_min, Py_ssize_t num_max, Py_ssize_t num_found); /*proto*/
@@ -747,131 +906,77 @@ static CYTHON_INLINE int  __Pyx_GetBufferAndValidate(Py_buffer* buf, PyObject* o
     __Pyx_TypeInfo* dtype, int flags, int nd, int cast, __Pyx_BufFmt_StackElem* stack);
 static CYTHON_INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info);
 
-#define __Pyx_BufPtrStrided1d(type, buf, i0, s0) (type)((char*)buf + i0 * s0)
-#define __Pyx_BufPtrStrided2d(type, buf, i0, s0, i1, s1) (type)((char*)buf + i0 * s0 + i1 * s1)
+#define __Pyx_BufPtrCContig1d(type, buf, i0, s0) ((type)buf + i0)
+#define __Pyx_BufPtrCContig2d(type, buf, i0, s0, i1, s1) ((type)((char*)buf + i0 * s0) + i1)
 static CYTHON_INLINE void __Pyx_ErrRestore(PyObject *type, PyObject *value, PyObject *tb); /*proto*/
 static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyObject **tb); /*proto*/
 
-static CYTHON_INLINE PyObject* __Pyx_PyObject_Pop(PyObject* L) {
-#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x02040000
-    if (likely(PyList_CheckExact(L))
-        && likely(PyList_GET_SIZE(L) > (((PyListObject*)L)->allocated >> 1))) {
-        Py_SIZE(L) -= 1;
-        return PyList_GET_ITEM(L, PyList_GET_SIZE(L));
-    }
-#if PY_VERSION_HEX >= 0x02050000
-    else if (Py_TYPE(L) == (&PySet_Type)) {
-        return PySet_Pop(L);
-    }
-#endif
-#endif
-    return PyObject_CallMethod(L, (char*)"pop", NULL);
+static PyObject* __Pyx_PyObject_CallMethodTuple(PyObject* obj, PyObject* method_name, PyObject* args) {
+    PyObject *method, *result = NULL;
+    if (unlikely(!args)) return NULL;
+    method = __Pyx_PyObject_GetAttrStr(obj, method_name);
+    if (unlikely(!method)) goto bad;
+    result = PyObject_Call(method, args, NULL);
+    Py_DECREF(method);
+bad:
+    Py_DECREF(args);
+    return result;
 }
+#define __Pyx_PyObject_CallMethod3(obj, name, arg1, arg2, arg3) \
+    __Pyx_PyObject_CallMethodTuple(obj, name, PyTuple_Pack(3, arg1, arg2, arg3))
+#define __Pyx_PyObject_CallMethod2(obj, name, arg1, arg2) \
+    __Pyx_PyObject_CallMethodTuple(obj, name, PyTuple_Pack(2, arg1, arg2))
+#define __Pyx_PyObject_CallMethod1(obj, name, arg1) \
+    __Pyx_PyObject_CallMethodTuple(obj, name, PyTuple_Pack(1, arg1))
+#define __Pyx_PyObject_CallMethod0(obj, name) \
+    __Pyx_PyObject_CallMethodTuple(obj, name, (Py_INCREF(__pyx_empty_tuple), __pyx_empty_tuple))
+
+static CYTHON_INLINE PyObject* __Pyx_PyObject_Pop(PyObject* L); /*proto*/
 
-static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) {
-    PyObject *r;
-    if (!j) return NULL;
-    r = PyObject_GetItem(o, j);
-    Py_DECREF(j);
-    return r;
-}
-#define __Pyx_GetItemInt_List(o, i, size, to_py_func) (((size) <= sizeof(Py_ssize_t)) ? \
-                                                    __Pyx_GetItemInt_List_Fast(o, i) : \
-                                                    __Pyx_GetItemInt_Generic(o, to_py_func(i)))
-static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i) {
-#if CYTHON_COMPILING_IN_CPYTHON
-    if (likely((0 <= i) & (i < PyList_GET_SIZE(o)))) {
-        PyObject *r = PyList_GET_ITEM(o, i);
-        Py_INCREF(r);
-        return r;
-    }
-    else if ((-PyList_GET_SIZE(o) <= i) & (i < 0)) {
-        PyObject *r = PyList_GET_ITEM(o, PyList_GET_SIZE(o) + i);
-        Py_INCREF(r);
-        return r;
-    }
-    return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i));
-#else
-    return PySequence_GetItem(o, i);
-#endif
-}
-#define __Pyx_GetItemInt_Tuple(o, i, size, to_py_func) (((size) <= sizeof(Py_ssize_t)) ? \
-                                                    __Pyx_GetItemInt_Tuple_Fast(o, i) : \
-                                                    __Pyx_GetItemInt_Generic(o, to_py_func(i)))
-static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i) {
 #if CYTHON_COMPILING_IN_CPYTHON
-    if (likely((0 <= i) & (i < PyTuple_GET_SIZE(o)))) {
-        PyObject *r = PyTuple_GET_ITEM(o, i);
-        Py_INCREF(r);
-        return r;
-    }
-    else if ((-PyTuple_GET_SIZE(o) <= i) & (i < 0)) {
-        PyObject *r = PyTuple_GET_ITEM(o, PyTuple_GET_SIZE(o) + i);
-        Py_INCREF(r);
-        return r;
+static CYTHON_INLINE int __Pyx_PyList_Append(PyObject* list, PyObject* x) {
+    PyListObject* L = (PyListObject*) list;
+    Py_ssize_t len = Py_SIZE(list);
+    if (likely(L->allocated > len) & likely(len > (L->allocated >> 1))) {
+        Py_INCREF(x);
+        PyList_SET_ITEM(list, len, x);
+        Py_SIZE(list) = len+1;
+        return 0;
     }
-    return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i));
-#else
-    return PySequence_GetItem(o, i);
-#endif
+    return PyList_Append(list, x);
 }
-#define __Pyx_GetItemInt(o, i, size, to_py_func) (((size) <= sizeof(Py_ssize_t)) ? \
-                                                    __Pyx_GetItemInt_Fast(o, i) : \
-                                                    __Pyx_GetItemInt_Generic(o, to_py_func(i)))
-static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i) {
-#if CYTHON_COMPILING_IN_CPYTHON
-    if (PyList_CheckExact(o)) {
-        Py_ssize_t n = (likely(i >= 0)) ? i : i + PyList_GET_SIZE(o);
-        if (likely((n >= 0) & (n < PyList_GET_SIZE(o)))) {
-            PyObject *r = PyList_GET_ITEM(o, n);
-            Py_INCREF(r);
-            return r;
-        }
-    }
-    else if (PyTuple_CheckExact(o)) {
-        Py_ssize_t n = (likely(i >= 0)) ? i : i + PyTuple_GET_SIZE(o);
-        if (likely((n >= 0) & (n < PyTuple_GET_SIZE(o)))) {
-            PyObject *r = PyTuple_GET_ITEM(o, n);
-            Py_INCREF(r);
-            return r;
-        }
-    } else {  /* inlined PySequence_GetItem() */
-        PySequenceMethods *m = Py_TYPE(o)->tp_as_sequence;
-        if (likely(m && m->sq_item)) {
-            if (unlikely(i < 0) && likely(m->sq_length)) {
-                Py_ssize_t l = m->sq_length(o);
-                if (unlikely(l < 0)) return NULL;
-                i += l;
-            }
-            return m->sq_item(o, i);
-        }
-    }
 #else
-    if (PySequence_Check(o)) {
-        return PySequence_GetItem(o, i);
-    }
+#define __Pyx_PyList_Append(L,x) PyList_Append(L,x)
 #endif
-    return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i));
-}
+
+#define __Pyx_GetItemInt(o, i, size, to_py_func, is_list, wraparound, boundscheck) \
+    (((size) <= sizeof(Py_ssize_t)) ? \
+    __Pyx_GetItemInt_Fast(o, i, is_list, wraparound, boundscheck) : \
+    __Pyx_GetItemInt_Generic(o, to_py_func(i)))
+#define __Pyx_GetItemInt_List(o, i, size, to_py_func, is_list, wraparound, boundscheck) \
+    (((size) <= sizeof(Py_ssize_t)) ? \
+    __Pyx_GetItemInt_List_Fast(o, i, wraparound, boundscheck) : \
+    __Pyx_GetItemInt_Generic(o, to_py_func(i)))
+static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i,
+                                                              int wraparound, int boundscheck);
+#define __Pyx_GetItemInt_Tuple(o, i, size, to_py_func, is_list, wraparound, boundscheck) \
+    (((size) <= sizeof(Py_ssize_t)) ? \
+    __Pyx_GetItemInt_Tuple_Fast(o, i, wraparound, boundscheck) : \
+    __Pyx_GetItemInt_Generic(o, to_py_func(i)))
+static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i,
+                                                              int wraparound, int boundscheck);
+static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j);
+static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i,
+                                                     int is_list, int wraparound, int boundscheck);
+
+static CYTHON_INLINE PyObject *__Pyx_GetModuleGlobalName(PyObject *name); /*proto*/
 
 static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type); /*proto*/
 
 static void __Pyx_RaiseBufferFallbackError(void); /*proto*/
 
-static CYTHON_INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) {
-    if (likely(PyList_CheckExact(L))) {
-        if (unlikely(PyList_Append(L, x) < 0)) return NULL;
-        Py_INCREF(Py_None);
-        return Py_None; /* this is just to have an accurate signature */
-    } else {
-        PyObject *r, *m;
-        m = __Pyx_GetAttrString(L, "append");
-        if (!m) return NULL;
-        r = PyObject_CallFunctionObjArgs(m, x, NULL);
-        Py_DECREF(m);
-        return r;
-    }
-}
+#define __Pyx_BufPtrStrided1d(type, buf, i0, s0) (type)((char*)buf + i0 * s0)
+static CYTHON_INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x); /*proto*/
 
 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject *cause); /*proto*/
 
@@ -910,7 +1015,11 @@ typedef struct {
 static Py_ssize_t __Pyx_zeros[] = {0, 0, 0, 0, 0, 0, 0, 0};
 static Py_ssize_t __Pyx_minusones[] = {-1, -1, -1, -1, -1, -1, -1, -1};
 
-static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, long level); /*proto*/
+static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level); /*proto*/
+
+static CYTHON_INLINE Py_intptr_t __Pyx_PyInt_from_py_Py_intptr_t(PyObject *);
+
+static CYTHON_INLINE PyObject *__Pyx_PyInt_to_py_Py_intptr_t(Py_intptr_t);
 
 #if CYTHON_CCOMPLEX
   #ifdef __cplusplus
@@ -1080,6 +1189,8 @@ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t); /*proto*/
 
 /* Module declarations from 'cpython.ref' */
 
+/* Module declarations from 'libc.string' */
+
 /* Module declarations from 'libc.stdio' */
 
 /* Module declarations from 'cpython.object' */
@@ -1105,7 +1216,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *, cha
 
 /* Module declarations from 'sklearn.cluster._hierarchical' */
 static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_7sklearn_7cluster_13_hierarchical_DOUBLE = { "DOUBLE", NULL, sizeof(__pyx_t_7sklearn_7cluster_13_hierarchical_DOUBLE), { 0 }, 0, 'R', 0, 0 };
-static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_7sklearn_7cluster_13_hierarchical_INT = { "INT", NULL, sizeof(__pyx_t_7sklearn_7cluster_13_hierarchical_INT), { 0 }, 0, IS_UNSIGNED(__pyx_t_7sklearn_7cluster_13_hierarchical_INT) ? 'U' : 'I', IS_UNSIGNED(__pyx_t_7sklearn_7cluster_13_hierarchical_INT), 0 };
+static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_7sklearn_7cluster_13_hierarchical_INTP = { "INTP", NULL, sizeof(__pyx_t_7sklearn_7cluster_13_hierarchical_INTP), { 0 }, 0, IS_UNSIGNED(__pyx_t_7sklearn_7cluster_13_hierarchical_INTP) ? 'U' : 'I', IS_UNSIGNED(__pyx_t_7sklearn_7cluster_13_hierarchical_INTP), 0 };
 static __Pyx_TypeInfo __Pyx_TypeInfo_nn___pyx_t_7sklearn_7cluster_13_hierarchical_INT8 = { "INT8", NULL, sizeof(__pyx_t_7sklearn_7cluster_13_hierarchical_INT8), { 0 }, 0, IS_UNSIGNED(__pyx_t_7sklearn_7cluster_13_hierarchical_INT8) ? 'U' : 'I', IS_UNSIGNED(__pyx_t_7sklearn_7cluster_13_hierarchical_INT8), 0 };
 #define __Pyx_MODULE_NAME "sklearn.cluster._hierarchical"
 int __pyx_module_is_main_sklearn__cluster___hierarchical = 0;
@@ -1115,7 +1226,7 @@ static PyObject *__pyx_builtin_range;
 static PyObject *__pyx_builtin_ValueError;
 static PyObject *__pyx_builtin_RuntimeError;
 static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_compute_ward_dist(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_m_1, PyArrayObject *__pyx_v_m_2, PyArrayObject *__pyx_v_coord_row, PyArrayObject *__pyx_v_coord_col, PyArrayObject *__pyx_v_res); /* proto */
-static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_2_hc_get_descendent(CYTHON_UNUSED PyObject *__pyx_self, int __pyx_v_node, PyObject *__pyx_v_children, int __pyx_v_n_leaves); /* proto */
+static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_2_hc_get_descendent(CYTHON_UNUSED PyObject *__pyx_self, __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_v_node, PyObject *__pyx_v_children, __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_v_n_leaves); /* proto */
 static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_4hc_get_heads(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_parents, PyObject *__pyx_v_copy); /* proto */
 static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_6_get_parents(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_nodes, PyObject *__pyx_v_heads, PyArrayObject *__pyx_v_parents, PyArrayObject *__pyx_v_not_visited); /* proto */
 static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags); /* proto */
@@ -1126,7 +1237,7 @@ static char __pyx_k_6[] = "Non-native byte order not supported";
 static char __pyx_k_8[] = "unknown dtype code in numpy.pxd (%d)";
 static char __pyx_k_9[] = "Format string allocated too short, see comment in numpy.pxd";
 static char __pyx_k_12[] = "Format string allocated too short.";
-static char __pyx_k_16[] = "/scratch/apps/src/scikit-learn/sklearn/cluster/_hierarchical.pyx";
+static char __pyx_k_16[] = "/home/lars/src/scikit-learn/sklearn/cluster/_hierarchical.pyx";
 static char __pyx_k_17[] = "sklearn.cluster._hierarchical";
 static char __pyx_k__B[] = "B";
 static char __pyx_k__H[] = "H";
@@ -1153,6 +1264,7 @@ static char __pyx_k__col[] = "col";
 static char __pyx_k__ind[] = "ind";
 static char __pyx_k__m_1[] = "m_1";
 static char __pyx_k__m_2[] = "m_2";
+static char __pyx_k__pop[] = "pop";
 static char __pyx_k__res[] = "res";
 static char __pyx_k__row[] = "row";
 static char __pyx_k__copy[] = "copy";
@@ -1163,6 +1275,7 @@ static char __pyx_k__node0[] = "node0";
 static char __pyx_k__nodes[] = "nodes";
 static char __pyx_k__numpy[] = "numpy";
 static char __pyx_k__range[] = "range";
+static char __pyx_k__append[] = "append";
 static char __pyx_k__extend[] = "extend";
 static char __pyx_k__parent[] = "parent";
 static char __pyx_k__parents[] = "parents";
@@ -1175,14 +1288,17 @@ static char __pyx_k__coord_col[] = "coord_col";
 static char __pyx_k__coord_row[] = "coord_row";
 static char __pyx_k__n_indices[] = "n_indices";
 static char __pyx_k__ValueError[] = "ValueError";
+static char __pyx_k____import__[] = "__import__";
 static char __pyx_k__descendent[] = "descendent";
 static char __pyx_k__n_features[] = "n_features";
 static char __pyx_k__not_visited[] = "not_visited";
 static char __pyx_k__RuntimeError[] = "RuntimeError";
 static char __pyx_k___get_parents[] = "_get_parents";
 static char __pyx_k__hc_get_heads[] = "hc_get_heads";
+static char __pyx_k____pyx_getbuffer[] = "__pyx_getbuffer";
 static char __pyx_k__compute_ward_dist[] = "compute_ward_dist";
 static char __pyx_k___hc_get_descendent[] = "_hc_get_descendent";
+static char __pyx_k____pyx_releasebuffer[] = "__pyx_releasebuffer";
 static PyObject *__pyx_kp_u_12;
 static PyObject *__pyx_kp_s_16;
 static PyObject *__pyx_n_s_17;
@@ -1193,10 +1309,14 @@ static PyObject *__pyx_kp_u_8;
 static PyObject *__pyx_kp_u_9;
 static PyObject *__pyx_n_s__RuntimeError;
 static PyObject *__pyx_n_s__ValueError;
+static PyObject *__pyx_n_s____import__;
 static PyObject *__pyx_n_s____main__;
+static PyObject *__pyx_n_s____pyx_getbuffer;
+static PyObject *__pyx_n_s____pyx_releasebuffer;
 static PyObject *__pyx_n_s____test__;
 static PyObject *__pyx_n_s___get_parents;
 static PyObject *__pyx_n_s___hc_get_descendent;
+static PyObject *__pyx_n_s__append;
 static PyObject *__pyx_n_s__children;
 static PyObject *__pyx_n_s__col;
 static PyObject *__pyx_n_s__compute_ward_dist;
@@ -1225,6 +1345,7 @@ static PyObject *__pyx_n_s__numpy;
 static PyObject *__pyx_n_s__pa;
 static PyObject *__pyx_n_s__parent;
 static PyObject *__pyx_n_s__parents;
+static PyObject *__pyx_n_s__pop;
 static PyObject *__pyx_n_s__range;
 static PyObject *__pyx_n_s__res;
 static PyObject *__pyx_n_s__row;
@@ -1256,6 +1377,9 @@ static PyObject *__pyx_pw_7sklearn_7cluster_13_hierarchical_1compute_ward_dist(P
   PyArrayObject *__pyx_v_coord_row = 0;
   PyArrayObject *__pyx_v_coord_col = 0;
   PyArrayObject *__pyx_v_res = 0;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("compute_ward_dist (wrapper)", 0);
@@ -1282,26 +1406,26 @@ static PyObject *__pyx_pw_7sklearn_7cluster_13_hierarchical_1compute_ward_dist(P
         case  1:
         if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__m_2)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("compute_ward_dist", 1, 5, 5, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("compute_ward_dist", 1, 5, 5, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
         case  2:
         if (likely((values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__coord_row)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("compute_ward_dist", 1, 5, 5, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("compute_ward_dist", 1, 5, 5, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
         case  3:
         if (likely((values[3] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__coord_col)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("compute_ward_dist", 1, 5, 5, 3); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("compute_ward_dist", 1, 5, 5, 3); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
         case  4:
         if (likely((values[4] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__res)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("compute_ward_dist", 1, 5, 5, 4); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("compute_ward_dist", 1, 5, 5, 4); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "compute_ward_dist") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "compute_ward_dist") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 5) {
       goto __pyx_L5_argtuple_error;
@@ -1320,17 +1444,17 @@ static PyObject *__pyx_pw_7sklearn_7cluster_13_hierarchical_1compute_ward_dist(P
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("compute_ward_dist", 1, 5, 5, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("compute_ward_dist", 1, 5, 5, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("sklearn.cluster._hierarchical.compute_ward_dist", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_m_1), __pyx_ptype_5numpy_ndarray, 1, "m_1", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_m_2), __pyx_ptype_5numpy_ndarray, 1, "m_2", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 15; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_coord_row), __pyx_ptype_5numpy_ndarray, 1, "coord_row", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 16; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_coord_col), __pyx_ptype_5numpy_ndarray, 1, "coord_col", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_res), __pyx_ptype_5numpy_ndarray, 1, "res", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_m_1), __pyx_ptype_5numpy_ndarray, 1, "m_1", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_m_2), __pyx_ptype_5numpy_ndarray, 1, "m_2", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 18; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_coord_row), __pyx_ptype_5numpy_ndarray, 1, "coord_row", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 19; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_coord_col), __pyx_ptype_5numpy_ndarray, 1, "coord_col", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 20; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_res), __pyx_ptype_5numpy_ndarray, 1, "res", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 21; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_r = __pyx_pf_7sklearn_7cluster_13_hierarchical_compute_ward_dist(__pyx_self, __pyx_v_m_1, __pyx_v_m_2, __pyx_v_coord_row, __pyx_v_coord_col, __pyx_v_res);
   goto __pyx_L0;
   __pyx_L1_error:;
@@ -1340,21 +1464,21 @@ static PyObject *__pyx_pw_7sklearn_7cluster_13_hierarchical_1compute_ward_dist(P
   return __pyx_r;
 }
 
-/* "sklearn/cluster/_hierarchical.pyx":14
+/* "sklearn/cluster/_hierarchical.pyx":17
  * @cython.wraparound(False)
  * @cython.cdivision(True)
- * def compute_ward_dist(np.ndarray[DOUBLE, ndim=1] m_1,\             # <<<<<<<<<<<<<<
- *                     np.ndarray[DOUBLE, ndim=2] m_2,\
- *                     np.ndarray[INT, ndim=1] coord_row,
+ * def compute_ward_dist(np.ndarray[DOUBLE, ndim=1, mode='c'] m_1,             # <<<<<<<<<<<<<<
+ *                       np.ndarray[DOUBLE, ndim=2, mode='c'] m_2,
+ *                       np.ndarray[INTP, ndim=1, mode='c'] coord_row,
  */
 
 static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_compute_ward_dist(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_m_1, PyArrayObject *__pyx_v_m_2, PyArrayObject *__pyx_v_coord_row, PyArrayObject *__pyx_v_coord_col, PyArrayObject *__pyx_v_res) {
-  int __pyx_v_size_max;
-  int __pyx_v_n_features;
-  int __pyx_v_i;
-  int __pyx_v_j;
-  int __pyx_v_row;
-  int __pyx_v_col;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_v_size_max;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_v_n_features;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_v_i;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_v_j;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_v_row;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_v_col;
   __pyx_t_7sklearn_7cluster_13_hierarchical_DOUBLE __pyx_v_pa;
   __pyx_t_7sklearn_7cluster_13_hierarchical_DOUBLE __pyx_v_n;
   __Pyx_LocalBuf_ND __pyx_pybuffernd_coord_col;
@@ -1369,22 +1493,22 @@ static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_compute_ward_dist(CY
   __Pyx_Buffer __pyx_pybuffer_res;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
-  int __pyx_t_1;
-  int __pyx_t_2;
-  int __pyx_t_3;
-  int __pyx_t_4;
-  int __pyx_t_5;
-  int __pyx_t_6;
-  int __pyx_t_7;
-  int __pyx_t_8;
-  int __pyx_t_9;
-  int __pyx_t_10;
-  int __pyx_t_11;
-  int __pyx_t_12;
-  int __pyx_t_13;
-  int __pyx_t_14;
-  int __pyx_t_15;
-  int __pyx_t_16;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_t_1;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_t_2;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_t_3;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_t_4;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_t_5;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_t_6;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_t_7;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_t_8;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_t_9;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_t_10;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_t_11;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_t_12;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_t_13;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_t_14;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_t_15;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_t_16;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
@@ -1411,51 +1535,51 @@ static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_compute_ward_dist(CY
   __pyx_pybuffernd_res.rcbuffer = &__pyx_pybuffer_res;
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_m_1.rcbuffer->pybuffer, (PyObject*)__pyx_v_m_1, &__Pyx_TypeInfo_nn___pyx_t_7sklearn_7cluster_13_hierarchical_DOUBLE, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_m_1.rcbuffer->pybuffer, (PyObject*)__pyx_v_m_1, &__Pyx_TypeInfo_nn___pyx_t_7sklearn_7cluster_13_hierarchical_DOUBLE, PyBUF_FORMAT| PyBUF_C_CONTIGUOUS, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_pybuffernd_m_1.diminfo[0].strides = __pyx_pybuffernd_m_1.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_m_1.diminfo[0].shape = __pyx_pybuffernd_m_1.rcbuffer->pybuffer.shape[0];
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_m_2.rcbuffer->pybuffer, (PyObject*)__pyx_v_m_2, &__Pyx_TypeInfo_nn___pyx_t_7sklearn_7cluster_13_hierarchical_DOUBLE, PyBUF_FORMAT| PyBUF_STRIDES, 2, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_m_2.rcbuffer->pybuffer, (PyObject*)__pyx_v_m_2, &__Pyx_TypeInfo_nn___pyx_t_7sklearn_7cluster_13_hierarchical_DOUBLE, PyBUF_FORMAT| PyBUF_C_CONTIGUOUS, 2, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_pybuffernd_m_2.diminfo[0].strides = __pyx_pybuffernd_m_2.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_m_2.diminfo[0].shape = __pyx_pybuffernd_m_2.rcbuffer->pybuffer.shape[0]; __pyx_pybuffernd_m_2.diminfo[1].strides = __pyx_pybuffernd_m_2.rcbuffer->pybuffer.strides[1]; __pyx_pybuffernd_m_2.diminfo[1].shape = __pyx_pybuffernd_m_2.rcbuffer->pybuffer.shape[1];
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_coord_row.rcbuffer->pybuffer, (PyObject*)__pyx_v_coord_row, &__Pyx_TypeInfo_nn___pyx_t_7sklearn_7cluster_13_hierarchical_INT, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_coord_row.rcbuffer->pybuffer, (PyObject*)__pyx_v_coord_row, &__Pyx_TypeInfo_nn___pyx_t_7sklearn_7cluster_13_hierarchical_INTP, PyBUF_FORMAT| PyBUF_C_CONTIGUOUS, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_pybuffernd_coord_row.diminfo[0].strides = __pyx_pybuffernd_coord_row.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_coord_row.diminfo[0].shape = __pyx_pybuffernd_coord_row.rcbuffer->pybuffer.shape[0];
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_coord_col.rcbuffer->pybuffer, (PyObject*)__pyx_v_coord_col, &__Pyx_TypeInfo_nn___pyx_t_7sklearn_7cluster_13_hierarchical_INT, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_coord_col.rcbuffer->pybuffer, (PyObject*)__pyx_v_coord_col, &__Pyx_TypeInfo_nn___pyx_t_7sklearn_7cluster_13_hierarchical_INTP, PyBUF_FORMAT| PyBUF_C_CONTIGUOUS, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_pybuffernd_coord_col.diminfo[0].strides = __pyx_pybuffernd_coord_col.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_coord_col.diminfo[0].shape = __pyx_pybuffernd_coord_col.rcbuffer->pybuffer.shape[0];
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_res.rcbuffer->pybuffer, (PyObject*)__pyx_v_res, &__Pyx_TypeInfo_nn___pyx_t_7sklearn_7cluster_13_hierarchical_DOUBLE, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_res.rcbuffer->pybuffer, (PyObject*)__pyx_v_res, &__Pyx_TypeInfo_nn___pyx_t_7sklearn_7cluster_13_hierarchical_DOUBLE, PyBUF_FORMAT| PyBUF_C_CONTIGUOUS| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_pybuffernd_res.diminfo[0].strides = __pyx_pybuffernd_res.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_res.diminfo[0].shape = __pyx_pybuffernd_res.rcbuffer->pybuffer.shape[0];
 
-  /* "sklearn/cluster/_hierarchical.pyx":19
- *                     np.ndarray[INT, ndim=1] coord_col,\
- *                     np.ndarray[DOUBLE, ndim=1] res):
- *     cdef int size_max = coord_row.shape[0]             # <<<<<<<<<<<<<<
- *     cdef int n_features = m_2.shape[1]
- *     cdef int i, j, row, col
+  /* "sklearn/cluster/_hierarchical.pyx":22
+ *                       np.ndarray[INTP, ndim=1, mode='c'] coord_col,
+ *                       np.ndarray[DOUBLE, ndim=1, mode='c'] res):
+ *     cdef INTP size_max = coord_row.shape[0]             # <<<<<<<<<<<<<<
+ *     cdef INTP n_features = m_2.shape[1]
+ *     cdef INTP i, j, row, col
  */
   __pyx_v_size_max = (__pyx_v_coord_row->dimensions[0]);
 
-  /* "sklearn/cluster/_hierarchical.pyx":20
- *                     np.ndarray[DOUBLE, ndim=1] res):
- *     cdef int size_max = coord_row.shape[0]
- *     cdef int n_features = m_2.shape[1]             # <<<<<<<<<<<<<<
- *     cdef int i, j, row, col
+  /* "sklearn/cluster/_hierarchical.pyx":23
+ *                       np.ndarray[DOUBLE, ndim=1, mode='c'] res):
+ *     cdef INTP size_max = coord_row.shape[0]
+ *     cdef INTP n_features = m_2.shape[1]             # <<<<<<<<<<<<<<
+ *     cdef INTP i, j, row, col
  *     cdef DOUBLE pa, n
  */
   __pyx_v_n_features = (__pyx_v_m_2->dimensions[1]);
 
-  /* "sklearn/cluster/_hierarchical.pyx":23
- *     cdef int i, j, row, col
+  /* "sklearn/cluster/_hierarchical.pyx":27
  *     cdef DOUBLE pa, n
+ * 
  *     for i in range(size_max):             # <<<<<<<<<<<<<<
  *         row = coord_row[i]
  *         col = coord_col[i]
@@ -1464,17 +1588,17 @@ static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_compute_ward_dist(CY
   for (__pyx_t_2 = 0; __pyx_t_2 < __pyx_t_1; __pyx_t_2+=1) {
     __pyx_v_i = __pyx_t_2;
 
-    /* "sklearn/cluster/_hierarchical.pyx":24
- *     cdef DOUBLE pa, n
+    /* "sklearn/cluster/_hierarchical.pyx":28
+ * 
  *     for i in range(size_max):
  *         row = coord_row[i]             # <<<<<<<<<<<<<<
  *         col = coord_col[i]
  *         n = (m_1[row] * m_1[col]) / (m_1[row] + m_1[col])
  */
     __pyx_t_3 = __pyx_v_i;
-    __pyx_v_row = (*__Pyx_BufPtrStrided1d(__pyx_t_7sklearn_7cluster_13_hierarchical_INT *, __pyx_pybuffernd_coord_row.rcbuffer->pybuffer.buf, __pyx_t_3, __pyx_pybuffernd_coord_row.diminfo[0].strides));
+    __pyx_v_row = (*__Pyx_BufPtrCContig1d(__pyx_t_7sklearn_7cluster_13_hierarchical_INTP *, __pyx_pybuffernd_coord_row.rcbuffer->pybuffer.buf, __pyx_t_3, __pyx_pybuffernd_coord_row.diminfo[0].strides));
 
-    /* "sklearn/cluster/_hierarchical.pyx":25
+    /* "sklearn/cluster/_hierarchical.pyx":29
  *     for i in range(size_max):
  *         row = coord_row[i]
  *         col = coord_col[i]             # <<<<<<<<<<<<<<
@@ -1482,9 +1606,9 @@ static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_compute_ward_dist(CY
  *         pa = 0.
  */
     __pyx_t_4 = __pyx_v_i;
-    __pyx_v_col = (*__Pyx_BufPtrStrided1d(__pyx_t_7sklearn_7cluster_13_hierarchical_INT *, __pyx_pybuffernd_coord_col.rcbuffer->pybuffer.buf, __pyx_t_4, __pyx_pybuffernd_coord_col.diminfo[0].strides));
+    __pyx_v_col = (*__Pyx_BufPtrCContig1d(__pyx_t_7sklearn_7cluster_13_hierarchical_INTP *, __pyx_pybuffernd_coord_col.rcbuffer->pybuffer.buf, __pyx_t_4, __pyx_pybuffernd_coord_col.diminfo[0].strides));
 
-    /* "sklearn/cluster/_hierarchical.pyx":26
+    /* "sklearn/cluster/_hierarchical.pyx":30
  *         row = coord_row[i]
  *         col = coord_col[i]
  *         n = (m_1[row] * m_1[col]) / (m_1[row] + m_1[col])             # <<<<<<<<<<<<<<
@@ -1495,32 +1619,32 @@ static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_compute_ward_dist(CY
     __pyx_t_6 = __pyx_v_col;
     __pyx_t_7 = __pyx_v_row;
     __pyx_t_8 = __pyx_v_col;
-    __pyx_v_n = (((*__Pyx_BufPtrStrided1d(__pyx_t_7sklearn_7cluster_13_hierarchical_DOUBLE *, __pyx_pybuffernd_m_1.rcbuffer->pybuffer.buf, __pyx_t_5, __pyx_pybuffernd_m_1.diminfo[0].strides)) * (*__Pyx_BufPtrStrided1d(__pyx_t_7sklearn_7cluster_13_hierarchical_DOUBLE *, __pyx_pybuffernd_m_1.rcbuffer->pybuffer.buf, __pyx_t_6, __pyx_pybuffernd_m_1.diminfo[0].strides))) / ((*__Pyx_BufPtrStrided1d(__pyx_t_7sklearn_7cluster_13_hierarchical_DOUBLE *, __pyx_pybuffernd_m_1.rcbuffer->pybuffer.buf, __pyx_t_7, __pyx_pybuffernd_m_1.diminfo[0].strides)) + (*__Pyx_BufPtrStrided1d(__pyx_t_7sklearn_7cluster_13_hierarchical_DOUBLE *, __pyx_pybuffernd_m_1.rcbuffer->pybuffer.buf, __pyx_t_8, __pyx_pybuffernd_m_1.diminfo[0].strides))));
+    __pyx_v_n = (((*__Pyx_BufPtrCContig1d(__pyx_t_7sklearn_7cluster_13_hierarchical_DOUBLE *, __pyx_pybuffernd_m_1.rcbuffer->pybuffer.buf, __pyx_t_5, __pyx_pybuffernd_m_1.diminfo[0].strides)) * (*__Pyx_BufPtrCContig1d(__pyx_t_7sklearn_7cluster_13_hierarchical_DOUBLE *, __pyx_pybuffernd_m_1.rcbuffer->pybuffer.buf, __pyx_t_6, __pyx_pybuffernd_m_1.diminfo[0].strides))) / ((*__Pyx_BufPtrCContig1d(__pyx_t_7sklearn_7cluster_13_hierarchical_DOUBLE *, __pyx_pybuffernd_m_1.rcbuffer->pybuffer.buf, __pyx_t_7, __pyx_pybuffernd_m_1.diminfo[0].strides)) + (*__Pyx_BufPtrCContig1d(__pyx_t_7sklearn_7cluster_13_hierarchical_DOUBLE *, __pyx_pybuffernd_m_1.rcbuffer->pybuffer.buf, __pyx_t_8, __pyx_pybuffernd_m_1.diminfo[0].strides))));
 
-    /* "sklearn/cluster/_hierarchical.pyx":27
+    /* "sklearn/cluster/_hierarchical.pyx":31
  *         col = coord_col[i]
  *         n = (m_1[row] * m_1[col]) / (m_1[row] + m_1[col])
  *         pa = 0.             # <<<<<<<<<<<<<<
  *         for j in range(n_features):
- *             pa += (m_2[row, j] / m_1[row] - m_2[col, j] / m_1[col])**2
+ *             pa += (m_2[row, j] / m_1[row] - m_2[col, j] / m_1[col]) ** 2
  */
     __pyx_v_pa = 0.;
 
-    /* "sklearn/cluster/_hierarchical.pyx":28
+    /* "sklearn/cluster/_hierarchical.pyx":32
  *         n = (m_1[row] * m_1[col]) / (m_1[row] + m_1[col])
  *         pa = 0.
  *         for j in range(n_features):             # <<<<<<<<<<<<<<
- *             pa += (m_2[row, j] / m_1[row] - m_2[col, j] / m_1[col])**2
+ *             pa += (m_2[row, j] / m_1[row] - m_2[col, j] / m_1[col]) ** 2
  *         res[i] = pa * n
  */
     __pyx_t_9 = __pyx_v_n_features;
     for (__pyx_t_10 = 0; __pyx_t_10 < __pyx_t_9; __pyx_t_10+=1) {
       __pyx_v_j = __pyx_t_10;
 
-      /* "sklearn/cluster/_hierarchical.pyx":29
+      /* "sklearn/cluster/_hierarchical.pyx":33
  *         pa = 0.
  *         for j in range(n_features):
- *             pa += (m_2[row, j] / m_1[row] - m_2[col, j] / m_1[col])**2             # <<<<<<<<<<<<<<
+ *             pa += (m_2[row, j] / m_1[row] - m_2[col, j] / m_1[col]) ** 2             # <<<<<<<<<<<<<<
  *         res[i] = pa * n
  *     return res
  */
@@ -1530,22 +1654,22 @@ static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_compute_ward_dist(CY
       __pyx_t_14 = __pyx_v_col;
       __pyx_t_15 = __pyx_v_j;
       __pyx_t_16 = __pyx_v_col;
-      __pyx_v_pa = (__pyx_v_pa + pow((((*__Pyx_BufPtrStrided2d(__pyx_t_7sklearn_7cluster_13_hierarchical_DOUBLE *, __pyx_pybuffernd_m_2.rcbuffer->pybuffer.buf, __pyx_t_11, __pyx_pybuffernd_m_2.diminfo[0].strides, __pyx_t_12, __pyx_pybuffernd_m_2.diminfo[1].strides)) / (*__Pyx_BufPtrStrided1d(__pyx_t_7sklearn_7cluster_13_hierarchical_DOUBLE *, __pyx_pybuffernd_m_1.rcbuffer->pybuffer.buf, __pyx_t_13, __pyx_pybuffernd_m_1.diminfo[0].strides))) - ((*__Pyx_BufPtrStrided2d(__pyx_t_7sklearn_7cluster_13_hierarchical_DOUBLE *, __pyx_pybuffernd_m_2.rcbuffer->pybuffer.buf, __pyx_t_14, __pyx_pybuffernd_m_2.diminfo[0].strides, __pyx_t_15, __pyx_pybuffernd_m_2.diminfo[1].strides)) / (*__Pyx_BufPtrStrided1d(__pyx_t_7sklearn_7cluster_13_hierarchical_DOUBLE *, __pyx_pybuffernd_m_1.rcbuffer->pybuffer.buf, __pyx_t_16, __pyx_pybuffernd_m_1.diminfo[0].strides)))), 2.0));
+      __pyx_v_pa = (__pyx_v_pa + pow((((*__Pyx_BufPtrCContig2d(__pyx_t_7sklearn_7cluster_13_hierarchical_DOUBLE *, __pyx_pybuffernd_m_2.rcbuffer->pybuffer.buf, __pyx_t_11, __pyx_pybuffernd_m_2.diminfo[0].strides, __pyx_t_12, __pyx_pybuffernd_m_2.diminfo[1].strides)) / (*__Pyx_BufPtrCContig1d(__pyx_t_7sklearn_7cluster_13_hierarchical_DOUBLE *, __pyx_pybuffernd_m_1.rcbuffer->pybuffer.buf, __pyx_t_13, __pyx_pybuffernd_m_1.diminfo[0].strides))) - ((*__Pyx_BufPtrCContig2d(__pyx_t_7sklearn_7cluster_13_hierarchical_DOUBLE *, __pyx_pybuffernd_m_2.rcbuffer->pybuffer.buf, __pyx_t_14, __pyx_pybuffernd_m_2.diminfo[0].strides, __pyx_t_15, __pyx_pybuffernd_m_2.diminfo[1].strides)) / (*__Pyx_BufPtrCContig1d(__pyx_t_7sklearn_7cluster_13_hierarchical_DOUBLE *, __pyx_pybuffernd_m_1.rcbuffer->pybuffer.buf, __pyx_t_16, __pyx_pybuffernd_m_1.diminfo[0].strides)))), 2.0));
     }
 
-    /* "sklearn/cluster/_hierarchical.pyx":30
+    /* "sklearn/cluster/_hierarchical.pyx":34
  *         for j in range(n_features):
- *             pa += (m_2[row, j] / m_1[row] - m_2[col, j] / m_1[col])**2
+ *             pa += (m_2[row, j] / m_1[row] - m_2[col, j] / m_1[col]) ** 2
  *         res[i] = pa * n             # <<<<<<<<<<<<<<
  *     return res
  * 
  */
     __pyx_t_9 = __pyx_v_i;
-    *__Pyx_BufPtrStrided1d(__pyx_t_7sklearn_7cluster_13_hierarchical_DOUBLE *, __pyx_pybuffernd_res.rcbuffer->pybuffer.buf, __pyx_t_9, __pyx_pybuffernd_res.diminfo[0].strides) = (__pyx_v_pa * __pyx_v_n);
+    *__Pyx_BufPtrCContig1d(__pyx_t_7sklearn_7cluster_13_hierarchical_DOUBLE *, __pyx_pybuffernd_res.rcbuffer->pybuffer.buf, __pyx_t_9, __pyx_pybuffernd_res.diminfo[0].strides) = (__pyx_v_pa * __pyx_v_n);
   }
 
-  /* "sklearn/cluster/_hierarchical.pyx":31
- *             pa += (m_2[row, j] / m_1[row] - m_2[col, j] / m_1[col])**2
+  /* "sklearn/cluster/_hierarchical.pyx":35
+ *             pa += (m_2[row, j] / m_1[row] - m_2[col, j] / m_1[col]) ** 2
  *         res[i] = pa * n
  *     return res             # <<<<<<<<<<<<<<
  * 
@@ -1584,12 +1708,15 @@ static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_compute_ward_dist(CY
 
 /* Python wrapper */
 static PyObject *__pyx_pw_7sklearn_7cluster_13_hierarchical_3_hc_get_descendent(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_7sklearn_7cluster_13_hierarchical_2_hc_get_descendent[] = "\n    Function returning all the descendent leaves of a set of nodes in the tree.\n\n    Parameters\n    ----------\n    node : int\n        The node for which we want the descendents.\n\n    children : list of pairs. Length of n_nodes\n        List of the children of each nodes.\n        This is not defined for leaves.\n\n    n_leaves : int\n        Number of leaves.\n\n    Return\n    ------\n    descendent : list of int\n    ";
+static char __pyx_doc_7sklearn_7cluster_13_hierarchical_2_hc_get_descendent[] = "\n    Function returning all the descendent leaves of a set of nodes in the tree.\n\n    Parameters\n    ----------\n    node : integer\n        The node for which we want the descendents.\n\n    children : list of pairs, length n_nodes\n        The children of each non-leaf node. Values less than `n_samples` refer\n        to leaves of the tree. A greater value `i` indicates a node with\n        children `children[i - n_samples]`.\n\n    n_leaves : integer\n        Number of leaves.\n\n    Returns\n    -------\n    descendent : list of int\n    ";
 static PyMethodDef __pyx_mdef_7sklearn_7cluster_13_hierarchical_3_hc_get_descendent = {__Pyx_NAMESTR("_hc_get_descendent"), (PyCFunction)__pyx_pw_7sklearn_7cluster_13_hierarchical_3_hc_get_descendent, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7sklearn_7cluster_13_hierarchical_2_hc_get_descendent)};
 static PyObject *__pyx_pw_7sklearn_7cluster_13_hierarchical_3_hc_get_descendent(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
-  int __pyx_v_node;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_v_node;
   PyObject *__pyx_v_children = 0;
-  int __pyx_v_n_leaves;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_v_n_leaves;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("_hc_get_descendent (wrapper)", 0);
@@ -1614,16 +1741,16 @@ static PyObject *__pyx_pw_7sklearn_7cluster_13_hierarchical_3_hc_get_descendent(
         case  1:
         if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__children)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("_hc_get_descendent", 1, 3, 3, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("_hc_get_descendent", 1, 3, 3, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
         case  2:
         if (likely((values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__n_leaves)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("_hc_get_descendent", 1, 3, 3, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("_hc_get_descendent", 1, 3, 3, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "_hc_get_descendent") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "_hc_get_descendent") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 3) {
       goto __pyx_L5_argtuple_error;
@@ -1632,13 +1759,13 @@ static PyObject *__pyx_pw_7sklearn_7cluster_13_hierarchical_3_hc_get_descendent(
       values[1] = PyTuple_GET_ITEM(__pyx_args, 1);
       values[2] = PyTuple_GET_ITEM(__pyx_args, 2);
     }
-    __pyx_v_node = __Pyx_PyInt_AsInt(values[0]); if (unlikely((__pyx_v_node == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_node = __Pyx_PyInt_from_py_Py_intptr_t(values[0]); if (unlikely((__pyx_v_node == (npy_intp)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
     __pyx_v_children = values[1];
-    __pyx_v_n_leaves = __Pyx_PyInt_AsInt(values[2]); if (unlikely((__pyx_v_n_leaves == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+    __pyx_v_n_leaves = __Pyx_PyInt_from_py_Py_intptr_t(values[2]); if (unlikely((__pyx_v_n_leaves == (npy_intp)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("_hc_get_descendent", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("_hc_get_descendent", 1, 3, 3, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("sklearn.cluster._hierarchical._hc_get_descendent", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
@@ -1649,65 +1776,66 @@ static PyObject *__pyx_pw_7sklearn_7cluster_13_hierarchical_3_hc_get_descendent(
   return __pyx_r;
 }
 
-/* "sklearn/cluster/_hierarchical.pyx":34
+/* "sklearn/cluster/_hierarchical.pyx":38
  * 
  * 
- * def _hc_get_descendent(int node, children, int n_leaves):             # <<<<<<<<<<<<<<
+ * def _hc_get_descendent(INTP node, children, INTP n_leaves):             # <<<<<<<<<<<<<<
  *     """
  *     Function returning all the descendent leaves of a set of nodes in the tree.
  */
 
-static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_2_hc_get_descendent(CYTHON_UNUSED PyObject *__pyx_self, int __pyx_v_node, PyObject *__pyx_v_children, int __pyx_v_n_leaves) {
+static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_2_hc_get_descendent(CYTHON_UNUSED PyObject *__pyx_self, __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_v_node, PyObject *__pyx_v_children, __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_v_n_leaves) {
   PyObject *__pyx_v_ind = NULL;
   PyObject *__pyx_v_descendent = NULL;
-  int __pyx_v_n_indices;
-  int __pyx_v_i;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_v_i;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_v_n_indices;
   PyObject *__pyx_r = NULL;
   __Pyx_RefNannyDeclarations
   PyObject *__pyx_t_1 = NULL;
   PyObject *__pyx_t_2 = NULL;
   int __pyx_t_3;
-  int __pyx_t_4;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_t_4;
   int __pyx_t_5;
-  PyObject *__pyx_t_6 = NULL;
+  int __pyx_t_6;
+  PyObject *__pyx_t_7 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
   __Pyx_RefNannySetupContext("_hc_get_descendent", 0);
 
-  /* "sklearn/cluster/_hierarchical.pyx":54
+  /* "sklearn/cluster/_hierarchical.pyx":59
  *     descendent : list of int
  *     """
  *     ind = [node]             # <<<<<<<<<<<<<<
  *     if node < n_leaves:
  *         return ind
  */
-  __pyx_t_1 = PyInt_FromLong(__pyx_v_node); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_PyInt_to_py_Py_intptr_t(__pyx_v_node); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 54; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyList_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 59; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
   PyList_SET_ITEM(__pyx_t_2, 0, __pyx_t_1);
   __Pyx_GIVEREF(__pyx_t_1);
   __pyx_t_1 = 0;
-  __pyx_v_ind = __pyx_t_2;
+  __pyx_v_ind = ((PyObject*)__pyx_t_2);
   __pyx_t_2 = 0;
 
-  /* "sklearn/cluster/_hierarchical.pyx":55
+  /* "sklearn/cluster/_hierarchical.pyx":60
  *     """
  *     ind = [node]
  *     if node < n_leaves:             # <<<<<<<<<<<<<<
  *         return ind
  *     descendent = []
  */
-  __pyx_t_3 = (__pyx_v_node < __pyx_v_n_leaves);
+  __pyx_t_3 = ((__pyx_v_node < __pyx_v_n_leaves) != 0);
   if (__pyx_t_3) {
 
-    /* "sklearn/cluster/_hierarchical.pyx":56
+    /* "sklearn/cluster/_hierarchical.pyx":61
  *     ind = [node]
  *     if node < n_leaves:
  *         return ind             # <<<<<<<<<<<<<<
  *     descendent = []
- *     # It is actually faster to do the accounting of the number of
+ * 
  */
     __Pyx_XDECREF(__pyx_r);
     __Pyx_INCREF(((PyObject *)__pyx_v_ind));
@@ -1717,73 +1845,74 @@ static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_2_hc_get_descendent(
   }
   __pyx_L3:;
 
-  /* "sklearn/cluster/_hierarchical.pyx":57
+  /* "sklearn/cluster/_hierarchical.pyx":62
  *     if node < n_leaves:
  *         return ind
  *     descendent = []             # <<<<<<<<<<<<<<
+ * 
  *     # It is actually faster to do the accounting of the number of
- *     # elements is the list ourselves: len is a lengthy operation on a
  */
-  __pyx_t_2 = PyList_New(0); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 57; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_2 = PyList_New(0); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 62; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_2);
-  __pyx_v_descendent = __pyx_t_2;
+  __pyx_v_descendent = ((PyObject*)__pyx_t_2);
   __pyx_t_2 = 0;
 
-  /* "sklearn/cluster/_hierarchical.pyx":61
+  /* "sklearn/cluster/_hierarchical.pyx":67
  *     # elements is the list ourselves: len is a lengthy operation on a
  *     # chained list
- *     cdef int n_indices = 1             # <<<<<<<<<<<<<<
- *     cdef int i
+ *     cdef INTP i, n_indices = 1             # <<<<<<<<<<<<<<
+ * 
  *     while n_indices:
  */
   __pyx_v_n_indices = 1;
 
-  /* "sklearn/cluster/_hierarchical.pyx":63
- *     cdef int n_indices = 1
- *     cdef int i
+  /* "sklearn/cluster/_hierarchical.pyx":69
+ *     cdef INTP i, n_indices = 1
+ * 
  *     while n_indices:             # <<<<<<<<<<<<<<
  *         i = ind.pop()
  *         if i < n_leaves:
  */
   while (1) {
-    if (!__pyx_v_n_indices) break;
+    __pyx_t_3 = (__pyx_v_n_indices != 0);
+    if (!__pyx_t_3) break;
 
-    /* "sklearn/cluster/_hierarchical.pyx":64
- *     cdef int i
+    /* "sklearn/cluster/_hierarchical.pyx":70
+ * 
  *     while n_indices:
  *         i = ind.pop()             # <<<<<<<<<<<<<<
  *         if i < n_leaves:
  *             descendent.append(i)
  */
-    __pyx_t_2 = __Pyx_PyObject_Pop(((PyObject *)__pyx_v_ind)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = __Pyx_PyObject_Pop(((PyObject *)__pyx_v_ind)); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_4 = __Pyx_PyInt_AsInt(__pyx_t_2); if (unlikely((__pyx_t_4 == (int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 64; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = __Pyx_PyInt_from_py_Py_intptr_t(__pyx_t_2); if (unlikely((__pyx_t_4 == (npy_intp)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 70; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
     __pyx_v_i = __pyx_t_4;
 
-    /* "sklearn/cluster/_hierarchical.pyx":65
+    /* "sklearn/cluster/_hierarchical.pyx":71
  *     while n_indices:
  *         i = ind.pop()
  *         if i < n_leaves:             # <<<<<<<<<<<<<<
  *             descendent.append(i)
  *             n_indices -= 1
  */
-    __pyx_t_3 = (__pyx_v_i < __pyx_v_n_leaves);
+    __pyx_t_3 = ((__pyx_v_i < __pyx_v_n_leaves) != 0);
     if (__pyx_t_3) {
 
-      /* "sklearn/cluster/_hierarchical.pyx":66
+      /* "sklearn/cluster/_hierarchical.pyx":72
  *         i = ind.pop()
  *         if i < n_leaves:
  *             descendent.append(i)             # <<<<<<<<<<<<<<
  *             n_indices -= 1
  *         else:
  */
-      __pyx_t_2 = PyInt_FromLong(__pyx_v_i); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 66; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = __Pyx_PyInt_to_py_Py_intptr_t(__pyx_v_i); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 72; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
-      __pyx_t_5 = PyList_Append(__pyx_v_descendent, __pyx_t_2); if (unlikely(__pyx_t_5 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 66; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_5 = __Pyx_PyList_Append(__pyx_v_descendent, __pyx_t_2); if (unlikely(__pyx_t_5 == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 72; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
 
-      /* "sklearn/cluster/_hierarchical.pyx":67
+      /* "sklearn/cluster/_hierarchical.pyx":73
  *         if i < n_leaves:
  *             descendent.append(i)
  *             n_indices -= 1             # <<<<<<<<<<<<<<
@@ -1795,30 +1924,30 @@ static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_2_hc_get_descendent(
     }
     /*else*/ {
 
-      /* "sklearn/cluster/_hierarchical.pyx":69
+      /* "sklearn/cluster/_hierarchical.pyx":75
  *             n_indices -= 1
  *         else:
  *             ind.extend(children[i - n_leaves])             # <<<<<<<<<<<<<<
  *             n_indices += 1
  *     return descendent
  */
-      __pyx_t_2 = PyObject_GetAttr(((PyObject *)__pyx_v_ind), __pyx_n_s__extend); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_2 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_ind), __pyx_n_s__extend); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 75; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_2);
-      __pyx_t_4 = (__pyx_v_i - __pyx_v_n_leaves);
-      __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_children, __pyx_t_4, sizeof(int), PyInt_FromLong); if (!__pyx_t_1) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_6 = (__pyx_v_i - __pyx_v_n_leaves);
+      __pyx_t_1 = __Pyx_GetItemInt(__pyx_v_children, __pyx_t_6, sizeof(int), PyInt_FromLong, 0, 1, 1); if (!__pyx_t_1) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 75; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_1);
-      __pyx_t_6 = PyTuple_New(1); if (unlikely(!__pyx_t_6)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_GOTREF(__pyx_t_6);
-      PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_1);
+      __pyx_t_7 = PyTuple_New(1); if (unlikely(!__pyx_t_7)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 75; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_7);
+      PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_1);
       __Pyx_GIVEREF(__pyx_t_1);
       __pyx_t_1 = 0;
-      __pyx_t_1 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_t_6), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 69; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_1 = PyObject_Call(__pyx_t_2, ((PyObject *)__pyx_t_7), NULL); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 75; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_1);
       __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-      __Pyx_DECREF(((PyObject *)__pyx_t_6)); __pyx_t_6 = 0;
+      __Pyx_DECREF(((PyObject *)__pyx_t_7)); __pyx_t_7 = 0;
       __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-      /* "sklearn/cluster/_hierarchical.pyx":70
+      /* "sklearn/cluster/_hierarchical.pyx":76
  *         else:
  *             ind.extend(children[i - n_leaves])
  *             n_indices += 1             # <<<<<<<<<<<<<<
@@ -1830,7 +1959,7 @@ static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_2_hc_get_descendent(
     __pyx_L6:;
   }
 
-  /* "sklearn/cluster/_hierarchical.pyx":71
+  /* "sklearn/cluster/_hierarchical.pyx":77
  *             ind.extend(children[i - n_leaves])
  *             n_indices += 1
  *     return descendent             # <<<<<<<<<<<<<<
@@ -1847,7 +1976,7 @@ static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_2_hc_get_descendent(
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
   __Pyx_XDECREF(__pyx_t_2);
-  __Pyx_XDECREF(__pyx_t_6);
+  __Pyx_XDECREF(__pyx_t_7);
   __Pyx_AddTraceback("sklearn.cluster._hierarchical._hc_get_descendent", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __pyx_r = NULL;
   __pyx_L0:;
@@ -1860,11 +1989,14 @@ static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_2_hc_get_descendent(
 
 /* Python wrapper */
 static PyObject *__pyx_pw_7sklearn_7cluster_13_hierarchical_5hc_get_heads(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_7sklearn_7cluster_13_hierarchical_4hc_get_heads[] = " Return the heads of the forest, as defined by parents\n    \n    Parameters\n    ===========\n    parents: array of integers\n        The parent structure defining the forest (ensemble of trees)\n    copy: boolean\n        If copy is False, the input 'parents' array is modified inplace\n\n    Returns\n    =======\n    heads: array of integers of same shape as parents\n        The indices in the 'parents' of the tree heads\n\n    ";
+static char __pyx_doc_7sklearn_7cluster_13_hierarchical_4hc_get_heads[] = "Returns the heads of the forest, as defined by parents.\n\n    Parameters\n    ----------\n    parents : array of integers\n        The parent structure defining the forest (ensemble of trees)\n    copy : boolean\n        If copy is False, the input 'parents' array is modified inplace\n\n    Returns\n    -------\n    heads : array of integers of same shape as parents\n        The indices in the 'parents' of the tree heads\n\n    ";
 static PyMethodDef __pyx_mdef_7sklearn_7cluster_13_hierarchical_5hc_get_heads = {__Pyx_NAMESTR("hc_get_heads"), (PyCFunction)__pyx_pw_7sklearn_7cluster_13_hierarchical_5hc_get_heads, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7sklearn_7cluster_13_hierarchical_4hc_get_heads)};
 static PyObject *__pyx_pw_7sklearn_7cluster_13_hierarchical_5hc_get_heads(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   PyArrayObject *__pyx_v_parents = 0;
   PyObject *__pyx_v_copy = 0;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("hc_get_heads (wrapper)", 0);
@@ -1893,7 +2025,7 @@ static PyObject *__pyx_pw_7sklearn_7cluster_13_hierarchical_5hc_get_heads(PyObje
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "hc_get_heads") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 76; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "hc_get_heads") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 82; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     } else {
       switch (PyTuple_GET_SIZE(__pyx_args)) {
@@ -1908,13 +2040,13 @@ static PyObject *__pyx_pw_7sklearn_7cluster_13_hierarchical_5hc_get_heads(PyObje
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("hc_get_heads", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 76; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("hc_get_heads", 0, 1, 2, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 82; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("sklearn.cluster._hierarchical.hc_get_heads", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_parents), __pyx_ptype_5numpy_ndarray, 1, "parents", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 76; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_parents), __pyx_ptype_5numpy_ndarray, 1, "parents", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 82; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_r = __pyx_pf_7sklearn_7cluster_13_hierarchical_4hc_get_heads(__pyx_self, __pyx_v_parents, __pyx_v_copy);
   goto __pyx_L0;
   __pyx_L1_error:;
@@ -1924,19 +2056,19 @@ static PyObject *__pyx_pw_7sklearn_7cluster_13_hierarchical_5hc_get_heads(PyObje
   return __pyx_r;
 }
 
-/* "sklearn/cluster/_hierarchical.pyx":76
+/* "sklearn/cluster/_hierarchical.pyx":82
  * @cython.boundscheck(False)
  * @cython.wraparound(False)
- * def hc_get_heads(np.ndarray[INT, ndim=1] parents, copy=True):             # <<<<<<<<<<<<<<
- *     """ Return the heads of the forest, as defined by parents
+ * def hc_get_heads(np.ndarray[INTP, ndim=1] parents, copy=True):             # <<<<<<<<<<<<<<
+ *     """Returns the heads of the forest, as defined by parents.
  * 
  */
 
 static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_4hc_get_heads(CYTHON_UNUSED PyObject *__pyx_self, PyArrayObject *__pyx_v_parents, PyObject *__pyx_v_copy) {
-  unsigned int __pyx_v_parent;
-  unsigned int __pyx_v_node0;
-  unsigned int __pyx_v_node;
-  unsigned int __pyx_v_size;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_v_parent;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_v_node0;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_v_node;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_v_size;
   __Pyx_LocalBuf_ND __pyx_pybuffernd_parents;
   __Pyx_Buffer __pyx_pybuffer_parents;
   PyObject *__pyx_r = NULL;
@@ -1950,11 +2082,10 @@ static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_4hc_get_heads(CYTHON
   PyObject *__pyx_t_7 = NULL;
   PyObject *__pyx_t_8 = NULL;
   PyObject *__pyx_t_9 = NULL;
-  unsigned int __pyx_t_10;
-  unsigned int __pyx_t_11;
-  unsigned int __pyx_t_12;
-  unsigned int __pyx_t_13;
-  unsigned int __pyx_t_14;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_t_10;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_t_11;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_t_12;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_t_13;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
@@ -1966,50 +2097,50 @@ static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_4hc_get_heads(CYTHON
   __pyx_pybuffernd_parents.rcbuffer = &__pyx_pybuffer_parents;
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_parents.rcbuffer->pybuffer, (PyObject*)__pyx_v_parents, &__Pyx_TypeInfo_nn___pyx_t_7sklearn_7cluster_13_hierarchical_INT, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 76; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_parents.rcbuffer->pybuffer, (PyObject*)__pyx_v_parents, &__Pyx_TypeInfo_nn___pyx_t_7sklearn_7cluster_13_hierarchical_INTP, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 82; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_pybuffernd_parents.diminfo[0].strides = __pyx_pybuffernd_parents.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_parents.diminfo[0].shape = __pyx_pybuffernd_parents.rcbuffer->pybuffer.shape[0];
 
-  /* "sklearn/cluster/_hierarchical.pyx":93
+  /* "sklearn/cluster/_hierarchical.pyx":99
  *     """
- *     cdef unsigned int parent, node0, node, size
+ *     cdef INTP parent, node0, node, size
  *     if copy:             # <<<<<<<<<<<<<<
  *         parents = np.copy(parents)
  *     size = parents.size
  */
-  __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_v_copy); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 93; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_PyObject_IsTrue(__pyx_v_copy); if (unlikely(__pyx_t_1 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 99; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   if (__pyx_t_1) {
 
-    /* "sklearn/cluster/_hierarchical.pyx":94
- *     cdef unsigned int parent, node0, node, size
+    /* "sklearn/cluster/_hierarchical.pyx":100
+ *     cdef INTP parent, node0, node, size
  *     if copy:
  *         parents = np.copy(parents)             # <<<<<<<<<<<<<<
  *     size = parents.size
- *     for node0 in range(size):
+ * 
  */
-    __pyx_t_2 = __Pyx_GetName(__pyx_m, __pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 94; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = __Pyx_GetModuleGlobalName(__pyx_n_s__np); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
-    __pyx_t_3 = PyObject_GetAttr(__pyx_t_2, __pyx_n_s__copy); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 94; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_3 = __Pyx_PyObject_GetAttrStr(__pyx_t_2, __pyx_n_s__copy); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_3);
     __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
-    __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 94; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_2);
     __Pyx_INCREF(((PyObject *)__pyx_v_parents));
     PyTuple_SET_ITEM(__pyx_t_2, 0, ((PyObject *)__pyx_v_parents));
     __Pyx_GIVEREF(((PyObject *)__pyx_v_parents));
-    __pyx_t_4 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 94; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_4 = PyObject_Call(__pyx_t_3, ((PyObject *)__pyx_t_2), NULL); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_4);
     __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0;
     __Pyx_DECREF(((PyObject *)__pyx_t_2)); __pyx_t_2 = 0;
-    if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 94; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_5numpy_ndarray))))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __pyx_t_5 = ((PyArrayObject *)__pyx_t_4);
     {
       __Pyx_BufFmt_StackElem __pyx_stack[1];
       __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_parents.rcbuffer->pybuffer);
-      __pyx_t_6 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_parents.rcbuffer->pybuffer, (PyObject*)__pyx_t_5, &__Pyx_TypeInfo_nn___pyx_t_7sklearn_7cluster_13_hierarchical_INT, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack);
+      __pyx_t_6 = __Pyx_GetBufferAndValidate(&__pyx_pybuffernd_parents.rcbuffer->pybuffer, (PyObject*)__pyx_t_5, &__Pyx_TypeInfo_nn___pyx_t_7sklearn_7cluster_13_hierarchical_INTP, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack);
       if (unlikely(__pyx_t_6 < 0)) {
         PyErr_Fetch(&__pyx_t_7, &__pyx_t_8, &__pyx_t_9);
-        if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_parents.rcbuffer->pybuffer, (PyObject*)__pyx_v_parents, &__Pyx_TypeInfo_nn___pyx_t_7sklearn_7cluster_13_hierarchical_INT, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {
+        if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_parents.rcbuffer->pybuffer, (PyObject*)__pyx_v_parents, &__Pyx_TypeInfo_nn___pyx_t_7sklearn_7cluster_13_hierarchical_INTP, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {
           Py_XDECREF(__pyx_t_7); Py_XDECREF(__pyx_t_8); Py_XDECREF(__pyx_t_9);
           __Pyx_RaiseBufferFallbackError();
         } else {
@@ -2017,7 +2148,7 @@ static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_4hc_get_heads(CYTHON
         }
       }
       __pyx_pybuffernd_parents.diminfo[0].strides = __pyx_pybuffernd_parents.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_parents.diminfo[0].shape = __pyx_pybuffernd_parents.rcbuffer->pybuffer.shape[0];
-      if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 94; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      if (unlikely(__pyx_t_6 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 100; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     }
     __pyx_t_5 = 0;
     __Pyx_DECREF(((PyObject *)__pyx_v_parents));
@@ -2027,59 +2158,49 @@ static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_4hc_get_heads(CYTHON
   }
   __pyx_L3:;
 
-  /* "sklearn/cluster/_hierarchical.pyx":95
+  /* "sklearn/cluster/_hierarchical.pyx":101
  *     if copy:
  *         parents = np.copy(parents)
  *     size = parents.size             # <<<<<<<<<<<<<<
- *     for node0 in range(size):
- *         # Start from the top of the tree and go down
+ * 
+ *     # Start from the top of the tree and go down
  */
-  __pyx_t_4 = PyObject_GetAttr(((PyObject *)__pyx_v_parents), __pyx_n_s__size); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 95; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_4 = __Pyx_PyObject_GetAttrStr(((PyObject *)__pyx_v_parents), __pyx_n_s__size); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_4);
-  __pyx_t_10 = __Pyx_PyInt_AsUnsignedInt(__pyx_t_4); if (unlikely((__pyx_t_10 == (unsigned int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 95; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_10 = __Pyx_PyInt_from_py_Py_intptr_t(__pyx_t_4); if (unlikely((__pyx_t_10 == (npy_intp)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 101; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
   __pyx_v_size = __pyx_t_10;
 
-  /* "sklearn/cluster/_hierarchical.pyx":96
- *         parents = np.copy(parents)
- *     size = parents.size
- *     for node0 in range(size):             # <<<<<<<<<<<<<<
- *         # Start from the top of the tree and go down
- *         node0 = size - node0 - 1
- */
-  __pyx_t_10 = __pyx_v_size;
-  for (__pyx_t_11 = 0; __pyx_t_11 < __pyx_t_10; __pyx_t_11+=1) {
-    __pyx_v_node0 = __pyx_t_11;
-
-    /* "sklearn/cluster/_hierarchical.pyx":98
- *     for node0 in range(size):
- *         # Start from the top of the tree and go down
- *         node0 = size - node0 - 1             # <<<<<<<<<<<<<<
+  /* "sklearn/cluster/_hierarchical.pyx":104
+ * 
+ *     # Start from the top of the tree and go down
+ *     for node0 in range(size - 1, -1, -1):             # <<<<<<<<<<<<<<
  *         node = node0
  *         parent = parents[node]
  */
-    __pyx_v_node0 = ((__pyx_v_size - __pyx_v_node0) - 1);
+  for (__pyx_t_10 = (__pyx_v_size - 1); __pyx_t_10 > -1; __pyx_t_10-=1) {
+    __pyx_v_node0 = __pyx_t_10;
 
-    /* "sklearn/cluster/_hierarchical.pyx":99
- *         # Start from the top of the tree and go down
- *         node0 = size - node0 - 1
+    /* "sklearn/cluster/_hierarchical.pyx":105
+ *     # Start from the top of the tree and go down
+ *     for node0 in range(size - 1, -1, -1):
  *         node = node0             # <<<<<<<<<<<<<<
  *         parent = parents[node]
  *         while parent != node:
  */
     __pyx_v_node = __pyx_v_node0;
 
-    /* "sklearn/cluster/_hierarchical.pyx":100
- *         node0 = size - node0 - 1
+    /* "sklearn/cluster/_hierarchical.pyx":106
+ *     for node0 in range(size - 1, -1, -1):
  *         node = node0
  *         parent = parents[node]             # <<<<<<<<<<<<<<
  *         while parent != node:
  *             parents[node0] = parent
  */
-    __pyx_t_12 = __pyx_v_node;
-    __pyx_v_parent = (*__Pyx_BufPtrStrided1d(__pyx_t_7sklearn_7cluster_13_hierarchical_INT *, __pyx_pybuffernd_parents.rcbuffer->pybuffer.buf, __pyx_t_12, __pyx_pybuffernd_parents.diminfo[0].strides));
+    __pyx_t_11 = __pyx_v_node;
+    __pyx_v_parent = (*__Pyx_BufPtrStrided1d(__pyx_t_7sklearn_7cluster_13_hierarchical_INTP *, __pyx_pybuffernd_parents.rcbuffer->pybuffer.buf, __pyx_t_11, __pyx_pybuffernd_parents.diminfo[0].strides));
 
-    /* "sklearn/cluster/_hierarchical.pyx":101
+    /* "sklearn/cluster/_hierarchical.pyx":107
  *         node = node0
  *         parent = parents[node]
  *         while parent != node:             # <<<<<<<<<<<<<<
@@ -2087,20 +2208,20 @@ static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_4hc_get_heads(CYTHON
  *             node = parent
  */
     while (1) {
-      __pyx_t_1 = (__pyx_v_parent != __pyx_v_node);
+      __pyx_t_1 = ((__pyx_v_parent != __pyx_v_node) != 0);
       if (!__pyx_t_1) break;
 
-      /* "sklearn/cluster/_hierarchical.pyx":102
+      /* "sklearn/cluster/_hierarchical.pyx":108
  *         parent = parents[node]
  *         while parent != node:
  *             parents[node0] = parent             # <<<<<<<<<<<<<<
  *             node = parent
  *             parent = parents[node]
  */
-      __pyx_t_13 = __pyx_v_node0;
-      *__Pyx_BufPtrStrided1d(__pyx_t_7sklearn_7cluster_13_hierarchical_INT *, __pyx_pybuffernd_parents.rcbuffer->pybuffer.buf, __pyx_t_13, __pyx_pybuffernd_parents.diminfo[0].strides) = __pyx_v_parent;
+      __pyx_t_12 = __pyx_v_node0;
+      *__Pyx_BufPtrStrided1d(__pyx_t_7sklearn_7cluster_13_hierarchical_INTP *, __pyx_pybuffernd_parents.rcbuffer->pybuffer.buf, __pyx_t_12, __pyx_pybuffernd_parents.diminfo[0].strides) = __pyx_v_parent;
 
-      /* "sklearn/cluster/_hierarchical.pyx":103
+      /* "sklearn/cluster/_hierarchical.pyx":109
  *         while parent != node:
  *             parents[node0] = parent
  *             node = parent             # <<<<<<<<<<<<<<
@@ -2109,19 +2230,19 @@ static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_4hc_get_heads(CYTHON
  */
       __pyx_v_node = __pyx_v_parent;
 
-      /* "sklearn/cluster/_hierarchical.pyx":104
+      /* "sklearn/cluster/_hierarchical.pyx":110
  *             parents[node0] = parent
  *             node = parent
  *             parent = parents[node]             # <<<<<<<<<<<<<<
  *     return parents
  * 
  */
-      __pyx_t_14 = __pyx_v_node;
-      __pyx_v_parent = (*__Pyx_BufPtrStrided1d(__pyx_t_7sklearn_7cluster_13_hierarchical_INT *, __pyx_pybuffernd_parents.rcbuffer->pybuffer.buf, __pyx_t_14, __pyx_pybuffernd_parents.diminfo[0].strides));
+      __pyx_t_13 = __pyx_v_node;
+      __pyx_v_parent = (*__Pyx_BufPtrStrided1d(__pyx_t_7sklearn_7cluster_13_hierarchical_INTP *, __pyx_pybuffernd_parents.rcbuffer->pybuffer.buf, __pyx_t_13, __pyx_pybuffernd_parents.diminfo[0].strides));
     }
   }
 
-  /* "sklearn/cluster/_hierarchical.pyx":105
+  /* "sklearn/cluster/_hierarchical.pyx":111
  *             node = parent
  *             parent = parents[node]
  *     return parents             # <<<<<<<<<<<<<<
@@ -2157,13 +2278,16 @@ static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_4hc_get_heads(CYTHON
 
 /* Python wrapper */
 static PyObject *__pyx_pw_7sklearn_7cluster_13_hierarchical_7_get_parents(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
-static char __pyx_doc_7sklearn_7cluster_13_hierarchical_6_get_parents[] = " Return the heads of the given nodes, as defined by parents\n    \n    Modifies in-place 'heads' and 'not_visited'\n\n    Parameters\n    ===========\n    nodes: list of integers\n        The nodes to start from\n    heads: list of integers\n        A list to hold the results (modified inplace)\n    parents: array of integers\n        The parent structure defining the tree\n    not_visited:\n        The tree nodes to consider (modified inplace)\n\n    ";
+static char __pyx_doc_7sklearn_7cluster_13_hierarchical_6_get_parents[] = "Returns the heads of the given nodes, as defined by parents.\n\n    Modifies 'heads' and 'not_visited' in-place.\n\n    Parameters\n    ----------\n    nodes : list of integers\n        The nodes to start from\n    heads : list of integers\n        A list to hold the results (modified inplace)\n    parents : array of integers\n        The parent structure defining the tree\n    not_visited\n        The tree nodes to consider (modified inplace)\n\n    ";
 static PyMethodDef __pyx_mdef_7sklearn_7cluster_13_hierarchical_7_get_parents = {__Pyx_NAMESTR("_get_parents"), (PyCFunction)__pyx_pw_7sklearn_7cluster_13_hierarchical_7_get_parents, METH_VARARGS|METH_KEYWORDS, __Pyx_DOCSTR(__pyx_doc_7sklearn_7cluster_13_hierarchical_6_get_parents)};
 static PyObject *__pyx_pw_7sklearn_7cluster_13_hierarchical_7_get_parents(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
   PyObject *__pyx_v_nodes = 0;
   PyObject *__pyx_v_heads = 0;
   PyArrayObject *__pyx_v_parents = 0;
   PyArrayObject *__pyx_v_not_visited = 0;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
   PyObject *__pyx_r = 0;
   __Pyx_RefNannyDeclarations
   __Pyx_RefNannySetupContext("_get_parents (wrapper)", 0);
@@ -2189,21 +2313,21 @@ static PyObject *__pyx_pw_7sklearn_7cluster_13_hierarchical_7_get_parents(PyObje
         case  1:
         if (likely((values[1] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__heads)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("_get_parents", 1, 4, 4, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 110; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("_get_parents", 1, 4, 4, 1); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
         case  2:
         if (likely((values[2] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__parents)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("_get_parents", 1, 4, 4, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 110; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("_get_parents", 1, 4, 4, 2); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
         case  3:
         if (likely((values[3] = PyDict_GetItem(__pyx_kwds, __pyx_n_s__not_visited)) != 0)) kw_args--;
         else {
-          __Pyx_RaiseArgtupleInvalid("_get_parents", 1, 4, 4, 3); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 110; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+          __Pyx_RaiseArgtupleInvalid("_get_parents", 1, 4, 4, 3); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
         }
       }
       if (unlikely(kw_args > 0)) {
-        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "_get_parents") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 110; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+        if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "_get_parents") < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
       }
     } else if (PyTuple_GET_SIZE(__pyx_args) != 4) {
       goto __pyx_L5_argtuple_error;
@@ -2220,14 +2344,14 @@ static PyObject *__pyx_pw_7sklearn_7cluster_13_hierarchical_7_get_parents(PyObje
   }
   goto __pyx_L4_argument_unpacking_done;
   __pyx_L5_argtuple_error:;
-  __Pyx_RaiseArgtupleInvalid("_get_parents", 1, 4, 4, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 110; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
+  __Pyx_RaiseArgtupleInvalid("_get_parents", 1, 4, 4, PyTuple_GET_SIZE(__pyx_args)); {__pyx_filename = __pyx_f[0]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L3_error;}
   __pyx_L3_error:;
   __Pyx_AddTraceback("sklearn.cluster._hierarchical._get_parents", __pyx_clineno, __pyx_lineno, __pyx_filename);
   __Pyx_RefNannyFinishContext();
   return NULL;
   __pyx_L4_argument_unpacking_done:;
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_parents), __pyx_ptype_5numpy_ndarray, 1, "parents", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 110; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_not_visited), __pyx_ptype_5numpy_ndarray, 1, "not_visited", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 111; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_parents), __pyx_ptype_5numpy_ndarray, 1, "parents", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (unlikely(!__Pyx_ArgTypeTest(((PyObject *)__pyx_v_not_visited), __pyx_ptype_5numpy_ndarray, 1, "not_visited", 0))) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 117; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __pyx_r = __pyx_pf_7sklearn_7cluster_13_hierarchical_6_get_parents(__pyx_self, __pyx_v_nodes, __pyx_v_heads, __pyx_v_parents, __pyx_v_not_visited);
   goto __pyx_L0;
   __pyx_L1_error:;
@@ -2237,17 +2361,17 @@ static PyObject *__pyx_pw_7sklearn_7cluster_13_hierarchical_7_get_parents(PyObje
   return __pyx_r;
 }
 
-/* "sklearn/cluster/_hierarchical.pyx":110
+/* "sklearn/cluster/_hierarchical.pyx":116
  * @cython.boundscheck(False)
  * @cython.wraparound(False)
- * def _get_parents(nodes, heads, np.ndarray[INT, ndim=1] parents,             # <<<<<<<<<<<<<<
- *                  np.ndarray[INT8, ndim=1] not_visited):
- *     """ Return the heads of the given nodes, as defined by parents
+ * def _get_parents(nodes, heads, np.ndarray[INTP, ndim=1] parents,             # <<<<<<<<<<<<<<
+ *                  np.ndarray[INT8, ndim=1, mode='c'] not_visited):
+ *     """Returns the heads of the given nodes, as defined by parents.
  */
 
 static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_6_get_parents(CYTHON_UNUSED PyObject *__pyx_self, PyObject *__pyx_v_nodes, PyObject *__pyx_v_heads, PyArrayObject *__pyx_v_parents, PyArrayObject *__pyx_v_not_visited) {
-  unsigned int __pyx_v_parent;
-  unsigned int __pyx_v_node;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_v_parent;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_v_node;
   __Pyx_LocalBuf_ND __pyx_pybuffernd_not_visited;
   __Pyx_Buffer __pyx_pybuffer_not_visited;
   __Pyx_LocalBuf_ND __pyx_pybuffernd_parents;
@@ -2258,13 +2382,12 @@ static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_6_get_parents(CYTHON
   Py_ssize_t __pyx_t_2;
   PyObject *(*__pyx_t_3)(PyObject *);
   PyObject *__pyx_t_4 = NULL;
-  unsigned int __pyx_t_5;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_t_5;
   int __pyx_t_6;
-  unsigned int __pyx_t_7;
-  unsigned int __pyx_t_8;
-  __pyx_t_7sklearn_7cluster_13_hierarchical_INT8 __pyx_t_9;
-  unsigned int __pyx_t_10;
-  PyObject *__pyx_t_11 = NULL;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_t_7;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_t_8;
+  __pyx_t_7sklearn_7cluster_13_hierarchical_INTP __pyx_t_9;
+  PyObject *__pyx_t_10 = NULL;
   int __pyx_lineno = 0;
   const char *__pyx_filename = NULL;
   int __pyx_clineno = 0;
@@ -2279,18 +2402,18 @@ static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_6_get_parents(CYTHON
   __pyx_pybuffernd_not_visited.rcbuffer = &__pyx_pybuffer_not_visited;
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_parents.rcbuffer->pybuffer, (PyObject*)__pyx_v_parents, &__Pyx_TypeInfo_nn___pyx_t_7sklearn_7cluster_13_hierarchical_INT, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 110; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_parents.rcbuffer->pybuffer, (PyObject*)__pyx_v_parents, &__Pyx_TypeInfo_nn___pyx_t_7sklearn_7cluster_13_hierarchical_INTP, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_pybuffernd_parents.diminfo[0].strides = __pyx_pybuffernd_parents.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_parents.diminfo[0].shape = __pyx_pybuffernd_parents.rcbuffer->pybuffer.shape[0];
   {
     __Pyx_BufFmt_StackElem __pyx_stack[1];
-    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_not_visited.rcbuffer->pybuffer, (PyObject*)__pyx_v_not_visited, &__Pyx_TypeInfo_nn___pyx_t_7sklearn_7cluster_13_hierarchical_INT8, PyBUF_FORMAT| PyBUF_STRIDES| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 110; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_not_visited.rcbuffer->pybuffer, (PyObject*)__pyx_v_not_visited, &__Pyx_TypeInfo_nn___pyx_t_7sklearn_7cluster_13_hierarchical_INT8, PyBUF_FORMAT| PyBUF_C_CONTIGUOUS| PyBUF_WRITABLE, 1, 0, __pyx_stack) == -1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   }
   __pyx_pybuffernd_not_visited.diminfo[0].strides = __pyx_pybuffernd_not_visited.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_not_visited.diminfo[0].shape = __pyx_pybuffernd_not_visited.rcbuffer->pybuffer.shape[0];
 
-  /* "sklearn/cluster/_hierarchical.pyx":129
- *     """
- *     cdef unsigned int parent, node
+  /* "sklearn/cluster/_hierarchical.pyx":136
+ *     cdef INTP parent, node
+ * 
  *     for node in nodes:             # <<<<<<<<<<<<<<
  *         parent = parents[node]
  *         while parent != node:
@@ -2299,7 +2422,7 @@ static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_6_get_parents(CYTHON
     __pyx_t_1 = __pyx_v_nodes; __Pyx_INCREF(__pyx_t_1); __pyx_t_2 = 0;
     __pyx_t_3 = NULL;
   } else {
-    __pyx_t_2 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_v_nodes); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_2 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_v_nodes); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 136; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_GOTREF(__pyx_t_1);
     __pyx_t_3 = Py_TYPE(__pyx_t_1)->tp_iternext;
   }
@@ -2307,43 +2430,43 @@ static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_6_get_parents(CYTHON
     if (!__pyx_t_3 && PyList_CheckExact(__pyx_t_1)) {
       if (__pyx_t_2 >= PyList_GET_SIZE(__pyx_t_1)) break;
       #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_4 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 136; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #else
-      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 136; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #endif
     } else if (!__pyx_t_3 && PyTuple_CheckExact(__pyx_t_1)) {
       if (__pyx_t_2 >= PyTuple_GET_SIZE(__pyx_t_1)) break;
       #if CYTHON_COMPILING_IN_CPYTHON
-      __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_2); __Pyx_INCREF(__pyx_t_4); __pyx_t_2++; if (unlikely(0 < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 136; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #else
-      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = PySequence_ITEM(__pyx_t_1, __pyx_t_2); __pyx_t_2++; if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 136; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       #endif
     } else {
       __pyx_t_4 = __pyx_t_3(__pyx_t_1);
       if (unlikely(!__pyx_t_4)) {
         if (PyErr_Occurred()) {
           if (likely(PyErr_ExceptionMatches(PyExc_StopIteration))) PyErr_Clear();
-          else {__pyx_filename = __pyx_f[0]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+          else {__pyx_filename = __pyx_f[0]; __pyx_lineno = 136; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
         }
         break;
       }
       __Pyx_GOTREF(__pyx_t_4);
     }
-    __pyx_t_5 = __Pyx_PyInt_AsUnsignedInt(__pyx_t_4); if (unlikely((__pyx_t_5 == (unsigned int)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 129; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+    __pyx_t_5 = __Pyx_PyInt_from_py_Py_intptr_t(__pyx_t_4); if (unlikely((__pyx_t_5 == (npy_intp)-1) && PyErr_Occurred())) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 136; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
     __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
     __pyx_v_node = __pyx_t_5;
 
-    /* "sklearn/cluster/_hierarchical.pyx":130
- *     cdef unsigned int parent, node
+    /* "sklearn/cluster/_hierarchical.pyx":137
+ * 
  *     for node in nodes:
  *         parent = parents[node]             # <<<<<<<<<<<<<<
  *         while parent != node:
  *             node = parent
  */
     __pyx_t_5 = __pyx_v_node;
-    __pyx_v_parent = (*__Pyx_BufPtrStrided1d(__pyx_t_7sklearn_7cluster_13_hierarchical_INT *, __pyx_pybuffernd_parents.rcbuffer->pybuffer.buf, __pyx_t_5, __pyx_pybuffernd_parents.diminfo[0].strides));
+    __pyx_v_parent = (*__Pyx_BufPtrStrided1d(__pyx_t_7sklearn_7cluster_13_hierarchical_INTP *, __pyx_pybuffernd_parents.rcbuffer->pybuffer.buf, __pyx_t_5, __pyx_pybuffernd_parents.diminfo[0].strides));
 
-    /* "sklearn/cluster/_hierarchical.pyx":131
+    /* "sklearn/cluster/_hierarchical.pyx":138
  *     for node in nodes:
  *         parent = parents[node]
  *         while parent != node:             # <<<<<<<<<<<<<<
@@ -2351,10 +2474,10 @@ static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_6_get_parents(CYTHON
  *             parent = parents[node]
  */
     while (1) {
-      __pyx_t_6 = (__pyx_v_parent != __pyx_v_node);
+      __pyx_t_6 = ((__pyx_v_parent != __pyx_v_node) != 0);
       if (!__pyx_t_6) break;
 
-      /* "sklearn/cluster/_hierarchical.pyx":132
+      /* "sklearn/cluster/_hierarchical.pyx":139
  *         parent = parents[node]
  *         while parent != node:
  *             node = parent             # <<<<<<<<<<<<<<
@@ -2363,7 +2486,7 @@ static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_6_get_parents(CYTHON
  */
       __pyx_v_node = __pyx_v_parent;
 
-      /* "sklearn/cluster/_hierarchical.pyx":133
+      /* "sklearn/cluster/_hierarchical.pyx":140
  *         while parent != node:
  *             node = parent
  *             parent = parents[node]             # <<<<<<<<<<<<<<
@@ -2371,10 +2494,10 @@ static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_6_get_parents(CYTHON
  *             not_visited[node] = 0
  */
       __pyx_t_7 = __pyx_v_node;
-      __pyx_v_parent = (*__Pyx_BufPtrStrided1d(__pyx_t_7sklearn_7cluster_13_hierarchical_INT *, __pyx_pybuffernd_parents.rcbuffer->pybuffer.buf, __pyx_t_7, __pyx_pybuffernd_parents.diminfo[0].strides));
+      __pyx_v_parent = (*__Pyx_BufPtrStrided1d(__pyx_t_7sklearn_7cluster_13_hierarchical_INTP *, __pyx_pybuffernd_parents.rcbuffer->pybuffer.buf, __pyx_t_7, __pyx_pybuffernd_parents.diminfo[0].strides));
     }
 
-    /* "sklearn/cluster/_hierarchical.pyx":134
+    /* "sklearn/cluster/_hierarchical.pyx":141
  *             node = parent
  *             parent = parents[node]
  *         if not_visited[node]:             # <<<<<<<<<<<<<<
@@ -2382,38 +2505,38 @@ static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_6_get_parents(CYTHON
  *             heads.append(node)
  */
     __pyx_t_8 = __pyx_v_node;
-    __pyx_t_9 = (*__Pyx_BufPtrStrided1d(__pyx_t_7sklearn_7cluster_13_hierarchical_INT8 *, __pyx_pybuffernd_not_visited.rcbuffer->pybuffer.buf, __pyx_t_8, __pyx_pybuffernd_not_visited.diminfo[0].strides));
-    if (__pyx_t_9) {
+    __pyx_t_6 = ((*__Pyx_BufPtrCContig1d(__pyx_t_7sklearn_7cluster_13_hierarchical_INT8 *, __pyx_pybuffernd_not_visited.rcbuffer->pybuffer.buf, __pyx_t_8, __pyx_pybuffernd_not_visited.diminfo[0].strides)) != 0);
+    if (__pyx_t_6) {
 
-      /* "sklearn/cluster/_hierarchical.pyx":135
+      /* "sklearn/cluster/_hierarchical.pyx":142
  *             parent = parents[node]
  *         if not_visited[node]:
  *             not_visited[node] = 0             # <<<<<<<<<<<<<<
  *             heads.append(node)
  *     return heads
  */
-      __pyx_t_10 = __pyx_v_node;
-      *__Pyx_BufPtrStrided1d(__pyx_t_7sklearn_7cluster_13_hierarchical_INT8 *, __pyx_pybuffernd_not_visited.rcbuffer->pybuffer.buf, __pyx_t_10, __pyx_pybuffernd_not_visited.diminfo[0].strides) = 0;
+      __pyx_t_9 = __pyx_v_node;
+      *__Pyx_BufPtrCContig1d(__pyx_t_7sklearn_7cluster_13_hierarchical_INT8 *, __pyx_pybuffernd_not_visited.rcbuffer->pybuffer.buf, __pyx_t_9, __pyx_pybuffernd_not_visited.diminfo[0].strides) = 0;
 
-      /* "sklearn/cluster/_hierarchical.pyx":136
+      /* "sklearn/cluster/_hierarchical.pyx":143
  *         if not_visited[node]:
  *             not_visited[node] = 0
  *             heads.append(node)             # <<<<<<<<<<<<<<
  *     return heads
  */
-      __pyx_t_4 = PyLong_FromUnsignedLong(__pyx_v_node); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 136; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __pyx_t_4 = __Pyx_PyInt_to_py_Py_intptr_t(__pyx_v_node); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 143; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
       __Pyx_GOTREF(__pyx_t_4);
-      __pyx_t_11 = __Pyx_PyObject_Append(__pyx_v_heads, __pyx_t_4); if (unlikely(!__pyx_t_11)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 136; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-      __Pyx_GOTREF(__pyx_t_11);
+      __pyx_t_10 = __Pyx_PyObject_Append(__pyx_v_heads, __pyx_t_4); if (unlikely(!__pyx_t_10)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 143; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_10);
       __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
-      __Pyx_DECREF(__pyx_t_11); __pyx_t_11 = 0;
+      __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
       goto __pyx_L7;
     }
     __pyx_L7:;
   }
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "sklearn/cluster/_hierarchical.pyx":137
+  /* "sklearn/cluster/_hierarchical.pyx":144
  *             not_visited[node] = 0
  *             heads.append(node)
  *     return heads             # <<<<<<<<<<<<<<
@@ -2428,7 +2551,7 @@ static PyObject *__pyx_pf_7sklearn_7cluster_13_hierarchical_6_get_parents(CYTHON
   __pyx_L1_error:;
   __Pyx_XDECREF(__pyx_t_1);
   __Pyx_XDECREF(__pyx_t_4);
-  __Pyx_XDECREF(__pyx_t_11);
+  __Pyx_XDECREF(__pyx_t_10);
   { PyObject *__pyx_type, *__pyx_value, *__pyx_tb;
     __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb);
     __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_not_visited.rcbuffer->pybuffer);
@@ -2462,7 +2585,7 @@ static CYTHON_UNUSED int __pyx_pw_5numpy_7ndarray_1__getbuffer__(PyObject *__pyx
  *         # -- the details of this may change.
  *         def __getbuffer__(ndarray self, Py_buffer* info, int flags):             # <<<<<<<<<<<<<<
  *             # This implementation of getbuffer is geared towards Cython
- *             # requirements, and does not yet fulfill the PEP.
+ *             # requirements, and does not yet fullfill the PEP.
  */
 
 static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, Py_buffer *__pyx_v_info, int __pyx_v_flags) {
@@ -2503,7 +2626,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  * 
  *             cdef int copy_shape, i, ndim
  */
-  __pyx_t_1 = (__pyx_v_info == NULL);
+  __pyx_t_1 = ((__pyx_v_info == NULL) != 0);
   if (__pyx_t_1) {
     __pyx_r = 0;
     goto __pyx_L0;
@@ -2545,7 +2668,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  *                 copy_shape = 1
  *             else:
  */
-  __pyx_t_1 = ((sizeof(npy_intp)) != (sizeof(Py_ssize_t)));
+  __pyx_t_1 = (((sizeof(npy_intp)) != (sizeof(Py_ssize_t))) != 0);
   if (__pyx_t_1) {
 
     /* "numpy.pxd":209
@@ -2578,7 +2701,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  *                 and not PyArray_CHKFLAGS(self, NPY_C_CONTIGUOUS)):
  *                 raise ValueError(u"ndarray is not C contiguous")
  */
-  __pyx_t_1 = ((__pyx_v_flags & PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS);
+  __pyx_t_1 = (((__pyx_v_flags & PyBUF_C_CONTIGUOUS) == PyBUF_C_CONTIGUOUS) != 0);
   if (__pyx_t_1) {
 
     /* "numpy.pxd":214
@@ -2588,7 +2711,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  *                 raise ValueError(u"ndarray is not C contiguous")
  * 
  */
-    __pyx_t_2 = (!PyArray_CHKFLAGS(__pyx_v_self, NPY_C_CONTIGUOUS));
+    __pyx_t_2 = ((!(PyArray_CHKFLAGS(__pyx_v_self, NPY_C_CONTIGUOUS) != 0)) != 0);
     __pyx_t_3 = __pyx_t_2;
   } else {
     __pyx_t_3 = __pyx_t_1;
@@ -2618,7 +2741,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  *                 and not PyArray_CHKFLAGS(self, NPY_F_CONTIGUOUS)):
  *                 raise ValueError(u"ndarray is not Fortran contiguous")
  */
-  __pyx_t_3 = ((__pyx_v_flags & PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS);
+  __pyx_t_3 = (((__pyx_v_flags & PyBUF_F_CONTIGUOUS) == PyBUF_F_CONTIGUOUS) != 0);
   if (__pyx_t_3) {
 
     /* "numpy.pxd":218
@@ -2628,7 +2751,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  *                 raise ValueError(u"ndarray is not Fortran contiguous")
  * 
  */
-    __pyx_t_1 = (!PyArray_CHKFLAGS(__pyx_v_self, NPY_F_CONTIGUOUS));
+    __pyx_t_1 = ((!(PyArray_CHKFLAGS(__pyx_v_self, NPY_F_CONTIGUOUS) != 0)) != 0);
     __pyx_t_2 = __pyx_t_1;
   } else {
     __pyx_t_2 = __pyx_t_3;
@@ -2676,7 +2799,8 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  *                 # Allocate new buffer for strides and shape info.
  *                 # This is allocated as one block, strides first.
  */
-  if (__pyx_v_copy_shape) {
+  __pyx_t_2 = (__pyx_v_copy_shape != 0);
+  if (__pyx_t_2) {
 
     /* "numpy.pxd":226
  *                 # Allocate new buffer for strides and shape info.
@@ -2774,7 +2898,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  * 
  *             cdef int t
  */
-  __pyx_v_info->readonly = (!PyArray_ISWRITEABLE(__pyx_v_self));
+  __pyx_v_info->readonly = (!(PyArray_ISWRITEABLE(__pyx_v_self) != 0));
 
   /* "numpy.pxd":239
  * 
@@ -2813,9 +2937,9 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  *                 # do not call releasebuffer
  *                 info.obj = None
  */
-  __pyx_t_2 = (!__pyx_v_hasfields);
+  __pyx_t_2 = ((!(__pyx_v_hasfields != 0)) != 0);
   if (__pyx_t_2) {
-    __pyx_t_3 = (!__pyx_v_copy_shape);
+    __pyx_t_3 = ((!(__pyx_v_copy_shape != 0)) != 0);
     __pyx_t_1 = __pyx_t_3;
   } else {
     __pyx_t_1 = __pyx_t_2;
@@ -2860,7 +2984,7 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  *                 t = descr.type_num
  *                 if ((descr.byteorder == c'>' and little_endian) or
  */
-  __pyx_t_1 = (!__pyx_v_hasfields);
+  __pyx_t_1 = ((!(__pyx_v_hasfields != 0)) != 0);
   if (__pyx_t_1) {
 
     /* "numpy.pxd":254
@@ -2880,9 +3004,9 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  *                     (descr.byteorder == c'<' and not little_endian)):
  *                     raise ValueError(u"Non-native byte order not supported")
  */
-    __pyx_t_1 = (__pyx_v_descr->byteorder == '>');
+    __pyx_t_1 = ((__pyx_v_descr->byteorder == '>') != 0);
     if (__pyx_t_1) {
-      __pyx_t_2 = __pyx_v_little_endian;
+      __pyx_t_2 = (__pyx_v_little_endian != 0);
     } else {
       __pyx_t_2 = __pyx_t_1;
     }
@@ -2895,9 +3019,9 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
  *                     raise ValueError(u"Non-native byte order not supported")
  *                 if   t == NPY_BYTE:        f = "b"
  */
-      __pyx_t_1 = (__pyx_v_descr->byteorder == '<');
+      __pyx_t_1 = ((__pyx_v_descr->byteorder == '<') != 0);
       if (__pyx_t_1) {
-        __pyx_t_3 = (!__pyx_v_little_endian);
+        __pyx_t_3 = ((!(__pyx_v_little_endian != 0)) != 0);
         __pyx_t_7 = __pyx_t_3;
       } else {
         __pyx_t_7 = __pyx_t_1;
@@ -2924,227 +3048,202 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
     }
     __pyx_L12:;
 
-    /* "numpy.pxd":258
+    /* "numpy.pxd":274
+ *                 elif t == NPY_CDOUBLE:     f = "Zd"
+ *                 elif t == NPY_CLONGDOUBLE: f = "Zg"
+ *                 elif t == NPY_OBJECT:      f = "O"             # <<<<<<<<<<<<<<
+ *                 else:
+ *                     raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)
+ */
+    switch (__pyx_v_t) {
+
+      /* "numpy.pxd":258
  *                     (descr.byteorder == c'<' and not little_endian)):
  *                     raise ValueError(u"Non-native byte order not supported")
  *                 if   t == NPY_BYTE:        f = "b"             # <<<<<<<<<<<<<<
  *                 elif t == NPY_UBYTE:       f = "B"
  *                 elif t == NPY_SHORT:       f = "h"
  */
-    __pyx_t_1 = (__pyx_v_t == NPY_BYTE);
-    if (__pyx_t_1) {
+      case NPY_BYTE:
       __pyx_v_f = __pyx_k__b;
-      goto __pyx_L13;
-    }
+      break;
 
-    /* "numpy.pxd":259
+      /* "numpy.pxd":259
  *                     raise ValueError(u"Non-native byte order not supported")
  *                 if   t == NPY_BYTE:        f = "b"
  *                 elif t == NPY_UBYTE:       f = "B"             # <<<<<<<<<<<<<<
  *                 elif t == NPY_SHORT:       f = "h"
  *                 elif t == NPY_USHORT:      f = "H"
  */
-    __pyx_t_1 = (__pyx_v_t == NPY_UBYTE);
-    if (__pyx_t_1) {
+      case NPY_UBYTE:
       __pyx_v_f = __pyx_k__B;
-      goto __pyx_L13;
-    }
+      break;
 
-    /* "numpy.pxd":260
+      /* "numpy.pxd":260
  *                 if   t == NPY_BYTE:        f = "b"
  *                 elif t == NPY_UBYTE:       f = "B"
  *                 elif t == NPY_SHORT:       f = "h"             # <<<<<<<<<<<<<<
  *                 elif t == NPY_USHORT:      f = "H"
  *                 elif t == NPY_INT:         f = "i"
  */
-    __pyx_t_1 = (__pyx_v_t == NPY_SHORT);
-    if (__pyx_t_1) {
+      case NPY_SHORT:
       __pyx_v_f = __pyx_k__h;
-      goto __pyx_L13;
-    }
+      break;
 
-    /* "numpy.pxd":261
+      /* "numpy.pxd":261
  *                 elif t == NPY_UBYTE:       f = "B"
  *                 elif t == NPY_SHORT:       f = "h"
  *                 elif t == NPY_USHORT:      f = "H"             # <<<<<<<<<<<<<<
  *                 elif t == NPY_INT:         f = "i"
  *                 elif t == NPY_UINT:        f = "I"
  */
-    __pyx_t_1 = (__pyx_v_t == NPY_USHORT);
-    if (__pyx_t_1) {
+      case NPY_USHORT:
       __pyx_v_f = __pyx_k__H;
-      goto __pyx_L13;
-    }
+      break;
 
-    /* "numpy.pxd":262
+      /* "numpy.pxd":262
  *                 elif t == NPY_SHORT:       f = "h"
  *                 elif t == NPY_USHORT:      f = "H"
  *                 elif t == NPY_INT:         f = "i"             # <<<<<<<<<<<<<<
  *                 elif t == NPY_UINT:        f = "I"
  *                 elif t == NPY_LONG:        f = "l"
  */
-    __pyx_t_1 = (__pyx_v_t == NPY_INT);
-    if (__pyx_t_1) {
+      case NPY_INT:
       __pyx_v_f = __pyx_k__i;
-      goto __pyx_L13;
-    }
+      break;
 
-    /* "numpy.pxd":263
+      /* "numpy.pxd":263
  *                 elif t == NPY_USHORT:      f = "H"
  *                 elif t == NPY_INT:         f = "i"
  *                 elif t == NPY_UINT:        f = "I"             # <<<<<<<<<<<<<<
  *                 elif t == NPY_LONG:        f = "l"
  *                 elif t == NPY_ULONG:       f = "L"
  */
-    __pyx_t_1 = (__pyx_v_t == NPY_UINT);
-    if (__pyx_t_1) {
+      case NPY_UINT:
       __pyx_v_f = __pyx_k__I;
-      goto __pyx_L13;
-    }
+      break;
 
-    /* "numpy.pxd":264
+      /* "numpy.pxd":264
  *                 elif t == NPY_INT:         f = "i"
  *                 elif t == NPY_UINT:        f = "I"
  *                 elif t == NPY_LONG:        f = "l"             # <<<<<<<<<<<<<<
  *                 elif t == NPY_ULONG:       f = "L"
  *                 elif t == NPY_LONGLONG:    f = "q"
  */
-    __pyx_t_1 = (__pyx_v_t == NPY_LONG);
-    if (__pyx_t_1) {
+      case NPY_LONG:
       __pyx_v_f = __pyx_k__l;
-      goto __pyx_L13;
-    }
+      break;
 
-    /* "numpy.pxd":265
+      /* "numpy.pxd":265
  *                 elif t == NPY_UINT:        f = "I"
  *                 elif t == NPY_LONG:        f = "l"
  *                 elif t == NPY_ULONG:       f = "L"             # <<<<<<<<<<<<<<
  *                 elif t == NPY_LONGLONG:    f = "q"
  *                 elif t == NPY_ULONGLONG:   f = "Q"
  */
-    __pyx_t_1 = (__pyx_v_t == NPY_ULONG);
-    if (__pyx_t_1) {
+      case NPY_ULONG:
       __pyx_v_f = __pyx_k__L;
-      goto __pyx_L13;
-    }
+      break;
 
-    /* "numpy.pxd":266
+      /* "numpy.pxd":266
  *                 elif t == NPY_LONG:        f = "l"
  *                 elif t == NPY_ULONG:       f = "L"
  *                 elif t == NPY_LONGLONG:    f = "q"             # <<<<<<<<<<<<<<
  *                 elif t == NPY_ULONGLONG:   f = "Q"
  *                 elif t == NPY_FLOAT:       f = "f"
  */
-    __pyx_t_1 = (__pyx_v_t == NPY_LONGLONG);
-    if (__pyx_t_1) {
+      case NPY_LONGLONG:
       __pyx_v_f = __pyx_k__q;
-      goto __pyx_L13;
-    }
+      break;
 
-    /* "numpy.pxd":267
+      /* "numpy.pxd":267
  *                 elif t == NPY_ULONG:       f = "L"
  *                 elif t == NPY_LONGLONG:    f = "q"
  *                 elif t == NPY_ULONGLONG:   f = "Q"             # <<<<<<<<<<<<<<
  *                 elif t == NPY_FLOAT:       f = "f"
  *                 elif t == NPY_DOUBLE:      f = "d"
  */
-    __pyx_t_1 = (__pyx_v_t == NPY_ULONGLONG);
-    if (__pyx_t_1) {
+      case NPY_ULONGLONG:
       __pyx_v_f = __pyx_k__Q;
-      goto __pyx_L13;
-    }
+      break;
 
-    /* "numpy.pxd":268
+      /* "numpy.pxd":268
  *                 elif t == NPY_LONGLONG:    f = "q"
  *                 elif t == NPY_ULONGLONG:   f = "Q"
  *                 elif t == NPY_FLOAT:       f = "f"             # <<<<<<<<<<<<<<
  *                 elif t == NPY_DOUBLE:      f = "d"
  *                 elif t == NPY_LONGDOUBLE:  f = "g"
  */
-    __pyx_t_1 = (__pyx_v_t == NPY_FLOAT);
-    if (__pyx_t_1) {
+      case NPY_FLOAT:
       __pyx_v_f = __pyx_k__f;
-      goto __pyx_L13;
-    }
+      break;
 
-    /* "numpy.pxd":269
+      /* "numpy.pxd":269
  *                 elif t == NPY_ULONGLONG:   f = "Q"
  *                 elif t == NPY_FLOAT:       f = "f"
  *                 elif t == NPY_DOUBLE:      f = "d"             # <<<<<<<<<<<<<<
  *                 elif t == NPY_LONGDOUBLE:  f = "g"
  *                 elif t == NPY_CFLOAT:      f = "Zf"
  */
-    __pyx_t_1 = (__pyx_v_t == NPY_DOUBLE);
-    if (__pyx_t_1) {
+      case NPY_DOUBLE:
       __pyx_v_f = __pyx_k__d;
-      goto __pyx_L13;
-    }
+      break;
 
-    /* "numpy.pxd":270
+      /* "numpy.pxd":270
  *                 elif t == NPY_FLOAT:       f = "f"
  *                 elif t == NPY_DOUBLE:      f = "d"
  *                 elif t == NPY_LONGDOUBLE:  f = "g"             # <<<<<<<<<<<<<<
  *                 elif t == NPY_CFLOAT:      f = "Zf"
  *                 elif t == NPY_CDOUBLE:     f = "Zd"
  */
-    __pyx_t_1 = (__pyx_v_t == NPY_LONGDOUBLE);
-    if (__pyx_t_1) {
+      case NPY_LONGDOUBLE:
       __pyx_v_f = __pyx_k__g;
-      goto __pyx_L13;
-    }
+      break;
 
-    /* "numpy.pxd":271
+      /* "numpy.pxd":271
  *                 elif t == NPY_DOUBLE:      f = "d"
  *                 elif t == NPY_LONGDOUBLE:  f = "g"
  *                 elif t == NPY_CFLOAT:      f = "Zf"             # <<<<<<<<<<<<<<
  *                 elif t == NPY_CDOUBLE:     f = "Zd"
  *                 elif t == NPY_CLONGDOUBLE: f = "Zg"
  */
-    __pyx_t_1 = (__pyx_v_t == NPY_CFLOAT);
-    if (__pyx_t_1) {
+      case NPY_CFLOAT:
       __pyx_v_f = __pyx_k__Zf;
-      goto __pyx_L13;
-    }
+      break;
 
-    /* "numpy.pxd":272
+      /* "numpy.pxd":272
  *                 elif t == NPY_LONGDOUBLE:  f = "g"
  *                 elif t == NPY_CFLOAT:      f = "Zf"
  *                 elif t == NPY_CDOUBLE:     f = "Zd"             # <<<<<<<<<<<<<<
  *                 elif t == NPY_CLONGDOUBLE: f = "Zg"
  *                 elif t == NPY_OBJECT:      f = "O"
  */
-    __pyx_t_1 = (__pyx_v_t == NPY_CDOUBLE);
-    if (__pyx_t_1) {
+      case NPY_CDOUBLE:
       __pyx_v_f = __pyx_k__Zd;
-      goto __pyx_L13;
-    }
+      break;
 
-    /* "numpy.pxd":273
+      /* "numpy.pxd":273
  *                 elif t == NPY_CFLOAT:      f = "Zf"
  *                 elif t == NPY_CDOUBLE:     f = "Zd"
  *                 elif t == NPY_CLONGDOUBLE: f = "Zg"             # <<<<<<<<<<<<<<
  *                 elif t == NPY_OBJECT:      f = "O"
  *                 else:
  */
-    __pyx_t_1 = (__pyx_v_t == NPY_CLONGDOUBLE);
-    if (__pyx_t_1) {
+      case NPY_CLONGDOUBLE:
       __pyx_v_f = __pyx_k__Zg;
-      goto __pyx_L13;
-    }
+      break;
 
-    /* "numpy.pxd":274
+      /* "numpy.pxd":274
  *                 elif t == NPY_CDOUBLE:     f = "Zd"
  *                 elif t == NPY_CLONGDOUBLE: f = "Zg"
  *                 elif t == NPY_OBJECT:      f = "O"             # <<<<<<<<<<<<<<
  *                 else:
  *                     raise ValueError(u"unknown dtype code in numpy.pxd (%d)" % t)
  */
-    __pyx_t_1 = (__pyx_v_t == NPY_OBJECT);
-    if (__pyx_t_1) {
+      case NPY_OBJECT:
       __pyx_v_f = __pyx_k__O;
-      goto __pyx_L13;
-    }
-    /*else*/ {
+      break;
+      default:
 
       /* "numpy.pxd":276
  *                 elif t == NPY_OBJECT:      f = "O"
@@ -3169,8 +3268,8 @@ static int __pyx_pf_5numpy_7ndarray___getbuffer__(PyArrayObject *__pyx_v_self, P
       __Pyx_Raise(__pyx_t_8, 0, 0, 0);
       __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
       {__pyx_filename = __pyx_f[1]; __pyx_lineno = 276; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      break;
     }
-    __pyx_L13:;
 
     /* "numpy.pxd":277
  *                 else:
@@ -3294,7 +3393,7 @@ static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_s
  *                 stdlib.free(info.format)
  *             if sizeof(npy_intp) != sizeof(Py_ssize_t):
  */
-  __pyx_t_1 = PyArray_HASFIELDS(__pyx_v_self);
+  __pyx_t_1 = (PyArray_HASFIELDS(__pyx_v_self) != 0);
   if (__pyx_t_1) {
 
     /* "numpy.pxd":290
@@ -3316,7 +3415,7 @@ static void __pyx_pf_5numpy_7ndarray_2__releasebuffer__(PyArrayObject *__pyx_v_s
  *                 stdlib.free(info.strides)
  *                 # info.shape was stored after info.strides in the same block
  */
-  __pyx_t_1 = ((sizeof(npy_intp)) != (sizeof(Py_ssize_t)));
+  __pyx_t_1 = (((sizeof(npy_intp)) != (sizeof(Py_ssize_t))) != 0);
   if (__pyx_t_1) {
 
     /* "numpy.pxd":292
@@ -3665,7 +3764,9 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
       __Pyx_INCREF(__pyx_t_4);
       #else
       __pyx_t_3 = PySequence_ITEM(sequence, 0); if (unlikely(!__pyx_t_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 796; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_3);
       __pyx_t_4 = PySequence_ITEM(sequence, 1); if (unlikely(!__pyx_t_4)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 796; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+      __Pyx_GOTREF(__pyx_t_4);
       #endif
     } else if (1) {
       __Pyx_RaiseNoneNotIterableError(); {__pyx_filename = __pyx_f[1]; __pyx_lineno = 796; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
@@ -3745,9 +3846,9 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
  *             (child.byteorder == c'<' and not little_endian)):
  *             raise ValueError(u"Non-native byte order not supported")
  */
-    __pyx_t_7 = (__pyx_v_child->byteorder == '>');
+    __pyx_t_7 = ((__pyx_v_child->byteorder == '>') != 0);
     if (__pyx_t_7) {
-      __pyx_t_8 = __pyx_v_little_endian;
+      __pyx_t_8 = (__pyx_v_little_endian != 0);
     } else {
       __pyx_t_8 = __pyx_t_7;
     }
@@ -3760,9 +3861,9 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
  *             raise ValueError(u"Non-native byte order not supported")
  *             # One could encode it in the format string and have Cython
  */
-      __pyx_t_7 = (__pyx_v_child->byteorder == '<');
+      __pyx_t_7 = ((__pyx_v_child->byteorder == '<') != 0);
       if (__pyx_t_7) {
-        __pyx_t_9 = (!__pyx_v_little_endian);
+        __pyx_t_9 = ((!(__pyx_v_little_endian != 0)) != 0);
         __pyx_t_10 = __pyx_t_9;
       } else {
         __pyx_t_10 = __pyx_t_7;
@@ -3851,7 +3952,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
  *             t = child.type_num
  *             if end - f < 5:
  */
-    __pyx_t_7 = (!PyDataType_HASFIELDS(__pyx_v_child));
+    __pyx_t_7 = ((!(PyDataType_HASFIELDS(__pyx_v_child) != 0)) != 0);
     if (__pyx_t_7) {
 
       /* "numpy.pxd":821
@@ -3874,7 +3975,7 @@ static CYTHON_INLINE char *__pyx_f_5numpy__util_dtypestring(PyArray_Descr *__pyx
  *                 raise RuntimeError(u"Format string allocated too short.")
  * 
  */
-      __pyx_t_7 = ((__pyx_v_end - __pyx_v_f) < 5);
+      __pyx_t_7 = (((__pyx_v_end - __pyx_v_f) < 5) != 0);
       if (__pyx_t_7) {
 
         /* "numpy.pxd":823
@@ -4296,6 +4397,7 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a
   PyObject *__pyx_v_baseptr;
   __Pyx_RefNannyDeclarations
   int __pyx_t_1;
+  int __pyx_t_2;
   __Pyx_RefNannySetupContext("set_array_base", 0);
 
   /* "numpy.pxd":967
@@ -4306,7 +4408,8 @@ static CYTHON_INLINE void __pyx_f_5numpy_set_array_base(PyArrayObject *__pyx_v_a
  *      else:
  */
   __pyx_t_1 = (__pyx_v_base == Py_None);
-  if (__pyx_t_1) {
+  __pyx_t_2 = (__pyx_t_1 != 0);
+  if (__pyx_t_2) {
 
     /* "numpy.pxd":968
  *      cdef PyObject* baseptr
@@ -4382,7 +4485,7 @@ static CYTHON_INLINE PyObject *__pyx_f_5numpy_get_array_base(PyArrayObject *__py
  *         return None
  *     else:
  */
-  __pyx_t_1 = (__pyx_v_arr->base == NULL);
+  __pyx_t_1 = ((__pyx_v_arr->base == NULL) != 0);
   if (__pyx_t_1) {
 
     /* "numpy.pxd":977
@@ -4425,7 +4528,11 @@ static PyMethodDef __pyx_methods[] = {
 
 #if PY_MAJOR_VERSION >= 3
 static struct PyModuleDef __pyx_moduledef = {
+  #if PY_VERSION_HEX < 0x03020000
+    { PyObject_HEAD_INIT(NULL) NULL, 0, NULL },
+  #else
     PyModuleDef_HEAD_INIT,
+  #endif
     __Pyx_NAMESTR("_hierarchical"),
     0, /* m_doc */
     -1, /* m_size */
@@ -4448,10 +4555,14 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_kp_u_9, __pyx_k_9, sizeof(__pyx_k_9), 0, 1, 0, 0},
   {&__pyx_n_s__RuntimeError, __pyx_k__RuntimeError, sizeof(__pyx_k__RuntimeError), 0, 0, 1, 1},
   {&__pyx_n_s__ValueError, __pyx_k__ValueError, sizeof(__pyx_k__ValueError), 0, 0, 1, 1},
+  {&__pyx_n_s____import__, __pyx_k____import__, sizeof(__pyx_k____import__), 0, 0, 1, 1},
   {&__pyx_n_s____main__, __pyx_k____main__, sizeof(__pyx_k____main__), 0, 0, 1, 1},
+  {&__pyx_n_s____pyx_getbuffer, __pyx_k____pyx_getbuffer, sizeof(__pyx_k____pyx_getbuffer), 0, 0, 1, 1},
+  {&__pyx_n_s____pyx_releasebuffer, __pyx_k____pyx_releasebuffer, sizeof(__pyx_k____pyx_releasebuffer), 0, 0, 1, 1},
   {&__pyx_n_s____test__, __pyx_k____test__, sizeof(__pyx_k____test__), 0, 0, 1, 1},
   {&__pyx_n_s___get_parents, __pyx_k___get_parents, sizeof(__pyx_k___get_parents), 0, 0, 1, 1},
   {&__pyx_n_s___hc_get_descendent, __pyx_k___hc_get_descendent, sizeof(__pyx_k___hc_get_descendent), 0, 0, 1, 1},
+  {&__pyx_n_s__append, __pyx_k__append, sizeof(__pyx_k__append), 0, 0, 1, 1},
   {&__pyx_n_s__children, __pyx_k__children, sizeof(__pyx_k__children), 0, 0, 1, 1},
   {&__pyx_n_s__col, __pyx_k__col, sizeof(__pyx_k__col), 0, 0, 1, 1},
   {&__pyx_n_s__compute_ward_dist, __pyx_k__compute_ward_dist, sizeof(__pyx_k__compute_ward_dist), 0, 0, 1, 1},
@@ -4480,6 +4591,7 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {&__pyx_n_s__pa, __pyx_k__pa, sizeof(__pyx_k__pa), 0, 0, 1, 1},
   {&__pyx_n_s__parent, __pyx_k__parent, sizeof(__pyx_k__parent), 0, 0, 1, 1},
   {&__pyx_n_s__parents, __pyx_k__parents, sizeof(__pyx_k__parents), 0, 0, 1, 1},
+  {&__pyx_n_s__pop, __pyx_k__pop, sizeof(__pyx_k__pop), 0, 0, 1, 1},
   {&__pyx_n_s__range, __pyx_k__range, sizeof(__pyx_k__range), 0, 0, 1, 1},
   {&__pyx_n_s__res, __pyx_k__res, sizeof(__pyx_k__res), 0, 0, 1, 1},
   {&__pyx_n_s__row, __pyx_k__row, sizeof(__pyx_k__row), 0, 0, 1, 1},
@@ -4488,9 +4600,9 @@ static __Pyx_StringTabEntry __pyx_string_tab[] = {
   {0, 0, 0, 0, 0, 0, 0}
 };
 static int __Pyx_InitCachedBuiltins(void) {
-  __pyx_builtin_range = __Pyx_GetName(__pyx_b, __pyx_n_s__range); if (!__pyx_builtin_range) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 23; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_builtin_ValueError = __Pyx_GetName(__pyx_b, __pyx_n_s__ValueError); if (!__pyx_builtin_ValueError) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 215; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
-  __pyx_builtin_RuntimeError = __Pyx_GetName(__pyx_b, __pyx_n_s__RuntimeError); if (!__pyx_builtin_RuntimeError) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 799; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_builtin_range = __Pyx_GetBuiltinName(__pyx_n_s__range); if (!__pyx_builtin_range) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 27; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_builtin_ValueError = __Pyx_GetBuiltinName(__pyx_n_s__ValueError); if (!__pyx_builtin_ValueError) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 215; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_builtin_RuntimeError = __Pyx_GetBuiltinName(__pyx_n_s__RuntimeError); if (!__pyx_builtin_RuntimeError) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 799; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   return 0;
   __pyx_L1_error:;
   return -1;
@@ -4507,11 +4619,8 @@ static int __Pyx_InitCachedConstants(void) {
  * 
  *             if ((flags & pybuf.PyBUF_F_CONTIGUOUS == pybuf.PyBUF_F_CONTIGUOUS)
  */
-  __pyx_k_tuple_3 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 215; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_k_tuple_3 = PyTuple_Pack(1, ((PyObject *)__pyx_kp_u_2)); if (unlikely(!__pyx_k_tuple_3)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 215; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_k_tuple_3);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_u_2));
-  PyTuple_SET_ITEM(__pyx_k_tuple_3, 0, ((PyObject *)__pyx_kp_u_2));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_2));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_3));
 
   /* "numpy.pxd":219
@@ -4521,11 +4630,8 @@ static int __Pyx_InitCachedConstants(void) {
  * 
  *             info.buf = PyArray_DATA(self)
  */
-  __pyx_k_tuple_5 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 219; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_k_tuple_5 = PyTuple_Pack(1, ((PyObject *)__pyx_kp_u_4)); if (unlikely(!__pyx_k_tuple_5)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 219; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_k_tuple_5);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_u_4));
-  PyTuple_SET_ITEM(__pyx_k_tuple_5, 0, ((PyObject *)__pyx_kp_u_4));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_4));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_5));
 
   /* "numpy.pxd":257
@@ -4535,11 +4641,8 @@ static int __Pyx_InitCachedConstants(void) {
  *                 if   t == NPY_BYTE:        f = "b"
  *                 elif t == NPY_UBYTE:       f = "B"
  */
-  __pyx_k_tuple_7 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_7)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 257; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_k_tuple_7 = PyTuple_Pack(1, ((PyObject *)__pyx_kp_u_6)); if (unlikely(!__pyx_k_tuple_7)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 257; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_k_tuple_7);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_u_6));
-  PyTuple_SET_ITEM(__pyx_k_tuple_7, 0, ((PyObject *)__pyx_kp_u_6));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_6));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_7));
 
   /* "numpy.pxd":799
@@ -4549,11 +4652,8 @@ static int __Pyx_InitCachedConstants(void) {
  * 
  *         if ((child.byteorder == c'>' and little_endian) or
  */
-  __pyx_k_tuple_10 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_10)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 799; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_k_tuple_10 = PyTuple_Pack(1, ((PyObject *)__pyx_kp_u_9)); if (unlikely(!__pyx_k_tuple_10)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 799; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_k_tuple_10);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_u_9));
-  PyTuple_SET_ITEM(__pyx_k_tuple_10, 0, ((PyObject *)__pyx_kp_u_9));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_9));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_10));
 
   /* "numpy.pxd":803
@@ -4563,11 +4663,8 @@ static int __Pyx_InitCachedConstants(void) {
  *             # One could encode it in the format string and have Cython
  *             # complain instead, BUT: < and > in format strings also imply
  */
-  __pyx_k_tuple_11 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_11)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 803; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_k_tuple_11 = PyTuple_Pack(1, ((PyObject *)__pyx_kp_u_6)); if (unlikely(!__pyx_k_tuple_11)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 803; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_k_tuple_11);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_u_6));
-  PyTuple_SET_ITEM(__pyx_k_tuple_11, 0, ((PyObject *)__pyx_kp_u_6));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_6));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_11));
 
   /* "numpy.pxd":823
@@ -4577,156 +4674,57 @@ static int __Pyx_InitCachedConstants(void) {
  * 
  *             # Until ticket #99 is fixed, use integers to avoid warnings
  */
-  __pyx_k_tuple_13 = PyTuple_New(1); if (unlikely(!__pyx_k_tuple_13)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 823; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_k_tuple_13 = PyTuple_Pack(1, ((PyObject *)__pyx_kp_u_12)); if (unlikely(!__pyx_k_tuple_13)) {__pyx_filename = __pyx_f[1]; __pyx_lineno = 823; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_k_tuple_13);
-  __Pyx_INCREF(((PyObject *)__pyx_kp_u_12));
-  PyTuple_SET_ITEM(__pyx_k_tuple_13, 0, ((PyObject *)__pyx_kp_u_12));
-  __Pyx_GIVEREF(((PyObject *)__pyx_kp_u_12));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_13));
 
-  /* "sklearn/cluster/_hierarchical.pyx":14
+  /* "sklearn/cluster/_hierarchical.pyx":17
  * @cython.wraparound(False)
  * @cython.cdivision(True)
- * def compute_ward_dist(np.ndarray[DOUBLE, ndim=1] m_1,\             # <<<<<<<<<<<<<<
- *                     np.ndarray[DOUBLE, ndim=2] m_2,\
- *                     np.ndarray[INT, ndim=1] coord_row,
+ * def compute_ward_dist(np.ndarray[DOUBLE, ndim=1, mode='c'] m_1,             # <<<<<<<<<<<<<<
+ *                       np.ndarray[DOUBLE, ndim=2, mode='c'] m_2,
+ *                       np.ndarray[INTP, ndim=1, mode='c'] coord_row,
  */
-  __pyx_k_tuple_14 = PyTuple_New(13); if (unlikely(!__pyx_k_tuple_14)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_k_tuple_14 = PyTuple_Pack(13, ((PyObject *)__pyx_n_s__m_1), ((PyObject *)__pyx_n_s__m_2), ((PyObject *)__pyx_n_s__coord_row), ((PyObject *)__pyx_n_s__coord_col), ((PyObject *)__pyx_n_s__res), ((PyObject *)__pyx_n_s__size_max), ((PyObject *)__pyx_n_s__n_features), ((PyObject *)__pyx_n_s__i), ((PyObject *)__pyx_n_s__j), ((PyObject *)__pyx_n_s__row), ((PyObject *)__pyx_n_s__col), ((PyObject *)__pyx_n_s__pa), ((PyObject *)__pyx_n_s__n)); if (unlikely(!__pyx_k_tuple_14)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_k_tuple_14);
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__m_1));
-  PyTuple_SET_ITEM(__pyx_k_tuple_14, 0, ((PyObject *)__pyx_n_s__m_1));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__m_1));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__m_2));
-  PyTuple_SET_ITEM(__pyx_k_tuple_14, 1, ((PyObject *)__pyx_n_s__m_2));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__m_2));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__coord_row));
-  PyTuple_SET_ITEM(__pyx_k_tuple_14, 2, ((PyObject *)__pyx_n_s__coord_row));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__coord_row));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__coord_col));
-  PyTuple_SET_ITEM(__pyx_k_tuple_14, 3, ((PyObject *)__pyx_n_s__coord_col));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__coord_col));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__res));
-  PyTuple_SET_ITEM(__pyx_k_tuple_14, 4, ((PyObject *)__pyx_n_s__res));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__res));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__size_max));
-  PyTuple_SET_ITEM(__pyx_k_tuple_14, 5, ((PyObject *)__pyx_n_s__size_max));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__size_max));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__n_features));
-  PyTuple_SET_ITEM(__pyx_k_tuple_14, 6, ((PyObject *)__pyx_n_s__n_features));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__n_features));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__i));
-  PyTuple_SET_ITEM(__pyx_k_tuple_14, 7, ((PyObject *)__pyx_n_s__i));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__i));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__j));
-  PyTuple_SET_ITEM(__pyx_k_tuple_14, 8, ((PyObject *)__pyx_n_s__j));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__j));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__row));
-  PyTuple_SET_ITEM(__pyx_k_tuple_14, 9, ((PyObject *)__pyx_n_s__row));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__row));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__col));
-  PyTuple_SET_ITEM(__pyx_k_tuple_14, 10, ((PyObject *)__pyx_n_s__col));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__col));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__pa));
-  PyTuple_SET_ITEM(__pyx_k_tuple_14, 11, ((PyObject *)__pyx_n_s__pa));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__pa));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__n));
-  PyTuple_SET_ITEM(__pyx_k_tuple_14, 12, ((PyObject *)__pyx_n_s__n));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__n));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_14));
-  __pyx_k_codeobj_15 = (PyObject*)__Pyx_PyCode_New(5, 0, 13, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_k_tuple_14, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_16, __pyx_n_s__compute_ward_dist, 14, __pyx_empty_bytes); if (unlikely(!__pyx_k_codeobj_15)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_k_codeobj_15 = (PyObject*)__Pyx_PyCode_New(5, 0, 13, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_k_tuple_14, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_16, __pyx_n_s__compute_ward_dist, 17, __pyx_empty_bytes); if (unlikely(!__pyx_k_codeobj_15)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-  /* "sklearn/cluster/_hierarchical.pyx":34
+  /* "sklearn/cluster/_hierarchical.pyx":38
  * 
  * 
- * def _hc_get_descendent(int node, children, int n_leaves):             # <<<<<<<<<<<<<<
+ * def _hc_get_descendent(INTP node, children, INTP n_leaves):             # <<<<<<<<<<<<<<
  *     """
  *     Function returning all the descendent leaves of a set of nodes in the tree.
  */
-  __pyx_k_tuple_18 = PyTuple_New(7); if (unlikely(!__pyx_k_tuple_18)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_k_tuple_18 = PyTuple_Pack(7, ((PyObject *)__pyx_n_s__node), ((PyObject *)__pyx_n_s__children), ((PyObject *)__pyx_n_s__n_leaves), ((PyObject *)__pyx_n_s__ind), ((PyObject *)__pyx_n_s__descendent), ((PyObject *)__pyx_n_s__i), ((PyObject *)__pyx_n_s__n_indices)); if (unlikely(!__pyx_k_tuple_18)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_k_tuple_18);
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__node));
-  PyTuple_SET_ITEM(__pyx_k_tuple_18, 0, ((PyObject *)__pyx_n_s__node));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__node));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__children));
-  PyTuple_SET_ITEM(__pyx_k_tuple_18, 1, ((PyObject *)__pyx_n_s__children));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__children));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__n_leaves));
-  PyTuple_SET_ITEM(__pyx_k_tuple_18, 2, ((PyObject *)__pyx_n_s__n_leaves));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__n_leaves));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__ind));
-  PyTuple_SET_ITEM(__pyx_k_tuple_18, 3, ((PyObject *)__pyx_n_s__ind));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__ind));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__descendent));
-  PyTuple_SET_ITEM(__pyx_k_tuple_18, 4, ((PyObject *)__pyx_n_s__descendent));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__descendent));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__n_indices));
-  PyTuple_SET_ITEM(__pyx_k_tuple_18, 5, ((PyObject *)__pyx_n_s__n_indices));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__n_indices));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__i));
-  PyTuple_SET_ITEM(__pyx_k_tuple_18, 6, ((PyObject *)__pyx_n_s__i));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__i));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_18));
-  __pyx_k_codeobj_19 = (PyObject*)__Pyx_PyCode_New(3, 0, 7, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_k_tuple_18, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_16, __pyx_n_s___hc_get_descendent, 34, __pyx_empty_bytes); if (unlikely(!__pyx_k_codeobj_19)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_k_codeobj_19 = (PyObject*)__Pyx_PyCode_New(3, 0, 7, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_k_tuple_18, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_16, __pyx_n_s___hc_get_descendent, 38, __pyx_empty_bytes); if (unlikely(!__pyx_k_codeobj_19)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-  /* "sklearn/cluster/_hierarchical.pyx":76
+  /* "sklearn/cluster/_hierarchical.pyx":82
  * @cython.boundscheck(False)
  * @cython.wraparound(False)
- * def hc_get_heads(np.ndarray[INT, ndim=1] parents, copy=True):             # <<<<<<<<<<<<<<
- *     """ Return the heads of the forest, as defined by parents
+ * def hc_get_heads(np.ndarray[INTP, ndim=1] parents, copy=True):             # <<<<<<<<<<<<<<
+ *     """Returns the heads of the forest, as defined by parents.
  * 
  */
-  __pyx_k_tuple_20 = PyTuple_New(6); if (unlikely(!__pyx_k_tuple_20)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 76; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_k_tuple_20 = PyTuple_Pack(6, ((PyObject *)__pyx_n_s__parents), ((PyObject *)__pyx_n_s__copy), ((PyObject *)__pyx_n_s__parent), ((PyObject *)__pyx_n_s__node0), ((PyObject *)__pyx_n_s__node), ((PyObject *)__pyx_n_s__size)); if (unlikely(!__pyx_k_tuple_20)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 82; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_k_tuple_20);
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__parents));
-  PyTuple_SET_ITEM(__pyx_k_tuple_20, 0, ((PyObject *)__pyx_n_s__parents));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__parents));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__copy));
-  PyTuple_SET_ITEM(__pyx_k_tuple_20, 1, ((PyObject *)__pyx_n_s__copy));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__copy));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__parent));
-  PyTuple_SET_ITEM(__pyx_k_tuple_20, 2, ((PyObject *)__pyx_n_s__parent));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__parent));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__node0));
-  PyTuple_SET_ITEM(__pyx_k_tuple_20, 3, ((PyObject *)__pyx_n_s__node0));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__node0));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__node));
-  PyTuple_SET_ITEM(__pyx_k_tuple_20, 4, ((PyObject *)__pyx_n_s__node));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__node));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__size));
-  PyTuple_SET_ITEM(__pyx_k_tuple_20, 5, ((PyObject *)__pyx_n_s__size));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__size));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_20));
-  __pyx_k_codeobj_21 = (PyObject*)__Pyx_PyCode_New(2, 0, 6, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_k_tuple_20, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_16, __pyx_n_s__hc_get_heads, 76, __pyx_empty_bytes); if (unlikely(!__pyx_k_codeobj_21)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 76; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_k_codeobj_21 = (PyObject*)__Pyx_PyCode_New(2, 0, 6, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_k_tuple_20, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_16, __pyx_n_s__hc_get_heads, 82, __pyx_empty_bytes); if (unlikely(!__pyx_k_codeobj_21)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 82; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
 
-  /* "sklearn/cluster/_hierarchical.pyx":110
+  /* "sklearn/cluster/_hierarchical.pyx":116
  * @cython.boundscheck(False)
  * @cython.wraparound(False)
- * def _get_parents(nodes, heads, np.ndarray[INT, ndim=1] parents,             # <<<<<<<<<<<<<<
- *                  np.ndarray[INT8, ndim=1] not_visited):
- *     """ Return the heads of the given nodes, as defined by parents
+ * def _get_parents(nodes, heads, np.ndarray[INTP, ndim=1] parents,             # <<<<<<<<<<<<<<
+ *                  np.ndarray[INT8, ndim=1, mode='c'] not_visited):
+ *     """Returns the heads of the given nodes, as defined by parents.
  */
-  __pyx_k_tuple_22 = PyTuple_New(6); if (unlikely(!__pyx_k_tuple_22)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 110; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_k_tuple_22 = PyTuple_Pack(6, ((PyObject *)__pyx_n_s__nodes), ((PyObject *)__pyx_n_s__heads), ((PyObject *)__pyx_n_s__parents), ((PyObject *)__pyx_n_s__not_visited), ((PyObject *)__pyx_n_s__parent), ((PyObject *)__pyx_n_s__node)); if (unlikely(!__pyx_k_tuple_22)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_k_tuple_22);
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__nodes));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 0, ((PyObject *)__pyx_n_s__nodes));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__nodes));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__heads));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 1, ((PyObject *)__pyx_n_s__heads));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__heads));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__parents));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 2, ((PyObject *)__pyx_n_s__parents));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__parents));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__not_visited));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 3, ((PyObject *)__pyx_n_s__not_visited));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__not_visited));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__parent));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 4, ((PyObject *)__pyx_n_s__parent));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__parent));
-  __Pyx_INCREF(((PyObject *)__pyx_n_s__node));
-  PyTuple_SET_ITEM(__pyx_k_tuple_22, 5, ((PyObject *)__pyx_n_s__node));
-  __Pyx_GIVEREF(((PyObject *)__pyx_n_s__node));
   __Pyx_GIVEREF(((PyObject *)__pyx_k_tuple_22));
-  __pyx_k_codeobj_23 = (PyObject*)__Pyx_PyCode_New(4, 0, 6, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_k_tuple_22, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_16, __pyx_n_s___get_parents, 110, __pyx_empty_bytes); if (unlikely(!__pyx_k_codeobj_23)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 110; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_k_codeobj_23 = (PyObject*)__Pyx_PyCode_New(4, 0, 6, 0, 0, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_k_tuple_22, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_16, __pyx_n_s___get_parents, 116, __pyx_empty_bytes); if (unlikely(!__pyx_k_codeobj_23)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_RefNannyFinishContext();
   return 0;
   __pyx_L1_error:;
@@ -4751,6 +4749,9 @@ PyMODINIT_FUNC PyInit__hierarchical(void)
 #endif
 {
   PyObject *__pyx_t_1 = NULL;
+  int __pyx_lineno = 0;
+  const char *__pyx_filename = NULL;
+  int __pyx_clineno = 0;
   __Pyx_RefNannyDeclarations
   #if CYTHON_REFNANNY
   __Pyx_RefNanny = __Pyx_RefNannyImportAPI("refnanny");
@@ -4788,6 +4789,8 @@ PyMODINIT_FUNC PyInit__hierarchical(void)
   __pyx_m = PyModule_Create(&__pyx_moduledef);
   #endif
   if (unlikely(!__pyx_m)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_d = PyModule_GetDict(__pyx_m); if (unlikely(!__pyx_d)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  Py_INCREF(__pyx_d);
   #if PY_MAJOR_VERSION >= 3
   {
     PyObject *modules = PyImport_GetModuleDict(); if (unlikely(!modules)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
@@ -4803,6 +4806,9 @@ PyMODINIT_FUNC PyInit__hierarchical(void)
   if (__Pyx_SetAttrString(__pyx_m, "__builtins__", __pyx_b) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
   /*--- Initialize various global constants etc. ---*/
   if (unlikely(__Pyx_InitGlobals() < 0)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  #if PY_MAJOR_VERSION < 3 && (__PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT)
+  if (__Pyx_init_sys_getdefaultencoding_params() < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  #endif
   if (__pyx_module_is_main_sklearn__cluster___hierarchical) {
     if (__Pyx_SetAttrString(__pyx_m, "__name__", __pyx_n_s____main__) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;};
   }
@@ -4831,17 +4837,19 @@ PyMODINIT_FUNC PyInit__hierarchical(void)
   /*--- Function import code ---*/
   /*--- Execution code ---*/
 
-  /* "sklearn/cluster/_hierarchical.pyx":1
+  /* "sklearn/cluster/_hierarchical.pyx":3
+ * # Author: Gael Varoquaux <gael.varoquaux@normalesup.org>
+ * 
  * import numpy as np             # <<<<<<<<<<<<<<
  * cimport numpy as np
  * cimport cython
  */
-  __pyx_t_1 = __Pyx_Import(((PyObject *)__pyx_n_s__numpy), 0, -1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_Import(((PyObject *)__pyx_n_s__numpy), 0, -1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__np, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s__np, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 3; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "sklearn/cluster/_hierarchical.pyx":8
+  /* "sklearn/cluster/_hierarchical.pyx":11
  * ctypedef np.int8_t INT8
  * 
  * np.import_array()             # <<<<<<<<<<<<<<
@@ -4850,67 +4858,67 @@ PyMODINIT_FUNC PyInit__hierarchical(void)
  */
   import_array();
 
-  /* "sklearn/cluster/_hierarchical.pyx":14
+  /* "sklearn/cluster/_hierarchical.pyx":17
  * @cython.wraparound(False)
  * @cython.cdivision(True)
- * def compute_ward_dist(np.ndarray[DOUBLE, ndim=1] m_1,\             # <<<<<<<<<<<<<<
- *                     np.ndarray[DOUBLE, ndim=2] m_2,\
- *                     np.ndarray[INT, ndim=1] coord_row,
+ * def compute_ward_dist(np.ndarray[DOUBLE, ndim=1, mode='c'] m_1,             # <<<<<<<<<<<<<<
+ *                       np.ndarray[DOUBLE, ndim=2, mode='c'] m_2,
+ *                       np.ndarray[INTP, ndim=1, mode='c'] coord_row,
  */
-  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7sklearn_7cluster_13_hierarchical_1compute_ward_dist, NULL, __pyx_n_s_17); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7sklearn_7cluster_13_hierarchical_1compute_ward_dist, NULL, __pyx_n_s_17); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__compute_ward_dist, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 14; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s__compute_ward_dist, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 17; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "sklearn/cluster/_hierarchical.pyx":34
+  /* "sklearn/cluster/_hierarchical.pyx":38
  * 
  * 
- * def _hc_get_descendent(int node, children, int n_leaves):             # <<<<<<<<<<<<<<
+ * def _hc_get_descendent(INTP node, children, INTP n_leaves):             # <<<<<<<<<<<<<<
  *     """
  *     Function returning all the descendent leaves of a set of nodes in the tree.
  */
-  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7sklearn_7cluster_13_hierarchical_3_hc_get_descendent, NULL, __pyx_n_s_17); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7sklearn_7cluster_13_hierarchical_3_hc_get_descendent, NULL, __pyx_n_s_17); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyObject_SetAttr(__pyx_m, __pyx_n_s___hc_get_descendent, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 34; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s___hc_get_descendent, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 38; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "sklearn/cluster/_hierarchical.pyx":76
+  /* "sklearn/cluster/_hierarchical.pyx":82
  * @cython.boundscheck(False)
  * @cython.wraparound(False)
- * def hc_get_heads(np.ndarray[INT, ndim=1] parents, copy=True):             # <<<<<<<<<<<<<<
- *     """ Return the heads of the forest, as defined by parents
+ * def hc_get_heads(np.ndarray[INTP, ndim=1] parents, copy=True):             # <<<<<<<<<<<<<<
+ *     """Returns the heads of the forest, as defined by parents.
  * 
  */
-  __pyx_t_1 = __Pyx_PyBool_FromLong(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 76; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = __Pyx_PyBool_FromLong(1); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 82; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
   __pyx_k_1 = __pyx_t_1;
   __Pyx_GIVEREF(__pyx_t_1);
   __pyx_t_1 = 0;
-  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7sklearn_7cluster_13_hierarchical_5hc_get_heads, NULL, __pyx_n_s_17); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 76; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7sklearn_7cluster_13_hierarchical_5hc_get_heads, NULL, __pyx_n_s_17); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 82; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyObject_SetAttr(__pyx_m, __pyx_n_s__hc_get_heads, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 76; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s__hc_get_heads, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 82; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
-  /* "sklearn/cluster/_hierarchical.pyx":110
+  /* "sklearn/cluster/_hierarchical.pyx":116
  * @cython.boundscheck(False)
  * @cython.wraparound(False)
- * def _get_parents(nodes, heads, np.ndarray[INT, ndim=1] parents,             # <<<<<<<<<<<<<<
- *                  np.ndarray[INT8, ndim=1] not_visited):
- *     """ Return the heads of the given nodes, as defined by parents
+ * def _get_parents(nodes, heads, np.ndarray[INTP, ndim=1] parents,             # <<<<<<<<<<<<<<
+ *                  np.ndarray[INT8, ndim=1, mode='c'] not_visited):
+ *     """Returns the heads of the given nodes, as defined by parents.
  */
-  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7sklearn_7cluster_13_hierarchical_7_get_parents, NULL, __pyx_n_s_17); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 110; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  __pyx_t_1 = PyCFunction_NewEx(&__pyx_mdef_7sklearn_7cluster_13_hierarchical_7_get_parents, NULL, __pyx_n_s_17); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(__pyx_t_1);
-  if (PyObject_SetAttr(__pyx_m, __pyx_n_s___get_parents, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 110; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s___get_parents, __pyx_t_1) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 116; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
 
   /* "sklearn/cluster/_hierarchical.pyx":1
- * import numpy as np             # <<<<<<<<<<<<<<
- * cimport numpy as np
- * cimport cython
+ * # Author: Gael Varoquaux <gael.varoquaux@normalesup.org>             # <<<<<<<<<<<<<<
+ * 
+ * import numpy as np
  */
   __pyx_t_1 = PyDict_New(); if (unlikely(!__pyx_t_1)) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_GOTREF(((PyObject *)__pyx_t_1));
-  if (PyObject_SetAttr(__pyx_m, __pyx_n_s____test__, ((PyObject *)__pyx_t_1)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
+  if (PyDict_SetItem(__pyx_d, __pyx_n_s____test__, ((PyObject *)__pyx_t_1)) < 0) {__pyx_filename = __pyx_f[0]; __pyx_lineno = 1; __pyx_clineno = __LINE__; goto __pyx_L1_error;}
   __Pyx_DECREF(((PyObject *)__pyx_t_1)); __pyx_t_1 = 0;
 
   /* "numpy.pxd":975
@@ -4955,17 +4963,15 @@ end:
 }
 #endif /* CYTHON_REFNANNY */
 
-static PyObject *__Pyx_GetName(PyObject *dict, PyObject *name) {
-    PyObject *result;
-    result = PyObject_GetAttr(dict, name);
-    if (!result) {
-        if (dict != __pyx_b) {
-            PyErr_Clear();
-            result = PyObject_GetAttr(__pyx_b, name);
-        }
-        if (!result) {
-            PyErr_SetObject(PyExc_NameError, name);
-        }
+static PyObject *__Pyx_GetBuiltinName(PyObject *name) {
+    PyObject* result = __Pyx_PyObject_GetAttrStr(__pyx_b, name);
+    if (unlikely(!result)) {
+        PyErr_Format(PyExc_NameError,
+#if PY_MAJOR_VERSION >= 3
+            "name '%U' is not defined", name);
+#else
+            "name '%s' is not defined", PyString_AS_STRING(name));
+#endif
     }
     return result;
 }
@@ -5703,6 +5709,117 @@ static CYTHON_INLINE void __Pyx_ErrFetch(PyObject **type, PyObject **value, PyOb
 #endif
 }
 
+static CYTHON_INLINE PyObject* __Pyx_PyObject_Pop(PyObject* L) {
+#if CYTHON_COMPILING_IN_CPYTHON && PY_VERSION_HEX >= 0x02040000
+    if (likely(PyList_CheckExact(L))
+        && likely(PyList_GET_SIZE(L) > (((PyListObject*)L)->allocated >> 1))) {
+        Py_SIZE(L) -= 1;
+        return PyList_GET_ITEM(L, PyList_GET_SIZE(L));
+    }
+#if PY_VERSION_HEX >= 0x02050000
+    else if (Py_TYPE(L) == (&PySet_Type)) {
+        return PySet_Pop(L);
+    }
+#endif
+#endif
+    return __Pyx_PyObject_CallMethod0(L, __pyx_n_s__pop);
+}
+
+static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) {
+    PyObject *r;
+    if (!j) return NULL;
+    r = PyObject_GetItem(o, j);
+    Py_DECREF(j);
+    return r;
+}
+static CYTHON_INLINE PyObject *__Pyx_GetItemInt_List_Fast(PyObject *o, Py_ssize_t i,
+                                                              int wraparound, int boundscheck) {
+#if CYTHON_COMPILING_IN_CPYTHON
+    if (wraparound & unlikely(i < 0)) i += PyList_GET_SIZE(o);
+    if ((!boundscheck) || likely((0 <= i) & (i < PyList_GET_SIZE(o)))) {
+        PyObject *r = PyList_GET_ITEM(o, i);
+        Py_INCREF(r);
+        return r;
+    }
+    return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i));
+#else
+    return PySequence_GetItem(o, i);
+#endif
+}
+static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Tuple_Fast(PyObject *o, Py_ssize_t i,
+                                                              int wraparound, int boundscheck) {
+#if CYTHON_COMPILING_IN_CPYTHON
+    if (wraparound & unlikely(i < 0)) i += PyTuple_GET_SIZE(o);
+    if ((!boundscheck) || likely((0 <= i) & (i < PyTuple_GET_SIZE(o)))) {
+        PyObject *r = PyTuple_GET_ITEM(o, i);
+        Py_INCREF(r);
+        return r;
+    }
+    return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i));
+#else
+    return PySequence_GetItem(o, i);
+#endif
+}
+static CYTHON_INLINE PyObject *__Pyx_GetItemInt_Fast(PyObject *o, Py_ssize_t i,
+                                                     int is_list, int wraparound, int boundscheck) {
+#if CYTHON_COMPILING_IN_CPYTHON
+    if (is_list || PyList_CheckExact(o)) {
+        Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyList_GET_SIZE(o);
+        if ((!boundscheck) || (likely((n >= 0) & (n < PyList_GET_SIZE(o))))) {
+            PyObject *r = PyList_GET_ITEM(o, n);
+            Py_INCREF(r);
+            return r;
+        }
+    }
+    else if (PyTuple_CheckExact(o)) {
+        Py_ssize_t n = ((!wraparound) | likely(i >= 0)) ? i : i + PyTuple_GET_SIZE(o);
+        if ((!boundscheck) || likely((n >= 0) & (n < PyTuple_GET_SIZE(o)))) {
+            PyObject *r = PyTuple_GET_ITEM(o, n);
+            Py_INCREF(r);
+            return r;
+        }
+    } else {
+        PySequenceMethods *m = Py_TYPE(o)->tp_as_sequence;
+        if (likely(m && m->sq_item)) {
+            if (wraparound && unlikely(i < 0) && likely(m->sq_length)) {
+                Py_ssize_t l = m->sq_length(o);
+                if (likely(l >= 0)) {
+                    i += l;
+                } else {
+                    if (PyErr_ExceptionMatches(PyExc_OverflowError))
+                        PyErr_Clear();
+                    else
+                        return NULL;
+                }
+            }
+            return m->sq_item(o, i);
+        }
+    }
+#else
+    if (is_list || PySequence_Check(o)) {
+        return PySequence_GetItem(o, i);
+    }
+#endif
+    return __Pyx_GetItemInt_Generic(o, PyInt_FromSsize_t(i));
+}
+
+static CYTHON_INLINE PyObject *__Pyx_GetModuleGlobalName(PyObject *name) {
+    PyObject *result;
+#if CYTHON_COMPILING_IN_CPYTHON
+    result = PyDict_GetItem(__pyx_d, name);
+    if (result) {
+        Py_INCREF(result);
+    } else {
+#else
+    result = PyObject_GetItem(__pyx_d, name);
+    if (!result) {
+        PyErr_Clear();
+#endif
+        result = __Pyx_GetBuiltinName(name);
+    }
+    return result;
+}
+
 static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
     if (unlikely(!type)) {
         PyErr_Format(PyExc_SystemError, "Missing type object");
@@ -5720,6 +5837,16 @@ static void __Pyx_RaiseBufferFallbackError(void) {
      "Buffer acquisition failed on assignment; and then reacquiring the old buffer failed too!");
 }
 
+static CYTHON_INLINE PyObject* __Pyx_PyObject_Append(PyObject* L, PyObject* x) {
+    if (likely(PyList_CheckExact(L))) {
+        if (unlikely(__Pyx_PyList_Append(L, x) < 0)) return NULL;
+        Py_INCREF(Py_None);
+        return Py_None; /* this is just to have an accurate signature */
+    } else {
+        return __Pyx_PyObject_CallMethod1(L, __pyx_n_s__append, x);
+    }
+}
+
 #if PY_MAJOR_VERSION < 3
 static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb,
                         CYTHON_UNUSED PyObject *cause) {
@@ -5758,24 +5885,23 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb,
         }
         value = type;
         #if PY_VERSION_HEX < 0x02050000
-            if (PyInstance_Check(type)) {
-                type = (PyObject*) ((PyInstanceObject*)type)->in_class;
-                Py_INCREF(type);
-            }
-            else {
-                type = 0;
-                PyErr_SetString(PyExc_TypeError,
-                    "raise: exception must be an old-style class or instance");
-                goto raise_error;
-            }
-        #else
-            type = (PyObject*) Py_TYPE(type);
+        if (PyInstance_Check(type)) {
+            type = (PyObject*) ((PyInstanceObject*)type)->in_class;
             Py_INCREF(type);
-            if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
-                PyErr_SetString(PyExc_TypeError,
-                    "raise: exception class must be a subclass of BaseException");
-                goto raise_error;
-            }
+        } else {
+            type = 0;
+            PyErr_SetString(PyExc_TypeError,
+                "raise: exception must be an old-style class or instance");
+            goto raise_error;
+        }
+        #else
+        type = (PyObject*) Py_TYPE(type);
+        Py_INCREF(type);
+        if (!PyType_IsSubtype((PyTypeObject *)type, (PyTypeObject *)PyExc_BaseException)) {
+            PyErr_SetString(PyExc_TypeError,
+                "raise: exception class must be a subclass of BaseException");
+            goto raise_error;
+        }
         #endif
     }
     __Pyx_ErrRestore(type, value, tb);
@@ -5813,8 +5939,7 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
         else if (PyTuple_Check(value)) {
             Py_INCREF(value);
             args = value;
-        }
-        else
+        } else
             args = PyTuple_Pack(1, value);
         if (!args)
             goto bad;
@@ -5835,18 +5960,22 @@ static void __Pyx_Raise(PyObject *type, PyObject *value, PyObject *tb, PyObject
             "raise: exception class must be a subclass of BaseException");
         goto bad;
     }
+#if PY_VERSION_HEX >= 0x03030000
+    if (cause) {
+#else
     if (cause && cause != Py_None) {
+#endif
         PyObject *fixed_cause;
-        if (PyExceptionClass_Check(cause)) {
+        if (cause == Py_None) {
+            fixed_cause = NULL;
+        } else if (PyExceptionClass_Check(cause)) {
             fixed_cause = PyObject_CallObject(cause, NULL);
             if (fixed_cause == NULL)
                 goto bad;
-        }
-        else if (PyExceptionInstance_Check(cause)) {
+        } else if (PyExceptionInstance_Check(cause)) {
             fixed_cause = cause;
             Py_INCREF(fixed_cause);
-        }
-        else {
+        } else {
             PyErr_SetString(PyExc_TypeError,
                             "exception causes must derive from "
                             "BaseException");
@@ -5932,27 +6061,23 @@ static int __Pyx_IternextUnpackEndCheck(PyObject *retval, Py_ssize_t expected) {
 
 #if PY_MAJOR_VERSION < 3
 static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags) {
-    CYTHON_UNUSED PyObject *getbuffer_cobj;
   #if PY_VERSION_HEX >= 0x02060000
     if (PyObject_CheckBuffer(obj)) return PyObject_GetBuffer(obj, view, flags);
   #endif
         if (PyObject_TypeCheck(obj, __pyx_ptype_5numpy_ndarray)) return __pyx_pw_5numpy_7ndarray_1__getbuffer__(obj, view, flags);
   #if PY_VERSION_HEX < 0x02060000
-    if (obj->ob_type->tp_dict &&
-        (getbuffer_cobj = PyMapping_GetItemString(obj->ob_type->tp_dict,
-                                             "__pyx_getbuffer"))) {
-        getbufferproc func;
-      #if PY_VERSION_HEX >= 0x02070000 && !(PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION == 0)
-        func = (getbufferproc) PyCapsule_GetPointer(getbuffer_cobj, "getbuffer(obj, view, flags)");
-      #else
-        func = (getbufferproc) PyCObject_AsVoidPtr(getbuffer_cobj);
-      #endif
-        Py_DECREF(getbuffer_cobj);
-        if (!func)
-            goto fail;
-        return func(obj, view, flags);
-    } else {
-        PyErr_Clear();
+    if (obj->ob_type->tp_dict) {
+        PyObject *getbuffer_cobj = PyObject_GetItem(
+            obj->ob_type->tp_dict, __pyx_n_s____pyx_getbuffer);
+        if (getbuffer_cobj) {
+            getbufferproc func = (getbufferproc) PyCObject_AsVoidPtr(getbuffer_cobj);
+            Py_DECREF(getbuffer_cobj);
+            if (!func)
+                goto fail;
+            return func(obj, view, flags);
+        } else {
+            PyErr_Clear();
+        }
     }
   #endif
     PyErr_Format(PyExc_TypeError, "'%100s' does not have the buffer interface", Py_TYPE(obj)->tp_name);
@@ -5963,7 +6088,6 @@ fail:
 }
 static void __Pyx_ReleaseBuffer(Py_buffer *view) {
     PyObject *obj = view->obj;
-    CYTHON_UNUSED PyObject *releasebuffer_cobj;
     if (!obj) return;
   #if PY_VERSION_HEX >= 0x02060000
     if (PyObject_CheckBuffer(obj)) {
@@ -5973,22 +6097,19 @@ static void __Pyx_ReleaseBuffer(Py_buffer *view) {
   #endif
         if (PyObject_TypeCheck(obj, __pyx_ptype_5numpy_ndarray)) { __pyx_pw_5numpy_7ndarray_3__releasebuffer__(obj, view); return; }
   #if PY_VERSION_HEX < 0x02060000
-    if (obj->ob_type->tp_dict &&
-        (releasebuffer_cobj = PyMapping_GetItemString(obj->ob_type->tp_dict,
-                                                      "__pyx_releasebuffer"))) {
-        releasebufferproc func;
-      #if PY_VERSION_HEX >= 0x02070000 && !(PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION == 0)
-        func = (releasebufferproc) PyCapsule_GetPointer(releasebuffer_cobj, "releasebuffer(obj, view)");
-      #else
-        func = (releasebufferproc) PyCObject_AsVoidPtr(releasebuffer_cobj);
-      #endif
-        Py_DECREF(releasebuffer_cobj);
-        if (!func)
-            goto fail;
-        func(obj, view);
-        return;
-    } else {
-        PyErr_Clear();
+    if (obj->ob_type->tp_dict) {
+        PyObject *releasebuffer_cobj = PyObject_GetItem(
+            obj->ob_type->tp_dict, __pyx_n_s____pyx_releasebuffer);
+        if (releasebuffer_cobj) {
+            releasebufferproc func = (releasebufferproc) PyCObject_AsVoidPtr(releasebuffer_cobj);
+            Py_DECREF(releasebuffer_cobj);
+            if (!func)
+                goto fail;
+            func(obj, view);
+            return;
+        } else {
+            PyErr_Clear();
+        }
     }
   #endif
     goto nofail;
@@ -6003,16 +6124,18 @@ nofail:
 #endif /*  PY_MAJOR_VERSION < 3 */
 
 
-    static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, long level) {
-    PyObject *py_import = 0;
+        static PyObject *__Pyx_Import(PyObject *name, PyObject *from_list, int level) {
     PyObject *empty_list = 0;
     PyObject *module = 0;
     PyObject *global_dict = 0;
     PyObject *empty_dict = 0;
     PyObject *list;
-    py_import = __Pyx_GetAttrString(__pyx_b, "__import__");
+    #if PY_VERSION_HEX < 0x03030000
+    PyObject *py_import;
+    py_import = __Pyx_PyObject_GetAttrStr(__pyx_b, __pyx_n_s____import__);
     if (!py_import)
         goto bad;
+    #endif
     if (from_list)
         list = from_list;
     else {
@@ -6032,13 +6155,17 @@ nofail:
         #if PY_MAJOR_VERSION >= 3
         if (level == -1) {
             if (strchr(__Pyx_MODULE_NAME, '.')) {
-                /* try package relative import first */
+                #if PY_VERSION_HEX < 0x03030000
                 PyObject *py_level = PyInt_FromLong(1);
                 if (!py_level)
                     goto bad;
                 module = PyObject_CallFunctionObjArgs(py_import,
                     name, global_dict, empty_dict, list, py_level, NULL);
                 Py_DECREF(py_level);
+                #else
+                module = PyImport_ImportModuleLevelObject(
+                    name, global_dict, empty_dict, list, 1);
+                #endif
                 if (!module) {
                     if (!PyErr_ExceptionMatches(PyExc_ImportError))
                         goto bad;
@@ -6049,12 +6176,17 @@ nofail:
         }
         #endif
         if (!module) {
+            #if PY_VERSION_HEX < 0x03030000
             PyObject *py_level = PyInt_FromLong(level);
             if (!py_level)
                 goto bad;
             module = PyObject_CallFunctionObjArgs(py_import,
                 name, global_dict, empty_dict, list, py_level, NULL);
             Py_DECREF(py_level);
+            #else
+            module = PyImport_ImportModuleLevelObject(
+                name, global_dict, empty_dict, list, level);
+            #endif
         }
     }
     #else
@@ -6066,12 +6198,96 @@ nofail:
         name, global_dict, empty_dict, list, NULL);
     #endif
 bad:
-    Py_XDECREF(empty_list);
+    #if PY_VERSION_HEX < 0x03030000
     Py_XDECREF(py_import);
+    #endif
+    Py_XDECREF(empty_list);
     Py_XDECREF(empty_dict);
     return module;
 }
 
+static CYTHON_INLINE Py_intptr_t __Pyx_PyInt_from_py_Py_intptr_t(PyObject* x) {
+    const Py_intptr_t neg_one = (Py_intptr_t)-1, const_zero = (Py_intptr_t)0;
+    const int is_unsigned = const_zero < neg_one;
+    if (sizeof(Py_intptr_t) == sizeof(char)) {
+        if (is_unsigned)
+            return (Py_intptr_t)__Pyx_PyInt_AsUnsignedChar(x);
+        else
+            return (Py_intptr_t)__Pyx_PyInt_AsSignedChar(x);
+    } else if (sizeof(Py_intptr_t) == sizeof(short)) {
+        if (is_unsigned)
+            return (Py_intptr_t)__Pyx_PyInt_AsUnsignedShort(x);
+        else
+            return (Py_intptr_t)__Pyx_PyInt_AsSignedShort(x);
+    } else if (sizeof(Py_intptr_t) == sizeof(int)) {
+        if (is_unsigned)
+            return (Py_intptr_t)__Pyx_PyInt_AsUnsignedInt(x);
+        else
+            return (Py_intptr_t)__Pyx_PyInt_AsSignedInt(x);
+    } else if (sizeof(Py_intptr_t) == sizeof(long)) {
+        if (is_unsigned)
+            return (Py_intptr_t)__Pyx_PyInt_AsUnsignedLong(x);
+        else
+            return (Py_intptr_t)__Pyx_PyInt_AsSignedLong(x);
+    } else if (sizeof(Py_intptr_t) == sizeof(PY_LONG_LONG)) {
+        if (is_unsigned)
+            return (Py_intptr_t)__Pyx_PyInt_AsUnsignedLongLong(x);
+        else
+            return (Py_intptr_t)__Pyx_PyInt_AsSignedLongLong(x);
+    }  else {
+        #if CYTHON_COMPILING_IN_PYPY && !defined(_PyLong_AsByteArray)
+        PyErr_SetString(PyExc_RuntimeError,
+                        "_PyLong_AsByteArray() not available in PyPy, cannot convert large numbers");
+        #else
+        Py_intptr_t val;
+        PyObject *v = __Pyx_PyNumber_Int(x);
+        #if PY_MAJOR_VERSION < 3
+        if (likely(v) && !PyLong_Check(v)) {
+            PyObject *tmp = v;
+            v = PyNumber_Long(tmp);
+            Py_DECREF(tmp);
+        }
+        #endif
+        if (likely(v)) {
+            int one = 1; int is_little = (int)*(unsigned char *)&one;
+            unsigned char *bytes = (unsigned char *)&val;
+            int ret = _PyLong_AsByteArray((PyLongObject *)v,
+                                          bytes, sizeof(val),
+                                          is_little, !is_unsigned);
+            Py_DECREF(v);
+            if (likely(!ret))
+                return val;
+        }
+        #endif
+        return (Py_intptr_t)-1;
+    }
+}
+
+static CYTHON_INLINE PyObject *__Pyx_PyInt_to_py_Py_intptr_t(Py_intptr_t val) {
+    const Py_intptr_t neg_one = (Py_intptr_t)-1, const_zero = (Py_intptr_t)0;
+    const int is_unsigned = const_zero < neg_one;
+    if ((sizeof(Py_intptr_t) == sizeof(char))  ||
+        (sizeof(Py_intptr_t) == sizeof(short))) {
+        return PyInt_FromLong((long)val);
+    } else if ((sizeof(Py_intptr_t) == sizeof(int)) ||
+               (sizeof(Py_intptr_t) == sizeof(long))) {
+        if (is_unsigned)
+            return PyLong_FromUnsignedLong((unsigned long)val);
+        else
+            return PyInt_FromLong((long)val);
+    } else if (sizeof(Py_intptr_t) == sizeof(PY_LONG_LONG)) {
+        if (is_unsigned)
+            return PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG)val);
+        else
+            return PyLong_FromLongLong((PY_LONG_LONG)val);
+    } else {
+        int one = 1; int little = (int)*(unsigned char *)&one;
+        unsigned char *bytes = (unsigned char *)&val;
+        return _PyLong_FromByteArray(bytes, sizeof(Py_intptr_t),
+                                     little, !is_unsigned);
+    }
+}
+
 #if CYTHON_CCOMPLEX
   #ifdef __cplusplus
     static CYTHON_INLINE __pyx_t_float_complex __pyx_t_float_complex_from_parts(float x, float y) {
@@ -6502,10 +6718,15 @@ static CYTHON_INLINE int __Pyx_PyInt_AsLongDouble(PyObject* x) {
     return (int)__Pyx_PyInt_AsLong(x);
 }
 
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+#if CYTHON_USE_PYLONG_INTERNALS
+#include "longintrepr.h"
+#endif
+#endif
 static CYTHON_INLINE unsigned long __Pyx_PyInt_AsUnsignedLong(PyObject* x) {
     const unsigned long neg_one = (unsigned long)-1, const_zero = 0;
     const int is_unsigned = neg_one > const_zero;
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION < 3
     if (likely(PyInt_Check(x))) {
         long val = PyInt_AS_LONG(x);
         if (is_unsigned && unlikely(val < 0)) {
@@ -6518,6 +6739,16 @@ static CYTHON_INLINE unsigned long __Pyx_PyInt_AsUnsignedLong(PyObject* x) {
 #endif
     if (likely(PyLong_Check(x))) {
         if (is_unsigned) {
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+#if CYTHON_USE_PYLONG_INTERNALS
+            if (sizeof(digit) <= sizeof(unsigned long)) {
+                switch (Py_SIZE(x)) {
+                    case  0: return 0;
+                    case  1: return (unsigned long) ((PyLongObject*)x)->ob_digit[0];
+                }
+            }
+#endif
+#endif
             if (unlikely(Py_SIZE(x) < 0)) {
                 PyErr_SetString(PyExc_OverflowError,
                                 "can't convert negative value to unsigned long");
@@ -6525,6 +6756,17 @@ static CYTHON_INLINE unsigned long __Pyx_PyInt_AsUnsignedLong(PyObject* x) {
             }
             return (unsigned long)PyLong_AsUnsignedLong(x);
         } else {
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+#if CYTHON_USE_PYLONG_INTERNALS
+            if (sizeof(digit) <= sizeof(unsigned long)) {
+                switch (Py_SIZE(x)) {
+                    case  0: return 0;
+                    case  1: return +(unsigned long) ((PyLongObject*)x)->ob_digit[0];
+                    case -1: return -(unsigned long) ((PyLongObject*)x)->ob_digit[0];
+                }
+            }
+#endif
+#endif
             return (unsigned long)PyLong_AsLong(x);
         }
     } else {
@@ -6537,10 +6779,15 @@ static CYTHON_INLINE unsigned long __Pyx_PyInt_AsUnsignedLong(PyObject* x) {
     }
 }
 
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+#if CYTHON_USE_PYLONG_INTERNALS
+#include "longintrepr.h"
+#endif
+#endif
 static CYTHON_INLINE unsigned PY_LONG_LONG __Pyx_PyInt_AsUnsignedLongLong(PyObject* x) {
     const unsigned PY_LONG_LONG neg_one = (unsigned PY_LONG_LONG)-1, const_zero = 0;
     const int is_unsigned = neg_one > const_zero;
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION < 3
     if (likely(PyInt_Check(x))) {
         long val = PyInt_AS_LONG(x);
         if (is_unsigned && unlikely(val < 0)) {
@@ -6553,6 +6800,16 @@ static CYTHON_INLINE unsigned PY_LONG_LONG __Pyx_PyInt_AsUnsignedLongLong(PyObje
 #endif
     if (likely(PyLong_Check(x))) {
         if (is_unsigned) {
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+#if CYTHON_USE_PYLONG_INTERNALS
+            if (sizeof(digit) <= sizeof(unsigned PY_LONG_LONG)) {
+                switch (Py_SIZE(x)) {
+                    case  0: return 0;
+                    case  1: return (unsigned PY_LONG_LONG) ((PyLongObject*)x)->ob_digit[0];
+                }
+            }
+#endif
+#endif
             if (unlikely(Py_SIZE(x) < 0)) {
                 PyErr_SetString(PyExc_OverflowError,
                                 "can't convert negative value to unsigned PY_LONG_LONG");
@@ -6560,6 +6817,17 @@ static CYTHON_INLINE unsigned PY_LONG_LONG __Pyx_PyInt_AsUnsignedLongLong(PyObje
             }
             return (unsigned PY_LONG_LONG)PyLong_AsUnsignedLongLong(x);
         } else {
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+#if CYTHON_USE_PYLONG_INTERNALS
+            if (sizeof(digit) <= sizeof(unsigned PY_LONG_LONG)) {
+                switch (Py_SIZE(x)) {
+                    case  0: return 0;
+                    case  1: return +(unsigned PY_LONG_LONG) ((PyLongObject*)x)->ob_digit[0];
+                    case -1: return -(unsigned PY_LONG_LONG) ((PyLongObject*)x)->ob_digit[0];
+                }
+            }
+#endif
+#endif
             return (unsigned PY_LONG_LONG)PyLong_AsLongLong(x);
         }
     } else {
@@ -6572,10 +6840,15 @@ static CYTHON_INLINE unsigned PY_LONG_LONG __Pyx_PyInt_AsUnsignedLongLong(PyObje
     }
 }
 
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+#if CYTHON_USE_PYLONG_INTERNALS
+#include "longintrepr.h"
+#endif
+#endif
 static CYTHON_INLINE long __Pyx_PyInt_AsLong(PyObject* x) {
     const long neg_one = (long)-1, const_zero = 0;
     const int is_unsigned = neg_one > const_zero;
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION < 3
     if (likely(PyInt_Check(x))) {
         long val = PyInt_AS_LONG(x);
         if (is_unsigned && unlikely(val < 0)) {
@@ -6588,6 +6861,16 @@ static CYTHON_INLINE long __Pyx_PyInt_AsLong(PyObject* x) {
 #endif
     if (likely(PyLong_Check(x))) {
         if (is_unsigned) {
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+#if CYTHON_USE_PYLONG_INTERNALS
+            if (sizeof(digit) <= sizeof(long)) {
+                switch (Py_SIZE(x)) {
+                    case  0: return 0;
+                    case  1: return (long) ((PyLongObject*)x)->ob_digit[0];
+                }
+            }
+#endif
+#endif
             if (unlikely(Py_SIZE(x) < 0)) {
                 PyErr_SetString(PyExc_OverflowError,
                                 "can't convert negative value to long");
@@ -6595,6 +6878,17 @@ static CYTHON_INLINE long __Pyx_PyInt_AsLong(PyObject* x) {
             }
             return (long)PyLong_AsUnsignedLong(x);
         } else {
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+#if CYTHON_USE_PYLONG_INTERNALS
+            if (sizeof(digit) <= sizeof(long)) {
+                switch (Py_SIZE(x)) {
+                    case  0: return 0;
+                    case  1: return +(long) ((PyLongObject*)x)->ob_digit[0];
+                    case -1: return -(long) ((PyLongObject*)x)->ob_digit[0];
+                }
+            }
+#endif
+#endif
             return (long)PyLong_AsLong(x);
         }
     } else {
@@ -6607,10 +6901,15 @@ static CYTHON_INLINE long __Pyx_PyInt_AsLong(PyObject* x) {
     }
 }
 
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+#if CYTHON_USE_PYLONG_INTERNALS
+#include "longintrepr.h"
+#endif
+#endif
 static CYTHON_INLINE PY_LONG_LONG __Pyx_PyInt_AsLongLong(PyObject* x) {
     const PY_LONG_LONG neg_one = (PY_LONG_LONG)-1, const_zero = 0;
     const int is_unsigned = neg_one > const_zero;
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION < 3
     if (likely(PyInt_Check(x))) {
         long val = PyInt_AS_LONG(x);
         if (is_unsigned && unlikely(val < 0)) {
@@ -6623,6 +6922,16 @@ static CYTHON_INLINE PY_LONG_LONG __Pyx_PyInt_AsLongLong(PyObject* x) {
 #endif
     if (likely(PyLong_Check(x))) {
         if (is_unsigned) {
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+#if CYTHON_USE_PYLONG_INTERNALS
+            if (sizeof(digit) <= sizeof(PY_LONG_LONG)) {
+                switch (Py_SIZE(x)) {
+                    case  0: return 0;
+                    case  1: return (PY_LONG_LONG) ((PyLongObject*)x)->ob_digit[0];
+                }
+            }
+#endif
+#endif
             if (unlikely(Py_SIZE(x) < 0)) {
                 PyErr_SetString(PyExc_OverflowError,
                                 "can't convert negative value to PY_LONG_LONG");
@@ -6630,6 +6939,17 @@ static CYTHON_INLINE PY_LONG_LONG __Pyx_PyInt_AsLongLong(PyObject* x) {
             }
             return (PY_LONG_LONG)PyLong_AsUnsignedLongLong(x);
         } else {
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+#if CYTHON_USE_PYLONG_INTERNALS
+            if (sizeof(digit) <= sizeof(PY_LONG_LONG)) {
+                switch (Py_SIZE(x)) {
+                    case  0: return 0;
+                    case  1: return +(PY_LONG_LONG) ((PyLongObject*)x)->ob_digit[0];
+                    case -1: return -(PY_LONG_LONG) ((PyLongObject*)x)->ob_digit[0];
+                }
+            }
+#endif
+#endif
             return (PY_LONG_LONG)PyLong_AsLongLong(x);
         }
     } else {
@@ -6642,10 +6962,15 @@ static CYTHON_INLINE PY_LONG_LONG __Pyx_PyInt_AsLongLong(PyObject* x) {
     }
 }
 
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+#if CYTHON_USE_PYLONG_INTERNALS
+#include "longintrepr.h"
+#endif
+#endif
 static CYTHON_INLINE signed long __Pyx_PyInt_AsSignedLong(PyObject* x) {
     const signed long neg_one = (signed long)-1, const_zero = 0;
     const int is_unsigned = neg_one > const_zero;
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION < 3
     if (likely(PyInt_Check(x))) {
         long val = PyInt_AS_LONG(x);
         if (is_unsigned && unlikely(val < 0)) {
@@ -6658,6 +6983,16 @@ static CYTHON_INLINE signed long __Pyx_PyInt_AsSignedLong(PyObject* x) {
 #endif
     if (likely(PyLong_Check(x))) {
         if (is_unsigned) {
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+#if CYTHON_USE_PYLONG_INTERNALS
+            if (sizeof(digit) <= sizeof(signed long)) {
+                switch (Py_SIZE(x)) {
+                    case  0: return 0;
+                    case  1: return (signed long) ((PyLongObject*)x)->ob_digit[0];
+                }
+            }
+#endif
+#endif
             if (unlikely(Py_SIZE(x) < 0)) {
                 PyErr_SetString(PyExc_OverflowError,
                                 "can't convert negative value to signed long");
@@ -6665,6 +7000,17 @@ static CYTHON_INLINE signed long __Pyx_PyInt_AsSignedLong(PyObject* x) {
             }
             return (signed long)PyLong_AsUnsignedLong(x);
         } else {
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+#if CYTHON_USE_PYLONG_INTERNALS
+            if (sizeof(digit) <= sizeof(signed long)) {
+                switch (Py_SIZE(x)) {
+                    case  0: return 0;
+                    case  1: return +(signed long) ((PyLongObject*)x)->ob_digit[0];
+                    case -1: return -(signed long) ((PyLongObject*)x)->ob_digit[0];
+                }
+            }
+#endif
+#endif
             return (signed long)PyLong_AsLong(x);
         }
     } else {
@@ -6677,10 +7023,15 @@ static CYTHON_INLINE signed long __Pyx_PyInt_AsSignedLong(PyObject* x) {
     }
 }
 
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+#if CYTHON_USE_PYLONG_INTERNALS
+#include "longintrepr.h"
+#endif
+#endif
 static CYTHON_INLINE signed PY_LONG_LONG __Pyx_PyInt_AsSignedLongLong(PyObject* x) {
     const signed PY_LONG_LONG neg_one = (signed PY_LONG_LONG)-1, const_zero = 0;
     const int is_unsigned = neg_one > const_zero;
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION < 3
     if (likely(PyInt_Check(x))) {
         long val = PyInt_AS_LONG(x);
         if (is_unsigned && unlikely(val < 0)) {
@@ -6693,6 +7044,16 @@ static CYTHON_INLINE signed PY_LONG_LONG __Pyx_PyInt_AsSignedLongLong(PyObject*
 #endif
     if (likely(PyLong_Check(x))) {
         if (is_unsigned) {
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+#if CYTHON_USE_PYLONG_INTERNALS
+            if (sizeof(digit) <= sizeof(signed PY_LONG_LONG)) {
+                switch (Py_SIZE(x)) {
+                    case  0: return 0;
+                    case  1: return (signed PY_LONG_LONG) ((PyLongObject*)x)->ob_digit[0];
+                }
+            }
+#endif
+#endif
             if (unlikely(Py_SIZE(x) < 0)) {
                 PyErr_SetString(PyExc_OverflowError,
                                 "can't convert negative value to signed PY_LONG_LONG");
@@ -6700,6 +7061,17 @@ static CYTHON_INLINE signed PY_LONG_LONG __Pyx_PyInt_AsSignedLongLong(PyObject*
             }
             return (signed PY_LONG_LONG)PyLong_AsUnsignedLongLong(x);
         } else {
+#if CYTHON_COMPILING_IN_CPYTHON && PY_MAJOR_VERSION >= 3
+#if CYTHON_USE_PYLONG_INTERNALS
+            if (sizeof(digit) <= sizeof(signed PY_LONG_LONG)) {
+                switch (Py_SIZE(x)) {
+                    case  0: return 0;
+                    case  1: return +(signed PY_LONG_LONG) ((PyLongObject*)x)->ob_digit[0];
+                    case -1: return -(signed PY_LONG_LONG) ((PyLongObject*)x)->ob_digit[0];
+                }
+            }
+#endif
+#endif
             return (signed PY_LONG_LONG)PyLong_AsLongLong(x);
         }
     } else {
@@ -6757,6 +7129,10 @@ static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class
     PyObject *result = 0;
     PyObject *py_name = 0;
     char warning[200];
+    Py_ssize_t basicsize;
+#ifdef Py_LIMITED_API
+    PyObject *py_basicsize;
+#endif
     py_module = __Pyx_ImportModule(module_name);
     if (!py_module)
         goto bad;
@@ -6776,7 +7152,19 @@ static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class
             module_name, class_name);
         goto bad;
     }
-    if (!strict && (size_t)((PyTypeObject *)result)->tp_basicsize > size) {
+#ifndef Py_LIMITED_API
+    basicsize = ((PyTypeObject *)result)->tp_basicsize;
+#else
+    py_basicsize = PyObject_GetAttrString(result, "__basicsize__");
+    if (!py_basicsize)
+        goto bad;
+    basicsize = PyLong_AsSsize_t(py_basicsize);
+    Py_DECREF(py_basicsize);
+    py_basicsize = 0;
+    if (basicsize == (Py_ssize_t)-1 && PyErr_Occurred())
+        goto bad;
+#endif
+    if (!strict && (size_t)basicsize > size) {
         PyOS_snprintf(warning, sizeof(warning),
             "%s.%s size changed, may indicate binary incompatibility",
             module_name, class_name);
@@ -6786,7 +7174,7 @@ static PyTypeObject *__Pyx_ImportType(const char *module_name, const char *class
         if (PyErr_WarnEx(NULL, warning, 0) < 0) goto bad;
         #endif
     }
-    else if ((size_t)((PyTypeObject *)result)->tp_basicsize != size) {
+    else if ((size_t)basicsize != size) {
         PyErr_Format(PyExc_ValueError,
             "%s.%s has the wrong size, try recompiling",
             module_name, class_name);
@@ -6992,27 +7380,82 @@ static int __Pyx_InitStrings(__Pyx_StringTabEntry *t) {
     return 0;
 }
 
-
-/* Type Conversion Functions */
-
+static CYTHON_INLINE PyObject* __Pyx_PyUnicode_FromString(char* c_str) {
+    return __Pyx_PyUnicode_FromStringAndSize(c_str, strlen(c_str));
+}
+static CYTHON_INLINE char* __Pyx_PyObject_AsString(PyObject* o) {
+    Py_ssize_t ignore;
+    return __Pyx_PyObject_AsStringAndSize(o, &ignore);
+}
+static CYTHON_INLINE char* __Pyx_PyObject_AsStringAndSize(PyObject* o, Py_ssize_t *length) {
+#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT
+    if (
+#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII
+            __Pyx_sys_getdefaultencoding_not_ascii &&
+#endif
+            PyUnicode_Check(o)) {
+#if PY_VERSION_HEX < 0x03030000
+        char* defenc_c;
+        PyObject* defenc = _PyUnicode_AsDefaultEncodedString(o, NULL);
+        if (!defenc) return NULL;
+        defenc_c = PyBytes_AS_STRING(defenc);
+#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII
+        {
+            char* end = defenc_c + PyBytes_GET_SIZE(defenc);
+            char* c;
+            for (c = defenc_c; c < end; c++) {
+                if ((unsigned char) (*c) >= 128) {
+                    PyUnicode_AsASCIIString(o);
+                    return NULL;
+                }
+            }
+        }
+#endif /*__PYX_DEFAULT_STRING_ENCODING_IS_ASCII*/
+        *length = PyBytes_GET_SIZE(defenc);
+        return defenc_c;
+#else /* PY_VERSION_HEX < 0x03030000 */
+        if (PyUnicode_READY(o) == -1) return NULL;
+#if __PYX_DEFAULT_STRING_ENCODING_IS_ASCII
+        if (PyUnicode_IS_ASCII(o)) {
+            *length = PyUnicode_GET_DATA_SIZE(o);
+            return PyUnicode_AsUTF8(o);
+        } else {
+            PyUnicode_AsASCIIString(o);
+            return NULL;
+        }
+#else /* __PYX_DEFAULT_STRING_ENCODING_IS_ASCII */
+        return PyUnicode_AsUTF8AndSize(o, length);
+#endif /* __PYX_DEFAULT_STRING_ENCODING_IS_ASCII */
+#endif /* PY_VERSION_HEX < 0x03030000 */
+    } else
+#endif /* __PYX_DEFAULT_STRING_ENCODING_IS_ASCII  || __PYX_DEFAULT_STRING_ENCODING_IS_DEFAULT */
+    {
+        char* result;
+        int r = PyBytes_AsStringAndSize(o, &result, length);
+        if (r < 0) {
+            return NULL;
+        } else {
+            return result;
+        }
+    }
+}
 static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject* x) {
    int is_true = x == Py_True;
    if (is_true | (x == Py_False) | (x == Py_None)) return is_true;
    else return PyObject_IsTrue(x);
 }
-
 static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x) {
   PyNumberMethods *m;
   const char *name = NULL;
   PyObject *res = NULL;
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION < 3
   if (PyInt_Check(x) || PyLong_Check(x))
 #else
   if (PyLong_Check(x))
 #endif
     return Py_INCREF(x), x;
   m = Py_TYPE(x)->tp_as_number;
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION < 3
   if (m && m->nb_int) {
     name = "int";
     res = PyNumber_Int(x);
@@ -7028,7 +7471,7 @@ static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x) {
   }
 #endif
   if (res) {
-#if PY_VERSION_HEX < 0x03000000
+#if PY_MAJOR_VERSION < 3
     if (!PyInt_Check(res) && !PyLong_Check(res)) {
 #else
     if (!PyLong_Check(res)) {
@@ -7046,7 +7489,6 @@ static CYTHON_INLINE PyObject* __Pyx_PyNumber_Int(PyObject* x) {
   }
   return res;
 }
-
 static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) {
   Py_ssize_t ival;
   PyObject* x = PyNumber_Index(b);
@@ -7055,7 +7497,6 @@ static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) {
   Py_DECREF(x);
   return ival;
 }
-
 static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) {
 #if PY_VERSION_HEX < 0x02050000
    if (ival <= LONG_MAX)
@@ -7069,14 +7510,12 @@ static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) {
    return PyInt_FromSize_t(ival);
 #endif
 }
-
 static CYTHON_INLINE size_t __Pyx_PyInt_AsSize_t(PyObject* x) {
    unsigned PY_LONG_LONG val = __Pyx_PyInt_AsUnsignedLongLong(x);
-   if (unlikely(val == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred())) {
-       return (size_t)-1;
-   } else if (unlikely(val != (unsigned PY_LONG_LONG)(size_t)val)) {
-       PyErr_SetString(PyExc_OverflowError,
-                       "value too large to convert to size_t");
+   if (unlikely(val != (unsigned PY_LONG_LONG)(size_t)val)) {
+       if ((val != (unsigned PY_LONG_LONG)-1) || !PyErr_Occurred())
+           PyErr_SetString(PyExc_OverflowError,
+                           "value too large to convert to size_t");
        return (size_t)-1;
    }
    return (size_t)val;
diff --git a/sklearn/cluster/_hierarchical.pyx b/sklearn/cluster/_hierarchical.pyx
index 881c126a64ce922ee1c527786e0dad8e2ce50662..c07b90c71d1681f0bc185b27a6d6c6c14830d6d1 100644
--- a/sklearn/cluster/_hierarchical.pyx
+++ b/sklearn/cluster/_hierarchical.pyx
@@ -1,8 +1,11 @@
+# Author: Gael Varoquaux <gael.varoquaux@normalesup.org>
+
 import numpy as np
 cimport numpy as np
 cimport cython
+
 ctypedef np.float64_t DOUBLE
-ctypedef np.int_t INT
+ctypedef np.npy_intp INTP
 ctypedef np.int8_t INT8
 
 np.import_array()
@@ -11,41 +14,42 @@ np.import_array()
 @cython.boundscheck(False)
 @cython.wraparound(False)
 @cython.cdivision(True)
-def compute_ward_dist(np.ndarray[DOUBLE, ndim=1] m_1,\
-                    np.ndarray[DOUBLE, ndim=2] m_2,\
-                    np.ndarray[INT, ndim=1] coord_row,
-                    np.ndarray[INT, ndim=1] coord_col,\
-                    np.ndarray[DOUBLE, ndim=1] res):
-    cdef int size_max = coord_row.shape[0]
-    cdef int n_features = m_2.shape[1]
-    cdef int i, j, row, col
+def compute_ward_dist(np.ndarray[DOUBLE, ndim=1, mode='c'] m_1,
+                      np.ndarray[DOUBLE, ndim=2, mode='c'] m_2,
+                      np.ndarray[INTP, ndim=1, mode='c'] coord_row,
+                      np.ndarray[INTP, ndim=1, mode='c'] coord_col,
+                      np.ndarray[DOUBLE, ndim=1, mode='c'] res):
+    cdef INTP size_max = coord_row.shape[0]
+    cdef INTP n_features = m_2.shape[1]
+    cdef INTP i, j, row, col
     cdef DOUBLE pa, n
+
     for i in range(size_max):
         row = coord_row[i]
         col = coord_col[i]
         n = (m_1[row] * m_1[col]) / (m_1[row] + m_1[col])
         pa = 0.
         for j in range(n_features):
-            pa += (m_2[row, j] / m_1[row] - m_2[col, j] / m_1[col])**2
+            pa += (m_2[row, j] / m_1[row] - m_2[col, j] / m_1[col]) ** 2
         res[i] = pa * n
     return res
 
 
-def _hc_get_descendent(int node, children, int n_leaves):
+def _hc_get_descendent(INTP node, children, INTP n_leaves):
     """
     Function returning all the descendent leaves of a set of nodes in the tree.
 
     Parameters
     ----------
-    node : int
+    node : integer
         The node for which we want the descendents.
 
-    children : list of pairs. Length of n_nodes
+    children : list of pairs, length n_nodes
         The children of each non-leaf node. Values less than `n_samples` refer
         to leaves of the tree. A greater value `i` indicates a node with
         children `children[i - n_samples]`.
 
-    n_leaves : int
+    n_leaves : integer
         Number of leaves.
 
     Returns
@@ -56,11 +60,12 @@ def _hc_get_descendent(int node, children, int n_leaves):
     if node < n_leaves:
         return ind
     descendent = []
+
     # It is actually faster to do the accounting of the number of
     # elements is the list ourselves: len is a lengthy operation on a
     # chained list
-    cdef int n_indices = 1
-    cdef int i
+    cdef INTP i, n_indices = 1
+
     while n_indices:
         i = ind.pop()
         if i < n_leaves:
@@ -74,29 +79,29 @@ def _hc_get_descendent(int node, children, int n_leaves):
 
 @cython.boundscheck(False)
 @cython.wraparound(False)
-def hc_get_heads(np.ndarray[INT, ndim=1] parents, copy=True):
-    """ Return the heads of the forest, as defined by parents
-    
+def hc_get_heads(np.ndarray[INTP, ndim=1] parents, copy=True):
+    """Returns the heads of the forest, as defined by parents.
+
     Parameters
-    ===========
-    parents: array of integers
+    ----------
+    parents : array of integers
         The parent structure defining the forest (ensemble of trees)
-    copy: boolean
+    copy : boolean
         If copy is False, the input 'parents' array is modified inplace
 
     Returns
-    =======
-    heads: array of integers of same shape as parents
+    -------
+    heads : array of integers of same shape as parents
         The indices in the 'parents' of the tree heads
 
     """
-    cdef unsigned int parent, node0, node, size
+    cdef INTP parent, node0, node, size
     if copy:
         parents = np.copy(parents)
     size = parents.size
-    for node0 in range(size):
-        # Start from the top of the tree and go down
-        node0 = size - node0 - 1
+
+    # Start from the top of the tree and go down
+    for node0 in range(size - 1, -1, -1):
         node = node0
         parent = parents[node]
         while parent != node:
@@ -108,25 +113,26 @@ def hc_get_heads(np.ndarray[INT, ndim=1] parents, copy=True):
 
 @cython.boundscheck(False)
 @cython.wraparound(False)
-def _get_parents(nodes, heads, np.ndarray[INT, ndim=1] parents,
-                 np.ndarray[INT8, ndim=1] not_visited):
-    """ Return the heads of the given nodes, as defined by parents
-    
-    Modifies in-place 'heads' and 'not_visited'
+def _get_parents(nodes, heads, np.ndarray[INTP, ndim=1] parents,
+                 np.ndarray[INT8, ndim=1, mode='c'] not_visited):
+    """Returns the heads of the given nodes, as defined by parents.
+
+    Modifies 'heads' and 'not_visited' in-place.
 
     Parameters
-    ===========
-    nodes: list of integers
+    ----------
+    nodes : list of integers
         The nodes to start from
-    heads: list of integers
+    heads : list of integers
         A list to hold the results (modified inplace)
-    parents: array of integers
+    parents : array of integers
         The parent structure defining the tree
-    not_visited:
+    not_visited
         The tree nodes to consider (modified inplace)
 
     """
-    cdef unsigned int parent, node
+    cdef INTP parent, node
+
     for node in nodes:
         parent = parents[node]
         while parent != node:
diff --git a/sklearn/cluster/hierarchical.py b/sklearn/cluster/hierarchical.py
index 3d4b9165dd9e9813699ff73aa381b42994e5b613..8e101f3f63c90b316cfc7b92e21ea1326ec18325 100644
--- a/sklearn/cluster/hierarchical.py
+++ b/sklearn/cluster/hierarchical.py
@@ -95,7 +95,7 @@ def ward_tree(X, connectivity=None, n_components=None, copy=True,
                           'structured Ward clustering (i.e. with '
                           'explicit connectivity.', stacklevel=2)
         out = hierarchy.ward(X)
-        children_ = out[:, :2].astype(np.int)
+        children_ = out[:, :2].astype(np.intp)
         return children_, 1, n_samples, None
 
     # Compute the number of nodes
@@ -140,27 +140,27 @@ def ward_tree(X, connectivity=None, n_components=None, copy=True,
         coord_row.extend(len(row) * [ind, ])
         coord_col.extend(row)
 
-    coord_row = np.array(coord_row, dtype=np.int)
-    coord_col = np.array(coord_col, dtype=np.int)
+    coord_row = np.array(coord_row, dtype=np.intp, order='C')
+    coord_col = np.array(coord_col, dtype=np.intp, order='C')
 
     # build moments as a list
-    moments_1 = np.zeros(n_nodes)
+    moments_1 = np.zeros(n_nodes, order='C')
     moments_1[:n_samples] = 1
-    moments_2 = np.zeros((n_nodes, n_features))
+    moments_2 = np.zeros((n_nodes, n_features), order='C')
     moments_2[:n_samples] = X
-    inertia = np.empty(len(coord_row), dtype=np.float)
+    inertia = np.empty(len(coord_row), dtype=np.float, order='C')
     _hierarchical.compute_ward_dist(moments_1, moments_2, coord_row, coord_col,
                                     inertia)
     inertia = list(six.moves.zip(inertia, coord_row, coord_col))
     heapify(inertia)
 
     # prepare the main fields
-    parent = np.arange(n_nodes, dtype=np.int)
+    parent = np.arange(n_nodes, dtype=np.intp)
     heights = np.zeros(n_nodes)
     used_node = np.ones(n_nodes, dtype=bool)
     children = []
 
-    not_visited = np.empty(n_nodes, dtype=np.int8)
+    not_visited = np.empty(n_nodes, dtype=np.int8, order='C')
 
     # recursive merge loop
     for k in range(n_samples, n_nodes):
@@ -186,11 +186,11 @@ def ward_tree(X, connectivity=None, n_components=None, copy=True,
         # List comprehension is faster than a for loop
         [A[l].append(k) for l in coord_col]
         A.append(coord_col)
-        coord_col = np.array(coord_col, dtype=np.int)
-        coord_row = np.empty_like(coord_col)
+        coord_col = np.array(coord_col, dtype=np.intp, order='C')
+        coord_row = np.empty(coord_col.shape, dtype=np.intp, order='C')
         coord_row.fill(k)
         n_additions = len(coord_row)
-        ini = np.empty(n_additions, dtype=np.float)
+        ini = np.empty(n_additions, dtype=np.float, order='C')
 
         _hierarchical.compute_ward_dist(moments_1, moments_2,
                                         coord_row, coord_col, ini)
@@ -268,7 +268,7 @@ def _hc_cut(n_clusters, children, n_leaves):
         # Insert the 2 children and remove the largest node
         heappush(nodes, -these_children[0])
         heappushpop(nodes, -these_children[1])
-    label = np.zeros(n_leaves, dtype=np.int)
+    label = np.zeros(n_leaves, dtype=np.intp)
     for i, node in enumerate(nodes):
         label[_hierarchical._hc_get_descendent(-node, children, n_leaves)] = i
     return label