From 3a1fc0a43c7804303436772bbe23c0d79300de5a Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Thu, 13 Jul 2023 13:37:22 +0200 Subject: [PATCH 01/30] API: Make intp the default integer in NumPy core --- numpy/core/src/multiarray/abstractdtypes.c | 10 +++++----- numpy/core/src/multiarray/ctors.c | 2 +- numpy/core/src/umath/ufunc_object.c | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/numpy/core/src/multiarray/abstractdtypes.c b/numpy/core/src/multiarray/abstractdtypes.c index da44fd01f11f..5a707ac82bb9 100644 --- a/numpy/core/src/multiarray/abstractdtypes.c +++ b/numpy/core/src/multiarray/abstractdtypes.c @@ -16,7 +16,7 @@ static inline PyArray_Descr * int_default_descriptor(PyArray_DTypeMeta* NPY_UNUSED(cls)) { - return PyArray_DescrFromType(NPY_LONG); + return PyArray_DescrFromType(NPY_INTP); } static PyArray_Descr * @@ -33,8 +33,8 @@ discover_descriptor_from_pyint( PyErr_Clear(); } else { - if (NPY_MIN_LONG <= value && value <= NPY_MAX_LONG) { - return PyArray_DescrFromType(NPY_LONG); + if (NPY_MIN_INTP <= value && value <= NPY_MAX_INTP) { + return PyArray_DescrFromType(NPY_INTP); } return PyArray_DescrFromType(NPY_LONGLONG); } @@ -153,7 +153,7 @@ int_common_dtype(PyArray_DTypeMeta *NPY_UNUSED(cls), PyArray_DTypeMeta *other) if (NPY_DT_is_legacy(other) && other->type_num < NPY_NTYPES) { if (other->type_num == NPY_BOOL) { /* Use the default integer for bools: */ - return PyArray_DTypeFromTypeNum(NPY_LONG); + return PyArray_DTypeFromTypeNum(NPY_INTP); } else if (PyTypeNum_ISNUMBER(other->type_num) || other->type_num == NPY_TIMEDELTA) { @@ -190,7 +190,7 @@ int_common_dtype(PyArray_DTypeMeta *NPY_UNUSED(cls), PyArray_DTypeMeta *other) return res; } /* And finally, we will try the default integer, just for sports... */ - PyArray_DTypeMeta *default_int = PyArray_DTypeFromTypeNum(NPY_LONG); + PyArray_DTypeMeta *default_int = PyArray_DTypeFromTypeNum(NPY_INTP); res = NPY_DT_CALL_common_dtype(other, default_int); Py_DECREF(default_int); if (res == NULL) { diff --git a/numpy/core/src/multiarray/ctors.c b/numpy/core/src/multiarray/ctors.c index 29b5f9891382..219a617a092e 100644 --- a/numpy/core/src/multiarray/ctors.c +++ b/numpy/core/src/multiarray/ctors.c @@ -3209,7 +3209,7 @@ PyArray_ArangeObj(PyObject *start, PyObject *stop, PyObject *step, PyArray_Descr if (!dtype) { /* intentionally made to be at least NPY_LONG */ - dtype = PyArray_DescrFromType(NPY_LONG); + dtype = PyArray_DescrFromType(NPY_INTP); Py_SETREF(dtype, PyArray_DescrFromObject(start, dtype)); if (dtype == NULL) { goto fail; diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c index 5b75b3bfcdfa..faba54b779c5 100644 --- a/numpy/core/src/umath/ufunc_object.c +++ b/numpy/core/src/umath/ufunc_object.c @@ -6512,7 +6512,7 @@ py_resolve_dtypes_generic(PyUFuncObject *ufunc, npy_bool return_context, } /* Explicitly allow int, float, and complex for the "weak" types. */ else if (descr_obj == (PyObject *)&PyLong_Type) { - descr = PyArray_DescrFromType(NPY_LONG); + descr = PyArray_DescrFromType(NPY_INTP); dummy_arrays[i] = (PyArrayObject *)PyArray_Empty(0, NULL, descr, 0); if (dummy_arrays[i] == NULL) { goto finish; From aaad5b53378a714f9e4531d33cf3a09600abc03f Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Thu, 13 Jul 2023 13:38:28 +0200 Subject: [PATCH 02/30] API: Remove `int_` and `uint_` from Cython as they are misleading as long --- numpy/__init__.pxd | 5 ----- 1 file changed, 5 deletions(-) diff --git a/numpy/__init__.pxd b/numpy/__init__.pxd index da74eaaa9803..0bb088688b24 100644 --- a/numpy/__init__.pxd +++ b/numpy/__init__.pxd @@ -701,12 +701,7 @@ ctypedef npy_float64 float64_t ctypedef float complex complex64_t ctypedef double complex complex128_t -# The int types are mapped a bit surprising -- -# numpy.int corresponds to 'l' and numpy.long to 'q' -ctypedef npy_long int_t ctypedef npy_longlong longlong_t - -ctypedef npy_ulong uint_t ctypedef npy_ulonglong ulonglong_t ctypedef npy_intp intp_t From 1841db73a10ac81cd642ec8d7dd16f6b08c8252a Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Thu, 13 Jul 2023 13:38:50 +0200 Subject: [PATCH 03/30] MAINT: Keep using `long` in for legacy random number generation The new random number generation defaults to int64 throughout. --- numpy/random/mtrand.pyx | 49 +++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/numpy/random/mtrand.pyx b/numpy/random/mtrand.pyx index 752d9beaefd2..04c68eae9de0 100644 --- a/numpy/random/mtrand.pyx +++ b/numpy/random/mtrand.pyx @@ -622,8 +622,13 @@ cdef class RandomState: tomaxint(size=None) Return a sample of uniformly distributed random integers in the interval - [0, ``np.iinfo(np.int_).max``]. The `np.int_` type translates to the C long - integer type and its precision is platform dependent. + [0, ``np.iinfo("long"").max``]. + + .. warning:: + This function users the C-long dtype, which is 32bit on windows + and otherwise 64bit on 64bit platforms (and 32bit on 32bit ones). + Since NumPy 2.0, NumPy's default integer is 32bit on 32bit platforms + and 64bit on 64bit platforms. Parameters ---------- @@ -675,9 +680,9 @@ cdef class RandomState: randoms_data[i] = random_positive_int(&self._bitgen) return randoms - def randint(self, low, high=None, size=None, dtype=int): + def randint(self, low, high=None, size=None, dtype="long"): """ - randint(low, high=None, size=None, dtype=int) + randint(low, high=None, size=None, dtype="long") Return random integers from `low` (inclusive) to `high` (exclusive). @@ -706,10 +711,16 @@ cdef class RandomState: single value is returned. dtype : dtype, optional Desired dtype of the result. Byteorder must be native. - The default value is int. + The default value is "long". .. versionadded:: 1.11.0 + .. warning:: + This function defaults to the C-long dtype, which is 32bit on windows + and otherwise 64bit on 64bit platforms (and 32bit on 32bit ones). + Since NumPy 2.0, NumPy's default integer is 32bit on 32bit platforms + and 64bit on 64bit platforms. Which corresponds to `np.intp`. + Returns ------- out : int or ndarray of ints @@ -851,6 +862,13 @@ cdef class RandomState: method of a `~numpy.random.Generator` instance instead; please see the :ref:`random-quick-start`. + .. warning:: + This function uses the C-long dtype, which is 32bit on windows + and otherwise 64bit on 64bit platforms (and 32bit on 32bit ones). + Since NumPy 2.0, NumPy's default integer is 32bit on 32bit platforms + and 64bit on 64bit platforms. + + Parameters ---------- a : 1-D array-like or int @@ -992,7 +1010,7 @@ cdef class RandomState: idx = cdf.searchsorted(uniform_samples, side='right') # searchsorted returns a scalar # force cast to int for LLP64 - idx = np.array(idx, copy=False).astype(int, casting='unsafe') + idx = np.array(idx, copy=False).astype("long", casting='unsafe') else: idx = self.randint(0, pop_size, size=shape) else: @@ -1007,7 +1025,7 @@ cdef class RandomState: raise ValueError("Fewer non-zero entries in p than size") n_uniq = 0 p = p.copy() - found = np.zeros(shape, dtype=int) + found = np.zeros(shape, dtype="long") flat_found = found.ravel() while n_uniq < size: x = self.rand(size - n_uniq) @@ -3490,7 +3508,7 @@ cdef class RandomState: return legacy_random_binomial(&self._bitgen, _dp, _in, &self._binomial) - randoms = np.empty(size, int) + randoms = np.empty(size, "long") cnt = np.PyArray_SIZE(randoms) randoms_data = np.PyArray_DATA(randoms) @@ -3536,6 +3554,12 @@ cdef class RandomState: where each sample is equal to N, the number of failures that occurred before a total of n successes was reached. + .. warning:: + This function returns the C-long dtype, which is 32bit on windows + and otherwise 64bit on 64bit platforms (and 32bit on 32bit ones). + Since NumPy 2.0, NumPy's default integer is 32bit on 32bit platforms + and 64bit on 64bit platforms. + See Also -------- random.Generator.negative_binomial: which should be used for new code. @@ -4272,6 +4296,13 @@ cdef class RandomState: method of a `~numpy.random.Generator` instance instead; please see the :ref:`random-quick-start`. + .. warning:: + This function defaults to the C-long dtype, which is 32bit on windows + and otherwise 64bit on 64bit platforms (and 32bit on 32bit ones). + Since NumPy 2.0, NumPy's default integer is 32bit on 32bit platforms + and 64bit on 64bit platforms. + + Parameters ---------- n : int @@ -4374,7 +4405,7 @@ cdef class RandomState: shape = (operator.index(size), d) except: shape = tuple(size) + (d,) - multin = np.zeros(shape, dtype=int) + multin = np.zeros(shape, dtype="long") mnarr = multin mnix = np.PyArray_DATA(mnarr) sz = np.PyArray_SIZE(mnarr) From 253c615b168bff83342bb57c4b94ea06a0a852f1 Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Thu, 13 Jul 2023 13:58:28 +0200 Subject: [PATCH 04/30] fixup cython --- numpy/__init__.cython-30.pxd | 5 ----- 1 file changed, 5 deletions(-) diff --git a/numpy/__init__.cython-30.pxd b/numpy/__init__.cython-30.pxd index 2453cd27a249..3b900af9682d 100644 --- a/numpy/__init__.cython-30.pxd +++ b/numpy/__init__.cython-30.pxd @@ -743,12 +743,7 @@ ctypedef npy_float64 float64_t ctypedef float complex complex64_t ctypedef double complex complex128_t -# The int types are mapped a bit surprising -- -# numpy.int corresponds to 'l' and numpy.long to 'q' -ctypedef npy_long int_t ctypedef npy_longlong longlong_t - -ctypedef npy_ulong uint_t ctypedef npy_ulonglong ulonglong_t ctypedef npy_intp intp_t From eb274911fd7080f68ee88939fd5d59a04839ad90 Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Thu, 13 Jul 2023 13:58:34 +0200 Subject: [PATCH 05/30] fixup initial change --- numpy/core/src/multiarray/descriptor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/numpy/core/src/multiarray/descriptor.c b/numpy/core/src/multiarray/descriptor.c index 36a95f8138b8..18f6c2023b72 100644 --- a/numpy/core/src/multiarray/descriptor.c +++ b/numpy/core/src/multiarray/descriptor.c @@ -1537,7 +1537,7 @@ _convert_from_type(PyObject *obj) { return PyArray_DescrFromTypeObject(obj); } else if (typ == &PyLong_Type) { - return PyArray_DescrFromType(NPY_LONG); + return PyArray_DescrFromType(NPY_INTP); } else if (typ == &PyFloat_Type) { return PyArray_DescrFromType(NPY_DOUBLE); From e9821aedcfa71264e3fe367f85b1d10588fc3d9a Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Thu, 13 Jul 2023 15:28:37 +0200 Subject: [PATCH 06/30] API: Add NPY_DEFAULT_INT which is runtime (unless NumPy >2 is forced) Also test it within cython --- numpy/__init__.cython-30.pxd | 1 + numpy/__init__.pxd | 1 + numpy/core/code_generators/generate_numpy_api.py | 15 +++++++++++---- numpy/core/include/numpy/ndarraytypes.h | 7 +++++++ numpy/core/tests/examples/cython/checks.pyx | 8 ++++++++ numpy/core/tests/test_cython.py | 4 ++++ 6 files changed, 32 insertions(+), 4 deletions(-) diff --git a/numpy/__init__.cython-30.pxd b/numpy/__init__.cython-30.pxd index 3b900af9682d..b55116c654c3 100644 --- a/numpy/__init__.cython-30.pxd +++ b/numpy/__init__.cython-30.pxd @@ -82,6 +82,7 @@ cdef extern from "numpy/arrayobject.h": NPY_COMPLEX512 NPY_INTP + NPY_DEFAULT_INT # Not a compile time constant (normally)! ctypedef enum NPY_ORDER: NPY_ANYORDER diff --git a/numpy/__init__.pxd b/numpy/__init__.pxd index 0bb088688b24..e3cf6bd4b885 100644 --- a/numpy/__init__.pxd +++ b/numpy/__init__.pxd @@ -79,6 +79,7 @@ cdef extern from "numpy/arrayobject.h": NPY_COMPLEX512 NPY_INTP + NPY_DEFAULT_INT ctypedef enum NPY_ORDER: NPY_ANYORDER diff --git a/numpy/core/code_generators/generate_numpy_api.py b/numpy/core/code_generators/generate_numpy_api.py index b3af9536b61c..8f76c5534657 100644 --- a/numpy/core/code_generators/generate_numpy_api.py +++ b/numpy/core/code_generators/generate_numpy_api.py @@ -26,16 +26,22 @@ #else #if defined(PY_ARRAY_UNIQUE_SYMBOL) -#define PyArray_API PY_ARRAY_UNIQUE_SYMBOL + #define PyArray_API PY_ARRAY_UNIQUE_SYMBOL + #define _NPY_VERSION_CONCAT_HELPER2(x, y) x ## y + #define _NPY_VERSION_CONCAT_HELPER(arg) NPY_EXP_DTYPE_API_CONCAT_HELPER2(arg, _RUNTIME_VERSION) + #define PyArray_RUNTIME_VERSION _NPY_VERSION_CONCAT_HELPER(PY_ARRAY_UNIQUE_SYMBOL) #endif #if defined(NO_IMPORT) || defined(NO_IMPORT_ARRAY) extern void **PyArray_API; +extern int PyArray_RUNTIME_VERSION; #else #if defined(PY_ARRAY_UNIQUE_SYMBOL) void **PyArray_API; +int PyArray_RUNTIME_VERSION; #else -static void **PyArray_API=NULL; +static void **PyArray_API = NULL; +static int PyArray_RUNTIME_VERSION = 0; #endif #endif @@ -82,7 +88,8 @@ (int) NPY_VERSION, (int) PyArray_GetNDArrayCVersion()); return -1; } - if (NPY_FEATURE_VERSION > PyArray_GetNDArrayCFeatureVersion()) { + PyArray_RUNTIME_VERSION = (int)PyArray_GetNDArrayCFeatureVersion(); + if (NPY_FEATURE_VERSION > PyArray_RUNTIME_VERSION) { PyErr_Format(PyExc_RuntimeError, "module compiled against "\ "API version 0x%%x but this version of numpy is 0x%%x . "\ "Check the section C-API incompatibility at the "\ @@ -90,7 +97,7 @@ "https://numpy.org/devdocs/user/troubleshooting-importerror.html"\ "#c-api-incompatibility "\ "for indications on how to solve this problem .", \ - (int) NPY_FEATURE_VERSION, (int) PyArray_GetNDArrayCFeatureVersion()); + (int)NPY_FEATURE_VERSION, PyArray_RUNTIME_VERSION); return -1; } diff --git a/numpy/core/include/numpy/ndarraytypes.h b/numpy/core/include/numpy/ndarraytypes.h index 27b18e263b26..1160cc6f21a4 100644 --- a/numpy/core/include/numpy/ndarraytypes.h +++ b/numpy/core/include/numpy/ndarraytypes.h @@ -1458,6 +1458,13 @@ PyArrayNeighborhoodIter_Next2D(PyArrayNeighborhoodIterObject* iter); /* The default array type */ #define NPY_DEFAULT_TYPE NPY_DOUBLE +/* default integer type */ +#if NPY_FEATURE_VERSION >= NPY_2_0_API_VERSION + #define NPY_DEFAULT_INT NPY_INTP +#else + #define NPY_DEFAULT_INT \ + (PyArray_RUNTIME_VERSION >= NPY_2_0_API_VERSION ? NPY_INTP : NPY_LONG) +#endif /* * All sorts of useful ways to look into a PyArrayObject. It is recommended diff --git a/numpy/core/tests/examples/cython/checks.pyx b/numpy/core/tests/examples/cython/checks.pyx index ba32ef21320a..d4d464ddcbaf 100644 --- a/numpy/core/tests/examples/cython/checks.pyx +++ b/numpy/core/tests/examples/cython/checks.pyx @@ -77,3 +77,11 @@ def make_iso_8601_datetime(dt: "datetime"): cnp.NPY_NO_CASTING, ) return result + + +def get_default_integer(): + if cnp.NPY_DEFAULT_INT == cnp.NPY_LONG: + return cnp.dtype("long") + if cnp.NPY_DEFAULT_INT == cnp.NPY_INTP: + return cnp.dtype("intp") + return None \ No newline at end of file diff --git a/numpy/core/tests/test_cython.py b/numpy/core/tests/test_cython.py index 73e1b7a7bc36..fa6d70ce2213 100644 --- a/numpy/core/tests/test_cython.py +++ b/numpy/core/tests/test_cython.py @@ -138,6 +138,10 @@ def test_abstract_scalars(install_temp): assert checks.is_integer(np.int8(1)) assert checks.is_integer(np.uint64(1)) +def test_default_int(install_temp): + import checks + + assert checks.get_default_integer() is np.dtype(int) def test_convert_datetime64_to_datetimestruct(install_temp): # GH#21199 From 8a872786f7a5b8386d436d2266de93a0d3a24728 Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Thu, 13 Jul 2023 15:54:04 +0200 Subject: [PATCH 07/30] fixup initial (add/multiply reduction) --- numpy/core/src/umath/ufunc_object.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c index faba54b779c5..d234c6449dd0 100644 --- a/numpy/core/src/umath/ufunc_object.c +++ b/numpy/core/src/umath/ufunc_object.c @@ -2738,14 +2738,14 @@ reducelike_promote_and_resolve(PyUFuncObject *ufunc, && ((strcmp(ufunc->name, "add") == 0) || (strcmp(ufunc->name, "multiply") == 0))) { if (PyTypeNum_ISBOOL(typenum)) { - typenum = NPY_LONG; + typenum = NPY_INTP; } - else if ((size_t)PyArray_DESCR(arr)->elsize < sizeof(long)) { + else if ((size_t)PyArray_DESCR(arr)->elsize < sizeof(npy_intp)) { if (PyTypeNum_ISUNSIGNED(typenum)) { - typenum = NPY_ULONG; + typenum = NPY_UINTP; } else { - typenum = NPY_LONG; + typenum = NPY_INTP; } } signature[0] = PyArray_DTypeFromTypeNum(typenum); From 9c4a9cd10c88a634ea262331753116528ce09991 Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Thu, 13 Jul 2023 16:09:12 +0200 Subject: [PATCH 08/30] Fixup NPY_DEFAULT_INT definition (and version exposure) --- numpy/core/code_generators/generate_numpy_api.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/numpy/core/code_generators/generate_numpy_api.py b/numpy/core/code_generators/generate_numpy_api.py index 8f76c5534657..e3446382ea92 100644 --- a/numpy/core/code_generators/generate_numpy_api.py +++ b/numpy/core/code_generators/generate_numpy_api.py @@ -28,7 +28,7 @@ #if defined(PY_ARRAY_UNIQUE_SYMBOL) #define PyArray_API PY_ARRAY_UNIQUE_SYMBOL #define _NPY_VERSION_CONCAT_HELPER2(x, y) x ## y - #define _NPY_VERSION_CONCAT_HELPER(arg) NPY_EXP_DTYPE_API_CONCAT_HELPER2(arg, _RUNTIME_VERSION) + #define _NPY_VERSION_CONCAT_HELPER(arg) _NPY_VERSION_CONCAT_HELPER2(arg, PyArray_RUNTIME_VERSION) #define PyArray_RUNTIME_VERSION _NPY_VERSION_CONCAT_HELPER(PY_ARRAY_UNIQUE_SYMBOL) #endif From c226fa2d4a30bb42f27aba86a759cfdf29e24a75 Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Thu, 20 Jul 2023 15:48:12 +0200 Subject: [PATCH 09/30] ENH: Allow int64 explicitly in `ldexp` This way, any integer input should work fine, in particular any 64 bit platform. Chosing this rather than intp, since there seems little reason to not support 64bit ints on 32bit platforms. --- numpy/core/code_generators/generate_umath.py | 8 ++++---- numpy/core/src/umath/loops.c.src | 10 +++++----- numpy/core/src/umath/loops.h.src | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/numpy/core/code_generators/generate_umath.py b/numpy/core/code_generators/generate_umath.py index a170f83be622..463d07d3accc 100644 --- a/numpy/core/code_generators/generate_umath.py +++ b/numpy/core/code_generators/generate_umath.py @@ -1090,12 +1090,12 @@ def english_upper(s): None, [TypeDescription('e', None, 'ei', 'e'), TypeDescription('f', None, 'fi', 'f', dispatch='loops_exponent_log'), - TypeDescription('e', FuncNameSuffix('long'), 'el', 'e'), - TypeDescription('f', FuncNameSuffix('long'), 'fl', 'f'), + TypeDescription('e', FuncNameSuffix('int64'), 'e'+int64, 'e'), + TypeDescription('f', FuncNameSuffix('int64'), 'f'+int64, 'f'), TypeDescription('d', None, 'di', 'd', dispatch='loops_exponent_log'), - TypeDescription('d', FuncNameSuffix('long'), 'dl', 'd'), + TypeDescription('d', FuncNameSuffix('int64'), 'd'+int64, 'd'), TypeDescription('g', None, 'gi', 'g'), - TypeDescription('g', FuncNameSuffix('long'), 'gl', 'g'), + TypeDescription('g', FuncNameSuffix('int64'), 'g'+int64, 'g'), ], ), 'frexp' : diff --git a/numpy/core/src/umath/loops.c.src b/numpy/core/src/umath/loops.c.src index 97a74b4257aa..4fec1d9fb3a4 100644 --- a/numpy/core/src/umath/loops.c.src +++ b/numpy/core/src/umath/loops.c.src @@ -1321,16 +1321,16 @@ NPY_NO_EXPORT void } NPY_NO_EXPORT void -@TYPE@_ldexp_long(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)) +@TYPE@_ldexp_int64(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)) { /* * Additional loop to handle npy_long integer inputs (cf. #866, #1633). * npy_long != npy_int on many 64-bit platforms, so we need this second loop - * to handle the default integer type. + * to handle the default (and larger) integer types. */ BINARY_LOOP { const @type@ in1 = *(@type@ *)ip1; - const long in2 = *(long *)ip2; + const npy_int64 in2 = *(npy_int64 *)ip2; if (((int)in2) == in2) { /* Range OK */ *((@type@ *)op1) = npy_ldexp@c@(in1, ((int)in2)); @@ -1853,7 +1853,7 @@ HALF_ldexp(char **args, npy_intp const *dimensions, npy_intp const *steps, void } NPY_NO_EXPORT void -HALF_ldexp_long(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)) +HALF_ldexp_int64(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)) { /* * Additional loop to handle npy_long integer inputs (cf. #866, #1633). @@ -1862,7 +1862,7 @@ HALF_ldexp_long(char **args, npy_intp const *dimensions, npy_intp const *steps, */ BINARY_LOOP { const float in1 = npy_half_to_float(*(npy_half *)ip1); - const long in2 = *(long *)ip2; + const npy_int64 in2 = *(npy_int64 *)ip2; if (((int)in2) == in2) { /* Range OK */ *((npy_half *)op1) = npy_float_to_half(npy_ldexpf(in1, ((int)in2))); diff --git a/numpy/core/src/umath/loops.h.src b/numpy/core/src/umath/loops.h.src index cce73aff8504..25fa4e2cae93 100644 --- a/numpy/core/src/umath/loops.h.src +++ b/numpy/core/src/umath/loops.h.src @@ -525,7 +525,7 @@ NPY_NO_EXPORT void @TYPE@_ldexp(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)); NPY_NO_EXPORT void -@TYPE@_ldexp_long(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)); +@TYPE@_ldexp_int64(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)); /**end repeat**/ /**begin repeat From 2e21ba8b5f341d9274433600d1f515329326c4bb Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Thu, 20 Jul 2023 16:02:52 +0200 Subject: [PATCH 10/30] TST: Adapt _ufunc_tests to use intp in ufuncs (default integer) --- numpy/core/src/umath/_umath_tests.c.src | 40 ++++++++++++------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/numpy/core/src/umath/_umath_tests.c.src b/numpy/core/src/umath/_umath_tests.c.src index b427991e5463..f3d180f524ad 100644 --- a/numpy/core/src/umath/_umath_tests.c.src +++ b/numpy/core/src/umath/_umath_tests.c.src @@ -84,8 +84,8 @@ char *inner1d_signature = "(i),(i)->()"; /**begin repeat - #TYPE=LONG,DOUBLE# - #typ=npy_long,npy_double# + #TYPE=INTP,DOUBLE# + #typ=npy_intp,npy_double# */ /* @@ -118,8 +118,8 @@ char *innerwt_signature = "(i),(i),(i)->()"; /**begin repeat - #TYPE=LONG,DOUBLE# - #typ=npy_long,npy_double# + #TYPE=INTP,DOUBLE# + #typ=npy_intp,npy_double# */ @@ -156,8 +156,8 @@ char *matmul_signature = "(m?,n),(n,p?)->(m?,p?)"; /**begin repeat - #TYPE=FLOAT,DOUBLE,LONG# - #typ=npy_float,npy_double,npy_long# + #TYPE=FLOAT,DOUBLE,INTP# + #typ=npy_float,npy_double,npy_intp# */ /* @@ -224,8 +224,8 @@ char *cross1d_signature = "(3),(3)->(3)"; /**begin repeat - #TYPE=LONG,DOUBLE# - #typ=npy_long, npy_double# + #TYPE=INTP,DOUBLE# + #typ=npy_intp, npy_double# */ /* @@ -326,8 +326,8 @@ char *cumsum_signature = "(i)->(i)"; /**begin repeat - #TYPE=LONG,DOUBLE# - #typ=npy_long,npy_double# + #TYPE=INTP,DOUBLE# + #typ=npy_intp,npy_double# */ static void @@ -417,27 +417,27 @@ defdict = { static PyUFuncGenericFunction always_error_functions[] = { always_error_loop }; static void *always_error_data[] = { (void *)NULL }; static char always_error_signatures[] = { NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE }; -static PyUFuncGenericFunction inner1d_functions[] = { LONG_inner1d, DOUBLE_inner1d }; +static PyUFuncGenericFunction inner1d_functions[] = { INTP_inner1d, DOUBLE_inner1d }; static void *inner1d_data[] = { (void *)NULL, (void *)NULL }; -static char inner1d_signatures[] = { NPY_LONG, NPY_LONG, NPY_LONG, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE }; -static PyUFuncGenericFunction innerwt_functions[] = { LONG_innerwt, DOUBLE_innerwt }; +static char inner1d_signatures[] = { NPY_INTP, NPY_INTP, NPY_INTP, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE }; +static PyUFuncGenericFunction innerwt_functions[] = { INTP_innerwt, DOUBLE_innerwt }; static void *innerwt_data[] = { (void *)NULL, (void *)NULL }; -static char innerwt_signatures[] = { NPY_LONG, NPY_LONG, NPY_LONG, NPY_LONG, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE }; -static PyUFuncGenericFunction matrix_multiply_functions[] = { LONG_matrix_multiply, FLOAT_matrix_multiply, DOUBLE_matrix_multiply }; +static char innerwt_signatures[] = { NPY_INTP, NPY_INTP, NPY_INTP, NPY_INTP, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE }; +static PyUFuncGenericFunction matrix_multiply_functions[] = { INTP_matrix_multiply, FLOAT_matrix_multiply, DOUBLE_matrix_multiply }; static void *matrix_multiply_data[] = { (void *)NULL, (void *)NULL, (void *)NULL }; -static char matrix_multiply_signatures[] = { NPY_LONG, NPY_LONG, NPY_LONG, NPY_FLOAT, NPY_FLOAT, NPY_FLOAT, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE }; -static PyUFuncGenericFunction cross1d_functions[] = { LONG_cross1d, DOUBLE_cross1d }; +static char matrix_multiply_signatures[] = { NPY_INTP, NPY_INTP, NPY_INTP, NPY_FLOAT, NPY_FLOAT, NPY_FLOAT, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE }; +static PyUFuncGenericFunction cross1d_functions[] = { INTP_cross1d, DOUBLE_cross1d }; static void *cross1d_data[] = { (void *)NULL, (void *)NULL }; -static char cross1d_signatures[] = { NPY_LONG, NPY_LONG, NPY_LONG, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE }; +static char cross1d_signatures[] = { NPY_INTP, NPY_INTP, NPY_INTP, NPY_DOUBLE, NPY_DOUBLE, NPY_DOUBLE }; static PyUFuncGenericFunction euclidean_pdist_functions[] = { FLOAT_euclidean_pdist, DOUBLE_euclidean_pdist }; static void *eucldiean_pdist_data[] = { (void *)NULL, (void *)NULL }; static char euclidean_pdist_signatures[] = { NPY_FLOAT, NPY_FLOAT, NPY_DOUBLE, NPY_DOUBLE }; -static PyUFuncGenericFunction cumsum_functions[] = { LONG_cumsum, DOUBLE_cumsum }; +static PyUFuncGenericFunction cumsum_functions[] = { INTP_cumsum, DOUBLE_cumsum }; static void *cumsum_data[] = { (void *)NULL, (void *)NULL }; -static char cumsum_signatures[] = { NPY_LONG, NPY_LONG, NPY_DOUBLE, NPY_DOUBLE }; +static char cumsum_signatures[] = { NPY_INTP, NPY_INTP, NPY_DOUBLE, NPY_DOUBLE }; static int From 4e80df95c0a84e46cc9fba7a0d62cc75dc217d42 Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Thu, 20 Jul 2023 19:49:43 +0200 Subject: [PATCH 11/30] API: rewire/rename np.int_ and np.uint scalars and add np.long/np.ulong Some tests will be failing and docs will need update probably. --- numpy/__init__.py | 10 ++++------ numpy/core/_add_newdocs_scalars.py | 8 ++++++-- numpy/core/_type_aliases.py | 15 +++++---------- numpy/core/src/multiarray/arraytypes.h.src | 4 ++-- numpy/core/tests/test_deprecations.py | 2 +- numpy/core/tests/test_numerictypes.py | 22 +++++++++------------- numpy/core/tests/test_scalarbuffer.py | 4 ++-- 7 files changed, 29 insertions(+), 36 deletions(-) diff --git a/numpy/__init__.py b/numpy/__init__.py index efdeb6f36e9a..37493211535d 100644 --- a/numpy/__init__.py +++ b/numpy/__init__.py @@ -211,7 +211,7 @@ # probably wait for NumPy 1.26 or 2.0. # When defined, these should possibly not be added to `__all__` to avoid # import with `from numpy import *`. - __future_scalars__ = {"bool", "long", "ulong", "str", "bytes", "object"} + __future_scalars__ = {"bool", "str", "bytes", "object"} __deprecated_attrs__.update({ n: (alias, _msg.format(n=n, an=an)) for n, alias, an in _type_info}) @@ -239,11 +239,9 @@ # both `numpy.core.issubdtype` and `numpy.lib.issubdtype`. __all__.remove('issubdtype') - # These are exported by np.core, but are replaced by the builtins below - # remove them to ensure that we don't end up with `np.long == np.int_`, - # which would be a breaking change. - del long, unicode - __all__.remove('long') + # This is exported by np.core, but is not exported as it used to be the + # builtin unicode version. + del unicode __all__.remove('unicode') # Remove things that are in the numpy.lib but not in the numpy namespace diff --git a/numpy/core/_add_newdocs_scalars.py b/numpy/core/_add_newdocs_scalars.py index b505e9b268c9..42a5ca36ee9c 100644 --- a/numpy/core/_add_newdocs_scalars.py +++ b/numpy/core/_add_newdocs_scalars.py @@ -120,9 +120,12 @@ def add_newdoc_for_scalar_type(obj, fixed_aliases, doc): Signed integer type, compatible with C ``int``. """) +# TODO: These docs probably need an if to highlight the default rather than +# the C-types (and be correct). add_newdoc_for_scalar_type('int_', [], """ - Signed integer type, compatible with Python `int` and C ``long``. + Default signed integer type, 64bit on 64bit systems and 32bit on 32bit + systems. """) add_newdoc_for_scalar_type('longlong', [], @@ -147,7 +150,8 @@ def add_newdoc_for_scalar_type(obj, fixed_aliases, doc): add_newdoc_for_scalar_type('uint', [], """ - Unsigned integer type, compatible with C ``unsigned long``. + Unsigned signed integer type, 64bit on 64bit systems and 32bit on 32bit + systems. """) add_newdoc_for_scalar_type('ulonglong', [], diff --git a/numpy/core/_type_aliases.py b/numpy/core/_type_aliases.py index cef5b1d81562..83420f0195d6 100644 --- a/numpy/core/_type_aliases.py +++ b/numpy/core/_type_aliases.py @@ -155,8 +155,11 @@ def _set_up_aliases(): ('float_', 'double'), ('intc', 'int'), ('uintc', 'uint'), - ('int_', 'long'), - ('uint', 'ulong'), + ('long', 'long'), + ('ulong', 'ulong'), + # Default integer is a misnomer + ('int_', 'intp'), + ('uint', 'uintp'), ('cfloat', 'cdouble'), ('longfloat', 'longdouble'), ('clongfloat', 'clongdouble'), @@ -182,14 +185,6 @@ def _set_up_aliases(): except KeyError: pass - # Additional aliases in sctypeDict that should not be exposed as attributes - attrs_to_remove = ['ulong'] - - for t in attrs_to_remove: - try: - del allTypes[t] - except KeyError: - pass _set_up_aliases() diff --git a/numpy/core/src/multiarray/arraytypes.h.src b/numpy/core/src/multiarray/arraytypes.h.src index 90a075dad4f7..7a9590205ff2 100644 --- a/numpy/core/src/multiarray/arraytypes.h.src +++ b/numpy/core/src/multiarray/arraytypes.h.src @@ -123,8 +123,8 @@ NPY_CPU_DISPATCH_DECLARE(NPY_NO_EXPORT int BOOL_argmax, * #NAME = BYTE, SHORT, INT, LONG, LONGLONG, * UBYTE, USHORT, UINT, ULONG, ULONGLONG# * #CNAME = (BYTE, SHORT, INT, LONG, LONGLONG)*2# - * #cname = byte, short, intc, int_, longlong, - * ubyte, ushort, uintc, uint, ulonglong# + * #cname = byte, short, intc, long, longlong, + * ubyte, ushort, uintc, ulong, ulonglong# * #CName = Byte, Short, Int, Long, LongLong, * UByte, UShort, UInt, ULong, ULongLong# * #bitname = int*5, uint*5# diff --git a/numpy/core/tests/test_deprecations.py b/numpy/core/tests/test_deprecations.py index 3f1d3e3c1ca5..521eee6acf44 100644 --- a/numpy/core/tests/test_deprecations.py +++ b/numpy/core/tests/test_deprecations.py @@ -710,7 +710,7 @@ def test_type_aliases(self): @pytest.mark.parametrize("name", - ["bool", "long", "ulong", "str", "bytes", "object"]) + ["bool", "str", "bytes", "object"]) def test_future_scalar_attributes(name): # FutureWarning added 2022-11-17, NumPy 1.24, assert name not in dir(np) # we may want to not add them diff --git a/numpy/core/tests/test_numerictypes.py b/numpy/core/tests/test_numerictypes.py index bab5bf246664..c0a51c29ec5d 100644 --- a/numpy/core/tests/test_numerictypes.py +++ b/numpy/core/tests/test_numerictypes.py @@ -444,13 +444,9 @@ def test_longdouble(self): assert_(np.sctypeDict['c16'] is not np.clongdouble) def test_ulong(self): - # Test that 'ulong' behaves like 'long'. np.sctypeDict['long'] is an - # alias for np.int_, but np.long is not supported for historical - # reasons (gh-21063) - assert_(np.sctypeDict['ulong'] is np.uint) - with pytest.warns(FutureWarning): - # We will probably allow this in the future: - assert not hasattr(np, 'ulong') + assert np.sctypeDict['ulong'] is np.ulong + assert np.dtype(np.ulong) is np.dtype("ulong") + assert np.dtype(np.ulong).itemsize == np.dtype(np.long).itemsize class TestBitName: def test_abstract(self): @@ -545,19 +541,19 @@ class TestScalarTypeNames: # gh-9799 numeric_types = [ - np.byte, np.short, np.intc, np.int_, np.longlong, - np.ubyte, np.ushort, np.uintc, np.uint, np.ulonglong, + np.byte, np.short, np.intc, np.int_, np.long, np.longlong, + np.ubyte, np.ushort, np.uintc, np.uint, np.ulong, np.ulonglong, np.half, np.single, np.double, np.longdouble, np.csingle, np.cdouble, np.clongdouble, ] def test_names_are_unique(self): - # none of the above may be aliases for each other - assert len(set(self.numeric_types)) == len(self.numeric_types) + # exactly np.int and np.uint will cause a duplicate in the above + assert len(set(self.numeric_types)) == len(self.numeric_types) - 2 - # names must be unique + # names must be unique except those two names = [t.__name__ for t in self.numeric_types] - assert len(set(names)) == len(names) + assert len(set(names)) == len(names) - 2 @pytest.mark.parametrize('t', numeric_types) def test_names_reflect_attributes(self, t): diff --git a/numpy/core/tests/test_scalarbuffer.py b/numpy/core/tests/test_scalarbuffer.py index 31b0494cf00b..c7fb1308df7e 100644 --- a/numpy/core/tests/test_scalarbuffer.py +++ b/numpy/core/tests/test_scalarbuffer.py @@ -14,12 +14,12 @@ (np.byte, 'b'), (np.short, 'h'), (np.intc, 'i'), - (np.int_, 'l'), + (np.long, 'l'), (np.longlong, 'q'), (np.ubyte, 'B'), (np.ushort, 'H'), (np.uintc, 'I'), - (np.uint, 'L'), + (np.ulong, 'L'), (np.ulonglong, 'Q'), (np.half, 'e'), (np.single, 'f'), From 716ca6a85a1545796da3def2f855b975baa22281 Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Fri, 21 Jul 2023 07:32:38 +0200 Subject: [PATCH 12/30] BUG: Fix (probably) legacy binomial and use `np.long` in random --- numpy/random/mtrand.pyx | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/numpy/random/mtrand.pyx b/numpy/random/mtrand.pyx index 04c68eae9de0..c3f6ef15c0ba 100644 --- a/numpy/random/mtrand.pyx +++ b/numpy/random/mtrand.pyx @@ -622,7 +622,7 @@ cdef class RandomState: tomaxint(size=None) Return a sample of uniformly distributed random integers in the interval - [0, ``np.iinfo("long"").max``]. + [0, ``np.iinfo("long").max``]. .. warning:: This function users the C-long dtype, which is 32bit on windows @@ -680,9 +680,9 @@ cdef class RandomState: randoms_data[i] = random_positive_int(&self._bitgen) return randoms - def randint(self, low, high=None, size=None, dtype="long"): + def randint(self, low, high=None, size=None, dtype=np.long): """ - randint(low, high=None, size=None, dtype="long") + randint(low, high=None, size=None, dtype=np.long) Return random integers from `low` (inclusive) to `high` (exclusive). @@ -711,7 +711,7 @@ cdef class RandomState: single value is returned. dtype : dtype, optional Desired dtype of the result. Byteorder must be native. - The default value is "long". + The default value is long. .. versionadded:: 1.11.0 @@ -1010,7 +1010,7 @@ cdef class RandomState: idx = cdf.searchsorted(uniform_samples, side='right') # searchsorted returns a scalar # force cast to int for LLP64 - idx = np.array(idx, copy=False).astype("long", casting='unsafe') + idx = np.array(idx, copy=False).astype(np.long, casting='unsafe') else: idx = self.randint(0, pop_size, size=shape) else: @@ -1025,7 +1025,7 @@ cdef class RandomState: raise ValueError("Fewer non-zero entries in p than size") n_uniq = 0 p = p.copy() - found = np.zeros(shape, dtype="long") + found = np.zeros(shape, dtype=np.long) flat_found = found.ravel() while n_uniq < size: x = self.rand(size - n_uniq) @@ -3477,10 +3477,10 @@ cdef class RandomState: check_array_constraint(p_arr, 'p', CONS_BOUNDED_0_1) check_array_constraint(n_arr, 'n', CONS_NON_NEGATIVE) if size is not None: - randoms = np.empty(size, int) + randoms = np.empty(size, np.long) else: it = np.PyArray_MultiIterNew2(p_arr, n_arr) - randoms = np.empty(it.shape, int) + randoms = np.empty(it.shape, np.long) cnt = np.PyArray_SIZE(randoms) @@ -3508,7 +3508,7 @@ cdef class RandomState: return legacy_random_binomial(&self._bitgen, _dp, _in, &self._binomial) - randoms = np.empty(size, "long") + randoms = np.empty(size, np.long) cnt = np.PyArray_SIZE(randoms) randoms_data = np.PyArray_DATA(randoms) @@ -4405,7 +4405,7 @@ cdef class RandomState: shape = (operator.index(size), d) except: shape = tuple(size) + (d,) - multin = np.zeros(shape, dtype="long") + multin = np.zeros(shape, dtype=np.long) mnarr = multin mnix = np.PyArray_DATA(mnarr) sz = np.PyArray_SIZE(mnarr) From 1aac477971a23e58f68ebe57f5456d67da689dec Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Fri, 21 Jul 2023 07:38:43 +0200 Subject: [PATCH 13/30] TST: Adapt some tests to ensure long use and test default int a bit --- numpy/core/tests/test_numerictypes.py | 3 ++- numpy/core/tests/test_ufunc.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/numpy/core/tests/test_numerictypes.py b/numpy/core/tests/test_numerictypes.py index c0a51c29ec5d..e98ba451bcea 100644 --- a/numpy/core/tests/test_numerictypes.py +++ b/numpy/core/tests/test_numerictypes.py @@ -486,7 +486,8 @@ class Test_sctype2char: def test_scalar_type(self): assert_equal(np.sctype2char(np.double), 'd') - assert_equal(np.sctype2char(np.int_), 'l') + assert_equal(np.sctype2char(np.long), 'l') + assert_equal(np.sctype2char(np.int_), np.array(0).dtype.char) assert_equal(np.sctype2char(np.str_), 'U') assert_equal(np.sctype2char(np.bytes_), 'S') diff --git a/numpy/core/tests/test_ufunc.py b/numpy/core/tests/test_ufunc.py index 99390e48c3db..cb0bf3e570b2 100644 --- a/numpy/core/tests/test_ufunc.py +++ b/numpy/core/tests/test_ufunc.py @@ -1893,7 +1893,7 @@ def test_operand_flags(self): assert_equal(a, np.array([[0, 2, 4, 3], [7, 9, 11, 7], [14, 16, 18, 11], [12, 13, 14, 15]], dtype='l')) - a = np.array(0) + a = np.array(0, dtype="l") opflag_tests.inplace_add(a, 3) assert_equal(a, 3) opflag_tests.inplace_add(a, [3, 4]) From d169c41545b91cf4c400e2319b31630c0d5ff1bf Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Fri, 21 Jul 2023 07:42:48 +0200 Subject: [PATCH 14/30] TST: Fix ufunc type resolution test for long (and a bit more) --- numpy/core/tests/test_ufunc.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/numpy/core/tests/test_ufunc.py b/numpy/core/tests/test_ufunc.py index cb0bf3e570b2..bf0d63c8e4f8 100644 --- a/numpy/core/tests/test_ufunc.py +++ b/numpy/core/tests/test_ufunc.py @@ -2890,8 +2890,16 @@ def test_weird_dtypes(self): np.equal.resolve_dtypes((dts, dts, None)) def test_resolve_dtypes_reduction(self): + i2 = np.dtype("i2") + default_int_ = np.dtype(np.int_) + # Check special addition resolution: + res = np.add.resolve_dtypes((None, i2, None), reduction=True) + assert res == (default_int_, default_int_, default_int_) + + def test_resolve_dtypes_reduction_no_output(self): i4 = np.dtype("i4") - with pytest.raises(NotImplementedError): + with pytest.raises(TypeError): + # May be allowable at some point? np.add.resolve_dtypes((i4, i4, i4), reduction=True) @pytest.mark.parametrize("dtypes", [ @@ -2903,13 +2911,6 @@ def test_resolve_dtypes_errors(self, dtypes): with pytest.raises(TypeError): np.add.resolve_dtypes(dtypes) - def test_resolve_dtypes_reduction(self): - i2 = np.dtype("i2") - long_ = np.dtype("long") - # Check special addition resolution: - res = np.add.resolve_dtypes((None, i2, None), reduction=True) - assert res == (long_, long_, long_) - def test_resolve_dtypes_reduction_errors(self): i2 = np.dtype("i2") From 654d8457f064bf91a08707a0b85fec6f3b5a8b19 Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Fri, 21 Jul 2023 08:57:01 +0200 Subject: [PATCH 15/30] TST: Fix legacy random test hashes to toggle on long (not default int) --- numpy/random/tests/test_randomstate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/numpy/random/tests/test_randomstate.py b/numpy/random/tests/test_randomstate.py index 3099853d2a8e..07323f0ddbf7 100644 --- a/numpy/random/tests/test_randomstate.py +++ b/numpy/random/tests/test_randomstate.py @@ -24,7 +24,7 @@ 'zipf': (2,), } -if np.iinfo(int).max < 2**32: +if np.iinfo(np.long).max < 2**32: # Windows and some 32-bit platforms, e.g., ARM INT_FUNC_HASHES = {'binomial': '2fbead005fc63942decb5326d36a1f32fe2c9d32c904ee61e46866b88447c263', 'logseries': '23ead5dcde35d4cfd4ef2c105e4c3d43304b45dc1b1444b7823b9ee4fa144ebb', From 2c5e3ad418f76beca9c332e0f1af4ba4e6c05ab7 Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Fri, 21 Jul 2023 08:59:35 +0200 Subject: [PATCH 16/30] TST: Remove duplicated test that needed adaption for default int change --- numpy/core/tests/test_dtype.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/numpy/core/tests/test_dtype.py b/numpy/core/tests/test_dtype.py index 2db170d09c4e..49982e76eed6 100644 --- a/numpy/core/tests/test_dtype.py +++ b/numpy/core/tests/test_dtype.py @@ -1524,11 +1524,6 @@ def test_keyword_argument(): assert np.dtype(dtype=np.float64) == np.dtype(np.float64) -def test_ulong_dtype(): - # test for gh-21063 - assert np.dtype("ulong") == np.dtype(np.uint) - - class TestFromDTypeAttribute: def test_simple(self): class dt: From 17f2dd6ca71ca0be3fd1d908ba0122b285829253 Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Fri, 21 Jul 2023 09:04:07 +0200 Subject: [PATCH 17/30] TST: Fix inplace_add ufunc test by using intp/default int Otherwise, fixing the rest of the test seems actually more annoying. --- numpy/core/src/umath/_operand_flag_tests.c | 4 ++-- numpy/core/tests/test_ufunc.py | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/numpy/core/src/umath/_operand_flag_tests.c b/numpy/core/src/umath/_operand_flag_tests.c index c59e13baf6b1..a674dfa560b7 100644 --- a/numpy/core/src/umath/_operand_flag_tests.c +++ b/numpy/core/src/umath/_operand_flag_tests.c @@ -25,7 +25,7 @@ inplace_add(char **args, npy_intp const *dimensions, npy_intp const *steps, void npy_intp in2_step = steps[1]; for (i = 0; i < n; i++) { - (*(long *)in1) = *(long*)in1 + *(long*)in2; + (*(npy_intp *)in1) = *(npy_intp*)in1 + *(npy_intp*)in2; in1 += in1_step; in2 += in2_step; } @@ -36,7 +36,7 @@ inplace_add(char **args, npy_intp const *dimensions, npy_intp const *steps, void PyUFuncGenericFunction funcs[1] = {&inplace_add}; /* These are the input and return dtypes of logit.*/ -static char types[2] = {NPY_LONG, NPY_LONG}; +static char types[2] = {NPY_INTP, NPY_INTP}; static void *data[1] = {NULL}; diff --git a/numpy/core/tests/test_ufunc.py b/numpy/core/tests/test_ufunc.py index bf0d63c8e4f8..fe85d6cfb9a2 100644 --- a/numpy/core/tests/test_ufunc.py +++ b/numpy/core/tests/test_ufunc.py @@ -1887,13 +1887,13 @@ def test_ufunc_custom_out(self): _rational_tests.test_add(a, np.uint16(2)) def test_operand_flags(self): - a = np.arange(16, dtype='l').reshape(4, 4) - b = np.arange(9, dtype='l').reshape(3, 3) + a = np.arange(16, dtype=int).reshape(4, 4) + b = np.arange(9, dtype=int).reshape(3, 3) opflag_tests.inplace_add(a[:-1, :-1], b) assert_equal(a, np.array([[0, 2, 4, 3], [7, 9, 11, 7], - [14, 16, 18, 11], [12, 13, 14, 15]], dtype='l')) + [14, 16, 18, 11], [12, 13, 14, 15]])) - a = np.array(0, dtype="l") + a = np.array(0) opflag_tests.inplace_add(a, 3) assert_equal(a, 3) opflag_tests.inplace_add(a, [3, 4]) From 88059324ced02a0639cbf55ab644a3150f88f23b Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Fri, 21 Jul 2023 09:32:07 +0200 Subject: [PATCH 18/30] TST: Adjust random test for long (not default int) return and branching --- numpy/random/tests/test_randomstate.py | 2 +- numpy/random/tests/test_randomstate_regression.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/numpy/random/tests/test_randomstate.py b/numpy/random/tests/test_randomstate.py index 07323f0ddbf7..04de539e94dc 100644 --- a/numpy/random/tests/test_randomstate.py +++ b/numpy/random/tests/test_randomstate.py @@ -495,7 +495,7 @@ def test_tomaxint(self): random.seed(self.seed) rs = random.RandomState(self.seed) actual = rs.tomaxint(size=(3, 2)) - if np.iinfo(int).max == 2147483647: + if np.iinfo(np.long).max == 2147483647: desired = np.array([[1328851649, 731237375], [1270502067, 320041495], [1908433478, 499156889]], dtype=np.int64) diff --git a/numpy/random/tests/test_randomstate_regression.py b/numpy/random/tests/test_randomstate_regression.py index 7ad19ab5562b..6e55cf5f1f29 100644 --- a/numpy/random/tests/test_randomstate_regression.py +++ b/numpy/random/tests/test_randomstate_regression.py @@ -165,15 +165,15 @@ def test_named_argument_initialization(self): assert rs1.randint(0, 100) == rs2.randint(0, 100) def test_choice_retun_dtype(self): - # GH 9867 + # GH 9867, now long since the NumPy default changed. c = np.random.choice(10, p=[.1]*10, size=2) - assert c.dtype == np.dtype(int) + assert c.dtype == np.dtype(np.long) c = np.random.choice(10, p=[.1]*10, replace=False, size=2) - assert c.dtype == np.dtype(int) + assert c.dtype == np.dtype(np.long) c = np.random.choice(10, size=2) - assert c.dtype == np.dtype(int) + assert c.dtype == np.dtype(np.long) c = np.random.choice(10, replace=False, size=2) - assert c.dtype == np.dtype(int) + assert c.dtype == np.dtype(np.long) @pytest.mark.skipif(np.iinfo('l').max < 2**32, reason='Cannot test with 32-bit C long') From 2ea12e9ef8b7b4f96a013e60ca03d0670cd295c0 Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Fri, 21 Jul 2023 09:32:49 +0200 Subject: [PATCH 19/30] Use intp in np.random.binomial for inputs (core uses int64 always) This is just minimal, really should use int64, but this is the legacy API anyway. --- numpy/random/mtrand.pyx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/numpy/random/mtrand.pyx b/numpy/random/mtrand.pyx index c3f6ef15c0ba..6b6711db2cf0 100644 --- a/numpy/random/mtrand.pyx +++ b/numpy/random/mtrand.pyx @@ -3461,7 +3461,7 @@ cdef class RandomState: # Uses a custom implementation since self._binomial is required cdef double _dp = 0 - cdef long _in = 0 + cdef np.npy_intp _in = 0 cdef bint is_scalar = True cdef np.npy_intp i, cnt cdef np.ndarray randoms @@ -3470,7 +3470,7 @@ cdef class RandomState: p_arr = np.PyArray_FROM_OTF(p, np.NPY_DOUBLE, np.NPY_ALIGNED) is_scalar = is_scalar and np.PyArray_NDIM(p_arr) == 0 - n_arr = np.PyArray_FROM_OTF(n, np.NPY_LONG, np.NPY_ALIGNED) + n_arr = np.PyArray_FROM_OTF(n, np.NPY_INTP, np.NPY_ALIGNED) is_scalar = is_scalar and np.PyArray_NDIM(n_arr) == 0 if not is_scalar: @@ -3489,7 +3489,7 @@ cdef class RandomState: with self.lock, nogil: for i in range(cnt): _dp = (np.PyArray_MultiIter_DATA(it, 1))[0] - _in = (np.PyArray_MultiIter_DATA(it, 2))[0] + _in = (np.PyArray_MultiIter_DATA(it, 2))[0] (np.PyArray_MultiIter_DATA(it, 0))[0] = \ legacy_random_binomial(&self._bitgen, _dp, _in, &self._binomial) From d09d661e728dd613fdeec93b6ecd722d636e358f Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Fri, 21 Jul 2023 10:10:20 +0200 Subject: [PATCH 20/30] BUG: Fix previously unused int64/uint64 in umath generation for cross compile (emscriptn CI was failing due to this) --- numpy/core/code_generators/generate_umath.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/numpy/core/code_generators/generate_umath.py b/numpy/core/code_generators/generate_umath.py index 463d07d3accc..f583a5135d8c 100644 --- a/numpy/core/code_generators/generate_umath.py +++ b/numpy/core/code_generators/generate_umath.py @@ -94,7 +94,8 @@ def finish_signature(self, nin, nout): def _check_order(types1, types2): - dtype_order = allP + "O" + # Insert kK (int64) after all other ints (assumes long long isn't larger) + dtype_order = bints + 'kK' + times + flts + cmplxP + "O" for t1, t2 in zip(types1, types2): # We have no opinion on object or time ordering for now: if t1 in "OP" or t2 in "OP": @@ -275,6 +276,10 @@ def english_upper(s): 'I': 'uint', 'l': 'long', 'L': 'ulong', + # We sometimes need int64, but we have no obvious char for it, use k and + # define it as `int64` below. + 'k': 'int64', + 'K': 'uint64', 'q': 'longlong', 'Q': 'ulonglong', 'e': 'half', @@ -330,13 +335,8 @@ def english_upper(s): no_bool_times_obj = ints + inexact # Find which code corresponds to int64. -int64 = '' -uint64 = '' -for code in 'bhilq': - if struct.calcsize(code) == 8: - int64 = code - uint64 = english_upper(code) - break +int64 = 'k' +uint64 = 'K' # This dictionary describes all the ufunc implementations, generating # all the function names and their corresponding ufunc signatures. TD is From d998d40c6fca0c59bc74827321a30cac1c83cae8 Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Fri, 21 Jul 2023 10:49:05 +0200 Subject: [PATCH 21/30] BUG: Another random path that should probably keep using long (Might be good to have more tests, seemed mainly tested indirectly via `choice` tests.) --- numpy/random/mtrand.pyx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/numpy/random/mtrand.pyx b/numpy/random/mtrand.pyx index 6b6711db2cf0..04954e636942 100644 --- a/numpy/random/mtrand.pyx +++ b/numpy/random/mtrand.pyx @@ -4743,7 +4743,8 @@ cdef class RandomState: """ if isinstance(x, (int, np.integer)): - arr = np.arange(x) + # keep using long as the default here (main numpy switched to intp) + arr = np.arange(x, dtype=np.result_type(x, np.long)) self.shuffle(arr) return arr From 9be0cbea5ccbbded68cd2a2fbcf93a52c17eaaaa Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Fri, 21 Jul 2023 11:05:26 +0200 Subject: [PATCH 22/30] TST: One more small test fixup for changed default dtype --- numpy/core/tests/test_multiarray.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py index a7c89aa4380d..bbc54e7ab526 100644 --- a/numpy/core/tests/test_multiarray.py +++ b/numpy/core/tests/test_multiarray.py @@ -312,7 +312,8 @@ def test_attributes(self): def test_dtypeattr(self): assert_equal(self.one.dtype, np.dtype(np.int_)) assert_equal(self.three.dtype, np.dtype(np.float_)) - assert_equal(self.one.dtype.char, 'l') + assert_equal(self.one.dtype.char, np.dtype(int).char) + assert self.one.dtype.char in "lq" assert_equal(self.three.dtype.char, 'd') assert_(self.three.dtype.str[0] in '<>') assert_equal(self.one.dtype.str[1], 'i') From a545a9a5efa7b4892ddd0d12e48c7e0604ca0bf6 Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Fri, 21 Jul 2023 11:57:47 +0200 Subject: [PATCH 23/30] BUG,API: like int32, intp must map to long if long and int are same size Otherwise things get confusing, the default integer must be long after all if long and int are the same size. --- numpy/core/include/numpy/npy_common.h | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/numpy/core/include/numpy/npy_common.h b/numpy/core/include/numpy/npy_common.h index fb976aa6ae09..74c2101d9010 100644 --- a/numpy/core/include/numpy/npy_common.h +++ b/numpy/core/include/numpy/npy_common.h @@ -225,16 +225,7 @@ typedef Py_uintptr_t npy_uintp; * functions use different formatting codes that are portably specified * according to the Python documentation. See issue gh-2388. */ -#if NPY_SIZEOF_PY_INTPTR_T == NPY_SIZEOF_INT - #define NPY_INTP NPY_INT - #define NPY_UINTP NPY_UINT - #define PyIntpArrType_Type PyIntArrType_Type - #define PyUIntpArrType_Type PyUIntArrType_Type - #define NPY_MAX_INTP NPY_MAX_INT - #define NPY_MIN_INTP NPY_MIN_INT - #define NPY_MAX_UINTP NPY_MAX_UINT - #define NPY_INTP_FMT "d" -#elif NPY_SIZEOF_PY_INTPTR_T == NPY_SIZEOF_LONG +#if NPY_SIZEOF_PY_INTPTR_T == NPY_SIZEOF_LONG #define NPY_INTP NPY_LONG #define NPY_UINTP NPY_ULONG #define PyIntpArrType_Type PyLongArrType_Type @@ -243,6 +234,16 @@ typedef Py_uintptr_t npy_uintp; #define NPY_MIN_INTP NPY_MIN_LONG #define NPY_MAX_UINTP NPY_MAX_ULONG #define NPY_INTP_FMT "ld" +#elif NPY_SIZEOF_PY_INTPTR_T == NPY_SIZEOF_INT + /* NumPy always prefers long over int if the size is identical! */ + #define NPY_INTP NPY_INT + #define NPY_UINTP NPY_UINT + #define PyIntpArrType_Type PyIntArrType_Type + #define PyUIntpArrType_Type PyUIntArrType_Type + #define NPY_MAX_INTP NPY_MAX_INT + #define NPY_MIN_INTP NPY_MIN_INT + #define NPY_MAX_UINTP NPY_MAX_UINT + #define NPY_INTP_FMT "d" #elif defined(PY_LONG_LONG) && (NPY_SIZEOF_PY_INTPTR_T == NPY_SIZEOF_LONGLONG) #define NPY_INTP NPY_LONGLONG #define NPY_UINTP NPY_ULONGLONG From 779f021ed945fa9ca9834e3ac7bf6b12b02e9cd3 Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Fri, 21 Jul 2023 16:37:10 +0200 Subject: [PATCH 24/30] MAINT: Fix hypergeometric to use INT64, but raise if values surpass long Also does this for bernoulli, its a mixed bag, many legacy ones use the `disc()` which just force-casts from int64 to long anyway... --- numpy/random/mtrand.pyx | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/numpy/random/mtrand.pyx b/numpy/random/mtrand.pyx index 04954e636942..b121d454f5a5 100644 --- a/numpy/random/mtrand.pyx +++ b/numpy/random/mtrand.pyx @@ -26,6 +26,9 @@ from ._common cimport (POISSON_LAM_MAX, CONS_POSITIVE, CONS_NONE, validate_output_shape ) +cdef extern from "limits.h": + cdef long LONG_MAX # NumPy has it, maybe `__init__.pyd` should expose it + cdef extern from "numpy/random/distributions.h": struct s_binomial_t: int has_binomial @@ -3490,6 +3493,10 @@ cdef class RandomState: for i in range(cnt): _dp = (np.PyArray_MultiIter_DATA(it, 1))[0] _in = (np.PyArray_MultiIter_DATA(it, 2))[0] + if _in > LONG_MAX: + raise ValueError( + "`n` is out of bounds for long, consider using " + "the new generator API for 64bit integers.") (np.PyArray_MultiIter_DATA(it, 0))[0] = \ legacy_random_binomial(&self._bitgen, _dp, _in, &self._binomial) @@ -3499,9 +3506,13 @@ cdef class RandomState: return randoms _dp = PyFloat_AsDouble(p) - _in = n + _in = n check_constraint(_dp, 'p', CONS_BOUNDED_0_1) check_constraint(_in, 'n', CONS_NON_NEGATIVE) + if _in > LONG_MAX: + raise ValueError( + "`n` is out of bounds for long, consider using " + "the new generator API for 64bit integers.") if size is None: with self.lock: @@ -3957,15 +3968,18 @@ cdef class RandomState: cdef int64_t lngood, lnbad, lnsample # This cast to long is required to ensure that the values are inbounds - ongood = np.PyArray_FROM_OTF(ngood, np.NPY_LONG, np.NPY_ALIGNED) - onbad = np.PyArray_FROM_OTF(nbad, np.NPY_LONG, np.NPY_ALIGNED) - onsample = np.PyArray_FROM_OTF(nsample, np.NPY_LONG, np.NPY_ALIGNED) + ongood = np.PyArray_FROM_OTF(ngood, np.NPY_INT64, np.NPY_ALIGNED) + onbad = np.PyArray_FROM_OTF(nbad, np.NPY_INT64, np.NPY_ALIGNED) + onsample = np.PyArray_FROM_OTF(nsample, np.NPY_INT64, np.NPY_ALIGNED) if np.PyArray_NDIM(ongood) == np.PyArray_NDIM(onbad) == np.PyArray_NDIM(onsample) == 0: - lngood = ngood lnbad = nbad lnsample = nsample + if lnsample > LONG_MAX: + raise ValueError( + "`nsample` is out of bounds for long, consider using " + "the new generator API for 64bit integers.") if lngood + lnbad < lnsample: raise ValueError("ngood + nbad < nsample") @@ -3978,10 +3992,11 @@ cdef class RandomState: if np.any(np.less(np.add(ongood, onbad), onsample)): raise ValueError("ngood + nbad < nsample") - # Convert to int64, if necessary, to use int64 infrastructure - ongood = ongood.astype(np.int64) - onbad = onbad.astype(np.int64) - onsample = onsample.astype(np.int64) + if np.any(onsample > LONG_MAX): + raise ValueError( + "`nsample` is out of bounds for long, consider using " + "the new generator API for 64bit integers.") + out = discrete_broadcast_iii(&legacy_random_hypergeometric,&self._bitgen, size, self.lock, ongood, 'ngood', CONS_NON_NEGATIVE, onbad, 'nbad', CONS_NON_NEGATIVE, From d9a18280d5feee544bf1a11bc9d0908ae0561e4c Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Fri, 21 Jul 2023 20:29:28 +0200 Subject: [PATCH 25/30] Try with py_ssize_t (I am very unclear why float doesn't fail earlier) --- numpy/random/mtrand.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/numpy/random/mtrand.pyx b/numpy/random/mtrand.pyx index b121d454f5a5..5572518ae04a 100644 --- a/numpy/random/mtrand.pyx +++ b/numpy/random/mtrand.pyx @@ -3506,7 +3506,7 @@ cdef class RandomState: return randoms _dp = PyFloat_AsDouble(p) - _in = n + _in = n check_constraint(_dp, 'p', CONS_BOUNDED_0_1) check_constraint(_in, 'n', CONS_NON_NEGATIVE) if _in > LONG_MAX: From d39d7143b370fdeae9ebd0afc50d175c801279c4 Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Fri, 21 Jul 2023 21:50:08 +0200 Subject: [PATCH 26/30] Simply us Python `int()`... --- numpy/random/mtrand.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/numpy/random/mtrand.pyx b/numpy/random/mtrand.pyx index 5572518ae04a..ebced51a5caa 100644 --- a/numpy/random/mtrand.pyx +++ b/numpy/random/mtrand.pyx @@ -3506,7 +3506,7 @@ cdef class RandomState: return randoms _dp = PyFloat_AsDouble(p) - _in = n + _in = int(n) check_constraint(_dp, 'p', CONS_BOUNDED_0_1) check_constraint(_in, 'n', CONS_NON_NEGATIVE) if _in > LONG_MAX: From 63410498717aa8aafe5b35e97b68b245c64cc644 Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Wed, 12 Jul 2023 11:24:31 +0200 Subject: [PATCH 27/30] WIP: Make it so we only have Int8, Int16... and no C version DTypes This retains the python descriptor instances. The main problem with this approach is that it confuses the legacy loop finder, since that searches for exact matches. That can be worked around, by forcing the singleton (which should be fine, only affects execution speed very mildly for metadata probably). That part needs a bit tweaking, otherwise I added a loop using "q" for unsigned int and signed int comparisons. "q" isn't always the canonical name for int64, so that loop cannot be found. --- numpy/core/src/multiarray/arraytypes.c.src | 23 +++++---- numpy/core/src/multiarray/arraytypes.h.src | 49 +++++++++++++------- numpy/core/src/multiarray/convert_datatype.c | 15 ++++++ numpy/core/src/multiarray/datetime.c | 3 ++ numpy/core/src/multiarray/dtypemeta.c | 28 +++++++++-- numpy/core/src/multiarray/dtypemeta.h | 6 ++- numpy/core/src/multiarray/usertypes.c | 2 +- numpy/core/src/umath/ufunc_object.c | 11 ++--- 8 files changed, 97 insertions(+), 40 deletions(-) diff --git a/numpy/core/src/multiarray/arraytypes.c.src b/numpy/core/src/multiarray/arraytypes.c.src index 10cdc1394e7a..be3244453bbd 100644 --- a/numpy/core/src/multiarray/arraytypes.c.src +++ b/numpy/core/src/multiarray/arraytypes.c.src @@ -4608,8 +4608,8 @@ set_typeinfo(PyObject *dict) /**begin repeat * * #NAME = BOOL, - * BYTE, UBYTE, SHORT, USHORT, INT, UINT, - * LONG, ULONG, LONGLONG, ULONGLONG, + * INT8, UINT8, INT16, UINT16, + * INT32, UINT32, INT64, UINT64, * HALF, FLOAT, DOUBLE, LONGDOUBLE, * CFLOAT, CDOUBLE, CLONGDOUBLE, * OBJECT, STRING, UNICODE, VOID, @@ -4617,16 +4617,19 @@ set_typeinfo(PyObject *dict) */ if (dtypemeta_wrap_legacy_descriptor( _builtin_descrs[NPY_@NAME@], - "numpy.dtypes." NPY_@NAME@_Name "DType", -#ifdef NPY_@NAME@_alias - "numpy.dtypes." NPY_@NAME@_Alias "DType" -#else - NULL -#endif - ) < 0) { + "numpy.dtypes." NPY_@NAME@_Name "DType") < 0) { + return -1; + } + /**end repeat**/ + /**begin repeat + * #NAME = BYTE, UBYTE, SHORT, USHORT, INT, UINT, + * LONG, ULONG, LONGLONG, ULONGLONG# + */ + if (make_dtypemeta_integer_alias( + _builtin_descrs[NPY_@NAME@], + NPY_@NAME@, NPY_@NAME@_BASE, NPY_@NAME@_Alias) < 0) { return -1; } - /**end repeat**/ /* diff --git a/numpy/core/src/multiarray/arraytypes.h.src b/numpy/core/src/multiarray/arraytypes.h.src index 7a9590205ff2..3cba0ed72143 100644 --- a/numpy/core/src/multiarray/arraytypes.h.src +++ b/numpy/core/src/multiarray/arraytypes.h.src @@ -73,16 +73,19 @@ NPY_CPU_DISPATCH_DECLARE(NPY_NO_EXPORT int BOOL_argmax, /**begin repeat * #NAME = BOOL, + * INT8, UINT8, INT16, UINT16, INT32, UINT32, INT64, UINT64, * HALF, FLOAT, DOUBLE, LONGDOUBLE, * CFLOAT, CDOUBLE, CLONGDOUBLE, * STRING, UNICODE, VOID, OBJECT, * DATETIME, TIMEDELTA# * #name = bool_, + * int8, uint8, int16, uint16, int32, uint32, int64, uint64, * float16, float32, float64, longdouble, * complex64, complex128, clongdouble, * bytes_, str_, void, object_, * datetime64, timedelta64# * #Name = Bool, + * Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, * Float16, Float32, Float64, LongDouble, * Complex64, Complex128, CLongDouble, * Bytes, Str, Void, Object, @@ -129,32 +132,44 @@ NPY_CPU_DISPATCH_DECLARE(NPY_NO_EXPORT int BOOL_argmax, * UByte, UShort, UInt, ULong, ULongLong# * #bitname = int*5, uint*5# * #BitName = Int*5, UInt*5# + * #BITNAME = INT*5, UINT*5# */ + +/* The bitsof macro includes math, so cannot be stringified */ +#if NPY_BITSOF_@CNAME@ == 8 + #define NPY_@NAME@_BASE NPY_@BITNAME@8 + #define NPY_@NAME@_name "@bitname@8" + #define NPY_@NAME@_Name "@BitName@8" +#elif NPY_BITSOF_@CNAME@ == 16 + #define NPY_@NAME@_BASE NPY_@BITNAME@16 + #define NPY_@NAME@_name "@bitname@16" + #define NPY_@NAME@_Name "@BitName@16" +#elif NPY_BITSOF_@CNAME@ == 32 + #define NPY_@NAME@_BASE NPY_@BITNAME@32 + #define NPY_@NAME@_name "@bitname@32" + #define NPY_@NAME@_Name "@BitName@32" +#elif NPY_BITSOF_@CNAME@ == 64 + #define NPY_@NAME@_BASE NPY_@BITNAME@64 + #define NPY_@NAME@_name "@bitname@64" + #define NPY_@NAME@_Name "@BitName@64" +#else + #error "need to fix integer bit-length name code" +#endif + + #ifdef @CNAME@_not_size_named + /* not the main bit-sized integer, so name is also the C name alias */ + #undef NPY_@NAME@_name + #undef NPY_@NAME@_Name #define NPY_@NAME@_name "@cname@" #define NPY_@NAME@_Name "@CName@" + #define NPY_@NAME@_alias "@cname@" + #define NPY_@NAME@_Alias "@CName@" #else /* The C-name is considered just an alias for these: */ #define NPY_@NAME@_alias "@cname@" #define NPY_@NAME@_Alias "@CName@" - - /* The bitsof macro includes math, so cannot be stringified */ - #if NPY_BITSOF_@CNAME@ == 8 - #define NPY_@NAME@_name "@bitname@8" - #define NPY_@NAME@_Name "@BitName@8" - #elif NPY_BITSOF_@CNAME@ == 16 - #define NPY_@NAME@_name "@bitname@16" - #define NPY_@NAME@_Name "@BitName@16" - #elif NPY_BITSOF_@CNAME@ == 32 - #define NPY_@NAME@_name "@bitname@32" - #define NPY_@NAME@_Name "@BitName@32" - #elif NPY_BITSOF_@CNAME@ == 64 - #define NPY_@NAME@_name "@bitname@64" - #define NPY_@NAME@_Name "@BitName@64" - #else - #error "need to fix integer bit-length name code" - #endif #endif /**end repeat**/ diff --git a/numpy/core/src/multiarray/convert_datatype.c b/numpy/core/src/multiarray/convert_datatype.c index 4311139f2b43..b012256c0eee 100644 --- a/numpy/core/src/multiarray/convert_datatype.c +++ b/numpy/core/src/multiarray/convert_datatype.c @@ -2733,19 +2733,30 @@ PyArray_InitializeNumericCasts(void) continue; } PyArray_DTypeMeta *from_dt = PyArray_DTypeFromTypeNum(from); + if (from_dt->type_num != from) { + Py_DECREF(from_dt); /* This is just an integer alias */ + continue; + } for (int to = 0; to < NPY_NTYPES; to++) { if (!PyTypeNum_ISNUMBER(to) && to != NPY_BOOL) { continue; } PyArray_DTypeMeta *to_dt = PyArray_DTypeFromTypeNum(to); + if (to_dt->type_num != to) { + Py_DECREF(to_dt); /* This is just an integer alias */ + continue; + } + int res = add_numeric_cast(from_dt, to_dt); Py_DECREF(to_dt); if (res < 0) { + printf("failed for %d, %d\n", from, to); Py_DECREF(from_dt); return -1; } } + Py_DECREF(from_dt); } return 0; } @@ -3004,6 +3015,10 @@ PyArray_InitializeStringCasts(void) continue; } other_dt = PyArray_DTypeFromTypeNum(other); + if (other_dt->type_num != other) { + Py_CLEAR(other_dt); + continue; + } /* The functions skip string == other_dt or unicode == other_dt */ if (add_other_to_and_from_string_cast(string, other_dt) < 0) { diff --git a/numpy/core/src/multiarray/datetime.c b/numpy/core/src/multiarray/datetime.c index 9cd67c0971e0..cc389fa577c1 100644 --- a/numpy/core/src/multiarray/datetime.c +++ b/numpy/core/src/multiarray/datetime.c @@ -4166,6 +4166,9 @@ PyArray_InitializeDatetimeCasts() } Py_XSETREF(tmp, PyArray_DTypeFromTypeNum(num)); + if (tmp->type_num != num) { + continue; /* integer type alias */ + } if (PyArray_AddLegacyWrapping_CastingImpl( tmp, datetime, NPY_UNSAFE_CASTING) < 0) { diff --git a/numpy/core/src/multiarray/dtypemeta.c b/numpy/core/src/multiarray/dtypemeta.c index eef8d2f996e6..1147541a08ad 100644 --- a/numpy/core/src/multiarray/dtypemeta.c +++ b/numpy/core/src/multiarray/dtypemeta.c @@ -738,8 +738,7 @@ object_common_dtype( * @returns 0 on success, -1 on failure. */ NPY_NO_EXPORT int -dtypemeta_wrap_legacy_descriptor(PyArray_Descr *descr, - const char *name, const char *alias) +dtypemeta_wrap_legacy_descriptor(PyArray_Descr *descr, const char *name) { int has_type_set = Py_TYPE(descr) == &PyArrayDescr_Type; @@ -913,7 +912,7 @@ dtypemeta_wrap_legacy_descriptor(PyArray_Descr *descr, if (PyObject_CallFunction( add_dtype_helper, - "Os", (PyObject *)dtype_class, alias) == NULL) { + "Os", (PyObject *)dtype_class, NULL) == NULL) { return -1; } } @@ -921,6 +920,29 @@ dtypemeta_wrap_legacy_descriptor(PyArray_Descr *descr, return 0; } +NPY_NO_EXPORT int +make_dtypemeta_integer_alias( + PyArray_Descr *descr, int dtype, int base, char *name) +{ + PyArray_DTypeMeta *dtype_class = PyArray_DTypeFromTypeNum(base); + + Py_SET_TYPE(descr, (PyTypeObject *)dtype_class); + /* And it to the types submodule if it is a builtin dtype */ + static PyObject *add_dtype_helper = NULL; + npy_cache_import("numpy.dtypes", "_add_dtype_helper", &add_dtype_helper); + if (add_dtype_helper == NULL) { + return -1; + } + + /* Sets the name multiple times, but that shouldn't matter. */ + if (PyObject_CallFunction( + add_dtype_helper, + "Os", (PyObject *)dtype_class, name) == NULL) { + return -1; + } + return 0; +} + static PyObject * dtypemeta_get_abstract(PyArray_DTypeMeta *self) { diff --git a/numpy/core/src/multiarray/dtypemeta.h b/numpy/core/src/multiarray/dtypemeta.h index 6c641a3bd138..fe6774d1c59c 100644 --- a/numpy/core/src/multiarray/dtypemeta.h +++ b/numpy/core/src/multiarray/dtypemeta.h @@ -140,7 +140,11 @@ python_builtins_are_known_scalar_types( NPY_NO_EXPORT int dtypemeta_wrap_legacy_descriptor( - PyArray_Descr *dtypem, const char *name, const char *alias); + PyArray_Descr *dtypem, const char *name); + +NPY_NO_EXPORT int +make_dtypemeta_integer_alias( + PyArray_Descr *descr, int dtype, int base, char *name); #ifdef __cplusplus } diff --git a/numpy/core/src/multiarray/usertypes.c b/numpy/core/src/multiarray/usertypes.c index 5e36c914b220..32bce0b0c1be 100644 --- a/numpy/core/src/multiarray/usertypes.c +++ b/numpy/core/src/multiarray/usertypes.c @@ -294,7 +294,7 @@ PyArray_RegisterDataType(PyArray_Descr *descr) userdescrs[NPY_NUMUSERTYPES++] = descr; descr->type_num = typenum; - if (dtypemeta_wrap_legacy_descriptor(descr, name, NULL) < 0) { + if (dtypemeta_wrap_legacy_descriptor(descr, name) < 0) { descr->type_num = -1; NPY_NUMUSERTYPES--; PyMem_Free(name); /* free the name only on failure */ diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c index d234c6449dd0..0314ca762ccc 100644 --- a/numpy/core/src/umath/ufunc_object.c +++ b/numpy/core/src/umath/ufunc_object.c @@ -5812,19 +5812,14 @@ trivial_at_loop(PyArrayMethodObject *ufuncimpl, NPY_ARRAYMETHOD_FLAGS flags, } } + npy_intp *inner_size = NpyIter_GetInnerLoopSizePtr(iter->outer); + if (!(flags & NPY_METH_NO_FLOATINGPOINT_ERRORS)) { npy_clear_floatstatus_barrier((char *)context); } do { - npy_intp *inner_size = NpyIter_GetInnerLoopSizePtr(iter->outer); - npy_intp * indxP = (npy_intp *)iter->outer_ptrs[0]; - for (npy_intp i=0; i < *inner_size; i++) { - if (indxP[i] < 0) { - indxP[i] += iter->fancy_dims[0]; - } - } - args[1] = (char *)indxP; + args[1] = (char *) iter->outer_ptrs[0]; steps[1] = iter->outer_strides[0]; res = ufuncimpl->contiguous_indexed_loop( From 2226994450552faa173d8fb902eaee1340659d72 Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Wed, 12 Jul 2023 11:51:51 +0200 Subject: [PATCH 28/30] WIP: Set up int64 in ufunc generation (requires more updates to loops) --- numpy/core/code_generators/generate_umath.py | 24 ++++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/numpy/core/code_generators/generate_umath.py b/numpy/core/code_generators/generate_umath.py index f583a5135d8c..eaa4b0dd777d 100644 --- a/numpy/core/code_generators/generate_umath.py +++ b/numpy/core/code_generators/generate_umath.py @@ -529,8 +529,8 @@ def english_upper(s): docstrings.get('numpy.core.umath.greater'), 'PyUFunc_SimpleBinaryComparisonTypeResolver', TD(bints, out='?'), - [TypeDescription('q', FullTypeDescr, 'qQ', '?'), - TypeDescription('q', FullTypeDescr, 'Qq', '?')], + [TypeDescription(int64, FullTypeDescr, int64+uint64, '?'), + TypeDescription(int64, FullTypeDescr, uint64+int64, '?')], TD(inexact+times, out='?', dispatch=[('loops_comparison', bints+'fd')]), TD('O', out='?'), [TypeDescription('O', FullTypeDescr, 'OO', 'O')], @@ -540,8 +540,8 @@ def english_upper(s): docstrings.get('numpy.core.umath.greater_equal'), 'PyUFunc_SimpleBinaryComparisonTypeResolver', TD(bints, out='?'), - [TypeDescription('q', FullTypeDescr, 'qQ', '?'), - TypeDescription('q', FullTypeDescr, 'Qq', '?')], + [TypeDescription(int64, FullTypeDescr, int64+uint64, '?'), + TypeDescription(int64, FullTypeDescr, uint64+int64, '?')], TD(inexact+times, out='?', dispatch=[('loops_comparison', bints+'fd')]), TD('O', out='?'), [TypeDescription('O', FullTypeDescr, 'OO', 'O')], @@ -551,8 +551,8 @@ def english_upper(s): docstrings.get('numpy.core.umath.less'), 'PyUFunc_SimpleBinaryComparisonTypeResolver', TD(bints, out='?'), - [TypeDescription('q', FullTypeDescr, 'qQ', '?'), - TypeDescription('q', FullTypeDescr, 'Qq', '?')], + [TypeDescription(int64, FullTypeDescr, int64+uint64, '?'), + TypeDescription(int64, FullTypeDescr, uint64+int64, '?')], TD(inexact+times, out='?', dispatch=[('loops_comparison', bints+'fd')]), TD('O', out='?'), [TypeDescription('O', FullTypeDescr, 'OO', 'O')], @@ -562,8 +562,8 @@ def english_upper(s): docstrings.get('numpy.core.umath.less_equal'), 'PyUFunc_SimpleBinaryComparisonTypeResolver', TD(bints, out='?'), - [TypeDescription('q', FullTypeDescr, 'qQ', '?'), - TypeDescription('q', FullTypeDescr, 'Qq', '?')], + [TypeDescription(int64, FullTypeDescr, int64+uint64, '?'), + TypeDescription(int64, FullTypeDescr, uint64+int64, '?')], TD(inexact+times, out='?', dispatch=[('loops_comparison', bints+'fd')]), TD('O', out='?'), [TypeDescription('O', FullTypeDescr, 'OO', 'O')], @@ -573,8 +573,8 @@ def english_upper(s): docstrings.get('numpy.core.umath.equal'), 'PyUFunc_SimpleBinaryComparisonTypeResolver', TD(bints, out='?'), - [TypeDescription('q', FullTypeDescr, 'qQ', '?'), - TypeDescription('q', FullTypeDescr, 'Qq', '?')], + [TypeDescription(int64, FullTypeDescr, int64+uint64, '?'), + TypeDescription(int64, FullTypeDescr, uint64+int64, '?')], TD(inexact+times, out='?', dispatch=[('loops_comparison', bints+'fd')]), TD('O', out='?'), [TypeDescription('O', FullTypeDescr, 'OO', 'O')], @@ -584,8 +584,8 @@ def english_upper(s): docstrings.get('numpy.core.umath.not_equal'), 'PyUFunc_SimpleBinaryComparisonTypeResolver', TD(bints, out='?'), - [TypeDescription('q', FullTypeDescr, 'qQ', '?'), - TypeDescription('q', FullTypeDescr, 'Qq', '?')], + [TypeDescription(int64, FullTypeDescr, int64+uint64, '?'), + TypeDescription(int64, FullTypeDescr, uint64+int64, '?')], TD(inexact+times, out='?', dispatch=[('loops_comparison', bints+'fd')]), TD('O', out='?'), [TypeDescription('O', FullTypeDescr, 'OO', 'O')], From efb423612d44ba13be251ed722ad1d2f89dabb99 Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Wed, 26 Jul 2023 20:20:17 +0200 Subject: [PATCH 29/30] Fixup datetime loops to use "k" --- numpy/core/code_generators/generate_umath.py | 12 ++++++------ numpy/core/src/umath/loops.c.src | 14 +++++++------- numpy/core/src/umath/loops.h.src | 16 ++++++++-------- numpy/core/src/umath/ufunc_type_resolution.c | 6 +++--- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/numpy/core/code_generators/generate_umath.py b/numpy/core/code_generators/generate_umath.py index eaa4b0dd777d..9b0ef61e17f3 100644 --- a/numpy/core/code_generators/generate_umath.py +++ b/numpy/core/code_generators/generate_umath.py @@ -384,8 +384,8 @@ def english_upper(s): ('loops_arithm_fp', 'fdFD'), ('loops_autovec', ints), ]), - [TypeDescription('m', FullTypeDescr, 'mq', 'm'), - TypeDescription('m', FullTypeDescr, 'qm', 'm'), + [TypeDescription('m', FullTypeDescr, 'mk', 'm'), + TypeDescription('m', FullTypeDescr, 'km', 'm'), TypeDescription('m', FullTypeDescr, 'md', 'm'), TypeDescription('m', FullTypeDescr, 'dm', 'm'), ], @@ -400,9 +400,9 @@ def english_upper(s): TD(ints, cfunc_alias='divide', dispatch=[('loops_arithmetic', 'bBhHiIlLqQ')]), TD(flts), - [TypeDescription('m', FullTypeDescr, 'mq', 'm'), + [TypeDescription('m', FullTypeDescr, 'mk', 'm'), TypeDescription('m', FullTypeDescr, 'md', 'm'), - TypeDescription('m', FullTypeDescr, 'mm', 'q'), + TypeDescription('m', FullTypeDescr, 'mm', 'k'), ], TD(O, f='PyNumber_FloorDivide'), indexed=flts + ints @@ -412,7 +412,7 @@ def english_upper(s): docstrings.get('numpy.core.umath.divide'), 'PyUFunc_TrueDivisionTypeResolver', TD(flts+cmplx, cfunc_alias='divide', dispatch=[('loops_arithm_fp', 'fd')]), - [TypeDescription('m', FullTypeDescr, 'mq', 'm', cfunc_alias='divide'), + [TypeDescription('m', FullTypeDescr, 'mk', 'm', cfunc_alias='divide'), TypeDescription('m', FullTypeDescr, 'md', 'm', cfunc_alias='divide'), TypeDescription('m', FullTypeDescr, 'mm', 'd', cfunc_alias='divide'), ], @@ -1011,7 +1011,7 @@ def english_upper(s): 'PyUFunc_DivmodTypeResolver', TD(ints, dispatch=[('loops_modulo', ints)]), TD(flts), - [TypeDescription('m', FullTypeDescr, 'mm', 'qm')], + [TypeDescription('m', FullTypeDescr, 'mm', 'km')], # TD(O, f='PyNumber_Divmod'), # gh-9730 ), 'hypot': diff --git a/numpy/core/src/umath/loops.c.src b/numpy/core/src/umath/loops.c.src index 4fec1d9fb3a4..dcdec4cdb1d4 100644 --- a/numpy/core/src/umath/loops.c.src +++ b/numpy/core/src/umath/loops.c.src @@ -556,7 +556,7 @@ NPY_NO_EXPORT void * #OP = ==, !=, <, <=, >, >=# */ NPY_NO_EXPORT void -LONGLONG_Qq_bool_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)) +INT64_Kk_bool_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)) { BINARY_LOOP { const npy_ulonglong in1 = *(npy_ulonglong *)ip1; @@ -571,7 +571,7 @@ LONGLONG_Qq_bool_@kind@(char **args, npy_intp const *dimensions, npy_intp const } NPY_NO_EXPORT void -LONGLONG_qQ_bool_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)) +INT64_kK_bool_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)) { BINARY_LOOP { const npy_longlong in1 = *(npy_longlong *)ip1; @@ -841,7 +841,7 @@ TIMEDELTA_mm_m_subtract(char **args, npy_intp const *dimensions, npy_intp const /* Note: Assuming 'q' == NPY_LONGLONG */ NPY_NO_EXPORT void -TIMEDELTA_mq_m_multiply(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)) +TIMEDELTA_mk_m_multiply(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)) { BINARY_LOOP { const npy_timedelta in1 = *(npy_timedelta *)ip1; @@ -857,7 +857,7 @@ TIMEDELTA_mq_m_multiply(char **args, npy_intp const *dimensions, npy_intp const /* Note: Assuming 'q' == NPY_LONGLONG */ NPY_NO_EXPORT void -TIMEDELTA_qm_m_multiply(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)) +TIMEDELTA_km_m_multiply(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)) { BINARY_LOOP { const npy_int64 in1 = *(npy_int64 *)ip1; @@ -915,7 +915,7 @@ TIMEDELTA_dm_m_multiply(char **args, npy_intp const *dimensions, npy_intp const /* Note: Assuming 'q' == NPY_LONGLONG */ NPY_NO_EXPORT void -TIMEDELTA_mq_m_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)) +TIMEDELTA_mk_m_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)) { /* NOTE: This code is similar to array floor divide */ BINARY_DEFS @@ -1028,7 +1028,7 @@ TIMEDELTA_mm_m_remainder(char **args, npy_intp const *dimensions, npy_intp const } NPY_NO_EXPORT void -TIMEDELTA_mm_q_floor_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)) +TIMEDELTA_mm_k_floor_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)) { /* NOTE: This code is similar to array floor divide */ BINARY_DEFS @@ -1099,7 +1099,7 @@ TIMEDELTA_mm_q_floor_divide(char **args, npy_intp const *dimensions, npy_intp co } NPY_NO_EXPORT void -TIMEDELTA_mm_qm_divmod(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)) +TIMEDELTA_mm_km_divmod(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)) { BINARY_LOOP_TWO_OUT { const npy_timedelta in1 = *(npy_timedelta *)ip1; diff --git a/numpy/core/src/umath/loops.h.src b/numpy/core/src/umath/loops.h.src index 25fa4e2cae93..08ce179487f3 100644 --- a/numpy/core/src/umath/loops.h.src +++ b/numpy/core/src/umath/loops.h.src @@ -216,9 +216,9 @@ NPY_NO_EXPORT void * #OP = ==, !=, <, <=, >, >=# */ NPY_NO_EXPORT void -LONGLONG_Qq_bool_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)); +INT64_Kk_bool_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)); NPY_NO_EXPORT void -LONGLONG_qQ_bool_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)); +INT64_kK_bool_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)); /**end repeat**/ @@ -759,10 +759,10 @@ NPY_NO_EXPORT void TIMEDELTA_mm_m_subtract(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)); NPY_NO_EXPORT void -TIMEDELTA_mq_m_multiply(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)); +TIMEDELTA_mk_m_multiply(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)); NPY_NO_EXPORT void -TIMEDELTA_qm_m_multiply(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)); +TIMEDELTA_km_m_multiply(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)); NPY_NO_EXPORT void TIMEDELTA_md_m_multiply(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)); @@ -771,7 +771,7 @@ NPY_NO_EXPORT void TIMEDELTA_dm_m_multiply(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)); NPY_NO_EXPORT void -TIMEDELTA_mq_m_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)); +TIMEDELTA_mk_m_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)); NPY_NO_EXPORT void TIMEDELTA_md_m_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)); @@ -780,16 +780,16 @@ NPY_NO_EXPORT void TIMEDELTA_mm_d_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)); NPY_NO_EXPORT void -TIMEDELTA_mm_q_floor_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)); +TIMEDELTA_mm_k_floor_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)); NPY_NO_EXPORT void TIMEDELTA_mm_m_remainder(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)); NPY_NO_EXPORT void -TIMEDELTA_mm_qm_divmod(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)); +TIMEDELTA_mm_km_divmod(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)); /* Special case equivalents to above functions */ -#define TIMEDELTA_mq_m_floor_divide TIMEDELTA_mq_m_divide +#define TIMEDELTA_mk_m_floor_divide TIMEDELTA_mk_m_divide #define TIMEDELTA_md_m_floor_divide TIMEDELTA_md_m_divide /* #define TIMEDELTA_mm_d_floor_divide TIMEDELTA_mm_d_divide */ diff --git a/numpy/core/src/umath/ufunc_type_resolution.c b/numpy/core/src/umath/ufunc_type_resolution.c index 4eea566842db..11640b5d826e 100644 --- a/numpy/core/src/umath/ufunc_type_resolution.c +++ b/numpy/core/src/umath/ufunc_type_resolution.c @@ -1441,7 +1441,7 @@ find_userloop(PyUFuncObject *ufunc, break; } - type_num = dtypes[i]->type_num; + type_num = NPY_DTYPE(dtypes[i])->type_num; if (type_num != last_userdef && (PyTypeNum_ISUSERDEF(type_num) || type_num == NPY_VOID)) { PyObject *key, *obj; @@ -1468,7 +1468,7 @@ find_userloop(PyUFuncObject *ufunc, int *types = funcdata->arg_types; for (j = 0; j < nargs; ++j) { - if (types[j] != dtypes[j]->type_num) { + if (types[j] != NPY_DTYPE(dtypes[j])->type_num) { break; } } @@ -1518,7 +1518,7 @@ PyUFunc_DefaultLegacyInnerLoopSelector(PyUFuncObject *ufunc, for (i = 0; i < ufunc->ntypes; ++i) { /* Copy the types into an int array for matching */ for (j = 0; j < nargs; ++j) { - if (types[j] != dtypes[j]->type_num) { + if (types[j] != NPY_DTYPE(dtypes[j])->type_num) { break; } } From 600cd4ec88151ac523b183e22c21c6de8caa8c10 Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Thu, 27 Jul 2023 10:11:08 +0200 Subject: [PATCH 30/30] Undo bad ufunc.at conflict (accidentally didn't have the new fix) --- numpy/core/src/umath/ufunc_object.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c index 0314ca762ccc..d234c6449dd0 100644 --- a/numpy/core/src/umath/ufunc_object.c +++ b/numpy/core/src/umath/ufunc_object.c @@ -5812,14 +5812,19 @@ trivial_at_loop(PyArrayMethodObject *ufuncimpl, NPY_ARRAYMETHOD_FLAGS flags, } } - npy_intp *inner_size = NpyIter_GetInnerLoopSizePtr(iter->outer); - if (!(flags & NPY_METH_NO_FLOATINGPOINT_ERRORS)) { npy_clear_floatstatus_barrier((char *)context); } do { - args[1] = (char *) iter->outer_ptrs[0]; + npy_intp *inner_size = NpyIter_GetInnerLoopSizePtr(iter->outer); + npy_intp * indxP = (npy_intp *)iter->outer_ptrs[0]; + for (npy_intp i=0; i < *inner_size; i++) { + if (indxP[i] < 0) { + indxP[i] += iter->fancy_dims[0]; + } + } + args[1] = (char *)indxP; steps[1] = iter->outer_strides[0]; res = ufuncimpl->contiguous_indexed_loop(