Skip to content

[WIP] Fix ndarray constructor #305

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
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion code/ndarray.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Copy link
Owner

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like a plan 🏂


mp_obj_t mp_shape = args[0];
mp_obj_t mp_ndim_maybe = mp_obj_len_maybe(mp_shape);
// single-number shapes "x" are interpreted the same as "(x,)"
uint8_t ndim;
size_t shape[ULAB_MAX_DIMS];

if (mp_ndim_maybe == MP_OBJ_NULL) {
Copy link
Owner

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:

if(MP_OBJ_IS_INT(oshape)) {

ndim = 1;
shape[ULAB_MAX_DIMS - 1] = MP_OBJ_SMALL_INT_VALUE(mp_shape);
} else {
mp_int_t mp_int;
mp_obj_get_int_maybe(mp_ndim_maybe, &mp_int);
ndim = MP_OBJ_SMALL_INT_VALUE(mp_int);

mp_obj_iter_buf_t iter_buf;
mp_obj_t mp_shape_iter = mp_getiter(mp_shape, &iter_buf);

for (uint8_t i = ULAB_MAX_DIMS - ndim; i < ULAB_MAX_DIMS; i++) {
shape[i] = MP_OBJ_SMALL_INT_VALUE(mp_iternext(mp_shape_iter));
}
}

return MP_OBJ_FROM_PTR(
ndarray_new_dense_ndarray(ndim, shape, dtype)
);
}
#endif

Expand Down
20 changes: 10 additions & 10 deletions code/numpy/approx/approx.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,17 @@ const mp_obj_float_t approx_trapz_dx = {{&mp_type_float}, MICROPY_FLOAT_CONST(1.

#if ULAB_NUMPY_HAS_INTERP
//| def interp(
//| x: ulab.array,
//| xp: ulab.array,
//| fp: ulab.array,
//| x: ulab.ndarray,
//| xp: ulab.ndarray,
//| fp: ulab.ndarray,
//| *,
//| left: Optional[float] = None,
//| right: Optional[float] = None
//| ) -> ulab.array:
//| ) -> ulab.ndarray:
//| """
//| :param ulab.array x: The x-coordinates at which to evaluate the interpolated values.
//| :param ulab.array xp: The x-coordinates of the data points, must be increasing
//| :param ulab.array fp: The y-coordinates of the data points, same length as xp
//| :param ulab.ndarray x: The x-coordinates at which to evaluate the interpolated values.
//| :param ulab.ndarray xp: The x-coordinates of the data points, must be increasing
//| :param ulab.ndarray fp: The y-coordinates of the data points, same length as xp
//| :param left: Value to return for ``x < xp[0]``, default is ``fp[0]``.
//| :param right: Value to return for ``x > xp[-1]``, default is ``fp[-1]``.
//|
Expand Down Expand Up @@ -137,10 +137,10 @@ MP_DEFINE_CONST_FUN_OBJ_KW(approx_interp_obj, 2, approx_interp);
#endif

#if ULAB_NUMPY_HAS_TRAPZ
//| def trapz(y: ulab.array, x: Optional[ulab.array] = None, dx: float = 1.0) -> float:
//| def trapz(y: ulab.ndarray, x: Optional[ulab.ndarray] = None, dx: float = 1.0) -> float:
//| """
//| :param 1D ulab.array y: the values of the dependent variable
//| :param 1D ulab.array x: optional, the coordinates of the independent variable. Defaults to uniformly spaced values.
//| :param 1D ulab.ndarray y: the values of the dependent variable
//| :param 1D ulab.ndarray x: optional, the coordinates of the independent variable. Defaults to uniformly spaced values.
//| :param float dx: the spacing between sample points, if x=None
//|
//| Returns the integral of y(x) using the trapezoidal rule.
Expand Down
12 changes: 6 additions & 6 deletions code/numpy/fft/fft.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@
//|


//| def fft(r: ulab.array, c: Optional[ulab.array] = None) -> Tuple[ulab.array, ulab.array]:
//| def fft(r: ulab.ndarray, c: Optional[ulab.ndarray] = None) -> Tuple[ulab.ndarray, ulab.ndarray]:
//| """
//| :param ulab.array r: A 1-dimension array of values whose size is a power of 2
//| :param ulab.array c: An optional 1-dimension array of values whose size is a power of 2, giving the complex part of the value
//| :param ulab.ndarray r: A 1-dimension array of values whose size is a power of 2
//| :param ulab.ndarray c: An optional 1-dimension array of values whose size is a power of 2, giving the complex part of the value
//| :return tuple (r, c): The real and complex parts of the FFT
//|
//| Perform a Fast Fourier Transform from the time domain into the frequency domain
Expand All @@ -48,10 +48,10 @@ static mp_obj_t fft_fft(size_t n_args, const mp_obj_t *args) {

MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fft_fft_obj, 1, 2, fft_fft);

//| def ifft(r: ulab.array, c: Optional[ulab.array] = None) -> Tuple[ulab.array, ulab.array]:
//| def ifft(r: ulab.ndarray, c: Optional[ulab.ndarray] = None) -> Tuple[ulab.ndarray, ulab.ndarray]:
//| """
//| :param ulab.array r: A 1-dimension array of values whose size is a power of 2
//| :param ulab.array c: An optional 1-dimension array of values whose size is a power of 2, giving the complex part of the value
//| :param ulab.ndarray r: A 1-dimension array of values whose size is a power of 2
//| :param ulab.ndarray c: An optional 1-dimension array of values whose size is a power of 2, giving the complex part of the value
//| :return tuple (r, c): The real and complex parts of the inverse FFT
//|
//| Perform an Inverse Fast Fourier Transform from the frequeny domain into the time domain"""
Expand Down
26 changes: 13 additions & 13 deletions code/numpy/linalg/linalg.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ static ndarray_obj_t *linalg_object_is_square(mp_obj_t obj) {
#endif

#if ULAB_MAX_DIMS > 1
//| def cholesky(A: ulab.array) -> ulab.array:
//| def cholesky(A: ulab.ndarray) -> ulab.ndarray:
//| """
//| :param ~ulab.array A: a positive definite, symmetric square matrix
//| :return ~ulab.array L: a square root matrix in the lower triangular form
//| :param ~ulab.ndarray A: a positive definite, symmetric square matrix
//| :return ~ulab.ndarray L: a square root matrix in the lower triangular form
//| :raises ValueError: If the input does not fulfill the necessary conditions
//|
//| The returned matrix satisfies the equation m=LL*"""
Expand Down Expand Up @@ -111,7 +111,7 @@ static mp_obj_t linalg_cholesky(mp_obj_t oin) {

MP_DEFINE_CONST_FUN_OBJ_1(linalg_cholesky_obj, linalg_cholesky);

//| def det(m: ulab.array) -> float:
//| def det(m: ulab.ndarray) -> float:
//| """
//| :param: m, a square matrix
//| :return float: The determinant of the matrix
Expand Down Expand Up @@ -182,10 +182,10 @@ MP_DEFINE_CONST_FUN_OBJ_1(linalg_det_obj, linalg_det);

#endif

//| def dot(m1: ulab.array, m2: ulab.array) -> Union[ulab.array, float]:
//| def dot(m1: ulab.ndarray, m2: ulab.ndarray) -> Union[ulab.ndarray, float]:
//| """
//| :param ~ulab.array m1: a matrix, or a vector
//| :param ~ulab.array m2: a matrix, or a vector
//| :param ~ulab.ndarray m1: a matrix, or a vector
//| :param ~ulab.ndarray m2: a matrix, or a vector
//|
//| Computes the product of two matrices, or two vectors. In the letter case, the inner product is returned."""
//| ...
Expand Down Expand Up @@ -247,7 +247,7 @@ static mp_obj_t linalg_dot(mp_obj_t _m1, mp_obj_t _m2) {
MP_DEFINE_CONST_FUN_OBJ_2(linalg_dot_obj, linalg_dot);

#if ULAB_MAX_DIMS > 1
//| def eig(m: ulab.array) -> Tuple[ulab.array, ulab.array]:
//| def eig(m: ulab.ndarray) -> Tuple[ulab.ndarray, ulab.ndarray]:
//| """
//| :param m: a square matrix
//| :return tuple (eigenvectors, eigenvalues):
Expand Down Expand Up @@ -308,9 +308,9 @@ static mp_obj_t linalg_eig(mp_obj_t oin) {

MP_DEFINE_CONST_FUN_OBJ_1(linalg_eig_obj, linalg_eig);

//| def inv(m: ulab.array) -> ulab.array:
//| def inv(m: ulab.ndarray) -> ulab.ndarray:
//| """
//| :param ~ulab.array m: a square matrix
//| :param ~ulab.ndarray m: a square matrix
//| :return: The inverse of the matrix, if it exists
//| :raises ValueError: if the matrix is not invertible
//|
Expand Down Expand Up @@ -346,9 +346,9 @@ static mp_obj_t linalg_inv(mp_obj_t o_in) {
MP_DEFINE_CONST_FUN_OBJ_1(linalg_inv_obj, linalg_inv);
#endif

//| def norm(x: ulab.array) -> float:
//| def norm(x: ulab.ndarray) -> float:
//| """
//| :param ~ulab.array x: a vector or a matrix
//| :param ~ulab.ndarray x: a vector or a matrix
//|
//| Computes the 2-norm of a vector or a matrix, i.e., ``sqrt(sum(x*x))``, however, without the RAM overhead."""
//| ...
Expand Down Expand Up @@ -388,7 +388,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(linalg_norm_obj, linalg_norm);
#if ULAB_MAX_DIMS > 1
#if ULAB_LINALG_HAS_TRACE

//| def trace(m: ulab.array) -> float:
//| def trace(m: ulab.ndarray) -> float:
//| """
//| :param m: a square matrix
//|
Expand Down
16 changes: 8 additions & 8 deletions code/numpy/numerical/numerical.c
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(numerical_argmin_obj, 1, numerical_argmin);
#endif

#if ULAB_NUMPY_HAS_ARGSORT
//| def argsort(array: ulab.array, *, axis: int = -1) -> ulab.array:
//| def argsort(array: ulab.ndarray, *, axis: int = -1) -> ulab.ndarray:
//| """Returns an array which gives indices into the input array from least to greatest."""
//| ...
//|
Expand Down Expand Up @@ -627,7 +627,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(numerical_argsort_obj, 1, numerical_argsort);
#endif

#if ULAB_NUMPY_HAS_CROSS
//| def cross(a: ulab.array, b: ulab.array) -> ulab.array:
//| def cross(a: ulab.ndarray, b: ulab.ndarray) -> ulab.ndarray:
//| """Return the cross product of two vectors of length 3"""
//| ...
//|
Expand Down Expand Up @@ -705,7 +705,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(numerical_cross_obj, numerical_cross);
#endif /* ULAB_NUMERICAL_HAS_CROSS */

#if ULAB_NUMPY_HAS_DIFF
//| def diff(array: ulab.array, *, n: int = 1, axis: int = -1) -> ulab.array:
//| def diff(array: ulab.ndarray, *, n: int = 1, axis: int = -1) -> ulab.ndarray:
//| """Return the numerical derivative of successive elements of the array, as
//| an array. axis=None is not supported."""
//| ...
Expand Down Expand Up @@ -786,7 +786,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(numerical_diff_obj, 1, numerical_diff);
#endif

#if ULAB_NUMPY_HAS_FLIP
//| def flip(array: ulab.array, *, axis: Optional[int] = None) -> ulab.array:
//| def flip(array: ulab.ndarray, *, axis: Optional[int] = None) -> ulab.ndarray:
//| """Returns a new array that reverses the order of the elements along the
//| given axis, or along all axes if axis is None."""
//| ...
Expand Down Expand Up @@ -860,7 +860,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(numerical_mean_obj, 1, numerical_mean);
#endif

#if ULAB_NUMPY_HAS_MEDIAN
//| def median(array: ulab.array, *, axis: int = -1) -> ulab.array:
//| def median(array: ulab.ndarray, *, axis: int = -1) -> ulab.ndarray:
//| """Find the median value in an array along the given axis, or along all axes if axis is None."""
//| ...
//|
Expand Down Expand Up @@ -968,7 +968,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(numerical_min_obj, 1, numerical_min);
#endif

#if ULAB_NUMPY_HAS_ROLL
//| def roll(array: ulab.array, distance: int, *, axis: Optional[int] = None) -> None:
//| def roll(array: ulab.ndarray, distance: int, *, axis: Optional[int] = None) -> None:
//| """Shift the content of a vector by the positions given as the second
//| argument. If the ``axis`` keyword is supplied, the shift is applied to
//| the given axis. The array is modified in place."""
Expand Down Expand Up @@ -1133,7 +1133,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(numerical_roll_obj, 2, numerical_roll);
#endif

#if ULAB_NUMPY_HAS_SORT
//| def sort(array: ulab.array, *, axis: int = -1) -> ulab.array:
//| def sort(array: ulab.ndarray, *, axis: int = -1) -> ulab.ndarray:
//| """Sort the array along the given axis, or along all axes if axis is None.
//| The array is modified in place."""
//| ...
Expand Down Expand Up @@ -1209,7 +1209,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(numerical_std_obj, 1, numerical_std);
#endif

#if ULAB_NUMPY_HAS_SUM
//| def sum(array: _ArrayLike, *, axis: Optional[int] = None) -> Union[float, int, ulab.array]:
//| def sum(array: _ArrayLike, *, axis: Optional[int] = None) -> Union[float, int, ulab.ndarray]:
//| """Return the sum of the array, as a number if axis is None, otherwise as an array."""
//| ...
//|
Expand Down
Loading