[python/ulab] Updated ulab

This commit is contained in:
Laury
2021-12-17 21:36:19 +01:00
parent d5dbb8df6f
commit ed06b4e48b
43 changed files with 666 additions and 619 deletions

View File

@@ -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 \

View File

@@ -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)

View File

@@ -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.

View File

@@ -16,11 +16,11 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <py/runtime.h>
#include <py/binary.h>
#include <py/obj.h>
#include <py/objtuple.h>
#include <py/objint.h>
#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

View File

@@ -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 *);

View File

@@ -11,8 +11,8 @@
#include <math.h>
#include <py/runtime.h>
#include <py/objtuple.h>
#include "py/runtime.h"
#include "py/objtuple.h"
#include "ndarray.h"
#include "ndarray_operators.h"
#include "ulab.h"

View File

@@ -14,11 +14,12 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <py/obj.h>
#include <py/runtime.h>
#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;

View File

@@ -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 <py/runtime.h>
#include <py/binary.h>
#include <py/obj.h>
#include <py/objarray.h>
#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);

View File

@@ -13,12 +13,12 @@
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <py/obj.h>
#include <py/runtime.h>
#include <py/misc.h>
#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.

View File

@@ -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)

View File

@@ -13,13 +13,13 @@
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <py/obj.h>
#include <py/runtime.h>
#include <py/misc.h>
#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) {

View File

@@ -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,

View File

@@ -14,22 +14,23 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <py/runtime.h>
#include <py/builtin.h>
#include <py/binary.h>
#include <py/obj.h>
#include <py/objarray.h>
#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"""

View File

@@ -9,7 +9,7 @@
*/
#include <math.h>
#include <py/runtime.h>
#include "py/runtime.h"
#include "../../ndarray.h"
#include "../../ulab_tools.h"

View File

@@ -15,12 +15,12 @@
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <py/obj.h>
#include <py/runtime.h>
#include <py/misc.h>
#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;

View File

@@ -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

View File

@@ -16,9 +16,9 @@
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <py/obj.h>
#include <py/runtime.h>
#include <py/misc.h>
#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 },

View File

@@ -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

View File

@@ -10,7 +10,7 @@
#include <math.h>
#include <string.h>
#include <py/runtime.h>
#include "py/runtime.h"
#include "linalg_tools.h"

View File

@@ -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 <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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 */

View File

@@ -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

View File

@@ -14,14 +14,14 @@
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <py/obj.h>
#include <py/objint.h>
#include <py/runtime.h>
#include <py/builtin.h>
#include <py/misc.h>
#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."""
//| ...
//|

View File

@@ -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;\

View File

@@ -14,26 +14,45 @@
#include <math.h>
#include <string.h>
#include <py/runtime.h>
#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 },

View File

@@ -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 <py/obj.h>
#include <py/runtime.h>
#include <py/objarray.h>
#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);

View File

@@ -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);

View File

@@ -15,18 +15,18 @@
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <py/obj.h>
#include <py/runtime.h>
#include <py/misc.h>
#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
//|

View File

@@ -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);

View File

@@ -12,17 +12,17 @@
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <py/obj.h>
#include <py/runtime.h>
#include <py/misc.h>
#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

View File

@@ -15,12 +15,12 @@
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <py/obj.h>
#include <py/runtime.h>
#include <py/misc.h>
#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);

View File

@@ -15,13 +15,13 @@
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <py/runtime.h>
#include <py/binary.h>
#include <py/obj.h>
#include <py/objarray.h>
#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;

View File

@@ -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);

View File

@@ -7,31 +7,31 @@
* The MIT License (MIT)
*
* Copyright (c) 2021 Vikas Udupa
*
*
*/
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <py/obj.h>
#include <py/runtime.h>
#include <py/misc.h>
#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"));
}

View File

@@ -13,9 +13,9 @@
*/
#include <math.h>
#include <py/obj.h>
#include <py/runtime.h>
#include <py/misc.h>
#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);

View File

@@ -13,7 +13,7 @@
*/
#include <math.h>
#include <py/runtime.h>
#include "py/runtime.h"
#include "../ulab.h"
#include "optimize/optimize.h"

View File

@@ -14,16 +14,18 @@
#include <math.h>
#include <string.h>
#include <py/runtime.h>
#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``."""

View File

@@ -13,10 +13,10 @@
*/
#include <math.h>
#include <py/runtime.h>
#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) },

View File

@@ -14,27 +14,26 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <py/runtime.h>
#include <py/binary.h>
#include <py/obj.h>
#include <py/objarray.h>
#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) },

View File

@@ -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

View File

@@ -14,8 +14,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <py/obj.h>
#include <py/runtime.h>
#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[] = {

View File

@@ -10,7 +10,7 @@
#include <string.h>
#include <py/runtime.h>
#include "py/runtime.h"
#include "ulab.h"
#include "ndarray.h"

View File

@@ -12,9 +12,9 @@
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <py/obj.h>
#include <py/runtime.h>
#include <py/misc.h>
#include "py/obj.h"
#include "py/runtime.h"
#include "py/misc.h"
#include "user.h"
#if ULAB_HAS_USER_MODULE

View File

@@ -11,9 +11,9 @@
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <py/obj.h>
#include <py/runtime.h>
#include <py/misc.h>
#include "py/obj.h"
#include "py/runtime.h"
#include "py/misc.h"
#include "utils.h"
#if ULAB_HAS_UTILS_MODULE