@@ -1866,10 +1866,9 @@ PyArray_LexSort(PyObject *sort_keys, int axis)
1866
1866
*
1867
1867
* For each key use bisection to find the first index i s.t. key <= arr[i].
1868
1868
* When there is no such index i, set i = len(arr). Return the results in ret.
1869
- * All arrays are assumed contiguous on entry and both arr and key must be of
1870
- * the same comparable type.
1869
+ * Both arr and key must be of the same comparable type.
1871
1870
*
1872
- * @param arr contiguous sorted array to be searched.
1871
+ * @param arr 1d, strided, sorted array to be searched.
1873
1872
* @param key contiguous array of keys.
1874
1873
* @param ret contiguous array of intp for returned indices.
1875
1874
* @return void
@@ -1883,15 +1882,16 @@ local_search_left(PyArrayObject *arr, PyArrayObject *key, PyArrayObject *ret)
1883
1882
char * parr = PyArray_DATA (arr );
1884
1883
char * pkey = PyArray_DATA (key );
1885
1884
npy_intp * pret = (npy_intp * )PyArray_DATA (ret );
1886
- int elsize = PyArray_DESCR (arr )-> elsize ;
1885
+ int elsize = PyArray_DESCR (key )-> elsize ;
1886
+ npy_intp arrstride = * PyArray_STRIDES (arr );
1887
1887
npy_intp i ;
1888
1888
1889
1889
for (i = 0 ; i < nkeys ; ++ i ) {
1890
1890
npy_intp imin = 0 ;
1891
1891
npy_intp imax = nelts ;
1892
1892
while (imin < imax ) {
1893
1893
npy_intp imid = imin + ((imax - imin ) >> 1 );
1894
- if (compare (parr + elsize * imid , pkey , key ) < 0 ) {
1894
+ if (compare (parr + arrstride * imid , pkey , key ) < 0 ) {
1895
1895
imin = imid + 1 ;
1896
1896
}
1897
1897
else {
@@ -1909,10 +1909,9 @@ local_search_left(PyArrayObject *arr, PyArrayObject *key, PyArrayObject *ret)
1909
1909
*
1910
1910
* For each key use bisection to find the first index i s.t. key < arr[i].
1911
1911
* When there is no such index i, set i = len(arr). Return the results in ret.
1912
- * All arrays are assumed contiguous on entry and both arr and key must be of
1913
- * the same comparable type.
1912
+ * Both arr and key must be of the same comparable type.
1914
1913
*
1915
- * @param arr contiguous sorted array to be searched.
1914
+ * @param arr 1d, strided, sorted array to be searched.
1916
1915
* @param key contiguous array of keys.
1917
1916
* @param ret contiguous array of intp for returned indices.
1918
1917
* @return void
@@ -1926,15 +1925,16 @@ local_search_right(PyArrayObject *arr, PyArrayObject *key, PyArrayObject *ret)
1926
1925
char * parr = PyArray_DATA (arr );
1927
1926
char * pkey = PyArray_DATA (key );
1928
1927
npy_intp * pret = (npy_intp * )PyArray_DATA (ret );
1929
- int elsize = PyArray_DESCR (arr )-> elsize ;
1928
+ int elsize = PyArray_DESCR (key )-> elsize ;
1929
+ npy_intp arrstride = * PyArray_STRIDES (arr );
1930
1930
npy_intp i ;
1931
1931
1932
1932
for (i = 0 ; i < nkeys ; ++ i ) {
1933
1933
npy_intp imin = 0 ;
1934
1934
npy_intp imax = nelts ;
1935
1935
while (imin < imax ) {
1936
1936
npy_intp imid = imin + ((imax - imin ) >> 1 );
1937
- if (compare (parr + elsize * imid , pkey , key ) <= 0 ) {
1937
+ if (compare (parr + arrstride * imid , pkey , key ) <= 0 ) {
1938
1938
imin = imid + 1 ;
1939
1939
}
1940
1940
else {
@@ -1951,11 +1951,11 @@ local_search_right(PyArrayObject *arr, PyArrayObject *key, PyArrayObject *ret)
1951
1951
*
1952
1952
* For each key use bisection to find the first index i s.t. key <= arr[i].
1953
1953
* When there is no such index i, set i = len(arr). Return the results in ret.
1954
- * All arrays are assumed contiguous on entry and both arr and key must be of
1955
- * the same comparable type.
1954
+ * Both arr and key must be of the same comparable type.
1956
1955
*
1957
- * @param arr contiguous sorted array to be searched.
1956
+ * @param arr 1d, strided array to be searched.
1958
1957
* @param key contiguous array of keys.
1958
+ * @param sorter 1d, strided array of intp that sorts arr.
1959
1959
* @param ret contiguous array of intp for returned indices.
1960
1960
* @return int
1961
1961
*/
@@ -1968,22 +1968,24 @@ local_argsearch_left(PyArrayObject *arr, PyArrayObject *key,
1968
1968
npy_intp nkeys = PyArray_SIZE (key );
1969
1969
char * parr = PyArray_DATA (arr );
1970
1970
char * pkey = PyArray_DATA (key );
1971
- npy_intp * psorter = ( npy_intp * ) PyArray_DATA (sorter );
1971
+ char * psorter = PyArray_DATA (sorter );
1972
1972
npy_intp * pret = (npy_intp * )PyArray_DATA (ret );
1973
- int elsize = PyArray_DESCR (arr )-> elsize ;
1973
+ int elsize = PyArray_DESCR (key )-> elsize ;
1974
+ npy_intp arrstride = * PyArray_STRIDES (arr );
1975
+ npy_intp sorterstride = * PyArray_STRIDES (sorter );
1974
1976
npy_intp i ;
1975
1977
1976
1978
for (i = 0 ; i < nkeys ; ++ i ) {
1977
1979
npy_intp imin = 0 ;
1978
1980
npy_intp imax = nelts ;
1979
1981
while (imin < imax ) {
1980
1982
npy_intp imid = imin + ((imax - imin ) >> 1 );
1981
- npy_intp indx = psorter [ imid ] ;
1983
+ npy_intp indx = * ( npy_intp * )( psorter + sorterstride * imid ) ;
1982
1984
1983
1985
if (indx < 0 || indx >= nelts ) {
1984
1986
return -1 ;
1985
1987
}
1986
- if (compare (parr + elsize * indx , pkey , key ) < 0 ) {
1988
+ if (compare (parr + arrstride * indx , pkey , key ) < 0 ) {
1987
1989
imin = imid + 1 ;
1988
1990
}
1989
1991
else {
@@ -2002,11 +2004,11 @@ local_argsearch_left(PyArrayObject *arr, PyArrayObject *key,
2002
2004
*
2003
2005
* For each key use bisection to find the first index i s.t. key < arr[i].
2004
2006
* When there is no such index i, set i = len(arr). Return the results in ret.
2005
- * All arrays are assumed contiguous on entry and both arr and key must be of
2006
- * the same comparable type.
2007
+ * Both arr and key must be of the same comparable type.
2007
2008
*
2008
- * @param arr contiguous sorted array to be searched.
2009
+ * @param arr 1d, strided array to be searched.
2009
2010
* @param key contiguous array of keys.
2011
+ * @param sorter 1d, strided array of intp that sorts arr.
2010
2012
* @param ret contiguous array of intp for returned indices.
2011
2013
* @return int
2012
2014
*/
@@ -2019,22 +2021,24 @@ local_argsearch_right(PyArrayObject *arr, PyArrayObject *key,
2019
2021
npy_intp nkeys = PyArray_SIZE (key );
2020
2022
char * parr = PyArray_DATA (arr );
2021
2023
char * pkey = PyArray_DATA (key );
2022
- npy_intp * psorter = ( npy_intp * ) PyArray_DATA (sorter );
2024
+ char * psorter = PyArray_DATA (sorter );
2023
2025
npy_intp * pret = (npy_intp * )PyArray_DATA (ret );
2024
- int elsize = PyArray_DESCR (arr )-> elsize ;
2026
+ int elsize = PyArray_DESCR (key )-> elsize ;
2027
+ npy_intp arrstride = * PyArray_STRIDES (arr );
2028
+ npy_intp sorterstride = * PyArray_STRIDES (sorter );
2025
2029
npy_intp i ;
2026
2030
2027
2031
for (i = 0 ; i < nkeys ; ++ i ) {
2028
2032
npy_intp imin = 0 ;
2029
2033
npy_intp imax = nelts ;
2030
2034
while (imin < imax ) {
2031
2035
npy_intp imid = imin + ((imax - imin ) >> 1 );
2032
- npy_intp indx = psorter [ imid ] ;
2036
+ npy_intp indx = * ( npy_intp * )( psorter + sorterstride * imid ) ;
2033
2037
2034
2038
if (indx < 0 || indx >= nelts ) {
2035
2039
return -1 ;
2036
2040
}
2037
- if (compare (parr + elsize * indx , pkey , key ) <= 0 ) {
2041
+ if (compare (parr + arrstride * indx , pkey , key ) <= 0 ) {
2038
2042
imin = imid + 1 ;
2039
2043
}
2040
2044
else {
@@ -2087,6 +2091,7 @@ PyArray_SearchSorted(PyArrayObject *op1, PyObject *op2,
2087
2091
PyArrayObject * sorter = NULL ;
2088
2092
PyArrayObject * ret = NULL ;
2089
2093
PyArray_Descr * dtype ;
2094
+ int ap1_flags = NPY_ARRAY_NOTSWAPPED | NPY_ARRAY_ALIGNED ;
2090
2095
NPY_BEGIN_THREADS_DEF ;
2091
2096
2092
2097
/* Find common type */
@@ -2095,23 +2100,28 @@ PyArray_SearchSorted(PyArrayObject *op1, PyObject *op2,
2095
2100
return NULL ;
2096
2101
}
2097
2102
2098
- /* need ap1 as contiguous array and of right type */
2103
+ /* need ap2 as contiguous array and of right type */
2099
2104
Py_INCREF (dtype );
2100
- ap1 = (PyArrayObject * )PyArray_CheckFromAny (( PyObject * ) op1 , dtype ,
2101
- 1 , 1 ,
2102
- NPY_ARRAY_DEFAULT | NPY_ARRAY_NOTSWAPPED ,
2105
+ ap2 = (PyArrayObject * )PyArray_CheckFromAny (op2 , dtype ,
2106
+ 0 , 0 ,
2107
+ NPY_ARRAY_CARRAY_RO | NPY_ARRAY_NOTSWAPPED ,
2103
2108
NULL );
2104
- if (ap1 == NULL ) {
2109
+ if (ap2 == NULL ) {
2105
2110
Py_DECREF (dtype );
2106
2111
return NULL ;
2107
2112
}
2108
2113
2109
- /* need ap2 as contiguous array and of right type */
2110
- ap2 = (PyArrayObject * )PyArray_CheckFromAny (op2 , dtype ,
2111
- 0 , 0 ,
2112
- NPY_ARRAY_DEFAULT | NPY_ARRAY_NOTSWAPPED ,
2113
- NULL );
2114
- if (ap2 == NULL ) {
2114
+ /*
2115
+ * If the needle (ap2) is larger than the haystack (op1) we copy the
2116
+ * haystack to a continuous array for improved cache utilization.
2117
+ */
2118
+ if (PyArray_SIZE (ap2 ) > PyArray_SIZE (op1 )) {
2119
+ ap1_flags |= NPY_ARRAY_CARRAY_RO ;
2120
+ }
2121
+
2122
+ ap1 = (PyArrayObject * )PyArray_CheckFromAny ((PyObject * )op1 , dtype ,
2123
+ 1 , 1 , ap1_flags , NULL );
2124
+ if (ap1 == NULL ) {
2115
2125
goto fail ;
2116
2126
}
2117
2127
/* check that comparison function exists */
@@ -2125,7 +2135,7 @@ PyArray_SearchSorted(PyArrayObject *op1, PyObject *op2,
2125
2135
/* need ap3 as contiguous array and of right type */
2126
2136
ap3 = (PyArrayObject * )PyArray_CheckFromAny (perm , NULL ,
2127
2137
1 , 1 ,
2128
- NPY_ARRAY_DEFAULT | NPY_ARRAY_NOTSWAPPED ,
2138
+ NPY_ARRAY_ALIGNED | NPY_ARRAY_NOTSWAPPED ,
2129
2139
NULL );
2130
2140
if (ap3 == NULL ) {
2131
2141
PyErr_SetString (PyExc_TypeError ,
@@ -2140,7 +2150,7 @@ PyArray_SearchSorted(PyArrayObject *op1, PyObject *op2,
2140
2150
/* convert to known integer size */
2141
2151
sorter = (PyArrayObject * )PyArray_FromArray (ap3 ,
2142
2152
PyArray_DescrFromType (NPY_INTP ),
2143
- NPY_ARRAY_DEFAULT | NPY_ARRAY_NOTSWAPPED );
2153
+ NPY_ARRAY_ALIGNED | NPY_ARRAY_NOTSWAPPED );
2144
2154
if (sorter == NULL ) {
2145
2155
PyErr_SetString (PyExc_ValueError ,
2146
2156
"could not parse sorter argument" );
0 commit comments