From ed06b4e48b70782f499f104ed4e8e4755ff75683 Mon Sep 17 00:00:00 2001 From: Laury Date: Fri, 17 Dec 2021 21:36:19 +0100 Subject: [PATCH] [python/ulab] Updated ulab --- python/Makefile | 17 +- python/port/genhdr/qstrdefs.in.h | 4 + python/port/mod/ulab/LICENSE | 21 ++ python/port/mod/ulab/ndarray.c | 243 ++---------------- python/port/mod/ulab/ndarray.h | 20 +- python/port/mod/ulab/ndarray_operators.c | 4 +- python/port/mod/ulab/ndarray_properties.c | 12 +- python/port/mod/ulab/ndarray_properties.h | 22 +- .../port/mod/ulab/numpy/{approx => }/approx.c | 34 +-- .../port/mod/ulab/numpy/{approx => }/approx.h | 4 +- .../mod/ulab/numpy/{compare => }/compare.c | 16 +- .../mod/ulab/numpy/{compare => }/compare.h | 4 +- python/port/mod/ulab/numpy/fft/fft.c | 23 +- python/port/mod/ulab/numpy/fft/fft_tools.c | 2 +- .../port/mod/ulab/numpy/{filter => }/filter.c | 12 +- .../port/mod/ulab/numpy/{filter => }/filter.h | 4 +- python/port/mod/ulab/numpy/linalg/linalg.c | 145 ++++++++++- python/port/mod/ulab/numpy/linalg/linalg.h | 1 + .../port/mod/ulab/numpy/linalg/linalg_tools.c | 2 +- .../mod/ulab/numpy/ndarray/ndarray_iter.c | 66 +++++ .../mod/ulab/numpy/ndarray/ndarray_iter.h | 36 +++ .../ulab/numpy/{numerical => }/numerical.c | 83 ++++-- .../ulab/numpy/{numerical => }/numerical.h | 8 +- python/port/mod/ulab/numpy/numpy.c | 49 +++- python/port/mod/ulab/numpy/{poly => }/poly.c | 48 ++-- python/port/mod/ulab/numpy/{poly => }/poly.h | 6 +- .../port/mod/ulab/numpy/{stats => }/stats.c | 12 +- .../port/mod/ulab/numpy/{stats => }/stats.h | 4 +- .../ulab/numpy/{transform => }/transform.c | 15 +- .../ulab/numpy/{transform => }/transform.h | 10 +- .../port/mod/ulab/numpy/{vector => }/vector.c | 85 +++--- .../port/mod/ulab/numpy/{vector => }/vector.h | 4 +- python/port/mod/ulab/scipy/linalg/linalg.c | 24 +- .../port/mod/ulab/scipy/optimize/optimize.c | 16 +- python/port/mod/ulab/scipy/scipy.c | 2 +- python/port/mod/ulab/scipy/signal/signal.c | 8 +- python/port/mod/ulab/scipy/special/special.c | 4 +- python/port/mod/ulab/ulab.c | 35 ++- python/port/mod/ulab/ulab.h | 22 +- python/port/mod/ulab/ulab_create.c | 144 +---------- python/port/mod/ulab/ulab_tools.c | 2 +- python/port/mod/ulab/user/user.c | 6 +- python/port/mod/ulab/utils/utils.c | 6 +- 43 files changed, 666 insertions(+), 619 deletions(-) create mode 100644 python/port/mod/ulab/LICENSE rename python/port/mod/ulab/numpy/{approx => }/approx.c (89%) rename python/port/mod/ulab/numpy/{approx => }/approx.h (93%) rename python/port/mod/ulab/numpy/{compare => }/compare.c (98%) rename python/port/mod/ulab/numpy/{compare => }/compare.h (99%) rename python/port/mod/ulab/numpy/{filter => }/filter.c (95%) rename python/port/mod/ulab/numpy/{filter => }/filter.h (86%) create mode 100644 python/port/mod/ulab/numpy/ndarray/ndarray_iter.c create mode 100644 python/port/mod/ulab/numpy/ndarray/ndarray_iter.h rename python/port/mod/ulab/numpy/{numerical => }/numerical.c (95%) rename python/port/mod/ulab/numpy/{numerical => }/numerical.h (99%) rename python/port/mod/ulab/numpy/{poly => }/poly.c (94%) rename python/port/mod/ulab/numpy/{poly => }/poly.h (71%) rename python/port/mod/ulab/numpy/{stats => }/stats.c (87%) rename python/port/mod/ulab/numpy/{stats => }/stats.h (84%) rename python/port/mod/ulab/numpy/{transform => }/transform.c (94%) rename python/port/mod/ulab/numpy/{transform => }/transform.h (75%) rename python/port/mod/ulab/numpy/{vector => }/vector.c (90%) rename python/port/mod/ulab/numpy/{vector => }/vector.h (99%) diff --git a/python/Makefile b/python/Makefile index d9ac8de19..a957082c1 100644 --- a/python/Makefile +++ b/python/Makefile @@ -169,19 +169,20 @@ port_src += $(addprefix python/port/,\ mod/ulab/ulab_tools.c \ mod/ulab/ndarray.c \ mod/ulab/ndarray_properties.c \ - mod/ulab/numpy/approx/approx.c \ - mod/ulab/numpy/compare/compare.c \ + mod/ulab/numpy/approx.c \ + mod/ulab/numpy/compare.c \ mod/ulab/ulab_create.c \ mod/ulab/numpy/fft/fft.c \ mod/ulab/numpy/fft/fft_tools.c \ - mod/ulab/numpy/filter/filter.c \ + mod/ulab/numpy/filter.c \ mod/ulab/numpy/linalg/linalg.c \ mod/ulab/numpy/linalg/linalg_tools.c \ - mod/ulab/numpy/numerical/numerical.c \ - mod/ulab/numpy/poly/poly.c \ - mod/ulab/numpy/stats/stats.c \ - mod/ulab/numpy/transform/transform.c \ - mod/ulab/numpy/vector/vector.c \ + mod/ulab/numpy/ndarray/ndarray_iter.c \ + mod/ulab/numpy/numerical.c \ + mod/ulab/numpy/poly.c \ + mod/ulab/numpy/stats.c \ + mod/ulab/numpy/transform.c \ + mod/ulab/numpy/vector.c \ mod/ulab/numpy/numpy.c \ mod/ulab/scipy/scipy.c \ mod/ulab/user/user.c \ diff --git a/python/port/genhdr/qstrdefs.in.h b/python/port/genhdr/qstrdefs.in.h index 91c67f9e8..ec26ab46f 100644 --- a/python/port/genhdr/qstrdefs.in.h +++ b/python/port/genhdr/qstrdefs.in.h @@ -581,6 +581,10 @@ Q(listdir) #if defined(INCLUDE_ULAB) // ulab QSTRs +Q(reduced) +Q(qr) +Q(flat) +Q(flatiter) Q(threshold) Q(edgeitems) Q(inplace) diff --git a/python/port/mod/ulab/LICENSE b/python/port/mod/ulab/LICENSE new file mode 100644 index 000000000..1d4df66d3 --- /dev/null +++ b/python/port/mod/ulab/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Zoltán Vörös + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/python/port/mod/ulab/ndarray.c b/python/port/mod/ulab/ndarray.c index e37802efe..45e19c262 100644 --- a/python/port/mod/ulab/ndarray.c +++ b/python/port/mod/ulab/ndarray.c @@ -16,11 +16,11 @@ #include #include #include -#include -#include -#include -#include -#include +#include "py/runtime.h" +#include "py/binary.h" +#include "py/obj.h" +#include "py/objtuple.h" +#include "py/objint.h" #include "ulab_tools.h" #include "ndarray.h" @@ -45,195 +45,6 @@ mp_uint_t ndarray_print_edgeitems = NDARRAY_PRINT_EDGEITEMS; //| possible. Numpy's documentation can be found at //| https://docs.scipy.org/doc/numpy/index.html""" //| -//| from typing import Dict -//| -//| _DType = int -//| """`ulab.int8`, `ulab.uint8`, `ulab.int16`, `ulab.uint16`, `ulab.float` or `ulab.bool`""" -//| -//| _float = float -//| """Type alias of the bulitin float""" -//| -//| _bool = bool -//| """Type alias of the bulitin bool""" -//| -//| _Index = Union[int, slice, ulab.ndarray, Tuple[Union[int, slice], ...]] -//| - -//| class ndarray: -//| """1- and 2- dimensional ndarray""" -//| -//| def __init__( -//| self, -//| values: Union[ndarray, Iterable[Union[_float, _bool, Iterable[Any]]]], -//| *, -//| dtype: _DType = ulab.float -//| ) -> None: -//| """:param sequence values: Sequence giving the initial content of the ndarray. -//| :param ~ulab._DType dtype: The type of ndarray values, `ulab.int8`, `ulab.uint8`, `ulab.int16`, `ulab.uint16`, `ulab.float` or `ulab.bool` -//| -//| The ``values`` sequence can either be another ~ulab.ndarray, sequence of numbers -//| (in which case a 1-dimensional ndarray is created), or a sequence where each -//| subsequence has the same length (in which case a 2-dimensional ndarray is -//| created). -//| -//| Passing a `ulab.ndarray` and a different dtype can be used to convert an ndarray -//| from one dtype to another. -//| -//| In many cases, it is more convenient to create an ndarray from a function -//| like `zeros` or `linspace`. -//| -//| `ulab.ndarray` implements the buffer protocol, so it can be used in many -//| places an `array.array` can be used.""" -//| ... -//| -//| shape: Tuple[int, ...] -//| """The size of the array, a tuple of length 1 or 2""" -//| -//| size: int -//| """The number of elements in the array""" -//| -//| itemsize: int -//| """The size of a single item in the array""" -//| -//| strides: Tuple[int, ...] -//| """Tuple of bytes to step in each dimension, a tuple of length 1 or 2""" -//| -//| def copy(self) -> ulab.ndarray: -//| """Return a copy of the array""" -//| ... -//| -//| def dtype(self) -> _DType: -//| """Returns the dtype of the array""" -//| ... -//| -//| def flatten(self, *, order: str = "C") -> ulab.ndarray: -//| """:param order: Whether to flatten by rows ('C') or columns ('F') -//| -//| Returns a new `ulab.ndarray` object which is always 1 dimensional. -//| If order is 'C' (the default", then the data is ordered in rows; -//| If it is 'F', then the data is ordered in columns. "C" and "F" refer -//| to the typical storage organization of the C and Fortran languages.""" -//| ... -//| -//| def reshape(self, shape: Tuple[int, ...]) -> ulab.ndarray: -//| """Returns an ndarray containing the same data with a new shape.""" -//| ... -//| -//| def sort(self, *, axis: Optional[int] = 1) -> None: -//| """:param axis: Whether to sort elements within rows (0), columns (1), or elements (None)""" -//| ... -//| -//| def tobytes(self) -> bytearray: -//| """Return the raw data bytes in the ndarray""" -//| ... -//| -//| def transpose(self) -> ulab.ndarray: -//| """Swap the rows and columns of a 2-dimensional ndarray""" -//| ... -//| -//| def __add__(self, other: Union[ndarray, _float]) -> ulab.ndarray: -//| """Adds corresponding elements of the two ndarrays, or adds a number to all -//| elements of the ndarray. If both arguments are ndarrays, their sizes must match.""" -//| ... -//| def __radd__(self, other: _float) -> ulab.ndarray: ... -//| -//| def __sub__(self, other: Union[ndarray, _float]) -> ulab.ndarray: -//| """Subtracts corresponding elements of the two ndarrays, or subtracts a number from all -//| elements of the ndarray. If both arguments are ndarrays, their sizes must match.""" -//| ... -//| def __rsub__(self, other: _float) -> ulab.ndarray: ... -//| -//| def __mul__(self, other: Union[ndarray, _float]) -> ulab.ndarray: -//| """Multiplies corresponding elements of the two ndarrays, or multiplies -//| all elements of the ndarray by a number. If both arguments are ndarrays, -//| their sizes must match.""" -//| ... -//| def __rmul__(self, other: _float) -> ulab.ndarray: ... -//| -//| def __div__(self, other: Union[ndarray, _float]) -> ulab.ndarray: -//| """Multiplies corresponding elements of the two ndarrays, or divides -//| all elements of the ndarray by a number. If both arguments are ndarrays, -//| their sizes must match.""" -//| ... -//| def __rdiv__(self, other: _float) -> ulab.ndarray: ... -//| -//| def __pow__(self, other: Union[ndarray, _float]) -> ulab.ndarray: -//| """Computes the power (x**y) of corresponding elements of the the two ndarrays, -//| or one number and one ndarray. If both arguments are ndarrays, their sizes -//| must match.""" -//| ... -//| def __rpow__(self, other: _float) -> ulab.ndarray: ... -//| -//| def __inv__(self) -> ulab.ndarray: -//| ... -//| def __neg__(self) -> ulab.ndarray: -//| ... -//| def __pos__(self) -> ulab.ndarray: -//| ... -//| def __abs__(self) -> ulab.ndarray: -//| ... -//| def __len__(self) -> int: -//| ... -//| def __lt__(self, other: Union[ndarray, _float]) -> ulab.ndarray: -//| ... -//| def __le__(self, other: Union[ndarray, _float]) -> ulab.ndarray: -//| ... -//| def __gt__(self, other: Union[ndarray, _float]) -> ulab.ndarray: -//| ... -//| def __ge__(self, other: Union[ndarray, _float]) -> ulab.ndarray: -//| ... -//| -//| def __iter__(self) -> Union[Iterator[ndarray], Iterator[_float]]: -//| ... -//| -//| def __getitem__(self, index: _Index) -> Union[ndarray, _float]: -//| """Retrieve an element of the ndarray.""" -//| ... -//| -//| def __setitem__(self, index: _Index, value: Union[ndarray, _float]) -> None: -//| """Set an element of the ndarray.""" -//| ... -//| -//| _ArrayLike = Union[ndarray, List[_float], Tuple[_float], range] -//| """`ulab.ndarray`, ``List[float]``, ``Tuple[float]`` or `range`""" -//| -//| int8: _DType -//| """Type code for signed integers in the range -128 .. 127 inclusive, like the 'b' typecode of `array.array`""" -//| -//| int16: _DType -//| """Type code for signed integers in the range -32768 .. 32767 inclusive, like the 'h' typecode of `array.array`""" -//| -//| float: _DType -//| """Type code for floating point values, like the 'f' typecode of `array.array`""" -//| -//| uint8: _DType -//| """Type code for unsigned integers in the range 0 .. 255 inclusive, like the 'H' typecode of `array.array`""" -//| -//| uint16: _DType -//| """Type code for unsigned integers in the range 0 .. 65535 inclusive, like the 'h' typecode of `array.array`""" -//| -//| bool: _DType -//| """Type code for boolean values""" -//| -//| def get_printoptions() -> Dict[str, int]: -//| """Get printing options""" -//| ... -//| -//| def set_printoptions(threshold: Optional[int] = None, edgeitems: Optional[int] = None) -> None: -//| """Set printing options""" -//| ... -//| -//| def ndinfo(array: ulab.ndarray) -> None: -//| ... -//| -//| def array( -//| values: Union[ndarray, Iterable[Union[_float, _bool, Iterable[Any]]]], -//| *, -//| dtype: _DType = ulab.float -//| ) -> ulab.ndarray: -//| """alternate constructor function for `ulab.ndarray`. Mirrors numpy.array""" -//| ... - #ifdef CIRCUITPY void ndarray_set_value(char typecode, void *p, size_t index, mp_obj_t val_in) { @@ -257,7 +68,7 @@ void ndarray_set_value(char typecode, void *p, size_t index, mp_obj_t val_in) { } #endif -#if defined(MICROPY_VERSION_MAJOR) && MICROPY_VERSION_MAJOR == 1 && MICROPY_VERSION_MINOR == 12 +#if defined(MICROPY_VERSION_MAJOR) && MICROPY_VERSION_MAJOR == 1 && MICROPY_VERSION_MINOR == 11 void mp_obj_slice_indices(mp_obj_t self_in, mp_int_t length, mp_bound_slice_t *result) { mp_obj_slice_t *self = MP_OBJ_TO_PTR(self_in); @@ -581,11 +392,13 @@ static void ndarray_print_row(const mp_print_t *print, ndarray_obj_t * ndarray, mp_print_str(print, "]"); } +#if ULAB_MAX_DIMS > 1 static void ndarray_print_bracket(const mp_print_t *print, const size_t condition, const size_t shape, const char *string) { if(condition < shape) { mp_print_str(print, string); } } +#endif void ndarray_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { (void)kind; @@ -596,9 +409,13 @@ void ndarray_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t ki mp_print_str(print, "[]"); if(self->ndim > 1) { mp_print_str(print, ", shape=("); + #if ULAB_MAX_DIMS > 1 for(uint8_t ndim = self->ndim; ndim > 1; ndim--) { mp_printf(MP_PYTHON_PRINTER, "%d,", self->shape[ULAB_MAX_DIMS - ndim]); } + #else + mp_printf(MP_PYTHON_PRINTER, "%d,", self->shape[0]); + #endif mp_printf(MP_PYTHON_PRINTER, "%d)", self->shape[ULAB_MAX_DIMS - 1]); } } else { @@ -1110,18 +927,6 @@ mp_obj_t ndarray_array_constructor(size_t n_args, const mp_obj_t *pos_args, mp_m } MP_DEFINE_CONST_FUN_OBJ_KW(ndarray_array_constructor_obj, 1, ndarray_array_constructor); -#ifdef CIRCUITPY -mp_obj_t ndarray_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { - (void) type; - mp_arg_check_num(n_args, kw_args, 1, 2, true); - size_t n_kw = 0; - if (kw_args != 0) { - n_kw = kw_args->used; - } - 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); -} -#else mp_obj_t ndarray_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) { (void) type; mp_arg_check_num(n_args, n_kw, 1, 2, true); @@ -1129,7 +934,6 @@ mp_obj_t ndarray_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, 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); } -#endif // broadcasting is used at a number of places, always include bool ndarray_can_broadcast(ndarray_obj_t *lhs, ndarray_obj_t *rhs, uint8_t *ndim, size_t *shape, int32_t *lstrides, int32_t *rstrides) { @@ -1555,12 +1359,12 @@ mp_obj_t ndarray_iternext(mp_obj_t self_in) { mp_obj_t ndarray_new_ndarray_iterator(mp_obj_t ndarray, mp_obj_iter_buf_t *iter_buf) { assert(sizeof(mp_obj_ndarray_it_t) <= sizeof(mp_obj_iter_buf_t)); - mp_obj_ndarray_it_t *o = (mp_obj_ndarray_it_t*)iter_buf; - o->base.type = &mp_type_polymorph_iter; - o->iternext = ndarray_iternext; - o->ndarray = ndarray; - o->cur = 0; - return MP_OBJ_FROM_PTR(o); + mp_obj_ndarray_it_t *iter = (mp_obj_ndarray_it_t *)iter_buf; + iter->base.type = &mp_type_polymorph_iter; + iter->iternext = ndarray_iternext; + iter->ndarray = ndarray; + iter->cur = 0; + return MP_OBJ_FROM_PTR(iter); } #endif /* NDARRAY_IS_ITERABLE */ @@ -1675,12 +1479,13 @@ mp_obj_t ndarray_itemsize(mp_obj_t self_in) { #if NDARRAY_HAS_SHAPE mp_obj_t ndarray_shape(mp_obj_t self_in) { ndarray_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_obj_t *items = m_new(mp_obj_t, self->ndim); - for(uint8_t i=0; i < self->ndim; i++) { - items[self->ndim - i - 1] = mp_obj_new_int(self->shape[ULAB_MAX_DIMS - i - 1]); + uint8_t nitems = MAX(1, self->ndim); + mp_obj_t *items = m_new(mp_obj_t, nitems); + for(uint8_t i = 0; i < nitems; i++) { + items[nitems - i - 1] = mp_obj_new_int(self->shape[ULAB_MAX_DIMS - i - 1]); } - mp_obj_t tuple = mp_obj_new_tuple(self->ndim, items); - m_del(mp_obj_t, items, self->ndim); + mp_obj_t tuple = mp_obj_new_tuple(nitems, items); + m_del(mp_obj_t, items, nitems); return tuple; } #endif diff --git a/python/port/mod/ulab/ndarray.h b/python/port/mod/ulab/ndarray.h index aa7f499af..04abd9659 100644 --- a/python/port/mod/ulab/ndarray.h +++ b/python/port/mod/ulab/ndarray.h @@ -39,7 +39,7 @@ typedef struct _mp_obj_float_t { mp_float_t value; } mp_obj_float_t; -#if defined(MICROPY_VERSION_MAJOR) && MICROPY_VERSION_MAJOR == 1 && MICROPY_VERSION_MINOR == 12 +#if defined(MICROPY_VERSION_MAJOR) && MICROPY_VERSION_MAJOR == 1 && MICROPY_VERSION_MINOR == 11 typedef struct _mp_obj_slice_t { mp_obj_base_t base; mp_obj_t start; @@ -49,6 +49,13 @@ typedef struct _mp_obj_slice_t { #define MP_ERROR_TEXT(x) x #endif +#if !defined(MP_TYPE_FLAG_EXTENDED) +#define MP_TYPE_CALL call +#define mp_type_get_call_slot(t) t->call +#define MP_TYPE_FLAG_EXTENDED (0) +#define MP_TYPE_EXTENDED_FIELDS(...) __VA_ARGS__ +#endif + #if !CIRCUITPY #define translate(x) MP_ERROR_TEXT(x) #define ndarray_set_value(a, b, c, d) mp_binary_set_val_array(a, b, c, d) @@ -96,15 +103,14 @@ typedef struct _dtype_obj_t { void ndarray_dtype_print(const mp_print_t *, mp_obj_t , mp_print_kind_t ); -#ifdef CIRCUITPY -mp_obj_t ndarray_dtype_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args); -#else mp_obj_t ndarray_dtype_make_new(const mp_obj_type_t *, size_t , size_t , const mp_obj_t *); -#endif /* CIRCUITPY */ #endif /* ULAB_HAS_DTYPE_OBJECT */ +extern const mp_obj_type_t ndarray_flatiter_type; + mp_obj_t ndarray_new_ndarray_iterator(mp_obj_t , mp_obj_iter_buf_t *); +mp_obj_t ndarray_get_item(ndarray_obj_t *, void *); mp_float_t ndarray_get_float_value(void *, uint8_t ); mp_float_t ndarray_get_float_index(void *, uint8_t , size_t ); bool ndarray_object_is_array_like(mp_obj_t ); @@ -135,11 +141,7 @@ ndarray_obj_t *ndarray_copy_view(ndarray_obj_t *); void ndarray_copy_array(ndarray_obj_t *, ndarray_obj_t *); MP_DECLARE_CONST_FUN_OBJ_KW(ndarray_array_constructor_obj); -#ifdef CIRCUITPY -mp_obj_t ndarray_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args); -#else mp_obj_t ndarray_make_new(const mp_obj_type_t *, size_t , size_t , const mp_obj_t *); -#endif mp_obj_t ndarray_subscr(mp_obj_t , mp_obj_t , mp_obj_t ); mp_obj_t ndarray_getiter(mp_obj_t , mp_obj_iter_buf_t *); bool ndarray_can_broadcast(ndarray_obj_t *, ndarray_obj_t *, uint8_t *, size_t *, int32_t *, int32_t *); diff --git a/python/port/mod/ulab/ndarray_operators.c b/python/port/mod/ulab/ndarray_operators.c index ac2386053..465140b65 100644 --- a/python/port/mod/ulab/ndarray_operators.c +++ b/python/port/mod/ulab/ndarray_operators.c @@ -11,8 +11,8 @@ #include -#include -#include +#include "py/runtime.h" +#include "py/objtuple.h" #include "ndarray.h" #include "ndarray_operators.h" #include "ulab.h" diff --git a/python/port/mod/ulab/ndarray_properties.c b/python/port/mod/ulab/ndarray_properties.c index 0fcf83bca..4a93fb823 100644 --- a/python/port/mod/ulab/ndarray_properties.c +++ b/python/port/mod/ulab/ndarray_properties.c @@ -14,11 +14,12 @@ #include #include #include -#include -#include +#include "py/obj.h" +#include "py/runtime.h" #include "ulab.h" #include "ndarray.h" +#include "numpy/ndarray/ndarray_iter.h" #ifndef CIRCUITPY @@ -51,6 +52,11 @@ void ndarray_properties_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { dest[0] = ndarray_dtype(self_in); break; #endif + #if NDARRAY_HAS_FLATITER + case MP_QSTR_flat: + dest[0] = ndarray_flatiter_make_new(self_in); + break; + #endif #if NDARRAY_HAS_ITEMSIZE case MP_QSTR_itemsize: dest[0] = ndarray_itemsize(self_in); @@ -83,11 +89,13 @@ void ndarray_properties_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } else { if(dest[1]) { switch(attr) { + #if ULAB_MAX_DIMS > 1 #if NDARRAY_HAS_RESHAPE case MP_QSTR_shape: ndarray_reshape_core(self_in, dest[1], 1); break; #endif + #endif default: return; break; diff --git a/python/port/mod/ulab/ndarray_properties.h b/python/port/mod/ulab/ndarray_properties.h index 9d3b4ee9b..28da7c063 100644 --- a/python/port/mod/ulab/ndarray_properties.h +++ b/python/port/mod/ulab/ndarray_properties.h @@ -7,19 +7,20 @@ * The MIT License (MIT) * * Copyright (c) 2020 Jeff Epler for Adafruit Industries - * 2020 Zoltán Vörös + * 2020-2021 Zoltán Vörös */ #ifndef _NDARRAY_PROPERTIES_ #define _NDARRAY_PROPERTIES_ -#include -#include -#include -#include +#include "py/runtime.h" +#include "py/binary.h" +#include "py/obj.h" +#include "py/objarray.h" #include "ulab.h" #include "ndarray.h" +#include "numpy/ndarray/ndarray_iter.h" #if CIRCUITPY typedef struct _mp_obj_property_t { @@ -37,6 +38,16 @@ STATIC const mp_obj_property_t ndarray_dtype_obj = { }; #endif /* NDARRAY_HAS_DTYPE */ +#if NDARRAY_HAS_FLATITER +MP_DEFINE_CONST_FUN_OBJ_1(ndarray_flatiter_make_new_obj, ndarray_flatiter_make_new); +STATIC const mp_obj_property_t ndarray_flat_obj = { + .base.type = &mp_type_property, + .proxy = {(mp_obj_t)&ndarray_flatiter_make_new_obj, + mp_const_none, + mp_const_none }, +}; +#endif /* NDARRAY_HAS_FLATITER */ + #if NDARRAY_HAS_ITEMSIZE MP_DEFINE_CONST_FUN_OBJ_1(ndarray_get_itemsize_obj, ndarray_itemsize); STATIC const mp_obj_property_t ndarray_itemsize_obj = { @@ -82,6 +93,7 @@ STATIC const mp_obj_property_t ndarray_strides_obj = { void ndarray_properties_attr(mp_obj_t , qstr , mp_obj_t *); MP_DEFINE_CONST_FUN_OBJ_1(ndarray_dtype_obj, ndarray_dtype); +MP_DEFINE_CONST_FUN_OBJ_1(ndarray_flatiter_make_new_obj, ndarray_flatiter_make_new); MP_DEFINE_CONST_FUN_OBJ_1(ndarray_itemsize_obj, ndarray_itemsize); MP_DEFINE_CONST_FUN_OBJ_1(ndarray_shape_obj, ndarray_shape); MP_DEFINE_CONST_FUN_OBJ_1(ndarray_size_obj, ndarray_size); diff --git a/python/port/mod/ulab/numpy/approx/approx.c b/python/port/mod/ulab/numpy/approx.c similarity index 89% rename from python/port/mod/ulab/numpy/approx/approx.c rename to python/port/mod/ulab/numpy/approx.c index 706a969a7..6ed5d7c2d 100644 --- a/python/port/mod/ulab/numpy/approx/approx.c +++ b/python/port/mod/ulab/numpy/approx.c @@ -13,12 +13,12 @@ #include #include #include -#include -#include -#include +#include "py/obj.h" +#include "py/runtime.h" +#include "py/misc.h" -#include "../../ulab.h" -#include "../../ulab_tools.h" +#include "../ulab.h" +#include "../ulab_tools.h" #include "approx.h" //| """Numerical approximation methods""" @@ -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.ndarray, -//| xp: ulab.ndarray, -//| fp: ulab.ndarray, +//| x: ulab.numpy.ndarray, +//| xp: ulab.numpy.ndarray, +//| fp: ulab.numpy.ndarray, //| *, -//| left: Optional[float] = None, -//| right: Optional[float] = None -//| ) -> ulab.ndarray: +//| left: Optional[_float] = None, +//| right: Optional[_float] = None +//| ) -> ulab.numpy.ndarray: //| """ -//| :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 ulab.numpy.ndarray x: The x-coordinates at which to evaluate the interpolated values. +//| :param ulab.numpy.ndarray xp: The x-coordinates of the data points, must be increasing +//| :param ulab.numpy.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]``. //| @@ -136,10 +136,10 @@ MP_DEFINE_CONST_FUN_OBJ_KW(approx_interp_obj, 2, approx_interp); #endif #if ULAB_NUMPY_HAS_TRAPZ -//| def trapz(y: ulab.ndarray, x: Optional[ulab.ndarray] = None, dx: float = 1.0) -> float: +//| def trapz(y: ulab.numpy.ndarray, x: Optional[ulab.numpy.ndarray] = None, dx: _float = 1.0) -> _float: //| """ -//| :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 1D ulab.numpy.ndarray y: the values of the dependent variable +//| :param 1D ulab.numpy.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. diff --git a/python/port/mod/ulab/numpy/approx/approx.h b/python/port/mod/ulab/numpy/approx.h similarity index 93% rename from python/port/mod/ulab/numpy/approx/approx.h rename to python/port/mod/ulab/numpy/approx.h index 7708bb789..487a98b58 100644 --- a/python/port/mod/ulab/numpy/approx/approx.h +++ b/python/port/mod/ulab/numpy/approx.h @@ -12,8 +12,8 @@ #ifndef _APPROX_ #define _APPROX_ -#include "../../ulab.h" -#include "../../ndarray.h" +#include "../ulab.h" +#include "../ndarray.h" #define APPROX_EPS MICROPY_FLOAT_CONST(1.0e-4) #define APPROX_NONZDELTA MICROPY_FLOAT_CONST(0.05) diff --git a/python/port/mod/ulab/numpy/compare/compare.c b/python/port/mod/ulab/numpy/compare.c similarity index 98% rename from python/port/mod/ulab/numpy/compare/compare.c rename to python/port/mod/ulab/numpy/compare.c index 73dfaa135..b9154569c 100644 --- a/python/port/mod/ulab/numpy/compare/compare.c +++ b/python/port/mod/ulab/numpy/compare.c @@ -13,13 +13,13 @@ #include #include #include -#include -#include -#include +#include "py/obj.h" +#include "py/runtime.h" +#include "py/misc.h" -#include "../../ulab.h" -#include "../../ndarray_operators.h" -#include "../../ulab_tools.h" +#include "../ulab.h" +#include "../ndarray_operators.h" +#include "../ulab_tools.h" #include "compare.h" static mp_obj_t compare_function(mp_obj_t x1, mp_obj_t x2, uint8_t op) { @@ -89,7 +89,7 @@ static mp_obj_t compare_function(mp_obj_t x1, mp_obj_t x2, uint8_t op) { } else if(rhs->dtype == NDARRAY_INT16) { RUN_COMPARE_LOOP(NDARRAY_FLOAT, mp_float_t, uint16_t, int16_t, larray, lstrides, rarray, rstrides, ndim, shape, op); } else if(rhs->dtype == NDARRAY_FLOAT) { - RUN_COMPARE_LOOP(NDARRAY_FLOAT, mp_float_t, uint8_t, mp_float_t, larray, lstrides, rarray, rstrides, ndim, shape, op); + RUN_COMPARE_LOOP(NDARRAY_FLOAT, mp_float_t, uint16_t, mp_float_t, larray, lstrides, rarray, rstrides, ndim, shape, op); } } else if(lhs->dtype == NDARRAY_INT16) { if(rhs->dtype == NDARRAY_UINT8) { @@ -101,7 +101,7 @@ static mp_obj_t compare_function(mp_obj_t x1, mp_obj_t x2, uint8_t op) { } else if(rhs->dtype == NDARRAY_INT16) { RUN_COMPARE_LOOP(NDARRAY_INT16, int16_t, int16_t, int16_t, larray, lstrides, rarray, rstrides, ndim, shape, op); } else if(rhs->dtype == NDARRAY_FLOAT) { - RUN_COMPARE_LOOP(NDARRAY_FLOAT, mp_float_t, uint16_t, mp_float_t, larray, lstrides, rarray, rstrides, ndim, shape, op); + RUN_COMPARE_LOOP(NDARRAY_FLOAT, mp_float_t, int16_t, mp_float_t, larray, lstrides, rarray, rstrides, ndim, shape, op); } } else if(lhs->dtype == NDARRAY_FLOAT) { if(rhs->dtype == NDARRAY_UINT8) { diff --git a/python/port/mod/ulab/numpy/compare/compare.h b/python/port/mod/ulab/numpy/compare.h similarity index 99% rename from python/port/mod/ulab/numpy/compare/compare.h rename to python/port/mod/ulab/numpy/compare.h index 12a559e0a..90ceaf7ce 100644 --- a/python/port/mod/ulab/numpy/compare/compare.h +++ b/python/port/mod/ulab/numpy/compare.h @@ -12,8 +12,8 @@ #ifndef _COMPARE_ #define _COMPARE_ -#include "../../ulab.h" -#include "../../ndarray.h" +#include "../ulab.h" +#include "../ndarray.h" enum COMPARE_FUNCTION_TYPE { COMPARE_EQUAL, diff --git a/python/port/mod/ulab/numpy/fft/fft.c b/python/port/mod/ulab/numpy/fft/fft.c index ff2373fe0..6f6534f49 100644 --- a/python/port/mod/ulab/numpy/fft/fft.c +++ b/python/port/mod/ulab/numpy/fft/fft.c @@ -14,22 +14,23 @@ #include #include #include -#include -#include -#include -#include -#include +#include "py/runtime.h" +#include "py/builtin.h" +#include "py/binary.h" +#include "py/obj.h" +#include "py/objarray.h" #include "fft.h" //| """Frequency-domain functions""" //| +//| import ulab.numpy -//| def fft(r: ulab.ndarray, c: Optional[ulab.ndarray] = None) -> Tuple[ulab.ndarray, ulab.ndarray]: +//| def fft(r: ulab.numpy.ndarray, c: Optional[ulab.numpy.ndarray] = None) -> Tuple[ulab.numpy.ndarray, ulab.numpy.ndarray]: //| """ -//| :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 +//| :param ulab.numpy.ndarray r: A 1-dimension array of values whose size is a power of 2 +//| :param ulab.numpy.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 @@ -48,10 +49,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.ndarray, c: Optional[ulab.ndarray] = None) -> Tuple[ulab.ndarray, ulab.ndarray]: +//| def ifft(r: ulab.numpy.ndarray, c: Optional[ulab.numpy.ndarray] = None) -> Tuple[ulab.numpy.ndarray, ulab.numpy.ndarray]: //| """ -//| :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 +//| :param ulab.numpy.ndarray r: A 1-dimension array of values whose size is a power of 2 +//| :param ulab.numpy.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""" diff --git a/python/port/mod/ulab/numpy/fft/fft_tools.c b/python/port/mod/ulab/numpy/fft/fft_tools.c index ab737a850..6dd2ca47c 100644 --- a/python/port/mod/ulab/numpy/fft/fft_tools.c +++ b/python/port/mod/ulab/numpy/fft/fft_tools.c @@ -9,7 +9,7 @@ */ #include -#include +#include "py/runtime.h" #include "../../ndarray.h" #include "../../ulab_tools.h" diff --git a/python/port/mod/ulab/numpy/filter/filter.c b/python/port/mod/ulab/numpy/filter.c similarity index 95% rename from python/port/mod/ulab/numpy/filter/filter.c rename to python/port/mod/ulab/numpy/filter.c index 9be43946b..bf2d16cd4 100644 --- a/python/port/mod/ulab/numpy/filter/filter.c +++ b/python/port/mod/ulab/numpy/filter.c @@ -15,12 +15,12 @@ #include #include #include -#include -#include -#include +#include "py/obj.h" +#include "py/runtime.h" +#include "py/misc.h" -#include "../../ulab.h" -#include "../../scipy/signal/signal.h" +#include "../ulab.h" +#include "../scipy/signal/signal.h" #include "filter.h" #if ULAB_NUMPY_HAS_CONVOLVE @@ -57,7 +57,7 @@ mp_obj_t filter_convolve(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_a mp_float_t *outptr = (mp_float_t *)out->array; uint8_t *aarray = (uint8_t *)a->array; uint8_t *carray = (uint8_t *)c->array; - + int32_t off = len_c - 1; int32_t as = a->strides[ULAB_MAX_DIMS - 1] / a->itemsize; int32_t cs = c->strides[ULAB_MAX_DIMS - 1] / c->itemsize; diff --git a/python/port/mod/ulab/numpy/filter/filter.h b/python/port/mod/ulab/numpy/filter.h similarity index 86% rename from python/port/mod/ulab/numpy/filter/filter.h rename to python/port/mod/ulab/numpy/filter.h index 9b1ad1875..d6d0f1723 100644 --- a/python/port/mod/ulab/numpy/filter/filter.h +++ b/python/port/mod/ulab/numpy/filter.h @@ -13,8 +13,8 @@ #ifndef _FILTER_ #define _FILTER_ -#include "../../ulab.h" -#include "../../ndarray.h" +#include "../ulab.h" +#include "../ndarray.h" MP_DECLARE_CONST_FUN_OBJ_KW(filter_convolve_obj); #endif diff --git a/python/port/mod/ulab/numpy/linalg/linalg.c b/python/port/mod/ulab/numpy/linalg/linalg.c index 209330f86..596280fea 100644 --- a/python/port/mod/ulab/numpy/linalg/linalg.c +++ b/python/port/mod/ulab/numpy/linalg/linalg.c @@ -16,9 +16,9 @@ #include #include #include -#include -#include -#include +#include "py/obj.h" +#include "py/runtime.h" +#include "py/misc.h" #include "../../ulab.h" #include "../../ulab_tools.h" @@ -364,7 +364,141 @@ static mp_obj_t linalg_norm(size_t n_args, const mp_obj_t *pos_args, mp_map_t *k } MP_DEFINE_CONST_FUN_OBJ_KW(linalg_norm_obj, 1, linalg_norm); -// MP_DEFINE_CONST_FUN_OBJ_1(linalg_norm_obj, linalg_norm); + +#if ULAB_MAX_DIMS > 1 +//| def qr(m: ulab.numpy.ndarray) -> Tuple[ulab.numpy.ndarray, ulab.numpy.ndarray]: +//| """ +//| :param m: a matrix +//| :return tuple (Q, R): +//| +//| Factor the matrix a as QR, where Q is orthonormal and R is upper-triangular. +//| """ +//| ... +//| + +static mp_obj_t linalg_qr(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + static const mp_arg_t allowed_args[] = { + { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_rom_obj = mp_const_none } }, + { MP_QSTR_mode, MP_ARG_OBJ, { .u_rom_obj = MP_ROM_QSTR(MP_QSTR_reduced) } }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + + if(!mp_obj_is_type(args[0].u_obj, &ulab_ndarray_type)) { + mp_raise_TypeError(translate("operation is defined for ndarrays only")); + } + ndarray_obj_t *source = MP_OBJ_TO_PTR(args[0].u_obj); + if(source->ndim != 2) { + mp_raise_ValueError(translate("operation is defined for 2D arrays only")); + } + + size_t m = source->shape[ULAB_MAX_DIMS - 2]; // rows + size_t n = source->shape[ULAB_MAX_DIMS - 1]; // columns + + ndarray_obj_t *Q = ndarray_new_dense_ndarray(2, ndarray_shape_vector(0, 0, m, m), NDARRAY_FLOAT); + ndarray_obj_t *R = ndarray_new_dense_ndarray(2, source->shape, NDARRAY_FLOAT); + + mp_float_t *qarray = (mp_float_t *)Q->array; + mp_float_t *rarray = (mp_float_t *)R->array; + + // simply copy the entries of source to a float array + mp_float_t (*func)(void *) = ndarray_get_float_function(source->dtype); + uint8_t *sarray = (uint8_t *)source->array; + + for(size_t i = 0; i < m; i++) { + for(size_t j = 0; j < n; j++) { + *rarray++ = func(sarray); + sarray += source->strides[ULAB_MAX_DIMS - 1]; + } + sarray -= n * source->strides[ULAB_MAX_DIMS - 1]; + sarray += source->strides[ULAB_MAX_DIMS - 2]; + } + rarray -= m * n; + + // start with the unit matrix + for(size_t i = 0; i < m; i++) { + qarray[i * (m + 1)] = 1.0; + } + + for(size_t j = 0; j < n; j++) { // columns + for(size_t i = m - 1; i > j; i--) { // rows + mp_float_t c, s; + // Givens matrix: note that numpy uses a strange form of the rotation + // [[c s], + // [s -c]] + if(MICROPY_FLOAT_C_FUN(fabs)(rarray[i * n + j]) < LINALG_EPSILON) { // r[i, j] + c = (rarray[(i - 1) * n + j] >= 0.0) ? 1.0 : -1.0; // r[i-1, j] + s = 0.0; + } else if(MICROPY_FLOAT_C_FUN(fabs)(rarray[(i - 1) * n + j]) < LINALG_EPSILON) { // r[i-1, j] + c = 0.0; + s = (rarray[i * n + j] >= 0.0) ? -1.0 : 1.0; // r[i, j] + } else { + mp_float_t t, u; + if(MICROPY_FLOAT_C_FUN(fabs)(rarray[(i - 1) * n + j]) > MICROPY_FLOAT_C_FUN(fabs)(rarray[i * n + j])) { // r[i-1, j], r[i, j] + t = rarray[i * n + j] / rarray[(i - 1) * n + j]; // r[i, j]/r[i-1, j] + u = MICROPY_FLOAT_C_FUN(sqrt)(1 + t * t); + c = -1.0 / u; + s = c * t; + } else { + t = rarray[(i - 1) * n + j] / rarray[i * n + j]; // r[i-1, j]/r[i, j] + u = MICROPY_FLOAT_C_FUN(sqrt)(1 + t * t); + s = -1.0 / u; + c = s * t; + } + } + + mp_float_t r1, r2; + // update R: multiply with the rotation matrix from the left + for(size_t k = 0; k < n; k++) { + r1 = rarray[(i - 1) * n + k]; // r[i-1, k] + r2 = rarray[i * n + k]; // r[i, k] + rarray[(i - 1) * n + k] = c * r1 + s * r2; // r[i-1, k] + rarray[i * n + k] = s * r1 - c * r2; // r[i, k] + } + + // update Q: multiply with the transpose of the rotation matrix from the right + for(size_t k = 0; k < m; k++) { + r1 = qarray[k * m + (i - 1)]; + r2 = qarray[k * m + i]; + qarray[k * m + (i - 1)] = c * r1 + s * r2; + qarray[k * m + i] = s * r1 - c * r2; + } + } + } + + mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL)); + GET_STR_DATA_LEN(args[1].u_obj, mode, len); + if(memcmp(mode, "complete", 8) == 0) { + tuple->items[0] = MP_OBJ_FROM_PTR(Q); + tuple->items[1] = MP_OBJ_FROM_PTR(R); + } else if(memcmp(mode, "reduced", 7) == 0) { + size_t k = MAX(m, n) - MIN(m, n); + ndarray_obj_t *q = ndarray_new_dense_ndarray(2, ndarray_shape_vector(0, 0, m, m - k), NDARRAY_FLOAT); + ndarray_obj_t *r = ndarray_new_dense_ndarray(2, ndarray_shape_vector(0, 0, m - k, n), NDARRAY_FLOAT); + mp_float_t *qa = (mp_float_t *)q->array; + mp_float_t *ra = (mp_float_t *)r->array; + for(size_t i = 0; i < m; i++) { + memcpy(qa, qarray, (m - k) * q->itemsize); + qa += (m - k); + qarray += m; + } + for(size_t i = 0; i < m - k; i++) { + memcpy(ra, rarray, n * r->itemsize); + ra += n; + rarray += n; + } + tuple->items[0] = MP_OBJ_FROM_PTR(q); + tuple->items[1] = MP_OBJ_FROM_PTR(r); + } else { + mp_raise_ValueError(translate("mode must be complete, or reduced")); + } + return tuple; +} + +MP_DEFINE_CONST_FUN_OBJ_KW(linalg_qr_obj, 1, linalg_qr); +#endif STATIC const mp_rom_map_elem_t ulab_linalg_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_linalg) }, @@ -381,6 +515,9 @@ STATIC const mp_rom_map_elem_t ulab_linalg_globals_table[] = { #if ULAB_LINALG_HAS_INV { MP_ROM_QSTR(MP_QSTR_inv), (mp_obj_t)&linalg_inv_obj }, #endif + #if ULAB_LINALG_HAS_QR + { MP_ROM_QSTR(MP_QSTR_qr), (mp_obj_t)&linalg_qr_obj }, + #endif #endif #if ULAB_LINALG_HAS_NORM { MP_ROM_QSTR(MP_QSTR_norm), (mp_obj_t)&linalg_norm_obj }, diff --git a/python/port/mod/ulab/numpy/linalg/linalg.h b/python/port/mod/ulab/numpy/linalg/linalg.h index fc1867fb8..cf6b0adc7 100644 --- a/python/port/mod/ulab/numpy/linalg/linalg.h +++ b/python/port/mod/ulab/numpy/linalg/linalg.h @@ -23,4 +23,5 @@ MP_DECLARE_CONST_FUN_OBJ_1(linalg_det_obj); MP_DECLARE_CONST_FUN_OBJ_1(linalg_eig_obj); MP_DECLARE_CONST_FUN_OBJ_1(linalg_inv_obj); MP_DECLARE_CONST_FUN_OBJ_KW(linalg_norm_obj); +MP_DECLARE_CONST_FUN_OBJ_KW(linalg_qr_obj); #endif diff --git a/python/port/mod/ulab/numpy/linalg/linalg_tools.c b/python/port/mod/ulab/numpy/linalg/linalg_tools.c index cf48f1140..5e03a50ab 100644 --- a/python/port/mod/ulab/numpy/linalg/linalg_tools.c +++ b/python/port/mod/ulab/numpy/linalg/linalg_tools.c @@ -10,7 +10,7 @@ #include #include -#include +#include "py/runtime.h" #include "linalg_tools.h" diff --git a/python/port/mod/ulab/numpy/ndarray/ndarray_iter.c b/python/port/mod/ulab/numpy/ndarray/ndarray_iter.c new file mode 100644 index 000000000..8704836a3 --- /dev/null +++ b/python/port/mod/ulab/numpy/ndarray/ndarray_iter.c @@ -0,0 +1,66 @@ + +/* + * This file is part of the micropython-ulab project, + * + * https://github.com/v923z/micropython-ulab + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Zoltán Vörös + * +*/ + +#include +#include +#include +#include +#include "py/obj.h" +#include "py/runtime.h" + +#include "ndarray_iter.h" + +#ifdef NDARRAY_HAS_FLATITER +mp_obj_t ndarray_flatiter_make_new(mp_obj_t self_in) { + ndarray_flatiter_t *flatiter = m_new_obj(ndarray_flatiter_t); + flatiter->base.type = &ndarray_flatiter_type; + flatiter->iternext = ndarray_flatiter_next; + flatiter->ndarray = MP_OBJ_TO_PTR(self_in); + flatiter->cur = 0; + return flatiter; +} + +mp_obj_t ndarray_flatiter_next(mp_obj_t self_in) { + ndarray_flatiter_t *self = MP_OBJ_TO_PTR(self_in); + ndarray_obj_t *ndarray = MP_OBJ_TO_PTR(self->ndarray); + uint8_t *array = (uint8_t *)ndarray->array; + + if(self->cur < ndarray->len) { + uint32_t remainder = self->cur; + uint8_t i = ULAB_MAX_DIMS - 1; + do { + size_t div = (remainder / ndarray->shape[i]); + array += remainder * ndarray->strides[i]; + remainder -= div * ndarray->shape[i]; + i--; + } while(i > ULAB_MAX_DIMS - ndarray->ndim); + self->cur++; + return ndarray_get_item(ndarray, array); + } + return MP_OBJ_STOP_ITERATION; +} + +mp_obj_t ndarray_new_flatiterator(mp_obj_t flatiter_in, mp_obj_iter_buf_t *iter_buf) { + assert(sizeof(ndarray_flatiter_t) <= sizeof(mp_obj_iter_buf_t)); + ndarray_flatiter_t *iter = (ndarray_flatiter_t *)iter_buf; + ndarray_flatiter_t *flatiter = MP_OBJ_TO_PTR(flatiter_in); + iter->base.type = &mp_type_polymorph_iter; + iter->iternext = ndarray_flatiter_next; + iter->ndarray = flatiter->ndarray; + iter->cur = 0; + return MP_OBJ_FROM_PTR(iter); +} + +mp_obj_t ndarray_get_flatiterator(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) { + return ndarray_new_flatiterator(o_in, iter_buf); +} +#endif /* NDARRAY_HAS_FLATITER */ diff --git a/python/port/mod/ulab/numpy/ndarray/ndarray_iter.h b/python/port/mod/ulab/numpy/ndarray/ndarray_iter.h new file mode 100644 index 000000000..b3fc48db2 --- /dev/null +++ b/python/port/mod/ulab/numpy/ndarray/ndarray_iter.h @@ -0,0 +1,36 @@ + +/* + * This file is part of the micropython-ulab project, + * + * https://github.com/v923z/micropython-ulab + * + * The MIT License (MIT) + * + * Copyright (c) 2020 Jeff Epler for Adafruit Industries + * 2020-2021 Zoltán Vörös +*/ + +#ifndef _NDARRAY_ITER_ +#define _NDARRAY_ITER_ + +#include "py/runtime.h" +#include "py/binary.h" +#include "py/obj.h" +#include "py/objarray.h" + +#include "../../ulab.h" +#include "../../ndarray.h" + +// TODO: take simply mp_obj_ndarray_it_t from ndarray.c +typedef struct _mp_obj_ndarray_flatiter_t { + mp_obj_base_t base; + mp_fun_1_t iternext; + mp_obj_t ndarray; + size_t cur; +} ndarray_flatiter_t; + +mp_obj_t ndarray_get_flatiterator(mp_obj_t , mp_obj_iter_buf_t *); +mp_obj_t ndarray_flatiter_make_new(mp_obj_t ); +mp_obj_t ndarray_flatiter_next(mp_obj_t ); + +#endif \ No newline at end of file diff --git a/python/port/mod/ulab/numpy/numerical/numerical.c b/python/port/mod/ulab/numpy/numerical.c similarity index 95% rename from python/port/mod/ulab/numpy/numerical/numerical.c rename to python/port/mod/ulab/numpy/numerical.c index 7ee4edfa7..39a5f9791 100644 --- a/python/port/mod/ulab/numpy/numerical/numerical.c +++ b/python/port/mod/ulab/numpy/numerical.c @@ -14,14 +14,14 @@ #include #include #include -#include -#include -#include -#include -#include +#include "py/obj.h" +#include "py/objint.h" +#include "py/runtime.h" +#include "py/builtin.h" +#include "py/misc.h" -#include "../../ulab.h" -#include "../../ulab_tools.h" +#include "../ulab.h" +#include "../ulab_tools.h" #include "numerical.h" enum NUMERICAL_FUNCTION_TYPE { @@ -41,7 +41,33 @@ enum NUMERICAL_FUNCTION_TYPE { //| Most of these functions take an "axis" argument, which indicates whether to //| operate over the flattened array (None), or a particular axis (integer).""" //| -//| from ulab import _ArrayLike +//| from typing import Dict +//| +//| _ArrayLike = Union[ndarray, List[_float], Tuple[_float], range] +//| +//| _DType = int +//| """`ulab.numpy.int8`, `ulab.numpy.uint8`, `ulab.numpy.int16`, `ulab.numpy.uint16`, `ulab.numpy.float` or `ulab.numpy.bool`""" +//| +//| from builtins import float as _float +//| from builtins import bool as _bool +//| +//| int8: _DType +//| """Type code for signed integers in the range -128 .. 127 inclusive, like the 'b' typecode of `array.array`""" +//| +//| int16: _DType +//| """Type code for signed integers in the range -32768 .. 32767 inclusive, like the 'h' typecode of `array.array`""" +//| +//| float: _DType +//| """Type code for floating point values, like the 'f' typecode of `array.array`""" +//| +//| uint8: _DType +//| """Type code for unsigned integers in the range 0 .. 255 inclusive, like the 'H' typecode of `array.array`""" +//| +//| uint16: _DType +//| """Type code for unsigned integers in the range 0 .. 65535 inclusive, like the 'h' typecode of `array.array`""" +//| +//| bool: _DType +//| """Type code for boolean values""" //| static void numerical_reduce_axes(ndarray_obj_t *ndarray, int8_t axis, size_t *shape, int32_t *strides) { @@ -78,8 +104,7 @@ static mp_obj_t numerical_all_any(mp_obj_t oin, mp_obj_t axis, uint8_t optype) { } // always get a float, so that we don't have to resolve the dtype later mp_float_t (*func)(void *) = ndarray_get_float_function(ndarray->dtype); - // We set results to true here because it crash if it is NULL - ndarray_obj_t *results = mp_const_true; + ndarray_obj_t *results = NULL; uint8_t *rarray = NULL; shape_strides _shape_strides = tools_reduce_axes(ndarray, axis); if(axis != mp_const_none) { @@ -153,8 +178,16 @@ static mp_obj_t numerical_all_any(mp_obj_t oin, mp_obj_t axis, uint8_t optype) { array -= _shape_strides.strides[ULAB_MAX_DIMS - 2] * _shape_strides.shape[ULAB_MAX_DIMS - 2]; array += _shape_strides.strides[ULAB_MAX_DIMS - 3]; i++; - } while(i < _shape_strides.shape[ULAB_MAX_DIMS - 3]) + } while(i < _shape_strides.shape[ULAB_MAX_DIMS - 3]); #endif + if(axis == mp_const_none) { + // the innermost loop fell through, so return the result here + if(!anytype) { + return mp_const_false; + } else { + return mp_const_true; + } + } return results; } else if(mp_obj_is_int(oin) || mp_obj_is_float(oin)) { return mp_obj_is_true(oin) ? mp_const_true : mp_const_false; @@ -265,7 +298,7 @@ static mp_obj_t numerical_sum_mean_std_ndarray(ndarray_obj_t *ndarray, mp_obj_t if(ndarray->dtype == NDARRAY_FLOAT) { return mp_obj_new_float(M * ndarray->len); } else { - return mp_obj_new_int((int32_t)(M * ndarray->len)); + return mp_obj_new_int((int32_t)MICROPY_FLOAT_C_FUN(round)(M * ndarray->len)); } } else if(optype == NUMERICAL_MEAN) { return mp_obj_new_float(M); @@ -551,6 +584,7 @@ static mp_obj_t numerical_sort_helper(mp_obj_t oin, mp_obj_t axis, uint8_t inpla int8_t ax = 0; if(axis == mp_const_none) { // flatten the array + #if ULAB_MAX_DIMS > 1 for(uint8_t i=0; i < ULAB_MAX_DIMS - 1; i++) { ndarray->shape[i] = 0; ndarray->strides[i] = 0; @@ -558,6 +592,7 @@ static mp_obj_t numerical_sort_helper(mp_obj_t oin, mp_obj_t axis, uint8_t inpla ndarray->shape[ULAB_MAX_DIMS - 1] = ndarray->len; ndarray->strides[ULAB_MAX_DIMS - 1] = ndarray->itemsize; ndarray->ndim = 1; + #endif } else { ax = mp_obj_get_int(axis); if(ax < 0) ax += ndarray->ndim; @@ -630,7 +665,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(numerical_argmin_obj, 1, numerical_argmin); #endif #if ULAB_NUMPY_HAS_ARGSORT -//| def argsort(array: ulab.ndarray, *, axis: int = -1) -> ulab.ndarray: +//| def argsort(array: ulab.numpy.ndarray, *, axis: int = -1) -> ulab.numpy.ndarray: //| """Returns an array which gives indices into the input array from least to greatest.""" //| ... //| @@ -739,7 +774,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(numerical_argsort_obj, 1, numerical_argsort); #endif #if ULAB_NUMPY_HAS_CROSS -//| def cross(a: ulab.ndarray, b: ulab.ndarray) -> ulab.ndarray: +//| def cross(a: ulab.numpy.ndarray, b: ulab.numpy.ndarray) -> ulab.numpy.ndarray: //| """Return the cross product of two vectors of length 3""" //| ... //| @@ -817,7 +852,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.ndarray, *, n: int = 1, axis: int = -1) -> ulab.ndarray: +//| def diff(array: ulab.numpy.ndarray, *, n: int = 1, axis: int = -1) -> ulab.numpy.ndarray: //| """Return the numerical derivative of successive elements of the array, as //| an array. axis=None is not supported.""" //| ... @@ -898,7 +933,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(numerical_diff_obj, 1, numerical_diff); #endif #if ULAB_NUMPY_HAS_FLIP -//| def flip(array: ulab.ndarray, *, axis: Optional[int] = None) -> ulab.ndarray: +//| def flip(array: ulab.numpy.ndarray, *, axis: Optional[int] = None) -> ulab.numpy.ndarray: //| """Returns a new array that reverses the order of the elements along the //| given axis, or along all axes if axis is None.""" //| ... @@ -946,7 +981,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(numerical_flip_obj, 1, numerical_flip); #endif #if ULAB_NUMPY_HAS_MINMAX -//| def max(array: _ArrayLike, *, axis: Optional[int] = None) -> float: +//| def max(array: _ArrayLike, *, axis: Optional[int] = None) -> _float: //| """Return the maximum element of the 1D array""" //| ... //| @@ -959,7 +994,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(numerical_max_obj, 1, numerical_max); #endif #if ULAB_NUMPY_HAS_MEAN -//| def mean(array: _ArrayLike, *, axis: Optional[int] = None) -> float: +//| def mean(array: _ArrayLike, *, axis: Optional[int] = None) -> _float: //| """Return the mean element of the 1D array, as a number if axis is None, otherwise as an array.""" //| ... //| @@ -972,7 +1007,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(numerical_mean_obj, 1, numerical_mean); #endif #if ULAB_NUMPY_HAS_MEDIAN -//| def median(array: ulab.ndarray, *, axis: int = -1) -> ulab.ndarray: +//| def median(array: ulab.numpy.ndarray, *, axis: int = -1) -> ulab.numpy.ndarray: //| """Find the median value in an array along the given axis, or along all axes if axis is None.""" //| ... //| @@ -1072,7 +1107,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(numerical_median_obj, 1, numerical_median); #endif #if ULAB_NUMPY_HAS_MINMAX -//| def min(array: _ArrayLike, *, axis: Optional[int] = None) -> float: +//| def min(array: _ArrayLike, *, axis: Optional[int] = None) -> _float: //| """Return the minimum element of the 1D array""" //| ... //| @@ -1085,7 +1120,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(numerical_min_obj, 1, numerical_min); #endif #if ULAB_NUMPY_HAS_ROLL -//| def roll(array: ulab.ndarray, distance: int, *, axis: Optional[int] = None) -> None: +//| def roll(array: ulab.numpy.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.""" @@ -1250,7 +1285,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(numerical_roll_obj, 2, numerical_roll); #endif #if ULAB_NUMPY_HAS_SORT -//| def sort(array: ulab.ndarray, *, axis: int = -1) -> ulab.ndarray: +//| def sort(array: ulab.numpy.ndarray, *, axis: int = -1) -> ulab.numpy.ndarray: //| """Sort the array along the given axis, or along all axes if axis is None. //| The array is modified in place.""" //| ... @@ -1289,7 +1324,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(numerical_sort_inplace_obj, 1, numerical_sort_inplace #endif /* NDARRAY_HAS_SORT */ #if ULAB_NUMPY_HAS_STD -//| def std(array: _ArrayLike, *, axis: Optional[int] = None, ddof: int = 0) -> float: +//| def std(array: _ArrayLike, *, axis: Optional[int] = None, ddof: int = 0) -> _float: //| """Return the standard deviation of the array, as a number if axis is None, otherwise as an array.""" //| ... //| @@ -1326,7 +1361,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.ndarray]: +//| def sum(array: _ArrayLike, *, axis: Optional[int] = None) -> Union[_float, int, ulab.numpy.ndarray]: //| """Return the sum of the array, as a number if axis is None, otherwise as an array.""" //| ... //| diff --git a/python/port/mod/ulab/numpy/numerical/numerical.h b/python/port/mod/ulab/numpy/numerical.h similarity index 99% rename from python/port/mod/ulab/numpy/numerical/numerical.h rename to python/port/mod/ulab/numpy/numerical.h index ef7b95d74..8d2971cd4 100644 --- a/python/port/mod/ulab/numpy/numerical/numerical.h +++ b/python/port/mod/ulab/numpy/numerical.h @@ -12,8 +12,8 @@ #ifndef _NUMERICAL_ #define _NUMERICAL_ -#include "../../ulab.h" -#include "../../ndarray.h" +#include "../ulab.h" +#include "../ndarray.h" // TODO: implement cumsum @@ -201,7 +201,7 @@ } while(0) #define RUN_MEAN_STD(type, array, rarray, ss, div, isStd) do {\ - RUN_MEAN_STD1(type, (array), (results), (rarray), (ss), (div), (isStd));\ + RUN_MEAN_STD1(type, (array), (rarray), (ss), (div), (isStd));\ } while(0) #define RUN_ARGMIN(ndarray, type, array, results, rarray, shape, strides, index, op) do {\ @@ -444,7 +444,7 @@ #endif #if ULAB_MAX_DIMS == 4 -#define RUN_SUM(type, array, results, rarray, shape, strides, index) do {\ +#define RUN_SUM(type, array, results, rarray, ss) do {\ size_t j = 0;\ do {\ size_t k = 0;\ diff --git a/python/port/mod/ulab/numpy/numpy.c b/python/port/mod/ulab/numpy/numpy.c index 8d8f3ab6b..a6559ff8a 100644 --- a/python/port/mod/ulab/numpy/numpy.c +++ b/python/port/mod/ulab/numpy/numpy.c @@ -14,26 +14,45 @@ #include #include -#include +#include "py/runtime.h" #include "numpy.h" #include "../ulab_create.h" -#include "approx/approx.h" -#include "compare/compare.h" +#include "approx.h" +#include "compare.h" #include "fft/fft.h" -#include "filter/filter.h" +#include "filter.h" #include "linalg/linalg.h" -#include "numerical/numerical.h" -#include "stats/stats.h" -#include "transform/transform.h" -#include "poly/poly.h" -#include "vector/vector.h" +#include "numerical.h" +#include "stats.h" +#include "transform.h" +#include "poly.h" +#include "vector.h" //| """Compatibility layer for numpy""" //| //| class ndarray: ... +//| def get_printoptions() -> Dict[str, int]: +//| """Get printing options""" +//| ... +//| +//| def set_printoptions(threshold: Optional[int] = None, edgeitems: Optional[int] = None) -> None: +//| """Set printing options""" +//| ... +//| +//| def ndinfo(array: ulab.numpy.ndarray) -> None: +//| ... +//| +//| def array( +//| values: Union[ndarray, Iterable[Union[_float, _bool, Iterable[Any]]]], +//| *, +//| dtype: _DType = ulab.numpy.float +//| ) -> ulab.numpy.ndarray: +//| """alternate constructor function for `ulab.numpy.ndarray`. Mirrors numpy.array""" +//| ... + // math constants #if ULAB_NUMPY_HAS_E #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C @@ -127,7 +146,9 @@ static const mp_rom_map_elem_t ulab_numpy_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_concatenate), (mp_obj_t)&create_concatenate_obj }, #endif #if ULAB_NUMPY_HAS_DIAG - { MP_ROM_QSTR(MP_QSTR_diag), (mp_obj_t)&create_diag_obj }, + #if ULAB_MAX_DIMS > 1 + { MP_ROM_QSTR(MP_QSTR_diag), (mp_obj_t)&create_diag_obj }, + #endif #endif #if ULAB_NUMPY_HAS_EMPTY { MP_ROM_QSTR(MP_QSTR_empty), (mp_obj_t)&create_zeros_obj }, @@ -210,10 +231,14 @@ static const mp_rom_map_elem_t ulab_numpy_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_diff), (mp_obj_t)&numerical_diff_obj }, #endif #if ULAB_NUMPY_HAS_DOT - { MP_OBJ_NEW_QSTR(MP_QSTR_dot), (mp_obj_t)&transform_dot_obj }, + #if ULAB_MAX_DIMS > 1 + { MP_OBJ_NEW_QSTR(MP_QSTR_dot), (mp_obj_t)&transform_dot_obj }, + #endif #endif #if ULAB_NUMPY_HAS_TRACE - { MP_ROM_QSTR(MP_QSTR_trace), (mp_obj_t)&stats_trace_obj }, + #if ULAB_MAX_DIMS > 1 + { MP_ROM_QSTR(MP_QSTR_trace), (mp_obj_t)&stats_trace_obj }, + #endif #endif #if ULAB_NUMPY_HAS_FLIP { MP_OBJ_NEW_QSTR(MP_QSTR_flip), (mp_obj_t)&numerical_flip_obj }, diff --git a/python/port/mod/ulab/numpy/poly/poly.c b/python/port/mod/ulab/numpy/poly.c similarity index 94% rename from python/port/mod/ulab/numpy/poly/poly.c rename to python/port/mod/ulab/numpy/poly.c index c9a07655f..124d3bc86 100644 --- a/python/port/mod/ulab/numpy/poly/poly.c +++ b/python/port/mod/ulab/numpy/poly.c @@ -1,6 +1,6 @@ /* - * This file is part of the micropython-ulab project, + * This file is part of the micropython-ulab project, * * https://github.com/v923z/micropython-ulab * @@ -12,13 +12,13 @@ * 2020 Taku Fukada */ -#include -#include -#include +#include "py/obj.h" +#include "py/runtime.h" +#include "py/objarray.h" -#include "../../ulab.h" -#include "../linalg/linalg_tools.h" -#include "../../ulab_tools.h" +#include "../ulab.h" +#include "linalg/linalg_tools.h" +#include "../ulab_tools.h" #include "poly.h" #if ULAB_NUMPY_HAS_POLYFIT @@ -32,7 +32,7 @@ mp_obj_t poly_polyfit(size_t n_args, const mp_obj_t *args) { mp_float_t *x, *XT, *y, *prod; if(n_args == 2) { // only the y values are supplied - // TODO: this is actually not enough: the first argument can very well be a matrix, + // TODO: this is actually not enough: the first argument can very well be a matrix, // in which case we are between the rock and a hard place leny = (size_t)mp_obj_get_int(mp_obj_len_maybe(args[0])); deg = (uint8_t)mp_obj_get_int(args[1]); @@ -64,8 +64,8 @@ mp_obj_t poly_polyfit(size_t n_args, const mp_obj_t *args) { y = m_new(mp_float_t, leny); fill_array_iterable(y, args[1]); } - - // one could probably express X as a function of XT, + + // one could probably express X as a function of XT, // and thereby save RAM, because X is used only in the product XT = m_new(mp_float_t, (deg+1)*leny); // XT is a matrix of shape (deg+1, len) (rows, columns) for(size_t i=0; i < leny; i++) { // column index @@ -74,15 +74,15 @@ mp_obj_t poly_polyfit(size_t n_args, const mp_obj_t *args) { XT[i+j*leny] = XT[i+(j-1)*leny]*x[i]; } } - + prod = m_new(mp_float_t, (deg+1)*(deg+1)); // the product matrix is of shape (deg+1, deg+1) mp_float_t sum; for(uint8_t i=0; i < deg+1; i++) { // column index for(uint8_t j=0; j < deg+1; j++) { // row index sum = 0.0; for(size_t k=0; k < lenx; k++) { - // (j, k) * (k, i) - // Note that the second matrix is simply the transpose of the first: + // (j, k) * (k, i) + // Note that the second matrix is simply the transpose of the first: // X(k, i) = XT(i, k) = XT[k*lenx+i] sum += XT[j*lenx+k]*XT[i*lenx+k]; // X[k*(deg+1)+i]; } @@ -90,15 +90,15 @@ mp_obj_t poly_polyfit(size_t n_args, const mp_obj_t *args) { } } if(!linalg_invert_matrix(prod, deg+1)) { - // Although X was a Vandermonde matrix, whose inverse is guaranteed to exist, - // we bail out here, if prod couldn't be inverted: if the values in x are not all + // Although X was a Vandermonde matrix, whose inverse is guaranteed to exist, + // we bail out here, if prod couldn't be inverted: if the values in x are not all // distinct, prod is singular m_del(mp_float_t, XT, (deg+1)*lenx); m_del(mp_float_t, x, lenx); m_del(mp_float_t, y, lenx); m_del(mp_float_t, prod, (deg+1)*(deg+1)); mp_raise_ValueError(translate("could not invert Vandermonde matrix")); - } + } // at this point, we have the inverse of X^T * X // y is a column vector; x is free now, we can use it for storing intermediate values for(uint8_t i=0; i < deg+1; i++) { // row index @@ -110,12 +110,12 @@ mp_obj_t poly_polyfit(size_t n_args, const mp_obj_t *args) { } // XT is no longer needed m_del(mp_float_t, XT, (deg+1)*leny); - + ndarray_obj_t *beta = ndarray_new_linear_array(deg+1, NDARRAY_FLOAT); mp_float_t *betav = (mp_float_t *)beta->array; // x[0..(deg+1)] contains now the product X^T * y; we can get rid of y m_del(float, y, leny); - + // now, we calculate beta, i.e., we apply prod = (X^T * X)^(-1) on x = X^T * y; x is a column vector now for(uint8_t i=0; i < deg+1; i++) { sum = 0.0; @@ -127,7 +127,7 @@ mp_obj_t poly_polyfit(size_t n_args, const mp_obj_t *args) { m_del(mp_float_t, x, lenx); m_del(mp_float_t, prod, (deg+1)*(deg+1)); for(uint8_t i=0; i < (deg+1)/2; i++) { - // We have to reverse the array, for the leading coefficient comes first. + // We have to reverse the array, for the leading coefficient comes first. SWAP(mp_float_t, betav[i], betav[deg-i]); } return MP_OBJ_FROM_PTR(beta); @@ -147,13 +147,13 @@ mp_obj_t poly_polyval(mp_obj_t o_p, mp_obj_t o_x) { mp_float_t *p = m_new(mp_float_t, plen); mp_obj_iter_buf_t p_buf; mp_obj_t p_item, p_iterable = mp_getiter(o_p, &p_buf); - uint8_t i = 0; + uint8_t i = 0; while((p_item = mp_iternext(p_iterable)) != MP_OBJ_STOP_ITERATION) { p[i] = mp_obj_get_float(p_item); i++; } - // polynomials are going to be of type float, except, when both + // polynomials are going to be of type float, except, when both // the coefficients and the independent variable are integers ndarray_obj_t *ndarray; if(mp_obj_is_type(o_x, &ulab_ndarray_type)) { @@ -161,10 +161,10 @@ mp_obj_t poly_polyval(mp_obj_t o_p, mp_obj_t o_x) { uint8_t *sarray = (uint8_t *)source->array; ndarray = ndarray_new_dense_ndarray(source->ndim, source->shape, NDARRAY_FLOAT); mp_float_t *array = (mp_float_t *)ndarray->array; - + mp_float_t (*func)(void *) = ndarray_get_float_function(source->dtype); - // TODO: these loops are really nothing, but the re-impplementation of + // TODO: these loops are really nothing, but the re-impplementation of // ITERATE_VECTOR from vectorise.c. We could pass a function pointer here #if ULAB_MAX_DIMS > 3 size_t i = 0; @@ -207,7 +207,7 @@ mp_obj_t poly_polyval(mp_obj_t o_p, mp_obj_t o_x) { sarray += source->strides[ULAB_MAX_DIMS - 4]; i++; } while(i < source->shape[ULAB_MAX_DIMS - 4]); - #endif + #endif } else { // o_x had better be a one-dimensional standard iterable ndarray = ndarray_new_linear_array(mp_obj_get_int(mp_obj_len_maybe(o_x)), NDARRAY_FLOAT); diff --git a/python/port/mod/ulab/numpy/poly/poly.h b/python/port/mod/ulab/numpy/poly.h similarity index 71% rename from python/port/mod/ulab/numpy/poly/poly.h rename to python/port/mod/ulab/numpy/poly.h index cf66ab193..59cb9f514 100644 --- a/python/port/mod/ulab/numpy/poly/poly.h +++ b/python/port/mod/ulab/numpy/poly.h @@ -1,6 +1,6 @@ /* - * This file is part of the micropython-ulab project, + * This file is part of the micropython-ulab project, * * https://github.com/v923z/micropython-ulab * @@ -12,8 +12,8 @@ #ifndef _POLY_ #define _POLY_ -#include "../../ulab.h" -#include "../../ndarray.h" +#include "../ulab.h" +#include "../ndarray.h" MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(poly_polyfit_obj); MP_DECLARE_CONST_FUN_OBJ_2(poly_polyval_obj); diff --git a/python/port/mod/ulab/numpy/stats/stats.c b/python/port/mod/ulab/numpy/stats.c similarity index 87% rename from python/port/mod/ulab/numpy/stats/stats.c rename to python/port/mod/ulab/numpy/stats.c index 9172b2340..a63964fea 100644 --- a/python/port/mod/ulab/numpy/stats/stats.c +++ b/python/port/mod/ulab/numpy/stats.c @@ -15,18 +15,18 @@ #include #include #include -#include -#include -#include +#include "py/obj.h" +#include "py/runtime.h" +#include "py/misc.h" -#include "../../ulab.h" -#include "../../ulab_tools.h" +#include "../ulab.h" +#include "../ulab_tools.h" #include "stats.h" #if ULAB_MAX_DIMS > 1 #if ULAB_NUMPY_HAS_TRACE -//| def trace(m: ulab.numpy.ndarray) -> float: +//| def trace(m: ulab.numpy.ndarray) -> _float: //| """ //| :param m: a square matrix //| diff --git a/python/port/mod/ulab/numpy/stats/stats.h b/python/port/mod/ulab/numpy/stats.h similarity index 84% rename from python/port/mod/ulab/numpy/stats/stats.h rename to python/port/mod/ulab/numpy/stats.h index e5fab5f9f..62bba9ff4 100644 --- a/python/port/mod/ulab/numpy/stats/stats.h +++ b/python/port/mod/ulab/numpy/stats.h @@ -12,8 +12,8 @@ #ifndef _STATS_ #define _STATS_ -#include "../../ulab.h" -#include "../../ndarray.h" +#include "../ulab.h" +#include "../ndarray.h" MP_DECLARE_CONST_FUN_OBJ_1(stats_trace_obj); diff --git a/python/port/mod/ulab/numpy/transform/transform.c b/python/port/mod/ulab/numpy/transform.c similarity index 94% rename from python/port/mod/ulab/numpy/transform/transform.c rename to python/port/mod/ulab/numpy/transform.c index 71473f5c6..2c2d2dbdd 100644 --- a/python/port/mod/ulab/numpy/transform/transform.c +++ b/python/port/mod/ulab/numpy/transform.c @@ -12,17 +12,17 @@ #include #include #include -#include -#include -#include +#include "py/obj.h" +#include "py/runtime.h" +#include "py/misc.h" -#include "../../ulab.h" -#include "../../ulab_tools.h" +#include "../ulab.h" +#include "../ulab_tools.h" #include "transform.h" - +#if ULAB_MAX_DIMS > 1 #if ULAB_NUMPY_HAS_DOT -//| def dot(m1: ulab.numpy.ndarray, m2: ulab.numpy.ndarray) -> Union[ulab.numpy.ndarray, float]: +//| def dot(m1: ulab.numpy.ndarray, m2: ulab.numpy.ndarray) -> Union[ulab.numpy.ndarray, _float]: //| """ //| :param ~ulab.numpy.ndarray m1: a matrix, or a vector //| :param ~ulab.numpy.ndarray m2: a matrix, or a vector @@ -87,3 +87,4 @@ mp_obj_t transform_dot(mp_obj_t _m1, mp_obj_t _m2) { MP_DEFINE_CONST_FUN_OBJ_2(transform_dot_obj, transform_dot); #endif +#endif \ No newline at end of file diff --git a/python/port/mod/ulab/numpy/transform/transform.h b/python/port/mod/ulab/numpy/transform.h similarity index 75% rename from python/port/mod/ulab/numpy/transform/transform.h rename to python/port/mod/ulab/numpy/transform.h index ba4194e3b..f4a09b8ef 100644 --- a/python/port/mod/ulab/numpy/transform/transform.h +++ b/python/port/mod/ulab/numpy/transform.h @@ -15,12 +15,12 @@ #include #include #include -#include -#include -#include +#include "py/obj.h" +#include "py/runtime.h" +#include "py/misc.h" -#include "../../ulab.h" -#include "../../ulab_tools.h" +#include "../ulab.h" +#include "../ulab_tools.h" #include "transform.h" MP_DECLARE_CONST_FUN_OBJ_2(transform_dot_obj); diff --git a/python/port/mod/ulab/numpy/vector/vector.c b/python/port/mod/ulab/numpy/vector.c similarity index 90% rename from python/port/mod/ulab/numpy/vector/vector.c rename to python/port/mod/ulab/numpy/vector.c index bc8326c6d..ceba25598 100644 --- a/python/port/mod/ulab/numpy/vector/vector.c +++ b/python/port/mod/ulab/numpy/vector.c @@ -15,13 +15,13 @@ #include #include #include -#include -#include -#include -#include +#include "py/runtime.h" +#include "py/binary.h" +#include "py/obj.h" +#include "py/objarray.h" -#include "../../ulab.h" -#include "../../ulab_tools.h" +#include "../ulab.h" +#include "../ulab_tools.h" #include "vector.h" //| """Element-by-element functions @@ -30,8 +30,6 @@ //| applying the function to every element in the array. This is typically //| much more efficient than expressing the same operation as a Python loop.""" //| -//| from ulab import _DType, _ArrayLike -//| static mp_obj_t vectorise_generic_vector(mp_obj_t o_in, mp_float_t (*f)(mp_float_t)) { // Return a single value, if o_in is not iterable @@ -111,7 +109,7 @@ static mp_obj_t vectorise_generic_vector(mp_obj_t o_in, mp_float_t (*f)(mp_float } #if ULAB_NUMPY_HAS_ACOS -//| def acos(a: _ArrayLike) -> ulab.ndarray: +//| def acos(a: _ArrayLike) -> ulab.numpy.ndarray: //| """Computes the inverse cosine function""" //| ... //| @@ -121,7 +119,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(vectorise_acos_obj, vectorise_acos); #endif #if ULAB_NUMPY_HAS_ACOSH -//| def acosh(a: _ArrayLike) -> ulab.ndarray: +//| def acosh(a: _ArrayLike) -> ulab.numpy.ndarray: //| """Computes the inverse hyperbolic cosine function""" //| ... //| @@ -131,7 +129,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(vectorise_acosh_obj, vectorise_acosh); #endif #if ULAB_NUMPY_HAS_ASIN -//| def asin(a: _ArrayLike) -> ulab.ndarray: +//| def asin(a: _ArrayLike) -> ulab.numpy.ndarray: //| """Computes the inverse sine function""" //| ... //| @@ -141,7 +139,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(vectorise_asin_obj, vectorise_asin); #endif #if ULAB_NUMPY_HAS_ASINH -//| def asinh(a: _ArrayLike) -> ulab.ndarray: +//| def asinh(a: _ArrayLike) -> ulab.numpy.ndarray: //| """Computes the inverse hyperbolic sine function""" //| ... //| @@ -151,7 +149,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(vectorise_asinh_obj, vectorise_asinh); #endif #if ULAB_NUMPY_HAS_AROUND -//| def around(a: _ArrayLike, *, decimals: int = 0) -> ulab.ndarray: +//| def around(a: _ArrayLike, *, decimals: int = 0) -> ulab.numpy.ndarray: //| """Returns a new float array in which each element is rounded to //| ``decimals`` places.""" //| ... @@ -221,7 +219,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(vectorise_around_obj, 1, vectorise_around); #endif #if ULAB_NUMPY_HAS_ATAN -//| def atan(a: _ArrayLike) -> ulab.ndarray: +//| def atan(a: _ArrayLike) -> ulab.numpy.ndarray: //| """Computes the inverse tangent function; the return values are in the //| range [-pi/2,pi/2].""" //| ... @@ -232,7 +230,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(vectorise_atan_obj, vectorise_atan); #endif #if ULAB_NUMPY_HAS_ARCTAN2 -//| def arctan2(ya: _ArrayLike, xa: _ArrayLike) -> ulab.ndarray: +//| def arctan2(ya: _ArrayLike, xa: _ArrayLike) -> ulab.numpy.ndarray: //| """Computes the inverse tangent function of y/x; the return values are in //| the range [-pi, pi].""" //| ... @@ -315,7 +313,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(vectorise_arctan2_obj, vectorise_arctan2); #endif /* ULAB_VECTORISE_HAS_ARCTAN2 */ #if ULAB_NUMPY_HAS_ATANH -//| def atanh(a: _ArrayLike) -> ulab.ndarray: +//| def atanh(a: _ArrayLike) -> ulab.numpy.ndarray: //| """Computes the inverse hyperbolic tangent function""" //| ... //| @@ -325,7 +323,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(vectorise_atanh_obj, vectorise_atanh); #endif #if ULAB_NUMPY_HAS_CEIL -//| def ceil(a: _ArrayLike) -> ulab.ndarray: +//| def ceil(a: _ArrayLike) -> ulab.numpy.ndarray: //| """Rounds numbers up to the next whole number""" //| ... //| @@ -335,7 +333,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(vectorise_ceil_obj, vectorise_ceil); #endif #if ULAB_NUMPY_HAS_COS -//| def cos(a: _ArrayLike) -> ulab.ndarray: +//| def cos(a: _ArrayLike) -> ulab.numpy.ndarray: //| """Computes the cosine function""" //| ... //| @@ -345,7 +343,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(vectorise_cos_obj, vectorise_cos); #endif #if ULAB_NUMPY_HAS_COSH -//| def cosh(a: _ArrayLike) -> ulab.ndarray: +//| def cosh(a: _ArrayLike) -> ulab.numpy.ndarray: //| """Computes the hyperbolic cosine function""" //| ... //| @@ -355,7 +353,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(vectorise_cosh_obj, vectorise_cosh); #endif #if ULAB_NUMPY_HAS_DEGREES -//| def degrees(a: _ArrayLike) -> ulab.ndarray: +//| def degrees(a: _ArrayLike) -> ulab.numpy.ndarray: //| """Converts angles from radians to degrees""" //| ... //| @@ -372,7 +370,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(vectorise_degrees_obj, vectorise_degrees); #endif #if ULAB_SCIPY_SPECIAL_HAS_ERF -//| def erf(a: _ArrayLike) -> ulab.ndarray: +//| def erf(a: _ArrayLike) -> ulab.numpy.ndarray: //| """Computes the error function, which has applications in statistics""" //| ... //| @@ -382,7 +380,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(vectorise_erf_obj, vectorise_erf); #endif #if ULAB_SCIPY_SPECIAL_HAS_ERFC -//| def erfc(a: _ArrayLike) -> ulab.ndarray: +//| def erfc(a: _ArrayLike) -> ulab.numpy.ndarray: //| """Computes the complementary error function, which has applications in statistics""" //| ... //| @@ -392,7 +390,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(vectorise_erfc_obj, vectorise_erfc); #endif #if ULAB_NUMPY_HAS_EXP -//| def exp(a: _ArrayLike) -> ulab.ndarray: +//| def exp(a: _ArrayLike) -> ulab.numpy.ndarray: //| """Computes the exponent function.""" //| ... //| @@ -402,7 +400,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(vectorise_exp_obj, vectorise_exp); #endif #if ULAB_NUMPY_HAS_EXPM1 -//| def expm1(a: _ArrayLike) -> ulab.ndarray: +//| def expm1(a: _ArrayLike) -> ulab.numpy.ndarray: //| """Computes $e^x-1$. In certain applications, using this function preserves numeric accuracy better than the `exp` function.""" //| ... //| @@ -412,7 +410,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(vectorise_expm1_obj, vectorise_expm1); #endif #if ULAB_NUMPY_HAS_FLOOR -//| def floor(a: _ArrayLike) -> ulab.ndarray: +//| def floor(a: _ArrayLike) -> ulab.numpy.ndarray: //| """Rounds numbers up to the next whole number""" //| ... //| @@ -422,7 +420,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(vectorise_floor_obj, vectorise_floor); #endif #if ULAB_SCIPY_SPECIAL_HAS_GAMMA -//| def gamma(a: _ArrayLike) -> ulab.ndarray: +//| def gamma(a: _ArrayLike) -> ulab.numpy.ndarray: //| """Computes the gamma function""" //| ... //| @@ -432,7 +430,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(vectorise_gamma_obj, vectorise_gamma); #endif #if ULAB_SCIPY_SPECIAL_HAS_GAMMALN -//| def lgamma(a: _ArrayLike) -> ulab.ndarray: +//| def lgamma(a: _ArrayLike) -> ulab.numpy.ndarray: //| """Computes the natural log of the gamma function""" //| ... //| @@ -442,7 +440,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(vectorise_lgamma_obj, vectorise_lgamma); #endif #if ULAB_NUMPY_HAS_LOG -//| def log(a: _ArrayLike) -> ulab.ndarray: +//| def log(a: _ArrayLike) -> ulab.numpy.ndarray: //| """Computes the natural log""" //| ... //| @@ -452,7 +450,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(vectorise_log_obj, vectorise_log); #endif #if ULAB_NUMPY_HAS_LOG10 -//| def log10(a: _ArrayLike) -> ulab.ndarray: +//| def log10(a: _ArrayLike) -> ulab.numpy.ndarray: //| """Computes the log base 10""" //| ... //| @@ -462,7 +460,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(vectorise_log10_obj, vectorise_log10); #endif #if ULAB_NUMPY_HAS_LOG2 -//| def log2(a: _ArrayLike) -> ulab.ndarray: +//| def log2(a: _ArrayLike) -> ulab.numpy.ndarray: //| """Computes the log base 2""" //| ... //| @@ -472,7 +470,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(vectorise_log2_obj, vectorise_log2); #endif #if ULAB_NUMPY_HAS_RADIANS -//| def radians(a: _ArrayLike) -> ulab.ndarray: +//| def radians(a: _ArrayLike) -> ulab.numpy.ndarray: //| """Converts angles from degrees to radians""" //| ... //| @@ -489,7 +487,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(vectorise_radians_obj, vectorise_radians); #endif #if ULAB_NUMPY_HAS_SIN -//| def sin(a: _ArrayLike) -> ulab.ndarray: +//| def sin(a: _ArrayLike) -> ulab.numpy.ndarray: //| """Computes the sine function""" //| ... //| @@ -499,7 +497,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(vectorise_sin_obj, vectorise_sin); #endif #if ULAB_NUMPY_HAS_SINH -//| def sinh(a: _ArrayLike) -> ulab.ndarray: +//| def sinh(a: _ArrayLike) -> ulab.numpy.ndarray: //| """Computes the hyperbolic sine""" //| ... //| @@ -509,7 +507,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(vectorise_sinh_obj, vectorise_sinh); #endif #if ULAB_NUMPY_HAS_SQRT -//| def sqrt(a: _ArrayLike) -> ulab.ndarray: +//| def sqrt(a: _ArrayLike) -> ulab.numpy.ndarray: //| """Computes the square root""" //| ... //| @@ -519,7 +517,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(vectorise_sqrt_obj, vectorise_sqrt); #endif #if ULAB_NUMPY_HAS_TAN -//| def tan(a: _ArrayLike) -> ulab.ndarray: +//| def tan(a: _ArrayLike) -> ulab.numpy.ndarray: //| """Computes the tangent""" //| ... //| @@ -529,7 +527,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(vectorise_tan_obj, vectorise_tan); #endif #if ULAB_NUMPY_HAS_TANH -//| def tanh(a: _ArrayLike) -> ulab.ndarray: +//| def tanh(a: _ArrayLike) -> ulab.numpy.ndarray: //| """Computes the hyperbolic tangent""" //| ... @@ -549,7 +547,7 @@ static mp_obj_t vectorise_vectorized_function_call(mp_obj_t self_in, size_t n_ar ndarray_obj_t *ndarray = ndarray_new_dense_ndarray(source->ndim, source->shape, self->otypes); for(size_t i=0; i < source->len; i++) { avalue[0] = mp_binary_get_val_array(source->dtype, source->array, i); - fvalue = self->type->call(self->fun, 1, 0, avalue); + fvalue = self->type->MP_TYPE_CALL(self->fun, 1, 0, avalue); ndarray_set_value(self->otypes, ndarray->array, i, fvalue); } return MP_OBJ_FROM_PTR(ndarray); @@ -561,14 +559,14 @@ static mp_obj_t vectorise_vectorized_function_call(mp_obj_t self_in, size_t n_ar mp_obj_t iterable = mp_getiter(args[0], &iter_buf); size_t i=0; while ((avalue[0] = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { - fvalue = self->type->call(self->fun, 1, 0, avalue); + fvalue = self->type->MP_TYPE_CALL(self->fun, 1, 0, avalue); ndarray_set_value(self->otypes, ndarray->array, i, fvalue); i++; } return MP_OBJ_FROM_PTR(ndarray); } else if(mp_obj_is_int(args[0]) || mp_obj_is_float(args[0])) { ndarray_obj_t *ndarray = ndarray_new_linear_array(1, self->otypes); - fvalue = self->type->call(self->fun, 1, 0, args); + fvalue = self->type->MP_TYPE_CALL(self->fun, 1, 0, args); ndarray_set_value(self->otypes, ndarray->array, 0, fvalue); return MP_OBJ_FROM_PTR(ndarray); } else { @@ -579,15 +577,18 @@ static mp_obj_t vectorise_vectorized_function_call(mp_obj_t self_in, size_t n_ar const mp_obj_type_t vectorise_function_type = { { &mp_type_type }, + .flags = MP_TYPE_FLAG_EXTENDED, .name = MP_QSTR_, + MP_TYPE_EXTENDED_FIELDS( .call = vectorise_vectorized_function_call, + ) }; //| def vectorize( -//| f: Union[Callable[[int], float], Callable[[float], float]], +//| f: Union[Callable[[int], _float], Callable[[_float], _float]], //| *, //| otypes: Optional[_DType] = None -//| ) -> Callable[[_ArrayLike], ulab.ndarray]: +//| ) -> Callable[[_ArrayLike], ulab.numpy.ndarray]: //| """ //| :param callable f: The function to wrap //| :param otypes: List of array types that may be returned by the function. None is interpreted to mean the return value is float. @@ -605,7 +606,7 @@ static mp_obj_t vectorise_vectorize(size_t n_args, const mp_obj_t *pos_args, mp_ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); const mp_obj_type_t *type = mp_obj_get_type(args[0].u_obj); - if(type->call == NULL) { + if(mp_type_get_call_slot(type) == NULL) { mp_raise_TypeError(translate("first argument must be a callable")); } mp_obj_t _otypes = args[1].u_obj; diff --git a/python/port/mod/ulab/numpy/vector/vector.h b/python/port/mod/ulab/numpy/vector.h similarity index 99% rename from python/port/mod/ulab/numpy/vector/vector.h rename to python/port/mod/ulab/numpy/vector.h index 6b00a221b..dbd0b33ea 100644 --- a/python/port/mod/ulab/numpy/vector/vector.h +++ b/python/port/mod/ulab/numpy/vector.h @@ -12,8 +12,8 @@ #ifndef _VECTOR_ #define _VECTOR_ -#include "../../ulab.h" -#include "../../ndarray.h" +#include "../ulab.h" +#include "../ndarray.h" MP_DECLARE_CONST_FUN_OBJ_1(vectorise_acos_obj); MP_DECLARE_CONST_FUN_OBJ_1(vectorise_acosh_obj); diff --git a/python/port/mod/ulab/scipy/linalg/linalg.c b/python/port/mod/ulab/scipy/linalg/linalg.c index 0f1b933af..a7266a4a1 100644 --- a/python/port/mod/ulab/scipy/linalg/linalg.c +++ b/python/port/mod/ulab/scipy/linalg/linalg.c @@ -7,31 +7,31 @@ * The MIT License (MIT) * * Copyright (c) 2021 Vikas Udupa - * + * */ #include #include #include -#include -#include -#include +#include "py/obj.h" +#include "py/runtime.h" +#include "py/misc.h" #include "../../ulab.h" #include "../../ulab_tools.h" +#include "../../numpy/linalg/linalg_tools.h" #include "linalg.h" #if ULAB_SCIPY_HAS_LINALG_MODULE //| //| import ulab.scipy +//| import ulab.numpy //| //| """Linear algebra functions""" //| #if ULAB_MAX_DIMS > 1 -#define TOLERANCE 0.0000001 - //| def solve_triangular(A: ulab.numpy.ndarray, b: ulab.numpy.ndarray, lower: bool) -> ulab.numpy.ndarray: //| """ //| :param ~ulab.numpy.ndarray A: a matrix @@ -46,9 +46,9 @@ //| static mp_obj_t solve_triangular(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - + size_t i, j; - + static const mp_arg_t allowed_args[] = { { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_rom_obj = mp_const_none} } , { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_rom_obj = mp_const_none} } , @@ -64,7 +64,7 @@ static mp_obj_t solve_triangular(size_t n_args, const mp_obj_t *pos_args, mp_map ndarray_obj_t *A = MP_OBJ_TO_PTR(args[0].u_obj); ndarray_obj_t *b = MP_OBJ_TO_PTR(args[1].u_obj); - + if(!ndarray_is_dense(A) || !ndarray_is_dense(b)) { mp_raise_TypeError(translate("input must be a dense ndarray")); } @@ -82,7 +82,7 @@ static mp_obj_t solve_triangular(size_t n_args, const mp_obj_t *pos_args, mp_map // check if input matrix A is singular for (i = 0; i < A_rows; i++) { - if (MICROPY_FLOAT_C_FUN(fabs)(get_A_ele(A_arr)) < TOLERANCE) + if (MICROPY_FLOAT_C_FUN(fabs)(get_A_ele(A_arr)) < LINALG_EPSILON) mp_raise_ValueError(translate("input matrix is singular")); A_arr += A->strides[ULAB_MAX_DIMS - 2]; A_arr += A->strides[ULAB_MAX_DIMS - 1]; @@ -92,7 +92,7 @@ static mp_obj_t solve_triangular(size_t n_args, const mp_obj_t *pos_args, mp_map ndarray_obj_t *x = ndarray_new_dense_ndarray(b->ndim, b->shape, NDARRAY_FLOAT); mp_float_t *x_arr = (mp_float_t *)x->array; - + if (mp_obj_is_true(args[2].u_obj)) { // Solve the lower triangular matrix by iterating each row of A. // Start by finding the first unknown using the first row. @@ -166,7 +166,7 @@ static mp_obj_t cho_solve(mp_obj_t _L, mp_obj_t _b) { ndarray_obj_t *L = MP_OBJ_TO_PTR(_L); ndarray_obj_t *b = MP_OBJ_TO_PTR(_b); - + if(!ndarray_is_dense(L) || !ndarray_is_dense(b)) { mp_raise_TypeError(translate("input must be a dense ndarray")); } diff --git a/python/port/mod/ulab/scipy/optimize/optimize.c b/python/port/mod/ulab/scipy/optimize/optimize.c index 9218e6936..c2ed6fff8 100644 --- a/python/port/mod/ulab/scipy/optimize/optimize.c +++ b/python/port/mod/ulab/scipy/optimize/optimize.c @@ -13,9 +13,9 @@ */ #include -#include -#include -#include +#include "py/obj.h" +#include "py/runtime.h" +#include "py/misc.h" #include "../../ndarray.h" #include "../../ulab.h" @@ -30,7 +30,7 @@ static mp_float_t optimize_python_call(const mp_obj_type_t *type, mp_obj_t fun, // where f is defined in python. Takes a float, returns a float. // The array of mp_obj_t type must be supplied, as must the number of parameters (a, b, c...) in nparams fargs[0] = mp_obj_new_float(x); - return mp_obj_get_float(type->call(fun, nparams+1, 0, fargs)); + return mp_obj_get_float(type->MP_TYPE_CALL(fun, nparams+1, 0, fargs)); } #if ULAB_SCIPY_OPTIMIZE_HAS_BISECT @@ -70,7 +70,7 @@ STATIC mp_obj_t optimize_bisect(size_t n_args, const mp_obj_t *pos_args, mp_map_ mp_obj_t fun = args[0].u_obj; const mp_obj_type_t *type = mp_obj_get_type(fun); - if(type->call == NULL) { + if(mp_type_get_call_slot(type) == NULL) { mp_raise_TypeError(translate("first argument must be a function")); } mp_float_t xtol = mp_obj_get_float(args[3].u_obj); @@ -140,7 +140,7 @@ STATIC mp_obj_t optimize_fmin(size_t n_args, const mp_obj_t *pos_args, mp_map_t mp_obj_t fun = args[0].u_obj; const mp_obj_type_t *type = mp_obj_get_type(fun); - if(type->call == NULL) { + if(mp_type_get_call_slot(type) == NULL) { mp_raise_TypeError(translate("first argument must be a function")); } @@ -276,7 +276,7 @@ mp_obj_t optimize_curve_fit(size_t n_args, const mp_obj_t *pos_args, mp_map_t *k mp_obj_t fun = args[0].u_obj; const mp_obj_type_t *type = mp_obj_get_type(fun); - if(type->call == NULL) { + if(mp_type_get_call_slot(type) == NULL) { mp_raise_TypeError(translate("first argument must be a function")); } @@ -365,7 +365,7 @@ static mp_obj_t optimize_newton(size_t n_args, const mp_obj_t *pos_args, mp_map_ mp_obj_t fun = args[0].u_obj; const mp_obj_type_t *type = mp_obj_get_type(fun); - if(type->call == NULL) { + if(mp_type_get_call_slot(type) == NULL) { mp_raise_TypeError(translate("first argument must be a function")); } mp_float_t x = mp_obj_get_float(args[1].u_obj); diff --git a/python/port/mod/ulab/scipy/scipy.c b/python/port/mod/ulab/scipy/scipy.c index 3e3a8280f..c37aa4ee8 100644 --- a/python/port/mod/ulab/scipy/scipy.c +++ b/python/port/mod/ulab/scipy/scipy.c @@ -13,7 +13,7 @@ */ #include -#include +#include "py/runtime.h" #include "../ulab.h" #include "optimize/optimize.h" diff --git a/python/port/mod/ulab/scipy/signal/signal.c b/python/port/mod/ulab/scipy/signal/signal.c index 0dbafd2c1..cc559b598 100644 --- a/python/port/mod/ulab/scipy/signal/signal.c +++ b/python/port/mod/ulab/scipy/signal/signal.c @@ -14,16 +14,18 @@ #include #include -#include +#include "py/runtime.h" #include "../../ulab.h" #include "../../ndarray.h" #include "../../numpy/fft/fft_tools.h" #if ULAB_SCIPY_SIGNAL_HAS_SPECTROGRAM -//| def spectrogram(r: ulab.ndarray) -> ulab.ndarray: +//| import ulab.numpy +//| +//| def spectrogram(r: ulab.numpy.ndarray) -> ulab.numpy.ndarray: //| """ -//| :param ulab.ndarray r: A 1-dimension array of values whose size is a power of 2 +//| :param ulab.numpy.ndarray r: A 1-dimension array of values whose size is a power of 2 //| //| Computes the spectrum of the input signal. This is the absolute value of the (complex-valued) fft of the signal. //| This function is similar to scipy's ``scipy.signal.spectrogram``.""" diff --git a/python/port/mod/ulab/scipy/special/special.c b/python/port/mod/ulab/scipy/special/special.c index bd4cf87c4..82b53247d 100644 --- a/python/port/mod/ulab/scipy/special/special.c +++ b/python/port/mod/ulab/scipy/special/special.c @@ -13,10 +13,10 @@ */ #include -#include +#include "py/runtime.h" #include "../../ulab.h" -#include "../../numpy/vector/vector.h" +#include "../../numpy/vector.h" static const mp_rom_map_elem_t ulab_scipy_special_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_special) }, diff --git a/python/port/mod/ulab/ulab.c b/python/port/mod/ulab/ulab.c index d7a563c85..2b9ebd73f 100644 --- a/python/port/mod/ulab/ulab.c +++ b/python/port/mod/ulab/ulab.c @@ -14,27 +14,26 @@ #include #include #include -#include -#include -#include -#include +#include "py/runtime.h" +#include "py/binary.h" +#include "py/obj.h" +#include "py/objarray.h" #include "ulab.h" #include "ulab_create.h" #include "ndarray.h" #include "ndarray_properties.h" +#include "numpy/ndarray/ndarray_iter.h" #include "numpy/numpy.h" #include "scipy/scipy.h" -#include "numpy/fft/fft.h" -#include "numpy/linalg/linalg.h" // TODO: we should get rid of this; array.sort depends on it -#include "numpy/numerical/numerical.h" +#include "numpy/numerical.h" #include "user/user.h" #include "utils/utils.h" -#define ULAB_VERSION 3.1.0 +#define ULAB_VERSION 3.3.8 #define xstr(s) str(s) #define str(s) #s #define ULAB_VERSION_STRING xstr(ULAB_VERSION) xstr(-) xstr(ULAB_MAX_DIMS) xstr(D) @@ -70,6 +69,9 @@ STATIC const mp_rom_map_elem_t ulab_ndarray_locals_dict_table[] = { #if NDARRAY_HAS_DTYPE { MP_ROM_QSTR(MP_QSTR_dtype), MP_ROM_PTR(&ndarray_dtype_obj) }, #endif + #if NDARRAY_HAS_FLATITER + { MP_ROM_QSTR(MP_QSTR_flat), MP_ROM_PTR(&ndarray_flat_obj) }, + #endif #if NDARRAY_HAS_ITEMSIZE { MP_ROM_QSTR(MP_QSTR_itemsize), MP_ROM_PTR(&ndarray_itemsize_obj) }, #endif @@ -89,12 +91,15 @@ STATIC MP_DEFINE_CONST_DICT(ulab_ndarray_locals_dict, ulab_ndarray_locals_dict_t const mp_obj_type_t ulab_ndarray_type = { { &mp_type_type }, + .flags = MP_TYPE_FLAG_EXTENDED #if defined(MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE) && defined(MP_TYPE_FLAG_EQ_HAS_NEQ_TEST) - .flags = MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_EQ_HAS_NEQ_TEST, + | MP_TYPE_FLAG_EQ_CHECKS_OTHER_TYPE | MP_TYPE_FLAG_EQ_HAS_NEQ_TEST, #endif .name = MP_QSTR_ndarray, .print = ndarray_print, .make_new = ndarray_make_new, + .locals_dict = (mp_obj_dict_t*)&ulab_ndarray_locals_dict, + MP_TYPE_EXTENDED_FIELDS( #if NDARRAY_IS_SLICEABLE .subscr = ndarray_subscr, #endif @@ -111,7 +116,7 @@ const mp_obj_type_t ulab_ndarray_type = { .attr = ndarray_properties_attr, #endif .buffer_p = { .get_buffer = ndarray_get_buffer, }, - .locals_dict = (mp_obj_dict_t*)&ulab_ndarray_locals_dict, + ) }; #if ULAB_HAS_DTYPE_OBJECT @@ -123,6 +128,16 @@ const mp_obj_type_t ulab_dtype_type = { }; #endif +#if NDARRAY_HAS_FLATITER +const mp_obj_type_t ndarray_flatiter_type = { + { &mp_type_type }, + .name = MP_QSTR_flatiter, + MP_TYPE_EXTENDED_FIELDS( + .getiter = ndarray_get_flatiterator, + ) +}; +#endif + STATIC const mp_map_elem_t ulab_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_ulab) }, { MP_ROM_QSTR(MP_QSTR___version__), MP_ROM_PTR(&ulab_version_obj) }, diff --git a/python/port/mod/ulab/ulab.h b/python/port/mod/ulab/ulab.h index f57db68c6..248047c85 100644 --- a/python/port/mod/ulab/ulab.h +++ b/python/port/mod/ulab/ulab.h @@ -34,16 +34,22 @@ // Determines, whether scipy is defined in ulab. The sub-modules and functions // of scipy have to be defined separately +#ifndef ULAB_HAS_SCIPY #define ULAB_HAS_SCIPY (1) +#endif // The maximum number of dimensions the firmware should be able to support // Possible values lie between 1, and 4, inclusive +#ifndef ULAB_MAX_DIMS #define ULAB_MAX_DIMS 2 +#endif // By setting this constant to 1, iteration over array dimensions will be implemented // as a function (ndarray_rewind_array), instead of writing out the loops in macros // This reduces firmware size at the expense of speed +#ifndef ULAB_HAS_FUNCTION_ITERATOR #define ULAB_HAS_FUNCTION_ITERATOR (0) +#endif // If NDARRAY_IS_ITERABLE is 1, the ndarray object defines its own iterator function // This option saves approx. 250 bytes of flash space @@ -80,12 +86,8 @@ // 2 kB in the two-dimensional case, and around 4 kB in the four-dimensional case. #ifndef NDARRAY_BINARY_USES_FUN_POINTER -#if defined(DEVICE_N0100) -#define NDARRAY_BINARY_USES_FUN_POINTER (1) -#else #define NDARRAY_BINARY_USES_FUN_POINTER (0) #endif -#endif #ifndef NDARRAY_HAS_BINARY_OP_ADD #define NDARRAY_HAS_BINARY_OP_ADD (1) @@ -262,6 +264,12 @@ #define ULAB_NUMPY_HAS_NDINFO (1) #endif +// if this constant is set to 1, the interpreter can iterate +// over the flat array without copying any data +#ifndef NDARRAY_HAS_FLATITER +#define NDARRAY_HAS_FLATITER (1) +#endif + // frombuffer adds 600 bytes to the firmware #ifndef ULAB_NUMPY_HAS_FROMBUFFER #define ULAB_NUMPY_HAS_FROMBUFFER (1) @@ -367,6 +375,10 @@ #define ULAB_LINALG_HAS_NORM (1) #endif +#ifndef ULAB_LINALG_HAS_QR +#define ULAB_LINALG_HAS_QR (1) +#endif + // the FFT module; functions of the fft module still have // to be defined separately #ifndef ULAB_NUMPY_HAS_FFT_MODULE @@ -638,7 +650,7 @@ #endif #ifndef ULAB_HAS_UTILS_MODULE -#define ULAB_HAS_UTILS_MODULE (0) +#define ULAB_HAS_UTILS_MODULE (1) #endif #ifndef ULAB_UTILS_HAS_FROM_INT16_BUFFER diff --git a/python/port/mod/ulab/ulab_create.c b/python/port/mod/ulab/ulab_create.c index 2cb8f2325..a93ec741b 100644 --- a/python/port/mod/ulab/ulab_create.c +++ b/python/port/mod/ulab/ulab_create.c @@ -14,8 +14,8 @@ #include #include #include -#include -#include +#include "py/obj.h" +#include "py/runtime.h" #include "ulab.h" #include "ulab_create.h" @@ -89,24 +89,6 @@ static ndarray_obj_t *create_linspace_arange(mp_float_t start, mp_float_t step, #endif #if ULAB_NUMPY_HAS_ARANGE -//| @overload -//| def arange(stop: _float, step: _float = 1, *, dtype: _DType = ulab.float) -> ulab.ndarray: ... -//| @overload -//| def arange(start: _float, stop: _float, step: _float = 1, *, dtype: _DType = ulab.float) -> ulab.ndarray: -//| """ -//| .. param: start -//| First value in the array, optional, defaults to 0 -//| .. param: stop -//| Final value in the array -//| .. param: step -//| Difference between consecutive elements, optional, defaults to 1.0 -//| .. param: dtype -//| Type of values in the array -//| -//| Return a new 1-D array with elements ranging from ``start`` to ``stop``, with step size ``step``.""" -//| ... -//| - mp_obj_t create_arange(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_rom_obj = mp_const_none } }, @@ -157,17 +139,6 @@ MP_DEFINE_CONST_FUN_OBJ_KW(create_arange_obj, 1, create_arange); #endif #if ULAB_NUMPY_HAS_CONCATENATE -//| def concatenate(arrays: Tuple[ulab.ndarray], *, axis: int = 0) -> ulab.ndarray: -//| """ -//| .. param: arrays -//| tuple of ndarrays -//| .. param: axis -//| axis along which the arrays will be joined -//| -//| Join a sequence of arrays along an existing axis.""" -//| ... -//| - mp_obj_t create_concatenate(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_rom_obj = mp_const_none } }, @@ -281,17 +252,8 @@ mp_obj_t create_concatenate(size_t n_args, const mp_obj_t *pos_args, mp_map_t *k MP_DEFINE_CONST_FUN_OBJ_KW(create_concatenate_obj, 1, create_concatenate); #endif +#if ULAB_MAX_DIMS > 1 #if ULAB_NUMPY_HAS_DIAG -//| def diag(a: ulab.ndarray, *, k: int = 0) -> ulab.ndarray: -//| """ -//| .. param: a -//| an ndarray -//| .. param: k -//| Offset of the diagonal from the main diagonal. Can be positive or negative. -//| -//| Return specified diagonals.""" -//| ... -//| mp_obj_t create_diag(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_rom_obj = mp_const_none } }, @@ -353,14 +315,7 @@ mp_obj_t create_diag(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) MP_DEFINE_CONST_FUN_OBJ_KW(create_diag_obj, 1, create_diag); #endif /* ULAB_NUMPY_HAS_DIAG */ -#if ULAB_MAX_DIMS > 1 #if ULAB_NUMPY_HAS_EYE -//| def eye(size: int, *, M: Optional[int] = None, k: int = 0, dtype: _DType = ulab.float) -> ulab.ndarray: -//| """Return a new square array of size, with the diagonal elements set to 1 -//| and the other elements set to 0.""" -//| ... -//| - mp_obj_t create_eye(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_INT, { .u_int = 0 } }, @@ -407,19 +362,6 @@ MP_DEFINE_CONST_FUN_OBJ_KW(create_eye_obj, 1, create_eye); #endif /* ULAB_MAX_DIMS > 1 */ #if ULAB_NUMPY_HAS_FULL -//| def full(shape: Union[int, Tuple[int, ...]], fill_value: Union[_float, _bool], *, dtype: _DType = ulab.float) -> ulab.ndarray: -//| """ -//| .. param: shape -//| Shape of the array, either an integer (for a 1-D array) or a tuple of integers (for tensors of higher rank) -//| .. param: fill_value -//| scalar, the value with which the array is filled -//| .. param: dtype -//| Type of values in the array -//| -//| Return a new array of the given shape with all elements set to 0.""" -//| ... -//| - mp_obj_t create_full(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_obj = MP_OBJ_NULL } }, @@ -440,35 +382,6 @@ MP_DEFINE_CONST_FUN_OBJ_KW(create_full_obj, 0, create_full); #if ULAB_NUMPY_HAS_LINSPACE -//| def linspace( -//| start: _float, -//| stop: _float, -//| *, -//| dtype: _DType = ulab.float, -//| num: int = 50, -//| endpoint: _bool = True, -//| retstep: _bool = False -//| ) -> ulab.ndarray: -//| """ -//| .. param: start -//| First value in the array -//| .. param: stop -//| Final value in the array -//| .. param int: num -//| Count of values in the array. -//| .. param: dtype -//| Type of values in the array -//| .. param bool: endpoint -//| Whether the ``stop`` value is included. Note that even when -//| endpoint=True, the exact ``stop`` value may not be included due to the -//| inaccuracy of floating point arithmetic. -// .. param bool: retstep, -//| If True, return (`samples`, `step`), where `step` is the spacing between samples. -//| -//| Return a new 1-D array with ``num`` elements ranging from ``start`` to ``stop`` linearly.""" -//| ... -//| - mp_obj_t create_linspace(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_, MP_ARG_REQUIRED | MP_ARG_OBJ, { .u_rom_obj = mp_const_none } }, @@ -506,37 +419,6 @@ MP_DEFINE_CONST_FUN_OBJ_KW(create_linspace_obj, 2, create_linspace); #endif #if ULAB_NUMPY_HAS_LOGSPACE -//| def logspace( -//| start: _float, -//| stop: _float, -//| *, -//| dtype: _DType = ulab.float, -//| num: int = 50, -//| endpoint: _bool = True, -//| base: _float = 10.0 -//| ) -> ulab.ndarray: -//| """ -//| .. param: start -//| First value in the array -//| .. param: stop -//| Final value in the array -//| .. param int: num -//| Count of values in the array. Defaults to 50. -//| .. param: base -//| The base of the log space. The step size between the elements in -//| ``ln(samples) / ln(base)`` (or ``log_base(samples)``) is uniform. Defaults to 10.0. -//| .. param: dtype -//| Type of values in the array -//| .. param bool: endpoint -//| Whether the ``stop`` value is included. Note that even when -//| endpoint=True, the exact ``stop`` value may not be included due to the -//| inaccuracy of floating point arithmetic. Defaults to True. -//| -//| Return a new 1-D array with ``num`` evenly spaced elements on a log scale. -//| The sequence starts at ``base ** start``, and ends with ``base ** stop``.""" -//| ... -//| - const mp_obj_float_t create_float_const_ten = {{&mp_type_float}, MICROPY_FLOAT_CONST(10.0)}; mp_obj_t create_logspace(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { @@ -593,16 +475,6 @@ MP_DEFINE_CONST_FUN_OBJ_KW(create_logspace_obj, 2, create_logspace); #endif #if ULAB_NUMPY_HAS_ONES -//| def ones(shape: Union[int, Tuple[int, ...]], *, dtype: _DType = ulab.float) -> ulab.ndarray: -//| """ -//| .. param: shape -//| Shape of the array, either an integer (for a 1-D array) or a tuple of 2 integers (for a 2-D array) -//| .. param: dtype -//| Type of values in the array -//| -//| Return a new array of the given shape with all elements set to 1.""" -//| ... -//| mp_obj_t create_ones(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { @@ -622,16 +494,6 @@ MP_DEFINE_CONST_FUN_OBJ_KW(create_ones_obj, 0, create_ones); #endif #if ULAB_NUMPY_HAS_ZEROS -//| def zeros(shape: Union[int, Tuple[int, ...]], *, dtype: _DType = ulab.float) -> ulab.ndarray: -//| """ -//| .. param: shape -//| Shape of the array, either an integer (for a 1-D array) or a tuple of 2 integers (for a 2-D array) -//| .. param: dtype -//| Type of values in the array -//| -//| Return a new array of the given shape with all elements set to 0.""" -//| ... -//| mp_obj_t create_zeros(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { diff --git a/python/port/mod/ulab/ulab_tools.c b/python/port/mod/ulab/ulab_tools.c index dd93787ba..acd3d8a58 100644 --- a/python/port/mod/ulab/ulab_tools.c +++ b/python/port/mod/ulab/ulab_tools.c @@ -10,7 +10,7 @@ #include -#include +#include "py/runtime.h" #include "ulab.h" #include "ndarray.h" diff --git a/python/port/mod/ulab/user/user.c b/python/port/mod/ulab/user/user.c index be7c6d0a0..835c091c7 100644 --- a/python/port/mod/ulab/user/user.c +++ b/python/port/mod/ulab/user/user.c @@ -12,9 +12,9 @@ #include #include #include -#include -#include -#include +#include "py/obj.h" +#include "py/runtime.h" +#include "py/misc.h" #include "user.h" #if ULAB_HAS_USER_MODULE diff --git a/python/port/mod/ulab/utils/utils.c b/python/port/mod/ulab/utils/utils.c index 6ff787b3b..2b7dc093c 100644 --- a/python/port/mod/ulab/utils/utils.c +++ b/python/port/mod/ulab/utils/utils.c @@ -11,9 +11,9 @@ #include #include #include -#include -#include -#include +#include "py/obj.h" +#include "py/runtime.h" +#include "py/misc.h" #include "utils.h" #if ULAB_HAS_UTILS_MODULE