v923z / micropython-ulab

a numpy-like fast vector module for micropython, circuitpython, and their derivatives
https://micropython-ulab.readthedocs.io/en/latest
MIT License
422 stars 116 forks source link

add implementation of size and asarray #481

Closed v923z closed 2 years ago

v923z commented 2 years ago

@wired8 Phil, here is the implementation of asarray, and size. Could you,please, check it out? My tests have passed, but that might not mean too much. If these are OK, then I would merge it as soon as possible, so that you can update your snippets. Thanks!

wired8 commented 2 years ago

When calling asarray in micropython:

>>> np.asarray(5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: wrong input type
>>> np.asarray([5])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: bad typecode

Regular python:

print(np.asarray(5))
5
print(np.asarray([5]))
[5]

Note: asarray will always return a type of ndarray.

https://stackoverflow.com/questions/40378427/numpy-formal-definition-of-array-like-objects

v923z commented 2 years ago

@wired8 Thanks for catching this. I have updated the code. If you think that the test script has to be extended, so be it.

wired8 commented 2 years ago

Also np.size:

Micropython:

>>> np.size(5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: first argument must be an ndarray
>>> np.size([5])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: first argument must be an ndarray

Regular python:

print(np.size(5))
1
print(np.size([5]))
1

Regular python accepts an array_like.

v923z commented 2 years ago

@wired8 I believe it should be OK now. Let me know if there are still glitches.

wired8 commented 2 years ago

Breaks numpy.any

Actual:

Wn = 5
print(np.any(Wn <= 0))
TypeError: 'bool' object isn't iterable

Expected:

Wn = 5
print(np.any(Wn <= 0))
False
v923z commented 2 years ago

Breaks numpy.any

Actual:

Wn = 5
print(np.any(Wn <= 0))
TypeError: 'bool' object isn't iterable

That is actually a totally separate issue. And I am not sure, whether it is worth the overhead. Virtually all numpy functions should be able to handle scalars, and the only way of handling this is adding an if clause at the beginning of each function, and if the input is a scalar, then return there, otherwise, move to the array handling section. My guess is that this adds something like 50-100 bytes for each function, so overall, we are talking about 5-10 kB extra. circuitpython is already very tight on the flash, and I would rather drop extra features and corner cases than complete functions.

There is a reason, why numpy occupies 30+ MB of space, while ulab only approx. 100 kB. I am not saying that we shouldn't strive for compatibility, but it doesn't come cheap. I am also open to discussion. I am merging this as is, but if you think that this issue is really troublesome, open a separate ticket, and we can pick it up from there. This is definitely a worthwhile discussion, and I am glad you brought this up.

@jepler Would you like to comment on this?