Skip to content

BUG: Bitshift operations on scalar integers change type to int64 or fail #21261

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

Open
maxnoe opened this issue Mar 29, 2022 · 3 comments
Open
Labels

Comments

@maxnoe
Copy link

maxnoe commented Mar 29, 2022

Describe the issue:

Scalar bitshifts seem not to be implemented and are either upcasting to int64 or failing to upcast (for uint64).

Reproduce the code example:

import numpy as np


dtypes = np.uint16, np.uint32, np.uint64


for dtype in dtypes:
    scalar = dtype(15)
    array = np.array([15], dtype=dtype)

    print("dtype = ", dtype)

    print("Scalar right shift: ", end="")
    try:
        result = scalar >> 1
        print(result, type(result))
    except:
        print("Error")


    print("Scalar left shift: ", end="")
    try:
        result = scalar << 1
        print(result, type(result))
    except:
        print("Error")


    print("Array right shift: ", end="")
    try:
        result = array >> 1
        print(result, result.dtype)
    except:
        print("Error")

    print("Array left shift: ", end="")
    try:
        result = array << 1
        print(result, result.dtype)
    except:
        print("Error")

    print()

Error message:

❯ python bitshift_dtypes.py
dtype =  <class 'numpy.uint16'>
Scalar right shift: 7 <class 'numpy.int64'>
Scalar left shift: 30 <class 'numpy.int64'>
Array right shift: [7] uint16
Array left shift: [30] uint16

dtype =  <class 'numpy.uint32'>
Scalar right shift: 7 <class 'numpy.int64'>
Scalar left shift: 30 <class 'numpy.int64'>
Array right shift: [7] uint32
Array left shift: [30] uint32

dtype =  <class 'numpy.uint64'>
Scalar right shift: Error
Scalar left shift: Error
Array right shift: [7] uint64
Array left shift: [30] uint64
``

NumPy/Python version information:

❯ python -c 'import sys, numpy; print(numpy.version, sys.version)'
1.21.5 3.10.2 (main, Jan 15 2022, 19:56:27) [GCC 11.1.0]

@seberg
Copy link
Member

seberg commented Mar 29, 2022

@maxnoe this is due to how NumPy does promotion for scalars. If you do np.uint8(1) + 1, NumPy effectively does np.uint8(1) + np.asarray(1) which gives you int64. If you do np.array([1], dtype=np.uint8) + 1, NumPy figures out what the "smallest dtype" is that can hold the 1, and figures it is uint8 here. So it will do np.array([1], dtype=np.uint8) + np.uint8(1).

We are trying to push us beyond that behaviour, but it may mean a "NumPy 2.0" (in the sense of: most users will be fine, but careful larger than typical change). My main main start is gh-21103. I also had made a small poll here (Without explaining the issues/reasons in depth, the expectations seem pretty mixed though, unfortunately.)

@seberg
Copy link
Member

seberg commented Mar 29, 2022

Ah, of course there could be an argument that bit-shifts should never depend on the dtype of the second argument, which would indeed be a different issue. But I am not sure that is what you mean?

@maxnoe
Copy link
Author

maxnoe commented Mar 29, 2022

Type promotion for additions and subtractions is fine and kind of expected.

Type promotion for bitshifts is not.

Sorry: C/C++ also promotes shifts to int. Very suprising to me, but hey... https://godbolt.org/z/6qjfMjsT1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants