-
Notifications
You must be signed in to change notification settings - Fork 118
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
[WIP] Fix ndarray constructor #305
base: master
Are you sure you want to change the base?
Conversation
code/ndarray.c
Outdated
@@ -935,7 +935,33 @@ mp_obj_t ndarray_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, | |||
mp_arg_check_num(n_args, n_kw, 1, 2, true); | |||
mp_map_t kw_args; | |||
mp_map_init_fixed_table(&kw_args, n_kw, args + n_args); | |||
return ndarray_make_new_core(type, n_args, n_kw, args, &kw_args); | |||
uint8_t dtype = ndarray_init_helper(n_args, args, &kw_args); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't it be simpler to move this whole block to make_new_core
? That would solve the circuitpytthon
problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds like a plan 🏂
@CallumJHays Cal, I am struggling to understand, what this PR is trying to fix: while
is perfectly valid in
And while the initialisation doesn't raise an exception, this mode is not mentioned in the official documentation: https://numpy.org/doc/stable/reference/generated/numpy.array.html#numpy.array. The first argument should be something that looks like an array, walks like an array, and quacks like an array. I am a bit flabbergasted to say the least. Not by the PR, but by the fact that there seems to be a bit of an inconsistency in |
@v923z The main point of the PR will only affect >>> import numpy as np
>>> np.ndarray([1, 2, 3])
array([[[4.63760270e-310, 0.00000000e+000, 4.63760245e-310],
[6.91622088e-310, 1.92343089e-313, 6.91625378e-310]]])
>>> np.array([1, 2, 3])
array([1, 2, 3]) I believe currently both As for accepting an int rather than either an int or iterable this was just the behaviour I noticed when testing numpy locally so I replicated it. I'm not well-versed on the nuances of numpy's API, but I would have to assume it could have benefits when using scalar arithmetic in numpy with the data already being in C memory. I can definitely see it having benefits in streamlining some usage of the numpy API in a pythonic duck-typing way. I also agree the numpy documentation is inconsistent. Something I wanted to bring up btw is supporting kwargs that match the position of a positional arg, ie let this work: >>> np.array(object=[1, 2, 3])
array([1, 2, 3])
>>> np.ndarray(shape=[1, 2, 3])
array([[[4.63760270e-310, 0.00000000e+000, 4.63760245e-310],
[6.91622088e-310, 1.92343089e-313, 6.91625378e-310]]]) Last time I checked it threw an error similar to "required positional argument not included". Is there a way we can fix this without firmware bloat? |
Thanks for the explanation! If you move the code block to
I am not against this option, if you deem this to be useful. The keyword argument will add approx. 200-400 bytes to the firmware size. If you find that to be too much, you could make that configurable via a |
implmenetation to make_new_core
@v923z that last commit has the basic functionality of passing Do you think we should handle Also, do you know of a standard way to populate a C arr from a micropython iterator?, like a: size_t len = 3;
uint8_t arr[len];
MP_ITER_FILL_ARR(mp_iter, uint8_t, arr, len); |
Oh, don't worry, this is a project run by enthusiasts. I am not going to hold you to any specific deadline, and I am grateful for any contribution. By the way, thanks for patching up the doc stubs!
If you think it is useful, I don't see any reason not to. But I don't see pressing reasons for, either. I leave it up to you.
Do you mean something like micropython-ulab/code/ndarray.c Line 567 in 96a944c
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@CallumJHays Cal, sorry for the belated reply. I only had time now to look at your code. Could you, please, address the two issues? Otherwise, I think this is a nice addition. Thanks for the undertaking!
In addition, don't forget to increment the version number
Line 36 in ab964b9
#define ULAB_VERSION 2.3.5 |
mp_int_t ndim; | ||
size_t shape[ULAB_MAX_DIMS]; | ||
|
||
if (mp_ndim_maybe == MP_OBJ_NULL) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will fail with ndarray(-12.3)
. You can make it safe by explicitly checking for the input type:
micropython-ulab/code/ulab_create.c
Line 29 in ab964b9
if(MP_OBJ_IS_INT(oshape)) { |
ndim = 1; | ||
shape[ULAB_MAX_DIMS - 1] = MP_OBJ_SMALL_INT_VALUE(mp_shape); | ||
} else { | ||
mp_obj_get_int_maybe(mp_ndim_maybe, &ndim); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here you have to bail out, if the tuple is longer then ULAB_MAX_DIMS. The loop below is safe, but the user would still be left wondering, why the array is not what they expected.
@CallumJHays do you want to go ahead with this PR? I could take over, if you have no time. I would just like to close the issue, because I think this would be a valuable addition. |
WIP fix for #301
Hey @v923z could you give this a look and let me know if there's a better way to write this?