Skip to content

Commit ba38186

Browse files
committed
Simplify implementation of _is_sorted.
We don't need a separate specialization for ints (we can rely on the compiler to inline isnan<int> as always false), and having a separate loop to find the first non-nan value isn't necessary either. One change in behavior this causes (in this private function) is that a fully nan input is considered as being sorted, but this is consistent with empty inputs being considered sorted too, and also OK with the actual use of the function (determine whether to go through a fast path in drawing lines -- fully nan lines are not drawn anyways).
1 parent ccbd641 commit ba38186

File tree

2 files changed

+24
-93
lines changed

2 files changed

+24
-93
lines changed

src/_path.h

+13-57
Original file line numberDiff line numberDiff line change
@@ -1244,68 +1244,24 @@ bool convert_to_string(PathIterator &path,
12441244
}
12451245

12461246
template<class T>
1247-
struct _is_sorted
1247+
bool is_sorted(PyArrayObject *array)
12481248
{
1249-
bool operator()(PyArrayObject *array)
1250-
{
1251-
npy_intp size;
1252-
npy_intp i;
1253-
T last_value = -INFINITY;
1254-
T current_value;
1255-
1256-
size = PyArray_DIM(array, 0);
1257-
1258-
for (i = 0; i < size; ++i) {
1259-
last_value = *((T *)PyArray_GETPTR1(array, i));
1260-
if (!std::isnan(last_value)) {
1261-
break;
1262-
}
1263-
}
1264-
1265-
if (i == size) {
1266-
// The whole array is non-finite
1267-
return false;
1268-
}
1269-
1270-
for (; i < size; ++i) {
1271-
current_value = *((T *)PyArray_GETPTR1(array, i));
1272-
if (!std::isnan(current_value)) {
1273-
if (current_value < last_value) {
1274-
return false;
1275-
}
1276-
last_value = current_value;
1277-
}
1278-
}
1279-
1280-
return true;
1281-
}
1282-
};
1283-
1284-
1285-
template<class T>
1286-
struct _is_sorted_int
1287-
{
1288-
bool operator()(PyArrayObject *array)
1289-
{
1290-
npy_intp size;
1291-
npy_intp i;
1292-
T last_value;
1293-
T current_value;
1294-
1295-
size = PyArray_DIM(array, 0);
1296-
1297-
last_value = *((T *)PyArray_GETPTR1(array, 0));
1298-
1299-
for (i = 1; i < size; ++i) {
1300-
current_value = *((T *)PyArray_GETPTR1(array, i));
1301-
if (current_value < last_value) {
1249+
npy_intp size = PyArray_DIM(array, 0);
1250+
using limits = std::numeric_limits<T>;
1251+
T last = limits::has_infinity ? -limits::infinity() : limits::min();
1252+
1253+
for (npy_intp i = 0; i < size; ++i) {
1254+
T current = *(T *)PyArray_GETPTR1(array, i);
1255+
// The following tests !isnan(current), but also works for integral
1256+
// types. (The isnan(IntegralType) overload is absent on MSVC.)
1257+
if (current == current) {
1258+
if (current < last) {
13021259
return false;
13031260
}
1304-
last_value = current_value;
1261+
last = current;
13051262
}
1306-
1307-
return true;
13081263
}
1264+
return true;
13091265
};
13101266

13111267

src/_path_wrapper.cpp

+11-36
Original file line numberDiff line numberDiff line change
@@ -807,54 +807,29 @@ static PyObject *Py_is_sorted(PyObject *self, PyObject *obj)
807807

808808
/* Handle just the most common types here, otherwise coerce to
809809
double */
810-
switch(PyArray_TYPE(array)) {
810+
switch (PyArray_TYPE(array)) {
811811
case NPY_INT:
812-
{
813-
_is_sorted_int<npy_int> is_sorted;
814-
result = is_sorted(array);
815-
}
812+
result = is_sorted<npy_int>(array);
816813
break;
817-
818814
case NPY_LONG:
819-
{
820-
_is_sorted_int<npy_long> is_sorted;
821-
result = is_sorted(array);
822-
}
815+
result = is_sorted<npy_long>(array);
823816
break;
824-
825817
case NPY_LONGLONG:
826-
{
827-
_is_sorted_int<npy_longlong> is_sorted;
828-
result = is_sorted(array);
829-
}
818+
result = is_sorted<npy_longlong>(array);
830819
break;
831-
832820
case NPY_FLOAT:
833-
{
834-
_is_sorted<npy_float> is_sorted;
835-
result = is_sorted(array);
836-
}
821+
result = is_sorted<npy_float>(array);
837822
break;
838-
839823
case NPY_DOUBLE:
840-
{
841-
_is_sorted<npy_double> is_sorted;
842-
result = is_sorted(array);
843-
}
824+
result = is_sorted<npy_double>(array);
844825
break;
845-
846826
default:
847-
{
848-
Py_DECREF(array);
849-
array = (PyArrayObject *)PyArray_FromObject(obj, NPY_DOUBLE, 1, 1);
850-
851-
if (array == NULL) {
852-
return NULL;
853-
}
854-
855-
_is_sorted<npy_double> is_sorted;
856-
result = is_sorted(array);
827+
Py_DECREF(array);
828+
array = (PyArrayObject *)PyArray_FromObject(obj, NPY_DOUBLE, 1, 1);
829+
if (array == NULL) {
830+
return NULL;
857831
}
832+
result = is_sorted<npy_double>(array);
858833
}
859834

860835
Py_DECREF(array);

0 commit comments

Comments
 (0)