Skip to content

Bitwise Operations on numpy.int32 and int have different result types in macOS vs Windows, but same dtype __repr__ #17351

Open

Description

@finagle29

Reproducing code example:

on macOS

>>>import numpy as np
>>>type((np.ones(1, dtype=np.int32) | 0)[0])
numpy.int32
>>>(np.ones(1, dtype=np.int32) | 0)[0].dtype
dtype('int32')

on Windows

>>>import numpy as np
>>>type((np.ones(1, dtype=np.int32) | 0)[0])
numpy.intc
>>>(np.ones(1, dtype=np.int32) | 0)[0].dtype
dtype('int32')

Expected Behavior

>>>import numpy as np
>>>type((np.ones(1, dtype=np.int32) | 0)[0])
numpy.int32
>>>(np.ones(1, dtype=np.int32) | 0)[0].dtype
dtype('int32')

on both platforms

NumPy/Python version information:

On macOS
1.19.1 3.7.8 | packaged by conda-forge | (default, Jul 23 2020, 03:39:37)
[Clang 10.0.0 ]
and
1.19.1 3.8.5 | packaged by conda-forge | (default, Sep 16 2020, 17:43:11)
[Clang 10.0.1 ]

On Windows
1.19.1 3.7.7 (default, May 6 2020, 11:45:54) [MSC v.1916 64 bit (AMD64)]
and
1.19.1 3.8.5 | packaged by conda-forge | (default, Sep 16 2020, 17:19:16) [MSC v.1916 64 bit (AMD64)]

Activity

  1. BvB93 commented on Sep 19, 2020

    @BvB93
    Member

    Some further testing shows that there are some serious inconsistencies here between integers, 0D arrays and >0D arrays:

    In [1]: import operator
       ...: from typing import Callable, Dict, Type, Any
       ...:
       ...: import numpy as np
       ...:
       ...: INT_DICT = {
       ...:     # Scalars
       ...:     'int8': np.int8(1),  # np.byte
       ...:     'int16': np.int16(1),  # np.short
       ...:     'int32': np.int32(1),  # np.int_
       ...:     'int64': np.int64(1),  # np.longlong
       ...:
       ...:     # 0D arrays
       ...:     'int8_0d': np.array(1, dtype=np.int8),
       ...:     'int16_0d': np.array(1, dtype=np.int16),
       ...:     'int32_0d': np.array(1, dtype=np.int32),
       ...:     'int64_0d': np.array(1, dtype=np.int64),
       ...:
       ...:     # 1D arrays
       ...:     'int8_1d': np.array([1], dtype=np.int8),
       ...:     'int16_1d': np.array([1], dtype=np.int16),
       ...:     'int32_1d': np.array([1], dtype=np.int32),
       ...:     'int64_1d': np.array([1], dtype=np.int64),
       ...: }
       ...:
       ...: def get_output_types(op: Callable, *args: Any) -> Dict[str, Type[np.integer]]:
       ...:     return {name: op(value, *args).dtype.type for name, value in INT_DICT.items()}
       ...:
    
    # `builtins.int` and `np.int32` exhibit identical behavior
    In [2]: get_output_types(operator.__and__, 1)
    Out[2]:
    {'int8': numpy.intc,
     'int16': numpy.intc,
     'int32': numpy.int32,
     'int64': numpy.int64,
    
     'int8_0d': numpy.intc,
     'int16_0d': numpy.intc,
     'int32_0d': numpy.intc,
     'int64_0d': numpy.int64,
    
     'int8_1d': numpy.int8,
     'int16_1d': numpy.int16,
     'int32_1d': numpy.intc,
     'int64_1d': numpy.int64}
    
    In [3]: get_output_types(operator.__and__, np.int64(1))
    Out[3]:
    {'int8': numpy.int64,
     'int16': numpy.int64,
     'int32': numpy.int64,
     'int64': numpy.int64,
    
     'int8_0d': numpy.int64,
     'int16_0d': numpy.int64,
     'int32_0d': numpy.int64,
     'int64_0d': numpy.int64,
    
     'int8_1d': numpy.int8,
     'int16_1d': numpy.int16,
     'int32_1d': numpy.intc,
     'int64_1d': numpy.int64}

    Numpy: 1.20.0.dev0+9e63ecf
    Python: 3.8.5 | packaged by conda-forge | (default, Jul 31 2020, 01:53:45) [MSC v.1916 64 bit (AMD64)]

  2. eric-wieser commented on Sep 19, 2020

    @eric-wieser
    Member

    @BvB93, I'd recommend you perform your tests with the canonical char, short, intc, int_, longlong names so that you don't accidentally miss a type.

  3. eric-wieser commented on Sep 19, 2020

    @eric-wieser
    Member

    The danger of changing dtype.__repr__ is that the array repr no longer round-trips to a platform-guaranteed memory layout. Perhaps the rarity of platforms where this matters makes this point moot.

  4. BvB93 commented on Sep 19, 2020

    @BvB93
    Member

    @BvB93, I'd recommend you perform your tests with the canonical char, short, intc, int_, longlong names so that you don't accidentally miss a type.

    Good to know, I'll keep it in mind for next time.

    Still, what I find somewhat concerning is the discrepancy between the output (d)type of >0D arrays
    versus those from 0D arrays/integers.

    EDIT: Nevermind the last part, this behavior is clearly documented in the np.result_type docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions