summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--numpy/core/src/multiarray/item_selection.c87
-rw-r--r--numpy/core/src/npysort/heapsort.c.src67
-rw-r--r--numpy/core/src/npysort/mergesort.c.src85
-rw-r--r--numpy/core/src/npysort/npysort_common.h53
-rw-r--r--numpy/core/src/npysort/quicksort.c.src50
-rw-r--r--numpy/core/src/private/npy_sort.h9
-rw-r--r--numpy/core/tests/test_multiarray.py67
7 files changed, 361 insertions, 57 deletions
diff --git a/numpy/core/src/multiarray/item_selection.c b/numpy/core/src/multiarray/item_selection.c
index 977580d70..76b26d266 100644
--- a/numpy/core/src/multiarray/item_selection.c
+++ b/numpy/core/src/multiarray/item_selection.c
@@ -890,7 +890,7 @@ _new_argsort(PyArrayObject *op, int axis, NPY_SORTKIND which)
static PyArrayObject *global_obj;
static int
-qsortCompare (const void *a, const void *b)
+sortCompare (const void *a, const void *b)
{
return PyArray_DESCR(global_obj)->f->compare(a,b,global_obj);
}
@@ -954,7 +954,9 @@ PyArray_Sort(PyArrayObject *op, int axis, NPY_SORTKIND which)
PyArrayObject *ap = NULL, *store_arr = NULL;
char *ip;
int i, n, m, elsize, orign;
- int axis_orig=axis;
+ int res = 0;
+ int axis_orig = axis;
+ int (*sort)(void *, size_t, size_t, npy_comparator);
n = PyArray_NDIM(op);
if ((n == 0) || (PyArray_SIZE(op) == 1)) {
@@ -975,13 +977,30 @@ PyArray_Sort(PyArrayObject *op, int axis, NPY_SORTKIND which)
if (PyArray_DESCR(op)->f->sort[which] != NULL) {
return _new_sort(op, axis, which);
}
- if ((which != NPY_QUICKSORT)
- || PyArray_DESCR(op)->f->compare == NULL) {
+
+ if (PyArray_DESCR(op)->f->compare == NULL) {
PyErr_SetString(PyExc_TypeError,
- "desired sort not supported for this type");
+ "type does not have compare function");
return -1;
}
+ switch (which) {
+ case NPY_QUICKSORT :
+ sort = npy_quicksort;
+ break;
+ case NPY_HEAPSORT :
+ sort = npy_heapsort;
+ break;
+ case NPY_MERGESORT :
+ sort = npy_mergesort;
+ break;
+ default:
+ PyErr_SetString(PyExc_TypeError,
+ "requested sort kind is not supported");
+ goto fail;
+ }
+
+
SWAPAXES2(op);
ap = (PyArrayObject *)PyArray_FromAny((PyObject *)op,
@@ -1001,13 +1020,26 @@ PyArray_Sort(PyArrayObject *op, int axis, NPY_SORTKIND which)
store_arr = global_obj;
global_obj = ap;
for (ip = PyArray_DATA(ap), i = 0; i < n; i++, ip += elsize*m) {
- qsort(ip, m, elsize, qsortCompare);
+ res = sort(ip, m, elsize, sortCompare);
+ if (res < 0) {
+ break;
+ }
}
global_obj = store_arr;
if (PyErr_Occurred()) {
goto fail;
}
+ else if (res == -NPY_ENOMEM) {
+ PyErr_NoMemory();
+ goto fail;
+ }
+ else if (res == -NPY_ECOMP) {
+ PyErr_SetString(PyExc_TypeError,
+ "sort comparison failed");
+ goto fail;
+ }
+
finish:
Py_DECREF(ap); /* Should update op if needed */
@@ -1045,6 +1077,8 @@ PyArray_ArgSort(PyArrayObject *op, int axis, NPY_SORTKIND which)
npy_intp i, j, n, m, orign;
int argsort_elsize;
char *store_ptr;
+ int res = 0;
+ int (*sort)(void *, size_t, size_t, npy_comparator);
n = PyArray_NDIM(op);
if ((n == 0) || (PyArray_SIZE(op) == 1)) {
@@ -1071,14 +1105,32 @@ PyArray_ArgSort(PyArrayObject *op, int axis, NPY_SORTKIND which)
return (PyObject *)ret;
}
- if ((which != NPY_QUICKSORT) || PyArray_DESCR(op2)->f->compare == NULL) {
+ if (PyArray_DESCR(op2)->f->compare == NULL) {
PyErr_SetString(PyExc_TypeError,
- "requested sort not available for type");
+ "type does not have compare function");
Py_DECREF(op2);
op = NULL;
goto fail;
}
+ switch (which) {
+ case NPY_QUICKSORT :
+ sort = npy_quicksort;
+ break;
+ case NPY_HEAPSORT :
+ sort = npy_heapsort;
+ break;
+ case NPY_MERGESORT :
+ sort = npy_mergesort;
+ break;
+ default:
+ PyErr_SetString(PyExc_TypeError,
+ "requested sort kind is not supported");
+ Py_DECREF(op2);
+ op = NULL;
+ goto fail;
+ }
+
/* ap will contain the reference to op2 */
SWAPAXES(ap, op2);
op = (PyArrayObject *)PyArray_ContiguousFromAny((PyObject *)ap,
@@ -1109,11 +1161,27 @@ PyArray_ArgSort(PyArrayObject *op, int axis, NPY_SORTKIND which)
for (j = 0; j < m; j++) {
ip[j] = j;
}
- qsort((char *)ip, m, sizeof(npy_intp), argsort_static_compare);
+ res = sort((char *)ip, m, sizeof(npy_intp), argsort_static_compare);
+ if (res < 0) {
+ break;
+ }
}
global_data = store_ptr;
global_obj = store;
+ if (PyErr_Occurred()) {
+ goto fail;
+ }
+ else if (res == -NPY_ENOMEM) {
+ PyErr_NoMemory();
+ goto fail;
+ }
+ else if (res == -NPY_ECOMP) {
+ PyErr_SetString(PyExc_TypeError,
+ "sort comparison failed");
+ goto fail;
+ }
+
finish:
Py_DECREF(op);
SWAPBACK(op, ret);
@@ -1123,7 +1191,6 @@ PyArray_ArgSort(PyArrayObject *op, int axis, NPY_SORTKIND which)
Py_XDECREF(op);
Py_XDECREF(ret);
return NULL;
-
}
diff --git a/numpy/core/src/npysort/heapsort.c.src b/numpy/core/src/npysort/heapsort.c.src
index 7fd7c2fd1..6a8c79f7a 100644
--- a/numpy/core/src/npysort/heapsort.c.src
+++ b/numpy/core/src/npysort/heapsort.c.src
@@ -182,7 +182,7 @@ heapsort_@suff@(@type@ *start, npy_intp n, PyArrayObject *arr)
size_t len = PyArray_ITEMSIZE(arr)/sizeof(@type@);
@type@ *tmp = malloc(PyArray_ITEMSIZE(arr));
@type@ *a = start - len;
- npy_intp i,j,l;
+ npy_intp i, j, l;
for (l = n>>1; l > 0; --l) {
@TYPE@_COPY(tmp, a + l*len, len);
@@ -274,3 +274,68 @@ aheapsort_@suff@(@type@ *v, npy_intp *tosort, npy_intp n, PyArrayObject *arr)
}
/**end repeat**/
+
+
+/*
+ *****************************************************************************
+ ** GENERIC SORT **
+ *****************************************************************************
+ */
+
+
+/*
+ * This sort has almost the same signature as libc qsort and is intended to
+ * provide a heapsort for array types that don't have type specific sorts.
+ * The difference in the signature is an error return, as it might be the
+ * case that a memory allocation fails.
+ */
+int
+npy_heapsort(void *base, size_t num, size_t size, npy_comparator cmp)
+{
+ char *tmp = (char *) malloc(size);
+ char *a = (char *) base - size;
+ size_t i, j, l;
+
+ if (tmp == NULL) {
+ return -NPY_ENOMEM;
+ }
+
+ for (l = num >> 1; l > 0; --l) {
+ GENERIC_COPY(tmp, a + l*size, size);
+ for (i = l, j = l << 1; j <= num;) {
+ if (j < num && GENERIC_LT(a + j*size, a + (j+1)*size, cmp))
+ j += 1;
+ if (GENERIC_LT(tmp, a + j*size, cmp)) {
+ GENERIC_COPY(a + i*size, a + j*size, size);
+ i = j;
+ j += j;
+ }
+ else {
+ break;
+ }
+ }
+ GENERIC_COPY(a + i*size, tmp, size);
+ }
+
+ for (; num > 1;) {
+ GENERIC_COPY(tmp, a + num*size, size);
+ GENERIC_COPY(a + num*size, a + size, size);
+ num -= 1;
+ for (i = 1, j = 2; j <= num;) {
+ if (j < num && GENERIC_LT(a + j*size, a + (j+1)*size, cmp))
+ j++;
+ if (GENERIC_LT(tmp, a + j*size, cmp)) {
+ GENERIC_COPY(a + i*size, a + j*size, size);
+ i = j;
+ j += j;
+ }
+ else {
+ break;
+ }
+ }
+ GENERIC_COPY(a + i*size, tmp, size);
+ }
+
+ free(tmp);
+ return 0;
+}
diff --git a/numpy/core/src/npysort/mergesort.c.src b/numpy/core/src/npysort/mergesort.c.src
index 59582deda..a4f6bdb99 100644
--- a/numpy/core/src/npysort/mergesort.c.src
+++ b/numpy/core/src/npysort/mergesort.c.src
@@ -340,3 +340,88 @@ amergesort_@suff@(@type@ *v, npy_intp *tosort, npy_intp num, PyArrayObject *arr)
}
/**end repeat**/
+
+
+/*
+ *****************************************************************************
+ ** GENERIC SORT **
+ *****************************************************************************
+ */
+
+
+static void
+npy_mergesort0(char *pl, char *pr, char *pw, char *vp, size_t size, npy_comparator cmp)
+{
+ char *pi, *pj, *pk, *pm;
+
+ if ((size_t)(pr - pl) > SMALL_MERGESORT*size) {
+ /* merge sort */
+ pm = pl + (((pr - pl)/size) >> 1)*size;
+ npy_mergesort0(pl, pm, pw, vp, size, cmp);
+ npy_mergesort0(pm, pr, pw, vp, size, cmp);
+ GENERIC_COPY(pw, pl, pm - pl);
+ pi = pw + (pm - pl);
+ pj = pw;
+ pk = pl;
+ while (pj < pi && pm < pr) {
+ if (GENERIC_LT(pm, pj, cmp)) {
+ GENERIC_COPY(pk, pm, size);
+ pm += size;
+ }
+ else {
+ GENERIC_COPY(pk, pj, size);
+ pj += size;
+ }
+ pk += size;
+ }
+ GENERIC_COPY(pk, pj, pi - pj);
+ }
+ else {
+ /* insertion sort */
+ for (pi = pl + size; pi < pr; pi += size) {
+ GENERIC_COPY(vp, pi, size);
+ pj = pi;
+ pk = pi - size;
+ while (pj > pl && GENERIC_LT(vp, pk, cmp)) {
+ GENERIC_COPY(pj, pk, size);
+ pj -= size;
+ pk -= size;
+ }
+ GENERIC_COPY(pj, vp, size);
+ }
+ }
+}
+
+
+/*
+ * This sort has almost the same signature as libc qsort and is intended to
+ * provide a mergesort for array types that don't have type specific sorts.
+ * The difference in the signature is an error return, as it might be the
+ * case that a memory allocation fails.
+ */
+int
+npy_mergesort(void *base, size_t num, size_t size, npy_comparator cmp)
+{
+ char *pl, *pr, *pw, *vp;
+ int err = 0;
+
+ pl = (char *)base;
+ pr = pl + num*size;
+ pw = (char *) PyDataMem_NEW((num/2)*size);
+ if (pw == NULL) {
+ err = -NPY_ENOMEM;
+ goto fail_0;
+ }
+ vp = (char *) PyDataMem_NEW(size);
+ if (vp == NULL) {
+ err = -NPY_ENOMEM;
+ goto fail_1;
+ }
+ npy_mergesort0(pl, pr, pw, vp, size, cmp);
+
+ PyDataMem_FREE(vp);
+fail_1:
+ PyDataMem_FREE(pw);
+fail_0:
+ return err;
+}
diff --git a/numpy/core/src/npysort/npysort_common.h b/numpy/core/src/npysort/npysort_common.h
index bc1d278b0..318a80222 100644
--- a/numpy/core/src/npysort/npysort_common.h
+++ b/numpy/core/src/npysort/npysort_common.h
@@ -1,15 +1,9 @@
#ifndef __NPY_SORT_COMMON_H__
#define __NPY_SORT_COMMON_H__
-/*
-#include "Python.h"
-#include "numpy/npy_common.h"
-#include "numpy/npy_math.h"
-#include "npy_config.h"
-*/
+#include <stdlib.h>
#include <numpy/ndarraytypes.h>
-
/*
*****************************************************************************
** SWAP MACROS **
@@ -155,14 +149,17 @@ npy_half_lt_nonan(npy_half h1, npy_half h2)
if (h1&0x8000u) {
if (h2&0x8000u) {
return (h1&0x7fffu) > (h2&0x7fffu);
- } else {
+ }
+ else {
/* Signed zeros are equal, have to check for it */
return (h1 != 0x8000u) || (h2 != 0x0000u);
}
- } else {
+ }
+ else {
if (h2&0x8000u) {
return 0;
- } else {
+ }
+ else {
return (h1&0x7fffu) < (h2&0x7fffu);
}
}
@@ -176,7 +173,8 @@ HALF_LT(npy_half a, npy_half b)
if (npy_half_isnan(b)) {
ret = !npy_half_isnan(a);
- } else {
+ }
+ else {
ret = !npy_half_isnan(a) && npy_half_lt_nonan(a, b);
}
@@ -254,14 +252,6 @@ CLONGDOUBLE_LT(npy_clongdouble a, npy_clongdouble b)
}
-/* The PyObject functions are stubs for later use */
-NPY_INLINE static int
-PyObject_LT(PyObject *pa, PyObject *pb)
-{
- return 0;
-}
-
-
NPY_INLINE static void
STRING_COPY(char *s1, char *s2, size_t len)
{
@@ -333,4 +323,29 @@ UNICODE_LT(npy_ucs4 *s1, npy_ucs4 *s2, size_t len)
return ret;
}
+
+NPY_INLINE static void
+GENERIC_COPY(char *a, char *b, size_t len)
+{
+ memcpy(a, b, len);
+}
+
+
+NPY_INLINE static void
+GENERIC_SWAP(char *a, char *b, size_t len)
+{
+ while(len--) {
+ const char t = *a;
+ *a++ = *b;
+ *b++ = t;
+ }
+}
+
+
+NPY_INLINE static int
+GENERIC_LT(char *a, char *b, int (*cmp)(const void *, const void *))
+{
+ return cmp(a, b) < 0;
+}
+
#endif
diff --git a/numpy/core/src/npysort/quicksort.c.src b/numpy/core/src/npysort/quicksort.c.src
index 68140fe6f..2225887b1 100644
--- a/numpy/core/src/npysort/quicksort.c.src
+++ b/numpy/core/src/npysort/quicksort.c.src
@@ -63,10 +63,12 @@
int
quicksort_@suff@(@type@ *start, npy_intp num, void *NOT_USED)
{
+ @type@ vp;
@type@ *pl = start;
@type@ *pr = start + num - 1;
- @type@ vp;
- @type@ *stack[PYA_QS_STACK], **sptr = stack, *pm, *pi, *pj, *pk;
+ @type@ *stack[PYA_QS_STACK];
+ @type@ **sptr = stack;
+ @type@ *pm, *pi, *pj, *pk;
for (;;) {
while ((pr - pl) > SMALL_QUICKSORT) {
@@ -127,30 +129,30 @@ int
aquicksort_@suff@(@type@ *v, npy_intp* tosort, npy_intp num, void *NOT_USED)
{
@type@ vp;
- npy_intp *pl, *pr;
- npy_intp *stack[PYA_QS_STACK], **sptr=stack, *pm, *pi, *pj, *pk, vi;
-
- pl = tosort;
- pr = tosort + num - 1;
+ npy_intp *pl = tosort;
+ npy_intp *pr = tosort + num - 1;
+ npy_intp *stack[PYA_QS_STACK];
+ npy_intp **sptr = stack;
+ npy_intp *pm, *pi, *pj, *pk, vi;
for (;;) {
while ((pr - pl) > SMALL_QUICKSORT) {
/* quicksort partition */
pm = pl + ((pr - pl) >> 1);
- if (@TYPE@_LT(v[*pm],v[*pl])) INTP_SWAP(*pm,*pl);
- if (@TYPE@_LT(v[*pr],v[*pm])) INTP_SWAP(*pr,*pm);
- if (@TYPE@_LT(v[*pm],v[*pl])) INTP_SWAP(*pm,*pl);
+ if (@TYPE@_LT(v[*pm],v[*pl])) INTP_SWAP(*pm, *pl);
+ if (@TYPE@_LT(v[*pr],v[*pm])) INTP_SWAP(*pr, *pm);
+ if (@TYPE@_LT(v[*pm],v[*pl])) INTP_SWAP(*pm, *pl);
vp = v[*pm];
pi = pl;
pj = pr - 1;
- INTP_SWAP(*pm,*pj);
+ INTP_SWAP(*pm, *pj);
for (;;) {
- do ++pi; while (@TYPE@_LT(v[*pi],vp));
- do --pj; while (@TYPE@_LT(vp,v[*pj]));
+ do ++pi; while (@TYPE@_LT(v[*pi], vp));
+ do --pj; while (@TYPE@_LT(vp, v[*pj]));
if (pi >= pj) {
break;
}
- INTP_SWAP(*pi,*pj);
+ INTP_SWAP(*pi, *pj);
}
pk = pr - 1;
INTP_SWAP(*pi,*pk);
@@ -339,3 +341,23 @@ aquicksort_@suff@(@type@ *v, npy_intp* tosort, npy_intp num, PyArrayObject *arr)
}
/**end repeat**/
+
+
+/*
+ *****************************************************************************
+ ** GENERIC SORT **
+ *****************************************************************************
+ */
+
+
+/*
+ * This sort has almost the same signature as libc qsort and is intended to
+ * supply an error return for compatibility with the other generic sort
+ * kinds.
+ */
+int
+npy_quicksort(void *base, size_t num, size_t size, npy_comparator cmp)
+{
+ qsort(base, num, size, cmp);
+ return 0;
+}
diff --git a/numpy/core/src/private/npy_sort.h b/numpy/core/src/private/npy_sort.h
index 94d831f86..120e7efc2 100644
--- a/numpy/core/src/private/npy_sort.h
+++ b/numpy/core/src/private/npy_sort.h
@@ -6,6 +6,10 @@
#include <numpy/npy_common.h>
#include <numpy/ndarraytypes.h>
+#define NPY_ENOMEM 1
+#define NPY_ECOMP 2
+
+typedef int (*npy_comparator)(const void *, const void *);
int quicksort_bool(npy_bool *vec, npy_intp cnt, void *null);
int heapsort_bool(npy_bool *vec, npy_intp cnt, void *null);
@@ -166,4 +170,9 @@ int aquicksort_unicode(npy_ucs4 *vec, npy_intp *ind, npy_intp cnt, PyArrayObject
int aheapsort_unicode(npy_ucs4 *vec, npy_intp *ind, npy_intp cnt, PyArrayObject *arr);
int amergesort_unicode(npy_ucs4 *vec, npy_intp *ind, npy_intp cnt, PyArrayObject *arr);
+
+int npy_quicksort(void *base, size_t num, size_t size, npy_comparator cmp);
+int npy_heapsort(void *base, size_t num, size_t size, npy_comparator cmp);
+int npy_mergesort(void *base, size_t num, size_t size, npy_comparator cmp);
+
#endif
diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py
index ab4e3e479..fba7a2981 100644
--- a/numpy/core/tests/test_multiarray.py
+++ b/numpy/core/tests/test_multiarray.py
@@ -538,7 +538,7 @@ class TestMethods(TestCase):
c.sort(kind=kind)
assert_equal(c, a, msg)
- # test unicode sort.
+ # test unicode sorts.
s = 'aaaaaaaa'
a = np.array([s + chr(i) for i in range(100)], dtype=np.unicode)
b = a[::-1].copy()
@@ -551,11 +551,11 @@ class TestMethods(TestCase):
c.sort(kind=kind)
assert_equal(c, a, msg)
- # test object array sort.
+ # test object array sorts.
a = np.empty((100,), dtype=np.object)
a[:] = range(100)
b = a[::-1]
- for kind in ['q'] :
+ for kind in ['q', 'h', 'm'] :
msg = "object sort, kind=%s" % kind
c = a.copy();
c.sort(kind=kind)
@@ -564,11 +564,11 @@ class TestMethods(TestCase):
c.sort(kind=kind)
assert_equal(c, a, msg)
- # test record array sort.
+ # test record array sorts.
dt = np.dtype([('f',float),('i',int)])
a = array([(i,i) for i in range(100)], dtype = dt)
b = a[::-1]
- for kind in ['q'] :
+ for kind in ['q', 'h', 'm'] :
msg = "object sort, kind=%s" % kind
c = a.copy();
c.sort(kind=kind)
@@ -577,6 +577,30 @@ class TestMethods(TestCase):
c.sort(kind=kind)
assert_equal(c, a, msg)
+ # test datetime64 sorts.
+ a = np.arange(0, 100, dtype='datetime64[D]')
+ b = a[::-1]
+ for kind in ['q', 'h', 'm'] :
+ msg = "datetime64 sort, kind=%s" % kind
+ c = a.copy();
+ c.sort(kind=kind)
+ assert_equal(c, a, msg)
+ c = b.copy();
+ c.sort(kind=kind)
+ assert_equal(c, a, msg)
+
+ # test timedelta64 sorts.
+ a = np.arange(0, 100, dtype='timedelta64[D]')
+ b = a[::-1]
+ for kind in ['q', 'h', 'm'] :
+ msg = "timedelta64 sort, kind=%s" % kind
+ c = a.copy();
+ c.sort(kind=kind)
+ assert_equal(c, a, msg)
+ c = b.copy();
+ c.sort(kind=kind)
+ assert_equal(c, a, msg)
+
# check axis handling. This should be the same for all type
# specific sorts, so we only check it for one type and one kind
a = np.array([[3,2],[1,0]])
@@ -591,10 +615,6 @@ class TestMethods(TestCase):
d = a.copy()
d.sort()
assert_equal(d, c, "test sort with default axis")
- # using None is known fail at this point
- # d = a.copy()
- # d.sort(axis=None)
- #assert_equal(d, c, "test sort with axis=None")
def test_sort_order(self):
@@ -681,28 +701,49 @@ class TestMethods(TestCase):
assert_equal(a.copy().argsort(kind=kind), r, msg)
assert_equal(b.copy().argsort(kind=kind), rr, msg)
- # test object array argsort.
+ # test object array argsorts.
a = np.empty((100,), dtype=np.object)
a[:] = range(100)
b = a[::-1]
r = np.arange(100)
rr = r[::-1]
- for kind in ['q'] :
+ for kind in ['q', 'm', 'h'] :
msg = "object argsort, kind=%s" % kind
assert_equal(a.copy().argsort(kind=kind), r, msg)
assert_equal(b.copy().argsort(kind=kind), rr, msg)
- # test structured array sort.
+ # test structured array argsorts.
dt = np.dtype([('f',float),('i',int)])
a = array([(i,i) for i in range(100)], dtype = dt)
b = a[::-1]
r = np.arange(100)
rr = r[::-1]
- for kind in ['q'] :
+ for kind in ['q', 'm', 'h'] :
msg = "structured array argsort, kind=%s" % kind
assert_equal(a.copy().argsort(kind=kind), r, msg)
assert_equal(b.copy().argsort(kind=kind), rr, msg)
+ # test datetime64 argsorts.
+ a = np.arange(0, 100, dtype='datetime64[D]')
+ b = a[::-1]
+ r = np.arange(100)
+ rr = r[::-1]
+ for kind in ['q', 'h', 'm'] :
+ msg = "datetime64 argsort, kind=%s" % kind
+ assert_equal(a.copy().argsort(kind=kind), r, msg)
+ assert_equal(b.copy().argsort(kind=kind), rr, msg)
+
+ # test timedelta64 argsorts.
+ a = np.arange(0, 100, dtype='timedelta64[D]')
+ b = a[::-1]
+ r = np.arange(100)
+ rr = r[::-1]
+ for kind in ['q', 'h', 'm'] :
+ msg = "timedelta64 argsort, kind=%s" % kind
+ assert_equal(a.copy().argsort(kind=kind), r, msg)
+ assert_equal(b.copy().argsort(kind=kind), rr, msg)
+
+
# check axis handling. This should be the same for all type
# specific argsorts, so we only check it for one type and one kind
a = np.array([[3,2],[1,0]])