dpctl icon indicating copy to clipboard operation
dpctl copied to clipboard

Shape setter does not work with integer scalar

Open antonwolfy opened this issue 1 year ago • 2 comments

The below example reproduces an issue with passing integer scalar to the shape setter:

import numpy, dpctl, dpctl.tensor as dpt

dpctl.__version__
# Out: '0.18.0dev0+158.g7450558d25'

a = dpt.usm_ndarray((2, 3))
a.shape = 6
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[3], line 1
----> 1 a.shape = 6

File dpctl/tensor/_usmarray.pyx:579, in dpctl.tensor._usmarray.usm_ndarray.shape.__set__()

TypeError: object of type 'int' has no len()

# but works in numpy
a = numpy.ndarray((2, 3))
a.shape = 6

antonwolfy avatar Jul 29 '24 13:07 antonwolfy

The .shape setter requires value to be a tuple, or a list, or a object with __len__. This is different from NumPy's behavior:


In [30]: a = dpt.ones((2,3))

In [31]: class Six:
    ...:     def __init__(self, dim=1):
    ...:         self.v = (1,) * (dim - 1) + (6,)
    ...:     def __len__(self):
    ...:         return len(self.v)
    ...:     def __iter__(self):
    ...:         return iter(self.v)
    ...:

In [32]: a.shape = Six(3)

In [33]: a
Out[33]: usm_ndarray([[[1., 1., 1., 1., 1., 1.]]], dtype=float32)

In [34]: a.shape
Out[34]: (1, 1, 6)

In [35]: import numpy as np

In [36]: b = np.ones((2,3))

In [37]: b.shape = Six(3)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[37], line 1
----> 1 b.shape = Six(3)

TypeError: expected a sequence of integers or a single integer, got '<__main__.Six object at 0x7f7ee86258e0>'

oleksandr-pavlyk avatar Jul 29 '24 21:07 oleksandr-pavlyk

Should that be properly clarified in the documentation? Since it might be unclear that .shape setter and reshape method behaves differently (different requirements on supported type of new shape argument) in case when the reshaping to the requested dimensions can be returned as a view.

a = dpt.usm_ndarray((2, 3))
dpt.reshape(a, 6, copy=False)
# Out: usm_ndarray([0., 0., 0., 0., 0., 0.])

antonwolfy avatar Jul 30 '24 07:07 antonwolfy