Thanks to visit codestin.com
Credit goes to github.com

Skip to content

API: Make 64bit default integer on 64bit windows #24224

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 41 commits into from
Nov 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
f1d1491
API: Make intp the default integer in NumPy core
seberg Jul 13, 2023
e3af907
API: Remove `int_` and `uint_` from Cython as they are misleading as …
seberg Jul 13, 2023
fbbecab
MAINT: Keep using `long` in for legacy random number generation
seberg Jul 13, 2023
9b9325b
fixup cython
seberg Jul 13, 2023
044e56e
fixup initial change
seberg Jul 13, 2023
329d6bf
API: Add NPY_DEFAULT_INT which is runtime (unless NumPy >2 is forced)
seberg Jul 13, 2023
4d13583
fixup initial (add/multiply reduction)
seberg Jul 13, 2023
830c912
Fixup NPY_DEFAULT_INT definition (and version exposure)
seberg Jul 13, 2023
da9055e
ENH: Allow int64 explicitly in `ldexp`
seberg Jul 20, 2023
1f942e3
TST: Adapt _ufunc_tests to use intp in ufuncs (default integer)
seberg Jul 20, 2023
e03e93e
API: rewire/rename np.int_ and np.uint scalars and add np.long/np.ulong
seberg Jul 20, 2023
6402c8e
BUG: Fix (probably) legacy binomial and use `np.long` in random
seberg Jul 21, 2023
59654aa
TST: Adapt some tests to ensure long use and test default int a bit
seberg Jul 21, 2023
2a2600f
TST: Fix ufunc type resolution test for long (and a bit more)
seberg Jul 21, 2023
ab03464
TST: Fix legacy random test hashes to toggle on long (not default int)
seberg Jul 21, 2023
fc8ace2
TST: Remove duplicated test that needed adaption for default int change
seberg Jul 21, 2023
a901757
TST: Fix inplace_add ufunc test by using intp/default int
seberg Jul 21, 2023
ab675a3
TST: Adjust random test for long (not default int) return and branching
seberg Jul 21, 2023
9532739
Use intp in np.random.binomial for inputs (core uses int64 always)
seberg Jul 21, 2023
a205087
BUG: Fix previously unused int64/uint64 in umath generation for cross…
seberg Jul 21, 2023
8874e8e
BUG: Another random path that should probably keep using long
seberg Jul 21, 2023
4a9f8a2
TST: One more small test fixup for changed default dtype
seberg Jul 21, 2023
60bb095
BUG,API: like int32, intp must map to long if long and int are same size
seberg Jul 21, 2023
a2ceb3d
MAINT: Fix hypergeometric to use INT64, but raise if values surpass long
seberg Jul 21, 2023
cfe9960
Try with py_ssize_t (I am very unclear why float doesn't fail earlier)
seberg Jul 21, 2023
dd60409
Simply us Python `int()`...
seberg Jul 21, 2023
3e38281
BUG: Ensure `randint` returns a Python integer by default
seberg Aug 9, 2023
8f3fa96
Adjust type aliases after rebase
mtsokol Oct 9, 2023
80308a7
Apply linting
mtsokol Oct 9, 2023
960a4f0
TST: Fix random test for `dtype=int` being special cased in mtrand
seberg Oct 10, 2023
9e69004
DOC: Rephrase now incorrect comment in mtrand.pyx
seberg Oct 17, 2023
25b9d6c
TYP: Fixup typing for long changes
seberg Oct 19, 2023
178966c
TST,BUG: Work around random bug in tests
seberg Oct 26, 2023
83b5125
TST: Fix test due to changes on main
seberg Oct 27, 2023
a00fed5
TST: Fix randint test the right way
seberg Oct 27, 2023
b6df6cd
MAINT: Move Long-bound checks into helper
seberg Oct 27, 2023
2cb3ab6
Update numpy/random/mtrand.pyx
seberg Oct 27, 2023
fe23665
DOC: Add release note and transition guide entry
seberg Oct 30, 2023
6fbcd01
Fix typing and typo based on review
seberg Oct 31, 2023
b3bf8c3
TYP: Try fixing/working around windows ctypeslib mypy failures
seberg Oct 31, 2023
ba58f8b
Update doc/source/numpy_2_0_migration_guide.rst
seberg Nov 1, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions doc/release/upcoming_changes/24224.change.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Default integer now 64bit on 64bit windows
------------------------------------------
The default NumPy integer is now 64bit on all 64bit systems as the
historic 32bit default on windows was a common source of issues.
Most users should not notice this, the main issues may occur
with code interfacing with libraries written in a compiled language
like C. For more information see :ref:`migration_windows_int64`.
43 changes: 39 additions & 4 deletions doc/source/numpy_2_0_migration_guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,48 @@
NumPy 2.0 Migration Guide
*************************

This document contains a set of instructions on how to update your code to work with
the Numpy 2.0 Python API. Most of the changes are trivial, and require the end user
to use a different name/module to access a given function/constant.
This document contains a set of instructions on how to update your code to
work with Numpy 2.0.


.. _migration_windows_int64:

Windows default integer
=======================
The default integer used by NumPy is now 64bit on all 64bit systems (and
32bit on 32bit system). For historic reasons related to Python 2 it was
previously equivalent to the C ``long`` type.
The default integer is now equivalent to ``np.intp``.

Most end-users should not be affected by this change. Some operations will
use more memory, but some operations may actually become faster.
If you experience issues due to calling a library written in a compiled
language it may help to explicitly cast to a ``long``, for example with:
``arr = arr.astype("long", copy=False)``.

Libraries interfacing with compiled code that are written in C, Cython, or
a similar language may require updating to accomodate user input if they
are using the ``long`` or equivalent type on the C-side.
In this case, you may wish to use ``intp`` and cast user input or support
both ``long`` and ``intp`` (to better support NumPy 1.x as well).
When creating a new integer array in C or Cython, the new ``NPY_DEFAULT_INT``
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should define this in 1.26 too?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might make it a bit easier to use for downstream, but they still will need to force numpy>=1.26 at compile time. So I am tempted to say that unfortunately, it is better to vendor it:

#ifndef NPY_DEFAULT_INT
#define NPY_DEFAULT_INT NPY_LONG
#endif

(unless you force >2.0 at compile time)?

Happy to follow-up with a backport, not sure it's helpful, but wouldn't hurt.

macro will evaluate to either ``NPY_LONG`` or ``NPY_INTP`` depending on the
NumPy version.

Note that the NumPy random API is not affected by this change.

Namespace changes
=================

In NumPy 2.0 certain functions, modules, and constants were moved or removed
to make the NumPy namespace more userfriendly by removing unnecessary or
outdated functionality and clarifying which parts of NumPy are considered
private.
Please see the tables below for guidance on migration. For most changes this
means replacing it with a backwards compatible alternative.

Please refer to `NEP 52 <https://numpy.org/neps/nep-0052-python-api-cleanup.html>`_ for more details.


Main namespace
--------------

Expand Down
6 changes: 1 addition & 5 deletions numpy/__init__.cython-30.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -777,12 +778,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
Expand Down
6 changes: 1 addition & 5 deletions numpy/__init__.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ cdef extern from "numpy/arrayobject.h":
NPY_COMPLEX512

NPY_INTP
NPY_DEFAULT_INT

ctypedef enum NPY_ORDER:
NPY_ANYORDER
Expand Down Expand Up @@ -699,12 +700,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
Expand Down
4 changes: 2 additions & 2 deletions numpy/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -2858,7 +2858,7 @@ byte = signedinteger[_NBitByte]
short = signedinteger[_NBitShort]
intc = signedinteger[_NBitIntC]
intp = signedinteger[_NBitIntP]
int_ = signedinteger[_NBitInt]
int_ = intp
long = signedinteger[_NBitLong]
longlong = signedinteger[_NBitLongLong]

Expand Down Expand Up @@ -2940,7 +2940,7 @@ ubyte = unsignedinteger[_NBitByte]
ushort = unsignedinteger[_NBitShort]
uintc = unsignedinteger[_NBitIntC]
uintp = unsignedinteger[_NBitIntP]
uint = unsignedinteger[_NBitInt]
uint = uintp
ulong = unsignedinteger[_NBitLong]
ulonglong = unsignedinteger[_NBitLongLong]

Expand Down
8 changes: 6 additions & 2 deletions numpy/_core/_add_newdocs_scalars.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 :class:`int` and C ``long``.
Default signed integer type, 64bit on 64bit systems and 32bit on 32bit
systems.
""")

add_newdoc_for_scalar_type('longlong', [],
Expand All @@ -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', [],
Expand Down
5 changes: 3 additions & 2 deletions numpy/_core/_type_aliases.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,9 @@
"single": "float32",
"csingle": "complex64",
"half": "float16",
"int_": "long",
"uint": "ulong",
# Default integer:
"int_": "intp",
"uint": "uintp",
}

for k, v in _aliases.items():
Expand Down
17 changes: 13 additions & 4 deletions numpy/_core/code_generators/generate_numpy_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,24 @@
#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_VERSION_CONCAT_HELPER2(arg, PyArray_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

Expand Down Expand Up @@ -85,15 +93,16 @@
(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 "\
"Troubleshooting ImportError section at "\
"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;
}

Expand Down
29 changes: 17 additions & 12 deletions numpy/_core/code_generators/generate_umath.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,13 @@ def finish_signature(self, nin, nout):


def _check_order(types1, types2):
dtype_order = allP + "O"
"""
Helper to check that the loop types are ordered. The legacy type resolver
(and potentially downstream) may pick use the first loop to which operands
can be cast safely.
"""
# 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":
Expand Down Expand Up @@ -275,6 +281,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',
Expand Down Expand Up @@ -330,13 +340,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
Expand Down Expand Up @@ -1090,12 +1095,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' :
Expand Down
7 changes: 7 additions & 0 deletions numpy/_core/include/numpy/ndarraytypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -1486,6 +1486,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
Expand Down
21 changes: 11 additions & 10 deletions numpy/_core/include/numpy/npy_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -228,16 +228,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
Expand All @@ -246,6 +237,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
Expand Down
10 changes: 5 additions & 5 deletions numpy/_core/src/multiarray/abstractdtypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 *
Expand All @@ -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);
}
Expand Down Expand Up @@ -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 (NPY_DT_is_legacy(other)) {
Expand Down Expand Up @@ -184,7 +184,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) {
Expand Down
2 changes: 1 addition & 1 deletion numpy/_core/src/multiarray/ctors.c
Original file line number Diff line number Diff line change
Expand Up @@ -3223,7 +3223,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;
Expand Down
2 changes: 1 addition & 1 deletion numpy/_core/src/multiarray/descriptor.c
Original file line number Diff line number Diff line change
Expand Up @@ -1542,7 +1542,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);
Expand Down
4 changes: 2 additions & 2 deletions numpy/_core/src/umath/_operand_flag_tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -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};

Expand Down
Loading