Skip to content

np.dtype(int) should be np.longlong on python 3 #12332

@eric-wieser

Description

@eric-wieser

This has come up before, but I'm not sure we have a canonical issue.

Historically in python 2:

  • builtins.int is mapped to np.int_ (C long), since builtins.int is stored as a C long
  • builtins.long is mapped to np.longlong (C long long), since builtins.long is infinite precision and that's the largest available integer type
# python 2.7
>>> np.dtype(int).char
'l'
>>> np.dtype(long).char
'q'

Note the above output only reflects the state of windows - other platforms have sizeof(long) == sizeof(long long), so the distinction isn't important.

In python 3, builtins.int has been removed, and builtins.long has been renamed to __builtins__.int. Yet:

# python 3.5
>>> new_long = int
>>> np.dtype(new_long).char
'l'  # smaller than it was on python 2

This means that python code translated from 2 to 3 by replacing long with int will start behaving differently:

# python 2
>>> np.array(10**10, dtype=long)
array(10000000000L, dtype=int64)
# python 3 translation
>>> np.array(10**10, dtype=int)
OverflowError: Python int too large to convert to C long

Since this affects users transitioning from 2 to 3, I think it's important that we get it fixed in 1.16, which will be the last version that transitioning users can test both version of python against.


The current implementation, introduced in aa7be88 by @pv, is:

#if !defined(NPY_PY3K)
        if (obj == (PyObject *)(&PyInt_Type)) {
            check_num = NPY_LONG;
        }
        else if (obj == (PyObject *)(&PyLong_Type)) {
            check_num = NPY_LONGLONG;
        }
#else
        if (obj == (PyObject *)(&PyLong_Type)) {
            check_num = NPY_LONG;
        }
#endif

I'd propose it should have been:

#if !defined(NPY_PY3K)
        if (obj == (PyObject *)(&PyInt_Type)) {
            check_num = NPY_LONG;
        }
        else
#endif 
        if (obj == (PyObject *)(&PyLong_Type)) {
            check_num = NPY_LONGLONG;
        }

Ie, treating PyLong_Type in python 3 just as we always did in python 2.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions